123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774 |
- <template>
- <div class="rolling-three-dashboard flex flex-col">
- <div class="search-wrapper">
- <BasicForm class="search-form" @register="registerForm" @submit="handleSubmit" @reset="handleReSubmit">
- <template #shiftObj>
- <div class="shift-performance-tags flex-1">
- <a-tag :color="shiftColor[index]" @click="() => (currentShift = index)" v-for="(item, index) in shiftPerformanceColumns">
- {{ item.createTime ? item.createTime.substring(5, 16) : '' }} ~
- {{ item.changeShiftTime ? item.changeShiftTime.substring(5, 16) : '' }}
- 【{{ getTeamShift(item.shift, item.shiftGroup) }}】
- <span class="current-shift" :style="{ background: shiftColor[index] }" v-if="index === currentShift"></span>
- </a-tag>
- </div>
- </template>
- <template #advanceBefore>
- <a-button type="primary" preIcon="ant-design:export-outlined" style="margin-right: 10px" @click="onExportXls"> 导出</a-button>
- </template>
- </BasicForm>
- </div>
- <a-spin :spinning="loading">
- <div class="common-table">
- <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 font-weight" :style="{ color: sizeColor[ele.size] }">
- <span class="nums">{{ ele.size }}: {{ 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 font-weight"
- :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
- :style="{ cursor: 'pointer', color: sizeColor[ele.size] }"
- 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 font-weight"
- :class="[item.sizeValue !== ele.value ? 'noprint' : 'selected']"
- :style="{ cursor: 'pointer', color: sizeColor[ele.size] }"
- 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,
- exportOneExcel,
- getRollHeightList,
- exportHeightExcel,
- } 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';
- import { list } from '../ShiftPerformance/ShiftPerformance.api';
- import { getTeamShift } from './dashboard.api';
- import { useMethods } from '/@/hooks/system/useMethods';
- import { Colors } from './dashboard.data';
- // 导入导出方法
- const { handleExportXlsx } = useMethods();
- const userStore = useUserStore();
- const isAuth = userStore.userInfo && userStore.userInfo.username === '5';
- const threeList = ref<any[]>([]);
- const machineNum = getMachineNum(true) || '3';
- // 明细展示
- 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 shiftPerformanceColumns = ref<any>([]);
- const shiftColor = ['#f50', '#2db7f5', '#87d068'];
- const currentShift = ref(-1);
- //自定义表单字段
- const formSchemas: FormSchema[] = [
- {
- label: '炉号',
- field: 'heatNo',
- component: 'Input',
- },
- {
- label: '定尺',
- field: 'size',
- component: 'Input',
- },
- {
- label: '日期',
- field: 'arrivalTime',
- component: 'RangePicker',
- componentProps: {
- showTime: true,
- valueFormat: 'YYYY-MM-DD HH:mm:ss',
- },
- },
- {
- label: '牌号',
- field: 'brandNum',
- component: 'JDictSelectTag',
- componentProps: {
- dictCode: 'billet_spec',
- },
- colProps: { span: 6 },
- },
- // {
- // label: '',
- // field: 'yuzhanyuan',
- // component: 'Input',
- // slot: 'yuzhanyuan',
- // colProps: { span: 6 },
- // },
- {
- label: '班次日期',
- field: 'queryDate',
- component: 'DatePicker',
- componentProps: {
- valueFormat: 'YYYY-MM-DD',
- onChange: (v) => {
- currentShift.value = -1;
- getShiftInfo(3, dayjs(v));
- },
- },
- },
- {
- label: '',
- field: 'shiftObj',
- component: 'Input',
- slot: 'shiftObj',
- colProps: { span: 12 },
- },
- // {
- // label: '班组',
- // field: 'shiftGroup',
- // component: 'JDictSelectTag',
- // componentProps: {
- // dictCode: 'lg_bz',
- // },
- // },
- // {
- // label: '班别',
- // field: 'shift',
- // component: 'JDictSelectTag',
- // componentProps: {
- // dictCode: 'lg_bb',
- // },
- // },
- ];
- /**
- * BasicForm绑定注册;
- */
- const [registerForm, { getFieldsValue }] = useForm({
- //注册表单列
- schemas: formSchemas,
- //是否显示展开收起按钮,默认false
- showAdvancedButton: false,
- //超过指定行数折叠,默认3行
- autoAdvancedCol: 3,
- //折叠时默认显示行数,默认1行
- alwaysShowLines: 3,
- //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
- fieldMapToTime: [
- ['arrivalTime', ['startTime', 'endTime'], '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();
- }
- function handleReSubmit() {
- currentShift.value = -1;
- currentPage.value = 1;
- shiftPerformanceColumns.value = [];
- 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 = {
- '1': '棒一',
- '5': '高线',
- };
- const getList = async () => {
- try {
- const values = getFieldsValue();
- let params: any = Object.assign({}, values, { destination: destinationTxt[machineNum] });
- values.ccmNo = machineNum == '1' ? '5' : '6';
- loading.value = true;
- if (!values.arrivalTime) {
- params = Object.assign({}, values, {
- // arrivalTime: dateObj.value.format('YYYY-MM-DD 00:00:00'),
- destination: destinationTxt[machineNum],
- });
- }
- // 班次
- let changeShiftId = undefined;
- if (currentShift.value !== -1) {
- changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
- }
- loading.value = true;
- const fetchFn = machineNum == '1' ? getRollClubOneList : getRollHeightList;
- const res = await fetchFn({ pageNo: currentPage.value, pageSize: pageLimit.value, ...params, changeShiftId });
- totalPage.value = res.total;
- currentPage.value = res.current;
- threeList.value = (res.records || []).map((item) => {
- const {
- heatNoDetails,
- storageCenterHeatNoInvoicing: { rollClubOneDetails, rollHeightDetails },
- } = item;
- const { sizeDetails, confirmTime, id, brandNum } = rollClubOneDetails ? rollClubOneDetails : rollHeightDetails;
- const sizeObj = {};
- sizeDetails.forEach((item) => {
- sizeObj[item.size] = item;
- });
- return {
- ...heatNoDetails[0],
- sizeObj,
- sizeValue: sizeDetails && sizeDetails.length ? 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();
- });
- };
- const sizeColor = ref({});
- // 获取统计信息
- /**
- * ccmNo、changeShiftId、queryDate、queryType(1、2、3、4)代表棒一、棒二、棒三、上若, 就这四个参数,ccmNo、queryType 必输,changeShiftId、queryDate(2025-06-24)非必输,
- **/
- const getStatistics = async () => {
- try {
- const values = getFieldsValue();
- let params: any = Object.assign({}, values, { queryType: '1', ccmNo: machineNum == '1' ? '5' : '6' });
- // 班次
- let changeShiftId = undefined;
- if (currentShift.value !== -1) {
- changeShiftId = shiftPerformanceColumns.value[currentShift.value].id;
- }
- const staticsRres = await getrollClubStatistics({ ...params, changeShiftId });
- const res = staticsRres[0];
- dtlList.value[0].blankOutput = res.totalWeight || 0;
- dtlList.value[0].nums = res.counts || 0;
- let totalObj = {
- 5: { blankOutput: 0, nums: 0 },
- };
- let statisticsDetailsList5: any[] = [];
- res.billetStatisticList.forEach((element, index) => {
- sizeColor.value[element.size] = Colors[index] ? Colors[index] : '#f50';
- 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: [],
- },
- ];
- }
- };
- // 获取班次信息
- const getShiftInfo = async (pageSize: number = 3, date?: Dayjs) => {
- try {
- if (date && !date.isValid()) {
- shiftPerformanceColumns.value = [];
- currentShift.value = -1;
- return false;
- }
- loading.value = true;
- const createTime_begin = date ? date.subtract(1, 'day').format('YYYY-MM-DD 23:55:00') : undefined;
- const createTime_end = date ? date.add(1, 'day').format('YYYY-MM-DD 00:05:00') : undefined;
- const res = await list({
- ccmNo: machineNum == '1' ? '5' : '6',
- pageNo: 1,
- pageSize: pageSize,
- column: 'createTime',
- order: 'asc',
- ...(date ? { createTime_begin, createTime_end } : {}),
- });
- const { records } = res;
- const arr = records || [];
- shiftPerformanceColumns.value = arr
- .filter((item) => item.createTime && item.changeShiftTime) // 过滤掉 createTime 为空的数据
- .sort((a, b) => {
- const dateA = new Date(a.createTime).getTime(); // 转换为时间戳
- const dateB = new Date(b.createTime).getTime(); // 转换为时间戳
- if (isNaN(dateA) || isNaN(dateB)) {
- console.warn('Invalid date detected:', a.createTime, b.createTime);
- return 0; // 如果日期无效,视为相等
- }
- return dateA - dateB; // 按时间戳排序
- });
- // currentShift.value = shiftPerformanceColumns.value.length > 0 ? shiftPerformanceColumns.value.length - 1 : 0;
- } catch (error) {
- console.error(error);
- } finally {
- loading.value = false;
- }
- };
- // 导出
- const onExportXls = () => {
- const values = getFieldsValue();
- let params = Object.assign({}, values, { ccmNo: machineNum == '1' ? '5' : '6' });
- if (currentShift.value >= 0) {
- params = {
- changeShiftId: shiftPerformanceColumns.value[currentShift.value].id,
- queryDate: values.queryDate,
- ccmNo: machineNum == '1' ? '5' : '6',
- };
- }
- let queryParams = Object.keys(params)
- .filter((v) => params[v])
- .map((key) => {
- return `${key}=${params[key]}`;
- });
- const exportExlUrl = machineNum == '1' ? exportOneExcel() : exportHeightExcel();
- const exportExlTitle = machineNum == '1' ? '棒一数据' : '高线数据';
- return handleExportXlsx(exportExlTitle, exportExlUrl + (queryParams.length > 0 ? '?' + queryParams.join('&') : ''));
- };
- onMounted(() => {
- getList();
- // getShiftInfo(3, dayjs());
- 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;
- }
- }
- }
- .shift-performance-tags {
- margin-left: 10px;
- .ant-tag {
- padding: 6px 6px;
- position: relative;
- cursor: pointer;
- margin-bottom: 20px;
- }
- .current-shift {
- position: absolute;
- display: inline-block;
- width: 60px;
- height: 4px;
- border-radius: 4px;
- bottom: -8px;
- left: 50%;
- transform: translateX(-30px);
- }
- }
- .font-weight {
- font-weight: 700;
- }
- }
- </style>
|