huang
2025-09-30 64ff6a48658f9a31bba9d238b23d33008c7709f1
添加工程排产功能页面
9个文件已修改
1个文件已添加
455 ■■■■■ 已修改文件
UI-Project/src/router/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/EngineerScheduling/engineerScheduling.vue 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/controller/OptimizeProjectController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeProjectMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeProjectService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeProjectServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/resources/mapper/OptimizeProjectMapper.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/router/index.js
@@ -273,6 +273,20 @@
      },
    ]
  },
  /*----------- 工程排产 ----------------*/
  {
    path: 'engineerScheduling',
    name: 'engineerScheduling',
    component: () => import('../views/EngineerScheduling/engineerScheduling.vue'),
    children: [
      {
        path: '/EngineerScheduling/engineerScheduling',
        name: 'engineerScheduling',
        component: () => import('../views/EngineerScheduling/engineerScheduling.vue')
      },
    ]
  },
        /*----------- 中空 ----------------*/
        {
          path: 'hollow',
UI-Project/src/views/EngineerScheduling/engineerScheduling.vue
New file
@@ -0,0 +1,248 @@
<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 request from '@/utils/request'
const { t } = useI18n()
const activeTab = ref('cutting1')
// Transfer组件所需的数据格式
interface TransferDataItem {
    key: string
    label: string
    projectNo: string
    projectName: string
}
// 所有可选数据(左侧)
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 fetchDataSource = async () => {
    try {
        // 根据当前标签页选择不同的接口
        const apiUrl = activeTab.value === 'tempered'
            ? '/cacheVerticalGlass/bigStorageCageDetails/queryEngineer'
            : '/loadGlass/optimizeProject/queryEngineer';
        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('请稍后重试')
    }
}
// 获取右侧已选数据
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('请稍后重试')
    }
}
// 保存排产信息
const saveScheduling = async () => {
    try {
        // 根据当前标签页确定type参数
        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 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('请稍后重试')
    }
}
// 重置排产信息
const resetScheduling = async () => {
    await fetchDataSource()
    await fetchTargetKeys()
    ElMessage.info(t('已取消'))
}
// 监听标签页切换,根据不同标签页加载对应的数据
watch(activeTab, async (newTab) => {
    // 重新获取数据
    await fetchDataSource()
    await fetchTargetKeys()
})
// 移除formatFunc,使用默认配置,Element Plus Transfer组件默认就会显示数量统计
// 如果需要自定义标题显示,可以通过titles属性处理
// 组件挂载时获取数据
onMounted(async () => {
    await fetchDataSource()
    await fetchTargetKeys()
})
</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="transfer-wrapper">
            <el-transfer
                v-model="targetKeys"
                filterable
                :data="dataSource"
                :titles="['待排产', getRightListTitle]"
                :button-texts="['', '']"
            />
            <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>
