Browse Source

钢坯增加送样卡功能

zhangafei 4 weeks ago
parent
commit
502c076e76

+ 6 - 5
.env.development

@@ -5,14 +5,15 @@ VITE_USE_MOCK = false
 VITE_PUBLIC_PATH = /
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
-# VITE_PROXY = [["/jeecgboot","http://192.168.0.105:9999"],["/upload","http://localhost:3300/upload"]]
-VITE_PROXY = [["/jeecgboot","http://192.168.1.6:9999"],["/upload","http://localhost:3300/upload"]]
+# 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://123.57.213.14:9898"],["/upload","http://localhost:3300/upload"]]
 
 #后台接口全路径地址(必填)
 # VITE_GLOB_DOMAIN_URL=http://localhost:9999
-# VITE_GLOB_DOMAIN_URL=http://192.168.0.105:8080/jeecg-boot
-# VITE_GLOB_DOMAIN_URL=http://192.168.6.24:8080/jeecg-boot
-VITE_GLOB_DOMAIN_URL=http://192.168.1.6: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://123.57.213.14:9898
 
 
 

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

@@ -49,6 +49,15 @@ enum Api {
   shiftRollClubThree = '/rollClubThreeDetails/rollClubThreeWorkbenchesQuery', // 轧钢棒三工作台根据班次天次查询总接收明细信息
   shiftRollClubHeight = '/rollHeightDetails/rollHeightWorkbenchesQuery', // 轧钢高线工作台根据班次天次查询总接收明细信息
   shiftRollClubShipp = '/rollOutShippDetails/rollOutShippWorkbenchesQuery', // 轧钢外运工作台根据班次天次查询总接收明细信息
+
+  // 打印明细 棒三
+  storageBillPrintList = '/storageBillPrint/storageBillPrint/list',
+  storageBillPrintEdit = '/storageBillPrint/storageBillPrint/edit',
+  // 棒一
+  rollClubOneList = '/rollClubOne/rollClubOneList',
+  confirmRecord = '/billet/billetOriginalProductRecord/confirmRecord',
+  // 棒线工作台统计
+  rollClubStatistics = '/billet/billetOriginalProductRecord/queryBilletStatisticsDetailByCcmNo',
 }
 
 export interface ListItem {
@@ -209,3 +218,26 @@ export const getShiftRollOutShipp = (params: any) => {
 export const getShiftRollHeight = (params: any) => {
   return defHttp.get({ url: Api.shiftRollClubHeight, params }, { joinParamsToUrl: true });
 };
+
+// 打印明细系列
+export const getStorageBillPrintList = (params: any) => {
+  return defHttp.get({ url: Api.storageBillPrintList, params }, { joinParamsToUrl: true });
+};
+export const saveStorageBillPrint = (params: any) => {
+  return defHttp.post({ url: Api.storageBillPrintEdit, params }, { joinParamsToUrl: true });
+};
+
+// 得到棒一
+export const getRollClubOneList = (params: any) => {
+  return defHttp.get({ url: Api.rollClubOneList, params }, { joinParamsToUrl: true });
+};
+
+// 确认
+export const confirmRollClubOne = (params: any) => {
+  return defHttp.put({ url: Api.confirmRecord, params }, { joinParamsToUrl: true });
+};
+
+// 棒线工作台统计
+export const getrollClubStatistics = (params: any) => {
+  return defHttp.get({ url: Api.rollClubStatistics, params }, { joinParamsToUrl: true });
+};

+ 588 - 0
src/views/billet/Dashboard/rollingOne.vue

@@ -0,0 +1,588 @@
+<template>
+  <div class="rolling-three-dashboard flex flex-col">
+    <div class="search-wrapper">
+      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleSubmit" />
+    </div>
+    <a-spin :spinning="loading">
+      <div class="common-table">
+        <a-descriptions bordered style="min-height: 72px" size="small" :column="5" :label-style="{ fontWeight: 'bold', width: '70px' }">
+          <template v-for="item in dtlList" :key="item.title">
+            <a-descriptions-item :label-style="!item.title ? { display: 'none' } : {}" :label="item.title">
+              <div :class="'wrapper-' + item.zjNo">
+                <div class="nb-left">
+                  <div class="flex">
+                    <div class="flex nick">
+                      <span class="total">总数:{{ item.nums }} 支</span>
+                    </div>
+
+                    <div class="flex nick">
+                      <span>重量:{{ item.blankOutput ? Number(item.blankOutput).toFixed(4) : 0 }} t</span>
+                    </div>
+                  </div>
+
+                  <div class="flex dtl-wrapper" v-if="item.statisticsDetailsList.length > 0">
+                    <div>明细:</div>
+                    <div class="dtl flex-1 flex flex-wrap">
+                      <div class="flex-dlt-item flex" v-for="ele in item.statisticsDetailsList">
+                        <div class="flex dtl-item bt-line">
+                          <span class="nums">{{ ele.size }}:&nbsp;&nbsp;&nbsp;{{ ele.nums }} 支</span>
+                        </div>
+                        <div class="flex dtl-item">
+                          <span class="nums bt-line">重量:{{ ele.blankOutput ? Number(ele.blankOutput).toFixed(4) : 0 }} t</span>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <!-- <div class="flex nb-right">
+            <div class="flex nick">
+              <span>重量:{{ item.blankOutput }}</span>
+            </div>
+
+            <div class="flex dtl-wrapper" v-if="item.statisticsDetailsList.length > 0">
+              <div class="dtl">
+                <div class="flex dtl-item" v-for="ele in item.statisticsDetailsList">
+                  <span>重量:{{ ele.blankOutput }}</span>
+                </div>
+              </div>
+            </div>
+          </div> -->
+              </div>
+            </a-descriptions-item>
+          </template>
+        </a-descriptions>
+      </div>
+      <template v-if="threeList.length">
+        <a-row :gutter="[16, 8]">
+          <a-col class="gutter-row" v-for="(item, index) in threeList" :key="index">
+            <div class="ticket next-ticket" :class="{ disabled: !!item.confirmTime }">
+              <div class="ticket-op-w" v-if="!isAuth">
+                <a-button type="primary" :disabled="!!item.confirmTime" size="small" @click="confirmCard(item)">确认热送单</a-button>
+              </div>
+              <div class="flex" style="line-height: 24px">
+                <div class="flex-1">序号:{{ item.heatNo }}</div>
+                <div class="flex-1" style="text-align: center; font-size: 13px">日期:{{ dayjs(item.createTime).format('MM. DD') }}</div>
+                <div class="flex-1" style="text-align: right; font-size: 12px">
+                  班次:<component :is="renderDictTag(item.shift, 'lg_bb')" /> / <component :is="renderDictTag(item.shiftGroup, 'lg_bz')" />
+                </div>
+              </div>
+              <a-descriptions class="ticket-info" layout="vertical" bordered :column="8" size="small">
+                <a-descriptions-item class="ticket-info-item" label="起止时间">
+                  <div style="min-height: 80px; display: flex; align-items: center; justify-content: center">{{ item.createTime }}</div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="炉号">
+                  {{ item.heatNo }}
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="钢种">
+                  {{ item.brandNum }}
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="规格尺寸">
+                  <!-- <a-select v-model:value="sizeValue" :options="sizeOptions" @change="getStartEnd" style="width: 100%" :bordered="false"></a-select> -->
+                  <div
+                    class="line"
+                    :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
+                    style="cursor: pointer"
+                    v-for="ele in item.sizeObj"
+                    @click="
+                      () => {
+                        // sizeValue = ele.size;
+                        // getStartEnd();
+                      }
+                    "
+                  >
+                    {{ ele.size }}
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="合格支数">
+                  <!-- {{ sizeValue && rollOneInfo.size[sizeValue] ? rollOneInfo.size[sizeValue] : '' }} -->
+                  <div
+                    class="line"
+                    :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
+                    style="cursor: pointer"
+                    v-for="ele in item.sizeObj"
+                    @click="
+                      () => {
+                        // sizeValue = ele.size;
+                        // getStartEnd();
+                      }
+                    "
+                  >
+                    {{ ele.sizeAmount }}
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="本炉起始根">
+                  <div
+                    class="line"
+                    :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
+                    style="cursor: pointer"
+                    v-for="ele in item.sizeObj"
+                    @click="
+                      () => {
+                        // sizeValue = ele.size;
+                        // getStartEnd();
+                      }
+                    "
+                  >
+                    {{ ele.startAmount }}
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="本炉终止根">
+                  <div
+                    class="line"
+                    :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
+                    style="cursor: pointer"
+                    v-for="ele in item.sizeObj"
+                    @click="
+                      () => {
+                        // sizeValue = ele.size;
+                        // getStartEnd();
+                      }
+                    "
+                  >
+                    {{ ele.endAmount }}
+                  </div>
+                </a-descriptions-item>
+              </a-descriptions>
+            </div>
+          </a-col>
+        </a-row>
+
+        <a-pagination
+          class="pagination"
+          :defaultPageSize="pageLimit"
+          v-model:current="currentPage"
+          show-quick-jumper
+          :total="totalPage"
+          @change="onPageChange"
+        />
+      </template>
+      <a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
+    </a-spin>
+  </div>
+
+  <!-- 确认 -->
+  <a-modal v-model:open="open" title="确认信息" ok-text="确认" cancel-text="取消" @ok="confirmSubmit">
+    <div style="margin: 20px">
+      <a-textarea v-model:value="remark" placeholder="备注" :auto-size="{ minRows: 2, maxRows: 5 }" />
+    </div>
+  </a-modal>
+</template>
+<script setup lang="ts">
+  import { onMounted, ref } from 'vue';
+  import { getRollClubOneList, confirmRollClubOne, getrollClubStatistics } from './dashboard.api';
+  import dayjs, { Dayjs } from 'dayjs';
+  import { useForm, BasicForm, FormSchema } from '/@/components/Form';
+  import { Empty } from 'ant-design-vue';
+  import { render } from '/@/utils/common/renderUtils';
+  import { getMachineNum } from '../hotDelivery/common.data';
+  import { Pagination as APagination } from 'ant-design-vue';
+  import { useUserStore } from '/@/store/modules/user';
+
+  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[]>([
+    {
+      // title: '总计',
+      title: '',
+      zjNo: 0,
+      blankOutput: 0,
+      nums: 0,
+      statisticsDetailsList: [],
+    },
+    {
+      title: '5#机',
+      zjNo: 5,
+      blankOutput: 0,
+      nums: 0,
+      statisticsDetailsList: [],
+    },
+  ]);
+
+  // 渲染字典标签
+  const renderDictTag = (value: string, dictCode: string) => {
+    return render.renderDict(value, dictCode);
+  };
+
+  //自定义表单字段
+  const formSchemas: FormSchema[] = [
+    {
+      label: '日期',
+      field: 'arrivalTime',
+      component: 'DatePicker',
+      componentProps: {
+        showTime: false,
+        valueFormat: 'YYYY-MM-DD',
+      },
+    },
+    // {
+    //   label: '班组',
+    //   field: 'shiftGroup',
+    //   component: 'JDictSelectTag',
+    //   componentProps: {
+    //     dictCode: 'lg_bz',
+    //   },
+    // },
+    // {
+    //   label: '班别',
+    //   field: 'shift',
+    //   component: 'JDictSelectTag',
+    //   componentProps: {
+    //     dictCode: 'lg_bb',
+    //   },
+    // },
+  ];
+  /**
+   * BasicForm绑定注册;
+   */
+  const [registerForm, { getFieldsValue }] = useForm({
+    //注册表单列
+    schemas: formSchemas,
+    //是否显示展开收起按钮,默认false
+    showAdvancedButton: true,
+    //超过指定行数折叠,默认3行
+    autoAdvancedCol: 3,
+    //折叠时默认显示行数,默认1行
+    alwaysShowLines: 3,
+    //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
+    fieldMapToTime: [
+      // ['createTime', ['createTime_begin', 'createTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+      // ['storageTime', ['storageTime_begin', 'storageTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+    ],
+    //每列占比,默认一行为24
+    baseColProps: { span: 6 },
+  });
+
+  /**
+   * 点击提交按钮的value值
+   * @param values
+   */
+  function handleSubmit() {
+    currentPage.value = 1;
+    getList();
+    getStatistics();
+  }
+
+  const currentPage = ref(1);
+  const totalPage = ref(0);
+  const pageLimit = ref(20);
+  const onPageChange = (n) => {
+    currentPage.value = n;
+    getList();
+  };
+
+  // 获取列表
+  const loading = ref(false);
+  const destinationTxt = {
+    '3': '棒三',
+    '4': '上若',
+  };
+  const getList = async () => {
+    try {
+      const values = getFieldsValue();
+      let params: any = Object.assign({}, values, { destination: destinationTxt[machineNum] });
+      if (!values.ccmNo) {
+        values.ccmNo = '5';
+      }
+      loading.value = true;
+
+      if (!values.arrivalTime) {
+        params = Object.assign({}, values, {
+          arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
+          destination: destinationTxt[machineNum],
+        });
+      }
+
+      loading.value = true;
+      const res = await getRollClubOneList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params });
+
+      totalPage.value = res.total;
+      currentPage.value = res.current;
+      threeList.value = (res.records || []).map((item) => {
+        const {
+          heatNoDetails,
+          storageCenterHeatNoInvoicing: { rollClubOneDetails },
+        } = item;
+
+        const { sizeDetails, confirmTime, id, brandNum } = rollClubOneDetails;
+
+        const sizeObj = {};
+        sizeDetails.forEach((item) => {
+          sizeObj[item.size] = item;
+        });
+
+        return {
+          ...heatNoDetails[0],
+          sizeObj,
+          sizeValue: sizeDetails[0].size,
+          confirmTime,
+          id,
+          brandNum,
+        };
+      });
+    } catch (error) {
+      console.log(error);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 确定
+  const open = ref(false);
+  const confirmInfo = ref({});
+  const remark = ref('确认热送单炉支数传递单无误!');
+  const confirmCard = (record) => {
+    open.value = true;
+    confirmInfo.value = record;
+    remark.value = '确认热送单炉支数传递单无误!';
+  };
+  const confirmSubmit = () => {
+    const info: any = confirmInfo.value;
+    confirmRollClubOne({
+      id: info.id,
+      confirmTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+      remark: remark.value,
+    }).then(() => {
+      open.value = false;
+      getList();
+    });
+  };
+
+  // 获取统计信息
+  /**
+   * ccmNo、changeShiftId、queryDate、queryType(1、2、3、4)代表棒一、棒二、棒三、上若,  就这四个参数,ccmNo、queryType  必输,changeShiftId、queryDate(2025-06-24)非必输,
+   **/
+  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'),
+      });
+      const res = staticsRres[0];
+      dtlList.value[0].blankOutput = res.totalWeight || 0;
+      dtlList.value[0].nums = res.counts || 0;
+      let totalObj = {
+        5: { blankOutput: 0, nums: 0 },
+      };
+      let statisticsDetailsList5: any[] = [];
+      res.rollClubOneStatisticsList.forEach((element) => {
+        statisticsDetailsList5.push({ ...element, nums: element.amountTotal, blankOutput: element.blankOutput.toFixed(4) });
+        totalObj[5].blankOutput += element.blankOutput;
+        totalObj[5].nums += element.amountTotal;
+      });
+      dtlList.value[1].statisticsDetailsList = statisticsDetailsList5;
+      dtlList.value[1].blankOutput = totalObj[5].blankOutput ? totalObj[5].blankOutput.toFixed(4) : 0;
+      dtlList.value[1].nums = totalObj[5].nums;
+    } catch (error) {
+      dtlList.value = [
+        {
+          // title: '总计',
+          title: '',
+          zjNo: 0,
+          blankOutput: 0,
+          nums: 0,
+          statisticsDetailsList: [],
+        },
+        {
+          title: '5#机',
+          zjNo: 5,
+          blankOutput: 0,
+          nums: 0,
+          statisticsDetailsList: [],
+        },
+      ];
+    }
+  };
+
+  onMounted(() => {
+    getList();
+    getStatistics();
+  });
+</script>
+<style scoped lang="less">
+  .rolling-three-dashboard {
+    width: 100%;
+    height: 100%;
+    padding: 20px;
+    overflow: hidden;
+    background: var(--bg-s-color);
+
+    .search-wrapper {
+      margin-bottom: 10px;
+      background-color: #005baf;
+      padding: 20px 20px 0;
+      border-radius: 4px;
+
+      .search-form {
+        :deep(.btnArea) {
+          .ant-form-item-row {
+            width: 100%;
+            justify-content: flex-end;
+          }
+        }
+      }
+
+      :deep(.ant-form) {
+        .ant-form-item .ant-form-item-label > label {
+          color: #fff;
+        }
+      }
+    }
+
+    :deep(.ant-spin-nested-loading) {
+      flex: 1;
+      overflow: hidden;
+    }
+
+    .ant-empty {
+      margin-top: 60px;
+      color: #cbcbcb;
+    }
+
+    .gutter-row {
+      max-width: 660px;
+      position: relative;
+
+      .ticket {
+        padding: 10px 10px 0;
+        border: 1px solid #c5c5c5;
+        background: beige;
+
+        &.disabled {
+          background: #e9e9e9;
+        }
+
+        .ticket-op-w {
+          margin-bottom: 10px;
+          text-align: right;
+
+          .ant-btn {
+            margin-left: 20px;
+          }
+        }
+
+        .ant-select {
+          :deep(.ant-select-selector) {
+            font-size: 14px;
+            padding: 0;
+
+            .ant-select-selection-item,
+            .ant-select-selection-placeholder {
+              padding-inline-end: 0;
+            }
+          }
+
+          :deep(.ant-select-arrow) {
+            display: none;
+          }
+        }
+
+        .ticket-info {
+          margin-top: 6px;
+          margin-bottom: 4px;
+
+          :deep(.ant-descriptions-view) {
+            .ticket-info-item {
+              border: 1px solid #bfbfbf;
+              font-size: 14px;
+              padding: 4px !important;
+              text-align: center;
+              height: 36px;
+              position: relative;
+              color: #333;
+
+              .line {
+                border-bottom: 1px solid #bfbfbf;
+
+                &:last-child {
+                  border-bottom: none;
+                }
+              }
+            }
+          }
+
+          .heatNo-item {
+            min-width: 120px;
+          }
+        }
+      }
+    }
+
+    .pagination {
+      margin-top: 20px;
+      text-align: right;
+      padding-right: 30px;
+
+      :deep(.ant-pagination-item) {
+        a {
+          color: rgba(51, 51, 51, 0.88);
+        }
+
+        &.ant-pagination-item-active {
+          background-color: var(--vxe-primary-color);
+          border-color: var(--vxe-primary-color);
+          a {
+            color: #fff;
+          }
+        }
+      }
+    }
+
+    .common-table {
+      margin-bottom: 20px;
+      color: #fff;
+
+      .wrapper-0 {
+        min-width: 300px;
+      }
+
+      .nb-left,
+      .nb-right {
+        flex-direction: column;
+      }
+
+      .nick {
+        padding: 0;
+        font-weight: 700;
+        // color: rgba(0, 0, 0, 0.8);
+
+        .total {
+          display: inline-block;
+          min-width: 130px;
+          margin-right: 30px;
+        }
+      }
+
+      .dtl-wrapper {
+        margin-top: 10px;
+      }
+
+      .dtl {
+        display: flex;
+        // color: rgba(0, 0, 0, 0.6);
+        gap: 8px 16px;
+
+        .nums {
+          display: inline-block;
+          min-width: 130px;
+          margin-right: 30px;
+        }
+
+        .bt-line {
+          border-bottom: 1px solid #eee;
+        }
+      }
+    }
+  }
+</style>

