diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8919852..71c9ce5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -65,6 +65,7 @@ dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) + implementation(libs.androidx.gridlayout) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d328061..a756eb4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -76,6 +76,8 @@ android:name=".ui.FoodSearchActivity" android:screenOrientation="portrait" tools:ignore="DiscouragedApi,LockedOrientationActivity" /> + + diff --git a/app/src/main/assets/default_seasoning_list.json b/app/src/main/assets/default_seasoning_list.json index 0cab75f..0b9fc26 100644 --- a/app/src/main/assets/default_seasoning_list.json +++ b/app/src/main/assets/default_seasoning_list.json @@ -183,7 +183,7 @@ "popularName" : "生抽", "canteenId" : "1678234139391512577", "relateionType_dictText" : "食材原材料", - "sort" : 12, + "sort" : 11, "isDel" : 0, "createTime" : "2025-08-18 10:19:08" }, @@ -200,7 +200,7 @@ "popularName" : "菜籽油,爱菊菜籽油", "canteenId" : "1678234139391512577", "relateionType_dictText" : "食材原材料", - "sort" : 14, + "sort" : 10, "isDel" : 0, "createTime" : "2025-08-18 10:19:19" } diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/TextCellAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/TextCellAdapter.kt index 431cc47..943466e 100644 --- a/app/src/main/java/com/shuwei/dish/match/adapter/TextCellAdapter.kt +++ b/app/src/main/java/com/shuwei/dish/match/adapter/TextCellAdapter.kt @@ -71,8 +71,17 @@ class TextCellAdapter(var list: MutableList) : fun loadCell(tvCell: TextView, item: SeasoningEntity) { if (item.goodsName.isNullOrBlank()) { tvCell.run { - text = "未配置" - setTextColor(ContextCompat.getColor(context, R.color.black999)) + text = buildSpannableString { + appendText( + "未配置", + ForegroundColorSpan("#999999".toColorInt()), + StyleSpan(Typeface.BOLD), + AbsoluteSizeSpan(28, true), + LineHeightSpan { text, start, end, spanstartv, v, fm -> + fm.descent += 10.dp // 增加行间距 + } + )} + //setTextColor(ContextCompat.getColor(context, R.color.black999)) } } else { // if (item.pageType == 1) { @@ -87,7 +96,7 @@ class TextCellAdapter(var list: MutableList) : } fun getTextSpan(item: SeasoningEntity): SpannableStringBuilder { - val endIndex = if (item.sort == 14) 10 else 6 + val endIndex = if (item.sort == 10 || item.sort == 14) 10 else 6 var name = item.goodsName!! if (name.length > endIndex) { name = "${name.substring(0, endIndex)}…" @@ -103,7 +112,6 @@ class TextCellAdapter(var list: MutableList) : } ) append("\n") - val weight = item.useWeight ?: 0.toDouble() val weightColor = if (weight == 0.toDouble()) "#999999" else "#00BC71" appendText( diff --git a/app/src/main/java/com/shuwei/dish/match/db/DatabaseRepository.kt b/app/src/main/java/com/shuwei/dish/match/db/DatabaseRepository.kt index b0572ac..7c293d2 100644 --- a/app/src/main/java/com/shuwei/dish/match/db/DatabaseRepository.kt +++ b/app/src/main/java/com/shuwei/dish/match/db/DatabaseRepository.kt @@ -89,8 +89,8 @@ class AppRepository(val appDao: AppDao) { appDao.clearAllSeasoning() } - suspend fun deleteEmptySeasoning() = withContext(Dispatchers.IO) { - appDao.deleteEmptySeasoning() + suspend fun deleteSeasoningBySort(sort: Int) = withContext(Dispatchers.IO) { + appDao.deleteSeasoningBySort(sort) } suspend fun insertSeasoningList(items: MutableList) = diff --git a/app/src/main/java/com/shuwei/dish/match/db/dao/AppDao.kt b/app/src/main/java/com/shuwei/dish/match/db/dao/AppDao.kt index 26c1fa9..72cbc38 100644 --- a/app/src/main/java/com/shuwei/dish/match/db/dao/AppDao.kt +++ b/app/src/main/java/com/shuwei/dish/match/db/dao/AppDao.kt @@ -60,7 +60,7 @@ interface AppDao { suspend fun getSeasoningById(id: Long): SeasoningEntity? @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND sort = :sort") - suspend fun getSeasoningBySort(sort: Int): SeasoningEntity? + suspend fun getSeasoningBySort(sort: Int): MutableList? @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId = :goodsId") suspend fun getSeasoningByGoodsId(goodsId: Int): SeasoningEntity? @@ -71,8 +71,8 @@ interface AppDao { @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsName LIKE '%' || :query || '%'") suspend fun search(query: String): MutableList - @Query("DELETE FROM dm_seasoning WHERE isDel = 0 AND goodsId = -1 AND goodsName = ''") - suspend fun deleteEmptySeasoning(): Int + @Query("DELETE FROM dm_seasoning WHERE isDel = 0 AND sort = :sort") + suspend fun deleteSeasoningBySort(sort:Int): Int @Query("DELETE FROM dm_seasoning WHERE isDel = 0") suspend fun clearAllSeasoning(): Int diff --git a/app/src/main/java/com/shuwei/dish/match/http/UrlConfig.kt b/app/src/main/java/com/shuwei/dish/match/http/UrlConfig.kt index 65c8f0e..fe24123 100644 --- a/app/src/main/java/com/shuwei/dish/match/http/UrlConfig.kt +++ b/app/src/main/java/com/shuwei/dish/match/http/UrlConfig.kt @@ -6,8 +6,8 @@ object UrlConfig { // const val DISH_DETAIL = "$BASE_URL/scales/goodsUseList?foodId={foodId}&foodWeight={foodWeight}" // const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName" -// const val BASE_URL = "http://192.168.1.207:9102" - const val BASE_URL = "https://yyjk.shuziweidao.com/gateway" + const val BASE_URL = "http://192.168.1.207:9102" +// const val BASE_URL = "https://yyjk.shuziweidao.com/gateway" // const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName" const val DISH_DETAIL = "$BASE_URL/food/stFoodInfoMatching/queryById" diff --git a/app/src/main/java/com/shuwei/dish/match/ui/DeviceConfigActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/DeviceConfigActivity.kt new file mode 100644 index 0000000..371cfb1 --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/ui/DeviceConfigActivity.kt @@ -0,0 +1,318 @@ +package com.shuwei.dish.match.ui + +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.widget.TextView +import androidx.core.graphics.toColorInt +import androidx.core.view.forEach +import androidx.lifecycle.ViewModelProvider +import com.shuwei.dish.match.base.BaseActivity +import com.shuwei.dish.match.base.BaseApp +import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding +import com.shuwei.dish.match.db.AppRepository +import com.shuwei.dish.match.dialog.CommonDialog +import com.shuwei.dish.match.entity.SeasoningEntity +import com.shuwei.dish.match.entity.ResetReasoningRecord +import com.shuwei.dish.match.utils.DataUtil +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.startActivity +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.R +import com.shuwei.dish.match.adapter.TextCellAdapter +import com.shuwei.dish.match.databinding.ActivityDeviceConfigBinding +import com.shuwei.dish.match.dialog.BottomDialog2 +import com.shuwei.dish.match.utils.ext.clickWithDebounce + +class DeviceConfigActivity : BaseActivity() { + + companion object { + + const val TAG = "DeviceSettingActivity" + + const val COOK_MODE = "cookMode" + + val modeList = listOf( + ModeBean("制作模式", "菜品快速制作,记录熟重"), + ModeBean("采样模式", "菜品快速制作,记录熟重"), + ModeBean("品控模式", "菜品快速制作,记录熟重") + ) + } + + data class ModeBean( + var modeName: String, + var modeDesc: String + ) + + private lateinit var binding: ActivityDeviceConfigBinding + + private lateinit var appViewModel: AppViewModel + + private var cookMode: Int = 0 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityDeviceConfigBinding.inflate(layoutInflater) + setContentView(binding.root) + cookMode = intent.getIntExtra(COOK_MODE, 0) + initViewModel() + setHeaderBackground() + setTitleBar(titleBarAction = { + it.visible() + }, titleAction = { + it.text = "设备配置" + }, rightIconActon = { + it.visible() + it.alpha = 0.0F + it.setImageResource(R.drawable.ic_setting) + it.setOnClickListener { + detector.setOnDelayedMultiClickListener(it) { + defaultDataSettingDialog() + } + } + }) + + 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 { + binding.rbModeCook.isChecked = true + binding.rbModeSampling.isChecked = false + loadCookSpan(isClicked = true) + loadSamplingSpan() + startActivity { } + finish() + } + binding.rbModeSampling.setOnClickListener { + binding.rbModeCook.isChecked = false + binding.rbModeSampling.isChecked = true + loadCookSpan() + loadSamplingSpan(isClicked = true) + startActivity { } + finish() + } + addGridItemListener() + loadSeasoning() + } + + private var seasoningItems = mutableListOf() + private fun addGridItemListener() { + binding.include.root.forEach { child-> + (child as TextView).run { + clickWithDebounce { + val sort = tag.toString().toInt() + val entity = seasoningItems.firstOrNull { it.sort == sort } ?: SeasoningEntity() + clickGridItem(sort, entity) + } + } + } + } + + val detector = MultiClickDetector(targetCount = 10, intervalMs = 800) + + private fun defaultDataSettingDialog() { + val remindBinding = LayoutFoodRemindBinding.inflate(layoutInflater) + remindBinding.tvDialogTitle.text = "温馨提示" + remindBinding.tvDialogContent.text = + "您好,使用默认配置作为您的调料数据,则已有配置将被清除,确认吗?" + CommonDialog(this).apply { + messageView = remindBinding.root + leftText = "取消" + rightText = "确认" + onLeftClick = { dismiss() } + onRightClick = { + dismiss() + resetList() + } + onDismiss = { hideStatusBar() } + }.show() + } + + private fun resetList() { + runCatching { + val record = JsonAssetsLoader.parseJsonFromAssets( + this, + "default_seasoning_list.json" + ) + val addressArray = DataUtil.getWeighAddressArray() + val weightArray = WeightUtil.weightArray + appViewModel.clearAllSeasoning { + record?.list?.forEach { entity -> + entity.useWeight = weightArray[addressArray[entity.sort]].toDouble() + appViewModel.saveSeasoning(entity) {} + } + loadSeasoning() + } + }.onFailure { it.printStackTrace() } + } + + private fun initViewModel() { + val db = BaseApp.instance!!.database + val factory = + AppFactory(AppRepository(db.appDao())) + appViewModel = + ViewModelProvider(this, factory)[AppViewModel::class.java] + } + + private fun loadSeasoning() { + appViewModel.loadSeasoning { + seasoningItems.clear() + seasoningItems.addAll(it) + initConfigData() + setGridData(seasoningItems) + } + } + + 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) { + val gridLayout = binding.include.root + list.forEach { entity -> + val tag = entity.sort.toString() + val child = gridLayout.findViewWithTag(tag) + TextCellAdapter.loadCell(child, entity) + } + } + + private fun clickGridItem(sort: Int, entity: SeasoningEntity) { + val currentAddress = DataUtil.getWeighAddressArray().get(sort) +// val seasoningEntity = list.first{it.sort == sort} + BottomDialog2( + weighIndex = sort, + weighAddress = currentAddress, + clickName = entity.goodsName + ).show(this) { item -> + syncItem(entity, item) + //3-调料 + entity.materialType = 3 + entity.sort = sort + saveSeasoning(entity) { + val child = binding.include.root.findViewWithTag(sort.toString()) + TextCellAdapter.loadCell(child, 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 + } + } + + 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) + ) + } + } + + fun saveSeasoning(entity: SeasoningEntity, action: () -> Unit = {}) { + appViewModel.saveSeasoning(entity) { + action() + toast("保存成功") + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/shuwei/dish/match/ui/DishSamplingActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/DishSamplingActivity.kt index d847b1f..9ab38ce 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/DishSamplingActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/DishSamplingActivity.kt @@ -236,7 +236,8 @@ class DishSamplingActivity : BaseActivity() { food.foodName = showFoodName food.cookMode = 1 Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}") - startActivity { +// startActivity { + startActivity { putExtra(SubmitDishActivity.GOODS_LIST, list as java.io.Serializable) putExtra(SubmitDishActivity.FOOD_ITEM, food as Serializable) } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/HomeActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/HomeActivity.kt index 81d1a8d..780910d 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/HomeActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/HomeActivity.kt @@ -60,7 +60,10 @@ class HomeActivity : BaseActivity() { // startActivity() // } -// appViewModel.deleteEmptySeasoning() +// appViewModel.deleteSeasoningBySort(12) +// appViewModel.deleteSeasoningBySort(11) +// appViewModel.deleteSeasoningBySort(13) +// appViewModel.deleteSeasoningBySort(14) // appViewModel.deleteCookFoodAndGoods(0,"") {} // appViewModel.getCookFoodGoodsList("") {goodsList-> // goodsList.forEach { @@ -68,8 +71,12 @@ class HomeActivity : BaseActivity() { // appViewModel.updateGoods(it) // } // } -// appViewModel.clearAllSeasoning() +// appViewModel.clearAllSeasoning(){} + + binding.btnDeviceConfig.setOnClickListener { + startActivity{} + } } private fun initRecyclerView() { diff --git a/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt index b759f40..8b1e6c1 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt @@ -148,7 +148,8 @@ class PrepareCookActivity : BaseActivity() { return } Log.d(TAG, "goToSubmit: goodsList:${goodsList?.toJsonString()}") - startActivity { +// startActivity { + startActivity { putExtra(SubmitDishActivity.GOODS_LIST, goodsList as Serializable) putExtra(SubmitDishActivity.FOOD_ITEM, food as Serializable) } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SamplingListActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SamplingListActivity.kt index e931472..5559171 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/SamplingListActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/SamplingListActivity.kt @@ -64,8 +64,11 @@ class SamplingListActivity : BaseActivity() { it.visible() it.setImageResource(R.drawable.ic_setting) it.setOnClickListener { - startActivity { - putExtra(DeviceSettingActivity.COOK_MODE, 2) +// startActivity { +// putExtra(DeviceSettingActivity.COOK_MODE, 2) +// } + startActivity { + putExtra(DeviceConfigActivity.COOK_MODE, 2) } } }, backAction = { @@ -116,7 +119,8 @@ class SamplingListActivity : BaseActivity() { val item = list[position] if (item.isCooking) { //烹饪中,跳到称熟重页面 - context.startActivity { +// context.startActivity { + context.startActivity { putExtra( SubmitDishActivity.FOOD_ITEM, item as Serializable diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SelectDishActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SelectDishActivity.kt index af58bc2..eb21b7e 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/SelectDishActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/SelectDishActivity.kt @@ -54,8 +54,11 @@ class SelectDishActivity : BaseActivity() { it.visible() it.setImageResource(R.drawable.ic_setting) it.setOnClickListener { - startActivity { - putExtra(DeviceSettingActivity.COOK_MODE, 1) +// startActivity { +// putExtra(DeviceSettingActivity.COOK_MODE, 1) +// } + startActivity { + putExtra(DeviceConfigActivity.COOK_MODE, 1) } } }, backAction = { diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt new file mode 100644 index 0000000..c77b241 --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt @@ -0,0 +1,440 @@ +package com.shuwei.dish.match.ui + +import android.annotation.SuppressLint +import android.os.Bundle +import android.util.Log +import android.util.SparseArray +import android.util.SparseIntArray +import android.widget.TextView +import androidx.core.util.forEach +import androidx.lifecycle.ViewModelProvider +import com.aithings.Weigher +import com.google.gson.reflect.TypeToken +import com.shuwei.dish.match.R +import com.shuwei.dish.match.adapter.SeasoningCellTool +import com.shuwei.dish.match.adapter.TextCellAdapter +import com.shuwei.dish.match.base.BaseActivity +import com.shuwei.dish.match.base.BaseApp +import com.shuwei.dish.match.databinding.ActivitySubmitDishBinding +import com.shuwei.dish.match.databinding.ActivitySubmitFoodBinding +import com.shuwei.dish.match.db.AppRepository + +import com.shuwei.dish.match.entity.CookFoodEntity +import com.shuwei.dish.match.entity.CookFoodGoodsEntity +import com.shuwei.dish.match.entity.FoodRecord +import com.shuwei.dish.match.entity.SeasoningEntity +import com.shuwei.dish.match.http.HttpUtil +import com.shuwei.dish.match.http.UrlConfig +import com.shuwei.dish.match.utils.DataUtil +import com.shuwei.dish.match.utils.WeightUtil +import com.shuwei.dish.match.utils.ext.clickWithDebounce +import com.shuwei.dish.match.utils.ext.gone +import com.shuwei.dish.match.utils.ext.startActivity +import com.shuwei.dish.match.utils.ext.toJsonString +import com.shuwei.dish.match.utils.ext.toType +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 + +@SuppressLint("UseSparseArrays") +class SubmitFoodActivity : BaseActivity() { + + companion object { + const val TAG = "SubmitDishActivity" + const val FOOD_ITEM = "foodItem" + const val GOODS_LIST = "goodsList" + } + + private lateinit var binding: ActivitySubmitFoodBinding + + private var food: FoodRecord? = null + private var goodsList: MutableList? = null + + private var isCooking = false + + private val cookFoodEntity by lazy { + CookFoodEntity().apply { + food?.let { + foodId = it.foodId ?: "" + foodName = it.foodName + cookMode = it.cookMode + dinnerType = it.dinnerType + } + canteenId = BaseApp.canteenId + } + } + + @Suppress("unchecked_cast", "DEPRECATION") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivitySubmitFoodBinding.inflate(layoutInflater) + setContentView(binding.root) + initViewModel() + setHeaderBackground() + intent.extras?.apply { + food = getSerializable(FOOD_ITEM) as FoodRecord? + Log.d(TAG, "onCreate: cookMode=${food?.cookMode}") + isCooking = food?.isCooking ?: false + if (isCooking) { + //烹饪中,从本地查询数据 + loadSeasoningFromLocal() + } else { + //非烹饪中,从菜品主辅材配置页面带入数据 + goodsList = getSerializable(GOODS_LIST) as MutableList? + } + } + setTitleBar(titleBarAction = { + it.visible() + }, titleAction = { + it.text = food?.foodName + }, rightIconActon = { + it.gone() + it.setImageResource(R.drawable.ic_setting) + it.setOnClickListener { + //startActivity() + } + }) + addViewListener() + } + + private fun loadSeasoningFromLocal() { + appViewModel.getCookFoodGoodsList(foodId = food!!.foodId!!, cookMode = food!!.cookMode) { it -> + goodsList = mutableListOf() + //设置主辅材数据 + goodsList?.addAll(it.filter { goods -> goods.materialType != 3 }) + + //获取调料数据并展示 + val filterList: List? = it.filter { goods -> goods.materialType == 3 } + .map { entity -> + SeasoningEntity().also { se -> + se.goodsId = entity.goodsId + se.goodsName = entity.goodsName + se.goodsOrRelationCode = entity.goodsOrRelationCode + se.relateionType = entity.relateionType + se.materialType = entity.materialType + se.allEdible = entity.allEdible + se.useWeight = entity.useWeight + se.popularName = entity.popularName + se.canteenId = entity.canteenId + se.relateionType_dictText = entity.relateionType_dictText + se.foodId = entity.foodId + se.sort = entity.sort + se.pageType = 0 + } + } + filterList?.toMutableList()?.let { cellData -> + loadTextCell(cellData) + } + } + } + + +// private lateinit var seasoningList: List +// private var isFirstSave = true +// fun updateSeasoningList(list: MutableList) { +// if (isFirstSave) { +// val json = list.toJsonString() +// val typeToken = object : TypeToken>() {} +// seasoningList = json.toType(typeToken = typeToken) +// isFirstSave = false +// } +// } + + private val seasoningArray by lazy { + SparseArray() + } + + + private val firstGoodsArray by lazy { + SparseArray() + } + + private fun addViewListener() { + addWeightListener() + binding.btnWeightClear.setOnClickListener { Weigher.tareTwo(1) } + + binding.btnCook.clickWithDebounce { + cook() + } + + binding.btnSubmit.clickWithDebounce { + if (cookFoodEntity.foodWeight <= 0.toDouble()) { + toast("未识别到菜品熟重") + return@clickWithDebounce + } + submit() + } + } + + private fun addWeightListener() { + WeightUtil.addWeightListener(getWeight = { address, state, weight -> + if (address == 1) { + cookFoodEntity.foodWeight = weight.toDouble() + binding.tvTotalWeight.text = "${weight / 1000f}" + } + val firstWeight = firstGoodsArray.get(address, null) + if (firstWeight == null) { + //未设置数据 + firstGoodsArray.put(address, weight) + return@addWeightListener + } + var realUseWeight = firstWeight - weight + realUseWeight = if (realUseWeight > 0) realUseWeight else 0 + seasoningArray.put(address, realUseWeight.toDouble()) + + refreshSeasoningWeight() + }) + } + + @SuppressLint("NotifyDataSetChanged") + private fun refreshSeasoningWeight() { + if (seasoningItems.isEmpty()) { + return + } + seasoningItems.let { items -> + weightRelateArray.forEach { key, value -> + items[key].useWeight = + (seasoningArray.get(value) ?: 0.toDouble()) + getCookingSeasoning(value) + } + } + setGridData(seasoningItems) +// binding.rvSeasoning.adapter?.let { adapter -> +// if (adapter is TextCellAdapter) { +// adapter.list.let { items -> +// weightRelateArray.forEach { key, value -> +// items[key].useWeight = +// (seasoningArray.get(value) ?: 0.toDouble()) + getCookingSeasoning(value) +// } +// } +// adapter.notifyDataSetChanged() +// } +// } + } + + private fun getCookingSeasoning(address: Int): Double { + if (isCooking.not()) return 0.toDouble() + if (seasoningItems.isEmpty()) return 0.toDouble() + val weight = seasoningItems[weightRelateArray2.get(address)].useWeight ?: 0.toDouble() + //Log.i(TAG, "getCookingSeasoning: weight[${address}]=$weight,seasoningList=${seasoningList.toJsonString()}") + return weight + } + + private val weightRelateArray2 by lazy { + SparseIntArray().apply { + weightRelateArray.forEach { key, value -> + put(value, key) +// if (value == 3) { +// put(3, 14) +// } else { +// put(value, key) +// } + } + } + } + + private val weightRelateArray by lazy { + DataUtil.getWeighAddressArray() + } + +// private fun prepareData(acton: () -> Unit) { +// +// //只有制作和采样列表页面才能进入设置页面,提交页面无法进行设置,不存在调料数据被修改的问题 +// val seasoningJson = realSeasoningData.toJsonString() +// val typeToken = object : TypeToken>() {} +// val tempSeasoningList = seasoningJson.toType(typeToken = typeToken) +// goodsList?.addAll(tempSeasoningList) +// acton() +// +// } + + private fun cook() { + if (food == null || goodsList.isNullOrEmpty()) { + toast("未获取到菜品或构成信息") + return + } + val realSeasoningData = seasoningItems + //(binding.rvSeasoning.adapter as TextCellAdapter).list + if (realSeasoningData.isEmpty() && !isCooking) { + toast("未获取到调料信息") + return + } + if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isNullOrBlank()) { + toast("还未设置调料信息,请去设置页面操作") + return + } + showLoading() + //只有制作和采样列表页面才能进入设置页面,提交页面无法进行设置,不存在调料数据被修改的问题 + val seasoningJson = realSeasoningData.toJsonString() + val typeToken = object : TypeToken>() {} + val tempSeasoningList = seasoningJson.toType(typeToken = typeToken) + goodsList?.addAll(tempSeasoningList) + cookFoodEntity.let { + it.dinnerType = when (it.dinnerType) { + "早餐" -> "1" + "午餐" -> "2" + "晚餐" -> "3" + else -> it.dinnerType + } + } + val isSamplingData = food!!.cookMode == 1 + if (isSamplingData) { + //生成临时foodId,解决采样模式没有foodId,无法关联数据的问题 + val tempFoodId = cookFoodEntity.foodId.ifBlank { "${System.currentTimeMillis()}" } + cookFoodEntity.foodId = tempFoodId + } + //全部设置同一foodId + goodsList?.forEach { + it.foodId = cookFoodEntity.foodId + } + //保存菜品-保存主辅料调料 + appViewModel.saveCookFoodAndGoods( + cookMode = food!!.cookMode, + entity = cookFoodEntity, + list = goodsList, + onFinish = { + runOnUiThread { + dismissLoading() + jumpPage(isSamplingData, true) + } + }) + } + + private fun submit() { + if (food == null || goodsList.isNullOrEmpty()) { + toast("未获取到菜品或构成信息") + return + } + val realSeasoningData = seasoningItems + if (realSeasoningData.isEmpty() && !isCooking) { + toast("未获取到调料信息") + return + } + if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isNullOrBlank()) { + toast("还未设置调料信息,请去设置页面操作") + return + } + showLoading() + //只有制作和采样列表页面才能进入设置页面,提交页面无法进行设置,不存在调料数据被修改的问题 + val seasoningJson = realSeasoningData.toJsonString() + val typeToken = object : TypeToken>() {} + val tempSeasoningList = seasoningJson.toType(typeToken = typeToken) + tempSeasoningList.forEach { entity -> + val realWeight = entity.useWeight ?: 0.toDouble() + val filterData = goodsList?.firstOrNull { it.goodsId == entity.goodsId } + //确保重量大于0,且无重复数据 + if (realWeight > 0.toDouble() && filterData == null) { + goodsList?.add(entity) + } + } + + cookFoodEntity.let { + it.stFoodInfoConstituteList = this@SubmitFoodActivity.goodsList + it.dinnerType = when(it.dinnerType) { + "1" -> "早餐" + "2" -> "午餐" + "3" -> "晚餐" + else -> null + } + } + + val isSamplingData = food!!.cookMode == 1 + if (isSamplingData) { + //采样模式没有foodId + cookFoodEntity.foodId = "" + goodsList?.forEach { it.foodId = "" } + } + val json = cookFoodEntity.toJsonString() + Log.d(TAG, "submit: json=$json") + HttpUtil.postJson( + url = UrlConfig.SUBMIT_DISH, + json = json, + doSuccess = { + Log.d(TAG, "submit: postJson=$it") + submitSuccess(isSamplingData) + }, doFailure = { code, msg -> + Log.d(TAG, "submit: postJson:code=$code,msg=$msg") + toast(msg) + dismissLoading() + }) + } + + private fun submitSuccess(isSamplingData: Boolean) { + if (food?.foodId.isNullOrBlank()) { + //本地无删除数据直接跳转页面 + dismissLoading() + jumpPage(isSamplingData, false) + return + } + //删除本地数据 + appViewModel.deleteCookFoodAndGoods( + cookMode = food!!.cookMode, + foodId = food!!.foodId!! + ) { + dismissLoading() + jumpPage(isSamplingData, false) + } + } + + private fun jumpPage(isSampling: Boolean, isCooking: Boolean) { + if (isSampling) { + startActivity { + putExtra(SelectDishActivity.IS_COOKING, isCooking) + } + return + } + startActivity { + putExtra(SelectDishActivity.IS_COOKING, isCooking) + putExtra(SelectDishActivity.DINNER_TYPE, food?.dinnerType) + } + } + + private lateinit var appViewModel: AppViewModel + + private fun initViewModel() { + val db = BaseApp.instance!!.database + val factory = + AppFactory(AppRepository(db.appDao())) + appViewModel = + ViewModelProvider(this, factory)[AppViewModel::class.java] + } + + override fun onResume() { + super.onResume() + if (isCooking.not()) { + //烹饪中使用本地数据,未烹饪则使用默认的调料配置数据 + appViewModel.loadSeasoning { + Log.d(TAG, "onResume: loadSeasoning:${it.toJsonString()}") + loadTextCell(it) + } + } + } + + private var seasoningItems = mutableListOf() + private fun loadTextCell(list: MutableList) { + seasoningItems.clear() + seasoningItems.addAll(list) + initConfigData() + setGridData(list) + } + + 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) { + val gridLayout = binding.include.root + list.forEach { entity -> + val tag = entity.sort.toString() + val child = gridLayout.findViewWithTag(tag) + TextCellAdapter.loadCell(child, entity) + } + } +} + + diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/DishListFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/DishListFragment.kt index 607e428..cd92db9 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/DishListFragment.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/DishListFragment.kt @@ -21,6 +21,7 @@ import com.shuwei.dish.match.http.UrlConfig import com.shuwei.dish.match.ui.PrepareCookActivity import com.shuwei.dish.match.ui.SelectDishActivity import com.shuwei.dish.match.ui.SubmitDishActivity +import com.shuwei.dish.match.ui.SubmitFoodActivity import com.shuwei.dish.match.utils.SwipeCallback import com.shuwei.dish.match.utils.ext.startActivity import com.shuwei.dish.match.utils.ext.toJsonString @@ -59,7 +60,8 @@ class DishListFragment : Fragment() { val item = list[position] if (item.isCooking) { //烹饪中,跳到称熟重页面 - context.startActivity { +// context.startActivity { + context.startActivity { putExtra( SubmitDishActivity.FOOD_ITEM, item as Serializable diff --git a/app/src/main/java/com/shuwei/dish/match/utils/DataUtil.kt b/app/src/main/java/com/shuwei/dish/match/utils/DataUtil.kt index 4ef9bb1..727d220 100644 --- a/app/src/main/java/com/shuwei/dish/match/utils/DataUtil.kt +++ b/app/src/main/java/com/shuwei/dish/match/utils/DataUtil.kt @@ -16,13 +16,30 @@ object DataUtil { put(7, 7) put(8, 8) put(9, 5) - put(12, 4) put(10, 3) - put(11, 3) - put(13, 3) - put(14, 3) + put(11, 4) } } +// fun getWeighAddressArray(): SparseIntArray { +// return SparseIntArray().apply { +// put(0, 12) +// put(1, 13) +// put(2, 14) +// put(3, 9) +// put(4, 10) +// put(5, 11) +// put(6, 6) +// put(7, 7) +// put(8, 8) +// put(9, 5) +// put(12, 4) +// put(10, 3) +// put(11, 3) +// put(13, 3) +// put(14, 3) +// } +// } + } \ No newline at end of file diff --git a/app/src/main/java/com/shuwei/dish/match/viewmodel/AppViewModel.kt b/app/src/main/java/com/shuwei/dish/match/viewmodel/AppViewModel.kt index c575ae6..8455a9f 100644 --- a/app/src/main/java/com/shuwei/dish/match/viewmodel/AppViewModel.kt +++ b/app/src/main/java/com/shuwei/dish/match/viewmodel/AppViewModel.kt @@ -161,9 +161,9 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() { } } - fun deleteEmptySeasoning() { + fun deleteSeasoningBySort(sort: Int) { viewModelScope.launch { - rep.deleteEmptySeasoning() + rep.deleteSeasoningBySort(sort) } } @@ -174,23 +174,30 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() { } } - fun updateAll(list: MutableList) { - viewModelScope.launch { - list.forEach { - rep.updateSeasoning(it) - } - } - } +// fun updateAll(list: MutableList) { +// viewModelScope.launch { +// list.forEach { +// rep.updateSeasoning(it) +// } +// } +// } fun saveSeasoning(entity: SeasoningEntity, block: () -> Unit) { viewModelScope.launch { - val seasoning = rep.getSeasoningBySort(entity.sort) - if (seasoning == null) { - rep.insertSeasoning(entity) + val list = rep.getSeasoningBySort(entity.sort) + val size = list?.size?:0 + if (size == 1) { + rep.updateSeasoning(entity.also { it.id = list!![0].id }) block() return@launch } - rep.updateSeasoning(entity.also { it.id = seasoning.id }) + if (size > 1) { + list?.forEach { + rep.deleteSeasoningBySort(it.sort) + } + } + entity.id = 0 + rep.insertSeasoning(entity) block() } } diff --git a/app/src/main/res/layout/activity_device_config.xml b/app/src/main/res/layout/activity_device_config.xml new file mode 100644 index 0000000..2efca5a --- /dev/null +++ b/app/src/main/res/layout/activity_device_config.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 0f82f14..9e25cd6 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -35,208 +35,4 @@ tools:itemCount="3" tools:listitem="@layout/list_item_home_mode"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_submit_food.xml b/app/src/main/res/layout/activity_submit_food.xml new file mode 100644 index 0000000..9cf1b72 --- /dev/null +++ b/app/src/main/res/layout/activity_submit_food.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/layout_grid.xml b/app/src/main/res/layout/layout_grid.xml new file mode 100644 index 0000000..8e78397 --- /dev/null +++ b/app/src/main/res/layout/layout_grid.xml @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_search_goods_info.xml b/app/src/main/res/layout/list_item_search_goods_info.xml index 1da3490..6dfefda 100644 --- a/app/src/main/res/layout/list_item_search_goods_info.xml +++ b/app/src/main/res/layout/list_item_search_goods_info.xml @@ -13,6 +13,8 @@ android:gravity="center" android:layout_margin="15dp" tools:text="椒盐" + android:maxLines="1" + android:ellipsize="end" android:background="@drawable/shape_white_12_corners"/> \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index df0c2e9..66c318f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ junitVersion = "1.1.5" espressoCore = "3.5.1" appcompat = "1.6.1" material = "1.10.0" +gridlayout = "1.1.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -16,6 +17,7 @@ androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "j androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } +androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }