Browse Source

手动原始数据和送样卡

zhangafei 3 weeks ago
parent
commit
cf1d042394

+ 6 - 4
.env.development

@@ -5,14 +5,16 @@ VITE_USE_MOCK = false
 VITE_PUBLIC_PATH = /
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
-# VITE_PROXY = [["/jeecgboot","http://192.168.1.32:9999"],["/upload","http://localhost:3300/upload"]]
-VITE_PROXY = [["/jeecgboot","http://192.168.0.119:9999"],["/upload","http://localhost:3300/upload"]]
+VITE_PROXY = [["/jeecgboot","http://192.168.1.53:9999"],["/upload","http://localhost:3300/upload"]]
+# VITE_PROXY = [["/jeecgboot","http://192.168.1.8:9999"],["/upload","http://localhost:3300/upload"]]
+# VITE_PROXY = [["/jeecgboot","http://192.168.0.119:9999"],["/upload","http://localhost:3300/upload"]]
 # VITE_PROXY = [["/jeecgboot","http://123.57.213.14:9898"],["/upload","http://localhost:3300/upload"]]
 
 #后台接口全路径地址(必填)
 # VITE_GLOB_DOMAIN_URL=http://localhost:9999
-# VITE_GLOB_DOMAIN_URL=http://192.168.1.32:9999
-VITE_GLOB_DOMAIN_URL=http://192.168.0.119:9999
+# VITE_GLOB_DOMAIN_URL=http://192.168.1.8:9999
+VITE_GLOB_DOMAIN_URL=http://192.168.1.53:9999
+# VITE_GLOB_DOMAIN_URL=http://192.168.0.119:9999
 # VITE_GLOB_DOMAIN_URL=http://123.57.213.14:9898
 
 

+ 16 - 0
src/views/billet/Dashboard/dashboard.api.ts

@@ -58,8 +58,24 @@ enum Api {
   confirmRecord = '/billet/billetOriginalProductRecord/confirmRecord',
   // 棒线工作台统计
   rollClubStatistics = '/billet/billetOriginalProductRecord/queryBilletStatisticsDetailByCcmNo',
+  // 导出
+  exportOneXlsUrl = '/rollClubOne/exportOneXls', // 棒一
+  exportThreeXlsUrl = '/rollClubThreeDetails/exportThreeXls', // 棒三
+  exportOutXlsUrl = '/rollOutShippDetails/exportOutXls', // 上若
 }
 
+export const exportOneExcel = () => {
+  return Api.exportOneXlsUrl;
+};
+
+export const exportThreeExcel = () => {
+  return Api.exportThreeXlsUrl;
+};
+
+export const exportOutExcel = () => {
+  return Api.exportOutXlsUrl;
+};
+
 export interface ListItem {
   size: string;
   nums: number;

+ 178 - 17
src/views/billet/Dashboard/rollingOne.vue

@@ -1,7 +1,22 @@
 <template>
   <div class="rolling-three-dashboard flex flex-col">
     <div class="search-wrapper">
-      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleSubmit" />
+      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleReSubmit">
+        <template #shiftObj>
+          <div class="shift-performance-tags flex-1">
+            <a-tag :color="shiftColor[index]" @click="() => (currentShift = index)" v-for="(item, index) in shiftPerformanceColumns">
+              {{ item.createTime ? item.createTime.substring(5, 16) : '' }} ~
+              {{ item.changeShiftTime ? item.changeShiftTime.substring(5, 16) : '' }}
+              【{{ getTeamShift(item.shift, item.shiftGroup) }}】
+              <span class="current-shift" :style="{ background: shiftColor[index] }" v-if="index === currentShift"></span>
+            </a-tag>
+          </div>
+        </template>
+
+        <template #advanceBefore>
+          <a-button type="primary" preIcon="ant-design:export-outlined" style="margin-right: 10px" @click="onExportXls"> 导出</a-button>
+        </template>
+      </BasicForm>
     </div>
     <a-spin :spinning="loading">
       <div class="common-table">
@@ -170,7 +185,7 @@
 </template>
 <script setup lang="ts">
   import { onMounted, ref } from 'vue';
-  import { getRollClubOneList, confirmRollClubOne, getrollClubStatistics } from './dashboard.api';
+  import { getRollClubOneList, confirmRollClubOne, getrollClubStatistics, exportOneExcel } from './dashboard.api';
   import dayjs, { Dayjs } from 'dayjs';
   import { useForm, BasicForm, FormSchema } from '/@/components/Form';
   import { Empty } from 'ant-design-vue';
@@ -178,15 +193,18 @@
   import { getMachineNum } from '../hotDelivery/common.data';
   import { Pagination as APagination } from 'ant-design-vue';
   import { useUserStore } from '/@/store/modules/user';
+  import { list } from '../ShiftPerformance/ShiftPerformance.api';
+  import { getTeamShift } from '../Dashboard/dashboard.api';
+  import { useMethods } from '/@/hooks/system/useMethods';
 
+  // 导入导出方法
+  const { handleExportXlsx } = useMethods();
   const userStore = useUserStore();
 
   const isAuth = userStore.userInfo && userStore.userInfo.username === '5';
 
   const threeList = ref<any[]>([]);
-  const dateObj = ref<Dayjs>(dayjs());
   const machineNum = getMachineNum(true) || '3';
-  const changeShiftId = ref('');
 
   // 明细展示
   const dtlList = ref<any[]>([
@@ -212,17 +230,56 @@
     return render.renderDict(value, dictCode);
   };
 
+  const shiftPerformanceColumns = ref<any>([]);
+  const shiftColor = ['#f50', '#2db7f5', '#87d068'];
+  const currentShift = ref(-1);
   //自定义表单字段
   const formSchemas: FormSchema[] = [
+    {
+      label: '炉号',
+      field: 'heatNo',
+      component: 'Input',
+    },
+    {
+      label: '定尺',
+      field: 'size',
+      component: 'Input',
+    },
     {
       label: '日期',
       field: 'arrivalTime',
+      component: 'RangePicker',
+      componentProps: {
+        showTime: true,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      },
+    },
+    {
+      label: '',
+      field: 'yuzhanyuan',
+      component: 'Input',
+      slot: 'yuzhanyuan',
+      colProps: { span: 6 },
+    },
+    {
+      label: '班次日期',
+      field: 'queryDate',
       component: 'DatePicker',
       componentProps: {
-        showTime: false,
         valueFormat: 'YYYY-MM-DD',
+        onChange: (v) => {
+          currentShift.value = -1;
+          getShiftInfo(3, dayjs(v));
+        },
       },
     },
+    {
+      label: '',
+      field: 'shiftObj',
+      component: 'Input',
+      slot: 'shiftObj',
+      colProps: { span: 12 },
+    },
     // {
     //   label: '班组',
     //   field: 'shiftGroup',
@@ -247,14 +304,14 @@
     //注册表单列
     schemas: formSchemas,
     //是否显示展开收起按钮,默认false
-    showAdvancedButton: true,
+    showAdvancedButton: false,
     //超过指定行数折叠,默认3行
     autoAdvancedCol: 3,
     //折叠时默认显示行数,默认1行
     alwaysShowLines: 3,
     //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
     fieldMapToTime: [
-      // ['createTime', ['createTime_begin', 'createTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+      ['arrivalTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'],
       // ['storageTime', ['storageTime_begin', 'storageTime_end'], 'YYYY-MM-DD HH:mm:ss'],
     ],
     //每列占比,默认一行为24
@@ -271,6 +328,14 @@
     getStatistics();
   }
 
+  function handleReSubmit() {
+    currentShift.value = -1;
+    currentPage.value = 1;
+    shiftPerformanceColumns.value = [];
+    getList();
+    getStatistics();
+  }
+
   const currentPage = ref(1);
   const totalPage = ref(0);
   const pageLimit = ref(20);
@@ -296,13 +361,19 @@
 
       if (!values.arrivalTime) {
         params = Object.assign({}, values, {
-          arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
-          destination: destinationTxt[machineNum],
+          // arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
+          // destination: destinationTxt[machineNum],
         });
       }
 
+      // 班次
+      let changeShiftId = undefined;
+      if (currentShift.value !== -1) {
+        changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
+      }
+
       loading.value = true;
-      const res = await getRollClubOneList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params });
+      const res = await getRollClubOneList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params, changeShiftId });
 
       totalPage.value = res.total;
       currentPage.value = res.current;
