huang
2025-04-15 ef714be504f98f6b9549b134148a18d416a9dcb0
添加看板大屏2
2个文件已修改
17个文件已添加
2705 ■■■■■ 已修改文件
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/controller/QuantityController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/entity/Quantity.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/mapper/QuantityMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/service/QuantityService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/service/impl/QuantityServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/controller/UtilizationController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/entity/Utilization.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/mapper/UtilizationMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/service/UtilizationService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/service/impl/UtilizationServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/controller/YieldController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/entity/Yield.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/mapper/YieldMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/YieldService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/impl/YieldServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/router/index.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/KanbanData/kanbanData.vue 817 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/KanbanDisplay2/kanbanDisplay2.vue 1317 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/controller/QuantityController.java
New file
@@ -0,0 +1,96 @@
package com.mes.quantity.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mes.utils.Result;
import com.mes.quantity.entity.Quantity;
import com.mes.quantity.service.QuantityService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Api(tags = "在制品数量接口")
@RestController
@RequestMapping("/quantity")
public class QuantityController {
    @Autowired
    private QuantityService quantityService;
    @ApiOperation("获取在制品数量数据列表")
    @PostMapping("/listQuantity")
    @ResponseBody
    public Result listQuantity(@RequestBody Map<String, Object> params) {
        Integer page = params.get("page") == null ? 1 : (Integer) params.get("page");
        Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
        String locationCode = (String) params.get("locationCode");
        QueryWrapper<Quantity> queryWrapper = new QueryWrapper<Quantity>().orderByDesc("record_time");
        if (StringUtils.hasText(locationCode)) {
            queryWrapper.eq("location_code", locationCode);
        }
        Page<Quantity> pageData = quantityService.page(
            new Page<>(page, pageSize),
            queryWrapper
        );
        return Result.build(200, "查询成功", pageData);
    }
    @ApiOperation("添加在制品数量记录")
    @PostMapping("/addQuantity")
    @ResponseBody
    public Result addQuantity(@RequestBody Quantity quantity) {
        quantity.setCreateTime(new Date());
        quantity.setUpdateTime(new Date());
        boolean success = quantityService.save(quantity);
        int count = success ? 1 : 0;
        String message = count > 0 ? "添加成功:" + count : "添加失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("修改在制品数量记录")
    @PostMapping("/updateQuantity")
    @ResponseBody
    public Result updateQuantity(@RequestBody Quantity quantity) {
        quantity.setUpdateTime(new Date());
        boolean success = quantityService.updateById(quantity);
        int count = success ? 1 : 0;
        String message = count > 0 ? "修改成功:" + count : "修改失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("删除在制品数量记录")
    @PostMapping("/deleteQuantity")
    @ResponseBody
    public Result deleteQuantity(@RequestBody Quantity quantity) {
        boolean success = quantityService.removeById(quantity.getId());
        int count = success ? 1 : 0;
        String message = count > 0 ? "删除成功:" + count : "删除失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("获取图表数据")
    @PostMapping("/chartQuantity")
    @ResponseBody
    public Result getChartData(@RequestBody(required = false) Map<String, Object> params) {
        String locationCode = params != null ? (String) params.get("locationCode") : null;
        QueryWrapper<Quantity> queryWrapper = new QueryWrapper<Quantity>().orderByAsc("record_time");
        if (StringUtils.hasText(locationCode)) {
            queryWrapper.eq("location_code", locationCode);
        }
        queryWrapper.last("limit 30");
        List<Quantity> data = quantityService.list(queryWrapper);
        return Result.build(200, "查询成功", data);
    }
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/entity/Quantity.java
New file
@@ -0,0 +1,39 @@
package com.mes.quantity.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@TableName("quantity")
@ApiModel(value = "Quantity", description = "在制量")
public class Quantity {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("ID")
    private Long id;
    @ApiModelProperty("类型编号")
    private String locationCode;
    @ApiModelProperty("数量")
    private Integer quantity;
    @ApiModelProperty("记录时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date recordTime;
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    @ApiModelProperty("更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/mapper/QuantityMapper.java
New file
@@ -0,0 +1,9 @@
package com.mes.quantity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes.quantity.entity.Quantity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface QuantityMapper extends BaseMapper<Quantity> {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/service/QuantityService.java
New file
@@ -0,0 +1,12 @@
package com.mes.quantity.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mes.quantity.entity.Quantity;
import java.util.List;
import java.util.Map;
public interface QuantityService extends IService<Quantity> {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/quantity/service/impl/QuantityServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.mes.quantity.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.quantity.entity.Quantity;
import com.mes.quantity.mapper.QuantityMapper;
import com.mes.quantity.service.QuantityService;
import org.springframework.stereotype.Service;
@Service
public class QuantityServiceImpl extends ServiceImpl<QuantityMapper, Quantity> implements QuantityService {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/controller/UtilizationController.java
New file
@@ -0,0 +1,96 @@
package com.mes.utilization.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mes.utils.Result;
import com.mes.utilization.entity.Utilization;
import com.mes.utilization.service.UtilizationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Api(tags = "生产线利用率接口")
@RestController
@RequestMapping("/utilization")
public class UtilizationController {
    @Autowired
    private UtilizationService utilizationService;
    @ApiOperation("获取生产线利用率数据列表")
    @PostMapping("/listUtilization")
    @ResponseBody
    public Result listUtilization(@RequestBody Map<String, Object> params) {
        Integer page = params.get("page") == null ? 1 : (Integer) params.get("page");
        Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
        String lineNo = (String) params.get("lineNo");
        QueryWrapper<Utilization> queryWrapper = new QueryWrapper<Utilization>().orderByDesc("record_time");
        if (StringUtils.hasText(lineNo)) {
            queryWrapper.eq("line_no", lineNo);
        }
        Page<Utilization> pageData = utilizationService.page(
            new Page<>(page, pageSize),
            queryWrapper
        );
        return Result.build(200, "查询成功", pageData);
    }
    @ApiOperation("添加生产线利用率记录")
    @PostMapping("/addUtilization")
    @ResponseBody
    public Result addUtilization(@RequestBody Utilization utilization) {
        utilization.setCreateTime(new Date());
        utilization.setUpdateTime(new Date());
        boolean success = utilizationService.save(utilization);
        int count = success ? 1 : 0;
        String message = count > 0 ? "添加成功:" + count : "添加失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("修改生产线利用率记录")
    @PostMapping("/updateUtilization")
    @ResponseBody
    public Result updateUtilization(@RequestBody Utilization utilization) {
        utilization.setUpdateTime(new Date());
        boolean success = utilizationService.updateById(utilization);
        int count = success ? 1 : 0;
        String message = count > 0 ? "修改成功:" + count : "修改失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("删除生产线利用率记录")
    @PostMapping("/deleteUtilization")
    @ResponseBody
    public Result deleteUtilization(@RequestBody Utilization utilization) {
        boolean success = utilizationService.removeById(utilization.getId());
        int count = success ? 1 : 0;
        String message = count > 0 ? "删除成功:" + count : "删除失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("获取图表数据")
    @PostMapping("/chartUtilization")
    @ResponseBody
    public Result getChartData(@RequestBody(required = false) Map<String, Object> params) {
        String lineNo = params != null ? (String) params.get("lineNo") : null;
        QueryWrapper<Utilization> queryWrapper = new QueryWrapper<Utilization>().orderByAsc("record_time");
        if (StringUtils.hasText(lineNo)) {
            queryWrapper.eq("line_no", lineNo);
        }
        queryWrapper.last("limit 30");
        List<Utilization> data = utilizationService.list(queryWrapper);
        return Result.build(200, "查询成功", data);
    }
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/entity/Utilization.java
New file
@@ -0,0 +1,39 @@
package com.mes.utilization.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@TableName("utilization")
@ApiModel(value = "Utilization", description = "利用率")
public class Utilization {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("ID")
    private Long id;
    @ApiModelProperty("生产线编号")
    private String lineNo;
    @ApiModelProperty("利用率")
    private Double utilizationRate;
    @ApiModelProperty("记录时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date recordTime;
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    @ApiModelProperty("更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/mapper/UtilizationMapper.java
New file
@@ -0,0 +1,9 @@
package com.mes.utilization.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes.utilization.entity.Utilization;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UtilizationMapper extends BaseMapper<Utilization> {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/service/UtilizationService.java
New file
@@ -0,0 +1,11 @@
package com.mes.utilization.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mes.utilization.entity.Utilization;
import java.util.List;
import java.util.Map;
public interface UtilizationService extends IService<Utilization> {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/utilization/service/impl/UtilizationServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.mes.utilization.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.utilization.entity.Utilization;
import com.mes.utilization.mapper.UtilizationMapper;
import com.mes.utilization.service.UtilizationService;
import org.springframework.stereotype.Service;
@Service
public class UtilizationServiceImpl extends ServiceImpl<UtilizationMapper, Utilization> implements UtilizationService {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/controller/YieldController.java
New file
@@ -0,0 +1,96 @@
package com.mes.yield.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mes.utils.Result;
import com.mes.yield.entity.Yield;
import com.mes.yield.service.YieldService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Api(tags = "单小时产量接口")
@RestController
@RequestMapping("/yield")
public class YieldController {
    @Autowired
    private YieldService yieldService;
    @ApiOperation("获取单小时产量数据列表")
    @PostMapping("/listYield")
    @ResponseBody
    public Result listYield(@RequestBody Map<String, Object> params) {
        Integer page = params.get("page") == null ? 1 : (Integer) params.get("page");
        Integer pageSize = params.get("pageSize") == null ? 10 : (Integer) params.get("pageSize");
        String lineNo = (String) params.get("lineNo");
        QueryWrapper<Yield> queryWrapper = new QueryWrapper<Yield>().orderByDesc("record_time");
        if (StringUtils.hasText(lineNo)) {
            queryWrapper.eq("line_no", lineNo);
        }
        Page<Yield> pageData = yieldService.page(
            new Page<>(page, pageSize),
            queryWrapper
        );
        return Result.build(200, "查询成功", pageData);
    }
    @ApiOperation("添加单小时产量记录")
    @PostMapping("/addYield")
    @ResponseBody
    public Result addYield(@RequestBody Yield yieldValue) {
        yieldValue.setCreateTime(new Date());
        yieldValue.setUpdateTime(new Date());
        boolean success = yieldService.save(yieldValue);
        int count = success ? 1 : 0;
        String message = count > 0 ? "添加成功:" + count : "添加失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("修改单小时产量记录")
    @PostMapping("/updateYield")
    @ResponseBody
    public Result updateYield(@RequestBody Yield yieldValue) {
        yieldValue.setUpdateTime(new Date());
        boolean success = yieldService.updateById(yieldValue);
        int count = success ? 1 : 0;
        String message = count > 0 ? "修改成功:" + count : "修改失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("删除单小时产量记录")
    @PostMapping("/deleteYield")
    @ResponseBody
    public Result deleteYield(@RequestBody Yield yield) {
        boolean success = yieldService.removeById(yield.getId());
        int count = success ? 1 : 0;
        String message = count > 0 ? "删除成功:" + count : "删除失败!";
        return Result.build(200, message, count);
    }
    @ApiOperation("获取图表数据")
    @PostMapping("/chartYield")
    @ResponseBody
    public Result getChartData(@RequestBody(required = false) Map<String, Object> params) {
        String lineNo = params != null ? (String) params.get("lineNo") : null;
        QueryWrapper<Yield> queryWrapper = new QueryWrapper<Yield>().orderByAsc("record_time");
        if (StringUtils.hasText(lineNo)) {
            queryWrapper.eq("line_no", lineNo);
        }
        queryWrapper.last("limit 30");
        List<Yield> data = yieldService.list(queryWrapper);
        return Result.build(200, "查询成功", data);
    }
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/entity/Yield.java
New file
@@ -0,0 +1,39 @@
package com.mes.yield.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@TableName("yield")
@ApiModel(value = "Yield", description = "单小时产量")
public class Yield {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("ID")
    private Long id;
    @ApiModelProperty("生产线编号")
    private String lineNo;
    @ApiModelProperty("产量")
    private Double yieldvalue;
    @ApiModelProperty("记录时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date recordTime;
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    @ApiModelProperty("更新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/mapper/YieldMapper.java
New file
@@ -0,0 +1,9 @@
package com.mes.yield.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes.yield.entity.Yield;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface YieldMapper extends BaseMapper<Yield> {
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/YieldService.java
New file
@@ -0,0 +1,16 @@
package com.mes.yield.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mes.yield.entity.Yield;
import java.util.List;
import java.util.Map;
public interface YieldService extends IService<Yield> {
    /**
     * 通知产量数据更新
     * @param yieldvalue 产量数据
     */
    void notifyYieldUpdate(Yield yieldvalue);
}
JiuMuMesParent/moduleService/DeviceInteractionModule/src/main/java/com/mes/yield/service/impl/YieldServiceImpl.java
New file
@@ -0,0 +1,33 @@
package com.mes.yield.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.yield.entity.Yield;
import com.mes.yield.mapper.YieldMapper;
import com.mes.yield.service.YieldService;
import com.mes.tools.WebSocketServer;
import cn.hutool.json.JSONObject;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class YieldServiceImpl extends ServiceImpl<YieldMapper, Yield> implements YieldService {
    @Override
    public void notifyYieldUpdate(Yield yield) {
        JSONObject message = new JSONObject();
        message.set("type", "yield_update");
        message.set("data", yield);
        ArrayList<WebSocketServer> servers = WebSocketServer.sessionMap.get("yield");
        if (servers != null) {
            for (WebSocketServer server : servers) {
                server.sendMessage(message.toString());
            }
        }
    }
}
UI-Project/src/router/index.js
@@ -76,6 +76,32 @@
          ]
        },
        {
          /*----------- 大屏2数据----------------*/
          path: 'KanbanData/kanbanData',
          name: 'kanbanData',
          component: () => import('../views/KanbanData/kanbanData.vue'),
          children: [
            {
              path: '/KanbanData/kanbanData',
              name: 'kanbanData',
              component: () => import('../views/KanbanData/kanbanData.vue'),
            }
          ]
        },
        {
          /*----------- 大屏2 ----------------*/
          path: 'KanbanDisplay2/kanbanDisplay2',
          name: 'kanbanDisplay2',
          component: () => import('../views/KanbanDisplay2/kanbanDisplay2.vue'),
          children: [
            {
              path: '/KanbanDisplay2/kanbanDisplay2',
              name: 'kanbanDisplay2',
              component: () => import('../views/KanbanDisplay2/kanbanDisplay2.vue'),
            }
          ]
        },
        {
          /*----------- 能耗管理 ----------------*/
          path: 'Energy/energyConsumption',
          name: 'energyConsumption',
UI-Project/src/views/KanbanData/kanbanData.vue
New file
@@ -0,0 +1,817 @@
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
// 加载初始数据
onMounted(() => {
  loadYieldData()
  loadUtilizationData()
  loadQuantityData()
})
// 关闭页面停止定时器
onBeforeUnmount(() => {
  // 清理工作
})
// 处理实时数据更新
const handleYieldUpdate = (data) => {
  const index = yieldData.value.findIndex(item => item.id === data.id)
  if (index > -1) {
    yieldData.value[index] = { ...data, editing: false, originalData: { ...data } }
  } else {
    yieldData.value.unshift({ ...data, editing: false, originalData: { ...data } })
  }
}
const handleUtilizationUpdate = (data) => {
  const index = utilizationData.value.findIndex(item => item.id === data.id)
  if (index > -1) {
    utilizationData.value[index] = { ...data, editing: false, originalData: { ...data } }
  } else {
    utilizationData.value.unshift({ ...data, editing: false, originalData: { ...data } })
  }
}
const handleQuantityUpdate = (data) => {
  const index = quantityData.value.findIndex(item => item.id === data.id)
  if (index > -1) {
    quantityData.value[index] = { ...data, editing: false, originalData: { ...data } }
  } else {
    quantityData.value.unshift({ ...data, editing: false, originalData: { ...data } })
  }
}
// 当前激活的标签页
const activeTab = ref('yield')
// 单小时产量数据
const yieldFormData = ref({
  recordDate: new Date().toISOString().slice(0, 10),
  lineNo: '',
  yieldvalue: null
})
const yieldData = ref([])
const yieldLoading = ref(false)
// 利用率数据
const utilizationFormData = ref({
  recordDate: new Date().toISOString().slice(0, 10),
  lineNo: '',
  utilizationRate: null
})
const utilizationData = ref([])
const utilizationLoading = ref(false)
// 在制量
const locationOptions = [
  { label: '半成品', value: '半成品' },
  { label: '7014库位', value: '7014库位' },
  { label: '7016库位', value: '7016库位' }
]
// 在制量数据
const quantityFormData = ref({
  recordDate: new Date().toISOString().slice(0, 10),
  locationCode: '',
  quantity: null
})
const quantityData = ref([])
const quantityLoading = ref(false)
// 日期格式化
const formatDate = (dateStr) => {
  if (!dateStr) return '';
  // 解析日期字符串,确保按照中国时区(GMT+8)处理
  const [datePart] = dateStr.split(' ');  // 只取日期部分,忽略时间部分
  return datePart;  // 直接返回日期部分,如"2025-04-16"
}
// 检查日期和生产线/产品是否重复
const checkExists = (date, code, data, excludeId = null) => {
  return data.some(item => {
    const itemDate = item.recordTime ? formatDate(item.recordTime) : item.recordDate;
    return itemDate === date &&
      (item.lineNo === code || item.locationCode === code) &&
      (!excludeId || item.id !== excludeId);
  });
}
// 加载数据
const loadYieldData = async () => {
  yieldLoading.value = true
  try {
    const res = await request({
      url: '/deviceInteraction/yield/listYield',
      method: 'post',
      data: { page: 1, pageSize: 50 }
    })
    if (res.code === 200 && res.data?.records) {
      yieldData.value = res.data.records.map(item => {
        // 转换日期格式
        const formattedDate = item.recordTime ? formatDate(item.recordTime) : '';
        return {
          ...item,
          recordDate: formattedDate, // 添加前端使用的recordDate字段
          editing: false,
          originalData: { ...item, recordDate: formattedDate }
        };
      });
    }
  } catch (error) {
    ElMessage.error('单小时产量数据加载失败')
    console.error(error)
  } finally {
    yieldLoading.value = false
  }
}
const loadUtilizationData = async () => {
  utilizationLoading.value = true
  try {
    const res = await request({
      url: '/deviceInteraction/utilization/listUtilization',
      method: 'post',
      data: { page: 1, pageSize: 50 }
    })
    if (res.code === 200 && res.data?.records) {
      utilizationData.value = res.data.records.map(item => {
        // 转换日期格式
        const formattedDate = item.recordTime ? formatDate(item.recordTime) : '';
        return {
          ...item,
          recordDate: formattedDate, // 添加前端使用的recordDate字段
          editing: false,
          originalData: { ...item, recordDate: formattedDate }
        };
      });
    }
  } catch (error) {
    ElMessage.error('利用率数据加载失败')
    console.error(error)
  } finally {
    utilizationLoading.value = false
  }
}
const loadQuantityData = async () => {
  quantityLoading.value = true
  try {
    const res = await request({
      url: '/deviceInteraction/quantity/listQuantity',
      method: 'post',
      data: { page: 1, pageSize: 50 }
    })
    if (res.code === 200 && res.data?.records) {
      quantityData.value = res.data.records.map(item => {
        // 转换日期格式
        const formattedDate = item.recordTime ? formatDate(item.recordTime) : '';
        return {
          ...item,
          recordDate: formattedDate, // 添加前端使用的recordDate字段
          editing: false,
          originalData: { ...item, recordDate: formattedDate }
        };
      });
    }
  } catch (error) {
    ElMessage.error('在制量数据加载失败')
    console.error(error)
  } finally {
    quantityLoading.value = false
  }
}
// 提交表单
const handleYieldSubmit = async () => {
  if (!yieldFormData.value.recordDate || !yieldFormData.value.lineNo || yieldFormData.value.yieldvalue === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  if (checkExists(yieldFormData.value.recordDate, yieldFormData.value.lineNo, yieldData.value)) {
    ElMessage.error('该日期和生产线的记录已存在')
    return
  }
  try {
    const recordTimeStr = `${yieldFormData.value.recordDate} 00:00:00`;
    await request({
      url: '/deviceInteraction/yield/addYield',
      method: 'post',
      data: {
        ...yieldFormData.value,
        recordTime: recordTimeStr
      }
    })
    ElMessage.success('添加成功')
    resetYieldForm()
    loadYieldData() // 刷新数据
  } catch (error) {
    ElMessage.error('添加失败')
    console.error(error)
  }
}
const handleUtilizationSubmit = async () => {
  if (!utilizationFormData.value.recordDate || !utilizationFormData.value.lineNo || utilizationFormData.value.utilizationRate === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  if (checkExists(utilizationFormData.value.recordDate, utilizationFormData.value.lineNo, utilizationData.value)) {
    ElMessage.error('该日期和生产线的记录已存在')
    return
  }
  try {
    const recordTimeStr = `${utilizationFormData.value.recordDate} 00:00:00`;
    await request({
      url: '/deviceInteraction/utilization/addUtilization',
      method: 'post',
      data: {
        ...utilizationFormData.value,
        recordTime: recordTimeStr
      }
    })
    ElMessage.success('添加成功')
    resetUtilizationForm()
    loadUtilizationData() // 刷新数据
  } catch (error) {
    ElMessage.error('添加失败')
    console.error(error)
  }
}
const handleQuantitySubmit = async () => {
  if (!quantityFormData.value.recordDate || !quantityFormData.value.locationCode || quantityFormData.value.quantity === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  if (checkExists(quantityFormData.value.recordDate, quantityFormData.value.locationCode, quantityData.value)) {
    ElMessage.error('该日期和产品的记录已存在')
    return
  }
  try {
    // 拼接日期时间字符串,确保是当天的00:00:00
    const dateStr = quantityFormData.value.recordDate;
    const recordTimeStr = `${dateStr} 00:00:00`;
    const locationCode = quantityFormData.value.locationCode;
    await request({
      url: '/deviceInteraction/quantity/addQuantity',
      method: 'post',
      data: {
        ...quantityFormData.value,
        recordTime: recordTimeStr
      }
    })
    ElMessage.success('添加成功')
    resetQuantityForm()
    loadQuantityData() // 刷新数据
  } catch (error) {
    ElMessage.error('添加失败')
    console.error(error)
  }
}
// 重置表单
const resetYieldForm = () => {
  yieldFormData.value = {
    recordDate: new Date().toISOString().slice(0, 10),
    lineNo: '',
    yieldvalue: null
  }
}
const resetUtilizationForm = () => {
  utilizationFormData.value = {
    recordDate: new Date().toISOString().slice(0, 10),
    lineNo: '',
    utilizationRate: null
  }
}
const resetQuantityForm = () => {
  quantityFormData.value = {
    recordDate: new Date().toISOString().slice(0, 10),
    locationCode: '',
    quantity: null
  }
}
// 表格编辑操作
const handleYieldEdit = async (index, row) => {
  if (!row.editing) {
    row.editing = true
    return
  }
  if (!row.recordDate || !row.lineNo || row.yieldvalue === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  try {
    // 转换日期格式为服务器需要的格式 yyyy-MM-dd HH:mm:ss
    const date = new Date(row.recordDate);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const recordTimeStr = `${year}-${month}-${day} 00:00:00`;
    await request({
      url: '/deviceInteraction/yield/updateYield',
      method: 'post',
      data: {
        id: row.id,
        lineNo: row.lineNo,
        yieldvalue: row.yieldvalue,
        recordTime: recordTimeStr
      }
    })
    row.editing = false
    row.originalData = { ...row }
    ElMessage.success('修改成功')
    loadYieldData() // 刷新数据
  } catch (error) {
    ElMessage.error('修改失败')
    console.error(error)
  }
}
const handleUtilizationEdit = async (index, row) => {
  if (!row.editing) {
    row.editing = true
    return
  }
  if (!row.recordDate || !row.lineNo || row.utilizationRate === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  try {
    // 转换日期格式为服务器需要的格式 yyyy-MM-dd HH:mm:ss
    const date = new Date(row.recordDate);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const recordTimeStr = `${year}-${month}-${day} 00:00:00`;
    await request({
      url: '/deviceInteraction/utilization/updateUtilization',
      method: 'post',
      data: {
        id: row.id,
        lineNo: row.lineNo,
        utilizationRate: row.utilizationRate,
        recordTime: recordTimeStr
      }
    })
    row.editing = false
    row.originalData = { ...row }
    ElMessage.success('修改成功')
    loadUtilizationData() // 刷新数据
  } catch (error) {
    ElMessage.error('修改失败')
    console.error(error)
  }
}
const handleQuantityEdit = async (index, row) => {
  if (!row.editing) {
    row.editing = true
    return
  }
  if (!row.recordDate || !row.locationCode || row.quantity === null) {
    ElMessage.error('请填写完整信息')
    return
  }
  try {
    // 拼接日期时间字符串,确保是当天的00:00:00
    const dateStr = row.recordDate;
    const recordTimeStr = `${dateStr} 00:00:00`;
    // 获取用户友好名称
    const locationCode = row.locationCode;
    await request({
      url: '/deviceInteraction/quantity/updateQuantity',
      method: 'post',
      data: {
        id: row.id,
        locationCode: locationCode,
        quantity: row.quantity,
        recordTime: recordTimeStr
      }
    })
    row.editing = false
    row.originalData = { ...row }
    ElMessage.success('修改成功')
    loadQuantityData() // 刷新数据
  } catch (error) {
    ElMessage.error('修改失败')
    console.error(error)
  }
}
// 取消编辑
const cancelEdit = (row) => {
  Object.assign(row, row.originalData)
  row.editing = false
}
// 删除操作
const handleDelete = async (index, data, type) => {
  try {
    await ElMessageBox.confirm('确认删除该记录?', '警告', {
      type: 'warning'
    })
    const id = data[index].id
    if (type === 'yieldvalue') {
      await request({
        url: '/deviceInteraction/yield/deleteYield',
        method: 'post',
        data: { id: id }
      })
    } else if (type === 'utilization') {
      await request({
        url: '/deviceInteraction/utilization/deleteUtilization',
        method: 'post',
        data: { id: id }
      })
    } else if (type === 'quantity') {
      await request({
        url: '/deviceInteraction/quantity/deleteQuantity',
        method: 'post',
        data: { id: id }
      })
    }
    ElMessage.success('删除成功')
    // 刷新相应数据
    if (type === 'yieldvalue') loadYieldData()
    else if (type === 'utilization') loadUtilizationData()
    else if (type === 'quantity') loadQuantityData()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
      console.error(error)
    }
  }
}
</script>
<template>
  <el-container>
    <el-main>
      <el-tabs v-model="activeTab">
        <!-- 单小时产量标签页 -->
        <el-tab-pane label="单小时产量" name="yield">
          <el-form :inline="true" :model="yieldFormData" label-width="100px" class="form-container">
            <el-form-item label="日期">
              <el-date-picker
                v-model="yieldFormData.recordDate"
                type="date"
                value-format="YYYY-MM-DD"
                placeholder="选择日期"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item label="生产线">
              <el-select v-model="yieldFormData.lineNo" placeholder="选择生产线" style="width: 180px">
                <el-option label="一线" value="一线" />
                <el-option label="二线" value="二线" />
              </el-select>
            </el-form-item>
            <el-form-item label="产量">
              <el-input-number
                v-model="yieldFormData.yieldvalue"
                :precision="2"
                :step="0.1"
                :min="0"
                controls-position="right"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleYieldSubmit">提交</el-button>
              <el-button @click="resetYieldForm">重置</el-button>
            </el-form-item>
          </el-form>
          <el-table :data="yieldData"  v-loading="yieldLoading" style="width: 100%">
            <el-table-column prop="recordDate" label="日期" width="180">
              <template #default="scope">
                <el-date-picker
                  v-if="scope.row.editing"
                  v-model="scope.row.recordDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.recordDate }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="lineNo" label="生产线" width="180">
              <template #default="scope">
                <el-select v-if="scope.row.editing" v-model="scope.row.lineNo" style="width: 140px">
                  <el-option label="一线" value="一线" />
                  <el-option label="二线" value="二线" />
                </el-select>
                <span v-else>{{ scope.row.lineNo }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="yieldvalue" label="产量" width="180">
              <template #default="scope">
                <el-input-number
                  v-if="scope.row.editing"
                  v-model="scope.row.yieldvalue"
                  :precision="2"
                  :step="0.1"
                  :min="0"
                  controls-position="right"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.yieldvalue }}</span>
              </template>
            </el-table-column>
            <!-- <el-table-column prop="createTime" label="创建时间" width="180" />
            <el-table-column prop="updateTime" label="更新时间" width="180" /> -->
            <el-table-column label="操作" width="200" fixed="right">
              <template #default="scope">
                <el-button-group>
                  <el-button
                    size="small"
                    :type="scope.row.editing ? 'success' : 'primary'"
                    @click="handleYieldEdit(scope.$index, scope.row)"
                  >
                    {{ scope.row.editing ? '保存' : '编辑' }}
                  </el-button>
                  <el-button
                    v-if="scope.row.editing"
                    size="small"
                    @click="cancelEdit(scope.row)"
                  >
                    取消
                  </el-button>
                  <el-button
                    v-else
                    size="small"
                    type="danger"
                    @click="handleDelete(scope.$index, yieldData, 'yieldvalue')"
                  >
                    删除
                  </el-button>
                </el-button-group>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
        <!-- 利用率标签页 -->
        <el-tab-pane label="利用率" name="utilization">
          <el-form :inline="true" :model="utilizationFormData" label-width="100px" class="form-container">
            <el-form-item label="日期">
              <el-date-picker
                v-model="utilizationFormData.recordDate"
                type="date"
                value-format="YYYY-MM-DD"
                placeholder="选择日期"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item label="生产线">
              <el-select v-model="utilizationFormData.lineNo" placeholder="选择生产线" style="width: 180px">
                <el-option label="一线" value="一线" />
                <el-option label="二线" value="二线" />
              </el-select>
            </el-form-item>
            <el-form-item label="利用率">
              <el-input-number
                v-model="utilizationFormData.utilizationRate"
                :precision="2"
                :step="0.1"
                :min="0"
                :max="100"
                controls-position="right"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleUtilizationSubmit">提交</el-button>
              <el-button @click="resetUtilizationForm">重置</el-button>
            </el-form-item>
          </el-form>
          <el-table :data="utilizationData"  v-loading="utilizationLoading" style="width: 100%">
            <el-table-column prop="recordDate" label="日期" width="180">
              <template #default="scope">
                <el-date-picker
                  v-if="scope.row.editing"
                  v-model="scope.row.recordDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.recordDate }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="lineNo" label="生产线" width="180">
              <template #default="scope">
                <el-select v-if="scope.row.editing" v-model="scope.row.lineNo" style="width: 140px">
                  <el-option label="一线" value="一线" />
                  <el-option label="二线" value="二线" />
                </el-select>
                <span v-else>{{ scope.row.lineNo }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="utilizationRate" label="利用率" width="180">
              <template #default="scope">
                <el-input-number
                  v-if="scope.row.editing"
                  v-model="scope.row.utilizationRate"
                  :precision="2"
                  :step="0.1"
                  :min="0"
                  :max="100"
                  controls-position="right"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.utilizationRate }}%</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="200" fixed="right">
              <template #default="scope">
                <el-button-group>
                  <el-button
                    size="small"
                    :type="scope.row.editing ? 'success' : 'primary'"
                    @click="handleUtilizationEdit(scope.$index, scope.row)"
                  >
                    {{ scope.row.editing ? '保存' : '编辑' }}
                  </el-button>
                  <el-button
                    v-if="scope.row.editing"
                    size="small"
                    @click="cancelEdit(scope.row)"
                  >
                    取消
                  </el-button>
                  <el-button
                    v-else
                    size="small"
                    type="danger"
                    @click="handleDelete(scope.$index, utilizationData, 'utilization')"
                  >
                    删除
                  </el-button>
                </el-button-group>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
        <!-- 在制量标签页 -->
        <el-tab-pane label="在制量" name="quantity">
          <el-form :inline="true" :model="quantityFormData" label-width="100px" class="form-container">
            <el-form-item label="日期">
              <el-date-picker
                v-model="quantityFormData.recordDate"
                type="date"
                value-format="YYYY-MM-DD"
                placeholder="选择日期"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item label="类型">
              <el-select v-model="quantityFormData.locationCode" placeholder="选择类型" style="width: 180px">
                <el-option label="半成品" value="半成品" />
                <el-option label="7014库位" value="7014库位" />
                <el-option label="7016库位" value="7016库位" />
              </el-select>
            </el-form-item>
            <el-form-item label="数量">
              <el-input-number
                v-model="quantityFormData.quantity"
                :precision="0"
                :step="1"
                :min="0"
                controls-position="right"
                style="width: 180px"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleQuantitySubmit">提交</el-button>
              <el-button @click="resetQuantityForm">重置</el-button>
            </el-form-item>
          </el-form>
          <el-table :data="quantityData"  v-loading="quantityLoading" style="width: 100%">
            <el-table-column prop="recordDate" label="日期" width="180">
              <template #default="scope">
                <el-date-picker
                  v-if="scope.row.editing"
                  v-model="scope.row.recordDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.recordDate }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="locationCode" label="产品" width="180">
              <template #default="scope">
                <el-select v-if="scope.row.editing" v-model="scope.row.locationCode" style="width: 140px">
                  <el-option label="半成品" value="半成品" />
                  <el-option label="7014库位" value="7014库位" />
                  <el-option label="7016库位" value="7016库位" />
                </el-select>
                <span v-else>
                  {{
                    scope.row.locationCode === '半成品' ? '半成品' :
                    scope.row.locationCode === '7014库位' ? '7014库位' : '7016库位'
                  }}
                </span>
              </template>
            </el-table-column>
            <el-table-column prop="quantity" label="数量" width="180">
              <template #default="scope">
                <el-input-number
                  v-if="scope.row.editing"
                  v-model="scope.row.quantity"
                  :precision="0"
                  :step="1"
                  :min="0"
                  controls-position="right"
                  style="width: 140px"
                />
                <span v-else>{{ scope.row.quantity }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="200" fixed="right">
              <template #default="scope">
                <el-button-group>
                  <el-button
                    size="small"
                    :type="scope.row.editing ? 'success' : 'primary'"
                    @click="handleQuantityEdit(scope.$index, scope.row)"
                  >
                    {{ scope.row.editing ? '保存' : '编辑' }}
                  </el-button>
                  <el-button
                    v-if="scope.row.editing"
                    size="small"
                    @click="cancelEdit(scope.row)"
                  >
                    取消
                  </el-button>
                  <el-button
                    v-else
                    size="small"
                    type="danger"
                    @click="handleDelete(scope.$index, quantityData, 'quantity')"
                  >
                    删除
                  </el-button>
                </el-button-group>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-main>
  </el-container>
</template>
<style scoped>
.form-container {
  margin-bottom: 20px;
  background-color: #f5f7fa;
  padding: 20px;
  border-radius: 4px;
}
.el-table {
  margin-top: 20px;
}
:deep(.el-tabs__header) {
  margin-bottom: 25px;
}
</style>
UI-Project/src/views/KanbanDisplay/kanbanDisplay.vue
@@ -433,7 +433,6 @@
        type: 'category',
        boundaryGap: false,
        axisTick: { alignWithLabel: true },
        boundaryGap: true,
        axisLabel: {
          fontSize: 20,
          interval: 'auto',
@@ -544,7 +543,7 @@
        {
          type: 'category',
          axisTick: { alignWithLabel: true },
          boundaryGap: true,
          boundaryGap: '20%',
          axisLabel: {
            fontSize: 20,
            interval: 'auto',
@@ -586,8 +585,8 @@
        {
          name: '计划量',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          barWidth: '27%',
          barGap: '20%',
          label: {
            show: true,
            fontSize: 16,
@@ -599,8 +598,8 @@
        {
          name: '一线',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          barWidth: '27%',
          barGap: '20%',
          label: {
            show: true,
            fontSize: 16,
@@ -612,8 +611,8 @@
        {
          name: '二线',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          barWidth: '27%',
          barGap: '10%',
          label: {
            show: true,
            fontSize: 16,
@@ -815,7 +814,7 @@
  color: white;
}
:deep(.el-table__body tr:hover > td) {
:deep(.el-table__body tr:hover td) {
  background-color: #1a4d7f !important;
}
</style>
UI-Project/src/views/KanbanDisplay2/kanbanDisplay2.vue
New file
@@ -0,0 +1,1317 @@
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import * as echarts from 'echarts'
import request from '@/utils/request'
const dashboardRef = ref(null)
const standardWidth = 1920 // 设计稿标准宽度
const standardHeight = 1080 // 设计稿标准高度
// 计算缩放比例并应用
const setScale = () => {
  if (!dashboardRef.value) return
  const w = window.innerWidth
  const h = window.innerHeight
  // 计算宽高比例
  const wScale = w / standardWidth
  const hScale = h / standardHeight
  // 使用较小的缩放比例,确保内容完全显示
  const scale = Math.min(wScale, hScale)
  // 计算居中偏移
  const offsetX = (w - standardWidth * scale) / 2
  const offsetY = (h - standardHeight * scale) / 2
  // 应用变换
  dashboardRef.value.style.transform = `scale(${scale})`
  dashboardRef.value.style.transformOrigin = '0 0'
  dashboardRef.value.style.marginLeft = `${offsetX}px`
  dashboardRef.value.style.marginTop = `${offsetY}px`
}
// 监听窗口大小变化
const handleResize = () => {
  setScale()
  // 重新渲染所有图表
  charts.forEach(chart => {
    chart.resize()
  })
}
// 存储所有图表实例
const charts = []
// 获取能耗数据
const loadEnergyData = async () => {
  try {
    const res = await request({
      url: '/deviceInteraction/energy/consumption/chartEnergy',
      method: 'post'
    })
    if (res.code === 200) {
      console.log('能耗数据加载成功')
      // 暂时不处理能耗数据
    }
  } catch (error) {
    console.error('获取能耗数据失败:', error)
  }
}
// 单小时产量数据
const loadYieldData = async () => {
  try {
    const res = await request.post('/deviceInteraction/yield/chartYield', {
      dayCount: 30  // 确保请求30天的数据
    });
    if (res.code === 200) {
      yieldData.value = res.data;
      updateOptionYield();
    }
  } catch (error) {
    console.error('获取单小时产量数据失败:', error);
  }
}
// 加载利用率数据
const loadUtilizationData = async () => {
  try {
    const res = await request.post('/deviceInteraction/utilization/chartUtilization', {
      dayCount: 30  // 确保请求30天的数据
    });
    if (res.code === 200) {
      utilizationData.value = res.data;
      updateOptionUtilization();
    }
  } catch (error) {
    console.error('获取利用率数据失败:', error);
  }
}
// 加载在制量数据
const loadInventoryData = async () => {
  try {
    const res = await request.post('/deviceInteraction/quantity/chartQuantity', {
      dayCount: 30  // 确保请求30天的数据
    });
    if (res.code === 200) {
      quantityData.value = res.data;
      updateOptionQuantity();
    }
  } catch (error) {
    console.error('获取在制量数据失败:', error);
  }
}
const yieldData = ref([]) // 单小时产量数据
const utilizationData = ref([]) // 利用率数据
const quantityData = ref([]) // 在制量数据
const notCompleteData = ref([]) // 完整数据集
const displayedData = ref([]) // 当前显示的数据集
const pageSize = 20 // 每批显示的数据量
let currentPage = 0 // 当前显示的批次
let scrollTimer = null // 滚动计时器
// 获取未完成数据
const loadNotCompleteData = async () => {
  try {
    const res = await request.post('/deviceInteraction/primitiveTask/findDayNotCompleteOutput', {
      "dayCount": 2
    })
    if (res.code === 200) {
      notCompleteData.value = res.data;
      console.log("加载数据完成,共" + res.data.length + "条");
    } else {
      console.error('请求当日产量数据失败:', res.message);
    }
  } catch (error) {
    console.error('请求当日产量数据失败:', error);
  }
}
const updateOptionYield = () => {
  // 按日期排序并处理数据
  const sortedData = [...yieldData.value].sort((a, b) =>
    new Date(a.recordTime) - new Date(b.recordTime)
  );
  // 生成最近30天的日期
  const today = new Date();
  const dates = [];
  for (let i = 29; i >= 0; i--) {
    const date = new Date();
    date.setDate(today.getDate() - i);
    // 确保年月日格式完整
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    dates.push(formattedDate);
  }
  // 分离一线和二线数据
  const line1Data = Array(30).fill(0);
  const line2Data = Array(30).fill(0);
  // 为每个日期准备数据
  sortedData.forEach(item => {
    const date = new Date(item.recordTime);
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    const dateIndex = dates.indexOf(formattedDate);
    if (dateIndex !== -1) {
      if (item.lineNo === '一线') {
        line1Data[dateIndex] += item.yieldvalue;
      } else if (item.lineNo === '二线') {
        line2Data[dateIndex] += item.yieldvalue;
      }
    }
  });
  // 单小时产量的配置 - 分上下两个子图表
  const OptionYield = {
    title: {
      text: '单小时产量',
      textStyle: {
        fontSize: 25,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    legend: {
      data: ['一线', '二线'],
      textStyle: {
        fontSize: 20,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    grid: [{
      left: '3%',
      right: '4%',
      top: '15%',
      height: '35%',
      containLabel: true
    }, {
      left: '3%',
      right: '4%',
      top: '55%',
      height: '35%',
      containLabel: true
    }],
    xAxis: [
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 0,
        axisLabel: {
          show: false  // 隐藏上图的x轴标签
        }
      },
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 1,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          interval: 'auto',
          formatter: (value, index) => {
            // 如果是日期格式
            if (value.includes('-')) {
              // 对第一个日期显示完整年月日
              if (index === 0) {
                return value;  // 返回完整日期 (例如: 2024-03-21)
              }
              // 其他日期只显示月-日
              return value.split('-').slice(1).join('-');  // (例如: 03-21)
            }
            return value;
          }
        }
      }
    ],
    yAxis: [
      {
        type: 'value',
        gridIndex: 0,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          show:false
        },
        splitLine: {
          show: false // 隐藏横线
                }
      },
      {
        type: 'value',
        gridIndex: 1,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          show:false
        },
        splitLine: {
          show: false // 隐藏横线
                }
      }
    ],
    series: [
      {
        name: '一线',
        type: 'line',
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: {
          width: 4,
          color: '#91cc75'  // 设置一线颜色
        },
        itemStyle: {
          color: '#91cc75'
        },
        emphasis: {
          focus: 'series'
        },
        data: line1Data,
        label: {
          show: true,
          fontSize: 15,
          color: 'white'
        }
      },
      {
        name: '二线',
        type: 'line',
        xAxisIndex: 1,
        yAxisIndex: 1,
        lineStyle: {
          width: 4,
          color: '#5470c6'  // 设置二线颜色
        },
        itemStyle: {
          color: '#5470c6'
        },
        emphasis: {
          focus: 'series'
        },
        data: line2Data,
        label: {
          show: true,
          fontSize: 15,
          color: 'white'
        }
      }
    ]
  };
  const chart = echarts.init(document.getElementById('drawLineChart_yield'));
  chart.setOption(OptionYield);
  charts.push(chart);
}
const updateOptionUtilization = () => {
  // 按日期排序并处理数据
  const sortedData = [...utilizationData.value].sort((a, b) =>
    new Date(a.recordTime || a.recordDate) - new Date(b.recordTime || b.recordDate)
  );
  // 生成最近30天的日期
  const today = new Date();
  const dates = [];
  for (let i = 29; i >= 0; i--) {
    const date = new Date();
    date.setDate(today.getDate() - i);
    // 确保年月日格式完整
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    dates.push(formattedDate);
  }
  // 分离一线和二线数据
  const line1Data = Array(30).fill(0);
  const line2Data = Array(30).fill(0);
  // 为每个日期准备数据
  sortedData.forEach(item => {
    const date = new Date(item.recordTime || item.recordDate);
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    const dateIndex = dates.indexOf(formattedDate);
    if (dateIndex !== -1) {
      if (item.lineNo === '一线') {
        line1Data[dateIndex] = item.utilizationRate;
      } else if (item.lineNo === '二线') {
        line2Data[dateIndex] = item.utilizationRate;
      }
    }
  });
  // 利用率的配置 - 分上下两个子图表
  const OptionUtilization = {
    title: {
      text: '利用率',
      textStyle: {
        fontSize: 25,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    legend: {
      data: ['一线', '二线'],
      textStyle: {
        fontSize: 20,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    grid: [{
      left: '3%',
      right: '4%',
      top: '15%',
      height: '35%',
      containLabel: true
    }, {
      left: '3%',
      right: '4%',
      top: '55%',
      height: '35%',
      containLabel: true
    }],
    xAxis: [
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 0,
        axisLabel: {
          show: false  // 隐藏上图的x轴标签
        }
      },
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 1,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          interval: 'auto',
          formatter: (value, index) => {
            // 如果是日期格式
            if (value.includes('-')) {
              // 对第一个日期显示完整年月日
              if (index === 0) {
                return value;  // 返回完整日期 (例如: 2024-03-21)
              }
              // 其他日期只显示月-日
              return value.split('-').slice(1).join('-');  // (例如: 03-21)
            }
            return value;
          }
        }
      }
    ],
    yAxis: [
      {
        type: 'value',
        gridIndex: 0,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          formatter: '{value}%',
          show:false
        },
        splitLine: {
          show: false // 隐藏横线
                }
      },
      {
        type: 'value',
        gridIndex: 1,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          formatter: '{value}%',
          show:false
        },
        splitLine: {
          show: false // 隐藏横线
                }
      }
    ],
    series: [
      {
        name: '一线',
        type: 'line',
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: {
          width: 4,
          color: '#91cc75'  // 设置一线颜色
        },
        itemStyle: {
          color: '#91cc75'
        },
        emphasis: {
          focus: 'series'
        },
        data: line1Data,
        label: {
          show: true,
          fontSize: 15,
          color: 'white',
          formatter: '{c}%'
        }
      },
      {
        name: '二线',
        type: 'line',
        xAxisIndex: 1,
        yAxisIndex: 1,
        lineStyle: {
          width: 4,
          color: '#5470c6'  // 设置二线颜色
        },
        itemStyle: {
          color: '#5470c6'
        },
        emphasis: {
          focus: 'series'
        },
        data: line2Data,
        label: {
          show: true,
          fontSize: 15,
          color: 'white',
          formatter: '{c}%'
        }
      }
    ]
  };
  const chart = echarts.init(document.getElementById('drawLineChart_utilization'));
  chart.setOption(OptionUtilization);
  charts.push(chart);
}
const updateOptionQuantity = () => {
  // 按日期排序并处理数据
  const sortedData = [...quantityData.value].sort((a, b) =>
    new Date(a.recordTime || a.recordDate) - new Date(b.recordTime || b.recordDate)
  );
  // 生成最近30天的日期
  const today = new Date();
  const dates = [];
  for (let i = 29; i >= 0; i--) {
    const date = new Date();
    date.setDate(today.getDate() - i);
    // 确保年月日格式完整
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    dates.push(formattedDate);
  }
  // 分离各库位数据
  const semiData = Array(30).fill(0);
  const data7014 = Array(30).fill(0);
  const data7016 = Array(30).fill(0);
  // 为每个日期准备数据
  sortedData.forEach(item => {
    const date = new Date(item.recordTime || item.recordDate);
    const formattedDate = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    const dateIndex = dates.indexOf(formattedDate);
    if (dateIndex !== -1) {
      if (item.locationCode === '半成品') {
        semiData[dateIndex] = item.quantity;
      } else if (item.locationCode === '7014库位') {
        data7014[dateIndex] = item.quantity;
      } else if (item.locationCode === '7016库位') {
        data7016[dateIndex] = item.quantity;
      }
    }
  });
  // 在制量的配置 - 上中下三层布局
  const OptionQuantity = {
    title: {
      text: '在制量',
      textStyle: {
        fontSize: 25,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    legend: {
      data: ['半成品', '7014库位', '7016库位'],
      textStyle: {
        fontSize: 20,
        fontWeight: 'bold',
        color: 'white'
      }
    },
    grid: [
      {
        left: '3%',
        right: '4%',
        top: '15%',
        height: '20%',
        containLabel: true
      },
      {
        left: '3%',
        right: '4%',
        top: '45%',
        height: '20%',
        containLabel: true
      },
      {
        left: '3%',
        right: '4%',
        top: '75%',
        height: '25%',
        containLabel: true
      }
    ],
    xAxis: [
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 0,
        axisLabel: {
          show: false,  // 隐藏上层x轴标签
          color: 'white'
        },
        splitLine: {
          show: false // 隐藏横线
        }
      },
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 1,
        axisLabel: {
          show: false,  // 隐藏中层x轴标签
          color: 'white'
        },
        splitLine: {
          show: false // 隐藏横线
        }
      },
      {
        type: 'category',
        boundaryGap: false,
        data: dates,
        gridIndex: 2,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          interval: 'auto',
          formatter: (value, index) => {
            // 如果是日期格式
            if (value.includes('-')) {
              // 对第一个日期显示完整年月日
              if (index === 0) {
                return value;  // 返回完整日期 (例如: 2024-03-21)
              }
              // 其他日期只显示月-日
              return value.split('-').slice(1).join('-');  // (例如: 03-21)
            }
            return value;
          }
        },
        splitLine: {
          show: false // 隐藏横线
        }
      }
    ],
    yAxis: [
      {
        type: 'value',
        gridIndex: 0,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          show: false
        },
        splitLine: {
          show: false // 隐藏横线
        }
      },
      {
        type: 'value',
        gridIndex: 1,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          show: false
        },
        splitLine: {
          show: false // 隐藏横线
        }
      },
      {
        type: 'value',
        gridIndex: 2,
        axisLabel: {
          fontSize: 20,
          color: 'white',
          show: false
        },
        splitLine: {
          show: false // 隐藏横线
        }
      }
    ],
    series: [
      {
        name: '半成品',
        type: 'line',
        xAxisIndex: 0,
        yAxisIndex: 0,
        lineStyle: {
          width: 4,
          color: '#91cc75'  // 设置颜色
        },
        itemStyle: {
          color: '#91cc75'
        },
        emphasis: {
          focus: 'series'
        },
        data: semiData,
        label: {
          show: true,
          fontSize: 14,
          color: 'white'
        }
      },
      {
        name: '7014库位',
        type: 'line',
        xAxisIndex: 1,
        yAxisIndex: 1,
        lineStyle: {
          width: 4,
          color: 'red'  // 设置颜色
        },
        itemStyle: {
          color: 'red'
        },
        emphasis: {
          focus: 'series'
        },
        data: data7014,
        label: {
          show: true,
          fontSize: 14,
          color: 'white'
        }
      },
      {
        name: '7016库位',
        type: 'line',
        xAxisIndex: 2,
        yAxisIndex: 2,
        lineStyle: {
          width: 4,
          color: '#fac858'  // 设置颜色
        },
        itemStyle: {
          color: '#fac858'
        },
        emphasis: {
          focus: 'series'
        },
        data: data7016,
        label: {
          show: true,
          fontSize: 14,
          color: 'white'
        }
      }
    ]
  };
  const chart = echarts.init(document.getElementById('drawLineChart_quantity'));
  chart.setOption(OptionQuantity);
  charts.push(chart);
}
onMounted(() => {
  setScale()
  window.addEventListener('resize', handleResize)
  loadEnergyData();
  loadNotCompleteData();
  loadYieldData();
  loadUtilizationData();
  loadInventoryData();
  // 设置定时刷新
  const refreshInterval = setInterval(() => {
    loadYieldData();
    loadUtilizationData();
    loadInventoryData();
    console.log('数据已刷新');
  }, 60000); // 每分钟刷新一次
  onUnmounted(() => {
    clearInterval(refreshInterval);
  });
})
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  charts.forEach(chart => {
    chart.dispose()
  })
})
</script>
<template>
  <div class="dashboard-container" ref="dashboardRef">
    <div class="dashboard-content">
      <div
        style="font-weight: 800;font-size: 30px;height: 70px;line-height: 70px;border: 1px solid #ccc;text-align: center;">
        JOMOO配套工厂镜片车间生产看板
      </div>
      <div style="width:100% ;height: 1080px;">
        <div style="width:100% ;height: 25%;border: 1px solid #ccc;">
          <div id="drawLineChart_day11" style="height: 100%;width: 30%;border: 1px solid #ccc;float: left;">日单达成率-片数
          </div>
          <div style="width:70% ;height: 100%;border: 1px solid #ccc;float: left;">
            <div id="drawLineChart_day51" style="height: 100%;width: 80%;border: 1px solid #ccc;float: left;">计划量-片数、平方
            </div>
            <div id="drawLineChart_day91" style="height: 100%;width: 20%;float: left;">
              <div
                style="font-weight: 700;font-size: 20px;height: 30px;line-height: 30px;text-align: center;border: 1px solid #ccc;">
                总计划量-片数、平方</div>
              <div id="textDay" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">日期:2023-03-01 -
                2023-03-01</div>
                <br>
              <div id="textprice" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">片数:25</div>
              <div id="textarea" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">平方数:2999</div>
            </div>
          </div>
        </div>
        <div style="width:100% ;height: 25%;border: 1px solid #ccc;">
          <div id="drawLineChart_yield" style="height: 100%;width: 100%;border: 1px solid #ccc;">单小时产量</div>
        </div>
        <div style="width:100% ;height: 25%;border: 1px solid #ccc;">
          <div id="drawLineChart_utilization" style="height: 100%;width: 100%;border: 1px solid #ccc;">利用率</div>
        </div>
        <div style="width:100% ;height: 25%;border: 1px solid #ccc;">
          <div id="drawLineChart_quantity" style="height: 100%;width: 100%;border: 1px solid #ccc;">在制量</div>
        </div>
      </div>
      <!-- <div style="width:33% ;height: 880px;border: 1px solid #ccc;">
        <div id="drawLineChart_day1" style="height: 300px;width: 25%;border: 1px solid #ccc;float: left;"></div>
        <div id="drawLineChart_day2" style="height: 300px;width: 25%;border: 1px solid #ccc;float: left;"></div>
      </div> -->
    </div>
  </div>
</template>
<script>
export default {
  mounted() {
    const OptionDayMode = {
      title: {
        text: '计划量看板',
        textStyle: {
          fontSize: 25,
          fontWeight: 'bold',
          color: 'white' // 设置标题颜色为白色
        }
      },
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          label: {
            fontSize: 16,
            color: 'white' // 设置提示框文字颜色为白色
          }
        }
      },
      legend: {
        textStyle: {
          fontSize: 20,
          fontWeight: 'bold',
          color: 'white' // 设置图例文字颜色为白色
        }
      },
      toolbox: {
        show: true,
        feature: {
          dataZoom: {
            yAxisIndex: 'none'
          },
          dataView: { readOnly: false },
          magicType: { type: ['line', 'bar'] },
          restore: {},
          saveAsImage: {}
        },
        iconStyle: {
          color: 'white' // 设置工具框图标颜色为白色
        }
      },
      grid: [
        {
          left: '3%',
          right: '4%',
          top: '15%',
          height: '35%',
          containLabel: true
        },
        {
          left: '3%',
          right: '4%',
          top: '55%',
          height: '35%',
          containLabel: true
        }
      ],
      xAxis: [
        {
          type: 'category',
          boundaryGap: false,
          data: [],
          gridIndex: 0,
          axisLabel: {
            show: false,
            fontSize: 20,
            color: 'white'
          },
          splitLine: {
            show: false // 隐藏横线
          }
        },
        {
          type: 'category',
          boundaryGap: false,
          data: [],
          gridIndex: 1,
          axisLabel: {
            fontSize: 20,
            color: 'white',
            interval: 'auto',
            formatter: (value, index) => {
              // 如果是日期格式
              if (value.includes('-')) {
                // 对第一个日期显示完整年月日
                if (index === 0) {
                  return value;  // 返回完整日期 (例如: 2024-03-21)
                }
                // 其他日期只显示月-日
                return value.split('-').slice(1).join('-');  // (例如: 03-21)
              }
              return value;
            }
          },
          splitLine: {
            show: false // 隐藏横线
          }
        }
      ],
      yAxis: [
        {
          type: 'value',
          gridIndex: 0,
          axisLabel: {
            fontSize: 20,
            formatter: '{value} ',
            color: 'white',
            show: false
          },
          splitLine: {
            show: false // 隐藏横线
          },
          nameTextStyle: {
            fontSize: 20,
            color: 'white' // 设置 y 轴名称颜色为白色
          }
        },
        {
          type: 'value',
          gridIndex: 1,
          axisLabel: {
            fontSize: 20,
            formatter: '{value} ',
            color: 'white',
            show: false
          },
          splitLine: {
            show: false // 隐藏横线
          },
          nameTextStyle: {
            fontSize: 20,
            color: 'white' // 设置 y 轴名称颜色为白色
          }
        }
      ],
      series: [
        {
          name: '平方',
          type: 'line',
          xAxisIndex: 0,
          yAxisIndex: 0,
          barWidth: '40%',
          barGap: '10%',
          lineStyle: {
            width: 4,
            color: '#91cc75'
          },
          itemStyle: {
            color: '#91cc75'
          },
          label: {
            show: true,
            fontSize: 16,
            formatter: (params) => {
              // 保留两位小数
              return params.value ? Number(params.value).toFixed(2) : '0.00';
            },
            color: 'white' // 设置数据标签颜色为白色
          }
        },
        {
          name: '片数',
          type: 'line',
          xAxisIndex: 1,
          yAxisIndex: 1,
          barWidth: '40%',
          barGap: '10%',
          lineStyle: {
            width: 4,
            color: '#5470c6'
          },
          itemStyle: {
            color: '#5470c6'
          },
          label: {
            show: true,
            fontSize: 16,
            color: 'white' // 设置数据标签颜色为白色
          }
        }
      ]
    };
    const OptionYear = {
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'shadow',
          label: {
            fontSize: 16,
            color: 'white' // 设置提示框文字颜色为白色
          }
        }
      },
      legend: {
        textStyle: {
          fontSize: 20,
          fontWeight: 'bold',
          color: 'white' // 设置图例文字颜色为白色
        }
      },
      toolbox: {
        show: true,
        feature: {
          dataZoom: {
            yAxisIndex: 'none'
          },
          dataView: { readOnly: false },
          magicType: { type: ['line', 'bar'] },
          restore: {},
          saveAsImage: {}
        },
        iconStyle: {
          color: 'white' // 设置工具框图标颜色为白色
        }
      },
      grid: {
        left: '3%',
        right: '4%',
        bottom: '10%',
        containLabel: true
      },
      xAxis: [
        {
          type: 'category',
          axisTick: { alignWithLabel: true },
          boundaryGap: true,
          axisLabel: {
            fontSize: 20,
            interval: 'auto',
            margin: 15,
            formatter: (value, index) => {
              // 如果是日期格式
              if (value.includes('-')) {
                // 对第一个日期显示完整年月日
                if (index === 0) {
                  return value;  // 返回完整日期 (例如: 2024-03-21)
                }
                // 其他日期只显示月-日
                return value.split('-').slice(1).join('-');  // (例如: 03-21)
              }
              return value;
            },
            color: 'white' // 设置 x 轴标签颜色为白色
          },
          nameTextStyle: {
            fontSize: 20,
            color: 'white' // 设置 x 轴名称颜色为白色
          }
        }
      ],
      yAxis: [
        {
          type: 'value',
          axisLabel: {
            fontSize: 20,
            color: 'white' // 设置 y 轴标签颜色为白色
          },
          nameTextStyle: {
            fontSize: 20,
            color: 'white' // 设置 y 轴名称颜色为白色
          }
        }
      ],
      series: [
        {
          name: '计划量',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          label: {
            show: true,
            fontSize: 16,
            formatter: (params) => params.value,
            color: 'white',
            position: 'top'
          }
        },
        {
          name: '一线',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          label: {
            show: true,
            fontSize: 16,
            formatter: (params) => params.value,
            color: 'white',
            position: 'top'
          },
        },
        {
          name: '二线',
          type: 'bar',
          barWidth: '30%',
          barGap: '10%',
          label: {
            show: true,
            fontSize: 16,
            formatter: (params) => params.value,
            color: 'white',
            position: 'top'
          },
        }
      ]
    };
    // 请求当日产量
    request.post('/deviceInteraction/primitiveTask/findDailyOutput',
      {
        "dayCount": 1
      }).then((res) => {
        if (res.code == 200) {
          const modeOptions = res.data;
          this.drawDay('drawLineChart_day11', OptionYear, modeOptions);
          // this.drawDay('drawLineChart_day31', OptionYear, modeOptions);
          // this.drawYear('drawLineChart_day51', OptionDayMode, modeOptions);
        } else {
          console.error('请求当日产量数据失败:', error);
        }
      });
    //请求日产量-月
    request.post('/deviceInteraction/primitiveTask/findDailyOutput',
      {
        "dayCount": 30
      }).then((res) => {
        if (res.code == 200) {
          const modeOptions = res.data;
          //this.drawDay('drawLineChart_day11', OptionYear, modeOptions);
          this.drawDay('drawLineChart_day31', OptionYear, modeOptions);
          // this.drawYear('drawLineChart_day51', OptionDayMode, modeOptions);
        } else {
          console.error('请求日产量-月数据失败:', error);
        }
      });
    //请求计划量
    request.post('/deviceInteraction/primitiveTask/findPlannedQuantity',
      {
        "dayCount": 30
      }).then((res) => {
        if (res.code == 200) {
          const modeOptions = res.data;
          this.drawYear('drawLineChart_day51', OptionDayMode, modeOptions);
          let textDay = document.getElementById('textDay');
          let textprice = document.getElementById('textprice');
          let textarea = document.getElementById('textarea');
          let y_pingfang = res.data.map(v => { return v.area_sum });
          let y_pianshu = res.data.map(v => { return v.task_quantity_sum });
          let y_pingfang_sum = 0;
          let y_pianshu_sum = 0;
          for (let i = 0; i < y_pingfang.length; i++) {
            y_pingfang_sum += y_pingfang[i];
          }
          for (let i = 0; i < y_pianshu.length; i++) {
            y_pianshu_sum += y_pianshu[i];
          }
          textDay.innerHTML = "日期:" + "<br>" + res.data[0].CreateDate + " - " + res.data[res.data.length - 1].CreateDate;
          textprice.innerHTML = "片数:" + y_pianshu_sum;
          textarea.innerHTML = "平方数:" + Number(y_pingfang_sum).toFixed(2);
          // this.drawYear('drawLineChart_day51', OptionDayMode, modeOptions);
        } else {
          console.error('请求计划量-月数据失败:', error);
        }
      });
  },
  methods: {
    draw(name, Option) {
      var myChart = echarts.init(document.getElementById(name));
      myChart.setOption(Option);
    },
    drawDay(name, Option, data) {
      // console.log(data);
      //Option.title.text="日看板";
      //日看板- 计划量,一线完成,二线完成(片数)
      let x_data = data.map(v => { return v.date });
      let y_jihua = data.map(v => { return v.plan });
      let y_one = data.map(v => { return v.line1 });
      let y_two = data.map(v => { return v.line2 });
      Option.xAxis[0].data = x_data;
      Option.series[0].data = y_jihua;
      Option.series[1].data = y_one;
      Option.series[2].data = y_two;
      this.draw(name, Option);
    },
    drawYear(name, Option, data) {
      //计划量- 平方,片数
      let x_data = data.map(v => { return v.CreateDate });
      let y_pingfang = data.map(v => { return v.area_sum });
      let y_pianshu = data.map(v => { return v.task_quantity_sum });
      Option.xAxis[0].data = x_data;
      Option.xAxis[1].data = x_data;
      Option.series[0].data = y_pingfang;
      Option.series[1].data = y_pianshu;
      this.draw(name, Option);
    },
    requsstData() {
    },
    // // 渲染单小时产量图表
    // drawYieldChart(data) {
    //   const option = { ...OptionYield };
    //   option.xAxis.data = data.map(v => v.date);
    //   option.series[0].data = data.map(v => v.line1_yield);
    //   option.series[1].data = data.map(v => v.line2_yield);
    //   this.draw('drawLineChart_yield', option);
    // },
    // // 渲染利用率图表
    // drawUtilizationChart(data) {
    //   const option = { ...OptionUtilization };
    //   option.xAxis.data = data.map(v => v.date);
    //   option.series[0].data = data.map(v => v.line1_utilization);
    //   option.series[1].data = data.map(v => v.line2_utilization);
    //   this.draw('drawLineChart_utilization', option);
    // },
    // // 渲染在制量图表
    // drawQuantityChart(data) {
    //   const option = { ...OptionQuantity };
    //   option.xAxis.data = data.map(v => v.date);
    //   option.series[0].data = data.map(v => v.semi_finished);
    //   option.series[1].data = data.map(v => v.location_7014);
    //   option.series[2].data = data.map(v => v.location_7016);
    //   this.draw('drawLineChart_quantity', option);
    // },
  }
}
</script>
<style scoped>
.dashboard-container {
  position: absolute;
  width: 1920px;
  /* 设计稿宽度 */
  background: linear-gradient(to bottom, #001f3f, #0074d9d7);
  color: white;
  overflow: hidden;
  transition: transform 0.3s ease-out, margin 0.3s ease-out;
}
.dashboard-content {
  width: 100%;
  height: 100%;
}
/*0b3d6f*/
.float {
  float: left;
}
.style {
  width: 600px;
  height: 400px;
  border: 1px solid #ccc;
}
.chart {
  height: 400px;
}
/* 确保图表容器内的echarts实例能够正确显示 */
:deep(.echarts) {
  width: 100% !important;
  height: 100% !important;
}
</style>