前端页面更新
This commit is contained in:
@@ -6,17 +6,14 @@
|
||||
<span class="spacer"></span>
|
||||
<span class="source-meta">{{ news.source_name }} · {{ timeAgo }}</span>
|
||||
</div>
|
||||
|
||||
<h3 class="card-title">{{ news.title_zh }}</h3>
|
||||
<p class="card-summary">{{ news.summary }}</p>
|
||||
|
||||
<div v-if="news.opinion" class="opinion-block">
|
||||
<b>核心观点</b>{{ news.opinion }}
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="kw-row">
|
||||
<span v-for="kw in (news.keywords || []).slice(0, 5)" :key="kw" class="kw-tag">{{ kw }}</span>
|
||||
<span v-for="kw in (news.keywords || []).slice(0, 5)" :key="kw" class="kw-chip">{{ kw }}</span>
|
||||
</div>
|
||||
<a :href="news.source_url" target="_blank" @click.stop class="orig-link">查看原文 →</a>
|
||||
</div>
|
||||
@@ -49,42 +46,45 @@ const timeAgo = computed(() => {
|
||||
|
||||
<style scoped>
|
||||
.news-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--rule);
|
||||
background: #fff;
|
||||
border: 1px solid var(--rule2);
|
||||
border-radius: var(--r);
|
||||
padding: 16px;
|
||||
margin-bottom: 10px;
|
||||
padding: 18px;
|
||||
cursor: pointer;
|
||||
transition: border-color .15s, transform .15s;
|
||||
transition: all 0.15s;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.news-card:hover { border-color: var(--rule2); transform: translateY(-1px); }
|
||||
.news-card.featured { border-left: 2px solid var(--blue-2); }
|
||||
.news-card:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow);
|
||||
border-color: var(--blue-bd);
|
||||
}
|
||||
.news-card.featured { border-left: 3px solid var(--blue); }
|
||||
|
||||
/* Top row */
|
||||
.card-top { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
|
||||
|
||||
.score-badge {
|
||||
flex-shrink: 0;
|
||||
padding: 2px 7px;
|
||||
border-radius: 6px;
|
||||
border-radius: 5px;
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.badge-red { background: rgba(255,77,106,.2); color: var(--red); }
|
||||
.badge-amber { background: rgba(255,163,54,.2); color: var(--amber); }
|
||||
.badge-blue { background: rgba(46,85,245,.2); color: var(--blue-2); }
|
||||
.badge-gray { background: rgba(122,128,160,.15); color: var(--t3); }
|
||||
.badge-red { background: #fef2f2; color: #dc2626; }
|
||||
.badge-amber { background: #fffbeb; color: #d97706; }
|
||||
.badge-blue { background: #eff6ff; color: #2563eb; }
|
||||
.badge-gray { background: #f9fafb; color: #6b7280; }
|
||||
|
||||
.cat-label { font-size: 11px; color: var(--t3); }
|
||||
.spacer { flex: 1; }
|
||||
.cat-label { font-size: 12px; color: var(--t3); }
|
||||
.spacer { flex: 1; }
|
||||
.source-meta { font-size: 11px; color: var(--t4); font-family: var(--mono); }
|
||||
|
||||
/* Body */
|
||||
.card-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--t1);
|
||||
line-height: 1.4;
|
||||
line-height: 1.45;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.card-summary {
|
||||
@@ -98,15 +98,14 @@ const timeAgo = computed(() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Opinion */
|
||||
.opinion-block {
|
||||
background: var(--blue-gl);
|
||||
border-left: 2px solid var(--blue-bd);
|
||||
background: #eff6ff;
|
||||
border-left: 2px solid rgba(37, 99, 235, 0.35);
|
||||
border-radius: 0 6px 6px 0;
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 12.5px;
|
||||
color: #8AAAFF;
|
||||
color: var(--t2);
|
||||
line-height: 1.55;
|
||||
}
|
||||
.opinion-block b {
|
||||
@@ -115,27 +114,26 @@ const timeAgo = computed(() => {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 3px;
|
||||
opacity: .7;
|
||||
letter-spacing: .04em;
|
||||
color: var(--blue);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.card-footer { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
||||
.kw-row { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; }
|
||||
.kw-tag {
|
||||
font-size: 10px;
|
||||
.kw-chip {
|
||||
font-size: 11px;
|
||||
font-family: var(--mono);
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
background: rgba(46,85,245,.15);
|
||||
color: #7B9BFF;
|
||||
background: #eff6ff;
|
||||
color: #3b82f6;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.orig-link {
|
||||
font-size: 12px;
|
||||
color: var(--blue-2);
|
||||
color: var(--blue);
|
||||
white-space: nowrap;
|
||||
transition: color .15s;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
.orig-link:hover { color: var(--t1); }
|
||||
.orig-link:hover { color: #1d4ed8; }
|
||||
</style>
|
||||
|
||||
@@ -1,37 +1,41 @@
|
||||
/* 设计令牌——与 HTML 参考文件保持一致 */
|
||||
/* Light theme design tokens */
|
||||
:root {
|
||||
--bg: #07091A;
|
||||
--bg-1: #0B0E24;
|
||||
--bg-2: #10142E;
|
||||
--bg-card: #0D1028;
|
||||
--bg-hi: #141838;
|
||||
--bg: #f0f2f5;
|
||||
--bg-card: #ffffff;
|
||||
--bg-hover: #f0f4ff;
|
||||
--bg-1: #ffffff;
|
||||
--bg-2: #f8f9fc;
|
||||
--bg-hi: #f3f4f6;
|
||||
|
||||
--blue: #2E55F5;
|
||||
--blue-2: #5578FF;
|
||||
--blue-gl: rgba(46, 85, 245, 0.15);
|
||||
--blue-bd: rgba(46, 85, 245, 0.3);
|
||||
--blue: #2563eb;
|
||||
--blue-2: #3b82f6;
|
||||
--blue-gl: rgba(37, 99, 235, 0.06);
|
||||
--blue-bd: rgba(37, 99, 235, 0.2);
|
||||
|
||||
--violet: #7B3FE4;
|
||||
--violet-2: #9A68EE;
|
||||
--cyan: #19C3E6;
|
||||
--mint: #25D6A3;
|
||||
--amber: #FFA336;
|
||||
--red: #FF4D6A;
|
||||
--violet: #7c3aed;
|
||||
--cyan: #0ea5e9;
|
||||
--mint: #10b981;
|
||||
--amber: #f59e0b;
|
||||
--red: #ef4444;
|
||||
|
||||
--t1: #F0F2FF;
|
||||
--t2: #B8BEDD;
|
||||
--t3: #7A80A0;
|
||||
--t4: #4A506A;
|
||||
--t1: #111827;
|
||||
--t2: #374151;
|
||||
--t3: #6b7280;
|
||||
--t4: #9ca3af;
|
||||
|
||||
--rule: rgba(255, 255, 255, 0.07);
|
||||
--rule2: rgba(255, 255, 255, 0.13);
|
||||
--rule: #f3f4f6;
|
||||
--rule2: #e5e7eb;
|
||||
|
||||
--sans: 'Noto Sans SC', system-ui, sans-serif;
|
||||
--mono: 'JetBrains Mono', 'Courier New', monospace;
|
||||
|
||||
--r: 12px;
|
||||
--r-sm: 8px;
|
||||
--r-pill: 20px;
|
||||
--r-pill: 9999px;
|
||||
|
||||
--shadow-sm: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
|
||||
--shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
--shadow-lg: 0 8px 24px rgba(37,99,235,0.12);
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
@@ -47,13 +51,14 @@ html, body {
|
||||
}
|
||||
|
||||
a { color: inherit; text-decoration: none; }
|
||||
button { cursor: pointer; font-family: inherit; }
|
||||
button { cursor: pointer; font-family: inherit; border: none; background: none; }
|
||||
input, select, textarea { font-family: inherit; }
|
||||
|
||||
/* Element Plus 暗色覆盖 */
|
||||
.el-table { --el-table-bg-color: var(--bg-card); --el-table-header-bg-color: var(--bg-2); }
|
||||
.el-input__wrapper { background: var(--bg-2) !important; box-shadow: 0 0 0 1px var(--rule2) !important; }
|
||||
/* Element Plus light theme */
|
||||
.el-input__wrapper { background: #fff !important; box-shadow: 0 0 0 1px var(--rule2) !important; }
|
||||
.el-input__inner { color: var(--t1) !important; }
|
||||
.el-select-dropdown { background: var(--bg-2); border-color: var(--rule2); }
|
||||
.el-select-dropdown { background: #fff; border-color: var(--rule2); }
|
||||
.el-select-dropdown__item { color: var(--t2); }
|
||||
.el-select-dropdown__item.hover, .el-select-dropdown__item:hover { background: var(--bg-hi); }
|
||||
.el-select-dropdown__item.hover,
|
||||
.el-select-dropdown__item:hover { background: var(--bg-hover); }
|
||||
.el-table { --el-table-bg-color: #fff; --el-table-header-bg-color: var(--bg-2); }
|
||||
|
||||
@@ -1,94 +1,167 @@
|
||||
<template>
|
||||
<div class="reader-layout">
|
||||
<!-- ── 顶部导航 ─────────────────────────────────────────────────── -->
|
||||
<header class="topbar">
|
||||
<div class="topbar-left">
|
||||
<div class="logo-chip">PI</div>
|
||||
<span class="app-title">医药情报</span>
|
||||
</div>
|
||||
<div class="live-bar">
|
||||
<span class="live-dot"></span>
|
||||
<span>{{ selectedDate }} · 今日 {{ totalCount }} 条</span>
|
||||
</div>
|
||||
<div class="topbar-right">
|
||||
<router-link to="/admin" class="admin-link">管理后台 →</router-link>
|
||||
<div class="app">
|
||||
|
||||
<!-- ── Header ──────────────────────────────────────────────────── -->
|
||||
<header class="header">
|
||||
<div class="header-inner">
|
||||
<div class="hd-left">
|
||||
<div class="logo">
|
||||
<div class="logo-icon">PI</div>
|
||||
<span class="logo-text">医药情报</span>
|
||||
</div>
|
||||
<div class="hd-sep"></div>
|
||||
<nav class="tab-nav">
|
||||
<button
|
||||
v-for="tab in TABS"
|
||||
:key="tab.id"
|
||||
:class="['tab-btn', { active: activeTab === tab.id }]"
|
||||
@click="activeTab = tab.id"
|
||||
>{{ tab.label }}</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="hd-right">
|
||||
<div class="live-chip">
|
||||
<span class="live-dot"></span>
|
||||
<span class="live-text">{{ totalCount }} 条</span>
|
||||
</div>
|
||||
<select class="date-select" v-model="selectedDate" @change="loadDate(selectedDate)">
|
||||
<option v-for="d in archiveDates" :key="d.date" :value="d.date">
|
||||
{{ d.date }}
|
||||
</option>
|
||||
</select>
|
||||
<router-link to="/admin" class="admin-link">管理后台</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- ── 分类筛选 ─────────────────────────────────────────────────── -->
|
||||
<nav class="cat-nav">
|
||||
<button
|
||||
v-for="c in CATEGORIES"
|
||||
:key="c.value"
|
||||
:class="['cat-pill', { active: activeCategory === c.value }]"
|
||||
@click="setCategory(c.value)"
|
||||
>{{ c.label }}</button>
|
||||
</nav>
|
||||
<!-- ── Main ────────────────────────────────────────────────────── -->
|
||||
<main class="main">
|
||||
|
||||
<!-- ── 主内容区 ─────────────────────────────────────────────────── -->
|
||||
<div class="main-content">
|
||||
<TopTenPanel
|
||||
:items="featuredNews"
|
||||
:dates="archiveDates"
|
||||
:active-id="selectedNews?.id"
|
||||
:selected-date="selectedDate"
|
||||
@select="openDetail"
|
||||
@date-change="loadDate"
|
||||
/>
|
||||
|
||||
<div class="news-feed">
|
||||
<div v-if="loading" class="feed-state">
|
||||
<div class="spinner"></div>
|
||||
<span>加载中...</span>
|
||||
<!-- 精选 -->
|
||||
<div v-show="activeTab === 'featured'" class="tab-content">
|
||||
<div v-if="loading" class="state-msg"><div class="spinner"></div>加载中...</div>
|
||||
<div v-else-if="featuredNews.length === 0" class="state-msg">
|
||||
今日暂无精选,请在管理后台触发抓取
|
||||
</div>
|
||||
<template v-else-if="newsList.length">
|
||||
<NewsCard
|
||||
v-for="n in newsList"
|
||||
<div v-else class="featured-grid">
|
||||
<article
|
||||
v-for="(n, i) in featuredNews"
|
||||
:key="n.id"
|
||||
:news="n"
|
||||
@open="openDetail"
|
||||
/>
|
||||
<div v-if="hasMore" class="load-more" @click="loadMore">加载更多</div>
|
||||
</template>
|
||||
<div v-else class="feed-state">今日暂无数据,请先在管理后台触发抓取</div>
|
||||
:class="['fc-card', { 'fc-hero': i === 0 }]"
|
||||
@click="openDetail(n)"
|
||||
>
|
||||
<div class="fc-top">
|
||||
<span class="fc-rank">{{ String(i + 1).padStart(2, '0') }}</span>
|
||||
<span class="score-badge" :class="badgeClass(n.importance_score)">
|
||||
{{ n.importance_score?.toFixed(1) }}
|
||||
</span>
|
||||
<span class="fc-cat">{{ n.category }}</span>
|
||||
<span class="fc-source">{{ n.source_name }}</span>
|
||||
</div>
|
||||
<h3 class="fc-title">{{ n.title_zh }}</h3>
|
||||
<p class="fc-summary">{{ n.summary }}</p>
|
||||
<div class="fc-footer">
|
||||
<div class="fc-kws">
|
||||
<span v-for="kw in (n.keywords || []).slice(0, 3)" :key="kw" class="kw-chip">{{ kw }}</span>
|
||||
</div>
|
||||
<a :href="n.source_url" target="_blank" @click.stop class="fc-link">原文 →</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── 详情面板 ─────────────────────────────────────────────────── -->
|
||||
<!-- 全部动态 -->
|
||||
<div v-show="activeTab === 'all'" class="tab-content">
|
||||
<nav class="cat-bar">
|
||||
<button
|
||||
v-for="c in CATEGORIES"
|
||||
:key="c.value"
|
||||
:class="['cat-pill', { active: activeCategory === c.value }]"
|
||||
@click="setCategory(c.value)"
|
||||
>{{ c.label }}</button>
|
||||
</nav>
|
||||
<div v-if="loading" class="state-msg"><div class="spinner"></div>加载中...</div>
|
||||
<div v-else-if="newsList.length === 0" class="state-msg">
|
||||
今日暂无数据,请在管理后台触发抓取
|
||||
</div>
|
||||
<template v-else>
|
||||
<div class="news-list">
|
||||
<NewsCard v-for="n in newsList" :key="n.id" :news="n" @open="openDetail" />
|
||||
</div>
|
||||
<button v-if="hasMore" class="load-more-btn" @click="loadMore">加载更多</button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- AI日报 -->
|
||||
<div v-show="activeTab === 'digest'" class="tab-content">
|
||||
<div class="digest-hd">
|
||||
<div class="digest-date">{{ selectedDate }}</div>
|
||||
<h1 class="digest-title">医药情报 · AI日报</h1>
|
||||
<p class="digest-sub">
|
||||
今日处理 <strong>{{ totalCount }}</strong> 条资讯,
|
||||
精选 <strong>{{ featuredNews.length }}</strong> 条要闻
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="featuredNews.length === 0" class="state-msg">
|
||||
今日暂无精选,请在管理后台触发抓取
|
||||
</div>
|
||||
<div v-else class="digest-list">
|
||||
<article
|
||||
v-for="(n, i) in featuredNews"
|
||||
:key="n.id"
|
||||
class="digest-entry"
|
||||
@click="openDetail(n)"
|
||||
>
|
||||
<div class="de-meta">
|
||||
<span class="de-num">{{ String(i + 1).padStart(2, '0') }}</span>
|
||||
<span class="score-badge" :class="badgeClass(n.importance_score)">
|
||||
{{ n.importance_score?.toFixed(1) }}
|
||||
</span>
|
||||
<span class="de-cat">{{ n.category }}</span>
|
||||
<span class="de-source">{{ n.source_name }} · {{ n.published_at?.slice(0, 10) }}</span>
|
||||
</div>
|
||||
<h3 class="de-title">{{ n.title_zh }}</h3>
|
||||
<p class="de-summary">{{ n.summary }}</p>
|
||||
<div v-if="n.opinion" class="de-opinion">
|
||||
<span class="de-op-label">◆ 核心观点</span>
|
||||
<span>{{ n.opinion }}</span>
|
||||
</div>
|
||||
<a :href="n.source_url" target="_blank" @click.stop class="de-link">查看原文 →</a>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- ── Detail sheet ─────────────────────────────────────────────── -->
|
||||
<Transition name="sheet">
|
||||
<div v-if="selectedNews" class="sheet-bg" @click.self="selectedNews = null">
|
||||
<div class="sheet">
|
||||
<div class="sheet-handle" @click="selectedNews = null"></div>
|
||||
<div class="sheet-inner">
|
||||
<div class="sheet-head">
|
||||
<div class="sheet-hd">
|
||||
<div class="sh-tags">
|
||||
<span class="kw-tag cat-tag">{{ selectedNews.category }}</span>
|
||||
<span class="cat-chip">{{ selectedNews.category }}</span>
|
||||
<span class="score-badge" :class="badgeClass(selectedNews.importance_score)">
|
||||
{{ selectedNews.importance_score?.toFixed(1) }}
|
||||
</span>
|
||||
</div>
|
||||
<h2 class="sh-title">{{ selectedNews.title_zh }}</h2>
|
||||
<div class="sh-meta">
|
||||
{{ selectedNews.source_name }} · {{ selectedNews.published_at?.slice(0, 10) }}
|
||||
</div>
|
||||
<p class="sh-meta">{{ selectedNews.source_name }} · {{ selectedNews.published_at?.slice(0, 10) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="sheet-body">
|
||||
<div class="sheet-bd">
|
||||
<p class="sh-summary">{{ selectedNews.summary }}</p>
|
||||
|
||||
<div v-if="selectedNews.opinion" class="sh-block sh-blue">
|
||||
<b>核心观点</b>{{ selectedNews.opinion }}
|
||||
</div>
|
||||
|
||||
<div v-if="selectedNews.importance_reason" class="sh-block sh-mint">
|
||||
<div v-if="selectedNews.importance_reason" class="sh-block sh-green">
|
||||
<b>评分依据 · {{ selectedNews.importance_score?.toFixed(1) }} 分</b>
|
||||
{{ selectedNews.importance_reason }}
|
||||
</div>
|
||||
|
||||
<div v-if="selectedNews.keywords?.length" class="sh-kw">
|
||||
<span v-for="kw in selectedNews.keywords" :key="kw" class="kw-tag">{{ kw }}</span>
|
||||
<div v-if="selectedNews.keywords?.length" class="sh-kws">
|
||||
<span v-for="kw in selectedNews.keywords" :key="kw" class="kw-chip">{{ kw }}</span>
|
||||
</div>
|
||||
|
||||
<div class="sh-actions">
|
||||
<a :href="selectedNews.source_url" target="_blank" class="btn-primary">查看原文 →</a>
|
||||
<button class="btn-secondary" @click="selectedNews = null">关闭</button>
|
||||
@@ -98,33 +171,40 @@
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import NewsCard from '../components/NewsCard.vue'
|
||||
import TopTenPanel from '../components/TopTenPanel.vue'
|
||||
import { fetchFeatured, fetchNews, fetchDates } from '../api/index.js'
|
||||
|
||||
const TABS = [
|
||||
{ id: 'featured', label: '精选' },
|
||||
{ id: 'all', label: '全部动态' },
|
||||
{ id: 'digest', label: 'AI日报' },
|
||||
]
|
||||
|
||||
const CATEGORIES = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '药品监管', value: '药品监管' },
|
||||
{ label: '临床研究', value: '临床研究' },
|
||||
{ label: '行业动态', value: '行业动态' },
|
||||
{ label: '政策法规', value: '政策法规' },
|
||||
]
|
||||
|
||||
const selectedDate = ref(new Date().toISOString().slice(0, 10))
|
||||
const activeTab = ref('featured')
|
||||
const selectedDate = ref(new Date().toISOString().slice(0, 10))
|
||||
const activeCategory = ref('')
|
||||
const featuredNews = ref([])
|
||||
const newsList = ref([])
|
||||
const archiveDates = ref([])
|
||||
const loading = ref(false)
|
||||
const page = ref(1)
|
||||
const totalCount = ref(0)
|
||||
const hasMore = ref(false)
|
||||
const selectedNews = ref(null)
|
||||
const featuredNews = ref([])
|
||||
const newsList = ref([])
|
||||
const archiveDates = ref([])
|
||||
const loading = ref(false)
|
||||
const page = ref(1)
|
||||
const totalCount = ref(0)
|
||||
const hasMore = ref(false)
|
||||
const selectedNews = ref(null)
|
||||
|
||||
function badgeClass(score) {
|
||||
if (score >= 9) return 'badge-red'
|
||||
@@ -142,11 +222,14 @@ async function loadAll(date) {
|
||||
fetchDates(),
|
||||
])
|
||||
featuredNews.value = feat.items || []
|
||||
newsList.value = list.items || []
|
||||
totalCount.value = list.total || 0
|
||||
hasMore.value = list.items?.length < list.total
|
||||
newsList.value = list.items || []
|
||||
totalCount.value = list.total || 0
|
||||
hasMore.value = (list.items?.length || 0) < (list.total || 0)
|
||||
page.value = 1
|
||||
archiveDates.value = dates || []
|
||||
page.value = 1
|
||||
if (!archiveDates.value.find(d => d.date === date)) {
|
||||
archiveDates.value = [{ date, count: list.total || 0 }, ...archiveDates.value]
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -162,10 +245,10 @@ async function setCategory(cat) {
|
||||
loading.value = true
|
||||
try {
|
||||
const list = await fetchNews({ date: selectedDate.value, category: cat, page: 1 })
|
||||
newsList.value = list.items || []
|
||||
newsList.value = list.items || []
|
||||
totalCount.value = list.total || 0
|
||||
hasMore.value = list.items?.length < list.total
|
||||
page.value = 1
|
||||
hasMore.value = (list.items?.length || 0) < (list.total || 0)
|
||||
page.value = 1
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -178,13 +261,12 @@ async function loadMore() {
|
||||
hasMore.value = newsList.value.length < list.total
|
||||
}
|
||||
|
||||
function openDetail(news) {
|
||||
selectedNews.value = news
|
||||
}
|
||||
function openDetail(news) { selectedNews.value = news }
|
||||
|
||||
function onKeyDown(e) {
|
||||
if (e.key === 'Escape' && selectedNews.value) selectedNews.value = null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadAll(selectedDate.value)
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
@@ -193,213 +275,306 @@ onUnmounted(() => window.removeEventListener('keydown', onKeyDown))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.reader-layout {
|
||||
.app {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
/* ── Topbar ─────────────────────────────────────────────────────────────────── */
|
||||
.topbar {
|
||||
/* ── Header ─────────────────────────────────────────────────────── */
|
||||
.header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
height: 56px;
|
||||
background: rgba(7,9,26,.95);
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
background: #fff;
|
||||
border-bottom: 1px solid var(--rule2);
|
||||
box-shadow: 0 1px 0 var(--rule);
|
||||
}
|
||||
.header-inner {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 24px;
|
||||
gap: 16px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.topbar-left { display: flex; align-items: center; gap: 10px; }
|
||||
.logo-chip {
|
||||
width: 30px; height: 30px;
|
||||
background: linear-gradient(135deg, var(--blue), var(--violet));
|
||||
.hd-left { display: flex; align-items: center; }
|
||||
.logo { display: flex; align-items: center; gap: 8px; margin-right: 20px; }
|
||||
.logo-icon {
|
||||
width: 32px; height: 32px;
|
||||
background: linear-gradient(135deg, #2563eb, #7c3aed);
|
||||
border-radius: 8px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-family: var(--mono); font-size: 11px; font-weight: 700; color: #fff;
|
||||
font-size: 11px; font-weight: 700; color: #fff;
|
||||
font-family: var(--mono);
|
||||
}
|
||||
.app-title { font-size: 16px; font-weight: 700; letter-spacing: -.02em; }
|
||||
.live-bar {
|
||||
flex: 1;
|
||||
display: flex; align-items: center; gap: 6px; justify-content: center;
|
||||
font-size: 12px; color: var(--t4); font-family: var(--mono);
|
||||
.logo-text { font-size: 16px; font-weight: 700; color: var(--t1); letter-spacing: -0.02em; }
|
||||
.hd-sep { width: 1px; height: 20px; background: var(--rule2); margin: 0 16px; }
|
||||
|
||||
.tab-nav { display: flex; gap: 0; }
|
||||
.tab-btn {
|
||||
padding: 8px 18px;
|
||||
font-size: 14px; font-weight: 500;
|
||||
color: var(--t3);
|
||||
border-bottom: 2px solid transparent;
|
||||
border-radius: 0;
|
||||
transition: all 0.15s;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.tab-btn:hover { color: var(--t1); }
|
||||
.tab-btn.active { color: var(--blue); border-bottom-color: var(--blue); font-weight: 600; }
|
||||
|
||||
.hd-right { display: flex; align-items: center; gap: 12px; }
|
||||
.live-chip {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
padding: 4px 10px;
|
||||
background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: var(--r-pill);
|
||||
}
|
||||
.live-dot {
|
||||
width: 6px; height: 6px; border-radius: 50%; background: var(--mint);
|
||||
box-shadow: 0 0 0 0 rgba(37,214,163,.4);
|
||||
width: 6px; height: 6px; border-radius: 50%; background: #10b981;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(37,214,163,.4); }
|
||||
70% { box-shadow: 0 0 0 6px rgba(37,214,163,0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(37,214,163,0); }
|
||||
0%, 100% { box-shadow: 0 0 0 0 rgba(16,185,129,0.4); }
|
||||
50% { box-shadow: 0 0 0 5px rgba(16,185,129,0); }
|
||||
}
|
||||
.live-text { font-size: 12px; color: #059669; font-weight: 500; }
|
||||
.date-select {
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--rule2); border-radius: var(--r-sm);
|
||||
font-size: 13px; color: var(--t2); background: #fff; cursor: pointer;
|
||||
}
|
||||
.topbar-right { display: flex; align-items: center; }
|
||||
.admin-link {
|
||||
font-size: 12px; color: var(--blue-2); font-family: var(--mono);
|
||||
padding: 5px 12px; border: 1px solid var(--blue-bd); border-radius: var(--r-pill);
|
||||
transition: background .15s;
|
||||
font-size: 13px; color: var(--t3);
|
||||
padding: 6px 14px;
|
||||
border: 1px solid var(--rule2); border-radius: var(--r-sm);
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.admin-link:hover { background: var(--blue-gl); }
|
||||
.admin-link:hover { color: var(--t1); border-color: var(--t4); }
|
||||
|
||||
/* ── Category nav ────────────────────────────────────────────────────────────── */
|
||||
.cat-nav {
|
||||
position: sticky;
|
||||
top: 56px;
|
||||
z-index: 99;
|
||||
background: rgba(7,9,26,.92);
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
padding: 10px 24px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.cat-nav::-webkit-scrollbar { display: none; }
|
||||
.cat-pill {
|
||||
flex-shrink: 0;
|
||||
padding: 5px 14px;
|
||||
border-radius: var(--r-pill);
|
||||
border: 1px solid var(--rule2);
|
||||
background: var(--bg-2);
|
||||
color: var(--t3);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
transition: all .15s;
|
||||
}
|
||||
.cat-pill:hover { color: var(--t2); border-color: var(--rule2); }
|
||||
.cat-pill.active { background: var(--blue-gl); border-color: var(--blue-bd); color: var(--blue-2); }
|
||||
|
||||
/* ── Main layout ─────────────────────────────────────────────────────────────── */
|
||||
.main-content {
|
||||
/* ── Main ────────────────────────────────────────────────────────── */
|
||||
.main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 20px 24px;
|
||||
max-width: 1400px;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.news-feed { flex: 1; min-width: 0; }
|
||||
|
||||
.feed-state {
|
||||
.tab-content { width: 100%; }
|
||||
.state-msg {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 40px 0; color: var(--t4); font-size: 13px;
|
||||
padding: 80px 0; color: var(--t4); font-size: 14px; justify-content: center;
|
||||
}
|
||||
.spinner {
|
||||
width: 16px; height: 16px; border-radius: 50%;
|
||||
border: 2px solid var(--rule2); border-top-color: var(--blue-2);
|
||||
animation: spin .8s linear infinite;
|
||||
width: 16px; height: 16px;
|
||||
border: 2px solid var(--rule2); border-top-color: var(--blue);
|
||||
border-radius: 50%; animation: spin 0.8s linear infinite;
|
||||
}
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
.load-more {
|
||||
text-align: center; padding: 16px;
|
||||
font-size: 13px; color: var(--blue-2);
|
||||
cursor: pointer; border: 1px dashed var(--blue-bd);
|
||||
border-radius: var(--r); transition: background .15s;
|
||||
/* ── Score badges ──────────────────────────────────────────────── */
|
||||
.score-badge {
|
||||
padding: 2px 7px; border-radius: 5px;
|
||||
font-family: var(--mono); font-size: 11px; font-weight: 700; flex-shrink: 0;
|
||||
}
|
||||
.load-more:hover { background: var(--blue-gl); }
|
||||
.badge-red { background: #fef2f2; color: #dc2626; }
|
||||
.badge-amber { background: #fffbeb; color: #d97706; }
|
||||
.badge-blue { background: #eff6ff; color: #2563eb; }
|
||||
.badge-gray { background: #f9fafb; color: #6b7280; }
|
||||
|
||||
/* ── Detail sheet ────────────────────────────────────────────────────────────── */
|
||||
/* ── KW chips ──────────────────────────────────────────────────── */
|
||||
.kw-chip {
|
||||
font-size: 11px; font-family: var(--mono);
|
||||
padding: 2px 8px; border-radius: 4px;
|
||||
background: #eff6ff; color: #3b82f6; white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ── 精选 ────────────────────────────────────────────────────────── */
|
||||
.featured-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.fc-card {
|
||||
background: #fff; border: 1px solid var(--rule2); border-radius: var(--r);
|
||||
padding: 20px; cursor: pointer;
|
||||
transition: all 0.15s; box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.fc-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow); border-color: var(--blue-bd);
|
||||
}
|
||||
.fc-hero { grid-column: 1 / -1; border-left: 3px solid var(--blue); }
|
||||
.fc-hero .fc-title { font-size: 20px; }
|
||||
.fc-hero .fc-summary { -webkit-line-clamp: 4; }
|
||||
|
||||
.fc-top { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
|
||||
.fc-rank { font-family: var(--mono); font-size: 13px; font-weight: 700; color: var(--blue); min-width: 22px; }
|
||||
.fc-cat { font-size: 12px; color: var(--t3); }
|
||||
.fc-source { font-size: 11px; color: var(--t4); font-family: var(--mono); margin-left: auto; }
|
||||
|
||||
.fc-title {
|
||||
font-size: 16px; font-weight: 600; color: var(--t1);
|
||||
line-height: 1.45; margin-bottom: 8px;
|
||||
}
|
||||
.fc-summary {
|
||||
font-size: 13px; color: var(--t3); line-height: 1.65; margin-bottom: 14px;
|
||||
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
|
||||
}
|
||||
.fc-footer { display: flex; align-items: center; gap: 8px; }
|
||||
.fc-kws { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; }
|
||||
.fc-link { font-size: 12px; color: var(--blue); white-space: nowrap; transition: color 0.15s; }
|
||||
.fc-link:hover { color: #1d4ed8; }
|
||||
|
||||
/* ── 全部动态 ────────────────────────────────────────────────────── */
|
||||
.cat-bar { display: flex; gap: 8px; padding: 0 0 20px; flex-wrap: wrap; }
|
||||
.cat-pill {
|
||||
padding: 6px 16px; border-radius: var(--r-pill);
|
||||
border: 1px solid var(--rule2); background: #fff;
|
||||
color: var(--t3); font-size: 13px; font-weight: 500; transition: all 0.15s;
|
||||
}
|
||||
.cat-pill:hover { border-color: var(--blue-bd); color: var(--blue); }
|
||||
.cat-pill.active { background: var(--blue); border-color: var(--blue); color: #fff; }
|
||||
|
||||
.news-list { display: flex; flex-direction: column; gap: 10px; }
|
||||
.load-more-btn {
|
||||
width: 100%; margin-top: 12px; padding: 14px;
|
||||
border: 1px dashed var(--rule2); border-radius: var(--r);
|
||||
background: transparent; color: var(--blue);
|
||||
font-size: 13px; font-weight: 500; transition: all 0.15s;
|
||||
}
|
||||
.load-more-btn:hover { background: var(--blue-gl); border-color: var(--blue-bd); }
|
||||
|
||||
/* ── AI日报 ──────────────────────────────────────────────────────── */
|
||||
.digest-hd {
|
||||
text-align: center;
|
||||
padding: 40px 0 36px;
|
||||
border-bottom: 2px solid var(--rule2);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.digest-date {
|
||||
font-family: var(--mono); font-size: 12px; color: var(--t4);
|
||||
margin-bottom: 10px; letter-spacing: 0.1em;
|
||||
}
|
||||
.digest-title {
|
||||
font-size: 28px; font-weight: 700; color: var(--t1);
|
||||
margin-bottom: 10px; letter-spacing: -0.02em;
|
||||
}
|
||||
.digest-sub { font-size: 14px; color: var(--t3); line-height: 1.5; }
|
||||
.digest-sub strong { color: var(--blue); }
|
||||
|
||||
.digest-list { display: flex; flex-direction: column; }
|
||||
.digest-entry {
|
||||
padding: 28px 0;
|
||||
border-bottom: 1px solid var(--rule2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.digest-entry:last-child { border-bottom: none; }
|
||||
.digest-entry:hover .de-title { color: var(--blue); }
|
||||
|
||||
.de-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
|
||||
.de-num { font-family: var(--mono); font-size: 22px; font-weight: 700; color: var(--rule2); min-width: 32px; }
|
||||
.de-cat { font-size: 12px; color: var(--t3); }
|
||||
.de-source { font-size: 12px; color: var(--t4); font-family: var(--mono); margin-left: auto; }
|
||||
|
||||
.de-title {
|
||||
font-size: 18px; font-weight: 700; color: var(--t1);
|
||||
line-height: 1.4; margin-bottom: 10px; transition: color 0.15s;
|
||||
}
|
||||
.de-summary {
|
||||
font-size: 14px; color: var(--t2); line-height: 1.7; margin-bottom: 12px;
|
||||
}
|
||||
.de-opinion {
|
||||
display: flex; gap: 10px;
|
||||
background: #eff6ff; border-left: 3px solid var(--blue);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 10px 14px; margin-bottom: 14px;
|
||||
font-size: 13px; color: var(--t2); line-height: 1.6;
|
||||
}
|
||||
.de-op-label { color: var(--blue); font-weight: 600; white-space: nowrap; flex-shrink: 0; }
|
||||
.de-link {
|
||||
display: inline-block;
|
||||
font-size: 13px; color: var(--blue); font-weight: 500; transition: color 0.15s;
|
||||
}
|
||||
.de-link:hover { color: #1d4ed8; }
|
||||
|
||||
/* ── Detail sheet ───────────────────────────────────────────────── */
|
||||
.sheet-bg {
|
||||
position: fixed; inset: 0;
|
||||
background: rgba(0,0,0,.6);
|
||||
backdrop-filter: blur(4px);
|
||||
z-index: 200;
|
||||
display: flex; align-items: flex-end; justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.4); backdrop-filter: blur(4px);
|
||||
z-index: 200; display: flex; align-items: flex-end; justify-content: center;
|
||||
}
|
||||
.sheet {
|
||||
width: 100%; max-width: 680px;
|
||||
background: var(--bg-1);
|
||||
border-radius: 20px 20px 0 0;
|
||||
background: #fff; border-radius: 20px 20px 0 0;
|
||||
border-top: 1px solid var(--rule2);
|
||||
max-height: 85vh;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none;
|
||||
max-height: 88vh; overflow-y: auto; scrollbar-width: none;
|
||||
}
|
||||
.sheet::-webkit-scrollbar { display: none; }
|
||||
.sheet-handle {
|
||||
width: 36px; height: 4px; background: var(--rule2); border-radius: 2px;
|
||||
margin: 10px auto 0; cursor: pointer;
|
||||
width: 36px; height: 4px; background: var(--rule2);
|
||||
border-radius: 2px; margin: 12px auto 0; cursor: pointer;
|
||||
}
|
||||
.sheet-inner { padding: 8px 0 40px; }
|
||||
|
||||
.sheet-head { padding: 12px 24px 16px; }
|
||||
.sh-tags { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
|
||||
.cat-tag { background: rgba(122,128,160,.15); color: var(--t3); }
|
||||
.score-badge {
|
||||
padding: 2px 8px; border-radius: 5px;
|
||||
font-family: var(--mono); font-size: 11px; font-weight: 700;
|
||||
.sheet-inner { padding: 8px 0 48px; }
|
||||
.sheet-hd { padding: 14px 24px 16px; }
|
||||
.sh-tags { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
|
||||
.cat-chip {
|
||||
font-size: 12px; padding: 3px 10px;
|
||||
border-radius: var(--r-pill); background: #f3f4f6; color: var(--t3);
|
||||
}
|
||||
.badge-red { background: rgba(255,77,106,.2); color: var(--red); }
|
||||
.badge-amber { background: rgba(255,163,54,.2); color: var(--amber); }
|
||||
.badge-blue { background: rgba(46,85,245,.2); color: var(--blue-2); }
|
||||
.badge-gray { background: rgba(122,128,160,.15); color: var(--t3); }
|
||||
|
||||
.sh-title { font-size: 18px; font-weight: 700; color: var(--t1); line-height: 1.4; margin-bottom: 6px; }
|
||||
.sh-meta { font-size: 11px; color: var(--t4); font-family: var(--mono); }
|
||||
|
||||
.sheet-body { padding: 0 24px; }
|
||||
.sh-summary { font-size: 14px; color: var(--t2); line-height: 1.7; margin-bottom: 14px; }
|
||||
.sh-title {
|
||||
font-size: 20px; font-weight: 700; color: var(--t1);
|
||||
line-height: 1.4; margin-bottom: 6px;
|
||||
}
|
||||
.sh-meta { font-size: 12px; color: var(--t4); font-family: var(--mono); }
|
||||
|
||||
.sheet-bd { padding: 0 24px; }
|
||||
.sh-summary { font-size: 14px; color: var(--t2); line-height: 1.7; margin-bottom: 16px; }
|
||||
.sh-block {
|
||||
border-radius: 0 var(--r-sm) var(--r-sm) 0;
|
||||
padding: 10px 14px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
border-radius: 0 8px 8px 0; padding: 10px 14px;
|
||||
margin-bottom: 12px; font-size: 13px; line-height: 1.6;
|
||||
}
|
||||
.sh-blue { background: var(--blue-gl); border-left: 2px solid var(--blue-bd); color: #8AAAFF; }
|
||||
.sh-mint { background: rgba(37,214,163,.06); border-left: 2px solid rgba(37,214,163,.4); color: rgba(37,214,163,.85); }
|
||||
.sh-blue { background: #eff6ff; border-left: 2px solid var(--blue); color: var(--t2); }
|
||||
.sh-green { background: #f0fdf4; border-left: 2px solid #10b981; color: var(--t2); }
|
||||
.sh-block b {
|
||||
display: block; font-family: var(--mono); font-size: 10px;
|
||||
font-weight: 700; margin-bottom: 4px; opacity: .7; letter-spacing: .04em;
|
||||
display: block; font-family: var(--mono); font-size: 11px; font-weight: 700;
|
||||
margin-bottom: 4px; letter-spacing: 0.04em; color: var(--t4);
|
||||
}
|
||||
|
||||
.sh-kw { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
|
||||
|
||||
.kw-tag {
|
||||
font-size: 10px; font-family: var(--mono);
|
||||
padding: 2px 7px; border-radius: 4px;
|
||||
background: rgba(46,85,245,.15); color: #7B9BFF;
|
||||
}
|
||||
|
||||
.sh-kws { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 18px; }
|
||||
.sh-actions { display: flex; gap: 10px; }
|
||||
|
||||
.btn-primary {
|
||||
flex: 1; height: 42px; border-radius: 10px;
|
||||
flex: 1; height: 44px; border-radius: var(--r);
|
||||
background: var(--blue); color: #fff;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 13px; font-weight: 600;
|
||||
transition: background .15s;
|
||||
font-size: 14px; font-weight: 600; transition: background 0.15s;
|
||||
}
|
||||
.btn-primary:hover { background: var(--blue-2); }
|
||||
.btn-primary:hover { background: #1d4ed8; }
|
||||
.btn-secondary {
|
||||
flex: 1; height: 42px; border-radius: 10px;
|
||||
background: var(--bg-2); border: 1px solid var(--rule2); color: var(--t2);
|
||||
font-size: 13px; font-weight: 600;
|
||||
transition: background .15s;
|
||||
flex: 1; height: 44px; border-radius: var(--r);
|
||||
background: #f9fafb; border: 1px solid var(--rule2); color: var(--t2);
|
||||
font-size: 14px; font-weight: 600; transition: background 0.15s;
|
||||
}
|
||||
.btn-secondary:hover { background: var(--bg-hi); }
|
||||
.btn-secondary:hover { background: #f3f4f6; }
|
||||
|
||||
/* ── Transitions ─────────────────────────────────────────────────────────────── */
|
||||
.sheet-enter-active, .sheet-leave-active { transition: opacity .25s; }
|
||||
.sheet-enter-active .sheet, .sheet-leave-active .sheet { transition: transform .3s cubic-bezier(.32,.72,0,1); }
|
||||
/* ── Transitions ─────────────────────────────────────────────────── */
|
||||
.sheet-enter-active, .sheet-leave-active { transition: opacity 0.25s; }
|
||||
.sheet-enter-active .sheet,
|
||||
.sheet-leave-active .sheet { transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); }
|
||||
.sheet-enter-from, .sheet-leave-to { opacity: 0; }
|
||||
.sheet-enter-from .sheet, .sheet-leave-to .sheet { transform: translateY(100%); }
|
||||
|
||||
/* ── Mobile ──────────────────────────────────────────────────────────────────── */
|
||||
/* ── Mobile ──────────────────────────────────────────────────────── */
|
||||
@media (max-width: 768px) {
|
||||
.main-content { padding: 12px 16px; gap: 0; }
|
||||
/* TopTenPanel becomes horizontally scrollable on mobile — handled in component */
|
||||
.topbar { padding: 0 16px; }
|
||||
.cat-nav { padding: 8px 16px; }
|
||||
.live-bar { display: none; }
|
||||
.header-inner { padding: 0 16px; }
|
||||
.hd-sep, .logo-text { display: none; }
|
||||
.live-chip { display: none; }
|
||||
.main { padding: 16px; }
|
||||
.featured-grid { grid-template-columns: 1fr; }
|
||||
.fc-hero { grid-column: auto; }
|
||||
.digest-title { font-size: 22px; }
|
||||
.de-source { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user