feat: 完善任务排档功能 - 添加数据模型、列表显示和编辑对话框

新增功能:
- 创建 TaskSchedulerBean 数据模型,支持任务名称、备注、起始时间、排档幅度
- 添加任务项布局 item_task_scheduler.xml,包含排档按钮
- 创建编辑对话框布局 dialog_task_edit.xml,支持编辑所有字段
- 实现 RecyclerView 列表显示任务数据
- 添加 showEditTaskDialog() 编辑对话框功能
- 实现 performSchedule() 排档时间计算功能
- 添加 addMinutesToTime() 时间计算工具方法
- 完整的输入验证逻辑
- 示例数据初始化

修改内容:
- 更新 activity_task_scheduler.xml 为 RecyclerView 布局
- 修改 TaskSchedulerActivity 继承 WinBoLLActivity
- 实现完整的列表适配器和 ViewHolder
- 添加排档按钮点击事件处理
This commit is contained in:
Transformers
2026-05-18 03:22:11 +08:00
parent 510f50458b
commit 3609c07daf
5 changed files with 656 additions and 25 deletions
@@ -1,20 +1,42 @@
package cc.winboll.studio.stallhelper.activities;
import android.app.Dialog;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.stallhelper.R;
import cc.winboll.studio.stallhelper.beans.TaskSchedulerBean;
import java.util.ArrayList;
import java.util.Calendar;
/**
* @Author ZhanGSKen
* @Date 2026/05/18
* @Describe 任务排档窗口
*/
public class TaskSchedulerActivity extends AppCompatActivity {
public class TaskSchedulerActivity extends WinBoLLActivity {
public static final String TAG = "TaskSchedulerActivity";
ArrayList<TaskSchedulerBean> mTaskList;
TaskSchedulerAdapter mAdapter;
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -24,5 +46,234 @@ public class TaskSchedulerActivity extends AppCompatActivity {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle("任务排档");
// 初始化任务列表
mTaskList = new ArrayList<TaskSchedulerBean>();
initSampleData();
// 设置 RecyclerView
RecyclerView recyclerView = findViewById(R.id.task_scheduler_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
mAdapter = new TaskSchedulerAdapter(mTaskList);
recyclerView.setAdapter(mAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
WinBoLLActivityManager.getInstance().finish(this);
}
return super.onOptionsItemSelected(item);
}
/**
* 初始化示例数据
*/
private void initSampleData() {
mTaskList.add(new TaskSchedulerBean("准备食材", "购买新鲜蔬菜和肉类", "09:00", 60));
mTaskList.add(new TaskSchedulerBean("烹饪午餐", "按照食谱准备午餐", "10:00", 90));
mTaskList.add(new TaskSchedulerBean("用餐休息", "享受美食并休息", "11:30", 60));
mTaskList.add(new TaskSchedulerBean("清洁厨房", "清洗餐具和整理厨房", "12:30", 45));
mTaskList.add(new TaskSchedulerBean("准备晚餐", "提前准备晚餐食材", "16:00", 60));
mTaskList.add(new TaskSchedulerBean("烹饪晚餐", "制作丰盛的晚餐", "17:00", 90));
}
/**
* 显示编辑任务对话框
* @param position 要编辑的任务位置
*/
private void showEditTaskDialog(final int position) {
if (position < 0 || position >= mTaskList.size()) {
return;
}
final TaskSchedulerBean task = mTaskList.get(position);
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_task_edit);
// 初始化对话框控件
final EditText etTaskName = dialog.findViewById(R.id.dialog_et_task_name);
final EditText etStartTime = dialog.findViewById(R.id.dialog_et_start_time);
final EditText etDuration = dialog.findViewById(R.id.dialog_et_duration);
final EditText etRemark = dialog.findViewById(R.id.dialog_et_remark);
Button btnCancel = dialog.findViewById(R.id.dialog_btn_cancel);
Button btnSave = dialog.findViewById(R.id.dialog_btn_save);
// 填充现有数据
etTaskName.setText(task.getTaskName());
etStartTime.setText(task.getStartTime());
etDuration.setText(Integer.toString(task.getDurationMinutes()));
etRemark.setText(task.getRemark());
// 取消按钮
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
// 保存按钮
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 获取输入的数据
String taskName = etTaskName.getText().toString().trim();
String startTime = etStartTime.getText().toString().trim();
String durationStr = etDuration.getText().toString().trim();
String remark = etRemark.getText().toString().trim();
// 验证输入
if (taskName.isEmpty()) {
etTaskName.setError("请输入任务名称");
return;
}
if (startTime.isEmpty()) {
etStartTime.setError("请输入起始时间");
return;
}
if (durationStr.isEmpty()) {
etDuration.setError("请输入排档幅度");
return;
}
// 解析排档幅度
int duration = 0;
try {
duration = Integer.parseInt(durationStr);
} catch (NumberFormatException e) {
etDuration.setError("请输入有效的数字");
return;
}
// 更新任务数据
task.setTaskName(taskName);
task.setStartTime(startTime);
task.setDurationMinutes(duration);
task.setRemark(remark);
// 刷新列表
mAdapter.notifyItemChanged(position);
LogUtils.i(TAG, "showEditTaskDialog: 任务 [" + taskName + "] 数据已更新");
dialog.dismiss();
}
});
dialog.show();
}
/**
* 执行排档操作
* @param position 点击排档按钮的任务位置
*/
private void performSchedule(int position) {
if (position < 0 || position >= mTaskList.size()) {
return;
}
TaskSchedulerBean currentTask = mTaskList.get(position);
String currentTime = currentTask.getStartTime();
int duration = currentTask.getDurationMinutes();
// 计算新的时间
String newTime = addMinutesToTime(currentTime, duration);
LogUtils.i(TAG, "performSchedule: 当前时间 " + currentTime + " + " + duration + "分钟 = " + newTime);
// 更新下一个任务的时间(如果有)
if (position + 1 < mTaskList.size()) {
TaskSchedulerBean nextTask = mTaskList.get(position + 1);
nextTask.setStartTime(newTime);
mAdapter.notifyItemChanged(position + 1);
LogUtils.i(TAG, "performSchedule: 更新任务 [" + nextTask.getTaskName() + "] 时间更新为 " + newTime);
}
}
/**
* 将时间字符串加上分钟,返回新的时间字符串
* @param timeStr 格式为 "HH:mm" 的时间字符串
* @param minutes 要增加的分钟数
* @return 新的时间字符串
*/
private String addMinutesToTime(String timeStr, int minutes) {
try {
// 解析时间字符串
String[] parts = timeStr.split(":");
int hour = Integer.parseInt(parts[0]);
int minute = Integer.parseInt(parts[1]);
// 计算总分钟数
int totalMinutes = hour * 60 + minute + minutes;
// 计算新的小时和分钟
int newHour = (totalMinutes / 60) % 24;
int newMinute = totalMinutes % 60;
// 格式化返回
return String.format("%02d:%02d", newHour, newMinute);
} catch (Exception e) {
LogUtils.e(TAG, "addMinutesToTime: 时间解析错误", e);
return timeStr;
}
}
/**
* RecyclerView 适配器
*/
class TaskSchedulerAdapter extends RecyclerView.Adapter {
ArrayList<TaskSchedulerBean> mDataList;
public TaskSchedulerAdapter(ArrayList<TaskSchedulerBean> dataList) {
mDataList = dataList;
}
@Override
public int getItemCount() {
return mDataList.size();
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final TaskSchedulerBean item = mDataList.get(position);
final TaskViewHolder viewHolder = (TaskViewHolder) holder;
viewHolder.mtvTaskName.setText(item.getTaskName());
viewHolder.mtvStartTime.setText(item.getStartTime());
viewHolder.mtvDuration.setText(Integer.toString(item.getDurationMinutes()));
viewHolder.mtvRemark.setText(item.getRemark());
// 设置排档按钮点击事件 - 打开编辑对话框
viewHolder.mbtnSchedule.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showEditTaskDialog(position);
}
});
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_task_scheduler, parent, false);
return new TaskViewHolder(view);
}
class TaskViewHolder extends RecyclerView.ViewHolder {
TextView mtvTaskName;
TextView mtvStartTime;
TextView mtvDuration;
TextView mtvRemark;
Button mbtnSchedule;
TaskViewHolder(View itemView) {
super(itemView);
mtvTaskName = itemView.findViewById(R.id.item_task_name);
mtvStartTime = itemView.findViewById(R.id.item_start_time);
mtvDuration = itemView.findViewById(R.id.item_duration);
mtvRemark = itemView.findViewById(R.id.item_remark);
mbtnSchedule = itemView.findViewById(R.id.item_btn_schedule);
}
}
}
}
@@ -0,0 +1,117 @@
package cc.winboll.studio.stallhelper.beans;
/**
* @Author ZhanGSKen
* @Date 2026/05/18
* @Describe 任务排档数据模型
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class TaskSchedulerBean extends BaseBean {
public static final String TAG = "TaskSchedulerBean";
// 任务排档名称
String taskName;
// 备注
String remark;
// 起始任务排档时间
String startTime;
// 排档时间幅度(分钟)- 用于计算下一个任务的起始时间
int durationMinutes;
public TaskSchedulerBean() {
this.taskName = "";
this.remark = "";
this.startTime = "";
this.durationMinutes = 0;
}
public TaskSchedulerBean(String taskName, String remark, String startTime, int durationMinutes) {
this.taskName = taskName;
this.remark = remark;
this.startTime = startTime;
this.durationMinutes = durationMinutes;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public int getDurationMinutes() {
return durationMinutes;
}
public void setDurationMinutes(int durationMinutes) {
this.durationMinutes = durationMinutes;
}
@Override
public String getName() {
return TaskSchedulerBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
TaskSchedulerBean bean = this;
jsonWriter.name("taskName").value(bean.getTaskName());
jsonWriter.name("remark").value(bean.getRemark());
jsonWriter.name("startTime").value(bean.getStartTime());
jsonWriter.name("durationMinutes").value(bean.getDurationMinutes());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("taskName")) {
setTaskName(jsonReader.nextString());
} else if (name.equals("remark")) {
setRemark(jsonReader.nextString());
} else if (name.equals("startTime")) {
setStartTime(jsonReader.nextString());
} else if (name.equals("durationMinutes")) {
setDurationMinutes(jsonReader.nextInt());
} else {
return false;
}
}
return true;
}
@Override
public TaskSchedulerBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
jsonReader.endObject();
return this;
}
}
@@ -12,29 +12,11 @@
android:background="?attr/toolbarBackgroundColor"
android:id="@+id/toolbar"/>
<LinearLayout
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="任务排档"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="功能开发中..."
android:textSize="16sp"
android:layout_marginTop="16dp"
android:gravity="center"/>
</LinearLayout>
android:layout_height="0dp"
android:layout_weight="1"
android:padding="10dp"
android:id="@+id/task_scheduler_recycler_view"/>
</LinearLayout>
@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp"
android:background="?android:attr/windowBackground">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="编辑任务排档"
android:textSize="18sp"
android:textStyle="bold"
android:gravity="center"
android:paddingBottom="15dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="任务名称:"
android:textSize="14sp"
android:paddingBottom="5dp"/>
<EditText
android:id="@+id/dialog_et_task_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入任务名称"
android:inputType="text"
android:padding="10dp"
android:background="@android:drawable/edit_text"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="起始时间(HH:mm):"
android:textSize="14sp"
android:paddingTop="15dp"
android:paddingBottom="5dp"/>
<EditText
android:id="@+id/dialog_et_start_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="例如:09:00"
android:inputType="time"
android:padding="10dp"
android:background="@android:drawable/edit_text"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="排档幅度(分钟):"
android:textSize="14sp"
android:paddingTop="15dp"
android:paddingBottom="5dp"/>
<EditText
android:id="@+id/dialog_et_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入排档幅度"
android:inputType="number"
android:padding="10dp"
android:background="@android:drawable/edit_text"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="备注:"
android:textSize="14sp"
android:paddingTop="15dp"
android:paddingBottom="5dp"/>
<EditText
android:id="@+id/dialog_et_remark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入备注信息"
android:inputType="textMultiLine"
android:minLines="3"
android:gravity="top|start"
android:padding="10dp"
android:background="@android:drawable/edit_text"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="20dp"
android:gravity="end">
<Button
android:id="@+id/dialog_btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"
android:layout_marginEnd="10dp"/>
<Button
android:id="@+id/dialog_btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保存"/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/bg_frame"
android:padding="10dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="任务:"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"/>
<TextView
android:id="@+id/item_task_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"/>
<Button
android:id="@+id/item_btn_schedule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="排档"
android:textSize="12sp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间:"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/item_start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 排档幅度:"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/item_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分钟"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="备注:"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/item_remark"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时间:"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/item_start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 持续:"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/item_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分钟"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="备注:"
android:textAppearance="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/item_remark"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</LinearLayout>