<template>
  <div class="aisbtk-page">
    <!-- 搜索表单 -->
    <a-form layout="inline" class="search-form">
      <a-form-item label="基地选择">
        <a-select
          v-model:value="searchData.baseid"
          placeholder="请选择基地"
          style="width: 180px"
          :options="jidiOptions"
          @change="handleBaseChange"
        />
      </a-form-item>
      <a-form-item v-if="vdListShow !== '3'" label="电站名称">
        <a-input
          v-model:value="searchData.stnm"
          placeholder="请输入电站"
          allow-clear
          style="width: 180px"
        />
      </a-form-item>
      <a-form-item v-else label="电站选择">
        <a-select
          v-model:value="searchData.rstcd"
          placeholder="请选择电站"
          style="width: 180px"
          :options="stcdData"
          allow-clear
        />
      </a-form-item>
      <a-form-item label="时间">
        <a-date-picker
          v-model:value="searchData.month"
          picker="month"
          format="YYYY-MM"
          :allow-clear="false"
          style="width: 150px"
        />
      </a-form-item>
      <a-form-item>
        <a-button type="primary" @click="handleSearch">查询</a-button>
      </a-form-item>
    </a-form>

    <!-- Tabs + 图表表格 -->
    <a-tabs v-model:activeKey="tabIndex" class="aisbtk-tabs">
      <!-- 视图切换按钮 -->
      <div class="view-switch-buttons">
        <a-tooltip placement="top" title="视频">
          <div
            class="view-btn"
            :class="{ active: vdListShow === '1' }"
            @click="vdListShow = '1'"
          >
            <i class="icon iconfont icon-video"></i>
          </div>
        </a-tooltip>
        <a-tooltip placement="top" title="数据列表">
          <div
            class="view-btn"
            :class="{ active: vdListShow === '2' }"
            @click="vdListShow = '2'"
          >
            <i class="icon iconfont icon-dataTable"></i>
          </div>
        </a-tooltip>
        <a-tooltip placement="top" title="日历">
          <div
            class="view-btn"
            :class="{ active: vdListShow === '3' }"
            @click="vdListShow = '3'"
          >
            <i class="icon iconfont icon-calendar"></i>
          </div>
        </a-tooltip>
      </div>
      <a-tab-pane
        v-for="item in tabDisplayList"
        :key="String(item.key)"
        :tab="item.tabLabel"
      >
        <!-- 数据列表视图（饼图+表格） -->
        <div v-show="vdListShow === '2'" class="chart-table-layout">
          <!-- 左侧饼图 -->
          <div class="chart-section">
            <a-spin :spinning="chartLoading">
              <div
                :ref="(el: any) => setChartRef(el, String(item.key))"
                class="chart-container"
              ></div>
            </a-spin>
            <div
              v-if="!chartLoading && chartData.length === 0"
              class="chart-empty-overlay"
            >
              <a-empty description="暂无数据" />
            </div>
          </div>

          <!-- 右侧表格 -->
          <div class="table-section">
            <BasicTable
              :ref="(el: any) => setTableRef(el, String(item.key))"
              :columns="currentColumns"
              :scroll-y="450"
              :scroll-x="600"
              :list-url="getAiChartTable"
              :search-params="tableSearchParams"
              :transform-data="customTransform"
            >
              <template #tm="{ record }">
                {{ record.tm ? dayjs(record.tm).format('YYYY-MM-DD') : '-' }}
              </template>
              <template #fid="{ record }">
                <a-button
                  type="link"
                  style="padding: 4px"
                  :disabled="!record.fid"
                  @click="handleViewAttachment(record.fid)"
                >
                  查看附件
                </a-button>
              </template>
              <template #isBigDebrisArea="{ record }">
                <span v-if="record.isBigDebrisArea === 1" style="color: red"
                  >是</span
                >
                <span
                  v-else-if="record.isBigDebrisArea === 0"
                  style="color: green"
                  >否</span
                >
                <span v-else>-</span>
              </template>
              <template #aiVal="{ record }">
                {{
                  record.aiVal === 'open'
                    ? '开启'
                    : record.aiVal === 'close'
                    ? '关闭'
                    : record.aiVal ?? '-'
                }}
              </template>
            </BasicTable>
          </div>
        </div>

        <!-- 视频视图 -->
        <div v-show="vdListShow === '1'" class="chart-table-layout">
          <!-- 左侧饼图 -->
          <div class="chart-section">
            <a-spin :spinning="chartLoading">
              <div
                :ref="(el: any) => setVideoChartRef(el, String(item.key))"
                class="chart-container"
              ></div>
            </a-spin>
            <div
              v-if="!chartLoading && chartData.length === 0"
              class="chart-empty-overlay"
            >
              <a-empty description="暂无数据" />
            </div>
          </div>

          <!-- 右侧视频列表 -->
          <div class="video-section">
            <div class="video-mode">
              <div class="video-main" v-loading="videoLoading">
                <div
                  v-if="activeMedia.type === 'image' && activeMedia.src"
                  class="media-display"
                >
                  <img
                    :src="activeMedia.src"
                    style="width: 100%; height: 100%; object-fit: contain"
                  />
                </div>
                <div
                  v-else-if="activeMedia.type === 'video' && activeMedia.src"
                  class="media-display"
                >
                  <LiveVideoBox
                    :videoData="{ url: activeMedia.src }"
                    height="100%"
                    :showTitle="false"
                  />
                </div>
                <div v-else class="media-empty">
                  <a-empty description="请选择右侧数据" />
                </div>
              </div>
              <div class="video-sidebar" v-loading="videoLoading">
                <div class="sidebar-list" v-if="videoList.length > 0">
                  <div
                    v-for="item in videoList"
                    :key="item.fid"
                    class="sidebar-item"
                    :class="{ active: activeFid === item.fid }"
                    @click="handleSelectMedia(item)"
                  >
                    <!-- {{ item }}12132131313 -->
                    <div class="item-thumb">
                      <img v-if="item.type === 'img'" :src="item.imgPath" />
                      <div
                        v-else-if="item.type === 'vdsp'"
                        class="thumb-placeholder"
                      >
                        <img :src="videoCover" />
                      </div>
                      <span v-else class="no-media">无媒体</span>
                    </div>
                    <div class="item-time">{{ item.stName }}{{ item.tm }}</div>
                  </div>
                </div>
                <a-empty v-else description="暂无数据" class="sidebar-empty" />
              </div>
            </div>
            <div
              class="sidebar-pagination"
              style="margin-top: 10px; display: flex; justify-content: end"
            >
              <a-pagination
                v-model:current="videoPage"
                v-model:pageSize="videoTake"
                :page-size-options="videoPageSizeOptions"
                :total="videoTotal"
                show-size-changer
                size="small"
                @change="handleVideoPageChange"
              />
            </div>
          </div>
        </div>

        <!-- 日历视图 -->
        <div v-show="vdListShow === '3'" class="calendar-mode">
          <a-spin :spinning="calendarLoading">
            <a-calendar
              v-model:value="calendarValue"
              @panelChange="handleCalendarPanelChange"
              @select="handleCalendarSelect"
            >
              <template #headerRender="{ current }"> </template>
              <template #dateCellRender="{ current }">
                <div class="calendar-content">
                  <template v-if="isCurrentMonth(current)">
                    <div
                      class="content_state1"
                      v-if="getCalendarDataForDay(current)"
                    >
                      监测
                    </div>
                    <div class="content_state4" v-else>未监测</div>
                    <!-- 漂浮物识别和清漂识别：显示漂浮物状态和清漂状态 -->
                    <template v-if="tabIndex === '1' || tabIndex === '3'">
                      <div
                        v-if="getCalendarDataForDay(current)?.status"
                        :class="
                          getStatusClass(getCalendarDataForDay(current)?.status)
                        "
                        @click.stop="
                          handleCalendarDayClick(
                            current,
                            getCalendarDataForDay(current)
                          )
                        "
                      >
                        {{
                          getStatusText(getCalendarDataForDay(current)?.status)
                        }}
                      </div>
                      <div
                        v-if="getCalendarDataForDay(current)?.qpStatus"
                        :class="
                          getStatusClass(
                            getCalendarDataForDay(current)?.qpStatus
                          )
                        "
                        @click.stop="
                          handleCalendarDayClick(
                            current,
                            getCalendarDataForDay(current)
                          )
                        "
                      >
                        {{
                          getStatusText(
                            getCalendarDataForDay(current)?.qpStatus
                          )
                        }}
                      </div>
                    </template>
                    <!-- 叠梁门运行识别：只显示运行状态 -->
                    <template v-else-if="tabIndex === '2'">
                      <div
                        v-if="getCalendarDataForDay(current)?.status"
                        :class="
                          getStatusClass(getCalendarDataForDay(current)?.status)
                        "
                        @click.stop="
                          handleCalendarDayClick(
                            current,
                            getCalendarDataForDay(current)
                          )
                        "
                      >
                        {{
                          getStatusText(getCalendarDataForDay(current)?.status)
                        }}
                      </div>
                    </template>
                  </template>
                </div>
              </template>
            </a-calendar>
          </a-spin>
        </div>
      </a-tab-pane>
    </a-tabs>

    <!-- 附件预览弹框 -->
    <CommonAttachmentModal
      v-model:open="attachmentModalVisible"
      :fid="currentAttachmentFid"
      title="查看附件"
    />

    <!-- 日历详情弹窗 -->
    <a-modal
      v-model:open="detailModalVisible"
      title="视频详情"
      width="80vw"
      :footer="null"
      destroyOnClose
      :teleport="false"
      :bodyStyle="{ height: '70vh' }"
    >
      <a-tabs v-model:activeKey="detailActiveKey">
        <a-tab-pane
          v-for="item in detailTabItems"
          :key="item.key"
          :tab="item.label"
        >
          <div v-show="detailActiveKey === item.key">
            <VideoPlayer
              :list="detailVideoList"
              :activeFid="detailActiveFid"
              :activeMedia="detailActiveMedia"
              :loading="detailVideoLoading"
              :page="detailVideoPage"
              :pageSize="detailVideoTake"
              :pageSizeOptions="detailVideoPageSizeOptions"
              :total="detailVideoTotal"
              @select="handleSelectDetailMedia"
              @pageChange="handleDetailVideoPageChange"
            />
          </div>
        </a-tab-pane>
      </a-tabs>
    </a-modal>

    <!-- 清漂附件预览弹框 -->
    <CommonAttachmentModal
      v-model:open="qingpiaoModalVisible"
      :fid="qingpiaoFids.join(',')"
      title="附件预览"
    />
  </div>
