云
17 小时以前 c2e8526f8f857be5e3a8c6f2b39c5efd424de33e
src/views/bi/warehouse/index.vue
@@ -17,6 +17,7 @@
} from '#/api/bi/warehouseCoordinate';
import ClockWidget from '../dashboard/modules/ClockWidget.vue';
import RealtimeTable from '../dashboard/modules/RealtimeTable.vue';
import {
  getChinaMapOptions,
  getWarehouseAreaLineOptions,
@@ -30,19 +31,29 @@
const charts = ref<BiDashboardApi.ChartItem[]>([]);
const loading = ref(true);
const lastUpdateTime = ref('');
let fetching = false;
let disposed = false;
async function loadData() {
async function loadData(background = false) {
  if (fetching || disposed) return false;
  fetching = true;
  try {
    loading.value = true;
    if (!background) loading.value = true;
    const data = await getDashboardData('warehouse');
    if (disposed) return false;
    charts.value = data.length > 0 ? data : [];
    lastUpdateTime.value = new Date().toLocaleTimeString('zh-CN', { hour12: false });
    return true;
  } catch {
    charts.value = [];
    if (!background && !disposed) charts.value = [];
    return false;
  } finally {
    loading.value = false;
    await nextTick();
    resizeAllCharts();
    fetching = false;
    if (!disposed) {
      loading.value = false;
      await nextTick();
      if (!disposed) resizeAllCharts();
    }
  }
}
@@ -233,10 +244,7 @@
// ======== 表格数据 ========
const tableData = computed(() => tableChart.value?.data || []);
const tableColumns = computed(() => {
  if (tableData.value.length === 0) return [];
  return Object.keys(tableData.value[0] || {});
});
// ======== 库存预警 ========
const warningList = computed(() => {
@@ -428,7 +436,8 @@
function setupTimer() {
  clearTimer();
  refreshTimer = setInterval(async () => {
    await loadData();
    if (document.hidden || editMode.value || disposed) return;
    if (!(await loadData(true))) return;
    await nextTick();
    await renderAllCharts();
    if (editMode.value) await nextTick().then(() => attachMapListeners());
@@ -497,13 +506,16 @@
  resizeObserver = new ResizeObserver(() => resizeAllCharts());
  if (dashboardRef.value) resizeObserver.observe(dashboardRef.value);
  await loadCoordinates();
  if (disposed) return;
  await loadData();
  if (disposed) return;
  await nextTick();
  await renderAllCharts();
  setupTimer();
});
onBeforeUnmount(() => {
  disposed = true;
  document.removeEventListener('fullscreenchange', onFullscreenChange);
  resizeObserver?.disconnect();
  clearTimer();
@@ -720,26 +732,11 @@
          最近入库记录
          <span class="wh-table-badge">实时滚动</span>
        </div>
        <div v-if="tableData.length > 0" class="wh-table-wrap">
          <table class="wh-table">
            <thead>
              <tr>
                <th v-for="col in tableColumns" :key="col">{{ col }}</th>
              </tr>
            </thead>
            <tbody>
              <tr
                v-for="(row, ri) in tableData"
                :key="ri"
                :style="{ animationDelay: `${ri * 50}ms` }"
              >
                <td v-for="col in tableColumns" :key="col">
                  {{ getCellValue(row, col) }}
                </td>
              </tr>
            </tbody>
          </table>
        </div>
        <RealtimeTable
          v-if="tableData.length > 0"
          :rows="tableData"
          :format-cell="getCellValue"
        />
        <Empty v-else description="暂无数据" />
      </div>
    </template>
@@ -1187,50 +1184,6 @@
  padding: 2px 8px; border-radius: 10px;
  background: rgba(0,255,136,0.08); color: var(--green);
  border: 1px solid rgba(0,255,136,0.15);
}
.wh-table-wrap {
  overflow-x: auto; border-radius: 8px;
  background: rgba(4, 14, 36, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(0, 229, 255, 0.08);
}
.wh-table {
  width: 100%; border-collapse: collapse; font-size: 12px;
}
.wh-table thead th {
  background: rgba(6, 18, 42, 0.8);
  color: var(--text-secondary);
  font-weight: 600; font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.8px;
  padding: 10px 14px; text-align: left;
  border-bottom: 1px solid rgba(0,229,255,0.12);
  white-space: nowrap;
}
.wh-table tbody td {
  padding: 9px 14px; color: var(--text-primary);
  border-bottom: 1px solid rgba(0, 229, 255, 0.04);
  white-space: nowrap;
}
.wh-table tbody tr {
  transition: all 0.25s;
  opacity: 0;
  animation: row-fade-in 0.45s ease forwards;
}
.wh-table tbody tr:hover {
  background: rgba(0, 229, 255, 0.06);
  box-shadow: inset 0 0 20px rgba(0, 229, 255, 0.03);
}
@keyframes row-fade-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
/* ======== 全屏 ======== */