diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
index 63db0ec..50d1742 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
@@ -1,12 +1,64 @@
package com.casic.smart.town.sanxi.util.retrofit
-import retrofit2.http.GET
+import retrofit2.http.*
interface RetrofitService {
+ /**
+ * PublicKey校验
+ */
+ @GET("/config/baseConfig")
+ suspend fun obtainPublicKey(): String
+
+ /**
+ * 登录并获取Token
+ *
+ * @param sid
+ * @param account 用户名
+ * @param secretKey 加密后的密码
+ */
+ @FormUrlEncoded
+ @POST("/user/login")
+ suspend fun login(
+ @Field("sid") sid: String,
+ @Field("username") account: String,
+ @Field("password") secretKey: String
+ ): String
+
+ /**
+ * 退出登录
+ */
+ @GET("/user/logout")
+ suspend fun loginOut(@Header("token") token: String): String
+
+ /**
+ * 获取用户信息
+ */
+ @GET("/user/info")
+ suspend fun obtainUserDetail(@Header("token") token: String): String
+
+ /**
+ * 修改密码
+ *
+ * @param oldPwd 旧密码
+ * @param newPwd 新密码
+ */
+ @FormUrlEncoded
+ @POST("/mgr/changePwd")
+ suspend fun changePassword(
+ @Header("token") token: String,
+ @Field("oldPwd") oldPwd: String,
+ @Field("newPwd") newPwd: String
+ ): String
/**
* 根据布防状态统计闸井数量接口
*/
@GET("/well/countByBfzt")
- suspend fun countWellByState(): String
+ suspend fun countWellByState(@Header("token") token: String): String
+
+ /**
+ * 更新APK版本
+ */
+ @POST("/app/checkVersion")
+ suspend fun obtainVersionResult(@Header("token") token: String): String
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
index 63db0ec..50d1742 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
@@ -1,12 +1,64 @@
package com.casic.smart.town.sanxi.util.retrofit
-import retrofit2.http.GET
+import retrofit2.http.*
interface RetrofitService {
+ /**
+ * PublicKey校验
+ */
+ @GET("/config/baseConfig")
+ suspend fun obtainPublicKey(): String
+
+ /**
+ * 登录并获取Token
+ *
+ * @param sid
+ * @param account 用户名
+ * @param secretKey 加密后的密码
+ */
+ @FormUrlEncoded
+ @POST("/user/login")
+ suspend fun login(
+ @Field("sid") sid: String,
+ @Field("username") account: String,
+ @Field("password") secretKey: String
+ ): String
+
+ /**
+ * 退出登录
+ */
+ @GET("/user/logout")
+ suspend fun loginOut(@Header("token") token: String): String
+
+ /**
+ * 获取用户信息
+ */
+ @GET("/user/info")
+ suspend fun obtainUserDetail(@Header("token") token: String): String
+
+ /**
+ * 修改密码
+ *
+ * @param oldPwd 旧密码
+ * @param newPwd 新密码
+ */
+ @FormUrlEncoded
+ @POST("/mgr/changePwd")
+ suspend fun changePassword(
+ @Header("token") token: String,
+ @Field("oldPwd") oldPwd: String,
+ @Field("newPwd") newPwd: String
+ ): String
/**
* 根据布防状态统计闸井数量接口
*/
@GET("/well/countByBfzt")
- suspend fun countWellByState(): String
+ suspend fun countWellByState(@Header("token") token: String): String
+
+ /**
+ * 更新APK版本
+ */
+ @POST("/app/checkVersion")
+ suspend fun obtainVersionResult(@Header("token") token: String): String
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
index 46bbf4b..410444b 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
@@ -1,5 +1,6 @@
package com.casic.smart.town.sanxi.util.retrofit
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
import com.casic.smart.town.sanxi.util.LocaleConstant
import com.pengxh.kt.lite.utils.RetrofitFactory
import com.pengxh.kt.lite.utils.SaveKeyValues
@@ -15,9 +16,52 @@
}
/**
+ * 验证PublicKey
+ */
+ suspend fun authenticate(): String {
+ return api.obtainPublicKey()
+ }
+
+ /**
+ * 登录并获取Token
+ */
+ suspend fun login(sid: String, account: String, secretKey: String): String {
+ return api.login(sid, account, secretKey)
+ }
+
+ /**
+ * 退出登录
+ */
+ suspend fun loginOut(): String {
+ return api.loginOut(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 获取用户信息
+ */
+ suspend fun obtainUserDetail(): String {
+ return api.obtainUserDetail(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 修改密码
+ */
+ suspend fun changePassword(oldPwd: String, newPwd: String): String {
+ return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd)
+ }
+
+ /**
* 根据布防状态统计闸井数量接口
*/
suspend fun countWellByState(): String {
- return api.countWellByState()
+ return api.countWellByState(AuthenticationHelper.token!!)
}
+
+ /**
+ * 更新APK版本
+ */
+ suspend fun updateVersion(): String {
+ return api.obtainVersionResult(AuthenticationHelper.token!!)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
index 63db0ec..50d1742 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
@@ -1,12 +1,64 @@
package com.casic.smart.town.sanxi.util.retrofit
-import retrofit2.http.GET
+import retrofit2.http.*
interface RetrofitService {
+ /**
+ * PublicKey校验
+ */
+ @GET("/config/baseConfig")
+ suspend fun obtainPublicKey(): String
+
+ /**
+ * 登录并获取Token
+ *
+ * @param sid
+ * @param account 用户名
+ * @param secretKey 加密后的密码
+ */
+ @FormUrlEncoded
+ @POST("/user/login")
+ suspend fun login(
+ @Field("sid") sid: String,
+ @Field("username") account: String,
+ @Field("password") secretKey: String
+ ): String
+
+ /**
+ * 退出登录
+ */
+ @GET("/user/logout")
+ suspend fun loginOut(@Header("token") token: String): String
+
+ /**
+ * 获取用户信息
+ */
+ @GET("/user/info")
+ suspend fun obtainUserDetail(@Header("token") token: String): String
+
+ /**
+ * 修改密码
+ *
+ * @param oldPwd 旧密码
+ * @param newPwd 新密码
+ */
+ @FormUrlEncoded
+ @POST("/mgr/changePwd")
+ suspend fun changePassword(
+ @Header("token") token: String,
+ @Field("oldPwd") oldPwd: String,
+ @Field("newPwd") newPwd: String
+ ): String
/**
* 根据布防状态统计闸井数量接口
*/
@GET("/well/countByBfzt")
- suspend fun countWellByState(): String
+ suspend fun countWellByState(@Header("token") token: String): String
+
+ /**
+ * 更新APK版本
+ */
+ @POST("/app/checkVersion")
+ suspend fun obtainVersionResult(@Header("token") token: String): String
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
index 46bbf4b..410444b 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
@@ -1,5 +1,6 @@
package com.casic.smart.town.sanxi.util.retrofit
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
import com.casic.smart.town.sanxi.util.LocaleConstant
import com.pengxh.kt.lite.utils.RetrofitFactory
import com.pengxh.kt.lite.utils.SaveKeyValues
@@ -15,9 +16,52 @@
}
/**
+ * 验证PublicKey
+ */
+ suspend fun authenticate(): String {
+ return api.obtainPublicKey()
+ }
+
+ /**
+ * 登录并获取Token
+ */
+ suspend fun login(sid: String, account: String, secretKey: String): String {
+ return api.login(sid, account, secretKey)
+ }
+
+ /**
+ * 退出登录
+ */
+ suspend fun loginOut(): String {
+ return api.loginOut(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 获取用户信息
+ */
+ suspend fun obtainUserDetail(): String {
+ return api.obtainUserDetail(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 修改密码
+ */
+ suspend fun changePassword(oldPwd: String, newPwd: String): String {
+ return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd)
+ }
+
+ /**
* 根据布防状态统计闸井数量接口
*/
suspend fun countWellByState(): String {
- return api.countWellByState()
+ return api.countWellByState(AuthenticationHelper.token!!)
}
+
+ /**
+ * 更新APK版本
+ */
+ suspend fun updateVersion(): String {
+ return api.obtainVersionResult(AuthenticationHelper.token!!)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
new file mode 100644
index 0000000..7e43c47
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
@@ -0,0 +1,34 @@
+package com.casic.smart.town.sanxi.view
+
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.convertColor
+import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
+import kotlinx.android.synthetic.main.activity_about_us.*
+import kotlinx.android.synthetic.main.include_base_title.*
+
+class AboutUsActivity : KotlinBaseActivity() {
+
+ override fun initLayoutView(): Int = R.layout.activity_about_us
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(false).init()
+ ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this))
+ titleView.text = "关于我们"
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ versionCodeView.text = String.format("版本信息:V${BuildConfig.VERSION_NAME}")
+ }
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun initEvent() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
index 63db0ec..50d1742 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
@@ -1,12 +1,64 @@
package com.casic.smart.town.sanxi.util.retrofit
-import retrofit2.http.GET
+import retrofit2.http.*
interface RetrofitService {
+ /**
+ * PublicKey校验
+ */
+ @GET("/config/baseConfig")
+ suspend fun obtainPublicKey(): String
+
+ /**
+ * 登录并获取Token
+ *
+ * @param sid
+ * @param account 用户名
+ * @param secretKey 加密后的密码
+ */
+ @FormUrlEncoded
+ @POST("/user/login")
+ suspend fun login(
+ @Field("sid") sid: String,
+ @Field("username") account: String,
+ @Field("password") secretKey: String
+ ): String
+
+ /**
+ * 退出登录
+ */
+ @GET("/user/logout")
+ suspend fun loginOut(@Header("token") token: String): String
+
+ /**
+ * 获取用户信息
+ */
+ @GET("/user/info")
+ suspend fun obtainUserDetail(@Header("token") token: String): String
+
+ /**
+ * 修改密码
+ *
+ * @param oldPwd 旧密码
+ * @param newPwd 新密码
+ */
+ @FormUrlEncoded
+ @POST("/mgr/changePwd")
+ suspend fun changePassword(
+ @Header("token") token: String,
+ @Field("oldPwd") oldPwd: String,
+ @Field("newPwd") newPwd: String
+ ): String
/**
* 根据布防状态统计闸井数量接口
*/
@GET("/well/countByBfzt")
- suspend fun countWellByState(): String
+ suspend fun countWellByState(@Header("token") token: String): String
+
+ /**
+ * 更新APK版本
+ */
+ @POST("/app/checkVersion")
+ suspend fun obtainVersionResult(@Header("token") token: String): String
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
index 46bbf4b..410444b 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
@@ -1,5 +1,6 @@
package com.casic.smart.town.sanxi.util.retrofit
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
import com.casic.smart.town.sanxi.util.LocaleConstant
import com.pengxh.kt.lite.utils.RetrofitFactory
import com.pengxh.kt.lite.utils.SaveKeyValues
@@ -15,9 +16,52 @@
}
/**
+ * 验证PublicKey
+ */
+ suspend fun authenticate(): String {
+ return api.obtainPublicKey()
+ }
+
+ /**
+ * 登录并获取Token
+ */
+ suspend fun login(sid: String, account: String, secretKey: String): String {
+ return api.login(sid, account, secretKey)
+ }
+
+ /**
+ * 退出登录
+ */
+ suspend fun loginOut(): String {
+ return api.loginOut(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 获取用户信息
+ */
+ suspend fun obtainUserDetail(): String {
+ return api.obtainUserDetail(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 修改密码
+ */
+ suspend fun changePassword(oldPwd: String, newPwd: String): String {
+ return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd)
+ }
+
+ /**
* 根据布防状态统计闸井数量接口
*/
suspend fun countWellByState(): String {
- return api.countWellByState()
+ return api.countWellByState(AuthenticationHelper.token!!)
}
+
+ /**
+ * 更新APK版本
+ */
+ suspend fun updateVersion(): String {
+ return api.obtainVersionResult(AuthenticationHelper.token!!)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
new file mode 100644
index 0000000..7e43c47
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
@@ -0,0 +1,34 @@
+package com.casic.smart.town.sanxi.view
+
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.convertColor
+import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
+import kotlinx.android.synthetic.main.activity_about_us.*
+import kotlinx.android.synthetic.main.include_base_title.*
+
+class AboutUsActivity : KotlinBaseActivity() {
+
+ override fun initLayoutView(): Int = R.layout.activity_about_us
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(false).init()
+ ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this))
+ titleView.text = "关于我们"
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ versionCodeView.text = String.format("版本信息:V${BuildConfig.VERSION_NAME}")
+ }
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun initEvent() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt
new file mode 100644
index 0000000..b5d1d50
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt
@@ -0,0 +1,97 @@
+package com.casic.smart.town.sanxi.view
+
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.vm.AuthenticateViewModel
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import kotlinx.android.synthetic.main.activity_login.*
+
+class LoginActivity : KotlinBaseActivity() {
+
+ private lateinit var authenticateViewModel: AuthenticateViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var userViewModel: UserViewModel
+
+ override fun initLayoutView(): Int = R.layout.activity_login
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ }
+
+ override fun initData() {
+ // 设置默认账号密码
+ userNameView.setText(SaveKeyValues.getValue(LocaleConstant.ACCOUNT, "") as String)
+ userPasswordView.setText(SaveKeyValues.getValue(LocaleConstant.PASSWORD, "") as String)
+ authenticateViewModel = ViewModelProvider(this)[AuthenticateViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+
+ 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请求
+ loginViewModel.enter(it.data!!.sid!!, account, dataByPublicKey)
+ loginViewModel.enterResultModel.observe(this, { loginResult ->
+ if (loginResult.code == 200) {
+ AuthenticationHelper.saveToken(loginResult.data!!.token!!)
+ /**
+ * 获取token之后保存用户信息
+ * */
+ userViewModel.obtainUserDetail()
+ //验证成功登录
+ navigatePageTo()
+ finish()
+ }
+ })
+ }
+ })
+ }
+
+ override fun observeRequestState() {
+ authenticateViewModel.loadState.observe(this, {
+ LoadingDialogHub.show(this, "登录中,请稍后")
+ })
+
+ loginViewModel.loadState.observe(this, {
+ LoadingDialogHub.dismiss()
+ })
+ }
+
+ override fun initEvent() {
+ loginButton.setOnClickListener {
+ val account = userNameView.text.toString().trim()
+ val userPassword = userPasswordView.text.toString().trim()
+ if (account.isBlank()) {
+ "用户名不能为空".show(this)
+ return@setOnClickListener
+ }
+ if (userPassword.isBlank()) {
+ "密码不能为空".show(this)
+ return@setOnClickListener
+ }
+ SaveKeyValues.putValue(LocaleConstant.ACCOUNT, account)
+ SaveKeyValues.putValue(LocaleConstant.PASSWORD, userPassword)
+ authenticateViewModel.obtainPublicKey()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List getDevices() {
+ return devices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setIpAddr(String ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ public String getIpAddr() {
+ return ipAddr;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setRoleList(List roleList) {
+ this.roleList = roleList;
+ }
+
+ public List getRoleList() {
+ return roleList;
+ }
+
+ public void setRoleNames(List roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ public List getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleTips(List roleTips) {
+ this.roleTips = roleTips;
+ }
+
+ public List getRoleTips() {
+ return roleTips;
+ }
+
+ public void setScopeType(String scopeType) {
+ this.scopeType = scopeType;
+ }
+
+ public String getScopeType() {
+ return scopeType;
+ }
+
+ public void setSysData(String sysData) {
+ this.sysData = sysData;
+ }
+
+ public String getSysData() {
+ return sysData;
+ }
+
+ public void setTargetId(String targetId) {
+ this.targetId = targetId;
+ }
+
+ public String getTargetId() {
+ return targetId;
+ }
+
+ public void setTargetName(String targetName) {
+ this.targetName = targetName;
+ }
+
+ public String getTargetName() {
+ return targetName;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
new file mode 100644
index 0000000..79374e0
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/VersionResultModel.java
@@ -0,0 +1,61 @@
+package com.casic.smart.town.sanxi.model;
+
+public class VersionResultModel {
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String downloadUrl;
+ private String version;
+
+ public String getDownloadUrl() {
+ return downloadUrl;
+ }
+
+ public void setDownloadUrl(String downloadUrl) {
+ this.downloadUrl = downloadUrl;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
new file mode 100644
index 0000000..f498e4e
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/AuthenticationHelper.kt
@@ -0,0 +1,24 @@
+package com.casic.smart.town.sanxi.util
+
+import com.pengxh.kt.lite.utils.SaveKeyValues
+
+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/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
index ab1a36d..99f0d19 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt
@@ -14,5 +14,9 @@
const val PAGE_LIMIT = 20
const val DEFAULT_SERVER_CONFIG = "defaultServerConfig"
- const val DEFAULT_SERVER = "http://111.198.10.15:11308"
+ const val DEFAULT_SERVER = "http://36.133.189.112:8082"
+ const val APP_AUTHORITY = "com.casic.smart.town.sanxi.fileprovider"
+ 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/smart/town/sanxi/util/RSAUtils.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
new file mode 100644
index 0000000..b9216ba
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/RSAUtils.kt
@@ -0,0 +1,55 @@
+package com.casic.smart.town.sanxi.util
+
+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/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
index 63db0ec..50d1742 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt
@@ -1,12 +1,64 @@
package com.casic.smart.town.sanxi.util.retrofit
-import retrofit2.http.GET
+import retrofit2.http.*
interface RetrofitService {
+ /**
+ * PublicKey校验
+ */
+ @GET("/config/baseConfig")
+ suspend fun obtainPublicKey(): String
+
+ /**
+ * 登录并获取Token
+ *
+ * @param sid
+ * @param account 用户名
+ * @param secretKey 加密后的密码
+ */
+ @FormUrlEncoded
+ @POST("/user/login")
+ suspend fun login(
+ @Field("sid") sid: String,
+ @Field("username") account: String,
+ @Field("password") secretKey: String
+ ): String
+
+ /**
+ * 退出登录
+ */
+ @GET("/user/logout")
+ suspend fun loginOut(@Header("token") token: String): String
+
+ /**
+ * 获取用户信息
+ */
+ @GET("/user/info")
+ suspend fun obtainUserDetail(@Header("token") token: String): String
+
+ /**
+ * 修改密码
+ *
+ * @param oldPwd 旧密码
+ * @param newPwd 新密码
+ */
+ @FormUrlEncoded
+ @POST("/mgr/changePwd")
+ suspend fun changePassword(
+ @Header("token") token: String,
+ @Field("oldPwd") oldPwd: String,
+ @Field("newPwd") newPwd: String
+ ): String
/**
* 根据布防状态统计闸井数量接口
*/
@GET("/well/countByBfzt")
- suspend fun countWellByState(): String
+ suspend fun countWellByState(@Header("token") token: String): String
+
+ /**
+ * 更新APK版本
+ */
+ @POST("/app/checkVersion")
+ suspend fun obtainVersionResult(@Header("token") token: String): String
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
index 46bbf4b..410444b 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt
@@ -1,5 +1,6 @@
package com.casic.smart.town.sanxi.util.retrofit
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
import com.casic.smart.town.sanxi.util.LocaleConstant
import com.pengxh.kt.lite.utils.RetrofitFactory
import com.pengxh.kt.lite.utils.SaveKeyValues
@@ -15,9 +16,52 @@
}
/**
+ * 验证PublicKey
+ */
+ suspend fun authenticate(): String {
+ return api.obtainPublicKey()
+ }
+
+ /**
+ * 登录并获取Token
+ */
+ suspend fun login(sid: String, account: String, secretKey: String): String {
+ return api.login(sid, account, secretKey)
+ }
+
+ /**
+ * 退出登录
+ */
+ suspend fun loginOut(): String {
+ return api.loginOut(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 获取用户信息
+ */
+ suspend fun obtainUserDetail(): String {
+ return api.obtainUserDetail(AuthenticationHelper.token!!)
+ }
+
+ /**
+ * 修改密码
+ */
+ suspend fun changePassword(oldPwd: String, newPwd: String): String {
+ return api.changePassword(AuthenticationHelper.token!!, oldPwd, newPwd)
+ }
+
+ /**
* 根据布防状态统计闸井数量接口
*/
suspend fun countWellByState(): String {
- return api.countWellByState()
+ return api.countWellByState(AuthenticationHelper.token!!)
}
+
+ /**
+ * 更新APK版本
+ */
+ suspend fun updateVersion(): String {
+ return api.obtainVersionResult(AuthenticationHelper.token!!)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
new file mode 100644
index 0000000..7e43c47
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/AboutUsActivity.kt
@@ -0,0 +1,34 @@
+package com.casic.smart.town.sanxi.view
+
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.convertColor
+import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil
+import kotlinx.android.synthetic.main.activity_about_us.*
+import kotlinx.android.synthetic.main.include_base_title.*
+
+class AboutUsActivity : KotlinBaseActivity() {
+
+ override fun initLayoutView(): Int = R.layout.activity_about_us
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(false).init()
+ ImmerseStatusBarUtil.setColor(this, R.color.mainThemeColor.convertColor(this))
+ titleView.text = "关于我们"
+ leftBackView.setOnClickListener { finish() }
+ }
+
+ override fun initData() {
+ versionCodeView.text = String.format("版本信息:V${BuildConfig.VERSION_NAME}")
+ }
+
+ override fun observeRequestState() {
+
+ }
+
+ override fun initEvent() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt
new file mode 100644
index 0000000..b5d1d50
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/LoginActivity.kt
@@ -0,0 +1,97 @@
+package com.casic.smart.town.sanxi.view
+
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.vm.AuthenticateViewModel
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.gyf.immersionbar.ImmersionBar
+import com.pengxh.kt.lite.base.KotlinBaseActivity
+import com.pengxh.kt.lite.extensions.navigatePageTo
+import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import kotlinx.android.synthetic.main.activity_login.*
+
+class LoginActivity : KotlinBaseActivity() {
+
+ private lateinit var authenticateViewModel: AuthenticateViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var userViewModel: UserViewModel
+
+ override fun initLayoutView(): Int = R.layout.activity_login
+
+ override fun setupTopBarLayout() {
+ ImmersionBar.with(this).statusBarDarkFont(true).init()
+ }
+
+ override fun initData() {
+ // 设置默认账号密码
+ userNameView.setText(SaveKeyValues.getValue(LocaleConstant.ACCOUNT, "") as String)
+ userPasswordView.setText(SaveKeyValues.getValue(LocaleConstant.PASSWORD, "") as String)
+ authenticateViewModel = ViewModelProvider(this)[AuthenticateViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+
+ 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请求
+ loginViewModel.enter(it.data!!.sid!!, account, dataByPublicKey)
+ loginViewModel.enterResultModel.observe(this, { loginResult ->
+ if (loginResult.code == 200) {
+ AuthenticationHelper.saveToken(loginResult.data!!.token!!)
+ /**
+ * 获取token之后保存用户信息
+ * */
+ userViewModel.obtainUserDetail()
+ //验证成功登录
+ navigatePageTo()
+ finish()
+ }
+ })
+ }
+ })
+ }
+
+ override fun observeRequestState() {
+ authenticateViewModel.loadState.observe(this, {
+ LoadingDialogHub.show(this, "登录中,请稍后")
+ })
+
+ loginViewModel.loadState.observe(this, {
+ LoadingDialogHub.dismiss()
+ })
+ }
+
+ override fun initEvent() {
+ loginButton.setOnClickListener {
+ val account = userNameView.text.toString().trim()
+ val userPassword = userPasswordView.text.toString().trim()
+ if (account.isBlank()) {
+ "用户名不能为空".show(this)
+ return@setOnClickListener
+ }
+ if (userPassword.isBlank()) {
+ "密码不能为空".show(this)
+ return@setOnClickListener
+ }
+ SaveKeyValues.putValue(LocaleConstant.ACCOUNT, account)
+ SaveKeyValues.putValue(LocaleConstant.PASSWORD, userPassword)
+ authenticateViewModel.obtainPublicKey()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/view/MainActivity.kt b/app/src/main/java/com/casic/smart/town/sanxi/view/MainActivity.kt
index 3bea1c9..a4fa951 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/view/MainActivity.kt
@@ -7,6 +7,7 @@
import com.casic.smart.town.sanxi.R
import com.casic.smart.town.sanxi.adapter.ViewPagerAdapter
import com.casic.smart.town.sanxi.fragment.AlarmPageFragment
+import com.casic.smart.town.sanxi.fragment.MinePageFragment
import com.casic.smart.town.sanxi.fragment.MonitorPageFragment
import com.casic.smart.town.sanxi.fragment.StatisticsPageFragment
import com.gyf.immersionbar.ImmersionBar
@@ -33,6 +34,7 @@
fragmentPages.add(StatisticsPageFragment())
fragmentPages.add(MonitorPageFragment())
fragmentPages.add(AlarmPageFragment())
+ fragmentPages.add(MinePageFragment())
}
override fun initLayoutView(): Int = R.layout.activity_main
@@ -68,6 +70,9 @@
R.id.nav_alarm -> {
mainViewPager.currentItem = 2
}
+ R.id.nav_more -> {
+ mainViewPager.currentItem = 3
+ }
}
false
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1df917d..8d4f33b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
+
@@ -32,11 +33,14 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/svg/mine.svg b/app/src/main/assets/svg/mine.svg
new file mode 100644
index 0000000..3fbb0a3
--- /dev/null
+++ b/app/src/main/assets/svg/mine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
index d730417..b1972c2 100644
--- a/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
+++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/String.kt
@@ -1,8 +1,10 @@
package com.casic.smart.town.sanxi.extensions
import com.casic.smart.town.sanxi.model.ErrorMessageModel
+import com.casic.smart.town.sanxi.util.LocaleConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.utils.SaveKeyValues
import org.json.JSONObject
fun String.separateResponseCode(): Int {
@@ -17,4 +19,15 @@
this, object : TypeToken() {}.type
)
return errorModel.message.toString()
+}
+
+/**
+ * 下载路径为 http://xx.com/static/ 拼接downloadUrl
+ * */
+fun String.appendDownloadUrl(): String {
+ if (this.isEmpty()) return this
+ val defaultValue = SaveKeyValues.getValue(
+ LocaleConstant.DEFAULT_SERVER_CONFIG, LocaleConstant.DEFAULT_SERVER
+ ) as String
+ return "$defaultValue/static/${this}"
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
new file mode 100644
index 0000000..1809dc5
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/MinePageFragment.kt
@@ -0,0 +1,288 @@
+package com.casic.smart.town.sanxi.fragment
+
+import android.app.ProgressDialog
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.CountDownTimer
+import androidx.core.content.FileProvider
+import androidx.lifecycle.ViewModelProvider
+import com.casic.smart.town.sanxi.BuildConfig
+import com.casic.smart.town.sanxi.R
+import com.casic.smart.town.sanxi.extensions.appendDownloadUrl
+import com.casic.smart.town.sanxi.model.UserDetailModel
+import com.casic.smart.town.sanxi.util.AuthenticationHelper
+import com.casic.smart.town.sanxi.util.LoadingDialogHub
+import com.casic.smart.town.sanxi.util.LocaleConstant
+import com.casic.smart.town.sanxi.util.RSAUtils
+import com.casic.smart.town.sanxi.view.AboutUsActivity
+import com.casic.smart.town.sanxi.view.LoginActivity
+import com.casic.smart.town.sanxi.vm.LoginViewModel
+import com.casic.smart.town.sanxi.vm.UserViewModel
+import com.casic.smart.town.sanxi.vm.VersionViewModel
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.pengxh.kt.lite.base.KotlinBaseFragment
+import com.pengxh.kt.lite.callback.OnDownloadListener
+import com.pengxh.kt.lite.extensions.*
+import com.pengxh.kt.lite.utils.PageNavigationManager
+import com.pengxh.kt.lite.utils.SaveKeyValues
+import com.pengxh.kt.lite.vm.LoadState
+import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ChangePasswordDialog
+import kotlinx.android.synthetic.main.fragment_mine.*
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+class MinePageFragment : KotlinBaseFragment() {
+
+ private lateinit var userData: UserDetailModel.Data
+ private lateinit var userViewModel: UserViewModel
+ private lateinit var loginViewModel: LoginViewModel
+ private lateinit var versionViewModel: VersionViewModel
+ private lateinit var progressDialog: ProgressDialog
+
+ override fun initLayoutView(): Int = R.layout.fragment_mine
+
+ override fun setupTopBarLayout() {
+
+ }
+
+ override fun initData() {
+ userViewModel = ViewModelProvider(this)[UserViewModel::class.java]
+ loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
+ versionViewModel = ViewModelProvider(this)[VersionViewModel::class.java]
+
+ //初始化下载对话框
+ progressDialog = ProgressDialog(requireContext())
+ progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ progressDialog.setProgressDrawable(resources.getDrawable(R.drawable.download_progress))
+ progressDialog.setCanceledOnTouchOutside(false)
+ progressDialog.setCancelable(false)
+
+ /**
+ * 数据监听
+ * */
+ dataObserve()
+ }
+
+ override fun observeRequestState() {
+ userViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "修改中,请稍后")
+ is LoadState.Success -> {
+ "修改成功,请重新登录".show(requireContext())
+ LoadingDialogHub.dismiss()
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+
+ versionViewModel.loadState.observe(this, {
+ when (it) {
+ is LoadState.Loading -> LoadingDialogHub.show(requireActivity(), "检查版本中,请稍后")
+ else -> LoadingDialogHub.dismiss()
+ }
+ })
+ }
+
+ override fun initEvent() {
+ userImageView.setOnClickListener {
+ "尽情期待~".show(requireContext())
+ }
+
+ updateUserButton.setOnClickListener {
+ LoadingDialogHub.show(requireActivity(), "同步中,请稍后...")
+ userViewModel.obtainUserDetail()
+ }
+
+ changePwdLayout.setOnClickListener {
+ ChangePasswordDialog.Builder()
+ .setContext(requireContext())
+ .setOnDialogButtonClickListener(object :
+ ChangePasswordDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick(oldPwd: String, newPwd: String) {
+ val publicKey =
+ RSAUtils.keyStrToPublicKey(AuthenticationHelper.publicKey)!!
+ val oldPassKey = RSAUtils.encryptDataByPublicKey(
+ oldPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ val newPassKey = RSAUtils.encryptDataByPublicKey(
+ newPwd.toByteArray(StandardCharsets.UTF_8),
+ publicKey
+ )
+ userViewModel.changePassword(oldPassKey, newPassKey)
+ }
+ }).build().show()
+ }
+
+ aboutUsLayout.setOnClickListener {
+ requireContext().navigatePageTo()
+ }
+
+ updateVersionLayout.setOnClickListener {
+ versionViewModel.updateVersion()
+ }
+
+ clearCacheLayout.setOnClickListener {
+ //删除缓存之后在设置缓存大小
+ LoadingDialogHub.show(requireActivity(), "清理中,请稍后")
+ File(requireContext().cacheDir.path).deleteFile()
+ object : CountDownTimer(1500, 500) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialogHub.dismiss()
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ }
+ }.start()
+ }
+
+ loginOutButton.setOnClickListener {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("退出登录")
+ .setMessage("确定要退出吗?")
+ .setNegativeButton("取消")
+ .setPositiveButton("确定")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ loginViewModel.out()
+ }
+
+ override fun onCancelClick() {}
+ }).build().show()
+ }
+ }
+
+ private fun dataObserve() {
+ userViewModel.userDetailModel.observe(this, {
+ if (it.code == 200) {
+ LoadingDialogHub.dismiss()
+ "同步完成".show(requireContext())
+ userData = it.data
+ updateUserInfo()
+ }
+ })
+
+ versionViewModel.versionResultModel.observe(this, {
+ if (BuildConfig.VERSION_NAME == it.version) {
+ "已是最新版本,无需更新".show(requireContext())
+ } else {
+ AlertControlDialog.Builder()
+ .setContext(requireContext())
+ .setTitle("提示")
+ .setMessage("有新版本,是否更新?")
+ .setNegativeButton("稍后再说")
+ .setPositiveButton("立即下载")
+ .setOnDialogButtonClickListener(object :
+ AlertControlDialog.OnDialogButtonClickListener {
+ override fun onConfirmClick() {
+ downloadApk(it.downloadUrl)
+ }
+
+ override fun onCancelClick() {
+
+ }
+ }).build().show()
+ }
+ })
+
+ loginViewModel.outResultModel.observe(this, {
+ if (it.code == 200) {
+ AuthenticationHelper.removeToken()
+ requireContext().navigatePageTo()
+ PageNavigationManager.finishAllActivity()
+ }
+ })
+ }
+
+ private fun collectApplicationCache(): Long {
+ return File(requireContext().cacheDir.path).calculateSize()
+ }
+
+ override fun onResume() {
+ val userDetailJson = SaveKeyValues.getValue(LocaleConstant.USER_DETAIL_MODEL, "") as String
+ if (userDetailJson.isNotBlank()) {
+ userData = Gson().fromJson(
+ userDetailJson, object : TypeToken() {}.type
+ )
+ updateUserInfo()
+ }
+ //缓存
+ cacheSizeView.text = collectApplicationCache().formatFileSize()
+ super.onResume()
+ }
+
+ private fun updateUserInfo() {
+ //设置头像,圆形,暂时是默认的
+// val roundDrawable =
+// BitmapFactory.decodeResource(requireContext().resources, R.mipmap.login_casic)
+// .createRoundDrawable(
+// requireContext(),
+// 3f.dp2px(requireContext()),
+// R.color.mainThemeColor.convertColor(requireContext())
+// )
+// userImageView.setImageDrawable(roundDrawable)
+ userNameView.text = userData.name
+ userPhoneView.text = String.format("电话:${userData.phone}")
+ userDeptView.text = String.format("部门:${userData.deptName}")
+ }
+
+ private fun downloadApk(url: String?) {
+ progressDialog.setMessage("下载新版本中...")
+ progressDialog.show()
+ if (url.toString().isBlank()) {
+ "抱歉,版本下载失败".show(requireContext())
+ return
+ }
+ /**
+ * http://111.198.10.15:11304/static/apk/1.0.1.apk
+ * */
+ val downloadPath = url!!.appendDownloadUrl()
+ //开始下载
+ downloadPath.downloadFile(requireContext().createDownloadFileDir().toString(),
+ object : OnDownloadListener {
+ override fun onDownloadStart(totalBytes: Long) {
+ progressDialog.max = totalBytes.toInt()
+ }
+
+ override fun onProgressChanged(currentBytes: Long) {
+ progressDialog.progress = currentBytes.toInt()
+ }
+
+ override fun onDownloadEnd(file: File?) {
+ progressDialog.dismiss()
+ progressDialog.progress = 0
+ //安装APK
+ installApk(file)
+ }
+ })
+ }
+
+ private fun installApk(apkPackage: File?) {
+ if (apkPackage == null) {
+ "文件异常,无法安装".show(requireContext())
+ return
+ }
+ val intent = Intent(Intent.ACTION_VIEW)
+ val data: Uri
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //判断版本大于等于7.0
+ data = FileProvider.getUriForFile(
+ requireContext(), LocaleConstant.APP_AUTHORITY, apkPackage
+ )
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 给目标应用一个临时授权
+ } else {
+ data = Uri.fromFile(apkPackage)
+ }
+ intent.setDataAndType(data, "application/vnd.android.package-archive")
+ requireContext().startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
new file mode 100644
index 0000000..467e33d
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/CommonResultModel.java
@@ -0,0 +1,43 @@
+package com.casic.smart.town.sanxi.model;
+
+/**
+ * 普通实体类,失败/成功数据结构一致
+ */
+public class CommonResultModel {
+ private int code;
+ private String data;
+ private String message;
+ private boolean isSuccess;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return isSuccess;
+ }
+
+ public void setSuccess(boolean success) {
+ isSuccess = success;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
new file mode 100644
index 0000000..9bdabef
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LoginResultModel.java
@@ -0,0 +1,62 @@
+package com.casic.smart.town.sanxi.model;
+
+public class LoginResultModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private String kaptcha;
+ private String token;
+
+ public String getKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(String kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
new file mode 100644
index 0000000..09f8d59
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/PublicKeyModel.java
@@ -0,0 +1,80 @@
+package com.casic.smart.town.sanxi.model;
+
+public class PublicKeyModel {
+
+ private int code;
+ private DataBean data;
+ private String message;
+ private boolean success;
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public DataBean getData() {
+ return data;
+ }
+
+ public void setData(DataBean data) {
+ this.data = data;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public static class DataBean {
+ private boolean appKaptcha;
+ private boolean kaptcha;
+ private String publicKey;
+ private String sid;
+
+ public boolean isAppKaptcha() {
+ return appKaptcha;
+ }
+
+ public void setAppKaptcha(boolean appKaptcha) {
+ this.appKaptcha = appKaptcha;
+ }
+
+ public boolean isKaptcha() {
+ return kaptcha;
+ }
+
+ public void setKaptcha(boolean kaptcha) {
+ this.kaptcha = kaptcha;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ }
+}
diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
new file mode 100644
index 0000000..db577fb
--- /dev/null
+++ b/app/src/main/java/com/casic/smart/town/sanxi/model/UserDetailModel.java
@@ -0,0 +1,227 @@
+package com.casic.smart.town.sanxi.model;
+
+
+import java.util.List;
+
+public class UserDetailModel {
+ private int code;
+ private Data data;
+ private String message;
+ private boolean success;
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setData(Data data) {
+ this.data = data;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public static class Data {
+
+ private String account;
+ private String attr1;
+ private String avatar;
+ private String bizData;
+ private List dataScope;
+ private String deptId;
+ private String deptName;
+ private List devices;
+ private String id;
+ private String ipAddr;
+ private String name;
+ private String phone;
+ private List roleList;
+ private List roleNames;
+ private List roleTips;
+ private String scopeType;
+ private String sysData;
+ private String targetId;
+ private String targetName;
+ private String tenantId;
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAttr1(String attr1) {
+ this.attr1 = attr1;
+ }
+
+ public String getAttr1() {
+ return attr1;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setBizData(String bizData) {
+ this.bizData = bizData;
+ }
+
+ public String getBizData() {
+ return bizData;
+ }
+
+ public void setDataScope(List dataScope) {
+ this.dataScope = dataScope;
+ }
+
+ public List getDataScope() {
+ return dataScope;
+ }
+
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDevices(List devices) {
+ this.devices = devices;
+ }
+
+ public List