Daily Performance Management System Built with Spring Boot, Vue.js, and UniApp
Technology Stack
Backend Framework: Spring Boot
Spring Boot, built atop Spring Framework, simplifies enterprise-grade Java application development by embedding servers like Tomcat, Jetty, or Undertow directly. Its auto-configuration mechanism tailors settings based on project dependencies, while integrated modules such as Spring Data JPA, Spring Security, and Spring Cloud streamline common tasks like data access, authentication, and microservices orchestration. This reduces boilerplate code drastically, shortens development cycles, and improves maintainability and scalability.
Here’s a modified minimal example:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class CourseScoreApp {
public static void main(String[] args) {
SpringApplication.run(CourseScoreApp.class, args);
}
@GetMapping("/greet/{username}")
public String welcomeUser(@PathVariable String username) {
return String.format("Welcome %s to the Daily Score System!", username);
}
}
This code creates a Spring Boot app with a REST endpoint that greets a user by name, auto-configuring an embedded server accessible at http://localhost:8080/greet/[username].
Frontend Framework: Vue.js
Vue.js is a progressive JavaScript framework ideal for building single-page applications (SPAs) and reusable UI components. Its reactive data-binding system ensures automatic UI updates when underlying data changes, while the virtual DOM minimizes costly DOM manipulations. Component-based architecture encapsulates logic, templates, and styles, making code modular and easy to test.
A revised Vue 3 demo using composition API:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Score Tracker Snippet</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="score-widget">
<h3>Current Quiz Score: {{ quizScore }}</h3>
<button @click="addBonusPoints(5)">Add 5 Bonus Points</button>
<button @click="resetScore">Reset</button>
</div>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const quizScore = ref(0);
const addBonusPoints = (points) => quizScore.value += points;
const resetScore = () => quizScore.value = 0;
return { quizScore, addBonusPoints, resetScore };
}
}).mount('#score-widget');
</script>
</body>
</html>
This snippet uses Vue 3’s composition API to manage a quiz score state, with buttons to adjust or reset it, demonstrating reactive updates.
Persistence Layer: MyBatis
MyBatis is an open-source ORM alternative that decouples SQL logic from Java code via XML mappings or annotations. It offers fine-grained control over SQL queries, supports dynamic SQL generation for complex conditional operations, and provides first- and second-level caching to reduce database round-trips. Its plugin architecture allows easy customization for advanced use cases.
System Testing
Functional Testing Approach
Black-box testing is used to validate core system workflows without examining internal code. Test cases cover edge values, required field validation, and role-based access control. Each test case documents input data, expected results, actual results, and analysis.
Login Module Test Cases
| Test Input | Expected Outcome | Actual Outcome | Analysis |
|---|---|---|---|
| Teacher ID: TCH001, Password: SecurePass123, Captcha: ABCD | Redirect to teacher dashboard | Successfully navigated to dashboard | Pass |
| Teacher ID: TCH001, Password: WrongPass, Captcha: ABCD | Display "Invalid credentials" | Invalid credentials shown | Pass |
| Teacher ID: empty, Password: SecurePass123, Captcha: ABCD | Highlight empty field and prompt | Field highlighted and required prompt displayed | Pass |
| Teacher ID: TCH001, Password: SecurePass123, Captcha: wrong | Display "Captcha mismatch" | Captcha mismatch shown | Pass |
Student Score Entry Module Test Cases
| Test Input | Expected Outcome | Actual Outcome | Analysis |
|---|---|---|---|
| Student ID: STD202, Quiz Score: 85, Date: 2024-05-20 | Save score and update list | Score saved and list refreshed | Pass |
| Student ID: STD202, Quiz Score: 110, Date: 2024-05-20 | Prompt "Score must be 0-100" | Score range error displayed | Pass |
| Student ID: empty, Quiz Score: 70, Date: 2024-05-20 | Highlight empty field | Field highlighted and required prompt displayed | Pass |
Test Conclusion
All core functional modules (login, score management, user management, report generation) passed black-box testing. The system behaves as specified, handles invalid inputs gracefully, and enforces role-based accesss control correctly. Performance under light load is acceptable for typical classroom use.
Code Reference Snippets
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.dailyscore.entity.SysUser;
import com.example.dailyscore.service.SysUserService;
import com.example.dailyscore.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private SysUserService sysUserService;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/signin")
public Map<String, Object> authenticate(@RequestBody Map<String, String> loginData) {
Map<String, Object> response = new HashMap<>();
String userId = loginData.get("userId");
String password = loginData.get("password");
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUserId, userId);
SysUser user = sysUserService.getOne(queryWrapper);
if (user == null || !user.getPassword().equals(password)) {
response.put("code", 401);
response.put("msg", "Invalid user ID or password");
return response;
}
String token = jwtUtil.createToken(user.getId(), user.getUserId(), user.getRole());
response.put("code", 200);
response.put("msg", "Login successful");
response.put("token", token);
response.put("userInfo", user);
return response;
}
}
This modified authentication controller uses MyBatis-Plus’s LambdaQueryWrapper for type-safe queries and JWT for stateless authentication.
Database Schema Example
-- Daily score record table
DROP TABLE IF EXISTS `daily_score`;
CREATE TABLE `daily_score` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
`student_id` VARCHAR(50) NOT NULL COMMENT 'Unique student ID',
`course_id` VARCHAR(50) NOT NULL COMMENT 'Unique course ID',
`score_type` VARCHAR(30) NOT NULL COMMENT 'e.g., quiz, homework, attendance',
`score_value` DECIMAL(5,2) NOT NULL COMMENT 'Score between 0.00 and 100.00',
`record_date` DATE NOT NULL COMMENT 'Date of score entry',
`teacher_id` VARCHAR(50) NOT NULL COMMENT 'ID of teacher who recorded the score',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation timestamp',
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Last update timestamp',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_student_course` (`student_id`, `course_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Daily performance score records';
-- Sample score entries
INSERT INTO `daily_score` (`student_id`, `course_id`, `score_type`, `score_value`, `record_date`, `teacher_id`)
VALUES ('STD2024001', 'CS101', 'homework', 92.50, '2024-05-19', 'TCH2024001'),
('STD2024001', 'CS101', 'quiz', 87.00, '2024-05-20', 'TCH2024001'),
('STD2024002', 'CS101', 'attendance', 100.00, '2024-05-20', 'TCH2024001');