RobinTan1024 пре 4 година
родитељ
комит
25e2b8a182

+ 27 - 22
app/src/main/java/com/doverfuelingsolutions/issp/api/FuelInfoApi.kt

@@ -21,13 +21,7 @@ import kotlin.coroutines.suspendCoroutine
 
 object FuelInfoApi {
 
-    private val retrofit: Retrofit by lazy {
-        val ip = SPUtil.getString(SPKeys.FUEL_IP)
-        val port = SPUtil.getString(SPKeys.FUEL_PORT)
-        val url = "http://$ip:$port"
-        RetrofitUtil.getGsonBuilder().baseUrl(url).build()
-    }
-    private val serviceStation: ServiceStation by lazyOf(retrofit.create(ServiceStation::class.java))
+    private var serviceStation: ServiceStation = serviceMaker()
 
     suspend fun getNozzleInfo() = suspendCoroutine<DFSResult<List<NozzleInfo>>> {
         GlobalScope.launch(Dispatchers.IO) {
@@ -68,26 +62,11 @@ object FuelInfoApi {
         }
     }
 
-    private fun getLocalBarcodeMap(): Map<Int, String> {
-        return mutableMapOf<Int, String>().apply {
-            val localBarcodeList = SPUtil.getString(SPKeys.FUEL_BARCODE)
-            localBarcodeList.split(",").forEach {
-                val kv = it.split("=")
-                if (kv.size == 2) put(kv[0].toInt(), kv[1])
-            }
-        }
-    }
-
-    private fun setLocalBarcodeMap(map: Map<Int, String>) {
-        SPUtil.putString(SPKeys.FUEL_BARCODE, map.entries.joinToString(",") { "${it.key}=${it.value}" })
-    }
-
     private suspend fun getNozzleData() = suspendCoroutine<DFSResult<Array<ResultNozzleInfo>>> {
         serviceStation.getNozzleInfo().enqueue(object : Callback<Array<ResultNozzleInfo>> {
             override fun onResponse(call: Call<Array<ResultNozzleInfo>>, response: Response<Array<ResultNozzleInfo>>) {
                 val code = response.code()
                 val body = response.body()
-                DFSLog.v("FuelInfoApi.getNozzleData.onResponse", code, body.toString())
                 if (code == 200 && body != null) {
                     it.resume(DFSResult.success(body))
                     return
@@ -101,4 +80,30 @@ object FuelInfoApi {
             }
         })
     }
+
+    private fun getLocalBarcodeMap(): Map<Int, String> {
+        return mutableMapOf<Int, String>().apply {
+            val localBarcodeList = SPUtil.getString(SPKeys.FUEL_BARCODE)
+            localBarcodeList.split(",").forEach {
+                val kv = it.split("=")
+                if (kv.size == 2) put(kv[0].toInt(), kv[1])
+            }
+        }
+    }
+
+    private fun setLocalBarcodeMap(map: Map<Int, String>) {
+        SPUtil.putString(SPKeys.FUEL_BARCODE, map.entries.joinToString(",") { "${it.key}=${it.value}" })
+    }
+
+    private fun serviceMaker(): ServiceStation {
+        val ip = SPUtil.getString(SPKeys.FUEL_IP)
+        val port = SPUtil.getString(SPKeys.FUEL_PORT)
+        val url = "http://$ip:$port"
+        DFSLog.i("new url is $url")
+        return RetrofitUtil.getGsonBuilder().baseUrl(url).build().create(ServiceStation::class.java)
+    }
+
+    fun generateService() {
+        serviceStation = serviceMaker()
+    }
 }

+ 11 - 2
app/src/main/java/com/doverfuelingsolutions/issp/api/basic/LoggingInterceptor.kt

@@ -3,16 +3,25 @@ package com.doverfuelingsolutions.issp.api.basic
 import com.doverfuelingsolutions.issp.utils.log.DFSLog
 import okhttp3.Interceptor
 import okhttp3.Response
+import java.util.*
 
 class LoggingInterceptor : Interceptor {
 
+    private var index = 1
+
     override fun intercept(chain: Interceptor.Chain): Response {
+        if (index >= 1000) index = 1
+        val currentIndex = index
+        index++
+
         val request = chain.request()
+        DFSLog.v("==========>>>>>>>>>> request $currentIndex <<<<<<<<<<==========")
+        DFSLog.v("${request.method()} ${request.url()}")
         val response = chain.proceed(request)
-        DFSLog.v("==========>>>>>>>>>> request <<<<<<<<<<==========")
         val body = response.body()
         val stringBody = if (body == null) "null" else response.peekBody(Long.MAX_VALUE).string()
-        DFSLog.v("${request.method()} ${request.url()}", response.code(), stringBody)
+        DFSLog.v("==========>>>>>>>>>> response $currentIndex <<<<<<<<<<==========")
+        DFSLog.v(response.code(), stringBody)
         return response
     }
 }

+ 1 - 0
app/src/main/java/com/doverfuelingsolutions/issp/fusion/FusionError.kt

@@ -5,4 +5,5 @@ enum class FusionError(val value: Int) {
     Timeout(1),
     Login(2),
     GetNozzleInfo(3),
+    WrongAddress(4),
 }

+ 33 - 22
app/src/main/java/com/doverfuelingsolutions/issp/fusion/FusionManager.kt

@@ -27,23 +27,25 @@ object FusionManager : LifecycleObserver, OnFdcClientStateChangedListener,
     OnFdcServiceResponseReceivedListener,
     OnFdcMessageReceivedListener {
 
-    private var mStateFusion: FdcClient.FdcClientState = FdcClient.FdcClientState.Stopped
-    private var mIsLogin = false
+    var stateFusion: FdcClient.FdcClientState = FdcClient.FdcClientState.Stopped
+    private const val timeoutMax = 4000
+    private var isLogin = false
     private val nozzleList = arrayListOf<NozzleInfo>()
 
     private val coroutineIO = CoroutineScope(Dispatchers.IO)
 
-    val stateFusion: FdcClient.FdcClientState get() = mStateFusion
-    val isLogin: Boolean get() = mIsLogin
     var onFusionEvent: OnFusionEvent? = null
 
     override fun onFdcClientStateChanged(sender: FdcClient?, state: FdcClient.FdcClientState?) {
         DFSLog.i("Fusion: state = ${state?.name}")
         if (sender == null || state == null) return
 
-        mStateFusion = state
+        stateFusion = state
         when (state) {
             FdcClient.FdcClientState.Connected -> loginFetchInfo()
+            // 中途断网重连
+            FdcClient.FdcClientState.Connecting -> onFusionEvent?.onFusionReconnect()
+            FdcClient.FdcClientState.MyAddReConnect -> onFusionEvent?.onFusionInit(FusionError.WrongAddress, StringUtil.get(R.string.wrong_fusion_address))
             else -> {}
         }
     }
@@ -75,7 +77,7 @@ object FusionManager : LifecycleObserver, OnFdcClientStateChangedListener,
 
         coroutineIO.launch {
             delay(12000)
-            if (mStateFusion != FdcClient.FdcClientState.Connected) {
+            if (stateFusion == FdcClient.FdcClientState.Stopped) {
                 onFusionEvent?.onFusionInit(FusionError.Timeout, StringUtil.get(R.string.connect_timeout))
             }
         }
@@ -93,21 +95,30 @@ object FusionManager : LifecycleObserver, OnFdcClientStateChangedListener,
         }
     }
 
-    private fun loginFetchInfo() {
+    fun restart() {
         coroutineIO.launch {
-            // retry if failed
-            val success = if (login()) true else {
-                DFSLog.d("Fusion: retry login after logout")
-                logout()
-                delay(7000)
-                login()
-            }
-            if (!success) {
-                mIsLogin = false
-                onFusionEvent?.onFusionInit(FusionError.Login, StringUtil.get(R.string.login_fail))
-                return@launch
-            } else {
-                mIsLogin = true
+            close()
+            delay(timeoutMax.toLong() + 1000L)
+            initialize()
+        }
+    }
+
+    fun loginFetchInfo() {
+        coroutineIO.launch {
+            if (!isLogin) {
+                val success = if (login()) true else {
+                    DFSLog.d("Fusion: retry login after logout")
+                    logout()
+                    delay(7000)
+                    login()
+                }
+                if (!success) {
+                    isLogin = false
+                    onFusionEvent?.onFusionInit(FusionError.Login, StringUtil.get(R.string.login_fail))
+                    return@launch
+                } else {
+                    isLogin = true
+                }
             }
 
             val resultNozzles = FuelInfoApi.getNozzleInfo()
@@ -135,7 +146,7 @@ object FusionManager : LifecycleObserver, OnFdcClientStateChangedListener,
                     it.resume(false)
                 }
             }
-        }, 10000)
+        }, timeoutMax)
     }
 
     private suspend fun logout() = suspendCoroutine<Boolean> {
@@ -149,6 +160,6 @@ object FusionManager : LifecycleObserver, OnFdcClientStateChangedListener,
                 DFSLog.d("Fusion: logout failed")
                 it.resume(false)
             }
