zhoushihao
2025-10-27 636bd027a92d4bf669410ee550a5ca6324f72c88
Merge remote-tracking branch 'origin/master'
16个文件已修改
7个文件已添加
1098 ■■■■ 已修改文件
UI-Project/src/lang/zh.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/utils/constants.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/EngineerScheduling/engineerScheduling.vue 670 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/controller/EngineerSchedulingController.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/entity/EngineerScheduling.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/mapper/EngineerSchedulingMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/mapper/xml/EngineerSchedulingMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/service/EngineerSchedulingService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/service/impl/EngineerSchedulingServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/controller/OptimizeProjectController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeProject.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/dto/ProgressDTO.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeProjectMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeProjectService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeProjectServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/resources/mapper/OptimizeProjectMapper.xml 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/mapper/BigStorageCageDetailsMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/mapper/BigStorageCageDetailsMapper.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/zh.js
@@ -559,7 +559,6 @@
        hollownumber: '中空总数量',
        hollowEngineer: '中空工程',
        hollowarea: '中空总面积',
        hollowtotal: '中空总时间',
        engineerId: '工程号',
        totalnumber: '总数量',
        tatalarea: '总面积',
@@ -990,5 +989,38 @@
        pwidth: '请输入宽度',
        pheight: '请输入高度',
        upnumber: '上片数量',
    }
    },
    scheduling:{
        cuttingCount: '切割',
        edgingCount: '磨边',
        temperingCount: '钢化',
        insulatingCount: '中空',
        completed:"已排产",
        completedCount: '完成数量',
        unfinished:'待排产',
        serial: '序号',
        projectNo: '工程ID',
        thickness: '厚度(mm)',
        glassType: '玻璃类型',
        coatingType: '膜系',
        layerCount: '层数',
        height: '长(mm)',
        width: '宽(mm)',
        state: '状态',
        glassCount: '数量',
        operate: '操作',
        totalCount: '总片数',
        totalArea: '总面积(㎡)',
        remove: '去除',
        top: '置顶',
        order: '出片顺序',
        flowCardId: '流程卡号',
        add: '添加',
        cancelled: '已取消',
        saveFailed: '保存排产信息失败',
        retryLater: '请稍后重试',
        saveSuccess: '保存成功',
        totalFireCount: '总炉数',
        fullFireCount: '满炉数',
    }
}
UI-Project/src/utils/constants.js
@@ -1,10 +1,10 @@
//  export const WebSocketHost = "192.168.2.100";
 export const WebSocketHost = "10.153.19.179";
