| | |
| | | package com.mes.md.controller; |
| | | |
| | | |
| | | import com.mes.md.service.TaskingLogService; |
| | | import com.mes.utils.Result; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | |
| | | |
| | | @Autowired |
| | | TaskingLogService taskingLogService; |
| | | |
| | | @ApiOperation("查询报表") |
| | | @PostMapping("/mechanicalReport") |
| | | @ResponseBody |
| | | public Result mechanicalReport( |
| | | @RequestParam(required = false) Integer dayCount, |
| | | @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startDate, |
| | | @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endDate, |
| | | @RequestParam(required = false) String taskType, |
| | | @RequestParam(required = false) String operationRecord, |
| | | @RequestParam(required = false) String lineType) { |
| | | try { |
| | | List<Map> result = taskingLogService.selectMechanicalReport( |
| | | dayCount, |
| | | startDate, |
| | | endDate, |
| | | taskType, |
| | | operationRecord, |
| | | lineType |
| | | ); |
| | | return Result.build(200, "查询成功", result); |
| | | } catch (Exception e) { |
| | | return Result.build(199, "查询异常", null); |
| | | } |
| | | } |
| | | |
| | | @ApiOperation("提交日志以及报工数据到九牧数据库") |
| | | @PostMapping("/reportTaskingLog") |
| | |
| | | return Result.build(199,"提交异常",map); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | import com.mes.md.entity.TaskLog; |
| | | import com.mes.md.entity.TaskingLog; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | * 查询完工数量-分线路 |
| | | */ |
| | | List<Map> selectTaskingLog(int dayCount); |
| | | |
| | | /** |
| | | * 查询产量 |
| | | * @param dayCount 天数 |
| | | * @param startDate 开始日期 |
| | | * @param endDate 结束日期 |
| | | * @param taskType 任务类型 |
| | | * @param operationRecord 设备 |
| | | * @param lineType 生产线(1:一线,2:二线) |
| | | * @return 产量数据列表 |
| | | */ |
| | | List<Map> selectMechanicalReport(int dayCount, Date startDate, Date endDate, String taskType, String operationRecord, String lineType); |
| | | |
| | | /** |
| | | * 回传报工数据+ 设备玻璃过片记录给 九牧 |
| | | */ |
| | |
| | | @Autowired |
| | | KBBTJPDrawingBPMapper kBBTJPDrawingBPMapper; |
| | | |
| | | @Override |
| | | public List<Map> selectMechanicalReport(int dayCount, Date startDate, Date endDate, String taskType, String operationRecord, String lineType) { |
| | | try { |
| | | // 构建查询条件 |
| | | QueryWrapper<TaskingLog> taskingWrapper = new QueryWrapper<>(); |
| | | |
| | | // 添加完工状态过滤 |
| | | taskingWrapper.eq("work_state", "完工"); |
| | | |
| | | // 时间范围处理 |
| | | if (startDate != null && endDate != null) { |
| | | taskingWrapper.ge("operation_record_time", startDate) |
| | | .le("operation_record_time", endDate); |
| | | } else if (dayCount > 0) { |
| | | // 如果没有时间范围,使用默认的dayCount |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(new Date()); |
| | | cal.set(Calendar.HOUR_OF_DAY, 0); |
| | | cal.set(Calendar.MINUTE, 0); |
| | | cal.set(Calendar.SECOND, 0); |
| | | cal.set(Calendar.MILLISECOND, 0); |
| | | cal.add(Calendar.DATE, 1 - dayCount); |
| | | Date defaultStartDate = cal.getTime(); |
| | | Date defaultEndDate = new Date(); |
| | | |
| | | taskingWrapper.ge("operation_record_time", defaultStartDate) |
| | | .le("operation_record_time", defaultEndDate); |
| | | } |
| | | |
| | | // 添加可选条件 |
| | | if (taskType != null && !taskType.isEmpty()) { |
| | | taskingWrapper.eq("task_type", taskType); |
| | | } |
| | | if (operationRecord != null && !operationRecord.isEmpty()) { |
| | | taskingWrapper.like("operation_record", operationRecord); |
| | | } |
| | | if (lineType != null && !lineType.isEmpty()) { |
| | | taskingWrapper.apply("operation_record REGEXP '.*[^0-9]" + lineType + "$'"); |
| | | } |
| | | |
| | | // 按时间排序 |
| | | taskingWrapper.orderByDesc("operation_record_time"); |
| | | |
| | | // 执行查询 |
| | | List<Map<String, Object>> taskingList = baseMapper.selectMaps(taskingWrapper); |
| | | |
| | | // 直接返回查询结果 |
| | | return new ArrayList<>(taskingList); |
| | | } catch (Exception e) { |
| | | log.error("查询异常", e); |
| | | throw e; |
| | | } |
| | | } |
| | | |
| | | public List<TaskingLog> findTaskingLog(){ |
| | | return new ArrayList<TaskingLog>(); |
| | | } |
| | |
| | | List<Map> list=kBBTJPDrawingBPMapper.selectMaps((QueryWrapper)queryWrapper); |
| | | |
| | | List<Map<String, Object>> listTasking1 = baseMapper.selectMaps(new QueryWrapper<TaskingLog>() |
| | | .select("operation_record,operation_mode,DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time,count(1) as count") |
| | | .select("task_type, operation_record, operation_mode, DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time, count(*) as count") |
| | | .eq("task_type", "定制") |
| | | .eq("operation_record", "旋转1") |
| | | .eq("operation_mode", "结束") |
| | | .gt("operation_record_time", startDate) |
| | | .groupBy("operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .groupBy("task_type", "operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .orderByAsc("DATE_FORMAT(operation_record_time, '%Y-%m-%d')")); |
| | | List<Map<String, Object>> listTasking2 = baseMapper.selectMaps(new QueryWrapper<TaskingLog>() |
| | | .select("operation_record,operation_mode,DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time,count(1) as count") |
| | | .select("task_type,operation_record,operation_mode,DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time,count(1) as count") |
| | | .eq("task_type", "定制") |
| | | .eq("operation_record", "旋转2") |
| | | .eq("operation_mode", "结束") |
| | | .gt("operation_record_time", startDate) |
| | | .groupBy("operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .groupBy("task_type", "operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .orderByAsc("DATE_FORMAT(operation_record_time, '%Y-%m-%d')")); |
| | | |
| | | //标准上片记录 |
| | | List<Map<String, Object>> loadTaskingList1 = baseMapper.selectMaps(new QueryWrapper<TaskingLog>() |
| | | .select("task_type, operation_record, operation_mode, DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time, count(*) as count") |
| | | .eq("task_type", "标准") |
| | | .eq("operation_record", "上片1") |
| | | .eq("operation_mode", "结束") |
| | | .gt("operation_record_time", startDate) |
| | | .groupBy("task_type", "operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .orderByAsc("DATE_FORMAT(operation_record_time, '%Y-%m-%d')")); |
| | | List<Map<String, Object>> loadTaskingList2 = baseMapper.selectMaps(new QueryWrapper<TaskingLog>() |
| | | .select("task_type, operation_record, operation_mode, DATE_FORMAT(operation_record_time, '%Y-%m-%d') as operation_record_time, count(*) as count") |
| | | .eq("task_type", "标准") |
| | | .eq("operation_record", "上片2") |
| | | .eq("operation_mode", "结束") |
| | | .gt("operation_record_time", startDate) |
| | | .groupBy("task_type", "operation_record", "operation_mode", "DATE_FORMAT(operation_record_time, '%Y-%m-%d')") |
| | | .orderByAsc("DATE_FORMAT(operation_record_time, '%Y-%m-%d')")); |
| | | |
| | | // 存储每条线路的数据 |
| | | Map<String, Map<String, Integer>> lineDataMap = new HashMap<>(); |
| | | lineDataMap.put("line1", new HashMap<>()); |
| | | lineDataMap.put("line2", new HashMap<>()); |
| | | |
| | | // 处理第一条线路数据 |
| | | // 处理旋转1结束记录 |
| | | for (Map<String, Object> map : listTasking1) { |
| | | String date = map.get("operation_record_time").toString(); |
| | | int count = Integer.parseInt(map.get("count").toString()); |
| | | Map<String, Integer> line1Map = lineDataMap.get("line1"); |
| | | line1Map.put(date, line1Map.getOrDefault(date, 0) + count); |
| | | } |
| | | // 处理线路1上片记录 |
| | | for (Map<String, Object> map : loadTaskingList1) { |
| | | String date = map.get("operation_record_time").toString(); |
| | | int count = Integer.parseInt(map.get("count").toString()); |
| | | Map<String, Integer> line1Map = lineDataMap.get("line1"); |
| | | line1Map.put(date, line1Map.getOrDefault(date, 0) + count); |
| | | } |
| | | |
| | | // 处理第二条线路数据 |
| | | // 处理旋转2结束记录 |
| | | for (Map<String, Object> map : listTasking2) { |
| | | String date = map.get("operation_record_time").toString(); |
| | | int count = Integer.parseInt(map.get("count").toString()); |
| | | Map<String, Integer> line2Map = lineDataMap.get("line2"); |
| | | line2Map.put(date, line2Map.getOrDefault(date, 0) + count); |
| | | } |
| | | // 处理线路2上片记录 |
| | | for (Map<String, Object> map : loadTaskingList2) { |
| | | String date = map.get("operation_record_time").toString(); |
| | | int count = Integer.parseInt(map.get("count").toString()); |
| | | Map<String, Integer> line2Map = lineDataMap.get("line2"); |
| | | line2Map.put(date, line2Map.getOrDefault(date, 0) + count); |
| | | } |
| | | |
| | | |
| | | //log.info("客户表计划量:{},{},{}",list,listTasking1,listTasking2); |
| | | List<Map> Result=new ArrayList<>(); |
| | | for (int i=0;i<dayCount;i++){ |
| | |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | String dateString = sdf.format(thisdate); |
| | | thisMap.put("date",dateString); |
| | | if (listTasking1.size()>0&&listTasking1.get(0).get("operation_record_time").toString().equals(dateString)){ |
| | | |
| | | thisMap.put("line1",listTasking1.get(0).get("count")); |
| | | listTasking1.remove(0); |
| | | }else{ |
| | | thisMap.put("line1",0); |
| | | } |
| | | if (listTasking2.size()>0&&listTasking2.get(0).get("operation_record_time").toString().equals(dateString)){ |
| | | thisMap.put("line2",listTasking2.get(0).get("count")); |
| | | listTasking2.remove(0); |
| | | }else{ |
| | | thisMap.put("line2",0); |
| | | } |
| | | // if(list.size()>0){ |
| | | // log.info("对比:{},{},{}", |
| | | // list.get(0).get("CreateDate"), |
| | | // dateString, |
| | | // list.get(0).get("CreateDate").toString().equals(dateString)); |
| | | // } |
| | | // 获取一线数据 |
| | | thisMap.put("line1", lineDataMap.get("line1").getOrDefault(dateString, 0)); |
| | | |
| | | // 获取二线数据 |
| | | thisMap.put("line2", lineDataMap.get("line2").getOrDefault(dateString, 0)); |
| | | |
| | | if (list.size()>0&&list.get(0).get("CreateDate").toString().equals(dateString)){ |
| | | |
| | | thisMap.put("plan",list.get(0).get("task_quantity_sum")); |
| | | list.remove(0); |
| | | }else{ |
| | |
| | | sendContent: '发送内容', |
| | | warehouse:'仓库', |
| | | notCompleteCount:'未完成量', |
| | | notCompleteArea:'未完成面积' |
| | | notCompleteArea:'未完成面积', |
| | | OrderNo:'订单号' |
| | | }, |
| | | machine: { |
| | | mechanicalArm:'自动上片机', |
| | |
| | | import 'element-plus/dist/index.css' |
| | | import zhCn from 'element-plus/dist/locale/zh-cn.mjs' |
| | | import VXETable from 'vxe-table' |
| | | import { VxeButton, VxeLoading, VxeTooltip } from 'vxe-pc-ui' |
| | | import 'vxe-table/lib/style.css' |
| | | import 'vxe-pc-ui/lib/style.css' |
| | | import i18n from '@/lang' |
| | | import Echarts from "vue-echarts" |
| | | import * as echarts from "echarts"; |
| | |
| | | app.use(VXETable) |
| | | app.use(pinia) |
| | | app.use(router) |
| | | app.use(VxeButton) |
| | | app.use(VxeLoading) |
| | | app.use(VxeTooltip) |
| | | // app.use(ElementPlus) |
| | | app.use(ElementPlus,{ |
| | | locale: zhCn, |
| | |
| | | path: 'KanbanDisplay2/kanbanDisplay2', |
| | | name: 'kanbanDisplay2', |
| | | component: () => import('../views/KanbanDisplay2/kanbanDisplay2.vue'), |
| | | props: true, |
| | | children: [ |
| | | { |
| | | path: '/KanbanDisplay2/kanbanDisplay2', |
| | | name: 'kanbanDisplay2', |
| | | component: () => import('../views/KanbanDisplay2/kanbanDisplay2.vue'), |
| | | props: true |
| | | } |
| | | ] |
| | | }, |
| | |
| | | ] |
| | | }, |
| | | { |
| | | /*----------- 报表 ----------------*/ |
| | | path: 'MechanicalReport/mechanicalReport', |
| | | name: 'mechanicalReport', |
| | | component: () => import('../views/MechanicalReport/mechanicalReport.vue'), |
| | | children: [ |
| | | { |
| | | path: '/MechanicalReport/mechanicalReport', |
| | | name: 'mechanicalReport', |
| | | component: () => import('../views/MechanicalReport/mechanicalReport.vue'), |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | /*----------- 设备状态 ----------------*/ |
| | | path: 'MechanicalMonitor/mechanicalMonitor', |
| | | name: 'mechanicalMonitor', |
| | |
| | | import { ref, onMounted, onBeforeUnmount } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import request from '@/utils/request' |
| | | import { useRoute, useRouter } from 'vue-router' |
| | | |
| | | const router = useRouter() |
| | | const route = useRoute() |
| | | |
| | | // 加载初始数据 |
| | | onMounted(() => { |
| | | // 从localStorage获取存储的目标值 |
| | | yieldTargetValue1.value = localStorage.getItem('yieldTarget1') ? Number(localStorage.getItem('yieldTarget1')) : 0 |
| | | yieldTargetValue2.value = localStorage.getItem('yieldTarget2') ? Number(localStorage.getItem('yieldTarget2')) : 0 |
| | | |
| | | utilizationTargetValue1.value = localStorage.getItem('utilizationTarget1') ? Number(localStorage.getItem('utilizationTarget1')) : 0 |
| | | utilizationTargetValue2.value = localStorage.getItem('utilizationTarget2') ? Number(localStorage.getItem('utilizationTarget2')) : 0 |
| | | |
| | | quantityTargetValue1.value = localStorage.getItem('quantityTarget1') ? Number(localStorage.getItem('quantityTarget1')) : 0 |
| | | quantityTargetValue2.value = localStorage.getItem('quantityTarget2') ? Number(localStorage.getItem('quantityTarget2')) : 0 |
| | | quantityTargetValue3.value = localStorage.getItem('quantityTarget3') ? Number(localStorage.getItem('quantityTarget3')) : 0 |
| | | |
| | | // 加载其他数据 |
| | | loadYieldData() |
| | | loadUtilizationData() |
| | | loadQuantityData() |
| | |
| | | lineNo: '', |
| | | yieldvalue: null |
| | | }) |
| | | const yieldTargetValue1 = ref() // 一线目标值 |
| | | const yieldTargetValue2 = ref() // 二线目标值 |
| | | const yieldData = ref([]) |
| | | const yieldLoading = ref(false) |
| | | |
| | |
| | | lineNo: '', |
| | | utilizationRate: null |
| | | }) |
| | | const utilizationTargetValue1 = ref() // 标准线目标值 |
| | | const utilizationTargetValue2 = ref() // 定制线目标值 |
| | | const utilizationData = ref([]) |
| | | const utilizationLoading = ref(false) |
| | | |
| | |
| | | locationCode: '', |
| | | quantity: null |
| | | }) |
| | | const quantityTargetValue1 = ref(4000) // 半成品目标值 |
| | | const quantityTargetValue2 = ref(4000) // 7014目标值 |
| | | const quantityTargetValue3 = ref(4000) // 7016目标值 |
| | | const quantityData = ref([]) |
| | | const quantityLoading = ref(false) |
| | | |
| | |
| | | } |
| | | |
| | | try { |
| | | const recordTimeStr = `${yieldFormData.value.recordDate} 00:00:00`; |
| | | const recordTimeStr = `${yieldFormData.value.recordDate} 00:00:00` |
| | | |
| | | await request({ |
| | | const res = await request({ |
| | | url: '/deviceInteraction/yield/addYield', |
| | | method: 'post', |
| | | data: { |
| | |
| | | recordTime: recordTimeStr |
| | | } |
| | | }) |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('添加成功') |
| | | resetYieldForm() |
| | | loadYieldData() // 刷新数据 |
| | | } else { |
| | | ElMessage.error(res.message || '添加失败') |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('添加失败') |
| | | console.error(error) |
| | |
| | | } |
| | | |
| | | try { |
| | | const recordTimeStr = `${utilizationFormData.value.recordDate} 00:00:00`; |
| | | const recordTimeStr = `${utilizationFormData.value.recordDate} 00:00:00` |
| | | |
| | | await request({ |
| | | const res = await request({ |
| | | url: '/deviceInteraction/utilization/addUtilization', |
| | | method: 'post', |
| | | data: { |
| | |
| | | recordTime: recordTimeStr |
| | | } |
| | | }) |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('添加成功') |
| | | resetUtilizationForm() |
| | | loadUtilizationData() // 刷新数据 |
| | | } else { |
| | | ElMessage.error(res.message || '添加失败') |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('添加失败') |
| | | console.error(error) |
| | |
| | | } |
| | | |
| | | try { |
| | | // 拼接日期时间字符串,确保是当天的00:00:00 |
| | | const dateStr = quantityFormData.value.recordDate; |
| | | const recordTimeStr = `${dateStr} 00:00:00`; |
| | | const recordTimeStr = `${quantityFormData.value.recordDate} 00:00:00` |
| | | |
| | | |
| | | const locationCode = quantityFormData.value.locationCode; |
| | | |
| | | await request({ |
| | | const res = await request({ |
| | | url: '/deviceInteraction/quantity/addQuantity', |
| | | method: 'post', |
| | | data: { |
| | |
| | | recordTime: recordTimeStr |
| | | } |
| | | }) |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('添加成功') |
| | | resetQuantityForm() |
| | | loadQuantityData() // 刷新数据 |
| | | } else { |
| | | ElMessage.error(res.message || '添加失败') |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('添加失败') |
| | | console.error(error) |
| | |
| | | // 重置表单 |
| | | const resetYieldForm = () => { |
| | | yieldFormData.value = { |
| | | recordDate: yieldFormData.value.recordDate, // 保持当前选择的日期 |
| | | recordDate: yieldFormData.value.recordDate, |
| | | lineNo: '', |
| | | yieldvalue: null |
| | | } |
| | |
| | | |
| | | const resetUtilizationForm = () => { |
| | | utilizationFormData.value = { |
| | | recordDate: utilizationFormData.value.recordDate, // 保持当前选择的日期 |
| | | recordDate: utilizationFormData.value.recordDate, |
| | | lineNo: '', |
| | | utilizationRate: null |
| | | } |
| | |
| | | |
| | | const resetQuantityForm = () => { |
| | | quantityFormData.value = { |
| | | recordDate: quantityFormData.value.recordDate, // 保持当前选择的日期 |
| | | recordDate: quantityFormData.value.recordDate, |
| | | locationCode: '', |
| | | quantity: null |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // 修改设置目标值的方法 |
| | | const setYieldTarget = () => { |
| | | // 更新产量目标值并保存到localStorage |
| | | localStorage.setItem('yieldTarget1', yieldTargetValue1.value.toString()) |
| | | localStorage.setItem('yieldTarget2', yieldTargetValue2.value.toString()) |
| | | ElMessage.success('目标值设置成功') |
| | | } |
| | | |
| | | const setUtilizationTarget = () => { |
| | | // 更新利用率目标值并保存到localStorage |
| | | localStorage.setItem('utilizationTarget1', utilizationTargetValue1.value.toString()) |
| | | localStorage.setItem('utilizationTarget2', utilizationTargetValue2.value.toString()) |
| | | ElMessage.success('目标值设置成功') |
| | | } |
| | | |
| | | const setQuantityTarget = () => { |
| | | // 更新在制量目标值并保存到localStorage |
| | | localStorage.setItem('quantityTarget1', quantityTargetValue1.value.toString()) |
| | | localStorage.setItem('quantityTarget2', quantityTargetValue2.value.toString()) |
| | | localStorage.setItem('quantityTarget3', quantityTargetValue3.value.toString()) |
| | | ElMessage.success('目标值设置成功') |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | |
| | | <el-tabs v-model="activeTab"> |
| | | <!-- 单小时产量标签页 --> |
| | | <el-tab-pane label="单小时产量" name="yield"> |
| | | <!-- 添加目标值设置部分 --> |
| | | <div class="target-setting"> |
| | | <el-form :inline="true" label-width="100px"> |
| | | <el-form-item label="一线目标值"> |
| | | <el-input-number |
| | | v-model="yieldTargetValue1" |
| | | :precision="0" |
| | | :step="100" |
| | | :min="0" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="二线目标值"> |
| | | <el-input-number |
| | | v-model="yieldTargetValue2" |
| | | :precision="0" |
| | | :step="100" |
| | | :min="0" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="setYieldTarget">设置目标值</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <el-form :inline="true" :model="yieldFormData" label-width="100px" class="form-container"> |
| | | <el-form-item label="日期"> |
| | | <el-date-picker |
| | |
| | | |
| | | <!-- 利用率标签页 --> |
| | | <el-tab-pane label="利用率" name="utilization"> |
| | | <!-- 添加目标值设置部分 --> |
| | | <div class="target-setting"> |
| | | <el-form :inline="true" label-width="100px"> |
| | | <el-form-item label="标准线目标值"> |
| | | <el-input-number |
| | | v-model="utilizationTargetValue1" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | :max="100" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="定制线目标值"> |
| | | <el-input-number |
| | | v-model="utilizationTargetValue2" |
| | | :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="setUtilizationTarget">设置目标值</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <el-form :inline="true" :model="utilizationFormData" label-width="100px" class="form-container"> |
| | | <el-form-item label="日期"> |
| | | <el-date-picker |
| | |
| | | |
| | | <!-- 在制量标签页 --> |
| | | <el-tab-pane label="在制量" name="quantity"> |
| | | <!-- 添加目标值设置部分 --> |
| | | <div class="target-setting"> |
| | | <el-form :inline="true" label-width="100px"> |
| | | <el-form-item label="半成品目标值"> |
| | | <el-input-number |
| | | v-model="quantityTargetValue1" |
| | | :precision="0" |
| | | :step="100" |
| | | :min="0" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="7014目标值"> |
| | | <el-input-number |
| | | v-model="quantityTargetValue2" |
| | | :precision="0" |
| | | :step="100" |
| | | :min="0" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="7016目标值"> |
| | | <el-input-number |
| | | v-model="quantityTargetValue3" |
| | | :precision="0" |
| | | :step="100" |
| | | :min="0" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="setQuantityTarget">设置目标值</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <el-form :inline="true" :model="quantityFormData" label-width="100px" class="form-container"> |
| | | <el-form-item label="日期"> |
| | | <el-date-picker |
| | |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .target-setting { |
| | | margin-bottom: 20px; |
| | | background-color: #f5f7fa; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .form-container { |
| | | margin-bottom: 20px; |
| | | background-color: #f5f7fa; |
| | |
| | | <script setup> |
| | | import { ref, onMounted, onUnmounted, nextTick } from 'vue' |
| | | import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue' |
| | | import * as echarts from 'echarts' |
| | | import request from '@/utils/request' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const route = useRoute() |
| | | const dashboardRef = ref(null) |
| | | const standardWidth = 2220 // 设计稿标准宽度 |
| | | const standardHeight = 1224 // 设计稿标准高度, |
| | | const standardHeight = 1224 // 设计稿标准高度 |
| | | |
| | | // 从路由参数中获取目标值 |
| | | const yieldTarget1 = ref(Number(localStorage.getItem('yieldTarget1')) || Number(route.query.yieldTarget1) || 0) |
| | | const yieldTarget2 = ref(Number(localStorage.getItem('yieldTarget2')) || Number(route.query.yieldTarget2) || 0) |
| | | const utilizationTarget1 = ref(Number(localStorage.getItem('utilizationTarget1')) || Number(route.query.utilizationTarget1) || 0) |
| | | const utilizationTarget2 = ref(Number(localStorage.getItem('utilizationTarget2')) || Number(route.query.utilizationTarget2) || 0) |
| | | const quantityTarget1 = ref(Number(localStorage.getItem('quantityTarget1')) || Number(route.query.quantityTarget1) || 0) |
| | | const quantityTarget2 = ref(Number(localStorage.getItem('quantityTarget2')) || Number(route.query.quantityTarget2) || 0) |
| | | const quantityTarget3 = ref(Number(localStorage.getItem('quantityTarget3')) || Number(route.query.quantityTarget3) || 0) |
| | | |
| | | // 监听路由参数变化 |
| | | watch(() => route.query, (newQuery) => { |
| | | if (newQuery.yieldTarget1) { |
| | | yieldTarget1.value = Number(newQuery.yieldTarget1) |
| | | localStorage.setItem('yieldTarget1', newQuery.yieldTarget1) |
| | | updateOptionYield(yieldTarget1.value, yieldTarget2.value) |
| | | } |
| | | if (newQuery.yieldTarget2) { |
| | | yieldTarget2.value = Number(newQuery.yieldTarget2) |
| | | localStorage.setItem('yieldTarget2', newQuery.yieldTarget2) |
| | | updateOptionYield(yieldTarget1.value, yieldTarget2.value) |
| | | } |
| | | if (newQuery.utilizationTarget1) { |
| | | utilizationTarget1.value = Number(newQuery.utilizationTarget1) |
| | | localStorage.setItem('utilizationTarget1', newQuery.utilizationTarget1) |
| | | updateOptionUtilization(utilizationTarget1.value, utilizationTarget2.value) |
| | | } |
| | | if (newQuery.utilizationTarget2) { |
| | | utilizationTarget2.value = Number(newQuery.utilizationTarget2) |
| | | localStorage.setItem('utilizationTarget2', newQuery.utilizationTarget2) |
| | | updateOptionUtilization(utilizationTarget1.value, utilizationTarget2.value) |
| | | } |
| | | if (newQuery.quantityTarget1) { |
| | | quantityTarget1.value = Number(newQuery.quantityTarget1) |
| | | localStorage.setItem('quantityTarget1', newQuery.quantityTarget1) |
| | | updateOptionQuantity(quantityTarget1.value, quantityTarget2.value, quantityTarget3.value) |
| | | } |
| | | if (newQuery.quantityTarget2) { |
| | | quantityTarget2.value = Number(newQuery.quantityTarget2) |
| | | localStorage.setItem('quantityTarget2', newQuery.quantityTarget2) |
| | | updateOptionQuantity(quantityTarget1.value, quantityTarget2.value, quantityTarget3.value) |
| | | } |
| | | if (newQuery.quantityTarget3) { |
| | | quantityTarget3.value = Number(newQuery.quantityTarget3) |
| | | localStorage.setItem('quantityTarget3', newQuery.quantityTarget3) |
| | | updateOptionQuantity(quantityTarget1.value, quantityTarget2.value, quantityTarget3.value) |
| | | } |
| | | }, { deep: true }) |
| | | |
| | | // 计算缩放比例并应用 |
| | | const setScale = () => { |
| | |
| | | }); |
| | | if (res.code === 200) { |
| | | yieldData.value = res.data; |
| | | updateOptionYield(); |
| | | updateOptionYield(yieldTarget1.value, yieldTarget2.value); |
| | | } |
| | | } catch (error) { |
| | | console.error('获取单小时产量数据失败:', error); |
| | |
| | | }); |
| | | if (res.code === 200) { |
| | | utilizationData.value = res.data; |
| | | updateOptionUtilization(); |
| | | updateOptionUtilization(utilizationTarget1.value, utilizationTarget2.value); |
| | | } |
| | | } catch (error) { |
| | | console.error('获取利用率数据失败:', error); |
| | |
| | | }); |
| | | if (res.code === 200) { |
| | | quantityData.value = res.data; |
| | | updateOptionQuantity(); |
| | | updateOptionQuantity(quantityTarget1.value, quantityTarget2.value, quantityTarget3.value); |
| | | } |
| | | } catch (error) { |
| | | console.error('获取在制量数据失败:', error); |
| | |
| | | draw('drawLineChart_day51', OptionDayMode) |
| | | } |
| | | |
| | | const updateOptionYield = () => { |
| | | const updateOptionYield = (targetValue1, targetValue2) => { |
| | | // 按日期排序并处理数据 |
| | | const sortedData = [...yieldData.value].sort((a, b) => |
| | | new Date(a.recordTime) - new Date(b.recordTime) |
| | |
| | | |
| | | // 单小时产量的配置 - 分上下两个子图表 |
| | | const OptionYield = { |
| | | title: { |
| | | title: [ |
| | | { |
| | | text: '单小时产量', |
| | | textStyle: { |
| | | fontSize: 20, |
| | |
| | | color: 'white' |
| | | } |
| | | }, |
| | | { |
| | | text: '目标' + targetValue1, |
| | | bottom: 140, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | { |
| | | text: '目标' + targetValue2, |
| | | bottom: 35, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | ], |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | |
| | | x: 'left', |
| | | y: 'center', |
| | | orient: 'vertical', |
| | | itemGap: 90, |
| | | textStyle: { |
| | | fontSize: 20, |
| | | fontWeight: 'bold', |
| | | color: 'white', |
| | | color: 'white' |
| | | } |
| | | }, |
| | | grid: [{ |
| | |
| | | areaStyle: { |
| | | color: '#000000', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue1, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | |
| | | areaStyle: { |
| | | color: 'white', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue2, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | |
| | | draw('drawLineChart_yield', OptionYield) |
| | | } |
| | | |
| | | const updateOptionUtilization = () => { |
| | | const updateOptionUtilization = (targetValue1, targetValue2) => { |
| | | // 按日期排序并处理数据 |
| | | const sortedData = [...utilizationData.value].sort((a, b) => |
| | | new Date(a.recordTime || a.recordDate) - new Date(b.recordTime || b.recordDate) |
| | |
| | | |
| | | // 利用率的配置 - 分上下两个子图表 |
| | | const OptionUtilization = { |
| | | title: { |
| | | title: [ |
| | | { |
| | | text: '利用率', |
| | | textStyle: { |
| | | fontSize: 20, |
| | |
| | | color: 'white' |
| | | } |
| | | }, |
| | | { |
| | | text: '目标' + targetValue1 + '%', |
| | | bottom: 140, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | { |
| | | text: '目标' + targetValue2 + '%', |
| | | bottom: 35, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | ], |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | |
| | | x: 'left', |
| | | y: 'center', |
| | | orient: 'vertical', |
| | | itemGap: 90, |
| | | textStyle: { |
| | | fontSize: 20, |
| | | fontWeight: 'bold', |
| | |
| | | areaStyle: { |
| | | color: '#000000', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue1, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | |
| | | areaStyle: { |
| | | color: 'white', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue2, |
| | | name: "line", |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | |
| | | |
| | | } |
| | | |
| | | const updateOptionQuantity = () => { |
| | | const updateOptionQuantity = (targetValue1, targetValue2, targetValue3) => { |
| | | // 按日期排序并处理数据 |
| | | |
| | | const sortedData = [...quantityData.value].sort((a, b) => |
| | | new Date(a.recordTime || a.recordDate) - new Date(b.recordTime || b.recordDate) |
| | | ); |
| | |
| | | |
| | | // 在制量的配置 - 上中下三层布局 |
| | | const OptionQuantity = { |
| | | title: { |
| | | title: [{ |
| | | text: '在制量', |
| | | textStyle: { |
| | | fontSize: 20, |
| | |
| | | color: 'white' |
| | | } |
| | | }, |
| | | { |
| | | text: '目标' + targetValue1, |
| | | bottom: 160, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | { |
| | | text: '目标' + targetValue2, |
| | | bottom: 95, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | { |
| | | text: '目标' + targetValue3, |
| | | bottom: 20, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 17 |
| | | }, |
| | | }, |
| | | ], |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | |
| | | x: 'left', |
| | | y: 'center', |
| | | orient: 'vertical', |
| | | itemGap: 50, |
| | | textStyle: { |
| | | fontSize: 20, |
| | | fontWeight: 'bold', |
| | |
| | | areaStyle: { |
| | | color: '#91cc75', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue1, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | |
| | | areaStyle: { |
| | | color: '#000000', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue2, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | |
| | | areaStyle: { |
| | | color: 'white', |
| | | opacity: 0.3 |
| | | }, |
| | | markLine: { |
| | | data: [ |
| | | { |
| | | yAxis: targetValue3, |
| | | name: 'Line', |
| | | label: { |
| | | formatter: '', |
| | | }, |
| | | lineStyle: { |
| | | width: 2, |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | ] |
| | |
| | | window.addEventListener('resize', handleResize) |
| | | |
| | | // 确保DOM加载完成后再初始化图表 |
| | | nextTick(() => { |
| | | loadNotCompleteData(); |
| | | loadYieldData(); |
| | | loadUtilizationData(); |
| | | loadInventoryData(); |
| | | loadPlannedData(); |
| | | }); |
| | | nextTick(async () => { |
| | | try { |
| | | // 从localStorage中获取目标值,如果没有则从路由参数获取,都没有则使用默认值0 |
| | | yieldTarget1.value = Number(localStorage.getItem('yieldTarget1')) || Number(route.query.yieldTarget1) || 0 |
| | | yieldTarget2.value = Number(localStorage.getItem('yieldTarget2')) || Number(route.query.yieldTarget2) || 0 |
| | | utilizationTarget1.value = Number(localStorage.getItem('utilizationTarget1')) || Number(route.query.utilizationTarget1) || 0 |
| | | utilizationTarget2.value = Number(localStorage.getItem('utilizationTarget2')) || Number(route.query.utilizationTarget2) || 0 |
| | | quantityTarget1.value = Number(localStorage.getItem('quantityTarget1')) || Number(route.query.quantityTarget1) || 0 |
| | | quantityTarget2.value = Number(localStorage.getItem('quantityTarget2')) || Number(route.query.quantityTarget2) || 0 |
| | | quantityTarget3.value = Number(localStorage.getItem('quantityTarget3')) || Number(route.query.quantityTarget3) || 0 |
| | | |
| | | // 设置定时刷新 |
| | | const refreshInterval = setInterval(() => { |
| | | loadYieldData(); |
| | | loadUtilizationData(); |
| | | loadInventoryData(); |
| | | loadPlannedData(); |
| | | console.log('数据已刷新'); |
| | | }, 30000); // 每分钟刷新一次 |
| | | // 按顺序加载数据 |
| | | await loadNotCompleteData() |
| | | await loadYieldData() |
| | | await loadUtilizationData() |
| | | await loadInventoryData() |
| | | await loadPlannedData() |
| | | |
| | | // 设置定时刷新数据 |
| | | const refreshInterval = setInterval(async () => { |
| | | try { |
| | | await loadYieldData() |
| | | await loadUtilizationData() |
| | | await loadInventoryData() |
| | | await loadPlannedData() |
| | | console.log('数据已刷新') |
| | | } catch (error) { |
| | | console.error('数据刷新失败:', error) |
| | | } |
| | | }, 15000) // 每15秒刷新一次 |
| | | |
| | | // 添加监听localStorage变化的定时器 |
| | | const checkTargetsInterval = setInterval(() => { |
| | | const newYieldTarget1 = Number(localStorage.getItem('yieldTarget1')) |
| | | const newYieldTarget2 = Number(localStorage.getItem('yieldTarget2')) |
| | | const newUtilizationTarget1 = Number(localStorage.getItem('utilizationTarget1')) |
| | | const newUtilizationTarget2 = Number(localStorage.getItem('utilizationTarget2')) |
| | | const newQuantityTarget1 = Number(localStorage.getItem('quantityTarget1')) |
| | | const newQuantityTarget2 = Number(localStorage.getItem('quantityTarget2')) |
| | | const newQuantityTarget3 = Number(localStorage.getItem('quantityTarget3')) |
| | | |
| | | // 检查目标值是否有变化 |
| | | if (newYieldTarget1 !== yieldTarget1.value || newYieldTarget2 !== yieldTarget2.value) { |
| | | yieldTarget1.value = newYieldTarget1 |
| | | yieldTarget2.value = newYieldTarget2 |
| | | updateOptionYield(newYieldTarget1, newYieldTarget2) |
| | | } |
| | | if (newUtilizationTarget1 !== utilizationTarget1.value || newUtilizationTarget2 !== utilizationTarget2.value) { |
| | | utilizationTarget1.value = newUtilizationTarget1 |
| | | utilizationTarget2.value = newUtilizationTarget2 |
| | | updateOptionUtilization(newUtilizationTarget1, newUtilizationTarget2) |
| | | } |
| | | if (newQuantityTarget1 !== quantityTarget1.value || |
| | | newQuantityTarget2 !== quantityTarget2.value || |
| | | newQuantityTarget3 !== quantityTarget3.value) { |
| | | quantityTarget1.value = newQuantityTarget1 |
| | | quantityTarget2.value = newQuantityTarget2 |
| | | quantityTarget3.value = newQuantityTarget3 |
| | | updateOptionQuantity(newQuantityTarget1, newQuantityTarget2, newQuantityTarget3) |
| | | } |
| | | }, 1000) // 每秒检查一次 |
| | | |
| | | onUnmounted(() => { |
| | | clearInterval(refreshInterval); |
| | | }); |
| | | clearInterval(refreshInterval) |
| | | clearInterval(checkTargetsInterval) |
| | | }) |
| | | } catch (error) { |
| | | console.error('初始化数据失败:', error) |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | window.removeEventListener('resize', handleResize) |
| | | // 清理所有图表实例 |
| | | charts.forEach(chart => { |
| | | if (chart && !chart.isDisposed()) { |
| | | chart.dispose() |
| | | } |
| | | }) |
| | | charts.length = 0 |
| | | }) |
| | | |
| | | </script> |
| | |
| | | 总计划量-片数、平方</div> |
| | | <div id="textDay" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">日期:</div> |
| | | <br> |
| | | <div id="textprice" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">片数:</div> |
| | | <div id="textarea" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">平方数:</div> |
| | | <div id="textprice" style="font-size: 20px;height: 30px;margin-left: 20px;margin-top: 20px;">片数:</div> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | |
| | | <script> |
| | | export default { |
| | | mounted() { |
| | | |
| | | const OptionYear = { |
| | | data() { |
| | | return { |
| | | timer: null, |
| | | OptionYear: { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | |
| | | } |
| | | } |
| | | }, |
| | | title: { |
| | | text: '已完成 已完成', |
| | | left: '48%', |
| | | bottom: 0, // |
| | | textStyle: { |
| | | color: 'white', |
| | | fontSize: 16 |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ['计划量', '一线', '二线'], |
| | | icon: 'roundRect', |
| | | itemGap: 50, |
| | | y:'bottom', |
| | | itemGap: 90, |
| | | y: '80%', |
| | | 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%', |
| | |
| | | axisLabel: { |
| | | fontSize: 20, |
| | | interval: 'auto', |
| | | margin: 15, |
| | | formatter: (value, index) => { |
| | | // 如果是日期格式 |
| | | if (value.includes('-')) { |
| | |
| | | fontSize: 20, |
| | | color: 'white' // 设置 x 轴名称颜色为白色 |
| | | }, |
| | | position: 'top' |
| | | position: 'top', |
| | | offset: 15 // 调整 x 轴标签的位置 |
| | | } |
| | | ], |
| | | yAxis: [ |
| | |
| | | formatter: (params) => params.value, |
| | | color: 'white', |
| | | position: 'top' |
| | | }, |
| | | } |
| | | }, |
| | | { |
| | | name: '二线', |
| | |
| | | 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; |
| | | // console.log("获取当日产量",modeOptions); |
| | | // 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; |
| | | const modeOptions2 = [res.data[res.data.length - 1]]; |
| | | // this.drawDay('drawLineChart_day11', OptionYear, modeOptions); |
| | | //this.drawDay('drawLineChart_day31', OptionYear, modeOptions); |
| | | // this.drawYear('drawLineChart_day51', OptionDayMode, modeOptions); |
| | | this.drawDay('drawLineChart_day11', OptionYear, modeOptions2); |
| | | } 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); |
| | | // } |
| | | // }); |
| | | |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.fetchData(); |
| | | // 每半分钟刷新一次数据 |
| | | this.timer = setInterval(() => { |
| | | this.fetchData(); |
| | | }, 30000); |
| | | }, |
| | | beforeDestroy() { |
| | | if (this.timer) { |
| | | clearInterval(this.timer); |
| | | } |
| | | }, |
| | | methods: { |
| | | draw(name, Option) { |
| | |
| | | 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 }); |
| | |
| | | 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.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); |
| | | // }, |
| | | |
| | | fetchData() { |
| | | // 请求日产量-月 |
| | | request.post('/deviceInteraction/primitiveTask/findDailyOutput', { |
| | | "dayCount": 30 |
| | | }).then((res) => { |
| | | if (res.code == 200) { |
| | | const modeOptions = res.data; |
| | | const modeOptions2 = [res.data[res.data.length - 1]]; |
| | | this.drawDay('drawLineChart_day11', this.OptionYear, modeOptions2); |
| | | } else { |
| | | console.error('请求日产量-月数据失败:', res); |
| | | } |
| | | }).catch((error) => { |
| | | console.error('请求数据时发生错误:', error); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
New file |
| | |
| | | <script setup> |
| | | import { ref, onMounted, reactive, onUnmounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import request from '@/utils/request' |
| | | |
| | | const timer = ref(null) |
| | | const xGrid = ref() |
| | | const tableData = ref([]) |
| | | const loading = ref(false) |
| | | |
| | | // 筛选条件 |
| | | const filterForm = ref({ |
| | | startDate: null, |
| | | endDate: null, |
| | | taskType: '', |
| | | operationRecord: '', |
| | | lineType: '' |
| | | }) |
| | | |
| | | // 获取本月第一天和最后一天 |
| | | const getCurrentMonthRange = () => { |
| | | const now = new Date() |
| | | const firstDay = new Date(now.getFullYear(), now.getMonth(), 1) |
| | | const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0) |
| | | return { |
| | | startDate: formatDate(firstDay), |
| | | endDate: formatDate(lastDay) |
| | | } |
| | | } |
| | | |
| | | // 格式化日期为 yyyy-MM-dd HH:mm:ss |
| | | const formatDate = (date, isEndDate = false) => { |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | const time = isEndDate ? '23:59:59' : '00:00:00' |
| | | return `${year}-${month}-${day} ${time}` |
| | | } |
| | | |
| | | // 格式化表格中的时间显示 |
| | | const formatTableDateTime = ({ cellValue }) => { |
| | | if (!cellValue) return '' |
| | | try { |
| | | // 处理ISO格式的时间字符串 |
| | | const date = new Date(cellValue) |
| | | if (isNaN(date.getTime())) return cellValue |
| | | |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | const hours = String(date.getHours()).padStart(2, '0') |
| | | const minutes = String(date.getMinutes()).padStart(2, '0') |
| | | const seconds = String(date.getSeconds()).padStart(2, '0') |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
| | | } catch (error) { |
| | | console.error('日期格式化错误:', error) |
| | | return cellValue |
| | | } |
| | | } |
| | | |
| | | // 添加日期选择的限制逻辑 |
| | | const validateDateRange = (startDate, endDate) => { |
| | | if (!startDate || !endDate) return true |
| | | |
| | | const start = new Date(startDate) |
| | | const end = new Date(endDate) |
| | | |
| | | // 计算两个日期之间的毫秒差 |
| | | const diffTime = Math.abs(end - start) |
| | | // 转换为天数 |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) |
| | | |
| | | // 检查是否超过31天 |
| | | return diffDays <= 31 |
| | | } |
| | | |
| | | const gridOptions = reactive({ |
| | | border: true, |
| | | height: '500px', |
| | | showOverflow: true, |
| | | loading: loading, |
| | | exportConfig: {}, |
| | | columnConfig: { |
| | | resizable: true |
| | | }, |
| | | toolbarConfig: |
| | | { |
| | | print: true, |
| | | export: true, |
| | | custom: true, |
| | | zoom: true |
| | | }, |
| | | columns: [ |
| | | { type: 'seq', width: 60, title: '序号' }, |
| | | { field: 'glass_id', title: '玻璃ID', width: 120 }, |
| | | { field: 'batch_number', title: '批次号', width: 120 }, |
| | | { field: 'scan_id', title: '扫描ID', width: 120 }, |
| | | { field: 'operation_record_time', title: '操作时间', width: 180, formatter: formatTableDateTime }, |
| | | { field: 'task_type', title: '类型', width: 100 }, |
| | | { field: 'operation_record', title: '设备名称', width: 120 }, |
| | | { field: 'operation_mode', title: '操作模式', width: 100 }, |
| | | { field: 'drawing_marking', title: '图纸标记', width: 120 }, |
| | | { field: 'state', title: '状态', width: 100 }, |
| | | { field: 'work_state', title: '工作状态', width: 100 }, |
| | | { field: 'glass_state', title: '玻璃状态', width: 100 }, |
| | | { field: 'line_configuration_id', title: '产线ID', width: 100 }, |
| | | { field: 'is_marking', title: '是否标记', width: 100 }, |
| | | { field: 'is_send', title: '发送状态', width: 100 }, |
| | | { field: 'is_silk_screen', title: '是否丝印', width: 100 }, |
| | | { field: 'length', title: '长度', width: 100 }, |
| | | { field: 'width', title: '宽度', width: 100 }, |
| | | { field: 'thickness', title: '厚度', width: 100 }, |
| | | { field: 'program_id', title: '程序ID', width: 120 }, |
| | | { field: 'silk_screen_x', title: '丝印X', width: 100 }, |
| | | { field: 'silk_screen_y', title: '丝印Y', width: 100 }, |
| | | { field: 'task_quantity', title: '任务数量', width: 100 }, |
| | | { field: 'task_sequence', title: '任务序列', width: 100 } |
| | | ], |
| | | data: tableData |
| | | }) |
| | | |
| | | // 获取数据 |
| | | const fetchData = async () => { |
| | | loading.value = true |
| | | try { |
| | | if (!filterForm.value.startDate || !filterForm.value.endDate) { |
| | | ElMessage.warning('请选择时间范围') |
| | | loading.value = false |
| | | return |
| | | } |
| | | |
| | | // 验证日期范围 |
| | | if (!validateDateRange(filterForm.value.startDate, filterForm.value.endDate)) { |
| | | ElMessage.warning('时间范围不能超过一个月') |
| | | loading.value = false |
| | | return |
| | | } |
| | | |
| | | const startDate = formatDate(new Date(filterForm.value.startDate), false) // 开始日期使用 00:00:00 |
| | | const endDate = formatDate(new Date(filterForm.value.endDate), true) // 结束日期使用 23:59:59 |
| | | |
| | | const params = { |
| | | dayCount: 0, |
| | | startDate: startDate, |
| | | endDate: endDate, |
| | | taskType: filterForm.value.taskType || null, |
| | | operationRecord: filterForm.value.operationRecord || null, |
| | | lineType: filterForm.value.lineType || null |
| | | } |
| | | |
| | | const response = await request({ |
| | | url: '/deviceInteraction/taskingLog/mechanicalReport', |
| | | method: 'post', |
| | | params: params |
| | | }) |
| | | |
| | | if (response && response.code === 200) { |
| | | if (Array.isArray(response.data)) { |
| | | //console.log('设置表格数据:', response.data) |
| | | gridOptions.data = response.data |
| | | } else { |
| | | gridOptions.data = [] |
| | | ElMessage.warning('暂无数据') |
| | | } |
| | | } else { |
| | | gridOptions.data = [] |
| | | ElMessage.error(response?.message || '查询失败') |
| | | } |
| | | } catch (error) { |
| | | console.error('获取数据失败:', error) |
| | | ElMessage.error('获取数据失败:' + (error.message || '未知错误')) |
| | | gridOptions.data = [] |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 重置筛选条件 |
| | | const resetFilter = () => { |
| | | const today = new Date() |
| | | const firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1) |
| | | |
| | | filterForm.value = { |
| | | startDate: formatDate(firstDayOfMonth), |
| | | endDate: formatDate(today), |
| | | taskType: '', |
| | | operationRecord: '', |
| | | lineType: '' |
| | | } |
| | | fetchData() |
| | | } |
| | | |
| | | // 限制结束日期不能超过开始日期一个月 |
| | | const disabledEndDate = (time) => { |
| | | if (!filterForm.value.startDate) { |
| | | return false |
| | | } |
| | | const startDate = new Date(filterForm.value.startDate) |
| | | const oneMonthLater = new Date(startDate) |
| | | oneMonthLater.setMonth(oneMonthLater.getMonth() + 1) |
| | | return time.getTime() > oneMonthLater.getTime() |
| | | } |
| | | |
| | | // 限制开始日期不能离结束日期超过一个月 |
| | | const disabledStartDate = (time) => { |
| | | if (!filterForm.value.endDate) { |
| | | return false |
| | | } |
| | | const endDate = new Date(filterForm.value.endDate) |
| | | const oneMonthEarlier = new Date(endDate) |
| | | oneMonthEarlier.setMonth(oneMonthEarlier.getMonth() - 1) |
| | | return time.getTime() < oneMonthEarlier.getTime() |
| | | } |
| | | |
| | | // 页面加载时获取数据 |
| | | onMounted(() => { |
| | | resetFilter() |
| | | // 每分钟刷新一次数据 |
| | | timer.value = setInterval(fetchData, 60000) |
| | | }) |
| | | |
| | | // 页面卸载时清除定时器 |
| | | onUnmounted(() => { |
| | | if (timer.value) { |
| | | clearInterval(timer.value) |
| | | } |
| | | }) |
| | | |
| | | |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="mechanical-report"> |
| | | <!-- 筛选条件 --> |
| | | <el-card class="filter-card"> |
| | | <el-form :inline="true" :model="filterForm" class="filter-form"> |
| | | <el-form-item label="开始日期" required> |
| | | <el-date-picker v-model="filterForm.startDate" type="date" placeholder="选择开始日期" format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" :disabledDate="disabledStartDate" /> |
| | | </el-form-item> |
| | | <el-form-item label="结束日期" required> |
| | | <el-date-picker v-model="filterForm.endDate" type="date" placeholder="选择结束日期" format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" :disabledDate="disabledEndDate" /> |
| | | </el-form-item> |
| | | <el-form-item label="类型"> |
| | | <el-select v-model="filterForm.taskType" placeholder="请选择类型" style="width: 100px;" clearable> |
| | | <el-option label="全部" value="" /> |
| | | <el-option label="定制" value="定制" /> |
| | | <el-option label="标准" value="标准" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设备名称"> |
| | | <el-select v-model="filterForm.operationRecord" placeholder="请选择设备" style="width: 100px;" clearable> |
| | | <el-option label="全部" value="" /> |
| | | <el-option label="上片" value="上片" /> |
| | | <el-option label="磨边" value="磨边" /> |
| | | <el-option label="翻片" value="翻片" /> |
| | | <el-option label="打标" value="打标" /> |
| | | <el-option label="丝印" value="丝印" /> |
| | | <el-option label="旋转" value="旋转" /> |
| | | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="生产线"> |
| | | <el-select v-model="filterForm.lineType" placeholder="请选择生产线" style="width: 100px;" clearable> |
| | | <el-option label="全部" value="" /> |
| | | <el-option label="一线" value="1" /> |
| | | <el-option label="二线" value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="fetchData">查询</el-button> |
| | | <el-button @click="resetFilter">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- 数据表格 --> |
| | | <el-card class="table-card"> |
| | | <vxe-grid v-bind="gridOptions"></vxe-grid> |
| | | <div class="total-info"> |
| | | <el-tag type="info" style="font-size: 22px; padding: 8px 16px;">总数量: {{ gridOptions.data.length }}</el-tag> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .mechanical-report { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .filter-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .filter-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .table-card { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .total-info { |
| | | margin-top: 2px; |
| | | display: left; |
| | | padding-right: 20px; |
| | | font-weight: bold; |
| | | } |
| | | </style> |