</template>
<style scoped>
.engineer-scheduling-container {
    padding: 20px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    background-color: #fff;
}
.custom-tabs {
    margin-bottom: 20px;
}
::v-deep(.custom-tabs .el-tabs__item) {
    font-size: 20px;
}
.transfer-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
}
.transfer-save {
    display: flex;
    gap: 10px;
}
/* 自定义Transfer组件的样式 */
::v-deep(.el-transfer-panel) {
    font-size: 16px;
    width: 350px;
    height: 440px;
}
::v-deep(.el-transfer-panel-body-height) {
    height: 470px;
}
::v-deep(.el-transfer-panel__header) {
    font-weight: bold;
    font-size: 18px;
}
::v-deep(.el-checkbox__label) {
    font-size: 16px;
}
</style>
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/controller/OptimizeProjectController.java
@@ -1,12 +1,14 @@
package com.mes.pp.controller;
import com.baomidou.mybatisplus.extension.api.R;
import com.mes.pp.entity.OptimizeProject;
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.*;
@@ -41,6 +43,30 @@
        return Result.build(200, "", glass);
    }
    @ApiOperation("查询工程信息")
    @PostMapping("/queryEngineer") //显示工程信息 pp表
    @ResponseBody
    public Result<List<OptimizeProject>> queryEngineer() {
        List<OptimizeProject> resultList = optimizeProjectService.queryEngineer();
        return Result.build(200, "", resultList);
    }
    @ApiOperation("查询工程排产信息")
    @PostMapping("/engineerScheduling") //显示工程排产信息 engineerScheduling表
    @ResponseBody
    public Result<List<OptimizeProject>> engineerScheduling(@RequestBody OptimizeProject optimizeProject) {
        List<OptimizeProject> engineerScheduling = optimizeProjectService.engineerScheduling(optimizeProject);
        return Result.build(200, "", engineerScheduling);
    }
    @ApiOperation("更新工程信息")
    @PostMapping("/updateEngineerScheduling") //更新工程排产信息 engineerScheduling表
    @ResponseBody
    public Result<List<OptimizeProject>> updateEngineerScheduling(@RequestParam Integer type, @RequestBody List<OptimizeProject> engineerList) {
        List<OptimizeProject> resultList = optimizeProjectService.updateEngineerScheduling(type, engineerList);
        return Result.build(200, "更新成功", resultList);
    }
//    @ApiOperation("保存工程信息")
//    @PostMapping("/saveProject") //显示工程选择信息
//    public Result<List<OptimizeProject>> saveProject(@RequestBody OptimizeRequest optimizeRequest) {
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeProjectMapper.java
@@ -4,6 +4,8 @@
import com.github.yulichang.base.MPJBaseMapper;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.entity.request.OptimizeRequest;
import liquibase.pro.packaged.L;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -18,4 +20,34 @@
@DS("pp")
public interface OptimizeProjectMapper extends MPJBaseMapper<OptimizeProject> {
    List<OptimizeProject> saveProject(OptimizeRequest optimizeRequest);
    /**
     * 查询工程信息
     *
     * @return
     */
    List<OptimizeProject> queryEngineer();
    /**
     * 查询工程排产信息
     *
     * @param optimizeProject
     * @return
     */
    List<OptimizeProject> engineerScheduling(OptimizeProject optimizeProject);
    /**
     * 删除工程信息
     *
     * @param type
     */
    void deleteByType(@Param("type") Integer type);
    /**
     * 更新工程信息
     *
     * @param projectList
     */
    void batchInsert(@Param("list") List<OptimizeProject> projectList);
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeProjectService.java
@@ -40,4 +40,22 @@
     */
    List<OptimizeProject> getDoingTask();
    /**
     * 查询工程信息
     * @return
     */
    List<OptimizeProject> queryEngineer();
    /**
     * 查询工程排序信息
     * @return
     */
    List<OptimizeProject> engineerScheduling(OptimizeProject optimizeProject);
    /**
     * 更新工程排产信息
     * @return
     */
    List<OptimizeProject> updateEngineerScheduling(Integer type , List<OptimizeProject> engineerList);
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeProjectServiceImpl.java
@@ -15,8 +15,10 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
@@ -90,5 +92,32 @@
        return this.list(wrapper);
    }
    @Override
    public List<OptimizeProject> queryEngineer() {
        return this.baseMapper.queryEngineer();
    }
    @Override
    public List<OptimizeProject> engineerScheduling(OptimizeProject optimizeProject) {
        return this.baseMapper.engineerScheduling(optimizeProject);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<OptimizeProject> updateEngineerScheduling(Integer type , List<OptimizeProject> projectList) {
        // 1. 删除对应类型的数据
        baseMapper.deleteByType(type);
        // 2. 设置值
        projectList.forEach(project -> {
            project.setType(type);
            project.setState(100);
            project.setId(null); // 清除ID
        });
        // 3. 批量插入新数据
        baseMapper.batchInsert(projectList);
        return projectList;
    }
}
hangzhoumesParent/common/servicebase/src/main/resources/mapper/OptimizeProjectMapper.xml
@@ -13,6 +13,14 @@
    </resultMap>
    <resultMap id="resultMap" type="com.mes.pp.entity.OptimizeProject">
        <result property="id" column="id"/>
        <result property="projectNo" column="project_no"/>
        <result property="projectName" column="project_name"/>
        <result property="state" column="state"/>
        <result property="type" column="type"/>
    </resultMap>
    <select id="saveProject" parameterType="com.mes.pp.entity.request.OptimizeRequest" resultMap="sequenceMap">
        select a.project_no, 1 as glass_type, a.width, a.height, REGEXP_REPLACE(b.glass_thickness, '\\D', '')as glass_thickness, a.heat_layout_sort, 0 as state
        from optimize_detail a
@@ -20,5 +28,53 @@
        where a.project_no = #{projectNo}
    </select>
    <select id="queryEngineer" parameterType="com.mes.pp.entity.OptimizeProject" resultMap="resultMap">
        select p.project_no,
               p.project_name
        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
            )
        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
        from north_glass_mes.engineer_scheduling es
        where es.state = 100
        <if test="type != null and type != ''">
            and es.type = #{type}
        </if>
        order by es.id
    </select>
    <!-- 根据类型删除engineer_scheduling表中的数据 -->
    <delete id="deleteByType">
        DELETE FROM north_glass_mes.engineer_scheduling
        WHERE type = #{type}
    </delete>
    <!-- 批量插入数据到engineer_scheduling表 -->
    <insert id="batchInsert">
        INSERT INTO north_glass_mes.engineer_scheduling (
        project_no,
        project_name,
        state,
        type
        ) VALUES
        <foreach collection="list" item="item" separator=",">
            (
            #{item.projectNo},
            #{item.projectName},
            #{item.state},
            #{item.type}
            )
        </foreach>
    </insert>
</mapper>
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java
@@ -10,15 +10,13 @@
import com.mes.bigstorage.service.BigStorageCageDetailsService;
import com.mes.bigstorage.service.BigStorageCageService;
import com.mes.common.config.Const;
import com.mes.pp.entity.OptimizeProject;
import com.mes.utils.RedisUtil;
import com.mes.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@@ -197,5 +195,13 @@
        String glassId = map.get("glassId");
        return Result.build(200, "报破损成功", bigStorageCageDetailsService.bigStorageGlassDamageByGlassId(glassId));
    }
    @ApiOperation("查询工程待排产信息")
    @PostMapping("/queryEngineer") //显示工程排产信息
    @ResponseBody
    public Result<List<BigStorageCageDetails>> queryEngineer() {
        List<BigStorageCageDetails> result = bigStorageCageDetailsService.queryEngineer();
        return Result.build(200, "", result);
    }
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java
@@ -7,6 +7,7 @@
import com.mes.bigstorage.entity.vo.BigStorageQueryVO;
import com.mes.bigstoragetask.entity.UpdateBigStorageCageDTO;
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.pp.entity.OptimizeProject;
import java.util.List;
import java.util.Map;
@@ -134,4 +135,11 @@
     * @return
     */
    boolean cancelTemperingTask();
    /**
     * 查询工程待排序信息
     * @return
     */
    List<BigStorageCageDetails> queryEngineer();
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java
@@ -2,6 +2,7 @@
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
@@ -28,6 +29,7 @@
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.sysconfig.entity.SysConfig;
import com.mes.sysconfig.service.SysConfigService;
import com.mes.temperingglass.entity.TemperingGlassInfo;
@@ -568,4 +570,12 @@
    public void updateDeviceIdBySlot(List<Integer> slotList) {
        baseMapper.updateDeviceIdBySlot(slotList);
    }
    @Override
    public List<BigStorageCageDetails> queryEngineer() {
        QueryWrapper<BigStorageCageDetails> wrapper = new QueryWrapper<>();
        wrapper.select("distinct engineer_id")
                .eq("state", 100);
        return this.list(wrapper);
    }
}