-        }, 10000)
+        }, timeoutMax)
     }
 }

+ 2 - 0
app/src/main/java/com/doverfuelingsolutions/issp/fusion/callback/OnFusionEvent.kt

@@ -5,4 +5,6 @@ import com.doverfuelingsolutions.issp.fusion.FusionError
 interface OnFusionEvent {
 
     fun onFusionInit(code: FusionError, msg: String = "")
+
+    fun onFusionReconnect()
 }

+ 95 - 17
app/src/main/java/com/doverfuelingsolutions/issp/view/MainActivity.kt

@@ -4,9 +4,11 @@ import android.content.Context
 import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
+import android.view.View
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
 import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.lifecycleScope
@@ -18,15 +20,16 @@ import com.doverfuelingsolutions.issp.fusion.FusionManager
 import com.doverfuelingsolutions.issp.fusion.callback.OnFusionEvent
 import com.doverfuelingsolutions.issp.utils.ActivityUtil
 import com.doverfuelingsolutions.issp.utils.StringUtil
-import com.doverfuelingsolutions.issp.view.fragment.FragmentInit
+import com.doverfuelingsolutions.issp.utils.log.DFSLog
+import com.doverfuelingsolutions.issp.view.fragment.FragmentHolder
 import com.doverfuelingsolutions.issp.view.fragment.FragmentSelect
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.wayne.www.waynelib.fdc.FdcClient
 import com.youth.banner.adapter.BannerImageAdapter
 import com.youth.banner.holder.BannerImageHolder
 import kotlinx.coroutines.launch
 import java.io.File
 
