Bladeren bron

Merge branch 'release/1.2.15'

Zhenghanjv 6 dagen geleden
bovenliggende
commit
0227e01a57

+ 6 - 0
.idea/AndroidProjectSystem.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AndroidProjectSystem">
+    <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
+  </component>
+</project>

+ 17 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
+        <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
+        <option value="com.intellij.execution.junit.PatternConfigurationProducer" />
+        <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
+        <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
+        <option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
+        <option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
+        <option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 2 - 2
app/build.gradle

@@ -21,8 +21,8 @@ android {
         applicationId "com.doverfuelingsolutions.issp"
         minSdkVersion 22
         targetSdkVersion 26
-        versionCode 23
-        versionName "1.2.10"
+        versionCode 28
+        versionName "1.2.15"
         archivesBaseName = versionName + "." + getTime()
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

+ 26 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/SystemApi.kt

@@ -39,6 +39,28 @@ object SystemApi {
     private var serviceAssets = makeAssetsService()
     private var serviceCheck = makeCheckService()
 
+    /**
+     * 获取账户对应设备
+     */
+    suspend fun getUserDevice(accountName: String,SN:String) = suspendCoroutine<DFSResult<Boolean>> {
+        DFSLog.i("验证当前账户:${accountName}是否可以登录设备:${SN}")
+        serviceCheck.getUserDevice(accountName,SN).enqueue(object :Callback<UserDevice>{
+            override fun onResponse(call: Call<UserDevice>, response: Response<UserDevice>) {
+                val code = response.code()
+                val body = response.body()
+                DFSLog.i("验证当前账户:${accountName}是否可以登录设备:${SN}结果:$body")
+
+
+                it.resume(DFSResult.success((body?.result)?:false))
+            }
+
+            override fun onFailure(call: Call<UserDevice>, t: Throwable) {
+                DFSLog.e("验证当前账户:${accountName}是否可以登录设备:${SN}失败",t.message)
+                it.resume(DFSResult.fail("验证当前账户:${accountName}是否可以登录设备:${SN}失败,${t.message}"))
+            }
+        })
+    }
+
     /**
      * 登录 + 获取油站信息
      */
@@ -275,6 +297,9 @@ object SystemApi {
                     codeResponse == 406 -> {
                         it.resume(DFSResult.fail("优惠券核销不通过"))
                     }
+                    codeResponse == 410 -> {
+                        it.resume(DFSResult.fail("订单支付中"))
+                    }
                     else -> {
                         it.resume(DFSResult.fail(R.string.fail_pay))
                     }
@@ -527,6 +552,7 @@ object SystemApi {
         serviceTrx = makeTrxService()
         servicePay = makePayService()
         serviceConfig = makeConfigService()
+        serviceCheck = makeCheckService()
     }
 
     /**

+ 7 - 1
app/src/main/java/com/doverfuelingsolutions/issp/api/WayneApiConfig.kt

@@ -41,10 +41,12 @@ class WayneApiConfig {
         const val PORT_TRX_DEFAULT = "8699"
         const val PORT_CONFIG_DEFAULT = "8889"
         const val PORT_ASSETS_DEFAULT = "8080"
+        const val PORT_MIDDLE_TOOL_DEFAULT = "8721"
         private const val HOST_BASE_DEFAULT = "$DOMAIN_DEFAULT:$PORT_BASE_DEFAULT"
         private const val HOST_TRX_DEFAULT = "$DOMAIN_DEFAULT:$PORT_TRX_DEFAULT"
         private const val HOST_CONFIG_DEFAULT = "$DOMAIN_DEFAULT:$PORT_CONFIG_DEFAULT"
         private const val HOST_ASSETS_DEFAULT = "$DOMAIN_DEFAULT:$PORT_ASSETS_DEFAULT"
+        private const val HOST_MIDDLE_TOOL_DEFAULT = "$DOMAIN_DEFAULT_RELEASE:$PORT_MIDDLE_TOOL_DEFAULT"
         // 默认值 - 中控
         const val MIDDLE_IP_DEFAULT = "192.168.1.80"
         const val MIDDLE_PORT_DEFAULT = "4711"
@@ -82,7 +84,11 @@ class WayneApiConfig {
             return if (domain.isEmpty() || port.isEmpty()) HOST_ASSETS_DEFAULT else "$domain:$port"
         }
         val CHECK_ORDER_BASE:String get() {
-            return "http://tkhs.net.cn:8721"  //生产
+            val domain = SPUtil.getString(SPKeys.SERVER_DOMAIN)
+            val port = SPUtil.getString(SPKeys.SERVER_PORT_TOOL)
+            return if (domain.isEmpty() || port.isEmpty()) HOST_MIDDLE_TOOL_DEFAULT else "$domain:$port"
+
+//            return "http://tkhs.net.cn:8721"  //生产
 //            return "http://47.97.120.160:8721"//测试
 //            return "http://47.101.220.106:8721" //开发
         }

+ 25 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/dto/UserDevice.kt

@@ -0,0 +1,25 @@
+package com.doverfuelingsolutions.issp.api.dto
+
+import com.google.gson.annotations.SerializedName
+
+data class UserDevice(
+    var result: Boolean? = null,
+
+    var statusCode: String? = null,
+
+    var message: String? = null
+
+
+)
+//
+//data class UserDeviceValue(
+//    /**
+//     * 账户
+//     */
+//    var Key: String? = null,
+//
+//    /**
+//     * 设备sn
+//     */
+//    var Value: String? = null
+//)

+ 4 - 0
app/src/main/java/com/doverfuelingsolutions/issp/api/service/ServiceCheck.kt

@@ -4,6 +4,7 @@ import com.doverfuelingsolutions.issp.api.WayneApiConfig
 import com.doverfuelingsolutions.issp.api.dto.CheckRequest
 import com.doverfuelingsolutions.issp.api.dto.CheckResponse
 import com.doverfuelingsolutions.issp.api.dto.ResultPayment
+import com.doverfuelingsolutions.issp.api.dto.UserDevice
 import com.wayne.www.waynelib.webservice.entity.PosTrxMop
 import retrofit2.Call
 import retrofit2.http.*
@@ -19,4 +20,7 @@ interface ServiceCheck {
         @Query("NozzleId") nozzleId:String,
         @Query("sn") sn: String,
         @Query("token") token:String = "123456789"): Call<CheckResponse>
+
+    @GET("api/Account/GetUserDevice_bool")
+    fun getUserDevice(@Query("UserID") userName:String,@Query("Sn") sn:String):Call<UserDevice>
 }

+ 1 - 0
app/src/main/java/com/doverfuelingsolutions/issp/utils/sp/SPKeys.kt

@@ -28,6 +28,7 @@ class SPKeys {
         val SERVER_PORT_TRX: String = StringUtil.get(R.string.sp_server_port_trx)
         val SERVER_PORT_CONFIG: String = StringUtil.get(R.string.sp_server_port_config)
         val SERVER_PORT_ASSETS: String = StringUtil.get(R.string.sp_server_port_assets)
+        val SERVER_PORT_TOOL: String = StringUtil.get(R.string.sp_server_port_tool)
         val MIDDLE_IP: String = StringUtil.get(R.string.sp_middle_ip)
         val MIDDLE_PORT: String = StringUtil.get(R.string.sp_middle_port)
         val MIDDLE_WORKSTATION_ID: String = StringUtil.get(R.string.sp_middle_workstation_id)

+ 8 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/LoginActivity.kt

@@ -2,6 +2,7 @@ package com.doverfuelingsolutions.issp.view
 
 import android.content.Context
 import android.content.Intent
+import android.os.Build
 import android.os.Bundle
 import android.view.View
 import androidx.activity.viewModels
@@ -107,6 +108,7 @@ class LoginActivity : AppCompatActivity(),
             val password = loginViewModel.password.value
             when {
                 accountName.isNullOrBlank() || password.isNullOrBlank() -> snackbar.setText(R.string.input_not_right).show()
+                !isRightAccountAndDevice(accountName) -> snackbar.setText(R.string.error_account_device).show()
                 else -> {
                     val result = SystemApi.login(accountName, password)
                     if (!result.success) snackbar.setText(StringUtil.get(R.string.login_fail_reason, result.message)).show()
@@ -154,6 +156,12 @@ class LoginActivity : AppCompatActivity(),
         finish()
     }
 
+    private suspend fun isRightAccountAndDevice(accountName:String):Boolean{
+        val userDevice = SystemApi.getUserDevice(accountName, GlobalData.serialNumber.get())
+
+        return userDevice.success && userDevice.data == true
+    }
+
     class LoginViewModel : ViewModel() {
         val accountName = MutableLiveData(GlobalData.accountName.get())
         val password = MutableLiveData(GlobalData.password.get())

+ 2 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentNozzle.kt

@@ -20,6 +20,7 @@ import com.doverfuelingsolutions.issp.utils.sp.SPUtil
 import com.doverfuelingsolutions.issp.view.MainActivity
 import com.doverfuelingsolutions.issp.view.adapter.ChooseListAdapter
 import com.doverfuelingsolutions.issp.view.fragment.callback.RefreshNozzle
+import com.doverfuelingsolutions.issp.view.util.ClickUtils
 import com.scwang.smart.refresh.header.ClassicsHeader
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.async
@@ -82,6 +83,7 @@ class FragmentNozzle private constructor() : FragmentBasic(),RefreshNozzle{
     }
 
     private fun select(physicalId: String) {
+        if (ClickUtils.isFastClick()) return
         if (GlobalData.paymentId.get() == -1) {
             DFSToastUtil.fail(R.string.fail_get_pay_param_retry)
             GlobalScope.launch {

+ 16 - 13
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentOrderList.kt

@@ -25,6 +25,7 @@ import com.doverfuelingsolutions.issp.view.MainActivity
 import com.doverfuelingsolutions.issp.view.adapter.ChooseListAdapter
 import com.doverfuelingsolutions.issp.view.adapter.OrderListAdapter
 import com.doverfuelingsolutions.issp.view.fragment.callback.RefreshOrder
+import com.doverfuelingsolutions.issp.view.util.ClickUtils
 import com.scwang.smart.refresh.header.ClassicsHeader
 import com.wayne.www.waynelib.fdc.message.DeviceClass
 import com.wayne.www.waynelib.util.log.DFSLog
@@ -112,6 +113,7 @@ class FragmentOrderList private constructor() : FragmentBasic(),RefreshOrder {
 //    }
 
     private fun selectOrder(dc: DeviceClass, type: Int, position: Int) {
+        if (ClickUtils.isFastClick()) return
         lifecycleScope.launchWhenStarted {
             when {
                 dc.releaseTokenElement == null || dc.releaseTokenAttribute == null -> {
@@ -236,24 +238,24 @@ class FragmentOrderList private constructor() : FragmentBasic(),RefreshOrder {
                         DFSLog.w("barcodeId:$barcodeId")
                     }
 
-                    // 获取云订单(本地需要缓存,避免重复生成订单)
-                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
-                    if (posTrx == null) {
-                        val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
-                        if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
-                            posTrx = resultReportPayment.data
-                            SPUtil.addWayneOrder(dc, posTrx)
-                        } else {
-                            dialog.dismiss()
-                            (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
-                            DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
-                        }
+                    // 获取云订单(本地需要缓存,避免重复生成订单),2025-07 ,从接口处理,不需要再缓存
+//                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
+//                    if (posTrx == null) {
+//
+//                    }
+                    var posTrx:PosTrx? = null
+                    val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
+                    if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
+                        posTrx = resultReportPayment.data
+                    } else {
+                        dialog.dismiss()
+                        (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
+                        DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
                     }
 
                     // 锁定订单
                     if (posTrx == null) return@launchWhenStarted
                     val resultLock = FusionManager.lockOrder(dc, true)
-                    dialog.dismiss()
                     (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
                     if (resultLock.success) {
                         dc.state = "Locked"
@@ -262,6 +264,7 @@ class FragmentOrderList private constructor() : FragmentBasic(),RefreshOrder {
                     } else {
                         DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.lock_order), resultLock.message))
                     }
+                    dialog.dismiss()
                 }
             } else {
                 dialog.dismiss()

+ 13 - 12
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentPayType.kt

@@ -112,18 +112,19 @@ class FragmentPayType private constructor(): FragmentBasic(), View.OnClickListen
                 DFSLog.w("barcodeId:$barcodeId")
             }
 
-            // 获取云订单(本地需要缓存,避免重复生成订单)
-            var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
-            if (posTrx == null) {
-                val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
-                if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
-                    posTrx = resultReportPayment.data
-                    SPUtil.addWayneOrder(dc, posTrx)
-                } else {
-                    dialog.dismiss()
-                    (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
-                    DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
-                }
+            // 获取云订单(本地需要缓存,避免重复生成订单),2025-07 ,从接口处理,不需要再缓存
+//                    var posTrx: PosTrx? = SPUtil.findWayneOrder(dc)
+//                    if (posTrx == null) {
+//
+//                    }
+            var posTrx:PosTrx? = null
+            val resultReportPayment = SystemApi.generateOrder(dc, posItemUniqueId)
+            if (resultReportPayment.success && resultReportPayment.data != null && !resultReportPayment.data.id.isNullOrEmpty()) {
+                posTrx = resultReportPayment.data
+            } else {
+                dialog.dismiss()
+                (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
+                DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.make_cloud_order), resultReportPayment.message))
             }
 
             // 锁定订单

+ 2 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/fragment/FragmentPreference.kt

@@ -24,6 +24,7 @@ class FragmentPreference : PreferenceFragmentCompat(), EditTextPreference.OnBind
         setNumberInput(SPKeys.SERVER_PORT_TRX)
         setNumberInput(SPKeys.SERVER_PORT_CONFIG)
         setNumberInput(SPKeys.SERVER_PORT_ASSETS)
+        setNumberInput(SPKeys.SERVER_PORT_TOOL)
         setNumberInput(SPKeys.MIDDLE_PORT)
         setNumberInput(SPKeys.MIDDLE_WORKSTATION_ID)
         setNumberInput(SPKeys.FUEL_PORT)
@@ -48,6 +49,7 @@ class FragmentPreference : PreferenceFragmentCompat(), EditTextPreference.OnBind
             SPKeys.SERVER_PORT_TRX,
             SPKeys.SERVER_PORT_CONFIG,
             SPKeys.SERVER_PORT_ASSETS,
+            SPKeys.SERVER_PORT_TOOL,
             SPKeys.MIDDLE_PORT,
             SPKeys.MIDDLE_WORKSTATION_ID,
             SPKeys.FUEL_PORT,

+ 15 - 0
app/src/main/java/com/doverfuelingsolutions/issp/view/util/ClickUtils.kt

@@ -0,0 +1,15 @@
+package com.doverfuelingsolutions.issp.view.util
+
+object ClickUtils {
+    private var lastClickTime:Long = 0L
+    private val SINGLECLICKTIME:Long = 1000L
+
+
+    fun isFastClick():Boolean{
+        val clickTime = System.currentTimeMillis()
+        if (clickTime - lastClickTime < SINGLECLICKTIME) return true
+
+        lastClickTime = clickTime
+        return false
+    }
+}

+ 25 - 11
app/src/main/java/com/doverfuelingsolutions/issp/view/util/LoginTokenRefresher.kt

@@ -1,6 +1,7 @@
 package com.doverfuelingsolutions.issp.view.util
 
 import android.app.Activity
+import android.os.Build
 import androidx.core.os.bundleOf
 import com.doverfuelingsolutions.issp.R
 import com.doverfuelingsolutions.issp.api.SystemApi
@@ -22,6 +23,15 @@ class LoginTokenRefresher {
             val expireMoment = GlobalData.accessTokenExpire.get()
             val delayTime = expireMoment - 480_000 - System.currentTimeMillis()
             if (delayTime > 0) delay(delayTime)
+
+//            val userDevice = SystemApi.getUserDevice(GlobalData.accountName.get(), GlobalData.serialNumber.get())
+//            if (!userDevice.success || userDevice.data != true) {
+//                DFSLog.d("loginToken refresh 账户与设备不符合")
+//                val msg = StringUtil.get(R.string.error_account_device)
+//                toLogin(msg,activity)
+//                return@launch
+//            }
+
             val result = SystemApi.login(GlobalData.accountName.get(), GlobalData.password.get())
             if (result.success) {
                 DFSLog.d("loginToken refresh succeeded")
@@ -29,18 +39,8 @@ class LoginTokenRefresher {
                 start(activity)
             } else {
                 DFSLog.d("loginToken refresh failed: ${result.message}")
-                GlobalData.isLogin = false
                 val msg = StringUtil.get(R.string.fail_refresh_login)
-                DFSToastUtil.fail(msg)
-                // Back to login.
-                activity.finish()
-                LoginActivity.start(
-                    activity,
-                    bundleOf(
-                        Pair(LoginActivity.autoLogin, false),
-                        Pair(LoginActivity.loginMessage, msg),
-                    )
-                )
+                toLogin(msg,activity)
             }
         }
     }
@@ -50,4 +50,18 @@ class LoginTokenRefresher {
             if (it.isActive) it.cancel()
         }
     }
+
+    fun toLogin(msg:String,activity: Activity){
+        GlobalData.isLogin = false
+        DFSToastUtil.fail(msg)
+        // Back to login.
+        activity.finish()
+        LoginActivity.start(
+            activity,
+            bundleOf(
+                Pair(LoginActivity.autoLogin, false),
+                Pair(LoginActivity.loginMessage, msg),
+            )
+        )
+    }
 }

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

@@ -18,6 +18,7 @@
     <string name="sp_server_port_trx">server_port_trx</string>
     <string name="sp_server_port_config">server_port_config</string>
     <string name="sp_server_port_assets">server_port_assets</string>
+    <string name="sp_server_port_tool">server_port_tool</string>
     <string name="sp_middle_ip">middle_ip</string>
     <string name="sp_middle_port">middle_port</string>
     <string name="sp_middle_workstation_id">middle_workstation_id</string>

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

@@ -48,6 +48,7 @@
     <string name="fail_operate">操作失败</string>
     <string name="in_loading">加载中&#8230;</string>
     <string name="input_not_right">填写数据不正确</string>
+    <string name="error_account_device">该账户不能在此设备登录</string>
     <string name="return_data_error">请求返回数据不正确</string>
     <string name="account_name_password_error">账号名或密码错误</string>
     <string name="bu_null">BU值为空</string>
@@ -71,6 +72,7 @@
     <string name="port_config">配置端口</string>
     <string name="port_assets">资源端口</string>
     <string name="port_update">升级端口</string>
+    <string name="port_tool">工具端口</string>
     <string name="middle_info">中控信息</string>
     <string name="workstation_id">workstationId</string>
     <string name="fuel_info">加油信息</string>

+ 7 - 0
app/src/main/res/xml/root_preferences.xml

@@ -47,6 +47,13 @@
             app:key="@string/sp_server_port_assets"
             app:title="@string/port_assets"
             app:useSimpleSummaryProvider="true" />
+
+        <EditTextPreference
+            app:dialogTitle="@string/hint_port_input"
+            android:defaultValue="8721"
+            app:key="@string/sp_server_port_tool"
+            app:title="@string/port_tool"
+            app:useSimpleSummaryProvider="true" />
     </PreferenceCategory>
 
     <PreferenceCategory app:title="@string/middle_info">