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);
    }
}
UsageRequestRepository
点击查看代码
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> {
    
    
}
UsageRequest实体类
点击查看代码
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 + '\'' +
                '}';
    }
}
UsageRequestService
点击查看代码
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>
posted @ 2025-04-17 22:16  YANGzLIN...11  阅读(7)  评论(0)    收藏  举报