//  export const WebSocketHost = "10.153.19.179";
// export const WebSocketHost = "192.168.0.39";
// export const WebSocketHost = "10.153.19.150";
// export const WebSocketHost = "10.153.19.218";
// export const WebSocketHost = "10.153.19.162";
// export const WebSocketHost = "127.0.0.1";
export const WebSocketHost = "127.0.0.1";
export const host = "88";
export const ErpIp = "10.153.19.179";
export const ErpHost = "8086";
UI-Project/src/views/EngineerScheduling/engineerScheduling.vue
@@ -1,161 +1,201 @@
<script lang="ts" setup>
import { ref, computed, watch, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage, ElTransfer, ElTabs, ElTabPane, ElButton } from 'element-plus'
import {ref, computed, watch, onMounted} from 'vue'
import {useI18n} from 'vue-i18n'
import {ElMessage, ElTransfer, ElTabs, ElTabPane, ElButton} from 'element-plus'
import request from '@/utils/request'
const { t } = useI18n()
const {t} = useI18n()
const activeTab = ref('cutting1')
// Transfer组件所需的数据格式
interface TransferDataItem {
    key: string
    label: string
    projectNo: string
    projectName: string
  key: string
  label: string
  projectNo: string
  projectName: string
}
// 所有可选数据(左侧)
// Transfer组件所需的数据格式 - 完善字段定义
interface TransferDataItem {
  key: string
  projectNo: string
  projectName: string
  state?: number
  type?: number
  glassThickness?: string  // 玻璃厚度
  glassType?: string       // 玻璃类型
  glassTotal?: number      // 玻璃总数
  glassTotalArea?: number  // 玻璃总面积
}
// 所有可选数据(左侧表格)
const dataSource = ref<TransferDataItem[]>([])
// 已选数据的keys(右侧)
const targetKeys = ref<string[]>([])
// 根据当前标签页获取右侧列表标题
const getRightListTitle = computed(() => {
    switch (activeTab.value) {
        case 'cutting1':
            return t('large.countOutOne')
        case 'cutting2':
            return t('large.countOutTwo')
        case 'tempered':
            return t('large.temp')
        default:
            return '已排产'
// 已选数据(右侧表格)
const rightDataSource = ref<TransferDataItem[]>([])
// 左侧表格选中项
const selectedLeft = ref<TransferDataItem[]>([])
// 右侧表格选中项
const selectedRight = ref<TransferDataItem[]>([])
// 详情数据状态(改为数组类型,适应列表返回)
const detailData = ref<any[]>([]);
const showDetail = ref(false);
// 获取项目详情接口(更新为实际接口)
const fetchProjectDetail = async (projectNo: string) => {
  try {
    const response = await request.post('/loadGlass/optimizeProject/selectProgress', {
      projectNo: projectNo  // 传入工程ID(projectNo)
    });
    if (response.code === 200) {
      detailData.value = response.data;  // 假设返回数组
      showDetail.value = true;
    } else {
      ElMessage.error(`获取详情失败: ${response.message || '未知错误'}`);
    }
})
  } catch (error) {
    console.error('获取项目详情失败:', error);
    ElMessage.error('获取详情失败,请稍后重试');
  }
};
// 获取左侧数据源
// 获取左侧数据源 - 更新映射逻辑(包含所有字段)
const fetchDataSource = async () => {
    try {
        // 根据当前标签页选择不同的接口
        const apiUrl = activeTab.value === 'tempered'
            ? '/cacheVerticalGlass/bigStorageCageDetails/queryEngineer'
            : '/loadGlass/optimizeProject/queryEngineer';
  try {
    const apiUrl = activeTab.value === 'tempered'
        ? '/cacheVerticalGlass/bigStorageCageDetails/queryEngineer'
        : '/loadGlass/optimizeProject/queryEngineer';
        const response = await request.post(apiUrl)
    const response = await request.post(apiUrl)
        if (response.code === 200) {
            dataSource.value = response.data.map((item: any) => {
                const projectNo = activeTab.value === 'tempered' ? item.engineerId : item.projectNo
                const name = activeTab.value === 'tempered' ? item.engineerId : (item.projectNo + "-" + item.projectName)
                return {
                    key: projectNo,
                    label: name,
                    projectNo: projectNo,
                    projectName: activeTab.value === 'tempered' ? '' : item.projectName
                }
            })
        } else {
            ElMessage.error(`获取数据失败: ${response.message || '未知错误'}`)
        }
    } catch (error) {
        console.error('获取左侧数据失败:', error)
        ElMessage.error('请稍后重试')
    if (response.code === 200) {
      dataSource.value = response.data.map((item: any) => ({
        key: activeTab.value === 'tempered' ? item.engineerId : item.projectNo,
        projectNo: activeTab.value === 'tempered' ? item.engineerId : item.projectNo,
        projectName: item.projectName || '',
        state: item.state,
        type: item.type,
        glassThickness: item.glassThickness || '',
        glassType: item.glassType || '',
        glassTotal: item.glassTotal || 0,
        glassTotalArea: item.glassTotalArea || 0
      }))
    } else {
      ElMessage.error(`获取数据失败: ${response.message || '未知错误'}`)
    }
  } catch (error) {
    console.error('获取左侧数据失败:', error)
    ElMessage.error('请稍后重试')
  }
}
// 获取右侧已选数据
// 获取右侧已选数据 - 直接填充右侧表格
const fetchTargetKeys = async () => {
    try {
        // 根据当前标签页确定type参数
        let type = 1; // 默认切割一线
        if (activeTab.value === 'cutting2') {
            type = 2; // 切割二线
        } else if (activeTab.value === 'tempered') {
            type = 3; // 钢化
        }
        const response = await request.post('/loadGlass/optimizeProject/engineerScheduling', {
            type: type
        })
        if (response.code === 200) {
            // 对于所有标签页,使用projectNo作为key
            targetKeys.value = response.data.map((item: any) => item.projectNo)
            // 将右侧数据添加到dataSource中,确保Transfer组件能找到对应的项
            response.data.forEach((item: any) => {
                // 检查dataSource中是否已存在该项
                const exists = dataSource.value.some(dataItem => dataItem.key === item.projectNo)
                if (!exists) {
                    // 如果不存在,添加到dataSource中
                    const newItem: TransferDataItem = {
                        key: item.projectNo,
                        label: `${item.projectNo}-${item.projectName || 'null'}`,
                        projectNo: item.projectNo,
                        projectName: item.projectName || ''
                    }
                    dataSource.value.push(newItem)
                }
            })
        } else {
            ElMessage.error(`获取数据失败: ${response.message || '未知错误'}`)
        }
    } catch (error) {
        console.error('获取右侧数据失败:', error)
        ElMessage.error('请稍后重试')
  try {
    let type = 1;
    let response;
    if (activeTab.value === 'cutting2') {
      type = 2;
      response = await request.post('/loadGlass/optimizeProject/engineerScheduling', {type})
    } else if (activeTab.value === 'tempered') {
      type = 3;
      response = await request.post('/cacheVerticalGlass/bigStorageCageDetails/queryTemperingOrder')
    } else {
      response = await request.post('/loadGlass/optimizeProject/engineerScheduling', {type})
    }
    if (response.code === 200) {
      // 右侧表格数据
      rightDataSource.value = response.data.map((item: any) => ({
        key: item.projectNo,
        projectNo: item.projectNo,
        projectName: item.projectName || '',
        state: item.state,
        type: item.type,
        glassThickness: item.glassThickness || '',
        glassType: item.glassType || '',
        glassTotal: item.glassTotal || 0,
        glassTotalArea: item.glassTotalArea || 0
      }))
      // 从左侧数据源移除右侧已选数据
      dataSource.value = dataSource.value.filter(
          item => !rightDataSource.value.some(rightItem => rightItem.key === item.key)
      )
    } else {
      ElMessage.error(`获取数据失败: ${response.message || '未知错误'}`)
    }
  } catch (error) {
    console.error('获取右侧数据失败:', error)
    ElMessage.error('请稍后重试')
  }
}
// 保存排产信息
// 修改:支持单行数据移动到右侧表格末尾
const moveToRight = (row: TransferDataItem) => {
  if (!row) return;
  // 从左侧表格移除当前行
  dataSource.value = dataSource.value.filter(item => item.key !== row.key);
  // 添加到右侧表格末尾
  rightDataSource.value.push(row);
  ElMessage.success(`已添加项目 ${row.projectNo}`);
}
// 修改:支持单行数据从右侧表格移回左侧表格
const moveToLeft = (row: TransferDataItem) => {
  if (!row) return;
  // 从右侧表格移除当前行
  rightDataSource.value = rightDataSource.value.filter(item => item.key !== row.key);
  // 添加到左侧表格
  dataSource.value.push(row);
  ElMessage.success(`已移除项目 ${row.projectNo}`);
}
// 更新保存逻辑 - 使用右侧表格数据
const saveScheduling = async () => {
    try {
        // 根据当前标签页确定type参数
        let type = 1; // 默认切割一线
        if (activeTab.value === 'cutting2') {
            type = 2; // 切割二线
        } else if (activeTab.value === 'tempered') {
            type = 3; // 钢化
        }
  try {
    let type = 1;
    if (activeTab.value === 'cutting2') type = 2;
    else if (activeTab.value === 'tempered') type = 3;
        const engineerList = targetKeys.value.map(projectNo => {
            const dataItem = dataSource.value.find(item => item.key === projectNo)
            return {
                projectNo: projectNo,
                projectName: dataItem ? dataItem.projectName : ''
            }
        })
    // 右侧表格数据即为需要保存的排产数据
    const engineerList = rightDataSource.value.map(item => ({
      projectNo: item.projectNo,
      projectName: item.projectName
    }))
        const response = await request.post(`/loadGlass/optimizeProject/updateEngineerScheduling?type=${type}`, engineerList)
    const response = await request.post(
        `/loadGlass/optimizeProject/updateEngineerScheduling?type=${type}`,
        engineerList
    )
        if (response.code === 200) {
            ElMessage.success('保存成功')
            // 重新加载数据
            await fetchDataSource()
            await fetchTargetKeys()
        } else {
            ElMessage.error(`保存失败: ${response.message || '未知错误'}`)
        }
    } catch (error) {
        console.error('保存排产信息失败:', error)
        ElMessage.error('请稍后重试')
    if (response.code === 200) {
      ElMessage.success('保存成功')
      await fetchDataSource()
      await fetchTargetKeys()
    } else {
      ElMessage.error(`保存失败: ${response.message || '未知错误'}`)
    }
  } catch (error) {
    console.error('保存排产信息失败:', error)
    ElMessage.error('请稍后重试')
  }
}
// 重置排产信息
const resetScheduling = async () => {
    await fetchDataSource()
    await fetchTargetKeys()
    ElMessage.info(t('已取消'))
  await fetchDataSource()
  await fetchTargetKeys()
  ElMessage.info(t('scheduling.cancelled'))
}
// 监听标签页切换,根据不同标签页加载对应的数据
watch(activeTab, async (newTab) => {
    // 重新获取数据
    await fetchDataSource()
    await fetchTargetKeys()
  // 重新获取数据
  await fetchDataSource()
  await fetchTargetKeys()
})
@@ -164,85 +204,389 @@
// 组件挂载时获取数据
onMounted(async () => {
    await fetchDataSource()
    await fetchTargetKeys()
  await fetchDataSource()
  await fetchTargetKeys()
})
// 判断是否为第一行
const isFirstRow = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  return index === 0;
};
// 判断是否为最后一行
const isLastRow = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  return index === rightDataSource.value.length - 1;
};
// 判断上方是否有进行中的行(修复:使用正确的状态值1)
const hasInProgressAbove = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  // 查找当前行上方是否有进行中的任务
  return rightDataSource.value.some((item, i) => i < index && item.state === 1);
};
// 向上移动一行
const moveUp = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  if (index > 0) {
    // 检查是否会超过进行中的任务
    const prevItem = rightDataSource.value[index - 1];
    if (prevItem.state === 1) {
      // 直接上方是进行中任务,提示用户不可超过
      ElMessage.warning('操作不可超过进行中的任务');
      return;
    }
    // 交换位置
    [rightDataSource.value[index], rightDataSource.value[index - 1]] =
        [rightDataSource.value[index - 1], rightDataSource.value[index]];
    // 触发响应式更新
    rightDataSource.value = [...rightDataSource.value];
  }
};
// 向下移动一行
const moveDown = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  if (index < rightDataSource.value.length - 1) {
    // 交换位置
    [rightDataSource.value[index], rightDataSource.value[index + 1]] =
        [rightDataSource.value[index + 1], rightDataSource.value[index]];
    // 触发响应式更新
    rightDataSource.value = [...rightDataSource.value];
  }
};
// 判断是否可以置顶(即是否有可置顶的位置)
const canMoveToTop = (row: TransferDataItem) => {
  // 进行中任务不能置顶
  if (row.state === 1) return false;
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  // 已经是第一行的不能置顶
  if (index === 0) return false;
  // 查找第一个非进行中任务的位置
  const firstNonProgressIndex = rightDataSource.value.findIndex(item => item.state !== 1);
  // 如果当前行已经在第一个非进行中任务的位置或之前,则不能置顶
  return index > firstNonProgressIndex;
};
// ... existing code (moveUp和moveDown函数保持不变)
// 置顶(移动到所有非进行中任务的最前面)
const moveToTop = (row: TransferDataItem) => {
  const index = rightDataSource.value.findIndex(item => item.key === row.key);
  if (index > 0) {
    // 移除当前行
    const newList = rightDataSource.value.filter(item => item.key !== row.key);
    // 查找所有非进行中任务的位置
    const nonProgressIndices = newList
        .map((item, i) => ({ item, index: i }))
        .filter(item => item.item.state !== 1)
        .map(item => item.index);
    if (nonProgressIndices.length > 0) {
      // 有非进行中任务,添加到第一个非进行中任务的位置
      newList.splice(nonProgressIndices[0], 0, row);
    } else {
      // 全部都是进行中任务,添加到开头
      newList.unshift(row);
    }
    // 更新数据源
    rightDataSource.value = newList;
  }
};
// 创建计算属性,根据标签页返回不同的表头配置
const tableHeaders = computed(() => {
  const baseHeaders = {
    serial: t('scheduling.serial'),
    projectNo: t('scheduling.projectNo'),
    thickness: t('scheduling.thickness'),
    glassType: t('scheduling.glassType'),
    totalCount: t('scheduling.totalCount'),
    totalArea: t('scheduling.totalArea'),
    operate: t('scheduling.operate')
  };
  // 根据不同标签页返回不同的表头配置
  if (activeTab.value === 'tempered') {
    return {
      ...baseHeaders,
      // 更改钢化标签页的特定表头
      totalCount: t('scheduling.totalFireCount'),
      totalArea: t('scheduling.fullFireCount')
    };
  }
  return baseHeaders;
});
// 状态格式化函数
const stateFormatter = (row: any) => {
  return row.state === 1 ? '进行中' : '未开始';
};
</script>
<template>
    <div class="engineer-scheduling-container">
        <el-tabs v-model="activeTab" class="custom-tabs">
            <el-tab-pane :label="t('large.countOutOne')" name="cutting1" />
            <el-tab-pane :label="t('large.countOutTwo')" name="cutting2" />
            <el-tab-pane :label="t('large.temp')" name="tempered" />
        </el-tabs>
  <div class="engineer-scheduling-container">
    <el-tabs v-model="activeTab" class="custom-tabs">
      <el-tab-pane :label="t('large.countOutOne')" name="cutting1"/>
      <el-tab-pane :label="t('large.countOutTwo')" name="cutting2"/>
      <el-tab-pane :label="t('large.temp')" name="tempered"/>
    </el-tabs>
        <div class="transfer-wrapper">
            <el-transfer v-model="targetKeys" class="custom-transfer" filterable :data="dataSource"
                :titles="['待排产', getRightListTitle]" :button-texts="['', '']">
                <template #right-empty>
                    <el-empty :image-size="80" description="No data" />
                </template>
            </el-transfer>
    <!-- 表格布局容器 -->
    <div class="table-container">
      <!-- 左侧表格:待排产 -->
      <div class="table-wrapper" v-if="activeTab !== 'tempered'">
        <h3 class="table-title">{{ t('scheduling.unfinished') }} ({{ dataSource.length }})</h3>
        <el-table
            :data="dataSource"
            border
            class="custom-table"
            height="400"
            row-key="key"
        >
          <el-table-column type="index" :label="$t('scheduling.serial')" width="55"/>
          <el-table-column prop="projectNo" :label="$t('scheduling.projectNo')" width="150"/>
          <el-table-column prop="glassThickness" :label="$t('scheduling.thickness')" width="120"/>
          <el-table-column prop="glassType" :label="$t('scheduling.glassType')" width="120"/>
          <el-table-column prop="glassTotal" :label="$t('scheduling.totalCount')" width="90"/>
          <el-table-column prop="glassTotalArea" :label="$t('scheduling.totalArea')" width="100"/>
          <el-table-column :label="$t('scheduling.operate')" width="90" align="center">
            <template #default="{ row }">
              <el-button type="primary" @click="moveToRight(row)">
                {{ t('scheduling.add') }}
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
            <div class="transfer-save">
                <el-button type="primary" @click="saveScheduling">
                    {{ t('searchOrder.makesure') }}
      <!-- 右侧表格:已排产 -->
      <div class="table-wrapper">
        <h3 class="table-title">{{ t('scheduling.completed') }} ({{ rightDataSource.length }})</h3>
        <el-table
            :data="rightDataSource"
            border
            class="custom-table"
            height="400"
            row-key="key"
            @row-click="(row) => fetchProjectDetail(row.key)"
            highlight-current-row
        >
          <el-table-column type="index" :label="tableHeaders.serial" width="55"/>
          <el-table-column prop="projectNo" :label="tableHeaders.projectNo" width="120"/>
          <el-table-column prop="glassThickness" :label="tableHeaders.thickness" width="120"/>
          <el-table-column prop="glassType" :label="tableHeaders.glassType" width="120"/>
          <el-table-column prop="glassTotal" :label="tableHeaders.totalCount" width="90"/>
          <el-table-column prop="glassTotalArea" :label="tableHeaders.totalArea" width="120"/>
          <el-table-column
              prop="state"
              :label="t('scheduling.state')"
              width="90"
              :formatter="stateFormatter"
          />
          <el-table-column :label="t('scheduling.operate')" :width="activeTab === 'tempered' ? 200 : 300" :align="center">
            <template #default="{ row }">
              <div style="display: flex; gap: 5px; align-items: center;">
                <el-button
                    v-if="activeTab !== 'tempered'"
                    type="default"
                    size="small"
                    @click="moveToLeft(row)"
                    :disabled="row.state === 1"
                    style="background: #ff4d4f; color: white; border-radius: 8px; min-width: 60px; display: inline-flex; justify-content: center; align-items: center;"
                >
                  {{ t('scheduling.remove') }}
                </el-button>
                <el-button type="primary" @click="resetScheduling">
                    {{ t('delivery.cancel') }}
                <el-button
                    type="default"
                    size="small"
                    @click="moveUp(row)"
                    :disabled="row.state === 1 || isFirstRow(row)"
                    style="background: #E6F4FF; color: #1890FF; border-radius: 8px; min-width: 40px; display: inline-flex; justify-content: center; align-items: center;"
                >
                  ↑
                </el-button>
            </div>
        </div>
                <el-button
                    type="default"
                    size="small"
                    @click="moveDown(row)"
                    :disabled="row.state === 1 || isLastRow(row)"
                    style="background: #E6F4FF; color: #1890FF; border-radius: 8px; min-width: 40px; display: inline-flex; justify-content: center; align-items: center;"
                >
                  ↓
                </el-button>
                <el-button
                    size="small"
                    @click="moveToTop(row)"
                    :disabled="row.state === 1 || isFirstRow(row) || !canMoveToTop(row)"
                    style="background: #E6F4FF; color: #1890FF; border-radius: 8px; min-width: 60px; display: inline-flex; justify-content: center; align-items: center;"
                >
                  {{ t('scheduling.top') }}
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- 保存和重置按钮 -->
    <div class="transfer-save">
      <el-button type="primary" @click="saveScheduling">
        {{ t('searchOrder.makesure') }}
      </el-button>
      <el-button type="primary" @click="resetScheduling">
        {{ t('delivery.cancel') }}
      </el-button>
    </div>
  </div>
  <!-- 详情展示区域(改为表格展示列表数据) -->
  <div v-if="showDetail" class="project-detail">
    <!--    <h3 class="detail-title">工程详情列表 ({{ detailData.length }})</h3>-->
    <el-table
        :data="detailData"
        border
        class="detail-table"
        height="230"
    >
      <el-table-column prop="engineerId" :label="$t('scheduling.projectNo')" width="120"/>
      <el-table-column prop="flowCardId" :label="$t('scheduling.flowCardId')" width="150"/>
      <el-table-column prop="layer" :label="$t('scheduling.layerCount')" width="80"/>
      <el-table-column prop="glassType" :label="$t('scheduling.serial')" width="80"/>
      <el-table-column prop="thickness" :label="$t('scheduling.thickness')" width="100"/>
      <el-table-column prop="filmsid" :label="$t('scheduling.coatingType')" width="120"/>
      <el-table-column prop="width" :label="$t('scheduling.width')" width="90"/>
      <el-table-column prop="height" :label="$t('scheduling.height')" width="90"/>
      <el-table-column prop="glassIdCount" :label="$t('scheduling.glassCount')" width="80"/>
      <el-table-column prop="cuttingCount" :label="$t('scheduling.cuttingCount')" width="80"/>
      <el-table-column prop="edgingCount" :label="$t('scheduling.edgingCount')" width="80"/>
      <el-table-column prop="temperingCount" :label="$t('scheduling.temperingCount')" width="80"/>
      <el-table-column prop="insulatingCount" :label="$t('scheduling.insulatingCount')" width="80"/>
    </el-table>
  </div>
