From 2b31fa203f3435a582be51f45899d99164c9917a Mon Sep 17 00:00:00 2001
From: zhuguifei <312353457@qq.com>
Date: 星期四, 09 四月 2026 13:34:59 +0800
Subject: [PATCH] Merge branch 'master' of http://lanpucloud.cn:1111/r/SC/gfzl

---
 ruoyi-plus-soybean/src/views/analy/store-silk/index.vue |  372 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 223 insertions(+), 149 deletions(-)

diff --git a/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue b/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
old mode 100644
new mode 100755
index addf095..90aa24c
--- a/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
+++ b/ruoyi-plus-soybean/src/views/analy/store-silk/index.vue
@@ -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,15 +10,41 @@
 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'
 });
 
-
 const appStore = useAppStore();
 const { download } = useDownload();
 const { hasAuth } = useAuth();
+
+const selectedRollerDetailList = ref<any[]>([]);
+const selectedPackerDetailList = ref<any[]>([]);
+
+// 妗戝熀鍥緎tart
+const showSankey = ref(false);
+const rollerRecordList = ref<any[]>([]);
+const packerRecordList = ref<any[]>([]);
+// 妗戝熀鍥緀nd
+
+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,
@@ -29,155 +55,163 @@
   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({
-  api: () => fetchGetStoreSilkList(searchParams.value),
-  transform: response => defaultTransform(response),
-  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'),
-      align: 'center',
-      width: 64,
-      render: (_, index) => index + 1
-    },
-    {
-      key: 'materialname',
-      title: '鐗屽彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'batchcode',
-      title: '鎵规鍙�',
-      align: 'center',
-      minWidth: 130
-    },
-    {
-      key: 'roller',
-      title: '鍗锋帴浜ч噺',
-      align: 'center',
-      minWidth: 100
-    },
-    {
-      key: 'packer',
-      title: '鍖呰浜ч噺',
-      align: 'center',
-      minWidth: 100
-    },
-    {
-      key: 'actualstarttime',
-      title: '鎶曟枡鏃ユ湡',
-      align: 'center',
-      width: 180
-    },
-    {
-      key: 'jobinput',
-      title: '鎶曟枡閲嶉噺',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'weight',
-      title: '鍌ㄤ笣鏌滈噸閲�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'distimebegin',
-      title: '鍌ㄤ笣鏌滃嚭鏂欏紑濮嬫椂闂�',
-      align: 'center',
-      width: 180
-    },
-    {
-      key: 'distimeend',
-      title: '鍌ㄤ笣鏌滃嚭鏂欑粨鏉熸椂闂�',
-      align: 'center',
-      width: 180
-    },
-    {
-      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 />;
-        };
+  useNaivePaginatedTable<any, any>({
+    api: () => fetchGetStoreSilkList(searchParams.value),
+    transform: response => {
+      const respData = (response as any).data;
+      const error = (response as any).error;
 
-        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)}
-            />
-          );
-        };
+      if (!error) {
+        const rows = Array.isArray(respData?.rows) ? respData.rows : [];
+        const apiRollerRecordList = respData?.rollerRecordList;
+        const apiPackerRecordList = respData?.packerRecordList;
 
-        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)}
-            />
-          );
-        };
+        rollerRecordList.value =
+          Array.isArray(apiRollerRecordList) && apiRollerRecordList.length > 0
+            ? apiRollerRecordList
+            : rows.flatMap((r: any) => (Array.isArray(r?.rollerDetailList) ? r.rollerDetailList : []));
 
-        return (
-          <div class="flex-center gap-8px">
-            {editBtn()}
-            {divider()}
-            {deleteBtn()}
-          </div>
-        );
+        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: () => [
+      {
+        key: 'index',
+        title: $t('common.index'),
+        align: 'center',
+        width: 64,
+        render: (_, index) => index + 1
+      },
+      {
+        key: 'materialname',
+        title: '鐗屽彿',
+        align: 'center',
+        minWidth: 96
+      },
+      {
+        key: 'batchcode',
+        title: '鎵规鍙�',
+        align: 'center',
+        minWidth: 110
+      },
+      {
+        key: 'rollerOutput',
+        title: '鍗锋帴浜ч噺(绠�)',
+        align: 'center',
+        minWidth: 112,
+        render: row => {
+          const v = calcRollerBox((row as any).rollerOutput);
+          if (v === null) return '-';
+          return v.toFixed(1);
+        }
+      },
+      {
+        key: 'rollerUnitCost',
+        title: '鍗锋帴鍗曡��',
+        align: 'center',
+        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: 160
+      },
+      {
+        key: 'jobinput',
+        title: '鎶曟枡閲嶉噺',
+        align: 'center',
+        minWidth: 96
+      },
+      {
+        key: 'weight',
+        title: '鍌ㄤ笣鏌滈噸閲�',
+        align: 'center',
+        minWidth: 96
+      },
+      {
+        key: 'distimebegin',
+        title: '鍌ㄤ笣鏌滃嚭鏂欏紑濮嬫椂闂�',
+        align: 'center',
+        width: 160
+      },
+      {
+        key: 'distimeend',
+        title: '鍌ㄤ笣鏌滃嚭鏂欑粨鏉熸椂闂�',
+        align: 'center',
+        width: 160
+      },
+      {
+        key: 'siloid',
+        title: '鏌滃瓙鍙�(鏈綅)',
+        align: 'center',
+        width: 120
+      }
+    ]
+  });
 
 const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
-  useTableOperate(data, 'id', getData);
+  useTableOperate<any>(data, 'id', getData);
 
 async function handleBatchDelete() {
   // request
@@ -200,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>
@@ -211,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>
@@ -231,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>
@@ -241,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"
@@ -252,7 +320,8 @@
         remote
         :row-key="row => row.id"
         :pagination="mobilePagination"
-        :class="['sm:h-full', tableSize === 'tiny' ? 'table-size-mini' : '']"
+        :row-props="handleRowClick"
+        class="sm:h-full"
       />
       <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>

--
Gitblit v1.9.3