zhangafei 1 день назад
Родитель
Сommit
4e2ae09bf7

+ 29 - 0
src/views/billet/ShiftPerformance/index.vue

@@ -45,6 +45,30 @@
                       >
                         浇铸炉次
                       </a-button>
+
+                      <a-button
+                        size="large"
+                        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 : '',
+                          })
+                        "
+                      >
+                        原始数据
+                      </a-button>
                     </div>
                   </div>
                 </div>
@@ -197,6 +221,8 @@
     </a-tabs>
   </div>
   <history @register="registerDetailModal" />
+  <!-- 打印原始数据 -->
+  <printOriginalRecords @register="registerPrintOriginalRecordsModal" />
 </template>
 <script lang="ts" setup>
   import { BasicTable } from '/@/components/Table';
@@ -215,11 +241,14 @@
   import dayjs from 'dayjs';
   import { useModal } from '/@/components/Modal';
   import history from './components/history.vue';
+  import printOriginalRecords from '../operator/components/printOriginalRecords.vue';
 
   const currentDate = ref<Dayjs>(dayjs());
 
   // 棒线堆垛明细
   const [registerDetailModal, { openModal: openDetailModal }] = useModal();
+  // 注册打印原始记录modal
+  const [registerPrintOriginalRecordsModal, { openModal: openPrintOriginalRecordsModal }] = useModal();
 
   const machine = getMachineNum();
 

+ 29 - 19
src/views/billet/operator/components/printBilletSampleCard.vue

@@ -139,6 +139,7 @@
   // 主机号
   const hostNumber = ref('5');
   const shiftInfoTxt = ref('');
+  const shiftInfo = ref({ shift: '', shiftGroup: '' });
   // label 样式
   const labelStyle = {
     width: '60px',
@@ -169,9 +170,10 @@
 
   //表单赋值
   const [registerModal, { changeOkLoading }] = useModalInner(async (data) => {
-    const { ccmNo, shiftText, queryType } = data;
+    const { ccmNo, shiftText, queryType, curShiftInfo } = data;
     hostNumber.value = ccmNo;
     shiftInfoTxt.value = shiftText.replace('-', '/');
+    shiftInfo.value = curShiftInfo;
 
     getHeatList({
       ccmNo,
@@ -188,30 +190,38 @@
       let sizeList: string[] = [];
       let sizeObj: any = {};
       const res = await queryHeatsActualsByCcmNo(params);
+      let newArr: any[] = [];
       if (res && Array.isArray(res)) {
-        res.forEach((item) => {
-          const lengthObj: Record<string, any> = JSON.parse(item.length);
-          const sizeArr: string[] = Object.keys(lengthObj);
-          sizeList = sizeList.concat(sizeArr);
+        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) {
+            const lengthObj: Record<string, any> = JSON.parse(item.length);
+            const sizeArr: string[] = Object.keys(lengthObj);
+            sizeList = sizeList.concat(sizeArr);
 
-          item.sizeInfo = lengthObj;
+            item.sizeInfo = lengthObj;
 
-          sizeArr.forEach((size) => {
-            if (!sizeObj[size]) {
-              sizeObj[size] = {
-                num: lengthObj[size].lengthTotalCount,
-                weight: lengthObj[size].lengthTotalWeight,
-              };
-            } else {
-              sizeObj[size].num += lengthObj[size].lengthTotalCount;
-              sizeObj[size].weight += lengthObj[size].lengthTotalWeight;
-            }
-          });
-        });
+            sizeArr.forEach((size) => {
+              if (!sizeObj[size]) {
+                sizeObj[size] = {
+                  num: lengthObj[size].lengthTotalCount,
+                  weight: lengthObj[size].lengthTotalWeight,
+                };
+              } else {
+                sizeObj[size].num += lengthObj[size].lengthTotalCount;
+                sizeObj[size].weight += lengthObj[size].lengthTotalWeight;
+              }
+            });
+            newArr.push(item);
+          }
+        }
+        // res.forEach((item) => {
+        // });
 
         sizeList = [...new Set(sizeList)];
         sizeArrs.value = sizeList;
-        heatList.value = res;
+        heatList.value = newArr;
         sizeObjs.value = sizeObj;
       }
     } catch (error) {

+ 442 - 0
src/views/billet/operator/components/printOriginalRecords.vue

@@ -0,0 +1,442 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="registerModal"
+    destroyOnClose
+    title="推钢室生产原始记录"
+    :width="1000"
+    :height="930"
+    ok-text="打印"
+    @ok="onPrint"
+  >
+    <section
+      ref="print"
+      style="padding: 10px 10px 0; position: relative; border: 1px solid #c5c5c5; background: #fff; width: 100%; height: 100%"
+      id="printBilletSampleCard"
+    >
+      <div class="ticket next-ticket">
+        <div style="text-align: center">
+          <p style="font-size: 24px; font-weight: 800; display: inline-block; margin-bottom: 16px; line-height: 30px">
+            <span class="ccmno">{{ hostNumber }}</span> #机推钢室生产原始记录
+          </p>
+        </div>
+        <div class="flex ccmno-info" style="line-height: 24px">
+          <div class="flex-1"> 班组:<component :is="renderDictTag(shiftInfo.shiftGroup, 'lg_bz')" /> </div>
+          <div class="flex-1"> 班次:<component :is="renderDictTag(shiftInfo.shift, 'lg_bb')" /> </div>
+          <div class="flex-1"> 定尺: </div>
+          <div class="flex-1" style="text-align: center; font-size: 13px">
+            {{ dayjs(curTime).format('YYYY 年 MM 月 DD 日') }}
+          </div>
+          <div class="flex-1" style="text-align: right; font-size: 12px"> lg/R05 </div>
+        </div>
+        <a-table :columns="columns" size="small" :data-source="dataSource" bordered :pagination="false">
+          <template #summary>
+            <a-table-summary-row>
+              <a-table-summary-cell :col-span="8" style="text-align: center">备注</a-table-summary-cell>
+              <a-table-summary-cell :col-span="2" style="text-align: center"> 定尺 </a-table-summary-cell>
+              <a-table-summary-cell :col-span="2" style="text-align: center"> 支数(支) </a-table-summary-cell>
+              <a-table-summary-cell :col-span="3" style="text-align: center"> 产量(吨) </a-table-summary-cell>
+            </a-table-summary-row>
+            <a-table-summary-row class="summary-row-no-border">
+              <a-table-summary-cell :col-span="8">
+                <div class="summary-cell-remark"></div>
+              </a-table-summary-cell>
+              <a-table-summary-cell :row-span="1"> 热送 </a-table-summary-cell>
+              <a-table-summary-cell :row-span="1"> </a-table-summary-cell>
+              <a-table-summary-cell :col-span="2"></a-table-summary-cell>
+              <a-table-summary-cell :col-span="3"> </a-table-summary-cell>
+            </a-table-summary-row>
+            <a-table-summary-row>
+              <a-table-summary-cell :col-span="8">
+                <div class="summary-cell-remark"></div>
+              </a-table-summary-cell>
+              <a-table-summary-cell :row-span="1"> 堆垛 </a-table-summary-cell>
+              <a-table-summary-cell :row-span="1"> </a-table-summary-cell>
+              <a-table-summary-cell :col-span="2"></a-table-summary-cell>
+              <a-table-summary-cell :col-span="3"> </a-table-summary-cell>
+            </a-table-summary-row>
+          </template>
+        </a-table>
+      </div>
+    </section>
+  </BasicModal>
+</template>
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import dayjs from 'dayjs';
+  import { printJS } from '/@/hooks/web/usePrintJS';
+  import type { TableColumnsType } from 'ant-design-vue';
+  import { queryHeatsActualsByCcmNo } from '../operator.api';
+  import { render } from '/@/utils/common/renderUtils';
+
+  // 渲染字典标签
+  const renderDictTag = (value: string, dictCode: string) => {
+    return render.renderDict(value, dictCode);
+  };
+  // 主机号
+  const hostNumber = ref('5');
+  const columns: TableColumnsType = [
+    {
+      title: '序号',
+      width: 40,
+      dataIndex: 'SerialNumber',
+      align: 'center',
+      key: 'SerialNumber',
+    },
+    {
+      title: '炉号',
+      dataIndex: 'heatNo',
+      width: 80,
+      align: 'center',
+      key: 'heatNo',
+    },
+    {
+      title: '钢种',
+      width: 80,
+      align: 'center',
+      dataIndex: 'brandNum',
+      key: 'brandNum',
+      customRender: ({ text }) => {
+        return render.renderDict(text, 'billet_spec');
+      },
+    },
+    {
+      title: '支数(根)',
+      align: 'center',
+      width: 570,
+      children: [
+        {
+          title: 'I流',
+          dataIndex: 'oneFlow',
+          key: 'oneFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'II流',
+          dataIndex: 'twoFlow',
+          key: 'twoFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'III流',
+          dataIndex: 'threeFlow',
+          key: 'threeFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'IV流',
+          dataIndex: 'fourFlow',
+          key: 'fourFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'V流',
+          dataIndex: 'fiveFlow',
+          key: 'fiveFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'VI流',
+          dataIndex: 'sixFlow',
+          key: 'sixFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'VII流',
+          dataIndex: 'sevenFlow',
+          key: 'sevenFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: 'VIII流',
+          dataIndex: 'eightFlow',
+          key: 'eightFlow',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '热送',
+          dataIndex: 'hotSend',
+          key: 'hotSend',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '堆垛',
+          dataIndex: 'stack',
+          key: 'stack',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '合计',
+          dataIndex: 'total',
+          key: 'total',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '备注',
+          dataIndex: 'remark',
+          key: 'remark',
+          align: 'center',
+          width: 60,
+        },
+      ],
+    },
+  ];
+
+  const dataSource = ref<any[]>([]);
+  const shiftInfoTxt = ref(['', '']);
+  const shiftInfo = ref({ shift: '', shiftGroup: '' });
+  const curTime = ref(dayjs().format('YYYY-MM-DD'));
+  //表单赋值
+  const [registerModal, { changeOkLoading }] = useModalInner(async (data) => {
+    const { ccmNo, shiftText, queryType, curShiftInfo, changeShiftId, time } = data;
+    console.log('data', data);
+
+    hostNumber.value = ccmNo;
+    shiftInfoTxt.value = shiftText.split('-');
+    shiftInfo.value = curShiftInfo;
+    if (time) {
+      curTime.value = time;
+    }
+
+    let newSip: any[] = [];
+    for (let index = 0; index < 22; index++) {
+      newSip.push({
+        SerialNumber: index + 1,
+        heatNo: '',
+        brandNum: '',
+        oneFlow: '',
+        twoFlow: '',
+        threeFlow: '',
+        fourFlow: '',
+        fiveFlow: '',
+        sixFlow: '',
+        sevenFlow: '',
+        eightFlow: '',
+        hotSend: '',
+        stack: '',
+        total: '',
+        remark: '',
+      });
+    }
+
+    dataSource.value = [...newSip];
+    getHeatList({
+      ccmNo,
+      queryType,
+      changeShiftId,
+    });
+  });
+
+  const getHeatList = async (params) => {
+    try {
+      const res = await queryHeatsActualsByCcmNo(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);
+          }
+        }
+
+        dataSource.value = dataSource.value.map((item, index) => {
+          if (!newArr[index]) return item;
+          let hotSendNum = 0;
+          let stackingNum = 0;
+          let totalNum = 0;
+          const { hotSend, directRolling, stacking, totalInfo } = newArr[index];
+          if (hotSend) {
+            const obj = JSON.parse(hotSend);
+            hotSendNum = obj.hotSendTotalCount;
+          }
+          if (directRolling) {
+            const obj = JSON.parse(directRolling);
+            hotSendNum = obj.directRollingTotalCount;
+          }
+          if (stacking) {
+            const obj = JSON.parse(stacking);
+            stackingNum = obj.stackingTotalCount;
+          }
+          if (totalInfo) {
+            const obj = JSON.parse(totalInfo);
+            totalNum = obj.totalCount;
+          }
+          return {
+            ...item,
+            heatNo: newArr[index].heatNo,
+            brandNum: newArr[index].brandNum,
+            oneFlow: newArr[index].oneStrandNo || '',
+            twoFlow: newArr[index].twoStrandNo || '',
+            threeFlow: newArr[index].threeStrandNo || '',
+            fourFlow: newArr[index].fourStrandNo || '',
+            fiveFlow: newArr[index].fiveStrandNo || '',
+            sixFlow: newArr[index].sixStrandNo || '',
+            sevenFlow: newArr[index].sevenStrandNo || '',
+            eightFlow: newArr[index].eightStrandNo || '',
+            hotSend: hotSendNum || '',
+            stack: stackingNum || '',
+            total: totalNum || '',
+            remark: '',
+          };
+        });
+      }
+    } catch (error) {
+      console.log(error);
+    }
+  };
+
+  function onPrint() {
+    changeOkLoading(true);
+    printJS({
+      printable: '#printBilletSampleCard',
+      type: 'html',
+    });
+    setTimeout(() => {
+      changeOkLoading(false);
+    }, 1000);
+  }
+</script>
+<style scoped lang="less">
+  .ticket {
+    max-width: 1000px;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    .ccmno-info {
+      font-family: 'Kingsoft_Cloud_Font';
+    }
+    .ccmno {
+      display: inline-block;
+      width: 60px;
+      border-bottom: 1px solid black;
+      text-align: center;
+    }
+
+    .size-items-title {
+      font-size: 12px;
+      line-height: 32px;
+      border-bottom: 1px solid #bfbfbf;
+      padding-left: 10px;
+      min-width: 100px;
+    }
+
+    .size-num-title {
+      font-size: 12px;
+      line-height: 32px;
+      padding-left: 10px;
+    }
+
+    .size-items-content {
+      height: 32px;
+      text-align: center;
+      line-height: 32px;
+    }
+
+    .size-items-remark {
+      width: 100%;
+      min-height: 90px;
+      flex-wrap: wrap;
+      font-family: 'Kingsoft_Cloud_Font';
+      align-content: flex-start;
+
+      .size-remark-item {
+        width: 50%;
+        height: 30px;
+        color: #000;
+      }
+
+      .size-remark-size {
+        display: inline-block;
+        width: 80px;
+      }
+
+      .size-remark-num {
+        display: inline-block;
+        width: 80px;
+        padding: 0 40px 0 0;
+        font-size: 12px;
+      }
+    }
+
+    .two-num-wrapper {
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 100%;
+      z-index: 10;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: flex-end;
+      padding-right: 6px;
+    }
+
+    .s-txt {
+      font-family: 'Kingsoft_Cloud_Font';
+    }
+
+    .ant-table-wrapper {
+      flex: 1;
+
+      :deep(.ant-spin-nested-loading) {
+        min-height: 100%;
+
+        .ant-table {
+          border-top: 1px solid rgba(0, 0, 0, 0.6);
+
+          > .ant-table-container {
+            border-inline-start: 1px solid rgba(0, 0, 0, 0.6);
+          }
+
+          .ant-table-content > table > thead > tr > th,
+          .ant-table-tbody > tr > td,
+          .ant-table-summary > tr > td {
+            padding: 2px;
+            border-inline-end: 1px solid rgba(0, 0, 0, 0.6);
+            border-bottom: 1px solid rgba(0, 0, 0, 0.6);
+            text-align: center;
+          }
+        }
+      }
+
+      .summary-row-no-border {
+        td:first-child {
+          border-bottom: none !important;
+        }
+      }
+
+      .summary-cell-remark {
+        min-height: 70px;
+      }
+    }
+  }
+</style>
+<style lang="less">
+  @media print {
+    header,
+    footer,
+    .noprint {
+      display: none;
+    }
+
+    @page :first {
+      margin-top: 10px; /* 第一页的页眉距离顶部为0 */
+      margin-bottom: 0; /* 第一页的页脚距离底部为0 */
+    }
+  }
+</style>

