chenlu
2024-12-05 a7cc9c3be58bccd868bc8c12ed57c2b90fedc6b8
north-glass-erp/northglass-erp/src/views/pp/glassOptimize/ProjectMange.vue
@@ -8,12 +8,16 @@
import useOrderInfoStore from "@/stores/sd/order/orderInfo";
import useUserInfoStore from "@/stores/userInfo";
import userInfo from "@/stores/userInfo";
import GlassComputed from "@/views/pp/glassOptimize/GlassComputed.vue";
import {useRouter} from 'vue-router';
import {defineEmits} from 'vue';
const {t} = useI18n()
const userStore = useUserInfoStore()
const user = userInfo()
const orderInfo = useOrderInfoStore()
const router = useRouter();
const xGrid = ref()
const gridOptions = reactive({
@@ -75,16 +79,16 @@
    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: '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: '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},
@@ -105,6 +109,23 @@
// 定义操作配置对象数组,集中管理不同操作选项对应的参数
const operationConfigs = [
  {
    code: 'openProject', // 打开工程
    initialState: ['10', '20', '100', '200'], //
    targetState: null,
    successMsg: '已打开工程!',
    checkMessage: '当前工程状态不符合条件,请确认工程状态后再操作!',
    requiresRow: true,
    openFile: async ({row}) => {
      const projectNumber = row.projectNumber;
      await router.replace({
        name: 'projectDetail',
        params: {
          projectNo: projectNumber
        }
      });
    }
  },
  {
    code: 'compute', // 打开模拟计算操作
    initialState: ['1', '2'], //
    targetState: null,
@@ -112,22 +133,12 @@
    checkMessage: '当前工程状态不符合模拟计算条件,请确认工程状态后再操作!',
    requiresRow: true,
    actionFunction: async ({row}) => {
      console.log('获取的行数据', row);
      try {
        // 使用浏览器原生Clipboard API复制工程号
        await navigator.clipboard.writeText(row.projectNumber);
        console.log('工程号已复制到剪贴板');
        ElMessage.success('工程号已成功复制');
      } catch (error) {
        console.error('复制工程号时出错:', error);
        ElMessage.error('复制工程号失败,请稍后重试');
      const projectNumber = row.projectNumber;
      emit('switch-dialog', projectNumber);
      }
      optimizeCompute.value = true;
      Mange.value = false;
    }
  },
  {
    code: 'undocompute',
    code: 'undoCompute',
    initialState: '10',
    targetState: 2,
    successMsg: '撤销模拟计算成功,数据已更新!',
@@ -135,7 +146,7 @@
    requiresRow: true,
  },
  {
    code: 'undooptimize',
    code: 'undoOptimize',
    initialState: '20',
    targetState: 10,
    successMsg: '撤销优化成功,数据已更新!',
@@ -159,7 +170,7 @@
    requiresRow: true,
  },
  {
    code: 'Initializeproject',
    code: 'InitializeProject',
    initialState: ['2', '10', '20'],
    targetState: 1,
    successMsg: '初始化工程成功!',
@@ -167,7 +178,7 @@
    requiresRow: true,
  },
  {
    code: 'delproject',
    code: 'delProject',
    initialState: ['1', '2', '10', '20', '100'],
    targetState: null,
    successMsg: '工程删除成功!',
@@ -196,6 +207,7 @@
    failureMsg: '工程删除失败,请联系管理员!',
  }
];
function getOriginalState(targetState) {
  // 根据工程状态返回对应的原始状态
  const stateMapping = {
@@ -203,13 +215,14 @@
    10: '20',
    100: '200',
    200: '100',
    1:['2', '10', '20'],
    1: ['2', '10', '20'],
  };
  return stateMapping[targetState] || targetState;
}
//右键菜单条件判断
function checkOperationCondition(config, row) {
  if (!config.requiresRow ||!row) {
  if (!config.requiresRow || !row) {
    return false;
  }
  if (Array.isArray(config.initialState)) {
@@ -217,14 +230,15 @@
  }
  return config.initialState === String(row.state);
}
// 右键菜单点击事件
const gridEvents = {
  menuClick({ menu, row }) {
  menuClick({menu, row}) {
    const $grid = xGrid.value;
    if ($grid) {
      const config = operationConfigs.find(c => c.code === menu.code);
      if (config) {
        if (config.requiresRow &&!row) {
        if (config.requiresRow && !row) {
          ElMessage.warning('未选中工程,请选中工程后再进行当前操作!');
          return;
        }
@@ -239,45 +253,50 @@
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
        if (config.code === 'viewTempered'){
          ElMessageBox.alert('当前点击的是查看钢化版图功能,目前暂时仅做提示,暂无实际查看操作!', '功能提示', {
            confirmButtonText: '我知道了'
          });
          return;
        }
        if (config.code === 'viewOptimize'){
          ElMessageBox.alert('当前点击的是查看钢化版图功能,目前暂时仅做提示,暂无实际查看操作!', '功能提示', {
            confirmButtonText: '我知道了'
          });
          return;
        }
        if (config.code === 'delproject') {
          if (!row) {
            ElMessage.warning(config.checkMessage);
          if (config.code === 'viewTempered') {
            ElMessageBox.alert('当前点击的是查看钢化版图功能,目前暂时仅做提示,暂无实际查看操作!', '功能提示', {
              confirmButtonText: '我知道了'
            });
            return;
          }
          const isInitialStateMatched = config.initialState.includes(String(row.state));
          if (!isInitialStateMatched) {
            ElMessage.warning(config.checkMessage);
          if (config.code === 'viewOptimize') {
            ElMessageBox.alert('当前点击的是查看钢化版图功能,目前暂时仅做提示,暂无实际查看操作!', '功能提示', {
              confirmButtonText: '我知道了'
            });
            return;
          }
          deleteProject(row.projectNumber, config);
        } else if (!checkOperationCondition(config, row)) {
          ElMessage.warning(config.checkMessage);
          return;
        } else {
          if (config.code === 'compute') {
            config.actionFunction({ row });
          } else {
            row.state = config.targetState;
            const index = produceList.value.findIndex(item => item === row);
            if (index!== -1) {
              produceList.value.splice(index, 1, {...row });
              xGrid.value.reloadData(produceList.value);
          if (config.code === 'delProject') {
            if (!row) {
              ElMessage.warning(config.checkMessage);
              return;
            }
            updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState, config.successMsg);
            const isInitialStateMatched = config.initialState.includes(String(row.state));
            if (!isInitialStateMatched) {
              ElMessage.warning(config.checkMessage);
              return;
            }
            deleteProject(row.projectNumber, config);
          } else if (!checkOperationCondition(config, row)) {
            ElMessage.warning(config.checkMessage);
            return;
          } else {
            if (config.code === 'openProject') {
              config.openFile({row});
              ElMessage.success(config.successMsg);
            }else
            if (config.code === 'compute') {
              config.actionFunction({row});
            }
             else {
              row.state = config.targetState;
              const index = produceList.value.findIndex(item => item === row);
              if (index !== -1) {
                produceList.value.splice(index, 1, {...row});
                xGrid.value.reloadData(produceList.value);
              }
              updateProjectStateAndHandleResponse(row, row.projectNumber, config.targetState, config.successMsg);
            }
          }
        }
        }).catch(() => {
          // 用户点击取消后执行的逻辑
          ElMessage.info('已取消操作');
@@ -286,17 +305,23 @@
        console.error(`未找到操作选项 ${menu.code} 对应的配置,请检查配置项`);
      }
    }
  },
  cellDblclick: ({ row }) => {
    const menu = { code: 'openProject' };
    gridEvents.menuClick({ menu, row });  // 直接通过gridEvents对象调用menuClick
  }
};
// 封装发送右键菜单请求、处理响应以及错误回滚等逻辑的函数
function rollbackStateAndReloadGrid(row, targetState) {
  row.state = getOriginalState(targetState);
  const rollbackIndex = produceList.value.findIndex(item => item === row);
  if (rollbackIndex!== -1) {
  if (rollbackIndex !== -1) {
    produceList.value.splice(rollbackIndex, 1, {...row});
    xGrid.value.reloadData(produceList.value);
  }
}
function updateProjectStateAndHandleResponse(row, projectNumber, targetState, successMsg) {
  const updateParams = {
    projectNumber: projectNumber,
@@ -312,13 +337,13 @@
    } 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 : '操作失败,未获取到具体原因,请联系管理员';
      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 : '操作失败,未获取到具体原因,请联系管理员';
    const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : '操作失败,未获取到具体原因,请联系管理员';
    ElMessage.error(`请求出错,操作未完成,原因: ${errorMsg}`);
    rollbackStateAndReloadGrid(row, targetState); // 调用回滚函数
  });
@@ -335,26 +360,25 @@
      ElMessage.success(config.successMsg);
      // 从列表中移除已删除的工程数据
      const index = produceList.value.findIndex(item => item.projectNumber === projectNumber);
      if (index!== -1) {
      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;
      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;
    const errorMsg = (res.data && res.data.errorMessage) ? res.data.errorMessage : config.failureMsg;
    ElMessage.error(`请求出错,工程删除未完成,原因: ${errorMsg}`);
  });
}
//定义模拟计算弹窗默认隐藏
const optimizeCompute = ref(false)
const Mange = ref(true)
//定义切换模拟计算弹窗
const emit = defineEmits(['switch-dialog']);
//定义工程状态
const optionVal = ref('all')
@@ -531,85 +555,82 @@
<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">
      <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"
      >
        <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"
        @filter-change="filterChanged"
    >
      <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 #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>
        </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>