</template>
<style scoped>
/* 表格布局容器 */
.table-container {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 20px;
}
/* 详情表格样式 */
.project-detail {
  margin-top: 0px;
  padding: 15px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  width: 100%;
  box-sizing: border-box;
  height: auto; /* 确保容器高度自适应 */
}
.detail-title {
  margin-bottom: 15px;
  font-size: 16px;
  font-weight: bold;
  color: #303133;
}
.detail-table {
  width: 100%;
  font-size: 14px;
}
/* 强制表格内容区域滚动 */
::v-deep(.detail-table .el-table__body-wrapper) {
  overflow-y: auto !important; /* 优先确保垂直滚动 */
  max-height: calc(230px - 50px); /* 适配表格高度(需与el-table height匹配) */
}
.table-wrapper {
  flex: 1;
}
.table-title {
  margin-bottom: 10px;
  font-size: 18px;
  font-weight: bold;
  color: #303133;
}
.custom-table {
  width: 100%;
  font-size: 14px;
}
/* 转移按钮样式 */
.transfer-buttons {
  display: flex;
  flex-direction: column;
}
/* 调整按钮区域位置 */
.transfer-save {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 20px;
}
.engineer-scheduling-container {
    padding: 20px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    background-color: #fff;
  padding: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background-color: #fff;
}
.custom-tabs {
    margin-bottom: 20px;
  margin-bottom: 20px;
}
::v-deep(.custom-tabs .el-tabs__item) {
    font-size: 20px;
  font-size: 20px;
}
.transfer-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}
.transfer-save {
    display: flex;
    gap: 10px;
  display: flex;
  gap: 10px;
}
/* 自定义Transfer组件的样式 */
::v-deep(.el-transfer-panel) {
    font-size: 16px;
    width: 350px;
    height: 440px;
  font-size: 16px;
  width: 350px;
  height: 440px;
}
.custom-transfer {
    --el-transfer-panel-body-height: 400px;
  --el-transfer-panel-body-height: 400px;
}
::v-deep(.el-transfer-panel__header) {
    font-weight: bold;
    font-size: 18px;
  font-weight: bold;
  font-size: 18px;
}
::v-deep(.el-checkbox__label) {
    font-size: 16px;
  font-size: 16px;
}
</style>
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/controller/EngineerSchedulingController.java
New file
@@ -0,0 +1,21 @@
package com.mes.engineerScheduling.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author wf
 * @since 2025-10-27
 */