+ 14 - 1
src/views/billet/operator/index.vue

@@ -9,7 +9,15 @@
     <a-layout class="operator-large-layout">
       <a-layout-header class="operator-header cover">
         <div class="change-shift print-billet-card">
-          <a-button type="primary" size="large" @click="() => openModal(true, { ccmNo, queryType: '1', shiftText })"> 钢坯送样卡 </a-button>
+          <a-button
+            type="primary"
+            style="margin-right: 20px"
+            size="large"
+            @click="() => openPrintOriginalRecordsModal(true, { ccmNo, queryType: '1', shiftText, curShiftInfo })"
+          >
+            原始记录
+          </a-button>
+          <a-button type="primary" size="large" @click="() => openModal(true, { ccmNo, queryType: '1', shiftText, curShiftInfo })"> 送样卡 </a-button>
         </div>
         <div class="shift-wrapper"> {{ shiftText }} </div>
         <div class="change-shift">
@@ -45,6 +53,8 @@
 
     <!-- 打印钢坯送样卡 -->
     <print-billet-sample-card @register="registerPrintModal" />
+    <!-- 打印原始数据 -->
+    <printOriginalRecords @register="registerPrintOriginalRecordsModal" />
     <!-- 交班 -->
     <a-modal
       v-model:open="openJiaobanModal"
