Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c19d84a7a6 | ||
|
|
8f1f15dd74 | ||
|
|
416a8366e1 | ||
|
|
03c5aee785 | ||
|
|
e3b01ff789 | ||
|
|
b6c9fe5aed | ||
|
|
45562a9fc1 | ||
|
|
7f455f2d8f | ||
|
|
dde0bbc4d5 | ||
|
|
d378cdcf97 | ||
|
|
e5b682f021 | ||
|
|
0498e124b3 | ||
|
|
30b2b178a9 | ||
|
|
2ba55ef027 | ||
|
|
a45690d3be | ||
|
|
ab0d9b35f5 | ||
|
|
0127697560 | ||
|
|
dbe3753821 | ||
|
|
b16147b1b2 | ||
|
|
d6528d33fc | ||
|
|
5479091959 | ||
|
|
12da153df3 | ||
|
|
3ef93c5f5e | ||
|
|
91800a6bb1 | ||
|
|
f40c2046f1 | ||
|
|
ee9f27bb9c | ||
|
|
5c230e38c3 | ||
|
|
10d1f966da | ||
|
|
57f8920442 | ||
|
|
fb4278d2b7 | ||
|
|
fcea0d785d | ||
|
|
c4a6101a7b | ||
|
|
bf8444e5d5 | ||
|
|
549e8d303f | ||
|
|
b51be58c64 |
+3
-6
@@ -1,15 +1,12 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
/.idea/caches
|
/.idea/
|
||||||
/.idea/libraries
|
|
||||||
/.idea/modules.xml
|
|
||||||
/.idea/workspace.xml
|
|
||||||
/.idea/navEditor.xml
|
|
||||||
/.idea/assetWizardSettings.xml
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
|
app/objectbox-models/*.json
|
||||||
|
app/objectbox-models/*.json.bak
|
||||||
|
|||||||
Generated
-3
@@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
Generated
-1
@@ -1 +0,0 @@
|
|||||||
DualScreen
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="AndroidProjectSystem">
|
|
||||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="17" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-18
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetSelector">
|
|
||||||
<selectionStates>
|
|
||||||
<SelectionState runConfigName="app">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
<DropdownSelection timestamp="2026-03-10T03:02:12.156794100Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.211:5555;connection=7435869e" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
|
||||||
</selectionStates>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-13
@@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DeviceTable">
|
|
||||||
<option name="columnSorters">
|
|
||||||
<list>
|
|
||||||
<ColumnSorterState>
|
|
||||||
<option name="column" value="Name" />
|
|
||||||
<option name="order" value="ASCENDING" />
|
|
||||||
</ColumnSorterState>
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-20
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleJvm" value="azul-17" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/app" />
|
|
||||||
<option value="$PROJECT_DIR$/lib_face" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
-6
@@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="UsePropertyAccessSyntax" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
||||||
Generated
-10
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="MaterialThemeProjectNewConfig">
|
|
||||||
<option name="metadata">
|
|
||||||
<MTProjectMetadataState>
|
|
||||||
<option name="userId" value="29face46:19ce5e8d9d0:-7fe0" />
|
|
||||||
</MTProjectMetadataState>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-10
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectMigrations">
|
|
||||||
<option name="MigrateToGradleLocalJavaHome">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-9
@@ -1,9 +0,0 @@
|
|||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="zulu-17" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-17
@@ -1,17 +0,0 @@
|
|||||||
<?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>
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
+11
-7
@@ -51,13 +51,15 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
}
|
}
|
||||||
viewBinding {
|
|
||||||
enable = true
|
buildFeatures {
|
||||||
|
viewBinding = true
|
||||||
|
buildConfig = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar", "*.jar"))))
|
//implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar", "*.jar"))))
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
@@ -108,17 +110,19 @@ dependencies {
|
|||||||
implementation(libs.pytorch.android)
|
implementation(libs.pytorch.android)
|
||||||
implementation(libs.pytorch.android.torchvision)
|
implementation(libs.pytorch.android.torchvision)
|
||||||
|
|
||||||
implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha")
|
implementation(libs.baseRecyclerViewAdapterHelper4)
|
||||||
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
|
|
||||||
|
implementation(libs.refresh.layout.kernel)
|
||||||
|
implementation(libs.refresh.header.classics)
|
||||||
|
|
||||||
val objectboxVersion = "5.0.1"
|
val objectboxVersion = "5.0.1"
|
||||||
debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion")
|
debugImplementation(libs.objectbox.android.objectbrowser)
|
||||||
// releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
|
// releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
|
||||||
// implementation("io.objectbox:objectbox-fulltext:5.0.1")
|
// implementation("io.objectbox:objectbox-fulltext:5.0.1")
|
||||||
|
|
||||||
implementation(libs.androidx.recyclerview)
|
implementation(libs.androidx.recyclerview)
|
||||||
|
|
||||||
implementation("org.greenrobot:eventbus:3.2.0")
|
implementation(libs.eventbus)
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(plugin = "io.objectbox")
|
apply(plugin = "io.objectbox")
|
||||||
Binary file not shown.
@@ -1,77 +0,0 @@
|
|||||||
{
|
|
||||||
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
|
|
||||||
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
|
|
||||||
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"id": "1:594331511073099531",
|
|
||||||
"lastPropertyId": "11:7949771231314213889",
|
|
||||||
"name": "Food",
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"id": "1:2317727855243736226",
|
|
||||||
"name": "id",
|
|
||||||
"type": 6,
|
|
||||||
"flags": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4:1528837175750321569",
|
|
||||||
"name": "foodVector",
|
|
||||||
"indexId": "1:6010838397086628487",
|
|
||||||
"type": 28,
|
|
||||||
"flags": 8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "5:5561277398349179032",
|
|
||||||
"name": "collectId",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "6:8313847979709019172",
|
|
||||||
"name": "foodId",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "7:1375536603452792462",
|
|
||||||
"name": "foodName",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "8:7942065542192169896",
|
|
||||||
"name": "version",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "9:4394472487596452023",
|
|
||||||
"name": "otherField",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10:5704890122356491756",
|
|
||||||
"name": "createTime",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "11:7949771231314213889",
|
|
||||||
"name": "isDel",
|
|
||||||
"type": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lastEntityId": "1:594331511073099531",
|
|
||||||
"lastIndexId": "1:6010838397086628487",
|
|
||||||
"lastRelationId": "0:0",
|
|
||||||
"lastSequenceId": "0:0",
|
|
||||||
"modelVersion": 5,
|
|
||||||
"modelVersionParserMinimum": 5,
|
|
||||||
"retiredEntityUids": [],
|
|
||||||
"retiredIndexUids": [],
|
|
||||||
"retiredPropertyUids": [
|
|
||||||
340951913928211738,
|
|
||||||
5484846939472684412
|
|
||||||
],
|
|
||||||
"retiredRelationUids": [],
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
{
|
|
||||||
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
|
|
||||||
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
|
|
||||||
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"id": "1:594331511073099531",
|
|
||||||
"lastPropertyId": "11:7949771231314213889",
|
|
||||||
"name": "Food",
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"id": "1:2317727855243736226",
|
|
||||||
"name": "id",
|
|
||||||
"type": 6,
|
|
||||||
"flags": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "4:1528837175750321569",
|
|
||||||
"name": "foodVector",
|
|
||||||
"indexId": "1:6010838397086628487",
|
|
||||||
"type": 28,
|
|
||||||
"flags": 8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "5:5561277398349179032",
|
|
||||||
"name": "collectId",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "6:8313847979709019172",
|
|
||||||
"name": "foodId",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "7:1375536603452792462",
|
|
||||||
"name": "foodName",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "8:7942065542192169896",
|
|
||||||
"name": "version",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "9:4394472487596452023",
|
|
||||||
"name": "otherField",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "10:5704890122356491756",
|
|
||||||
"name": "createTime",
|
|
||||||
"type": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "11:7949771231314213889",
|
|
||||||
"name": "isDel",
|
|
||||||
"type": 5
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"relations": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lastEntityId": "1:594331511073099531",
|
|
||||||
"lastIndexId": "1:6010838397086628487",
|
|
||||||
"lastRelationId": "0:0",
|
|
||||||
"lastSequenceId": "0:0",
|
|
||||||
"modelVersion": 5,
|
|
||||||
"modelVersionParserMinimum": 5,
|
|
||||||
"retiredEntityUids": [],
|
|
||||||
"retiredIndexUids": [],
|
|
||||||
"retiredPropertyUids": [
|
|
||||||
340951913928211738,
|
|
||||||
5484846939472684412
|
|
||||||
],
|
|
||||||
"retiredRelationUids": [],
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
@@ -61,7 +61,8 @@
|
|||||||
<!-- </activity>-->
|
<!-- </activity>-->
|
||||||
<!-- <activity android:name="com.sw.dualscreen.activity.CollectedDataActivity" />-->
|
<!-- <activity android:name="com.sw.dualscreen.activity.CollectedDataActivity" />-->
|
||||||
<activity android:name="com.sw.dualscreen.activity.SettingActivity"
|
<activity android:name="com.sw.dualscreen.activity.SettingActivity"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||||
|
android:launchMode="singleTask" />
|
||||||
<activity android:name="com.sw.dualscreen.activity.CollectedFoodActivity"
|
<activity android:name="com.sw.dualscreen.activity.CollectedFoodActivity"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
<activity android:name="com.sw.dualscreen.activity.PayActivity"
|
<activity android:name="com.sw.dualscreen.activity.PayActivity"
|
||||||
|
|||||||
@@ -17,11 +17,14 @@ object GlobalData {
|
|||||||
*/
|
*/
|
||||||
var appVersion: String = "1"
|
var appVersion: String = "1"
|
||||||
|
|
||||||
|
var appBaseUrl: String = ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 具体业务baseurl
|
* 具体业务 BaseUrl
|
||||||
*/
|
*/
|
||||||
var appBaseUrl2: String = "http://192.168.1.201:14801"
|
const val TEST_BASE_URL = "http://192.168.1.201:14801"
|
||||||
var appBaseUrl: String = "https://dev.yixiong-tech.com:8081"
|
const val UAT_BASE_URL = "https://dev.yixiong-tech.com:8083"
|
||||||
|
const val PROD_BASE_URL = "https://api.dm.yixiong-tech.com:8443"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜品识别模型版本号,后边以接口返回为准
|
* 菜品识别模型版本号,后边以接口返回为准
|
||||||
@@ -68,4 +71,6 @@ object GlobalKey {
|
|||||||
const val KEY_USER_INFO = "userInfoKey"
|
const val KEY_USER_INFO = "userInfoKey"
|
||||||
const val KEY_PICKUP_MODE = "pickupMode"
|
const val KEY_PICKUP_MODE = "pickupMode"
|
||||||
const val KEY_CHARGE_MODE = "chargeMode"
|
const val KEY_CHARGE_MODE = "chargeMode"
|
||||||
|
const val KEY_SETTLEMENT_MODE = "settlementMode"
|
||||||
|
const val KEY_BASE_URL = "baseUrlKey"
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,8 @@ import com.sw.dualscreen.objbox.ObjectBox
|
|||||||
import com.sw.dualscreen.sdk.SensorScaleUtils
|
import com.sw.dualscreen.sdk.SensorScaleUtils
|
||||||
import com.sw.dualscreen.utils.ActivityManager
|
import com.sw.dualscreen.utils.ActivityManager
|
||||||
import com.sw.dualscreen.utils.CrashHandler
|
import com.sw.dualscreen.utils.CrashHandler
|
||||||
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
|
import com.sw.dualscreen.utils.SpTool
|
||||||
import com.sw.plate.App
|
import com.sw.plate.App
|
||||||
import com.sw.plate.utils.AppUtil
|
import com.sw.plate.utils.AppUtil
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -13,7 +15,7 @@ import timber.log.Timber
|
|||||||
class MyApp : App() {
|
class MyApp : App() {
|
||||||
companion object {
|
companion object {
|
||||||
const val DEBUG: Boolean = true
|
const val DEBUG: Boolean = true
|
||||||
var instance: MyApp?=null
|
var instance: MyApp? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@@ -24,13 +26,23 @@ class MyApp : App() {
|
|||||||
Timber.d("deviceId = $deviceId")
|
Timber.d("deviceId = $deviceId")
|
||||||
// deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
|
// deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
|
||||||
GlobalData.deviceId = deviceId
|
GlobalData.deviceId = deviceId
|
||||||
GlobalData.appBaseUrl = if ("2987f0c5-5754-33e9-b00a-251db5e2e55f" == deviceId) GlobalData.appBaseUrl2 else GlobalData.appBaseUrl
|
|
||||||
ObjectBox.init(this)
|
ObjectBox.init(this)
|
||||||
// 初始化崩溃处理器
|
// 初始化崩溃处理器
|
||||||
CrashHandler.init(this)
|
CrashHandler.init(this)
|
||||||
|
|
||||||
SensorScaleUtils.startScale()
|
SensorScaleUtils.startScale()
|
||||||
addActivityLifecycleListener()
|
addActivityLifecycleListener()
|
||||||
|
|
||||||
|
// 优先读取用户手动切换后持久化的 url
|
||||||
|
val savedUrl = SpTool.baseUrl
|
||||||
|
if (!savedUrl.isNullOrEmpty()) {
|
||||||
|
GlobalData.appBaseUrl = savedUrl
|
||||||
|
} else {
|
||||||
|
// 未保存过则使用默认逻辑:特定设备走测试环境,其余走 UAT
|
||||||
|
GlobalData.appBaseUrl =
|
||||||
|
if ("2987f0c5-5754-33e9-b00a-251db5e2e55f" == deviceId) GlobalData.TEST_BASE_URL else GlobalData.PROD_BASE_URL
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addActivityLifecycleListener() {
|
private fun addActivityLifecycleListener() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.sw.dualscreen.activity
|
package com.sw.dualscreen.activity
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -182,4 +183,52 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var permissionCallback: ((isGranted: Boolean) -> Unit)? = null
|
||||||
|
private var activityCallback: ((intent: Intent?) -> Unit)? = null
|
||||||
|
|
||||||
|
fun requestMultiplePermissions(
|
||||||
|
permissions: Array<String>,
|
||||||
|
callback: (isGranted: Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
this.permissionCallback = callback
|
||||||
|
requestMultiplePermissionsLauncher.launch(permissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestPermission(permission: String, callback: (isGranted: Boolean) -> Unit) {
|
||||||
|
this.permissionCallback = callback
|
||||||
|
requestPermissionLauncher.launch(permission)
|
||||||
|
}
|
||||||
|
|
||||||
|
val requestMultiplePermissionsLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestMultiplePermissions()
|
||||||
|
) { permissions ->
|
||||||
|
var isGranted = true
|
||||||
|
permissions.entries.forEach {
|
||||||
|
if (!it.value) {
|
||||||
|
isGranted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permissionCallback?.invoke(isGranted)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 权限请求回调
|
||||||
|
val requestPermissionLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestPermission()
|
||||||
|
) { isGranted ->
|
||||||
|
permissionCallback?.invoke(isGranted)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startActivity(intent: Intent, callback: (Intent?) -> Unit) {
|
||||||
|
this.activityCallback = callback
|
||||||
|
startActivityLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// activity页面返回的回调
|
||||||
|
private val startActivityLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) {
|
||||||
|
activityCallback?.invoke(it.data)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@ import android.Manifest
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -12,46 +11,27 @@ import com.sw.dualscreen.GlobalData
|
|||||||
import com.sw.dualscreen.databinding.ActivityInitBinding
|
import com.sw.dualscreen.databinding.ActivityInitBinding
|
||||||
import com.sw.dualscreen.dialog.RemindDialog
|
import com.sw.dualscreen.dialog.RemindDialog
|
||||||
import com.sw.dualscreen.ext.clickWithDebounce
|
import com.sw.dualscreen.ext.clickWithDebounce
|
||||||
|
import com.sw.dualscreen.ext.invisible
|
||||||
import com.sw.dualscreen.ext.visible
|
import com.sw.dualscreen.ext.visible
|
||||||
import com.sw.dualscreen.model.response.FoodVector
|
|
||||||
import com.sw.dualscreen.objbox.Food
|
|
||||||
import com.sw.dualscreen.objbox.FoodModule
|
import com.sw.dualscreen.objbox.FoodModule
|
||||||
import com.sw.dualscreen.objbox.ObjectBox
|
import com.sw.dualscreen.utils.FoodVectorTool
|
||||||
import com.sw.dualscreen.utils.L
|
import com.sw.dualscreen.utils.L
|
||||||
|
import com.sw.dualscreen.utils.NetworkUtils
|
||||||
|
import com.sw.dualscreen.utils.SpTool
|
||||||
import com.sw.dualscreen.viewmodel.BaseViewModel
|
import com.sw.dualscreen.viewmodel.BaseViewModel
|
||||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||||
import com.sw.plate.utils.AppUtil
|
import com.sw.plate.utils.AppUtil
|
||||||
|
import com.sw.plate.utils.ToastUtils
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class InitActivity : BaseActivity<ActivityInitBinding>() {
|
class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val PAGE_SIZE = 100
|
const val PAGE_SIZE = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
private val userViewModel by viewModels<UserViewModel>()
|
private val userViewModel by viewModels<UserViewModel>()
|
||||||
private var pageNum = 1
|
private var pageNum = 1
|
||||||
|
|
||||||
// 相机权限请求回调
|
|
||||||
private val requestCameraPermissionLauncher = registerForActivityResult(
|
|
||||||
ActivityResultContracts.RequestPermission()
|
|
||||||
) { isGranted ->
|
|
||||||
if (isGranted) {
|
|
||||||
// 权限请求成功,打开 MainActivity
|
|
||||||
goMainActivity()
|
|
||||||
} else {
|
|
||||||
// 权限请求失败,显示弹窗
|
|
||||||
showPermissionDeniedDialog()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置页面返回的回调
|
|
||||||
private val startSettingsLauncher = registerForActivityResult(
|
|
||||||
ActivityResultContracts.StartActivityForResult()
|
|
||||||
) {
|
|
||||||
// 从设置页面返回,重新检查权限
|
|
||||||
checkCameraPermissionAfterSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getViewModel(): BaseViewModel {
|
override fun getViewModel(): BaseViewModel {
|
||||||
return userViewModel
|
return userViewModel
|
||||||
}
|
}
|
||||||
@@ -61,55 +41,22 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getCollectedFoodVector(block: () -> Unit) {
|
private fun getCollectedFoodVector(block: () -> Unit) {
|
||||||
userViewModel.getCollectedFoodVector(
|
FoodVectorTool.loadAndSaveFoodVector(
|
||||||
param = mutableMapOf(
|
userViewModel = userViewModel,
|
||||||
"pageNum" to "$pageNum",
|
lifecycleScope = lifecycleScope,
|
||||||
"pageSize" to "$PAGE_SIZE",
|
successBlock = { block() },
|
||||||
"version" to GlobalData.foodModelVersion
|
failureBlock = { getVectorErrorDialog() }
|
||||||
)
|
)
|
||||||
) { items ->
|
|
||||||
if (items == null) {
|
|
||||||
getVectorErrorDialog()
|
|
||||||
return@getCollectedFoodVector
|
|
||||||
}
|
|
||||||
val list = items
|
|
||||||
if (pageNum == 1 && list.isEmpty()) {
|
|
||||||
block()
|
|
||||||
return@getCollectedFoodVector
|
|
||||||
}
|
|
||||||
if (list.size >= PAGE_SIZE) {
|
|
||||||
saveFoodVector(list)
|
|
||||||
pageNum++
|
|
||||||
getCollectedFoodVector(block)
|
|
||||||
return@getCollectedFoodVector
|
|
||||||
}
|
|
||||||
if (list.isNotEmpty()) {
|
|
||||||
saveFoodVector(list)
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private val box by lazy { ObjectBox.boxStore.boxFor(Food::class) }
|
// private val box by lazy { ObjectBox.boxStore.boxFor(Food::class) }
|
||||||
private fun saveFoodVector(list: List<FoodVector>) {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
val vectorList = list.map { vt ->
|
|
||||||
val foodVector = vt.foodVector?.removeSurrounding("[", "]")?.split(",")
|
|
||||||
?.map { it.toFloatOrNull() ?: 0.0f }?.toFloatArray()
|
|
||||||
Food(
|
|
||||||
collectId = vt.id,
|
|
||||||
foodId = vt.foodId,
|
|
||||||
foodName = vt.foodName,
|
|
||||||
version = vt.version,
|
|
||||||
foodVector = foodVector
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ObjectBox.putAll(vectorList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
super.initialize()
|
super.initialize()
|
||||||
|
//写死,后续改为从接口获取结算类型 ------------------------------------------
|
||||||
|
//val settlementMode = 1
|
||||||
|
//SPUtil.getInstance().put(GlobalKey.KEY_SETTLEMENT_MODE, settlementMode)
|
||||||
|
|
||||||
registerKeyEvent()
|
registerKeyEvent()
|
||||||
initNetworkTimer()
|
initNetworkTimer()
|
||||||
binding.okButton.clickWithDebounce(500) {
|
binding.okButton.clickWithDebounce(500) {
|
||||||
@@ -146,6 +93,7 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getCollectedFoodVector() {
|
private fun getCollectedFoodVector() {
|
||||||
|
binding.okButton.invisible()
|
||||||
showWaitingDialog2("加载中……")
|
showWaitingDialog2("加载中……")
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
FoodModule.init(this@InitActivity) {
|
FoodModule.init(this@InitActivity) {
|
||||||
@@ -167,30 +115,30 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查相机权限
|
private fun hasCameraPermission(): Boolean {
|
||||||
private fun checkCameraPermissionAndGo() {
|
return ContextCompat.checkSelfPermission(
|
||||||
val hasCameraPermission = ContextCompat.checkSelfPermission(
|
|
||||||
this,
|
this,
|
||||||
Manifest.permission.CAMERA
|
Manifest.permission.CAMERA
|
||||||
) == android.content.pm.PackageManager.PERMISSION_GRANTED
|
) == android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
if (hasCameraPermission) {
|
// 检查相机权限
|
||||||
|
private fun checkCameraPermissionAndGo() {
|
||||||
|
val isGrantedCameraPermission = hasCameraPermission()
|
||||||
|
if (isGrantedCameraPermission) {
|
||||||
// 有权限,直接打开 MainActivity
|
// 有权限,直接打开 MainActivity
|
||||||
goMainActivity()
|
goMainActivity()
|
||||||
} else {
|
} else {
|
||||||
// 无权限,请求相机权限
|
// 无权限,请求相机权限
|
||||||
requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA)
|
requestPermission(Manifest.permission.CAMERA) { isGranted ->
|
||||||
|
checkCameraPermission(isGranted)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从设置页面返回后检查权限
|
// 从设置页面返回后检查权限
|
||||||
private fun checkCameraPermissionAfterSettings() {
|
private fun checkCameraPermission(isGranted: Boolean) {
|
||||||
val hasCameraPermission = ContextCompat.checkSelfPermission(
|
if (isGranted) {
|
||||||
this,
|
|
||||||
Manifest.permission.CAMERA
|
|
||||||
) == android.content.pm.PackageManager.PERMISSION_GRANTED
|
|
||||||
|
|
||||||
if (hasCameraPermission) {
|
|
||||||
// 权限已授予,打开 MainActivity
|
// 权限已授予,打开 MainActivity
|
||||||
goMainActivity()
|
goMainActivity()
|
||||||
} else {
|
} else {
|
||||||
@@ -209,7 +157,11 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
|||||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||||
data = android.net.Uri.fromParts("package", packageName, null)
|
data = android.net.Uri.fromParts("package", packageName, null)
|
||||||
}
|
}
|
||||||
startSettingsLauncher.launch(intent)
|
startActivity(intent) {
|
||||||
|
// 从设置页面返回,重新检查权限
|
||||||
|
val isGrantedCameraPermission = hasCameraPermission()
|
||||||
|
checkCameraPermission(isGrantedCameraPermission)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
@@ -230,17 +182,47 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
|||||||
loadNetworkErrorDialog()
|
loadNetworkErrorDialog()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
getDeviceConfig()
|
||||||
getCollectedFoodVector()
|
getCollectedFoodVector()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getDeviceConfig() {
|
||||||
|
userViewModel.getDeviceConfig { deviceConfig ->
|
||||||
|
runOnUiThread {
|
||||||
|
if (deviceConfig == null) {
|
||||||
|
ToastUtils.showToast("获取设备配置数据失败")
|
||||||
|
return@runOnUiThread
|
||||||
|
}
|
||||||
|
//var settlementMode = 1
|
||||||
|
//结算模式:1-独立支付,2-联合结算
|
||||||
|
val settlementMode = if (deviceConfig.payType == 2) 0 else 1
|
||||||
|
// TODO: 2022/10/13 修改为独立支付
|
||||||
|
SpTool.settlementMode = settlementMode
|
||||||
|
|
||||||
|
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
|
||||||
|
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
|
||||||
|
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadNetworkErrorDialog() {
|
private fun loadNetworkErrorDialog() {
|
||||||
RemindDialog(
|
RemindDialog(
|
||||||
context = context,
|
context = context,
|
||||||
content = "网络连接异常,请检查WiFi连接状态后重试",
|
content = "网络连接异常,请检查WiFi连接状态后重试",
|
||||||
confirmBlock = {
|
confirmBlock = {
|
||||||
startActivity(Intent("android.settings.WIFI_SETTINGS"))
|
val intent = Intent("android.settings.WIFI_SETTINGS")
|
||||||
|
startActivity(intent) {
|
||||||
|
// 从设置页面返回,重新检查网络连接状态
|
||||||
|
val isConnected = NetworkUtils.isNetworkConnected(this@InitActivity)
|
||||||
|
if (isConnected.not()) {
|
||||||
|
loadNetworkErrorDialog()
|
||||||
|
return@startActivity
|
||||||
|
}
|
||||||
|
getCollectedFoodVector()
|
||||||
|
}
|
||||||
}).show()
|
}).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import android.text.TextUtils
|
|||||||
import android.view.Display
|
import android.view.Display
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewOutlineProvider
|
import android.view.ViewOutlineProvider
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.core.CameraSelector
|
import androidx.camera.core.CameraSelector
|
||||||
@@ -22,23 +23,30 @@ import androidx.camera.core.ImageCaptureException
|
|||||||
import androidx.camera.core.Preview
|
import androidx.camera.core.Preview
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import com.sw.dualscreen.GlobalData
|
import com.sw.dualscreen.GlobalData
|
||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.dualscreen.adapter.MainFoodListAdapter
|
import com.sw.dualscreen.adapter.MainFoodListAdapter
|
||||||
import com.sw.dualscreen.databinding.ActivityMainBinding
|
import com.sw.dualscreen.databinding.ActivityMainBinding
|
||||||
|
import com.sw.dualscreen.databinding.LayoutEatDetailBinding
|
||||||
|
import com.sw.dualscreen.databinding.LayoutMainFoodList2Binding
|
||||||
|
import com.sw.dualscreen.databinding.LayoutMainFoodListBinding
|
||||||
|
import com.sw.dualscreen.dialog.EnvSwitchDialog
|
||||||
import com.sw.dualscreen.dialog.RemindDialog
|
import com.sw.dualscreen.dialog.RemindDialog
|
||||||
import com.sw.dualscreen.ext.dp
|
import com.sw.dualscreen.ext.dp
|
||||||
import com.sw.dualscreen.ext.gone
|
import com.sw.dualscreen.ext.gone
|
||||||
|
import com.sw.dualscreen.ext.invisible
|
||||||
import com.sw.dualscreen.ext.load
|
import com.sw.dualscreen.ext.load
|
||||||
import com.sw.dualscreen.ext.visible
|
import com.sw.dualscreen.ext.visible
|
||||||
import com.sw.dualscreen.model.response.ChargeModeEvent
|
import com.sw.dualscreen.model.response.ChargeModeEvent
|
||||||
import com.sw.dualscreen.model.response.ClickBackEvent
|
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
import com.sw.dualscreen.model.response.FoodOrder
|
import com.sw.dualscreen.model.response.FoodOrder
|
||||||
import com.sw.dualscreen.model.response.PaySuccessEvent
|
import com.sw.dualscreen.model.response.PaySuccessEvent
|
||||||
|
import com.sw.dualscreen.model.response.ResetRecognizeEvent
|
||||||
import com.sw.dualscreen.model.response.UpdateRefreshEvent
|
import com.sw.dualscreen.model.response.UpdateRefreshEvent
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
import com.sw.dualscreen.objbox.Food
|
import com.sw.dualscreen.objbox.Food
|
||||||
@@ -51,6 +59,7 @@ import com.sw.dualscreen.socket.TcpClient
|
|||||||
import com.sw.dualscreen.utils.ActivityManager
|
import com.sw.dualscreen.utils.ActivityManager
|
||||||
import com.sw.dualscreen.utils.BitmapSaver
|
import com.sw.dualscreen.utils.BitmapSaver
|
||||||
import com.sw.dualscreen.utils.Debouncer
|
import com.sw.dualscreen.utils.Debouncer
|
||||||
|
import com.sw.dualscreen.utils.FoodVectorTool
|
||||||
import com.sw.dualscreen.utils.GsonUtils
|
import com.sw.dualscreen.utils.GsonUtils
|
||||||
import com.sw.dualscreen.utils.ImageUtil
|
import com.sw.dualscreen.utils.ImageUtil
|
||||||
import com.sw.dualscreen.utils.IntervalExecutor
|
import com.sw.dualscreen.utils.IntervalExecutor
|
||||||
@@ -64,22 +73,26 @@ import com.sw.plate.utils.LightManager
|
|||||||
import com.sw.plate.utils.ToastUtils
|
import com.sw.plate.utils.ToastUtils
|
||||||
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
import com.sw.plate.utils.arcface.facedb.FaceDatabase
|
||||||
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
|
import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
|
||||||
|
import com.sw.plate.utils.arcface.faceserver.FaceServer
|
||||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +104,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MainActivity"
|
private const val TAG = "MainActivity"
|
||||||
const val TIME_OUT = 5 * 60 * 1000L
|
const val TIME_OUT = 5 * 60 * 1000L
|
||||||
|
|
||||||
|
const val WEIGHT_CHANGE_VALUE = 20
|
||||||
|
const val WEIGHT_RESET_RECOGNIZE = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModel by viewModels<UserViewModel>()
|
private val viewModel by viewModels<UserViewModel>()
|
||||||
@@ -101,23 +117,47 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
private var presentation: MainScreenPresentation? = null
|
private var presentation: MainScreenPresentation? = null
|
||||||
private val executor = Executors.newSingleThreadExecutor()
|
private val executor = Executors.newSingleThreadExecutor()
|
||||||
private val handler by lazy { Handler(Looper.getMainLooper()) }
|
private val handler by lazy { Handler(Looper.getMainLooper()) }
|
||||||
private val searchFoodList = mutableListOf<FoodInfo>()
|
|
||||||
private val adapter by lazy {
|
private val adapter by lazy {
|
||||||
MainFoodListAdapter(searchFoodList).apply {
|
MainFoodListAdapter(mutableListOf()).apply {
|
||||||
setOnItemClickListener { adapter, view, position ->
|
setOnItemClickListener { _, _, position ->
|
||||||
if (searchFoodList[position].isChecked) {
|
if (items[position].isChecked) {
|
||||||
return@setOnItemClickListener
|
return@setOnItemClickListener
|
||||||
}
|
}
|
||||||
searchFoodList.forEachIndexed { index, info ->
|
items.forEachIndexed { index, info ->
|
||||||
searchFoodList[index].isChecked = index == position
|
items[index].isChecked = index == position
|
||||||
}
|
}
|
||||||
val item = searchFoodList[position]
|
val item = items[position]
|
||||||
log("itemClick ${item.foodName}, position = $position")
|
log("itemClick ${item.foodName}, position = $position")
|
||||||
item.photoUri = null
|
item.photoUri = null
|
||||||
checkedItem = item
|
checkedItem = item
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
updateCurrentFood(item)
|
resetSelectedFood(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var isSwitchFood = false
|
||||||
|
/**
|
||||||
|
* 用于切换菜品时重置数据
|
||||||
|
*/
|
||||||
|
fun resetSelectedFood(foodInfo: FoodInfo) {
|
||||||
|
isSwitchFood = true
|
||||||
|
recognizeViewModel.resetFaceState()
|
||||||
|
updateCurrentFood(foodInfo)
|
||||||
|
if (settlementMode == 0) {
|
||||||
|
//联合支付,切换菜品重新请求接口
|
||||||
|
presentation?.let {
|
||||||
|
val userId = presentation?.currentUserId
|
||||||
|
if(userId.isNullOrBlank()) {
|
||||||
|
//切换菜品时,用户已离开重新打开识别功能
|
||||||
|
it.pauseCamera()
|
||||||
|
it.step2FaceRecognizing(foodInfo, true)
|
||||||
|
} else{
|
||||||
|
//切换菜品时,用户未离开,重新请求接口
|
||||||
|
it.step3ShowRecognizeResult(userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//0-计费,1-不计费
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
//不计费模式切换菜品,重新加载数据
|
//不计费模式切换菜品,重新加载数据
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
@@ -126,13 +166,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
var checkedItem: FoodInfo? = null
|
var checkedItem: FoodInfo? = null
|
||||||
private var imageAnalysis: ImageAnalysis? = null
|
private var imageAnalysis: ImageAnalysis? = null
|
||||||
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
|
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
|
||||||
private var canIdentify: Boolean = false
|
private var canIdentify: Boolean = false
|
||||||
private var bottomSheetDialog: CustomBottomSheetDialog? = null
|
private var bottomSheetDialog: CustomBottomSheetDialog? = null
|
||||||
private var lastWeight: Double = 0.0
|
private var lastWeight: Int = 0
|
||||||
|
var currentWeight: Int = 0
|
||||||
private var lastPhotoUri: Uri? = null // 最后拍照的图片
|
private var lastPhotoUri: Uri? = null // 最后拍照的图片
|
||||||
private var debouncer = Debouncer(2000)
|
private var debouncer = Debouncer(2000)
|
||||||
private var isRecognitionFood = true
|
private var isRecognitionFood = true
|
||||||
@@ -140,6 +181,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private var isStartRecognize = false
|
private var isStartRecognize = false
|
||||||
|
|
||||||
|
//0-联合支付,1-独立支付
|
||||||
|
var settlementMode: Int = 1
|
||||||
|
// val settlementMode by lazy {
|
||||||
|
// SPUtil.getInstance().get(GlobalKey.KEY_SETTLEMENT_MODE, 1)
|
||||||
|
// }
|
||||||
|
|
||||||
|
private lateinit var rvFoodList: RecyclerView
|
||||||
|
private lateinit var tvToSearch: TextView
|
||||||
|
lateinit var layoutEatDetailBinding: LayoutEatDetailBinding
|
||||||
|
|
||||||
override fun getViewModel(): BaseViewModel {
|
override fun getViewModel(): BaseViewModel {
|
||||||
return viewModel
|
return viewModel
|
||||||
}
|
}
|
||||||
@@ -150,6 +201,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
super.initialize()
|
super.initialize()
|
||||||
|
settlementMode = SpTool.settlementMode
|
||||||
isPageVisible = true
|
isPageVisible = true
|
||||||
// 拦截扫码枪按键事件,防止触发页面按钮点击
|
// 拦截扫码枪按键事件,防止触发页面按钮点击
|
||||||
registerKeyEvent()
|
registerKeyEvent()
|
||||||
@@ -162,24 +214,83 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
initData()
|
initData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initLayoutEatDetailBinding() {
|
||||||
|
Timber.tag(TAG).d("initLayoutEatDetailBinding,settlementMode=$settlementMode")
|
||||||
|
binding.flFoodList.removeAllViews()
|
||||||
|
if (settlementMode == 0) {
|
||||||
|
//联合支付
|
||||||
|
val b = LayoutMainFoodList2Binding.inflate(layoutInflater, binding.flFoodList, true)
|
||||||
|
rvFoodList = b.rvFoodList
|
||||||
|
tvToSearch = b.tvToSearch
|
||||||
|
layoutEatDetailBinding = b.detailInclude
|
||||||
|
layoutEatDetailBinding.llFoodTitle.gone()
|
||||||
|
// layoutEatDetailBinding.root.invisible()
|
||||||
|
} else {
|
||||||
|
//独立支付
|
||||||
|
val b = LayoutMainFoodListBinding.inflate(layoutInflater, binding.flFoodList, true)
|
||||||
|
rvFoodList = b.rvFoodList
|
||||||
|
tvToSearch = b.tvToSearch
|
||||||
|
layoutEatDetailBinding = b.detailInclude
|
||||||
|
layoutEatDetailBinding.llFoodTitle.gone()
|
||||||
|
layoutEatDetailBinding.root.gone()
|
||||||
|
}
|
||||||
|
tvToSearch.setOnClickListener {
|
||||||
|
bottomSheetDialog = CustomBottomSheetDialog.newInstance(viewModel) {
|
||||||
|
checkedItem = it
|
||||||
|
it.photoUri = null
|
||||||
|
adapter.items.forEachIndexed { index, info ->
|
||||||
|
adapter.items[index].isChecked = false
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
resetSelectedFood(it)
|
||||||
|
}
|
||||||
|
bottomSheetDialog!!.show(supportFragmentManager, "CustomBottomSheetDialog")
|
||||||
|
}
|
||||||
|
|
||||||
|
rvFoodList.let {
|
||||||
|
it.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
it.adapter = adapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun initData() {
|
private fun initData() {
|
||||||
startFaceTask()
|
startFaceTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
viewModel.getDeviceConfig { deviceConfig ->
|
|
||||||
runOnUiThread {
|
|
||||||
if (deviceConfig == null) {
|
|
||||||
ToastUtils.showToast("获取设备配置数据失败")
|
|
||||||
return@runOnUiThread
|
|
||||||
}
|
|
||||||
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
|
|
||||||
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
|
|
||||||
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
|
|
||||||
viewModel.activeEngine()
|
viewModel.activeEngine()
|
||||||
}
|
initLayoutEatDetailBinding()
|
||||||
}
|
|
||||||
updateDateTime()
|
updateDateTime()
|
||||||
|
binding.tvTitleTime.setOnClickListener {
|
||||||
|
EnvSwitchDialog(context = this, onEnvChanged = {
|
||||||
|
showWaitingDialog("重置人脸数据中……")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
FaceServer.getInstance().clearAllFaces()
|
||||||
|
ObjectBox.removeAll()
|
||||||
|
}
|
||||||
|
FoodVectorTool.loadAndSaveFoodVector(
|
||||||
|
userViewModel = viewModel,
|
||||||
|
lifecycleScope = lifecycleScope,
|
||||||
|
successBlock = {
|
||||||
|
viewModel.getUserFaceCache(pageNo = 1)
|
||||||
|
},
|
||||||
|
failureBlock = {
|
||||||
|
hideWaitingDialog()
|
||||||
|
ToastUtils.showToast(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
viewModel.getUserFaceCache(pageNo = 1, onSuccess = {
|
||||||
|
recognizeViewModel.refreshFaceList()
|
||||||
|
hideWaitingDialog()
|
||||||
|
ToastUtils.showToast("人脸数据已更新")
|
||||||
|
}, onFailure = { errMsg ->
|
||||||
|
hideWaitingDialog()
|
||||||
|
ToastUtils.showToast(errMsg)
|
||||||
|
})
|
||||||
|
}).show()
|
||||||
|
}
|
||||||
binding.ivSetting.setOnClickListener {
|
binding.ivSetting.setOnClickListener {
|
||||||
isRefreshPage = false
|
isRefreshPage = false
|
||||||
startActivity(Intent(this, SettingActivity::class.java))
|
startActivity(Intent(this, SettingActivity::class.java))
|
||||||
@@ -190,23 +301,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.previewView.clipToOutline = true
|
binding.previewView.clipToOutline = true
|
||||||
binding.tvToSearch.setOnClickListener {
|
|
||||||
bottomSheetDialog = CustomBottomSheetDialog.newInstance(viewModel) {
|
|
||||||
checkedItem = it
|
|
||||||
it.photoUri = null
|
|
||||||
updateCurrentFood(it)
|
|
||||||
searchFoodList.forEachIndexed { index, info ->
|
|
||||||
searchFoodList[index].isChecked = false
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
bottomSheetDialog!!.show(supportFragmentManager, "CustomBottomSheetDialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.recyclerview.let {
|
|
||||||
it.layoutManager = GridLayoutManager(this, 2)
|
|
||||||
it.adapter = adapter
|
|
||||||
}
|
|
||||||
binding.tvFoodName.setOnClickListener {
|
binding.tvFoodName.setOnClickListener {
|
||||||
SensorScaleUtils.zero()
|
SensorScaleUtils.zero()
|
||||||
}
|
}
|
||||||
@@ -215,7 +309,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var recognizeWeight = 0.0
|
private var recognizeWeight = 0
|
||||||
fun updateCurrentFood(foodInfo: FoodInfo?) {
|
fun updateCurrentFood(foodInfo: FoodInfo?) {
|
||||||
if (foodInfo == null) {
|
if (foodInfo == null) {
|
||||||
binding.tvFoodName.text = "-"
|
binding.tvFoodName.text = "-"
|
||||||
@@ -225,8 +319,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
pauseAnalysis()
|
pauseAnalysis()
|
||||||
recognizeWeight = lastWeight
|
recognizeWeight = currentWeight
|
||||||
log("registerDataChange,副屏updateFood调用前耗时:${System.currentTimeMillis() - startTime}")
|
log("registerDataChange,副屏updateFood调用前耗时:${System.currentTimeMillis() - startTime}, recognizeWeight = ${recognizeWeight}")
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
presentation?.updateFood(foodInfo)
|
presentation?.updateFood(foodInfo)
|
||||||
binding.tvFoodName.text = foodInfo.foodName
|
binding.tvFoodName.text = foodInfo.foodName
|
||||||
@@ -240,17 +334,115 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
binding.ivImg.load(imgUrl)
|
binding.ivImg.load(imgUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerDataChange() {
|
/**
|
||||||
super.registerDataChange()
|
* 联合支付-即放即取模式
|
||||||
SensorScaleUtils.addWeightListener { weight ->
|
*/
|
||||||
log("registerDataChange weight = $weight")
|
private fun loadJFJQBySettlement(weight: Int) {
|
||||||
//runOnUiThread { binding.tvShowWeight.text="${weight*1000}克" }
|
log("registerDataChange weight 联合支付-即放即取")
|
||||||
if (lastWeight - weight > 0.005) {
|
//即放即取+联合支付人脸查询订单完成
|
||||||
//及放及取,从秤上拿走超过5克
|
if (presentation!!.jointPaymentQueryFinish) {
|
||||||
if (presentation?.mealPickupMode == 0) {
|
log("registerDataChange weight 联合支付-即放即取,人脸查询订单完成")
|
||||||
|
if (weight > WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
//已识别完成人脸并查询到订单数据,增加重量不再重新识别
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,不再重新识别")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,step1FoodRecognizing")
|
||||||
|
//重量小于等于10克时改为识别中页面
|
||||||
|
isAnalyzing = false
|
||||||
|
presentation?.step1FoodRecognizing()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,人脸查询订单没有完成")
|
||||||
|
if (weight <= WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
//秤上重量过小,显示识别中页面
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,重量小于${WEIGHT_RESET_RECOGNIZE}g,step1FoodRecognizing")
|
||||||
|
presentation?.step1FoodRecognizing()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,recognizeByWeight")
|
||||||
|
// val isWeightChange = abs(weight - lastWeight) > 0.02
|
||||||
|
val isWeightChange = weight - lastWeight > WEIGHT_CHANGE_VALUE
|
||||||
|
if (weight != lastWeight) {
|
||||||
|
log("registerDataChange weight 联合支付-即放即取,recognizeByWeight---00001,weight=$weight,lastWeight=$lastWeight,isWeightChange=$isWeightChange")
|
||||||
|
}
|
||||||
|
recognizeByWeight(weight, isWeightChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联合支付-余量计量模式
|
||||||
|
*/
|
||||||
|
private fun loadYLJLBySettlement(weight: Int) {
|
||||||
|
log("registerDataChange weight 联合支付-余量计量")
|
||||||
|
if (weight <= WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
log("registerDataChange weight 联合支付-余量计量,重量小于${WEIGHT_RESET_RECOGNIZE}g,step1FoodRecognizing")
|
||||||
|
if (presentation?.currentUserId.isNullOrBlank().not() && presentation!!.jointPaymentQueryFinish) {
|
||||||
|
//联合支付+余量计量,已识别人脸的状态下,从秤上拿餐品后,不再读取数据,等待人脸离开提交订单
|
||||||
|
if (lastWeight != weight) {
|
||||||
presentation?.updateWeight(weight)
|
presentation?.updateWeight(weight)
|
||||||
lastWeight = weight
|
lastWeight = weight
|
||||||
return@addWeightListener
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//秤上重量过小,显示识别中页面
|
||||||
|
presentation?.step1FoodRecognizing()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("registerDataChange weight 联合支付-余量计量,订单完成状态:${presentation!!.jointPaymentQueryFinish}")
|
||||||
|
//余量计量+联合支付人脸查询订单完成
|
||||||
|
if (presentation!!.jointPaymentQueryFinish) {
|
||||||
|
log("registerDataChange weight 联合支付-余量计量,updateWeight")
|
||||||
|
if (lastWeight != weight) {
|
||||||
|
presentation?.updateWeight(weight)
|
||||||
|
log("registerDataChange weight 重置lastWeight与weigh:${weight}一致----------------1000006")
|
||||||
|
lastWeight = weight
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val isWeightChange = weight - lastWeight > WEIGHT_CHANGE_VALUE
|
||||||
|
recognizeByWeight(weight, isWeightChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readWeight(weight: Int) {
|
||||||
|
currentWeight = weight
|
||||||
|
log("registerDataChange weight = $weight, lastWeight = $lastWeight")
|
||||||
|
binding.tvShowWeight.let {
|
||||||
|
if (it.text.toString() != weight.toString()) {
|
||||||
|
it.text = "$weight"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (settlementMode == 0) {
|
||||||
|
log("registerDataChange weight 联合支付模式")
|
||||||
|
//联合支付-------------------------------------------
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
|
val mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
if (mealPickupMode == 1) {
|
||||||
|
loadYLJLBySettlement(weight)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (presentation?.currentUserId.isNullOrBlank().not()) {
|
||||||
|
//联合支付+即放即取,已识别人脸的状态下,从秤上拿餐品后,不再读取数据,等待人脸离开提交订单
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loadJFJQBySettlement(weight)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//独立支付-------------------------------------------
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
|
val mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
//0-计费,1-不计费
|
||||||
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
if(mealPickupMode == 0 && chargeMode == 1) {
|
||||||
|
//即放即取+不计费模式,
|
||||||
|
if (presentation?.currentUserId.isNullOrBlank().not()) {
|
||||||
|
//已识别人脸的状态下,从秤上拿餐品后,不再读取数据,等待人脸离开提交订单
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (weight <= WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
log("registerDataChange weight 秤重量小于${WEIGHT_RESET_RECOGNIZE}g")
|
||||||
|
//检测到秤上没有东西
|
||||||
|
presentation?.step1FoodRecognizing()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isPageVisible.not() || isStartRecognize.not()) {
|
if (isPageVisible.not() || isStartRecognize.not()) {
|
||||||
@@ -258,46 +450,69 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
isPageVisible = true
|
isPageVisible = true
|
||||||
isStartRecognize = true
|
isStartRecognize = true
|
||||||
}
|
}
|
||||||
return@addWeightListener
|
return
|
||||||
}
|
}
|
||||||
//0.05
|
val isWeightChange = weight - lastWeight > WEIGHT_CHANGE_VALUE
|
||||||
// val isWeightChange = abs(weight - lastWeight) > 0.02
|
|
||||||
val isWeightChange = weight - lastWeight > 0.02
|
|
||||||
log("recognizeByWeight---00001,weight=$weight,lastWeight=$lastWeight,isWeightChange=$isWeightChange")
|
|
||||||
recognizeByWeight(weight, isWeightChange)
|
recognizeByWeight(weight, isWeightChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun registerDataChange() {
|
||||||
|
super.registerDataChange()
|
||||||
|
SensorScaleUtils.addWeightListener { value ->
|
||||||
|
runOnUiThread {
|
||||||
|
if (foodRecognizeState.not()) {
|
||||||
|
if (value <= WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
presentation?.step1FoodRecognizing()
|
||||||
|
}
|
||||||
|
return@runOnUiThread
|
||||||
|
}
|
||||||
|
readWeight(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recognizeByWeight(weight: Double, isWeightChange: Boolean, block: () -> Unit = {}) {
|
private fun recognizeByWeight(weight: Int, isWeightChange: Boolean, block: () -> Unit = {}) {
|
||||||
presentation?.updateWeight(weight)
|
log("registerDataChange weight 开始识别")
|
||||||
|
if (weight != lastWeight) {
|
||||||
|
val payTypeDesc = if (settlementMode == 0) "联合支付" else "独立支付"
|
||||||
|
log("registerDataChange weight readWeight-${payTypeDesc},weight=$weight,lastWeight=$lastWeight,isWeightChange=$isWeightChange")
|
||||||
|
}
|
||||||
|
// presentation?.updateWeight(weight)
|
||||||
|
|
||||||
if (weight <= 0.005) {
|
if (weight <= WEIGHT_RESET_RECOGNIZE) {
|
||||||
log("recognizeByWeight---00002,秤重未超过5克")
|
log("registerDataChange weight recognizeByWeight---00002,秤重未超过${WEIGHT_RESET_RECOGNIZE}克")
|
||||||
//检测到秤上没有东西,重新启动识别菜品 && presentation?.mealPickupMode == 1
|
//检测到秤上没有东西,重新启动识别菜品
|
||||||
isRecognitionFood = true
|
isRecognitionFood = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWeightChange && isRecognitionFood) { // 大于50g
|
if (isWeightChange && isRecognitionFood) {
|
||||||
log("recognizeByWeight---00003,mealPickupMode=${presentation?.mealPickupMode}")
|
log("registerDataChange weight recognizeByWeight---00003,mealPickupMode=${presentation?.mealPickupMode}")
|
||||||
if (presentation?.mealPickupMode == 1) {
|
if (presentation?.mealPickupMode == 1 && checkedItem != null) {
|
||||||
isRecognitionFood = false
|
isRecognitionFood = false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
debouncer.debounce {
|
debouncer.debounce {
|
||||||
log("recognizeByWeight---00004")
|
log("registerDataChange weight recognizeByWeight---00004--recognizeFood")
|
||||||
|
//保存当前重量
|
||||||
|
currentWeight = weight
|
||||||
recognizeFood()
|
recognizeFood()
|
||||||
if (presentation?.mealPickupMode == 0) {
|
|
||||||
lastWeight = weight
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
log("registerDataChange weight recognizeByWeight---block")
|
||||||
block()
|
block()
|
||||||
}
|
}
|
||||||
|
if (presentation?.mealPickupMode == 1 || settlementMode == 0) {
|
||||||
|
log("registerDataChange weight recognizeByWeight---lastWeight=${lastWeight}, weight=${weight}, checkedItem=${checkedItem}")
|
||||||
|
if (weight - lastWeight > WEIGHT_CHANGE_VALUE && checkedItem == null) {
|
||||||
|
debouncer.debounce {
|
||||||
|
log("registerDataChange weight重新进行菜品识别 ")
|
||||||
|
recognizeFood()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (presentation?.mealPickupMode == 1) {
|
|
||||||
lastWeight = weight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var startTime = 0L
|
private var startTime = 0L
|
||||||
|
|
||||||
@@ -307,12 +522,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
LightManager.openGreenLight()
|
LightManager.openGreenLight()
|
||||||
showWaitingDialog("识别中,请稍后……")
|
showWaitingDialog("识别中,请稍后……")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(5000)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
hideWaitingDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
takePhoto(successCallback = { photoUri ->
|
takePhoto(successCallback = { photoUri ->
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
onTakePhotoSuccess(photoUri)
|
onTakePhotoSuccess(photoUri)
|
||||||
}.start()
|
}
|
||||||
failCount = 0
|
failCount = 0
|
||||||
}, failureCallback = {
|
}, failureCallback = {
|
||||||
|
log("registerDataChange main,拍照异常,请重试")
|
||||||
//ToastUtils.showToast("拍照异常,请重试")
|
//ToastUtils.showToast("拍照异常,请重试")
|
||||||
failCount++
|
failCount++
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
@@ -331,18 +553,29 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
*/
|
*/
|
||||||
private var failCount = 0
|
private var failCount = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否进行识别:true-识别,false-不识别,默认开启识别
|
||||||
|
*/
|
||||||
|
private var foodRecognizeState = true
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun updateFoodInfo(list: MutableList<FoodInfo>, scoreList: List<IdNameScore>) {
|
private fun updateFoodInfo(list: MutableList<FoodInfo>, scoreList: List<IdNameScore>) {
|
||||||
val queryData = GsonUtils.toJson(list)
|
val queryData = GsonUtils.toJson(list)
|
||||||
val recData = GsonUtils.toJson(scoreList)
|
val recData = GsonUtils.toJson(scoreList)
|
||||||
log("registerDataChange识别后查询接口数据:$queryData,识别数据:$recData")
|
log("registerDataChange识别后查询接口数据:$queryData,识别数据:$recData")
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
binding.tvToSearch.let {
|
foodRecognizeState = false
|
||||||
|
tvToSearch.let {
|
||||||
it.text = "未查询到,手动搜索"
|
it.text = "未查询到,手动搜索"
|
||||||
it.visible()
|
it.visible()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
foodRecognizeState = true
|
||||||
|
//查询到菜品信息,同步设置lastWeight=currentWeight
|
||||||
|
lastWeight=currentWeight
|
||||||
|
presentation?.updateWeight(currentWeight)
|
||||||
|
|
||||||
list.forEach { foodInfo ->
|
list.forEach { foodInfo ->
|
||||||
val scoreItem = scoreList.firstOrNull { it.name == foodInfo.foodName }
|
val scoreItem = scoreList.firstOrNull { it.name == foodInfo.foodName }
|
||||||
val score = scoreItem?.score ?: 0.0
|
val score = scoreItem?.score ?: 0.0
|
||||||
@@ -356,9 +589,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// e.printStackTrace()
|
// e.printStackTrace()
|
||||||
// list
|
// list
|
||||||
// }
|
// }
|
||||||
searchFoodList.clear()
|
|
||||||
searchFoodList.addAll(list)
|
adapter.submitList(list)
|
||||||
adapter.notifyDataSetChanged()
|
rvFoodList.visible()
|
||||||
|
|
||||||
checkedItem = list[0].also {
|
checkedItem = list[0].also {
|
||||||
it.photoUri = lastPhotoUri
|
it.photoUri = lastPhotoUri
|
||||||
@@ -369,10 +602,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// lastPhotoUri = null
|
// lastPhotoUri = null
|
||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
|
|
||||||
binding.tvToSearch.let {
|
tvToSearch.let {
|
||||||
it.text = "以上都不是,手动搜索"
|
it.text = "以上都不是,手动搜索"
|
||||||
it.visible()
|
it.visible()
|
||||||
}
|
}
|
||||||
|
log("registerDataChange识别完成:visible=${rvFoodList.isVisible},count=${rvFoodList.childCount}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupCamera() {
|
private fun setupCamera() {
|
||||||
@@ -541,10 +775,19 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun clearFoodList() {
|
fun clearRecognizeFood() {
|
||||||
//adapter.updateData(listOf())
|
log("clearRecognizeFood")
|
||||||
searchFoodList.clear()
|
rvFoodList.invisible()
|
||||||
adapter.notifyDataSetChanged()
|
layoutEatDetailBinding.root.invisible()
|
||||||
|
adapter.submitList(null)
|
||||||
|
tvToSearch.gone()
|
||||||
|
|
||||||
|
binding.previewView.visible()
|
||||||
|
binding.ivImg.gone()
|
||||||
|
checkedItem = null
|
||||||
|
lastWeight = 0
|
||||||
|
foodRecognizeState = true
|
||||||
|
isSwitchFood = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDateTime() {
|
private fun updateDateTime() {
|
||||||
@@ -576,7 +819,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
log("onResume-00001,isRefreshPage=$isRefreshPage")
|
log("onResume-00001,isRefreshPage=$isRefreshPage")
|
||||||
if (presentation == null || !presentation!!.isShowing) {
|
if (presentation == null || !presentation!!.isShowing) {
|
||||||
log("onResume-00002,副屏未显示,加载副屏")
|
log("onResume-00002,副屏未显示,加载副屏")
|
||||||
lastWeight = 0.0
|
lastWeight = 0
|
||||||
setupSecondaryDisplay()
|
setupSecondaryDisplay()
|
||||||
presentation?.step1FoodRecognizing()
|
presentation?.step1FoodRecognizing()
|
||||||
} else {
|
} else {
|
||||||
@@ -585,21 +828,23 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
isRefreshPage = false
|
isRefreshPage = false
|
||||||
//已显示副屏,则进行更新
|
//已显示副屏,则进行更新
|
||||||
val weight = lastWeight
|
val weight = lastWeight
|
||||||
lastWeight = 0.0
|
lastWeight = 0
|
||||||
|
presentation?.pauseCamera()
|
||||||
presentation?.hideRecImage()
|
presentation?.hideRecImage()
|
||||||
presentation?.step1FoodRecognizing()
|
presentation?.step1FoodRecognizing()
|
||||||
|
|
||||||
|
log("onResume-recognizeByWeight")
|
||||||
binding.root.postDelayed({
|
binding.root.postDelayed({
|
||||||
recognizeByWeight(weight, true)
|
recognizeByWeight(weight, true)
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据付费模式确认是否显示按钮
|
//根据付费模式确认是否显示按钮
|
||||||
binding.btnPay.run {
|
binding.btnPay.run {
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
//0-计费,1-不计费
|
||||||
if (mode == 0) visible() else gone()
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
if (settlementMode == 1 && chargeMode == 0) visible() else gone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,10 +885,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
eatWeight: Int,
|
eatWeight: Int,
|
||||||
eatNum: Int,
|
eatNum: Int,
|
||||||
userId: String?,
|
userId: String?,
|
||||||
|
isMember: Boolean,
|
||||||
notEnoughOneBlock: () -> Unit = {},
|
notEnoughOneBlock: () -> Unit = {},
|
||||||
block: () -> Unit
|
successBlock: () -> Unit
|
||||||
) {
|
) {
|
||||||
log("foodWeight=$foodWeight,eatWeight=$eatWeight")
|
log("foodWeight=$foodWeight,eatWeight=$eatWeight")
|
||||||
|
//0-计费,1-不计费
|
||||||
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
// if (pickupMode == 0) {
|
// if (pickupMode == 0) {
|
||||||
// if (foodWeight <= 5) {
|
// if (foodWeight <= 5) {
|
||||||
@@ -661,7 +910,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
showWaitingDialog("加载中,请稍候……")
|
showWaitingDialog("加载中,请稍候……")
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
|
||||||
val order = FoodOrder(
|
val order = FoodOrder(
|
||||||
deviceId = GlobalData.deviceId,
|
deviceId = GlobalData.deviceId,
|
||||||
foodId = foodInfo.foodId,
|
foodId = foodInfo.foodId,
|
||||||
@@ -675,12 +923,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
userId = userId,
|
userId = userId,
|
||||||
notPay = chargeMode != 0,
|
notPay = chargeMode != 0,
|
||||||
//即放即取-1,称重-2
|
//即放即取-1,称重-2
|
||||||
mode = if (pickupMode == 1) 1 else 2
|
mode = if (pickupMode == 1) 1 else 2,
|
||||||
|
paymentFrom = if (settlementMode == 0) 1 else 2,
|
||||||
|
member = isMember
|
||||||
)
|
)
|
||||||
submitOrder(order, block)
|
submitOrder(order, successBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun submitOrder(order: FoodOrder, block: () -> Unit) {
|
private fun submitOrder(order: FoodOrder, successBlock: () -> Unit) {
|
||||||
viewModel.createOrder(order) { orderId ->
|
viewModel.createOrder(order) { orderId ->
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.root.postDelayed({
|
binding.root.postDelayed({
|
||||||
@@ -690,13 +940,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
return@postDelayed
|
return@postDelayed
|
||||||
}
|
}
|
||||||
foodOrderId = orderId
|
foodOrderId = orderId
|
||||||
block()
|
successBlock()
|
||||||
|
|
||||||
if (checkedItem!!.isFromSearch == true) {
|
if (checkedItem?.isFromSearch == true) {
|
||||||
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
||||||
Thread {
|
lifecycleScope.launch {
|
||||||
saveFoodVector(checkedItem!!)
|
saveFoodVector(checkedItem!!)
|
||||||
}.start()
|
}
|
||||||
}
|
}
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
@@ -704,8 +954,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getEatNum(realWeight: Double?, specWeight: Double?): Int {
|
fun getEatNum(realWeight: Double?, specWeight: Double?): Int {
|
||||||
if (realWeight == null || realWeight <= 0.0 || specWeight == null || specWeight <= 0.0) return 0
|
if (realWeight == null || realWeight <= 0.0 || specWeight == null || specWeight <= 0.0) {
|
||||||
return (realWeight / specWeight).roundToInt()
|
log("getEatNum:realWeight=$realWeight,specWeight=$specWeight")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
val eatNum = (realWeight / specWeight).roundToInt()
|
||||||
|
log("getEatNum:eatNum=$eatNum,realWeight=$realWeight,specWeight=$specWeight,realWeight/$specWeight=${realWeight / specWeight}}")
|
||||||
|
return eatNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private var foodOrderId: String = ""
|
private var foodOrderId: String = ""
|
||||||
@@ -729,16 +984,27 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onUpdateRefreshEvent(event: UpdateRefreshEvent) {
|
fun onUpdateRefreshEvent(event: UpdateRefreshEvent) {
|
||||||
isRefreshPage = true
|
isRefreshPage = true
|
||||||
|
checkedItem = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onPaySuccessEvent(event: PaySuccessEvent) {
|
fun onPaySuccessEvent(event: PaySuccessEvent) {
|
||||||
isRefreshPage = true
|
isRefreshPage = true
|
||||||
|
checkedItem = null
|
||||||
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) ?: 0
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) ?: 0
|
||||||
presentation?.hideNutritionView(chargeMode)
|
presentation?.hideNutritionView(chargeMode)
|
||||||
presentation?.cancel()
|
presentation?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onResetRecognizeState(event: ResetRecognizeEvent) {
|
||||||
|
// presentation?.step1FoodRecognizing()
|
||||||
|
isRefreshPage = true
|
||||||
|
checkedItem = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onChargeModeEvent(event: ChargeModeEvent) {
|
fun onChargeModeEvent(event: ChargeModeEvent) {
|
||||||
isRefreshPage = true
|
isRefreshPage = true
|
||||||
@@ -762,46 +1028,50 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
private fun clickPayButton() {
|
private fun clickPayButton() {
|
||||||
|
log("eatWeight:recognizeWeight=$recognizeWeight, currentWeight=$currentWeight, lastWeight=$lastWeight")
|
||||||
if (checkedItem == null) {
|
if (checkedItem == null) {
|
||||||
ToastUtils.showToast("暂无识别数据,请搜索选择")
|
ToastUtils.showToast("暂无识别数据,请搜索选择")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//val realWeight = (lastWeight * 1000).roundToInt()
|
//val realWeight = (lastWeight * 1000).roundToInt()
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
val mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
val mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) ?: 0
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) ?: 0
|
||||||
var foodWeight = 0.0
|
var foodWeight = 0
|
||||||
var eatWeight = 0.0
|
var eatWeight = 0
|
||||||
if (chargeMode == 0) {
|
if (chargeMode == 0) {
|
||||||
//计费
|
//计费
|
||||||
if (mealPickupMode == 0) {
|
if (mealPickupMode == 0) {
|
||||||
//即放即取
|
//即放即取
|
||||||
eatWeight = lastWeight * 1000
|
eatWeight = currentWeight
|
||||||
foodWeight = lastWeight * 1000
|
foodWeight = currentWeight
|
||||||
} else {
|
} else {
|
||||||
//余量计量
|
//余量计量
|
||||||
eatWeight = (recognizeWeight - lastWeight) * 1000
|
eatWeight = recognizeWeight - currentWeight
|
||||||
foodWeight = recognizeWeight * 1000
|
foodWeight = recognizeWeight
|
||||||
log("eatWeight=$eatWeight, recognizeWeight=$recognizeWeight, lastWeight=$lastWeight")
|
log("eatWeight=$eatWeight, recognizeWeight=$recognizeWeight, currentWeight=$currentWeight, lastWeight=$lastWeight")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//不计费
|
//不计费
|
||||||
foodWeight = recognizeWeight * 1000
|
foodWeight = recognizeWeight
|
||||||
eatWeight = if (mealPickupMode == 0) {
|
eatWeight = if (mealPickupMode == 0) {
|
||||||
//即放即取
|
//即放即取
|
||||||
recognizeWeight * 1000
|
recognizeWeight
|
||||||
} else {
|
} else {
|
||||||
//余量计量
|
//余量计量
|
||||||
(recognizeWeight - lastWeight) * 1000
|
recognizeWeight - currentWeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val eatNum = getEatNum(eatWeight, checkedItem!!.specWeight)
|
val eatNum = getEatNum(eatWeight.toDouble(), checkedItem!!.specWeight)
|
||||||
createOrder(
|
createOrder(
|
||||||
foodInfo = checkedItem!!,
|
foodInfo = checkedItem!!,
|
||||||
foodWeight = foodWeight.roundToInt(),
|
foodWeight = foodWeight,
|
||||||
eatWeight = eatWeight.roundToInt(),
|
eatWeight = eatWeight,
|
||||||
eatNum = eatNum,
|
eatNum = eatNum,
|
||||||
userId = null,
|
userId = null,
|
||||||
|
isMember = false
|
||||||
) {
|
) {
|
||||||
isRefreshPage = false
|
isRefreshPage = false
|
||||||
shutdownCamera()
|
shutdownCamera()
|
||||||
@@ -925,7 +1195,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// private val dealyMillis = 10 * 60 * 1000L
|
// private val dealyMillis = 10 * 60 * 1000L
|
||||||
private val initialDelay = 10 * 1000L
|
private val initialDelay = 10 * 1000L
|
||||||
private val dealyMillis = 5 * 1000L
|
private val dealyMillis = 5 * 1000L
|
||||||
// private var taskPageNo = 1
|
|
||||||
|
// private var taskPageNo = 1
|
||||||
fun startFaceTask() {
|
fun startFaceTask() {
|
||||||
faceTaskJob =
|
faceTaskJob =
|
||||||
intervalExecutor.startIntervalTaskWithInitialDelay(initialDelay, dealyMillis) {
|
intervalExecutor.startIntervalTaskWithInitialDelay(initialDelay, dealyMillis) {
|
||||||
@@ -944,14 +1215,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
updateFaceData(list)
|
updateFaceData(list)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFaceData(list: List<UserFaceModel>) {
|
private fun updateFaceData(list: List<UserFaceModel>) {
|
||||||
Thread {
|
|
||||||
val faceList = mutableListOf<FaceEntity>()
|
val faceList = mutableListOf<FaceEntity>()
|
||||||
try {
|
try {
|
||||||
list.forEach { model ->
|
list.forEach { model ->
|
||||||
@@ -981,7 +1253,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendFaceData(faceData: String) {
|
private fun sendFaceData(faceData: String) {
|
||||||
@@ -995,18 +1266,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private var tcpClient: TcpClient? = null
|
private var tcpClient: TcpClient? = null
|
||||||
|
|
||||||
private fun onTakePhotoSuccess(photoUri: Uri) {
|
private suspend fun onTakePhotoSuccess(photoUri: Uri) {
|
||||||
lastPhotoUri = photoUri
|
lastPhotoUri = photoUri
|
||||||
log("registerDataChange main,takePhoto耗时:${System.currentTimeMillis() - startTime}")
|
log("registerDataChange main,takePhoto耗时:${System.currentTimeMillis() - startTime}")
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
log("registerDataChange photoUri = ${photoUri.path}")
|
log("registerDataChange photoUri = ${photoUri.path}")
|
||||||
// viewModel.getIdentifiedFoodList()
|
// viewModel.getIdentifiedFoodList()
|
||||||
lifecycleScope.launch {
|
|
||||||
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
ImageUtil.uriToBitmap(this@MainActivity, photoUri)?.let { bitmap ->
|
||||||
queryFoodData(bitmap)
|
queryFoodData(bitmap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun queryFoodData(bitmap: Bitmap) {
|
private suspend fun queryFoodData(bitmap: Bitmap) {
|
||||||
log("registerDataChange main,uriToBitmap耗时:${System.currentTimeMillis() - startTime}")
|
log("registerDataChange main,uriToBitmap耗时:${System.currentTimeMillis() - startTime}")
|
||||||
@@ -1033,11 +1302,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
log("registerDataChange photoUri 识别数据名称:$foodName")
|
log("registerDataChange photoUri 识别数据名称:$foodName")
|
||||||
runOnUiThread {
|
withContext(Dispatchers.Main) {
|
||||||
binding.flPay.run {
|
binding.flPay.run {
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
|
||||||
//0-计费,1-不计费
|
//0-计费,1-不计费
|
||||||
if (chargeMode == 0) visible() else gone()
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
//独立支付+计费模式才显示“去结算”按钮,否则使用人脸识别
|
||||||
|
if (settlementMode == 1 && chargeMode == 0) visible() else gone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TextUtils.isEmpty(foodName)) {
|
if (TextUtils.isEmpty(foodName)) {
|
||||||
@@ -1045,8 +1315,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
//binding.layoutRescan.visibility = View.VISIBLE
|
//binding.layoutRescan.visibility = View.VISIBLE
|
||||||
|
|
||||||
runOnUiThread {
|
withContext(Dispatchers.Main) {
|
||||||
binding.tvToSearch.let {
|
tvToSearch.let {
|
||||||
it.text = "未识别到,手动搜索"
|
it.text = "未识别到,手动搜索"
|
||||||
it.visible()
|
it.visible()
|
||||||
}
|
}
|
||||||
@@ -1071,4 +1341,5 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// ObjectBox.init(this)
|
// ObjectBox.init(this)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -166,6 +166,8 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memberDiscount = 1.0
|
||||||
|
|
||||||
var memberInfo: MemberInfo? = null
|
var memberInfo: MemberInfo? = null
|
||||||
fun showPayInfo(type: Int = 1, isVip: Boolean = false, memberInfo: MemberInfo? = null) {
|
fun showPayInfo(type: Int = 1, isVip: Boolean = false, memberInfo: MemberInfo? = null) {
|
||||||
this.memberInfo = memberInfo
|
this.memberInfo = memberInfo
|
||||||
@@ -191,10 +193,20 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
it.type = type
|
it.type = type
|
||||||
it.foodName = foodInfo?.foodName
|
it.foodName = foodInfo?.foodName
|
||||||
//确认使用vipPrice 还是 specPrice
|
//确认使用vipPrice 还是 specPrice
|
||||||
val onePrice = if (isVip) foodInfo?.vipPrice else foodInfo?.specPrice
|
//val onePrice = if (isVip) foodInfo?.vipPrice else foodInfo?.specPrice
|
||||||
it.totalPrice = (onePrice ?: 0.0) * eatNum
|
if (isVip) {
|
||||||
|
userViewModel.getMemberDiscount(memberInfo?.faceUserId?:"") { discount ->
|
||||||
|
memberDiscount = if (discount == null) 1.0 else discount / 10
|
||||||
|
var onePrice = foodInfo?.specPrice ?: 0.0
|
||||||
|
onePrice = if (isVip) onePrice * memberDiscount else onePrice
|
||||||
|
it.totalPrice = onePrice * eatNum
|
||||||
presentation.initView()
|
presentation.initView()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
it.totalPrice = (foodInfo?.specPrice ?: 0.0) * eatNum
|
||||||
|
presentation.initView()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateQrCodeImage(qrCodeUrl: String?) {
|
fun updateQrCodeImage(qrCodeUrl: String?) {
|
||||||
@@ -287,6 +299,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun bindOrder(userId: String, block: (Boolean) -> Unit) {
|
fun bindOrder(userId: String, block: (Boolean) -> Unit) {
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
||||||
val mode = if (pickupMode == 1) 1 else 2
|
val mode = if (pickupMode == 1) 1 else 2
|
||||||
userViewModel.bindOrder(userId, foodOrderId, mode = mode) { bindResult ->
|
userViewModel.bindOrder(userId, foodOrderId, mode = mode) { bindResult ->
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import com.sw.dualscreen.R
|
|||||||
import com.sw.dualscreen.activity.SettingActivity
|
import com.sw.dualscreen.activity.SettingActivity
|
||||||
import com.sw.dualscreen.databinding.FragmentBusinessBinding
|
import com.sw.dualscreen.databinding.FragmentBusinessBinding
|
||||||
import com.sw.dualscreen.model.response.ChargeModeEvent
|
import com.sw.dualscreen.model.response.ChargeModeEvent
|
||||||
|
import com.sw.dualscreen.model.response.ResetRecognizeEvent
|
||||||
import com.sw.dualscreen.sdk.SensorScaleUtils
|
import com.sw.dualscreen.sdk.SensorScaleUtils
|
||||||
import com.sw.dualscreen.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
|
import com.sw.dualscreen.utils.SpTool
|
||||||
import com.sw.plate.utils.ToastUtils
|
import com.sw.plate.utils.ToastUtils
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@@ -19,19 +21,21 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
|
binding.rgSettlement.let {
|
||||||
|
//val settlementMode = if (binding.rgSettlement.checkedRadioButtonId == R.id.rbJointPayment) 0 else 1
|
||||||
|
|
||||||
|
//val mode = SPUtil.getInstance().get(GlobalKey.KEY_SETTLEMENT_MODE, 1)
|
||||||
|
it.check(if (SpTool.settlementMode == 0) R.id.rbJointPayment else R.id.rbIndependentPayment)
|
||||||
|
binding.rbJointPayment.isEnabled = false
|
||||||
|
binding.rbIndependentPayment.isEnabled = false
|
||||||
|
}
|
||||||
binding.rgCharge.let {
|
binding.rgCharge.let {
|
||||||
// it.setOnCheckedChangeListener { group, checkedId ->
|
//0-计费,1-不计费
|
||||||
// val mode = if (checkedId == R.id.rbChargeYes) 0 else 1
|
|
||||||
// SPUtil.getInstance().put(GlobalKey.KEY_CHARGE_MODE, mode)
|
|
||||||
// }
|
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
it.check(if (mode == 0) R.id.rbChargeYes else R.id.rbChargeNot)
|
it.check(if (mode == 0) R.id.rbChargeYes else R.id.rbChargeNot)
|
||||||
}
|
}
|
||||||
binding.rgTakeFood.let {
|
binding.rgTakeFood.let {
|
||||||
// it.setOnCheckedChangeListener { group, checkedId ->
|
//0-即放即取,1-余量计量
|
||||||
// val mode = if (checkedId == R.id.rbPickAndPlace) 0 else 1
|
|
||||||
// SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode)
|
|
||||||
// }
|
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
||||||
it.check(if (mode == 0) R.id.rbPickAndPlace else R.id.rbSurplusCalculate)
|
it.check(if (mode == 0) R.id.rbPickAndPlace else R.id.rbSurplusCalculate)
|
||||||
}
|
}
|
||||||
@@ -39,6 +43,10 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
SensorScaleUtils.tare()
|
SensorScaleUtils.tare()
|
||||||
}
|
}
|
||||||
binding.btnConfirm.setOnClickListener { v ->
|
binding.btnConfirm.setOnClickListener { v ->
|
||||||
|
// if (binding.rgSettlement.checkedRadioButtonId == -1) {
|
||||||
|
// ToastUtils.showToast("请设置结算模式")
|
||||||
|
// return@setOnClickListener
|
||||||
|
// }
|
||||||
if (binding.rgCharge.checkedRadioButtonId == -1) {
|
if (binding.rgCharge.checkedRadioButtonId == -1) {
|
||||||
ToastUtils.showToast("请设置计费模式")
|
ToastUtils.showToast("请设置计费模式")
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
@@ -50,6 +58,7 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
|
|
||||||
val chargeMode = if (binding.rgCharge.checkedRadioButtonId == R.id.rbChargeYes) 0 else 1
|
val chargeMode = if (binding.rgCharge.checkedRadioButtonId == R.id.rbChargeYes) 0 else 1
|
||||||
//原来的支付模式
|
//原来的支付模式
|
||||||
|
//0-计费,1-不计费
|
||||||
val oldChargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val oldChargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
if (chargeMode != oldChargeMode) {
|
if (chargeMode != oldChargeMode) {
|
||||||
//支付模式有变化通知首页页面刷新
|
//支付模式有变化通知首页页面刷新
|
||||||
@@ -59,7 +68,7 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
|
|
||||||
val pickupMode = if (binding.rgTakeFood.checkedRadioButtonId == R.id.rbPickAndPlace) 0 else 1
|
val pickupMode = if (binding.rgTakeFood.checkedRadioButtonId == R.id.rbPickAndPlace) 0 else 1
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, pickupMode)
|
SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, pickupMode)
|
||||||
|
EventBus.getDefault().post(ResetRecognizeEvent())
|
||||||
//ToastUtils.showToast("设置已保存")
|
//ToastUtils.showToast("设置已保存")
|
||||||
(activity as SettingActivity).let {
|
(activity as SettingActivity).let {
|
||||||
it.showWaitingDialog("设置保存中")
|
it.showWaitingDialog("设置保存中")
|
||||||
@@ -70,8 +79,8 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SensorScaleUtils.addWeightListener { value ->
|
SensorScaleUtils.addWeightListener { value ->
|
||||||
val realWeight = (value * 1000).roundToInt()
|
//val realWeight = (value * 1000).roundToInt()
|
||||||
binding.tvFoodWeight.text = "$realWeight"
|
binding.tvFoodWeight.text = "$value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,11 +118,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
collectionAdapter.notifyItemChanged(index)
|
collectionAdapter.notifyItemChanged(index)
|
||||||
}
|
}
|
||||||
// settingActivity?.hideWaitingDialog()
|
// settingActivity?.hideWaitingDialog()
|
||||||
Thread {
|
activity?.lifecycleScope?.launch {
|
||||||
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
||||||
getImageVector(index, bitmap)
|
getImageVector(index, bitmap)
|
||||||
}
|
}
|
||||||
}.start()
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
settingActivity?.hideWaitingDialog()
|
settingActivity?.hideWaitingDialog()
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
|
|||||||
// }
|
// }
|
||||||
payActivity.foodInfo?.let {
|
payActivity.foodInfo?.let {
|
||||||
foodName = it.foodName
|
foodName = it.foodName
|
||||||
payAmount = (it.vipPrice ?: 0.0) * payActivity.eatNum
|
// payAmount = (it.vipPrice ?: 0.0) * payActivity.eatNum
|
||||||
|
val price = it.specPrice ?: 0.0
|
||||||
|
payAmount = price * payActivity.memberDiscount * payActivity.eatNum
|
||||||
}
|
}
|
||||||
showSubScreen()
|
showSubScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (memberInfo != null && memberInfo!!.member) {
|
if (memberInfo != null && memberInfo!!.member) {
|
||||||
totalPrice = (payActivity.foodInfo?.vipPrice ?: 0.0) * payActivity.eatNum
|
// totalPrice = (payActivity.foodInfo?.vipPrice ?: 0.0) * payActivity.eatNum
|
||||||
|
val price = payActivity.foodInfo?.specPrice ?: 0.0
|
||||||
|
totalPrice = price * payActivity.memberDiscount * payActivity.eatNum
|
||||||
binding.layoutVip.visible()
|
binding.layoutVip.visible()
|
||||||
balance = (memberInfo!!.topUpBalance ?: 0.0) + (memberInfo!!.rewardBalance ?: 0.0)
|
balance = (memberInfo!!.topUpBalance ?: 0.0) + (memberInfo!!.rewardBalance ?: 0.0)
|
||||||
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
|
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import androidx.core.graphics.toColorInt
|
|||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
import com.sw.dualscreen.databinding.ListItemSearchFoodBinding
|
import com.sw.dualscreen.databinding.ListItemSearchFood3Binding
|
||||||
import com.sw.dualscreen.ext.format2String
|
import com.sw.dualscreen.ext.format2String
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
|
|
||||||
class CollectFoodListAdapter(var list: MutableList<FoodInfo>) :
|
class CollectFoodListAdapter(var list: MutableList<FoodInfo>) :
|
||||||
BaseQuickAdapter<FoodInfo, CollectFoodListAdapter.VH>(list) {
|
BaseQuickAdapter<FoodInfo, CollectFoodListAdapter.VH>(list) {
|
||||||
inner class VH(var binding: ListItemSearchFoodBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemSearchFood3Binding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
val inflater = LayoutInflater.from(context)
|
val inflater = LayoutInflater.from(context)
|
||||||
val binding = ListItemSearchFoodBinding.inflate(inflater, parent, false)
|
val binding = ListItemSearchFood3Binding.inflate(inflater, parent, false)
|
||||||
return VH(binding)
|
return VH(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.sw.dualscreen.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.graphics.toColorInt
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.sw.dualscreen.databinding.ListItemFoodOrderBinding
|
||||||
|
import com.sw.dualscreen.ext.dp
|
||||||
|
import com.sw.dualscreen.ext.format2String
|
||||||
|
import com.sw.dualscreen.ext.gone
|
||||||
|
import com.sw.dualscreen.ext.visible
|
||||||
|
import com.sw.dualscreen.model.response.FoodItem
|
||||||
|
|
||||||
|
class FoodOrderAdapter(list: MutableList<FoodItem>) :
|
||||||
|
BaseQuickAdapter<FoodItem, FoodOrderAdapter.VH>(list) {
|
||||||
|
|
||||||
|
inner class VH(var binding: ListItemFoodOrderBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = ListItemFoodOrderBinding.inflate(inflater, parent, false)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
override fun onBindViewHolder(holder: VH, position: Int, item: FoodItem?) {
|
||||||
|
val binding = holder.binding
|
||||||
|
setTextColor(binding.tvFoodName, binding.tvPriceNorm, binding.tvWeight, binding.tvAmount)
|
||||||
|
item?.let {
|
||||||
|
binding.tvFoodName.text = it.foodName
|
||||||
|
binding.tvFoodName.setTextColor(if (it.isLocalData) Color.GREEN else "#FF33446A".toColorInt())
|
||||||
|
if (it.orderFrom == 2) {
|
||||||
|
binding.tvPriceNorm.text = if (it.specName.isNullOrBlank()) "${it.specWeight}克" else "${it.specName}/${it.specWeight}克"
|
||||||
|
} else {
|
||||||
|
val foodPrice = it.foodPrice.format2String(2)
|
||||||
|
binding.tvPriceNorm.text = "${foodPrice}/100克"
|
||||||
|
}
|
||||||
|
//if (it.specName.isNullOrBlank().not()) {
|
||||||
|
// binding.tvPriceFlag.text = "[${it.specName}]"
|
||||||
|
//}
|
||||||
|
binding.tvWeight.text = "${it.num}克"
|
||||||
|
binding.tvAmount.text = it.price.format2String(2)
|
||||||
|
binding.tvLabel.run {
|
||||||
|
if (it.orderFrom == 2) visible() else gone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.root.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||||
|
topMargin = 2.dp
|
||||||
|
bottomMargin = 2.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTextColor(vararg tvList: TextView) {
|
||||||
|
tvList.forEach {
|
||||||
|
it.setTextColor("#FF33446A".toColorInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.sw.dualscreen.dialog
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import com.sw.dualscreen.GlobalData
|
||||||
|
import com.sw.dualscreen.databinding.DialogEnvSwitchBinding
|
||||||
|
import com.sw.dualscreen.ext.dp
|
||||||
|
import com.sw.dualscreen.utils.SpTool
|
||||||
|
import com.sw.plate.utils.ToastUtils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 环境切换弹窗
|
||||||
|
*
|
||||||
|
* 提供 TEST / UAT / PROD 三套环境的切换功能,
|
||||||
|
* 初始化时自动根据 [GlobalData.appBaseUrl] 选中当前环境,
|
||||||
|
* 确认后更新 [GlobalData.appBaseUrl] 并通过 [onEnvChanged] 回调通知外部。
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param onEnvChanged 确认切换后的回调,参数为新的 baseUrl
|
||||||
|
*/
|
||||||
|
class EnvSwitchDialog(
|
||||||
|
context: Context,
|
||||||
|
private val onEnvChanged: (newBaseUrl: String) -> Unit = {}
|
||||||
|
) : BaseDialog(
|
||||||
|
context,
|
||||||
|
defWidth = 600.dp,
|
||||||
|
defHeight = WindowManager.LayoutParams.WRAP_CONTENT
|
||||||
|
) {
|
||||||
|
|
||||||
|
private lateinit var binding: DialogEnvSwitchBinding
|
||||||
|
|
||||||
|
override fun getRootView(): View {
|
||||||
|
binding = DialogEnvSwitchBinding.inflate(LayoutInflater.from(context))
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
// 根据当前 appBaseUrl 预选对应 RadioButton,不匹配则不选
|
||||||
|
when (GlobalData.appBaseUrl) {
|
||||||
|
GlobalData.TEST_BASE_URL -> binding.rbTest.isChecked = true
|
||||||
|
GlobalData.UAT_BASE_URL -> binding.rbUat.isChecked = true
|
||||||
|
GlobalData.PROD_BASE_URL -> binding.rbProd.isChecked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消按钮
|
||||||
|
binding.btnCancel.setOnClickListener { dismiss() }
|
||||||
|
|
||||||
|
// 确认按钮
|
||||||
|
binding.btnConfirm.setOnClickListener {
|
||||||
|
// 未选中任何选项时提示用户
|
||||||
|
if (binding.rgEnv.checkedRadioButtonId == -1) {
|
||||||
|
ToastUtils.showToast("请选择环境")
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val newUrl = when (binding.rgEnv.checkedRadioButtonId) {
|
||||||
|
binding.rbTest.id -> GlobalData.TEST_BASE_URL
|
||||||
|
binding.rbUat.id -> GlobalData.UAT_BASE_URL
|
||||||
|
binding.rbProd.id -> GlobalData.PROD_BASE_URL
|
||||||
|
else -> return@setOnClickListener
|
||||||
|
}
|
||||||
|
GlobalData.appBaseUrl = newUrl
|
||||||
|
SpTool.baseUrl = newUrl
|
||||||
|
onEnvChanged(newUrl)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,8 +7,11 @@ import android.graphics.BitmapFactory
|
|||||||
import android.graphics.ImageFormat
|
import android.graphics.ImageFormat
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.YuvImage
|
import android.graphics.YuvImage
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import android.view.TouchDelegate
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
@@ -159,3 +162,35 @@ fun View.invisible() {
|
|||||||
fun View.gone() {
|
fun View.gone() {
|
||||||
visibility = View.GONE
|
visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Context.screenSize: IntArray
|
||||||
|
get() {
|
||||||
|
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||||
|
val displayMetrics = DisplayMetrics()
|
||||||
|
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
|
return intArrayOf(
|
||||||
|
displayMetrics.widthPixels,
|
||||||
|
displayMetrics.heightPixels
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩大 View 的点击区域
|
||||||
|
* @param horizontal 水平方向扩大距离(dp)→ 左右各扩大一半
|
||||||
|
* @param vertical 垂直方向扩大距离(dp)→ 上下各扩大一半
|
||||||
|
*/
|
||||||
|
fun View.expandClickArea(horizontal: Int, vertical: Int) {
|
||||||
|
val density = resources.displayMetrics.density
|
||||||
|
val hPx = (horizontal * density).toInt()
|
||||||
|
val vPx = (vertical * density).toInt()
|
||||||
|
|
||||||
|
post {
|
||||||
|
val rect = android.graphics.Rect()
|
||||||
|
getHitRect(rect)
|
||||||
|
|
||||||
|
// 扩大区域:负值 = 向外扩大
|
||||||
|
rect.inset(-hPx, -vPx)
|
||||||
|
//rect.bottom += downPx // 只往下扩大
|
||||||
|
(parent as View).touchDelegate = TouchDelegate(rect, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ data class FoodOrder(
|
|||||||
var remark: String? = "",
|
var remark: String? = "",
|
||||||
|
|
||||||
//即放即取-1,称重-2
|
//即放即取-1,称重-2
|
||||||
var mode: Int
|
var mode: Int,
|
||||||
|
//设备模式,1 结算终端,2档口机
|
||||||
|
var paymentFrom: Int,
|
||||||
|
//是否会员
|
||||||
|
var member: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@@ -96,12 +100,14 @@ data class UserNutrition(
|
|||||||
val fruitsVegetablesNearExcess: String? = null,
|
val fruitsVegetablesNearExcess: String? = null,
|
||||||
//果蔬超量
|
//果蔬超量
|
||||||
val fruitsVegetablesExcess: String? = null,
|
val fruitsVegetablesExcess: String? = null,
|
||||||
//肉蛋推荐值
|
//肉蛋豆推荐值
|
||||||
val meatEggsRecommend: String? = null,
|
val meatEggsBeansRecommend: String? = null,
|
||||||
//肉蛋即将超量
|
//肉蛋豆即将超量
|
||||||
val meatEggsNearExcess: String? = null,
|
val meatEggsBeansNearExcess: String? = null,
|
||||||
//肉蛋超量
|
//肉蛋豆超量
|
||||||
val meatEggsExcess: String? = null,
|
val meatEggsBeansExcess: String? = null,
|
||||||
|
//总重量
|
||||||
|
val eatWeightSum:Double? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
//{"code":"00000","data":"{\"orderType\":0,\"orderPayFrom\":2,\"payType\":\"1\",\"paySuc\":0,\"totalFee\":0.01,\"orderCode\":\"1998193614899372032\",\"message\":\"支付成功\",\"payCode\":\"1998193614899372032508227\"}","msg":"成功","total":0}
|
//{"code":"00000","data":"{\"orderType\":0,\"orderPayFrom\":2,\"payType\":\"1\",\"paySuc\":0,\"totalFee\":0.01,\"orderCode\":\"1998193614899372032\",\"message\":\"支付成功\",\"payCode\":\"1998193614899372032508227\"}","msg":"成功","total":0}
|
||||||
@@ -123,7 +129,7 @@ data class RespCodeMsg(
|
|||||||
|
|
||||||
|
|
||||||
data class PostEvent(var name: String = "")
|
data class PostEvent(var name: String = "")
|
||||||
data class UpdateRefreshEvent(var name:String = "")
|
data class UpdateRefreshEvent(var name: String = "")
|
||||||
data class PaySuccessEvent(
|
data class PaySuccessEvent(
|
||||||
var name: String = ""
|
var name: String = ""
|
||||||
)
|
)
|
||||||
@@ -131,6 +137,9 @@ data class PaySuccessEvent(
|
|||||||
data class ChargeModeEvent(
|
data class ChargeModeEvent(
|
||||||
var chargeMode: Int = 0
|
var chargeMode: Int = 0
|
||||||
)
|
)
|
||||||
|
data class ResetRecognizeEvent(
|
||||||
|
var state: Int = 0
|
||||||
|
)
|
||||||
|
|
||||||
data class ClickBackEvent(
|
data class ClickBackEvent(
|
||||||
var name: String = ""
|
var name: String = ""
|
||||||
@@ -139,7 +148,9 @@ data class ClickBackEvent(
|
|||||||
data class DeviceConfig(
|
data class DeviceConfig(
|
||||||
var arcsoftAppId: String? = null,
|
var arcsoftAppId: String? = null,
|
||||||
var arcsoftSdkKey: String? = null,
|
var arcsoftSdkKey: String? = null,
|
||||||
var arcsoftActiveKey: String? = null
|
var arcsoftActiveKey: String? = null,
|
||||||
|
//结算模式:1-独立支付模式,2-联合结算模式
|
||||||
|
var payType: Int = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
data class FoodVector(
|
data class FoodVector(
|
||||||
@@ -159,3 +170,32 @@ data class WeightRecord(
|
|||||||
var lastWeight: Int = 0,
|
var lastWeight: Int = 0,
|
||||||
var currentWeight: Int = 0
|
var currentWeight: Int = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class FoodItem(
|
||||||
|
var id: String? = null,
|
||||||
|
var foodId: String? = null,
|
||||||
|
var foodName: String? = null,
|
||||||
|
var foodMaterialId: String? = null,
|
||||||
|
var specId: String? = null,
|
||||||
|
var num: Int = 0,
|
||||||
|
var eatNum: Int = 0,
|
||||||
|
var price: Double = 0.0,
|
||||||
|
var foodPrice: Double = 0.0,
|
||||||
|
var discount: Double = 0.0,
|
||||||
|
var income: Double = 0.0,
|
||||||
|
var foodDifferenceId: Long = 0,
|
||||||
|
var createTime: String? = null,
|
||||||
|
var specName: String? = null,
|
||||||
|
var specWeight: Int = 0,
|
||||||
|
var orderFrom: Int = 0,
|
||||||
|
var isLocalData: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FoodOrderModel(
|
||||||
|
val calorie: Double = 0.0,
|
||||||
|
val incomeSum: Double = 0.0,
|
||||||
|
val discountSum: Double = 0.0,
|
||||||
|
val eatWeightSum: Int = 0,
|
||||||
|
val orderNo: String? = null,
|
||||||
|
val list: List<FoodItem>? = null
|
||||||
|
)
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.sw.dualscreen.network
|
package com.sw.dualscreen.network
|
||||||
|
|
||||||
|
import com.sw.dualscreen.BuildConfig
|
||||||
import com.sw.dualscreen.MyApp
|
import com.sw.dualscreen.MyApp
|
||||||
import com.sw.dualscreen.network.api.ApiService
|
import com.sw.dualscreen.network.api.ApiService
|
||||||
import com.sw.dualscreen.network.interceptor.RequestInterceptor
|
import com.sw.dualscreen.network.interceptor.RequestInterceptor
|
||||||
|
import com.sw.dualscreen.utils.FileUtil
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
@@ -19,14 +22,23 @@ object ApiClient {
|
|||||||
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
|
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
|
||||||
.readTimeout(TIME_OUT, TimeUnit.SECONDS)
|
.readTimeout(TIME_OUT, TimeUnit.SECONDS)
|
||||||
.writeTimeout(TIME_OUT, TimeUnit.SECONDS)
|
.writeTimeout(TIME_OUT, TimeUnit.SECONDS)
|
||||||
.addNetworkInterceptor(HttpLoggingInterceptor(logger = {
|
.addNetworkInterceptor(Interceptor {chain ->
|
||||||
Timber.d("okhttp logger ==>${it}")
|
val request = chain.request()
|
||||||
|
val url = request.url.toString()
|
||||||
|
val tag = if (url.contains("terminal/neglect/common/app/faceFeature/increment/list")) "faceIncrement"
|
||||||
|
else if (url.contains("terminal/neglect/pay/app/turnOrderInfo")) "turnOrderInfo"
|
||||||
|
else "ApiClient"
|
||||||
|
val loggingInterceptor = HttpLoggingInterceptor(logger = {
|
||||||
|
Timber.tag(tag).d("okhttp logger ==>${it}")
|
||||||
|
FileUtil.saveLog("okhttp logger ==>${it}")
|
||||||
}).apply {
|
}).apply {
|
||||||
level = if (MyApp.DEBUG) {
|
level = if (BuildConfig.DEBUG) {
|
||||||
HttpLoggingInterceptor.Level.BODY
|
HttpLoggingInterceptor.Level.BODY
|
||||||
} else {
|
} else {
|
||||||
HttpLoggingInterceptor.Level.NONE
|
HttpLoggingInterceptor.Level.NONE
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
loggingInterceptor.intercept(chain)
|
||||||
})
|
})
|
||||||
.addInterceptor(RequestInterceptor())
|
.addInterceptor(RequestInterceptor())
|
||||||
.build()
|
.build()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.sw.dualscreen.model.response.DinnerType
|
|||||||
import com.sw.dualscreen.model.response.FaceData
|
import com.sw.dualscreen.model.response.FaceData
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
import com.sw.dualscreen.model.response.FoodOrder
|
import com.sw.dualscreen.model.response.FoodOrder
|
||||||
|
import com.sw.dualscreen.model.response.FoodOrderModel
|
||||||
import com.sw.dualscreen.model.response.FoodSearchReq
|
import com.sw.dualscreen.model.response.FoodSearchReq
|
||||||
import com.sw.dualscreen.model.response.FoodVector
|
import com.sw.dualscreen.model.response.FoodVector
|
||||||
import com.sw.dualscreen.model.response.MemberInfo
|
import com.sw.dualscreen.model.response.MemberInfo
|
||||||
@@ -311,4 +312,22 @@ interface ApiService {
|
|||||||
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/deleteBoothMachineCollection",
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/deleteBoothMachineCollection",
|
||||||
@QueryMap param: MutableMap<String, String?>
|
@QueryMap param: MutableMap<String, String?>
|
||||||
): ApiResponse<Any?>
|
): ApiResponse<Any?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询就餐数据
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getFoodOrderList(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/settlement/terminal/app/getFoodInfoBySettlement",
|
||||||
|
@Query("userId") userId: String
|
||||||
|
): ApiResponse<FoodOrderModel?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员折扣
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getMemberDiscount(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getMemberDiscount",
|
||||||
|
@Query("userId") userId: String
|
||||||
|
): ApiResponse<Double?>
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ object FoodModule {
|
|||||||
|
|
||||||
suspend fun queryFoodNameScore(
|
suspend fun queryFoodNameScore(
|
||||||
floatArray: FloatArray?,
|
floatArray: FloatArray?,
|
||||||
queryCount: Int = 15
|
queryCount: Int = 50
|
||||||
): List<IdNameScore> {
|
): List<IdNameScore> {
|
||||||
if (floatArray == null) return emptyList()
|
if (floatArray == null) return emptyList()
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
@@ -151,7 +151,7 @@ object FoodModule {
|
|||||||
return nameScoreList
|
return nameScoreList
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
|
suspend fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 50): List<IdNameScore> {
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
val floatArray = bitmap2FloatArray(bitmap, false)
|
val floatArray = bitmap2FloatArray(bitmap, false)
|
||||||
Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}")
|
Timber.tag(TAG).d("bitmap2FloatArray,耗时:${System.currentTimeMillis() - startTime}")
|
||||||
@@ -161,28 +161,26 @@ object FoodModule {
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
val maxScoreList = nameScoreList
|
val maxScoreList = nameScoreList
|
||||||
.filter { it.score < 1 - THRESHOLD }
|
// .filter { it.score < 1 - THRESHOLD }
|
||||||
.groupBy { it.name }
|
.groupBy { it.name }
|
||||||
.map { (_, value) -> value.minByOrNull { it.score }!! }
|
.map { (_, value) -> value.minByOrNull { it.score }!! }
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
val map = mutableMapOf<String, Int>()
|
// val map = mutableMapOf<String, Int>()
|
||||||
nameScoreList.forEach {
|
// nameScoreList.forEach {
|
||||||
val key = it.name
|
// val key = it.name
|
||||||
val count = map[key] ?: 0
|
// val count = map[key] ?: 0
|
||||||
map[key] = count + 1
|
// map[key] = count + 1
|
||||||
}
|
// }
|
||||||
val orderList = map.entries.sortedByDescending { it.value }.map { it.key }.toMutableList()
|
// val orderList = map.entries.sortedByDescending { it.value }.map { it.key }.toMutableList()
|
||||||
val firstFood = nameScoreList[0].name
|
// val firstFood = nameScoreList[0].name
|
||||||
orderList.remove(firstFood)
|
// orderList.remove(firstFood)
|
||||||
orderList.add(0, firstFood)
|
// orderList.add(0, firstFood)
|
||||||
|
//
|
||||||
val sortedScoreList = maxScoreList.sortedWith(compareBy {
|
// val sortedScoreList = maxScoreList.sortedWith(compareBy {
|
||||||
orderList.indexOf(it.name)
|
// orderList.indexOf(it.name)
|
||||||
})
|
// })
|
||||||
if (bitmap.isRecycled.not()) {
|
val sortedScoreList = maxScoreList.sortedBy { it.score }
|
||||||
bitmap.recycle()
|
Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toString()}")
|
||||||
}
|
|
||||||
//Timber.tag("FoodModule").d("getFoodScoreList数据:${sortedScoreList.toJsonString()}")
|
|
||||||
return sortedScoreList
|
return sortedScoreList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.sw.dualscreen.objbox
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.sw.dualscreen.BuildConfig
|
||||||
import com.sw.plate.App
|
import com.sw.plate.App
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.BoxStore
|
import io.objectbox.BoxStore
|
||||||
@@ -91,14 +92,14 @@ object ObjectBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
val syncAvailable = if (Sync.isAvailable()) "available" else "unavailable"
|
val syncAvailable = if (Sync.isAvailable()) "available" else "unavailable"
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.d("Using ObjectBox ${BoxStore.getVersion()} (${BoxStore.getVersionNative()}, sync $syncAvailable)")
|
.d("Using ObjectBox ${BoxStore.getVersion()} (${BoxStore.getVersionNative()}, sync $syncAvailable)")
|
||||||
// Enable ObjectBox Admin on debug builds.
|
// Enable ObjectBox Admin on debug builds.
|
||||||
// https://docs.objectbox.io/data-browser
|
// https://docs.objectbox.io/data-browser
|
||||||
Admin(boxStore).start(context.applicationContext)
|
Admin(boxStore).start(context.applicationContext)
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +1,50 @@
|
|||||||
package com.sw.dualscreen.presentation
|
package com.sw.dualscreen.presentation
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Presentation
|
import android.app.Presentation
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Outline
|
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
import android.hardware.Camera
|
import android.hardware.Camera
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.util.Log
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.Display
|
import android.view.Display
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewOutlineProvider
|
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.arcsoft.face.ErrorInfo
|
import com.arcsoft.face.ErrorInfo
|
||||||
|
import com.sw.dualscreen.BuildConfig
|
||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.dualscreen.MyApp
|
|
||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
import com.sw.dualscreen.activity.MainActivity
|
import com.sw.dualscreen.activity.MainActivity
|
||||||
|
import com.sw.dualscreen.adapter.FoodOrderAdapter
|
||||||
import com.sw.dualscreen.databinding.PresentationMainScreenBinding
|
import com.sw.dualscreen.databinding.PresentationMainScreenBinding
|
||||||
import com.sw.dualscreen.ext.dp
|
import com.sw.dualscreen.ext.dp
|
||||||
import com.sw.dualscreen.ext.format2String
|
import com.sw.dualscreen.ext.format2String
|
||||||
import com.sw.dualscreen.ext.gone
|
import com.sw.dualscreen.ext.gone
|
||||||
|
import com.sw.dualscreen.ext.invisible
|
||||||
import com.sw.dualscreen.ext.load
|
import com.sw.dualscreen.ext.load
|
||||||
import com.sw.dualscreen.ext.maskName
|
import com.sw.dualscreen.ext.maskName
|
||||||
import com.sw.dualscreen.ext.roundedDecimalPlace
|
import com.sw.dualscreen.ext.roundedDecimalPlace
|
||||||
|
import com.sw.dualscreen.ext.screenSize
|
||||||
import com.sw.dualscreen.ext.visible
|
import com.sw.dualscreen.ext.visible
|
||||||
import com.sw.dualscreen.model.response.DinnerType
|
import com.sw.dualscreen.model.response.DinnerType
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
|
import com.sw.dualscreen.model.response.FoodItem
|
||||||
import com.sw.dualscreen.model.response.UserEnergy
|
import com.sw.dualscreen.model.response.UserEnergy
|
||||||
import com.sw.dualscreen.model.response.UserNutrition
|
import com.sw.dualscreen.model.response.UserNutrition
|
||||||
import com.sw.dualscreen.utils.Debouncer
|
import com.sw.dualscreen.utils.Debouncer
|
||||||
import com.sw.dualscreen.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
|
import com.sw.dualscreen.utils.countDownByFlow
|
||||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||||
import com.sw.plate.utils.LightManager
|
import com.sw.plate.utils.LightManager
|
||||||
import com.sw.plate.utils.ToastUtils
|
import com.sw.plate.utils.ToastUtils
|
||||||
@@ -59,14 +61,15 @@ import com.sw.plate.utils.arcface.face.model.CompareResult
|
|||||||
import com.sw.plate.utils.arcface.face.model.FacePreviewInfo
|
import com.sw.plate.utils.arcface.face.model.FacePreviewInfo
|
||||||
import com.sw.plate.utils.arcface.face.model.RecognizeConfiguration
|
import com.sw.plate.utils.arcface.face.model.RecognizeConfiguration
|
||||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
||||||
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel.REGISTER_STATUS_READY
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.DecimalFormat
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged", "SetTextI18n")
|
||||||
class MainScreenPresentation(
|
class MainScreenPresentation(
|
||||||
val activity: MainActivity,
|
val activity: MainActivity,
|
||||||
display: Display,
|
display: Display,
|
||||||
@@ -76,7 +79,7 @@ class MainScreenPresentation(
|
|||||||
) : Presentation(activity, display), ViewTreeObserver.OnGlobalLayoutListener {
|
) : Presentation(activity, display), ViewTreeObserver.OnGlobalLayoutListener {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "SubScreenPresentation"
|
const val TAG = "MainScreenPresentation"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: PresentationMainScreenBinding
|
private lateinit var binding: PresentationMainScreenBinding
|
||||||
@@ -98,14 +101,14 @@ class MainScreenPresentation(
|
|||||||
private var irFaceRectTransformer: FaceRectTransformer? = null
|
private var irFaceRectTransformer: FaceRectTransformer? = null
|
||||||
|
|
||||||
private var detectWeight = 0.0 //识别菜品时的重量
|
private var detectWeight = 0.0 //识别菜品时的重量
|
||||||
var lastWeight = 0.0 // 上一次的计算热量结果
|
var lastWeight = 0 // 上一次的计算热量结果
|
||||||
|
|
||||||
// private var userNutritionData: UserNutritionData? = null
|
// private var userNutritionData: UserNutritionData? = null
|
||||||
private var userNutrition: UserNutrition? = null
|
private var userNutrition: UserNutrition? = null
|
||||||
private var dinnerTypeInfo: DinnerType? = null
|
private var dinnerTypeInfo: DinnerType? = null
|
||||||
private val debouncer = Debouncer(500)
|
private val debouncer = Debouncer(1500)
|
||||||
private var recognitionTime: Long = 0L // 人脸识别时的时间
|
private var recognitionTime: Long = 0L // 人脸识别时的时间
|
||||||
var recognitionWeight: Double = 0.0 // 人脸识别时的重量
|
var recognitionWeight: Int = 0 // 人脸识别时的重量
|
||||||
|
|
||||||
private var lastFaceTrackId: Int = -1 // 上一次的人脸信息
|
private var lastFaceTrackId: Int = -1 // 上一次的人脸信息
|
||||||
var mealPickupMode: Int = 0 // 取餐模式 0 即放即取 1 余量取餐
|
var mealPickupMode: Int = 0 // 取餐模式 0 即放即取 1 余量取餐
|
||||||
@@ -114,6 +117,7 @@ class MainScreenPresentation(
|
|||||||
var isKeepFaceState = false
|
var isKeepFaceState = false
|
||||||
|
|
||||||
var currentUserId: String? = null
|
var currentUserId: String? = null
|
||||||
|
var isMember: Boolean = false
|
||||||
|
|
||||||
var facePreviewInfoList: MutableList<FacePreviewInfo>? = null
|
var facePreviewInfoList: MutableList<FacePreviewInfo>? = null
|
||||||
|
|
||||||
@@ -121,11 +125,13 @@ class MainScreenPresentation(
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = PresentationMainScreenBinding.inflate(layoutInflater)
|
binding = PresentationMainScreenBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
window?.setBackgroundDrawableResource(android.R.color.white)
|
window?.setBackgroundDrawableResource(android.R.color.white)
|
||||||
initView()
|
initView()
|
||||||
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
if (chargeMode == 1) {
|
if (activity.settlementMode == 0 || chargeMode == 1) {
|
||||||
setupArcCamera()
|
setupArcCamera()
|
||||||
}
|
}
|
||||||
registerDataChange()
|
registerDataChange()
|
||||||
@@ -134,71 +140,83 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
private var isFirstGetWeight = true
|
private var isFirstGetWeight = true
|
||||||
|
|
||||||
fun updateWeight(weight: Double) {
|
fun updateWeight(weight: Int) {
|
||||||
lastWeight = weight * 1000 // 将千克转成克
|
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.d("updateWeight lastWeight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1")
|
.d("updateWeight weight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1")
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
// if (mealPickupMode == 1 && chargeMode == 0) {
|
if (currentStep == 2 && weight <= MainActivity.WEIGHT_RESET_RECOGNIZE && isGoStep1) {
|
||||||
// //余量计量+计费模式
|
|
||||||
// if (isFirstGetWeight && lastWeight > 5) {
|
|
||||||
// recognitionWeight = lastWeight
|
|
||||||
// isFirstGetWeight = false
|
|
||||||
// }
|
|
||||||
// if (lastWeight > 5) {
|
|
||||||
// //余量计量,有重量的情况下不回到重新识别状态
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// isFirstGetWeight = true
|
|
||||||
// }
|
|
||||||
if (currentStep == 2 && lastWeight <= 5 && isGoStep1) {
|
|
||||||
//人脸识别过程中,秤上物品拿走
|
//人脸识别过程中,秤上物品拿走
|
||||||
isGoStep1 = false
|
isGoStep1 = false
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
Timber.tag(TAG).e("切回step1")
|
Timber.tag(TAG).e("切回step1,------2000000000000")
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
}
|
}
|
||||||
} else if (lastWeight <= 5) {
|
} else if (weight <= MainActivity.WEIGHT_RESET_RECOGNIZE) {
|
||||||
isGoStep1 = false
|
isGoStep1 = false
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
Timber.tag(TAG).e("切回step1")
|
Timber.tag(TAG).e("切回step1,------2000000000001")
|
||||||
if (mealPickupMode == 0) {
|
if (mealPickupMode == 0) {
|
||||||
//即放即取
|
//即放即取
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
} else {
|
} else {
|
||||||
//秤上菜品不足,请补充
|
if (currentStep == 1 && currentFood == null) {
|
||||||
|
return@runOnUiThread
|
||||||
|
}
|
||||||
|
//余量计量
|
||||||
|
initCountDownResetJob(weight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (currentStep != 3) {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
if (currentFood == null) {
|
if (currentFood == null) {
|
||||||
Timber.tag(TAG).e("updateWeight currentFood is null")
|
Timber.tag(TAG).e("updateWeight currentFood is null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (userNutritionData == null) {
|
|
||||||
if (userNutrition == null) {
|
if (userNutrition == null) {
|
||||||
Timber.tag(TAG).e("updateWeight userNutritionData is null")
|
Timber.tag(TAG).e("updateWeight userNutritionData is null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if (dinnerTypeInfo == null) {
|
if (chargeMode == 1 || activity.settlementMode == 0) {
|
||||||
// Timber.tag(TAG).e("updateWeight dinnerType is null")
|
//不计费或者联合支付模式更新营养热量数据
|
||||||
// return
|
|
||||||
// }
|
|
||||||
if (chargeMode == 1) {
|
|
||||||
//不计费
|
|
||||||
if (mealPickupMode == 0) {
|
if (mealPickupMode == 0) {
|
||||||
//即放即取
|
//即放即取
|
||||||
calculateNutrition(lastWeight)
|
calculateNutrition(weight)
|
||||||
} else {
|
} else {
|
||||||
//余量计量
|
//余量计量
|
||||||
calculateNutrition(recognitionWeight - lastWeight)
|
val value = recognitionWeight - weight
|
||||||
|
Timber.tag(TAG).e("updateWeight 余量计量:${recognitionWeight} - ${weight} = ${value}")
|
||||||
|
calculateNutrition(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastWeight = weight
|
||||||
|
}
|
||||||
|
|
||||||
|
private var countDownResetJob: Job? = null
|
||||||
|
|
||||||
|
private fun initCountDownResetJob(weight: Int) {
|
||||||
|
if (countDownResetJob == null || countDownResetJob?.isActive == false) {
|
||||||
|
countDownResetJob = countDownByFlow(
|
||||||
|
total = 30,
|
||||||
|
scope = activity.lifecycleScope,
|
||||||
|
onStart = {},
|
||||||
|
onTick = { seconds ->
|
||||||
|
Timber.tag(TAG).e("余量计量模型秤重量已清空,等待${seconds}秒后继续重置识别状态")
|
||||||
|
if (weight > MainActivity.WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
countDownResetJob?.cancel()
|
||||||
|
countDownResetJob = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFinish = {
|
||||||
|
step1FoodRecognizing()
|
||||||
|
countDownResetJob?.cancel()
|
||||||
|
countDownResetJob = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStepChangeCallback(callback: (Int) -> Unit) {
|
fun setStepChangeCallback(callback: (Int) -> Unit) {
|
||||||
@@ -275,16 +293,58 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setTopInfoVisible() {
|
||||||
|
binding.llTopInfo.visible()
|
||||||
|
binding.flFoodDetail.gone()
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
try {
|
||||||
|
foodOrderList.clear()
|
||||||
|
foodOrderAdapter.submitList(foodOrderList)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.llTopInfo.updateLayoutParams {
|
||||||
|
height = activity.screenSize[1] / 2 + 120.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var isGoRecognize = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示识别出的菜品信息
|
* 显示识别出的菜品信息
|
||||||
*/
|
*/
|
||||||
fun step3ShowRecognizeResult(userId: String) {
|
fun step3ShowRecognizeResult(userId: String) {
|
||||||
|
step3Debouncer.debounce {
|
||||||
Timber.tag(TAG).d("main,step3,耗时:${System.currentTimeMillis() - startTime}")
|
Timber.tag(TAG).d("main,step3,耗时:${System.currentTimeMillis() - startTime}")
|
||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
LightManager.openGreenLight()
|
LightManager.openGreenLight()
|
||||||
currentStep = 3
|
currentStep = 3
|
||||||
stepChangeCallback(currentStep)
|
stepChangeCallback(currentStep)
|
||||||
//根据接口数据更新热量数据--------------------------
|
|
||||||
|
setTopInfoVisible()
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
//判断是联合支付调用接口查询就餐信息后,再查询热量营养数据
|
||||||
|
loadOrderList(userId) {
|
||||||
|
loadUserNutritionData(userId)
|
||||||
|
}
|
||||||
|
activity.layoutEatDetailBinding.root.visible()
|
||||||
|
} else {
|
||||||
|
//独立支付
|
||||||
|
loadUserNutritionData(userId)
|
||||||
|
}
|
||||||
|
step3Debouncer.reset()
|
||||||
|
activity.isSwitchFood = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val step3Debouncer = Debouncer(10*1000)
|
||||||
|
private var memberDiscount:Double = 1.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据接口数据更新热量、营养数据
|
||||||
|
*/
|
||||||
|
private fun loadUserNutritionData(userId: String) {
|
||||||
userViewModel.getUserNutritionData(userId = userId) { nutrition ->
|
userViewModel.getUserNutritionData(userId = userId) { nutrition ->
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
if (nutrition == null) {
|
if (nutrition == null) {
|
||||||
@@ -401,7 +461,7 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var isLoadUnbilledMode = false
|
private var isLoadUnbilledMode = false
|
||||||
private val df by lazy { DecimalFormat("#.##") }
|
// private val df by lazy { DecimalFormat("#.##") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 餐品识别成功,不计费模式
|
* 餐品识别成功,不计费模式
|
||||||
@@ -410,19 +470,6 @@ class MainScreenPresentation(
|
|||||||
if (currentUserId.isNullOrBlank()) {
|
if (currentUserId.isNullOrBlank()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//todo 清除人脸数据
|
|
||||||
// binding.dualCameraFaceRectView.clearFaceInfo()
|
|
||||||
// clearLeftFaceData()
|
|
||||||
// facePreviewInfoList?.clear()
|
|
||||||
// recognizeViewModel.updateRegisterStatus(REGISTER_STATUS_READY)
|
|
||||||
|
|
||||||
// pauseCamera()
|
|
||||||
|
|
||||||
// resumeCamera()
|
|
||||||
|
|
||||||
// TODO: 如何清除人脸数据重新识别
|
|
||||||
// stopCamera()
|
|
||||||
// setupArcCamera()
|
|
||||||
|
|
||||||
isLoadUnbilledMode = true
|
isLoadUnbilledMode = true
|
||||||
Timber.tag(TAG).d("loadUnbilledMode")
|
Timber.tag(TAG).d("loadUnbilledMode")
|
||||||
@@ -440,15 +487,16 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
//updateFoodInfo(foodInfo)
|
//updateFoodInfo(foodInfo)
|
||||||
binding.nutritionInclude.tvUserName.text = userNutrition?.name.maskName()
|
binding.nutritionInclude.tvUserName.text = userNutrition?.name.maskName()
|
||||||
val recommendCalorie = userNutrition?.recommendCalorie ?: 0.0
|
val recommendCalorie = (userNutrition?.recommendCalorie ?: 0.0).roundedDecimalPlace(1)
|
||||||
|
|
||||||
binding.nutritionInclude.tvRecommendHeat.text =
|
binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${recommendCalorie}kcal"
|
||||||
"推荐热量:${df.format(recommendCalorie)}kcal"
|
|
||||||
// binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${recommendCalorie.removeTrailingZeros()}kcal"
|
//0-即放即取,1-余量计量
|
||||||
//updateWeight(lastWeight / 1000)
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
// -------------------------------------------------
|
calculateNutrition(
|
||||||
// 删除userNutritionData,改为userNutrition
|
if (mealPickupMode == 1) recognitionWeight - lastWeight
|
||||||
calculateNutrition(recognitionWeight - lastWeight)
|
else recognitionWeight
|
||||||
|
)
|
||||||
binding.root.postDelayed({
|
binding.root.postDelayed({
|
||||||
isLoadUnbilledMode = false
|
isLoadUnbilledMode = false
|
||||||
}, 10000)
|
}, 10000)
|
||||||
@@ -465,24 +513,24 @@ class MainScreenPresentation(
|
|||||||
private var isFirstOpen = true
|
private var isFirstOpen = true
|
||||||
var startTime = 0L
|
var startTime = 0L
|
||||||
|
|
||||||
|
var jointPaymentQueryFinish = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 餐品识别中
|
* 餐品识别中
|
||||||
*/
|
*/
|
||||||
fun step1FoodRecognizing() {
|
fun step1FoodRecognizing() {
|
||||||
|
if (currentStep == 1 && currentFood == null) {
|
||||||
|
activity.clearRecognizeFood()
|
||||||
|
return
|
||||||
|
}
|
||||||
Timber.tag(TAG).d("main,step1,耗时:${System.currentTimeMillis() - startTime}")
|
Timber.tag(TAG).d("main,step1,耗时:${System.currentTimeMillis() - startTime}")
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
|
jointPaymentQueryFinish = false
|
||||||
hideStandbyScreen()
|
hideStandbyScreen()
|
||||||
activity.resetTouchTime()
|
activity.resetTouchTime()
|
||||||
if (isFirstOpen.not()) {
|
if (isFirstOpen.not()) {
|
||||||
activity.resumeAnalysis()
|
activity.resumeAnalysis()
|
||||||
}
|
}
|
||||||
//if (abs(lastWeight.toInt()) <= 5) {
|
|
||||||
// activity.runOnUiThread {
|
|
||||||
// ToastUtils.showToast("秤上重量几乎为0,请确认")
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
currentStep = 1
|
|
||||||
LightManager.closeGreenLight()
|
LightManager.closeGreenLight()
|
||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
|
|
||||||
@@ -490,9 +538,9 @@ class MainScreenPresentation(
|
|||||||
currentFood = null
|
currentFood = null
|
||||||
// userNutritionData = null
|
// userNutritionData = null
|
||||||
userNutrition = null
|
userNutrition = null
|
||||||
recognitionWeight = 0.0
|
recognitionWeight = 0
|
||||||
|
|
||||||
stepChangeCallback(currentStep)
|
setTopInfoVisible()
|
||||||
|
|
||||||
binding.calorieInclude.root.gone()
|
binding.calorieInclude.root.gone()
|
||||||
binding.nutritionInclude.root.gone()
|
binding.nutritionInclude.root.gone()
|
||||||
@@ -511,31 +559,23 @@ class MainScreenPresentation(
|
|||||||
binding.flRecognizeIr.gone()
|
binding.flRecognizeIr.gone()
|
||||||
|
|
||||||
pauseCamera()
|
pauseCamera()
|
||||||
activity.clearFoodList()
|
activity.clearRecognizeFood()
|
||||||
}
|
|
||||||
|
|
||||||
// fun foodRecSuccess(foodInfo: FoodInfo) {
|
currentStep = 1
|
||||||
// //识别逻辑完成根据是否计费显示不同页面
|
stepChangeCallback(currentStep)
|
||||||
// val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
}
|
||||||
// if (mode == 0) {
|
|
||||||
// //计费
|
|
||||||
// loadBilledMode()
|
|
||||||
// } else {
|
|
||||||
// //不计费
|
|
||||||
// //userViewModel.getUserNutritionData(
|
|
||||||
// // userId = userId,
|
|
||||||
// // foodId = currentFood!!.foodId!!
|
|
||||||
// //)
|
|
||||||
// loadUnbilledMode()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户人脸识别中
|
* 用户人脸识别中
|
||||||
*/
|
*/
|
||||||
fun step2FaceRecognizing(foodInfo: FoodInfo) {
|
fun step2FaceRecognizing(foodInfo: FoodInfo, hideFoodDetail: Boolean = false) {
|
||||||
isGoStep1 = true
|
isGoStep1 = true
|
||||||
Timber.tag(TAG).d("main,step2,耗时:${System.currentTimeMillis() - startTime}")
|
Timber.tag(TAG).d("main,step2,耗时:${System.currentTimeMillis() - startTime}")
|
||||||
|
|
||||||
|
if (hideFoodDetail) {
|
||||||
|
setTopInfoVisible()
|
||||||
|
}
|
||||||
|
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
currentStep = 2
|
currentStep = 2
|
||||||
LightManager.closeRedLight()
|
LightManager.closeRedLight()
|
||||||
@@ -559,7 +599,7 @@ class MainScreenPresentation(
|
|||||||
dinnerTypeInfo = null
|
dinnerTypeInfo = null
|
||||||
// userNutritionData = null
|
// userNutritionData = null
|
||||||
userNutrition = null
|
userNutrition = null
|
||||||
recognitionWeight = 0.0
|
recognitionWeight = 0
|
||||||
|
|
||||||
stepChangeCallback(currentStep)
|
stepChangeCallback(currentStep)
|
||||||
currentFood = foodInfo
|
currentFood = foodInfo
|
||||||
@@ -567,6 +607,10 @@ class MainScreenPresentation(
|
|||||||
// userViewModel.getDinnerType()
|
// userViewModel.getDinnerType()
|
||||||
|
|
||||||
resumeCamera()
|
resumeCamera()
|
||||||
|
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
activity.layoutEatDetailBinding.root.invisible()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideRecImage() {
|
fun hideRecImage() {
|
||||||
@@ -574,7 +618,7 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 当前食物信息
|
// 当前食物信息
|
||||||
private var currentFood: FoodInfo? = null
|
var currentFood: FoodInfo? = null
|
||||||
fun updateFood(foodInfo: FoodInfo?) {
|
fun updateFood(foodInfo: FoodInfo?) {
|
||||||
//if (isLoadUnbilledMode) return
|
//if (isLoadUnbilledMode) return
|
||||||
Timber.tag(TAG).d("main,updateFood,耗时:${System.currentTimeMillis() - startTime}")
|
Timber.tag(TAG).d("main,updateFood,耗时:${System.currentTimeMillis() - startTime}")
|
||||||
@@ -586,6 +630,7 @@ class MainScreenPresentation(
|
|||||||
binding.tvFoodName.text = foodInfo.foodName
|
binding.tvFoodName.text = foodInfo.foodName
|
||||||
binding.ivPreviewImage.gone()
|
binding.ivPreviewImage.gone()
|
||||||
binding.ivFrame.gone()
|
binding.ivFrame.gone()
|
||||||
|
//0-计费,1-不计费
|
||||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
if (chargeMode == 0) {
|
if (chargeMode == 0) {
|
||||||
binding.ivRecImage.let {
|
binding.ivRecImage.let {
|
||||||
@@ -597,22 +642,25 @@ class MainScreenPresentation(
|
|||||||
} else {
|
} else {
|
||||||
binding.ivRecImage.gone()
|
binding.ivRecImage.gone()
|
||||||
}
|
}
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
//独立支付+计费模式,使用人脸识别
|
||||||
if (mode == 0) {
|
if (activity.settlementMode == 1 && chargeMode == 0) {
|
||||||
//计费,查询营养信息、价格信息------------------------
|
//计费,查询营养信息、价格信息------------------------
|
||||||
loadBilledMode()
|
loadBilledMode()
|
||||||
} else {
|
} else {
|
||||||
//不计费
|
//联合支付,进行人脸识别
|
||||||
//开启人脸识别
|
if (activity.settlementMode == 0) {
|
||||||
|
if (activity.isSwitchFood.not()) {
|
||||||
|
step2FaceRecognizing(foodInfo)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//不计费,开启人脸识别
|
||||||
if (currentStep == 1 || binding.tvFaceTip.isVisible.not()) {
|
if (currentStep == 1 || binding.tvFaceTip.isVisible.not()) {
|
||||||
|
if (activity.isSwitchFood.not()) {
|
||||||
step2FaceRecognizing(foodInfo)
|
step2FaceRecognizing(foodInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (currentStep == 1) {
|
}
|
||||||
// step2FaceRecognizing(foodInfo)
|
}
|
||||||
//} else {
|
|
||||||
// updateFoodInfo(foodInfo)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFoodInfo(foodInfo: FoodInfo) {
|
private fun updateFoodInfo(foodInfo: FoodInfo) {
|
||||||
@@ -636,12 +684,80 @@ class MainScreenPresentation(
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateNutrition(weight1: Double) {
|
private var lastAddWeight = 0
|
||||||
|
private fun addFoodToOrder(weight: Int, foodInfo: FoodInfo) {
|
||||||
|
Timber.tag(TAG) .d("addFoodToOrder: ${weight == lastAddWeight}")
|
||||||
|
// if (weight == lastAddWeight) return
|
||||||
|
lastAddWeight = weight
|
||||||
|
if (weight <= 10) {
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
if (foodOrderList.isNotEmpty() && mealPickupMode == 1) {
|
||||||
|
val last = foodOrderList.last()
|
||||||
|
if (last.isLocalData) {
|
||||||
|
foodOrderList.remove(last)
|
||||||
|
// foodOrderAdapter.submitList(foodOrderList)
|
||||||
|
foodOrderAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//val foodPrice = if (isMember) foodInfo.vipPrice else foodInfo.specPrice
|
||||||
|
val foodPrice = (foodInfo.specPrice ?: 0.0) * memberDiscount
|
||||||
|
val eatNum = activity.getEatNum(weight.toDouble(), foodInfo.specWeight)
|
||||||
|
val price = eatNum * foodPrice
|
||||||
|
if (foodOrderList.isNotEmpty() && mealPickupMode == 1) {
|
||||||
|
val last = foodOrderList.last()
|
||||||
|
if (last.isLocalData) {
|
||||||
|
last.eatNum = eatNum
|
||||||
|
last.num = weight
|
||||||
|
last.price = price
|
||||||
|
// foodOrderAdapter.submitList(foodOrderList)
|
||||||
|
foodOrderAdapter.notifyItemChanged(foodOrderList.lastIndex)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foodOrderList.add(
|
||||||
|
FoodItem(
|
||||||
|
id = System.currentTimeMillis().toString(),
|
||||||
|
foodId = foodInfo.foodId,
|
||||||
|
foodName = foodInfo.foodName,
|
||||||
|
price = price,
|
||||||
|
specId = foodInfo.specId,
|
||||||
|
foodMaterialId = foodInfo.foodMaterialId,
|
||||||
|
specWeight = foodInfo.specWeight?.toInt() ?: 0,
|
||||||
|
orderFrom = 2,
|
||||||
|
num = weight,
|
||||||
|
eatNum = eatNum,
|
||||||
|
isLocalData = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// foodOrderAdapter.submitList(foodOrderList)
|
||||||
|
foodOrderAdapter.notifyDataSetChanged()
|
||||||
|
Timber.tag(TAG) .d(
|
||||||
|
"addFoodToOrder: size=${foodOrderList.size},新增数据:${foodOrderList.last()}"
|
||||||
|
)
|
||||||
|
//foodOrderAdapter.notifyDataSetChanged()
|
||||||
|
var eatWeightSum = 0
|
||||||
|
foodOrderList.forEach {
|
||||||
|
eatWeightSum += it.num
|
||||||
|
}
|
||||||
|
binding.detailInclude.tvTotalWeight.text = "总重量:${eatWeightSum}克"
|
||||||
|
Timber.tag(TAG) .d("addFoodToOrder: 更新总重量,新增数据------------------------------")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculateNutrition(value: Int) {
|
||||||
|
Timber.tag(TAG) .d("calculateNutrition:weight=$value,recognitionWeight=$recognitionWeight,foodInfo=$currentFood")
|
||||||
if (currentFood == null || userNutrition == null) {
|
if (currentFood == null || userNutrition == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var weight = weight1
|
var weight = value
|
||||||
if (weight < 0) weight = 0.0
|
if (weight < 0) weight = 0
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
activity.runOnUiThread {
|
||||||
|
addFoodToOrder(weight, currentFood!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
debouncer.debounce {
|
debouncer.debounce {
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
||||||
@@ -652,7 +768,7 @@ class MainScreenPresentation(
|
|||||||
currentFood!!,
|
currentFood!!,
|
||||||
// userNutritionData!!,
|
// userNutritionData!!,
|
||||||
userNutrition!!,
|
userNutrition!!,
|
||||||
weight,
|
weight.toDouble(),
|
||||||
dinnerType = dinnerType ?: ""
|
dinnerType = dinnerType ?: ""
|
||||||
)
|
)
|
||||||
// Timber.tag(TAG).d("calculateNutrition calcResultInfo = $calcResultInfo")
|
// Timber.tag(TAG).d("calculateNutrition calcResultInfo = $calcResultInfo")
|
||||||
@@ -666,6 +782,15 @@ class MainScreenPresentation(
|
|||||||
val fruitsVegetables = energy.fruitsVegetables
|
val fruitsVegetables = energy.fruitsVegetables
|
||||||
val meatEggs = energy.meatEggs
|
val meatEggs = energy.meatEggs
|
||||||
|
|
||||||
|
val showTotalCalorie = "总热量:${totalKcal.roundedDecimalPlace(1)}千卡"
|
||||||
|
binding.detailInclude.tvTotalCalorie.text = showTotalCalorie
|
||||||
|
activity.layoutEatDetailBinding.tvTotalCalorie.text = showTotalCalorie
|
||||||
|
|
||||||
|
val totalWeight = (userNutrition?.eatWeightSum ?: 0.0) + weight
|
||||||
|
val showTotalWeight = "总重量:${totalWeight.roundedDecimalPlace(1)}克"
|
||||||
|
binding.detailInclude.tvTotalWeight.text = showTotalWeight
|
||||||
|
activity.layoutEatDetailBinding.tvTotalWeight.text = showTotalWeight
|
||||||
|
|
||||||
val include = binding.nutritionInclude
|
val include = binding.nutritionInclude
|
||||||
|
|
||||||
// 设置热量---------------------------------------------------------------------
|
// 设置热量---------------------------------------------------------------------
|
||||||
@@ -684,7 +809,7 @@ class MainScreenPresentation(
|
|||||||
// 避免0作为被除数
|
// 避免0作为被除数
|
||||||
maxKcal = if (maxKcal <= 0.0) 1.0 else maxKcal
|
maxKcal = if (maxKcal <= 0.0) 1.0 else maxKcal
|
||||||
Timber.tag(TAG).d("maxKcal 1 = $maxKcal")
|
Timber.tag(TAG).d("maxKcal 1 = $maxKcal")
|
||||||
include.totalKcalTv.text = totalKcal.format2String(2)
|
include.totalKcalTv.text = totalKcal.roundedDecimalPlace(1).toString()
|
||||||
var totalKcalHeight = (totalKcal / maxKcal).toFloat()
|
var totalKcalHeight = (totalKcal / maxKcal).toFloat()
|
||||||
if (totalKcalHeight == 0F) {
|
if (totalKcalHeight == 0F) {
|
||||||
include.divKcalView.visible()
|
include.divKcalView.visible()
|
||||||
@@ -702,7 +827,7 @@ class MainScreenPresentation(
|
|||||||
)
|
)
|
||||||
val grainIndex = UserNutritionUtils.findCalorieIndex(energy.grain, grainArray)
|
val grainIndex = UserNutritionUtils.findCalorieIndex(energy.grain, grainArray)
|
||||||
include.customFoodColumn.setImageDrawable(false, grainIndex)
|
include.customFoodColumn.setImageDrawable(false, grainIndex)
|
||||||
include.totalFoodTv.text = grain.format2String(2)
|
include.totalFoodTv.text = grain.roundedDecimalPlace(1).toString()
|
||||||
columnMax = if (columnMax <= 0.0) 1.0 else columnMax
|
columnMax = if (columnMax <= 0.0) 1.0 else columnMax
|
||||||
var grainHeight = (grain / columnMax).toFloat()
|
var grainHeight = (grain / columnMax).toFloat()
|
||||||
if (grainHeight == 0F) {
|
if (grainHeight == 0F) {
|
||||||
@@ -722,7 +847,7 @@ class MainScreenPresentation(
|
|||||||
val fruitsIndex =
|
val fruitsIndex =
|
||||||
UserNutritionUtils.findCalorieIndex(energy.fruitsVegetables, fruitsArray)
|
UserNutritionUtils.findCalorieIndex(energy.fruitsVegetables, fruitsArray)
|
||||||
include.customVegetableColumn.setImageDrawable(false, fruitsIndex)
|
include.customVegetableColumn.setImageDrawable(false, fruitsIndex)
|
||||||
include.totalVegetableTv.text = fruitsVegetables.format2String(2)
|
include.totalVegetableTv.text = fruitsVegetables.roundedDecimalPlace(1).toString()
|
||||||
var fruitsHeight = (fruitsVegetables / columnMax).toFloat()
|
var fruitsHeight = (fruitsVegetables / columnMax).toFloat()
|
||||||
if (fruitsHeight == 0F) {
|
if (fruitsHeight == 0F) {
|
||||||
include.divVegetableView.visible()
|
include.divVegetableView.visible()
|
||||||
@@ -734,14 +859,14 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
// 设置肉蛋-----------------------------------------------------------
|
// 设置肉蛋-----------------------------------------------------------
|
||||||
val meatEggsArray = UserNutritionUtils.getCalorieArray(
|
val meatEggsArray = UserNutritionUtils.getCalorieArray(
|
||||||
left = userNutrition?.meatEggsRecommend,
|
left = userNutrition?.meatEggsBeansRecommend,
|
||||||
mid = userNutrition?.meatEggsNearExcess,
|
mid = userNutrition?.meatEggsBeansNearExcess,
|
||||||
right = userNutrition?.meatEggsExcess
|
right = userNutrition?.meatEggsBeansExcess
|
||||||
)
|
)
|
||||||
val meatEggsIndex =
|
val meatEggsIndex =
|
||||||
UserNutritionUtils.findCalorieIndex(energy.meatEggs, meatEggsArray)
|
UserNutritionUtils.findCalorieIndex(energy.meatEggs, meatEggsArray)
|
||||||
include.customMeatColumn.setImageDrawable(false, meatEggsIndex)
|
include.customMeatColumn.setImageDrawable(false, meatEggsIndex)
|
||||||
include.totalMeatTv.text = meatEggs.format2String(2)
|
include.totalMeatTv.text = meatEggs.roundedDecimalPlace(1).toString()
|
||||||
var meatHeight = (meatEggs / columnMax).toFloat()
|
var meatHeight = (meatEggs / columnMax).toFloat()
|
||||||
if (meatHeight == 0F) {
|
if (meatHeight == 0F) {
|
||||||
include.divMeatView.visible()
|
include.divMeatView.visible()
|
||||||
@@ -765,6 +890,7 @@ class MainScreenPresentation(
|
|||||||
*/
|
*/
|
||||||
fun updateMealPickupMode(mode: Int) {
|
fun updateMealPickupMode(mode: Int) {
|
||||||
Timber.tag(TAG).d("updateMealPickupMode mode = $mode")
|
Timber.tag(TAG).d("updateMealPickupMode mode = $mode")
|
||||||
|
Timber.tag(TAG).e("切回step1,------2000000000003")
|
||||||
mealPickupMode = mode
|
mealPickupMode = mode
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
}
|
}
|
||||||
@@ -785,7 +911,16 @@ class MainScreenPresentation(
|
|||||||
fun resumeCamera() {
|
fun resumeCamera() {
|
||||||
Timber.tag(TAG).d("resumeCamera isRecognition = $isRecognition")
|
Timber.tag(TAG).d("resumeCamera isRecognition = $isRecognition")
|
||||||
isRecognition = true
|
isRecognition = true
|
||||||
if (rgbCameraHelper != null && rgbCameraHelper!!.isStopped) {
|
if (rgbCameraHelper == null) {
|
||||||
|
Timber.tag(TAG).d("resumeCamera isRecognition ---1")
|
||||||
|
setupArcCamera()
|
||||||
|
binding.root.postDelayed({
|
||||||
|
if (rgbCameraHelper != null) {
|
||||||
|
rgbCameraHelper!!.start()
|
||||||
|
}
|
||||||
|
}, 2000)
|
||||||
|
} else if (rgbCameraHelper!!.isStopped) {
|
||||||
|
Timber.tag(TAG).d("resumeCamera isRecognition ---2")
|
||||||
rgbCameraHelper!!.start()
|
rgbCameraHelper!!.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -795,6 +930,23 @@ class MainScreenPresentation(
|
|||||||
isRecognition = false
|
isRecognition = false
|
||||||
|
|
||||||
recognizeViewModel.onPreviewFrame(ByteArray(1382400), true)
|
recognizeViewModel.onPreviewFrame(ByteArray(1382400), true)
|
||||||
|
//triggerReidentify()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置人脸跟踪状态,让已在画面中的人脸重新触发识别
|
||||||
|
* 适用场景:切换按钮后需要重新识别当前画面中的人脸
|
||||||
|
*/
|
||||||
|
fun triggerReidentify() {
|
||||||
|
// 清除UI上的人脸框
|
||||||
|
binding.dualCameraFaceRectView.clearFaceInfo()
|
||||||
|
// 清除本地跟踪数据
|
||||||
|
clearLeftFaceData()
|
||||||
|
// 重置上一次的 trackId,避免 drawPreviewInfo 中的去重逻辑拦截
|
||||||
|
lastFaceTrackId = -1
|
||||||
|
// 插入空帧,让引擎重置内部跟踪状态
|
||||||
|
// isRecognition 保持 true,相机继续送帧,下一帧真实人脸会产生新 trackId
|
||||||
|
recognizeViewModel.onPreviewFrame(ByteArray(1382400), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var recognizeTime = 0L
|
private var recognizeTime = 0L
|
||||||
@@ -842,23 +994,30 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
recognizeViewModel.recognizeUserId.observe(
|
recognizeViewModel.recognizeUserId.observe(
|
||||||
activity,
|
activity,
|
||||||
Observer { compareResult: CompareResult ->
|
Observer { result: CompareResult? ->
|
||||||
|
if (result == null) return@Observer
|
||||||
if (currentStep != 2 || System.currentTimeMillis() - recognizeTime <= 2000) {
|
if (currentStep != 2 || System.currentTimeMillis() - recognizeTime <= 2000) {
|
||||||
//忽略非识别中及两秒内的再次识别
|
//忽略非识别中及5秒内的再次识别
|
||||||
return@Observer
|
return@Observer
|
||||||
}
|
}
|
||||||
|
// if (isGoRecognize.not()) {
|
||||||
|
// return@Observer
|
||||||
|
// }
|
||||||
recognizeTime = System.currentTimeMillis()
|
recognizeTime = System.currentTimeMillis()
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
activity.showWaitingDialog("加载中,请稍后……")
|
activity.showWaitingDialog("加载中,请稍后……")
|
||||||
}
|
}
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}, step = $currentStep")
|
.i("recognizeUserId observe compareResult = ${result.trackId}, userId = ${result.faceEntity.userName}, step = $currentStep")
|
||||||
recognitionTime = System.currentTimeMillis()
|
recognitionTime = System.currentTimeMillis()
|
||||||
|
//识别成功时更新lastWeight,解决使用过程中给秤上放东西,导致重量错误问题
|
||||||
|
lastWeight = activity.currentWeight
|
||||||
recognitionWeight = lastWeight
|
recognitionWeight = lastWeight
|
||||||
lastFaceTrackId = compareResult.trackId
|
lastFaceTrackId = result.trackId
|
||||||
val faceEntity = compareResult.faceEntity
|
val faceEntity = result.faceEntity
|
||||||
val userId = faceEntity.userName
|
val userId = faceEntity.userName
|
||||||
currentUserId = userId
|
currentUserId = userId
|
||||||
|
isMember = faceEntity.userType == "1"
|
||||||
isAgainLoadData = false
|
isAgainLoadData = false
|
||||||
if (userId == null) return@Observer
|
if (userId == null) return@Observer
|
||||||
//ToastUtils.showToast("人脸识别成功,userId = $userId")
|
//ToastUtils.showToast("人脸识别成功,userId = $userId")
|
||||||
@@ -872,7 +1031,12 @@ class MainScreenPresentation(
|
|||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// pauseCamera()
|
||||||
|
//先查询会员折扣
|
||||||
|
userViewModel.getMemberDiscount(userId) { discount ->
|
||||||
|
memberDiscount = if (discount == null) 1.0 else discount / 10
|
||||||
step3ShowRecognizeResult(userId)
|
step3ShowRecognizeResult(userId)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
||||||
@@ -978,6 +1142,7 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
if (facePreviewInfoList.isNullOrEmpty()) {
|
if (facePreviewInfoList.isNullOrEmpty()) {
|
||||||
currentUserId = null
|
currentUserId = null
|
||||||
|
isMember = false
|
||||||
}
|
}
|
||||||
//recognizeViewModel.clearLeftFace(facePreviewInfoList)
|
//recognizeViewModel.clearLeftFace(facePreviewInfoList)
|
||||||
clearLeftFaceData()
|
clearLeftFaceData()
|
||||||
@@ -1135,46 +1300,90 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
val listIsEmpty = facePreviewInfoList.isEmpty()
|
val listIsEmpty = facePreviewInfoList.isEmpty()
|
||||||
val listFirstTrackId = if (listIsEmpty.not()) facePreviewInfoList[0].trackId else null
|
val listFirstTrackId = if (listIsEmpty.not()) facePreviewInfoList[0].trackId else null
|
||||||
Timber.tag(TAG)
|
// Timber.tag(TAG)
|
||||||
.d("listIsEmpty=$listIsEmpty,lastFaceTrackId=$lastFaceTrackId,listFirstTrackId=$listFirstTrackId")
|
// .d("drawPreviewInfo,listIsEmpty=$listIsEmpty,lastFaceTrackId=$lastFaceTrackId,listFirstTrackId=$listFirstTrackId")
|
||||||
if (listIsEmpty || (lastFaceTrackId != listFirstTrackId)) {
|
if (listIsEmpty || (lastFaceTrackId != listFirstTrackId)) {
|
||||||
if (lastFaceTrackId != -1 && currentUserId != null) {
|
if (lastFaceTrackId != -1 && currentUserId != null) {
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
Timber.tag(TAG).i("drawPreviewInfo,$lastFaceTrackId 用户离开")
|
||||||
lastFaceTrackId = -1
|
lastFaceTrackId = -1
|
||||||
Timber.tag(TAG)
|
Timber.tag(TAG)
|
||||||
.d("postUserData userNutritionData是否null: ${userNutrition == null}, currentFood是否null: ${currentFood == null},currentUserId是否null:${currentUserId == null}")
|
.d("drawPreviewInfo,postUserData userNutritionData是否null: ${userNutrition == null}, currentFood是否null: ${currentFood == null},currentUserId是否null:${currentUserId == null}")
|
||||||
if (userNutrition == null || currentFood == null || currentUserId == null) {
|
if (userNutrition == null || currentFood == null || currentUserId == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//重置人脸
|
||||||
|
recognizeViewModel.resetFaceState()
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,开始提交订单")
|
||||||
createOrder(notEnoughOneBlock = {
|
createOrder(notEnoughOneBlock = {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,notEnoughOneBlock")
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,notEnoughOneBlock,联合模式")
|
||||||
|
setTopInfoVisible()
|
||||||
|
}
|
||||||
// if (mealPickupMode == 0) {
|
// if (mealPickupMode == 0) {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,notEnoughOneBlock,step2FaceRecognizing")
|
||||||
currentStep = 2
|
currentStep = 2
|
||||||
step2FaceRecognizing(currentFood!!)
|
step2FaceRecognizing(currentFood!!)
|
||||||
// }
|
// }
|
||||||
}) {
|
}, successBlock = {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成")
|
||||||
// TODO: 测试人脸识别问题--------------------
|
// TODO: 测试人脸识别问题--------------------
|
||||||
//recognizeViewModel.updateRegisterStatus(REGISTER_STATUS_READY)
|
//recognizeViewModel.updateRegisterStatus(REGISTER_STATUS_READY)
|
||||||
if (MyApp.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
ToastUtils.showToast("订单已生成")
|
ToastUtils.showToast("订单已生成")
|
||||||
}
|
}
|
||||||
currentUserId = null
|
currentUserId = null
|
||||||
|
isMember = false
|
||||||
//ToastUtils.showToast("isKeepFaceState=$isKeepFaceState,mealPickupMode=$mealPickupMode")
|
//ToastUtils.showToast("isKeepFaceState=$isKeepFaceState,mealPickupMode=$mealPickupMode")
|
||||||
//|| isKeepFaceState
|
//|| isKeepFaceState
|
||||||
|
// if (activity.settlementMode == 0) {
|
||||||
|
// activity.isAnalyzing = false
|
||||||
|
// step1FoodRecognizing()
|
||||||
|
// } else {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,mealPickupMode=$mealPickupMode")
|
||||||
if (mealPickupMode == 1) {
|
if (mealPickupMode == 1) {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,step2FaceRecognizing")
|
||||||
|
if (activity.currentWeight > MainActivity.WEIGHT_RESET_RECOGNIZE) {
|
||||||
|
//余量计量拿走秤上最后一点餐品时,不用再进行人脸识别了
|
||||||
step2FaceRecognizing(currentFood!!)
|
step2FaceRecognizing(currentFood!!)
|
||||||
|
}
|
||||||
isKeepFaceState = false
|
isKeepFaceState = false
|
||||||
|
if (activity.settlementMode == 0) {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,step2FaceRecognizing,联合支付")
|
||||||
|
setTopInfoVisible()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,称重为:${activity.currentWeight}")
|
||||||
|
//即放即取未拿走餐品,不用重置为默认识别中状态
|
||||||
|
if (abs(activity.currentWeight) > 10) {
|
||||||
|
//提交订单后秤重量绝对值大于10克,都认为餐品还没拿走
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,未拿走餐品")
|
||||||
|
return@createOrder
|
||||||
|
}
|
||||||
|
Timber.tag(TAG).d("drawPreviewInfo,successBlock,订单已生成,step1FoodRecognizing")
|
||||||
|
Timber.tag(TAG).e("切回step1,------2000000000002")
|
||||||
activity.isAnalyzing = false
|
activity.isAnalyzing = false
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createOrder(notEnoughOneBlock: () -> Unit = {}, block: () -> Unit) {
|
/**
|
||||||
|
* 人脸离开后调用创建订单接口
|
||||||
|
*/
|
||||||
|
fun createOrder(notEnoughOneBlock: () -> Unit = {}, successBlock: () -> Unit) {
|
||||||
|
//0-即放即取,1-余量计量
|
||||||
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||||
|
//if (settlementMode == 0) {
|
||||||
|
// //使用联合支付方式
|
||||||
|
// ToastUtils.showToast("使用联合支付方式")
|
||||||
|
// return
|
||||||
|
//}
|
||||||
val eatWeight = if (mealPickupMode == 0) {
|
val eatWeight = if (mealPickupMode == 0) {
|
||||||
//即放即取
|
//即放即取
|
||||||
recognitionWeight
|
recognitionWeight
|
||||||
@@ -1190,16 +1399,21 @@ class MainScreenPresentation(
|
|||||||
// foodWeight = lastWeight
|
// foodWeight = lastWeight
|
||||||
//)
|
//)
|
||||||
//userViewModel.postUserNutritionData(listOf(userNutritionParam))
|
//userViewModel.postUserNutritionData(listOf(userNutritionParam))
|
||||||
|
val realWeight = eatWeight.toDouble()
|
||||||
|
val specWeight = currentFood!!.specWeight
|
||||||
|
val eatNum = activity.getEatNum(realWeight, specWeight)
|
||||||
|
activity.log("createOrder,realWeight=$realWeight,specWeight=$specWeight")
|
||||||
activity.createOrder(
|
activity.createOrder(
|
||||||
foodInfo = currentFood!!,
|
foodInfo = currentFood!!,
|
||||||
foodWeight = lastWeight.roundToInt(),
|
foodWeight = lastWeight,
|
||||||
eatWeight = eatWeight.roundToInt(),
|
eatWeight = eatWeight,
|
||||||
eatNum = activity.getEatNum(eatWeight, currentFood!!.specWeight),
|
eatNum = eatNum,
|
||||||
userId = currentUserId,
|
userId = currentUserId,
|
||||||
|
isMember = isMember,
|
||||||
notEnoughOneBlock = notEnoughOneBlock,
|
notEnoughOneBlock = notEnoughOneBlock,
|
||||||
block = {
|
successBlock = {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
block()
|
successBlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1244,4 +1458,75 @@ class MainScreenPresentation(
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var foodOrderList = mutableListOf<FoodItem>()
|
||||||
|
private val foodOrderAdapter by lazy {
|
||||||
|
FoodOrderAdapter(foodOrderList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initRv(rv: RecyclerView) {
|
||||||
|
rv.run {
|
||||||
|
if (adapter == null) {
|
||||||
|
layoutManager =
|
||||||
|
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
|
||||||
|
adapter = foodOrderAdapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载订单列表
|
||||||
|
*/
|
||||||
|
private fun loadOrderList(userId: String, callback: () -> Unit) {
|
||||||
|
binding.llTopInfo.gone()
|
||||||
|
binding.flFoodDetail.visible()
|
||||||
|
binding.detailInclude.let {
|
||||||
|
it.root.updateLayoutParams {
|
||||||
|
height = activity.screenSize[1] / 2 + 120.dp
|
||||||
|
}
|
||||||
|
initRv(it.rvFoodList)
|
||||||
|
initRv(activity.layoutEatDetailBinding.rvFoodList)
|
||||||
|
userViewModel.getFoodOrderList(userId) { model ->
|
||||||
|
activity.runOnUiThread {
|
||||||
|
if (model == null) return@runOnUiThread
|
||||||
|
foodOrderList.clear()
|
||||||
|
foodOrderList.addAll(model.list ?: emptyList())
|
||||||
|
//foodOrderAdapter.submitList(foodOrderList)
|
||||||
|
foodOrderAdapter.notifyDataSetChanged()
|
||||||
|
//binding.detailInclude.tvTotalWeight.text = "总重量:${model.eatWeightSum}克"
|
||||||
|
Timber.tag(TAG).d("addFoodToOrder: 更新总重量,订单列表------------------------------")
|
||||||
|
// binding.detailInclude.tvTotalCalorie.text = "总热量:${model.calorie.roundedDecimalPlace(1)}千卡"
|
||||||
|
jointPaymentQueryFinish = true
|
||||||
|
|
||||||
|
//重新加载营养信息
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造符合分辨率的 NV21 格式全黑帧
|
||||||
|
* @param width 图像宽度(如 1920)
|
||||||
|
* @param height 图像高度(如 1080)
|
||||||
|
* @return 合法的全黑帧字节数组
|
||||||
|
*/
|
||||||
|
private fun createBlackNV21Frame(width: Int, height: Int): ByteArray {
|
||||||
|
val frameSize = width * height
|
||||||
|
val nv21Data = ByteArray(frameSize * 3 / 2) // NV21 格式长度 = 宽×高×1.5
|
||||||
|
|
||||||
|
// Y 分量(亮度)设为 0(全黑),UV 分量设为 128(默认值)
|
||||||
|
// 1. 填充 Y 分量(前 frameSize 个字节)
|
||||||
|
// Arrays.fill(nv21Data, 0, frameSize, 0.toByte())
|
||||||
|
nv21Data.fill(0, 0, frameSize)
|
||||||
|
// 2. 填充 UV 分量(后 frameSize/2 个字节)
|
||||||
|
// Arrays.fill(nv21Data, frameSize, nv21Data.size, 128.toByte())
|
||||||
|
nv21Data.fill(128.toByte(), frameSize, nv21Data.size)
|
||||||
|
|
||||||
|
return nv21Data
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用示例:构造 1920×1080 的全黑帧(长度 1382400)
|
||||||
|
// private val emptyFrame = createBlackNV21Frame(1920, 1080)
|
||||||
|
private val emptyFrame = createBlackNV21Frame(1280, 720)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.sw.dualscreen.model.response.FaceData
|
|||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
import com.sw.dualscreen.model.response.FoodSearchReq
|
import com.sw.dualscreen.model.response.FoodSearchReq
|
||||||
import com.sw.dualscreen.model.response.FoodOrder
|
import com.sw.dualscreen.model.response.FoodOrder
|
||||||
|
import com.sw.dualscreen.model.response.FoodOrderModel
|
||||||
import com.sw.dualscreen.model.response.FoodVector
|
import com.sw.dualscreen.model.response.FoodVector
|
||||||
import com.sw.dualscreen.model.response.MemberInfo
|
import com.sw.dualscreen.model.response.MemberInfo
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
@@ -352,4 +353,16 @@ class RemoteRepository constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getFoodOrderList(userId: String): ApiResponse<FoodOrderModel?> {
|
||||||
|
return safeApiCall {
|
||||||
|
apiService.getFoodOrderList(userId = userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getMemberDiscount(userId: String): ApiResponse<Double?> {
|
||||||
|
return safeApiCall {
|
||||||
|
apiService.getMemberDiscount(userId = userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import timber.log.Timber
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
typealias Callback = (Double) -> Unit
|
typealias Callback = (Double) -> Unit
|
||||||
typealias WeightCallback = (Double) -> Unit
|
typealias WeightCallback = (Int) -> Unit
|
||||||
|
|
||||||
private const val TAG = "SensorScaleUtils"
|
private const val TAG = "SensorScaleUtils"
|
||||||
|
|
||||||
@@ -31,21 +31,24 @@ object SensorScaleUtils {
|
|||||||
* 读取重量
|
* 读取重量
|
||||||
*/
|
*/
|
||||||
override fun readWeight(state: Int, value: Double) {
|
override fun readWeight(state: Int, value: Double) {
|
||||||
val stateStr = when (state) {
|
// val stateStr = when (state) {
|
||||||
SensorScale.STATE_STABLE -> "稳定"
|
// SensorScale.STATE_STABLE -> "稳定"
|
||||||
SensorScale.STATE_UNSTABLE -> "不稳定"
|
// SensorScale.STATE_UNSTABLE -> "不稳定"
|
||||||
SensorScale.STATE_OVER_WEIGHT -> "量程溢出"
|
// SensorScale.STATE_OVER_WEIGHT -> "量程溢出"
|
||||||
else -> "未知"
|
// else -> "未知"
|
||||||
}
|
// }
|
||||||
// Log.d(TAG, "readWeight state = ${stateStr}, weight = $value")
|
// Log.d(TAG, "readWeight state = ${stateStr}, weight = $value")
|
||||||
// 只使用稳定值
|
// 只使用稳定值
|
||||||
if (state == SensorScale.STATE_STABLE && lastWeight != value) {
|
if (state == SensorScale.STATE_STABLE) {
|
||||||
|
if (lastWeight != value) {
|
||||||
lastWeight = value
|
lastWeight = value
|
||||||
callback?.invoke(value)
|
callback?.invoke(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCallbackList.forEach {
|
weightCallbackList.forEach {
|
||||||
it.invoke(value)
|
val currentWeight = value * 1000
|
||||||
|
it.invoke(currentWeight.roundToInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,8 +90,7 @@ object SensorScaleUtils {
|
|||||||
// Thread.sleep(1000)
|
// Thread.sleep(1000)
|
||||||
|
|
||||||
// TODO: 暂时不标定---------
|
// TODO: 暂时不标定---------
|
||||||
//zero()
|
zero()
|
||||||
|
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,15 +132,17 @@ object SensorScaleUtils {
|
|||||||
/**
|
/**
|
||||||
* 零位标定
|
* 零位标定
|
||||||
*/
|
*/
|
||||||
fun zero() {
|
fun zero(isShowToastRemind: Boolean = false) {
|
||||||
Timber.d("zero isOpened = $isOpened, mSensorScale = $mSensorScale")
|
Timber.d("zero isOpened = $isOpened, mSensorScale = $mSensorScale")
|
||||||
if (!isOpened) return
|
if (!isOpened) return
|
||||||
mSensorScale?.zero {
|
mSensorScale?.zero {
|
||||||
isZero = true
|
isZero = true
|
||||||
Timber.d("zero 零位标定操作成功")
|
Timber.d("zero 零位标定操作成功")
|
||||||
|
if (isShowToastRemind) {
|
||||||
ToastUtils.showToast("零位标定操作成功")
|
ToastUtils.showToast("零位标定操作成功")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 去皮置零
|
* 去皮置零
|
||||||
|
|||||||
@@ -19,11 +19,18 @@ import java.io.StringReader;
|
|||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class FileUtil {
|
public class FileUtil {
|
||||||
private static boolean isSaveLog = true;
|
private static boolean isSaveLog = true;
|
||||||
public static final String FILE_STR_PATH = App.getContext().getExternalCacheDir().getAbsolutePath();
|
// public static final String FILE_STR_PATH = App.getContext().getExternalCacheDir().getAbsolutePath();
|
||||||
|
// 使用内部存储,不会被系统缓存清理策略影响
|
||||||
|
public static final String FILE_STR_PATH = new File(App.getContext().getFilesDir(), "logs").getAbsolutePath();
|
||||||
|
// 单线程执行器,保证日志串行写入,避免多线程并发竞争
|
||||||
|
|
||||||
|
// 单线程执行器,保证日志串行写入,避免多线程并发竞争
|
||||||
|
private static final ExecutorService LOG_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||||
public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
|
public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
|
||||||
public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
|
public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
|
||||||
public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
|
public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
|
||||||
@@ -610,24 +617,19 @@ public class FileUtil {
|
|||||||
if (!isSaveLog) {
|
if (!isSaveLog) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new Thread() {
|
// 提交到单线程队列,串行执行,避免并发写入竞争
|
||||||
@Override
|
LOG_EXECUTOR.execute(() -> {
|
||||||
public void run() {
|
|
||||||
super.run();
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String log : logs) {
|
for (String log : logs) {
|
||||||
sb.append("===")
|
sb.append("===")
|
||||||
.append((AppUtil.formatDateGetCurrentTime()))
|
.append((AppUtil.formatDateGetCurrentTime()))
|
||||||
.append("===")
|
.append("===")
|
||||||
.append("\n")
|
|
||||||
.append(log)
|
.append(log)
|
||||||
.append("\n");
|
.append("\n");
|
||||||
}
|
}
|
||||||
String fileName = "log" + AppUtil.formatDateGetDay(System.currentTimeMillis()) + ".txt";
|
String fileName = "log" + AppUtil.formatDateGetDay(System.currentTimeMillis()) + ".txt";
|
||||||
FileUtil.saveStrFile(sb.toString(), fileName, FILE_STR_PATH, true);
|
FileUtil.saveStrFile(sb.toString(), fileName, FILE_STR_PATH, true);
|
||||||
|
});
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[][] MIME_MapTable = {
|
private static final String[][] MIME_MapTable = {
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
|
import com.sw.dualscreen.GlobalData
|
||||||
|
import com.sw.dualscreen.model.response.FoodVector
|
||||||
|
import com.sw.dualscreen.objbox.Food
|
||||||
|
import com.sw.dualscreen.objbox.ObjectBox
|
||||||
|
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
object FoodVectorTool {
|
||||||
|
|
||||||
|
/** 每页拉取条数 */
|
||||||
|
private const val PAGE_SIZE = 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一入口:分页拉取所有食物向量数据并保存到本地 ObjectBox
|
||||||
|
*
|
||||||
|
* @param userViewModel 请求 ViewModel
|
||||||
|
* @param lifecycleScope 协程作用域(用于保存操作)
|
||||||
|
* @param successBlock 全部数据拉取并保存成功后回调
|
||||||
|
* @param failureBlock 任意一次请求失败时回调,参数为错误信息
|
||||||
|
*/
|
||||||
|
fun loadAndSaveFoodVector(
|
||||||
|
userViewModel: UserViewModel,
|
||||||
|
lifecycleScope: LifecycleCoroutineScope,
|
||||||
|
successBlock: () -> Unit,
|
||||||
|
failureBlock: (String) -> Unit
|
||||||
|
) {
|
||||||
|
// 每次调用从第 1 页开始,避免单例状态污染
|
||||||
|
fetchPage(
|
||||||
|
pageNum = 1,
|
||||||
|
userViewModel = userViewModel,
|
||||||
|
lifecycleScope = lifecycleScope,
|
||||||
|
successBlock = successBlock,
|
||||||
|
failureBlock = failureBlock
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归分页请求(内部方法,外部不感知分页细节)
|
||||||
|
*
|
||||||
|
* @param pageNum 当前页码
|
||||||
|
* @param userViewModel 请求 ViewModel
|
||||||
|
* @param lifecycleScope 协程作用域
|
||||||
|
* @param successBlock 成功回调
|
||||||
|
* @param failureBlock 失败回调
|
||||||
|
*/
|
||||||
|
private fun fetchPage(
|
||||||
|
pageNum: Int,
|
||||||
|
userViewModel: UserViewModel,
|
||||||
|
lifecycleScope: LifecycleCoroutineScope,
|
||||||
|
successBlock: () -> Unit,
|
||||||
|
failureBlock: (String) -> Unit
|
||||||
|
) {
|
||||||
|
userViewModel.getCollectedFoodVector(
|
||||||
|
param = mutableMapOf(
|
||||||
|
"pageNum" to "$pageNum",
|
||||||
|
"pageSize" to "$PAGE_SIZE",
|
||||||
|
"version" to GlobalData.foodModelVersion
|
||||||
|
)
|
||||||
|
) { items ->
|
||||||
|
if (items == null) {
|
||||||
|
failureBlock("未查询到向量数据")
|
||||||
|
return@getCollectedFoodVector
|
||||||
|
}
|
||||||
|
// 第一页为空,视为成功(数据库无数据)
|
||||||
|
if (pageNum == 1 && items.isEmpty()) {
|
||||||
|
successBlock()
|
||||||
|
return@getCollectedFoodVector
|
||||||
|
}
|
||||||
|
// 有数据则保存
|
||||||
|
if (items.isNotEmpty()) {
|
||||||
|
saveFoodVector(lifecycleScope, items)
|
||||||
|
}
|
||||||
|
// 数据量达到一页上限,继续拉取下一页
|
||||||
|
if (items.size >= PAGE_SIZE) {
|
||||||
|
fetchPage(pageNum + 1, userViewModel, lifecycleScope, successBlock, failureBlock)
|
||||||
|
} else {
|
||||||
|
successBlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将向量数据列表保存到 ObjectBox 本地数据库
|
||||||
|
*
|
||||||
|
* @param lifecycleScope 协程作用域
|
||||||
|
* @param list 待保存的食物向量数据列表
|
||||||
|
*/
|
||||||
|
private fun saveFoodVector(lifecycleScope: LifecycleCoroutineScope, list: List<FoodVector>) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val vectorList = list.map { vt ->
|
||||||
|
// 解析向量字符串 "[0.1,0.2,...]" 为 FloatArray
|
||||||
|
val foodVector = vt.foodVector?.removeSurrounding("[", "]")
|
||||||
|
?.split(",")?.map { it.toFloatOrNull() ?: 0.0f }?.toFloatArray()
|
||||||
|
Food(
|
||||||
|
collectId = vt.id,
|
||||||
|
foodId = vt.foodId,
|
||||||
|
foodName = vt.foodName,
|
||||||
|
version = vt.version,
|
||||||
|
foodVector = foodVector
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ObjectBox.putAll(vectorList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络连接检测工具类
|
||||||
|
* 提供检测设备网络连接状态的功能
|
||||||
|
*/
|
||||||
|
object NetworkUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测设备是否连接到网络
|
||||||
|
* @param context 应用上下文
|
||||||
|
* @return true 表示已连接网络,false 表示未连接
|
||||||
|
*/
|
||||||
|
fun isNetworkConnected(context: Context): Boolean {
|
||||||
|
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
val network = connectivityManager.activeNetwork ?: return false
|
||||||
|
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
|
||||||
|
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.sw.dualscreen.utils
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.dualscreen.MyApp
|
import com.sw.dualscreen.MyApp
|
||||||
import com.sw.dualscreen.utils.SPUtil.Companion.getInstance
|
import com.sw.dualscreen.utils.SPUtil.Companion.getInstance
|
||||||
|
|
||||||
@@ -16,15 +17,26 @@ object SpTool {
|
|||||||
|
|
||||||
|
|
||||||
var lastFaceTimestamp: Long
|
var lastFaceTimestamp: Long
|
||||||
get() = spUtil?.get(LAST_FACE_TIMESTAMP, 0L)?:0L
|
get() = spUtil?.get(LAST_FACE_TIMESTAMP, 0L) ?: 0L
|
||||||
set(timestamp) {
|
set(timestamp) {
|
||||||
spUtil?.put(LAST_FACE_TIMESTAMP, timestamp)
|
spUtil?.put(LAST_FACE_TIMESTAMP, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstGetFace: Boolean
|
var firstGetFace: Boolean
|
||||||
get() = spUtil?.get(IS_FIRST_GET_FACE, true)?:true
|
get() = spUtil?.get(IS_FIRST_GET_FACE, true) ?: true
|
||||||
set(value) {
|
set(value) {
|
||||||
spUtil?.boolean(IS_FIRST_GET_FACE, value)
|
spUtil?.boolean(IS_FIRST_GET_FACE, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var baseUrl: String?
|
||||||
|
get() = spUtil?.get(GlobalKey.KEY_BASE_URL, "")
|
||||||
|
set(value) {
|
||||||
|
spUtil?.put(GlobalKey.KEY_BASE_URL, value)
|
||||||
|
}
|
||||||
|
var settlementMode: Int
|
||||||
|
get() = spUtil?.get(GlobalKey.KEY_SETTLEMENT_MODE, 0) ?: 0
|
||||||
|
set(value) {
|
||||||
|
spUtil?.put(GlobalKey.KEY_SETTLEMENT_MODE, value)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.sw.dualscreen.model.response.DeviceConfig
|
|||||||
import com.sw.dualscreen.model.response.DinnerType
|
import com.sw.dualscreen.model.response.DinnerType
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
import com.sw.dualscreen.model.response.FoodOrder
|
import com.sw.dualscreen.model.response.FoodOrder
|
||||||
|
import com.sw.dualscreen.model.response.FoodOrderModel
|
||||||
import com.sw.dualscreen.model.response.FoodVector
|
import com.sw.dualscreen.model.response.FoodVector
|
||||||
import com.sw.dualscreen.model.response.MemberInfo
|
import com.sw.dualscreen.model.response.MemberInfo
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
@@ -17,6 +18,7 @@ import com.sw.dualscreen.model.response.UserFaceModel2
|
|||||||
import com.sw.dualscreen.model.response.UserNutrition
|
import com.sw.dualscreen.model.response.UserNutrition
|
||||||
import com.sw.dualscreen.objbox.CollectedFoodInfo
|
import com.sw.dualscreen.objbox.CollectedFoodInfo
|
||||||
import com.sw.dualscreen.utils.Debouncer
|
import com.sw.dualscreen.utils.Debouncer
|
||||||
|
import com.sw.dualscreen.utils.FileUtil
|
||||||
import com.sw.dualscreen.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
import com.sw.dualscreen.utils.SpTool
|
import com.sw.dualscreen.utils.SpTool
|
||||||
import com.sw.plate.App
|
import com.sw.plate.App
|
||||||
@@ -90,21 +92,37 @@ class UserViewModel : BaseViewModel() {
|
|||||||
/**
|
/**
|
||||||
* 获取人脸数据
|
* 获取人脸数据
|
||||||
*/
|
*/
|
||||||
fun getUserFaceCache(pageNo: Int = 1, pageSize: Int = PAGE_SIZE) {
|
fun getUserFaceCache(
|
||||||
|
pageNo: Int = 1,
|
||||||
|
pageSize: Int = PAGE_SIZE,
|
||||||
|
onSuccess: () -> Unit = {},
|
||||||
|
onFailure: (String) -> Unit = {}
|
||||||
|
) {
|
||||||
|
// Initialize current page number
|
||||||
var currentPageNo = pageNo
|
var currentPageNo = pageNo
|
||||||
|
// Debug log to track current page
|
||||||
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
|
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
|
||||||
|
// Launch a coroutine to perform the face data retrieval
|
||||||
launch {
|
launch {
|
||||||
|
// Set loading state to false
|
||||||
_loadFaceResult.value = false
|
_loadFaceResult.value = false
|
||||||
//获取全量数据时,时间戳改为0
|
//获取全量数据时,时间戳改为0
|
||||||
SpTool.lastFaceTimestamp = 0
|
SpTool.lastFaceTimestamp = 0
|
||||||
|
FileUtil.saveLog("获取人脸全量数据开始,重置时间戳为0")
|
||||||
val response = repository.getUserFaceCache(currentPageNo)
|
val response = repository.getUserFaceCache(currentPageNo)
|
||||||
if (parseResponse(response)) {
|
val check = parseResponse(response)
|
||||||
|
if (!check) {
|
||||||
|
// 获取失败
|
||||||
|
onFailure("获取人脸数据失败,${response.msg}(${response.code})")
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
// 获取成功一次后缓存状态
|
// 获取成功一次后缓存状态
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val list: List<UserFaceModel> = response.data ?: emptyList()
|
val list: List<UserFaceModel> = response.data ?: emptyList()
|
||||||
if (pageNo == 1 && list.isEmpty()) {
|
if (pageNo == 1 && list.isEmpty()) {
|
||||||
//ToastUtils.showToast("查询人脸数据为空")
|
//ToastUtils.showToast("查询人脸数据为空")
|
||||||
|
onFailure("查询人脸数据为空")
|
||||||
return@withContext
|
return@withContext
|
||||||
}
|
}
|
||||||
//val item = list.map { it.member }
|
//val item = list.map { it.member }
|
||||||
@@ -128,9 +146,10 @@ class UserViewModel : BaseViewModel() {
|
|||||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||||
}
|
}
|
||||||
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
||||||
|
FileUtil.saveLog("获取人脸[全量]数据结束,时间戳为:$lastFaceTimestamp")
|
||||||
_loadFaceResult.value = true
|
_loadFaceResult.value = true
|
||||||
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
// val nextPageIndex = response.result?.nextPageIndex ?: -1
|
// val nextPageIndex = response.result?.nextPageIndex ?: -1
|
||||||
// if (nextPageIndex > 0) {
|
// if (nextPageIndex > 0) {
|
||||||
// getUserFaceCache(nextPageIndex)
|
// getUserFaceCache(nextPageIndex)
|
||||||
@@ -139,7 +158,6 @@ class UserViewModel : BaseViewModel() {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// fun getUserFaceCache2(index: Int = 0) {
|
// fun getUserFaceCache2(index: Int = 0) {
|
||||||
// Timber.d("getUserFaceCache index = $index")
|
// Timber.d("getUserFaceCache index = $index")
|
||||||
@@ -206,6 +224,7 @@ class UserViewModel : BaseViewModel() {
|
|||||||
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
lastFaceTimestamp = list.last().faceUpdateTimestamp ?: 0L
|
||||||
}
|
}
|
||||||
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
SpTool.lastFaceTimestamp = lastFaceTimestamp
|
||||||
|
FileUtil.saveLog("获取人脸[增量]数据结束,时间戳为:$lastFaceTimestamp")
|
||||||
onAllQueryFinished()
|
onAllQueryFinished()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -620,4 +639,28 @@ class UserViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFoodOrderList(userId: String, block: (FoodOrderModel?) -> Unit) {
|
||||||
|
Timber.tag(TAG).d("getFoodOrderList")
|
||||||
|
launchWithLoading {
|
||||||
|
val response = repository.getFoodOrderList(userId)
|
||||||
|
if (parseResponse(response)) {
|
||||||
|
block(response.data)
|
||||||
|
} else {
|
||||||
|
block(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMemberDiscount(userId: String, block: (Double?) -> Unit) {
|
||||||
|
Timber.tag(TAG).d("getMemberDiscount")
|
||||||
|
launchWithLoading {
|
||||||
|
val response = repository.getMemberDiscount(userId)
|
||||||
|
if (parseResponse(response)) {
|
||||||
|
block(response.data)
|
||||||
|
} else {
|
||||||
|
block(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#F2F2F2"/>
|
||||||
|
<!-- <stroke android:color="#cdcdcd" android:width="1dp"/>-->
|
||||||
|
<corners android:radius="5dp"/>
|
||||||
|
</shape>
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="28dp"
|
android:layout_marginStart="28dp"
|
||||||
|
android:paddingVertical="10dp"
|
||||||
android:textColor="#ff0a1428"
|
android:textColor="#ff0a1428"
|
||||||
android:textSize="26sp"
|
android:textSize="26sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
@@ -48,19 +49,23 @@
|
|||||||
android:textColor="#FF0A1428"
|
android:textColor="#FF0A1428"
|
||||||
android:textSize="52sp"
|
android:textSize="52sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
<!-- <TextView-->
|
|
||||||
<!-- android:id="@+id/tvShowWeight"-->
|
<TextView
|
||||||
<!-- android:layout_width="wrap_content"-->
|
android:id="@+id/tvShowWeight"
|
||||||
<!-- android:layout_height="80dp"-->
|
android:layout_width="match_parent"
|
||||||
<!-- android:textSize="30sp"-->
|
android:layout_height="80dp"
|
||||||
<!-- android:gravity="center"-->
|
android:textSize="20sp"
|
||||||
<!-- tools:text="100克"/>-->
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
tools:text="100克"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/foodDisplayLayout"
|
android:id="@+id/foodDisplayLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="560dp"
|
android:layout_height="560dp"
|
||||||
android:layout_marginHorizontal="28dp"
|
android:layout_marginHorizontal="28dp"
|
||||||
android:layout_marginTop="80dp"
|
android:layout_marginTop="0dp"
|
||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
|
||||||
<androidx.camera.view.PreviewView
|
<androidx.camera.view.PreviewView
|
||||||
@@ -84,53 +89,21 @@
|
|||||||
android:layout_margin="27dp"
|
android:layout_margin="27dp"
|
||||||
android:background="@drawable/ic_camera_rect" />
|
android:background="@drawable/ic_camera_rect" />
|
||||||
<!-- preview_border-->
|
<!-- preview_border-->
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<FrameLayout
|
||||||
android:id="@+id/recyclerview"
|
android:id="@+id/flFoodList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginHorizontal="14dp"
|
android:layout_weight="1"/>
|
||||||
android:layout_marginTop="42dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:overScrollMode="never"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
|
||||||
app:spanCount="2"
|
|
||||||
tools:itemCount="8"
|
|
||||||
tools:listitem="@layout/list_item_search_food" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvToSearch"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="38dp"
|
|
||||||
android:layout_marginBottom="0dp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:text="以上都不是,手动搜索"
|
|
||||||
android:textColor="#FFFF3232"
|
|
||||||
android:textSize="31sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="54dp"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvWeightRealInfo"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/black"
|
|
||||||
android:textSize="12sp"
|
|
||||||
tools:text="以上都不是,手动搜索" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/flPay"
|
android:id="@+id/flPay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
|
android:layout_marginTop="45dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<RadioGroup
|
<RadioGroup
|
||||||
android:id="@+id/rgSetting"
|
android:id="@+id/rgSetting"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="90dp"
|
android:layout_height="75dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingHorizontal="50dp"
|
android:paddingHorizontal="50dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="35dp"
|
android:paddingBottom="15dp"
|
||||||
android:text="经营设置"
|
android:text="经营设置"
|
||||||
android:textColor="@color/setting_radio"
|
android:textColor="@color/setting_radio"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingHorizontal="50dp"
|
android:paddingHorizontal="50dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="35dp"
|
android:paddingBottom="15dp"
|
||||||
android:text="餐品采集"
|
android:text="餐品采集"
|
||||||
android:textColor="@color/setting_radio"
|
android:textColor="@color/setting_radio"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="600dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_white_radius12"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="40dp"
|
||||||
|
android:paddingVertical="36dp">
|
||||||
|
|
||||||
|
<!-- 标题 -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="环境切换"
|
||||||
|
android:textColor="#ff141428"
|
||||||
|
android:textSize="36sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:background="#FFDCDCF0" />
|
||||||
|
|
||||||
|
<!-- 环境选项 -->
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/rgEnv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbTest"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="测试环境"
|
||||||
|
android:textColor="#ff141428"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbUat"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="UAT 环境"
|
||||||
|
android:textColor="#ff141428"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbProd"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="生产环境"
|
||||||
|
android:textColor="#ff141428"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:background="#FFDCDCF0" />
|
||||||
|
|
||||||
|
<!-- 底部按钮 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="88dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnCancel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_border_red"
|
||||||
|
android:text="取消"
|
||||||
|
android:textColor="#FFFF3232"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnConfirm"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_btn_save2"
|
||||||
|
android:text="确认"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- 结算设置模块 -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -16,6 +17,85 @@
|
|||||||
android:paddingTop="35dp"
|
android:paddingTop="35dp"
|
||||||
android:paddingBottom="42dp">
|
android:paddingBottom="42dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="17dp"
|
||||||
|
android:text="结算设置"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="36sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:drawableStartCompat="@drawable/line_shape" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="(不允许修改,由后端配置)"
|
||||||
|
android:textColor="#FFFF3232"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/rgSettlement"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="35dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbJointPayment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/setting_check_selector"
|
||||||
|
android:button="@null"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="联合支付"
|
||||||
|
android:textColor="@color/setting_radio"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rbIndependentPayment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/setting_check_selector"
|
||||||
|
android:button="@null"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="独立支付"
|
||||||
|
android:textColor="@color/setting_radio"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:checked="true" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 计费设置模块 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/setting_border"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:layout_marginTop="42dp"
|
||||||
|
android:paddingHorizontal="32dp"
|
||||||
|
android:paddingTop="35dp"
|
||||||
|
android:paddingBottom="42dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="32dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:background="@drawable/setting_border"
|
android:background="@drawable/setting_border"
|
||||||
android:paddingBottom="16dp">
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvChargeSetting"
|
android:id="@+id/tvChargeSetting"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="32dp"
|
android:layout_marginStart="32dp"
|
||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="20dp"
|
||||||
android:drawablePadding="17dp"
|
android:drawablePadding="17dp"
|
||||||
android:text="餐品采集"
|
android:text="餐品采集"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
android:id="@+id/flPreview"
|
android:id="@+id/flPreview"
|
||||||
android:layout_width="456dp"
|
android:layout_width="456dp"
|
||||||
android:layout_height="342dp"
|
android:layout_height="342dp"
|
||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="20dp"
|
||||||
app:layout_constraintStart_toStartOf="@id/tvChargeSetting"
|
app:layout_constraintStart_toStartOf="@id/tvChargeSetting"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvChargeSetting">
|
app:layout_constraintTop_toBottomOf="@id/tvChargeSetting">
|
||||||
|
|
||||||
@@ -111,9 +111,9 @@
|
|||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvFoodList"
|
android:id="@+id/rvFoodList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="382dp"
|
android:layout_height="358dp"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginVertical="10dp"
|
||||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_marginHorizontal="32dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="20dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
@@ -164,22 +164,22 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="18dp"
|
android:layout_marginTop="12dp"
|
||||||
android:minHeight="348dp"
|
android:minHeight="348dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
app:spanCount="2"
|
app:spanCount="2"
|
||||||
tools:itemCount="10"
|
tools:itemCount="11"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
tools:listitem="@layout/list_item_search_food"/>
|
tools:listitem="@layout/list_item_search_food3"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnSave"
|
android:id="@+id/btnSave"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_marginHorizontal="32dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:layout_marginBottom="32dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="保存"
|
android:text="保存"
|
||||||
android:background="@drawable/bg_btn_save"
|
android:background="@drawable/bg_btn_save"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
|
|||||||
@@ -285,7 +285,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/meatTv"
|
android:id="@+id/meatTv"
|
||||||
style="@style/takeFoodNameTv"
|
style="@style/takeFoodNameTv"
|
||||||
android:text="蛋肉"
|
android:text="肉蛋豆"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="HardcodedText,UseCompatTextViewDrawableXml">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/llFoodTitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="80dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:text="取餐明细"
|
||||||
|
android:textColor="#ff33446a"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:drawablePadding="17dp"
|
||||||
|
android:drawableStart="@drawable/ic_take_food" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvUserName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
tools:text="张三" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:background="#FFDDE5F0" />
|
||||||
|
|
||||||
|
<include layout="@layout/layout_food_list_header" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="#FFDDE5F0" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFoodList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
tools:listitem="@layout/layout_food_list_header" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginBottom="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTotalWeight"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="#ff889ac2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
tools:text="总重量:680克"
|
||||||
|
android:drawablePadding="17dp"
|
||||||
|
android:drawableStart="@drawable/ic_flag_weight" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTotalCalorie"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="#ff889ac2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
tools:text="总热量:793千卡"
|
||||||
|
android:drawablePadding="17dp"
|
||||||
|
android:drawableStart="@drawable/ic_flag_calorie" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<!-- 菜品名称列,权重2.5 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFoodName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2.1"
|
||||||
|
android:text="菜品名称"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center_vertical|start" />
|
||||||
|
|
||||||
|
<!-- 规格列,权重1.0 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPriceNorm"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.6"
|
||||||
|
android:text="规格"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
<!-- 重量列,权重1.0 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvWeight"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:text="重量(克)"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
<!-- 小计列,权重1.0 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAmount"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:text="小计(元)"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvToSearch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="38dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:padding="10dp"
|
||||||
|
tools:text="以上都不是,手动搜索"
|
||||||
|
android:textColor="#FFFF3232"
|
||||||
|
android:textSize="31sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFoodList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/tvToSearch"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:layout_marginHorizontal="14dp"
|
||||||
|
android:layout_marginTop="42dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
|
tools:itemCount="8"
|
||||||
|
tools:listitem="@layout/list_item_search_food" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/detailInclude"
|
||||||
|
layout="@layout/layout_eat_detail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFoodList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="264dp"
|
||||||
|
android:layout_marginHorizontal="14dp"
|
||||||
|
android:layout_marginTop="42dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
|
tools:itemCount="8"
|
||||||
|
tools:listitem="@layout/list_item_search_food" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvToSearch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="38dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:padding="10dp"
|
||||||
|
tools:text="以上都不是,手动搜索"
|
||||||
|
android:textColor="#FFFF3232"
|
||||||
|
android:textSize="31sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/detailInclude"
|
||||||
|
layout="@layout/layout_eat_detail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginHorizontal="14dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="150dp">
|
android:layout_height="130dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivPageBack"
|
android:id="@+id/ivPageBack"
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="212dp"
|
android:layout_width="212dp"
|
||||||
android:layout_height="159dp"
|
android:layout_height="159dp"
|
||||||
android:layout_margin="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="10dp"
|
||||||
android:background="@drawable/bg_gray2">
|
android:background="@drawable/bg_gray2">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<!-- 菜品名称列,权重2.5 -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2.1"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFoodName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="菜品名称"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="25sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
|
app:layout_constraintWidth_default="wrap"
|
||||||
|
app:layout_constraintHorizontal_bias="0"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/tvLabel"
|
||||||
|
android:gravity="center_vertical|start" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvLabel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="档口"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:background="@drawable/bg_order_flag"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:paddingVertical="1dp"
|
||||||
|
android:layout_marginHorizontal="2dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/tvFoodName"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<!-- 规格列,权重1.0 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.6"
|
||||||
|
android:gravity="center">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPriceNorm"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="规格"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="25sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPriceFlag"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="[大份]"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 重量列,权重1.0 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvWeight"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
tools:text="重量(克)"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="25sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
<!-- 小计列,权重1.0 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAmount"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
tools:text="小计(元)"
|
||||||
|
android:textColor="#FF889AC2"
|
||||||
|
android:textSize="25sp"
|
||||||
|
android:paddingHorizontal="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:layout_marginHorizontal="14dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginVertical="14dp"
|
android:layout_marginVertical="16dp"
|
||||||
android:paddingHorizontal="15dp"
|
android:paddingHorizontal="15dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
tools:textColor="@color/black"
|
tools:textColor="@color/black"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:layout_marginHorizontal="14dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginVertical="14dp"
|
android:layout_marginVertical="16dp"
|
||||||
android:paddingHorizontal="15dp"
|
android:paddingHorizontal="15dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/color_text_dialog"
|
android:textColor="@color/color_text_dialog"
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/tvFoodName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
tools:background="@drawable/bg_text_main"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
|
android:paddingHorizontal="15dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
tools:textColor="@color/black"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="肉沫干拌面" />
|
||||||
@@ -13,11 +13,13 @@
|
|||||||
android:padding="28dp">
|
android:padding="28dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/llTopInfo"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/setting_border"
|
android:background="@drawable/setting_border"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="26dp">
|
android:paddingBottom="26dp"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvFoodName"
|
android:id="@+id/tvFoodName"
|
||||||
@@ -30,10 +32,10 @@
|
|||||||
android:textSize="40sp"
|
android:textSize="40sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<!-- android:layout_width="300dp"-->
|
<!--android:layout_width="300dp"-->
|
||||||
<!-- android:layout_height="450dp"-->
|
<!--android:layout_height="450dp"-->
|
||||||
<!-- android:layout_width="330dp"-->
|
<!--android:layout_width="330dp"-->
|
||||||
<!-- android:layout_height="495dp"-->
|
<!--android:layout_height="495dp"-->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/flCameraView"
|
android:id="@+id/flCameraView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -187,6 +189,20 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/flFoodDetail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/setting_border"
|
||||||
|
android:paddingHorizontal="15dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/detailInclude"
|
||||||
|
layout="@layout/layout_eat_detail"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/flBottomView"
|
android:id="@+id/flBottomView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
agp = "8.10.1"
|
agp = "8.10.1"
|
||||||
core = "3.4.1"
|
core = "3.4.1"
|
||||||
androidCore = "3.3.0"
|
androidCore = "3.3.0"
|
||||||
|
eventbus = "3.2.0"
|
||||||
glide = "4.16.0"
|
glide = "4.16.0"
|
||||||
kotlin = "2.0.21"
|
kotlin = "2.0.21"
|
||||||
coreKtx = "1.10.1"
|
coreKtx = "1.10.1"
|
||||||
@@ -14,6 +15,9 @@ activity = "1.8.0"
|
|||||||
constraintlayout = "2.1.4"
|
constraintlayout = "2.1.4"
|
||||||
accompanistPermissions = "0.37.3"
|
accompanistPermissions = "0.37.3"
|
||||||
cameraCore = "1.4.1"
|
cameraCore = "1.4.1"
|
||||||
|
objectboxVersion = "5.0.1"
|
||||||
|
refreshLayoutKernel = "3.0.0-alpha"
|
||||||
|
refreshHeaderClassics = "3.0.0-alpha"
|
||||||
retrofit = "3.0.0"
|
retrofit = "3.0.0"
|
||||||
okhttp = "4.12.0"
|
okhttp = "4.12.0"
|
||||||
timber = "5.0.1"
|
timber = "5.0.1"
|
||||||
@@ -30,11 +34,13 @@ pytorch = "1.13.0"
|
|||||||
|
|
||||||
recyclerview = "1.3.2"
|
recyclerview = "1.3.2"
|
||||||
|
|
||||||
#baseQuickAdapter = "4.1.2"
|
baseQuickAdapter = "3.0.4"
|
||||||
|
baseQuickAdapter4 = "4.1.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
|
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
|
||||||
core = { module = "com.google.zxing:core", version.ref = "core" }
|
core = { module = "com.google.zxing:core", version.ref = "core" }
|
||||||
|
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
|
||||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
@@ -56,7 +62,10 @@ hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", ve
|
|||||||
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
|
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
|
||||||
|
|
||||||
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
||||||
|
objectbox-android-objectbrowser = { module = "io.objectbox:objectbox-android-objectbrowser", version.ref = "objectboxVersion" }
|
||||||
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||||
|
refresh-header-classics = { module = "io.github.scwang90:refresh-header-classics", version.ref = "refreshHeaderClassics" }
|
||||||
|
refresh-layout-kernel = { module = "io.github.scwang90:refresh-layout-kernel", version.ref = "refreshLayoutKernel" }
|
||||||
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||||
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
|
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
|
||||||
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
||||||
@@ -68,10 +77,12 @@ androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref
|
|||||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||||
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||||
|
|
||||||
|
#noinspection Aligned16KB
|
||||||
pytorch-android = { group = "org.pytorch", name = "pytorch_android", version.ref = "pytorch" }
|
pytorch-android = { group = "org.pytorch", name = "pytorch_android", version.ref = "pytorch" }
|
||||||
pytorch-android-torchvision = { group = "org.pytorch", name = "pytorch_android_torchvision", version.ref = "pytorch" }
|
pytorch-android-torchvision = { group = "org.pytorch", name = "pytorch_android_torchvision", version.ref = "pytorch" }
|
||||||
|
|
||||||
#base-quick-adapter-ktx = { module = "io.github.cymchad:BaseRecyclerViewAdapterHelper4", version.ref = "baseQuickAdapter" }
|
#baseRecyclerViewAdapterHelper = { module = "com.github.CymChad:BaseRecyclerViewAdapterHelper", version.ref = "baseQuickAdapter" }
|
||||||
|
baseRecyclerViewAdapterHelper4 = { module = "io.github.cymchad:BaseRecyclerViewAdapterHelper4", version.ref = "baseQuickAdapter4" }
|
||||||
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
|
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#Mon Jul 14 11:28:37 CST 2025
|
#Mon Jul 14 11:28:37 CST 2025
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-all.zip
|
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-bin.zip
|
||||||
#distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
#distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
#distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.14.3-all.zip
|
#distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.14.3-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -341,6 +341,14 @@ public class FaceHelper implements FaceListener {
|
|||||||
refreshTrackId(faceInfoList);
|
refreshTrackId(faceInfoList);
|
||||||
if (faceInfoList.isEmpty()) {
|
if (faceInfoList.isEmpty()) {
|
||||||
return facePreviewInfoList;
|
return facePreviewInfoList;
|
||||||
|
} else {
|
||||||
|
FaceInfo currentFaceInfo = faceInfoList.get(0);
|
||||||
|
// L.e("currentFaceInfo width=" + currentFaceInfo.getRect().width() +
|
||||||
|
// "---height" + currentFaceInfo.getRect().height());
|
||||||
|
if (currentFaceInfo.getRect().width() < 260) {//距离远(人脸小),不识别
|
||||||
|
clearLeftFace(facePreviewInfoList);
|
||||||
|
return facePreviewInfoList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!onlyDetectLiveness) {
|
if (!onlyDetectLiveness) {
|
||||||
code = ftEngine.process(rgbNv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList,
|
code = ftEngine.process(rgbNv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList,
|
||||||
|
|||||||
@@ -397,6 +397,19 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置人脸识别状态:清空上次识别结果及 FaceHelper 内部的 recognizeInfoMap,
|
||||||
|
* 使下一帧进入时能重新触发识别流程。
|
||||||
|
*/
|
||||||
|
public void resetFaceState() {
|
||||||
|
// 清空粘性 LiveData,防止旧结果被重新投递给 observer
|
||||||
|
recognizeUserId.postValue(null);
|
||||||
|
// 清空 FaceHelper 内部所有人脸状态,让 trackId 对应的状态回到 TO_RETRY
|
||||||
|
if (faceHelper != null) {
|
||||||
|
faceHelper.clearFacePreviewInfoList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 释放操作
|
* 释放操作
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user