</template>

<script lang="ts" setup>
import {
  ref,
  computed,
  watch,
  onMounted,
  onBeforeUnmount,
  nextTick
} from 'vue';
import * as echarts from 'echarts';
import type { ECharts } from 'echarts';
import BasicTable from '@/components/BasicTable/index.vue';
import CommonAttachmentModal from '@/components/MapModal/components/CommonAttachmentModal.vue';
import LiveVideoBox from '@/views/shiPinJianKong/components/LiveVideoBox.vue';
import VideoPlayer from './components/VideoPlayer.vue';
import {
  getAisbdbyxList,
  getAiChartTable,
  getAiPfwRecord,
  getAiRecord,
  getAiFile,
  getAiRstcd
} from '@/api/zngj';
import { postIdUrl } from '@/api/mapModal';
import dayjs from 'dayjs';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
import videoCover from '@/assets/images/videFm.jpg';

const baseUrl = import.meta.env.VITE_APP_ATTACHMENT_URL;

// ==================== Props ====================
const props = defineProps<{
  month?: string;
  tabIdx?: string;
  baseid?: string;
}>();

// ==================== Store ====================
const JidiSelectEventStore = useJidiSelectEventStore();

// ==================== 搜索状态 ====================
const jidiOptions = ref<Array<{ label: string; value: string }>>([]);
const searchData = ref({
  baseid: props.baseid || 'all',
  stnm: '',
  rstcd: '',
  month: props.month ? dayjs(props.month) : dayjs()
});
const stcdData = ref<Array<{ label: string; value: string }>>([]);

// ==================== 弹框状态 ====================
const attachmentModalVisible = ref(false);
const currentAttachmentFid = ref('');

// ==================== Tabs 状态 ====================
const tabIndex = ref(props.tabIdx ?? '1');
const tabList = ref<any[]>([
  { key: 1, value: '漂浮物识别', unit: '次', count: 0 },
  { key: 3, value: '清漂识别', unit: '次', count: 0 },
  { key: 2, value: '叠梁门运行识别', unit: '次', count: 0 }
]);

// ==================== 视图切换状态 ====================
const vdListShow = ref<'1' | '2' | '3'>('2');

// Tab 显示列表（根据视图类型动态计算标题）
const tabDisplayList = computed(() =>
  tabList.value.map(item => ({
    ...item,
    tabLabel:
      vdListShow.value === '3'
        ? item.value
        : `${item.value}(${item.count}${item.unit})`
  }))
);

// ==================== 图表状态 ====================
const chartRefs = ref<Map<string, HTMLElement>>(new Map());
let chartInstance: ECharts | null = null;
const chartData = ref<any[]>([]);
const chartLoading = ref(true);
const pieCode = ref<string[]>([]);

// ==================== 视频视图状态 ====================
const videoPage = ref(1);
const videoTake = ref(20);
const videoPageSizeOptions = ['20', '50', '100'];
const videoTotal = ref(0);
const videoLoading = ref(false);
const videoList = ref<any[]>([]);
const activeFid = ref('');
const activeMedia = ref<{ type: string; src: string }>({ type: '', src: '' });

// 视频视图饼图状态
const videoChartRefs = ref<Map<string, HTMLElement>>(new Map());
let videoChartInstance: ECharts | null = null;

// ==================== 日历视图状态 ====================
const calendarLoading = ref(false);
const calendarData = ref<any[]>([]);
const calendarValue = ref(searchData.value.month);
const detailModalVisible = ref(false);
const detailActiveKey = ref('');
const detailVideoLoading = ref(false);
const detailVideoList = ref<any[]>([]);
const detailVideoPage = ref(1);
const detailVideoTake = ref(20);
const detailVideoPageSizeOptions = ['20', '50', '100'];
const detailVideoTotal = ref(0);
const detailActiveFid = ref('');
const detailActiveMedia = ref<{ type: string; src: string }>({
  type: '',
  src: ''
});
const detailTabItems = ref<any[]>([]);
const detailDate = ref('');
const detailType = ref('');
const detailDataType = computed(() => detailActiveKey.value);
const qingpiaoModalVisible = ref(false);
const qingpiaoFids = ref<string[]>([]);

