三拍:检测计划

TestingPlanController

package com.example.demo.controller;

import com.example.demo.entity.TestingPlan;
import com.example.demo.service.TestingPlanService;
import com.example.demo.common.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/testing")
public class TestingPlanController {

    @Autowired
    private TestingPlanService testingPlanService;

    @GetMapping("/list")
    public Result getAll() {
        return Result.success(testingPlanService.getAllPlans());
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable("id") Integer planId) {
        return Result.success(testingPlanService.getPlanById(planId));
    }

    @PostMapping("/add")
    public Result add(@RequestBody TestingPlan plan) {
        return testingPlanService.addPlan(plan) 
            ? Result.success() 
            : Result.error("添加失败");
    }

    @PutMapping("/update")
    public Result update(@RequestBody TestingPlan plan) {
        return testingPlanService.updatePlan(plan) 
            ? Result.success() 
            : Result.error("更新失败");
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable("id") Integer planId) {
        return testingPlanService.deletePlan(planId) 
            ? Result.success() 
            : Result.error("删除失败");
    }

    @PutMapping("/status")
    public Result updateStatus(@RequestParam Integer planId, @RequestParam String status) {
        return testingPlanService.updatePlanStatus(planId, status) 
            ? Result.success() 
            : Result.error("状态更新失败");
    }
}

TestingPlan

package com.example.demo.entity;

import lombok.Data;
import java.time.LocalDateTime;

@Data
public class TestingPlan {
    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;
    }
}

TestingOrderServiceImpl

package com.example.demo.service.impl;

import com.example.demo.entity.TestingOrder;
import com.example.demo.mapper.TestingOrderMapper;
import com.example.demo.service.TestingOrderService;
import com.example.demo.utils.TestingOrderIdGenerator;
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;

@Service
public class TestingOrderServiceImpl implements TestingOrderService {

    @Autowired
    private TestingOrderMapper testingOrderMapper;

    @Override
    public List<TestingOrder> getAllOrders() {
        try {
            return testingOrderMapper.selectAll();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public TestingOrder getOrderById(String orderId) {
        try {
            return testingOrderMapper.selectById(orderId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    @Transactional
    public boolean addOrder(TestingOrder order) {
        try {
            order.setOrderId(TestingOrderIdGenerator.generateOrderId());
            if (order.getStatus() == null) {
                order.setStatus("待处理");
            }
            if (order.getPlanTime() == null) {
                order.setPlanTime(LocalDateTime.now());
            }
            return testingOrderMapper.insert(order) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional
    public boolean updateOrder(TestingOrder order) {
        try {
            if (order.getOrderId() == null) {
                return false;
            }
            return testingOrderMapper.update(order) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional
    public boolean deleteOrder(String orderId) {
        try {
            return testingOrderMapper.deleteById(orderId) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional
    public boolean updateOrderStatus(String orderId, String status) {
        try {
            if (!isValidStatus(status)) {
                return false;
            }
            return testingOrderMapper.updateStatus(orderId, status) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    @Transactional
    public boolean generateOrdersForPlans(List<Integer> planIds) {
        try {
            for (Integer planId : planIds) {
                TestingOrder order = new TestingOrder();
                order.setPlanId(planId);
                order.setPlanTime(LocalDateTime.now());
                order.setStatus("待处理");
                order.setEngineerId(null);
                order.setTestingDesc(null);
                order.setPhotos(null);
                
                // 生成工单
                if (!addOrder(order)) {
                    throw new RuntimeException("工单生成失败");
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean isValidStatus(String status) {
        if (status == null) {
            return false;
        }
        String[] validStatuses = {"待处理", "处理中", "待审批", "已完成", "已关闭"};
        for (String validStatus : validStatuses) {
            if (validStatus.equals(status)) {
                return true;
            }
        }
        return false;
    }
}

TestingPlanService

package com.example.demo.service;

import com.example.demo.entity.TestingPlan;
import java.util.List;

public interface TestingPlanService {
    List<TestingPlan> getAllPlans();
    TestingPlan getPlanById(Integer planId);
    boolean addPlan(TestingPlan plan);
    boolean updatePlan(TestingPlan plan);
    boolean deletePlan(Integer planId);
    boolean updatePlanStatus(Integer planId, String status);
}

Test.vue

<template>
  <div class="testing-container">
    <el-card class="testing-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-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/testing'
import { getDeviceList } from '@/api/device'
import { generateOrders } from '@/api/testingOrder'  // 添加这行

const planList = ref([])
const dialogVisible = ref(false)
const dialogTitle = ref('')
const isEdit = ref(false)
const deviceOptions = ref([])
const selectedPlans = ref([])

const planForm = ref({
  deviceId: '',
  location: '',
  frequency: '月',
  startTime: '',
  endTime: '',
  status: '待启用'
})

// 获取设备列表
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)
  }
}

// 获取计划列表
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 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
  }
}

// 提交表单
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 ? '更新失败' : '添加失败')
  }
}

onMounted(() => {
  fetchPlanList()
  fetchDeviceList()
})
</script>

<style scoped>
.testing-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>
posted @ 2025-05-10 22:18  QixunQiu  阅读(18)  评论(0)    收藏  举报