diff --git a/README.md b/README.md
deleted file mode 100644
index 576c717..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# test
-
diff --git a/doc/1.pptx b/doc/1.pptx
new file mode 100644
index 0000000..acc09ad
Binary files /dev/null and b/doc/1.pptx differ
diff --git a/doc/文档模板-开源软件维护报告文档 .docx b/doc/文档模板-开源软件维护报告文档 .docx
new file mode 100644
index 0000000..2b3a13b
Binary files /dev/null and b/doc/文档模板-开源软件维护报告文档 .docx differ
diff --git a/src/dairy/src/main/AndroidManifest.xml b/src/dairy/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d2bbc47
--- /dev/null
+++ b/src/dairy/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/dairy/src/main/ic_launcher-playstore.png b/src/dairy/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..83d1d54
Binary files /dev/null and b/src/dairy/src/main/ic_launcher-playstore.png differ
diff --git a/src/dairy/src/main/java/com/app/diary/Mapp.java b/src/dairy/src/main/java/com/app/diary/Mapp.java
new file mode 100644
index 0000000..252b622
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/Mapp.java
@@ -0,0 +1,61 @@
+package com.app.diary;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.room.Room;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import com.app.diary.data.DiaryDataSource;
+import com.app.diary.data.impl.DiaryDataSourceImpl;
+import com.app.diary.room.database.AppDatabase;
+
+public class Mapp extends Application {
+
+ private static Mapp instance;//单例
+
+ private AppDatabase appDatabase;//数据库
+ private DiaryDataSource diaryDataSource;//日记数据源
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ instance = this;
+ }
+
+ /**
+ * 获取实例
+ */
+ public static Mapp getInstance() {
+ return instance;
+ }
+
+ /**
+ * 懒加载获取数据库
+ */
+ public AppDatabase getAppDatabase() {
+ if (appDatabase == null) {
+ appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "diary.db").addMigrations(new Migration(1, 2) {
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // 将SQLite迁移到Room,数据结构未发生变化,所以这里不做任何处理,保持空实现
+ }
+
+ }).build();
+ }
+ return appDatabase;
+ }
+
+ /**
+ * 懒加载获取日记数据源
+ */
+ public DiaryDataSource getDiaryDataSource() {
+ if (diaryDataSource == null) {
+ diaryDataSource = new DiaryDataSourceImpl(getAppDatabase());
+ }
+ return diaryDataSource;
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/adapter/DiaryRecyclerAdapter.java b/src/dairy/src/main/java/com/app/diary/adapter/DiaryRecyclerAdapter.java
new file mode 100644
index 0000000..6047234
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/adapter/DiaryRecyclerAdapter.java
@@ -0,0 +1,114 @@
+package com.app.diary.adapter;
+
+import android.annotation.SuppressLint;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.app.diary.R;
+import com.app.diary.bean.Diary;
+import com.app.diary.utils.TimeUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+public class DiaryRecyclerAdapter extends RecyclerView.Adapter {
+
+ private List list;//日记本列表数据
+ private LayoutInflater inflater;//布局填充器
+
+ private OnItemClickListener onItemClickListener;//点击事件
+
+ @Override
+ public int getItemCount() {
+ return list == null ? 0 : list.size();
+ }
+
+ @NonNull
+ @Override
+ public DiaryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ //布局填充器可以重复使用,所以这里使用懒加载的方式创建
+ if (inflater == null) {
+ inflater = LayoutInflater.from(parent.getContext());
+ }
+ View view = inflater.inflate(R.layout.item_recycler_diary, parent, false);
+ return new DiaryViewHolder(view);
+ }
+
+ @SuppressLint("RecyclerView")
+ @Override
+ public void onBindViewHolder(@NonNull DiaryViewHolder holder, int position) {
+ Diary diary = list.get(position);
+
+ holder.rowLinearLayout.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (onItemClickListener != null) {
+ onItemClickListener.onItemClick(diary, position);
+ }
+ }
+
+ });
+ holder.dateTextView.setText(new SimpleDateFormat("yyyy年MM月dd日").format(diary.getDate()));
+ holder.weatherTextView.setText(diary.getWeather());
+ holder.titleTextView.setText(diary.getTitle());
+ holder.wordCountTextView.setText("字数" + diary.getContent().length() + "个");
+ holder.updateTimeTextView.setText("编辑于" + TimeUtils.getSimpleTime(diary.getUpdateTime().getTime()));
+ }
+
+ /**
+ * 设置新数据
+ */
+ public void setNewData(@Nullable List list) {
+ this.list = list;
+ notifyDataSetChanged();
+ }
+
+ /**
+ * 设置单个日记的点击事件
+ */
+ public void setOnItemClickListener(@Nullable OnItemClickListener listener) {
+ this.onItemClickListener = listener;
+ }
+
+ /**
+ * 视图固定器
+ */
+ public class DiaryViewHolder extends RecyclerView.ViewHolder {
+
+ LinearLayout rowLinearLayout;//行布局控件
+ TextView dateTextView;//日记时间文本控件
+ TextView weatherTextView;//天气文本控件
+ TextView titleTextView;//标题文本控件
+ TextView wordCountTextView;//字数文本控件
+ TextView updateTimeTextView;//修改时间文本控件
+
+ public DiaryViewHolder(@NonNull View itemView) {
+ super(itemView);
+ rowLinearLayout = itemView.findViewById(R.id.row_linearLayout);
+ dateTextView = itemView.findViewById(R.id.date_textView);
+ weatherTextView = itemView.findViewById(R.id.weather_textView);
+ titleTextView = itemView.findViewById(R.id.title_textView);
+ wordCountTextView = itemView.findViewById(R.id.wordCount_textView);
+ updateTimeTextView = itemView.findViewById(R.id.updateTime_textView);
+ }
+
+ }
+
+ /**
+ * 日记的点击事件
+ */
+ public interface OnItemClickListener {
+
+ void onItemClick(Diary diary, int position);
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/bean/BaseBean.java b/src/dairy/src/main/java/com/app/diary/bean/BaseBean.java
new file mode 100644
index 0000000..d9ed6dd
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/bean/BaseBean.java
@@ -0,0 +1,9 @@
+package com.app.diary.bean;
+
+import java.io.Serializable;
+
+/**
+ * 数据的基础类
+ */
+public class BaseBean implements Serializable {
+}
diff --git a/src/dairy/src/main/java/com/app/diary/bean/Constant.java b/src/dairy/src/main/java/com/app/diary/bean/Constant.java
new file mode 100644
index 0000000..80656bc
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/bean/Constant.java
@@ -0,0 +1,7 @@
+package com.app.diary.bean;
+
+public class Constant {
+
+ public static String DATA_CHANGE = "data_change";//数据是否改变
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/bean/Diary.java b/src/dairy/src/main/java/com/app/diary/bean/Diary.java
new file mode 100644
index 0000000..8137d79
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/bean/Diary.java
@@ -0,0 +1,96 @@
+package com.app.diary.bean;
+
+import androidx.annotation.NonNull;
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+import java.util.Date;
+
+/**
+ * 日记
+ */
+@Entity(tableName = "diary")
+public class Diary extends BaseBean {
+
+ @NonNull
+ @PrimaryKey(autoGenerate = true)
+ private Long id;//主键
+
+ @NonNull
+ private Date date;//日期
+
+ @NonNull
+ private String weather;//天气
+
+ @NonNull
+ private String title;//标题
+
+ @NonNull
+ private String content;//内容
+
+ @NonNull
+ @ColumnInfo(name = "create_time")
+ private Date createTime;//创建时间
+
+ @NonNull
+ @ColumnInfo(name = "update_time")
+ private Date updateTime;//修改时间
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public String getWeather() {
+ return weather;
+ }
+
+ public void setWeather(String weather) {
+ this.weather = weather;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/data/DiaryDataSource.java b/src/dairy/src/main/java/com/app/diary/data/DiaryDataSource.java
new file mode 100644
index 0000000..b780a23
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/data/DiaryDataSource.java
@@ -0,0 +1,42 @@
+package com.app.diary.data;
+
+import androidx.annotation.NonNull;
+
+import com.app.diary.bean.Diary;
+
+import java.util.List;
+
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Single;
+
+/**
+ * 日记本数据源
+ */
+public interface DiaryDataSource {
+
+ /**
+ * 新增一条日记本
+ */
+ Completable insertDiary(@NonNull Diary diary);
+
+ /**
+ * 删除一条日记本
+ */
+ Completable deleteDiary(long diaryId);
+
+ /**
+ * 修改一条日记本
+ */
+ Completable updateDiary(@NonNull Diary diary);
+
+ /**
+ * 根据主键查询日记本
+ */
+ Single selectOne(long diaryId);
+
+ /**
+ * 查找日记本列表
+ */
+ Single> selectList();
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/data/impl/DiaryDataSourceImpl.java b/src/dairy/src/main/java/com/app/diary/data/impl/DiaryDataSourceImpl.java
new file mode 100644
index 0000000..71d19b1
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/data/impl/DiaryDataSourceImpl.java
@@ -0,0 +1,58 @@
+package com.app.diary.data.impl;
+
+import androidx.annotation.NonNull;
+
+import com.app.diary.bean.Diary;
+import com.app.diary.data.DiaryDataSource;
+import com.app.diary.room.database.AppDatabase;
+
+import java.util.Date;
+import java.util.List;
+
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Single;
+
+/**
+ * 日志数据源的实现类
+ */
+public class DiaryDataSourceImpl implements DiaryDataSource {
+
+ @NonNull
+ private AppDatabase appDatabase;
+
+ public DiaryDataSourceImpl(@NonNull AppDatabase appDatabase) {
+ this.appDatabase = appDatabase;
+ }
+
+ @Override
+ public Completable insertDiary(@NonNull Diary diary) {
+ Date now = new Date();
+ diary.setCreateTime(now);
+ diary.setUpdateTime(now);
+ return appDatabase.diaryDao().insert(diary);
+ }
+
+ @Override
+ public Completable deleteDiary(long diaryId) {
+ Diary diary = new Diary();
+ diary.setId(diaryId);
+ return appDatabase.diaryDao().delete(diary);
+ }
+
+ @Override
+ public Completable updateDiary(@NonNull Diary diary) {
+ diary.setUpdateTime(new Date());
+ return appDatabase.diaryDao().update(diary);
+ }
+
+ @Override
+ public Single selectOne(long diaryId) {
+ return appDatabase.diaryDao().getOne(diaryId);
+ }
+
+ @Override
+ public Single> selectList() {
+ return appDatabase.diaryDao().getList();
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/room/converter/DateConverter.java b/src/dairy/src/main/java/com/app/diary/room/converter/DateConverter.java
new file mode 100644
index 0000000..16a42ad
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/room/converter/DateConverter.java
@@ -0,0 +1,19 @@
+package com.app.diary.room.converter;
+
+import androidx.room.TypeConverter;
+
+import java.util.Date;
+
+public class DateConverter {
+
+ @TypeConverter
+ public static Date timestampToDate(Long timestamp) {
+ return timestamp == null ? null : new Date(timestamp);
+ }
+
+ @TypeConverter
+ public static Long dateToTimestamp(Date date) {
+ return date == null ? null : date.getTime();
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/room/dao/DiaryDao.java b/src/dairy/src/main/java/com/app/diary/room/dao/DiaryDao.java
new file mode 100644
index 0000000..b9d8559
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/room/dao/DiaryDao.java
@@ -0,0 +1,49 @@
+package com.app.diary.room.dao;
+
+import androidx.room.Dao;
+import androidx.room.Delete;
+import androidx.room.Insert;
+import androidx.room.Query;
+import androidx.room.Update;
+
+import com.app.diary.bean.Diary;
+
+import java.util.List;
+
+import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Single;
+
+@Dao
+public interface DiaryDao {
+
+ /**
+ * 新增日记
+ */
+ @Insert
+ Completable insert(Diary diary);
+
+ /**
+ * 删除日记
+ */
+ @Delete
+ Completable delete(Diary diary);
+
+ /**
+ * 修改日记
+ */
+ @Update
+ Completable update(Diary diary);
+
+ /**
+ * 获取日记列表
+ */
+ @Query("SELECT * FROM diary ORDER BY date DESC")
+ Single> getList();
+
+ /**
+ * 获取日记详情
+ */
+ @Query("SELECT * FROM diary WHERE id = (:diaryId)")
+ Single getOne(long diaryId);
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/room/database/AppDatabase.java b/src/dairy/src/main/java/com/app/diary/room/database/AppDatabase.java
new file mode 100644
index 0000000..1553ff3
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/room/database/AppDatabase.java
@@ -0,0 +1,17 @@
+package com.app.diary.room.database;
+
+import androidx.room.Database;
+import androidx.room.RoomDatabase;
+import androidx.room.TypeConverters;
+
+import com.app.diary.bean.Diary;
+import com.app.diary.room.converter.DateConverter;
+import com.app.diary.room.dao.DiaryDao;
+
+@Database(entities = {Diary.class}, version = 2)
+@TypeConverters({DateConverter.class})
+public abstract class AppDatabase extends RoomDatabase {
+
+ public abstract DiaryDao diaryDao();
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/ui/BaseActivity.java b/src/dairy/src/main/java/com/app/diary/ui/BaseActivity.java
new file mode 100644
index 0000000..47bcf19
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/ui/BaseActivity.java
@@ -0,0 +1,33 @@
+package com.app.diary.ui;
+
+import android.view.MenuItem;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.navigation.ActivityNavigator;
+
+/**
+ * 页面的基础类
+ */
+public class BaseActivity extends AppCompatActivity {
+
+ /**
+ * 设置菜单点击
+ */
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ //设置标题栏的返回键点击事件
+ if (item.getItemId() == android.R.id.home) {
+ //页面返回
+ getOnBackPressedDispatcher().onBackPressed();
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ ActivityNavigator.applyPopAnimationsToPendingTransition(this);
+ }
+
+}
diff --git a/src/dairy/src/main/java/com/app/diary/ui/BaseFragment.java b/src/dairy/src/main/java/com/app/diary/ui/BaseFragment.java
new file mode 100644
index 0000000..8d462b4
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/ui/BaseFragment.java
@@ -0,0 +1,38 @@
+package com.app.diary.ui;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.fragment.app.Fragment;
+import androidx.navigation.NavController;
+import androidx.navigation.fragment.NavHostFragment;
+
+/**
+ * Fragment的基础类
+ */
+public class BaseFragment extends Fragment {
+
+ /**
+ * 获取导航控制器
+ */
+ protected NavController getNavController() {
+ return NavHostFragment.findNavController(this);
+ }
+
+ /**
+ * 初始化标题栏
+ *
+ * @param toolbar 标题栏
+ * @param showBack 是否显示返回键
+ */
+ protected void initSupportActionBar(@NonNull Toolbar toolbar, boolean showBack) {
+ if (getActivity() != null && (getActivity() instanceof AppCompatActivity)) {
+ if (toolbar.getTitle() == null) {
+ toolbar.setTitle("");
+ }
+ ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
+ ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(showBack);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/ui/BaseViewModel.java b/src/dairy/src/main/java/com/app/diary/ui/BaseViewModel.java
new file mode 100644
index 0000000..0a06636
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/ui/BaseViewModel.java
@@ -0,0 +1,35 @@
+package com.app.diary.ui;
+
+import android.app.Application;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+
+import io.reactivex.rxjava3.disposables.CompositeDisposable;
+import io.reactivex.rxjava3.disposables.Disposable;
+
+public class BaseViewModel extends AndroidViewModel {
+
+ protected boolean loaded;//是否已加载过数据
+ private CompositeDisposable compositeDisposable;
+
+ public BaseViewModel(@NonNull Application application) {
+ super(application);
+ }
+
+ public void addDisposable(@NonNull Disposable disposable) {
+ if (compositeDisposable == null) {
+ compositeDisposable = new CompositeDisposable();
+ }
+ compositeDisposable.add(disposable);
+ }
+
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ if (compositeDisposable != null) {
+ compositeDisposable.clear();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/dairy/src/main/java/com/app/diary/ui/DiaryBrowseFragment.java b/src/dairy/src/main/java/com/app/diary/ui/DiaryBrowseFragment.java
new file mode 100644
index 0000000..7859676
--- /dev/null
+++ b/src/dairy/src/main/java/com/app/diary/ui/DiaryBrowseFragment.java
@@ -0,0 +1,187 @@
+package com.app.diary.ui;
+
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.view.MenuProvider;
+import androidx.core.widget.NestedScrollView;
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.SavedStateHandle;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.navigation.NavBackStackEntry;
+
+import com.app.diary.R;
+import com.app.diary.bean.Constant;
+import com.app.diary.bean.Diary;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * 日志浏览
+ */
+public class DiaryBrowseFragment extends BaseFragment {
+
+ private Toolbar toolbar;//标题栏控件
+ private NestedScrollView scrollView;//滑动控件
+ private TextView dateTextView;//日期文本控件
+ private TextView weekTextView;//星期文本控件
+ private TextView weatherTextView;//天气文本控件
+ private TextView titleTextView;//标题文本控件
+ private TextView contentTextView;//内容文本控件
+ private TextView errorTextView;//错误文本控件
+
+ private long diaryId;//日记主键
+ private DiaryBrowseViewModel diaryBrowseViewModel;
+ private SavedStateHandle savedStateHandle;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ NavBackStackEntry navBackStackEntry = getNavController().getCurrentBackStackEntry();
+ navBackStackEntry.getSavedStateHandle().getLiveData(Constant.DATA_CHANGE).observe(navBackStackEntry, new Observer