@@ -81,12 +91,15 @@
   import { useMessage } from '/@/hooks/web/useMessage';
   import { useModal } from '/@/components/Modal';
   import printBilletSampleCard from './components/printBilletSampleCard.vue';
+  import printOriginalRecords from './components/printOriginalRecords.vue';
   import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
 
   const { createConfirm, createMessage } = useMessage();
 
   // 注册打印送样卡modal
   const [registerPrintModal, { openModal }] = useModal();
+  // 注册打印原始记录modal
+  const [registerPrintOriginalRecordsModal, { openModal: openPrintOriginalRecordsModal }] = useModal();
 
   const ccmNo = getMachineNum();
 

+ 1 - 1
src/views/billet/shippingBill/components/editForm.vue

@@ -71,7 +71,7 @@
             <JSearchSelect
               type="list"
               v-model:value="model.destination"
-              :disabled="Number(model.typeConfigId) !== 1024"
+              
               :dictOptions="machineConfig[model.ccmNo]"
               placeholder="请选择"
               allowClear

+ 299 - 30
src/views/billet/shippingBill/components/printModal.vue

@@ -1,9 +1,9 @@
 <template>
   <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose title="装运单打印" :height="400" :width="800" ok-text="打印" @ok="onPrint">
     <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"
-        >{{ info.ccmNo }}#机 / {{ info.btype == 1 ? '冷' : '热' }}</span
-      >
+      <span style="position: absolute; right: 20px; top: 10px; font-size: 16px; font-weight: bold; cursor: pointer" @click="changeBtype">
+        {{ info.ccmNo }}#机 / {{ info.btype == 1 ? '冷' : '热' }}
+      </span>
       <div class="ticket next-ticket">
         <div style="text-align: center">
           <p style="font-size: 24px; font-weight: 800; display: inline-block; border-bottom: 2px solid #000; margin-bottom: 16px; line-height: 30px">