@RestController
@RequestMapping("/engineerScheduling/engineer-scheduling")
public class EngineerSchedulingController {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/entity/EngineerScheduling.java
New file
@@ -0,0 +1,50 @@
package com.mes.engineerScheduling.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <p>
 *
 * </p>
 *
 * @author wf
 * @since 2025-10-27
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class EngineerScheduling implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 工程排产id
     */
      @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 工程编号
     */
    private String projectNo;
    /**
     * 工程项目名
     */
    private String projectName;
    /**
     * 类型
     */
    private Integer type;
    /**
     * 状态
     */
    private Integer state;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/mapper/EngineerSchedulingMapper.java
New file
@@ -0,0 +1,16 @@
package com.mes.engineerScheduling.mapper;
import com.mes.engineerScheduling.entity.EngineerScheduling;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author wf
 * @since 2025-10-27
 */
public interface EngineerSchedulingMapper extends BaseMapper<EngineerScheduling> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/mapper/xml/EngineerSchedulingMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mes.engineerScheduling.mapper.EngineerSchedulingMapper">
</mapper>
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/service/EngineerSchedulingService.java
New file
@@ -0,0 +1,16 @@
package com.mes.engineerScheduling.service;
import com.mes.engineerScheduling.entity.EngineerScheduling;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 *  服务类
 * </p>
 *
 * @author wf
 * @since 2025-10-27
 */
public interface EngineerSchedulingService extends IService<EngineerScheduling> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/engineerScheduling/service/impl/EngineerSchedulingServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.mes.engineerScheduling.service.impl;
import com.mes.engineerScheduling.entity.EngineerScheduling;
import com.mes.engineerScheduling.mapper.EngineerSchedulingMapper;
import com.mes.engineerScheduling.service.EngineerSchedulingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wf
 * @since 2025-10-27
 */
@Service
public class EngineerSchedulingServiceImpl extends ServiceImpl<EngineerSchedulingMapper, EngineerScheduling> implements EngineerSchedulingService {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/controller/OptimizeProjectController.java
@@ -1,14 +1,13 @@
package com.mes.pp.controller;
import com.baomidou.mybatisplus.extension.api.R;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.entity.dto.ProgressDTO;
import com.mes.pp.entity.request.OptimizeRequest;
import com.mes.pp.service.OptimizeProjectService;
import com.mes.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import liquibase.pro.packaged.O;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -66,6 +65,13 @@
        List<OptimizeProject> resultList = optimizeProjectService.updateEngineerScheduling(type, engineerList);
        return Result.build(200, "更新成功", resultList);
    }
    @ApiOperation("查询工程进度")
    @PostMapping("/selectProgress") //更新工程排产信息 engineerScheduling表
    @ResponseBody
    public Result<List<ProgressDTO>> selectProgress(@RequestBody OptimizeRequest optimizeRequest) {
        List<ProgressDTO> resultList = optimizeProjectService.selectProgress(optimizeRequest.getProjectNo());
        return Result.build(200, "更新成功", resultList);
    }
//    @ApiOperation("保存工程信息")
//    @PostMapping("/saveProject") //显示工程选择信息
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeProject.java
@@ -1,6 +1,5 @@
package com.mes.pp.entity;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -50,7 +49,7 @@
    /**
     * 玻璃厚度
     */
    private String glassThickness;
    private Integer  glassThickness;
    /**
     * 工程种类
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/dto/ProgressDTO.java
New file
@@ -0,0 +1,39 @@
package com.mes.pp.entity.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
 * <p>
 *
 * </p>
 *
 * @author wu
 * @since 2024-07-25
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class ProgressDTO implements Serializable {
    // 玻璃信息相关
    private String engineerId;         // 工程号(对应 glass_info.engineer_id)
    private String flowCardId;         // 流程卡号(对应 glass_info.flow_card_id)
    private Integer layer;             // 层号(对应 glass_info.layer)
    private Integer glassType;         // 玻璃类型(对应 glass_info.glass_type)
    private Double thickness;      // 厚度(对应 glass_info.thickness)
    private String filmsid;            // 膜系(对应 glass_info.filmsid)
    private Double width;          // 宽(对应 glass_info.width)
    private Double height;         // 高(对应 glass_info.height)
    // 数量统计相关
    private Integer glassIdCount;      // 玻璃总数(对应 COUNT(a.glass_id))
    // 报工统计相关(各工序报工数)
    private Integer cuttingCount;      // 切割报工数(对应切割工序 SUM(...))
    private Integer edgingCount;       // 磨边报工数(对应磨边工序 SUM(...))
    private Integer temperingCount;    // 钢化报工数(对应钢化工序 SUM(...))
    private Integer insulatingCount;   // 中空报工数(对应中空工序 SUM(...))
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeProjectMapper.java
@@ -3,6 +3,7 @@
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.yulichang.base.MPJBaseMapper;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.entity.dto.ProgressDTO;
import com.mes.pp.entity.request.OptimizeRequest;
import liquibase.pro.packaged.L;
import org.apache.ibatis.annotations.Param;
@@ -57,4 +58,11 @@
     * @param types
     */
    void deleteByScheduling(@Param("engineerId") String engineerId,@Param("types") List<Integer> types);
    /**
     * 查询工程进度
     *
     * @param engineerId
     */
    List<ProgressDTO> selectProgress(@Param("engineerId") String engineerId);
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeProjectService.java
@@ -2,6 +2,7 @@
import com.github.yulichang.base.MPJBaseService;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.entity.dto.ProgressDTO;
import com.mes.pp.entity.request.OptimizeRequest;
import com.mes.uppattenusage.entity.UpPattenUsage;
import io.swagger.models.auth.In;
@@ -71,4 +72,10 @@
     * @return
     */
    void deleteengineerSchedulingByid(String engineerId, List<Integer> types);
    /**
     * 查询工程进度
     *
     * @return ProgressDTO
     */
     List<ProgressDTO> selectProgress(String engineerId);
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeProjectServiceImpl.java
@@ -9,6 +9,7 @@
import com.mes.engineering.entity.Engineering;
import com.mes.engineering.service.EngineeringService;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.entity.dto.ProgressDTO;
import com.mes.pp.entity.request.OptimizeRequest;
import com.mes.pp.mapper.OptimizeProjectMapper;
import com.mes.pp.service.OptimizeProjectService;
@@ -127,4 +128,9 @@
    public void deleteengineerSchedulingByid(String engineerId, List<Integer> types) {
        baseMapper.deleteByScheduling(engineerId, types);
    }
    @Override
    public List<ProgressDTO> selectProgress(String engineerId) {
        return baseMapper.selectProgress(engineerId);
    }
}
hangzhoumesParent/common/servicebase/src/main/resources/mapper/OptimizeProjectMapper.xml
@@ -10,7 +10,6 @@
        <result property="thickness" column="glass_thickness"/>
        <result property="layoutSequence" column="heat_layout_sort"/>
        <result property="state" column="state"/>
    </resultMap>
    <resultMap id="resultMap" type="com.mes.pp.entity.OptimizeProject">
