1、更新多UniMp相关更新版本逻辑
2、首页UI更新
This commit is contained in:
shenzuqiang 2026-03-09 17:58:36 +08:00
parent 6598b54e85
commit 8dfffa0c95
12 changed files with 385 additions and 285 deletions

View File

@ -0,0 +1,9 @@
package com.img.rabbit.bean.local
import kotlinx.serialization.Serializable
@Serializable
data class UniMpVersionBean(
val uniId: String, // id
val version: String, // 版本
)

View File

@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
class UniVersionEntity( class UniVersionEntity(
var version: String = "", var version: String = "0.0.0",
var url: String = "", var url: String = "",
var last_version_force: String = "", var last_version_force: String = "",
var force: Boolean = false, var force: Boolean = false,

View File

@ -2,6 +2,7 @@ package com.img.rabbit.pages
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -61,6 +62,7 @@ sealed class TabItem(val title: String, val router:String, val normalIconRes: In
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable @Composable
fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewModel) { fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewModel) {
val context = LocalContext.current
val navController = rememberNavController() val navController = rememberNavController()
val networkStatus by generalViewModel.networkStatus.observeAsState(initial = true) val networkStatus by generalViewModel.networkStatus.observeAsState(initial = true)
val isNavigationBarVisible by generalViewModel.isNavigationBarVisible.observeAsState(initial = true) val isNavigationBarVisible by generalViewModel.isNavigationBarVisible.observeAsState(initial = true)
@ -89,12 +91,18 @@ fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewMode
Log.w("NetworkStatus","网络断开") Log.w("NetworkStatus","网络断开")
//延迟500ms确保页面初始化完成后再跳转网络错误页面 //延迟500ms确保页面初始化完成后再跳转网络错误页面
delay(500) delay(500)
Toast.makeText(context, "网络已断开,请检查网络设置!", Toast.LENGTH_SHORT).show()
/*
navController.navigate("netError") navController.navigate("netError")
generalViewModel.setNavigationBarVisible(false) generalViewModel.setNavigationBarVisible(false)
*/
}else{ }else{
/*
if(navBackStackEntry?.destination?.route == "home"||navBackStackEntry?.destination?.route == "mine"){ if(navBackStackEntry?.destination?.route == "home"||navBackStackEntry?.destination?.route == "mine"){
generalViewModel.setNavigationBarVisible(true) generalViewModel.setNavigationBarVisible(true)
} }
*/
Log.w("NetworkStatus","网络已连接") Log.w("NetworkStatus","网络已连接")
} }
} }
@ -102,7 +110,7 @@ fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewMode
Scaffold( Scaffold(
bottomBar = { bottomBar = {
if (isNavigationBarVisible) { if (isNavigationBarVisible) {
Box { Box(modifier = Modifier.height(52.dp)) {
NavigationBar( NavigationBar(
containerColor = Color.White, containerColor = Color.White,
contentColor = Color.Transparent contentColor = Color.Transparent
@ -135,7 +143,7 @@ fun MainScreen(generalViewModel: GeneralViewModel, loginViewModel: LoginViewMode
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(1.dp) .height(1.dp)
.background(Color.Gray.copy(alpha = 0.3f)) .background(Color(0x1AD0D0D0))
) )
} }
} }

View File

@ -126,18 +126,11 @@ fun HomeScreen(
.background(Color.White) .background(Color.White)
.fillMaxSize() .fillMaxSize()
){ ){
Image(
painter = painterResource(id = R.mipmap.ic_home_top_mask),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth()
)
LazyColumn ( LazyColumn (
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.weight(1f) .weight(1f)
.offset(y = (-17).dp) .padding(bottom = 52.dp)
.padding(bottom = 56.dp)
.background( .background(
color = Color.White, color = Color.White,
shape = RoundedCornerShape(topStart = 18.dp, topEnd = 18.dp) shape = RoundedCornerShape(topStart = 18.dp, topEnd = 18.dp)
@ -149,6 +142,23 @@ fun HomeScreen(
val rows = homeIconConfig?.chunked(columnsCount)?:emptyList() val rows = homeIconConfig?.chunked(columnsCount)?:emptyList()
item { item {
Column(
) {
Image(
painter = painterResource(id = R.mipmap.ic_home_top_mask),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth()
)
Column(
modifier = Modifier
.fillMaxWidth()
.offset(y = (-17).dp)
.background(
color = Color.White,
shape = RoundedCornerShape(topStart = 18.dp, topEnd = 18.dp)
)
) {
//通过配置展示-AD1(模拟器) //通过配置展示-AD1(模拟器)
val uniVersionConfig = uniVersionConfig val uniVersionConfig = uniVersionConfig
if(uniVersionConfig?.isNotEmpty() == true){ if(uniVersionConfig?.isNotEmpty() == true){
@ -425,6 +435,9 @@ fun HomeScreen(
} }
} }
} }
}
}
items(rows) {rowItems -> items(rows) {rowItems ->
//通过配置展示-AD2 //通过配置展示-AD2
Row(Modifier.fillMaxWidth()) { Row(Modifier.fillMaxWidth()) {

View File

@ -3,6 +3,9 @@ package com.img.rabbit.provider.storage
import android.text.TextUtils import android.text.TextUtils
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.img.rabbit.bean.local.UniMpVersionBean
import com.img.rabbit.bean.response.UserConfigEntity import com.img.rabbit.bean.response.UserConfigEntity
import com.img.rabbit.bean.response.LoginInfoEntity import com.img.rabbit.bean.response.LoginInfoEntity
import com.img.rabbit.bean.response.UserInfoEntity import com.img.rabbit.bean.response.UserInfoEntity
@ -10,6 +13,7 @@ import com.img.rabbit.provider.utils.HeadParamUtils.applicationContext
import com.img.rabbit.utils.MMKVUtils import com.img.rabbit.utils.MMKVUtils
import com.img.rabbit.utils.MMKVUtils.mmkv import com.img.rabbit.utils.MMKVUtils.mmkv
import com.img.rabbit.utils.appwalle.ChannelReader import com.img.rabbit.utils.appwalle.ChannelReader
import kotlinx.serialization.json.Json
import org.json.JSONObject import org.json.JSONObject
/** /**
@ -159,12 +163,31 @@ object PreferenceUtil {
return mmkv.decodeString(KEY_WX_CODE, null) return mmkv.decodeString(KEY_WX_CODE, null)
} }
fun saveWgtVersion(wgtVersion: String) { fun saveWgtVersion(uniId:String, wgtVersion: String) {
mmkv.encode(KEY_WGT_VERSION, wgtVersion) val json = mmkv.decodeString(KEY_WGT_VERSION, null)
val versions = if (!json.isNullOrEmpty()) {
Json.decodeFromString<MutableList<UniMpVersionBean>>(json)
} else {
mutableListOf()
} }
fun getWgtVersion(): String? { val existingIndex = versions.indexOfFirst { it.uniId == uniId }
return mmkv.decodeString(KEY_WGT_VERSION, null) if (existingIndex != -1) {
versions[existingIndex] = versions[existingIndex].copy(version = wgtVersion)
} else {
versions.add(UniMpVersionBean(uniId = uniId, version = wgtVersion))
}
mmkv.encode(KEY_WGT_VERSION, Json.encodeToString(versions))
}
fun getWgtVersion(uniId:String): String? {
val json = mmkv.decodeString(KEY_WGT_VERSION, null)
if(json.isNullOrEmpty()){
return "0.0.0"
}
val versions = Json.decodeFromString<MutableList<UniMpVersionBean>>(json)
return versions.find { it.uniId == uniId }?.version
} }
//真实的服务器时间 //真实的服务器时间

View File

@ -0,0 +1,7 @@
package com.img.rabbit.provider.utils
object NetworkUtils {
//实时更新网络状态
var globalNetworkStatus: Boolean = false
}

View File

@ -0,0 +1,31 @@
package com.img.rabbit.uni;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.img.rabbit.R;
import io.dcloud.feature.sdk.Interface.IDCUniMPAppSplashView;
public class UniMPAlipaySplashView implements IDCUniMPAppSplashView {
FrameLayout splashView;
@Override
public View getSplashView(Context context, String appid, String s1, String s2) {
splashView = new FrameLayout(context);
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.mipmap.ic_launch_alipay_unimp);
splashView.addView(imageView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
return splashView;
}
@Override
public void onCloseSplash(ViewGroup rootView) {
if(rootView != null)
rootView.removeView(splashView);
}
}

View File

@ -11,7 +11,7 @@ import com.img.rabbit.R;
import io.dcloud.feature.sdk.Interface.IDCUniMPAppSplashView; import io.dcloud.feature.sdk.Interface.IDCUniMPAppSplashView;
public class UniMPSplashView implements IDCUniMPAppSplashView { public class UniMPWxSplashView implements IDCUniMPAppSplashView {
FrameLayout splashView; FrameLayout splashView;
@Override @Override

View File

@ -11,7 +11,8 @@ import com.img.rabbit.provider.storage.PreferenceUtil
import com.img.rabbit.provider.storage.PreferenceUtil.getBDVID import com.img.rabbit.provider.storage.PreferenceUtil.getBDVID
import com.img.rabbit.provider.utils.HeadParamUtils.applicationContext import com.img.rabbit.provider.utils.HeadParamUtils.applicationContext
import com.img.rabbit.provider.utils.HeadParamUtils.getAppVersionName import com.img.rabbit.provider.utils.HeadParamUtils.getAppVersionName
import com.img.rabbit.uni.UniMPSplashView import com.img.rabbit.uni.UniMPAlipaySplashView
import com.img.rabbit.uni.UniMPWxSplashView
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.openapi.IWXAPI import com.tencent.mm.opensdk.openapi.IWXAPI
import io.dcloud.feature.sdk.DCUniMPSDK import io.dcloud.feature.sdk.DCUniMPSDK
@ -58,14 +59,14 @@ object UniAppUtils {
* 是否存在更新 * 是否存在更新
*/ */
fun isUpdate(uniVersion: UniVersionEntity): Boolean{ fun isUpdate(uniVersion: UniVersionEntity): Boolean{
return checkUpdate(uniVersion, PreferenceUtil.getWgtVersion()?:"0.0.0") return checkUpdate(uniVersion, PreferenceUtil.getWgtVersion(uniVersion.unimp_id)?:"0.0.0")
} }
/** /**
* 是否强制更新 * 是否强制更新
*/ */
private fun isUpdateForce(uniVersion: UniVersionEntity): Boolean{ private fun isUpdateForce(uniVersion: UniVersionEntity): Boolean{
return checkUpdate(uniVersion, PreferenceUtil.getWgtVersion()?:"0.0.0") && uniVersion.force return checkUpdate(uniVersion, PreferenceUtil.getWgtVersion(uniVersion.unimp_id)?:"0.0.0") && uniVersion.force
} }
/** /**
@ -96,8 +97,8 @@ object UniAppUtils {
if(version.isEmpty()){ if(version.isEmpty()){
return false return false
} }
val newVersions = version.split("\\.") val newVersions = version.split(".")
val originVersions = currentVersion.split("\\.") val originVersions = currentVersion.split(".")
if(newVersions.size != 3){ if(newVersions.size != 3){
return false return false
@ -144,7 +145,9 @@ object UniAppUtils {
Log.i("UniAppUtils", "startUniMp: 重新加载...") Log.i("UniAppUtils", "startUniMp: 重新加载...")
val configuration = getUniMPOpenConfiguration() val configuration = getUniMPOpenConfiguration()
if(uniVersion.unimp_type == "wx"){ if(uniVersion.unimp_type == "wx"){
configuration.splashClass = UniMPSplashView::class.java configuration.splashClass = UniMPWxSplashView::class.java
}else if("alipay" == uniVersion.unimp_type){
configuration.splashClass = UniMPAlipaySplashView::class.java
} }
updateUniMp(uniVersion.unimp_id, DCUniMPSDK.getInstance().openUniMP(context, uniVersion.unimp_id, configuration)) updateUniMp(uniVersion.unimp_id, DCUniMPSDK.getInstance().openUniMP(context, uniVersion.unimp_id, configuration))
} }
@ -174,11 +177,15 @@ object UniAppUtils {
// 启动直达页面 // 启动直达页面
val configuration = getUniMPOpenConfiguration() val configuration = getUniMPOpenConfiguration()
if(uniMpType == "wx"){ if(uniMpType == "wx"){
configuration.splashClass = UniMPSplashView::class.java configuration.splashClass = UniMPWxSplashView::class.java
}
if(uniMpType == "wx"){
configuration.splashClass = UniMPWxSplashView::class.java
}else if("alipay" == uniMpType){
configuration.splashClass = UniMPAlipaySplashView::class.java
} }
configuration.path = pagePath configuration.path = pagePath
updateUniMp(uniMpId, DCUniMPSDK.getInstance().openUniMP(context, uniMpId, configuration)) updateUniMp(uniMpId, DCUniMPSDK.getInstance().openUniMP(context, uniMpId, configuration))
// uniMpPair[uniMpId] = DCUniMPSDK.getInstance().openUniMP(context, uniMpId, configuration)
} }
private fun releaseWgt(versionEntity: UniVersionEntity, onReleaseWgt: (isSuccess: Boolean, versionEntity: UniVersionEntity) -> Unit) { private fun releaseWgt(versionEntity: UniVersionEntity, onReleaseWgt: (isSuccess: Boolean, versionEntity: UniVersionEntity) -> Unit) {
@ -225,6 +232,7 @@ object UniAppUtils {
downloadUniMp(scope, uniVersion){uniState, filePath, progress -> downloadUniMp(scope, uniVersion){uniState, filePath, progress ->
onProgress(uniState, filePath, progress) onProgress(uniState, filePath, progress)
if(uniState == UniMpUpdate.DOWNLOAD_FINISH){ if(uniState == UniMpUpdate.DOWNLOAD_FINISH){
PreferenceUtil.saveWgtVersion(uniVersion.unimp_id, uniVersion.version)
distributeUniMp(context, uniVersion) { _ ->} distributeUniMp(context, uniVersion) { _ ->}
} }
} }
@ -242,6 +250,7 @@ object UniAppUtils {
downloadUniMp(scope, uniVersion){uniState, _, progress -> downloadUniMp(scope, uniVersion){uniState, _, progress ->
onProgress(UniMpUpdate.DOWNLOAD_LOADING, progress) onProgress(UniMpUpdate.DOWNLOAD_LOADING, progress)
if(uniState == UniMpUpdate.DOWNLOAD_FINISH){ if(uniState == UniMpUpdate.DOWNLOAD_FINISH){
PreferenceUtil.saveWgtVersion(uniVersion.unimp_id, uniVersion.version)
onProgress(UniMpUpdate.DOWNLOAD_FINISH, 1f) onProgress(UniMpUpdate.DOWNLOAD_FINISH, 1f)
scope.launch { scope.launch {
val uniMPReleaseConfiguration = UniMPReleaseConfiguration().apply { val uniMPReleaseConfiguration = UniMPReleaseConfiguration().apply {
@ -278,6 +287,7 @@ object UniAppUtils {
val uniMpID = uniVersion.unimp_id val uniMpID = uniVersion.unimp_id
val wgtName = String.format("%s.wgt", uniMpID) val wgtName = String.format("%s.wgt", uniMpID)
val path = FileUtils.getInstance().cacheUniAppDir.absolutePath val path = FileUtils.getInstance().cacheUniAppDir.absolutePath
Log.i("UniAppUtils", "下载wgt---->downloadUniMp: $path/$wgtName ------>${uniVersion.url}")
UpdateUtils.download( UpdateUtils.download(
scope = scope, scope = scope,
url = uniVersion.url, url = uniVersion.url,

View File

@ -2,6 +2,7 @@ package com.img.rabbit.viewmodel
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.img.rabbit.provider.utils.NetworkUtils.globalNetworkStatus
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -12,6 +13,10 @@ open class BaseViewModel : ViewModel() {
val isLoading = mutableStateOf(false) val isLoading = mutableStateOf(false)
fun mLaunch(block: suspend () -> Unit) { fun mLaunch(block: suspend () -> Unit) {
if (!globalNetworkStatus) {
isLoading.value = false // 加载完成
return
}
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
block() block()

View File

@ -1,7 +1,6 @@
package com.img.rabbit.viewmodel package com.img.rabbit.viewmodel
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Application
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Context.RECEIVER_EXPORTED import android.content.Context.RECEIVER_EXPORTED
@ -14,28 +13,24 @@ import android.net.NetworkRequest
import android.os.Build import android.os.Build
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.img.rabbit.config.Constants import com.img.rabbit.config.Constants
import com.img.rabbit.provider.api.ApiManager import com.img.rabbit.provider.api.ApiManager
import com.img.rabbit.provider.storage.PreferenceUtil import com.img.rabbit.provider.storage.PreferenceUtil
import com.img.rabbit.provider.utils.HeadParamUtils
import com.img.rabbit.provider.utils.NetworkUtils.globalNetworkStatus
import com.tencent.mm.opensdk.constants.ConstantsAPI import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.openapi.IWXAPI import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.WXAPIFactory import com.tencent.mm.opensdk.openapi.WXAPIFactory
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@SuppressLint("ObsoleteSdkInt") @SuppressLint("ObsoleteSdkInt")
class GeneralViewModel(application: Application) : AndroidViewModel(application) { class GeneralViewModel: BaseViewModel(){
lateinit var api: IWXAPI lateinit var api: IWXAPI
lateinit var receiver: BroadcastReceiver lateinit var receiver: BroadcastReceiver
private val _networkStatus = MutableLiveData<Boolean>() private val _networkStatus = MutableLiveData<Boolean>()
val networkStatus: LiveData<Boolean> = _networkStatus val networkStatus: LiveData<Boolean> = _networkStatus
fun setNetworkStatus(status: Boolean) {
_networkStatus.value = status
}
private val _serverTime = mutableStateOf<Long?>(null) private val _serverTime = mutableStateOf<Long?>(null)
val serverTime: State<Long?> = _serverTime val serverTime: State<Long?> = _serverTime
@ -44,15 +39,17 @@ class GeneralViewModel(application: Application) : AndroidViewModel(application)
val isNavigationBarVisible: LiveData<Boolean> = _isNavigationBarVisible val isNavigationBarVisible: LiveData<Boolean> = _isNavigationBarVisible
private val connectivityManager = private val connectivityManager =
application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager HeadParamUtils.applicationContext?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() { private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
_networkStatus.postValue(true) _networkStatus.postValue(true)
globalNetworkStatus = true
} }
override fun onLost(network: Network) { override fun onLost(network: Network) {
_networkStatus.postValue(false) _networkStatus.postValue(false)
globalNetworkStatus = false
} }
} }
@ -76,7 +73,7 @@ class GeneralViewModel(application: Application) : AndroidViewModel(application)
_agreementStatus.value = PreferenceUtil.getAgreement() _agreementStatus.value = PreferenceUtil.getAgreement()
// 初始化微信API // 初始化微信API
initWXApi(application) HeadParamUtils.applicationContext?.let { initWXApi(it) }
} }
private fun isNetworkAvailable(): Boolean { private fun isNetworkAvailable(): Boolean {
@ -138,10 +135,7 @@ class GeneralViewModel(application: Application) : AndroidViewModel(application)
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
fun getServerTime() { fun getServerTime() {
if (networkStatus.value != true) { mLaunch {
return
}
GlobalScope.launch {
val response = ApiManager.serviceVo.getServerTime() val response = ApiManager.serviceVo.getServerTime()
if (response.status) { if (response.status) {
_serverTime.value = response.data _serverTime.value = response.data

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB