广丰卷烟厂数采质量分析系统
zhuguifei
7 天以前 2b31fa203f3435a582be51f45899d99164c9917a
ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
old mode 100644 new mode 100755
@@ -1,5 +1,5 @@
<script setup lang="tsx">
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { NDivider } from 'naive-ui';
import { fetchBatchDeleteStoreSilk, fetchGetStoreSilkList } from '@/service/api/analy/store-silk';
import { useAppStore } from '@/store/modules/app';
@@ -10,6 +10,8 @@
import ButtonIcon from '@/components/custom/button-icon.vue';
import StoreSilkOperateDrawer from './modules/store-silk-operate-drawer.vue';
import StoreSilkSearch from './modules/store-silk-search.vue';
import StoreSilkDetail from './modules/store-silk-detail.vue';
import StoreSilkSankey from './modules/store-silk-sankey.vue';
defineOptions({
  name: 'StoreSilkList'
@@ -18,6 +20,31 @@
const appStore = useAppStore();
const { download } = useDownload();
const { hasAuth } = useAuth();
const selectedRollerDetailList = ref<any[]>([]);
const selectedPackerDetailList = ref<any[]>([]);
// 桑基图start
const showSankey = ref(false);
const rollerRecordList = ref<any[]>([]);
const packerRecordList = ref<any[]>([]);
// 桑基图end
const sankeyRollerBoxList = computed(() => {
  return (rollerRecordList.value || []).map(item => {
    const v = calcRollerBox((item as any).output);
    const output = v === null ? null : Number(v.toFixed(2));
    return { ...(item as any), output };
  });
});
const sankeyPackerBoxList = computed(() => {
  return (packerRecordList.value || []).map(item => {
    const v = calcPackerBox((item as any).output);
    const output = v === null ? null : Number(v.toFixed(2));
    return { ...(item as any), output };
  });
});
const searchParams = ref<Api.Analy.StoreSilkSearchParams>({
  pageNum: 1,
@@ -28,29 +55,51 @@
  distimebegin: null,
  distimeend: null,
  siloid: null,
  params: {}
  params: {
    beginTime: `${new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000).getFullYear()}-${String(new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000).getMonth() + 1).padStart(2, '0')}-${String(new Date(new Date().getTime() - 3 * 24 * 60 * 60 * 1000).getDate()).padStart(2, '0')} 00:00:00`,
    endTime: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')} 23:59:59`
  }
});
const tableSize = ref<'tiny' | 'small' | 'medium' | 'large'>('small');
const tableSize = ref<'small' | 'medium' | 'large'>('small');
function handleTableSizeChange(size: 'tiny' | 'small' | 'medium' | 'large') {
function handleTableSizeChange(size: 'small' | 'medium' | 'large') {
  tableSize.value = size;
}
const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
  useNaivePaginatedTable({
  useNaivePaginatedTable<any, any>({
    api: () => fetchGetStoreSilkList(searchParams.value),
    transform: response => defaultTransform(response),
    transform: response => {
      const respData = (response as any).data;
      const error = (response as any).error;
      if (!error) {
        const rows = Array.isArray(respData?.rows) ? respData.rows : [];
        const apiRollerRecordList = respData?.rollerRecordList;
        const apiPackerRecordList = respData?.packerRecordList;
        rollerRecordList.value =
          Array.isArray(apiRollerRecordList) && apiRollerRecordList.length > 0
            ? apiRollerRecordList
            : rows.flatMap((r: any) => (Array.isArray(r?.rollerDetailList) ? r.rollerDetailList : []));
        packerRecordList.value =
          Array.isArray(apiPackerRecordList) && apiPackerRecordList.length > 0
            ? apiPackerRecordList
            : rows.flatMap((r: any) => (Array.isArray(r?.packerDetailList) ? r.packerDetailList : []));
      } else {
        rollerRecordList.value = [];
        packerRecordList.value = [];
      }
      return defaultTransform(response as any);
    },
    onPaginationParamsChange: params => {
      searchParams.value.pageNum = params.page;
      searchParams.value.pageSize = params.pageSize;
    },
    columns: () => [
      {
        type: 'selection',
        align: 'center',
        width: 48
      },
      {
        key: 'index',
        title: $t('common.index'),
@@ -62,121 +111,107 @@
        key: 'materialname',
        title: '牌号',
        align: 'center',
        minWidth: 120
        minWidth: 96
      },
      {
        key: 'batchcode',
        title: '批次号',
        align: 'center',
        minWidth: 130
        minWidth: 110
      },
      {
        key: 'roller',
        title: '卷接产量',
        key: 'rollerOutput',
        title: '卷接产量(箱)',
        align: 'center',
        minWidth: 100
        minWidth: 112,
        render: row => {
          const v = calcRollerBox((row as any).rollerOutput);
          if (v === null) return '-';
          return v.toFixed(1);
        }
      },
      {
        key: 'packer',
        title: '包装产量',
        key: 'rollerUnitCost',
        title: '卷接单耗',
        align: 'center',
        minWidth: 100
        minWidth: 96,
        render: row => {
          const box = calcRollerBox((row as any).rollerOutput);
          if (box === null || box <= 0) return '-';
          const weight = Number((row as any).weight);
          if (!Number.isFinite(weight)) return '-';
          const val = weight / box;
          if (!Number.isFinite(val)) return '-';
          return val.toFixed(2);
        }
      },
      {
        key: 'packerOutput',
        title: '包装产量(箱)',
        align: 'center',
        minWidth: 112,
        render: row => {
          const v = calcPackerBox((row as any).packerOutput);
          if (v === null) return '-';
          return v.toFixed(1);
        }
      },
      {
        key: 'packerUnitCost',
        title: '包装单耗',
        align: 'center',
        minWidth: 96,
        render: row => {
          const box = calcPackerBox((row as any).packerOutput);
          if (box === null || box <= 0) return '-';
          const weight = Number((row as any).weight);
          if (!Number.isFinite(weight)) return '-';
          const val = weight / box;
          if (!Number.isFinite(val)) return '-';
          return val.toFixed(2);
        }
      },
      {
        key: 'actualstarttime',
        title: '投料日期',
        align: 'center',
        width: 180
        width: 160
      },
      {
        key: 'jobinput',
        title: '投料重量',
        align: 'center',
        minWidth: 120
        minWidth: 96
      },
      {
        key: 'weight',
        title: '储丝柜重量',
        align: 'center',
        minWidth: 120
        minWidth: 96
      },
      {
        key: 'distimebegin',
        title: '储丝柜出料开始时间',
        align: 'center',
        width: 180
        width: 160
      },
      {
        key: 'distimeend',
        title: '储丝柜出料结束时间',
        align: 'center',
        width: 180
        width: 160
      },
      {
        key: 'siloid',
        title: '柜子号(末位)',
        align: 'center',
        width: 160
      },
      {
        key: 'operate',
        title: $t('common.operate'),
        align: 'center',
        fixed: 'right',
        width: 130,
        render: row => {
          const divider = () => {
            if (!hasAuth('analy:storeSilk:edit') || !hasAuth('analy:storeSilk:remove')) {
              return null;
            }
            return <NDivider vertical />;
          };
          const editBtn = () => {
            if (!hasAuth('analy:storeSilk:edit')) {
              return null;
            }
            return (
              <ButtonIcon
                text
                type="primary"
                icon="material-symbols:drive-file-rename-outline-outline"
                tooltipContent={$t('common.edit')}
                onClick={() => edit(row.id)}
              />
            );
          };
          const deleteBtn = () => {
            if (!hasAuth('analy:storeSilk:remove')) {
              return null;
            }
            return (
              <ButtonIcon
                text
                type="error"
                icon="material-symbols:delete-outline"
                tooltipContent={$t('common.delete')}
                popconfirmContent={$t('common.confirmDelete')}
                onPositiveClick={() => handleDelete(row.id)}
              />
            );
          };
          return (
            <div class="flex-center gap-8px">
              {editBtn()}
              {divider()}
              {deleteBtn()}
            </div>
          );
        }
        width: 120
      }
    ]
  });
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
  useTableOperate(data, 'id', getData);
  useTableOperate<any>(data, 'id', getData);
async function handleBatchDelete() {
  // request
@@ -199,6 +234,29 @@
function handleExport() {
  download('/analy/storeSilk/export', searchParams.value, `储丝柜产量_${new Date().getTime()}.xlsx`);
}
function calcRollerBox(val: unknown) {
  if (val === null || val === undefined) return null;
  const v = Number(val) / 50;
  if (!Number.isFinite(v)) return null;
  return v;
}
function calcPackerBox(val: unknown) {
  if (val === null || val === undefined) return null;
  const v = Number(val) / 10 / 250;
  if (!Number.isFinite(v)) return null;
  return v;
}
function handleRowClick(row: any) {
  return {
    onClick: () => {
      selectedRollerDetailList.value = row.rollerDetailList || [];
      selectedPackerDetailList.value = row.packerDetailList || [];
    },
    style: 'cursor: pointer;'
  };
}
</script>
<template>
@@ -210,14 +268,19 @@
          v-model:columns="columnChecks"
          :disabled-delete="checkedRowKeys.length === 0"
          :loading="loading"
          :show-add="hasAuth('analy:storeSilk:add')"
          :show-delete="hasAuth('analy:storeSilk:remove')"
          :show-export="hasAuth('analy:storeSilk:export')"
          :show-add="false"
          :show-delete="false"
          :show-export="!showSankey && hasAuth('analy:storeSilk:export')"
          @add="handleAdd"
          @delete="handleBatchDelete"
          @export="handleExport"
          @refresh="getData"
        >
          <template #prefix>
            <NButton size="small" ghost :type="showSankey ? 'primary' : 'default'" @click="showSankey = !showSankey">
              {{ showSankey ? '列表' : '桑基图' }}
            </NButton>
          </template>
          <template #suffix>
            <NPopover placement="bottom-end" trigger="click">
              <template #trigger>
@@ -230,7 +293,6 @@
              </template>
              <NRadioGroup :value="tableSize" @update:value="handleTableSizeChange">
                <NSpace vertical>
                  <NRadio value="tiny">mini</NRadio>
                  <NRadio value="small">小</NRadio>
                  <NRadio value="medium">中</NRadio>
                  <NRadio value="large">大</NRadio>
@@ -240,9 +302,16 @@
          </template>
        </TableHeaderOperation>
      </template>
      <StoreSilkSankey
        v-if="showSankey"
        :roller-record-list="sankeyRollerBoxList"
        :packer-record-list="sankeyPackerBoxList"
        :rows="data"
        class="h-full"
      />
      <NDataTable
        v-model:checked-row-keys="checkedRowKeys"
        :columns="columns"
        v-else
        :columns="columns as any"
        :data="data"
        :size="tableSize"
        :flex-height="!appStore.isMobile"
@@ -251,8 +320,8 @@
        remote
        :row-key="row => row.id"
        :pagination="mobilePagination"
        :row-props="handleRowClick"
        class="sm:h-full"
        :class="[tableSize === 'tiny' ? 'table-size-mini' : '']"
      />
      <StoreSilkOperateDrawer
        v-model:visible="drawerVisible"
@@ -261,13 +330,18 @@
        @submitted="getDataByPage"
      />
    </NCard>
    <StoreSilkDetail
      v-if="!showSankey"
      :roller-detail-list="selectedRollerDetailList"
      :packer-detail-list="selectedPackerDetailList"
      class="h-[192px] overflow-hidden"
    />
  </div>
</template>
<style scoped>
:deep(.table-size-mini .n-data-table-th),
:deep(.table-size-mini .n-data-table-td) {
  padding-top: 4px;
  padding-bottom: 4px;
:deep(.n-data-table-th),
:deep(.n-data-table-td) {
  padding: 4px 6px;
}
</style>