feat(task): 添加组配任务功能模块
- 新增组配任务列表页面和详情页面 - 实现组配任务查询、搜索和分页功能 - 添加组配任务详情展示和状态管理 - 集成溯源码获取功能到任务详情页面 - 添加组配任务相关的API接口定义和实现 - 创建组配任务数据模型和适配器 - 在设置页面添加组配任务入口 - 重构食材物料列表项布局和显示逻辑 - 更新应用启动时的设备ID初始化逻辑 - 生成配比秤终端接口文档
This commit is contained in:
@@ -79,6 +79,16 @@
|
|||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
|
|
||||||
|
<activity android:name=".ui.TaskActivity"
|
||||||
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
|
|
||||||
|
<activity android:name=".ui.TaskDetailActivity"
|
||||||
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.CookingModeActivity"
|
android:name=".ui.CookingModeActivity"
|
||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.databinding.ListItemTaskBinding
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务列表适配器
|
||||||
|
*/
|
||||||
|
class TaskAdapter(list: MutableList<NutComboTaskVO>) :
|
||||||
|
BaseQuickAdapter<NutComboTaskVO, TaskAdapter.VH>(list) {
|
||||||
|
|
||||||
|
inner class VH(var binding: ListItemTaskBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: VH,
|
||||||
|
position: Int,
|
||||||
|
item: NutComboTaskVO?
|
||||||
|
) {
|
||||||
|
holder.binding.apply {
|
||||||
|
tvTaskNo.text = "任务编号:${item?.taskNo}"
|
||||||
|
tvTargetDish.text = item?.targetDish
|
||||||
|
tvSpec.text = item?.spec
|
||||||
|
tvPlanDate.text = "计划日期:${item?.planDate}"
|
||||||
|
tvPortions.text = "总份数:${item?.portions}"
|
||||||
|
tvOwnerName.text = "负责人:${item?.ownerName}"
|
||||||
|
|
||||||
|
// 状态文本映射
|
||||||
|
val statusText = when (item?.comboStatus) {
|
||||||
|
0 -> "待组配"
|
||||||
|
1 -> "组配中"
|
||||||
|
2 -> "已完成"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
|
tvStatus.text = statusText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): VH {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = ListItemTaskBinding.inflate(inflater, parent, false)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.databinding.ListItemTaskDetailBinding
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskItemDetail
|
||||||
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务详情食材列表适配器
|
||||||
|
*/
|
||||||
|
class TaskDetailAdapter(list: MutableList<NutComboTaskItemDetail>) :
|
||||||
|
BaseQuickAdapter<NutComboTaskItemDetail, TaskDetailAdapter.VH>(list) {
|
||||||
|
|
||||||
|
inner class VH(var binding: ListItemTaskDetailBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化用量字符串,去掉小数点后末尾的0
|
||||||
|
*/
|
||||||
|
private fun formatQty(value: String?): String {
|
||||||
|
if (value.isNullOrBlank()) return "0"
|
||||||
|
return try {
|
||||||
|
BigDecimal(value).stripTrailingZeros().toPlainString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: VH,
|
||||||
|
position: Int,
|
||||||
|
item: NutComboTaskItemDetail?
|
||||||
|
) {
|
||||||
|
holder.binding.apply {
|
||||||
|
tvIngredientName.text = item?.ingredientName
|
||||||
|
|
||||||
|
// 食材类别
|
||||||
|
val classText = when (item?.ingredientClass) {
|
||||||
|
1 -> "主材"
|
||||||
|
2 -> "辅材"
|
||||||
|
3 -> "调料"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
|
tvIngredientClass.text = classText
|
||||||
|
|
||||||
|
val unit = item?.unit ?: "g"
|
||||||
|
tvPerPortionQty.text = "每份用量:${formatQty(item?.perPortionQty)}${unit}"
|
||||||
|
tvActualQty.text = "实际用量:${formatQty(item?.actualQty)}${unit}"
|
||||||
|
tvTotalQty.text = "合计用量:${formatQty(item?.totalQty)}${unit}"
|
||||||
|
|
||||||
|
tvTraceCode.visible()
|
||||||
|
tvTraceCode.text = "溯源码:${(item?.traceCode ?:"").ifBlank { "-" }}"
|
||||||
|
|
||||||
|
root.setBackgroundResource(
|
||||||
|
if (item?.isClicked == true) R.drawable.shape_item_cook_dish
|
||||||
|
else R.drawable.shape_white_fb_15_corners
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): VH {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = ListItemTaskDetailBinding.inflate(inflater, parent, false)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,9 @@ class BaseApp : Application() {
|
|||||||
GlobalData.appBaseUrl = savedBaseUrl
|
GlobalData.appBaseUrl = savedBaseUrl
|
||||||
}
|
}
|
||||||
CrashHandler.init(this)
|
CrashHandler.init(this)
|
||||||
|
|
||||||
|
GlobalData.deviceId = AppUtil.getUDID(this)
|
||||||
|
|
||||||
// val deviceId = if (BuildConfig.IS_TEST_DEVICE) ScaleDeviceConfig.DEVICE_ID_2 else AppUtil.getUDID(this)
|
// val deviceId = if (BuildConfig.IS_TEST_DEVICE) ScaleDeviceConfig.DEVICE_ID_2 else AppUtil.getUDID(this)
|
||||||
// Log.d(TAG, "onCreate: deviceId=$deviceId, isTestDevice=${BuildConfig.IS_TEST_DEVICE}")
|
// Log.d(TAG, "onCreate: deviceId=$deviceId, isTestDevice=${BuildConfig.IS_TEST_DEVICE}")
|
||||||
// GlobalData.deviceId = deviceId
|
// GlobalData.deviceId = deviceId
|
||||||
|
|||||||
@@ -183,6 +183,61 @@ data class NutSupMealPackageIngredient(
|
|||||||
val traceCode: String
|
val traceCode: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务VO - 未完成组配任务列表响应
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data class NutComboTaskVO(
|
||||||
|
val id: Long?,
|
||||||
|
val taskNo: String?,
|
||||||
|
val planDate: String?,
|
||||||
|
val canteenId: Long?,
|
||||||
|
val mealType: Int?,
|
||||||
|
val foodId: Long?,
|
||||||
|
val targetDish: String?,
|
||||||
|
val spec: String?,
|
||||||
|
val portions: Int?,
|
||||||
|
var comboStatus: Int?,
|
||||||
|
val ownerName: String?,
|
||||||
|
val createTime: String?
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务详情VO - 组配任务详情响应
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data class NutComboTaskDetailVO(
|
||||||
|
val id: Long?,
|
||||||
|
val taskNo: String?,
|
||||||
|
val planDate: String?,
|
||||||
|
val canteenId: Long?,
|
||||||
|
val mealType: Int?,
|
||||||
|
val foodId: Long?,
|
||||||
|
val targetDish: String?,
|
||||||
|
val spec: String?,
|
||||||
|
val portions: Int?,
|
||||||
|
val comboStatus: Int?,
|
||||||
|
val ownerName: String?,
|
||||||
|
val items: List<NutComboTaskItemDetail>?
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务食材明细
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data class NutComboTaskItemDetail(
|
||||||
|
val id: Long?,
|
||||||
|
val ingredientCode: String?,
|
||||||
|
val ingredientName: String?,
|
||||||
|
val ingredientClass: Int?,
|
||||||
|
var traceCode: String?,
|
||||||
|
val perPortionQty: String?,
|
||||||
|
val actualQty: String?,
|
||||||
|
val totalQty: String?,
|
||||||
|
val unit: String?,
|
||||||
|
var isClicked: Boolean? = false,
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID通用DTO - 用于开始/完成组配等需要id参数的接口
|
* ID通用DTO - 用于开始/完成组配等需要id参数的接口
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ data class SettingItem(
|
|||||||
WEIGHT_CONFIG("减重配置"),
|
WEIGHT_CONFIG("减重配置"),
|
||||||
CLEAN_PACKAGE("净菜包"),
|
CLEAN_PACKAGE("净菜包"),
|
||||||
MEAL_PACKAGE("餐品净菜包"),
|
MEAL_PACKAGE("餐品净菜包"),
|
||||||
|
GROUP_TASK("组配任务"),
|
||||||
MEAL_PACKAGE_TEST("餐品净菜包-测试"),
|
MEAL_PACKAGE_TEST("餐品净菜包-测试"),
|
||||||
DB_INSPECT("数据库查看"),
|
DB_INSPECT("数据库查看"),
|
||||||
SCALE_OBSERVE("秤数据监控"),
|
SCALE_OBSERVE("秤数据监控"),
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import com.shuwei.dish.match.model.NutSupHygieneIngredientOptionVO
|
|||||||
import com.shuwei.dish.match.model.NutProdComboVideoVO
|
import com.shuwei.dish.match.model.NutProdComboVideoVO
|
||||||
import com.shuwei.dish.match.model.NutProdComboTaskDTO
|
import com.shuwei.dish.match.model.NutProdComboTaskDTO
|
||||||
import com.shuwei.dish.match.model.IdDTO
|
import com.shuwei.dish.match.model.IdDTO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
@@ -135,4 +137,27 @@ interface ApiServiceV2 {
|
|||||||
@Body param: Map<String, @JvmSuppressWildcards Any>
|
@Body param: Map<String, @JvmSuppressWildcards Any>
|
||||||
): ApiResponse<Unit>
|
): ApiResponse<Unit>
|
||||||
|
|
||||||
|
// ========== 五、组配任务接口 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询未完成组配任务(分页)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getIncompleteComboTasks(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/nutrition/neglect/combo-task/incomplete",
|
||||||
|
@Query("deviceCode") deviceCode: String? = null,
|
||||||
|
@Query("keyword") keyword: String? = null,
|
||||||
|
@Query("pageNum") pageNum: Int = 1,
|
||||||
|
@Query("pageSize") pageSize: Int = 10
|
||||||
|
): ApiResponse<Page<NutComboTaskVO>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取组配任务详情
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getComboTaskDetail(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/nutrition/neglect/combo-task/detail",
|
||||||
|
@Query("id") id: Long
|
||||||
|
): ApiResponse<NutComboTaskDetailVO>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.shuwei.dish.match.net
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.shuwei.dish.match.model.NutCanteenVO
|
import com.shuwei.dish.match.model.NutCanteenVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import com.shuwei.dish.match.model.NutDictItemVO
|
import com.shuwei.dish.match.model.NutDictItemVO
|
||||||
import com.shuwei.dish.match.model.NutFoodOptionVO
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
import com.shuwei.dish.match.model.NutMaterOptionVO
|
import com.shuwei.dish.match.model.NutMaterOptionVO
|
||||||
@@ -203,4 +205,37 @@ class NetViewModelV2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 组配任务接口 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询未完成组配任务(回调版本)
|
||||||
|
*/
|
||||||
|
fun getIncompleteComboTasksWithCallback(
|
||||||
|
deviceCode: String? = null,
|
||||||
|
keyword: String? = null,
|
||||||
|
pageNum: Int = 1,
|
||||||
|
pageSize: Int = 10,
|
||||||
|
onLoading: () -> Unit = {},
|
||||||
|
onResult: (UiState<Page<NutComboTaskVO>?>) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
onResult(repository.getIncompleteComboTasks(deviceCode = deviceCode, keyword = keyword, pageNum = pageNum, pageSize = pageSize))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取组配任务详情(回调版本)
|
||||||
|
*/
|
||||||
|
fun getComboTaskDetailWithCallback(
|
||||||
|
id: Long,
|
||||||
|
onLoading: () -> Unit = {},
|
||||||
|
onResult: (UiState<NutComboTaskDetailVO?>) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
onResult(repository.getComboTaskDetail(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.shuwei.dish.match.net
|
|||||||
|
|
||||||
import com.shuwei.dish.match.model.IdDTO
|
import com.shuwei.dish.match.model.IdDTO
|
||||||
import com.shuwei.dish.match.model.NutCanteenVO
|
import com.shuwei.dish.match.model.NutCanteenVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import com.shuwei.dish.match.model.NutDictItemVO
|
import com.shuwei.dish.match.model.NutDictItemVO
|
||||||
import com.shuwei.dish.match.model.NutFoodOptionVO
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
import com.shuwei.dish.match.model.NutMaterOptionVO
|
import com.shuwei.dish.match.model.NutMaterOptionVO
|
||||||
@@ -87,4 +89,17 @@ class RemoteRepositoryV2 {
|
|||||||
suspend fun addMealPackage(param: Map<String, Any>): UiState<Unit?> =
|
suspend fun addMealPackage(param: Map<String, Any>): UiState<Unit?> =
|
||||||
safeApiCall { apiService.addMealPackage(param = param) }
|
safeApiCall { apiService.addMealPackage(param = param) }
|
||||||
|
|
||||||
|
// ========== 组配任务接口 ==========
|
||||||
|
|
||||||
|
suspend fun getIncompleteComboTasks(
|
||||||
|
deviceCode: String? = null,
|
||||||
|
keyword: String? = null,
|
||||||
|
pageNum: Int = 1,
|
||||||
|
pageSize: Int = 10
|
||||||
|
): UiState<Page<NutComboTaskVO>?> =
|
||||||
|
safeApiCall { apiService.getIncompleteComboTasks(deviceCode = deviceCode, keyword = keyword, pageNum = pageNum, pageSize = pageSize) }
|
||||||
|
|
||||||
|
suspend fun getComboTaskDetail(id: Long): UiState<NutComboTaskDetailVO?> =
|
||||||
|
safeApiCall { apiService.getComboTaskDetail(id = id) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ class PackActivity : BaseActivity() {
|
|||||||
binding.etInputDish.isFocusableInTouchMode = false
|
binding.etInputDish.isFocusableInTouchMode = false
|
||||||
binding.ivDishSearch.gone()
|
binding.ivDishSearch.gone()
|
||||||
|
|
||||||
|
binding.tvGoodsName.text = "食材名称"
|
||||||
|
|
||||||
addViewClickListener()
|
addViewClickListener()
|
||||||
addBackKeyListener()
|
addBackKeyListener()
|
||||||
initCamera(binding.flCameraContainer)
|
initCamera(binding.flCameraContainer)
|
||||||
@@ -206,7 +208,7 @@ class PackActivity : BaseActivity() {
|
|||||||
materialAdapter.notifyItemChanged(clickIndex)
|
materialAdapter.notifyItemChanged(clickIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.btnGetCode.clickWithDebounce {
|
binding.btnGetTraceCode.clickWithDebounce {
|
||||||
val item = list.getOrNull(clickIndex)?:return@clickWithDebounce
|
val item = list.getOrNull(clickIndex)?:return@clickWithDebounce
|
||||||
//viewModelV2.getCode
|
//viewModelV2.getCode
|
||||||
}
|
}
|
||||||
@@ -367,12 +369,19 @@ class PackActivity : BaseActivity() {
|
|||||||
private var clickIndex = -1
|
private var clickIndex = -1
|
||||||
private val materialAdapter by lazy {
|
private val materialAdapter by lazy {
|
||||||
FoodMaterialAdapter(list).apply {
|
FoodMaterialAdapter(list).apply {
|
||||||
onItemClick = { positon ->
|
onItemClick = onItemClick@{ positon ->
|
||||||
|
val item = getItem(positon) ?: return@onItemClick
|
||||||
this@PackActivity.clickIndex = positon
|
this@PackActivity.clickIndex = positon
|
||||||
list.forEachIndexed { index, entity ->
|
list.forEachIndexed { index, entity ->
|
||||||
entity.isClicked = index == positon
|
entity.isClicked = index == positon
|
||||||
}
|
}
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
binding.tvGoodsName.text = item.goodsName
|
||||||
|
binding.tvMaterialType.text = when (item.materialType) {
|
||||||
|
1 -> "主材"
|
||||||
|
2 -> "辅材"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, position ->
|
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, position ->
|
||||||
val item = list.getOrNull(position) ?: return@addOnItemChildClickListener
|
val item = list.getOrNull(position) ?: return@addOnItemChildClickListener
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ class SettingActivity : BaseActivity() {
|
|||||||
startActivity<MealListActivity> { }
|
startActivity<MealListActivity> { }
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
SettingItem(
|
||||||
|
type = SettingItem.Type.GROUP_TASK,
|
||||||
|
onClick = {
|
||||||
|
startActivity<TaskActivity> { }
|
||||||
|
}
|
||||||
|
),
|
||||||
SettingItem(
|
SettingItem(
|
||||||
type = SettingItem.Type.MEAL_PACKAGE_TEST,
|
type = SettingItem.Type.MEAL_PACKAGE_TEST,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.shuwei.dish.match.adapter.TaskAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
|
import com.shuwei.dish.match.databinding.ActivityTaskBinding
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
||||||
|
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.toast
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务列表页面
|
||||||
|
*/
|
||||||
|
class TaskActivity : BaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "TaskActivity"
|
||||||
|
const val TASK_ITEM = "taskItem"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by lazy { ActivityTaskBinding.inflate(layoutInflater) }
|
||||||
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
|
|
||||||
|
private val taskList = mutableListOf<NutComboTaskVO>()
|
||||||
|
private val taskAdapter by lazy {
|
||||||
|
TaskAdapter(taskList).apply {
|
||||||
|
setOnItemClickListener { adapter, view, position ->
|
||||||
|
startActivity<TaskDetailActivity> {
|
||||||
|
putExtra(TaskDetailActivity.TASK_ITEM, taskList[position])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var currentPage = 1
|
||||||
|
private var keyword: String? = null
|
||||||
|
private var isLoading = false
|
||||||
|
private var hasMore = true
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
setTitleBar(titleBarAction = {
|
||||||
|
it.visible()
|
||||||
|
}, titleAction = {
|
||||||
|
it.text = "组配任务"
|
||||||
|
}, rightIconAction = {
|
||||||
|
it.gone()
|
||||||
|
}, backAction = {
|
||||||
|
it.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
initRecyclerView()
|
||||||
|
initRefreshLayout()
|
||||||
|
initSearchListener()
|
||||||
|
loadTaskList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 RecyclerView
|
||||||
|
*/
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.rvTaskList.layoutManager = LinearLayoutManager(this)
|
||||||
|
binding.rvTaskList.adapter = taskAdapter
|
||||||
|
taskAdapter.setOnItemClickListener { _, _, position ->
|
||||||
|
val item = taskList.getOrNull(position) ?: return@setOnItemClickListener
|
||||||
|
val intent = Intent(this, TaskDetailActivity::class.java).apply {
|
||||||
|
putExtra(TASK_ITEM, item)
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 SmartRefreshLayout 下拉刷新和上拉加载
|
||||||
|
*/
|
||||||
|
private fun initRefreshLayout() {
|
||||||
|
binding.refreshLayout.apply {
|
||||||
|
// 下拉刷新
|
||||||
|
setOnRefreshListener {
|
||||||
|
currentPage = 1
|
||||||
|
hasMore = true
|
||||||
|
loadTaskList()
|
||||||
|
}
|
||||||
|
// 上拉加载
|
||||||
|
setOnLoadMoreListener { refreshLayout ->
|
||||||
|
if (isLoading || !hasMore) {
|
||||||
|
refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
return@setOnLoadMoreListener
|
||||||
|
}
|
||||||
|
currentPage++
|
||||||
|
loadTaskList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索栏交互
|
||||||
|
*/
|
||||||
|
private fun initSearchListener() {
|
||||||
|
binding.ivSearch.clickWithDebounce {
|
||||||
|
performSearch()
|
||||||
|
}
|
||||||
|
binding.etInputKeyword.addOnActionSearchListener {
|
||||||
|
performSearch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行搜索
|
||||||
|
*/
|
||||||
|
private fun performSearch() {
|
||||||
|
keyword = binding.etInputKeyword.text.toString().trim()
|
||||||
|
if (keyword.isNullOrBlank()) {
|
||||||
|
toast("请输入搜索关键字")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentPage = 1
|
||||||
|
hasMore = true
|
||||||
|
taskList.clear()
|
||||||
|
taskAdapter.notifyDataSetChanged()
|
||||||
|
binding.rvTaskList.visible()
|
||||||
|
binding.tvEmpty.gone()
|
||||||
|
loadTaskList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载组配任务列表
|
||||||
|
*/
|
||||||
|
private fun loadTaskList() {
|
||||||
|
isLoading = true
|
||||||
|
viewModelV2.getIncompleteComboTasksWithCallback(
|
||||||
|
deviceCode = GlobalData.deviceId,
|
||||||
|
keyword = keyword,
|
||||||
|
pageNum = currentPage,
|
||||||
|
pageSize = 10,
|
||||||
|
onLoading = {
|
||||||
|
if (currentPage == 1) {
|
||||||
|
showLoading("加载中……")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onResult = onResult@{ state ->
|
||||||
|
dismissLoading()
|
||||||
|
isLoading = false
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val records = state.data?.records
|
||||||
|
if (currentPage == 1 && records.isNullOrEmpty()) {
|
||||||
|
binding.rvTaskList.gone()
|
||||||
|
binding.tvEmpty.visible()
|
||||||
|
binding.refreshLayout.finishRefresh()
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
return@onResult
|
||||||
|
}
|
||||||
|
if (!records.isNullOrEmpty()) {
|
||||||
|
binding.rvTaskList.visible()
|
||||||
|
binding.tvEmpty.gone()
|
||||||
|
if (currentPage == 1) {
|
||||||
|
taskList.clear()
|
||||||
|
}
|
||||||
|
taskList.addAll(records)
|
||||||
|
taskAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
if (records.size < 10) {
|
||||||
|
hasMore = false
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasMore = false
|
||||||
|
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||||
|
}
|
||||||
|
binding.refreshLayout.finishRefresh()
|
||||||
|
binding.refreshLayout.finishLoadMore()
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
toast(state.msg)
|
||||||
|
if (currentPage > 1) {
|
||||||
|
currentPage--
|
||||||
|
}
|
||||||
|
if (currentPage == 1 && taskList.isEmpty()) {
|
||||||
|
binding.rvTaskList.gone()
|
||||||
|
binding.tvEmpty.visible()
|
||||||
|
}
|
||||||
|
binding.refreshLayout.finishRefresh()
|
||||||
|
binding.refreshLayout.finishLoadMore(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.core.content.IntentCompat
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.shuwei.dish.match.adapter.TaskDetailAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.databinding.ActivityTaskDetailBinding
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
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 kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配任务详情页面
|
||||||
|
*/
|
||||||
|
class TaskDetailActivity : BaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "TaskDetailActivity"
|
||||||
|
const val TASK_ITEM = "taskItem"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by lazy { ActivityTaskDetailBinding.inflate(layoutInflater) }
|
||||||
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
|
|
||||||
|
private var taskItem: NutComboTaskVO? = null
|
||||||
|
private val itemList = mutableListOf<com.shuwei.dish.match.model.NutComboTaskItemDetail>()
|
||||||
|
private val itemAdapter by lazy {
|
||||||
|
TaskDetailAdapter(itemList).apply {
|
||||||
|
setOnItemClickListener { adapter, view, position ->
|
||||||
|
getItem(position) ?: return@setOnItemClickListener
|
||||||
|
itemList.forEachIndexed { index, detail ->
|
||||||
|
detail.isClicked = index == position
|
||||||
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
|
||||||
|
taskItem = IntentCompat.getParcelableExtra(intent, TASK_ITEM, NutComboTaskVO::class.java)
|
||||||
|
|
||||||
|
setTitleBar(titleBarAction = {
|
||||||
|
it.visible()
|
||||||
|
}, titleAction = {
|
||||||
|
it.text = "任务详情"
|
||||||
|
}, rightIconAction = {
|
||||||
|
it.gone()
|
||||||
|
}, backAction = {
|
||||||
|
it.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
initRecyclerView()
|
||||||
|
initView()
|
||||||
|
loadDetail()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化任务概要信息
|
||||||
|
*/
|
||||||
|
private fun initView() {
|
||||||
|
taskItem?.let {
|
||||||
|
binding.tvTaskNo.text = "任务编号:${it.taskNo}"
|
||||||
|
binding.tvTargetDish.text = it.targetDish
|
||||||
|
binding.tvSpec.text = it.spec
|
||||||
|
binding.tvPlanDate.text = "计划日期:${it.planDate}"
|
||||||
|
binding.tvPortions.text = "总份数:${it.portions}"
|
||||||
|
binding.tvOwnerName.text = "负责人:${it.ownerName}"
|
||||||
|
binding.tvStatus.text = getStatusText(it.comboStatus)
|
||||||
|
|
||||||
|
// 仅待组配状态显示"开始组配"按钮
|
||||||
|
if (it.comboStatus == 0) {
|
||||||
|
binding.btnStart.visible()
|
||||||
|
binding.btnStart.clickWithDebounce {
|
||||||
|
startComboTask(it.id ?: return@clickWithDebounce)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.btnStart.gone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.btnGetTraceCode.clickWithDebounce {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 RecyclerView
|
||||||
|
*/
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.rvItemList.layoutManager = LinearLayoutManager(this)
|
||||||
|
binding.rvItemList.adapter = itemAdapter
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载任务详情(食材清单)
|
||||||
|
*/
|
||||||
|
private fun loadDetail() {
|
||||||
|
val taskId = taskItem?.id ?: return
|
||||||
|
viewModelV2.getComboTaskDetailWithCallback(
|
||||||
|
id = taskId,
|
||||||
|
onLoading = {
|
||||||
|
showLoading("加载中……")
|
||||||
|
},
|
||||||
|
onResult = onResult@{ state ->
|
||||||
|
dismissLoading()
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val detail = state.data
|
||||||
|
if (detail == null) {
|
||||||
|
toast("详情为空")
|
||||||
|
return@onResult
|
||||||
|
}
|
||||||
|
// 更新状态(可能已被其他设备修改)
|
||||||
|
binding.tvStatus.text = getStatusText(detail.comboStatus)
|
||||||
|
if (detail.comboStatus != 0) {
|
||||||
|
binding.btnStart.gone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载食材列表
|
||||||
|
val items = detail.items
|
||||||
|
if (!items.isNullOrEmpty()) {
|
||||||
|
itemList.clear()
|
||||||
|
itemList.addAll(items)
|
||||||
|
itemAdapter.notifyDataSetChanged()
|
||||||
|
} else {
|
||||||
|
toast("该任务无食材信息")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> toast(state.msg)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始组配
|
||||||
|
*/
|
||||||
|
private fun startComboTask(taskId: Long) {
|
||||||
|
showLoading("正在开始组配……")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModelV2.startComboTask(taskId)
|
||||||
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModelV2.startComboTaskState.collect { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
dismissLoading()
|
||||||
|
toast("已开始组配")
|
||||||
|
// 刷新详情
|
||||||
|
loadDetail()
|
||||||
|
// 更新本地状态
|
||||||
|
taskItem?.comboStatus = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
dismissLoading()
|
||||||
|
toast(state.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态文本映射
|
||||||
|
*/
|
||||||
|
private fun getStatusText(status: Int?): String {
|
||||||
|
return when (status) {
|
||||||
|
0 -> "待组配"
|
||||||
|
1 -> "组配中"
|
||||||
|
2 -> "已完成"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,31 +70,22 @@
|
|||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLength="12"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="豆腐" />
|
tools:text="豆腐" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvMaterialType"
|
android:id="@+id/tvMaterialType"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
android:textColor="@color/black999"
|
android:textColor="@color/black999"
|
||||||
android:textSize="26sp"
|
android:textSize="26sp"
|
||||||
tools:text="主材" />
|
tools:text="主材" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/btnGetCode"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_marginEnd="30dp"
|
|
||||||
android:paddingHorizontal="20dp"
|
|
||||||
android:text="获取溯源码"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@color/dish_green"
|
|
||||||
android:background="@drawable/ripple_effect_light"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
@@ -196,6 +187,20 @@
|
|||||||
android:textSize="28sp" />
|
android:textSize="28sp" />
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnGetTraceCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:paddingHorizontal="20dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:text="获取溯源码"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:background="@drawable/ripple_effect_light"/>
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/flCameraContainer"
|
android:id="@+id/flCameraContainer"
|
||||||
android:layout_width="1dp"
|
android:layout_width="1dp"
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<?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">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llSearchBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_margin="30dp"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etInputKeyword"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginHorizontal="28dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:autofillHints=""
|
||||||
|
android:background="@color/white"
|
||||||
|
android:gravity="center"
|
||||||
|
android:hint="请输入菜品名称"
|
||||||
|
android:inputType="text"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:paddingStart="3dp"
|
||||||
|
android:paddingEnd="3dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textColor="@color/black333"
|
||||||
|
android:textColorHint="@color/gray_c8"
|
||||||
|
android:textSize="40sp"
|
||||||
|
tools:ignore="TextFields" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivSearch"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:src="@drawable/ic_search_gray"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||||
|
android:id="@+id/refreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.header.ClassicsHeader
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvTaskList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
tools:itemCount="3"
|
||||||
|
tools:listitem="@layout/list_item_task" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvEmpty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="暂无数据"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.footer.ClassicsFooter
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
<?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">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llTaskInfo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="30dp"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="20dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTaskNo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="任务编号:RW20260601001" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTargetDish"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="红烧肉" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSpec"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:text="中组(8份)·50组" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvStatus"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="end"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:text="待组配" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPlanDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="计划日期:2026-06-01" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPortions"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="总份数:400" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvOwnerName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="负责人:张三" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="食材明细"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnGetTraceCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:background="@drawable/ripple_effect_light"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="20dp"
|
||||||
|
android:text="获取溯源码"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvItemList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
tools:itemCount="3"
|
||||||
|
tools:listitem="@layout/list_item_task_detail" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnStart"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_margin="30dp"
|
||||||
|
android:background="@drawable/shape_green_bg"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="开始组配"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/clBlock"
|
android:id="@+id/clBlock"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="120dp"
|
android:layout_height="140dp"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_marginEnd="30dp"
|
||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
@@ -21,41 +21,41 @@
|
|||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/tvGoodsCode"
|
app:layout_constraintBottom_toTopOf="@+id/tvDishType"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/tvDishWeight"
|
app:layout_constraintEnd_toStartOf="@+id/tvDishWeight"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
tools:text="雪菜" />
|
tools:text="雪菜" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvGoodsCode"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:layout_marginVertical="3dp"
|
|
||||||
android:textColor="@color/black999"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/tvDishType"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
|
||||||
android:text="溯源码:-" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvDishType"
|
android:id="@+id/tvDishType"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
|
android:layout_marginVertical="5dp"
|
||||||
android:textColor="@color/black999"
|
android:textColor="@color/black999"
|
||||||
android:textSize="23sp"
|
android:textSize="22sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/tvGoodsCode"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
||||||
|
tools:text="主辅材:主材" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvGoodsCode"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="18sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
||||||
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvGoodsCode"
|
app:layout_constraintTop_toBottomOf="@id/tvDishType"
|
||||||
tools:text="主辅材:主材" />
|
android:text="溯源码:-" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivOperateIcon"
|
android:id="@+id/ivOperateIcon"
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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="160dp"
|
||||||
|
android:layout_margin="15dp"
|
||||||
|
android:background="@drawable/shape_white_12_corners"
|
||||||
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="15dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTaskNo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="任务编号:RW20260601001" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTargetDish"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/tvPlanDate"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvTaskNo"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvTaskNo"
|
||||||
|
tools:text="红烧肉" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSpec"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="22sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tvTargetDish"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/tvTargetDish"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tvTargetDish"
|
||||||
|
tools:text="中组(8份)·50组" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPlanDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/tvPortions"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvTargetDish"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvTargetDish"
|
||||||
|
tools:text="计划日期:2026-06-01" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPortions"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvTargetDish"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvPlanDate"
|
||||||
|
tools:text="总份数:400" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvOwnerName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tvPortions"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tvPortions"
|
||||||
|
tools:text="负责人:张三" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="22sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tvTargetDish"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tvTargetDish"
|
||||||
|
tools:text="待组配" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="15dp"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:background="@drawable/shape_white_fb_15_corners"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="15dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvIngredientName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="五花肉" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvIngredientClass"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="主材" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPerPortionQty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="每份用量:200g" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvActualQty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="实际用量:200g" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTotalQty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="合计用量:80000g" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTraceCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="溯源码:TRACE-20260601001"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user