-class MainActivity : AppCompatActivity(), OnFusionEvent {
+class MainActivity : AppCompatActivity(), OnFusionEvent, View.OnLongClickListener {
 
     companion object {
         fun start(context: Context) {
@@ -37,7 +40,8 @@ class MainActivity : AppCompatActivity(), OnFusionEvent {
     private val binding: ActivityMainBinding by lazy { DataBindingUtil.setContentView(this, R.layout.activity_main) }
     private val mainViewModel: MainViewModel by viewModels()
 
-    private val fragmentInit = FragmentInit()
+    private val fragmentHolder = FragmentHolder()
+    private val fragmentSelect = FragmentSelect()
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -52,23 +56,80 @@ class MainActivity : AppCompatActivity(), OnFusionEvent {
         ActivityUtil.setFullscreen(this)
     }
 
+    override fun onDestroy() {
+        super.onDestroy()
+
+        FusionManager.onFusionEvent = null
+    }
+
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+        super.onActivityResult(requestCode, resultCode, data)
+
+        when (requestCode) {
+            PreferenceActivity.codeRequestResult -> {
+                data?.let {
+                    val isMiddleModified = it.getBooleanExtra(PreferenceActivity.isMiddleModified, false)
+                    val isFuelModified = it.getBooleanExtra(PreferenceActivity.isFuelModified, false)
+                    if (!isFuelModified && !isMiddleModified) return@let
+
+                    setFragment(fragmentHolder)
+                    if (isMiddleModified || FusionManager.stateFusion != FdcClient.FdcClientState.Connected) {
+                        fragmentHolder.loading(StringUtil.get(R.string.in_reconnect_fusion))
+                        FusionManager.restart()
+                    } else if (isFuelModified && FusionManager.stateFusion == FdcClient.FdcClientState.Connected) {
+                        fragmentHolder.loading(StringUtil.get(R.string.in_get_fuel))
+                        FusionManager.loginFetchInfo()
+                    }
+                }
+            }
+        }
+    }
+
+    override fun onLongClick(v: View?): Boolean {
+        when (v) {
+            binding.clock -> {
+                PreferenceActivity.startForResult(this)
+            }
+        }
+        return false
+    }
+
     override fun onFusionInit(code: FusionError, msg: String) {
         lifecycleScope.launch {
-            if (code != FusionError.Success) {
-                fragmentInit.fail(msg)
-                return@launch
-                MaterialAlertDialogBuilder(this@MainActivity)
-                    .setTitle(R.string.tip_opt_fail)
-                    .setCancelable(false)
-                    .setMessage(StringUtil.get(R.string.tip_connect_fail_reason_config, msg))
-                    .setPositiveButton(R.string.go_check) { _, _ ->
-                        PreferenceActivity.start(this@MainActivity)
+            // WrongAddress Timeout 需要修改中控信息,返回时如已修改则重启Fusion
+            // GetNozzleInfo 不重启Fusion,重新请求加油信息即可
+            when (code) {
+                FusionError.Success -> {
+                    setFragment(fragmentSelect)
+                }
+                FusionError.WrongAddress, FusionError.Timeout, FusionError.GetNozzleInfo -> {
+                    setFragment(fragmentHolder)
+                    val buttonText = if (code == FusionError.GetNozzleInfo) {
+                        StringUtil.get(R.string.go_check_fuel)
+                    } else {
+                        StringUtil.get(R.string.go_check_fusion)
+                    }
+                    fragmentHolder.action(StringUtil.get(R.string.connect_fail_reason, msg), buttonText) {
+                        PreferenceActivity.startForResult(this@MainActivity)
+                    }
+                }
+                FusionError.Login -> {
+                    setFragment(fragmentHolder)
+                    fragmentHolder.action(StringUtil.get(R.string.connect_fail_reason, msg), StringUtil.get(R.string.retry_login)) {
+                        FusionManager.loginFetchInfo()
                     }
-                    .show()
+                }
             }
         }
     }
 
+    override fun onFusionReconnect() {
+        lifecycleScope.launch {
+            setFragment(fragmentHolder)
+            fragmentHolder.loading(StringUtil.get(R.string.in_reconnect_fusion))
+        }
+    }
+
     private fun initView() {
         supportActionBar?.hide()
         mainViewModel.stationName.value = GlobalData.businessName.get()
@@ -84,17 +145,34 @@ class MainActivity : AppCompatActivity(), OnFusionEvent {
                     }
                 }
         }
+        binding.clock.setOnLongClickListener(this)
     }
 
     private fun initFusion() {
-        supportFragmentManager.beginTransaction()
-            .add(R.id.fragmentBox, fragmentInit)
-            .commit()
+        setFragment(fragmentHolder)
 
         FusionManager.onFusionEvent = this
         lifecycle.addObserver(FusionManager)
     }
 
+    private fun setFragment(fragment: Fragment, back: Boolean = false) {
+        val contain = supportFragmentManager.fragments.contains(fragment)
+        val show = fragment.isHidden
+
+        if (contain && !show) return
+
+        val transaction = supportFragmentManager.beginTransaction()
+        supportFragmentManager.fragments.forEach {
+            if (fragment != it && !it.isHidden) transaction.hide(it)
+        }
+        if (!contain) {
+            transaction.add(R.id.fragmentBox, fragment)
+        } else if (fragment.isHidden) {
+            transaction.show(fragment)
+        }
+        transaction.commit()
+    }
+
     class MainViewModel : ViewModel() {
         val stationName = MutableLiveData("")
     }

+ 54 - 1
app/src/main/java/com/doverfuelingsolutions/issp/view/PreferenceActivity.kt

@@ -1,22 +1,42 @@
 package com.doverfuelingsolutions.issp.view
 
+import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.os.Bundle
 import android.view.MenuItem
 import androidx.appcompat.app.AppCompatActivity
 import com.doverfuelingsolutions.issp.R
+import com.doverfuelingsolutions.issp.api.CloudApi
+import com.doverfuelingsolutions.issp.api.FuelInfoApi
+import com.doverfuelingsolutions.issp.utils.sp.SPKeys
+import com.doverfuelingsolutions.issp.utils.sp.SPUtil
 import com.doverfuelingsolutions.issp.view.fragment.FragmentPreference
 
 class PreferenceActivity : AppCompatActivity() {
 
     companion object {
 
+        const val codeRequestResult = 1001
+        const val isMiddleModified = "isMiddleModified"
+        const val isFuelModified = "isFuelModified"
+
         fun start(context: Context) {
             Intent(context, PreferenceActivity::class.java).let { context.startActivity(it) }
         }
+
+        fun startForResult(activity: Activity) {
+            Intent(activity, PreferenceActivity::class.java).let {
+                it.putExtra("forResult", true)
+                activity.startActivityForResult(it, codeRequestResult)
+            }
+        }
     }
 
+    private var isForResult = false
+    private var oldMiddleInfo = ""
+    private var oldFuelInfo = ""
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_preference)
@@ -27,12 +47,45 @@ class PreferenceActivity : AppCompatActivity() {
                 .replace(R.id.container, FragmentPreference())
                 .commit()
         }
+
+        val forResult = intent.getBooleanExtra("forResult", false)
+        if (forResult) {
+            isForResult = true
+            oldMiddleInfo = makeMiddleInfo()
+            oldFuelInfo = makeFuelInfo()
+        } else {
+            isForResult = false
+        }
+    }
+
+    override fun onBackPressed() {
+        val hasMiddleModified = makeMiddleInfo() != oldMiddleInfo
+        val hasFuelModified = makeFuelInfo() != oldFuelInfo
+        if (hasMiddleModified) CloudApi.regenerateAllService()
+        if (hasFuelModified) FuelInfoApi.generateService()
+        if (isForResult) {
+            setResult(Activity.RESULT_OK, Intent().apply {
+                putExtra(isMiddleModified, hasMiddleModified)
+                putExtra(isFuelModified, hasFuelModified)
+            })
+            finish()
+        } else {
+            super.onBackPressed()
+        }
     }
 
     override fun onOptionsItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
-            android.R.id.home -> finish()
+            android.R.id.home -> onBackPressed()
         }
         return super.onOptionsItemSelected(item)
     }
+
+    private fun makeMiddleInfo(): String {
+        return "${SPUtil.getString(SPKeys.MIDDLE_IP)}, ${SPUtil.getString(SPKeys.MIDDLE_PORT)}, ${SPUtil.getString(SPKeys.MIDDLE_WORKSTATION_ID)}"
+    }
+
+    private fun makeFuelInfo(): String {
+        return "${SPUtil.getString(SPKeys.FUEL_IP)}, ${SPUtil.getString(SPKeys.FUEL_PORT)}"
+    }
 }

