liu
2026-09-29 982c97ab82f3beb1b4febcf014562eda34b9fc05
src/views/dashboard/analytics/index.vue
@@ -1,90 +1,140 @@
<script lang="ts" setup>
import type { AnalysisOverviewItem } from '../../../packages/effects/common-ui/src';
import type { TabOption } from '../../../packages/types/src';
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import {
  AnalysisChartCard,
  AnalysisChartsTabs,
  AnalysisOverview,
} from '../../../packages/effects/common-ui/src';
import {
  SvgBellIcon,
  SvgCakeIcon,
  SvgCardIcon,
  SvgDownloadIcon,
} from '../../../packages/icons/src';
import { Page } from '@vben/common-ui';
import AnalyticsTrends from './analytics-trends.vue';
import AnalyticsVisitsData from './analytics-visits-data.vue';
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
import AnalyticsVisitsSource from './analytics-visits-source.vue';
import AnalyticsVisits from './analytics-visits.vue';
import { Col, Row } from 'ant-design-vue';
const overviewItems: AnalysisOverviewItem[] = [
  {
    icon: SvgCardIcon,
    title: '用户量',
    totalTitle: '总用户量',
    totalValue: 120_000,
    value: 2000,
  },
  {
    icon: SvgCakeIcon,
    title: '访问量',
    totalTitle: '总访问量',
    totalValue: 500_000,
    value: 20_000,
  },
  {
    icon: SvgDownloadIcon,
    title: '下载量',
    totalTitle: '总下载量',
    totalValue: 120_000,
    value: 8000,
  },
  {
    icon: SvgBellIcon,
    title: '使用量',
    totalTitle: '总使用量',
    totalValue: 50_000,
    value: 5000,
  },
];
import KpiCards from './modules/kpi-cards.vue';
import QuickActions from './modules/quick-actions.vue';
import RecentApplications from './modules/recent-applications.vue';
import TodoPanel from './modules/todo-panel.vue';
const chartTabs: TabOption[] = [
  {
    label: '流量趋势',
    value: 'trends',
  },
  {
    label: '月访问量',
    value: 'visits',
  },
];
defineOptions({ name: 'DashboardAnalytics' });
// vite.config.ts 注入的公司 Logo 路径
declare const __APP_LOGO__: string;
const brandLogo = __APP_LOGO__ || '/logos/JSSM.svg';
const router = useRouter();
const greeting = computed(() => {
  const hour = new Date().getHours();
  if (hour < 6) return '夜深了';
  if (hour < 9) return '早上好';
  if (hour < 12) return '上午好';
  if (hour < 14) return '中午好';
  if (hour < 18) return '下午好';
  return '晚上好';
});
const today = computed(() => {
  const d = new Date();
  const weekNames = ['日', '一', '二', '三', '四', '五', '六'];
  return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日 星期${weekNames[d.getDay()]}`;
});
function handleNavigate(name: string) {
  router.push({ name });
}
</script>
<template>
  <div class="p-5">
    <AnalysisOverview :items="overviewItems" />
    <AnalysisChartsTabs :tabs="chartTabs" class="mt-5">
      <template #trends>
        <AnalyticsTrends />
      </template>
      <template #visits>
        <AnalyticsVisits />
      </template>
    </AnalysisChartsTabs>
    <div class="mt-5 w-full md:flex">
      <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
        <AnalyticsVisitsData />
      </AnalysisChartCard>
      <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
        <AnalyticsVisitsSource />
      </AnalysisChartCard>
      <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">
        <AnalyticsVisitsSales />
      </AnalysisChartCard>
  <Page auto-content-height>
    <!-- 欢迎栏:藏青底 + 金色描边 -->
    <div class="elite-hero mb-6">
      <img alt="" class="elite-hero-mark" :src="brandLogo" />
      <div class="relative z-10 flex flex-wrap items-center justify-between gap-4">
        <div>
          <h1 class="elite-hero-title">{{ greeting }},欢迎回来</h1>
          <p class="elite-hero-date">{{ today }}</p>
        </div>
        <div class="elite-status">
          <span class="elite-status-dot"></span>
          系统运行中
        </div>
      </div>
    </div>
  </div>
    <!-- 系统指标 -->
    <KpiCards @navigate="handleNavigate" />
    <!-- 待办 + 快捷入口 -->
    <Row :gutter="16" class="mb-4">
      <Col :lg="14" :md="24" :sm="24" :xl="14" :xs="24" class="mb-4">
        <TodoPanel @navigate="handleNavigate" />
      </Col>
      <Col :lg="10" :md="24" :sm="24" :xl="10" :xs="24" class="mb-4">
        <QuickActions @navigate="handleNavigate" />
      </Col>
    </Row>
    <!-- 最近课题申报 -->
    <RecentApplications @navigate="handleNavigate" />
  </Page>
</template>
<style scoped>
/* ===== 欢迎栏 ===== */
.elite-hero {
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  padding: 30px 34px;
  background:
    radial-gradient(circle at 88% 12%, rgba(212, 175, 55, 0.08), transparent 50%),
    linear-gradient(135deg, #123156 0%, #0f2440 58%, #0b1c33 100%);
  border: 1px solid rgba(212, 175, 55, 0.24);
  box-shadow: 0 4px 18px rgba(15, 36, 64, 0.12);
}
/* 右侧淡淡的徽标水印 */
.elite-hero-mark {
  position: absolute;
  top: 50%;
  right: 168px;
  width: 118px;
  height: 118px;
  pointer-events: none;
  opacity: 0.05;
  transform: translateY(-50%);
}
.elite-hero-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 2px;
  color: #f5f0e4;
}
.elite-hero-date {
  margin: 8px 0 0;
  font-size: 13px;
  letter-spacing: 1px;
  color: rgba(212, 175, 55, 0.85);
}
.elite-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  font-size: 12.5px;
  letter-spacing: 1px;
  color: #f0e2b8;
  background: rgba(212, 175, 55, 0.12);
  border: 1px solid rgba(212, 175, 55, 0.38);
  border-radius: 999px;
}
/* 静态状态点,不做脉冲动画 */
.elite-status-dot {
  display: inline-flex;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: #d4af37;
}
</style>