提交昨天的修改:优化多个模块和UI效果
This commit is contained in:
Generated
+2
-2
@@ -4,10 +4,10 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2026-01-28T08:24:39.059017600Z">
|
||||
<DropdownSelection timestamp="2026-03-16T07:12:10.978585600Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.80:5555;connection=d6ad651e" />
|
||||
<DeviceId pluginId="Default" identifier="serial=192.168.1.115:5555;connection=8c23341a" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MaterialThemeProjectNewConfig">
|
||||
<option name="metadata">
|
||||
<MTProjectMetadataState>
|
||||
<option name="migrated" value="true" />
|
||||
<option name="pristineConfig" value="false" />
|
||||
<option name="userId" value="4ab8791:19ce5d9ffb1:-7ffe" />
|
||||
</MTProjectMetadataState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,4 @@
|
||||
kotlin version: 2.0.21
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
|
||||
+58
-25
@@ -1,8 +1,14 @@
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
id("com.google.devtools.ksp") version "2.0.21-1.0.27"
|
||||
// alias(libs.plugins.android.application)
|
||||
// alias(libs.plugins.kotlin.android)
|
||||
// id("com.google.devtools.ksp") version "2.0.21-1.0.27"
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
// id("com.google.dagger.hilt.android")
|
||||
id("com.google.devtools.ksp")
|
||||
id("kotlin-parcelize")
|
||||
kotlin("kapt")
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -42,10 +48,12 @@ android {
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
signingConfig = signingConfigs.getByName("debug_507")
|
||||
// buildConfigField("boolean", "DEBUG", "false")
|
||||
}
|
||||
debug {
|
||||
//507扫码秤主板在android.buildTypes{}内增加
|
||||
signingConfig = signingConfigs.getByName("debug_507")
|
||||
// buildConfigField("boolean", "DEBUG", "true")
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
@@ -57,6 +65,7 @@ android {
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
packagingOptions {
|
||||
pickFirst("lib/armeabi-v7a/libserial_port.so")
|
||||
@@ -74,7 +83,9 @@ android {
|
||||
}
|
||||
// li
|
||||
}
|
||||
|
||||
val isDebug = gradle.startParameter.taskNames.any {
|
||||
it.contains("debug", ignoreCase = true)
|
||||
}
|
||||
dependencies {
|
||||
implementation(fileTree("libs") { include("*.jar", "*.aar") })
|
||||
implementation(libs.androidx.core.ktx)
|
||||
@@ -86,32 +97,54 @@ dependencies {
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
implementation(libs.androidx.activity.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.ktx)
|
||||
|
||||
implementation("com.google.code.gson:gson:2.10.1")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.9.1")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||
implementation(libs.gson)
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.logging.interceptor)
|
||||
implementation(libs.retrofit)
|
||||
implementation(libs.converter.gson)
|
||||
|
||||
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.2")
|
||||
implementation(libs.baserecyclerviewadapterhelper4)
|
||||
|
||||
implementation("androidx.room:room-runtime:2.5.2")
|
||||
ksp("androidx.room:room-compiler:2.5.2")
|
||||
implementation("androidx.room:room-ktx:2.5.2") // Kotlin扩展
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
|
||||
implementation("androidx.activity:activity-ktx:1.8.0")
|
||||
// room
|
||||
implementation(libs.androidx.room.runtime)
|
||||
ksp(libs.androidx.room.compiler)
|
||||
implementation(libs.androidx.room.ktx)
|
||||
|
||||
// implementation("biz.laenger.android:vpbs:0.0.6")
|
||||
|
||||
//必须 1.0.0 以上
|
||||
implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha")
|
||||
//核心必须依赖
|
||||
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
|
||||
//经典刷新头
|
||||
implementation("io.github.scwang90:refresh-header-radar:3.0.0-alpha")
|
||||
implementation("io.github.scwang90:refresh-footer-classics:3.0.0-alpha")
|
||||
//经典加载
|
||||
// refresh-layout
|
||||
implementation(libs.refresh.layout.kernel)
|
||||
implementation(libs.refresh.header.classics)
|
||||
implementation(libs.refresh.header.radar)
|
||||
implementation(libs.refresh.footer.classics)
|
||||
|
||||
//implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
|
||||
}
|
||||
|
||||
// glide
|
||||
implementation(libs.glide)
|
||||
annotationProcessor(libs.compiler)
|
||||
|
||||
// camerax
|
||||
implementation(libs.androidx.camera.core)
|
||||
implementation(libs.androidx.camera.camera2)
|
||||
implementation(libs.androidx.camera.lifecycle)
|
||||
implementation(libs.androidx.camera.view)
|
||||
implementation(libs.androidx.camera.extensions)
|
||||
|
||||
//pytorch
|
||||
implementation (libs.pytorch.android)
|
||||
implementation (libs.pytorch.android.torchvision)
|
||||
|
||||
// objectbox
|
||||
if (isDebug) {
|
||||
debugImplementation(libs.objectbox.android.objectbrowser)
|
||||
} else {
|
||||
releaseImplementation(libs.objectbox.android)
|
||||
}
|
||||
}
|
||||
|
||||
apply(plugin = "io.objectbox")
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"_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:6465153867413579585",
|
||||
"lastPropertyId": "4:3660727688686055762",
|
||||
"name": "Food",
|
||||
"properties": [
|
||||
{
|
||||
"id": "1:3688350375714699356",
|
||||
"name": "id",
|
||||
"type": 6,
|
||||
"flags": 1
|
||||
},
|
||||
{
|
||||
"id": "2:6503828433160216329",
|
||||
"name": "name",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "3:1726525909323356793",
|
||||
"name": "foodIdx",
|
||||
"type": 5
|
||||
},
|
||||
{
|
||||
"id": "4:3660727688686055762",
|
||||
"name": "foodVector",
|
||||
"indexId": "1:5497952887792054610",
|
||||
"type": 28,
|
||||
"flags": 8
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
}
|
||||
],
|
||||
"lastEntityId": "1:6465153867413579585",
|
||||
"lastIndexId": "1:5497952887792054610",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
"modelVersion": 5,
|
||||
"modelVersionParserMinimum": 5,
|
||||
"retiredEntityUids": [],
|
||||
"retiredIndexUids": [],
|
||||
"retiredPropertyUids": [],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,12 @@
|
||||
<!-- android:sharedUserId="android.uid.system"-->
|
||||
<uses-feature android:name="android.hardware.usb.host" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
@@ -84,6 +89,9 @@
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||
<activity android:name="com.shuwei.dish.match.ui.DeviceConfigActivity" />
|
||||
<activity android:name="com.shuwei.dish.match.ui.SettingActivity"
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||
<activity android:name="com.shuwei.dish.match.ui.SubmitFoodActivity" />
|
||||
|
||||
<receiver
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.adapter
|
||||
package com.shuwei.dish.match.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
@@ -7,12 +7,10 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding
|
||||
import com.sw.dualscreen.ext.dp
|
||||
import com.sw.dualscreen.ext.load
|
||||
import com.sw.dualscreen.objbox.FoodCollectionBean
|
||||
import com.sw.dualscreen.utils.GlideUtils
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.databinding.ListItemFoodCollectionBinding
|
||||
import com.shuwei.dish.match.objbox.FoodCollectionBean
|
||||
import com.shuwei.dish.match.utils.ext.load
|
||||
|
||||
class FoodCollectionAdapter (var list: MutableList<FoodCollectionBean>) :
|
||||
BaseQuickAdapter<FoodCollectionBean, FoodCollectionAdapter.VH>(list) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.db.DatabaseProvider
|
||||
import com.shuwei.dish.match.objbox.FoodModule
|
||||
import com.shuwei.dish.match.objbox.ObjectBox
|
||||
import com.shuwei.dish.match.ui.InitActivity.Companion.TAG
|
||||
import com.shuwei.dish.match.utils.AppUtil
|
||||
import com.shuwei.dish.match.utils.BootReceiver
|
||||
@@ -26,6 +28,7 @@ class BaseApp : Application() {
|
||||
// GlobalData.deviceId = "39a7abdd06b3c7ab"
|
||||
val filter = IntentFilter(Intent.ACTION_BOOT_COMPLETED)
|
||||
registerReceiver(BootReceiver(), filter)
|
||||
ObjectBox.init(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -18,8 +18,16 @@ abstract class BaseFragment<VB : ViewBinding> : Fragment() {
|
||||
|
||||
abstract fun inflateBinding(inflater: LayoutInflater, container: ViewGroup?): VB
|
||||
|
||||
abstract fun initialize()
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
initialize()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.inbound.objbox
|
||||
package com.shuwei.dish.match.objbox
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.inbound.objbox
|
||||
package com.shuwei.dish.match.objbox
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.HnswIndex
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
package com.sw.inbound.objbox
|
||||
package com.shuwei.dish.match.objbox
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.renderscript.Element.DataType
|
||||
import android.util.Log
|
||||
import androidx.core.graphics.scale
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.sw.inbound.MyApp
|
||||
import com.sw.inbound.objbox.ObjectBox.boxStore
|
||||
import com.sw.inbound.utils.AssetsTool
|
||||
import com.sw.inbound.utils.ImageUtil
|
||||
import com.sw.inbound.utils.LogSaveUtil
|
||||
import com.sw.inbound.utils.ext.toJsonString
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.kotlin.boxFor
|
||||
import io.objectbox.query.IdWithScore
|
||||
import io.objectbox.query.Query
|
||||
import com.shuwei.dish.match.utils.AssetsTool
|
||||
import com.shuwei.dish.match.utils.LogSaveUtil
|
||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.internal.closeQuietly
|
||||
import org.pytorch.IValue
|
||||
import org.pytorch.Module
|
||||
import org.pytorch.torchvision.TensorImageUtils
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
@@ -313,7 +301,7 @@ object FoodModule {
|
||||
}
|
||||
|
||||
private fun logInfo(msg:String) {
|
||||
Timber.tag("FoodModule").d(msg)
|
||||
Log.d("FoodModule", msg)
|
||||
LogSaveUtil.saveLogFile(msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.sw.inbound.objbox
|
||||
package com.shuwei.dish.match.objbox
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.sw.inbound.MyApp
|
||||
import com.sw.inbound.utils.LogSaveUtil
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.utils.LogSaveUtil
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.BoxStore
|
||||
import io.objectbox.BoxStoreBuilder
|
||||
import io.objectbox.exception.DbException
|
||||
import io.objectbox.exception.FileCorruptException
|
||||
import io.objectbox.kotlin.boxFor
|
||||
import io.objectbox.query.IdWithScore
|
||||
import io.objectbox.query.Query
|
||||
import io.objectbox.sync.Sync
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -39,12 +38,12 @@ import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import com.shuwei.dish.match.BuildConfig
|
||||
|
||||
/**
|
||||
* Singleton to keep BoxStore reference and provide current list of Notes Objects.
|
||||
* Inserts demo data if no Objects are stored.
|
||||
*/
|
||||
@SuppressLint("LogNotTimber")
|
||||
object ObjectBox {
|
||||
|
||||
// 确保所有设备/版本使用相同的objectbox-models/default.json
|
||||
@@ -88,7 +87,7 @@ object ObjectBox {
|
||||
}
|
||||
}
|
||||
|
||||
if (com.sw.inbound.BuildConfig.DEBUG) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
var syncAvailable = if (Sync.isAvailable()) "available" else "unavailable"
|
||||
Log.d(
|
||||
TAG,
|
||||
@@ -144,7 +143,7 @@ object ObjectBox {
|
||||
e.printStackTrace()
|
||||
LogSaveUtil.saveLogFile("safeDbOp出现FileCorruptException异常:${e.message},${e.errorCode}")
|
||||
// 使用安全调用替代 !! 断言,避免 NPE
|
||||
val app = MyApp.instance ?: return@withContext null
|
||||
val app = BaseApp.instance ?: return@withContext null
|
||||
init(app)
|
||||
null
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.databinding.ActivityInitBinding
|
||||
import com.shuwei.dish.match.db.AppRepository
|
||||
import com.shuwei.dish.match.http.UrlConfig
|
||||
import com.shuwei.dish.match.objbox.FoodModule
|
||||
import com.shuwei.dish.match.utils.AppUtil
|
||||
import com.shuwei.dish.match.utils.QRCodeUtil
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
@@ -38,7 +39,9 @@ class InitActivity : BaseActivity() {
|
||||
// useBackground(false)
|
||||
binding = ActivityInitBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
lifecycleScope.launch {
|
||||
FoodModule.init(this@InitActivity)
|
||||
}
|
||||
// setHeaderBackground(isHomePage = true)
|
||||
setHeaderBgVisible(false)
|
||||
BaseApp.appVersion = AppUtil.getAppVersionCode(this).toString()
|
||||
|
||||
@@ -59,9 +59,7 @@ class SamplingListActivity : BaseActivity() {
|
||||
it.visible()
|
||||
it.setImageResource(R.drawable.ic_setting)
|
||||
it.setOnClickListener {
|
||||
startActivity<DeviceConfigActivity> {
|
||||
putExtra(DeviceConfigActivity.COOK_MODE, 2)
|
||||
}
|
||||
startActivity<SettingActivity>()
|
||||
}
|
||||
}, backAction = {
|
||||
it.gone()
|
||||
@@ -86,7 +84,7 @@ class SamplingListActivity : BaseActivity() {
|
||||
appViewModel.deleteCookFoodAndGoods(cookMode = 1, foodId = foodId, onFinish = action)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false
|
||||
if (isConfigPage) {
|
||||
@@ -394,9 +392,7 @@ class SamplingListActivity : BaseActivity() {
|
||||
rightBtnText = "去设置",
|
||||
leftBtnClick = {},
|
||||
rightBtnClick = {
|
||||
startActivity<DeviceConfigActivity> {
|
||||
putExtra(DeviceConfigActivity.COOK_MODE, 2)
|
||||
}
|
||||
startActivity<SettingActivity>()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ class SelectDishActivity : BaseActivity() {
|
||||
it.visible()
|
||||
it.setImageResource(R.drawable.ic_setting)
|
||||
it.setOnClickListener {
|
||||
startActivity<DeviceConfigActivity> {
|
||||
putExtra(DeviceConfigActivity.COOK_MODE, 1)
|
||||
}
|
||||
startActivity<SettingActivity>()
|
||||
}
|
||||
}, backAction = {
|
||||
it.gone()
|
||||
@@ -107,9 +105,7 @@ class SelectDishActivity : BaseActivity() {
|
||||
rightBtnText = "去设置",
|
||||
leftBtnClick = {},
|
||||
rightBtnClick = {
|
||||
startActivity<DeviceConfigActivity> {
|
||||
putExtra(DeviceConfigActivity.COOK_MODE, 1)
|
||||
}
|
||||
startActivity<SettingActivity>()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -167,7 +163,7 @@ class SelectDishActivity : BaseActivity() {
|
||||
appViewModel.deleteCookFoodAndGoods(cookMode = 0, foodId = foodId, onFinish = action)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
runCatching {
|
||||
val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.activity.fragment
|
||||
package com.shuwei.dish.match.ui.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@@ -7,38 +7,27 @@ import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.sw.dualscreen.GlobalData
|
||||
import com.sw.dualscreen.R
|
||||
import com.sw.dualscreen.activity.CollectedFoodActivity
|
||||
import com.sw.dualscreen.activity.SettingActivity
|
||||
import com.sw.dualscreen.adapter.CollectFoodListAdapter
|
||||
import com.sw.dualscreen.adapter.FoodCollectionAdapter
|
||||
import com.sw.dualscreen.databinding.FragmentCollectBinding
|
||||
import com.sw.dualscreen.databinding.LayoutCameraPreviewBinding
|
||||
import com.sw.dualscreen.ext.clickWithDebounce
|
||||
import com.sw.dualscreen.ext.dp
|
||||
import com.sw.dualscreen.model.response.FoodInfo
|
||||
import com.sw.dualscreen.objbox.Food
|
||||
import com.sw.dualscreen.objbox.FoodCollectionBean
|
||||
import com.sw.dualscreen.objbox.FoodModule
|
||||
import com.sw.dualscreen.objbox.ObjectBox
|
||||
import com.sw.dualscreen.utils.BitmapSaver
|
||||
import com.sw.dualscreen.utils.CameraUtils
|
||||
import com.sw.dualscreen.utils.Debouncer
|
||||
import com.sw.dualscreen.utils.ImageUploader
|
||||
import com.sw.dualscreen.utils.ImageUtil
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.FoodCollectionAdapter
|
||||
import com.shuwei.dish.match.base.BaseFragment
|
||||
import com.shuwei.dish.match.databinding.FragmentCollectBinding
|
||||
import com.shuwei.dish.match.objbox.FoodCollectionBean
|
||||
import com.shuwei.dish.match.objbox.FoodModule
|
||||
import com.shuwei.dish.match.objbox.ObjectBox
|
||||
import com.shuwei.dish.match.ui.SettingActivity
|
||||
import com.shuwei.dish.match.utils.BitmapSaver
|
||||
import com.shuwei.dish.match.utils.Debouncer
|
||||
import com.shuwei.dish.match.utils.ImageUtil
|
||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import timber.log.Timber
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
@@ -57,25 +46,22 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
private val searchFoodList = mutableListOf<FoodInfo>()
|
||||
private var settingActivity: SettingActivity? = null
|
||||
private var checkedItem: FoodInfo? = null
|
||||
private val searchFoodAdapter by lazy {
|
||||
CollectFoodListAdapter(searchFoodList).apply {
|
||||
setOnItemClickListener { adapter, view, position ->
|
||||
searchFoodList.forEachIndexed { index, item -> item.isChecked = index == position }
|
||||
checkedItem = searchFoodList[position]
|
||||
notifyDataSetChanged()
|
||||
selectedFoodId = checkedItem!!.foodId
|
||||
selectedFoodName = checkedItem!!.foodName
|
||||
}
|
||||
}
|
||||
}
|
||||
// private val searchFoodList = mutableListOf<FoodInfo>()
|
||||
// private var settingActivity: SettingActivity? = null
|
||||
// private var checkedItem: FoodInfo? = null
|
||||
// private val searchFoodAdapter by lazy {
|
||||
// CollectFoodListAdapter(searchFoodList).apply {
|
||||
// setOnItemClickListener { adapter, view, position ->
|
||||
// searchFoodList.forEachIndexed { index, item -> item.isChecked = index == position }
|
||||
// checkedItem = searchFoodList[position]
|
||||
// notifyDataSetChanged()
|
||||
// selectedFoodId = checkedItem!!.foodId
|
||||
// selectedFoodName = checkedItem!!.foodName
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
private val debouncer = Debouncer(2000)
|
||||
private lateinit var previewView: PreviewView
|
||||
private val cameraUtils: CameraUtils by lazy {
|
||||
CameraUtils(requireActivity())
|
||||
}
|
||||
private lateinit var settingActivity: SettingActivity
|
||||
|
||||
private val collectionAdapter: FoodCollectionAdapter by lazy {
|
||||
FoodCollectionAdapter(foodCollectionList).apply {
|
||||
@@ -94,18 +80,23 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun inflateViewBinding(): FragmentCollectBinding {
|
||||
|
||||
override fun inflateBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
): FragmentCollectBinding {
|
||||
return FragmentCollectBinding.inflate(LayoutInflater.from(context))
|
||||
}
|
||||
|
||||
//typealias CameraCallback = (Uri) -> Unit
|
||||
|
||||
private val cameraCallback: (Uri) -> Unit = { uri ->
|
||||
try {
|
||||
val index = foodCollectionList.indexOfFirst { it.imageFile == null }
|
||||
if (index == -1) {
|
||||
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
|
||||
settingActivity?.hideWaitingDialog()
|
||||
rerurn@ cameraCallback
|
||||
toast("每次只允许保存${MAX_COUNT}条数据")
|
||||
hideWaitingDialog()
|
||||
rerurn@cameraCallback
|
||||
}
|
||||
activity?.runOnUiThread {
|
||||
foodCollectionList[index].let {
|
||||
@@ -117,7 +108,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}
|
||||
collectionAdapter.notifyItemChanged(index)
|
||||
}
|
||||
// settingActivity?.hideWaitingDialog()
|
||||
// hideWaitingDialog()
|
||||
Thread {
|
||||
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
|
||||
getImageVector(index, bitmap)
|
||||
@@ -125,9 +116,9 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}.start()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
settingActivity?.hideWaitingDialog()
|
||||
ToastUtils.showToast("程序异常${e.message}")
|
||||
settingActivity?.log("程序异常${e.message}")
|
||||
hideWaitingDialog()
|
||||
toast("程序异常${e.message}")
|
||||
log("程序异常${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,15 +132,15 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
FoodModule.bitmap2FloatArray(bitmap, false)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
ToastUtils.showToast("操作失败")
|
||||
settingActivity?.log("操作失败:${e.message}")
|
||||
settingActivity?.hideWaitingDialog()
|
||||
toast("操作失败")
|
||||
log("操作失败:${e.message}")
|
||||
hideWaitingDialog()
|
||||
return
|
||||
}
|
||||
val file = BitmapSaver.saveToAppFilesDir(
|
||||
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
)
|
||||
settingActivity?.log("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
log("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
|
||||
activity?.runOnUiThread {
|
||||
foodCollectionList[index].let {
|
||||
@@ -163,45 +154,35 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
if (bitmap.isRecycled.not()) {
|
||||
bitmap.recycle()
|
||||
}
|
||||
settingActivity?.hideWaitingDialog()
|
||||
hideWaitingDialog()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun takePhoto() {
|
||||
val count = foodCollectionList.count { it.bitmap != null }
|
||||
if (count >= MAX_COUNT) {
|
||||
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
|
||||
toast("每次只允许保存${MAX_COUNT}条数据")
|
||||
return
|
||||
}
|
||||
settingActivity?.showWaitingDialog("采集中……")
|
||||
cameraUtils.takePhoto(cameraCallback) { errMsg ->
|
||||
settingActivity?.hideWaitingDialog()
|
||||
// ToastUtils.showToast("拍照异常,请重新操作")
|
||||
showWaitingDialog("采集中……")
|
||||
settingActivity.takePhoto(succCallback = cameraCallback, failCallback = { errMsg ->
|
||||
hideWaitingDialog()
|
||||
// toast("拍照异常,请重新操作")
|
||||
// if (cameraErrorCount >= 10) {
|
||||
// ToastUtils.showToast("拍照异常,请重新操作")
|
||||
// settingActivity?.log("拍照异常,请重新操作:$errMsg")
|
||||
// toast("拍照异常,请重新操作")
|
||||
// log("拍照异常,请重新操作:$errMsg")
|
||||
// cameraErrorCount = 0
|
||||
// return@takePhoto
|
||||
// }
|
||||
// cameraErrorCount++
|
||||
// takePhoto()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private var cameraErrorCount = 0
|
||||
|
||||
override fun initialize() {
|
||||
settingActivity = activity as SettingActivity
|
||||
cameraUtils.initCamera()
|
||||
val previewBinding =
|
||||
LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview)
|
||||
previewView = previewBinding.previewView.also {
|
||||
it.updateLayoutParams {
|
||||
width = 456.dp
|
||||
height = 342.dp
|
||||
}
|
||||
}
|
||||
cameraUtils.setPreviewController(previewView)
|
||||
// 首次显示 CollectFragment 时初始化相机
|
||||
settingActivity.initCamera(binding.flCameraPreview)
|
||||
|
||||
binding.rvFoodList.let {
|
||||
it.layoutManager =
|
||||
@@ -214,16 +195,16 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}
|
||||
|
||||
binding.btnSave.setOnClickListener {
|
||||
if (checkedItem == null || checkedItem!!.isChecked.not()) {
|
||||
ToastUtils.showToast("请选择菜品名称")
|
||||
return@setOnClickListener
|
||||
}
|
||||
val count = foodCollectionList.count { it.imageFile != null }
|
||||
if (count == 0) {
|
||||
ToastUtils.showToast("请拍摄菜品照片")
|
||||
return@setOnClickListener
|
||||
}
|
||||
upload()
|
||||
// if (checkedItem == null || checkedItem!!.isChecked.not()) {
|
||||
// toast("请选择菜品名称")
|
||||
// return@setOnClickListener
|
||||
// }
|
||||
// val count = foodCollectionList.count { it.imageFile != null }
|
||||
// if (count == 0) {
|
||||
// toast("请拍摄菜品照片")
|
||||
// return@setOnClickListener
|
||||
// }
|
||||
// upload()
|
||||
}
|
||||
|
||||
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
|
||||
@@ -239,173 +220,103 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
}
|
||||
|
||||
binding.btnCollectedFood.setOnClickListener {
|
||||
startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java))
|
||||
// startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java))
|
||||
}
|
||||
binding.btnTakePhoto.clickWithDebounce {
|
||||
val count = foodCollectionList.count { it.bitmap != null }
|
||||
if (count >= MAX_COUNT) {
|
||||
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
|
||||
toast("每次只允许保存${MAX_COUNT}条数据")
|
||||
return@clickWithDebounce
|
||||
}
|
||||
takePhoto()
|
||||
}
|
||||
binding.btnClearData.setOnClickListener { clearData() }
|
||||
binding.rvSearchFood.let {
|
||||
it.layoutManager = GridLayoutManager(context, 2)
|
||||
it.adapter = searchFoodAdapter
|
||||
}
|
||||
// binding.rvSearchFood.let {
|
||||
// it.layoutManager = GridLayoutManager(context, 2)
|
||||
// it.adapter = searchFoodAdapter
|
||||
// }
|
||||
|
||||
searchFood()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun upload() {
|
||||
lifecycleScope.launch {
|
||||
val totalFileCount = foodCollectionList.count { it.imageFile != null }
|
||||
settingActivity?.showWaitingDialog2("图片上传中0/$totalFileCount")
|
||||
val params = HashMap<String, RequestBody>()
|
||||
//params["placeId"] = restId.toRequestBody()
|
||||
params["foodId"] = checkedItem!!.foodId.toRequestBody()
|
||||
params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
|
||||
params["version"] = GlobalData.foodModelVersion.toRequestBody()
|
||||
|
||||
ImageUploader(totalList = foodCollectionList, uploadImage = { batch ->
|
||||
val files = batch.map { it.imageFile }
|
||||
val foodVectorList = batch.filter { it.imageVector != null }.map {
|
||||
it.imageVector!!.joinToString(
|
||||
separator = ",", prefix = "[", postfix = "]"
|
||||
)
|
||||
}
|
||||
val foodVectorJson =
|
||||
foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
|
||||
Timber.tag(TAG).d("json=$foodVectorJson")
|
||||
params["foodVector"] = foodVectorJson.toRequestBody()
|
||||
settingActivity?.viewModel?.uploadCollectFoodPics(files, params)
|
||||
}, onProgress = { count, batch, idList ->
|
||||
//batch.forEach {
|
||||
// it.uploadSuccess = true
|
||||
//}
|
||||
runBlocking {
|
||||
activity?.runOnUiThread {
|
||||
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
|
||||
}
|
||||
val foodList = batch.mapIndexed { index, it ->
|
||||
Food(
|
||||
collectId = if (index < idList.size) idList[index] else null,
|
||||
foodId = checkedItem!!.foodId,
|
||||
foodName = checkedItem!!.foodName,
|
||||
foodVector = it.imageVector,
|
||||
version = GlobalData.foodModelVersion
|
||||
)
|
||||
}
|
||||
ObjectBox.putAll(foodList)
|
||||
activity?.runOnUiThread {
|
||||
batch.forEach { it.isFinish = true }
|
||||
collectionAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}, onError = {
|
||||
activity?.runOnUiThread {
|
||||
binding.root.postDelayed({
|
||||
settingActivity?.hideWaitingDialog()
|
||||
ToastUtils.showToast("上传失败,请稍后重试")
|
||||
}, 1000)
|
||||
}
|
||||
}, onComplete = {
|
||||
//vectorThread()
|
||||
binding.root.postDelayed({
|
||||
settingActivity?.hideWaitingDialog()
|
||||
ToastUtils.showToast("上传成功")
|
||||
}, 1000)
|
||||
}).processUploads()
|
||||
}
|
||||
|
||||
|
||||
// for (index in foodCollectionList.indices step 5) {
|
||||
// val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
|
||||
// val subList = foodCollectionList.subList(index, end)
|
||||
// val subFiles = subList.map { it.imageFile }
|
||||
// uploadCollectFoodPics(subFiles, params) { isSuccess->
|
||||
// Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
|
||||
// subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
|
||||
// lifecycleScope.launch {
|
||||
// val totalFileCount = foodCollectionList.count { it.imageFile != null }
|
||||
// showWaitingDialog2("图片上传中0/$totalFileCount")
|
||||
// val params = HashMap<String, RequestBody>()
|
||||
// //params["placeId"] = restId.toRequestBody()
|
||||
// params["foodId"] = checkedItem!!.foodId.toRequestBody()
|
||||
// params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
|
||||
// params["version"] = GlobalData.foodModelVersion.toRequestBody()
|
||||
//
|
||||
//// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
||||
//// runOnUiThread {
|
||||
//// binding.btnUploadImage.text = "待上传图片${count}张"
|
||||
//// if (count == 0) {
|
||||
//// Loading.dismiss()
|
||||
//// }
|
||||
//// }
|
||||
// }
|
||||
// ImageUploader(totalList = foodCollectionList, uploadImage = { batch ->
|
||||
// val files = batch.map { it.imageFile }
|
||||
// val foodVectorList = batch.filter { it.imageVector != null }.map {
|
||||
// it.imageVector!!.joinToString(
|
||||
// separator = ",", prefix = "[", postfix = "]"
|
||||
// )
|
||||
// }
|
||||
// val foodVectorJson =
|
||||
// foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
|
||||
// log("json=$foodVectorJson")
|
||||
// params["foodVector"] = foodVectorJson.toRequestBody()
|
||||
// viewModel?.uploadCollectFoodPics(files, params)
|
||||
// }, onProgress = { count, batch, idList ->
|
||||
// //batch.forEach {
|
||||
// // it.uploadSuccess = true
|
||||
// //}
|
||||
// runBlocking {
|
||||
// activity?.runOnUiThread {
|
||||
// showWaitingDialog2("图片上传中$count/$totalFileCount")
|
||||
// }
|
||||
// val foodList = batch.mapIndexed { index, it ->
|
||||
// Food(
|
||||
// collectId = if (index < idList.size) idList[index] else null,
|
||||
// foodId = checkedItem!!.foodId,
|
||||
// foodName = checkedItem!!.foodName,
|
||||
// foodVector = it.imageVector,
|
||||
// version = GlobalData.foodModelVersion
|
||||
// )
|
||||
// }
|
||||
// ObjectBox.putAll(foodList)
|
||||
// activity?.runOnUiThread {
|
||||
// batch.forEach { it.isFinish = true }
|
||||
// collectionAdapter.notifyDataSetChanged()
|
||||
// }
|
||||
// }
|
||||
// }, onError = {
|
||||
// activity?.runOnUiThread {
|
||||
// binding.root.postDelayed({
|
||||
// hideWaitingDialog()
|
||||
// toast("上传失败,请稍后重试")
|
||||
// }, 1000)
|
||||
// }
|
||||
// }, onComplete = {
|
||||
// //vectorThread()
|
||||
// binding.root.postDelayed({
|
||||
// hideWaitingDialog()
|
||||
// toast("上传成功")
|
||||
// }, 1000)
|
||||
// }).processUploads()
|
||||
// }
|
||||
}
|
||||
|
||||
// private fun vectorThread() {
|
||||
// settingActivity?.showWaitingDialog("加载中……")
|
||||
// Thread {
|
||||
// foodCollectionList
|
||||
//// .filter { it.bitmap != null }
|
||||
//// .filter { it.imageVector != null }
|
||||
// .forEachIndexed { index, it ->
|
||||
// if (it.imageVector == null) {
|
||||
// return@forEachIndexed
|
||||
// }
|
||||
// image2VectorTask(imageVector = it.imageVector!!, index)
|
||||
// }
|
||||
// activity?.runOnUiThread {
|
||||
// binding.root.postDelayed({
|
||||
// settingActivity?.hideWaitingDialog()
|
||||
// }, 1000)
|
||||
// }
|
||||
// }.start()
|
||||
// }
|
||||
|
||||
// private fun image2VectorTask(imageVector: FloatArray?, position: Int) {
|
||||
// if (imageVector == null) return
|
||||
////// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
|
||||
//////
|
||||
//////// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
|
||||
//////// Timber.tag("mzf1").e(base64Str)
|
||||
////////// viewModel.postImageData(
|
||||
////////// context,
|
||||
////////// foodId = selectedFoodId.toString(),
|
||||
////////// foodName = selectedFoodName.toString(),
|
||||
////////// foodVector = base64Str,
|
||||
////////// uri = item.imageUri!!
|
||||
////////// )
|
||||
//// box.put(
|
||||
//// Food(
|
||||
//// collectId = null,
|
||||
//// foodId = checkedItem!!.foodId,
|
||||
//// foodName = checkedItem!!.foodName,
|
||||
//// foodVector = imageVector,
|
||||
//// version = "1.0.0"
|
||||
//// )
|
||||
//// )
|
||||
//// if (position > -1) {
|
||||
//// foodCollectionList[position].isFinish = true
|
||||
//// activity?.runOnUiThread {
|
||||
//// collectionAdapter.notifyItemChanged(position)
|
||||
//// }
|
||||
//// }
|
||||
// }
|
||||
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun searchFood() {
|
||||
fun searchFood() {
|
||||
debouncer.debounce {
|
||||
settingActivity?.searchByFoodName(binding.editFoodName.text.toString()) {
|
||||
searchFoodList.clear()
|
||||
searchFoodList.addAll(it)
|
||||
searchFoodAdapter.notifyDataSetChanged()
|
||||
searchByFoodName(binding.editFoodName.text.toString()) {
|
||||
// searchFoodList.clear()
|
||||
// searchFoodList.addAll(it)
|
||||
// searchFoodAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var clickIndex = -1
|
||||
var clickIndex = -1
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun clearData() {
|
||||
fun clearData() {
|
||||
foodCollectionList.forEach {
|
||||
it.bitmap = null
|
||||
it.imageVector = null
|
||||
@@ -422,20 +333,27 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
||||
searchFood()
|
||||
}
|
||||
|
||||
private var isFirstOpen = true
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
cameraUtils.bind()
|
||||
if (isVisible.not()) return
|
||||
binding.llCameraFlag.run {
|
||||
visibility = View.VISIBLE
|
||||
postDelayed({
|
||||
visibility = View.GONE
|
||||
}, 3000)
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
cameraUtils.unbind()
|
||||
binding.llCameraFlag.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun log(msg: String) {}
|
||||
private fun searchByFoodName(name: String, block:(String)-> Unit) {}
|
||||
private fun hideWaitingDialog() {}
|
||||
private fun showWaitingDialog(msg: String) {}
|
||||
private fun showWaitingDialog2(msg: String) {}
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
package com.shuwei.dish.match.ui.fragment
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.LineHeightSpan
|
||||
import android.text.style.StyleSpan
|
||||
import android.util.Log
|
||||
import android.util.SparseArray
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.graphics.toColorInt
|
||||
import androidx.core.view.forEach
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import com.shuwei.dish.match.base.BaseFragment
|
||||
import com.shuwei.dish.match.databinding.FragmentDeviceConfigBinding
|
||||
import com.shuwei.dish.match.db.AppRepository
|
||||
import com.shuwei.dish.match.dialog.CommonDialog
|
||||
import com.shuwei.dish.match.dialog.SeasoningSearchDialog
|
||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
||||
import com.shuwei.dish.match.entity.ResetReasoningRecord
|
||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.utils.AddressUtil
|
||||
import com.shuwei.dish.match.utils.JsonAssetsLoader
|
||||
import com.shuwei.dish.match.utils.MultiClickDetector
|
||||
import com.shuwei.dish.match.utils.WeightUtil
|
||||
import com.shuwei.dish.match.utils.ext.appendText
|
||||
import com.shuwei.dish.match.utils.ext.buildSpannableString
|
||||
import com.shuwei.dish.match.utils.ext.dp
|
||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||
import com.shuwei.dish.match.utils.ext.gone
|
||||
import com.shuwei.dish.match.utils.ext.toast
|
||||
import com.shuwei.dish.match.utils.ext.visible
|
||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
||||
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
||||
import com.shuwei.dish.match.ui.SamplingListActivity
|
||||
import com.shuwei.dish.match.ui.SelectDishActivity
|
||||
import com.shuwei.dish.match.utils.SpTool
|
||||
import com.shuwei.dish.match.utils.ext.startActivity
|
||||
|
||||
/**
|
||||
* 设备配置Fragment
|
||||
* 功能:支持三种模式选择(制作、采样、品控),调料网格配置管理
|
||||
*/
|
||||
class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "DeviceConfigFragment"
|
||||
const val COOK_MODE = "cookMode"
|
||||
|
||||
val modeList = listOf<ModeBean>(
|
||||
ModeBean("制作模式", "菜品快速制作,记录熟重"),
|
||||
ModeBean("采样模式", "菜品快速制作,记录熟重"),
|
||||
ModeBean("品控模式", "菜品快速制作,记录熟重")
|
||||
)
|
||||
|
||||
fun newInstance(cookMode: Int = 0): DeviceConfigFragment {
|
||||
return DeviceConfigFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt(COOK_MODE, cookMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ModeBean(
|
||||
var modeName: String,
|
||||
var modeDesc: String
|
||||
)
|
||||
|
||||
private lateinit var appViewModel: AppViewModel
|
||||
|
||||
private var cookMode: Int = 0
|
||||
private val weightArray = SparseArray<Double>()
|
||||
private val addressArray = AddressUtil.getWeighAddressArray()
|
||||
private var seasoningItems = mutableListOf<SeasoningEntity>()
|
||||
private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800)
|
||||
|
||||
override fun inflateBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
): FragmentDeviceConfigBinding {
|
||||
return FragmentDeviceConfigBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun initialize(){
|
||||
cookMode = arguments?.getInt(COOK_MODE, 0) ?: 0
|
||||
initViewModel()
|
||||
initUI()
|
||||
addWeighListener()
|
||||
addGridItemListener()
|
||||
loadSeasoning()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化ViewModel
|
||||
*/
|
||||
private fun initViewModel() {
|
||||
val db = BaseApp.instance!!.database
|
||||
val factory = AppFactory(AppRepository(db.appDao()))
|
||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化UI
|
||||
*/
|
||||
private fun initUI() {
|
||||
loadQualitySpan(isEnable = false)
|
||||
when (cookMode) {
|
||||
1 -> {
|
||||
binding.rbModeCook.isChecked = true
|
||||
binding.rbModeSampling.isChecked = false
|
||||
loadCookSpan(isClicked = true)
|
||||
loadSamplingSpan()
|
||||
}
|
||||
|
||||
2 -> {
|
||||
binding.rbModeCook.isChecked = false
|
||||
binding.rbModeSampling.isChecked = true
|
||||
loadCookSpan()
|
||||
loadSamplingSpan(isClicked = true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
binding.rbModeCook.isChecked = true
|
||||
binding.rbModeSampling.isChecked = false
|
||||
loadCookSpan(isClicked = true)
|
||||
loadSamplingSpan()
|
||||
}
|
||||
}
|
||||
|
||||
binding.rbModeCook.setOnClickListener {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 0)
|
||||
binding.rbModeCook.isChecked = true
|
||||
binding.rbModeSampling.isChecked = false
|
||||
loadCookSpan(isClicked = true)
|
||||
loadSamplingSpan()
|
||||
activity?.startActivity<SelectDishActivity> {
|
||||
putExtra(SelectDishActivity.IS_CONFIG_PAGE, true)
|
||||
}
|
||||
activity?.finish()
|
||||
}
|
||||
binding.rbModeSampling.setOnClickListener {
|
||||
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 1)
|
||||
binding.rbModeCook.isChecked = false
|
||||
binding.rbModeSampling.isChecked = true
|
||||
loadCookSpan()
|
||||
loadSamplingSpan(isClicked = true)
|
||||
activity?.startActivity<SamplingListActivity> {
|
||||
putExtra(SamplingListActivity.IS_CONFIG_PAGE, true) }
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加称重监听
|
||||
*/
|
||||
private fun addWeighListener() {
|
||||
WeightUtil.addWeightListener(
|
||||
weightKey = TAG,
|
||||
getWeight = { address, state, weight ->
|
||||
Log.d(TAG, "addWeighListener: address=$address,stat=$state,weight=$weight")
|
||||
weightArray.put(address, weight)
|
||||
val item = seasoningItems.firstOrNull { address == addressArray[it.sort] }
|
||||
item?.let {
|
||||
it.useWeight = weight.toDouble()
|
||||
updateGridData(it)
|
||||
}
|
||||
Log.d(TAG, "addWeighListener: update-----------------------")
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加网格项点击监听
|
||||
*/
|
||||
private fun addGridItemListener() {
|
||||
binding.include.root.forEach { child ->
|
||||
child.clickWithDebounce {
|
||||
val sort = child.tag.toString().toInt()
|
||||
val entity = seasoningItems.firstOrNull { it.sort == sort } ?: SeasoningEntity()
|
||||
clickGridItem(sort, entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载调料数据
|
||||
*/
|
||||
private fun loadSeasoning() {
|
||||
appViewModel.loadSeasoning {
|
||||
seasoningItems.clear()
|
||||
seasoningItems.addAll(it)
|
||||
initConfigData()
|
||||
setGridData(seasoningItems)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化配置数据,确保有12个调料位置
|
||||
*/
|
||||
private fun initConfigData() {
|
||||
repeat(12) { num ->
|
||||
val firstOne = seasoningItems.firstOrNull { it.sort == num }
|
||||
if (firstOne == null) {
|
||||
seasoningItems.add(SeasoningEntity().also { it.sort = num })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置网格数据
|
||||
*/
|
||||
private fun setGridData(list: MutableList<SeasoningEntity>) {
|
||||
val gridLayout = binding.include.root
|
||||
list.forEach { entity ->
|
||||
val tag = entity.sort.toString()
|
||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新网格数据
|
||||
*/
|
||||
private fun updateGridData(entity: SeasoningEntity) {
|
||||
val gridLayout = binding.include.root
|
||||
val tag = entity.sort.toString()
|
||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击网格项,打开调料搜索对话框
|
||||
*/
|
||||
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
|
||||
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
||||
SeasoningSearchDialog(
|
||||
weighIndex = sort,
|
||||
weighAddress = currentAddress,
|
||||
clickName = entity.goodsName
|
||||
).show(requireActivity() as BaseActivity) { item ->
|
||||
syncItem(entity, item)
|
||||
// 3-调料
|
||||
entity.materialType = 3
|
||||
entity.sort = sort
|
||||
saveSeasoning(entity) {
|
||||
val tag = sort.toString()
|
||||
val gridLayout = binding.include.root
|
||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步调料项数据
|
||||
*/
|
||||
private fun syncItem(oldItem: SeasoningEntity, newItem: SeasoningEntity) {
|
||||
oldItem.run {
|
||||
goodsId = newItem.goodsId
|
||||
goodsName = newItem.goodsName
|
||||
goodsOrRelationCode = newItem.goodsOrRelationCode
|
||||
relateionType = newItem.relateionType
|
||||
materialType = newItem.materialType
|
||||
allEdible = newItem.allEdible
|
||||
useWeight = newItem.useWeight
|
||||
popularName = newItem.popularName
|
||||
canteenId = newItem.canteenId
|
||||
relateionType_dictText = newItem.relateionType_dictText
|
||||
|
||||
foodId = newItem.foodId
|
||||
sort = newItem.sort
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存调料数据
|
||||
*/
|
||||
fun saveSeasoning(entity: SeasoningEntity, action: () -> Unit = {}) {
|
||||
appViewModel.saveSeasoning(entity) {
|
||||
action()
|
||||
toast("保存成功")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载品控模式文本样式
|
||||
*/
|
||||
private fun loadQualitySpan(isClicked: Boolean = false, isEnable: Boolean = true) {
|
||||
binding.rbModeQuality.text =
|
||||
getModeTextSpan(
|
||||
topText = modeList[2].modeName,
|
||||
bottomText = modeList[2].modeDesc,
|
||||
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
|
||||
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载采样模式文本样式
|
||||
*/
|
||||
private fun loadSamplingSpan(isClicked: Boolean = false, isEnable: Boolean = true) {
|
||||
binding.rbModeSampling.text =
|
||||
getModeTextSpan(
|
||||
topText = modeList[1].modeName,
|
||||
bottomText = modeList[1].modeDesc,
|
||||
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
|
||||
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载制作模式文本样式
|
||||
*/
|
||||
private fun loadCookSpan(isClicked: Boolean = false, isEnable: Boolean = true) {
|
||||
binding.rbModeCook.text =
|
||||
getModeTextSpan(
|
||||
topText = modeList[0].modeName,
|
||||
bottomText = modeList[0].modeDesc,
|
||||
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
|
||||
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成模式文本样式
|
||||
*/
|
||||
private fun getModeTextSpan(
|
||||
topText: String,
|
||||
topColor: String,
|
||||
bottomText: String,
|
||||
bottomColor: String
|
||||
): SpannableStringBuilder {
|
||||
return buildSpannableString {
|
||||
appendText(
|
||||
topText,
|
||||
ForegroundColorSpan(topColor.toColorInt()),
|
||||
StyleSpan(Typeface.BOLD),
|
||||
AbsoluteSizeSpan(36, true),
|
||||
LineHeightSpan { text, start, end, spanstartv, v, fm ->
|
||||
fm.descent += 10.dp // 增加行间距
|
||||
}
|
||||
)
|
||||
append("\n")
|
||||
appendText(
|
||||
bottomText,
|
||||
ForegroundColorSpan(bottomColor.toColorInt()),
|
||||
AbsoluteSizeSpan(26, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
// 移除称重监听
|
||||
WeightUtil.removeWeightListener(TAG)
|
||||
}
|
||||
}
|
||||
@@ -87,8 +87,7 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
|
||||
return FragmentDishListBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
override fun initialize() {
|
||||
activity = requireActivity() as SelectDishActivity
|
||||
dinnerType = arguments?.getString(DINNER_TYPE, "0") ?: "0"
|
||||
binding.rvDishList.run {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.inbound.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Environment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.activity.ComponentActivity
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
/**
|
||||
* 防抖工具
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.sw.inbound.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import com.sw.inbound.MyApp
|
||||
import timber.log.Timber
|
||||
import android.util.Log
|
||||
import com.shuwei.dish.match.base.BaseApp
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
@@ -21,11 +21,11 @@ object LogSaveUtil {
|
||||
try {
|
||||
saveLog(pattern, msg)
|
||||
} catch (e: Exception) {
|
||||
Timber.tag(TAG).e(e, "Error saving crash info to file")
|
||||
Log.d(TAG, "Error saving crash info to file:${e.message}")
|
||||
try {
|
||||
saveLog(pattern, "Error saving crash info to file:${e.message}")
|
||||
} catch (e: Exception) {
|
||||
Timber.tag(TAG).e(e, "save exception")
|
||||
Log.d(TAG, "save exception:${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,18 +41,18 @@ object LogSaveUtil {
|
||||
val saveTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
|
||||
FileOutputStream(crashFile, true).use { it.write("$saveTime||$logInfo\n".toByteArray()) }
|
||||
|
||||
Timber.tag(TAG).d("Crash info saved to: ${crashFile.absolutePath}")
|
||||
Log.d(TAG,"Crash info saved to: ${crashFile.absolutePath}")
|
||||
}
|
||||
|
||||
fun getCrashDir(): File {
|
||||
//val crashDir = File(context.getExternalFilesDir(null), CRASH_REPORTS_DIR)
|
||||
var crashDir = File(MyApp.instance!!.filesDir, CRASH_REPORTS_DIR)
|
||||
var crashDir = File(BaseApp.instance!!.filesDir, CRASH_REPORTS_DIR)
|
||||
if (!crashDir.exists()) {
|
||||
crashDir.mkdirs()
|
||||
}
|
||||
|
||||
if (!(crashDir.exists())) {
|
||||
crashDir = File(MyApp.instance!!.cacheDir, CRASH_REPORTS_DIR)
|
||||
crashDir = File(BaseApp.instance!!.cacheDir, CRASH_REPORTS_DIR)
|
||||
}
|
||||
return crashDir
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sw.dualscreen.utils
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
@@ -6,7 +6,6 @@ import androidx.camera.core.ImageCapture
|
||||
import androidx.camera.core.ImageCaptureException
|
||||
import androidx.camera.view.CameraController
|
||||
import androidx.core.content.ContextCompat
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -43,7 +42,7 @@ class PhotoCaptureHelper(
|
||||
fileNamePrefix: String = "IMG_",
|
||||
fileExtension: String = ".jpg"
|
||||
) {
|
||||
Timber.d("开始拍照采集")
|
||||
// Timber.d("开始拍照采集")
|
||||
|
||||
try {
|
||||
val executor = ContextCompat.getMainExecutor(context)
|
||||
@@ -62,7 +61,7 @@ class PhotoCaptureHelper(
|
||||
object : ImageCapture.OnImageSavedCallback {
|
||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||
val photoUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile)
|
||||
Timber.d("照片保存成功: $photoUri")
|
||||
// Timber.d("照片保存成功: $photoUri")
|
||||
onSuccess(photoUri)
|
||||
callbackList.forEach {
|
||||
it(photoUri)
|
||||
@@ -78,14 +77,14 @@ class PhotoCaptureHelper(
|
||||
}
|
||||
|
||||
}
|
||||
Timber.e(exception, errorMsg)
|
||||
// Timber.e(exception, errorMsg)
|
||||
onError(errorMsg)
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
val errorMsg = "创建临时文件失败: ${e.message}"
|
||||
Timber.e(e, errorMsg)
|
||||
// Timber.e(e, errorMsg)
|
||||
onError(errorMsg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.shuwei.dish.match.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -11,7 +13,20 @@ import com.shuwei.dish.match.R
|
||||
|
||||
object ToastUtil {
|
||||
|
||||
fun show(context: Context, message: String, duration:Int = Toast.LENGTH_SHORT) {
|
||||
private val mainHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
fun show(context: Context, message: String, duration: Int = Toast.LENGTH_SHORT) {
|
||||
// 确保在主线程中执行
|
||||
if (Thread.currentThread() == Looper.getMainLooper().thread) {
|
||||
showToast(context, message, duration)
|
||||
} else {
|
||||
mainHandler.post {
|
||||
showToast(context, message, duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showToast(context: Context, message: String, duration: Int) {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val layout: View = inflater.inflate(R.layout.custom_toast, null)
|
||||
val textView = layout.findViewById<TextView>(R.id.tvMessage)
|
||||
@@ -22,7 +37,6 @@ object ToastUtil {
|
||||
toast.setGravity(Gravity.CENTER, 0, 0) // 调整位置居中显示
|
||||
toast.setDuration(duration)
|
||||
toast.show()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,6 +82,10 @@ object WeightUtil {
|
||||
}
|
||||
}
|
||||
|
||||
fun removeWeightListener(weightKey: String){
|
||||
weightFuncMap?.remove(weightKey)
|
||||
}
|
||||
|
||||
fun addWeightListener(
|
||||
weightKey: String,
|
||||
getWeight: WeightCallback = { _, _, _ -> }
|
||||
|
||||
@@ -11,11 +11,13 @@ import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.shuwei.dish.match.utils.GlideUtils
|
||||
import com.shuwei.dish.match.utils.ToastUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -181,3 +183,6 @@ fun Double.roundedDecimalPlace(num: Int): Double {
|
||||
fun Double.roundedOneDecimalPlace(): Double {
|
||||
return this.roundedDecimalPlace(1)
|
||||
}
|
||||
fun ImageView.load(url: Any?) {
|
||||
GlideUtils.loadImage(context, url, this)
|
||||
}
|
||||
@@ -62,7 +62,7 @@
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:text="@string/dish_composition"
|
||||
android:text="@string/dish_list"
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
<?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:background="@drawable/bg_other_page"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:background="@drawable/shape_white_30_corners"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="106dp"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:background="@drawable/bg_bottom_line">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:text="菜品模式设置"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSetting"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:text="配置终端默认模式"
|
||||
android:textColor="@color/gray_b4"
|
||||
android:textSize="28sp" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/modeRadioGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbModeCook"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:button="@null"
|
||||
android:drawableEnd="@drawable/mode_select"
|
||||
android:background="@drawable/bg_bottom_line"
|
||||
android:textSize="36sp"
|
||||
tools:text="制作模式" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbModeSampling"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:button="@null"
|
||||
android:drawableEnd="@drawable/mode_select"
|
||||
android:background="@drawable/bg_bottom_line"
|
||||
android:textSize="36sp"
|
||||
tools:text="采样模式" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rbModeQuality"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:button="@null"
|
||||
android:drawableEnd="@drawable/ic_dish_disable"
|
||||
android:enabled="false"
|
||||
android:textColor="@color/gray_b4"
|
||||
android:textSize="36sp"
|
||||
tools:text="品控模式" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:background="@drawable/shape_white_30_corners"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/seasoning_setting"
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="@string/seasoning_setting2"
|
||||
android:textColor="@color/gray_b4"
|
||||
android:textSize="28sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/include"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
layout="@layout/layout_grid"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -22,7 +22,7 @@
|
||||
<string name="food_remind_02">是否按当前食材制作或调整食材后再制作</string>
|
||||
<string name="seasoning">调料</string>
|
||||
<string name="seasoning_setting">调料设置</string>
|
||||
<string name="seasoning_setting2">点击分格配置分配调料</string>
|
||||
<string name="seasoning_setting2">点击分格配置调料</string>
|
||||
<string name="input_seasoning_name">输入调料名称</string>
|
||||
<string name="rb_sampling_cooking">烹饪中</string>
|
||||
<string name="rb_sampling_finished">已采样</string>
|
||||
|
||||
+37
-3
@@ -1,5 +1,39 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
//plugins {
|
||||
// alias(libs.plugins.android.application) apply false
|
||||
// alias(libs.plugins.kotlin.android) apply false
|
||||
//}
|
||||
|
||||
buildscript {
|
||||
dependencies {
|
||||
classpath(libs.gradle)
|
||||
classpath(libs.kotlin.gradle.plugin)
|
||||
classpath(libs.com.google.devtools.ksp.gradle.plugin)
|
||||
classpath(libs.objectbox.gradle.plugin)
|
||||
}
|
||||
repositories {
|
||||
maven { url = uri("https://maven.aliyun.com/repository/public/") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/central") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/google") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/jcenter") }
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url = uri("https://maven.aliyun.com/repository/public/") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/central") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/google") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/jcenter") }
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.wrapper {
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
@@ -1,28 +1,81 @@
|
||||
[versions]
|
||||
activityKtx = "1.9.0"
|
||||
agp = "8.11.1"
|
||||
baserecyclerviewadapterhelper4 = "4.1.7"
|
||||
baserecyclerviewadapterhelper4Version = "4.1.2"
|
||||
comGoogleDevtoolsKspGradlePlugin = "2.0.21-1.0.27"
|
||||
converterGson = "2.9.0"
|
||||
glide = "4.12.0"
|
||||
compiler = "4.12.0"
|
||||
gradle = "8.10.1"
|
||||
gson = "2.10.1"
|
||||
kotlin = "2.0.21"
|
||||
coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
appcompat = "1.6.1"
|
||||
kotlinGradlePlugin = "2.0.21"
|
||||
lifecycleRuntimeKtx = "2.8.7"
|
||||
lifecycleViewmodelKtx = "2.8.7"
|
||||
loggingInterceptor = "4.9.1"
|
||||
material = "1.10.0"
|
||||
gridlayout = "1.1.0"
|
||||
core = "3.4.1"
|
||||
androidCore = "3.3.0"
|
||||
objectboxVersion = "5.3.0"
|
||||
pytorch="1.13.0"
|
||||
cameraCore = "1.4.1"
|
||||
refreshLayoutKernel = "3.0.0-alpha"
|
||||
refreshHeaderClassics = "3.0.0-alpha"
|
||||
refreshHeaderRadar = "3.0.0-alpha"
|
||||
roomRuntime = "2.5.2"
|
||||
|
||||
[libraries]
|
||||
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
|
||||
androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" }
|
||||
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
|
||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
|
||||
baserecyclerviewadapterhelper4 = { module = "io.github.cymchad:BaseRecyclerViewAdapterHelper4", version.ref = "baserecyclerviewadapterhelper4Version" }
|
||||
com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "comGoogleDevtoolsKspGradlePlugin" }
|
||||
compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "compiler" }
|
||||
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
|
||||
core = { module = "com.google.zxing:core", version.ref = "core" }
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||
gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinGradlePlugin" }
|
||||
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" }
|
||||
|
||||
objectbox-gradle-plugin = { module = "io.objectbox:objectbox-gradle-plugin", version.ref = "objectboxVersion" }
|
||||
objectbox-android-objectbrowser = { module = "io.objectbox:objectbox-android-objectbrowser", version.ref = "objectboxVersion" }
|
||||
objectbox-android = { module = "io.objectbox:objectbox-android", version.ref = "objectboxVersion" }
|
||||
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "loggingInterceptor" }
|
||||
#noinspection Aligned16KB
|
||||
pytorch-android={ group = "org.pytorch", name = "pytorch_android", version.ref = "pytorch" }
|
||||
pytorch-android-torchvision={ group = "org.pytorch", name = "pytorch_android_torchvision", version.ref = "pytorch" }
|
||||
|
||||
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCore" }
|
||||
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraCore" }
|
||||
androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "cameraCore" }
|
||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraCore" }
|
||||
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraCore" }
|
||||
refresh-footer-classics = { module = "io.github.scwang90:refresh-footer-classics", version.ref = "refreshLayoutKernel" }
|
||||
refresh-header-radar = { module = "io.github.scwang90:refresh-header-radar", version.ref = "refreshHeaderRadar" }
|
||||
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 = "converterGson" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
#Thu Jul 17 15:32:57 CST 2025
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
#distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionUrl=https\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.11.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+23
-23
@@ -1,26 +1,26 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://maven.aliyun.com/repository/public") }
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
}
|
||||
//pluginManagement {
|
||||
// repositories {
|
||||
// google {
|
||||
// content {
|
||||
// includeGroupByRegex("com\\.android.*")
|
||||
// includeGroupByRegex("com\\.google.*")
|
||||
// includeGroupByRegex("androidx.*")
|
||||
// }
|
||||
// }
|
||||
// mavenCentral()
|
||||
// gradlePluginPortal()
|
||||
// maven { url = uri("https://jitpack.io") }
|
||||
// }
|
||||
//}
|
||||
//dependencyResolutionManagement {
|
||||
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
// repositories {
|
||||
// google()
|
||||
// mavenCentral()
|
||||
// maven { url = uri("https://maven.aliyun.com/repository/public") }
|
||||
// maven { url = uri("https://jitpack.io") }
|
||||
// }
|
||||
//}
|
||||
|
||||
rootProject.name = "DishMatch"
|
||||
include(":app")
|
||||
|
||||
Reference in New Issue
Block a user