+ 53 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentHolder.kt

@@ -0,0 +1,53 @@
+package com.doverfuelingsolutions.issp.view.fragment
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.doverfuelingsolutions.issp.R
+import com.doverfuelingsolutions.issp.databinding.FragmentHolderBinding
+import com.doverfuelingsolutions.issp.utils.StringUtil
+
+class FragmentHolder : Fragment() {
+
+    companion object {
+        const val UI_LOADING = 1
+        const val UI_ACTION = 2
+    }
+
+    private lateinit var binding: FragmentHolderBinding
+    private val holderViewModel: FragmentHolderViewModel by viewModels()
+    private var buttonHandler: (() -> Unit)? = null
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_holder, container, false)
+        binding.lifecycleOwner = viewLifecycleOwner
+        binding.viewModel = holderViewModel
+        binding.actionButton.setOnClickListener { buttonHandler?.invoke() }
+        return binding.root
+    }
+
+    fun action(msg: String, buttonText: String, func: (() -> Unit)? = null) {
+        holderViewModel.uiType.value = UI_ACTION
+        holderViewModel.actionButtonText.value = buttonText
+        holderViewModel.actionText.value = msg
+        buttonHandler = func
+    }
+
+    fun loading(msg: String) {
+        holderViewModel.uiType.value = UI_LOADING
+        holderViewModel.loadingTip.value = msg
+    }
+
+    class FragmentHolderViewModel : ViewModel() {
+        val uiType = MutableLiveData(UI_LOADING)
+        val loadingTip = MutableLiveData(StringUtil.get(R.string.in_connect_fusion))
+        val actionText = MutableLiveData(StringUtil.get(R.string.connect_timeout))
+        val actionButtonText = MutableLiveData(StringUtil.get(R.string.go_check_fusion))
+    }
+}