@@ -11,42 +11,102 @@
           </p>
         </div>
         <div class="flex" style="line-height: 24px">
-          <div class="flex-1">库名:{{ info.destination }}</div>
-          <div class="flex-1" style="text-align: center; font-size: 13px">{{
-            dayjs(info.arrivalTime).format('YYYY 年 MM 月 DD 日 HH 时 mm 分')
-          }}</div>
+          <div class="flex-1">
+            库名:
+            <JSearchSelect
+              type="list"
+              style="width: 120px"
+              :bordered="false"
+              v-model:value="info.typeConfigId"
+              :options="destinationOptions[info.ccmNo]"
+              placeholder="请选择"
+              allowClear
+              @change="(v) => handleDestinationIdChange(v)"
+            />
+          </div>
+          <div class="flex-1" style="text-align: center; font-size: 13px">
+            <a-date-picker
+              class="lgprint-date-picker"
+              v-model:value="info.arrivalTimeDay"
+              format="YYYY 年 MM 月 DD 日 HH 时 mm 分"
+              showTime
+              :bordered="false"
+            />
+          </div>
           <div class="flex-1" style="text-align: right; font-size: 12px">
-            {{ dayjs(info.arrivalTime).format('YYYYMMDDHHmmss') }}/{{ info.carNum }}/{{ info.carAllNum }}/{{ info.shift_dictText }}/{{
-              info.shiftGroup_dictText
-            }}
+            <a-input v-model:value="info.classes" style="font-size: 12px; padding: 0; width: 100%; text-align: right" :bordered="false" />
           </div>
         </div>
         <a-descriptions style="margin-top: 6px; margin-bottom: 4px" layout="vertical" bordered :column="8" size="small">
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="序号">
-            <div style="min-height: 80px; display: flex; align-items: center; justify-content: center"
-              ><span>{{ info.carAllNum }}</span></div
-            >
+            <div style="min-height: 80px; display: flex; align-items: center; justify-content: center" @click="numberEdit.value.focus()">
+              <a-input
+                ref="numberEdit"
+                v-model:value="info.number"
+                style="font-size: 12px; padding: 0; width: 28px; text-align: center"
+                :bordered="false"
+              />
+            </div>
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="车号">
-            {{ info.licensePlate }}
+            <!-- {{ info.licensePlate }} -->
+            <JSearchSelect
+              type="list"
+              :bordered="false"
+              v-model:value="info.licensePlate"
+              dict="lg_car"
+              style="width: 110px; font-size: 12px"
+              placeholder="请选择"
+              allowClear
+            />
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="牌号">
-            <component :is="renderDictTag(info.brandNum, 'billet_spec')" />
+            <!-- <component :is="renderDictTag(info.brandNum, 'billet_spec')" /> -->
+            <JSearchSelect type="list" :bordered="false" v-model:value="info.brandNum" dict="billet_spec" placeholder="请选择" allowClear />
           </a-descriptions-item>
-          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="炉号">
-            <div v-for="item in headDtl" :key="item.id">{{ item.heatNo }} - {{ item.billetNos.length }}</div>
+          <a-descriptions-item
+            class="heat-wrapper"
+            style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px; position: relative"
+            label="炉号"
+          >
+            <div class="heatNo-item" v-for="(item, sindex) in headDtl" :key="item.id">
+              {{ item.heatNo }} - {{ item.heatNum ? item.heatNum : item.billetNos.length }}
+              <div class="op jian" @click="deleteHeatDtl(sindex)">-</div>
+            </div>
+            <div class="add-heatNo" @click="addHeatDtl">+</div>
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="规格">
-            170 / {{ sizeInfo.join(',') }}
+            <div style="min-width: 120px">
+              <span> 170 /</span>
+              <!-- {{ sizeInfo.join(',') }} -->
+              <!-- <JSelectMultiple type="list" :bordered="false" v-model:value="info.size" dictCode="lg_dcgg" placeholder="请选择" allowClear /> -->
+              <a-input v-model:value="info.size" :bordered="false" style="width: 80px; padding: 0; font-size: 12px; display: inline-block" />
+            </div>
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="名称">
-            方坯
+            <div style="min-width: 40px"> 方坯 </div>
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="支数">
-            {{ info.amountTotal }}
+            <!-- {{ info.amountTotal }} -->
+            <a-input-number
+              :bordered="false"
+              style="min-width: 50px; width: 50px; font-size: 12px; text-align: center"
+              v-model:value="info.amountTotal"
+              :min="0"
+              :max="99"
+              :precision="0"
+            />
           </a-descriptions-item>
           <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="重量">
-            {{ weight > 0 ? weight.toFixed(4) : 0 }}
+            <!-- {{ weight > 0 ? weight.toFixed(4) : 0 }} -->
+            <a-input-number
+              :bordered="false"
+              style="min-width: 80px; width: 80px; font-size: 12px; text-align: center"
+              v-model:value="info.weight"
+              :min="0"
+              :max="99"
+              :precision="4"
+            />
           </a-descriptions-item>
         </a-descriptions>
         <a-descriptions style="padding: 0 30px" size="small">
@@ -56,6 +116,19 @@
         </a-descriptions>
       </div>
     </section>
+    <div class="add-heat" v-if="showAddHeat" style="margin: 20px">
+      <a-input-group size="large">
+        <a-row :gutter="8">
+          <a-col :span="6">
+            <a-input-number placeholder="请输入炉号" style="min-width: 180px" size="large" v-model:value="headValue" :precision="0" />
+          </a-col>
+          <a-col :span="4">
+            <a-input-number placeholder="请输入支数" v-model:value="heatNum" size="large" :precision="0" />
+          </a-col>
+          <a-button type="primary" @click="confirmAddHeatDtl">添加</a-button>
+        </a-row>
+      </a-input-group>
+    </div>
   </BasicModal>
 </template>
 
@@ -63,9 +136,15 @@
   import { ref } from 'vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import dayjs from 'dayjs';
-  import { render } from '/@/utils/common/renderUtils';
+  // import { render } from '/@/utils/common/renderUtils';
   import { printJS } from '/@/hooks/web/usePrintJS';