@@ -19,8 +18,25 @@
        <result property="projectName" column="project_name"/>
        <result property="state" column="state"/>
        <result property="type" column="type"/>
        <result property="glassThickness" column="glass_thickness"/>
        <result property="glassType" column="glass_type"/>
        <result property="glassTotal" column="glass_total"/>
        <result property="glassTotalArea" column="glass_total_area"/>
    </resultMap>
    <resultMap id="progressResultMap" type="com.mes.pp.entity.dto.ProgressDTO">
        <!-- 玻璃信息表(a)字段映射 -->
        <result property="engineerId" column="engineer_id"/>    <!-- 玻璃No → a.engineer_id -->
        <result property="flowCardId" column="flow_card_id"/>     <!-- 流程卡号 → a.flow_card_id -->
        <result property="layer" column="layer"/>     <!-- 层号 → a.layer -->
        <result property="glassType" column="glass_type"/>      <!-- 玻璃名称 → a.glass_type -->
        <result property="width" column="width"/>                <!-- 宽 → a.width -->
        <result property="height" column="height"/>              <!-- 高 → a.height -->
        <result property="glassIdCount" column="glassIdCount"/>      <!-- 订单数量 → 统计的 glassIdCount -->
        <result property="cuttingCount" column="cuttingCount"/>       <!-- 切割报工数 → cuttingCount -->
        <result property="edgingCount" column="edgingCount"/>   <!-- 磨边报工数 → edgingCount -->
         <result property="temperingCount" column="temperingCount"/>
         <result property="insulatingCount" column="insulatingCount"/>
    </resultMap>
    <select id="saveProject" parameterType="com.mes.pp.entity.request.OptimizeRequest" resultMap="sequenceMap">
        select a.project_no,
               1                                            as glass_type,