// 日历状态映射（与React端一致）
const calendarStatusMap: Record<
  string,
  { name: string; className: string; type: string; dataType: string }
> = {
  '3': {
    name: '运行',
    className: 'content_state2',
    type: 'AI_5005',
    dataType: '2'
  },
  '4': {
    name: '未运行',
    className: 'content_state3',
    type: 'AI_5005',
    dataType: '1'
  },
  '5': {
    name: '清漂',
    className: 'content_state2',
    type: 'AI_5011',
    dataType: '3'
  },
  '6': {
    name: '未清漂',
    className: 'content_state3',
    type: 'AI_5011',
    dataType: '3'
  },
  '0': {
    name: '无漂浮物',
    className: 'content_state2',
    type: 'AI_5001',
    dataType: '3'
  },
  '1': {
    name: '小面积漂浮物',
    className: 'content_state5',
    type: 'AI_5001',
    dataType: '4'
  },
  '2': {
    name: '大面积漂浮物',
    className: 'content_state3',
    type: 'AI_5001',
    dataType: '5'
  }
};

// 函数式 ref 绑定
const setChartRef = (el: any, key: string) => {
  if (el instanceof HTMLElement) {
    chartRefs.value.set(key, el);
  }
};

const setVideoChartRef = (el: any, key: string) => {
  if (el instanceof HTMLElement) {
    videoChartRefs.value.set(key, el);
  }
};

// ==================== 表格引用 ====================
const tableRefs = ref<Map<string, any>>(new Map());

const setTableRef = (el: any, key: string) => {
  if (el && !(el instanceof HTMLElement)) {
    tableRefs.value.set(key, el);
  }
};

// 安全获取 table 实例
const getTableInstance = () => {
  return tableRefs.value.get(tabIndex.value) || null;
};

// ==================== 表格列配置 ====================
const pfwColumns = [
  {
    key: 'ennm',
    title: '所属电站',
    dataIndex: 'ennm',
    fixed: 'left' as const,
    width: 120,
    ellipsis: true
  },
  {
    key: 'stnm',
    title: '设施名称',
    dataIndex: 'stnm',
    width: 150,
    ellipsis: true
  },
  {
    key: 'hbRvcdName',
    title: '所在河流',
    dataIndex: 'hbRvcdName',
    width: 120,
    ellipsis: true
  },
  {
    key: 'tm',
    title: '时间',
    dataIndex: 'tm',
    width: 150,
    ellipsis: true,
    slots: { customRender: 'tm' }
  },
  {
    key: 'aiVal',
    title: '漂浮物面积',
    dataIndex: 'aiVal',
    width: 120,
    ellipsis: true
  },
  {
    key: 'isBigDebrisArea',
    title: '是否为大面积堆积',
    dataIndex: 'isBigDebrisArea',
    width: 140,
    ellipsis: true,
    slots: { customRender: 'isBigDebrisArea' }
  },
  {
    key: 'fid',
    title: '操作',
    dataIndex: 'fid',
    width: 100,
    ellipsis: true,
    slots: { customRender: 'fid' }
  }
];

const dlmColumns = [
  {
    key: 'stnm',
    title: '设施名称',
    dataIndex: 'stnm',
    fixed: 'left' as const,
    width: 150,
    ellipsis: true
  },
  {
    key: 'ennm',
    title: '所属电站',
    dataIndex: 'ennm',
    fixed: 'left' as const,
    width: 120,
    ellipsis: true
  },
  {
    key: 'tm',
    title: '操作时间',
    dataIndex: 'tm',
    width: 150,
    ellipsis: true,
    slots: { customRender: 'tm' }
  },
  {
    key: 'aiVal',
    title: '操作状态',
    dataIndex: 'aiVal',
    width: 120,
    ellipsis: true,
    slots: { customRender: 'aiVal' }
  },
  {
    key: 'fid',
    title: '操作',
    dataIndex: 'fid',
    width: 100,
    ellipsis: true,
    slots: { customRender: 'fid' }
  }
];

const dlmCntColumns = [
  {
    key: 'hbRvcdName',
    title: '所属河流',
    dataIndex: 'hbRvcdName',
    fixed: 'left' as const,
    width: 150,
    ellipsis: true
  },
  {
    key: 'ennm',
    title: '所属电站',
    dataIndex: 'ennm',
    fixed: 'left' as const,
    width: 120,
    ellipsis: true
  },
  {
    key: 'tm',
    title: '清漂时间',
    dataIndex: 'tm',
    width: 150,
    ellipsis: true,
    slots: { customRender: 'tm' }
  },
  {
    key: 'fid',
    title: '操作',
    dataIndex: 'fid',
    width: 100,
    ellipsis: true,
    slots: { customRender: 'fid' }
  }
];

const currentColumns = computed(() => {
  switch (tabIndex.value) {
    case '1':
      return pfwColumns;
    case '2':
      return dlmColumns;
    case '3':
      return dlmCntColumns;
    default:
      return pfwColumns;
  }
});

// ==================== 获取 type ====================
const getType = () => {
  switch (tabIndex.value) {
    case '1':
      return 'AI_5001';
    case '2':
      return 'AI_5005';
    case '3':
      return 'AI_5011';
    default:
      return 'AI_5001';
  }
};

// ==================== 构建过滤条件 ====================
const buildFilter = () => {
  const filters: any[] = [
    {
      field: 'type',
      operator: 'eq',
      value: getType()
    },
    pieCode.value.length > 0 && searchData.value.baseid === 'all'
      ? {
          field: 'baseId',
          operator: 'in',
          dataType: 'string',
          value: pieCode.value
        }
      : null,
    pieCode.value.length > 0 && searchData.value.baseid !== 'all'
      ? {
          field: 'rstcd',
          operator: 'in',
          dataType: 'string',
          value: pieCode.value
        }
      : null,
    searchData.value.baseid !== 'all' && pieCode.value.length === 0
      ? {
          field: 'baseId',
          operator: 'eq',
          dataType: 'string',
          value: searchData.value.baseid
        }
      : null,
    {
      field: 'tm',
      operator: 'gte',
      dataType: 'date',
      value: dayjs(searchData.value.month)
        .startOf('month')
        .format('YYYY-MM-DD 00:00:00')
    },
    {
      field: 'tm',
      operator: 'lte',
      dataType: 'date',
      value: dayjs(searchData.value.month)
        .endOf('month')
        .format('YYYY-MM-DD 23:59:59')
    },
    searchData.value.stnm
      ? {
          field: 'stnm',
          operator: 'contains',
          value: searchData.value.stnm
        }
      : null
  ].filter(Boolean);

  return {
    logic: 'and',
    filters
  };
};

// ==================== 表格搜索参数 ====================
const tableSearchParams = computed(() => ({
  sort: [
    { field: 'rstcdStepSort', dir: 'asc' },
    { field: 'tm', dir: 'desc' }
  ],
  group: [],
  select: [],
  groupResultFlat: false
}));