+ 0 - 38
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentInit.kt

@@ -1,38 +0,0 @@
-package com.doverfuelingsolutions.issp.view.fragment
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.databinding.DataBindingUtil
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import com.doverfuelingsolutions.issp.R
-import com.doverfuelingsolutions.issp.databinding.FragmentInitBinding
-import com.doverfuelingsolutions.issp.utils.StringUtil
-
-class FragmentInit : Fragment() {
-
-    private lateinit var binding: FragmentInitBinding
-    private val initViewModel: FragmentInitViewModel by viewModels()
-
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
-        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_init, container, false)
-        binding.lifecycleOwner = viewLifecycleOwner
-        binding.viewModel = initViewModel
-        return binding.root
-    }
-
-    fun fail(msg: String) {
-        initViewModel.isLoading.value = false
-        initViewModel.failTip.value = StringUtil.get(R.string.tip_connect_fail_reason_config, msg)
-    }
-
-    class FragmentInitViewModel : ViewModel() {
-        val isLoading = MutableLiveData(true)
-        val loadingTip = MutableLiveData(StringUtil.get(R.string.in_connect_fusion))
-        val failTip = MutableLiveData(StringUtil.get(R.string.connect_timeout))
-    }
-}

+ 1 - 6
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentPreference.kt

@@ -9,6 +9,7 @@ import androidx.preference.Preference
 import androidx.preference.PreferenceFragmentCompat
 import com.doverfuelingsolutions.issp.R
 import com.doverfuelingsolutions.issp.api.CloudApi
+import com.doverfuelingsolutions.issp.api.FuelInfoApi
 import com.doverfuelingsolutions.issp.utils.StringUtil
 import com.doverfuelingsolutions.issp.utils.ValidateUtil
 import com.doverfuelingsolutions.issp.utils.log.DFSLog
@@ -59,12 +60,6 @@ class FragmentPreference : PreferenceFragmentCompat(), EditTextPreference.OnBind
         return result
     }
 
-    override fun onDetach() {
-        super.onDetach()
-
-        CloudApi.regenerateAllService()
-    }
-
     private fun setNumberInput(key: String): EditTextPreference? {
         val fragment = this@FragmentPreference
         return findPreference<EditTextPreference>(key)?.apply {

+ 1 - 1
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentSelect.kt

@@ -51,7 +51,7 @@ class FragmentSelect : Fragment(), View.OnClickListener, View.OnLongClickListene
     }
 
     class SearchTypeViewModel : ViewModel() {
-        val deviceNum = MutableLiveData(GlobalData.serialNumber)
+        val deviceNum = MutableLiveData(GlobalData.serialNumber.get())
         val version: MutableLiveData<String> by lazy {
             val pm = DFSApplication.instance.applicationContext.packageManager
             val info = pm.getPackageInfo(DFSApplication.instance.applicationContext.packageName, android.content.pm.PackageManager.GET_ACTIVITIES)

+ 1 - 1
app/src/main/res/layout/activity_main.xml

@@ -50,7 +50,7 @@
                 android:contentDescription="@string/app_name" />
 
             <TextClock
-                android:id="@+id/textClock"
+                android:id="@+id/clock"
                 style="@style/wrap"
                 android:layout_marginStart="8dp"
                 android:format12Hour="@string/format_date"

+ 8 - 6
app/src/main/res/layout/fragment_init.xml → app/src/main/res/layout/fragment_holder.xml

@@ -5,10 +5,11 @@
     <data>
 
         <import type="android.view.View" />
+        <import type="com.doverfuelingsolutions.issp.view.fragment.FragmentHolder" />
 
         <variable
             name="viewModel"
-            type="com.doverfuelingsolutions.issp.view.fragment.FragmentInit.FragmentInitViewModel" />
+            type="com.doverfuelingsolutions.issp.view.fragment.FragmentHolder.FragmentHolderViewModel" />
     </data>
 
     <androidx.constraintlayout.widget.ConstraintLayout
@@ -16,7 +17,7 @@
 
         <!--loading-->
         <androidx.appcompat.widget.LinearLayoutCompat
-            android:visibility="@{viewModel.isLoading ? View.VISIBLE : View.GONE}"
+            android:visibility="@{viewModel.uiType == FragmentHolder.UI_LOADING ? View.VISIBLE : View.GONE}"
             style="@style/wrap"
             android:gravity="center"
             android:orientation="vertical"
@@ -37,9 +38,9 @@
                 android:textSize="18sp" />
         </androidx.appcompat.widget.LinearLayoutCompat>
 
-        <!--go preference-->
+        <!--info + button-->
         <androidx.appcompat.widget.LinearLayoutCompat
-            android:visibility="@{!viewModel.isLoading ? View.VISIBLE : View.GONE}"
+            android:visibility="@{viewModel.uiType == FragmentHolder.UI_ACTION ? View.VISIBLE : View.GONE}"
             style="@style/wrap"
             android:gravity="center"
             android:orientation="vertical"
@@ -51,14 +52,15 @@
             <androidx.appcompat.widget.AppCompatTextView
                 style="@style/wrap"
                 android:layout_marginBottom="60dp"
-                android:text="@{viewModel.failTip, default=@string/tip_connect_fail_reason_config}"
+                android:text="@{viewModel.actionText, default=@string/connect_fail}"
                 android:textSize="26sp" />
 
             <Button
+                android:id="@+id/actionButton"
                 style="@style/Widget.MaterialComponents.Button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/go_check" />
+                android:text="@{viewModel.actionButtonText, default=@string/go_check_fusion}" />
         </androidx.appcompat.widget.LinearLayoutCompat>
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>

+ 1 - 1
app/src/main/res/values/keys.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
     <string name="sp_first_launch">first_launch</string>
     <string name="sp_account_name">account_name</string>
     <string name="sp_password">password</string>

+ 8 - 2
app/src/main/res/values/strings.xml

@@ -58,10 +58,16 @@
     <string name="version_is">版本号:%1$s</string>
 
     <string name="in_connect_fusion">正在连接中控系统&#8230;</string>
-    <string name="tip_connect_fail_reason_config">连接中控系统异常:%1$s,请检查应用设置是否正确</string>
+    <string name="in_reconnect_fusion">正在重新连接中控系统&#8230;</string>
+    <string name="in_get_fuel">正在获取油品信息&#8230;</string>
+    <string name="connect_fail_reason">连接中控系统异常:%1$s</string>
     <string name="fail_get_nozzle">获取枪油品信息失败</string>
     <string name="connect_timeout">连接中控超时</string>
-    <string name="go_check">前往检查</string>
+    <string name="connect_fail">连接失败</string>
+    <string name="wrong_fusion_address">中控地址信息错误</string>
+    <string name="go_check_fusion">前往检查中控信息</string>
+    <string name="go_check_fuel">前往检查加油信息</string>
+    <string name="retry_login">重试登录</string>
 
     <string name="format_date">yyyy-MM-dd HH:mm:ss</string>