@@ -36,27 +52,36 @@
    <select id="queryEngineer" parameterType="com.mes.pp.entity.OptimizeProject" resultMap="resultMap">
        select p.project_no,
               p.project_name
               p.project_name,
               p.glass_thickness,
               p.glass_type,
               p.glass_total,
               p.glass_total_area
        from pp.optimize_project p
        where p.state = 100
          and p.project_no not in (
            select es.project_no
            from north_glass_mes.engineer_scheduling es
            where es.project_no is not null
        )
          and p.project_no not in (select es.project_no
                                   from north_glass_mes.engineer_scheduling es
                                   where es.project_no is not null)
        order by p.id
    </select>
    <select id="engineerScheduling" parameterType="com.mes.pp.entity.request.OptimizeRequest" resultMap="resultMap">
        select es.project_no,
        es.project_name,
        es.type
        es.type,
        p.glass_thickness,
        p.glass_type,
        p.glass_total,
        p.glass_total_area,
        IFNULL(e.state,0) as state
        from north_glass_mes.engineer_scheduling es
        left join pp.optimize_project p on es.project_no=p.project_no
        left join north_glass_mes.engineering e on es.project_no=e.engineer_id
        where es.state = 100
        <if test="type != null and type != ''">
            and es.type = #{type}
        </if>
        order by es.id
        order by case when IFNULL(e.state, 0) = 1 then 0 else 1 end, es.id
    </select>
    <!-- 根据类型删除engineer_scheduling表中的数据 -->