// ==================== 数据转换 ====================
const flattenNestedData = (data: any[]): any[] => {
  const result: any[] = [];
  data.forEach((level1: any) => {
    if (level1?.items?.length) {
      level1.items.forEach((level2: any) => {
        if (level2?.items?.length) {
          level2.items.forEach((level3: any) => {
            if (level3?.items?.length) {
              result.push(...level3.items);
            } else {
              result.push(level3);
            }
          });
        }
      });
    }
  });
  return result;
};

const customTransform = (res: any) => {
  return {
    records: res?.data?.data || [],
    total: res?.data?.total || 0
  };
};

// ==================== 获取 Tab 数量统计 ====================
const getTabList = async () => {
  try {
    const params = {
      filter: {
        logic: 'and',
        filters: [
          searchData.value.baseid !== 'all'
            ? {
                field: 'baseId',
                operator: 'eq',
                value: searchData.value.baseid
              }
            : null,
          {
            field: 'startTime',
            operator: 'gte',
            dataType: 'date',
            value: dayjs(searchData.value.month)
              .startOf('month')
              .format('YYYY-MM-DD 00:00:00')
          },
          {
            field: 'endTime',
            operator: 'lte',
            dataType: 'date',
            value: dayjs(searchData.value.month)
              .endOf('month')
              .format('YYYY-MM-DD 23:59:59')
          },
          searchData.value.stnm
            ? {
                field: 'stnm',
                operator: 'contains',
                value: searchData.value.stnm
              }
            : null
        ].filter(Boolean)
      }
    };

    const res = await getAisbdbyxList(params);
    const data = res?.data ?? {};

    tabList.value = [
      { key: 1, value: '漂浮物识别', unit: '次', count: data?.pfwCnt ?? 0 },
      { key: 3, value: '清漂识别', unit: '次', count: data?.pfwqlCnt ?? 0 },
      { key: 2, value: '叠梁门运行识别', unit: '次', count: data?.dlmCnt ?? 0 }
    ];
  } catch (error) {
    console.error('获取Tab统计失败:', error);
    tabList.value = [
      { key: 1, value: '漂浮物识别', unit: '次', count: 0 },
      { key: 3, value: '清漂识别', unit: '次', count: 0 },
      { key: 2, value: '叠梁门运行识别', unit: '次', count: 0 }
    ];
  }
};

// ==================== 获取饼图数据 ====================
const getChartData = async () => {
  chartLoading.value = true;
  try {
    const filter = buildFilter();
    const group =
      searchData.value.baseid === 'all'
        ? [
            { dir: 'asc', field: 'baseStepSort' },
            { dir: 'asc', field: 'baseId' },
            { dir: 'asc', field: 'baseName' }
          ]
        : [
            { dir: 'asc', field: 'rstcd' },
            { dir: 'asc', field: 'ennm' }
          ];

    const params = {
      filter,
      group,
      sort: [
        {
          field: 'rstcdStepSort',
          dir: 'asc'
        },
        {
          field: 'tm',
          dir: 'desc'
        }
      ]
    };

    const res = await getAiChartTable(params);
    const dataObj = res?.data?.data ?? {};
    const rawData = Array.isArray(dataObj) ? dataObj : dataObj?.data || [];

    const list: { name: string; value: number; key: string }[] = [];

    if (searchData.value.baseid === 'all') {
      rawData.forEach((level1: any) => {
        if (level1?.items?.length) {
          level1.items.forEach((level2: any) => {
            if (level2?.items?.length) {
              level2.items.forEach((level3: any) => {
                if (level3?.items?.length) {
                  level3.items.forEach((item: any) => {
                    list.push({
                      name: item?.BASENAME || level3.key || '-',
                      value:
                        item?.COUNT_BASENAME ||
                        item?.COUNT_BASEID ||
                        level3.count ||
                        0,
                      key: item?.BASEID || level2.key || ''
                    });
                  });
                } else {
                  list.push({
                    name: level3.key || '-',
                    value: level3.count || 0,
                    key: level2.key || ''
                  });
                }
              });
            }
          });
        }
      });
    } else {
      rawData.forEach((el: any) => {
        list.push({
          name: el?.ennm_value || el?.ennm || '-',
          value: el?.count_rstcd || el?.count_ennm || 0,
          key: el?.rstcd || el?.rstcd_value || ''
        });
      });
    }

    chartData.value = list;
  } catch (error) {
    console.error('获取饼图数据失败:', error);
    chartData.value = [];
  } finally {
    chartLoading.value = false;
    // 等待 DOM 更新后再初始化图表
    await nextTick();
    setTimeout(() => {
      initChart();
      initVideoChart();
    }, 50);
  }
};

// ==================== 初始化饼图 ====================
const initChart = (retryCount = 0) => {
  // 根据当前 tabIndex 获取对应 tab 的 DOM
  const dom = chartRefs.value.get(tabIndex.value);

  if (!dom) {
    console.warn(
      `[initChart] DOM not found for tab ${tabIndex.value}, retrying...`
    );
    if (retryCount < 10) {
      setTimeout(() => initChart(retryCount + 1), 100);
    }
    return;
  }

  // 检查 DOM 是否可见（宽高不为 0）
  const rect = dom.getBoundingClientRect();
  if (rect.width === 0 || rect.height === 0) {
    if (retryCount < 10) {
      console.warn(
        `[initChart] DOM has 0 dimensions, retrying in 100ms... (attempt ${
          retryCount + 1
        }/10)`
      );
      setTimeout(() => initChart(retryCount + 1), 100);
    } else {
      console.error(
        '[initChart] DOM still has 0 dimensions after 10 retries, giving up'
      );
    }
    return;
  }

  if (!chartInstance) {
    chartInstance = echarts.init(dom);
  }

  const option: echarts.EChartsOption = {
    tooltip: {
      trigger: 'item',
      formatter: (params: any) =>
        `${params.marker} ${params.name}: ${params.value}(次)`
    },
    legend: {
      orient: 'vertical',
      right: 10,
      top: 80,
      textStyle: { fontSize: 12 }
    },
    series: []
  };

  if (!chartData.value || chartData.value.length === 0) {
    chartInstance.setOption(option, true);
    return;
  }

  const total = chartData.value.reduce(
    (acc: number, item: any) => acc + (item.value || 0),
    0
  );
  const typeMap: Record<string, string> = {
    '1': '清漂(次)',
    '2': '叠梁门开启(次)',
    '3': '清漂识别(次)'
  };
  const titleText = typeMap[tabIndex.value] || '识别(次)';

  option.series = [
    {
      type: 'pie',
      radius: ['26%', '35%'],
      center: ['35%', '50%'],
      avoidLabelOverlap: false,
      label: {
        show: true,
        formatter: '{c}'
      },
      labelLine: {
        show: true,
        length: 12,
        length2: 12
      },
      data: chartData.value.map((item: any) => ({
        name: item.name,
        value: item.value
      }))
    }
  ];

  option.title = {
    text: String(total),
    left: '34%',
    top: '44%',
    textAlign: 'center',
    textStyle: {
      fontSize: 24,
      fontWeight: 'bold',
      color: '#333'
    },
    subtext: titleText,
    subtextStyle: {
      fontSize: 12,
      color: '#333'
    }
  };

  chartInstance.setOption(option, true);

  // 图例点击联动过滤表格
  chartInstance.off('legendselectchanged');
  chartInstance.on('legendselectchanged', (e: any) => {
    const trueRivers = Object.keys(e.selected).filter(
      (key: string) => e.selected[key]
    );
    const allFalse = Object.values(e.selected).every(
      (value: any) => value === false
    );
    const selectedKeys = chartData.value
      .filter((item: any) => trueRivers.includes(item.name))
      .map((item: any) => item.key);
    pieCode.value = allFalse ? [] : selectedKeys;
    nextTick(() => {
      const filter = buildFilter();
      getTableInstance()?.getList(filter);
    });
  });
};

// ==================== 初始化视频视图饼图 ====================
const initVideoChart = (retryCount = 0) => {
  const dom = videoChartRefs.value.get(tabIndex.value);

  if (!dom) {
    if (retryCount < 10) {
      setTimeout(() => initVideoChart(retryCount + 1), 100);
    }
    return;
  }

  const rect = dom.getBoundingClientRect();
  if (rect.width === 0 || rect.height === 0) {
    if (retryCount < 10) {
      setTimeout(() => initVideoChart(retryCount + 1), 100);
    }
    return;
  }

  if (!videoChartInstance) {
    videoChartInstance = echarts.init(dom);
  }

  const option: echarts.EChartsOption = {
    tooltip: {
      trigger: 'item',
      formatter: (params: any) =>
        `${params.marker} ${params.name}: ${params.value}(次)`
    },
    legend: {
      orient: 'vertical',
      right: 10,
      top: 80,
      textStyle: { fontSize: 12 }
    },
    series: []
  };

  if (!chartData.value || chartData.value.length === 0) {
    videoChartInstance.setOption(option, true);
    return;
  }

  const total = chartData.value.reduce(
    (acc: number, item: any) => acc + (item.value || 0),
    0
  );
  const typeMap: Record<string, string> = {
    '1': '清漂(次)',
    '2': '叠梁门开启(次)',
    '3': '清漂识别(次)'
  };
  const titleText = typeMap[tabIndex.value] || '识别(次)';

  option.series = [
    {
      type: 'pie',
      radius: ['26%', '35%'],
      center: ['35%', '50%'],
      avoidLabelOverlap: false,
      label: {
        show: true,
        formatter: '{c}'
      },
      labelLine: {
        show: true,
        length: 12,
        length2: 12
      },
      data: chartData.value.map((item: any) => ({
        name: item.name,
        value: item.value
      }))
    }
  ];

  option.title = {
    text: String(total),
    left: '34%',
    top: '44%',
    textAlign: 'center',
    textStyle: {
      fontSize: 24,
      fontWeight: 'bold',
      color: '#333'
    },
    subtext: titleText,
    subtextStyle: {
      fontSize: 12,
      color: '#333'
    }
  };

  videoChartInstance.setOption(option, true);

  // 图例点击联动过滤视频列表
  videoChartInstance.off('legendselectchanged');
  videoChartInstance.on('legendselectchanged', (e: any) => {
    const trueRivers = Object.keys(e.selected).filter(
      (key: string) => e.selected[key]
    );
    const allFalse = Object.values(e.selected).every(
      (value: any) => value === false
    );
    const selectedKeys = chartData.value
      .filter((item: any) => trueRivers.includes(item.name))
      .map((item: any) => item.key);
    pieCode.value = allFalse ? [] : selectedKeys;
    nextTick(() => {
      videoPage.value = 1;
      activeFid.value = '';
      activeMedia.value = { type: '', src: '' };
      fetchVideoList();
    });
  });
};

// ==================== 获取视频列表 ====================
const fetchVideoList = async () => {
  videoLoading.value = true;
  try {
    const filter = buildFilter();
    const skip = (videoPage.value - 1) * videoTake.value;

    const params = {
      filter,
      skip,
      take: videoTake.value,
      sort: [
        { field: 'rstcdStepSort', dir: 'asc' },
        { field: 'tm', dir: 'desc' }
      ]
    };

    const res = await getAiChartTable(params);
    const rData = res?.data ?? {};
    const rawData = rData?.data || [];
    videoTotal.value = rData?.total || rawData.length;

    // 按 fid 展开（与 React 一致，支持逗号分隔的多个 fid）
    const expandedData = rawData
      .map((item: any) => {
        const fids = item.fid ? item.fid.split(',') : [];
        return fids.map((fid: string) => ({ ...item, fid: fid.trim() }));
      })
      .flat();

    // 收集所有 fid
    const allFids = expandedData
      .filter((item: any) => item.fid)
      .map((item: any) => item.fid)
      .join(',');

    // 调用 postIdUrl 获取媒体详情
    let mediaMap: Record<string, any> = {};
    if (allFids) {
      const formData = new FormData();
      formData.append('id', allFids);
      const mediaRes: any = await postIdUrl(formData);
      mediaMap = mediaRes?.data || {};
    }

    // 构建列表（与 React 一致）
    const list: any[] = [];
    expandedData.forEach((vd: any) => {
      const fileInfo = mediaMap[vd.fid];
      const hasValidExtension =
        fileInfo && ['.jpg', '.png'].includes(fileInfo.ext);

      let flpth = '';
      let imgPath = '';
      let type = '';

      if (hasValidExtension !== undefined && !hasValidExtension) {
        // 非图片（视频）
        flpth = fileInfo.fullpath;
        type = 'vdsp';
      } else if (hasValidExtension !== undefined) {
        // 图片
        imgPath = fileInfo.fullpath;
        type = 'img';
      }

      const tm = vd.tm ? dayjs(vd.tm).format('YYYY-MM-DD HH:mm:ss') : '-';
      list.push({
        ...vd,
        flpth,
        imgPath,
        flnm: `${vd.ennm || ''}${tm}`,
        type,
        tm
      });
    });

    // 过滤掉无效项（与 React 一致）
    const listMap = list.filter(
      item => item.flpth !== '' || item.imgPath !== ''
    );
    videoList.value = listMap;
    // debugger
    // 默认选中第一条
    if (listMap.length > 0 && !activeFid.value) {
      handleSelectMedia(listMap[0]);
    }
  } catch (error) {
    console.error('获取视频列表失败:', error);
    videoList.value = [];
  } finally {
    videoLoading.value = false;
  }
};

// 选择媒体（与 React 一致）
const handleSelectMedia = (item: any) => {
  activeFid.value = item.fid;

  if (item.type === 'img') {
    activeMedia.value = {
      type: 'image',
      src: baseUrl + '?' + item.fid + '&view=jpg'
    };
  } else if (item.type === 'vdsp') {
    activeMedia.value = {
      type: 'video',
      src: baseUrl + '?' + item.fid + '&view=jpg'
    };
  } else {
    activeMedia.value = { type: '', src: '' };
  }
};

// 分页切换
const handleVideoPageChange = () => {
  activeFid.value = '';
  activeMedia.value = { type: '', src: '' };
  fetchVideoList();
};

