三拍:巡检计划
InspectionPlanController
package com.example.demo.controller;
import com.example.demo.entity.InspectionOrder;
import com.example.demo.service.InspectionOrderService;
import com.example.demo.common.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/inspection-order")
public class InspectionOrderController {
@Autowired
private InspectionOrderService inspectionOrderService;
@GetMapping("/list")
public Result getAll() {
return Result.success(inspectionOrderService.getAllOrders());
}
@GetMapping("/{id}")
public Result getById(@PathVariable("id") String orderId) {
return Result.success(inspectionOrderService.getOrderById(orderId));
}
@PostMapping("/add")
public Result add(@RequestBody InspectionOrder order) {
return inspectionOrderService.addOrder(order)
? Result.success()
: Result.error("添加工单失败");
}
@PutMapping("/update")
public Result update(@RequestBody InspectionOrder order) {
return inspectionOrderService.updateOrder(order)
? Result.success()
: Result.error("更新工单失败");
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable("id") String orderId) {
return inspectionOrderService.deleteOrder(orderId)
? Result.success()
: Result.error("删除工单失败");
}
@PutMapping("/status")
public Result updateStatus(@RequestParam String orderId, @RequestParam String status) {
return inspectionOrderService.updateOrderStatus(orderId, status)
? Result.success()
: Result.error("状态更新失败");
}
@PostMapping("/generate")
public Result generateOrders(@RequestBody Map<String, List<Integer>> request) {
List<Integer> planIds = request.get("planIds");
return inspectionOrderService.generateOrdersForPlans(planIds)
? Result.success()
: Result.error("工单生成失败");
}
}
InspectionPlan
package com.example.demo.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class InspectionPlan {
private Integer planId;
private String deviceId;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String frequency;
private String status;
private String location;
public Integer getPlanId() {
return planId;
}
public void setPlanId(Integer planId) {
this.planId = planId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public String getFrequency() {
return frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
InspectionPlanServiceImpl
package com.example.demo.service.impl;
import com.example.demo.entity.InspectionPlan;
import com.example.demo.mapper.InspectionPlanMapper;
import com.example.demo.service.InspectionPlanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class InspectionPlanServiceImpl implements InspectionPlanService {
@Autowired
private InspectionPlanMapper inspectionPlanMapper;
@Override
public List<InspectionPlan> getAllPlans() {
return inspectionPlanMapper.selectAll();
}
@Override
public InspectionPlan getPlanById(Integer planId) {
return inspectionPlanMapper.selectById(planId);
}
@Override
public boolean addPlan(InspectionPlan plan) {
if (plan.getStatus() == null) {
plan.setStatus("待启用");
}
return inspectionPlanMapper.insert(plan) > 0;
}
@Override
public boolean updatePlan(InspectionPlan plan) {
return inspectionPlanMapper.update(plan) > 0;
}
@Override
public boolean deletePlan(Integer planId) {
return inspectionPlanMapper.delete(planId) > 0;
}
@Override
public boolean updatePlanStatus(Integer planId, String status) {
if (!isValidStatus(status)) {
return false;
}
return inspectionPlanMapper.updateStatus(planId, status) > 0;
}
private boolean isValidStatus(String status) {
return status != null && (status.equals("待启用") ||
status.equals("启用") ||
status.equals("停用"));
}
}
InspectionPlanService
package com.example.demo.service;
import com.example.demo.entity.InspectionPlan;
import java.util.List;
public interface InspectionPlanService {
List<InspectionPlan> getAllPlans();
InspectionPlan getPlanById(Integer planId);
boolean addPlan(InspectionPlan plan);
boolean updatePlan(InspectionPlan plan);
boolean deletePlan(Integer planId);
boolean updatePlanStatus(Integer planId, String status);
}
Inspect.vue
<script>
export default {
name: "Inspect"
}
</script>
<template>
<div class="inspect-container">
<el-card class="inspect-card">
<template #header>
<div class="card-header">
<div class="header-left">
<span>巡检计划管理</span>
</div>
<div class="header-right">
<el-button type="primary" @click="showAddDialog">新增计划</el-button>
</div>
</div>
</template>
<!-- 批量操作按钮 -->
<div class="batch-actions" style="margin-bottom: 15px">
<el-button
type="success"
:disabled="!selectedPlans.length"
@click="handleBatchStatus('启用')"
>批量启用</el-button>
<el-button
type="warning"
:disabled="!selectedPlans.length"
@click="handleBatchStatus('停用')"
>批量停用</el-button>
</div>
<!-- 修改表格,添加多选功能 -->
<el-table
:data="planList"
border
style="width: 100%"
height="450"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<!-- 其他列保持不变 -->
<el-table-column prop="planId" label="计划编号" width="100" />
<el-table-column prop="deviceId" label="设备编号" width="120" />
<el-table-column prop="location" label="巡检位置" min-width="150" />
<el-table-column prop="frequency" label="巡检频率" width="100" />
<el-table-column prop="startTime" label="开始时间" width="160">
<template #default="scope">
{{ formatDateTime(scope.row.startTime) }}
</template>
</el-table-column>
<el-table-column prop="endTime" label="结束时间" width="160">
<template #default="scope">
{{ formatDateTime(scope.row.endTime) }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<el-tag :type="getStatusType(scope.row.status)">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="scope">
<el-button
size="small"
@click="handleEdit(scope.row)"
:disabled="scope.row.status === '启用'"
>编辑</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(scope.row)"
:disabled="scope.row.status === '启用'"
>删除</el-button>
</template>
</el-table-column>
<!-- 在表单中修改状态选择器 -->
<el-form-item label="状态">
<el-select
v-model="planForm.status"
style="width: 100%"
:disabled="true"
>
<el-option label="待启用" value="待启用" />
<el-option label="启用" value="启用" />
<el-option label="停用" value="停用" />
</el-select>
</el-form-item>
</el-table>
</el-card>
<!-- 添加/编辑对话框 -->
<el-dialog
:title="dialogTitle"
v-model="dialogVisible"
width="500px"
>
<el-form :model="planForm" label-width="100px">
<el-form-item label="设备编号">
<el-select
v-model="planForm.deviceId"
style="width: 100%"
filterable
placeholder="请选择设备"
@change="handleDeviceChange"
>
<el-option
v-for="item in deviceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="巡检位置">
<el-input v-model="planForm.location" />
</el-form-item>
<el-form-item label="巡检频率">
<el-select v-model="planForm.frequency" style="width: 100%">
<el-option label="日" value="日" />
<el-option label="周" value="周" />
<el-option label="月" value="月" />
<el-option label="季度" value="季度" />
<el-option label="半年" value="半年" />
<el-option label="年" value="年" />
</el-select>
</el-form-item>
<el-form-item label="开始时间">
<el-date-picker
v-model="planForm.startTime"
type="datetime"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="结束时间">
<el-date-picker
v-model="planForm.endTime"
type="datetime"
style="width: 100%"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getAllPlans, addPlan, updatePlan, deletePlan, updatePlanStatus } from '@/api/inspection'
import { getDeviceList } from '@/api/device'
import { generateOrders } from '@/api/inspectionOrder' // 添加这行
const planList = ref([])
const dialogVisible = ref(false)
const dialogTitle = ref('')
const isEdit = ref(false)
const planForm = ref({
deviceId: '',
location: '',
frequency: '日',
startTime: '',
endTime: '',
status: '待启用'
})
const deviceOptions = ref([])
// 添加获取设备列表的方法
const fetchDeviceList = async () => {
try {
const res = await getDeviceList()
if (res.code === 200) {
deviceOptions.value = res.data.map(device => ({
value: device.deviceId,
label: `${device.deviceId} - ${device.deviceType}`,
location: device.location
}))
}
} catch (error) {
console.error('获取设备列表失败:', error)
}
}
// 在 onMounted 中添加
onMounted(() => {
fetchPlanList()
fetchDeviceList() // 添加这行
})
const fetchPlanList = async () => {
try {
const res = await getAllPlans()
if (res.code === 200) {
planList.value = res.data
} else {
ElMessage.error(res.msg || '获取计划列表失败')
}
} catch (error) {
console.error('获取计划列表失败:', error)
ElMessage.error('获取计划列表失败')
}
}
// 格式化日期时间
const formatDateTime = (datetime) => {
if (!datetime) return ''
return new Date(datetime).toLocaleString('zh-CN')
}
// 获取状态标签类型
const getStatusType = (status) => {
const statusMap = {
'待启用': 'info',
'启用': 'success',
'停用': 'danger'
}
return statusMap[status] || ''
}
// 显示添加对话框
const showAddDialog = () => {
isEdit.value = false
dialogTitle.value = '新增巡检计划'
planForm.value = {
deviceId: '',
location: '',
frequency: '日',
startTime: '',
endTime: '',
status: '待启用'
}
dialogVisible.value = true
}
// 显示编辑对话框
const handleEdit = (row) => {
isEdit.value = true
dialogTitle.value = '编辑巡检计划'
planForm.value = { ...row }
dialogVisible.value = true
}
// 处理删除
const handleDelete = (row) => {
ElMessageBox.confirm('确认删除该巡检计划吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
try {
const res = await deletePlan(row.planId)
if (res.code === 200) {
ElMessage.success('删除成功')
fetchPlanList()
} else {
ElMessage.error(res.msg || '删除失败')
}
} catch (error) {
console.error('删除失败:', error)
ElMessage.error('删除失败')
}
})
}
// 提交表单
const handleSubmit = async () => {
try {
const api = isEdit.value ? updatePlan : addPlan
const res = await api(planForm.value)
if (res.code === 200) {
ElMessage.success(isEdit.value ? '更新成功' : '添加成功')
dialogVisible.value = false
fetchPlanList()
} else {
ElMessage.error(res.msg || (isEdit.value ? '更新失败' : '添加失败'))
}
} catch (error) {
console.error('操作失败:', error)
ElMessage.error(isEdit.value ? '更新失败' : '添加失败')
}
}
// 添加选中计划的数组
const selectedPlans = ref([])
// 处理表格选择变化
const handleSelectionChange = (selection) => {
selectedPlans.value = selection
}
// 修改批量状态更新方法
const handleBatchStatus = async (status) => {
try {
const promises = selectedPlans.value.map(plan =>
updatePlanStatus(plan.planId, status)
)
const results = await Promise.all(promises)
const allSuccess = results.every(res => res.code === 200)
if (allSuccess) {
if (status === '启用') {
// 获取所有选中计划的ID
const planIds = selectedPlans.value.map(plan => plan.planId)
// 调用生成工单的接口
const generateResult = await generateOrders(planIds)
if (generateResult.code === 200) {
ElMessage.success('批量启用成功,已生成相应工单')
} else {
ElMessage.warning('计划已启用,但工单生成失败')
}
} else {
ElMessage.success(`批量${status}成功`)
}
fetchPlanList()
} else {
ElMessage.error(`部分计划${status}失败`)
}
} catch (error) {
console.error('批量操作失败:', error)
ElMessage.error('批量操作失败')
}
}
// 处理设备选择变化
const handleDeviceChange = (deviceId) => {
const selectedDevice = deviceOptions.value.find(device => device.value === deviceId)
if (selectedDevice) {
planForm.value.location = selectedDevice.location
}
}
</script>
<style scoped>
.inspect-container {
padding: 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-left {
font-size: 16px;
font-weight: bold;
}
.header-right {
display: flex;
gap: 10px;
}
.batch-actions {
display: flex;
gap: 10px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>