@@ -93,5 +118,37 @@
            )
        </foreach>
    </insert>
    <select id="selectProgress" parameterType="com.mes.glassinfo.entity.GlassInfo" resultMap="progressResultMap">
        SELECT
        a.engineer_id,
        a.flow_card_id,
        a.layer,
        a.glass_type,
        a.thickness,
        a.filmsid,
        a.width,
        a.height,
        COUNT(a.glass_id) as glassIdCount,
        SUM(CASE WHEN d.working_procedure = '切割' AND d.type = 1 THEN 1 ELSE 0 END) as cuttingCount,
        SUM(CASE WHEN d.working_procedure = '磨边' AND d.type = 1 THEN 1 ELSE 0 END) as edgingCount,
        SUM(CASE WHEN d.working_procedure = '钢化' AND d.type = 1 THEN 1 ELSE 0 END) as temperingCount,
        SUM(CASE WHEN d.working_procedure = '中空' AND d.type = 1 THEN 1 ELSE 0 END) as insulatingCount
        FROM
        north_glass_mes.glass_info a
        LEFT JOIN
        north_glass_mes.damage d
        ON a.glass_id = d.glass_id
        AND a.engineer_id = d.engineer_id
        WHERE
        a.engineer_id = #{engineerId}
        GROUP BY
        a.engineer_id,
        a.flow_card_id,
        a.layer,
        a.glass_type,
        a.thickness,
        a.filmsid,
        a.width,
        a.height
    </select>
