4.17java大作业
领用申请和领用审核模块
UsageRequestController
点击查看代码
package com.example.controller;
import com.example.config.ResourceNotFoundException;
import com.example.entity.UsageRequest;
import com.example.service.UsageRequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/usage-requests")
public class UsageRequestController {
@Autowired
private UsageRequestService usageRequestService;
@PostMapping
public ResponseEntity<UsageRequest> create(@RequestBody UsageRequest request) {
return ResponseEntity.ok(usageRequestService.createUsageRequest(request));
}
@GetMapping
public ResponseEntity<List<UsageRequest>> getAll() {
return ResponseEntity.ok(usageRequestService.getAllUsageRequests());
}
@GetMapping("/{id}")
public ResponseEntity<UsageRequest> getById(@PathVariable Integer id) {
return ResponseEntity.ok(usageRequestService.getUsageRequestById(id));
}
@PutMapping("/{id}/approve")
public ResponseEntity<Void> approve(@PathVariable Integer id) {
usageRequestService.approveUsageRequest(id);
return ResponseEntity.ok().build();
}
@PutMapping("/{id}/reject")
public ResponseEntity<Void> reject(@PathVariable Integer id) {
usageRequestService.rejectUsageRequest(id);
return ResponseEntity.ok().build();
}
// 异常处理
@ExceptionHandler({ResourceNotFoundException.class})
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
@ExceptionHandler({IllegalStateException.class})
public ResponseEntity<String> handleIllegalState(IllegalStateException ex) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
}
}
点击查看代码
package com.example.config;
// 自定义异常类
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
点击查看代码
package com.example.dao;
import com.example.entity.UsageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UsageRequestRepository extends JpaRepository<UsageRequest, Integer> {
}
点击查看代码
package com.example.entity;
import jakarta.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "usagerequest", schema = "your_schema_name") // 替换为你的数据库schema名
public class UsageRequest implements Serializable {
public enum UsageType {
维修申领, 维修借用
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, columnDefinition = "INT COMMENT '领用单号'")
private Integer id;
@Column(name = "applicant_id", columnDefinition = "INT COMMENT '申请人'")
private Integer applicantId;
@Column(name = "sparepart_sn", columnDefinition = "VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '备件SN'")
private String sparepartSn;
@Enumerated(EnumType.STRING)
@Column(name = "type", columnDefinition = "ENUM('维修申领','维修借用') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '类型'")
private UsageType type;
@Column(name = "status", columnDefinition = "VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '状态'")
private String status;
@Column(name = "create_time", columnDefinition = "VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '创建时间'")
private String createTime;
// 无参构造函数(JPA 要求)
public UsageRequest() {
}
// Getter & Setter
// 这里可以使用 Lombok 的 @Data 注解简化
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getApplicantId() {
return applicantId;
}
public void setApplicantId(Integer applicantId) {
this.applicantId = applicantId;
}
public String getSparepartSn() {
return sparepartSn;
}
public void setSparepartSn(String sparepartSn) {
this.sparepartSn = sparepartSn;
}
public UsageType getType() {
return type;
}
public void setType(UsageType type) {
this.type = type;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
// toString() 方法
@Override
public String toString() {
return "UsageRequest{" +
"id=" + id +
", applicantId=" + applicantId +
", sparepartSn='" + sparepartSn + '\'' +
", type=" + type +
", status='" + status + '\'' +
", createTime='" + createTime + '\'' +
'}';
}
}
点击查看代码
package com.example.service;
import com.example.config.ResourceNotFoundException;
import com.example.dao.UsageRequestRepository;
import com.example.entity.UsageRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
@Service
public class UsageRequestService {
@Autowired
private UsageRequestRepository usageRequestRepository;
public UsageRequest createUsageRequest(UsageRequest usageRequest) {
// 设置初始状态为"待审核"
usageRequest.setStatus("待审核");
// 设置创建时间(使用中国时区)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
usageRequest.setCreateTime(sdf.format(new Date()));
return usageRequestRepository.save(usageRequest);
}
public List<UsageRequest> getAllUsageRequests() {
return usageRequestRepository.findAll();
}
public UsageRequest getUsageRequestById(Integer id) {
return usageRequestRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("申请单不存在"));
}
public void approveUsageRequest(Integer id) {
UsageRequest request = getUsageRequestById(id);
// 状态校验
if (!"待审核".equals(request.getStatus())) {
throw new IllegalStateException("当前状态不允许审批");
}
// 根据类型设置不同状态
if (request.getType() == UsageRequest.UsageType.维修借用) {
request.setStatus("待出库");
} else {
request.setStatus("已批准");
}
usageRequestRepository.save(request);
}
public void rejectUsageRequest(Integer id) {
UsageRequest request = getUsageRequestById(id);
if (!"待审核".equals(request.getStatus())) {
throw new IllegalStateException("当前状态不允许审批");
}
request.setStatus("已拒绝");
usageRequestRepository.save(request);
}
/*// UsageRequestService.java 添加新方法
public List<UsageRequest> getByApplicantId(Integer applicantId) {
return usageRequestRepository.findByApplicantId(applicantId);
}*/
}
领用申请前端
点击查看代码
<template>
<div>
<!-- 申请操作区和记录列表 -->
<el-button @click="openApplyDialog" type="primary" :icon="Plus">新建领用</el-button>
<!-- 领用记录表格 -->
<el-table :data="usageRequests" stripe style="width: 100%" class="mt-4">
<el-table-column prop="id" label="领用单号" width="120" />
<el-table-column prop="sparepartSn" label="备件SN" />
<el-table-column prop="type" label="类型">
<template #default="{row}">
<el-tag :type="row.type === '维修借用' ? 'warning' : ''">
{{ row.type }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="applicantId" label="申请人ID" />
<el-table-column prop="status" label="状态">
<template #default="{row}">
<el-tag :type="getStatusTagType(row.status)">
{{ row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="申请时间">
<template #default="{row}">
{{ formatDate(row.createTime) }}
</template>
</el-table-column>
</el-table>
<!-- 新增申请对话框 -->
<el-dialog v-model="applyDialogVisible" title="备件领用申请" @close="clearApplyForm">
<el-form :model="applyForm" label-width="100px">
<el-form-item label="备件SN" required>
<el-input v-model="applyForm.sparepartSn" placeholder="输入备件序列号"/>
</el-form-item>
<el-form-item label="领用类型" required>
<el-select v-model="applyForm.type" placeholder="请选择">
<el-option
v-for="t in usageTypes"
:key="t.value"
:label="t.label"
:value="t.value"
/>
</el-select>
</el-form-item>
<el-form-item label="申请说明">
<el-input
v-model="applyForm.description"
type="textarea"
placeholder="填写申请理由(可选)"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="applyDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitApply">提交</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import axios from 'axios';
import router from '@/router.js';
const applyDialogVisible = ref(false);
const usageRequests = ref([]);
const currentUser = ref(null);
const usageTypes = [
{ value: '维修申领', label: '维修申领(永久领用)' },
{ value: '维修借用', label: '维修借用(48小时内归还)' }
];
const applyForm = ref({
sparepartSn: '',
type: '',
description: ''
});
// 初始化加载
onMounted(async () => {
const user = JSON.parse(sessionStorage.getItem('user'));
if (!user) {
ElMessage.error('请先登录');
await router.push('/');
return;
}
currentUser.value = user;
await fetchUsageRequests();
});
// 获取领用记录(前端过滤)
const fetchUsageRequests = async () => {
try {
const res = await axios.get('/api/usage-requests', {
withCredentials: true
});
// 前端过滤当前用户记录
usageRequests.value = res.data.filter(item =>
item.applicantId === currentUser.value?.user_id
);
} catch (error) {
ElMessage.error('获取记录失败: ' + error.message);
}
};
// 提交申请
const submitApply = async () => {
try {
await axios.post('/api/usage-requests', {
...applyForm.value,
applicantId: currentUser.value.user_id
}, {
withCredentials: true
});
ElMessage.success('申请提交成功');
applyDialogVisible.value = false;
await fetchUsageRequests(); // 刷新列表
} catch (error) {
ElMessage.error(`提交失败: ${error.response?.data?.message || error.message}`);
}
};
// 审批操作
const handleApprove = async (id) => {
try {
await ElMessageBox.confirm('确定批准该申请?', '确认操作');
await axios.put(`/api/usage-requests/${id}/approve`, {}, {
withCredentials: true
});
await fetchUsageRequests();
ElMessage.success('操作成功');
} catch (error) {
if (error !== 'cancel') ElMessage.error(error.message);
}
};
const handleReject = async (id) => {
try {
await ElMessageBox.confirm('确定驳回该申请?', '确认操作');
await axios.put(`/api/usage-requests/${id}/reject`, {}, {
withCredentials: true
});
await fetchUsageRequests();
ElMessage.success('操作成功');
} catch (error) {
if (error !== 'cancel') ElMessage.error(error.message);
}
};
// 辅助方法
const formatDate = (timeString) => {
return new Date(timeString).toLocaleString('zh-CN');
};
const getStatusTagType = (status) => {
const typeMap = {
'待审核': 'warning',
'已批准': 'success',
'已拒绝': 'danger',
'待出库': 'info'
};
return typeMap[status] || '';
};
const openApplyDialog = () => {
applyForm.value = { sparepartSn: '', type: '', description: '' };
applyDialogVisible.value = true;
};
const clearApplyForm = () => {
applyDialogVisible.value = false;
};
</script>
<style scoped>
.mt-4 {
margin-top: 1rem;
}
</style>
点击查看代码
<template>
<el-table :data="usageRequests" stripe style="width:100%">
<el-table-column prop="id" label="单号" width="120" />
<el-table-column prop="sparepartSn" label="备件SN" />
<el-table-column prop="type" label="类型">
<template #default="{row}">
<el-tag :type="row.type === '维修借用' ? 'warning' : ''">
{{ row.type }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="applicantId" label="申请人ID" />
<el-table-column prop="status" label="状态">
<template #default="{row}">
<el-tag :type="statusTagType(row.status)">
{{ row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="申请时间" :formatter="formatTime" />
<el-table-column label="操作" width="180">
<template #default="{row}">
<el-button-group v-if="row.status === '待审核'">
<el-button
type="success"
size="small"
@click="handleApprove(row.id)"
>通过</el-button>
<el-button
type="danger"
size="small"
@click="handleReject(row.id)"
>驳回</el-button>
</el-button-group>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import axios from 'axios';
const usageRequests = ref([]);
onMounted(async () => {
try {
const { data } = await axios.get('/api/usage-requests');
usageRequests.value = data;
} catch (error) {
ElMessage.error('加载失败: ' + error.message);
}
});
const statusTagType = (status) => {
const map = {
'待审核': 'warning',
'已批准': 'success',
'已拒绝': 'danger',
'待出库': 'info'
};
return map[status] || '';
};
const formatTime = (row) => {
return new Date(row.createTime).toLocaleString();
};
const handleApprove = async (id) => {
try {
await ElMessageBox.confirm('确定批准该申请?', '确认操作');
await axios.put(`/api/usage-requests/${id}/approve`);
refreshData();
ElMessage.success('操作成功');
} catch (error) {
if (error !== 'cancel') {
ElMessage.error(error.message);
}
}
};
const handleReject = async (id) => {
try {
await ElMessageBox.confirm('确定驳回该申请?', '确认操作');
await axios.put(`/api/usage-requests/${id}/reject`);
refreshData();
ElMessage.success('操作成功');
} catch (error) {
if (error !== 'cancel') {
ElMessage.error(error.message);
}
}
};
const refreshData = async () => {
const { data } = await axios.get('/api/usage-requests');
usageRequests.value = data;
};
</script>
浙公网安备 33010602011771号