廖井涛
10 小时以前 f7a2fcdda7f1120498c5c5f75c5a99955fc54b43
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue
@@ -1,20 +1,24 @@
<script setup>
import {computed, reactive, ref} from "vue";
import {computed, nextTick, reactive, ref} from "vue";
import {useI18n} from "vue-i18n";
import deepClone from "@/utils/deepClone"
import {Search} from "@element-plus/icons-vue";
import request from "@/utils/request";
import {ElDatePicker, ElMessage} from "element-plus";
import {ElDatePicker, ElMessage, ElMessageBox} from "element-plus";
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
import useUserInfoStore from "@/stores/userInfo";
import userInfo from "@/stores/userInfo";
import {VxeUI} from 'vxe-pc-ui'
import GlassComputed from "@/views/pp/glassOptimize/GlassComputed.vue";
import {useRouter} from 'vue-router';
import {defineEmits} from 'vue';
import {changeFilterEvent, filterChanged} from "@/hook";
const {t} = useI18n()
const userStore = useUserInfoStore()
const user = userInfo()
const orderInfo = useOrderInfoStore()
const router = useRouter();
const xGrid = ref()
const gridOptions = reactive({
@@ -34,7 +38,7 @@
    useKey: true
  },
  filterConfig: {   //筛选配置项
    remote: true
    //remote: true
  },
  customConfig: {
    storage: true
@@ -46,141 +50,589 @@
  },
  columns: [
    {type: 'expand', fixed: "left", slots: {content: 'content'}, width: 50},
    {field: 'projectNumber', width: 100, title: '工程号', filters: [{data: ''}], slots: {filter: 'num1_filter'},},
    {type: 'seq', title: t('basicData.Number'), width: 80},
    {field: 'projectNumber', width: 100, title: '工程号',sortable: true,showOverflow:'ellipsis' ,filters:[{ data: '' }],slots: { filter: 'num1_filter' },filterMethod:filterChanged},
    {field: 'projectName', width: 50, title: '名称',},
    {field: 'glassType', width: 50, title: '膜系',},
    {field: 'thickness', width: 50, title: '厚度',},
    {field: 'type', width: 50, title: '类型',},
    {field: 'state', width: 50, title: '状态',},
    {field: 'temperingState', width: 50, title: '钢化模拟', filters: [{data: ''}], slots: {filter: 'select_filter1'},
      filterMethod:filterChanged, formatter: ({ cellValue }) => cellValue === 1 ? '是' : (cellValue === 0 ? '否' : cellValue)},
    {field: 'optimizeState', width: 50, title: '优化计算', filters: [{data: ''}], slots: {filter: 'select_filter1'},
      filterMethod:filterChanged, formatter: ({ cellValue }) => cellValue === 1 ? '是' : (cellValue === 0 ? '否' : cellValue)},
    {field: 'quantity', width: 50, title: '数量',},
    {field: 'area', width: 50, title: '面积',},
    {field: 'processCardQuantity', width: 100, title: '流程卡数量',},
    {field: 'usingQuantity', width: 100, title: '原片使用数',},
    {field: 'processCardCollection', width: 70, title: '流程卡',},
    {field: 'processCardCollection', width: 70, title: '流程卡',filters: [{data: ''}], slots: {filter: 'num1_filter'},filterMethod:filterChanged},
    {field: 'temperedLoadingRate', width: 100, title: '钢化装载率',},
    {field: 'numberOfTemperingFurnaces', width: 100, title: '钢化炉数',},
    {field: 'averageCuttingRate', width: 100, title: '平均切裁率',},
    {field: 'effectiveCuttingRate', width: 100, title: '有效切裁率',},
    {field: 'residueGlassCuttingRate', width: 100, title: '尾片切裁率',},
    {field: 'amountOfOriginalGlassUsage1', width: 100, title: '原料使用数',},
    {field: 'averageCuttingRate1', width: 100, title: '平均切裁率',},
    // {field: 'averageCuttingRate1', width: 100, title: '平均切裁率',},
    {field: 'notes', width: 50, title: '备注',},
    {field: 'creator', width: 100, title: '创建人',},
    {field: 'createTime', width: 100, title: '创建时间',},
    {field: 'modifyTime', width: 100, title: '修改时间',},
  ],//表头参数
  data: null,//表格数据
  toolbarConfig: {
    buttons: [
    ],
    import: false,
    // export: true,
    // print: true,
    zoom: true,
    custom: true
  },
  //右键菜单选项
  menuConfig: {
    body: {
      options: [
        [
          {code: 'openproject', name: '打开工程', prefixIcon: 'vxe-icon-folder-open'},
          {code: 'openProject', name: '打开工程', prefixIcon: 'vxe-icon-folder-open'},
          {code: 'compute', name: '模拟计算', prefixIcon: 'vxe-icon-subtable'},
          {code: 'optimizetypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'},
          {code: 'production', name: '允许生产', prefixIcon: 'vxe-icon-square-checked'},
          {code: 'novisible', name: '生产不可见', prefixIcon: 'vxe-icon-eye-fill-close'},
          //{code: 'optimizeTypography', name: '优化排版', prefixIcon: 'vxe-icon-menu'},
          {code: 'production', name: '确认生产', prefixIcon: 'vxe-icon-square-checked'},
          {code: 'novisible', name: '取消生产', prefixIcon: 'vxe-icon-eye-fill-close'},
          {code: 'copyproject', name: '复刻工程', prefixIcon: 'vxe-icon-copy'},
          {code: 'undooptimize', name: '撤销优化', prefixIcon: 'vxe-icon-error-circle-fill'},
          {code: 'undocompute', name: '撤销模拟计算', prefixIcon: 'vxe-icon-error-circle-fill'},
          {code: 'Initializeproject', name: '初始化工程', prefixIcon: 'vxe-icon-undo'},
          {code: 'delproject', name: '删除工程', prefixIcon: 'vxe-icon-delete'},
          {code: 'viewtempered ', name: '查看钢化版图', prefixIcon: 'vxe-icon-custom-column'},
          {code: 'viewoptimize', name: '查看优化版图', prefixIcon: 'vxe-icon-layout'},
          {code: 'undoOptimize', name: '撤销优化', prefixIcon: 'vxe-icon-error-circle-fill'},
          {code: 'undoCompute', name: '撤销模拟计算', prefixIcon: 'vxe-icon-error-circle-fill'},
          {code: 'InitializeProject', name: '初始化工程', prefixIcon: 'vxe-icon-undo'},
          {code: 'delProject', name: '删除工程', prefixIcon: 'vxe-icon-delete'},
          {code: 'viewTempered', name: '查看钢化版图', prefixIcon: 'vxe-icon-custom-column'},
          {code: 'viewOptimize', name: '查看优化版图', prefixIcon: 'vxe-icon-layout'},
          {code: 'Export', name: '数据导出', prefixIcon: 'vxe-icon-download', visible: true, disabled: false},
          {code: 'print', name: '打印优化报告', prefixIcon: 'vxe-icon-layout'},
          {code: 'print2', name: '打印优化版图报告', prefixIcon: 'vxe-icon-layout'},
        ],
        []
      ]
    },
  },
  toolbarConfig: {
    buttons: [],
    slots: {
      buttons: "toolbar_buttons"
    },
  },
})
//定义模拟计算弹窗默认隐藏
const optimizecompute = ref(false)
const Mange = ref(true)
//右键菜单点击事件
// 定义操作配置对象数组,集中管理不同操作选项对应的参数
const operationConfigs = [
  {
    code: 'openProject', // 打开工程
    initialState: ['1', '100', '200'], //
    targetState: null,
    successMsg: '已打开!',
    checkMessage: '当前工程状态不符合条件,请确认工程状态后再操作!',
    requiresRow: true,
    openFile: async ({row}) => {
      orderInfo.optimizeData.optimalResults=null
      orderInfo.optimizeData.originalFilm=null
      const projectNumber = row.projectNumber;
      const thickness = row.thickness;
      const glassType = row.glassType;
      const quantity = row.quantity;
      const area = row.area;
      const optimizeState = row.optimizeState;
      await router.push({
        name: 'optimizeInfo',
        params: {
          projectNo: projectNumber,
          thickNess: thickness,
          model: glassType,
          quantity: quantity,
          area: area,
          optimizeState:optimizeState
        }
      });
    }
  },
  {
    code: 'compute', // 打开模拟计算操作
    initialState: '1',
    temperingState: '0',
    targetState: null,
    successMsg: '模拟计算已启动!',
    checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
    actionFunction: async ({row}) => {
      const projectNo = row.projectNumber;
      emit('switch-dialog', row);
    }
  },
  {
    code: 'print', // 打印
    initialState: '1',
    temperingState: '0',
    targetState: null,
    successMsg: '模拟计算已启动!',
    checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
    actionFunction: async ({row}) => {
      const projectNo = row.projectNumber;
      emit('switch-dialog-print', row);
    }
  },
  {
    code: 'print2', // 打印
    initialState: '1',
    temperingState: '0',
    targetState: null,
    successMsg: '模拟计算已启动!',
    checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
    actionFunction: async ({row}) => {
      const projectNo = row.projectNumber;
      emit('switch-dialog-print2', row);
    }
  },
  {
    code: 'optimizeTypography',
    initialState: ['1','100'], //
    targetState: null,
    successMsg: '优化排版已启动!',
    checkMessage: '当前工程状态不符合优化排版条件,请确认工程状态后再操作!',
    requiresRow: true,
    Typography: async ({row}) => {
      const projectNumber = row.projectNumber;
      const thickness = row.thickness;
      const glassType = row.glassType;
      const quantity = row.quantity;
      const area = row.area;
      const optimizeState = row.optimizeState;
      await router.push({
        name: 'optimizeInfo',
        params: {
          projectNo: projectNumber,
          thickNess: thickness,
          model: glassType,
          quantity: quantity,
          area: area,
          optimizeState:optimizeState
        }
      });
    }
  },
  {
    code: 'undoCompute',
    initialState: 1,
    temperingState: 1,
    targetState: 0,
    targetStates: 0,
    successMsg: '撤销模拟计算成功,数据已更新!',
    checkMessage: '当前工程状态不符合撤销模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'undoOptimize',
    initialState: 1,
    optimizeState: 1,
    targetState: 0,
    targetStates: 0,
    successMsg: '撤销优化成功,数据已更新!',
    checkMessage: '当前工程状态不符合撤销优化条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'production',
    initialState: 1,
    // temperingState: 1,
    optimizeState: 1,
    targetState: 100,
    targetStates: 0,
    successMsg: '设置成功,允许生产!',
    checkMessage: '当前工程状态不符合允许生产条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'novisible',
    initialState: 100,
    // temperingState: 1,
    optimizeState: 1,
    targetState: 1,
    targetStates: 0,
    successMsg: '设置成功,生产不可见!',
    checkMessage: '当前工程状态不符合生产不可见条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'InitializeProject',
    initialState: '2',
    targetState: 1,
    successMsg: '初始化工程成功!',
    checkMessage: '当前工程状态不符合初始化条件,请确认工程状态后再操作!',
    requiresRow: true,
  },
  {
    code: 'delProject',
    initialState: ['1', '100'],
    targetState: null,
    successMsg: '工程删除成功!',
    checkMessage: '当前工程状态不符合删除条件,请确认工程状态后再操作!',
  },
  {
    code: 'Export', // 导出文件操作的配置
    initialState: [],
    targetState: null,
    successMsg: '文件导出成功!',
    gridRef: xGrid,
    requiresRow: false,
  },
  {
    code: 'viewTempered',
    initialState: [],
    targetState: null,
    successMsg: '钢化版图已打开!',
    failureMsg: '工程删除失败,请联系管理员!',
    requiresRow: true,
  },
  {
    code: 'viewOptimize',
    initialState: [],
    targetState: null,
    successMsg: '优化版图已打开!',
    failureMsg: '工程删除失败,请联系管理员!',
    requiresRow: true,
  }
];
function getOriginalState(targetState) {
  // 根据工程状态返回对应的原始状态
  const stateMapping = {
    1: '100',
    100: '1'
  };
  return stateMapping[targetState] || targetState;
}
//右键菜单条件判断
function checkOperationCondition(config, row) {
  if (!config.requiresRow || !row) {
    return false;
  }
  if (Array.isArray(config.initialState)) {
    return config.initialState.includes(String(row.state));
  }
  return config.initialState === String(row.state);
}
// 右键菜单点击事件
const gridEvents = {
  menuClick({menu, row, column}) {
    const $grid = xGrid.value
  menuClick({menu, row}) {
    const $grid = xGrid.value;
    if ($grid) {
      switch (menu.code) {
        case 'copy':
          if (row && column) {
            if (VxeUI.clipboard.copy(row[column.field])) {
              VxeUI.modal.message({content: '已复制到剪贴板!', status: 'success'})
            }
          }
          break
        case 'compute':
          optimizecompute.value = true;
          Mange.value = false;
          break
        case 'Export':
          $grid.exportData()
          break
        case 'undocompute':
          if (!row) {
            ElMessage.warning('未选中工程,请选中工程后再进行当前操作!');
      const config = operationConfigs.find(c => c.code === menu.code);
      if (config) {
        if (config.requiresRow && !row) {
          ElMessage.warning('未选中工程,请选中工程后再进行当前操作!');
          return;
        }
        if (config.code === 'Export') {
          config.gridRef.value.exportData();
          ElMessage.success(config.successMsg);
          return;
        }
        if (config.code === 'compute') {
          // 增加逻辑:检查钢化模拟列是否已经是"是"
          if (row.temperingState === 1) {
            ElMessage.warning('该项目已模拟计算');
            return;
          }
          if (String(row.state) === '10') {
            row.state = '2';
            const index = produceList.value.findIndex(item => item === row);
            if (index!== -1) {
              produceList.value.splice(index, 1, {...row });
              xGrid.value.reloadData(produceList.value);
          if(row.state===1 && row.temperingState===0){
            config.actionFunction({row});
          }else{
            ElMessage.warning(config.checkMessage);
          }
          return;
        }
        if (config.code === 'print') {
          if(row.optimizeState===1 ){
            config.actionFunction({row});
          }else{
            ElMessage.warning(config.checkMessage);
          }
          return;
        }
        if (config.code === 'print2') {
          if(row.optimizeState===1 ){
            config.actionFunction({row});
          }else{
            ElMessage.warning(config.checkMessage);
          }
          return;
        }
        else if (config.code === 'openProject') {
          handleSameDataOperation(row).then(({isRoutesEqual}) => {
            if (!isRoutesEqual) {
              config.openFile({row});
              ElMessage.success(config.successMsg);
            }
              const projectNumber = row.projectNumber;
              const state = 2; // 明确定义要更新的状态值为2
              const updateParams = {
                projectNumber: projectNumber,
                stateToUpdate: state
              };
            request.post(`/glassOptimize/updateProjectState/${projectNumber}/${state}`, updateParams, {
              headers: {
                'Content-Type': 'application/json'
          });
          return;
        }
        // 添加确认提示弹窗,询问用户是否进行当前操作
        ElMessageBox.confirm('是否进行当前操作?', '确认操作', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          if (config.code === 'viewTempered') {
            ElMessageBox.alert('当前点击的是查看钢化版图功能,目前暂时仅做提示,暂无实际查看操作!', '功能提示', {
              confirmButtonText: '我知道了'
            });
            return;
          }
          if (config.code === 'viewOptimize') {
            (async () => {
              if (!row) {
                ElMessage.warning('请选择要查看的工程');
                return;
              }
            }).then((res) => {
              if (res.code === 200 && res.data && res.data.success) { // 假设后端返回的data里有success字段表示操作是否成功,根据后端实际返回结构调整
                ElMessage.success('撤销模拟计算成功,数据已更新!');
              } else {
                console.log('撤销模拟计算失败,后端返回的详细信息:', res);
                const errorMsg = res.data? res.data.errorMessage : '撤销模拟计算失败,未获取到具体原因,请联系管理员'; // 尝试获取后端返回的详细错误消息,如果没有则显示通用提示
                ElMessage.error(`撤销模拟计算失败,原因: ${errorMsg}`);
                row.state = '10';
                const rollbackIndex = produceList.value.findIndex(item => item === row);
                if (rollbackIndex!== -1) {
                  produceList.value.splice(rollbackIndex, 1, {...row });
                  xGrid.value.reloadData(produceList.value);
              try {
                await router.push({
                  name: 'optimizeInfo',
                  params: {
                    projectNo: row.projectNumber,
                    thickNess: row.thickness,
                    model: row.glassType,
                    quantity: row.quantity,
                    area: row.area,
                    optimizeState: row.optimizeState
                  },
                  query: {
                    redirect: 'optimizeControl' // 添加跳转标识
                  }
                });
                // 同时保存 projectNo 到 localStorage 供后续页面使用
                localStorage.setItem('projectNo', row.projectNumber);
                console.log("projectNo:", row.projectNumber);
              } catch (error) {
                console.error('路由跳转失败:', error);
                ElMessage.error('页面跳转失败');
              }
            })();
            return;
          }
          if (config.code === 'delProject') {
            if (!row) {
              ElMessage.warning(config.checkMessage);
              return;
            }
            const isInitialStateMatched = config.initialState.includes(String(row.state));
            if (!isInitialStateMatched) {
              ElMessage.warning(config.checkMessage);
              return;
            }
            deleteProject(row.projectNumber, config);
          }else {
            if (config.code === 'optimizeTypography') {
              handleSameDataOperation(row).then(({isRoutesEqual}) => {
                if (!isRoutesEqual) {
                  config.Typography({row});
                  ElMessage.success(config.successMsg);
                  return;
                }
              });
            }
            else {
              let code=0
              if(config.code === 'undoCompute'){
                if(row.temperingState==1&&row.state===1){
                  row.temperingState = config.targetStates;
                  code=1
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }else if(config.code === 'undoOptimize'){
                if(row.optimizeState==1&&row.state===1){
                  // 先更新前端显示的状态
                  row.optimizeState = config.targetStates;
                  code=2;
                  // 更新列表中的数据以刷新显示
                  const index = produceList.value.findIndex(item => item === row);
                  if (index !== -1) {
                    produceList.value.splice(index, 1, {...row});
                    xGrid.value.reloadData(produceList.value);
                  }
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
            }).catch((error) => {
              console.error('请求出错,撤销模拟计算未完成,详细错误信息:', error);
              const errorMsg = error.message || '请求出错,未获取到具体原因,请联系管理员';
              ElMessage.error(`请求出错,撤销模拟计算未完成,原因: ${errorMsg}`);
              row.state = '10';
              const rollbackIndex = produceList.value.findIndex(item => item === row);
              if (rollbackIndex!== -1) {
                produceList.value.splice(rollbackIndex, 1, {...row });
              else if(config.code === 'production'){
                if(row.optimizeState===1&&row.state===1){
                  row.state = config.targetState;
                  code=3
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
              else if(config.code === 'novisible'){
                if(row.state===100){
                  row.state = config.targetState;
                  code=4
                }else{
                  ElMessage.warning(config.checkMessage);
                  return;
                }
              }
              const index = produceList.value.findIndex(item => item === row);
              if (index !== -1) {
                produceList.value.splice(index, 1, {...row});
                xGrid.value.reloadData(produceList.value);
              }
            });
          } else {
            ElMessage.warning('当前工程状态不符合撤销模拟计算条件,请确认工程状态后再操作!');
              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState,config.targetStates,code, config.successMsg);
            }
          }
          break;
        }).catch(() => {
          // 用户点击取消后执行的逻辑
          ElMessage.info('已取消操作');
        });
      } else {
        console.error(`未找到操作选项 ${menu.code} 对应的配置,请检查配置项`);
      }
    }
  },
  cellDblclick: ({row}) => {
    const menu = {code: 'openProject'};
    nextTick(() => {
      handleSameDataOperation(row).then(({isRoutesEqual}) => {
        if (!isRoutesEqual) {
          gridEvents.menuClick({menu, row});
        }
      });
    });
  },
};
// 公共处理函数,处理相同数据时的操作,并返回targetRoute对象(右键菜单和双击打开)
const handleSameDataOperation = async ({projectNumber, thickness, glassType,quantity,area,optimizeState}) => {
  const targetRoute = {
    name: 'optimizeInfo',
    params: {
      projectNo: projectNumber,
      thickNess: String(thickness),
      model: glassType,
      quantity: quantity,
      area: area,
      optimizeState:optimizeState
    }
  };
  const currentRoute = router.currentRoute.value;
  console.log(router.currentRoute.value)
  console.log(targetRoute)
  const isRoutesEqual = currentRoute.name === targetRoute.name &&
      currentRoute.params.projectNo === targetRoute.params.projectNo &&
      parseFloat(currentRoute.params.thickNess) === parseFloat(targetRoute.params.thickNess) &&
      currentRoute.params.model === targetRoute.params.model &&
      parseInt(currentRoute.params.quantity) === parseInt(targetRoute.params.quantity) &&
      parseFloat(currentRoute.params.area) === parseFloat(targetRoute.params.area)&&
      parseFloat(currentRoute.params.optimizeState) === parseFloat(targetRoute.params.optimizeState);
  if (isRoutesEqual) {
    handleConfirm();
  }
  return {isRoutesEqual};
};
//选中相同数据时弹窗提示
const handleConfirm = () => {
  const currentRoute = router.currentRoute.value;
  const projectNumber = currentRoute.params.projectNo;
  ElMessageBox.confirm(`当前工程(工程号:${projectNumber})已打开,是否重新打开?`, '确认操作', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
      .then(() => {
        emit('close-detail-page');
        ElMessage.success('已打开!');
      })
      .catch(() => {
        ElMessage.info('已取消操作');
      });
};
// 封装发送右键菜单请求、处理响应以及错误回滚等逻辑的函数
function rollbackStateAndReloadGrid(row, targetState) {
  row.state = getOriginalState(targetState);
  const rollbackIndex = produceList.value.findIndex(item => item === row);
  if (rollbackIndex !== -1) {
    produceList.value.splice(rollbackIndex, 1, {...row});
    xGrid.value.reloadData(produceList.value);
  }
}
function updateProjectStateAndHandleResponse(row, projectNumber, targetState, targetStates, code, successMsg) {
  const updateParams = {
    projectNumber: projectNumber,
    stateToUpdate: targetState,
    targetStates: targetStates
  };
  request.post(`/glassOptimize/updateProjectState/${projectNumber}/${targetState}/${targetStates}/${code}`, updateParams, {
    headers: {
      'Content-Type': 'application/json'
    }
  }).then((res) => {
    // 检查业务状态码,如果是201则抛出错误以在catch中处理
    if (Number(res.code) === 201) {
      // 抛出自定义错误对象,包含后端返回的msg信息
      throw new Error(res.msg || '操作失败');
    }
    if (Number(res.code) === 200 && (res.msg === "" || res.msg === null)) {
      ElMessage.success(successMsg);
    } else {
      console.log('res.code 的值:', res.code, ', 类型:', typeof res.code);
      console.log('res.msg 的值:', res.msg, ', 类型:', typeof res.msg);
      const errorMsg = res.data ? res.data.errorMessage : '操作失败,未获取到具体原因,请联系管理员';
      ElMessage.error(`操作失败,原因: ${errorMsg}`);
      rollbackStateAndReloadGrid(row, targetState); // 调用回滚函数
    }
  }).catch((error) => {
    console.error('请求出错,操作未完成,详细错误信息:', error);
    //const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : '操作失败,未获取到具体原因,请联系管理员';
    ElMessage.error(`请求出错,操作未完成  `+error);
    rollbackStateAndReloadGrid(row, targetState); // 调用回滚函数
  });
}
//删除工程
function deleteProject(projectNumber, config) {
  request.post(`/glassOptimize/deleteProject/${projectNumber}`, {
    headers: {
      'Content-Type': 'application/json'
    }
  }).then((res) => {
    if (res.code==200 && res.data===true) {
      ElMessage.success(config.successMsg);
      // 从列表中移除已删除的工程数据
      const index = produceList.value.findIndex(item => item.projectNumber === projectNumber);
      if (index !== -1) {
        produceList.value.splice(index, 1);
        xGrid.value.reloadData(produceList.value);
      }
    } else {
      console.log('res.code 的值:', res.code, ', 类型:', typeof res.code);
      console.log('res.msg 的值:', res.msg, ', 类型:', typeof res.msg);
      const errorMsg = res.data ? res.data.errorMessage : config.failureMsg;
      ElMessage.error(`操作失败,原因: ${errorMsg}`);
    }
  }).catch((error) => {
    console.error('请求出错,工程删除未完成,详细错误信息:', error);
    const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : config.failureMsg;
    ElMessage.error(`请求出错,工程删除未完成,原因: ${errorMsg}`);
  });
}
//定义切换模拟计算弹窗
const emit = defineEmits(['switch-dialog', 'close-detail-page','switch-dialog-print','switch-dialog-print2']);
//定义工程状态
const optionVal = ref('all')
const options = [
@@ -190,27 +642,27 @@
  },
  {
    value: '1',
    label: '初始工程',
    label: '初始状态,1',
  },
  {
  /*{
    value: '2',
    label: '第一次优化',
    label: '第一次优化,2',
  },
  {
    value: '10',
    label: '模拟计算保存',
    label: '模拟计算,10',
  },
  {
    value: '20',
    label: '优化保存',
  },
    label: '优化完成,20',
  },*/
  {
    value: '100',
    label: '完成优化',
    label: '生产可见,100',
  },
  {
    value: '200',
    label: '已领取',
    label: '生产领取,200',
  },
]
@@ -247,7 +699,7 @@
// 获取15天前到当前时间
function getNowTime() {
  const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 15)
  const start = new Date(new Date().getTime() - 3600 * 1000 * 24 * 70)
      .toISOString()
      .replace('T', ' ')
      .slice(0, 10) //默认开始时间15天前
@@ -271,13 +723,14 @@
    produceList.value = produceList.value.concat(deepClone(res.data.data))
    xGrid.value.reloadData(produceList.value);
    gridOptions.loading = false;
    console.log('工程管理表格数据',produceList.value);
  } else {
    ElMessage.warning(res.msg);
  }
})
/*使用筛选,后端获取数据*/
const changeFilterEvent = (event, option, $panel,) => {
/*const changeFilterEvent = (event, option, $panel,) => {
  // 手动触发筛选
  $panel.changeOption(event, !!option.data, option)
}
@@ -317,16 +770,17 @@
      ElMessage.warning(res.msg)
    }
  });
}
}*/
// 点击查询按钮触发的函数,根据当前筛选条件获取数据并加载到表格
const getWorkOrder = () => {
  const params = buildRequestParams();
  request.post(`/glassOptimize/optimizeProjectMange/${params.startSelectTime}/${params.endSelectTime}`, filterData.value).then((res) => {
    if (res.code == 200) {
      console.log(res.data.data)
      produceList.value = deepClone(res.data.data);
      gridOptions.data = produceList.value;
      xGrid.value.reloadData(produceList.value);
      xGrid.value.loadData(produceList.value);
      gridOptions.loading = false;
    } else {
      ElMessage.warning(res.msg);
@@ -351,90 +805,146 @@
// 原片面积固定为0,直接返回0
const originalPieceAreaInput = 0;
//日期左侧栏快捷选项
const shortcuts = [
  {
    text: '当日',
    value: () => {
      const end = new Date()
      const start = new Date(end)
      start.setHours(0, 0, 0, 0) // 设置为当天的凌晨 00:00:00
      return [start, end]
    }
  },
  {
    text: '近1周',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setDate(start.getDate() - 7)
      return [start, end]
    }
  },
  {
    text: '近1个月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setMonth(start.getMonth() - 1)
      return [start, end]
    }
  },
  {
    text: '近2个月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setMonth(start.getMonth() - 2)
      return [start, end]
    }
  },
  {
    text: '近3个月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setMonth(start.getMonth() - 3)
      return [start, end]
    }
  }
]
</script>
<template>
  <div id="mange">
    <glass-computed v-if="optimizecompute"/>
    <div style="height: 100%; width: 100%" v-if="Mange">
      <div id="select">
        <span>优化日期</span>
        <el-date-picker
            style="margin-left:10px; margin-top: -5px; "
            v-model="orderInfo.workOrderDate"
            :default-time="defaultTime"
            :start-placeholder="$t('basicData.startDate')"
            :end-placeholder="$t('basicData.endDate')"
            type="daterange"
            format="YYYY/MM/DD"
            value-format="YYYY-MM-DD"
        />
        <span class="input">工程状态</span>
        <el-select
            style="margin-left:10px; margin-top: -5px; width: 150px"
            :default-first-option="true"
            ref="getSelect"
            v-model="optionVal"
            clearable
            class="m-2"
            @change="handleOptionChange"
        >
          <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
          />
        </el-select>
        <!--查询-->
        <el-button
            style="margin-left:10px;margin-top: -5px"
            :icon="Search"
            type="primary"
            @click="getWorkOrder">{{ $t('basicData.search') }}
        </el-button>
      </div>
      <vxe-grid
          height="100%"
          class="mytable-scrollbar"
          ref="xGrid"
          v-bind="gridOptions"
          v-on="gridEvents"
          @filter-change="filterChanged"
    <div id="select" style="">
      <span>优化日期</span>
      <el-date-picker
          style="margin-left:10px; margin-top: -10px; "
          v-model="orderInfo.workOrderDate"
          :default-time="defaultTime"
          :start-placeholder="$t('basicData.startDate')"
          :end-placeholder="$t('basicData.endDate')"
          type="daterange"
          :shortcuts="shortcuts"
          showToday
          format="YYYY/MM/DD"
          value-format="YYYY-MM-DD"
      />
      <span class="input">工程状态</span>
      <el-select
          style="margin-left:10px; margin-top: -5px; width: 150px"
          :default-first-option="true"
          ref="getSelect"
          v-model="optionVal"
          clearable
          class="m-2"
          @change="handleOptionChange"
      >
        <template #select_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
              <vxe-select v-model="option.data" @change="changeFilterEvent($event, option, $panel)">
                <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
                <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
              </vxe-select>
            </div>
          </div>
        </template>
        <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
        />
      </el-select>
      <!--查询-->
      <el-button
          style="margin-left:10px;margin-top: -5px"
          :icon="Search"
          type="primary"
          @click="getWorkOrder">{{ $t('basicData.search') }}
      </el-button>
    </div>
        <template #num1_filter="{ column, $panel }">
          <div>
            <div v-for="(option, index) in column.filters" :key="index">
              <input v-model="option.data" type="text"
                     @keyup.enter.native="$panel.confirmFilter()"
                     @input="changeFilterEvent($event, option, $panel)"/>
            </div>
    <vxe-grid
        height="100%"
        class="mytable-scrollbar"
        ref="xGrid"
        v-bind="gridOptions"
        v-on="gridEvents"
    >
      <template #select_filter="{ column, $panel }">
        <div>
          <div v-for="(option, index) in column.filters" :key="index">
            <vxe-select v-model="option.data" @change="changeFilterEvent($event, option, $panel)">
              <vxe-option value="0" :label="$t('basicData.unchecked')"></vxe-option>
              <vxe-option value="1" :label="$t('basicData.selected')"></vxe-option>
            </vxe-select>
          </div>
        </template>
      </vxe-grid>
      <div id="last">
        小片数量
        <el-input class="input" disabled v-model="smallPieceQuantityInput"></el-input>
        小片面积
        <el-input class="input" disabled v-model="smallPieceAreaInput"></el-input>
        原片数量
        <el-input class="input" disabled v-model="originalPieceQuantityInput"></el-input>
        原片面积
        <el-input class="input" disabled v-model="originalPieceAreaInput"></el-input>
      </div>
        </div>
      </template>
      <template #select_filter1="{ column, $panel }">
        <div>
          <div v-for="(option, index) in column.filters" :key="index">
            <vxe-select v-model="option.data" @change="changeFilterEvent($event, option, $panel)">
              <vxe-option value="1" label="是"></vxe-option>
              <vxe-option value="0" label="否"></vxe-option>
            </vxe-select>
          </div>
        </div>
      </template>
      <template #num1_filter="{ column, $panel }">
        <div>
          <div v-for="(option, index) in column.filters" :key="index">
            <input type="type" v-model="option.data" @keyup.enter.native="$panel.confirmFilter()" @input="changeFilterEvent($event, option, $panel)"/>
          </div>
        </div>
      </template>
    </vxe-grid>
    <div id="last">
      小片数量
      <el-input class="input" disabled v-model="smallPieceQuantityInput"></el-input>
      小片面积
      <el-input class="input" disabled v-model="smallPieceAreaInput"></el-input>
      原片数量
      <el-input class="input" disabled v-model="originalPieceQuantityInput"></el-input>
      原片面积
      <el-input class="input" disabled v-model="originalPieceAreaInput"></el-input>
    </div>
  </div>
</template>
@@ -445,6 +955,10 @@
  height: 85%;
}
:deep(.vxe-button.type--button.is--circle) {
  margin-top: -20px;
}
#last {
  margin-top: 10px;
}