+ 651 - 0
src/views/billet/Dashboard/rollingThree.vue

@@ -0,0 +1,651 @@
+<template>
+  <div class="rolling-three-dashboard flex flex-col">
+    <div class="search-wrapper">
+      <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleSubmit">
+        <template #ccmNo="{ model, field }">
+          <segmented-select
+            v-model:value="model[field]"
+            @change="
+              () => {
+                handleSubmit();
+              }
+            "
+            dict="lg_zj"
+          />
+        </template>
+      </BasicForm>
+    </div>
+    <a-spin :spinning="loading">
+      <div class="common-table">
+        <a-descriptions bordered style="min-height: 72px" size="small" :column="5" :label-style="{ fontWeight: 'bold', width: '70px' }">
+          <template v-for="item in dtlList" :key="item.title">
+            <a-descriptions-item :label-style="!item.title ? { display: 'none' } : {}" :label="item.title">
+              <div :class="'wrapper-' + item.zjNo">
+                <div class="nb-left">
+                  <div class="flex">
+                    <div class="flex nick">
+                      <span class="total">总数:{{ item.nums }} 支</span>
+                    </div>
+
+                    <div class="flex nick">
+                      <span>重量:{{ item.blankOutput ? Number(item.blankOutput).toFixed(4) : 0 }} t</span>
+                    </div>
+                  </div>
+
+                  <div class="flex dtl-wrapper" v-if="item.statisticsDetailsList.length > 0">
+                    <div>明细:</div>
+                    <div class="dtl flex-1 flex flex-wrap">
+                      <div class="flex-dlt-item flex" v-for="ele in item.statisticsDetailsList">
+                        <div class="flex dtl-item bt-line">
+                          <span class="nums">{{ ele.size }}:&nbsp;&nbsp;&nbsp;{{ ele.nums }} 支</span>
+                        </div>
+                        <div class="flex dtl-item">
+                          <span class="nums bt-line">重量:{{ ele.blankOutput ? Number(ele.blankOutput).toFixed(4) : 0 }} t</span>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <!-- <div class="flex nb-right">
+            <div class="flex nick">
+              <span>重量:{{ item.blankOutput }}</span>
+            </div>
+
+            <div class="flex dtl-wrapper" v-if="item.statisticsDetailsList.length > 0">
+              <div class="dtl">
+                <div class="flex dtl-item" v-for="ele in item.statisticsDetailsList">
+                  <span>重量:{{ ele.blankOutput }}</span>
+                </div>
+              </div>
+            </div>
+          </div> -->
+              </div>
+            </a-descriptions-item>
+          </template>
+        </a-descriptions>
+      </div>
+      <template v-if="threeList.length">
+        <a-row :gutter="[16, 8]">
+          <a-col class="gutter-row" v-for="item in threeList" :key="item.id">
+            <div class="ticket next-ticket" :class="{ disabled: !!item.confirmTime }">
+              <div class="ticket-op-w" v-if="!isAuth">
+                <a-button type="primary" :disabled="!!item.confirmTime" size="small" @click="confirmCard(item)">确认装运单</a-button>
+                <a-button
+                  type="primary"
+                  size="small"
+                  :disabled="!!item.confirmTime"
+                  @click="
+                    openPrintModal(true, {
+                      record: item,
+                      isEdit: true,
+                      type: 'offline',
+                    })
+                  "
+                  ><Icon icon="ant-design:edit-outlined"
+                /></a-button>
+              </div>
+              <div class="flex" style="line-height: 24px">
+                <div class="flex-1"> 库名:{{ item.destination }} </div>
+                <div class="flex-1" style="text-align: center; font-size: 13px">
+                  {{ dayjs(item.arrivalTime).format('YYYY年MM月DD日 HH时mm分') }}
+                </div>
+                <div class="flex-1" style="text-align: right; font-size: 12px">
+                  <component :is="renderDictTag(item.shift, 'lg_bb')" />
+                  /
+                  <component :is="renderDictTag(item.shiftGroup, 'lg_bz')" />
+                </div>
+                <div class="flex-1" style="text-align: right"> {{ item.ccmNo }}#机 / {{ item.btype == 1 ? '冷' : '热' }} </div>
+              </div>
+              <a-descriptions class="ticket-info" layout="vertical" bordered :column="8" size="small">
+                <a-descriptions-item class="ticket-info-item" label="序号">
+                  <div style="min-height: 80px; display: flex; align-items: center; justify-content: center">
+                    {{ item.number }}
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="车号">
+                  {{ item.licensePlate }}
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="牌号">
+                  <component :is="renderDictTag(item.brandNum, 'billet_spec')" />
+                </a-descriptions-item>
+                <a-descriptions-item class="heat-wrapper ticket-info-item" label="炉号">
+                  <div style="min-width: 120px">
+                    <div class="heatNo-item" v-for="(ele, sindex) in item.headDtl" :key="item.id">
+                      {{ ele.heatNo }} - {{ ele.heatNum ? ele.heatNum : item.billetNos.length }}
+                    </div>
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="规格">
+                  <div style="min-width: 120px">
+                    <span> 170 /</span>
+                    {{ item.size }}
+                  </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="名称">
+                  <div style="min-width: 40px"> 方坯 </div>
+                </a-descriptions-item>
+                <a-descriptions-item class="ticket-info-item" label="支数">
+                  {{ item.amountTotal }}
+                </a-descriptions-item>
+                <!-- <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="重量">
+                <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">
+                <a-descriptions-item label="储运中心"> </a-descriptions-item>
+                <a-descriptions-item label="轧钢厂"> </a-descriptions-item>
+                <a-descriptions-item label="炼钢厂"> </a-descriptions-item>
+              </a-descriptions> -->
+            </div>
+          </a-col>
+        </a-row>
+
+        <a-pagination
+          class="pagination"
+          :defaultPageSize="pageLimit"
+          v-model:current="currentPage"
+          show-quick-jumper
+          :total="totalPage"
+          @change="onPageChange"
+        />
+      </template>
+      <a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
+    </a-spin>
+  </div>
+
+  <!-- 打印 -->
+  <printModal @register="registerPrintModal" @success="() => getList()" />
+
+  <!-- 确认 -->
+  <a-modal v-model:open="open" title="确认装运单" ok-text="确认" cancel-text="取消" @ok="confirmSubmit">
+    <div style="margin: 20px">
+      <div style="color: #f50; margin-bottom: 10px">说明:一经确认,装运单信息无法修改。</div>
+      <a-textarea v-model:value="remark" placeholder="备注" :auto-size="{ minRows: 2, maxRows: 5 }" />
+    </div>
+  </a-modal>
+</template>
+<script setup lang="ts">
+  import { onMounted, ref } from 'vue';
+  import { getStorageBillPrintList, saveStorageBillPrint, getrollClubStatistics } from './dashboard.api';
+  import dayjs, { Dayjs } from 'dayjs';
+  import { useForm, BasicForm, FormSchema } from '/@/components/Form';
+  import SegmentedSelect from '/@/components/SegmentedSelect/index.vue';
+  import { Empty } from 'ant-design-vue';
+  import { render } from '/@/utils/common/renderUtils';
+  import { useModal } from '/@/components/Modal';
+  import printModal from '../shippingBill/components/printModal.vue';
+  import { destinationOptions, machineDicts } from '../hotDelivery/common.data';
+  import { isJsonObjectString } from '/@/utils/is';
+  import { getMachineNum } from '../hotDelivery/common.data';
+  import { Pagination as APagination } from 'ant-design-vue';
+  import { useUserStore } from '/@/store/modules/user';
+  import { cloneDeep } from 'lodash-es';
+
+  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();
+  // 渲染字典标签
+  const renderDictTag = (value: string, dictCode: string) => {
+    return render.renderDict(value, dictCode);
+  };
+
+  //自定义表单字段
+  const formSchemas: FormSchema[] = [
+    {
+      field: 'ccmNo',
+      label: '铸机',
+      component: 'Input',
+      defaultValue: '5',
+      componentProps: {
+        dictCode: 'lg_zj',
+      },
+      colProps: { span: 6 },
+      slot: 'ccmNo',
+    },
+    {
+      label: '日期',
+      field: 'arrivalTime',
+      component: 'DatePicker',
+      componentProps: {
+        showTime: true,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      },
+    },
+    // {
+    //   label: '班组',
+    //   field: 'shiftGroup',
+    //   component: 'JDictSelectTag',
+    //   componentProps: {
+    //     dictCode: 'lg_bz',
+    //   },
+    // },
+    // {
+    //   label: '班别',
+    //   field: 'shift',
+    //   component: 'JDictSelectTag',
+    //   componentProps: {
+    //     dictCode: 'lg_bb',
+    //   },
+    // },
+  ];
+  /**
+   * BasicForm绑定注册;
+   */
+  const [registerForm, { getFieldsValue }] = useForm({
+    //注册表单列
+    schemas: formSchemas,
+    //是否显示展开收起按钮,默认false
+    showAdvancedButton: true,
+    //超过指定行数折叠,默认3行
+    autoAdvancedCol: 3,
+    //折叠时默认显示行数,默认1行
+    alwaysShowLines: 3,
+    //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
+    fieldMapToTime: [
+      // ['createTime', ['createTime_begin', 'createTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+      // ['storageTime', ['storageTime_begin', 'storageTime_end'], 'YYYY-MM-DD HH:mm:ss'],
+    ],
+    //每列占比,默认一行为24
+    baseColProps: { span: 6 },
+  });
+
+  /**
+   * 点击提交按钮的value值
+   * @param values
+   */
+  function handleSubmit() {
+    currentPage.value = 1;
+    getList();
+    getStatistics();
+  }
+
+  const currentPage = ref(1);
+  const totalPage = ref(0);
+  const pageLimit = ref(20);
+  const onPageChange = (n) => {
+    currentPage.value = n;
+    getList();
+  };
+
+  // 获取列表
+  const loading = ref(false);
+  const destinationTxt = {
+    '3': '棒三',
+    '4': '上若',
+  };
+  const nbDetinationTxt = {
+    '3': 'rollClubThreeStatisticsList',
+    '4': 'rollOutShippStatisticsList',
+  };
+  const getList = async () => {
+    try {
+      const values = getFieldsValue();
+      let params: any = Object.assign({}, values, { destination: destinationTxt[machineNum] });
+      if (!values.ccmNo) {
+        values.ccmNo = '5';
+      }
+      loading.value = true;
+
+      if (!values.arrivalTime) {
+        params = Object.assign({}, values, {
+          arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
+          destination: destinationTxt[machineNum],
+        });
+      }
+
+      loading.value = true;
+      const res = await getStorageBillPrintList({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params });
+
+      totalPage.value = res.total;
+      currentPage.value = res.current;
+      threeList.value = (res.records || []).map((item) => {
+        const shiftObj = item.classes.split('/');
+        let shift = '';
+        let shiftGroup = '';
+        if (shiftObj.length === 2) {
+          shift = shiftObj[0];
+          shiftGroup = shiftObj[1];
+        } else if (shiftObj.length > 2) {
+          shift = shiftObj[shiftObj.length - 2];
+          shiftGroup = shiftObj[shiftObj.length - 1];
+        }
+
+        const bzTxtObj = machineDicts['lg_bz'].find((el) => el.label === shiftObj[shiftObj.length - 1]);
+        if (bzTxtObj) {
+          shiftGroup = bzTxtObj.value;
+        }
+        const bbTxtObj = machineDicts['lg_bb'].find((el) => el.label === shiftObj[shiftObj.length - 2]);
+        if (bbTxtObj) {
+          shift = bbTxtObj.value;
+        }
+
+        const typeConfigId = destinationOptions[item.ccmNo].find((el) => el.label === item.destination);
+
+        const heatNos = isJsonObjectString(item.heatNo) ? JSON.parse(item.heatNo) : {};
+        const heatNosArr = Object.keys(heatNos).map((key) => {
+          return {
+            heatNo: key,
+            heatNum: heatNos[key],
+          };
+        });
+
+        return {
+          ...item,
+          recordId: item.id,
+          id: item.storageBillId,
+          shift,
+          shiftGroup,
+          typeConfigId: typeConfigId ? typeConfigId.value : '',
+          headDtl: heatNosArr,
+        };
+      });
+    } catch (error) {
+      console.log(error);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // 确定
+  const open = ref(false);
+  const confirmInfo = ref({});
+  const remark = ref('装运单确认无误!');
+  const confirmCard = (record) => {
+    open.value = true;
+    confirmInfo.value = record;
+    remark.value = '装运单确认无误!';
+  };
+  const confirmSubmit = () => {
+    const info: any = confirmInfo.value;
+    saveStorageBillPrint({
+      id: info.recordId,
+      confirmTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+      remark: remark.value,
+      storageBillId: info.id,
+      btype: info.btype,
+    }).then(() => {
+      open.value = false;
+      getList();
+    });
+  };
+
+  // 明细展示
+  const defaultDtl = [
+    {
+      // title: '总计',
+      title: '',
+      zjNo: 0,
+      blankOutput: 0,
+      nums: 0,
+      statisticsDetailsList: [],
+    },
+    {
+      title: '5#机',
+      zjNo: 5,
+      blankOutput: 0,
+      nums: 0,
+      statisticsDetailsList: [],
+    },
+    {
+      title: '6#机',
+      zjNo: 6,
+      blankOutput: 0,
+      nums: 0,
+      statisticsDetailsList: [],
+    },
+  ];
+  const dtlList = ref<any[]>(defaultDtl);
+  // 获取统计信息
+  /**
+   * ccmNo、changeShiftId、queryDate、queryType(1、2、3、4)代表棒一、棒二、棒三、上若,  就这四个参数,ccmNo、queryType  必输,changeShiftId、queryDate(2025-06-24)非必输,
+   **/
+  const getStatistics = async () => {
+    const values = getFieldsValue();
+    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'),
+      });
+      const res = staticsRres[0];
+      dtlItems[0].blankOutput = res.totalWeight || 0;
+      dtlItems[0].nums = res.counts || 0;
+      let totalObj = {
+        5: { blankOutput: 0, nums: 0 },
+        6: { blankOutput: 0, nums: 0 },
+      };
+      let statisticsDetailsList5: any[] = [];
+      let statisticsDetailsList6: any[] = [];
+
+      (res[nbDetinationTxt[machineNum]] || []).forEach((element) => {
+        if (ccmNo === '5') {
+          statisticsDetailsList5.push({ ...element, nums: element.amountTotal, blankOutput: element.blankOutput.toFixed(4) });
+          totalObj[5].blankOutput += element.blankOutput;
+          totalObj[5].nums += element.amountTotal;
+        }
+
+        if (ccmNo === '6') {
+          statisticsDetailsList6.push({ ...element, nums: element.amountTotal, blankOutput: element.blankOutput.toFixed(4) });
+          totalObj[6].blankOutput += element.blankOutput;
+          totalObj[6].nums += element.amountTotal;
+        }
+      });
+
+      if (ccmNo === '5') {
+        dtlItems[1].statisticsDetailsList = statisticsDetailsList5;
+        dtlItems[1].blankOutput = totalObj[5].blankOutput ? totalObj[5].blankOutput.toFixed(4) : 0;
+        dtlItems[1].nums = totalObj[5].nums;
+        dtlItems.splice(2, 1);
+      }
+
+      if (ccmNo === '6') {
+        dtlItems[2].statisticsDetailsList = statisticsDetailsList6;
+        dtlItems[2].blankOutput = totalObj[6].blankOutput ? totalObj[6].blankOutput.toFixed(4) : 0;
+        dtlItems[2].nums = totalObj[6].nums;
+        dtlItems.splice(1, 1);
+      }
+      dtlList.value = dtlItems;
+    } catch (error) {
+      if (ccmNo === '6') {
+        dtlItems.splice(1, 1);
+      }
+
+      if (ccmNo === '5') {
+        dtlItems.splice(2, 1);
+      }
+      dtlList.value = dtlItems;
+    }
+  };
+
+  onMounted(() => {
+    getStatistics();
+    getList();
+  });
+</script>
+<style scoped lang="less">
+  .rolling-three-dashboard {
+    width: 100%;
+    height: 100%;
+    padding: 20px;
+    overflow: hidden;
+    background: var(--bg-s-color);
+
+    .search-wrapper {
+      margin-bottom: 10px;
+      background-color: #005baf;
+      padding: 20px 20px 0;
+      border-radius: 4px;
+
+      .search-form {
+        :deep(.btnArea) {
+          .ant-form-item-row {
+            width: 100%;
+            justify-content: flex-end;
+          }
+        }
+      }
+
+      :deep(.ant-form) {
+        .ant-form-item .ant-form-item-label > label {
+          color: #fff;
+        }
+      }
+    }
+
+    :deep(.ant-spin-nested-loading) {
+      flex: 1;
+      overflow: hidden;
+    }
+
+    .ant-empty {
+      margin-top: 60px;
+      color: #cbcbcb;
+    }
+
+    .gutter-row {
+      max-width: 660px;
+      position: relative;
+
+      .ticket {
+        padding: 10px 10px 0;
+        border: 1px solid #c5c5c5;
+        background: beige;
+
+        &.disabled {
+          background: #e9e9e9;
+        }
+
+        .ticket-op-w {
+          margin-bottom: 10px;
+          text-align: right;
+
+          .ant-btn {
+            margin-left: 20px;
+          }
+        }
+
+        .ant-select {
+          :deep(.ant-select-selector) {
+            font-size: 14px;
+            padding: 0;
+
+            .ant-select-selection-item,
+            .ant-select-selection-placeholder {
+              padding-inline-end: 0;
+            }
+          }
+
+          :deep(.ant-select-arrow) {
+            display: none;
+          }
+        }
+
+        .ticket-info {
+          margin-top: 6px;
+          margin-bottom: 4px;
+
+          :deep(.ant-descriptions-view) {
+            .ticket-info-item {
+              border: 1px solid #bfbfbf;
+              font-size: 12px;
+              padding: 4px !important;
+              text-align: center;
+              height: 36px;
+              position: relative;
+              color: #333;
+            }
+          }
+
+          .heatNo-item {
+            min-width: 120px;
+          }
+        }
+      }
+    }
+
+    .pagination {
+      margin-top: 20px;
+      text-align: right;
+      padding-right: 30px;
+
+      :deep(.ant-pagination-item) {
+        a {
+          color: rgba(51, 51, 51, 0.88);
+        }
+
+        &.ant-pagination-item-active {
+          background-color: var(--vxe-primary-color);
+          border-color: var(--vxe-primary-color);
+          a {
+            color: #fff;
+          }
+        }
+      }
+    }
+
+    .common-table {
+      margin-bottom: 20px;
+      color: #fff;
+
+      .wrapper-0 {
+        min-width: 300px;
+      }
+
+      .nb-left,
+      .nb-right {
+        flex-direction: column;
+      }
+
+      .nick {
+        padding: 0;
+        font-weight: 700;
+        // color: rgba(0, 0, 0, 0.8);
+
+        .total {
+          display: inline-block;
+          min-width: 130px;
+          margin-right: 30px;
+        }
+      }
+
+      .dtl-wrapper {
+        margin-top: 10px;
+      }
+
+      .dtl {
+        display: flex;
+        // color: rgba(0, 0, 0, 0.6);
+        gap: 8px 16px;
+
+        .nums {
+          display: inline-block;
+          min-width: 130px;
+          margin-right: 30px;
+        }
+
+        .bt-line {
+          border-bottom: 1px solid #eee;
+        }
+      }
+    }
+  }
+</style>

