diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c892dee..7573d88 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,5 @@ +import com.android.tools.r8.internal.fA + plugins { // alias(libs.plugins.android.application) // alias(libs.plugins.kotlin.android) @@ -11,7 +13,6 @@ plugins { kotlin("kapt") alias(libs.plugins.kotlin.compose) } - android { signingConfigs { getByName("debug") { @@ -42,7 +43,11 @@ android { } buildTypes { + //debug { + // buildConfigField( "boolean", "DEBUG", "true") + //} release { + //buildConfigField( "boolean", "DEBUG", "false") isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), @@ -60,6 +65,7 @@ android { buildFeatures { compose = true viewBinding = true + buildConfig = true } // composeOptions { // kotlinCompilerExtensionVersion = "1.5.4" @@ -70,7 +76,9 @@ android { } } } - +val isDebug = gradle.startParameter.taskNames.any { + it.contains("debug", ignoreCase = true) +} dependencies { implementation(libs.androidx.core.ktx) @@ -140,8 +148,11 @@ dependencies { implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha") implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha") val objectboxVersion = "5.0.1" - debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion") -// releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion") + if (isDebug) { + debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion") + } else { + releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion") + } } apply(plugin = "io.objectbox") \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt index 8d23025..9dd0dee 100644 --- a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt @@ -22,6 +22,7 @@ import com.sw.inbound.model.response.SearchGoodsInfo import com.sw.inbound.objbox.Food import com.sw.inbound.objbox.FoodCollectionBean import com.sw.inbound.objbox.FoodModule +import com.sw.inbound.objbox.Food_ import com.sw.inbound.objbox.ObjectBox import com.sw.inbound.utils.BitmapCropper import com.sw.inbound.utils.BitmapSaver @@ -30,8 +31,10 @@ import com.sw.inbound.utils.ImageUtil import com.sw.inbound.utils.ext.addOnActionSearchListener import com.sw.inbound.utils.ext.clickWithDebounce import com.sw.inbound.utils.ext.dp +import com.sw.inbound.utils.ext.gone import com.sw.inbound.utils.ext.hideKeyboard import com.sw.inbound.utils.ext.toast +import com.sw.inbound.utils.ext.visible import com.sw.inbound.viewmodel.ReceiptViewModel import dagger.hilt.android.AndroidEntryPoint import io.objectbox.Box @@ -39,11 +42,11 @@ import io.objectbox.kotlin.boxFor import kotlinx.coroutines.runBlocking import timber.log.Timber +@SuppressLint("NotifyDataSetChanged") @AndroidEntryPoint class FoodCollectionActivity : ComponentActivity() { private val TAG = "FoodCollectionActivity" - private var selectedFoodName: String = "" private var box: Box? = null private val collectList: MutableList = mutableListOf( @@ -97,11 +100,13 @@ class FoodCollectionActivity : ComponentActivity() { cameraUtils.unbind() } + @SuppressLint("NotifyDataSetChanged") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityFoodCollectionBinding.inflate(layoutInflater) setContentView(binding.root) cameraUtils.initCamera() + binding.root.hideKeyboard() val previewBinding = LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview) previewView = previewBinding.previewView.also { @@ -149,15 +154,13 @@ class FoodCollectionActivity : ComponentActivity() { }.start() } binding.btnRemoveDefault.clickWithDebounce { - if (box == null) { - box = ObjectBox.boxStore.boxFor(Food::class) - } + initBox() val list = box?.all?.filter { it.foodIdx == FoodModule.DEFAULT_FOOD_INDEX } if (list.isNullOrEmpty()) { toast("不存在默认数据") return@clickWithDebounce } - box?.removeByIds(list!!.map { it.id }) + box?.removeByIds(list.map { it.id }) toast("移除完成") } binding.btnClearData.setOnClickListener { clearData() } @@ -176,7 +179,45 @@ class FoodCollectionActivity : ComponentActivity() { searchGoods() } } - loadEmptyView() + binding.radioGroup.setOnCheckedChangeListener { group, checkedId -> + if (checkedId == R.id.rbCollected) { + binding.llSearchInput.gone() + binding.refreshLayout.let { + it.setEnableRefresh(false) + it.setEnableLoadMore(false) + } + getCollectedGoods() + return@setOnCheckedChangeListener + } + if (checkedId == R.id.rbSearch) { + binding.llSearchInput.visible() + pageNo = 1 + clickIndex = -1 + searchGoodsList.clear() + searchAdapter.notifyDataSetChanged() + binding.refreshLayout.let { + it.setEnableRefresh(true) + it.setEnableLoadMore(false) + } + loadEmptyView() + return@setOnCheckedChangeListener + } + } + binding.radioGroup.check(R.id.rbCollected) + } + + @SuppressLint("NotifyDataSetChanged") + private fun getCollectedGoods() { + searchGoodsList.clear() + initBox() + box?.all?.distinctBy { it.name }?.forEach { + searchGoodsList.add((SearchGoodsInfo.Record(goodsName = it.name))) + } + binding.rvSearch.layoutManager = GridLayoutManager(this, 2, LinearLayoutManager.VERTICAL, false) + searchAdapter.notifyDataSetChanged() + if (searchGoodsList.isEmpty()) { + loadEmptyView() + } } private var pageNo = 1 @@ -284,9 +325,7 @@ class FoodCollectionActivity : ComponentActivity() { } private fun image2VectorTask(bitmap: Bitmap, position: Int) { - if (box == null) { - box = ObjectBox.boxStore.boxFor(Food::class) - } + initBox() val imageVector = FoodModule.bitmap2FloatArray(bitmap) box?.put(Food(name = searchGoodsList[clickIndex].goodsName, foodIdx = 0, foodVector = imageVector)) collectList[position].let { @@ -361,4 +400,10 @@ class FoodCollectionActivity : ComponentActivity() { } } + private fun initBox() { + if (box == null) { + box = ObjectBox.boxStore.boxFor(Food::class) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt index 235efbf..cd14a2f 100644 --- a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt @@ -321,6 +321,9 @@ abstract class GoodsListActivity : ComponentActivity() { goodsWeight = goods.goodsWeight } binding.rvGoodsList.adapter?.notifyItemChanged(goodsList.indexOf(item)) + if (this is ReceiptActivity) { + this.setConfirmNum() + } } fun searchGoods( diff --git a/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt b/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt index 83c7320..d79b083 100644 --- a/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt @@ -55,12 +55,7 @@ class ReceiptActivity : GoodsListActivity() { } goodsList.addAll(list) adapter.notifyDataSetChanged() - val confirmOrderCount = list.count { it.isAdjusted } - binding.tvConfirmNum.text = - getSpannable("已确认 ", num = confirmOrderCount, color = "#FF009632") - val notConfirmOrderCount = goodsList.size - confirmOrderCount - binding.tvNotConfirmNum.text = - getSpannable("未确认 ", num = notConfirmOrderCount, color = "#FFFF0000") + setConfirmNum() } } } else { @@ -91,4 +86,13 @@ class ReceiptActivity : GoodsListActivity() { } } + fun setConfirmNum() { + val confirmOrderCount = goodsList.count { it.isAdjusted } + binding.tvConfirmNum.text = + getSpannable("已确认 ", num = confirmOrderCount, color = "#FF009632") + val notConfirmOrderCount = goodsList.size - confirmOrderCount + binding.tvNotConfirmNum.text = + getSpannable("未确认 ", num = notConfirmOrderCount, color = "#FFFF0000") + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt index 53b2c1a..cc9a389 100644 --- a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt +++ b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt @@ -18,6 +18,7 @@ class RequestInterceptor : Interceptor { .header("Accept", "application/json") .header("deviceId", GlobalData.deviceId) .header("X-DEVICE-CODE", GlobalData.deviceId) +// .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41") .header("x-access-token", GlobalData.appToken) .header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d") // .header("Authorization", "Bearer ${getToken()}") diff --git a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt index 489da9f..fb97f4f 100644 --- a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt +++ b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt @@ -102,9 +102,10 @@ object FoodModule { fun initDefFoodData(context: Context, action:()-> Unit={}) { - //if (box.all.isNotEmpty()) { - // return - //} + val count = box.all.count { it.foodIdx == DEFAULT_FOOD_INDEX } + if (count > 0) { + return + } val embeddingsJson = AssetsTool.readAssetsFile(context, "data/embeddings.json") val labelsJson = AssetsTool.readAssetsFile(context, "data/labels.json") val classInfoJson = AssetsTool.readAssetsFile(context, "data/class_info.json") diff --git a/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt b/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt index 89026b4..25e9f94 100644 --- a/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt +++ b/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt @@ -20,7 +20,6 @@ import android.content.Context import android.util.Log import io.objectbox.BoxStore import io.objectbox.BoxStoreBuilder -import io.objectbox.android.Admin import io.objectbox.exception.DbException import io.objectbox.exception.FileCorruptException import io.objectbox.sync.Sync @@ -73,13 +72,13 @@ object ObjectBox { } } -// if (BuildConfig.DEBUG) { + if (com.sw.inbound.BuildConfig.DEBUG) { var syncAvailable = if (Sync.isAvailable()) "available" else "unavailable" Log.d(TAG,"Using ObjectBox ${BoxStore.getVersion()} (${BoxStore.getVersionNative()}, sync $syncAvailable)") // Enable ObjectBox Admin on debug builds. // https://docs.objectbox.io/data-browser - Admin(boxStore).start(context.applicationContext) -// } + io.objectbox.android.Admin(boxStore).start(context.applicationContext) + } } diff --git a/app/src/main/java/com/sw/inbound/ui/NavController.kt b/app/src/main/java/com/sw/inbound/ui/NavController.kt index eda88e4..519ea25 100644 --- a/app/src/main/java/com/sw/inbound/ui/NavController.kt +++ b/app/src/main/java/com/sw/inbound/ui/NavController.kt @@ -3,6 +3,8 @@ package com.sw.inbound.ui import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize @@ -16,6 +18,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.paint import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -70,8 +73,8 @@ fun AppScreen( Scaffold( modifier = Modifier .fillMaxSize() - .paint(painter = painterResource(R.mipmap.bg)), - containerColor = Color.Transparent, + //.paint(painter = painterResource(R.mipmap.bg)), + ,containerColor = Color.Transparent, content = { padding -> Box { // Image( @@ -80,9 +83,13 @@ fun AppScreen( // modifier = Modifier.fillMaxSize(), // contentScale = ContentScale.Crop // ) - + Image( + painter = painterResource(id = R.mipmap.bg), + contentDescription = "背景图片", + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.Crop + ) NavHost(padding, navController, onBackRequest) - } } ) diff --git a/app/src/main/res/color/radio_filter.xml b/app/src/main/res/color/radio_filter.xml new file mode 100644 index 0000000..add3e51 --- /dev/null +++ b/app/src/main/res/color/radio_filter.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radio_check.xml b/app/src/main/res/drawable/radio_check.xml new file mode 100644 index 0000000..b93c6ef --- /dev/null +++ b/app/src/main/res/drawable/radio_check.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_food_collection.xml b/app/src/main/res/layout/activity_food_collection.xml index 8ec622c..f1a2dfb 100644 --- a/app/src/main/res/layout/activity_food_collection.xml +++ b/app/src/main/res/layout/activity_food_collection.xml @@ -54,23 +54,23 @@ android:id="@+id/btnAddDefault" android:layout_width="wrap_content" android:layout_height="60dp" - android:gravity="center_vertical" - android:text="加载默认数据" - android:paddingHorizontal="10dp" - android:textColor="#FF0032C8" android:background="@drawable/bg_white_stroke_blue_ripple" + android:gravity="center_vertical" + android:paddingHorizontal="10dp" + android:text="加载默认数据" + android:textColor="#FF0032C8" android:textSize="18sp" /> @@ -127,6 +127,70 @@ tools:itemCount="6" tools:listitem="@layout/list_item_food_collection" /> + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/layoutTab" + android:visibility="gone"> + app:layout_constraintTop_toBottomOf="@id/btnTakePhoto" + android:visibility="gone"/> \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/ic_radio_checked.png b/app/src/main/res/mipmap-xxhdpi/ic_radio_checked.png new file mode 100644 index 0000000..b90aa3a Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_radio_checked.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_radio_normal.png b/app/src/main/res/mipmap-xxhdpi/ic_radio_normal.png new file mode 100644 index 0000000..7675ff4 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_radio_normal.png differ