增加过期逻辑

This commit is contained in:
2025-08-15 17:59:40 +08:00
parent 2162ba0c9e
commit f8453c7d76
16 changed files with 211 additions and 62 deletions
@@ -13,7 +13,6 @@ import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter4.util.setOnDebouncedItemClick
@@ -37,7 +36,6 @@ import com.shuwei.intelligent.shelves.utils.ext.visible
import com.shuwei.intelligent.shelves.utils.f2C
import com.shuwei.intelligent.shelves.utils.hexToBinary
import com.shuwei.intelligent.shelves.utils.hexToDec
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
@@ -74,6 +72,10 @@ class HomeActivity : BaseActivity() {
val weightArray = SparseArray<Double?>()
var shelfIndex = 0
// public fun getRealWeight():Double = weightArray[shelfIndex]?:0.0
// 温度
var showTemperatureC = ""
// 湿度
var showHumidity = "0"
}
private lateinit var binding: ActivityHomeBinding
@@ -134,6 +136,9 @@ class HomeActivity : BaseActivity() {
var androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
// androidId = "d0e7a2d5f25c775c"
Log.d(TAG, "onCreate: androidId=${androidId}")
if (androidId == "65e1012638f78260" || androidId == "40f89e91ee40611d") {
androidId = "d0e7a2d5f25c775c"
}
App.getInstance().deviceId = androidId
//"53babf69-0d2f-3875-a649-f2e12f80ad4c1"
@@ -258,7 +263,10 @@ class HomeActivity : BaseActivity() {
// Log.d(TAG, "receiveSerialPortData:心跳08: $data")
// heartBeat(data)
// }
"0202" -> {
//开关锁反馈
lockFeedback(data)
}
"0302" -> {
//获取设备状态
getDeviceInfo(data)
@@ -268,6 +276,34 @@ class HomeActivity : BaseActivity() {
}
}
private var fixedDataBody = ""
private fun lockFeedback(data: String) {
runCatching {
val fixedDataBodyEndIndex = data.length - FOOTER.length
val fixedDataBodyStartIndex = HEADER.length + "0202".length + 42
fixedDataBody = data.substring(fixedDataBodyStartIndex, fixedDataBodyEndIndex)
val lockNo = if (list[shelfIndex].deviceNo in 1..5) "01" else "02"
val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6)
if (lockOneState == "00") {
//锁1关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
}
}
val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8)
if (lockTwoState == "00") {
//锁2关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
}
}
}.onFailure {
it.printStackTrace()
}
}
private fun heartBeat(data: String) {
runCatching {
if (data.length < 200) {
@@ -285,11 +321,11 @@ class HomeActivity : BaseActivity() {
val temperatureHex = data.substring(temperatureStartIndex, temperatureEndIndex)
val temperature = hexToDec(temperatureHex)
val tempC = f2C(temperature.toDouble())
val showTemp = "%.1f".format(tempC)
showTemperatureC = "%.1f".format(tempC)
val percent = 10 * list.count { it.goodsName.isNullOrBlank().not() }
updateLeftStatus("1-1冷藏柜 ${showTemp}°C / ${percent}%")
updateLeftStatus("1-1冷藏柜 ${showTemperatureC}°C / ${percent}%")
}.onFailure {
it.printStackTrace()
}
@@ -349,11 +385,11 @@ class HomeActivity : BaseActivity() {
val temperatureHex = data.substring(temperatureStartIndex, temperatureEndIndex)
val temperature = hexToDec(temperatureHex)
val tempC = f2C(temperature.toDouble())
val showTemp = "%.1f".format(tempC)
showTemperatureC = "%.1f".format(tempC)
val percent = 10 * list.count { it.goodsName.isNullOrBlank().not() }
updateLeftStatus("1-1冷藏柜 ${showTemp}°C / ${percent}%")
updateLeftStatus("1-1冷藏柜 ${showTemperatureC}°C / ${percent}%")
getWeightInfo(
start = weightStartIndex,
@@ -396,7 +432,9 @@ class HomeActivity : BaseActivity() {
goodsId = model.goodsId
goodsName = model.goodsName
weight = model.weight
createTime = model.createTime
if (model.createTime.isNullOrBlank().not()) {
createTime = model.createTime
}
}
notifyItemChanged(position)
}
@@ -1,16 +1,12 @@
package com.shuwei.intelligent.shelves
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.view.updateLayoutParams
import androidx.core.widget.addTextChangedListener
@@ -109,7 +105,7 @@ class ShelfActivity : BaseActivity() {
getGoodsList()
KeyboardUtil.hideKeyboard(context, this)
}
addTextChangedListener(afterTextChanged = {editable ->
addTextChangedListener(afterTextChanged = { editable ->
if (editable.isNullOrBlank()) {
pageNo = 1
getGoodsList()
@@ -122,12 +118,14 @@ class ShelfActivity : BaseActivity() {
toast("请选择食材")
return@clickWithDebounce
}
val currentGoodsId = list[clickIndex].goodsId ?: ""
val data = ShelfModel(
shelfName = shelfModel?.shelfName,
goodsId = list[clickIndex].goodsId ?: "",
goodsId = currentGoodsId,
goodsName = list[clickIndex].goodsName,
weight = realWeight / 1000.0,
createTime = DateTimeUtil.formatDateTime(dateTime = Date())
overdueDay = list[clickIndex].overdueDay,
createTime = if (shelfModel?.goodsId == currentGoodsId) null else DateTimeUtil.formatDateTime(dateTime = Date())
)
val intent = Intent().apply {
putExtra(SHELF_MODEL, data)
@@ -152,7 +150,7 @@ class ShelfActivity : BaseActivity() {
SerialPortManager.send(DEVICE_INFO_CMD)
Loading.show(this@ShelfActivity)
v.postDelayed({Loading.dismiss()}, 5000)
v.postDelayed({ Loading.dismiss() }, 5000)
}
KeyboardUtil.hideKeyboard(v.context, v)
}
@@ -173,7 +171,7 @@ class ShelfActivity : BaseActivity() {
}
// registerReceiver(receiver, IntentFilter(RECEIVER_DEVICE_INFO + shelfModel?.deviceNo))
binding.ivBack?.setOnClickListener { finish() }
binding.refreshLayout.let {
it.setEnableRefresh(true)
it.setEnableLoadMore(false)
@@ -232,10 +230,31 @@ class ShelfActivity : BaseActivity() {
}
return
}
var firstOne:GoodsModel?=null
if (pageNo == 1) {
if (shelfModel?.goodsId.isNullOrBlank().not()) {
firstOne = list.firstOrNull { it.goodsId == shelfModel?.goodsId }
if (firstOne == null) {
firstOne = GoodsModel(
goodsId = shelfModel?.goodsId,
goodsName = shelfModel?.goodsName,
isClicked = true
)
}
}
list.clear()
}
val records = data.result.records
if (pageNo == 1) {
firstOne?.let { one ->
val filterResult = records.firstOrNull{one.goodsId == it.goodsId }
if (filterResult != null) {
records.remove(filterResult)
}
clickIndex = 0
list.add(one)
}
}
list.addAll(records)
val enableLoadMore = records.size >= PAGE_SIZE
binding.refreshLayout.setEnableLoadMore(enableLoadMore)
@@ -334,7 +353,7 @@ class ShelfActivity : BaseActivity() {
}
it.ivEmptyIcon.setImageResource(R.drawable.ic_empty_gray)
it.ivEmptyIcon.updateLayoutParams<LinearLayout.LayoutParams> {
val swDpValue = resources?.configuration?.smallestScreenWidthDp?:0
val swDpValue = resources?.configuration?.smallestScreenWidthDp ?: 0
width = if (swDpValue > 600) 200.dp else 120.dp
}
}
@@ -346,7 +365,7 @@ class ShelfActivity : BaseActivity() {
@Subscribe(threadMode = ThreadMode.MAIN)
public fun receiveWeightEvent(event: SendWeightEvent) {
if (event.shelfNo == (shelfModel?.deviceNo?:0)) {
if (event.shelfNo == (shelfModel?.deviceNo ?: 0)) {
binding.tvFoodWeight.text = "${event.weight}"
}
}
@@ -10,6 +10,10 @@ import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.intelligent.shelves.R
import com.shuwei.intelligent.shelves.databinding.ListItemShelfBinding
import com.shuwei.intelligent.shelves.model.ShelfModel
import com.shuwei.intelligent.shelves.utils.DateTimeUtil
import com.shuwei.intelligent.shelves.utils.ext.gone
import com.shuwei.intelligent.shelves.utils.ext.visible
import java.util.Date
class ShelfAdapter(list: MutableList<ShelfModel>) :
BaseQuickAdapter<ShelfModel, ShelfAdapter.VH>(list) {
@@ -22,14 +26,42 @@ class ShelfAdapter(list: MutableList<ShelfModel>) :
return VH(binding)
}
private fun stringToDate(createTime: String?): Date? {
if (createTime.isNullOrBlank()) {
return null
}
return DateTimeUtil.stringToDate(createTime)
}
override fun onBindViewHolder(holder: VH, position: Int, item: ShelfModel?) {
val shelfNo = item!!.deviceNo
item.shelfName = "货架-${if (shelfNo < 10) "0${shelfNo}" else "$shelfNo" }"
item.shelfName = "货架-${if (shelfNo < 10) "0${shelfNo}" else "$shelfNo"}"
val weight = item.weight ?: 0.toDouble()
val binding = holder.binding
if (item.overdueDay.isNullOrBlank()) {
binding.ivStaleFood.gone()
} else {
runCatching {
val shelfDate = stringToDate(item.createTime)
if (shelfDate == null) {
binding.ivStaleFood.gone()
} else {
val days = item.overdueDay!!.toInt()
val resultDate = DateTimeUtil.addDays(shelfDate, days)
if (resultDate.before(Date())) {
binding.ivStaleFood.visible()
} else {
binding.ivStaleFood.gone()
}
}
}.onFailure {
binding.ivStaleFood.gone()
}
}
//?.setImageResource()
binding.tvFoodWeight.run {
setTextColor(getColor(R.color.food_weight_orange))
val showWeight = if(weight == 0.toDouble()) "0" else "%.3f".format(weight)
val showWeight = if (weight == 0.toDouble()) "0" else "%.3f".format(weight)
text = "${showWeight}千克"
}
//val isBlankShelf = weight <= 0
@@ -5,5 +5,6 @@ import java.io.Serializable
data class GoodsModel(
var goodsId: String? = null,
var goodsName: String? = null,
var overdueDay: String? = null,
var isClicked: Boolean = false
) : Serializable
@@ -10,5 +10,8 @@ data class ShelfModel(
var goodsName: String? = null,
var deviceId: String? = null,
var weight: Double? = null,
var createTime: String? = null
var createTime: String? = null,
var overdueDay: String? = null,
var temperature: String? = null,
var humidity: String = "0",
) : Serializable
@@ -23,8 +23,8 @@ class NetViewModel : ViewModel() {
private val _getShelfListUiState = MutableStateFlow<UiState>(UiState.Initial)
val getShelfListUiState: StateFlow<UiState> = _getShelfListUiState
private val _saveShelfGoodsListUiState = MutableStateFlow<UiState>(UiState.Initial)
val saveShelfGoodsListUiState: StateFlow<UiState> = _saveShelfGoodsListUiState
// private val _saveShelfGoodsListUiState = MutableStateFlow<UiState>(UiState.Initial)
// val saveShelfGoodsListUiState: StateFlow<UiState> = _saveShelfGoodsListUiState
private val _getGoodsListUiState = MutableStateFlow<UiState>(UiState.Initial)
val getGoodsListUiState: StateFlow<UiState> = _getGoodsListUiState
@@ -64,21 +64,21 @@ class NetViewModel : ViewModel() {
}
}
fun saveShelfGoodsList(body: ShelfBody) {
viewModelScope.launch {
_saveShelfGoodsListUiState.value = UiState.Loading
runCatching {
val response = apiService.saveShelfGoodsList(body)
if (response.success) {
_saveShelfGoodsListUiState.value = UiState.Success(response)
} else {
_saveShelfGoodsListUiState.value = UiState.Error(response.message ?: "请求失败")
}
}.onFailure {
_saveShelfGoodsListUiState.value = UiState.Error(it.message ?: "请求异常")
}
}
}
// fun saveShelfGoodsList(body: ShelfBody) {
// viewModelScope.launch {
// _saveShelfGoodsListUiState.value = UiState.Loading
// runCatching {
// val response = apiService.saveShelfGoodsList(body)
// if (response.success) {
// _saveShelfGoodsListUiState.value = UiState.Success(response)
// } else {
// _saveShelfGoodsListUiState.value = UiState.Error(response.message ?: "请求失败")
// }
// }.onFailure {
// _saveShelfGoodsListUiState.value = UiState.Error(it.message ?: "请求异常")
// }
// }
// }
fun getGoodsList(
canteenId: String = "",
@@ -2,8 +2,8 @@ package com.shuwei.intelligent.shelves.net
object UrlConfig {
//const val BASE_URL = "http://192.168.1.7:9002"
const val BASE_URL = "https://yyjk.shuziweidao.com/gateway/"
const val BASE_URL = "http://192.168.1.3:9002"
// const val BASE_URL = "https://yyjk.shuziweidao.com/gateway/"
const val GET_ACCESS_TOKEN = "restaurant/equipment/stEquipment/getEquipmentToken"
const val GET_SHELF_LIST = "inventory/smartShelves/app/getShelvesListByDeviceId"
const val GET_GOODS_LIST = "inventory/smartShelves/app/getGoodsPageList"
@@ -38,6 +38,10 @@ class SyncTask(appContext: Context, workerParams: WorkerParameters) :
val list = HomeActivity.list
Log.d(TAG, "performSync: list:${list.toJsonString()}")
val submitList = list.sortedBy { it.deviceNo }
submitList.forEach {
it.temperature = HomeActivity.showTemperatureC
it.humidity = HomeActivity.showHumidity
}
val body = ShelfBody().also {
it.deviceId = App.getInstance().deviceId
it.canteenId = App.getInstance().canteenId
@@ -1,9 +1,11 @@
package com.shuwei.intelligent.shelves.utils
import androidx.annotation.NonNull
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Date
import java.util.Locale
@@ -19,6 +21,19 @@ object DateTimeUtil {
return sdf.format(dateTime)
}
fun stringToDate(dateText: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date? {
val sdf = SimpleDateFormat(pattern, Locale.CHINA)
return sdf.parse(dateText)
}
fun addDays(date: Date, days: Int): Date {
val calendar = Calendar.getInstance().apply {
time = date
add(Calendar.DAY_OF_MONTH, days)
}
return calendar.time
}
// fun convert(dateStr: String, pattern: String = YYYY_MM_DD_HH_MM_SS): Date {
// val formatter = DateTimeFormatter.ofPattern(pattern)
// val ldt = LocalDateTime.parse(dateStr, formatter)
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -35,10 +35,10 @@
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginTop="12dp"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:textColor="@color/bg_page"
android:textSize="15sp"
android:fontFamily="sans-serif-medium"
tools:text="货架 - 03" />
<Space
@@ -89,17 +89,27 @@
android:layout_marginEnd="12dp"
android:backgroundTint="@color/bg_page"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:insetTop="0dp"
android:insetBottom="0dp"
android:maxLines="1"
android:text="清零"
android:fontFamily="sans-serif-medium"
android:textColor="@color/white"
android:textSize="15sp"
app:cornerRadius="6dp"
app:elevation="0dp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="top|start"
android:layout_marginTop="12dp"
android:layout_marginStart="12dp"
android:src="@drawable/ic_back_512"
tools:ignore="ContentDescription" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
@@ -143,24 +153,24 @@
android:layout_height="36dp"
android:layout_marginEnd="12dp"
android:background="@null"
android:fontFamily="sans-serif-medium"
android:hint="输入食材名称"
android:maxLines="1"
android:inputType="text"
android:text=""
android:imeOptions="actionSearch"
android:textColor="@color/food_name_black"
android:inputType="text"
android:maxLines="1"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:text=""
android:textColor="@color/food_name_black"
android:textColorHint="#B4BEC8"
android:fontFamily="sans-serif-medium"
android:textSize="15sp"
tools:ignore="Autofill,HardcodedText,TextFields" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_marginTop="8dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_weight="1">
<com.scwang.smart.refresh.layout.SmartRefreshLayout
@@ -176,16 +186,16 @@
android:id="@+id/rvSearch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="12dp"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:clipToPadding="false"
android:overScrollMode="never"
tools:listitem="@layout/list_item_search"
android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="10"/>
tools:itemCount="10"
tools:listitem="@layout/list_item_search" />
<com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent"
@@ -195,30 +205,30 @@
<include
android:id="@+id/include"
layout="@layout/layout_empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/layout_empty_view"
android:visibility="gone"/>
android:visibility="gone" />
</FrameLayout>
<!-- android:layout_marginTop="48dp"-->
<!-- android:layout_marginTop="48dp"-->
<com.google.android.material.button.MaterialButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginBottom="24dp"
android:layout_marginBottom="12dp"
android:backgroundTint="@color/bg_page"
android:ellipsize="end"
android:insetTop="0dp"
android:insetBottom="0dp"
android:maxLines="1"
android:text="确定"
android:textStyle="bold"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
app:cornerRadius="6dp"
app:elevation="0dp"
tools:ignore="HardcodedText" />
@@ -75,5 +75,13 @@
tools:text="-" />
</LinearLayout>
<ImageView
android:id="@+id/ivStaleFood"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_stale_food_512"
android:layout_gravity="top|end"
tools:ignore="ContentDescription"
android:visibility="gone"/>
</com.google.android.material.card.MaterialCardView>
@@ -100,6 +100,16 @@
app:elevation="0dp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="top|start"
android:layout_marginTop="24dp"
android:layout_marginStart="24dp"
android:src="@drawable/ic_back_512"
tools:ignore="ContentDescription" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
@@ -210,7 +220,7 @@
android:layout_marginTop="24dp"
android:layout_marginEnd="48dp"
android:layout_marginStart="48dp"
android:layout_marginBottom="48dp"
android:layout_marginBottom="24dp"
android:backgroundTint="@color/bg_page"
android:ellipsize="end"
android:insetTop="0dp"
@@ -75,5 +75,13 @@
tools:text="-" />
</LinearLayout>
<ImageView
android:id="@+id/ivStaleFood"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_stale_food_512"
android:layout_gravity="top|end"
tools:ignore="ContentDescription"
android:visibility="gone"/>
</com.google.android.material.card.MaterialCardView>
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.1.3</domain>
<domain includeSubdomains="true">192.168.1.7</domain>
</domain-config>
</network-security-config>