// ==================== 获取电站列表（用于日历视图的rstcd下拉） ====================
const colStcdData = async () => {
  try {
    const type = getType();
    const filters: any[] = [
      { field: 'type', operator: 'eq', value: type },
      searchData.value.baseid !== 'all'
        ? { field: 'baseId', operator: 'eq', value: searchData.value.baseid }
        : null,
      {
        field: 'startTime',
        operator: 'gte',
        dataType: 'date',
        value: dayjs(searchData.value.month)
          .startOf('month')
          .format('YYYY-MM-DD 00:00:00')
      },
      {
        field: 'endTime',
        operator: 'lte',
        dataType: 'date',
        value: dayjs(searchData.value.month)
          .endOf('month')
          .format('YYYY-MM-DD 23:59:59')
      }
    ].filter(Boolean);

    const params = { filter: { logic: 'and', filters } };
    const res: any = await getAiRstcd(params);
    const _data = res?.data?.data ?? [];
    const list = _data.map((item: any) => ({
      label: item.stnm,
      value: item.stcd
    }));

    // 如果当前选中的rstcd不在新列表中，重置为第一个
    const selected = list?.filter(
      (item: any) => item.value === searchData.value.rstcd
    );
    if (selected?.length === 0) {
      searchData.value.rstcd = list?.[0]?.value ?? '';
    }

    stcdData.value = list;
  } catch (error) {
    console.error('获取电站列表失败:', error);
  }
};

// ==================== 日历视图函数 ====================
// 判断是否是当前月份
const isCurrentMonth = (current: any): boolean => {
  return (
    current.month() === calendarValue.value.month() &&
    current.year() === calendarValue.value.year()
  );
};

// 获取某天的日历数据
const getCalendarDataForDay = (current: any): any => {
  return calendarData.value.find(
    (item: any) => dayjs(item.dt).format('DD') === current.format('DD')
  );
};

// 获取状态样式类（支持数字和字符串类型）
const getStatusClass = (status: number | string) => {
  const statusKey = String(status);
  return calendarStatusMap[statusKey]?.className || '';
};

// 获取状态文本（支持数字和字符串类型）
const getStatusText = (status: number | string) => {
  const statusKey = String(status);
  return calendarStatusMap[statusKey]?.name || '';
};

// 获取日历数据（参考React端逻辑）
const fetchCalendarData = async () => {
  calendarLoading.value = true;
  try {
    const type = getType();
    const filters: any[] = [
      // baseId过滤（支持饼图联动）
      pieCode.value.length > 0 && searchData.value.baseid === 'all'
        ? {
            field: 'baseId',
            operator: 'in',
            dataType: 'string',
            value: pieCode.value
          }
        : searchData.value.baseid !== 'all'
        ? { field: 'baseId', operator: 'eq', value: searchData.value.baseid }
        : null,
      // rstcd过滤（饼图联动时）
      pieCode.value.length > 0 && searchData.value.baseid !== 'all'
        ? {
            field: 'rstcd',
            operator: 'in',
            dataType: 'string',
            value: pieCode.value
          }
        : null,
      // type过滤
      { field: 'type', operator: 'eq', value: type },
      // 时间范围
      {
        field: 'startTime',
        operator: 'gte',
        dataType: 'date',
        value: dayjs(searchData.value.month)
          .startOf('month')
          .format('YYYY-MM-DD 00:00:00')
      },
      {
        field: 'endTime',
        operator: 'lte',
        dataType: 'date',
        value: dayjs(searchData.value.month)
          .endOf('month')
          .format('YYYY-MM-DD 23:59:59')
      },
      // stnm文本搜索
      searchData.value.stnm
        ? { field: 'stnm', operator: 'contains', value: searchData.value.stnm }
        : null,
      // rstcd电站选择（日历视图下）
      searchData.value.rstcd
        ? {
            field: 'rstcd',
            operator: 'in',
            dataType: 'string',
            value: [searchData.value.rstcd]
          }
        : null
    ].filter(Boolean);

    const params = {
      filter: { logic: 'and', filters },
      sort: tabIndex.value === '1' ? [] : [{ field: 'tm', dir: 'desc' }]
    };

    // 根据类型调用不同接口（与React端一致：AI_5005用getAiRecord，其余用getAiPfwRecord）
    const apiFn = type === 'AI_5005' ? getAiRecord : getAiPfwRecord;
    const res: any = await apiFn(params);
    // 接口返回结构: { code, msg, data: [...] } - data 直接是数组，不是 res.data.data
    const payload = res?.data || {};
    calendarData.value = Array.isArray(payload) ? payload : payload.data || [];
  } catch (error) {
    console.error('获取日历数据失败:', error);
    calendarData.value = [];
  } finally {
    calendarLoading.value = false;
  }
};

// 日历面板切换
const handleCalendarPanelChange = (date: any) => {
  calendarValue.value = date;
  fetchCalendarData();
};

// 日历日期选择
const handleCalendarSelect = (date: any) => {
  calendarValue.value = date;
};

// 点击日历日期（参考React端逻辑）
const handleCalendarDayClick = async (current: any, dayData: any) => {
  const date = dayjs(current).format('YYYY-MM-DD');
  const status = dayData.status;
  const statusInfo = calendarStatusMap[status];
  if (!statusInfo) return;

  // 清漂识别直接打开附件预览
  if (tabIndex.value === '3') {
    const fidStr = dayData.fid;
    if (!fidStr) {
      return;
    }
    qingpiaoFids.value = fidStr
      .split(',')
      .map((s: string) => s.trim())
      .filter(Boolean);
    qingpiaoModalVisible.value = true;
    return;
  }

  // 漂浮物/叠梁门打开视频详情弹窗
  detailDate.value = date;
  detailType.value = statusInfo.type;

  // 设置 Tab 项（与React端一致）
  if (tabIndex.value === '2') {
    // 叠梁门运行识别：运行 / 未运行
    detailTabItems.value = [
      { key: '2', label: '运行' },
      { key: '1', label: '未运行' }
    ];
  } else {
    // 漂浮物识别：无漂浮物 / 小面积漂浮物 / 大面积漂浮物
    detailTabItems.value = [
      { key: '3', label: '无漂浮物' },
      { key: '4', label: '小面积漂浮物' },
      { key: '5', label: '大面积漂浮物' }
    ];
  }

  detailActiveKey.value = statusInfo.dataType;
  detailModalVisible.value = true;

  // 获取视频数据
  fetchDetailVideoList();
};

// 获取详情视频列表
const fetchDetailVideoList = async () => {
  detailVideoLoading.value = true;
  try {
    const filters: any[] = [
      // baseId过滤（支持饼图联动）
      pieCode.value.length > 0 && searchData.value.baseid === 'all'
        ? {
            field: 'baseId',
            operator: 'in',
            dataType: 'string',
            value: pieCode.value
          }
        : searchData.value.baseid !== 'all'
        ? { field: 'baseId', operator: 'eq', value: searchData.value.baseid }
        : null,
      // rstcd过滤（饼图联动时）
      pieCode.value.length > 0 && searchData.value.baseid !== 'all'
        ? {
            field: 'rstcd',
            operator: 'in',
            dataType: 'string',
            value: pieCode.value
          }
        : null,
      // type过滤
      { field: 'type', operator: 'eq', value: detailType.value },
      // dataType过滤
      { field: 'dataType', operator: 'eq', value: detailDataType.value },
      // 时间范围
      {
        field: 'tm',
        operator: 'gte',
        dataType: 'date',
        value: dayjs(detailDate.value)
          .startOf('day')
          .format('YYYY-MM-DD 00:00:00')
      },
      {
        field: 'tm',
        operator: 'lte',
        dataType: 'date',
        value: dayjs(detailDate.value)
          .endOf('day')
          .format('YYYY-MM-DD 23:59:59')
      },
      // stnm文本搜索
      searchData.value.stnm
        ? { field: 'stnm', operator: 'contains', value: searchData.value.stnm }
        : null,
      // rstcd电站选择（日历视图下）
      searchData.value.rstcd
        ? {
            field: 'rstcd',
            operator: 'in',
            dataType: 'string',
            value: [searchData.value.rstcd]
          }
        : null
    ].filter(Boolean);

    const params = {
      filter: { logic: 'and', filters },
      sort: tabIndex.value === '1' ? [] : [{ field: 'tm', dir: 'desc' }],
      skip: (detailVideoPage.value - 1) * detailVideoTake.value,
      take: detailVideoTake.value
    };

    const res: any = await getAiFile(params);
    console.log('二级弹框接口返回:', res);
    const rData = res?.data ?? {};
    const rawData = rData?.data || [];
    console.log('提取的原始数据:', rawData);
    detailVideoTotal.value = rData?.total || rawData.length;

    // 按 fid 展开（与 React 一致，支持逗号分隔的多个 fid）
    const expandedData = rawData
      .map((item: any) => {
        const fids = item.fid ? item.fid.split(',') : [];
        return fids.map((fid: string) => ({ ...item, fid: fid.trim() }));
      })
      .flat();

    // 收集所有 fid
    const allFids = expandedData
      .filter((item: any) => item.fid)
      .map((item: any) => item.fid)
      .join(',');

    // 调用 postIdUrl 获取媒体详情
    let mediaMap: Record<string, any> = {};
    if (allFids) {
      const formData = new FormData();
      formData.append('id', allFids);
      console.log('请求媒体详情, allFids:', allFids);
      try {
        const mediaRes: any = await postIdUrl(formData);
        console.log('媒体详情返回:', mediaRes);
        mediaMap = mediaRes?.data || {};
        console.log('mediaMap:', mediaMap);
      } catch (mediaError) {
        console.error('获取媒体详情失败:', mediaError);
        mediaMap = {};
      }
    }

    // 构建列表（与 React 一致）
    const list: any[] = [];
    expandedData.forEach((vd: any) => {
      const fileInfo = mediaMap[vd.fid];
      const hasValidExtension =
        fileInfo && ['.jpg', '.png'].includes(fileInfo.ext);

      let flpth = '';
      let imgPath = '';
      let type = '';

      if (hasValidExtension !== undefined && !hasValidExtension) {
        // 非图片（视频）
        flpth = fileInfo.fullpath;
        type = 'vdsp';
      } else if (hasValidExtension !== undefined) {
        // 图片
        imgPath = fileInfo.fullpath;
        type = 'img';
      }

      const tm = vd.tm ? dayjs(vd.tm).format('YYYY-MM-DD HH:mm:ss') : '-';
      list.push({
        ...vd,
        flpth,
        imgPath,
        flnm: `${vd.ennm || ''}${tm}`,
        type,
        tm
      });
    });

    console.log('构建的列表（过滤前）:', list);

    // 过滤掉无效项（与 React 一致）
    const listMap = list.filter(
      item => item.flpth !== '' || item.imgPath !== ''
    );
    console.log('过滤后的列表:', listMap);
    detailVideoList.value = listMap;

    // 默认选中第一条
    if (listMap.length > 0) {
      const first = listMap[0];
      detailActiveFid.value = first.fid;
      if (first.type === 'img') {
        detailActiveMedia.value = {
          type: 'image',
          src: baseUrl + '?' + first.fid + '&view=jpg'
        };
      } else if (first.type === 'vdsp') {
        detailActiveMedia.value = {
          type: 'video',
          src: baseUrl + '?' + first.fid + '&view=jpg'
        };
      } else {
        detailActiveMedia.value = { type: '', src: '' };
      }
    }
  } catch (error) {
    console.error('获取详情视频列表失败:', error);
    detailVideoList.value = [];
  } finally {
    detailVideoLoading.value = false;
  }
};

// 选择详情媒体（与 React 一致）
const handleSelectDetailMedia = (item: any) => {
  detailActiveFid.value = item.fid;

  if (item.type === 'img') {
    detailActiveMedia.value = {
      type: 'image',
      src: baseUrl + '?' + item.fid + '&view=jpg'
    };
  } else if (item.type === 'vdsp') {
    detailActiveMedia.value = {
      type: 'video',
      src: baseUrl + '?' + item.fid + '&view=jpg'
    };
  } else {
    detailActiveMedia.value = { type: '', src: '' };
  }
};

// 详情分页切换
const handleDetailVideoPageChange = (page: number, pageSize: number) => {
  detailVideoPage.value = page;
  detailVideoTake.value = pageSize;
  detailActiveFid.value = '';
  detailActiveMedia.value = { type: '', src: '' };
  fetchDetailVideoList();
};

// ==================== 事件处理 ====================
const handleBaseChange = () => {
  pieCode.value = [];
  handleSearch();
};

const handleSearch = () => {
  getTabList();
  getChartData();
  videoPage.value = 1;
  activeFid.value = '';
  activeMedia.value = { type: '', src: '' };
  fetchVideoList();
  fetchCalendarData();
  nextTick(() => {
    const filter = buildFilter();
    getTableInstance()?.getList(filter);
  });
};

const handleViewAttachment = (fid: string) => {
  currentAttachmentFid.value = fid;
  attachmentModalVisible.value = true;
};

// ==================== 监听基地变化 ====================
watch(
  () => JidiSelectEventStore.selectedItem,
  newVal => {
    if (newVal && newVal.wbsCode) {
      searchData.value.baseid = newVal.wbsCode;
    }
  },
  { deep: true, immediate: true }
);

// ==================== 监听视图切换 ====================
watch(vdListShow, () => {
  if (vdListShow.value === '1') {
    fetchVideoList();
    getChartData();
  } else if (vdListShow.value === '2') {
    getChartData();
    nextTick(() => {
      const filter = buildFilter();
      getTableInstance()?.getList(filter);
    });
  } else if (vdListShow.value === '3') {
    colStcdData();
    fetchCalendarData();
  }
});

// ==================== 监听baseid/tabIndex/month变化，更新电站列表 ====================
watch(
  () => [searchData.value.baseid, tabIndex.value, searchData.value.month],
  () => {
    colStcdData();
  }
);

// ==================== 监听月份变化，同步日历显示 ====================
watch(
  () => searchData.value.month,
  (newMonth) => {
    calendarValue.value = newMonth;
    
  }
);

// ==================== 监听 Tab 切换 ====================
watch(tabIndex, () => {
  pieCode.value = [];
  // 清空视频状态
  videoPage.value = 1;
  activeFid.value = '';
  activeMedia.value = { type: '', src: '' };
  // 销毁旧实例，避免 setOption 到已隐藏的 DOM
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  if (videoChartInstance) {
    videoChartInstance.dispose();
    videoChartInstance = null;
  }
  // 等待新 tab DOM 渲染后再请求数据
  nextTick(() => {
    getChartData();
    fetchVideoList();
    fetchCalendarData();
    nextTick(() => {
      const filter = buildFilter();
      getTableInstance()?.getList(filter);
    });
  });
});

// ==================== 监听详情弹窗 Tab 切换 ====================
watch(detailActiveKey, () => {
  if (detailModalVisible.value) {
    detailVideoPage.value = 1;
    fetchDetailVideoList();
  }
});