-  import { listShippingBill } from '../shippingBill.api';
+  import { listShippingBill, saveBeforePrint, getByStorageBillId } from '../shippingBill.api';
+  import JSearchSelect from '/@/components/Form/src/jeecg/components/JSearchSelect.vue';
+  // import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { destinationOptions } from '../../hotDelivery/common.data';
+
+  const { createMessage } = useMessage();
 
   const props = defineProps({
     api: {
@@ -78,22 +157,40 @@
   const headDtl = ref<any[]>([]);
   const weight = ref<number>(0);
   const sizeInfo = ref<string[]>([]);
+  const numberEdit = ref();
   //表单赋值
   const [registerModal, { changeLoading, changeOkLoading }] = useModalInner(async (data) => {
-    const { record } = data;
-    console.log(record);
+    const { record, type } = data;
     if (record) {
-      info.value = record;
-      getTableList();
+      info.value = {
+        ...record,
+        arrivalTimeDay: dayjs(record.arrivalTime),
+        number: record.carAllNum,
+        classes:
+          dayjs(record.arrivalTime).format('YYYYMMDDHHmmss') +
+          '/' +
+          record.carNum +
+          '/' +
+          record.carAllNum +
+          '/' +
+          record.shift_dictText +
+          '/' +
+          record.shiftGroup_dictText,
+      };
+
+      await getTableList();
+      if (type === 'offline') {
+        getOfflineBill();
+      }
     } else {
       info.value = {};
     }
   });
 
   // 渲染字典标签
-  const renderDictTag = (value: string, dictCode: string) => {
-    return render.renderDict(value, dictCode);
-  };
+  // const renderDictTag = (value: string, dictCode: string) => {
+  //   return render.renderDict(value, dictCode);
+  // };
 
   const getTableList = async () => {
     try {
@@ -144,6 +241,7 @@
       headDtl.value = newArr;
       weight.value = allWeight;
       sizeInfo.value = sizeArr;
+      info.value.weight = allWeight;
     } catch (error) {
       console.log(error);
     } finally {
@@ -152,8 +250,93 @@
     }
   };
 
+  // 获取线下票据数据
+  const getOfflineBill = async () => {
+    try {
+      changeLoading(true);
+      changeOkLoading(true);
+      getByStorageBillId({ storageBillId: info.value.id }).then((res) => {
+        if (res) {
+          info.value = {
+            ...info.value,
+            ...res,
+          };
+
+          headDtl.value = Object.keys(res.heatNo).map((item) => ({
+            heatNo: item,
+            heatNum: res.heatNo[item],
+          }));
+        }
+      });
+    } catch (error) {
+      console.log(error);
+    } finally {
+      changeLoading(false);
+      changeOkLoading(false);
+    }
+  };
+  const deleteHeatDtl = (index: number) => {
+    headDtl.value.splice(index, 1);
+  };
+
+  const headValue = ref<number | null>();
+  const heatNum = ref<number | null>();
+  const showAddHeat = ref(false);
+  const addHeatDtl = () => {
+    headValue.value = null;
+    heatNum.value = null;
+    showAddHeat.value = true;
+  };
+  const confirmAddHeatDtl = () => {
+    if (headValue.value && heatNum.value) {
+      headDtl.value.push({
+        id: headValue.value + '-' + heatNum.value,
+        heatNo: headValue.value,
+        heatNum: heatNum.value,
+      });
+      showAddHeat.value = false;
+    } else {
+      createMessage.warning('请填写炉号和支数');
+    }
+  };
+
+  const changeBtype = (v) => {
+    info.value.btype = info.value.btype == '1' ? '0' : '1';
+  };
+
+  // 修改目的地
+  function handleDestinationIdChange(v) {
+    if (v) {
+      const cur = destinationOptions[info.value.ccmNo].find((item) => item.value === v);
+      info.value.destination = cur.label;
+    } else {
+      info.value.destination = '';
+    }
+  }
+
   function onPrint() {
     changeOkLoading(true);
+
+    let headDtlObj = {};
+    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.classes,
+      btype: info.value.btype,
+      ccmNo: info.value.ccmNo,
+    });
     printJS({
       printable: '#printContent',
       type: 'html',
@@ -165,6 +348,92 @@
 </script>
 
 <style lang="less">
+  #printContent {
+    .lgprint-date-picker {
+      font-size: 13px;
+      padding: 0;
+
+      .ant-picker-input > input {
+        font-size: 13px;
+        text-align: center;
+      }
+
+      .ant-picker-suffix {
+        display: none;
+      }
+    }
+
+    .ant-select {
+      .ant-select-single .ant-select-selector {
+        font-size: 12px;
+      }
+
+      .ant-select-selection-item {
+        padding-inline-end: 0;
+      }
+
+      .ant-select-arrow {
+        display: none;
+      }
+    }
+
+    .heatNo-item {
+      position: relative;
+      min-width: 100px;
+
+      .op {
+        position: absolute;
+        right: 0;
+        top: 0;
+        font-size: 18px;
+        cursor: pointer;
+        width: 18px;
+        height: 18px;
+        line-height: 12px;
+        border-radius: 18px;
+        text-align: center;
+        background: #f5f5f5;
+        border: 1px solid #625dfa;
+        display: none;
+      }
+
+      .jian {
+        right: 0;
+        background-color: rgb(255, 205, 205);
+        border: 1 solid #fa5d5d;
+      }
+
+      &:hover {
+        .op {
+          display: block;
+        }
+      }
+    }
+
+    .add-heatNo {
+      position: absolute;
+      right: 0;
+      top: 0;
+      font-size: 18px;
+      cursor: pointer;
+      width: 18px;
+      height: 18px;
+      line-height: 12px;
+      border-radius: 18px;
+      text-align: center;
+      background: #f5f5f5;
+      border: 1px solid #625dfa;
+      display: none;
+    }
+
+    .heat-wrapper {
+      &:hover {
+        .add-heatNo {
+          display: block;
+        }
+      }
+    }
+  }
   @media print {
     header,
     footer,

+ 7 - 0
src/views/billet/shippingBill/index.vue

@@ -318,6 +318,13 @@
    */
   function getDropDownAction(record) {
     return [
+      {
+        label: '线下票据',
+        onClick: () => {
+          openPrintModal(true, { record, isUpdate: true, type: 'offline' });
+        },
+        disabled: false,
+      },
       {
         label: '装运明细',
         onClick: () => {

+ 14 - 0
src/views/billet/shippingBill/shippingBill.api.ts

@@ -41,6 +41,10 @@ enum Api {
   startCar = '/storageBill/startCar',
   // 棒线切换目的地
   destinationSwitch = '/storageBill/destinationSwitch',
+  // 打印之前保存数据
+  saveStorageBillPrint = '/storageBill/saveStorageBillPrint',
+  // 获取线下票据
+  getByStorageBillId = '/storageBill/getByStorageBillId',
 }
 
 /**
@@ -135,3 +139,13 @@ export const startCar = (params) => {
 export const destinationSwitch = (params) => {
   return defHttp.put({ url: Api.destinationSwitch, params }, { joinParamsToUrl: true });
 };
+
+// 打印之前保存数据
+export const saveBeforePrint = (params) => {
+  return defHttp.post({ url: Api.saveStorageBillPrint, params }, { joinParamsToUrl: true });
+};
+
+// 获取线下票据
+export const getByStorageBillId = (params) => {
+  return defHttp.get({ url: Api.getByStorageBillId, params }, { joinParamsToUrl: true });
+};

+ 45 - 2
src/views/billet/storageAndTransportation/index.vue

@@ -15,6 +15,7 @@
         </template>
         <template #advanceBefore>
           <a-button type="primary" preIcon="ant-design:export-outlined" style="margin-right: 10px" @click="onExportXls"> 导出</a-button>
+          <a-button type="primary" preIcon="ant-design:export-outlined" style="margin-right: 10px" @click="onExportTicketsXls"> 导出票据</a-button>
         </template>
       </BasicForm>
     </div>
@@ -91,7 +92,7 @@
   import { onMounted, ref } from 'vue';
   //引入依赖
   import { useForm, BasicForm, FormSchema } from '/@/components/Form';
-  import { getStorageCenterInvoicingInfo, exportExcel } from './storageAndTransportation.api';
+  import { getStorageCenterInvoicingInfo, exportExcel, exportInvoice } from './storageAndTransportation.api';
   import SegmentedSelect from '/@/components/SegmentedSelect/index.vue';
   import { isArray } from '/@/utils/is';
   import dayjs from 'dayjs';
@@ -159,6 +160,14 @@
         valueFormat: 'YYYY-MM-DD HH:mm:ss',
       },
     },
+    {
+      label: '票据打印时间',
+      field: 'receipt',
+      component: 'DatePicker',
+      componentProps: {
+        valueFormat: 'YYYY-MM-DD',
+      },
+    },
   ];
   /**
    * BasicForm绑定注册;
@@ -222,7 +231,14 @@
           let content: any[] = [];
           const {
             heatNoDetails,
-            storageCenterHeatNoInvoicing: { rollClubOneDetails, rollClubTwoDetails, rollClubThreeDetails, rollHeightDetails, rollOutShippDetails },
+            storageCenterHeatNoInvoicing: {
+              rollClubOneDetails,
+              rollClubTwoDetails,
+              rollClubThreeDetails,
+              rollHeightDetails,
+              rollOutShippDetails,
+              rollDeputyDetails,
+            },
           } = item;
 
           if (rollClubOneDetails) {
@@ -249,6 +265,14 @@
             });
           }
 
+          if (rollDeputyDetails) {
+            content.push({
+              title: '付跨',
+              type: 'car',
+              content: rollDeputyDetails,
+            });
+          }
+
           if (rollOutShippDetails) {
             content.push({
               title: '上若',
@@ -317,6 +341,25 @@
     return handleExportXlsx('储运中心', exportExcel() + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
   };
 
+  const onExportTicketsXls = () => {
+    const values = getFieldsValue();
+    console.log('values', values);
+    let queryParams = Object.keys(values)
+      .filter((v) => values[v])
+      .map((key) => {
+        return `${key}=${values[key]}`;
+      });
+
+    if (!values['receipt']) {
+      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`);
+    }
+    return handleExportXlsx('储运票据', exportInvoice() + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
+  };
+
   onMounted(() => {
     getList();
   });

+ 7 - 0
src/views/billet/storageAndTransportation/storageAndTransportation.api.ts

@@ -12,6 +12,8 @@ enum Api {
   storageCenterInvoicingInfo = '/storageBill/storageCenterInvoicingInfo',
   // 导出
   exportExcel = '/carUnit/carUnit/exportStorageCenterInfo',
+  // 导出票据
+  exportInvoicing = '/storageBillPrint/storageBillPrint/exportXls',
 }
 
 /**
@@ -47,3 +49,8 @@ export const getStorageCenterInvoicingInfo = (params) => {
 export const exportExcel = () => {
   return Api.exportExcel;
 };
+
+// 导出票据
+export const exportInvoice = () => {
+  return Api.exportInvoicing;
+};