个人作业老师登录的主页面与部分功能
Spring后端:
DailySummaryController
package com.example.demo.controller;
import com.example.demo.entity.DailySummary;
import com.example.demo.service.DailySummaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/dailySummary")
public class DailySummaryController {
@Autowired
private DailySummaryService dailySummaryService;
@PostMapping("/create")
public Map<String, Object> createSummary(@RequestBody DailySummary summary) {
Map<String, Object> result = new HashMap<>();
DailySummary created = dailySummaryService.createSummary(summary);
result.put("success", true);
result.put("data", created);
return result;
}
@GetMapping("/list/{studentId}")
public Map<String, Object> getStudentSummaries(@PathVariable String studentId) {
Map<String, Object> result = new HashMap<>();
List<DailySummary> summaries = dailySummaryService.getStudentSummaries(studentId);
result.put("success", true);
result.put("data", summaries);
return result;
}
@GetMapping("/today/{studentId}")
public Map<String, Object> getTodaySummary(@PathVariable String studentId) {
Map<String, Object> result = new HashMap<>();
DailySummary summary = dailySummaryService.getTodaySummary(studentId);
result.put("success", true);
result.put("data", summary);
return result;
}
@PutMapping("/update")
public Map<String, Object> updateSummary(@RequestBody DailySummary summary) {
Map<String, Object> result = new HashMap<>();
boolean success = dailySummaryService.updateSummary(summary);
result.put("success", success);
return result;
}
@DeleteMapping("/delete/{id}")
public Map<String, Object> deleteSummary(@PathVariable Integer id) {
Map<String, Object> result = new HashMap<>();
boolean success = dailySummaryService.deleteSummary(id);
result.put("success", success);
return result;
}
@GetMapping("/all")
public Map<String, Object> getAllSummaries() {
Map<String, Object> result = new HashMap<>();
List<DailySummary> summaries = dailySummaryService.getAllSummaries();
result.put("success", true);
result.put("data", summaries);
result.put("total", dailySummaryService.getTotalCheckInCount());
return result;
}
@GetMapping("/search")
public Map<String, Object> searchSummaries(@RequestParam String keyword) {
Map<String, Object> result = new HashMap<>();
List<DailySummary> summaries = dailySummaryService.searchSummaries(keyword);
result.put("success", true);
result.put("data", summaries);
return result;
}
@GetMapping("/statistics")
public Map<String, Object> getStatistics() {
Map<String, Object> result = new HashMap<>();
long uniqueCount = dailySummaryService.getUniqueCheckInCount();
result.put("success", true);
result.put("totalCheckIn", uniqueCount);
return result;
}
}
DailySummaryServiceImpl
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.entity.DailySummary;
import com.example.demo.mapper.DailySummaryMapper;
import com.example.demo.service.DailySummaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List;
@Service
public class DailySummaryServiceImpl implements DailySummaryService {
@Autowired
private DailySummaryMapper dailySummaryMapper;
@Override
public DailySummary createSummary(DailySummary summary) {
if (summary.getSummaryDate() == null) {
summary.setSummaryDate(LocalDate.now());
}
dailySummaryMapper.insert(summary);
return summary;
}
@Override
public List<DailySummary> getStudentSummaries(String studentId) {
QueryWrapper<DailySummary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("student_id", studentId)
.orderByDesc("summary_date");
return dailySummaryMapper.selectList(queryWrapper);
}
@Override
public DailySummary getTodaySummary(String studentId) {
QueryWrapper<DailySummary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("student_id", studentId)
.eq("summary_date", LocalDate.now());
return dailySummaryMapper.selectOne(queryWrapper);
}
@Override
public boolean updateSummary(DailySummary summary) {
return dailySummaryMapper.updateById(summary) > 0;
}
@Override
public boolean deleteSummary(Integer id) {
return dailySummaryMapper.deleteById(id) > 0;
}
@Override
public List<DailySummary> getAllSummaries() {
return dailySummaryMapper.selectList(null);
}
@Override
public List<DailySummary> searchSummaries(String keyword) {
QueryWrapper<DailySummary> queryWrapper = new QueryWrapper<>();
queryWrapper.like("summary_content", keyword)
.or()
.like("student_id", keyword)
.or()
.like("blog_url", keyword)
.orderByDesc("summary_date");
return dailySummaryMapper.selectList(queryWrapper);
}
@Override
public long getTotalCheckInCount() {
return dailySummaryMapper.selectCount(null);
}
@Override
public long getUniqueCheckInCount() {
QueryWrapper<DailySummary> queryWrapper = new QueryWrapper<>();
queryWrapper.select("DISTINCT student_id, DATE(summary_date)");
return dailySummaryMapper.selectCount(queryWrapper);
}
}
DailySummaryService
package com.example.demo.service;
import com.example.demo.entity.DailySummary;
import java.time.LocalDate;
import java.util.List;
public interface DailySummaryService {
DailySummary createSummary(DailySummary summary);
List<DailySummary> getStudentSummaries(String studentId);
DailySummary getTodaySummary(String studentId);
boolean updateSummary(DailySummary summary);
boolean deleteSummary(Integer id);
List<DailySummary> getAllSummaries();
List<DailySummary> searchSummaries(String keyword);
long getTotalCheckInCount();
long getUniqueCheckInCount(); // 添加新方法
}
安卓前端:
TeacherSummaryAdapter
package com.qi.demo.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.qi.demo.R
import com.qi.demo.entity.DailySummary
class TeacherSummaryAdapter(
private val summaries: MutableList<DailySummary> = mutableListOf()
) : RecyclerView.Adapter<TeacherSummaryAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val studentIdText: TextView = view.findViewById(R.id.studentIdText)
val dateText: TextView = view.findViewById(R.id.dateText)
val contentText: TextView = view.findViewById(R.id.contentText)
val blogUrlText: TextView = view.findViewById(R.id.blogUrlText)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_teacher_summary, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val summary = summaries[position]
holder.studentIdText.text = "学号:${summary.studentId}"
holder.dateText.text = "日期:${summary.summaryDate}"
holder.contentText.text = summary.summaryContent
holder.blogUrlText.text = summary.blogUrl
}
override fun getItemCount() = summaries.size
fun updateSummaries(newSummaries: List<DailySummary>) {
summaries.clear()
summaries.addAll(newSummaries)
notifyDataSetChanged()
}
}
DailySummaryService
package com.qi.demo.service
import com.qi.demo.entity.DailySummary
import retrofit2.Call
import retrofit2.http.*
interface DailySummaryService {
@POST("/dailySummary/create")
fun createSummary(@Body summary: DailySummary): Call<Map<String, Any>>
@GET("/dailySummary/list/{studentId}")
fun getStudentSummaries(@Path("studentId") studentId: String): Call<Map<String, Any>>
@GET("/dailySummary/today/{studentId}")
fun getTodaySummary(@Path("studentId") studentId: String): Call<Map<String, Any>>
@PUT("/dailySummary/update")
fun updateSummary(@Body summary: DailySummary): Call<Map<String, Any>>
@DELETE("/dailySummary/delete/{id}")
fun deleteSummary(@Path("id") id: Int): Call<Map<String, Any>>
@GET("/dailySummary/all")
fun getAllSummaries(): Call<Map<String, Any>>
@GET("/dailySummary/search")
fun searchSummaries(@Query("keyword") keyword: String): Call<Map<String, Any>>
}
DailySummaryActivity
package com.qi.demo
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.qi.demo.adapter.DailySummaryAdapter
import com.qi.demo.entity.DailySummary
import com.qi.demo.network.ServiceCreator
import com.qi.demo.service.DailySummaryService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.time.LocalDate
class DailySummaryActivity : AppCompatActivity() {
private lateinit var summaryInput: EditText
private lateinit var blogUrlInput: EditText
private lateinit var submitButton: Button
private lateinit var summaryList: RecyclerView
private lateinit var adapter: DailySummaryAdapter
private val dailySummaryService = ServiceCreator.create<DailySummaryService>()
private var studentId: String? = null
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_daily_summary)
studentId = intent.getStringExtra("studentId")
initViews()
setupRecyclerView()
loadSummaries()
submitButton.setOnClickListener {
submitSummary()
}
findViewById<Button>(R.id.backButton).setOnClickListener {
finish()
}
}
private fun initViews() {
summaryInput = findViewById(R.id.summaryInput)
blogUrlInput = findViewById(R.id.blogUrlInput)
submitButton = findViewById(R.id.submitButton)
summaryList = findViewById(R.id.summaryList)
}
private fun setupRecyclerView() {
adapter = DailySummaryAdapter()
summaryList.layoutManager = LinearLayoutManager(this)
summaryList.adapter = adapter
}
private fun loadSummaries() {
studentId?.let { id ->
dailySummaryService.getStudentSummaries(id).enqueue(object : Callback<Map<String, Any>> {
override fun onResponse(call: Call<Map<String, Any>>, response: Response<Map<String, Any>>) {
val result = response.body()
if (result?.get("success") == true) {
@Suppress("UNCHECKED_CAST")
val dataList = result["data"] as List<Map<String, Any>>
val summaries = dataList.map { map ->
DailySummary(
id = (map["id"] as Double).toInt(),
studentId = map["studentId"] as String,
summaryContent = map["summaryContent"] as String,
blogUrl = map["blogUrl"] as String?,
summaryDate = map["summaryDate"] as String?
)
}
adapter.updateSummaries(summaries)
}
}
override fun onFailure(call: Call<Map<String, Any>>, t: Throwable) {
Toast.makeText(this@DailySummaryActivity, "加载失败", Toast.LENGTH_SHORT).show()
}
})
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun submitSummary() {
val content = summaryInput.text.toString()
val blogUrl = blogUrlInput.text.toString()
if (content.isEmpty() || blogUrl.isEmpty()) {
Toast.makeText(this, "请填写完整信息", Toast.LENGTH_SHORT).show()
return
}
val summary = DailySummary(
studentId = studentId ?: "",
summaryContent = content,
blogUrl = blogUrl,
summaryDate = LocalDate.now().toString()
)
dailySummaryService.createSummary(summary).enqueue(object : Callback<Map<String, Any>> {
override fun onResponse(call: Call<Map<String, Any>>, response: Response<Map<String, Any>>) {
val result = response.body()
if (result?.get("success") == true) {
Toast.makeText(this@DailySummaryActivity, "提交成功", Toast.LENGTH_SHORT).show()
summaryInput.text.clear()
blogUrlInput.text.clear()
loadSummaries()
} else {
Toast.makeText(this@DailySummaryActivity, "提交失败", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<Map<String, Any>>, t: Throwable) {
Toast.makeText(this@DailySummaryActivity, "提交失败", Toast.LENGTH_SHORT).show()
}
})
}
}
activity_teacher_main.xml
<?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="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/welcomeText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="教师管理系统"
android:textSize="24sp"
android:gravity="center"
android:layout_marginBottom="32dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<Button
android:id="@+id/viewStudentsButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="查看学生列表"
android:layout_marginEnd="8dp"/>
<Button
android:id="@+id/viewRecordsButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="查看打卡记录"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="总打卡人数:"
android:textSize="16sp"/>
<TextView
android:id="@+id/totalCheckInCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@android:color/holo_blue_dark"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<EditText
android:id="@+id/searchInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="输入关键字搜索"/>
<Button
android:id="@+id/searchButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/summaryList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
item_teacher_summary.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/studentIdText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"/>
<TextView
android:id="@+id/dateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"/>
<TextView
android:id="@+id/contentText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>
<TextView
android:id="@+id/blogUrlText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@android:color/holo_blue_dark"
android:autoLink="web"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
浙公网安备 33010602011771号