+ 18 - 4
src/views/billet/ShiftPerformance/index.vue

@@ -41,9 +41,23 @@
                       <a-button
                         size="large"
                         type="primary"
-                        @click="openDetailModal(true, { record: shiftPerformanceColumns[currentShift], ccmNo: machine, isUpdate: true })"
+                        @click="
+                          openDetailModal(true, {
+                            shiftText: getTeamShift(
+                              shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shift : '',
+                              shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shiftGroup : ''
+                            ),
+                            curShiftInfo: {
+                              shift: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shift : '',
+                              shiftGroup: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shiftGroup : '',
+                            },
+                            queryType: '1',
+                            ccmNo: machine,
+                            changeShiftId: shiftPerformanceColumns[currentShift].id,
+                          })
+                        "
                       >
-                        浇铸炉次
+                        送样卡
                       </a-button>
 
                       <a-button
@@ -220,7 +234,7 @@
       </a-tab-pane>
     </a-tabs>
   </div>
-  <history @register="registerDetailModal" />
+  <printBilletSampleCard @register="registerDetailModal" />
   <!-- 打印原始数据 -->
   <printOriginalRecords @register="registerPrintOriginalRecordsModal" />
 </template>
@@ -240,8 +254,8 @@
   import type { Dayjs } from 'dayjs';
   import dayjs from 'dayjs';
   import { useModal } from '/@/components/Modal';