</mapper>
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java
@@ -203,5 +203,13 @@
        List<BigStorageCageDetails> result = bigStorageCageDetailsService.queryEngineer();
        return Result.build(200, "", result);
    }
    @ApiOperation("查询钢化排产顺序")
    @PostMapping("/queryTemperingOrder") //显示工程排产信息
    @ResponseBody
    public Result<List<OptimizeProject>> queryTemperingOrder() {
        List<OptimizeProject> result = bigStorageCageDetailsService.queryTemperingOrder();
        return Result.build(200, "", result);
    }
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/mapper/BigStorageCageDetailsMapper.java
@@ -71,4 +71,6 @@
    BigStorageSlotDTO queryNeedDispatchSlotBySequence();
    List<TemperingGlassCountDTO> queryTemperingGlassCountSummary(int isTempering);
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java
@@ -150,4 +150,9 @@
    List<BigStorageCageDetails> queryNeedDispatch();
    BigStorageSlotDTO queryNeedDispatchSlotBySequence();
    /**
     * 查询钢化排产顺序
     * @return OptimizeProject 钢化排产顺序
     */
    List<OptimizeProject> queryTemperingOrder();
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java
@@ -29,6 +29,8 @@
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.glassinfo.mapper.GlassInfoMapper;
import com.mes.glassinfo.service.GlassInfoService;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.service.OptimizeProjectService;
import com.mes.sysconfig.entity.SysConfig;
import com.mes.sysconfig.service.SysConfigService;
import com.mes.temperingglass.entity.TemperingGlassInfo;
@@ -41,6 +43,7 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -69,6 +72,8 @@
    private BigStorageCageService bigStorageCageService;
    @Resource
    private GlassInfoMapper glassInfoMapper;
    @Resource
    private OptimizeProjectService optimizeProjectService;
    @Resource
    private GlassInfoService glassInfoService;
@@ -587,4 +592,32 @@
    public BigStorageSlotDTO queryNeedDispatchSlotBySequence() {
        return baseMapper.queryNeedDispatchSlotBySequence();
    }
    @Override
    public List<OptimizeProject> queryTemperingOrder() {
        String temperingengineerId = redisUtil.getCacheObject("temperingEngineerId");
        List<TemperingGlassCountDTO> temperingGlassCountDTOS = baseMapper.queryTemperingGlassCountSummary(1);
        List<OptimizeProject> projectList = optimizeProjectService.engineerScheduling(new OptimizeProject() {{
            setType(3);
        }});
        Set<String> projectNoSet = projectList.stream()
                .map(OptimizeProject::getProjectNo)
                .collect(Collectors.toSet());
        List<OptimizeProject> resultList= new ArrayList<>();
        for (TemperingGlassCountDTO dto : temperingGlassCountDTOS) {
            if (projectNoSet.contains(dto.getEngineerId())) {
                OptimizeProject project = new OptimizeProject();
                if (Objects.equals(dto.getEngineerId(), temperingengineerId)) {
                    project.setState(1);
                }
                project.setProjectNo(dto.getEngineerId());
                project.setGlassType(dto.getFilmsId());
                project.setGlassThickness(dto.getThickness().intValue());
                project.setGlassTotal(dto.getTotalCount());
                project.setGlassTotalArea(dto.getRealCount());
                resultList.add(project);
            }
        }
        return resultList;
    }
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/application.yml
@@ -3,7 +3,7 @@
spring:
  profiles:
    active: yw
    active: dev
  application:
    name: cacheVerticalGlass
  liquibase:
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/resources/mapper/BigStorageCageDetailsMapper.xml
@@ -326,4 +326,60 @@
        t1.tempering_feed_sequence -1
        )select * from result limit 1
    </select>
    <select id="queryTemperingGlassCountSummary" resultMap="temperingGlassCount">
        with glass_info_temp as (
        select engineer_id, tempering_layout_id, count(*) as total_count
        from glass_info
        group by engineer_id, tempering_layout_id
        ),
        big_details_temp as (
        select engineer_id, tempering_layout_id, count(*) as real_count, films_id, thickness
        from big_storage_cage_details
        where state = 100
        <if test="isTempering == 0">
            and tempering_layout_id = 0
        </if>
        <if test="isTempering == 1">
            and tempering_layout_id != 0
        </if>
        group by engineer_id, tempering_layout_id, films_id, thickness
        ),
        damage_temp as (
        select engineer_id, tempering_layout_id, count(*) as damage_count
        from damage
        where type in(8,9) and STATUS = 1
        group by engineer_id, tempering_layout_id
        ),
        result as (
        select t.engineer_id,
        t.tempering_layout_id,
        t.films_id,
        t.thickness,
        total_count,
        real_count,
        ifnull(damage_count, 0) as damage_count,
        case when total_count - real_count - ifnull(damage_count, 0) &lt; 0 then 0 else
        total_count - real_count - ifnull(damage_count, 0) end as lack_count
        from big_details_temp t
        inner join glass_info_temp t1 on t.engineer_id = t1.engineer_id and
        t.tempering_layout_id = t1.tempering_layout_id
        left join damage_temp t2
        on t.engineer_id = t2.engineer_id and t.tempering_layout_id = t2.tempering_layout_id
        ),
        -- 二次汇总层
        secondary_summary as (
        select
        engineer_id,
        films_id,
        thickness,
        count(distinct tempering_layout_id) as total_count, -- 计算totalCount的累计数(去重计数)
        sum(total_count) as real_count -- 计算realCount的总和
        from result
        group by engineer_id, films_id, thickness
        )
        select *
        from secondary_summary
        order by engineer_id, films_id, thickness
    </select>
</mapper>
hangzhoumesParent/moduleService/LoadGlassModule/src/main/resources/application.yml
@@ -2,7 +2,7 @@
  port: 10015
spring:
  profiles:
    active: yw
    active: dev
  application:
    name: loadGlass
  liquibase: