5.30测试源代码
`package com.example.test.controller;
import com.example.test.entity.;
import com.example.test.service.AdminService;
import com.example.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.;
import jakarta.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
-
管理员控制器,提供对所有表的增删改查操作
*/
@RestController
@RequestMapping("/api/admin")
public class AdminController {private final UserService userService;
private final AdminService adminService;@Autowired
public AdminController(UserService userService, AdminService adminService) {
this.userService = userService;
this.adminService = adminService;
}/**
- 检查管理员权限
*/
private boolean checkAdminPermission(HttpSession session) {
User currentUser = (User) session.getAttribute("currentUser");
return currentUser != null && currentUser.isAdmin();
}
/**
- 获取未授权响应
*/
private ResponseEntity<?> getUnauthorizedResponse() {
Map<String, String> response = new HashMap<>();
response.put("message", "未授权的操作,需要管理员权限");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
}
/**
-
获取指定实体的所有记录
*/
@GetMapping("/{entityName}")
public ResponseEntity<?> getAllEntities(
@PathVariable String entityName,
HttpSession session) {// 检查管理员权限
if (!checkAdminPermission(session)) {
return getUnauthorizedResponse();
}try {
// 根据实体名称获取对应的类
Class<?> entityClass = adminService.getEntityClassByName(entityName);
if (entityClass == null) {
Map<String, String> response = new HashMap<>();
response.put("message", "实体不存在: " + entityName);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}// 查询所有记录 List<?> entities = adminService.findAll(entityClass); return ResponseEntity.ok(entities);
} catch (Exception e) {
Map<String, String> response = new HashMap<>();
response.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
/**
-
根据ID获取指定实体的记录
*/
@GetMapping("/{entityName}/{id}")
public ResponseEntity<?> getEntityById(
@PathVariable String entityName,
@PathVariable Long id,
HttpSession session) {// 检查管理员权限
if (!checkAdminPermission(session)) {
return getUnauthorizedResponse();
}try {
// 根据实体名称获取对应的类
Class<?> entityClass = adminService.getEntityClassByName(entityName);
if (entityClass == null) {
Map<String, String> response = new HashMap<>();
response.put("message", "实体不存在: " + entityName);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}// 查询指定ID的记录 Object entity = adminService.findById(entityClass, id); if (entity == null) { Map<String, String> response = new HashMap<>(); response.put("message", "未找到ID为: " + id + " 的记录"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response); } return ResponseEntity.ok(entity);
} catch (Exception e) {
Map<String, String> response = new HashMap<>();
response.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
/**
-
创建实体记录
*/
@PostMapping("/{entityName}")
public ResponseEntity<?> createEntity(
@PathVariable String entityName,
@RequestBody Object entityData,
HttpSession session) {// 检查管理员权限
if (!checkAdminPermission(session)) {
return getUnauthorizedResponse();
}try {
// 保存实体
Object savedEntity = adminService.save(entityData);
return ResponseEntity.status(HttpStatus.CREATED).body(savedEntity);} catch (Exception e) {
Map<String, String> response = new HashMap<>();
response.put("message", "创建失败: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
/**
-
更新实体记录
*/
@PutMapping("/{entityName}/{id}")
public ResponseEntity<?> updateEntity(
@PathVariable String entityName,
@PathVariable Long id,
@RequestBody Object entityData,
HttpSession session) {// 检查管理员权限
if (!checkAdminPermission(session)) {
return getUnauthorizedResponse();
}try {
// 根据实体名称获取对应的类
Class<?> entityClass = adminService.getEntityClassByName(entityName);
if (entityClass == null) {
Map<String, String> response = new HashMap<>();
response.put("message", "实体不存在: " + entityName);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}// 查询指定ID的记录 Object entity = adminService.findById(entityClass, id); if (entity == null) { Map<String, String> response = new HashMap<>(); response.put("message", "未找到ID为: " + id + " 的记录"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response); } // 更新实体 Object updatedEntity = adminService.save(entityData); return ResponseEntity.ok(updatedEntity);
} catch (Exception e) {
Map<String, String> response = new HashMap<>();
response.put("message", "更新失败: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
/**
-
删除实体记录
*/
@DeleteMapping("/{entityName}/{id}")
public ResponseEntity<?> deleteEntity(
@PathVariable String entityName,
@PathVariable Long id,
HttpSession session) {// 检查管理员权限
if (!checkAdminPermission(session)) {
return getUnauthorizedResponse();
}try {
// 根据实体名称获取对应的类
Class<?> entityClass = adminService.getEntityClassByName(entityName);
if (entityClass == null) {
Map<String, String> response = new HashMap<>();
response.put("message", "实体不存在: " + entityName);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}// 查询指定ID的记录 Object entity = adminService.findById(entityClass, id); if (entity == null) { Map<String, String> response = new HashMap<>(); response.put("message", "未找到ID为: " + id + " 的记录"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response); } // 删除实体 adminService.delete(entityClass, id); Map<String, String> response = new HashMap<>(); response.put("message", "记录已成功删除"); return ResponseEntity.ok(response);
} catch (Exception e) {
Map<String, String> response = new HashMap<>();
response.put("message", "删除失败: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
}package com.example.test.controller;
- 检查管理员权限
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
/**
-
自定义错误控制器
-
处理应用程序中的错误,提供友好的错误页面
*/
@Controller
public class CustomErrorController implements ErrorController {private final ErrorAttributes errorAttributes;
public CustomErrorController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}/**
-
处理HTML请求的错误页面
*/
@RequestMapping(value = "/error", produces = "text/html")
public String errorHtml(HttpServletRequest request, Model model) {
// 获取错误属性
WebRequest webRequest = new ServletWebRequest(request);
Map<String, Object> errorAttributes = this.errorAttributes.getErrorAttributes(
webRequest, ErrorAttributeOptions.defaults());// 将错误属性添加到模型中
model.addAllAttributes(errorAttributes);// 获取HTTP状态码
HttpStatus status = getStatus(request);
model.addAttribute("status", status.value());
model.addAttribute("error", status.getReasonPhrase());// 返回错误视图
return "error";
}
/**
-
处理API请求的错误响应
*/
@RequestMapping(value = "/error")
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
// 获取错误属性
WebRequest webRequest = new ServletWebRequest(request);
Map<String, Object> body = this.errorAttributes.getErrorAttributes(
webRequest, ErrorAttributeOptions.defaults());// 获取HTTP状态码
HttpStatus status = getStatus(request);// 返回错误响应
return new ResponseEntity<>(body, status);
}
/**
- 获取HTTP状态码
*/
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception ex) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
// 在Spring Boot 3.x中,ErrorController接口不再要求实现getErrorPath方法
}package com.example.test.controller; -
import com.example.test.entity.User;
import com.example.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
// 创建用户
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
}
// 用户登录
@PostMapping("/login")
public ResponseEntity<?> login(@RequestParam String username, @RequestParam String password) {
User user = userService.login(username, password);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "用户名或密码错误");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
}
}
// 获取所有用户
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.findAllUsers();
return ResponseEntity.ok(users);
}
// 根据用户名查询用户
@GetMapping("/username/{username}")
public ResponseEntity<?> getUserByUsername(@PathVariable String username) {
User user = userService.findUserByUsername(username);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到用户名为: " + username + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 根据邮箱查询用户
@GetMapping("/email/{email}")
public ResponseEntity<?> getUserByEmail(@PathVariable String email) {
User user = userService.findUserByEmail(email);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到邮箱为: " + email + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 根据电话查询用户
@GetMapping("/phone/{phone}")
public ResponseEntity<?> getUserByPhone(@PathVariable String phone) {
User user = userService.findUserByPhone(phone);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到电话为: " + phone + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 根据ID获取用户
@GetMapping("/{id}")
public ResponseEntity<?> getUserById(@PathVariable Long id) {
Optional<User> userOptional = userService.findUserById(id);
if (userOptional.isPresent()) {
return ResponseEntity.ok(userOptional.get());
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到ID为: " + id + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 根据部门查询用户列表
@GetMapping("/department/{department}")
public ResponseEntity<List<User>> getUsersByDepartment(@PathVariable String department) {
List<User> users = userService.findUsersByDepartment(department);
return ResponseEntity.ok(users);
}
// 根据职位查询用户列表
@GetMapping("/position/{position}")
public ResponseEntity<List<User>> getUsersByPosition(@PathVariable String position) {
List<User> users = userService.findUsersByPosition(position);
return ResponseEntity.ok(users);
}
// 根据部门和职位查询用户列表
@GetMapping("/department/{department}/position/{position}")
public ResponseEntity<List<User>> getUsersByDepartmentAndPosition(
@PathVariable String department,
@PathVariable String position) {
List<User> users = userService.findUsersByDepartmentAndPosition(department, position);
return ResponseEntity.ok(users);
}
// 根据状态查询用户列表
@GetMapping("/status/{status}")
public ResponseEntity<List<User>> getUsersByStatus(@PathVariable Boolean status) {
List<User> users = userService.findUsersByStatus(status);
return ResponseEntity.ok(users);
}
// 根据真实姓名模糊查询
@GetMapping("/search/realname")
public ResponseEntity<List<User>> searchUsersByRealName(@RequestParam String keyword) {
List<User> users = userService.findUsersByRealNameContaining(keyword);
return ResponseEntity.ok(users);
}
// 查询指定时间之后创建的用户
@GetMapping("/created-after")
public ResponseEntity<List<User>> getUsersCreatedAfter(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime) {
List<User> users = userService.findUsersByCreateTimeAfter(dateTime);
return ResponseEntity.ok(users);
}
// 查询指定时间之后登录的用户
@GetMapping("/login-after")
public ResponseEntity<List<User>> getUsersLoggedInAfter(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime) {
List<User> users = userService.findUsersByLastLoginTimeAfter(dateTime);
return ResponseEntity.ok(users);
}
// 更新用户
@PutMapping("/{id}")
public ResponseEntity<?> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
Optional<User> userOptional = userService.findUserById(id);
if (userOptional.isPresent()) {
User user = userOptional.get();
// 保存原始用户名,确保不被修改
String originalUsername = user.getUsername();
// 更新用户信息
if (userDetails.getPassword() != null) {
user.setPassword(userDetails.getPassword());
}
if (userDetails.getRealName() != null) {
user.setRealName(userDetails.getRealName());
}
if (userDetails.getEmail() != null) {
user.setEmail(userDetails.getEmail());
}
if (userDetails.getPhone() != null) {
user.setPhone(userDetails.getPhone());
}
if (userDetails.getDepartment() != null) {
user.setDepartment(userDetails.getDepartment());
}
if (userDetails.getPosition() != null) {
user.setPosition(userDetails.getPosition());
}
if (userDetails.getStatus() != null) {
user.setStatus(userDetails.getStatus());
}
// 确保用户名不变
user.setUsername(originalUsername);
User updatedUser = userService.updateUser(user);
return ResponseEntity.ok(updatedUser);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到ID为: " + id + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 启用用户
@PatchMapping("/{id}/enable")
public ResponseEntity<?> enableUser(@PathVariable Long id) {
User user = userService.enableUser(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到ID为: " + id + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 禁用用户
@PatchMapping("/{id}/disable")
public ResponseEntity<?> disableUser(@PathVariable Long id) {
User user = userService.disableUser(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到ID为: " + id + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
return userService.findUserById(id)
.map(user -> {
userService.deleteUser(id);
Map<String, String> response = new HashMap<>();
response.put("message", "用户已成功删除");
return ResponseEntity.ok(response);
})
.orElseGet(() -> {
Map<String, String> response = new HashMap<>();
response.put("message", "未找到ID为: " + id + " 的用户");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
});
}
}package com.example.test.controller;
import com.example.test.entity.User;
import com.example.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import jakarta.servlet.http.HttpSession;
import java.util.List;
/**
-
Web页面控制器,处理HTML页面的请求
*/
@Controller
public class WebController {private final UserService userService;
@Autowired
public WebController(UserService userService) {
this.userService = userService;
}/**
- 首页重定向到登录页
*/
@GetMapping("/")
public String index() {
return "redirect:/login";
}
/**
- 显示登录页面
*/
@GetMapping("/login")
public String showLoginPage() {
return "login";
}
/**
-
处理登录请求
*/
@PostMapping("/login")
public String processLogin(@RequestParam String username,
@RequestParam String password,
RedirectAttributes redirectAttributes,
HttpSession session) {
User user = userService.login(username, password);
if (user != null) {
// 登录成功,将用户信息存储在session中
session.setAttribute("currentUser", user);// 根据用户角色跳转到不同页面 if (user.isAdmin()) { return "redirect:/admin/dashboard"; } else { return "redirect:/dashboard"; }
} else {
// 登录失败,添加错误消息并返回登录页
redirectAttributes.addFlashAttribute("errorMessage", "用户名或密码错误");
return "redirect:/login";
}
}
/**
- 显示注册页面
*/
@GetMapping("/register")
public String showRegisterPage() {
return "redirect:/login?register";
}
/**
-
处理注册请求
*/
@PostMapping("/register")
public String processRegistration(@ModelAttribute User user,
RedirectAttributes redirectAttributes) {
// 检查用户名是否已存在
if (userService.findUserByUsername(user.getUsername()) != null) {
redirectAttributes.addFlashAttribute("errorMessage", "用户名已存在");
return "redirect:/login?register";
}// 检查邮箱是否已存在
if (userService.findUserByEmail(user.getEmail()) != null) {
redirectAttributes.addFlashAttribute("errorMessage", "邮箱已被注册");
return "redirect:/login?register";
}// 检查手机号是否已存在
if (user.getPhone() != null && userService.findUserByPhone(user.getPhone()) != null) {
redirectAttributes.addFlashAttribute("errorMessage", "手机号已被注册");
return "redirect:/login?register";
}// 设置用户状态为启用
user.setStatus(true);// 保存用户
try {
userService.createUser(user);
redirectAttributes.addFlashAttribute("success", "注册成功,请登录");
return "redirect:/login";
} catch (Exception e) {
redirectAttributes.addFlashAttribute("errorMessage", "注册失败: " + e.getMessage());
return "redirect:/login?register";
}
}
/**
- 用户仪表盘页面
*/
@GetMapping("/dashboard")
public String dashboard(HttpSession session, Model model) {
// 验证用户是否已登录
User currentUser = (User) session.getAttribute("currentUser");
if (currentUser == null) {
// 用户未登录,重定向到登录页
return "redirect:/login";
}
// 将用户信息添加到模型中,供模板使用
model.addAttribute("currentUser", currentUser);
return "dashboard";
}
/**
-
管理员仪表盘页面
*/
@GetMapping("/admin/dashboard")
public String adminDashboard(HttpSession session, Model model) {
// 验证用户是否已登录且是管理员
User currentUser = (User) session.getAttribute("currentUser");
if (currentUser == null) {
// 用户未登录,重定向到登录页
return "redirect:/login";
}if (!currentUser.isAdmin()) {
// 用户不是管理员,重定向到普通用户仪表盘
return "redirect:/dashboard";
}// 将用户信息添加到模型中,供模板使用
model.addAttribute("currentUser", currentUser);
return "admin/dashboard";
}
/**
-
管理员用户管理页面
*/
@GetMapping("/admin/users")
public String adminUserManagement(HttpSession session, Model model) {
// 验证用户是否已登录且是管理员
User currentUser = (User) session.getAttribute("currentUser");
if (currentUser == null) {
// 用户未登录,重定向到登录页
return "redirect:/login";
}if (!currentUser.isAdmin()) {
// 用户不是管理员,重定向到普通用户仪表盘
return "redirect:/dashboard";
}// 获取所有用户列表
Listusers = userService.findAllUsers(); // 将用户信息添加到模型中,供模板使用
model.addAttribute("currentUser", currentUser);
model.addAttribute("users", users);
return "admin/users";
}
/**
- 退出登录
*/
@GetMapping("/logout")
public String logout(HttpSession session) {
// 清除session
session.invalidate();
return "redirect:/login";
}
}package com.example.test.entity;
- 首页重定向到登录页
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
@Entity
@Table(name = "contact_form")
public class ContactForm {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "form_number", nullable = false, unique = true, length = 50)
private String formNumber;
@ManyToOne
@JoinColumn(name = "order_id")
private SalesOrder order;
@Column(name = "order_number", length = 50)
private String orderNumber;
@ManyToOne
@JoinColumn(name = "customer_id")
private User customer;
@Column(name = "customer_name", length = 100)
private String customerName;
@Column(name = "contact_type", length = 20)
private String contactType; // 订单咨询、产品咨询、投诉、建议、其他
@Column(name = "contact_content", nullable = false, length = 1000)
private String contactContent;
@Column(name = "contact_status", length = 20)
private String contactStatus; // 待处理、处理中、已完成
@Column(name = "priority", length = 10)
private String priority; // 高、中、低
@ManyToOne
@JoinColumn(name = "handler_id")
private User handler;
@Column(name = "handler_name", length = 50)
private String handlerName;
@Column(name = "handling_result", length = 1000)
private String handlingResult;
@Column(name = "handling_time")
private LocalDateTime handlingTime;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "created_by")
private Long createdBy;
@Column(name = "updated_by")
private Long updatedBy;
// 默认构造函数
public ContactForm() {
}
// 带基本参数的构造函数
public ContactForm(String formNumber, String contactType, String contactContent) {
this.formNumber = formNumber;
this.contactType = contactType;
this.contactContent = contactContent;
this.contactStatus = "待处理";
this.priority = "中";
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// 带订单和客户的构造函数
public ContactForm(String formNumber, SalesOrder order, User customer, String contactType, String contactContent) {
this(formNumber, contactType, contactContent);
this.order = order;
if (order != null) {
this.orderNumber = order.getOrderNumber();
}
this.customer = customer;
this.customerName = customer != null ? customer.getRealName() : null;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFormNumber() {
return formNumber;
}
public void setFormNumber(String formNumber) {
this.formNumber = formNumber;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
if (order != null) {
this.orderNumber = order.getOrderNumber();
}
}
public String getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public User getCustomer() {
return customer;
}
public void setCustomer(User customer) {
this.customer = customer;
this.customerName = customer != null ? customer.getRealName() : null;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getContactType() {
return contactType;
}
public void setContactType(String contactType) {
this.contactType = contactType;
}
public String getContactContent() {
return contactContent;
}
public void setContactContent(String contactContent) {
this.contactContent = contactContent;
}
public String getContactStatus() {
return contactStatus;
}
public void setContactStatus(String contactStatus) {
this.contactStatus = contactStatus;
}
public String getPriority() {
return priority;
}
public void setPriority(String priority) {
this.priority = priority;
}
public User getHandler() {
return handler;
}
public void setHandler(User handler) {
this.handler = handler;
this.handlerName = handler != null ? handler.getRealName() : null;
}
public String getHandlerName() {
return handlerName;
}
public void setHandlerName(String handlerName) {
this.handlerName = handlerName;
}
public String getHandlingResult() {
return handlingResult;
}
public void setHandlingResult(String handlingResult) {
this.handlingResult = handlingResult;
}
public LocalDateTime getHandlingTime() {
return handlingTime;
}
public void setHandlingTime(LocalDateTime handlingTime) {
this.handlingTime = handlingTime;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Long getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Long updatedBy) {
this.updatedBy = updatedBy;
}
@Override
public String toString() {
return "ContactForm{" +
"id=" + id +
", formNumber='" + formNumber + '\'' +
", orderNumber='" + orderNumber + '\'' +
", customerName='" + customerName + '\'' +
", contactType='" + contactType + '\'' +
", contactStatus='" + contactStatus + '\'' +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Table(name = "delivery_order")
public class DeliveryOrder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "delivery_number", nullable = false, unique = true, length = 50)
private String deliveryNumber;
@ManyToOne
@JoinColumn(name = "order_id")
private SalesOrder order;
@Column(name = "order_number", length = 50)
private String orderNumber;
@ManyToOne
@JoinColumn(name = "customer_id")
private User customer;
@Column(name = "customer_name", length = 100)
private String customerName;
@Column(name = "contact_address", length = 255)
private String contactAddress;
@Column(name = "delivery_date")
private LocalDateTime deliveryDate;
@Column(name = "shipping_method", length = 50)
private String shippingMethod;
@Column(name = "tracking_number", length = 50)
private String trackingNumber;
@Column(name = "delivery_status", length = 20)
private String deliveryStatus; // 待发货、已发货、已签收
@Column(name = "total_quantity")
private Integer totalQuantity;
@Column(name = "total_amount", precision = 10, scale = 2)
private BigDecimal totalAmount;
@Column(name = "remarks", length = 500)
private String remarks;
@ManyToOne
@JoinColumn(name = "handler_id")
private User handler;
@Column(name = "handler_name", length = 50)
private String handlerName;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "created_by")
private Long createdBy;
@Column(name = "updated_by")
private Long updatedBy;
// 默认构造函数
public DeliveryOrder() {
}
// 带基本参数的构造函数
public DeliveryOrder(String deliveryNumber, SalesOrder order) {
this.deliveryNumber = deliveryNumber;
this.order = order;
if (order != null) {
this.orderNumber = order.getOrderNumber();
this.customer = order.getCustomer();
this.customerName = order.getCustomerName();
this.contactAddress = order.getContactAddress();
this.shippingMethod = order.getShippingMethod();
}
this.deliveryStatus = "待发货";
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDeliveryNumber() {
return deliveryNumber;
}
public void setDeliveryNumber(String deliveryNumber) {
this.deliveryNumber = deliveryNumber;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
if (order != null) {
this.orderNumber = order.getOrderNumber();
this.customer = order.getCustomer();
this.customerName = order.getCustomerName();
this.contactAddress = order.getContactAddress();
this.shippingMethod = order.getShippingMethod();
}
}
public String getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public User getCustomer() {
return customer;
}
public void setCustomer(User customer) {
this.customer = customer;
this.customerName = customer != null ? customer.getRealName() : null;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getContactAddress() {
return contactAddress;
}
public void setContactAddress(String contactAddress) {
this.contactAddress = contactAddress;
}
public LocalDateTime getDeliveryDate() {
return deliveryDate;
}
public void setDeliveryDate(LocalDateTime deliveryDate) {
this.deliveryDate = deliveryDate;
}
public String getShippingMethod() {
return shippingMethod;
}
public void setShippingMethod(String shippingMethod) {
this.shippingMethod = shippingMethod;
}
public String getTrackingNumber() {
return trackingNumber;
}
public void setTrackingNumber(String trackingNumber) {
this.trackingNumber = trackingNumber;
}
public String getDeliveryStatus() {
return deliveryStatus;
}
public void setDeliveryStatus(String deliveryStatus) {
this.deliveryStatus = deliveryStatus;
}
public Integer getTotalQuantity() {
return totalQuantity;
}
public void setTotalQuantity(Integer totalQuantity) {
this.totalQuantity = totalQuantity;
}
public BigDecimal getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public User getHandler() {
return handler;
}
public void setHandler(User handler) {
this.handler = handler;
this.handlerName = handler != null ? handler.getRealName() : null;
}
public String getHandlerName() {
return handlerName;
}
public void setHandlerName(String handlerName) {
this.handlerName = handlerName;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Long getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Long updatedBy) {
this.updatedBy = updatedBy;
}
@Override
public String toString() {
return "DeliveryOrder{" +
"id=" + id +
", deliveryNumber='" + deliveryNumber + '\'' +
", orderNumber='" + orderNumber + '\'' +
", customerName='" + customerName + '\'' +
", deliveryDate=" + deliveryDate +
", deliveryStatus='" + deliveryStatus + '\'' +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Table(name = "delivery_statistics")
public class DeliveryStatistics {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "statistics_year")
private Integer statisticsYear;
@Column(name = "statistics_month")
private Integer statisticsMonth;
@Column(name = "statistics_quarter")
private Integer statisticsQuarter;
@Column(name = "customer_name", length = 100)
private String customerName;
@Column(name = "product_code", length = 50)
private String productCode;
@Column(name = "product_name", length = 100)
private String productName;
@Column(name = "product_model", length = 50)
private String productModel;
@Column(name = "delivery_quantity")
private Integer deliveryQuantity;
@Column(name = "delivery_amount", precision = 10, scale = 2)
private BigDecimal deliveryAmount;
@Column(name = "on_time_delivery_rate", precision = 5, scale = 2)
private BigDecimal onTimeDeliveryRate; // 准时交付率
@Column(name = "customer_satisfaction_rate", precision = 5, scale = 2)
private BigDecimal customerSatisfactionRate; // 客户满意度
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
// 默认构造函数
public DeliveryStatistics() {
}
// 带基本参数的构造函数
public DeliveryStatistics(Integer statisticsYear, Integer statisticsMonth) {
this.statisticsYear = statisticsYear;
this.statisticsMonth = statisticsMonth;
if (statisticsMonth != null) {
this.statisticsQuarter = (statisticsMonth - 1) / 3 + 1;
}
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getStatisticsYear() {
return statisticsYear;
}
public void setStatisticsYear(Integer statisticsYear) {
this.statisticsYear = statisticsYear;
}
public Integer getStatisticsMonth() {
return statisticsMonth;
}
public void setStatisticsMonth(Integer statisticsMonth) {
this.statisticsMonth = statisticsMonth;
if (statisticsMonth != null) {
this.statisticsQuarter = (statisticsMonth - 1) / 3 + 1;
}
}
public Integer getStatisticsQuarter() {
return statisticsQuarter;
}
public void setStatisticsQuarter(Integer statisticsQuarter) {
this.statisticsQuarter = statisticsQuarter;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductModel() {
return productModel;
}
public void setProductModel(String productModel) {
this.productModel = productModel;
}
public Integer getDeliveryQuantity() {
return deliveryQuantity;
}
public void setDeliveryQuantity(Integer deliveryQuantity) {
this.deliveryQuantity = deliveryQuantity;
}
public BigDecimal getDeliveryAmount() {
return deliveryAmount;
}
public void setDeliveryAmount(BigDecimal deliveryAmount) {
this.deliveryAmount = deliveryAmount;
}
public BigDecimal getOnTimeDeliveryRate() {
return onTimeDeliveryRate;
}
public void setOnTimeDeliveryRate(BigDecimal onTimeDeliveryRate) {
this.onTimeDeliveryRate = onTimeDeliveryRate;
}
public BigDecimal getCustomerSatisfactionRate() {
return customerSatisfactionRate;
}
public void setCustomerSatisfactionRate(BigDecimal customerSatisfactionRate) {
this.customerSatisfactionRate = customerSatisfactionRate;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "DeliveryStatistics{" +
"id=" + id +
", statisticsYear=" + statisticsYear +
", statisticsMonth=" + statisticsMonth +
", customerName='" + customerName + '\'' +
", productName='" + productName + '\'' +
", deliveryQuantity=" + deliveryQuantity +
", deliveryAmount=" + deliveryAmount +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Table(name = "forecast_plan")
public class ForecastPlan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "plan_number", nullable = false, unique = true, length = 50)
private String planNumber;
@Column(name = "plan_name", length = 100)
private String planName;
@Column(name = "plan_year")
private Integer planYear;
@Column(name = "plan_month")
private Integer planMonth;
@Column(name = "plan_quarter")
private Integer planQuarter;
@ManyToOne
@JoinColumn(name = "customer_id")
private User customer;
@Column(name = "customer_name", length = 100)
private String customerName;
@Column(name = "product_code", length = 50)
private String productCode;
@Column(name = "product_name", length = 100)
private String productName;
@Column(name = "forecast_quantity")
private Integer forecastQuantity;
@Column(name = "actual_quantity")
private Integer actualQuantity;
@Column(name = "forecast_amount", precision = 10, scale = 2)
private BigDecimal forecastAmount;
@Column(name = "actual_amount", precision = 10, scale = 2)
private BigDecimal actualAmount;
@Column(name = "plan_status", length = 20)
private String planStatus; // 草稿、已提交、已审核、已完成
@Column(name = "remarks", length = 500)
private String remarks;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "created_by")
private Long createdBy;
@Column(name = "updated_by")
private Long updatedBy;
// 默认构造函数
public ForecastPlan() {
}
// 带基本参数的构造函数
public ForecastPlan(String planNumber, String planName, Integer planYear, Integer planMonth) {
this.planNumber = planNumber;
this.planName = planName;
this.planYear = planYear;
this.planMonth = planMonth;
if (planMonth != null) {
this.planQuarter = (planMonth - 1) / 3 + 1;
}
this.planStatus = "草稿";
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPlanNumber() {
return planNumber;
}
public void setPlanNumber(String planNumber) {
this.planNumber = planNumber;
}
public String getPlanName() {
return planName;
}
public void setPlanName(String planName) {
this.planName = planName;
}
public Integer getPlanYear() {
return planYear;
}
public void setPlanYear(Integer planYear) {
this.planYear = planYear;
}
public Integer getPlanMonth() {
return planMonth;
}
public void setPlanMonth(Integer planMonth) {
this.planMonth = planMonth;
if (planMonth != null) {
this.planQuarter = (planMonth - 1) / 3 + 1;
}
}
public Integer getPlanQuarter() {
return planQuarter;
}
public void setPlanQuarter(Integer planQuarter) {
this.planQuarter = planQuarter;
}
public User getCustomer() {
return customer;
}
public void setCustomer(User customer) {
this.customer = customer;
this.customerName = customer != null ? customer.getRealName() : null;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Integer getForecastQuantity() {
return forecastQuantity;
}
public void setForecastQuantity(Integer forecastQuantity) {
this.forecastQuantity = forecastQuantity;
}
public Integer getActualQuantity() {
return actualQuantity;
}
public void setActualQuantity(Integer actualQuantity) {
this.actualQuantity = actualQuantity;
}
public BigDecimal getForecastAmount() {
return forecastAmount;
}
public void setForecastAmount(BigDecimal forecastAmount) {
this.forecastAmount = forecastAmount;
}
public BigDecimal getActualAmount() {
return actualAmount;
}
public void setActualAmount(BigDecimal actualAmount) {
this.actualAmount = actualAmount;
}
public String getPlanStatus() {
return planStatus;
}
public void setPlanStatus(String planStatus) {
this.planStatus = planStatus;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Long getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Long updatedBy) {
this.updatedBy = updatedBy;
}
@Override
public String toString() {
return "ForecastPlan{" +
"id=" + id +
", planNumber='" + planNumber + '\'' +
", planName='" + planName + '\'' +
", planYear=" + planYear +
", planMonth=" + planMonth +
", customerName='" + customerName + '\'' +
", forecastQuantity=" + forecastQuantity +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
@Entity
@Table(name = "missing_product")
public class MissingProduct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id")
private SalesOrder order;
@ManyToOne
@JoinColumn(name = "order_product_id")
private OrderProduct orderProduct;
@Column(name = "product_code", nullable = false, length = 50)
private String productCode;
@Column(name = "product_name", length = 100)
private String productName;
@Column(name = "product_model", length = 50)
private String productModel;
@Column(name = "unit", length = 20)
private String unit;
@Column(name = "missing_quantity", nullable = false)
private Integer missingQuantity;
@Column(name = "expected_arrival_date")
private LocalDateTime expectedArrivalDate;
@Column(name = "actual_arrival_date")
private LocalDateTime actualArrivalDate;
@Column(name = "status", length = 20)
private String status; // 缺货中、已到货、已取消
@Column(name = "remarks", length = 255)
private String remarks;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
// 默认构造函数
public MissingProduct() {
}
// 带基本参数的构造函数
public MissingProduct(SalesOrder order, OrderProduct orderProduct, Integer missingQuantity) {
this.order = order;
this.orderProduct = orderProduct;
this.productCode = orderProduct != null ? orderProduct.getProductCode() : null;
this.productName = orderProduct != null ? orderProduct.getProductName() : null;
this.productModel = orderProduct != null ? orderProduct.getProductModel() : null;
this.unit = orderProduct != null ? orderProduct.getUnit() : null;
this.missingQuantity = missingQuantity;
this.status = "缺货中";
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
}
public OrderProduct getOrderProduct() {
return orderProduct;
}
public void setOrderProduct(OrderProduct orderProduct) {
this.orderProduct = orderProduct;
if (orderProduct != null) {
this.productCode = orderProduct.getProductCode();
this.productName = orderProduct.getProductName();
this.productModel = orderProduct.getProductModel();
this.unit = orderProduct.getUnit();
}
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductModel() {
return productModel;
}
public void setProductModel(String productModel) {
this.productModel = productModel;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public Integer getMissingQuantity() {
return missingQuantity;
}
public void setMissingQuantity(Integer missingQuantity) {
this.missingQuantity = missingQuantity;
}
public LocalDateTime getExpectedArrivalDate() {
return expectedArrivalDate;
}
public void setExpectedArrivalDate(LocalDateTime expectedArrivalDate) {
this.expectedArrivalDate = expectedArrivalDate;
}
public LocalDateTime getActualArrivalDate() {
return actualArrivalDate;
}
public void setActualArrivalDate(LocalDateTime actualArrivalDate) {
this.actualArrivalDate = actualArrivalDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "MissingProduct{" +
"id=" + id +
", productCode='" + productCode + '\'' +
", productName='" + productName + '\'' +
", missingQuantity=" + missingQuantity +
", status='" + status + '\'' +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
@Entity
@Table(name = "order_change")
public class OrderChange {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id", nullable = false)
private SalesOrder order;
@Column(name = "change_type", nullable = false, length = 20)
private String changeType; // 订单信息变更、产品变更、交期变更、取消订单
@Column(name = "change_content", nullable = false, length = 500)
private String changeContent;
@Column(name = "change_reason", length = 500)
private String changeReason;
@Column(name = "change_status", nullable = false, length = 20)
private String changeStatus; // 待审核、已通过、已拒绝
@ManyToOne
@JoinColumn(name = "applicant_id")
private User applicant;
@Column(name = "applicant_name", length = 50)
private String applicantName;
@Column(name = "apply_time")
private LocalDateTime applyTime;
@ManyToOne
@JoinColumn(name = "reviewer_id")
private User reviewer;
@Column(name = "reviewer_name", length = 50)
private String reviewerName;
@Column(name = "review_time")
private LocalDateTime reviewTime;
@Column(name = "review_comments", length = 500)
private String reviewComments;
// 默认构造函数
public OrderChange() {
}
// 带基本参数的构造函数
public OrderChange(SalesOrder order, String changeType, String changeContent, User applicant) {
this.order = order;
this.changeType = changeType;
this.changeContent = changeContent;
this.changeStatus = "待审核";
this.applicant = applicant;
this.applicantName = applicant != null ? applicant.getRealName() : null;
this.applyTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
}
public String getChangeType() {
return changeType;
}
public void setChangeType(String changeType) {
this.changeType = changeType;
}
public String getChangeContent() {
return changeContent;
}
public void setChangeContent(String changeContent) {
this.changeContent = changeContent;
}
public String getChangeReason() {
return changeReason;
}
public void setChangeReason(String changeReason) {
this.changeReason = changeReason;
}
public String getChangeStatus() {
return changeStatus;
}
public void setChangeStatus(String changeStatus) {
this.changeStatus = changeStatus;
}
public User getApplicant() {
return applicant;
}
public void setApplicant(User applicant) {
this.applicant = applicant;
this.applicantName = applicant != null ? applicant.getRealName() : null;
}
public String getApplicantName() {
return applicantName;
}
public void setApplicantName(String applicantName) {
this.applicantName = applicantName;
}
public LocalDateTime getApplyTime() {
return applyTime;
}
public void setApplyTime(LocalDateTime applyTime) {
this.applyTime = applyTime;
}
public User getReviewer() {
return reviewer;
}
public void setReviewer(User reviewer) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
}
public String getReviewerName() {
return reviewerName;
}
public void setReviewerName(String reviewerName) {
this.reviewerName = reviewerName;
}
public LocalDateTime getReviewTime() {
return reviewTime;
}
public void setReviewTime(LocalDateTime reviewTime) {
this.reviewTime = reviewTime;
}
public String getReviewComments() {
return reviewComments;
}
public void setReviewComments(String reviewComments) {
this.reviewComments = reviewComments;
}
// 审核通过方法
public void approve(User reviewer, String comments) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
this.changeStatus = "已通过";
this.reviewComments = comments;
this.reviewTime = LocalDateTime.now();
}
// 审核拒绝方法
public void reject(User reviewer, String comments) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
this.changeStatus = "已拒绝";
this.reviewComments = comments;
this.reviewTime = LocalDateTime.now();
}
@Override
public String toString() {
return "OrderChange{" +
"id=" + id +
", changeType='" + changeType + '\'' +
", changeStatus='" + changeStatus + '\'' +
", applicantName='" + applicantName + '\'' +
", applyTime=" + applyTime +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
@Entity
@Table(name = "order_product")
public class OrderProduct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id", nullable = false)
private SalesOrder order;
@Column(name = "product_code", nullable = false, length = 50)
private String productCode;
@Column(name = "product_name", length = 100)
private String productName;
@Column(name = "product_model", length = 50)
private String productModel;
@Column(name = "unit", length = 20)
private String unit;
@Column(name = "quantity", nullable = false)
private Integer quantity;
@Column(name = "unit_price", precision = 10, scale = 2)
private BigDecimal unitPrice;
@Column(name = "total_price", precision = 10, scale = 2)
private BigDecimal totalPrice;
@Column(name = "remarks", length = 255)
private String remarks;
@Column(name = "production_status", length = 20)
private String productionStatus; // 未生产、生产中、已完成
// 默认构造函数
public OrderProduct() {
}
// 带基本参数的构造函数
public OrderProduct(SalesOrder order, String productCode, String productName, String productModel, String unit, Integer quantity) {
this.order = order;
this.productCode = productCode;
this.productName = productName;
this.productModel = productModel;
this.unit = unit;
this.quantity = quantity;
this.productionStatus = "未生产";
}
// 带价格的构造函数
public OrderProduct(SalesOrder order, String productCode, String productName, String productModel, String unit, Integer quantity, BigDecimal unitPrice) {
this(order, productCode, productName, productModel, unit, quantity);
this.unitPrice = unitPrice;
this.totalPrice = unitPrice != null && quantity != null ? unitPrice.multiply(new BigDecimal(quantity)) : null;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductModel() {
return productModel;
}
public void setProductModel(String productModel) {
this.productModel = productModel;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
// 更新总价
if (this.unitPrice != null && quantity != null) {
this.totalPrice = this.unitPrice.multiply(new BigDecimal(quantity));
}
}
public BigDecimal getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice) {
this.unitPrice = unitPrice;
// 更新总价
if (unitPrice != null && this.quantity != null) {
this.totalPrice = unitPrice.multiply(new BigDecimal(this.quantity));
}
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getProductionStatus() {
return productionStatus;
}
public void setProductionStatus(String productionStatus) {
this.productionStatus = productionStatus;
}
@Override
public String toString() {
return "OrderProduct{" +
"id=" + id +
", productCode='" + productCode + '\'' +
", productName='" + productName + '\'' +
", productModel='" + productModel + '\'' +
", quantity=" + quantity +
", unitPrice=" + unitPrice +
", totalPrice=" + totalPrice +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
@Entity
@Table(name = "order_review")
public class OrderReview {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "order_id", nullable = false)
private SalesOrder order;
@Column(name = "review_type", nullable = false, length = 20)
private String reviewType; // 销售审核、生产审核、财务审核
@Column(name = "review_status", nullable = false, length = 20)
private String reviewStatus; // 待审核、已通过、已拒绝
@Column(name = "review_comments", length = 500)
private String reviewComments;
@ManyToOne
@JoinColumn(name = "reviewer_id")
private User reviewer;
@Column(name = "reviewer_name", length = 50)
private String reviewerName;
@Column(name = "review_time")
private LocalDateTime reviewTime;
@Column(name = "create_time")
private LocalDateTime createTime;
// 默认构造函数
public OrderReview() {
}
// 带基本参数的构造函数
public OrderReview(SalesOrder order, String reviewType) {
this.order = order;
this.reviewType = reviewType;
this.reviewStatus = "待审核";
this.createTime = LocalDateTime.now();
}
// 带审核人的构造函数
public OrderReview(SalesOrder order, String reviewType, User reviewer) {
this(order, reviewType);
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public SalesOrder getOrder() {
return order;
}
public void setOrder(SalesOrder order) {
this.order = order;
}
public String getReviewType() {
return reviewType;
}
public void setReviewType(String reviewType) {
this.reviewType = reviewType;
}
public String getReviewStatus() {
return reviewStatus;
}
public void setReviewStatus(String reviewStatus) {
this.reviewStatus = reviewStatus;
}
public String getReviewComments() {
return reviewComments;
}
public void setReviewComments(String reviewComments) {
this.reviewComments = reviewComments;
}
public User getReviewer() {
return reviewer;
}
public void setReviewer(User reviewer) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
}
public String getReviewerName() {
return reviewerName;
}
public void setReviewerName(String reviewerName) {
this.reviewerName = reviewerName;
}
public LocalDateTime getReviewTime() {
return reviewTime;
}
public void setReviewTime(LocalDateTime reviewTime) {
this.reviewTime = reviewTime;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
// 审核通过方法
public void approve(User reviewer, String comments) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
this.reviewStatus = "已通过";
this.reviewComments = comments;
this.reviewTime = LocalDateTime.now();
}
// 审核拒绝方法
public void reject(User reviewer, String comments) {
this.reviewer = reviewer;
this.reviewerName = reviewer != null ? reviewer.getRealName() : null;
this.reviewStatus = "已拒绝";
this.reviewComments = comments;
this.reviewTime = LocalDateTime.now();
}
@Override
public String toString() {
return "OrderReview{" +
"id=" + id +
", reviewType='" + reviewType + '\'' +
", reviewStatus='" + reviewStatus + '\'' +
", reviewerName='" + reviewerName + '\'' +
", reviewTime=" + reviewTime +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
@Table(name = "product")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "product_code", nullable = false, unique = true, length = 50)
private String productCode;
@Column(name = "product_name", nullable = false, length = 100)
private String productName;
@Column(name = "product_model", length = 50)
private String productModel;
@Column(name = "product_type", length = 50)
private String productType;
@Column(name = "product_category", length = 50)
private String productCategory;
@Column(name = "unit", length = 20)
private String unit;
@Column(name = "standard_price", precision = 10, scale = 2)
private BigDecimal standardPrice;
@Column(name = "cost_price", precision = 10, scale = 2)
private BigDecimal costPrice;
@Column(name = "inventory_quantity")
private Integer inventoryQuantity;
@Column(name = "min_inventory")
private Integer minInventory;
@Column(name = "max_inventory")
private Integer maxInventory;
@Column(name = "production_cycle")
private Integer productionCycle; // 生产周期(天)
@Column(name = "product_status", length = 20)
private String productStatus; // 正常、停产、缺货
@Column(name = "description", length = 500)
private String description;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "created_by")
private Long createdBy;
@Column(name = "updated_by")
private Long updatedBy;
// 默认构造函数
public Product() {
}
// 带基本参数的构造函数
public Product(String productCode, String productName, String productModel, String unit) {
this.productCode = productCode;
this.productName = productName;
this.productModel = productModel;
this.unit = unit;
this.inventoryQuantity = 0;
this.productStatus = "正常";
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductModel() {
return productModel;
}
public void setProductModel(String productModel) {
this.productModel = productModel;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public BigDecimal getStandardPrice() {
return standardPrice;
}
public void setStandardPrice(BigDecimal standardPrice) {
this.standardPrice = standardPrice;
}
public BigDecimal getCostPrice() {
return costPrice;
}
public void setCostPrice(BigDecimal costPrice) {
this.costPrice = costPrice;
}
public Integer getInventoryQuantity() {
return inventoryQuantity;
}
public void setInventoryQuantity(Integer inventoryQuantity) {
this.inventoryQuantity = inventoryQuantity;
}
public Integer getMinInventory() {
return minInventory;
}
public void setMinInventory(Integer minInventory) {
this.minInventory = minInventory;
}
public Integer getMaxInventory() {
return maxInventory;
}
public void setMaxInventory(Integer maxInventory) {
this.maxInventory = maxInventory;
}
public Integer getProductionCycle() {
return productionCycle;
}
public void setProductionCycle(Integer productionCycle) {
this.productionCycle = productionCycle;
}
public String getProductStatus() {
return productStatus;
}
public void setProductStatus(String productStatus) {
this.productStatus = productStatus;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Long getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Long updatedBy) {
this.updatedBy = updatedBy;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", productCode='" + productCode + '\'' +
", productName='" + productName + '\'' +
", productModel='" + productModel + '\'' +
", inventoryQuantity=" + inventoryQuantity +
", productStatus='" + productStatus + '\'' +
'}';
}
}package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name = "product_cycle")
public class ProductCycle {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "product_id")
private Product product;
@Column(name = "product_code", nullable = false, length = 50)
private String productCode;
@Column(name = "product_name", length = 100)
private String productName;
@Column(name = "product_type", length = 50)
private String productType; // 产品类型:A、B、C等
@Column(name = "design_cycle")
private Integer designCycle; // 设计周期(天)
@Column(name = "material_preparation_cycle")
private Integer materialPreparationCycle; // 原材料准备周期(天)
@Column(name = "production_cycle")
private Integer productionCycle; // 生产周期(天)
@Column(name = "quality_inspection_cycle")
private Integer qualityInspectionCycle; // 质量检验周期(天)
@Column(name = "packaging_cycle")
private Integer packagingCycle; // 包装周期(天)
@Column(name = "total_cycle")
private Integer totalCycle; // 总周期(天)
// 默认构造函数
public ProductCycle() {
}
// 带基本参数的构造函数
public ProductCycle(Product product, String productType) {
this.product = product;
if (product != null) {
this.productCode = product.getProductCode();
this.productName = product.getProductName();
}
this.productType = productType;
}
// 带完整周期参数的构造函数
public ProductCycle(Product product, String productType, Integer designCycle, Integer materialPreparationCycle,
Integer productionCycle, Integer qualityInspectionCycle, Integer packagingCycle) {
this(product, productType);
this.designCycle = designCycle;
this.materialPreparationCycle = materialPreparationCycle;
this.productionCycle = productionCycle;
this.qualityInspectionCycle = qualityInspectionCycle;
this.packagingCycle = packagingCycle;
calculateTotalCycle();
}
// 计算总周期
private void calculateTotalCycle() {
this.totalCycle = (this.designCycle != null ? this.designCycle : 0) +
(this.materialPreparationCycle != null ? this.materialPreparationCycle : 0) +
(this.productionCycle != null ? this.productionCycle : 0) +
(this.qualityInspectionCycle != null ? this.qualityInspectionCycle : 0) +
(this.packagingCycle != null ? this.packagingCycle : 0);
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
if (product != null) {
this.productCode = product.getProductCode();
this.productName = product.getProductName();
}
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public Integer getDesignCycle() {
return designCycle;
}
public void setDesignCycle(Integer designCycle) {
this.designCycle = designCycle;
calculateTotalCycle();
}
public Integer getMaterialPreparationCycle() {
return materialPreparationCycle;
}
public void setMaterialPreparationCycle(Integer materialPreparationCycle) {
this.materialPreparationCycle = materialPreparationCycle;
calculateTotalCycle();
}
public Integer getProductionCycle() {
return productionCycle;
}
public void setProductionCycle(Integer productionCycle) {
this.productionCycle = productionCycle;
calculateTotalCycle();
}
public Integer getQualityInspectionCycle() {
return qualityInspectionCycle;
}
public void setQualityInspectionCycle(Integer qualityInspectionCycle) {
this.qualityInspectionCycle = qualityInspectionCycle;
calculateTotalCycle();
}
public Integer getPackagingCycle() {
return packagingCycle;
}
public void setPackagingCycle(Integer packagingCycle) {
this.packagingCycle = packagingCycle;
calculateTotalCycle();
}
public Integer getTotalCycle() {
return totalCycle;
}
public void setTotalCycle(Integer totalCycle) {
this.totalCycle = totalCycle;
}
@Override
public String toString() {
return "ProductCycle{" +
"id=" + id +
", productCode='" + productCode + '\'' +
", productName='" + productName + '\'' +
", productType='" + productType + '\'' +
", totalCycle=" + totalCycle +
'}';
}
}/*
- Copyright (c) 2008, 2020 Oracle and/or its affiliates. All rights reserved.
- This program and the accompanying materials are made available under the
- terms of the Eclipse Public License v. 2.0 which is available at
- http://www.eclipse.org/legal/epl-2.0,
- or the Eclipse Distribution License v. 1.0 which is available at
- http://www.eclipse.org/org/documents/edl-v10.php.
- SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Linda DeMichiel - 2.1
// Linda DeMichiel - 2.0
package jakarta.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
-
Specifies the mapped column for a persistent property or field.
-
If no
Column
annotation is specified, the default values apply. -
-
Example 1:
-
@Column(name="DESC", nullable=false, length=512)
-
public String getDescription()
-
Example 2:
-
@Column(name="DESC",
-
columnDefinition="CLOB NOT NULL",
-
table="EMP_DETAIL")
-
@Lob
-
public String getDescription()
-
Example 3:
-
@Column(name="ORDER_COST", updatable=false, precision=12, scale=2)
-
public BigDecimal getCost()
-
@since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Column {/**
- (Optional) The name of the column. Defaults to
- the property or field name.
*/
String name() default "";
/**
- (Optional) Whether the column is a unique key. This is a
- shortcut for the
UniqueConstraint
annotation at the table - level and is useful for when the unique key constraint
- corresponds to only a single column. This constraint applies
- in addition to any constraint entailed by primary key mapping and
- to constraints specified at the table level.
*/
boolean unique() default false;
/**
- (Optional) Whether the database column is nullable.
*/
boolean nullable() default true;
/**
- (Optional) Whether the column is included in SQL INSERT
- statements generated by the persistence provider.
*/
boolean insertable() default true;
/**
- (Optional) Whether the column is included in SQL UPDATE
- statements generated by the persistence provider.
*/
boolean updatable() default true;
/**
- (Optional) The SQL fragment that is used when
- generating the DDL for the column.
-
Defaults to the generated SQL to create a
- column of the inferred type.
*/
String columnDefinition() default "";
/**
- (Optional) The name of the table that contains the column.
- If absent the column is assumed to be in the primary table.
*/
String table() default "";
/**
- (Optional) The column length. (Applies only if a
- string-valued column is used.)
*/
int length() default 255;
/**
- (Optional) The precision for a decimal (exact numeric)
- column. (Applies only if a decimal column is used.)
- Value must be set by developer if used when generating
- the DDL for the column.
*/
int precision() default 0;
/**
- (Optional) The scale for a decimal (exact numeric) column.
- (Applies only if a decimal column is used.)
*/
int scale() default 0;
}
package com.example.test.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
@Entity
@Table(name = "user
")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50, unique = true)
private String username;
@Column(nullable = false, length = 100)
private String password;
@Column(name = "real_name", length = 50)
private String realName;
@Column(length = 100)
private String email;
@Column(length = 20)
private String phone;
@Column(length = 50)
private String department;
@Column(length = 50)
private String position;
@Column(columnDefinition = "tinyint(1) default 1")
private Boolean status;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "last_login_time")
private LocalDateTime lastLoginTime;
@Column(length = 20, columnDefinition = "varchar(20) default 'USER'")
private String role;
// 默认构造函数
public User() {
this.role = "USER";
}
// 带参数的构造函数
public User(String username, String password) {
this.username = username;
this.password = password;
this.status = true;
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
this.role = "USER";
}
// 完整参数的构造函数
public User(String username, String password, String realName, String email, String phone,
String department, String position, Boolean status,
LocalDateTime createTime, LocalDateTime updateTime, LocalDateTime lastLoginTime) {
this.username = username;
this.password = password;
this.realName = realName;
this.email = email;
this.phone = phone;
this.department = department;
this.position = position;
this.status = status;
this.createTime = createTime;
this.updateTime = updateTime;
this.lastLoginTime = lastLoginTime;
this.role = "USER";
}
// 完整参数的构造函数(包含角色)
public User(String username, String password, String realName, String email, String phone,
String department, String position, Boolean status,
LocalDateTime createTime, LocalDateTime updateTime, LocalDateTime lastLoginTime,
String role) {
this.username = username;
this.password = password;
this.realName = realName;
this.email = email;
this.phone = phone;
this.department = department;
this.position = position;
this.status = status;
this.createTime = createTime;
this.updateTime = updateTime;
this.lastLoginTime = lastLoginTime;
this.role = role;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public LocalDateTime getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(LocalDateTime lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
// 判断是否为管理员
public boolean isAdmin() {
return "ADMIN".equals(this.role);
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", realName='" + realName + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", department='" + department + '\'' +
", position='" + position + '\'' +
", status=" + status +
", createTime=" + createTime +
", updateTime=" + updateTime +
", lastLoginTime=" + lastLoginTime +
", role='" + role + '\'' +
'}';
}
}package com.example.test.repository;
import com.example.test.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
// 可以添加自定义查询方法
}package com.example.test.repository;
import com.example.test.entity.SalesOrder;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SalesOrderRepository extends JpaRepository<SalesOrder, Long> {
// 可以添加自定义查询方法
}package com.example.test.repository;
import com.example.test.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.List;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 根据用户名查找用户
User findByUsername(String username);
// 根据邮箱查找用户
User findByEmail(String email);
// 根据电话查找用户
User findByPhone(String phone);
// 根据部门查找用户列表
List<User> findByDepartment(String department);
// 根据职位查找用户列表
List<User> findByPosition(String position);
// 根据状态查找用户列表
List<User> findByStatus(Boolean status);
// 根据真实姓名模糊查询
List<User> findByRealNameContaining(String realName);
// 查找指定时间之后创建的用户
List<User> findByCreateTimeAfter(LocalDateTime createTime);
// 查找指定时间之后登录的用户
List<User> findByLastLoginTimeAfter(LocalDateTime lastLoginTime);
// 自定义查询 - 根据部门和职位查找用户
@Query("SELECT u FROM User u WHERE u.department = :department AND u.position = :position")
List<User> findByDepartmentAndPosition(@Param("department") String department, @Param("position") String position);
// 根据角色查找用户列表
List<User> findByRole(String role);
// 查找所有管理员
@Query("SELECT u FROM User u WHERE u.role = 'ADMIN'")
List<User> findAllAdmins();
}package com.example.test.service;
import com.example.test.entity.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import java.util.List;
/**
-
管理员服务类,提供对所有实体的通用操作
*/
@Service
public class AdminService {@PersistenceContext
private EntityManager entityManager;/**
- 获取所有实体记录
*/
publicList findAll(Class entityClass) {
return entityManager.createQuery("FROM " + entityClass.getSimpleName(), entityClass).getResultList();
}
/**
- 根据ID查找实体
*/
publicT findById(Class entityClass, Long id) {
return entityManager.find(entityClass, id);
}
/**
- 保存实体
*/
@Transactional
publicT save(T entity) {
if (entity == null) {
return null;
}
return entityManager.merge(entity);
}
/**
- 删除实体
*/
@Transactional
publicvoid delete(Class entityClass, Long id) {
T entity = findById(entityClass, id);
if (entity != null) {
entityManager.remove(entity);
}
}
/**
- 执行自定义查询
*/
publicList executeQuery(String jpql, Class resultClass) {
return entityManager.createQuery(jpql, resultClass).getResultList();
}
/**
- 执行自定义更新操作
*/
@Transactional
public int executeUpdate(String jpql) {
Query query = entityManager.createQuery(jpql);
return query.executeUpdate();
}
/**
- 根据实体名称获取对应的类
*/
public Class<?> getEntityClassByName(String entityName) {
try {
switch (entityName.toLowerCase()) {
case "user":
return User.class;
case "salesorder":
return SalesOrder.class;
case "orderproduct":
return OrderProduct.class;
case "missingproduct":
return MissingProduct.class;
case "product":
return Product.class;
case "productcycle":
return ProductCycle.class;
case "orderreview":
return OrderReview.class;
case "orderchange":
return OrderChange.class;
case "forecastplan":
return ForecastPlan.class;
case "deliveryorder":
return DeliveryOrder.class;
case "contactform":
return ContactForm.class;
case "deliverystatistics":
return DeliveryStatistics.class;
default:
return null;
}
} catch (Exception e) {
return null;
}
}
}package com.example.test.service;
- 获取所有实体记录
import com.example.test.entity.User;
import com.example.test.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 创建用户
@Transactional
public User createUser(User user) {
// 设置默认值
if (user.getStatus() == null) {
user.setStatus(true);
}
if (user.getCreateTime() == null) {
user.setCreateTime(LocalDateTime.now());
}
if (user.getUpdateTime() == null) {
user.setUpdateTime(LocalDateTime.now());
}
if (user.getRole() == null) {
user.setRole("USER");
}
return userRepository.save(user);
}
// 创建管理员
@Transactional
public User createAdmin(User user) {
user.setRole("ADMIN");
return createUser(user);
}
// 更新用户
@Transactional
public User updateUser(User user) {
user.setUpdateTime(LocalDateTime.now());
return userRepository.save(user);
}
// 保存用户(创建或更新)
@Transactional
public User saveUser(User user) {
if (user.getId() == null) {
return createUser(user);
} else {
return updateUser(user);
}
}
// 根据ID查找用户
public Optional<User> findUserById(Long id) {
return userRepository.findById(id);
}
// 查找所有用户
public List<User> findAllUsers() {
return userRepository.findAll();
}
// 根据用户名查找用户
public User findUserByUsername(String username) {
return userRepository.findByUsername(username);
}
// 根据邮箱查找用户
public User findUserByEmail(String email) {
return userRepository.findByEmail(email);
}
// 根据电话查找用户
public User findUserByPhone(String phone) {
return userRepository.findByPhone(phone);
}
// 根据部门查找用户列表
public List<User> findUsersByDepartment(String department) {
return userRepository.findByDepartment(department);
}
// 根据职位查找用户列表
public List<User> findUsersByPosition(String position) {
return userRepository.findByPosition(position);
}
// 根据部门和职位查找用户列表
public List<User> findUsersByDepartmentAndPosition(String department, String position) {
return userRepository.findByDepartmentAndPosition(department, position);
}
// 根据状态查找用户列表
public List<User> findUsersByStatus(Boolean status) {
return userRepository.findByStatus(status);
}
// 根据角色查找用户列表
public List<User> findUsersByRole(String role) {
return userRepository.findByRole(role);
}
// 查找所有管理员
public List<User> findAllAdmins() {
return userRepository.findAllAdmins();
}
// 根据真实姓名模糊查询
public List<User> findUsersByRealNameContaining(String realName) {
return userRepository.findByRealNameContaining(realName);
}
// 查找指定时间之后创建的用户
public List<User> findUsersByCreateTimeAfter(LocalDateTime createTime) {
return userRepository.findByCreateTimeAfter(createTime);
}
// 查找指定时间之后登录的用户
public List<User> findUsersByLastLoginTimeAfter(LocalDateTime lastLoginTime) {
return userRepository.findByLastLoginTimeAfter(lastLoginTime);
}
// 用户登录
@Transactional
public User login(String username, String password) {
User user = userRepository.findByUsername(username);
if (user != null && password.equals(user.getPassword())) {
// 更新最后登录时间
user.setLastLoginTime(LocalDateTime.now());
return userRepository.save(user);
}
return null;
}
// 启用用户
@Transactional
public User enableUser(Long id) {
Optional<User> optionalUser = userRepository.findById(id);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user.setStatus(true);
user.setUpdateTime(LocalDateTime.now());
return userRepository.save(user);
}
return null;
}
// 禁用用户
@Transactional
public User disableUser(Long id) {
Optional<User> optionalUser = userRepository.findById(id);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user.setStatus(false);
user.setUpdateTime(LocalDateTime.now());
return userRepository.save(user);
}
return null;
}
// 设置用户为管理员
@Transactional
public User setUserAsAdmin(Long id) {
Optional<User> optionalUser = userRepository.findById(id);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user.setRole("ADMIN");
user.setUpdateTime(LocalDateTime.now());
return userRepository.save(user);
}
return null;
}
// 取消用户的管理员权限
@Transactional
public User removeAdminRole(Long id) {
Optional<User> optionalUser = userRepository.findById(id);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
user.setRole("USER");
user.setUpdateTime(LocalDateTime.now());
return userRepository.save(user);
}
return null;
}
// 删除用户
@Transactional
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
package com.example.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block sidebar collapse">
<div class="position-sticky pt-3 sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/admin/dashboard">
<span data-feather="home"></span>
仪表盘
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/admin/users">
<span data-feather="users"></span>
用户管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('salesorder')">
<span data-feather="file"></span>
销售订单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('product')">
<span data-feather="shopping-cart"></span>
产品管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('productcycle')">
<span data-feather="clock"></span>
产品周期管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('orderreview')">
<span data-feather="check-square"></span>
订单审核管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('orderchange')">
<span data-feather="edit"></span>
订单变更管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('forecastplan')">
<span data-feather="trending-up"></span>
预测计划管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('deliveryorder')">
<span data-feather="truck"></span>
发货单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('contactform')">
<span data-feather="mail"></span>
联系单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('deliverystatistics')">
<span data-feather="bar-chart-2"></span>
发货统计管理
</a>
</li>
</ul>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">管理员仪表盘</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
<button type="button" class="btn btn-sm btn-outline-secondary" id="refreshBtn">刷新</button>
<button type="button" class="btn btn-sm btn-outline-primary" id="addBtn" style="display:none;">添加</button>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-3 mb-4">
<div class="card text-white bg-primary">
<div class="card-body">
<h5 class="card-title">用户总数</h5>
<p class="card-text" id="userCount">加载中...</p>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card text-white bg-success">
<div class="card-body">
<h5 class="card-title">订单总数</h5>
<p class="card-text" id="orderCount">加载中...</p>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card text-white bg-info">
<div class="card-body">
<h5 class="card-title">产品总数</h5>
<p class="card-text" id="productCount">加载中...</p>
</div>
</div>
</div>
<div class="col-md-3 mb-4">
<div class="card text-white bg-warning">
<div class="card-body">
<h5 class="card-title">待审核订单</h5>
<p class="card-text" id="pendingReviewCount">加载中...</p>
</div>
</div>
</div>
</div>
<div id="entityTableContainer" style="display:none;">
<h2 id="entityTitle"></h2>
<div class="table-responsive">
<table class="table table-striped table-sm" id="entityTable">
<thead>
<tr id="tableHeader">
<!-- 表头将动态生成 -->
</tr>
</thead>
<tbody id="tableBody">
<!-- 表内容将动态生成 -->
</tbody>
</table>
</div>
</div>
<div id="welcomeMessage">
<div class="jumbotron">
<h1 class="display-4">欢迎,<span th:text="${currentUser.realName}">管理员</span>!</h1>
<p class="lead">这是销售订单管理系统的管理员控制面板。您可以在这里管理系统中的所有数据。</p>
<hr class="my-4">
<p>请从左侧菜单选择要管理的数据类型。</p>
</div>
</div>
<!-- 添加/编辑实体的模态框 -->
<div class="modal fade" id="entityModal" tabindex="-1" aria-labelledby="entityModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="entityModalLabel">添加/编辑</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="entityForm">
<!-- 表单内容将动态生成 -->
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="saveEntityBtn">保存</button>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script>
<script>
// 初始化Feather图标
document.addEventListener('DOMContentLoaded', function() {
feather.replace();
loadDashboardData();
});
// 添加一个获取认证令牌的函数
function getAuthToken() {
// 从localStorage或sessionStorage获取令牌
return localStorage.getItem('authToken') || sessionStorage.getItem('authToken');
}
// 创建一个通用的fetch函数,自动添加认证头
function authenticatedFetch(url, options = {}) {
const token = getAuthToken();
const headers = {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : ''
};
return fetch(url, {
...options,
headers: {
...headers,
...(options.headers || {})
}
});
}
// 修改loadDashboardData函数
function loadDashboardData() {
// 获取用户总数
authenticatedFetch('/api/admin/user')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误 ${response.status}`);
}
return response.json();
})
.then(data => {
document.getElementById('userCount').textContent = data.length;
})
.catch(error => {
document.getElementById('userCount').textContent = '获取失败';
console.error('获取用户数据失败:', error);
});
// 其他fetch调用也需要类似修改
// 获取订单总数
fetch('/api/admin/salesorder')
.then(response => response.json())
.then(data => {
document.getElementById('orderCount').textContent = data.length;
})
.catch(error => {
document.getElementById('orderCount').textContent = '获取失败';
console.error('获取订单数据失败:', error);
});
// 获取产品总数
fetch('/api/admin/product')
.then(response => response.json())
.then(data => {
document.getElementById('productCount').textContent = data.length;
})
.catch(error => {
document.getElementById('productCount').textContent = '获取失败';
console.error('获取产品数据失败:', error);
});
// 获取待审核订单数
fetch('/api/admin/orderreview')
.then(response => response.json())
.then(data => {
const pendingReviews = data.filter(review => review.status === 'PENDING');
document.getElementById('pendingReviewCount').textContent = pendingReviews.length;
})
.catch(error => {
document.getElementById('pendingReviewCount').textContent = '获取失败';
console.error('获取审核数据失败:', error);
});
}
// 当前实体类型
let currentEntityType = '';
// 加载实体数据
function loadEntityData(entityType) {
currentEntityType = entityType;
document.getElementById('welcomeMessage').style.display = 'none';
document.getElementById('entityTableContainer').style.display = 'block';
// 确保addBtn元素存在并设置其样式
const addBtn = document.getElementById('addBtn');
if (addBtn) {
addBtn.style.display = 'block';
console.log('设置addBtn显示');
} else {
console.error('未找到addBtn元素');
}
// 设置实体标题
const entityTitles = {
'user': '用户管理',
'salesorder': '销售订单管理',
'orderproduct': '订单产品管理',
'missingproduct': '缺货产品管理',
'product': '产品管理',
'productcycle': '产品周期管理',
'orderreview': '订单审核管理',
'orderchange': '订单变更管理',
'forecastplan': '预测计划管理',
'deliveryorder': '发货单管理',
'contactform': '联系单管理',
'deliverystatistics': '发货统计管理'
};
document.getElementById('entityTitle').textContent = entityTitles[entityType] || entityType;
// 获取实体数据
authenticatedFetch(`/api/admin/${entityType}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误 ${response.status}`);
}
return response.json();
})
.then(data => {
renderEntityTable(data, entityType);
})
.catch(error => {
console.error(`获取${entityType}数据失败:`, error);
alert(`获取数据失败: ${error.message}`);
});
}
// 渲染实体表格
function renderEntityTable(data, entityType) {
const tableHeader = document.getElementById('tableHeader');
const tableBody = document.getElementById('tableBody');
// 清空表头和表内容
tableHeader.innerHTML = '';
tableBody.innerHTML = '';
// 如果没有数据,显示提示信息
if (!data || data.length === 0) {
tableBody.innerHTML = `<tr><td colspan="3">暂无${entityType}数据</td></tr>`;
return;
}
// 获取第一条数据的所有属性作为表头
const firstItem = data[0];
const headers = Object.keys(firstItem);
// 添加ID列
const idCell = document.createElement('th');
idCell.textContent = 'ID';
tableHeader.appendChild(idCell);
// 添加其他属性列(最多显示5个关键属性)
const keyProperties = getKeyProperties(entityType, headers);
keyProperties.forEach(prop => {
const headerCell = document.createElement('th');
headerCell.textContent = getPropertyDisplayName(prop);
tableHeader.appendChild(headerCell);
});
// 添加操作列
const actionCell = document.createElement('th');
actionCell.textContent = '操作';
tableHeader.appendChild(actionCell);
// 添加表内容
data.forEach(item => {
const row = document.createElement('tr');
// 添加ID列
const idCell = document.createElement('td');
idCell.textContent = item.id;
row.appendChild(idCell);
// 添加其他属性列
keyProperties.forEach(prop => {
const cell = document.createElement('td');
cell.textContent = formatPropertyValue(item[prop]);
row.appendChild(cell);
});
// 添加操作列
const actionCell = document.createElement('td');
actionCell.innerHTML = `
<button class="btn btn-sm btn-outline-primary me-1" onclick="editEntity('${entityType}', ${item.id})">编辑</button>
<button class="btn btn-sm btn-outline-danger" onclick="deleteEntity('${entityType}', ${item.id})">删除</button>
`;
row.appendChild(actionCell);
tableBody.appendChild(row);
});
}
// 获取实体的关键属性(最多5个)
function getKeyProperties(entityType, allProperties) {
// 排除id和一些不重要的属性
const excludeProps = ['id', 'createTime', 'updateTime', 'lastLoginTime'];
const filteredProps = allProperties.filter(prop => !excludeProps.includes(prop));
// 根据实体类型返回特定的关键属性
switch(entityType) {
case 'user':
return ['username', 'realName', 'department', 'position', 'role'];
case 'salesorder':
return ['orderNumber', 'customerName', 'orderDate', 'deliveryDate', 'status'];
case 'product':
return ['productCode', 'productName', 'specification', 'unit', 'price'];
default:
// 如果没有特定配置,返回前5个属性
return filteredProps.slice(0, 5);
}
}
// 获取属性的显示名称
function getPropertyDisplayName(propertyName) {
const displayNames = {
'username': '用户名',
'realName': '姓名',
'department': '部门',
'position': '职位',
'role': '角色',
'orderNumber': '订单编号',
'customerName': '客户名称',
'orderDate': '订单日期',
'deliveryDate': '交付日期',
'status': '状态',
'productCode': '产品编码',
'productName': '产品名称',
'specification': '规格',
'unit': '单位',
'price': '价格'
};
return displayNames[propertyName] || propertyName;
}
// 格式化属性值
function formatPropertyValue(value) {
if (value === null || value === undefined) {
return '';
}
if (value instanceof Date || (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/))) {
const date = new Date(value);
return date.toLocaleString();
}
if (typeof value === 'object') {
return JSON.stringify(value);
}
return value.toString();
}
// 编辑实体
function editEntity(entityType, id) {
// 获取实体数据
authenticatedFetch(`/api/admin/${entityType}/${id}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误 ${response.status}`);
}
return response.json();
})
.then(data => {
showEntityModal(entityType, data);
})
.catch(error => {
console.error(`获取${entityType}数据失败:`, error);
alert(`获取数据失败: ${error.message}`);
});
}
// 删除实体
function deleteEntity(entityType, id) {
if (confirm(`确定要删除ID为${id}的${entityType}记录吗?`)) {
authenticatedFetch(`/api/admin/${entityType}/${id}`, {
method: 'DELETE'
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误 ${response.status}`);
}
return response.json();
})
.then(data => {
alert(data.message || '删除成功');
loadEntityData(entityType);
})
.catch(error => {
console.error(`删除${entityType}数据失败:`, error);
alert(`删除失败: ${error.message}`);
});
}
}
// 显示实体模态框
function showEntityModal(entityType, data = null) {
const modal = new bootstrap.Modal(document.getElementById('entityModal'));
const form = document.getElementById('entityForm');
const modalTitle = document.getElementById('entityModalLabel');
// 设置模态框标题
modalTitle.textContent = data ? `编辑${entityType}` : `添加${entityType}`;
// 清空表单
form.innerHTML = '';
// 如果是编辑模式,添加隐藏的ID字段
if (data) {
const idField = document.createElement('input');
idField.type = 'hidden';
idField.name = 'id';
idField.value = data.id;
form.appendChild(idField);
}
// 根据实体类型创建表单字段
if (data) {
// 编辑模式:使用现有数据的所有字段
Object.keys(data).forEach(key => {
// 排除id字段(已经作为隐藏字段添加)
if (key !== 'id') {
createFormField(form, key, data[key]);
}
});
} else {
// 添加模式:根据实体类型创建必要的字段
const requiredFields = getRequiredFields(entityType);
requiredFields.forEach(field => {
createFormField(form, field.name, field.defaultValue);
});
}
// 设置保存按钮的点击事件
document.getElementById('saveEntityBtn').onclick = function() {
saveEntity(entityType, data ? data.id : null);
};
// 显示模态框
modal.show();
}
// 创建表单字段
function createFormField(form, fieldName, fieldValue) {
const formGroup = document.createElement('div');
formGroup.className = 'mb-3';
const label = document.createElement('label');
label.htmlFor = fieldName;
label.className = 'form-label';
label.textContent = getPropertyDisplayName(fieldName);
let input;
// 根据字段类型创建不同的输入控件
if (fieldName.toLowerCase().includes('date') || fieldName.toLowerCase().includes('time')) {
// 日期时间字段
input = document.createElement('input');
input.type = 'datetime-local';
if (fieldValue) {
const date = new Date(fieldValue);
input.value = date.toISOString().slice(0, 16);
}
} else if (typeof fieldValue === 'boolean') {
// 布尔字段
input = document.createElement('select');
const trueOption = document.createElement('option');
trueOption.value = 'true';
trueOption.textContent = '是';
const falseOption = document.createElement('option');
falseOption.value = 'false';
falseOption.textContent = '否';
input.appendChild(trueOption);
input.appendChild(falseOption);
input.value = fieldValue.toString();
} else if (fieldName === 'status' && typeof fieldValue === 'string') {
// 状态字段
input = document.createElement('select');
const statuses = ['PENDING', 'APPROVED', 'REJECTED', 'COMPLETED', 'CANCELLED'];
statuses.forEach(status => {
const option = document.createElement('option');
option.value = status;
option.textContent = status;
input.appendChild(option);
});
input.value = fieldValue;
} else if (fieldName === 'role') {
// 角色字段
input = document.createElement('select');
const roles = ['USER', 'ADMIN'];
roles.forEach(role => {
const option = document.createElement('option');
option.value = role;
option.textContent = role;
input.appendChild(option);
});
input.value = fieldValue || 'USER';
} else if (typeof fieldValue === 'number') {
// 数字字段
input = document.createElement('input');
input.type = 'number';
input.step = '0.01';
input.value = fieldValue;
} else if (typeof fieldValue === 'object' && fieldValue !== null) {
// 对象字段(如外键关联)
input = document.createElement('input');
input.type = 'text';
input.value = JSON.stringify(fieldValue);
} else {
// 文本字段
input = document.createElement('input');
input.type = 'text';
input.value = fieldValue || '';
}
input.id = fieldName;
input.name = fieldName;
input.className = 'form-control';
formGroup.appendChild(label);
formGroup.appendChild(input);
form.appendChild(formGroup);
}
// 获取实体的必要字段
function getRequiredFields(entityType) {
switch(entityType) {
case 'user':
return [
{ name: 'username', defaultValue: '' },
{ name: 'password', defaultValue: '' },
{ name: 'realName', defaultValue: '' },
{ name: 'email', defaultValue: '' },
{ name: 'phone', defaultValue: '' },
{ name: 'department', defaultValue: '' },
{ name: 'position', defaultValue: '' },
{ name: 'role', defaultValue: 'USER' },
{ name: 'status', defaultValue: true }
];
case 'product':
return [
{ name: 'productCode', defaultValue: '' },
{ name: 'productName', defaultValue: '' },
{ name: 'specification', defaultValue: '' },
{ name: 'unit', defaultValue: '' },
{ name: 'price', defaultValue: 0 }
];
// 可以根据需要添加其他实体类型的必要字段
default:
return [];
}
}
// 保存实体
// 保存实体
function saveEntity(entityType, id) {
const form = document.getElementById('entityForm');
const formData = new FormData(form);
const data = {};
// 将表单数据转换为JSON对象
formData.forEach((value, key) => {
// 处理特殊类型的值
if (key.toLowerCase().includes('date') || key.toLowerCase().includes('time')) {
// 日期时间字段
data[key] = value ? new Date(value).toISOString() : null;
} else if (value === 'true' || value === 'false') {
// 布尔字段
data[key] = value === 'true';
} else if (!isNaN(value) && value !== '' && !key.toLowerCase().includes('phone')) {
// 数字字段(排除电话号码)
data[key] = Number(value);
} else {
// 其他字段
data[key] = value;
}
});
// 确定请求方法和URL
const method = id ? 'PUT' : 'POST';
const url = id ? `/api/admin/${entityType}/${id}` : `/api/admin/${entityType}`;
// 发送请求
authenticatedFetch(url, {
method: method,
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP错误 ${response.status}`);
}
return response.json();
})
.then(result => {
// 关闭模态框
const modal = bootstrap.Modal.getInstance(document.getElementById('entityModal'));
modal.hide();
// 重新加载数据
loadEntityData(entityType);
// 显示成功消息
alert(id ? '更新成功' : '添加成功');
})
.catch(error => {
console.error(`保存${entityType}数据失败:`, error);
alert(`保存失败: ${error.message}`);
});
}
// 添加按钮点击事件
document.getElementById('addBtn').addEventListener('click', function() {
showEntityModal(currentEntityType);
});
// 刷新按钮点击事件
document.getElementById('refreshBtn').addEventListener('click', function() {
if (currentEntityType) {
loadEntityData(currentEntityType);
} else {
loadDashboardData();
}
});
</script>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block sidebar collapse">
<div class="position-sticky pt-3 sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="/admin/dashboard">
<span data-feather="home"></span>
仪表盘
</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/admin/users">
<span data-feather="users"></span>
用户管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('salesorder')">
<span data-feather="file"></span>
销售订单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('product')">
<span data-feather="shopping-cart"></span>
产品管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('productcycle')">
<span data-feather="clock"></span>
产品周期管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('orderreview')">
<span data-feather="check-square"></span>
订单审核管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('orderchange')">
<span data-feather="edit"></span>
订单变更管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('forecastplan')">
<span data-feather="trending-up"></span>
预测计划管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('deliveryorder')">
<span data-feather="truck"></span>
发货单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('contactform')">
<span data-feather="mail"></span>
联系单管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" onclick="loadEntityData('deliverystatistics')">
<span data-feather="bar-chart-2"></span>
发货统计管理
</a>
</li>
</ul>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">用户管理</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2">
<button type="button" class="btn btn-sm btn-outline-secondary" id="refreshBtn">刷新</button>
<button type="button" class="btn btn-sm btn-outline-primary" id="addUserBtn">添加用户</button>
</div>
</div>
</div>
<!-- 搜索表单 -->
<div class="row mb-3">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<form id="searchForm" class="row g-3">
<div class="col-md-3">
<label for="searchUsername" class="form-label">用户名</label>
<input type="text" class="form-control" id="searchUsername" name="username">
</div>
<div class="col-md-3">
<label for="searchRealName" class="form-label">姓名</label>
<input type="text" class="form-control" id="searchRealName" name="realName">
</div>
<div class="col-md-3">
<label for="searchDepartment" class="form-label">部门</label>
<input type="text" class="form-control" id="searchDepartment" name="department">
</div>
<div class="col-md-3">
<label for="searchPosition" class="form-label">职位</label>
<input type="text" class="form-control" id="searchPosition" name="position">
</div>
<div class="col-md-3">
<label for="searchRole" class="form-label">角色</label>
<select class="form-select" id="searchRole" name="role">
<option value="">全部</option>
<option value="USER">普通用户</option>
<option value="ADMIN">管理员</option>
</select>
</div>
<div class="col-md-3">
<label for="searchStatus" class="form-label">状态</label>
<select class="form-select" id="searchStatus" name="status">
<option value="">全部</option>
<option value="true">启用</option>
<option value="false">禁用</option>
</select>
</div>
<div class="col-md-3 d-flex align-items-end">
<button type="button" class="btn btn-primary" id="searchBtn">搜索</button>
<button type="button" class="btn btn-secondary ms-2" id="resetBtn">重置</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- 用户表格 -->
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>姓名</th>
<th>邮箱</th>
<th>电话</th>
<th>部门</th>
<th>职位</th>
<th>角色</th>
<th>状态</th>
<th>创建时间</th>
<th>最后登录</th>
<th>操作</th>
</tr>
</thead>
<tbody id="userTableBody">
<!-- 用户数据将动态加载 -->
</tbody>
</table>
</div>
<!-- 分页控件 -->
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center" id="pagination">
<!-- 分页将动态生成 -->
</ul>
</nav>
<!-- 添加/编辑用户模态框 -->
<div class="modal fade" id="userModal" tabindex="-1" aria-labelledby="userModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="userModalLabel">添加用户</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="userForm">
<input type="hidden" id="userId" name="id">
<div class="mb-3">
<label for="username" class="form-label">用户名</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3" id="passwordGroup">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3">
<label for="realName" class="form-label">姓名</label>
<input type="text" class="form-control" id="realName" name="realName" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">邮箱</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="phone" class="form-label">电话</label>
<input type="text" class="form-control" id="phone" name="phone" required>
</div>
<div class="mb-3">
<label for="department" class="form-label">部门</label>
<input type="text" class="form-control" id="department" name="department" required>
</div>
<div class="mb-3">
<label for="position" class="form-label">职位</label>
<input type="text" class="form-control" id="position" name="position" required>
</div>
<div class="mb-3">
<label for="role" class="form-label">角色</label>
<select class="form-select" id="role" name="role" required>
<option value="USER">普通用户</option>
<option value="ADMIN">管理员</option>
</select>
</div>
<div class="mb-3">
<label for="status" class="form-label">状态</label>
<select class="form-select" id="status" name="status" required>
<option value="true">启用</option>
<option value="false">禁用</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="saveUserBtn">保存</button>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons@4.28.0/dist/feather.min.js"></script>
<script>
// 初始化Feather图标
document.addEventListener('DOMContentLoaded', function() {
feather.replace();
loadUsers();
});
// 当前页码和每页数量
let currentPage = 0;
let pageSize = 10;
let totalPages = 0;
// 加载用户数据
function loadUsers(page = 0, size = 10) {
currentPage = page;
pageSize = size;
// 获取搜索参数
const searchParams = new URLSearchParams();
searchParams.append('page', page);
searchParams.append('size', size);
// 添加搜索条件
const username = document.getElementById('searchUsername').value;
const realName = document.getElementById('searchRealName').value;
const department = document.getElementById('searchDepartment').value;
const position = document.getElementById('searchPosition').value;
const role = document.getElementById('searchRole').value;
const status = document.getElementById('searchStatus').value;
if (username) searchParams.append('username', username);
if (realName) searchParams.append('realName', realName);
if (department) searchParams.append('department', department);
if (position) searchParams.append('position', position);
if (role) searchParams.append('role', role);
if (status) searchParams.append('status', status);
// 发送请求获取用户数据
fetch(`/api/admin/users?${searchParams.toString()}`)
.then(response => response.json())
.then(data => {
renderUsers(data.content);
renderPagination(data.totalPages);
})
.catch(error => {
console.error('获取用户数据失败:', error);
alert('获取用户数据失败: ' + error.message);
});
}
// 渲染用户表格
function renderUsers(users) {
const tableBody = document.getElementById('userTableBody');
tableBody.innerHTML = '';
if (!users || users.length === 0) {
const row = document.createElement('tr');
row.innerHTML = '<td colspan="12" class="text-center">暂无用户数据</td>';
tableBody.appendChild(row);
return;
}
users.forEach(user => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.realName || ''}</td>
<td>${user.email || ''}</td>
<td>${user.phone || ''}</td>
<td>${user.department || ''}</td>
<td>${user.position || ''}</td>
<td>${user.role === 'ADMIN' ? '<span class="badge bg-danger">管理员</span>' : '<span class="badge bg-secondary">普通用户</span>'}</td>
<td>${user.status ? '<span class="badge bg-success">启用</span>' : '<span class="badge bg-danger">禁用</span>'}</td>
<td>${formatDateTime(user.createTime)}</td>
<td>${formatDateTime(user.lastLoginTime)}</td>
<td>
<button class="btn btn-sm btn-outline-primary me-1" onclick="editUser(${user.id})">编辑</button>
<button class="btn btn-sm btn-outline-${user.status ? 'warning' : 'success'}" onclick="toggleUserStatus(${user.id}, ${!user.status})">${user.status ? '禁用' : '启用'}</button>
<button class="btn btn-sm btn-outline-danger" onclick="deleteUser(${user.id})">删除</button>
</td>
`;
tableBody.appendChild(row);
});
}
// 渲染分页控件
function renderPagination(totalPages) {
const pagination = document.getElementById('pagination');
pagination.innerHTML = '';
// 如果总页数小于等于1,不显示分页
if (totalPages <= 1) {
return;
}
// 上一页按钮
const prevItem = document.createElement('li');
prevItem.className = `page-item ${currentPage === 0 ? 'disabled' : ''}`;
prevItem.innerHTML = `<a class="page-link" href="#" onclick="${currentPage > 0 ? 'loadUsers(' + (currentPage - 1) + ')' : ''}">上一页</a>`;
pagination.appendChild(prevItem);
// 页码按钮
const maxVisiblePages = 5;
let startPage = Math.max(0, currentPage - Math.floor(maxVisiblePages / 2));
let endPage = Math.min(totalPages - 1, startPage + maxVisiblePages - 1);
// 调整startPage,确保显示maxVisiblePages个页码
if (endPage - startPage + 1 < maxVisiblePages) {
startPage = Math.max(0, endPage - maxVisiblePages + 1);
}
for (let i = startPage; i <= endPage; i++) {
const pageItem = document.createElement('li');
pageItem.className = `page-item ${i === currentPage ? 'active' : ''}`;
pageItem.innerHTML = `<a class="page-link" href="#" onclick="loadUsers(${i})">${i + 1}</a>`;
pagination.appendChild(pageItem);
}
// 下一页按钮
const nextItem = document.createElement('li');
nextItem.className = `page-item ${currentPage >= totalPages - 1 ? 'disabled' : ''}`;
nextItem.innerHTML = `<a class="page-link" href="#" onclick="${currentPage < totalPages - 1 ? 'loadUsers(' + (currentPage + 1) + ')' : ''}">下一页</a>`;
pagination.appendChild(nextItem);
}
// 格式化日期时间
function formatDateTime(dateTimeStr) {
if (!dateTimeStr) return '';
const date = new Date(dateTimeStr);
return date.toLocaleString();
}
// 添加用户按钮点击事件
document.getElementById('addUserBtn').addEventListener('click', function() {
// 重置表单
document.getElementById('userForm').reset();
document.getElementById('userId').value = '';
document.getElementById('passwordGroup').style.display = 'block';
document.getElementById('password').required = true;
document.getElementById('userModalLabel').textContent = '添加用户';
// 显示模态框
const modal = new bootstrap.Modal(document.getElementById('userModal'));
modal.show();
});
// 编辑用户
function editUser(userId) {
// 获取用户数据
fetch(`/api/admin/user/${userId}`)
.then(response => response.json())
.then(user => {
// 填充表单
document.getElementById('userId').value = user.id;
document.getElementById('username').value = user.username;
document.getElementById('passwordGroup').style.display = 'none';
document.getElementById('password').required = false;
document.getElementById('realName').value = user.realName || '';
document.getElementById('email').value = user.email || '';
document.getElementById('phone').value = user.phone || '';
document.getElementById('department').value = user.department || '';
document.getElementById('position').value = user.position || '';
document.getElementById('role').value = user.role || 'USER';
document.getElementById('status').value = user.status.toString();
document.getElementById('userModalLabel').textContent = '编辑用户';
// 显示模态框
const modal = new bootstrap.Modal(document.getElementById('userModal'));
modal.show();
})
.catch(error => {
console.error('获取用户数据失败:', error);
alert('获取用户数据失败: ' + error.message);
});
}
// 保存用户
document.getElementById('saveUserBtn').addEventListener('click', function() {
const form = document.getElementById('userForm');
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const userId = document.getElementById('userId').value;
const isEdit = userId !== '';
// 构建用户数据
const userData = {
username: document.getElementById('username').value,
realName: document.getElementById('realName').value,
email: document.getElementById('email').value,
phone: document.getElementById('phone').value,
department: document.getElementById('department').value,
position: document.getElementById('position').value,
role: document.getElementById('role').value,
status: document.getElementById('status').value === 'true'
};
// 如果是添加用户,需要包含密码
if (!isEdit) {
userData.password = document.getElementById('password').value;
}
// 如果是编辑用户,需要包含ID
if (isEdit) {
userData.id = parseInt(userId);
}
// 发送请求
const url = isEdit ? `/api/admin/user/${userId}` : '/api/admin/user';
const method = isEdit ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
})
.then(response => response.json())
.then(data => {
// 关闭模态框
const modal = bootstrap.Modal.getInstance(document.getElementById('userModal'));
modal.hide();
// 重新加载用户数据
loadUsers(currentPage, pageSize);
// 显示成功消息
alert(isEdit ? '用户更新成功' : '用户添加成功');
})
.catch(error => {
console.error('保存用户失败:', error);
alert('保存用户失败: ' + error.message);
});
});
// 切换用户状态
function toggleUserStatus(userId, newStatus) {
if (confirm(`确定要${newStatus ? '启用' : '禁用'}该用户吗?`)) {
fetch(`/api/admin/user/${userId}/status`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ status: newStatus })
})
.then(response => response.json())
.then(data => {
// 重新加载用户数据
loadUsers(currentPage, pageSize);
// 显示成功消息
alert(newStatus ? '用户已启用' : '用户已禁用');
})
.catch(error => {
console.error('更新用户状态失败:', error);
alert('更新用户状态失败: ' + error.message);
});
}
}
// 删除用户
function deleteUser(userId) {
if (confirm('确定要删除该用户吗?此操作不可恢复!')) {
fetch(`/api/admin/user/${userId}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
// 重新加载用户数据
loadUsers(currentPage, pageSize);
// 显示成功消息
alert('用户已删除');
})
.catch(error => {
console.error('删除用户失败:', error);
alert('删除用户失败: ' + error.message);
});
}
}
// 搜索按钮点击事件
document.getElementById('searchBtn').addEventListener('click', function() {
loadUsers(0, pageSize); // 重置为第一页
});
// 重置按钮点击事件
document.getElementById('resetBtn').addEventListener('click', function() {
document.getElementById('searchForm').reset();
loadUsers(0, pageSize); // 重置为第一页
});
// 刷新按钮点击事件
document.getElementById('refreshBtn').addEventListener('click', function() {
loadUsers(currentPage, pageSize);
});
</script>
404
页面未找到
<div class="error-image">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="#6c757d" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/>
</svg>
</div>
<p class="error-message">抱歉,您请求的页面不存在或已被移除。</p>
<div class="error-actions">
<a href="/" class="btn">返回首页</a>
</div>
</div>
500
服务器内部错误
<div class="error-image">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="#dc3545" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>
</svg>
</div>
<p class="error-message">抱歉,服务器遇到了一个错误,无法完成您的请求。</p>
<div class="error-details" th:if="${message}">
<p><strong>错误信息:</strong> <span th:text="${message}">错误详情</span></p>
<p th:if="${timestamp}"><strong>时间:</strong> <span th:text="${timestamp}">2023-01-01 00:00:00</span></p>
<p th:if="${path}"><strong>路径:</strong> <span th:text="${path}">/error</span></p>
</div>
<div class="error-actions">
<a href="/" class="btn">返回首页</a>
</div>
</div>
用户管理系统
<div class="sidebar">
<div class="sidebar-heading">数据管理</div>
<ul class="sidebar-menu">
<li data-entity="user" class="active"><i class="bi bi-people"></i>用户管理</li>
<li data-entity="salesorder"><i class="bi bi-cart"></i>销售订单</li>
<li data-entity="product"><i class="bi bi-box"></i>产品管理</li>
<li data-entity="orderproduct"><i class="bi bi-list-check"></i>订单产品</li>
<li data-entity="missingproduct"><i class="bi bi-exclamation-triangle"></i>缺货产品</li>
<li data-entity="productcycle"><i class="bi bi-arrow-repeat"></i>产品周期</li>
<li data-entity="orderreview"><i class="bi bi-star"></i>订单评审</li>
<li data-entity="orderchange"><i class="bi bi-pencil"></i>订单变更</li>
<li data-entity="forecastplan"><i class="bi bi-graph-up"></i>预测计划</li>
<li data-entity="deliveryorder"><i class="bi bi-truck"></i>交付订单</li>
<li data-entity="contactform"><i class="bi bi-envelope"></i>联系表单</li>
<li data-entity="deliverystatistics"><i class="bi bi-bar-chart"></i>交付统计</li>
</ul>
</div>
<div class="main-content">
<div class="welcome-message">
欢迎回来,<span th:text="${currentUser != null ? currentUser.username : '游客'}">用户</span>!
</div>
<div class="stats-container">
<div class="stat-card">
<h3>用户总数</h3>
<div class="value" id="userCount">0</div>
</div>
<div class="stat-card">
<h3>订单总数</h3>
<div class="value" id="orderCount">0</div>
</div>
<div class="stat-card">
<h3>产品总数</h3>
<div class="value" id="productCount">0</div>
</div>
<div class="stat-card">
<h3>评审总数</h3>
<div class="value" id="reviewCount">0</div>
</div>
</div>
<div class="entity-container">
<div class="entity-header">
<h2 id="entityTitle">用户管理</h2>
<div class="entity-actions">
<button id="refreshBtn" class="btn btn-secondary"><i class="bi bi-arrow-clockwise"></i> 刷新</button>
<button id="addBtn" class="btn btn-primary" th:if="${currentUser != null && currentUser.role == 'ADMIN'}"><i class="bi bi-plus"></i> 添加</button>
</div>
</div>
<div class="table-responsive">
<table class="entity-table" id="entityTable">
<thead>
<!-- 表头将通过JavaScript动态生成 -->
</thead>
<tbody>
<!-- 数据将通过JavaScript动态加载 -->
</tbody>
</table>
</div>
</div>
</div>
<!-- 添加/编辑实体的模态框 -->
<div class="modal fade" id="entityModal" tabindex="-1" aria-labelledby="entityModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="entityModalLabel">添加/编辑</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="entityForm">
<input type="hidden" id="entityId">
<div id="formFields">
<!-- 表单字段将通过JavaScript动态生成 -->
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="saveEntityBtn">保存</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 当前选中的实体类型
let currentEntityType = 'user';
// 模态框实例
let entityModal;
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 初始化模态框
entityModal = new bootstrap.Modal(document.getElementById('entityModal'));
// 加载仪表盘统计数据
loadDashboardStats();
// 加载默认实体数据(用户)
loadEntityData('user');
// 侧边栏菜单点击事件
document.querySelectorAll('.sidebar-menu li').forEach(item => {
item.addEventListener('click', function() {
// 移除所有活动状态
document.querySelectorAll('.sidebar-menu li').forEach(li => {
li.classList.remove('active');
});
// 添加当前项的活动状态
this.classList.add('active');
// 获取实体类型
const entityType = this.getAttribute('data-entity');
currentEntityType = entityType;
// 更新标题
document.getElementById('entityTitle').textContent = this.textContent.trim();
// 加载对应实体数据
loadEntityData(entityType);
});
});
// 刷新按钮点击事件
document.getElementById('refreshBtn').addEventListener('click', function() {
loadEntityData(currentEntityType);
});
// 添加按钮点击事件
document.getElementById('addBtn').addEventListener('click', function() {
showEntityModal();
});
// 保存实体按钮点击事件
document.getElementById('saveEntityBtn').addEventListener('click', function() {
saveEntity();
});
});
// 加载仪表盘统计数据
function loadDashboardStats() {
// 获取用户总数
fetch('/api/admin/user')
.then(response => response.json())
.then(data => {
document.getElementById('userCount').textContent = data.length;
})
.catch(error => console.error('获取用户数据失败:', error));
// 获取订单总数
fetch('/api/admin/salesorder')
.then(response => response.json())
.then(data => {
document.getElementById('orderCount').textContent = data.length;
})
.catch(error => console.error('获取订单数据失败:', error));
// 获取产品总数
fetch('/api/admin/product')
.then(response => response.json())
.then(data => {
document.getElementById('productCount').textContent = data.length;
})
.catch(error => console.error('获取产品数据失败:', error));
// 获取评审总数
fetch('/api/admin/orderreview')
.then(response => response.json())
.then(data => {
document.getElementById('reviewCount').textContent = data.length;
})
.catch(error => console.error('获取评审数据失败:', error));
}
// 加载实体数据
function loadEntityData(entityType) {
fetch(`/api/admin/${entityType}`)
.then(response => {
if (!response.ok) {
// 如果响应不成功,但状态码是404,可能是没有数据
if (response.status === 404) {
return [];
}
throw new Error('获取数据失败');
}
return response.json();
})
.then(data => {
renderEntityTable(entityType, data);
})
.catch(error => {
console.error(`获取${entityType}数据失败:`, error);
// 不再弹出错误提示,而是显示暂无数据
renderEntityTable(entityType, []);
});
}
// 渲染实体表格
function renderEntityTable(entityType, data) {
const table = document.getElementById('entityTable');
const thead = table.querySelector('thead');
const tbody = table.querySelector('tbody');
// 清空表格内容
tbody.innerHTML = '';
// 如果没有数据
if (!data || data.length === 0) {
tbody.innerHTML = `<tr><td colspan="7" class="text-center">暂无数据</td></tr>`;
return;
}
// 获取要显示的属性
const keyProperties = getKeyProperties(entityType);
// 创建表头
let headerRow = '<tr><th>ID</th>';
keyProperties.forEach(prop => {
headerRow += `<th>${getPropertyDisplayName(prop)}</th>`;
});
headerRow += '<th>操作</th></tr>';
thead.innerHTML = headerRow;
// 创建表格行
data.forEach(item => {
let row = document.createElement('tr');
// ID列
let idCell = document.createElement('td');
idCell.textContent = item.id;
row.appendChild(idCell);
// 属性列
keyProperties.forEach(prop => {
let cell = document.createElement('td');
cell.innerHTML = formatPropertyValue(item[prop], prop);
row.appendChild(cell);
});
// 操作列
let actionCell = document.createElement('td');
// 编辑按钮
let editBtn = document.createElement('button');
editBtn.className = 'action-btn edit-btn';
editBtn.innerHTML = '<i class="bi bi-pencil"></i>';
editBtn.addEventListener('click', function() {
editEntity(entityType, item.id);
});
actionCell.appendChild(editBtn);
// 删除按钮
let deleteBtn = document.createElement('button');
deleteBtn.className = 'action-btn delete-btn';
deleteBtn.innerHTML = '<i class="bi bi-trash"></i>';
deleteBtn.addEventListener('click', function() {
if (confirm('确定要删除这条记录吗?')) {
deleteEntity(entityType, item.id);
}
});
actionCell.appendChild(deleteBtn);
row.appendChild(actionCell);
tbody.appendChild(row);
});
}
// 获取要显示的属性
function getKeyProperties(entityType) {
switch (entityType) {
case 'user':
return ['username', 'realName', 'email', 'department', 'role'];
case 'salesorder':
return ['orderNumber', 'customerName', 'orderDate', 'totalAmount', 'orderStatus'];
case 'product':
return ['productName', 'productCode', 'productCategory', 'standardPrice', 'inventoryQuantity'];
case 'orderproduct':
return ['salesOrder', 'product', 'quantity', 'unitPrice', 'subtotal'];
case 'missingproduct':
return ['product', 'requiredQuantity', 'availableQuantity', 'reportDate', 'status'];
case 'productcycle':
return ['product', 'cycleStart', 'cycleEnd', 'phase', 'description'];
case 'orderreview':
return ['salesOrder', 'reviewer', 'reviewDate', 'status', 'comments'];
case 'orderchange':
return ['salesOrder', 'changeDate', 'changeType', 'description', 'status'];
case 'forecastplan':
return ['product', 'planDate', 'forecastQuantity', 'actualQuantity', 'accuracy'];
case 'deliveryorder':
return ['deliveryNumber', 'orderNumber', 'customerName', 'deliveryDate', 'deliveryStatus'];
case 'contactform':
return ['formNumber', 'customerName', 'contactType', 'contactStatus', 'priority'];
case 'deliverystatistics':
return ['period', 'totalDeliveries', 'onTimeDeliveries', 'delayedDeliveries', 'onTimeRate'];
default:
return ['name', 'description', 'createdAt', 'updatedAt'];
}
}
// 获取属性显示名称
function getPropertyDisplayName(prop) {
const displayNames = {
'username': '用户名',
'realName': '真实姓名',
'email': '邮箱',
'phone': '电话',
'department': '部门',
'position': '职位',
'role': '角色',
'status': '状态',
'createTime': '创建时间',
'updateTime': '更新时间',
'lastLoginTime': '最后登录时间',
'orderNumber': '订单编号',
'customerName': '客户名称',
'orderDate': '订单日期',
'totalAmount': '总金额',
'orderStatus': '订单状态',
'paymentStatus': '付款状态',
'paymentMethod': '付款方式',
'shippingMethod': '配送方式',
'expectedDeliveryDate': '预计交付日期',
'actualDeliveryDate': '实际交付日期',
'contactAddress': '联系地址',
'remarks': '备注',
'productName': '产品名称',
'productCode': '产品编码',
'productModel': '产品型号',
'productType': '产品类型',
'productCategory': '产品类别',
'productStatus': '产品状态',
'standardPrice': '标准价格',
'costPrice': '成本价格',
'inventoryQuantity': '库存数量',
'minInventory': '最小库存',
'maxInventory': '最大库存',
'productionCycle': '生产周期',
'unit': '单位',
'name': '名称',
'code': '编码',
'category': '类别',
'price': '价格',
'stock': '库存',
'quantity': '数量',
'unitPrice': '单价',
'subtotal': '小计',
'salesOrder': '销售订单',
'product': '产品',
'requiredQuantity': '需求数量',
'availableQuantity': '可用数量',
'reportDate': '报告日期',
'cycleStart': '周期开始',
'cycleEnd': '周期结束',
'phase': '阶段',
'description': '描述',
'reviewer': '评审人',
'reviewDate': '评审日期',
'comments': '评论',
'changeDate': '变更日期',
'changeType': '变更类型',
'planDate': '计划日期',
'forecastQuantity': '预测数量',
'actualQuantity': '实际数量',
'accuracy': '准确率',
'deliveryDate': '交付日期',
'carrier': '承运人',
'trackingNumber': '跟踪号',
'subject': '主题',
'message': '消息',
'submitDate': '提交日期',
'period': '周期',
'totalDeliveries': '总交付数',
'onTimeDeliveries': '按时交付数',
'delayedDeliveries': '延迟交付数',
'onTimeRate': '按时率',
'createdAt': '创建时间',
'updatedAt': '更新时间',
'deliveryNumber': '发货单号',
'deliveryStatus': '发货状态',
'formNumber': '表单编号',
'contactType': '联系类型',
'contactStatus': '处理状态',
'priority': '优先级',
'handlerName': '处理人',
'handlingResult': '处理结果',
'handlingTime': '处理时间',
'contactContent': '联系内容'
};
return displayNames[prop] || prop;
}
// 格式化属性值
function formatPropertyValue(value, prop) {
if (value === null || value === undefined) {
return '<span class="text-muted">未设置</span>';
}
// 日期类型属性
if (prop.includes('Date') || prop.includes('Time') || prop === 'createdAt' || prop === 'updatedAt') {
if (typeof value === 'string') {
// 尝试解析日期字符串
try {
const date = new Date(value);
return date.toLocaleString('zh-CN');
} catch (e) {
return value;
}
}
return value;
}
// 布尔类型属性
if (typeof value === 'boolean') {
return value ? '<span class="badge bg-success">是</span>' : '<span class="badge bg-danger">否</span>';
}
// 对象类型属性(如外键引用)
if (typeof value === 'object' && value !== null) {
if (value.id) {
if (value.name) {
return `${value.name} (ID: ${value.id})`;
} else if (value.orderNumber) {
return `订单 ${value.orderNumber} (ID: ${value.id})`;
} else if (value.username) {
return `${value.username} (ID: ${value.id})`;
} else if (value.productName) {
return `${value.productName} (ID: ${value.id})`;
} else {
return `ID: ${value.id}`;
}
}
return JSON.stringify(value);
}
// 角色属性特殊处理
if (prop === 'role') {
if (value === 'ADMIN') {
return '<span class="badge bg-danger">管理员</span>';
} else if (value === 'USER') {
return '<span class="badge bg-primary">普通用户</span>';
} else {
return value;
}
}
// 订单状态特殊处理
if (prop === 'orderStatus') {
if (value === 'PENDING') {
return '<span class="badge bg-warning">待处理</span>';
} else if (value === 'PROCESSING') {
return '<span class="badge bg-info">处理中</span>';
} else if (value === 'SHIPPED') {
return '<span class="badge bg-primary">已发货</span>';
} else if (value === 'DELIVERED') {
return '<span class="badge bg-success">已交付</span>';
} else if (value === 'CANCELLED') {
return '<span class="badge bg-danger">已取消</span>';
} else if (value === 'COMPLETED') {
return '<span class="badge bg-success">已完成</span>';
} else {
return value;
}
}
// 付款状态特殊处理
if (prop === 'paymentStatus') {
if (value === 'UNPAID') {
return '<span class="badge bg-warning">未付款</span>';
} else if (value === 'PARTIAL') {
return '<span class="badge bg-info">部分付款</span>';
} else if (value === 'PAID') {
return '<span class="badge bg-success">已付款</span>';
} else if (value === 'REFUNDED') {
return '<span class="badge bg-danger">已退款</span>';
} else {
return value;
}
}
// 产品状态特殊处理
if (prop === 'productStatus') {
if (value === 'ACTIVE') {
return '<span class="badge bg-success">在售</span>';
} else if (value === 'INACTIVE') {
return '<span class="badge bg-secondary">停售</span>';
} else if (value === 'DISCONTINUED') {
return '<span class="badge bg-danger">已停产</span>';
} else if (value === 'COMING_SOON') {
return '<span class="badge bg-info">即将上市</span>';
} else {
return value;
}
}
// 发货状态特殊处理
if (prop === 'deliveryStatus') {
if (value === '待发货' || value === 'PENDING') {
return '<span class="badge bg-warning">待发货</span>';
} else if (value === '已发货' || value === 'SHIPPED') {
return '<span class="badge bg-primary">已发货</span>';
} else if (value === '已签收' || value === 'DELIVERED') {
return '<span class="badge bg-success">已签收</span>';
} else if (value === '已取消' || value === 'CANCELLED') {
return '<span class="badge bg-danger">已取消</span>';
} else {
return value;
}
}
// 联系表单状态特殊处理
if (prop === 'contactStatus') {
if (value === '待处理' || value === 'PENDING') {
return '<span class="badge bg-warning">待处理</span>';
} else if (value === '处理中' || value === 'PROCESSING') {
return '<span class="badge bg-info">处理中</span>';
} else if (value === '已完成' || value === 'COMPLETED') {
return '<span class="badge bg-success">已完成</span>';
} else {
return value;
}
}
// 联系表单优先级特殊处理
if (prop === 'priority') {
if (value === '高' || value === 'HIGH') {
return '<span class="badge bg-danger">高</span>';
} else if (value === '中' || value === 'MEDIUM') {
return '<span class="badge bg-warning">中</span>';
} else if (value === '低' || value === 'LOW') {
return '<span class="badge bg-info">低</span>';
} else {
return value;
}
}
// 通用状态属性特殊处理
if (prop === 'status') {
if (value === true || value === 'ACTIVE' || value === 'COMPLETED' || value === 'APPROVED') {
return '<span class="badge bg-success">正常</span>';
} else if (value === false || value === 'INACTIVE' || value === 'PENDING' || value === 'REJECTED') {
return '<span class="badge bg-warning">待处理</span>';
} else if (value === 'CANCELLED' || value === 'FAILED') {
return '<span class="badge bg-danger">取消</span>';
} else {
return value;
}
}
// 金额类型特殊处理
if (prop === 'totalAmount' || prop === 'standardPrice' || prop === 'costPrice' || prop.includes('Price')) {
if (typeof value === 'number') {
return `¥${value.toFixed(2)}`;
}
return value;
}
// 数量类型特殊处理
if (prop === 'inventoryQuantity' || prop === 'minInventory' || prop === 'maxInventory' || prop.includes('Quantity')) {
if (typeof value === 'number') {
return value.toString();
}
return value;
}
return value;
}
// 编辑实体
function editEntity(entityType, id) {
fetch(`/api/admin/${entityType}/${id}`)
.then(response => {
if (!response.ok) {
throw new Error('获取数据失败');
}
return response.json();
})
.then(data => {
showEntityModal(entityType, data);
})
.catch(error => {
console.error(`获取${entityType}数据失败:`, error);
alert(`获取${entityType}数据失败: ${error.message}`);
});
}
// 删除实体
function deleteEntity(entityType, id) {
fetch(`/api/admin/${entityType}/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.message || '删除失败');
});
}
return response.json();
})
.then(data => {
alert(data.message || '删除成功');
loadEntityData(entityType);
})
.catch(error => {
console.error(`删除${entityType}失败:`, error);
alert(`删除失败: ${error.message}`);
});
}
// 显示实体模态框
function showEntityModal(entityType = currentEntityType, data = null) {
// 设置模态框标题
const modalTitle = data ? '编辑' : '添加';
document.getElementById('entityModalLabel').textContent = `${modalTitle} ${document.getElementById('entityTitle').textContent}`;
// 清空表单字段
const formFields = document.getElementById('formFields');
formFields.innerHTML = '';
// 设置实体ID
const entityIdInput = document.getElementById('entityId');
entityIdInput.value = data ? data.id : '';
// 获取要显示的属性
const keyProperties = getKeyProperties(entityType);
// 创建表单字段
for (const prop of keyProperties) {
// 跳过ID字段
if (prop === 'id') continue;
// 跳过只读字段
if (prop === 'createdAt' || prop === 'updatedAt' || prop === 'createTime' || prop === 'updateTime' || prop === 'lastLoginTime') continue;
// 获取字段值
const value = data ? data[prop] : '';
// 创建表单字段
const fieldHtml = createFormField(entityType, prop, value);
formFields.innerHTML += fieldHtml;
}
// 显示模态框
entityModal.show();
}
// 创建表单字段
function createFormField(entityType, prop, value) {
const displayName = getPropertyDisplayName(prop);
const isRequired = getRequiredFields(entityType).includes(prop);
const requiredAttr = isRequired ? 'required' : '';
// 处理不同类型的字段
if (prop === 'password') {
// 密码字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<input type="password" class="form-control" id="${prop}" name="${prop}" ${requiredAttr}>
<small class="form-text text-muted">留空表示不修改密码</small>
</div>
`;
} else if (prop === 'role') {
// 角色字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<select class="form-control" id="${prop}" name="${prop}" ${requiredAttr}>
<option value="USER" ${value === 'USER' ? 'selected' : ''}>普通用户</option>
<option value="ADMIN" ${value === 'ADMIN' ? 'selected' : ''}>管理员</option>
</select>
</div>
`;
} else if (prop === 'status' && typeof value === 'boolean') {
// 布尔状态字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<select class="form-control" id="${prop}" name="${prop}" ${requiredAttr}>
<option value="true" ${value === true ? 'selected' : ''}>启用</option>
<option value="false" ${value === false ? 'selected' : ''}>禁用</option>
</select>
</div>
`;
} else if (prop === 'status' && typeof value === 'string') {
// 字符串状态字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<select class="form-control" id="${prop}" name="${prop}" ${requiredAttr}>
<option value="ACTIVE" ${value === 'ACTIVE' ? 'selected' : ''}>正常</option>
<option value="PENDING" ${value === 'PENDING' ? 'selected' : ''}>待处理</option>
<option value="COMPLETED" ${value === 'COMPLETED' ? 'selected' : ''}>已完成</option>
<option value="CANCELLED" ${value === 'CANCELLED' ? 'selected' : ''}>已取消</option>
</select>
</div>
`;
} else if (prop.includes('Date') || prop.includes('Time')) {
// 日期时间字段
let dateValue = '';
if (value) {
try {
const date = new Date(value);
dateValue = date.toISOString().slice(0, 16);
} catch (e) {
dateValue = value;
}
}
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<input type="datetime-local" class="form-control" id="${prop}" name="${prop}" value="${dateValue}" ${requiredAttr}>
</div>
`;
} else if (typeof value === 'object' && value !== null) {
// 对象类型字段(如外键引用)
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<input type="text" class="form-control" id="${prop}Id" name="${prop}Id" value="${value.id || ''}" ${requiredAttr} placeholder="输入${displayName}ID">
</div>
`;
} else if (prop === 'description' || prop === 'comments' || prop === 'message') {
// 文本区域字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<textarea class="form-control" id="${prop}" name="${prop}" rows="3" ${requiredAttr}>${value || ''}</textarea>
</div>
`;
} else {
// 默认文本字段
return `
<div class="form-group">
<label for="${prop}">${displayName}${isRequired ? ' *' : ''}</label>
<input type="text" class="form-control" id="${prop}" name="${prop}" value="${value || ''}" ${requiredAttr}>
</div>
`;
}
}
// 获取必填字段
function getRequiredFields(entityType) {
switch (entityType) {
case 'user':
return ['username', 'role'];
default:
return [];
}
}
// 保存实体
function saveEntity() {
const entityId = document.getElementById('entityId').value;
const isUpdate = entityId !== '';
// 构建表单数据
const formData = {};
const form = document.getElementById('entityForm');
const formElements = form.elements;
// 如果是更新,添加ID
if (isUpdate) {
formData.id = entityId;
}
// 收集表单字段值
for (let i = 0; i < formElements.length; i++) {
const element = formElements[i];
if (element.name && element.name !== '') {
// 处理特殊字段
if (element.name.endsWith('Id')) {
// 处理外键引用
const propName = element.name.replace('Id', '');
formData[propName] = { id: element.value };
} else if (element.type === 'checkbox') {
formData[element.name] = element.checked;
} else if (element.name === 'status' && (element.value === 'true' || element.value === 'false')) {
formData[element.name] = element.value === 'true';
} else if (element.value === '') {
// 跳过空值,除非是密码字段(允许为空表示不修改)
if (element.name !== 'password') {
continue;
}
formData[element.name] = element.value;
} else {
formData[element.name] = element.value;
}
}
}
// 发送请求
const url = isUpdate ? `/api/admin/${currentEntityType}/${entityId}` : `/api/admin/${currentEntityType}`;
const method = isUpdate ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.message || '保存失败');
});
}
return response.json();
})
.then(data => {
// 关闭模态框
entityModal.hide();
// 显示成功消息
alert(isUpdate ? '更新成功' : '添加成功');
// 重新加载数据
loadEntityData(currentEntityType);
})
.catch(error => {
console.error(`保存${currentEntityType}失败:`, error);
alert(`保存失败: ${error.message}`);
});
}
</script>
500
Internal Server Error
<div class="error-message">
<p th:text="${message}">抱歉,服务器遇到了一个错误,无法完成您的请求。</p>
</div>
<div class="error-details">
<h3>错误详情</h3>
<p><strong>时间:</strong> <span th:text="${timestamp}">2023-01-01 00:00:00</span></p>
<p><strong>路径:</strong> <span th:text="${path}">/error</span></p>
<div th:if="${exception}">
<p><strong>异常:</strong> <span th:text="${exception}">Exception</span></p>
</div>
<div th:if="${trace}">
<p><strong>堆栈跟踪:</strong></p>
<pre th:text="${trace}">Stack trace</pre>
</div>
</div>
<div class="error-actions">
<a href="/" class="btn">返回首页</a>
</div>
</div>
销售订单管理系统
<div th:if="${param.error}" class="alert alert-danger">
用户名或密码错误,请重试
</div>
<div th:if="${param.logout}" class="alert alert-success">
您已成功退出登录
</div>
<div th:if="${errorMessage}" class="alert alert-danger" th:text="${errorMessage}">
错误信息
</div>
<div th:if="${success}" class="alert alert-success" th:text="${success}">
成功信息
</div>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="login-tab" data-bs-toggle="tab" type="button" role="tab" aria-selected="true" onclick="showLoginForm()">登录</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="register-tab" data-bs-toggle="tab" type="button" role="tab" aria-selected="false" onclick="showRegisterForm()">注册</button>
</li>
</ul>
<!-- 登录表单 -->
<form id="loginForm" action="/login" method="post">
<div class="form-floating">
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" required>
<label for="username">用户名</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="password" name="password" placeholder="密码" required>
<label for="password">密码</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">登录</button>
</form>
<!-- 注册表单 -->
<form id="registerForm" action="/register" method="post">
<div class="form-floating">
<input type="text" class="form-control" id="reg-username" name="username" placeholder="用户名" required>
<label for="reg-username">用户名</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="reg-password" name="password" placeholder="密码" required>
<label for="reg-password">密码</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="realName" name="realName" placeholder="真实姓名" required>
<label for="realName">真实姓名</label>
</div>
<div class="form-floating">
<input type="email" class="form-control" id="email" name="email" placeholder="邮箱" required>
<label for="email">邮箱</label>
</div>
<div class="form-floating">
<input type="tel" class="form-control" id="phone" name="phone" placeholder="电话" required>
<label for="phone">电话</label>
</div>
<div class="form-floating">
<select class="form-select" id="department" name="department" required>
<option value="">请选择部门</option>
<option value="客户">客户</option>
<option value="市场部">市场部</option>
<option value="工程部">工程部</option>
<option value="计划部">计划部</option>
</select>
<label for="department">部门</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="position" name="position" placeholder="职位" required>
<label for="position">职位</label>
</div>
<button class="w-100 btn btn-lg btn-success mt-3" type="submit">注册</button>
</form>
<p class="mt-5 mb-3 text-muted">© 2023-2024</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
function showLoginForm() {
document.getElementById('loginForm').style.display = 'block';
document.getElementById('registerForm').style.display = 'none';
document.getElementById('login-tab').classList.add('active');
document.getElementById('register-tab').classList.remove('active');
}
function showRegisterForm() {
document.getElementById('loginForm').style.display = 'none';
document.getElementById('registerForm').style.display = 'block';
document.getElementById('login-tab').classList.remove('active');
document.getElementById('register-tab').classList.add('active');
}
// 检查URL参数,如果有register参数,则显示注册表单
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('register')) {
showRegisterForm();
}
// 在登录表单提交前添加事件监听器
document.getElementById('loginForm').addEventListener('submit', function(event) {
event.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
// 创建表单数据
const formData = new FormData();
formData.append('username', username);
formData.append('password', password);
fetch('/login', {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
// 登录成功,重定向到仪表盘
window.location.href = '/admin/dashboard';
} else {
// 登录失败
return response.text().then(text => {
throw new Error(text || '用户名或密码错误');
});
}
})
.catch(error => {
console.error('登录失败:', error);
alert('登录失败: ' + (error.message || '未知错误'));
});
});
</script>
spring.application.name=test
MySQLæ°æ®åºè¿æ¥é ç½®
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=wcd20050614
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
JPAé ç½®
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
é误å¤çé ç½®
server.error.include-message=always
server.error.include-binding-errors=always
server.error.include-stacktrace=never
server.error.include-exception=true
server.error.whitelabel.enabled=false`