@@ -363,12 +434,14 @@
   const getStatistics = async () => {
     try {
       const values = getFieldsValue();
-      const staticsRres = await getrollClubStatistics({
-        ccmNo: '5',
-        queryType: '1',
-        changeShiftId: changeShiftId.value || undefined,
-        queryDate: values.arrivalTime ? values.arrivalTime : dayjs().format('YYYY-MM-DD'),
-      });
+      let params: any = Object.assign({}, values, { queryType: '1', ccmNo: '5' });
+      // 班次
+      let changeShiftId = undefined;
+      if (currentShift.value !== -1) {
+        changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
+      }
+
+      const staticsRres = await getrollClubStatistics({ ...params, changeShiftId });
       const res = staticsRres[0];
       dtlList.value[0].blankOutput = res.totalWeight || 0;
       dtlList.value[0].nums = res.counts || 0;
@@ -376,7 +449,7 @@
         5: { blankOutput: 0, nums: 0 },
       };
       let statisticsDetailsList5: any[] = [];
-      res.rollClubOneStatisticsList.forEach((element) => {
+      res.billetStatisticList.forEach((element) => {
         statisticsDetailsList5.push({ ...element, nums: element.amountTotal, blankOutput: element.blankOutput.toFixed(4) });
         totalObj[5].blankOutput += element.blankOutput;
         totalObj[5].nums += element.amountTotal;
@@ -405,8 +478,74 @@
     }
   };
 
+  // 获取班次信息
+  const getShiftInfo = async (pageSize: number = 3, date?: Dayjs) => {
+    const formVals = getFieldsValue();
+    try {
+      if (date && !date.isValid()) {
+        shiftPerformanceColumns.value = [];
+        currentShift.value = -1;
+        return false;
+      }
+
+      loading.value = true;
+      const createTime_begin = date ? date.subtract(1, 'day').format('YYYY-MM-DD 23:55:00') : undefined;
+      const createTime_end = date ? date.add(1, 'day').format('YYYY-MM-DD 00:05:00') : undefined;
+      const res = await list({
+        ccmNo: formVals.ccmNo || '5',
+        pageNo: 1,
+        pageSize: pageSize,
+        column: 'createTime',
+        order: 'asc',
+        ...(date ? { createTime_begin, createTime_end } : {}),
+      });
+      const { records } = res;
+
+      const arr = records || [];
+
+      shiftPerformanceColumns.value = arr
+        .filter((item) => item.createTime && item.changeShiftTime) // 过滤掉 createTime 为空的数据
+        .sort((a, b) => {
+          const dateA = new Date(a.createTime).getTime(); // 转换为时间戳
+          const dateB = new Date(b.createTime).getTime(); // 转换为时间戳
+          if (isNaN(dateA) || isNaN(dateB)) {
+            console.warn('Invalid date detected:', a.createTime, b.createTime);
+            return 0; // 如果日期无效,视为相等
+          }
+          return dateA - dateB; // 按时间戳排序
+        });
+
+      // currentShift.value = shiftPerformanceColumns.value.length > 0 ? shiftPerformanceColumns.value.length - 1 : 0;
+    } catch (error) {
+      console.error(error);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 导出
+  const onExportXls = () => {
+    const values = getFieldsValue();
+    let params = Object.assign({}, values, { ccmNo: '5' });
+    if (currentShift.value >= 0) {
+      params = {
+        changeShiftId: shiftPerformanceColumns.value[currentShift.value].id,
+        queryDate: values.queryDate,
+        ccmNo: '5',
+      };
+    }
+
+    let queryParams = Object.keys(params)
+      .filter((v) => params[v])
+      .map((key) => {
+        return `${key}=${params[key]}`;
+      });
+    return handleExportXlsx('棒一数据', exportOneExcel() + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
+  };
+
   onMounted(() => {
     getList();
+    // getShiftInfo(3, dayjs());
     getStatistics();
   });
 </script>
@@ -584,5 +723,27 @@
         }
       }
     }
+
+    .shift-performance-tags {
+      margin-left: 10px;
+
+      .ant-tag {
+        padding: 6px 6px;
+        position: relative;
+        cursor: pointer;
+        margin-bottom: 20px;
+      }
+
+      .current-shift {
+        position: absolute;
+        display: inline-block;
+        width: 60px;
+        height: 4px;
+        border-radius: 4px;
+        bottom: -8px;
+        left: 50%;
+        transform: translateX(-30px);
+      }
+    }
   }
 </style>

+ 216 - 22
src/views/billet/Dashboard/rollingThree.vue

@@ -1,18 +1,33 @@
 <template>
   <div class="rolling-three-dashboard flex flex-col">
     <div class="search-wrapper">
-      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleSubmit">
+      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleReSubmit">
         <template #ccmNo="{ model, field }">
           <segmented-select
             v-model:value="model[field]"
             @change="
               () => {
-                handleSubmit();
+                handleReSubmit();
               }
             "
             dict="lg_zj"
           />
         </template>
+
+        <template #shiftObj>
+          <div class="shift-performance-tags flex-1">
+            <a-tag :color="shiftColor[index]" @click="() => (currentShift = index)" v-for="(item, index) in shiftPerformanceColumns">
+              {{ item.createTime ? item.createTime.substring(5, 16) : '' }} ~
+              {{ item.changeShiftTime ? item.changeShiftTime.substring(5, 16) : '' }}
+              【{{ getTeamShift(item.shift, item.shiftGroup) }}】
+              <span class="current-shift" :style="{ background: shiftColor[index] }" v-if="index === currentShift"></span>
+            </a-tag>
+          </div>
+        </template>
+
+        <template #advanceBefore>
+          <a-button type="primary" preIcon="ant-design:export-outlined" style="margin-right: 10px" @click="onExportXls"> 导出</a-button>
+        </template>
       </BasicForm>
     </div>
     <a-spin :spinning="loading">
@@ -95,7 +110,9 @@
                   /
                   <component :is="renderDictTag(item.shiftGroup, 'lg_bz')" />
                 </div>
-                <div class="flex-1" style="text-align: right"> {{ item.ccmNo }}#机 / {{ item.btype == 1 ? '冷' : '热' }} </div>
+                <div class="flex-1" style="text-align: right">
+                  {{ item.ccmNo }}#机 / {{ item.btype === '1' ? '冷' : item.btype === '0' ? '热' : '' }}
+                </div>
               </div>
               <a-descriptions class="ticket-info" layout="vertical" bordered :column="8" size="small">
                 <a-descriptions-item class="ticket-info-item" label="序号">
@@ -174,7 +191,7 @@
 </template>
 <script setup lang="ts">
   import { onMounted, ref } from 'vue';
-  import { getStorageBillPrintList, saveStorageBillPrint, getrollClubStatistics } from './dashboard.api';
+  import { getStorageBillPrintList, saveStorageBillPrint, getrollClubStatistics, exportThreeExcel, exportOutExcel } from './dashboard.api';
   import dayjs, { Dayjs } from 'dayjs';
   import { useForm, BasicForm, FormSchema } from '/@/components/Form';
   import SegmentedSelect from '/@/components/SegmentedSelect/index.vue';
@@ -188,15 +205,18 @@
   import { Pagination as APagination } from 'ant-design-vue';
   import { useUserStore } from '/@/store/modules/user';
   import { cloneDeep } from 'lodash-es';
+  import { list } from '../ShiftPerformance/ShiftPerformance.api';
+  import { getTeamShift } from '../Dashboard/dashboard.api';
+  import { useMethods } from '/@/hooks/system/useMethods';
 
+  // 导入导出方法
+  const { handleExportXlsx } = useMethods();
   const userStore = useUserStore();
 
   const isAuth = userStore.userInfo && userStore.userInfo.username === '5';
 
   const threeList = ref<any[]>([]);
-  const dateObj = ref<Dayjs>(dayjs());
   const machineNum = getMachineNum(true) || '3';
-  const changeShiftId = ref('');
 
   // 注册打印modal
   const [registerPrintModal, { openModal: openPrintModal }] = useModal();
@@ -205,6 +225,9 @@
     return render.renderDict(value, dictCode);
   };
 
+  const shiftPerformanceColumns = ref<any>([]);
+  const shiftColor = ['#f50', '#2db7f5', '#87d068'];
+  const currentShift = ref(-1);
   //自定义表单字段
   const formSchemas: FormSchema[] = [
     {
@@ -218,15 +241,66 @@
       colProps: { span: 6 },
       slot: 'ccmNo',
     },
+    {
+      label: '炉号',
+      field: 'heatNo',
+      component: 'Input',
+    },
+    {
+      label: '车号',
+      field: 'licensePlate',
+      component: 'Input',
+    },
+    {
+      label: '定尺',
+      field: 'size',
+      component: 'Input',
+    },
+    {
+      label: '类型',
+      field: 'btype',
+      component: 'JDictSelectTag',
+      componentProps: {
+        dictCode: 'lg_btype',
+      },
+      colProps: { span: 6 },
+    },
     {
       label: '日期',
       field: 'arrivalTime',
-      component: 'DatePicker',
+      component: 'RangePicker',
       componentProps: {
         showTime: true,
         valueFormat: 'YYYY-MM-DD HH:mm:ss',
       },
     },
+    {
+      label: '',
+      field: 'zidingyi',
+      component: 'Input',
+      colProps: { span: 12 },
+      slot: 'zidingyi',
+    },
+    {
+      label: '班次日期',
+      field: 'queryDate',
+      component: 'DatePicker',
+      componentProps: {
+        valueFormat: 'YYYY-MM-DD',
+        onChange: (v) => {
+          currentShift.value = -1;
+          getShiftInfo(3, dayjs(v));
+        },
+      },
+    },
+    {
+      label: '',
+      field: 'shiftObj',
+      component: 'Input',
+      slot: 'shiftObj',
+      colProps: { span: 12 },
+    },
+
     // {
     //   label: '班组',
     //   field: 'shiftGroup',
@@ -251,14 +325,14 @@
     //注册表单列
     schemas: formSchemas,
     //是否显示展开收起按钮,默认false
-    showAdvancedButton: true,
+    showAdvancedButton: false,
     //超过指定行数折叠,默认3行
     autoAdvancedCol: 3,
     //折叠时默认显示行数,默认1行
     alwaysShowLines: 3,
     //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
     fieldMapToTime: [
-      // ['createTime', ['createTime_begin', 'createTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+      ['arrivalTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'],
       // ['storageTime', ['storageTime_begin', 'storageTime_end'], 'YYYY-MM-DD HH:mm:ss'],
     ],
     //每列占比,默认一行为24
@@ -275,6 +349,14 @@
     getStatistics();
   }
 
+  function handleReSubmit() {
+    currentShift.value = -1;
+    currentPage.value = 1;
+    shiftPerformanceColumns.value = [];
+    getList();
+    getStatistics();
+  }
+
   const currentPage = ref(1);
   const totalPage = ref(0);
   const pageLimit = ref(20);
@@ -286,13 +368,11 @@
   // 获取列表
   const loading = ref(false);
   const destinationTxt = {
+    '2': '棒二',
     '3': '棒三',
     '4': '上若',
   };
-  const nbDetinationTxt = {
-    '3': 'rollClubThreeStatisticsList',
-    '4': 'rollOutShippStatisticsList',
-  };
+
   const getList = async () => {
     try {
       const values = getFieldsValue();
@@ -304,13 +384,19 @@
 
       if (!values.arrivalTime) {
         params = Object.assign({}, values, {
-          arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
+          // queryDate: dateObj.value.format('YYYY-MM-DD'),
           destination: destinationTxt[machineNum],
         });
       }
 
+      // 班次
+      let changeShiftId = undefined;
+      if (currentShift.value !== -1) {
+        changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
+      }
+
       loading.value = true;
-      const res = await getStorageBillPrintList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params });
+      const res = await getStorageBillPrintList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params, changeShiftId });
 
       totalPage.value = res.total;
       currentPage.value = res.current;
@@ -420,12 +506,15 @@
     const ccmNo = values.ccmNo || '5';
     let dtlItems: any = cloneDeep(defaultDtl);
     try {
-      const staticsRres = await getrollClubStatistics({
-        ccmNo,
-        queryType: machineNum,
-        changeShiftId: changeShiftId.value || undefined,
-        queryDate: values.arrivalTime ? values.arrivalTime : dayjs().format('YYYY-MM-DD HH:mm:ss'),
-      });
+      let params: any = Object.assign({}, values, { destination: destinationTxt[machineNum], queryType: machineNum, ccmNo });
+
+      // 班次
+      let changeShiftId = undefined;
+      if (currentShift.value !== -1) {
+        changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
+      }
+
+      const staticsRres = await getrollClubStatistics({ ...params, changeShiftId });
       const res = staticsRres[0];
       dtlItems[0].blankOutput = res.totalWeight || 0;
       dtlItems[0].nums = res.counts || 0;
@@ -436,7 +525,7 @@
       let statisticsDetailsList5: any[] = [];
       let statisticsDetailsList6: any[] = [];
 
-      (res[nbDetinationTxt[machineNum]] || []).forEach((element) => {
+      (res.billetStatisticList || []).forEach((element) => {
         if (ccmNo === '5') {
           statisticsDetailsList5.push({ ...element, nums: element.amountTotal, blankOutput: element.blankOutput.toFixed(4) });
           totalObj[5].blankOutput += element.blankOutput;
@@ -476,8 +565,80 @@
     }
   };
 
+  // 获取班次信息
+  const getShiftInfo = async (pageSize: number = 3, date?: Dayjs) => {
+    const formVals = getFieldsValue();
+    try {
+      if (date && !date.isValid()) {
+        shiftPerformanceColumns.value = [];
+        currentShift.value = -1;
+        return false;
+      }
+
+      loading.value = true;
+      const createTime_begin = date ? date.subtract(1, 'day').format('YYYY-MM-DD 23:55:00') : undefined;
+      const createTime_end = date ? date.add(1, 'day').format('YYYY-MM-DD 00:05:00') : undefined;
+      const res = await list({
+        ccmNo: formVals.ccmNo || '5',
+        pageNo: 1,
+        pageSize: pageSize,
+        column: 'createTime',
+        order: 'asc',
+        ...(date ? { createTime_begin, createTime_end } : {}),
+      });
+      const { records } = res;
+
+      const arr = records || [];
+
+      shiftPerformanceColumns.value = arr
+        .filter((item) => item.createTime && item.changeShiftTime) // 过滤掉 createTime 为空的数据
+        .sort((a, b) => {
+          const dateA = new Date(a.createTime).getTime(); // 转换为时间戳
+          const dateB = new Date(b.createTime).getTime(); // 转换为时间戳
+          if (isNaN(dateA) || isNaN(dateB)) {
+            console.warn('Invalid date detected:', a.createTime, b.createTime);
+            return 0; // 如果日期无效,视为相等
+          }
+          return dateA - dateB; // 按时间戳排序
+        });
+
+      // currentShift.value = shiftPerformanceColumns.value.length > 0 ? shiftPerformanceColumns.value.length - 1 : 0;
+    } catch (error) {
+      console.error(error);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 导出
+  const onExportXls = () => {
+    const values = getFieldsValue();
+    let params = Object.assign({}, values, { ccmNo: values.ccmNo || '5' });
+    if (currentShift.value >= 0) {
+      params = {
+        changeShiftId: shiftPerformanceColumns.value[currentShift.value].id,
+        queryDate: values.queryDate,
+        ccmNo: values.ccmNo || '5',
+      };
+    }
+
+    let queryParams = Object.keys(params)
+      .filter((v) => params[v])
+      .map((key) => {
+        return `${key}=${params[key]}`;
+      });
+    let url = '';
+    if (machineNum === '3') {
+      url = exportThreeExcel();
+    } else if (machineNum === '4') {
+      url = exportOutExcel();
+    }
+    return handleExportXlsx(destinationTxt[machineNum] + '数据', url + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
+  };
+
   onMounted(() => {
     getStatistics();
+    // getShiftInfo(3, dayjs());
     getList();
   });
 </script>
@@ -508,6 +669,17 @@
         .ant-form-item .ant-form-item-label > label {
           color: #fff;
         }
+
+        .ant-col-12 {
+          width: 100%;
+
+          .ant-form-item-row {
+            .ant-form-item-control {
+              flex: 1;
+              max-width: 100%;
+            }
+          }
+        }
       }
     }
 
@@ -647,5 +819,27 @@
         }
       }
     }
+
+    .shift-performance-tags {
+      margin-left: 10px;
+
+      .ant-tag {
+        padding: 6px 6px;
+        position: relative;
+        cursor: pointer;
+        margin-bottom: 20px;
+      }
+
+      .current-shift {
+        position: absolute;
+        display: inline-block;
+        width: 60px;
+        height: 4px;
+        border-radius: 4px;
+        bottom: -8px;
+        left: 50%;
+        transform: translateX(-30px);
+      }
+    }
   }
 </style>

+ 16 - 14
src/views/billet/ShiftPerformance/index.vue

@@ -65,20 +65,22 @@
                         type="primary"
                         style="margin-left: 10px"
                         @click="
-                          openPrintOriginalRecordsModal(true, {
-                            ccmNo: machine,
-                            queryType: '2',
-                            shiftText: '',
-                            time:
-                              shiftPerformanceColumns[currentShift] && shiftPerformanceColumns[currentShift].changeShiftTime
-                                ? dayjs(shiftPerformanceColumns[currentShift].changeShiftTime).subtract(3, 'hour').format('YYYY-MM-DD HH:mm:ss')
-                                : '',
-                            curShiftInfo: {
-                              shift: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shift : '',
-                              shiftGroup: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shiftGroup : '',
-                            },
-                            changeShiftId: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].id : '',
-                          })
+                          () =>
+                            shiftPerformanceColumns[currentShift] &&
+                            openPrintOriginalRecordsModal(true, {
+                              ccmNo: machine,
+                              queryType: '2',
+                              shiftText: '',
+                              time:
+                                shiftPerformanceColumns[currentShift] && shiftPerformanceColumns[currentShift].changeShiftTime
+                                  ? dayjs(shiftPerformanceColumns[currentShift].changeShiftTime).subtract(3, 'hour').format('YYYY-MM-DD HH:mm:ss')
+                                  : '',
+                              curShiftInfo: {
+                                shift: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shift : '',
+                                shiftGroup: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shiftGroup : '',
+                              },
+                              changeShiftId: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].id : '',
+                            })
                         "
                       >
                         原始数据