-  import history from './components/history.vue';
   import printOriginalRecords from '../operator/components/printOriginalRecords.vue';
+  import printBilletSampleCard from '../operator/components/printBilletSampleCard.vue';
 
   const currentDate = ref<Dayjs>(dayjs());
 

+ 110 - 56
src/views/billet/operator/components/printBilletSampleCard.vue

@@ -23,13 +23,14 @@
         </div>
         <a-descriptions style="margin-top: 6px; margin-bottom: 4px" bordered :column="8" size="small">
           <a-descriptions-item label="序号" :labelStyle="labelStyle" :contentStyle="contentStyle">炉号</a-descriptions-item>
+          <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="contentStyle">钢种</a-descriptions-item>
           <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
             <div class="size-items-title">
               定尺&nbsp;&nbsp;&nbsp;&nbsp;
               <span class="s-txt">{{ sizeArrs[0] ? '170' : '' }}</span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[0] ? Number(sizeArrs[0]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[0] ? Number(sizeArrs[0]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
           <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
@@ -38,7 +39,7 @@
               <span class="s-txt">{{ sizeArrs[1] ? '170' : '' }}</span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[1] ? Number(sizeArrs[1]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[1] ? Number(sizeArrs[1]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
           <!-- <a-descriptions-item label="序号" :labelStyle="labelStyle" :contentStyle="contentStyle">
@@ -54,7 +55,7 @@
               <span class="s-txt">{{ sizeArrs[2] ? '170' : '' }}</span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[2] ? Number(sizeArrs[1]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[2] ? Number(sizeArrs[2]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
           <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
@@ -63,7 +64,7 @@
               <span class="s-txt">{{ sizeArrs[3] ? '170' : '' }}</span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[3] ? Number(sizeArrs[3]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[3] ? Number(sizeArrs[3]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
           <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
@@ -74,7 +75,7 @@
               </span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[4] ? Number(sizeArrs[4]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[4] ? Number(sizeArrs[4]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
           <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
@@ -85,31 +86,34 @@
               </span>
             </div>
             <div class="size-num-title">
-              支数 <span class="s-txt">{{ sizeArrs[5] ? Number(sizeArrs[5]) / 1000 + 'm' : '' }}</span>
+              支数 <span class="s-txt">{{ sizeArrs[5] ? Number(sizeArrs[5]) + 'm' : '' }}</span>
             </div>
           </a-descriptions-item>
-          <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
+          <!-- <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
             <div class="size-items-title"> </div>
             <div class="size-num-title"> </div>
-          </a-descriptions-item>
+          </a-descriptions-item> -->
 
           <template v-for="i in 22">
             <!-- 第一组 -->
-            <a-descriptions-item :label="i" :labelStyle="labelStyle" :contentStyle="contentStyle">{{
-              heatList[i - 1] ? heatList[i - 1].heatNo : ''
-            }}</a-descriptions-item>
+            <a-descriptions-item :label="i" :labelStyle="labelStyle" :contentStyle="contentStyle">
+              <div style="width: 70px">
+                {{ heatList[i - 1] ? heatList[i - 1].heatNo : '' }}
+              </div>
+            </a-descriptions-item>
+            <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
+              <div style="width: 70px; text-align: center">
+                {{ heatList[i - 1] ? heatList[i - 1].brandNum : '' }}
+              </div>
+            </a-descriptions-item>
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">{{
-                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[0]]
-                  ? heatList[i - 1].sizeInfo[sizeArrs[0]].lengthTotalCount
-                  : ''
+                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[0]] ? heatList[i - 1].sizeInfo[sizeArrs[0]] : ''
               }}</div>
             </a-descriptions-item>
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">{{
-                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[1]]
-                  ? heatList[i - 1].sizeInfo[sizeArrs[1]].lengthTotalCount
-                  : ''
+                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[1]] ? heatList[i - 1].sizeInfo[sizeArrs[1]] : ''
               }}</div>
             </a-descriptions-item>
 
@@ -117,36 +121,28 @@
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">
                 {{
-                  heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[2]]
-                    ? heatList[i - 1].sizeInfo[sizeArrs[2]].lengthTotalCount
-                    : ''
+                  heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[2]] ? heatList[i - 1].sizeInfo[sizeArrs[2]] : ''
                 }}
               </div>
             </a-descriptions-item>
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">{{
-                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[3]]
-                  ? heatList[i - 1].sizeInfo[sizeArrs[3]].lengthTotalCount
-                  : ''
+                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[3]] ? heatList[i - 1].sizeInfo[sizeArrs[3]] : ''
               }}</div>
             </a-descriptions-item>
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">{{
-                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[4]]
-                  ? heatList[i - 1].sizeInfo[sizeArrs[4]].lengthTotalCount
-                  : ''
+                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[4]] ? heatList[i - 1].sizeInfo[sizeArrs[4]] : ''
               }}</div>
             </a-descriptions-item>
             <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content">{{
-                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[4]]
-                  ? heatList[i - 1].sizeInfo[sizeArrs[5]].lengthTotalCount
-                  : ''
+                heatList[i - 1] && heatList[i - 1].sizeInfo && heatList[i - 1].sizeInfo[sizeArrs[4]] ? heatList[i - 1].sizeInfo[sizeArrs[5]] : ''
               }}</div>
             </a-descriptions-item>
-            <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
+            <!-- <a-descriptions-item :labelStyle="sizeLabelStyle" :contentStyle="sizeContentStyle">
               <div class="size-items-content"></div>
-            </a-descriptions-item>
+            </a-descriptions-item> -->
           </template>
         </a-descriptions>
         <a-descriptions style="padding: 0" size="small" :column="7">
@@ -162,15 +158,57 @@
         </a-descriptions>
       </div>
     </section>
+    <template #appendFooter>
+      <a-button @click="openJSModal = true"> 重量计算 </a-button>
+    </template>
   </BasicModal>
+  <a-modal
+    v-model:open="openJSModal"
+    title="重量计算"
+    centered
+    width="600px"
+    :zIndex="9999"
+    @ok="
+      () => {
+        openJSModal = false;
+      }
+    "
+    @cancel="
+      () => {
+        openJSModal = false;
+      }
+    "
+  >
+    <div class="flex justify-center items-center" style="margin: 20px; line-height: 40px">
+      <a-input-group size="large">
+        <a-row :gutter="8">
+          <a-col :span="5">
+            <a-input type="number" :min="1" v-model:value="weightNum" placeholder="支数" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">*</a-col>
+          <a-col :span="5">
+            <a-input type="number" v-model:value="sizeNum" placeholder="定尺" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">*</a-col>
+          <a-col :span="5">
+            <a-input type="number" v-model:value="xiShu" placeholder="请输入比例" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">=</a-col>
+
+          <a-col :span="6" style="line-height: 40px; text-align: center">{{ weightCalc }}</a-col>
+        </a-row>
+      </a-input-group>
+    </div>
+  </a-modal>
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue';
+  import { ref, computed } from 'vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import dayjs from 'dayjs';
   import { printJS } from '/@/hooks/web/usePrintJS';
-  import { queryHeatsActualsByCcmNo } from '../operator.api';
+  import { querySampleCard } from '../operator.api';
+  import { isNumber } from '/@/utils/is';
 
   // 主机号
   const hostNumber = ref('5');
@@ -191,7 +229,7 @@
   };
   // content 样式
   const contentStyle = {
-    width: '120px',
+    width: '90px',
     textAlign: 'center',
     padding: '0',
     color: '#000',
@@ -206,7 +244,7 @@
 
   //表单赋值
   const [registerModal, { changeOkLoading }] = useModalInner(async (data) => {
-    const { ccmNo, shiftText, queryType, curShiftInfo } = data;
+    const { ccmNo, shiftText, queryType, curShiftInfo, changeShiftId } = data;
     hostNumber.value = ccmNo;
     shiftInfoTxt.value = shiftText.replace('-', '/');
     shiftInfo.value = curShiftInfo;
@@ -214,6 +252,7 @@
     getHeatList({
       ccmNo,
       queryType,
+      changeShiftId,
     });
   });
 
@@ -225,32 +264,30 @@
     try {
       let sizeList: string[] = [];
       let sizeObj: any = {};
-      const res = await queryHeatsActualsByCcmNo(params);
+      const res = await querySampleCard(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) {
-            const lengthObj: Record<string, any> = JSON.parse(item.length);
-            const sizeArr: string[] = Object.keys(lengthObj);
-            sizeList = sizeList.concat(sizeArr);
+          const lengthObj: Record<string, any> = item.lengthCountMap;
+          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;
-              }
-            });
-            newArr.push(item);
-          }
+          sizeArr.forEach((size) => {
+            if (!sizeObj[size]) {
+              sizeObj[size] = {
+                num: lengthObj[size],
+                // weight: lengthObj[size].lengthTotalWeight,
+              };
+            } else {
+              sizeObj[size].num += lengthObj[size];
+              // sizeObj[size].weight += lengthObj[size].lengthTotalWeight;
+            }
+          });
+          newArr.push(item);
         }
         // res.forEach((item) => {
         // });
@@ -265,6 +302,23 @@
     }
   };
 
+  const openJSModal = ref(false);
+  const xiShu = ref(0.2265);
+  const sizeNum = ref();
+  const weightNum = ref();
+  // 重量计算按钮
+  const weightCalc = computed(() => {
+    const w = Number(weightNum.value);
+    const x = Number(xiShu.value);
+    const s = Number(sizeNum.value);
+    if (isNumber(w) && isNumber(x) && isNumber(s)) {
+      const r = w * x * s;
+
+      return !isNaN(r) ? r.toFixed(6) : '';
+    }
+    return '';
+  });
+
   function onPrint() {
     changeOkLoading(true);
     printJS({
@@ -295,13 +349,13 @@
       line-height: 32px;
       border-bottom: 1px solid #bfbfbf;
       padding-left: 10px;
-      min-width: 90px;
+      min-width: 77px;
     }
 
     .size-num-title {
       font-size: 12px;
       line-height: 32px;
-      padding-left: 10px;
+      padding-left: 4px;
     }
 
     .size-items-content {

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

@@ -0,0 +1,624 @@
+<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="8" 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="8"> </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="8"> </a-table-summary-cell>
+            </a-table-summary-row>
+          </template>
+        </a-table>
+      </div>
+    </section>
+
+    <template #appendFooter>
+      <a-button @click="openJSModal = true"> 重量计算 </a-button>
+    </template>
+  </BasicModal>
+  <a-modal
+    v-model:open="openJSModal"
+    title="重量计算"
+    centered
+    width="600px"
+    :zIndex="9999"
+    @ok="
+      () => {
+        openJSModal = false;
+      }
+    "
+    @cancel="
+      () => {
+        openJSModal = false;
+      }
+    "
+  >
+    <div class="flex justify-center items-center" style="margin: 20px; line-height: 40px">
+      <a-input-group size="large">
+        <a-row :gutter="8">
+          <a-col :span="5">
+            <a-input type="number" v-model:value="weightNum" placeholder="支数" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">*</a-col>
+          <a-col :span="5">
+            <a-input type="number" v-model:value="sizeNum" placeholder="定尺" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">*</a-col>
+          <a-col :span="5">
+            <a-input type="number" v-model:value="xiShu" placeholder="请输入比例" />
+          </a-col>
+          <a-col :span="1" style="line-height: 40px; text-align: center">=</a-col>
+
+          <a-col :span="6" style="line-height: 40px; text-align: center">{{ weightCalc }}</a-col>
+        </a-row>
+      </a-input-group>
+    </div>
+  </a-modal>
+</template>
+<script lang="ts" setup>
+  import { ref, computed, h } 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';
+  import { isNumber } from '/@/utils/is';
+
+  // 渲染字典标签
+  const renderDictTag = (value: string, dictCode: string) => {
+    return render.renderDict(value, dictCode);
+  };
+  // 主机号
+  const hostNumber = ref('5');
+  const defaultColumns: 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: 40,
+        },
+        {
+          title: 'II流',
+          dataIndex: 'twoFlow',
+          key: 'twoFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'III流',
+          dataIndex: 'threeFlow',
+          key: 'threeFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'IV流',
+          dataIndex: 'fourFlow',
+          key: 'fourFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'V流',
+          dataIndex: 'fiveFlow',
+          key: 'fiveFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'VI流',
+          dataIndex: 'sixFlow',
+          key: 'sixFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'VII流',
+          dataIndex: 'sevenFlow',
+          key: 'sevenFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: 'VIII流',
+          dataIndex: 'eightFlow',
+          key: 'eightFlow',
+          align: 'center',
+          width: 40,
+        },
+        {
+          title: '合计',
+          dataIndex: 'total',
+          key: 'total',
+          align: 'center',
+          width: 40,
+        },
+      ],
+    },
+    {
+      title: '棒一',
+      width: 40,
+      align: 'center',
+      dataIndex: 'rollOne',
+      key: 'rollOne',
+      children: [],
+    },
+  ];
+
+  const columns = ref<TableColumnsType>(defaultColumns);
+  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;
+
+    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: '',
+        total: '',
+      });
+    }
+
+    dataSource.value = [...newSip];
+    getHeatList({
+      ccmNo,
+      queryType,
+      changeShiftId,
+    });
+  });
+
+  // 字段映射
+  const headText = {
+    rollClubTwoCount: '二',
+    rollClubThreeCount: '三',
+  };
+
+  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);
+          }
+        }
+
+        let sizeColumn: string[] = [];
+        let sizeHeadContent = {};
+        // 棒一
+        const rollOneColumns: TableColumnsType = [];
+
+        dataSource.value = dataSource.value.map((item, index) => {
+          if (!newArr[index]) return item;
+          let totalNum = 0;
+          const { totalInfo, length, hotSend, directRolling } = newArr[index];
+          if (totalInfo) {
+            const obj = JSON.parse(totalInfo);
+            totalNum = obj.totalCount;
+          }
+
+          // 棒一
+          let rollOneNum = '';
+          let rollOneSizesObj = {};
+          if (hotSend) {
+            const obj = JSON.parse(hotSend);
+            rollOneNum = obj.hotSendTotalCount || '';
+          }
+          if (directRolling) {
+            const obj = JSON.parse(directRolling);
+            rollOneNum = obj.directRollingTotalCount || '';
+            const lengthGroupCount = obj.lengthGroupCount;
+            if (lengthGroupCount) {
+              Object.keys(lengthGroupCount).forEach((key) => {
+                const column = Number(key) / 1000 + 'm';
+                const columnKey = column + 'rollOneColumn';
+                const findIndex = rollOneColumns.findIndex((item: any) => item.dataIndex === columnKey);
+                if (findIndex === -1) {
+                  rollOneColumns.push({
+                    title: column,
+                    dataIndex: columnKey,
+                    key: columnKey,
+                    align: 'center',
+                    width: 40,
+                  });
+                }
+
+                rollOneSizesObj[columnKey] = lengthGroupCount[key];
+              });
+            }
+          }
+
+          // 定尺
+          let sizeArr = {};
+          if (length) {
+            const obj = JSON.parse(length);
+            Object.keys(obj).forEach((k) => {
+              const sizeFormat = Number(k) / 1000 + 'm';
+              sizeArr[sizeFormat] = obj[k].lengthTotalCount;
+              sizeArr[sizeFormat + 'Arr'] = {
+                rollClubTwoCount: obj[k].rollClubTwoCount,
+                rollClubThreeCount: obj[k].rollClubThreeCount,
+              };
+              sizeColumn.push(sizeFormat);
+
+              // 判断是否有该字段,列头显示
+              if (!sizeHeadContent[sizeFormat]) {
+                sizeHeadContent[sizeFormat] = [];
+              }
+
+              if (obj[k].rollClubTwoCount && !sizeHeadContent[sizeFormat].includes('rollClubTwoCount')) {
+                sizeHeadContent[sizeFormat].push('rollClubTwoCount');
+              }
+              if (obj[k].rollClubThreeCount && !sizeHeadContent[sizeFormat].includes('rollClubThreeCount')) {
+                sizeHeadContent[sizeFormat].push('rollClubThreeCount');
+              }
+            });
+          }
+
+          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 || '',
+            total: totalNum || '',
+            rollOne: rollOneNum,
+            ...sizeArr,
+            ...rollOneSizesObj,
+          };
+        });
+
+        const otherColumn: TableColumnsType = [...new Set(sizeColumn)].map((item) => {
+          return {
+            title: () => {
+              const subHead = Object.keys(headText)
+                .filter((key) => sizeHeadContent[item].includes(key))
+                .map((key) => headText[key]);
+
+              return h('div', {}, [h('div', { style: { fontSize: '12px' } }, subHead.join(' / ')), h('div', {}, item)]);
+            },
+            dataIndex: item,
+            key: item,
+            align: 'center',
+            width: 50,
+            customRender: ({ text, record }) => {
+              if (!text) return '';
+              const sizeArr = [h('div', { class: 'line' }, ''), h('div', { class: 'size-st-item' }, text)];
+              if (record[item + 'Arr']) {
+                const subHead = Object.keys(headText)
+                  .filter((key) => sizeHeadContent[item].includes(key))
+                  .map((key) => record[item + 'Arr'][key] || '~');
+                sizeArr.push(h('div', { class: ' size-st-num' }, subHead.join('/')));
+              }
+              return h('div', { class: 'size-st-wrapper' }, sizeArr);
+            },
+          };
+        });
+
+        // 添加空白列
+        otherColumn.push({
+          title: '',
+          dataIndex: '',
+          key: '',
+          align: 'center',
+          width: 40,
+        });
+        columns.value = [...defaultColumns, ...otherColumn];
+        if (rollOneColumns.length) {
+          columns.value[4].children = rollOneColumns;
+        }
+      }
+    } catch (error) {
+      console.log(error);
+    }
+  };
+
+  const openJSModal = ref(false);
+  const xiShu = ref(0.2265);
+  const sizeNum = ref();
+  const weightNum = ref();
+  // 重量计算按钮
+  const weightCalc = computed(() => {
+    const w = Number(weightNum.value);
+    const x = Number(xiShu.value);
+    const s = Number(sizeNum.value);
+    if (isNumber(w) && isNumber(x) && isNumber(s)) {
+      const r = w * x * s;
+
+      return !isNaN(r) ? r.toFixed(6) : '';
+    }
+    return '';
+  });
+
+  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;
+            position: relative;
+          }
+
+          .size-st-wrapper {
+            position: absolute;
+            top: 1px;
+            left: 1px;
+            right: 1px;
+            bottom: 1px;
+
+            .line {
+              content: '';
+              position: absolute;
+              top: 0;
+              left: 0;
+              width: 100%; /* 等于长方形宽度 */
+              height: 100%; /* 等于长方形高度 */
+
+              /* 创建斜线:线性渐变从左上到右下 */
+              background: linear-gradient(
+                to bottom right,
+                transparent 0%,
+                transparent calc(50% - 0.5px),
+                /* 斜线上方透明 */ rgba(0, 0, 0, 0.6) calc(50% - 0.5px),
+                /* 斜线颜色 */ rgba(0, 0, 0, 0.6) calc(50% + 0.5px),
+                /* 斜线厚度 */ transparent calc(50% + 0.5px) /* 斜线下方透明 */
+              );
+            }
+
+            .size-st-item {
+              position: absolute;
+              top: -4px;
+              left: 2px;
+              color: #108ee9;
+            }
+
+            .size-st-num {
+              position: absolute;
+              bottom: -4px;
+              right: 2px;
+              color: #f50;
+            }
+          }
+        }
+      }
+
+      .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 {
+      margin-top: 10px; /* 第一页的页眉距离顶部为0 */
+      margin-bottom: 0; /* 第一页的页脚距离底部为0 */
+    }
+  }
+</style>

File diff suppressed because it is too large
+ 782 - 71
src/views/billet/operator/components/printOriginalRecords.vue


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

@@ -27,6 +27,12 @@ enum Api {
   addRollOneBilletBasic = '/rollClubOneDetails/addBilletBasic',
   // 调整炉次支数
   adjustHeatBillet = '/billetHotsendBase/billetHotsendBase/changeHeatNo',
+  // 原始数据
+  queryBilletRecordByCcmNo = '/billet/billetOriginalProductRecord/queryBilletRecordByCcmNo',
+  // 编辑
+  billetRecordEdit = '/billet/billetOriginalProductRecord/edit',
+  // 送样卡
+  sampleCardDelivery = '/billet/billetOriginalProductRecord/lengthDetailsTable',
 }
 
 // 炉次信息
@@ -93,3 +99,18 @@ export const addRollOneBilletBasic = (params: any) => {
 export const adjustHeatBillet = (params: any) => {
   return defHttp.post({ url: Api.adjustHeatBillet, params });
 };
+
+// 原始数据
+export const queryBilletRecordByCcmNo = (params: any) => {
+  return defHttp.get({ url: Api.queryBilletRecordByCcmNo, params });
+};
+
+// 编辑原始数据
+export const editBilletRecord = (params: any) => {
+  return defHttp.post({ url: Api.billetRecordEdit, params });
+};
+
+// 送样卡雷彪
+export const querySampleCard = (params: any) => {
+  return defHttp.get({ url: Api.sampleCardDelivery, params });
+};

+ 108 - 51
src/views/billet/shippingBill/components/printModal.vue

@@ -1,5 +1,14 @@
 <template>
-  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose title="装运单打印" :height="400" :width="800" ok-text="打印" @ok="onPrint">
+  <BasicModal
+    v-bind="$attrs"
+    @register="registerModal"
+    destroyOnClose
+    :title="isEditCard ? '编辑装运单' : '装运单打印'"
+    :height="400"
+    :width="800"
+    :ok-text="isEditCard ? '确认' : '打印'"
+    @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; cursor: pointer" @click="changeBtype">
         {{ info.ccmNo }}#机 / {{ info.btype == 1 ? '冷' : '热' }}
@@ -13,7 +22,9 @@
         <div class="flex" style="line-height: 24px">
           <div class="flex-1">
             库名:
+            <span v-if="isEditCard">{{ info.destination }}</span>
             <JSearchSelect
+              v-else
               type="list"
               style="width: 120px"
               :bordered="false"
@@ -34,96 +45,108 @@
             />
             <!-- <a-input v-model:value="info.arrivalTimeDay" class="lgprint-date-picker" :bordered="false" /> -->
           </div>
-          <div class="flex-1" style="text-align: right; font-size: 12px">
-            <!-- <a-input v-model:value="info.classes" style="font-size: 12px; padding: 0; width: 100%; text-align: right" :bordered="false" /> -->
+          <div class="flex-1" style="text-align: right; font-size: 14px">
+            <!-- <a-input v-model:value="info.classes" style="font-size: 14px; padding: 0; width: 100%; text-align: right" :bordered="false" /> -->
             <JSearchSelect
               type="list"
               :bordered="false"
-              v-model:value="info.shiftGroup"
+              v-model:value="info.shift"
               dict="lg_bb"
-              style="width: 60px; font-size: 12px"
-              placeholder="请选择"
-              allowClear
+              style="width: 60px; font-size: 14px; text-align: right"
+              placeholder="班别"
             />
             /
             <JSearchSelect
               type="list"
               :bordered="false"
-              v-model:value="info.shift"
+              v-model:value="info.shiftGroup"
               dict="lg_bz"
-              style="width: 50px; font-size: 12px"
-              placeholder="请选择"
-              allowClear
+              style="width: 50px; font-size: 14px; text-align: left"
+              placeholder="班组"
             />
           </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="序号">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="序号">
             <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"
+                style="font-size: 14px; 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="车号">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="车号">
             <!-- {{ info.licensePlate }} -->
             <JSearchSelect
               type="list"
               :bordered="false"
               v-model:value="info.licensePlate"
               dict="lg_car"
-              style="width: 110px; font-size: 12px"
+              style="width: 110px; font-size: 14px"
               placeholder="请选择"
               allowClear
             />
           </a-descriptions-item>
-          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="牌号">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="牌号">
             <!-- <component :is="renderDictTag(info.brandNum, 'billet_spec')" /> -->
-            <JSearchSelect type="list" :bordered="false" v-model:value="info.brandNum" dict="billet_spec" placeholder="请选择" allowClear />
+            <JSearchSelect
+              type="list"
+              style="width: 110px; font-size: 14px"
+              :bordered="false"
+              v-model:value="info.brandNum"
+              dict="billet_spec"
+              placeholder="请选择"
+              allowClear
+            />
           </a-descriptions-item>
           <a-descriptions-item
             class="heat-wrapper"
-            style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px; position: relative"
+            style="border: 1px solid #bfbfbf; font-size: 14px; 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)"><Icon icon="ant-design:delete-outlined" /></div>
-              <div class="op add" @click="editHeatDtl(sindex)">
-                <Icon icon="ant-design:edit-outlined" />
+            <div style="min-width: 120px">
+              <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)"><Icon icon="ant-design:delete-outlined" /></div>
+                <div class="op add" @click="editHeatDtl(sindex)">
+                  <Icon icon="ant-design:edit-outlined" />
+                </div>
               </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="规格">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="规格">
             <div style="min-width: 120px">
               <span> 170 /</span>
               <!-- {{ sizeInfo.join(',') }} -->
+              <span v-if="isEditCard">{{ info.size }}</span>
               <!-- <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" />
+              <a-input v-else v-model:value="info.size" :bordered="false" style="width: 80px; padding: 0; font-size: 14px; 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="名称">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; 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="支数">
+          <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="支数">
+            <span v-if="isEditCard">{{ info.amountTotal }}</span>
             <!-- {{ info.amountTotal }} -->
             <a-input-number
+              v-else
               :bordered="false"
-              style="min-width: 50px; width: 50px; font-size: 12px; text-align: center"
+              style="min-width: 50px; width: 50px; font-size: 14px; text-align: center"
               v-model:value="info.amountTotal"
               :min="0"
               :max="99"
               :precision="0"
+              :controls="false"
             />
           </a-descriptions-item>
-          <!-- <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 12px; padding: 4px; text-align: center; height: 36px" label="重量">
+          <!-- <a-descriptions-item style="border: 1px solid #bfbfbf; font-size: 14px; padding: 4px; text-align: center; height: 36px" label="重量">
             <a-input-number
               :bordered="false"
-              style="min-width: 80px; width: 80px; font-size: 12px; text-align: center"
+              style="min-width: 80px; width: 80px; font-size: 14px; text-align: center"
               v-model:value="info.weight"
               :min="0"
               :max="99"
@@ -131,7 +154,7 @@
             />
           </a-descriptions-item> -->
         </a-descriptions>
-        <a-descriptions style="padding: 0 30px" size="small">
+        <a-descriptions style="padding: 0 30px" size="small" v-if="!isEditCard">
           <a-descriptions-item label="储运中心"> </a-descriptions-item>
           <a-descriptions-item label="轧钢厂"> </a-descriptions-item>
           <a-descriptions-item label="炼钢厂"> </a-descriptions-item>
@@ -151,11 +174,12 @@
         </a-row>
       </a-input-group>
     </div>
+    <div style="position: absolute;left: -1000px;">{{ getAllAmount }}</div>
   </BasicModal>
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue';
+  import { computed, ref } from 'vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import dayjs from 'dayjs';
   // import { render } from '/@/utils/common/renderUtils';
@@ -175,30 +199,41 @@
     },
   });
 
+  const emits = defineEmits(['success']);
+
   const info = ref<any>({});
   const headDtl = ref<any[]>([]);
   const weight = ref<number>(0);
   const sizeInfo = ref<string[]>([]);
   const numberEdit = ref();
+  const isEditCard = ref(false);
   //表单赋值
-  const [registerModal, { changeLoading, changeOkLoading }] = useModalInner(async (data) => {
-    const { record, type } = data;
+  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),
-        number: record.carAllNum,
+        number: record.carAllNum || record.number,
         classes:
-          // dayjs(record.arrivalTime).format('YYYYMMDDHHmmss') +
-          // '/' +
-          // record.carNum +
-          // '/' +
-          // record.carAllNum +
-          // '/' +
-          record.shift_dictText + '/' + record.shiftGroup_dictText,
+          isEdit === true
+            ? record.classes
+            : // dayjs(record.arrivalTime).format('YYYYMMDDHHmmss') +
+              // '/' +
+              // record.carNum +
+              // '/' +
+              // record.carAllNum +
+              // '/' +
+              record.shift_dictText + '/' + record.shiftGroup_dictText,
       };
 
-      await getTableList();
+      // 如果只是纯纯的编辑
+      if (isEdit === true) {
+      } else {
+        await getTableList();
+      }
+
       if (type === 'offline') {
         getOfflineBill();
       }
@@ -212,6 +247,13 @@
   // const renderDictTag = (value: string, dictCode: string) => {
   //   return render.renderDict(value, dictCode);
   // };
+  const getAllAmount = computed(() => {
+    const allNum = headDtl.value.reduce((acc, cur) => {
+      return acc + Number(cur.heatNum ? cur.heatNum : cur.billetNos.length);
+    }, 0);
+    info.value.amountTotal = allNum;
+    return allNum;
+  });
 
   const getTableList = async () => {
     try {
@@ -288,12 +330,15 @@
             shift = info.value.shift;
             shiftGroup = info.value.shiftGroup;
           }
+          const destinationInfo = (destinationOptions[info.value.ccmNo] || []).find((item) => item.label === res.destination);
           info.value = {
             ...info.value,
             ...res,
             shift,
             shiftGroup,
             arrivalTimeDay: dayjs(res.arrivalTime),
+            destination: res.destination,
+            typeConfigId: destinationInfo ? destinationInfo.value : '',
           };
 
           headDtl.value = Object.keys(res.heatNo).map((item) => ({
@@ -371,6 +416,11 @@
   function onPrint() {
     changeOkLoading(true);
 
+    if (!info.value.destination || !info.value.typeConfigId || info.value.typeConfigId === '1024') {
+      createMessage.error('请选择目的地!');
+      return;
+    }
+
     let headDtlObj = {};
     headDtl.value.forEach((item) => {
       headDtlObj[item.heatNo] = item.heatNum ? item.heatNum : item.billetNos.length;
@@ -390,11 +440,17 @@
       classes: info.value.shift + '/' + info.value.shiftGroup,
       btype: info.value.btype,
       ccmNo: info.value.ccmNo,
+    }).then((res) => {
+      emits('success', res);
+      closeModal();
     });
-    printJS({
-      printable: '#printContent',
-      type: 'html',
-    });
+
+    if (isEditCard.value !== true) {
+      printJS({
+        printable: '#printContent',
+        type: 'html',
+      });
+    }
     setTimeout(() => {
       changeOkLoading(false);
     }, 1000);
@@ -404,11 +460,11 @@
 <style lang="less">
   #printContent {
     .lgprint-date-picker {
-      font-size: 13px;
+      font-size: 14px;
       padding: 0;
 
       .ant-picker-input > input {
-        font-size: 13px;
+        font-size: 14px;
         text-align: center;
       }
 
@@ -418,8 +474,9 @@
     }
 
     .ant-select {
-      .ant-select-single .ant-select-selector {
-        font-size: 12px;
+      &.ant-select-single .ant-select-selector {
+        font-size: 14px;
+        padding: 0;
       }
 
       .ant-select-selection-item {

+ 5 - 4
src/views/billet/shippingBill/index.vue

@@ -296,10 +296,11 @@
           });
         },
       },
+
       {
-        label: '打印',
+        label: '票据',
         onClick: () => {
-          openPrintModal(true, { record, isUpdate: true });
+          openPrintModal(true, { record, isUpdate: true, type: 'offline' });
         },
         disabled: false,
       },
@@ -326,9 +327,9 @@
         disabled: false,
       },
       {
-        label: '线下票据',
+        label: '打印',
         onClick: () => {
-          openPrintModal(true, { record, isUpdate: true, type: 'offline' });
+          openPrintModal(true, { record, isUpdate: true });
         },
         disabled: false,
       },

+ 43 - 43
src/views/billet/shippingBill/shippingBill.data.ts

@@ -120,20 +120,6 @@ export const columns: BasicColumn[] = computed(() => [
       }
     },
   },
-  {
-    title: '组坯号',
-    align: 'center',
-    width: 280,
-    dataIndex: 'assemblyNumber',
-    ellipsis: false,
-    customRender(opt) {
-      const ph = opt.record.assemblyNumber;
-      if (!ph) return '';
-      const phArr = groupArray(ph.split(','), 2);
-
-      return phArr.join('\n\r').replaceAll(',', '、');
-    },
-  },
   {
     title: '总支数',
     align: 'center',
@@ -145,9 +131,9 @@ export const columns: BasicColumn[] = computed(() => [
     title: '到达轧钢时间',
     align: 'center',
     width: 160,
-    dataIndex: 'steelReachTime',
+    dataIndex: 'confirmTime',
     customRender(opt) {
-      return render.renderTag(opt.record.steelReachTime, '#f50');
+      return render.renderTag(opt.record.confirmTime, '#f50');
     },
   },
   {
@@ -180,39 +166,53 @@ export const columns: BasicColumn[] = computed(() => [
     dataIndex: 'carAllNum',
     // fixed: true,
   },
-  {
-    title: '钢种',
-    align: 'center',
-    width: 80,
-    dataIndex: 'steel',
-    // fixed: true
-  },
-  {
-    title: '规格',
-    align: 'center',
-    width: 80,
-    dataIndex: 'spec_dictText',
-    // fixed: true
-  },
-  {
-    title: '看板总支数',
-    align: 'center',
-    width: 120,
-    dataIndex: 'panelAmountTotal',
-    // fixed: true
-  },
-  {
-    title: '备注',
-    align: 'center',
-    width: 300,
-    dataIndex: 'remarks',
-  },
+  // {
+  //   title: '钢种',
+  //   align: 'center',
+  //   width: 80,
+  //   dataIndex: 'steel',
+  //   // fixed: true
+  // },
+  // {
+  //   title: '规格',
+  //   align: 'center',
+  //   width: 80,
+  //   dataIndex: 'spec_dictText',
+  //   // fixed: true
+  // },
+  // {
+  //   title: '看板总支数',
+  //   align: 'center',
+  //   width: 120,
+  //   dataIndex: 'panelAmountTotal',
+  //   // fixed: true
+  // },
+  // {
+  //   title: '备注',
+  //   align: 'center',
+  //   width: 300,
+  //   dataIndex: 'remarks',
+  // },
   {
     title: '创建日期',
     align: 'center',
     width: 160,
     dataIndex: 'createTime',
   },
+  {
+    title: '组坯号',
+    align: 'center',
+    width: 280,
+    dataIndex: 'assemblyNumber',
+    ellipsis: false,
+    customRender(opt) {
+      const ph = opt.record.assemblyNumber;
+      if (!ph) return '';
+      const phArr = groupArray(ph.split(','), 2);
+
+      return phArr.join('\n\r').replaceAll(',', '、');
+    },
+  },
   {
     title: '操作',
     dataIndex: 'action',

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

@@ -344,6 +344,10 @@
   const onExportTicketsXls = () => {
     const values = getFieldsValue();
     console.log('values', values);
+    if (!values.receipt) {
+      createMessage.error('请选择票据打印日期');
+      return;
+    }
     let queryParams = Object.keys(values)
       .filter((v) => values[v])
       .map((key) => {

Some files were not shown because too many files changed in this diff