// ==================== 窗口 resize ====================
const handleResize = () => {
  const dom = chartRefs.value.get(tabIndex.value);
  if (dom) {
    chartInstance?.resize();
  }
};

// ==================== 生命周期 ====================
onMounted(() => {
  // 初始化基地选项
  const jidiList = JidiSelectEventStore.jidiData || [];
  jidiOptions.value = jidiList.map((item: any) => ({
    label: item.wbsName,
    value: item.wbsCode
  }));

  getTabList();
  getChartData();
  fetchVideoList();
  fetchCalendarData();
  nextTick(() => {
    const filter = buildFilter();
    getTableInstance()?.getList(filter);
  });

  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize);
  chartInstance?.dispose();
  chartInstance = null;
});
</script>

<style lang="scss" scoped>
.aisbtk-page {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;

  .search-form {
    padding: 12px 0;
    border-bottom: 1px solid #f0f0f0;
    margin-bottom: 12px;
  }

  .aisbtk-tabs {
    flex: 1;
    display: flex;
    flex-direction: column;
    position: relative;

    :deep(.ant-tabs-content) {
      height: 100%;
    }

    :deep(.ant-tabs-tabpane) {
      height: 100%;
    }
  }

  .view-switch-buttons {
    position: absolute;
    right: 0;
    top: -60px;
    display: flex;
    z-index: 10;

    .view-btn {
      width: 30px;
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-right: 10px;
      border: 1px solid #ccdae7;
      border-radius: 2px;
      cursor: pointer;
      color: #333;
      background: transparent;
      transition: all 0.3s;

      &:hover {
        border-color: #2f6b98;
        color: #2f6b98;
      }

      &.active {
        background: #2f6b98;
        color: #ffffff;
        border-color: #2f6b98;
      }
    }
  }

  .view-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .chart-table-layout {
    display: flex;
    gap: 16px;
    height: 100%;

    .chart-section {
      width: 35%;
      min-width: 300px;
      position: relative;

      .chart-container {
        width: 100%;
        height: 480px;
      }

      .chart-empty-overlay {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10;
        background: rgba(255, 255, 255, 0.8);
      }
    }

    .table-section {
      flex: 1;
      min-width: 0;
    }

    .video-section {
      flex: 1;
      min-width: 0;
    }
  }

  .video-mode {
    display: flex;
    gap: 12px;
    width: 100%;
    height: 520px;

    .video-main {
      flex: 0 0 80%;
      background: #000;
      border-radius: 4px;
      overflow: hidden;

      .media-display {
        width: 100%;
        height: 100%;
      }

      .media-empty {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100%;
      }
    }

    .video-sidebar {
      flex: 0 0 20%;
      display: flex;
      flex-direction: column;
      border: 1px solid #e8e8e8;
      border-radius: 4px;
      overflow: hidden;

      .sidebar-list {
        flex: 1;
        overflow-y: auto;

        .sidebar-item {
          padding: 8px;
          cursor: pointer;
          border-bottom: 1px solid #f0f0f0;
          transition: background 0.2s;

          &:hover {
            background: #f5f5f5;
          }

          &.active {
            background: #e6f7ff;
          }

          .item-thumb {
            width: 100%;
            height: 110px;
            background: #1a1a1a;
            border-radius: 4px;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;

            img {
              width: 100%;
              height: 100%;
              object-fit: cover;
            }

            .thumb-placeholder {
              width: 100%;
              height: 100%;
              display: flex;
              align-items: center;
              justify-content: center;
              color: #fff;

              .no-media {
                font-size: 12px;
                color: #999;
              }
            }
          }

          .item-time {
            margin-top: 6px;
            font-size: 12px;
            color: #666;
            text-align: center;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }
      }

      .sidebar-empty {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-direction: column;
      }

      .sidebar-pagination {
        padding: 8px;
        text-align: center;
        border-top: 1px solid #e8e8e8;
      }
    }
  }

  .calendar-mode {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    height:60vh;
    overflow: auto;
    padding-top:200px;

    :deep(.ant-picker-calendar) {
      width: 90%;
      max-width: 1200px;
    }

    :deep(.ant-picker-content thead th) {
      font-size: 0;
    }

    :deep(.ant-picker-content thead th)::before {
      font-size: 16px;
      font-weight: 700;
      padding-right: 10px;
    }

    :deep(.ant-picker-content thead tr th:nth-child(1))::before {
      content: '周一';
    }

    :deep(.ant-picker-content thead tr th:nth-child(2))::before {
      content: '周二';
    }

    :deep(.ant-picker-content thead tr th:nth-child(3))::before {
      content: '周三';
    }

    :deep(.ant-picker-content thead tr th:nth-child(4))::before {
      content: '周四';
    }

    :deep(.ant-picker-content thead tr th:nth-child(5))::before {
      content: '周五';
    }

    :deep(.ant-picker-content thead tr th:nth-child(6))::before {
      content: '周六';
    }

    :deep(.ant-picker-content thead tr th:nth-child(7))::before {
      content: '周日';
    }

    :deep(.ant-picker-calendar) {
      .ant-picker-calendar-date-value {
        font-size: 18px !important;
        padding-right: 8px;
      }

      .ant-picker-calendar-date {
        border: 1px solid rgb(213, 225, 233) !important;
        margin: 0px !important;
        // height: 75px !important;
      }

      .ant-picker-panel {
        .ant-picker-content {
          thead {
            th {
              padding: 6px 0;
              border: 1px solid rgb(213, 225, 233) !important;
            }
          }

          td {
            padding: 0;

            .ant-picker-calendar-date {
              padding: 3px;
              border: none;
            }

            &.ant-picker-cell-selected .ant-picker-calendar-date {
              background: transparent;
            }

            &.ant-picker-cell-today .ant-picker-calendar-date::before {
              display: none;
            }
          }
        }
      }
    }

    .calendar-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 1px;
      padding: 2px;
      text-align: right;

      .content_state1 {
        width: 100%;
        background-color: #67c23a;
        color: #000;
        padding: 2px 0;
        border-radius: 3px;
        cursor: auto;
        padding-right: 8px;
        font-size: 12px;
      }

      .content_state4 {
        width: 100%;
        background-color: #e6a23c;
        padding: 2px 0;
        border-radius: 3px;
        cursor: auto;
        padding-right: 8px;
        font-size: 12px;
      }

      .content_state2 {
        width: 100%;
        background-color: #e1f3d8;
        padding: 2px 0;
        border-radius: 3px;
        cursor: pointer;
        padding-right: 8px;
        font-size: 12px;

        &:hover {
          opacity: 0.8;
        }
      }

      .content_state3 {
        width: 100%;
        background-color: #faecd8;
        padding: 2px 0;
        border-radius: 3px;
        cursor: pointer;
        padding-right: 8px;
        font-size: 12px;

        &:hover {
          opacity: 0.8;
        }
      }

      .content_state5 {
        width: 100%;
        background-color: #faecd8;
        padding: 2px 0;
        border-radius: 3px;
        cursor: pointer;
        padding-right: 8px;
        font-size: 12px;

        &:hover {
          opacity: 0.8;
        }
      }
    }
  }

  .detail-empty {
    height: 600px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
}
</style>