+ 2 - 2
src/views/billet/operator/components/car.vue

@@ -23,7 +23,7 @@
                   openPrintModal(true, {
                     record: vehicleInfo['info' + item],
                     typeConfigId: !vehicleInfo['info' + item].typeConfigId ? '1024' : vehicleInfo['info' + item].typeConfigId,
-                    type: 'offline'
+                    type: 'offline',
                   })
               "
               >打印</a-button
@@ -170,7 +170,7 @@
               pageNo: 1,
               pageSize: 1,
               positionNum: item,
-              ccmNo: props.ccmNo,
+              ...(item == 2 ? {} : { ccmNo: props.ccmNo }),
             })
           );
         });

+ 448 - 0
src/views/billet/operator/components/headTop - 副本.vue

@@ -0,0 +1,448 @@
+<template>
+  <a-row class="head-top">
+    <a-col :span="3" class="head-no bg flex items-center justify-center"
+      ><a-badge status="processing" /> 浇铸炉号:{{ info.billetHotsendChangeShift.heatNo }}
+    </a-col>
+    <a-col :span="1" class="amount-no bg flex items-center justify-center">
+      <a-statistic title="支数" :value="info.currentCastingFurnaceAmount || 0" />
+    </a-col>
+    <a-col :span="2" class="amount-no bg flex items-center justify-center">
+      <a-statistic title="重量/t" :value="info.currentCastingFurnace ? info.currentCastingFurnace.toFixed(3) : 0" />
+    </a-col>
+    <a-col :span="1" class="flex items-center justify-center">
+      <a-button type="primary" class="change-heat" @click="switchHeatNo" :loading="changeHeatLoading">换炉</a-button>
+    </a-col>
+    <a-col :span="1" class="current-shift flex items-center justify-center">当班统计:</a-col>
+    <a-col :span="1" class="flex items-center justify-center">
+      <a-statistic title="总支数" :value="info.billetHotsendChangeShift.shiftSum" />
+    </a-col>
+    <a-col :span="2" class="flex items-center justify-center">
+      <a-statistic title="总重量/t" :value="info.billetHotsendChangeShift.shiftProduct ? info.billetHotsendChangeShift.shiftProduct.toFixed(3) : 0" />
+    </a-col>
+    <a-col :span="3" class="flex flex-col" v-for="item of typeList">
+      <div class="type-item">
+        <span class="type-title" :style="{ color: item.titleColor }">{{ item.title }}:</span> {{ item.amount }} 支 / {{ item.weight }} t
+      </div>
+      <div class="type-item" v-for="ele of item.dtlList">
+        <div class="type-item-dtl">
+          <span class="type-title">{{ ele.size }}:</span> {{ ele.nums }} 支 / {{ ele.weight }} t
+        </div>
+      </div>
+      <!-- 冷床 -->
+      <template v-if="item.title == '堆垛'">
+        <template v-for="lc in coldBed">
+          <div class="type-item" style="border-top: 1px solid #108ee9;">
+            <span class="type-title" :style="{ color: lc.titleColor }">{{ lc.title }}:</span> {{ lc.amount }} 支 / {{ lc.weight }} t
+          </div>
+          <div class="type-item" v-for="lele of lc.dtlList">
+            <div class="type-item-dtl">
+              <span class="type-title">{{ lele.size }}:</span> {{ lele.nums }} 支 / {{ lele.weight }} t
+            </div>
+          </div>
+        </template>
+      </template>
+    </a-col>
+    <a-col :span="2" class="paihao flex flex-col items-center justify-center"
+      >当前牌号:<br /><component :is="renderDictTag(info.brandNum, 'billet_spec')"
+    /></a-col>
+    <a-col :span="2" class="current-shift flex items-center justify-center">
+      <a-button type="primary" danger @click="openPaihaoModal = true">切换牌号</a-button>
+    </a-col>
+  </a-row>
+  <a-modal
+    v-model:open="openPaihaoModal"
+    title="切换牌号"
+    centered
+    width="400px"
+    ok-text="确认"
+    :okButtonProps="{ loading: okLoading }"
+    cancel-text="取消"
+    @ok="switchSteelOne"
+    @cancel="
+      () => {
+        openPaihaoModal = false;
+        newBrandNum = '';
+      }
+    "
+  >
+    <div class="flex justify-center items-center" style="margin: 20px 0">
+      <div>选择牌号:</div>
+      <JSearchSelect type="list" style="width: 277px" v-model:value="newBrandNum" dict="billet_spec" placeholder="请选择" allowClear />
+    </div>
+  </a-modal>
+  <!-- 切换炉号确认 -->
+  <changeHeatModal @register="registerChangeHeatModal" @ok="() => {}" />
+</template>
+<script setup lang="ts">
+  import { ref, onMounted, onUnmounted } from 'vue';
+  import AStatistic from 'ant-design-vue/lib/statistic/Statistic';
+  import { getOnDutyInfo, getSteelPileBaseInfo, groupBy } from '../../Dashboard/dashboard.api';
+  import { useTimeoutFn } from '/@/hooks/core/useTimeout';
+  import { switchSteel, returnFurnaceChange } from '../operator.api';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
+  import { render } from '/@/utils/common/renderUtils';
+  import changeHeatModal from './changeHeatModal.vue';
+  import { useModal } from '/@/components/Modal';
+
+  const { createMessage } = useMessage();
+
+  // 注册打印modal
+  const [registerChangeHeatModal, { openModal: openChangeHeatModal }] = useModal();
+
+  const emits = defineEmits(['onShiftChange', 'lengthChange']);
+
+  const props = defineProps({
+    ccmNo: {
+      type: String,
+      default: '5',
+    },
+  });
+
+  const info = ref<any>({
+    brandNum: '',
+    billetHotsendChangeShift: {
+      heatNo: '',
+      shiftGroup: '',
+      shift: '',
+      wasteAmount: 0,
+      shiftProduct: 0,
+      shiftSum: 0,
+      wasteBlankOutput: 0,
+    },
+    currentCastingFurnaceAmount: null,
+    currentCastingFurnace: null,
+  });
+
+  // typeList
+  const typeList = ref<any>([
+    { title: '棒一', titleColor: '#f50', amount: 0, weight: 0, dtlList: [] },
+    { title: '热装', titleColor: '#f50', amount: 0, weight: 0, dtlList: [] },
+    { title: '堆垛', titleColor: '#b8ceff', amount: 0, weight: 0, dtlList: [] },
+  ]);
+  // 冷床
+  const coldBed = ref<any>([{ title: '冷床', titleColor: '#b8ceff', amount: 0, weight: 0, dtlList: [] }]);
+  // 渲染字典标签
+  const renderDictTag = (value: string, dictCode: string) => {
+    return render.renderDict(value, dictCode);
+  };
+
+  // 获取班组班别
+  const getShiftInfo = () => {
+    emits('onShiftChange', {
+      shift: info.value.billetHotsendChangeShift.shift,
+      shiftGroup: info.value.billetHotsendChangeShift.shiftGroup,
+    });
+  };
+
+  // 获取当前班次信息
+  const getInfo = async () => {
+    try {
+      const infoRes = await getOnDutyInfo({ ccmNo: props.ccmNo });
+      if (infoRes) {
+        info.value = infoRes;
+        try {
+          let standObj = {};
+          (JSON.parse(infoRes.standNoSize) || []).forEach((item) => {
+            standObj[item.strandNo] = item.length;
+          });
+          emits('lengthChange', JSON.stringify(standObj), infoRes.cutToLength);
+        } catch (error) {
+          console.log(error);
+        }
+      }
+
+      // 获取明细
+      getSteelPileBaseInfo({ ccmNo: props.ccmNo }).then((dtlRes) => {
+        // 按照目的地分组
+        if (dtlRes) {
+          const destinationArr = dtlRes.reduce((acc, cur) => {
+            const bt = cur.belongTable || 'lc';
+            acc[bt] = acc[bt] || [];
+            acc[bt].push(cur);
+            return acc;
+          }, {});
+
+          // roll_club_one 棒一
+          // roll_club_two 棒二
+          // roll_club_three 棒三
+          // roll_out_shipp 上若
+          // roll_height 高线
+          // stacking_and_loading_vehicles 堆垛
+          let hotsendData: any = [],
+            hotSendSum = 0,
+            hotSendTotalWeight = 0,
+            hotchargeData: any = [],
+            hotChargeSum = 0,
+            hotChargeTotalWeight = 0,
+            stackingData: any = [],
+            stackingSum = 0,
+            stackingTotalWeight = 0;
+          // 计算棒一
+          if (destinationArr['roll_club_one']) {
+            hotsendData = Object.values(groupBy(destinationArr['roll_club_one'] || [], 'length')).map((one: any) => {
+              hotSendSum += one.nums;
+              hotSendTotalWeight += one.weight;
+              return {
+                ...one,
+                weight: one.weight.toFixed(3),
+                size: one.size / 1000,
+              };
+            });
+          }
+
+          // 计算热装
+          if (destinationArr['roll_club_two'] || destinationArr['roll_club_three'] || destinationArr['roll_out_shipp']) {
+            const concatArr = [
+              ...(destinationArr['roll_club_two'] || []),
+              ...(destinationArr['roll_club_three'] || []),
+              ...(destinationArr['roll_out_shipp'] || []),
+            ];
+            hotchargeData = Object.values(groupBy(concatArr, 'length')).map((one: any) => {
+              hotChargeSum += one.nums;
+              hotChargeTotalWeight += one.weight;
+              return {
+                ...one,
+                weight: one.weight.toFixed(3),
+                size: one.size / 1000,
+              };
+            });
+          }
+
+          // 计算堆垛
+          if (destinationArr['stacking_and_loading_vehicles']) {
+            stackingData = Object.values(groupBy(destinationArr['stacking_and_loading_vehicles'] || [], 'length')).map((one: any) => {
+              stackingSum += one.nums;
+              stackingTotalWeight += one.weight;
+              return {
+                ...one,
+                weight: one.weight.toFixed(3),
+                size: one.size / 1000,
+              };
+            });
+          }
+
+          // 计算冷床
+          let lcSum = 0;
+          let lcTotalWeight = 0;
+          let lcData: any = [];
+          if (destinationArr['lc']) {
+            lcData = Object.values(groupBy(destinationArr['lc'] || [], 'length')).map((one: any) => {
+              lcSum += one.nums;
+              lcTotalWeight += one.weight;
+              return {
+                ...one,
+                weight: one.weight.toFixed(3),
+                size: one.size / 1000,
+              };
+            });
+          }
+
+          typeList.value = [
+            {
+              title: '棒一',
+              titleColor: '#f50',
+              amount: hotSendSum || 0,
+              weight: hotSendTotalWeight ? hotSendTotalWeight.toFixed(3) : 0,
+              dtlList: hotsendData,
+            },
+            {
+              title: '热装',
+              titleColor: '#f50',
+              amount: hotChargeSum || 0,
+              weight: hotChargeTotalWeight ? hotChargeTotalWeight.toFixed(3) : 0,
+              dtlList: hotchargeData,
+            },
+            {
+              title: '堆垛',
+              titleColor: '#b8ceff',
+              amount: stackingSum || 0,
+              weight: stackingTotalWeight ? stackingTotalWeight.toFixed(3) : 0,
+              dtlList: stackingData,
+            },
+          ];
+
+          coldBed.value = [
+            {
+              title: '冷床',
+              titleColor: '#108ee9',
+              amount: lcSum || 0,
+              weight: lcTotalWeight ? lcTotalWeight.toFixed(3) : 0,
+              dtlList: lcData,
+            },
+          ];
+
+          getShiftInfo();
+        }
+      });
+    } catch (error) {
+    } finally {
+      start();
+    }
+  };
+
+  const { start, stop } = useTimeoutFn(getInfo, 5000, true);
+
+  // 换炉
+  const changeHeatLoading = ref(false);
+  const switchHeatNo = async () => {
+    try {
+      if (!info.value.billetHotsendChangeShift.heatNo) return;
+      changeHeatLoading.value = true;
+      const heatInfo = await returnFurnaceChange({
+        heatNo: Number(info.value.billetHotsendChangeShift.heatNo) + 1,
+      });
+
+      if (heatInfo) {
+        openChangeHeatModal(true, {
+          record: { ...heatInfo, ccmNo: heatInfo.ccmNo || props.ccmNo },
+        });
+      }
+      changeHeatLoading.value = false;
+    } catch (error) {
+      changeHeatLoading.value = false;
+    }
+  };
+
+  // 切换牌号
+  const openPaihaoModal = ref(false);
+  const newBrandNum = ref('');
+  const okLoading = ref(false);
+  const switchSteelOne = async () => {
+    try {
+      if (newBrandNum.value == '') {
+        createMessage.error('请选择牌号');
+        return;
+      }
+      okLoading.value = true;
+      await switchSteel({
+        ccmNo: props.ccmNo,
+        brandNum: newBrandNum.value,
+      });
+
+      getInfo();
+      openPaihaoModal.value = false;
+      newBrandNum.value = '';
+      okLoading.value = false;
+    } catch (error) {
+      okLoading.value = false;
+    }
+  };
+
+  onMounted(() => {
+    getInfo();
+  });
+
+  onUnmounted(() => {
+    stop();
+  });
+
+  defineExpose({
+    reload: () => {
+      stop();
+      getInfo();
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .head-top {
+    height: 130px;
+    font-size: 16px;
+    color: var(--op-text-color-fff);
+    border: 1px solid var(--op-border-color);
+    border-radius: 6px;
+    background-color: #01396c;
+    overflow: hidden;
+
+    .ant-col {
+      height: 130px;
+      border-right: 1px solid var(--op-border-color);
+      overflow: hidden auto;
+      padding: 10px;
+      font-size: 16px;
+
+      &:last-child {
+        border-right: none;
+      }
+    }
+
+    .head-no {
+      height: 130px;
+      font-size: 24px;
+      font-family: 'Kingsoft_Cloud_Font';
+    }
+    .bg {
+      background: #0085ff;
+    }
+
+    .ant-statistic {
+      :deep(.ant-statistic-title),
+      :deep(.ant-statistic-content-value-int),
+      :deep(.ant-statistic-content-value-decimal) {
+        color: var(--op-text-color-fff);
+        text-align: center;
+        font-size: 16px;
+      }
+
+      :deep(.ant-statistic-content-value-int),
+      :deep(.ant-statistic-content-value-decimal) {
+        font-size: 30px;
+      }
+
+      :deep(.ant-statistic-content) {
+        text-align: center;
+      }
+    }
+
+    .ant-btn {
+      height: 80px;
+      font-size: 18px;
+      padding: 4px 10px;
+    }
+
+    .paihao {
+      color: #f50;
+      font-size: 16px;
+    }
+
+    .type-item {
+      font-size: 16px;
+    }
+
+    .type-title {
+      display: inline-block;
+      width: 50px;
+    }
+
+    .change-heat.is-disabled {
+      background: #d9d9d9;
+      color: #8a8a8a;
+    }
+
+    .ant-badge {
+      width: 12px;
+      height: 12px;
+      line-height: 12px;
+      margin-right: 8px;
+      margin-top: -7px;
+
+      :deep(.ant-badge-status-dot) {
+        width: 12px;
+        height: 12px;
+        color: #00fb6f;
+        background-color: #00fb6f;
+      }
+    }
+
+    @keyframes antStatusProcessing {
+      0% {
+        transform: scale(0.8);
+        opacity: 0.8;
+      }
+      100% {
+        transform: scale(2.4);
+        opacity: 0.2;
+      }
+    }
+  }
+</style>

+ 1339 - 0
src/views/billet/operator/components/new-heatList-copy.vue

@@ -0,0 +1,1339 @@
+<template>
+  <div class="cc-heatList flex flex-col">
+    <div class="tips-title flex" v-if="showAction">
+      <div class="left-tip">当班浇铸炉次</div>
+      <div class="flex flex-1 items-center">
+        <div class="flex flex-1">
+          <template v-for="item in 8">
+            <JSearchSelect
+              type="list"
+              style="width: 96px"
+              v-model:value="strandNoSelected[item]"
+              dict="lg_dcgg"
+              :placeholder="`${item}流定尺`"
+              :class="{ changele: strandNoSelectedOrg[item] != strandNoSelected[item] }"
+              allowClear
+            />
+          </template>
+        </div>
+        <div style="margin-right: 6px">
+          <a-button type="primary" danger style="font-size: 16px" @click="handlerChangeLength">
+            切换{{ cuttolengthStatus == 2 ? '手动定尺' : '自动定尺' }}
+          </a-button>
+        </div>
+        <div style="margin-right: 6px; display: none">
+          <span style="font-size: 16px; color: #f50">短尺:</span>
+          <a-select style="width: 120px" :options="shortSizeOptions" @change="changeShortLength" />
+        </div>
+        <div style="margin-right: 6px">
+          <a-button type="primary" @click="() => refresh()"> 刷新 </a-button>
+        </div>
+      </div>
+    </div>
+    <div class="current-table-list flex-1">
+      <!--引用表格-->
+      <BasicTable @register="registerTable">
+        <!--操作栏-->
+        <template #action="{ record, index }">
+          <TableAction class="flex flex-col" style="gap: 4px; min-height: 88px" :actions="getTableAction(record, index)" />
+        </template>
+        <!--字段回显插槽-->
+        <!-- <template v-slot:bodyCell="{ column, record, index, text }"> </template> -->
+      </BasicTable>
+    </div>
+    <BasicTable @register="registerExtraTable" v-if="otherShiftTableData.length > 0" :dataSource="otherShiftTableData">
+      <!--操作栏-->
+      <template #action="{ record }">
+        <TableAction class="flex flex-col" style="gap: 4px; min-height: 88px" :actions="getTableAction(record)" />
+      </template>
+      <!--字段回显插槽-->
+      <!-- <template v-slot:bodyCell="{ column, record, index, text }"> </template> -->
+    </BasicTable>
+    <!-- 流切换定尺 -->
+    <a-modal
+      v-model:open="openSizeModal"
+      title="切换定尺"
+      centered
+      width="400px"
+      ok-text="确认"
+      :okButtonProps="{ loading: okLoading }"
+      cancel-text="取消"
+      @ok="switchSteelOne"
+      @cancel="
+        () => {
+          openSizeModal = false;
+          newSizeNum = '';
+        }
+      "
+    >
+      <div class="flex justify-center items-center" style="margin: 20px 0">
+        <div>选择定尺:</div>
+        <JSearchSelect type="list" style="width: 277px" v-model:value="newSizeNum" dict="lg_dcgg" placeholder="请选择" allowClear />
+      </div>
+    </a-modal>
+    <!-- 补录钢坯 -->
+    <a-modal
+      v-model:open="openCompensateModal"
+      :title="'补录钢坯' + (heatInfo.heatNo ? ',炉号:' + heatInfo.heatNo : '')"
+      centered
+      width="700px"
+      ok-text="确认"
+      :okButtonProps="{ loading: okLoading }"
+      cancel-text="取消"
+      @ok="confirmCompensate"
+      @cancel="closeCompensateModal"
+    >
+      <div class="strand-list">
+        <div class="flex justify-between strand-item" v-if="isAllHeat" style="margin: 20px 0">
+          <div class="flex" style="height: 40px; line-height: 40px">
+            <span class="mr-2">炉号:</span>
+            <a-input
+              :status="newHeatNoStatus"
+              @change="handlerChange($event, 'newHeat')"
+              v-model:value="newHeatNo"
+              style="width: 180px"
+              size="large"
+              type="number"
+              placeholder="请输入炉号"
+            />
+          </div>
+        </div>
+        <div class="strand-item" v-else style="margin: 20px 0">
+          <a-radio-group v-model:value="isRollOne">
+            <a-radio-button value="default">默认</a-radio-button>
+            <a-radio-button value="rollOne">棒一</a-radio-button>
+          </a-radio-group>
+        </div>
+        <div v-for="(item, index) in Object.keys(strandFormInfo)" class="flex justify-between items-center strand-item" style="margin: 20px 0">
+          <div class="strand-num">{{ strandFormInfo[item].no }}流</div>
+          <div class="flex items-center" style="position: relative; width: 120px">
+            <component :is="formatDefineSize(heatInfo[item], heatInfo[lengthArr[index]])" />
+          </div>
+          <div>
+            <JSearchSelect
+              type="list"
+              style="width: 96px"
+              v-model:value="strandFormInfo[item].size"
+              dict="lg_dcgg"
+              :placeholder="`${strandFormInfo[item].no}流定尺`"
+              allowClear
+              :status="strandFormInfo[item].sizeStatus"
+              :disabled="isRollOne === 'rollOne' ? (strandFormInfo[item].hasOne ? false : true) : false"
+              @change="handlerChange($event, 'sizeStatus', item)"
+            />
+          </div>
+          <div>
+            <a-input-number
+              id="inputNumber"
+              :status="strandFormInfo[item].sumStatus"
+              @change="handlerChange($event, 'sumStatus', item)"
+              v-model:value="strandFormInfo[item].sum"
+              :disabled="isRollOne === 'rollOne' ? (strandFormInfo[item].hasOne ? false : true) : false"
+              :min="0"
+              :max="10"
+            />
+          </div>
+          <div style="width: 140px" v-if="isAllHeat">
+            <div class="flex items-center" v-if="isAllHeat && strandFormInfo[item].hasOne">
+              <span class="mr-2" style="color: #f50">去棒一:</span>
+              <a-input type="number" v-model:value="strandFormInfo[item].rollClubOne" style="width: 80px" suffix="支" placeholder="棒一" :min="0" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </a-modal>
+  </div>
+  <!-- 打印 -->
+  <rollLinePrint @register="registerPrintModal" />
+  <!-- 炉次调根数 -->
+  <a-modal
+    v-model:open="openLuciModal"
+    :title="`调整炉次支数【${adjustCurHeat.heatNo}】`"
+    centered
+    width="1400px"
+    ok-text="确认"
+    :okButtonProps="{ loading: okLoading }"
+    cancel-text="取消"
+    @ok="confirmChangeHeat"
+    @cancel="
+      () => {
+        openLuciModal = false;
+      }
+    "
+  >
+    <div class="flex flex-col justify-center items-center change-heat" style="margin: 20px 0">
+      <div style="width: 100%; padding: 0 20px">
+        <a-radio-group button-style="solid" size="large">
+          <a-radio-button disabled>{{ adjustCurHeat.heatNo }}</a-radio-button>
+        </a-radio-group>
+      </div>
+      <BasicTable @register="registerShiftTableTable" :dataSource="[adjustCurHeat]" />
+      <div style="width: 100%; padding: 10px 20px 0">
+        <span style="padding: 0; color: #f50">调拨至:</span>
+        <a-radio-group v-model:value="adjustHeatNo" button-style="solid" @change="changeHeatNum" size="large">
+          <template v-for="item in currentShiftTableData">
+            <a-radio-button :value="item.heatNo" v-if="item.heatNo !== adjustCurHeat.heatNo">{{ item.heatNo }}</a-radio-button>
+          </template>
+        </a-radio-group>
+      </div>
+      <BasicTable style="min-height: 160px" @register="registerShiftTableTable" :dataSource="[{ ...adjustSelectedHeat, columnIndex: '' }]" />
+      <div class="flex items-center justify-end" style="width: 100%; margin-bottom: 20px; padding-right: 30px">
+        <div style="width: 72px">棒一:</div>
+        <div style="width: 100px">
+          <a-switch v-model:checked="isGotoRollOne" />
+        </div>
+      </div>
+      <div class="flex items-center justify-end" style="width: 100%; margin-bottom: 20px; padding-right: 30px">
+        <div style="width: 72px">调整支数:</div>
+        <div style="width: 100px">
+          <a-input-number size="large" v-if="isGotoRollOne" :defaultValue="1" :step="1" v-model:value="adjustHeatNum" :min="1" />
+          <a-input-number size="large" v-else :defaultValue="4" :step="4" v-model:value="adjustHeatNum" :min="4" @change="handleChangeNum" />
+        </div>
+      </div>
+    </div>
+  </a-modal>
+
+  <!-- 热装堆垛选择定尺 -->
+  <a-modal
+    v-model:open="openHotSelectedModal"
+    title="选择定尺"
+    centered
+    width="400px"
+    ok-text="确认"
+    :okButtonProps="{ loading: okLoading }"
+    cancel-text="取消"
+    @ok="() => (opType === 'hot' ? doHotCharge(opRecord) : doStack(opRecord))"
+    @cancel="
+      () => {
+        openHotSelectedModal = false;
+        selectedSize = undefined;
+        opRecord = null;
+        opType = '';
+      }
+    "
+  >
+    <div class="flex justify-center items-center" style="margin: 20px 0">
+      <div>选择定尺:</div>
+      <a-select v-model:value="selectedSize" placeholder="请选择" allowClear style="width: 277px" :options="selectedSizeOptions"></a-select>
+    </div>
+  </a-modal>
+</template>
+
+<script lang="ts" name="billetLiftingBill" setup>
+  import { BasicTable, TableAction, ActionItem } from '/@/components/Table';
+  import { useListPage } from '/@/hooks/system/useListPage';
+  import { getColumns, renderStrandCell } from '../operator.data';
+  import {
+    queryOriginalHeatInfoByCcmNo as queryHeatsActualsByCcmNo,
+    addHotCharge,
+    stackingUpAdd,
+    changeDefiningLength,
+    changeStrandLength,
+    addBilletBasic,
+    addHeatBillet,
+    queryChangeShortLength,
+    addRollOneBilletBasic,
+    adjustHeatBillet,
+    queryBilletRecordByCcmNo,
+  } from '../operator.api';
+  import { h, onMounted, onUnmounted, ref, watch } from 'vue';
+  import { mapTableTotalSummary } from '/@/utils/common/compUtils';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
+  import { useModal } from '/@/components/Modal';
+  import rollLinePrint from './rollLinePrint.vue';
+  import { getDictItems } from '/@/utils/dict/JDictSelectUtil';
+  import dayjs from 'dayjs';
+
+  // 注册打印modal
+  const [registerPrintModal, { openModal: openPrintModal }] = useModal();
+
+  const { createMessage, createConfirm } = useMessage();
+
+  const emits = defineEmits(['changeLengthSuccess']);
+
+  const props = defineProps({
+    ccmNo: {
+      type: String,
+      default: '5',
+    },
+    carRef: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+    queryType: {
+      type: String,
+      default: '1',
+    },
+    changeShiftId: {
+      type: String,
+      default: '',
+    },
+    showAction: {
+      type: Boolean,
+      default: true,
+    },
+    canResize: {
+      type: Boolean,
+      default: true,
+    },
+    lengthList: {
+      type: String,
+      default: '',
+    },
+    curShiftInfo: {
+      type: Object,
+      default: () => ({
+        shift: '',
+        shiftGroup: '',
+      }),
+    },
+    cuttolength: {
+      // 1 手动定尺 2 自动定尺
+      type: [Number, String],
+      default: 2,
+    },
+  });
+
+  const otherShiftTableData = ref<any[]>([]);
+  const currentShiftTableData = ref<any[]>([]);
+
+  // 流修改定尺
+  const openSizeModal = ref(false); // 打开定尺modal
+  const newSizeNum = ref(''); // 新定尺
+  const okLoading = ref(false); // 确定按钮loading
+  const heatInfo = ref<any>({}); // 炉信息
+  const strandNum = ref<number>(); // 流号
+  const orgSizeNum = ref<number>(); // 原定尺
+  const isAllHeat = ref<boolean>(false); // 是否是整炉添加
+  const isRollOne = ref<string>('default'); // 是否是去棒一,不是整炉添加时有效
+  const cuttolengthStatus = ref<string | number>(props.cuttolength); // 1 手动定尺 2  自动定尺
+
+  // 调整炉次支数
+  const openLuciModal = ref(false);
+  const columns = getColumns({
+    clickCb: ({ record, size, strandNo }) => {
+      return;
+      newSizeNum.value = size;
+      orgSizeNum.value = size;
+      openSizeModal.value = true;
+      heatInfo.value = record;
+      strandNum.value = strandNo;
+    },
+    openCompensateModal: (record) => {
+      return;
+      openCompensateModal.value = true;
+      strandFormInfo.value = {
+        oneStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['1'],
+          sizeName: 'oneLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 1,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        twoStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['2'],
+          sizeName: 'twoLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 2,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        threeStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['3'],
+          sizeName: 'threeLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 3,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        fourStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['4'],
+          sizeName: 'fourLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 4,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        fiveStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['5'],
+          sizeName: 'fiveLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 5,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        sixStrandNo: {
+          sum: 0,
+          size: strandNoSelectedOrg.value['6'],
+          sizeName: 'sixLength',
+          sumStatus: '',
+          sizeStatus: '',
+          no: 6,
+          hasOne: true,
+          rollClubOne: 0,
+        },
+        sevenStrandNo: { sum: 0, size: strandNoSelectedOrg.value['7'], sizeName: 'sevenLength', sumStatus: '', sizeStatus: '', no: 7 },
+        eightStrandNo: { sum: 0, size: strandNoSelectedOrg.value['8'], sizeName: 'eightLength', sumStatus: '', sizeStatus: '', no: 8 },
+      };
+      if (record.dataIndex && record.dataIndex === 'totalInfo') {
+        heatInfo.value = {};
+        isAllHeat.value = true;
+        newHeatNo.value = '';
+      } else {
+        heatInfo.value = record;
+        isAllHeat.value = false;
+      }
+      isRollOne.value = 'default';
+    },
+    heatNoClick: (record) => {
+      return;
+      openLuciModal.value = true;
+      adjustCurHeat.value = record;
+      adjustHeatNo.value = '';
+      adjustHeatNum.value = 4;
+      isGotoRollOne.value = false;
+      adjustSelectedHeat.value = {};
+      okLoading.value = false;
+    },
+  });
+
+  // 调整炉次支数
+  const adjustCurHeat = ref({});
+  const adjustHeatNo = ref('');
+  const adjustSelectedHeat = ref<any>({});
+  const isGotoRollOne = ref(false); // 是否去棒一
+  const adjustHeatNum = ref(); // 需要调整的支数
+  const confirmChangeHeat = async () => {
+    try {
+      if (!adjustSelectedHeat.value.heatNo) {
+        createMessage.error('请选择要调整的炉次!');
+        return;
+      }
+      if (!adjustHeatNum.value) {
+        createMessage.error('请输入要调整的支数!');
+        return;
+      }
+
+      if (!isGotoRollOne.value && adjustHeatNum.value % 4 !== 0) {
+        createMessage.error('调整支数请输入4的倍数!');
+        return;
+      }
+
+      const { totalInfo } = adjustSelectedHeat.value;
+      if (totalInfo) {
+        const obj = JSON.parse(totalInfo);
+        if (obj.totalCount < adjustHeatNum.value) {
+          createMessage.error('支数不能大于总支数!');
+          return;
+        }
+      }
+
+      const params = {
+        ccmNo: props.ccmNo,
+        originalHeatNo: adjustCurHeat.value.heatNo,
+        changeHeatNo: adjustSelectedHeat.value.heatNo,
+        number: adjustHeatNum.value,
+        changeType: isGotoRollOne.value ? 1 : 2,
+      };
+      okLoading.value = true;
+      await adjustHeatBillet(params);
+
+      refresh();
+      okLoading.value = false;
+      openLuciModal.value = false;
+    } catch (error) {
+      okLoading.value = false;
+      openLuciModal.value = false;
+    }
+  };
+  const changeHeatNum = (v) => {
+    if (v.target.value) {
+      adjustSelectedHeat.value = currentShiftTableData.value.find((item) => item.heatNo === v.target.value);
+    } else {
+      adjustSelectedHeat.value = {};
+    }
+  };
+  // 不去棒一必须是4的倍数
+  const handleChangeNum = async (value) => {
+    if (!isGotoRollOne.value) {
+      if (value % 4 !== 0) {
+        adjustHeatNum.value = value - (value % 4);
+      }
+    }
+  };
+
+  // 补录钢坯
+  const openCompensateModal = ref(false);
+  // 补录钢坯信息 sum 数量 size 定尺 status 状态 no 流号
+  const strandFormInfo = ref<any>({
+    oneStrandNo: { sum: 0, size: undefined, sizeName: 'oneLength', sumStatus: '', sizeStatus: '', no: 1, hasOne: true, rollClubOne: 0 },
+    twoStrandNo: { sum: 0, size: undefined, sizeName: 'twoLength', sumStatus: '', sizeStatus: '', no: 2, hasOne: true, rollClubOne: 0 },
+    threeStrandNo: { sum: 0, size: undefined, sizeName: 'threeLength', sumStatus: '', sizeStatus: '', no: 3, hasOne: true, rollClubOne: 0 },
+    fourStrandNo: { sum: 0, size: undefined, sizeName: 'fourLength', sumStatus: '', sizeStatus: '', no: 4, hasOne: true, rollClubOne: 0 },
+    fiveStrandNo: { sum: 0, size: undefined, sizeName: 'fiveLength', sumStatus: '', sizeStatus: '', no: 5, hasOne: true, rollClubOne: 0 },
+    sixStrandNo: { sum: 0, size: undefined, sizeName: 'sixLength', sumStatus: '', sizeStatus: '', no: 6, hasOne: true, rollClubOne: 0 },
+    sevenStrandNo: { sum: 0, size: undefined, sizeName: 'sevenLength', sumStatus: '', sizeStatus: '', no: 7 },
+    eightStrandNo: { sum: 0, size: undefined, sizeName: 'eightLength', sumStatus: '', sizeStatus: '', no: 8 },
+  });
+
+  const closeCompensateModal = () => {
+    openCompensateModal.value = false;
+  };
+  // 格式化定尺
+  const formatDefineSize = (num, jsonStr) => {
+    if (!num) {
+      return h('div', { style: { color: '#f50' } }, 0);
+    }
+    return renderStrandCell({ num, lengthJsonStr: jsonStr });
+  };
+
+  // 验证状态
+  const handlerChange = (e, type, k?: string) => {
+    // newHeat, sizeStatus, sumStatus
+    if (type === 'newHeat') {
+      newHeatNoStatus.value = e && e.target && e.target.value.trim() ? '' : 'error';
+    }
+    if (type === 'sumStatus' && k) {
+      strandFormInfo.value[k].sumStatus = e >= 0 ? '' : 'error';
+    }
+    if (type === 'sizeStatus' && k) {
+      strandFormInfo.value[k].sizeStatus = e ? '' : 'error';
+    }
+  };
+
+  // 新炉号
+  const newHeatNo = ref('');
+  const newHeatNoStatus = ref('');
+  // 确认添加定尺
+  const confirmCompensate = async () => {
+    try {
+      // 整炉添加钢坯
+      if (isAllHeat.value) {
+        if (!newHeatNo.value) {
+          newHeatNoStatus.value = 'error';
+          createMessage.error('整炉补录钢坯, 需输入新炉号');
+          return;
+        }
+      }
+
+      // 获取所有流输入的总支数
+      const changeStrandNums = Object.keys(strandFormInfo.value).filter((item) => strandFormInfo.value[item].sum);
+      if (changeStrandNums.length === 0) {
+        createMessage.error('请输入要增加的根数');
+        return;
+      }
+
+      // 判断是否输入了定尺
+      const noInputSize = changeStrandNums
+        .filter((item) => !strandFormInfo.value[item].size)
+        .map((item) => {
+          strandFormInfo.value[item].sizeStatus = 'error';
+          return strandFormInfo.value[item].no + '流';
+        });
+      if (noInputSize.length > 0) {
+        createMessage.error(`请选择${noInputSize.join(' , ')}的定尺`);
+        return;
+      }
+
+      // 整炉补录,判断支数先减去棒一支数后是否是4的倍数
+      const allNums = changeStrandNums.reduce((pre, cur) => pre + Number(strandFormInfo.value[cur].sum), 0);
+      const rollOneList = Object.keys(strandFormInfo.value).filter((item) => strandFormInfo.value[item].rollClubOne);
+      const rollOneNums = rollOneList.reduce((pre, cur) => pre + Number(strandFormInfo.value[cur].rollClubOne), 0);
+
+      let rollClubOneListParams: any[] = [];
+      if (isAllHeat.value && rollOneNums) {
+        if ((allNums - rollOneNums) % 4 !== 0) {
+          createMessage.error('减去棒一支数,剩下的钢坯支数必须为4的倍数');
+          return;
+        }
+
+        rollClubOneListParams = rollOneList.map((item) => {
+          return {
+            strandNo: strandFormInfo.value[item].no,
+            addSum: Number(strandFormInfo.value[item].rollClubOne),
+            length: Number(strandFormInfo.value[item].size),
+          };
+        });
+      }
+
+      // 如果是补录棒一,就把数据放到补录棒一的列表中
+      if (isRollOne.value === 'rollOne') {
+        rollClubOneListParams = Object.keys(strandFormInfo.value)
+          .filter((item) => strandFormInfo.value[item].sum)
+          .map((item: any) => {
+            return {
+              strandNo: strandFormInfo.value[item].no,
+              addSum: Number(strandFormInfo.value[item].sum),
+              length: Number(strandFormInfo.value[item].size),
+            };
+          });
+      }
+
+      okLoading.value = true;
+      let params = {
+        ccmNo: props.ccmNo,
+        heatNo: isAllHeat.value ? newHeatNo.value : heatInfo.value.heatNo,
+        shift: heatInfo.value.shift || props.curShiftInfo.shift,
+        shiftGroup: heatInfo.value.shiftGroup || props.curShiftInfo.shiftGroup,
+        addType: isAllHeat.value ? 1 : 2,
+        rollClubOneList: rollClubOneListParams,
+        addCount: allNums,
+      };
+
+      changeStrandNums.forEach((item) => {
+        if (strandFormInfo.value[item].size) {
+          params = Object.assign(params, {
+            [item + 'Sum']: strandFormInfo.value[item].sum,
+            [strandFormInfo.value[item].sizeName]: strandFormInfo.value[item].size,
+            [item]: strandFormInfo.value[item].no,
+          });
+        }
+      });
+
+      const fetchFn = isAllHeat.value ? addHeatBillet : isRollOne.value === 'rollOne' ? addRollOneBilletBasic : addBilletBasic;
+      await fetchFn(params);
+      refresh();
+      closeCompensateModal();
+      okLoading.value = false;
+    } catch (error) {
+      okLoading.value = false;
+      console.log(error);
+    }
+  };
+
+  const switchSteelOne = async () => {
+    try {
+      if (newSizeNum.value == '') {
+        createMessage.error('请选择牌号');
+        return;
+      }
+      okLoading.value = true;
+      await changeStrandLength({
+        ccmNo: props.ccmNo,
+        heatNo: heatInfo.value.heatNo,
+        originalLength: Number(orgSizeNum.value),
+        length: Number(newSizeNum.value),
+        strandNo: strandNum.value,
+      });
+
+      getTableList();
+      openSizeModal.value = false;
+      newSizeNum.value = '';
+      okLoading.value = false;
+    } catch (error) {
+      okLoading.value = false;
+    }
+  };
+
+  // 获取短尺
+  const shortSizeOptions = ref([]);
+  const getShortRuler = async () => {
+    getDictItems('lg_dcgg', {}).then((res) => {
+      shortSizeOptions.value = res.filter((item) => Number(item.value) < 10000);
+    });
+  };
+
+  const getTableList = async () => {
+    try {
+      setLoading(true);
+      const res = await queryHeatsActualsByCcmNo({ ccmNo: props.ccmNo, queryType: props.queryType, changeShiftId: props.changeShiftId });
+      const { billetOriginalProductRecordList } = res;
+      const data = billetOriginalProductRecordList
+        .sort((a, b) => {
+          return dayjs(a.createTime).isBefore(dayjs(b.createTime)) ? -1 : 1;
+        })
+        .map((item) => {
+          const { rollClubOneDetails, hotChargeLength, stackLength, lengthDetails } = item;
+
+          // 棒一
+          let directRolling = {};
+          if (rollClubOneDetails) {
+            const oneObj = JSON.parse(rollClubOneDetails);
+            directRolling = {
+              directRollingTotalCount: oneObj.directRollingTotalCount,
+              directRollingTotalWeight: oneObj.directRollingTotalWeight,
+            };
+          }
+
+          // 热装
+          let hotZ: any = {};
+          if (hotChargeLength) {
+            const hotObj = JSON.parse(hotChargeLength);
+            hotObj.forEach((item) => {
+              if (!hotZ.hotChargeTotalCount) {
+                hotZ.hotChargeTotalCount = item.totalCount;
+              } else {
+                hotZ.hotChargeTotalCount += item.totalCount;
+              }
+              if (!hotZ.hotChargeTotalWeight) {
+                hotZ.hotChargeTotalWeight = item.totalWeight;
+              } else {
+                hotZ.hotChargeTotalWeight += item.totalWeight;
+              }
+            });
+          }
+
+          // 堆垛
+          let stack: any = {};
+          if (stackLength) {
+            const stackObj = JSON.parse(stackLength);
+            stackObj.forEach((item) => {
+              if (!stack.stackingTotalCount) {
+                stack.stackingTotalCount = item.stackingCount;
+              } else {
+                stack.stackingTotalCount += item.stackingCount;
+              }
+              if (!stack.stackingTotalWeight) {
+                stack.stackingTotalWeight = item.stackingWeight;
+              } else {
+                stack.stackingTotalWeight += item.stackingWeight;
+              }
+            });
+          }
+
+          // 定尺
+          let sizeObj = {};
+          if (lengthDetails) {
+            const obj = JSON.parse(lengthDetails);
+            Object.keys(obj).forEach((key) => {
+              sizeObj[key] = { lengthTotalCount: obj[key] };
+            });
+          }
+
+          return {
+            ...item,
+            brandNum: item.grade,
+            oneStrandNo: item.oneStrandSum,
+            twoStrandNo: item.twoStrandSum,
+            threeStrandNo: item.threeStrandSum,
+            fourStrandNo: item.fourStrandSum,
+            fiveStrandNo: item.fiveStrandSum,
+            sixStrandNo: item.sixStrandSum,
+            sevenStrandNo: item.sevenStrandSum,
+            eightStrandNo: item.eightStrandSum,
+            directRolling: JSON.stringify(directRolling),
+            hotCharge: hotChargeLength ? JSON.stringify(hotZ) : undefined,
+            stacking: JSON.stringify(stack),
+            length: JSON.stringify(sizeObj),
+            totalInfo: JSON.stringify({ totalCount: item.amount, totalWeight: null }),
+          };
+        });
+
+      // 处理数据
+      let cunShift: any[] = [],
+        otherShift: any[] = [];
+      data.forEach((item) => {
+        if (!props.curShiftInfo.shift && !props.curShiftInfo.shiftGroup) {
+          cunShift.push(item);
+        } else {
+          if (item.shift === props.curShiftInfo.shift && item.shiftGroup === props.curShiftInfo.shiftGroup) {
+            cunShift.push(item);
+          } else {
+            otherShift.push(item);
+          }
+        }
+      });
+
+      const length = cunShift.length;
+      otherShiftTableData.value = otherShift.map((item) => {
+        return {
+          ...item,
+          columnIndex: '#',
+        };
+      });
+
+      currentShiftTableData.value = cunShift.map((item, index) => {
+        return {
+          ...item,
+          columnIndex: length - index,
+        };
+      });
+
+      setTableData(currentShiftTableData.value);
+    } catch (error) {
+      console.log('error', error);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  //注册table数据
+  const { tableContext } = useListPage({
+    tableProps: {
+      // api: queryHeatsActualsByCcmNo,
+      beforeFetch: (params) => {
+        return Object.assign(params, { ccmNo: props.ccmNo, queryType: props.queryType, changeShiftId: props.changeShiftId });
+      },
+      afterFetch: (orgData) => {
+        return;
+        let cunShift: any[] = [],
+          otherShift: any[] = [];
+        const data = orgData.sort((a, b) => {
+          return dayjs(a.createTime).isBefore(dayjs(b.createTime)) ? -1 : 1;
+        });
+        data.forEach((item) => {
+          if (!props.curShiftInfo.shift && !props.curShiftInfo.shiftGroup) {
+            cunShift.push(item);
+          } else {
+            if (item.shift === props.curShiftInfo.shift && item.shiftGroup === props.curShiftInfo.shiftGroup) {
+              cunShift.push(item);
+            } else {
+              otherShift.push(item);
+            }
+          }
+        });
+
+        const length = cunShift.length;
+        otherShiftTableData.value = otherShift.map((item) => {
+          return {
+            ...item,
+            columnIndex: '#',
+          };
+        });
+
+        currentShiftTableData.value = cunShift;
+
+        return cunShift.map((item, index) => {
+          return {
+            ...item,
+            columnIndex: length - index,
+          };
+        });
+      },
+      columns,
+      showIndexColumn: false,
+      canResize: false,
+      striped: true,
+      showTableSetting: false,
+      pagination: false,
+      actionColumn: {
+        width: 60,
+        title: '操作',
+        fixed: 'right',
+      },
+      showActionColumn: props.showAction,
+      showSummary: true,
+      summaryFunc: onSummary,
+    },
+  });
+
+  // 调整炉次时展示的数据
+  const { tableContext: otherShiftTableContext } = useListPage({
+    tableProps: {
+      columns: getColumns({ clickCb: () => {} }),
+      showIndexColumn: false,
+      canResize: false,
+      striped: true,
+      showTableSetting: false,
+      pagination: false,
+      showActionColumn: false,
+    },
+  });
+
+  const [registerShiftTableTable] = otherShiftTableContext;
+
+  /**
+   * 计算合计
+   * @param tableData
+   */
+  const strandArr = ['oneStrandNo', 'twoStrandNo', 'threeStrandNo', 'fourStrandNo', 'fiveStrandNo', 'sixStrandNo', 'sevenStrandNo', 'eightStrandNo'];
+  const lengthArr = ['oneLength', 'twoLength', 'threeLength', 'fourLength', 'fiveLength', 'sixLength', 'sevenLength', 'eightLength'];
+  function onSummary(tableData: Recordable[]) {
+    const newTableData = tableData.filter((ele) => ele.shift === props.curShiftInfo.shift && ele.shiftGroup === props.curShiftInfo.shiftGroup);
+    // 可用工具方法自动计算合计
+    const totals = mapTableTotalSummary(newTableData, strandArr);
+    // 直轧,热装,堆垛,总计
+    let directRollingTotalCount = 0,
+      directRollingTotalWeight = 0,
+      hotChargeTotalCount = 0,
+      hotChargeTotalWeight = 0,
+      stackingTotalCount = 0,
+      stackingTotalWeight = 0,
+      totalCount = 0,
+      totalWeight = 0;
+    try {
+      newTableData.forEach((item) => {
+        const { hotSend, directRolling, hotCharge, stacking, totalInfo } = item;
+        // 直轧
+        if (hotSend) {
+          const obj = JSON.parse(hotSend);
+          directRollingTotalCount += Number(obj.hotSendTotalCount);
+          directRollingTotalWeight += parseFloat(obj.hotSendTotalWeight);
+        }
+        if (directRolling) {
+          const obj = JSON.parse(directRolling);
+          directRollingTotalCount += Number(obj.directRollingTotalCount);
+          directRollingTotalWeight += parseFloat(obj.directRollingTotalWeight);
+        }
+
+        // 热装
+        if (hotCharge) {
+          const obj = JSON.parse(hotCharge);
+          hotChargeTotalCount += Number(obj.hotChargeTotalCount);
+          hotChargeTotalWeight += parseFloat(obj.hotChargeTotalWeight);
+        }
+
+        // 堆垛
+        if (stacking) {
+          const obj = JSON.parse(stacking);
+          stackingTotalCount += Number(obj.stackingTotalCount);
+          stackingTotalWeight += parseFloat(obj.stackingTotalWeight);
+        }
+
+        // 总计
+        if (totalInfo) {
+          const obj = JSON.parse(totalInfo);
+          totalCount += Number(obj.totalCount);
+          totalWeight += parseFloat(obj.totalWeight);
+        }
+      });
+    } catch (error) {}
+
+    return [
+      {
+        ...totals,
+        directRolling: JSON.stringify({ directRollingTotalCount, directRollingTotalWeight: directRollingTotalWeight }),
+        hotCharge: JSON.stringify({ hotChargeTotalCount, hotChargeTotalWeight: hotChargeTotalWeight }),
+        stacking: JSON.stringify({ stackingTotalCount, stackingTotalWeight: stackingTotalWeight }),
+        totalInfo: JSON.stringify({ totalCount, totalWeight: totalWeight }),
+        columnIndex: '合',
+      },
+    ];
+  }
+
+  const [registerTable, { setLoading, setTableData }] = tableContext;
+
+  // 额外的表格
+  const { tableContext: extraTableContext } = useListPage({
+    tableProps: {
+      columns,
+      showIndexColumn: false,
+      canResize: false,
+      striped: true,
+      showTableSetting: false,
+      pagination: false,
+      actionColumn: {
+        width: 60,
+        title: '操作',
+        fixed: 'right',
+      },
+      showActionColumn: props.showAction,
+      showHeader: false,
+    },
+  });
+
+  const [registerExtraTable] = extraTableContext;
+
+  const useTimeoutFn = (fn: TimerHandler, delay: number) => {
+    let timer: number | undefined = undefined;
+
+    const start = () => {
+      stop();
+      timer = setTimeout(fn, delay);
+    };
+
+    const stop = () => {
+      if (timer) {
+        clearTimeout(timer);
+      }
+    };
+
+    return { start, stop };
+  };
+
+  const { start, stop } = useTimeoutFn(async () => {
+    if (!props.changeShiftId) {
+      // await queryBilletRecordByCcmNo({ ccmNo: props.ccmNo, queryType: 1 });
+      // await getTableList();
+      // start();
+    }
+  }, 10000);
+
+  onMounted(() => {
+    getTableList();
+    start();
+    // 获取短尺
+    getShortRuler();
+  });
+
+  onUnmounted(() => {
+    stop();
+  });
+
+  // 获取所有的定尺
+  const openHotSelectedModal = ref(false);
+  const selectedSize = ref(undefined);
+  const selectedSizeOptions = ref([]);
+  const opType = ref('');
+  const opRecord = ref(null);
+  const getSize = (record, type) => {
+    opType.value = type;
+    opRecord.value = record;
+    const { length } = record;
+    let lengthArr: any = [];
+    if (length) {
+      const obj = JSON.parse(length);
+
+      lengthArr = Object.keys(obj).map((key) => ({
+        label: key,
+        value: key,
+      }));
+    }
+
+    selectedSize.value = undefined;
+    if (lengthArr.length > 0) {
+      openHotSelectedModal.value = true;
+      selectedSizeOptions.value = lengthArr;
+      return;
+    }
+
+    if (type === 'hot') {
+      doHotCharge(record);
+    } else {
+      doStack(record);
+    }
+  };
+  // 热装
+  const doHotCharge = async (record) => {
+    try {
+      const valiDesRes = props.carRef && props.carRef.valirDest ? props.carRef.valirDest() : true;
+      if (!valiDesRes) {
+        return;
+      }
+
+      const chargeInfo = props.carRef && props.carRef.getCurrentCar ? props.carRef.getCurrentCar() : {};
+      if (!chargeInfo.id) {
+        createMessage.error('获取车辆信息失败,请刷新页面重试~');
+        return;
+      }
+
+      const params = {
+        ccmNo: props.ccmNo,
+        heatNo: record.heatNo,
+        storageId: chargeInfo.id,
+        shift: record.shift,
+        shiftGroup: record.shiftGroup,
+        length: !selectedSize.value ? 0 : Number(selectedSize.value),
+      };
+
+      setLoading(true);
+      await addHotCharge(params);
+      refresh();
+      props.carRef.refreshCarList && props.carRef.refreshCarList();
+    } catch (error) {
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  // 起垛
+  const doStack = async (record) => {
+    try {
+      const selectStackList = props.carRef && props.carRef.getSelectedStack ? props.carRef.getSelectedStack() : [];
+      const emptyAddress = selectStackList.filter((item) => !item.billetNos);
+      if (emptyAddress.length === 0) {
+        createMessage.error('请选择起垛位置!');
+        return;
+      }
+
+      // 堆垛信息
+      const stackInfo = props.carRef && props.carRef.getStackInfo ? props.carRef.getStackInfo() : {};
+      if (!stackInfo.id) {
+        createMessage.error('获取堆垛信息失败,请刷新页面重试~');
+        return;
+      }
+
+      let layerObj = {},
+        sortedStackList: any[] = [];
+      emptyAddress.forEach((item) => {
+        if (!layerObj[item.layer]) layerObj[item.layer] = [];
+        layerObj[item.layer].push(item);
+      });
+
+      // 根据层数和位置排序
+      Object.keys(layerObj)
+        .sort((a, b) => Number(a) - Number(b))
+        .forEach((item) => {
+          layerObj[item].sort((j, k) => Number(j.address) - Number(k.address)).forEach((item) => sortedStackList.push(item));
+        });
+
+      const params = {
+        ccmNo: props.ccmNo,
+        heatNo: record.heatNo,
+        billetHotsendTypeConfigId: stackInfo.id,
+        stackingAndLoadingVehiclesIds: sortedStackList.map((item) => item.id),
+        shift: record.shift,
+        shiftGroup: record.shiftGroup,
+        length: !selectedSize.value ? 0 : Number(selectedSize.value),
+      };
+
+      setLoading(true);
+      await stackingUpAdd(params);
+      refresh();
+      props.carRef.refreshCarList && props.carRef.refreshCarList();
+    } catch (error) {
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  // 变更定尺
+  const strandNoSelectedOrg = ref({
+    '1': undefined,
+    '2': undefined,
+    '3': undefined,
+    '4': undefined,
+    '5': undefined,
+    '6': undefined,
+    '7': undefined,
+    '8': undefined,
+  });
+  const strandNoSelected = ref({
+    '1': undefined,
+    '2': undefined,
+    '3': undefined,
+    '4': undefined,
+    '5': undefined,
+    '6': undefined,
+    '7': undefined,
+    '8': undefined,
+  });
+
+  watch(
+    () => props.lengthList,
+    (val) => {
+      const data = JSON.parse(val || '{}');
+      Object.keys(data).forEach((item) => {
+        strandNoSelectedOrg.value[item] = data[item];
+        if (!strandNoSelected.value[item]) {
+          strandNoSelected.value[item] = data[item];
+        }
+      });
+    },
+    {
+      deep: true,
+      immediate: true,
+    }
+  );
+  const handlerChangeLength = async () => {
+    const record = strandNoSelected.value;
+    const sizeList = Object.keys(record)
+      .filter((ele) => record[ele] && record[ele] !== strandNoSelectedOrg.value[ele])
+      .map((item) => ({
+        strandNo: item,
+        length: record[item],
+      }));
+
+    if (!sizeList.length) {
+      createMessage.error('请选择需要变更的定尺');
+      return;
+    }
+    createConfirm({
+      title: '变更定尺确认',
+      content: h(
+        'div',
+        null,
+        sizeList.map((item) => h('div', null, ` ${item.strandNo}流: ${item.length / 1000}`))
+      ),
+      iconType: 'warning',
+      onOk: () => {
+        const params = {
+          ccmNo: props.ccmNo,
+          cutToLength: cuttolengthStatus.value == 2 ? 1 : 2,
+          strandNoSizeList: Object.keys(record)
+            .filter((ele) => record[ele])
+            .map((item) => ({
+              strandNo: item,
+              length: record[item],
+            })),
+        };
+
+        return changeDefiningLength(params).then(() => {
+          emits('changeLengthSuccess');
+        });
+      },
+    });
+  };
+
+  const changeShortLength = (v) => {
+    createConfirm({
+      title: '变更短尺确认',
+      iconType: 'warning',
+      onOk: () => {
+        return queryChangeShortLength({
+          ccmNo: props.ccmNo,
+          length: v,
+        });
+      },
+    });
+  };
+
+  /**
+   * 操作栏
+   */
+  function getTableAction(record, index?: number): ActionItem[] | undefined {
+    const printAction: ActionItem[] = [
+      {
+        label: '打印',
+        type: 'primary',
+        onClick: () => {
+          openPrintModal(true, { record, list: currentShiftTableData.value, index });
+        },
+      },
+    ];
+    if (!record.operateStatus) return printAction;
+
+    const chargeInfo = props.carRef && props.carRef.getCurrentCar ? props.carRef.getCurrentCar() : {};
+    return [
+      {
+        label: '热装',
+        color: 'error',
+        disabled: !chargeInfo.id || !!chargeInfo.outTime,
+        type: 'primary',
+        onClick: () => {
+          getSize(record, 'hot');
+        },
+      },
+      {
+        label: '起垛',
+        color: 'warning',
+        type: 'primary',
+        onClick: () => {
+          getSize(record, 'stack');
+        },
+      },
+      ...printAction,
+    ];
+  }
+
+  const refresh = async () => {
+    stop();
+    await getTableList();
+    start();
+  };
+
+  defineExpose({
+    reload: refresh,
+  });
+</script>
+
+<style scoped lang="less">
+  .cc-heatList {
+    height: 100%;
+    overflow: hidden;
+
+    .tips-title {
+      color: #fff;
+      font-size: 18px;
+      text-align: center;
+      border: 1px solid #fff;
+      margin-bottom: 4px;
+
+      .left-tip {
+        width: 227px;
+        border-right: 1px solid #fff;
+      }
+    }
+
+    .current-table-list {
+      overflow: auto;
+    }
+
+    .jeecg-basic-table {
+      padding: 0;
+    }
+
+    :deep(.ant-table) {
+      .ant-table-thead > tr > th {
+        font-size: 16px;
+        font-weight: 800;
+        color: #fff;
+      }
+
+      .ant-table-thead > tr > th:nth-child(4),
+      .ant-table-thead > tr > th:nth-child(5),
+      .ant-table-thead > tr > th:nth-child(6),
+      .ant-table-thead > tr > th:nth-child(7),
+      .ant-table-thead > tr > th:nth-child(8),
+      .ant-table-thead > tr > th:nth-child(9),
+      .ant-table-thead > tr > th:nth-child(10),
+      .ant-table-thead > tr > th:nth-child(11) {
+        color: #f50;
+        padding: 0;
+      }
+
+      .ant-table-tbody {
+        font-size: 15px;
+        font-family: 'Kingsoft_Cloud_Font';
+
+        & > tr > td:nth-child(6),
+        & > tr > td:nth-child(7),
+        & > tr > td:nth-child(8),
+        & > tr > td:nth-child(9),
+        & > tr > td:nth-child(10),
+        & > tr > td:nth-child(11) {
+          padding: 0 8px;
+          position: relative;
+        }
+      }
+
+      .ant-table-footer {
+        padding: 0;
+      }
+    }
+
+    .changele {
+      :deep(.ant-select-selector) {
+        background-color: #faa19d;
+        color: #fff;
+      }
+    }
+  }
+  .strand-list {
+    padding: 0 30px;
+    font-family: 'Kingsoft_Cloud_Font';
+    color: #000;
+
+    .strand-num {
+      color: #f50;
+    }
+
+    .strand-item {
+      border-bottom: 1px solid #eee;
+      padding-bottom: 10px;
+
+      &:last-child {
+        border-bottom: none;
+      }
+    }
+  }
+
+  // .change-heat {
+  //   :deep(.ant-table-row-level-0) {
+  //     .ant-table-cell {
+  //       background-color: #9eceff !important;
+  //     }
+  //     &:not(.jeecg-basic-table-row__striped) {
+  //       background-color: rgba(51, 51, 51, 0.04) !important;
+  //       .ant-table-cell {
+  //         background-color: rgba(51, 51, 51, 0.04) !important;
+  //         border-color: #d9d9d9;
+  //       }
+  //     }
+  //   }
+  // }
+</style>

+ 41 - 4
src/views/billet/operator/components/printCarInfo.vue

@@ -22,8 +22,12 @@
             type="primary"
             :loading="btnLoading"
             @click="sendCar"
-            >发车</a-button
           >
+            发车
+          </a-button>
+          <a-button style="margin-left: 20px" v-if="carPositon == 2 && !info.outTime && info.id" type="primary" :loading="btnLoading" @click="updateCcmNo">
+            修改#{{ info.ccmNo }}
+          </a-button>
         </div>
         <div class="flex-1" style="text-align: center; font-size: 16px">{{ dayjs(info.arrivalTime).format('YYYY 年 MM 月 DD 日 HH 时 mm 分') }}</div>
         <div class="flex-1" style="text-align: right; font-size: 16px"></div>
@@ -109,9 +113,9 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue';
+  import { ref, h } from 'vue';
   import dayjs from 'dayjs';
-  import { listShippingBill, startCar } from '../../shippingBill/shippingBill.api';
+  import { listShippingBill, startCar, edit } from '../../shippingBill/shippingBill.api';
   import { destinationOptions } from '../../hotDelivery/common.data';
   import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
   import { useMessage } from '/@/hooks/web/useMessage';
@@ -239,10 +243,43 @@
     }
   };
 
+  // 修改铸机号
+  const updateCcmNo = async () => {
+    try {
+      if (!props.info.id) {
+        createMessage.error('信息不正确,无法修改铸机号。');
+        return;
+      }
+
+      createConfirm({
+        iconType: 'warning',
+        title: '确认修改',
+        width: '460px',
+        content: () => {
+          return h('div', { style: { fontSize: '16px' } }, [
+            h('span', null, `是否将`),
+            h('span', { style: { fontSize: '18px', color: '#d48806' } }, `${props.info.ccmNo}#机 `),
+            h('span', null, ` 改为 `),
+            h('span', { style: { fontSize: '18px', color: '#3b5999' } }, ` ${props.info.ccmNo === '5' ? ' 6 ' : ' 5 '}#机`),
+            h('span', null, `?`),
+          ]);
+        },
+        okText: '确认',
+        cancelText: '取消',
+        onOk: () => {
+          return edit({ ...props.info, ccmNo: props.info.ccmNo === '5' ? '6' : '5' }).then(() => {
+            emits('refresh');
+          });
+        },
+      });
+    } catch (error) {
+      console.log(error);
+    }
+  };
+
   defineExpose({
     getTableList,
     focusDestination: () => {
-      // console.log('22222222222222222222', destinationRef.value);
       // destinationRef.value && destinationRef.value.handleAsyncFocus();
     },
   });

+ 5 - 10
src/views/billet/operator/components/printOriginalRecords.vue

@@ -411,13 +411,10 @@
       const res = await queryBilletRecordByCcmNo(params);
       let newArr: any[] = [];
       if (res && Array.isArray(res)) {
-        const ln = res.length;
-        for (let i = ln - 1; i >= 0; i--) {
-          const item = res[i];
-          if (shiftInfo.value.shift === item.shift && shiftInfo.value.shiftGroup === item.shiftGroup) {
-            newArr.push(item);
-          }
-        }
+        // 根据时间排序
+        newArr = res.sort((a, b) => {
+          return dayjs(a.createTime).isBefore(dayjs(b.createTime)) ? -1 : 1;
+        });
 
         let sizeColumn: string[] = [];
         let sizeHeadContent = {};
@@ -449,7 +446,6 @@
                   },
                   class: 'noprint',
                   onClick: () => {
-                    console.log('点击了');
                     const rollOnrColumn = columns.value.find((item: any) => item.dataIndex === 'stackLength');
                     let newSize = '';
                     rollOnrColumn.children.push({
@@ -651,9 +647,8 @@
           if (stackLength) {
             const stackLeghtObj = JSON.parse(stackLength);
             stackLeghtObj.forEach((v) => {
-              const sSize = v.stackingLength;
+              const sSize = String(v.stackingLength);
               const hasChild = stackLengthColumn.children.findIndex((ele) => ele.dataIndex === sSize + 'stackLength');
-
               if (hasChild < 0) {
                 stackLengthColumn.children.push({
                   title: () => {

+ 4 - 0
src/views/billet/operator/operator.api.ts

@@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
 enum Api {
   // 炉次信息
   queryHeatsActualsByCcmNo = '/storageBill/queryHeatsActualsByCcmNo',
+  queryOriginalHeatInfoByCcmNo = '/billet/billetOriginalProductRecord/queryOriginalHeatInfoByCcmNo', // 手动修改的数据
   // 切换牌号
   switchSteel = '/shiftConfiguration/shiftConfiguration/switchSteel',
   // 换炉
@@ -39,6 +40,9 @@ enum Api {
 export const queryHeatsActualsByCcmNo = (params: any) => {
   return defHttp.get({ url: Api.queryHeatsActualsByCcmNo, params });
 };
+export const queryOriginalHeatInfoByCcmNo = (params: any) => {
+  return defHttp.get({ url: Api.queryOriginalHeatInfoByCcmNo, params });
+};
 
 // 切换牌号
 export const switchSteel = (params: any) => {

+ 7 - 3
src/views/billet/operator/operator.data.ts

@@ -4,8 +4,8 @@ import { render } from '/@/utils/common/renderUtils';
 
 const renderNum = (num, weight, backArr?: boolean, tag = 'div') => {
   let arr = [h(tag, { style: { color: '#0085ff' } }, num)];
-  if (weight !== null) {
-    arr.push(h(tag, {}, (tag === 'span' ? '/' : '') + weight.toFixed(2)));
+  if (weight) {
+    arr.push(h(tag, {}, (tag === 'span' ? '/' : '') + parseInt(weight).toFixed(2)));
   }
   if (backArr === true) {
     return arr;
@@ -270,8 +270,12 @@ export const getColumns = ({ clickCb, openCompensateModal, heatNoClick }): Basic
                   openCompensateModal && openCompensateModal(record);
                 },
               },
+              // renderNum(
+              //   h('span', {}, [h('span', {}, obj.totalCount), h('span', { style: { color: '#999' } }, '/' + (obj.totalCount - quXiaongGen))]),
+              //   obj.totalWeight
+              // )
               renderNum(
-                h('span', {}, [h('span', {}, obj.totalCount), h('span', { style: { color: '#999' } }, '/' + (obj.totalCount - quXiaongGen))]),
+                h('span', {}, [h('span', {}, obj.totalCount)]),
                 obj.totalWeight
               )
             );

+ 43 - 24
src/views/billet/shippingBill/components/printModal.vue

@@ -11,7 +11,7 @@
   >
     <section ref="print" style="padding: 10px 10px 0; position: relative; border: 1px solid #c5c5c5; background: beige; width: 98%" id="printContent">
       <span style="position: absolute; right: 20px; top: 10px; font-size: 16px; font-weight: bold; cursor: pointer" @click="changeBtype">
-        {{ info.ccmNo }}#机 / {{ info.btype == 1 ? '冷' : '热' }}
+        {{ info.ccmNo }}#机 / {{ info.btype === '1' ? '冷' : info.btype === '0' ? '热' : '' }}
       </span>
       <div class="ticket next-ticket">
         <div style="text-align: center">
@@ -161,6 +161,7 @@
         </a-descriptions>
       </div>
     </section>
+    <div v-if="!isCanEdit" class="mask-disabled-edit"></div>
     <div class="add-heat" v-if="showAddHeat" style="margin: 20px">
       <a-input-group size="large">
         <a-row :gutter="8">
@@ -174,7 +175,7 @@
         </a-row>
       </a-input-group>
     </div>
-    <div style="position: absolute;left: -1000px;">{{ getAllAmount }}</div>
+    <div style="position: absolute; left: -1000px">{{ getAllAmount }}</div>
   </BasicModal>
 </template>
 
@@ -189,16 +190,16 @@
   // import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { destinationOptions } from '../../hotDelivery/common.data';
+  import { useUserStore } from '/@/store/modules/user';
 
+  const userStore = useUserStore();
   const { createMessage } = useMessage();
-
   const props = defineProps({
     api: {
       type: Function as PropType<(params: any) => Promise<any>>,
       default: listShippingBill,
     },
   });
-
   const emits = defineEmits(['success']);
 
   const info = ref<any>({});
@@ -211,7 +212,9 @@
   const [registerModal, { changeLoading, changeOkLoading, closeModal }] = useModalInner(async (data) => {
     const { record, type, isEdit } = data;
     if (record) {
+      // 如果是单纯的编辑,就只能编辑部分,棒三,二,上若 可以部分编辑
       isEditCard.value = isEdit === true;
+
       info.value = {
         ...record,
         arrivalTimeDay: dayjs(record.arrivalTime),
@@ -243,6 +246,11 @@
     }
   });
 
+  // 是否可编辑 轧钢确认后,除了gp账号其他的都不能编辑
+  const isCanEdit = computed(() => {
+    return !info.value.confirmTime || (info.value.confirmTime && userStore.userInfo && userStore.userInfo.username === 'gp');
+  });
+
   // 渲染字典标签
   // const renderDictTag = (value: string, dictCode: string) => {
   //   return render.renderDict(value, dictCode);
@@ -399,7 +407,7 @@
     }
   };
 
-  const changeBtype = (v) => {
+  const changeBtype = () => {
     info.value.btype = info.value.btype == '1' ? '0' : '1';
   };
 
@@ -425,25 +433,27 @@
     headDtl.value.forEach((item) => {
       headDtlObj[item.heatNo] = item.heatNum ? item.heatNum : item.billetNos.length;
     });
-    saveBeforePrint({
-      amountTotal: info.value.amountTotal,
-      arrivalTime: info.value.arrivalTimeDay.format('YYYY-MM-DD HH:mm:ss'),
-      brandNum: info.value.brandNum,
-      destination: info.value.destination,
-      heatNo: headDtlObj,
-      licensePlate: info.value.licensePlate,
-      name: '方坯',
-      size: info.value.size,
-      storageBillId: info.value.id,
-      weight: info.value.weight,
-      number: info.value.number,
-      classes: info.value.shift + '/' + info.value.shiftGroup,
-      btype: info.value.btype,
-      ccmNo: info.value.ccmNo,
-    }).then((res) => {
-      emits('success', res);
-      closeModal();
-    });
+    if (isCanEdit) {
+      saveBeforePrint({
+        amountTotal: info.value.amountTotal,
+        arrivalTime: info.value.arrivalTimeDay.format('YYYY-MM-DD HH:mm:ss'),
+        brandNum: info.value.brandNum,
+        destination: info.value.destination,
+        heatNo: headDtlObj,
+        licensePlate: info.value.licensePlate,
+        name: '方坯',
+        size: info.value.size,
+        storageBillId: info.value.id,
+        weight: info.value.weight,
+        number: info.value.number,
+        classes: info.value.shift + '/' + info.value.shiftGroup,
+        btype: info.value.btype,
+        ccmNo: info.value.ccmNo,
+      }).then((res) => {
+        emits('success', res);
+        closeModal();
+      });
+    }
 
     if (isEditCard.value !== true) {
       printJS({
@@ -545,6 +555,15 @@
       }
     }
   }
+
+  .mask-disabled-edit {
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    z-index: 10;
+  }
   @media print {
     header,
     footer,

+ 6 - 4
src/views/billet/storageAndTransportation/index.vue

@@ -163,9 +163,10 @@
     {
       label: '票据打印时间',
       field: 'receipt',
-      component: 'DatePicker',
+      component: 'RangePicker',
       componentProps: {
-        valueFormat: 'YYYY-MM-DD',
+        showTime: true,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
       },
     },
   ];
@@ -358,8 +359,9 @@
       queryParams.push(`arrivalTime=${dayjs().format('YYYY-MM-DD 00:00:00')}`);
       queryParams.push(`createTime=${dayjs().format('YYYY-MM-DD 23:59:59')}`);
     } else {
-      queryParams.push(`arrivalTime=${values['receipt']} 00:00:00`);
-      queryParams.push(`createTime=${values['receipt']} 23:59:59`);
+      const receipts = values['receipt'].split(',');
+      queryParams.push(`arrivalTime=${receipts[0]}`);
+      queryParams.push(`createTime=${receipts[1]}`);
     }
     return handleExportXlsx('储运票据', exportInvoice() + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
   };