From 0ee14678b6b063d4ed7b772bcd25575319c6c9d7 Mon Sep 17 00:00:00 2001 From: liu <2302563948@qq.com> Date: Wed, 1 Jul 2026 21:05:42 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 55 +++++ src/app.less | 3 +- .../ArticleCard/ImageGridCard/index.less | 47 +++++ .../ArticleCard/ImageGridCard/index.tsx | 32 +++ .../ArticleCard/ImageTextCard/index.less | 63 ++++++ .../ArticleCard/ImageTextCard/index.tsx | 28 +++ .../ArticleCard/TextCard/index.less | 44 ++++ src/components/ArticleCard/TextCard/index.tsx | 21 ++ src/components/ArticleCard/index.tsx | 23 +++ src/mock/articles.ts | 168 ++++++++++++++++ src/pages/index/index.config.ts | 6 +- src/pages/index/index.less | 146 ++++++++++++++ src/pages/index/index.tsx | 188 +++++++++++++++--- src/types/article.ts | 34 ++++ tsconfig.json | 3 + 15 files changed, 831 insertions(+), 30 deletions(-) create mode 100644 src/components/ArticleCard/ImageGridCard/index.less create mode 100644 src/components/ArticleCard/ImageGridCard/index.tsx create mode 100644 src/components/ArticleCard/ImageTextCard/index.less create mode 100644 src/components/ArticleCard/ImageTextCard/index.tsx create mode 100644 src/components/ArticleCard/TextCard/index.less create mode 100644 src/components/ArticleCard/TextCard/index.tsx create mode 100644 src/components/ArticleCard/index.tsx create mode 100644 src/mock/articles.ts create mode 100644 src/types/article.ts diff --git a/CLAUDE.md b/CLAUDE.md index 16506c2..89bbac6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -72,3 +72,58 @@ Pages must be registered in `src/app.config.ts` under the `pages` array. - `src/app.ts` — class-based App component, renders `this.props.children` (the current page) - `src/app.config.ts` — defines routes (`pages` array), window config, and app-level settings - `src/index.html` — H5 entry HTML template + +## VantUI Component API Reference (v3.7) + +This project uses `@antmjs/vantui` v3.7. The official docs: https://antmjs.github.io/vantui/main/ + +**Always check the actual type definitions** in `node_modules/@antmjs/vantui/types/` when unsure about props. Key API notes for commonly used components: + +### Search +- `shape`: `'square'` (default) | `'round'` +- `background`: background color string (default `#FFFFFF`) +- `onFocus`, `onBlur`, `onChange`, `onSearch`, `onClear`, `onCancel` — event callbacks +- `leftIcon`, `rightIcon` — icon name or image URL +- `showAction` + `actionText` — right-side action button + +### Swiper (NOT the same as Taro's native Swiper) +- `autoPlay` — auto-play interval in ms (0 = disabled). **Not** `autoplay` +- `loop` — infinite loop mode. **Not** `circular` +- `paginationColor` — indicator dot color. **Not** `indicatorColor` +- `paginationVisible` — show/hide pagination dots +- `duration` — animation duration (default 500) +- `width` / `height` — card dimensions +- **No** `indicatorActiveColor` prop — only one `paginationColor` +- `onChange` callback: `(currPage: number) => void` (not an event object) + +### SwiperItem +- Minimal component, only `className` and `children`. No special props. + +### Grid / GridItem +- `Grid`: `columnNum`, `border`, `gutter`, `square`, `clickable`, `center`, `iconSize` +- `GridItem`: `icon` (string), `text` (ReactNode), `iconColor`, `dot`, `info`/`badge`, `url` + `linkType` + +### Tabs / Tab (v3.7) +- `Tabs`: + - `active` — current tab index (number | string) + - `sticky` — enable sticky mode + - `offsetTop` — sticky offset in px. **Not** `stickyOffsetTop` + - `color`, `titleActiveColor`, `titleInactiveColor` — color props + - `type`: `'line'` | `'card'` + - `swipeable` — enable swipe gesture switching + - `animated` — enable tab switch animation + - `ellipsis` — text overflow ellipsis (default true) + - **No** `lineWidth` or `lineHeight` props + - `onChange`: `(e: { detail: { index: number; name?: string; title?: string } }) => void` +- `Tab`: `title` (ReactNode), `name` (identifier), `dot`, `info`, `disabled`, `titleStyle` + +### Image (VantUI Image, not Taro's native Image) +- `src`, `fit` (`'contain' | 'cover' | 'fill' | 'widthFix' | 'heightFix' | 'none'`), `width`, `height`, `radius` +- `round` — circular image (boolean) +- `lazyLoad`, `showError`, `showLoading` +- `renderLoading`, `renderError` — custom render slots + +### Common VantUI pattern: Taro's native components vs VantUI components +- Use `@tarojs/components` for: `View`, `Text`, `ScrollView`, `Image` (native, simpler) +- Use `@antmjs/vantui` for: styled UI components (Search, Swiper, Tabs, Grid, Button, etc.) +- VantUI component props extend Taro's `ViewProps`, so `onClick`/`onTap` and style props are always available diff --git a/src/app.less b/src/app.less index 70defe9..fedbf94 100644 --- a/src/app.less +++ b/src/app.less @@ -1,7 +1,8 @@ +@import '@antmjs/vantui/es/style/var.less'; @import '@antmjs/vantui/lib/index.less'; page { - background: @pageBack; + background: @page-back; font-size: 28px; font-family: @base-font-family; color: @black; diff --git a/src/components/ArticleCard/ImageGridCard/index.less b/src/components/ArticleCard/ImageGridCard/index.less new file mode 100644 index 0000000..b8c6f92 --- /dev/null +++ b/src/components/ArticleCard/ImageGridCard/index.less @@ -0,0 +1,47 @@ +.image-grid-card { + .card-title { + font-size: 32px; + font-weight: 500; + color: #1a1a1a; + line-height: 1.4; + margin-bottom: 16px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-images { + display: flex; + flex-direction: row; + gap: 8px; + margin-bottom: 16px; + + .grid-image { + flex: 1; + height: 160px; + border-radius: 8px; + overflow: hidden; + } + } + + .card-meta { + display: flex; + align-items: center; + font-size: 24px; + color: #969799; + + .meta-source { + margin-right: 16px; + } + + .meta-time { + margin-right: 16px; + } + + .meta-read { + flex: 1; + text-align: right; + } + } +} diff --git a/src/components/ArticleCard/ImageGridCard/index.tsx b/src/components/ArticleCard/ImageGridCard/index.tsx new file mode 100644 index 0000000..79180a7 --- /dev/null +++ b/src/components/ArticleCard/ImageGridCard/index.tsx @@ -0,0 +1,32 @@ +import type { Article } from '@/types/article' +import { View, Text, Image } from '@tarojs/components' +import './index.less' + +interface ImageGridCardProps { + article: Article +} + +export default function ImageGridCard({ article }: ImageGridCardProps) { + const images = article.images.slice(0, 3) + + return ( + + {article.title} + + {images.map((img, index) => ( + + ))} + + + {article.source} + {article.time} + {article.readCount}阅读 + + + ) +} diff --git a/src/components/ArticleCard/ImageTextCard/index.less b/src/components/ArticleCard/ImageTextCard/index.less new file mode 100644 index 0000000..de4da7d --- /dev/null +++ b/src/components/ArticleCard/ImageTextCard/index.less @@ -0,0 +1,63 @@ +.image-text-card { + display: flex; + flex-direction: row; + + .card-thumb { + width: 200px; + height: 200px; + border-radius: 8px; + flex-shrink: 0; + margin-right: 20px; + } + + .card-body { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + } + + .card-title { + font-size: 32px; + font-weight: 500; + color: #1a1a1a; + line-height: 1.4; + margin-bottom: 8px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-excerpt { + font-size: 26px; + color: #646566; + line-height: 1.5; + flex: 1; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-meta { + display: flex; + align-items: center; + font-size: 24px; + color: #969799; + margin-top: 12px; + + .meta-source { + margin-right: 16px; + } + + .meta-time { + margin-right: 16px; + } + + .meta-read { + flex: 1; + text-align: right; + } + } +} diff --git a/src/components/ArticleCard/ImageTextCard/index.tsx b/src/components/ArticleCard/ImageTextCard/index.tsx new file mode 100644 index 0000000..b3ff249 --- /dev/null +++ b/src/components/ArticleCard/ImageTextCard/index.tsx @@ -0,0 +1,28 @@ +import type { Article } from '@/types/article' +import { View, Text, Image } from '@tarojs/components' +import './index.less' + +interface ImageTextCardProps { + article: Article +} + +export default function ImageTextCard({ article }: ImageTextCardProps) { + return ( + + + + {article.title} + {article.excerpt} + + {article.source} + {article.time} + {article.readCount}阅读 + + + + ) +} diff --git a/src/components/ArticleCard/TextCard/index.less b/src/components/ArticleCard/TextCard/index.less new file mode 100644 index 0000000..eb379a6 --- /dev/null +++ b/src/components/ArticleCard/TextCard/index.less @@ -0,0 +1,44 @@ +.text-card { + .card-title { + font-size: 32px; + font-weight: 500; + color: #1a1a1a; + line-height: 1.4; + margin-bottom: 12px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-excerpt { + font-size: 28px; + color: #646566; + line-height: 1.6; + margin-bottom: 16px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + } + + .card-meta { + display: flex; + align-items: center; + font-size: 24px; + color: #969799; + + .meta-source { + margin-right: 16px; + } + + .meta-time { + margin-right: 16px; + } + + .meta-read { + flex: 1; + text-align: right; + } + } +} diff --git a/src/components/ArticleCard/TextCard/index.tsx b/src/components/ArticleCard/TextCard/index.tsx new file mode 100644 index 0000000..1a1975d --- /dev/null +++ b/src/components/ArticleCard/TextCard/index.tsx @@ -0,0 +1,21 @@ +import type { Article } from '@/types/article' +import { View, Text } from '@tarojs/components' +import './index.less' + +interface TextCardProps { + article: Article +} + +export default function TextCard({ article }: TextCardProps) { + return ( + + {article.title} + {article.excerpt} + + {article.source} + {article.time} + {article.readCount}阅读 + + + ) +} diff --git a/src/components/ArticleCard/index.tsx b/src/components/ArticleCard/index.tsx new file mode 100644 index 0000000..e6f3c8d --- /dev/null +++ b/src/components/ArticleCard/index.tsx @@ -0,0 +1,23 @@ +import type { Article } from '@/types/article' +import TextCard from './TextCard' +import ImageTextCard from './ImageTextCard' +import ImageGridCard from './ImageGridCard' + +interface ArticleCardProps { + article: Article +} + +/** 根据文章 type 自动选择对应卡片组件 */ +export default function ArticleCard({ article }: ArticleCardProps) { + switch (article.type) { + case 'image-text': + return + case 'image-grid': + return + case 'text': + default: + return + } +} + +export { TextCard, ImageTextCard, ImageGridCard } diff --git a/src/mock/articles.ts b/src/mock/articles.ts new file mode 100644 index 0000000..47979c5 --- /dev/null +++ b/src/mock/articles.ts @@ -0,0 +1,168 @@ +import type { Article, BannerItem, NavItem } from '@/types/article' + +/** 轮播图数据 */ +export const banners: BannerItem[] = [ + { + id: '1', + image: 'https://picsum.photos/seed/banner1/750/350', + title: '校园新学期开学通知', + link: '', + }, + { + id: '2', + image: 'https://picsum.photos/seed/banner2/750/350', + title: '2024年度优秀学生表彰', + link: '', + }, + { + id: '3', + image: 'https://picsum.photos/seed/banner3/750/350', + title: '校园文化艺术节开幕', + link: '', + }, +] + +/** 导航组数据 (2行 x 5列 = 10项) */ +export const navItems: NavItem[] = [ + { id: '1', label: '课程表', icon: 'orders-o', path: '' }, + { id: '2', label: '通知公告', icon: 'bullhorn-o', path: '' }, + { id: '3', label: '成绩查询', icon: 'chart-trending-o', path: '' }, + { id: '4', label: '作业提交', icon: 'edit', path: '' }, + { id: '5', label: '考试安排', icon: 'description', path: '' }, + { id: '6', label: '校园活动', icon: 'friends-o', path: '' }, + { id: '7', label: '图书馆', icon: 'bookmark-o', path: '' }, + { id: '8', label: '一卡通', icon: 'credit-pay', path: '' }, + { id: '9', label: '校园地图', icon: 'map-marked', path: '' }, + { id: '10', label: '更多服务', icon: 'more-o', path: '' }, +] + +/** 文章模拟数据 */ +export const articles: Article[] = [ + // === 最新 (latest) === + { + id: '1', + title: '关于2024年秋季学期选课通知', + excerpt: '各位同学,2024年秋季学期选课将于8月25日上午10:00正式开始,请同学们提前查看培养方案,合理规划选课时间...', + source: '教务处', + time: '2小时前', + readCount: 1523, + images: [], + type: 'text', + category: 'latest', + }, + { + id: '2', + title: '校园道路施工临时封闭公告', + excerpt: '因校园管网改造工程需要,东门至图书馆路段将于8月20日至9月5日进行封闭施工...', + source: '后勤管理处', + time: '3小时前', + readCount: 892, + images: ['https://picsum.photos/seed/news2/200/200'], + type: 'image-text', + category: 'latest', + }, + { + id: '3', + title: '迎新志愿者招募启动,期待你的加入', + excerpt: '新的学期即将开始,为迎接2024级新生入学,现面向全校招募迎新志愿者...', + source: '学生工作部', + time: '5小时前', + readCount: 2341, + images: [ + 'https://picsum.photos/seed/vol1/200/200', + 'https://picsum.photos/seed/vol2/200/200', + 'https://picsum.photos/seed/vol3/200/200', + ], + type: 'image-grid', + category: 'latest', + }, + { + id: '4', + title: '关于调整校园班车运行时间的通知', + excerpt: '根据师生出行需求调研结果,自8月22日起,校园班车将调整早晚高峰时段发车频次...', + source: '后勤管理处', + time: '昨天', + readCount: 678, + images: [], + type: 'text', + category: 'latest', + }, + + // === 推荐 (recommend) === + { + id: '5', + title: '优秀学长分享:大学四年如何规划学习与生活', + excerpt: '来自计算机学院的张同学,GPA排名年级前5%,获得多项国家级竞赛奖项,他将分享自己的大学规划经验...', + source: '学工在线', + time: '1天前', + readCount: 4521, + images: ['https://picsum.photos/seed/share1/200/200'], + type: 'image-text', + category: 'recommend', + }, + { + id: '6', + title: '图书馆新书上架:2024年暑期推荐阅读书单', + excerpt: '图书馆最新上架图书2000余册,涵盖文学、历史、科技、艺术等多个领域,欢迎师生前来借阅...', + source: '图书馆', + time: '1天前', + readCount: 1892, + images: [ + 'https://picsum.photos/seed/book1/200/200', + 'https://picsum.photos/seed/book2/200/200', + 'https://picsum.photos/seed/book3/200/200', + ], + type: 'image-grid', + category: 'recommend', + }, + { + id: '7', + title: '考研经验交流会活动预告', + excerpt: '为帮助同学们更好地备战考研,学校将举办考研经验交流会,邀请2024届考研成功的学长学姐分享备考心得...', + source: '学生会', + time: '2天前', + readCount: 3156, + images: [], + type: 'text', + category: 'recommend', + }, + + // === 热点 (hot) === + { + id: '8', + title: '我校在2024年全国大学生数学建模竞赛中再创佳绩', + excerpt: '近日,2024年全国大学生数学建模竞赛结果揭晓,我校参赛队伍共获得国家一等奖3项、国家二等奖7项...', + source: '数学学院', + time: '1小时前', + readCount: 8934, + images: [ + 'https://picsum.photos/seed/award1/200/200', + 'https://picsum.photos/seed/award2/200/200', + 'https://picsum.photos/seed/award3/200/200', + ], + type: 'image-grid', + category: 'hot', + }, + { + id: '9', + title: '关于2024年国家奖学金评选结果的公示', + excerpt: '根据教育部相关文件精神,经学生个人申请、学院推荐、学校评审,现将2024年国家奖学金拟获奖名单予以公示...', + source: '学生工作部', + time: '3小时前', + readCount: 6789, + images: [], + type: 'text', + category: 'hot', + }, + { + id: '10', + title: '学校食堂推出新菜品,舌尖上的校园美食', + excerpt: '新学期伊始,学校各食堂纷纷推出新菜品,从川菜到粤菜、从面食到甜点,满足不同地域同学的口味需求...', + source: '后勤管理处', + time: '6小时前', + readCount: 5678, + images: ['https://picsum.photos/seed/food1/200/200'], + type: 'image-text', + category: 'hot', + }, +] diff --git a/src/pages/index/index.config.ts b/src/pages/index/index.config.ts index a2af952..577e9a9 100644 --- a/src/pages/index/index.config.ts +++ b/src/pages/index/index.config.ts @@ -1,3 +1,5 @@ export default definePageConfig({ - navigationBarTitleText: '首页' -}) \ No newline at end of file + navigationBarTitleText: '首页', + navigationStyle: 'custom', + enablePullDownRefresh: false, +}) diff --git a/src/pages/index/index.less b/src/pages/index/index.less index e69de29..5b5d25c 100644 --- a/src/pages/index/index.less +++ b/src/pages/index/index.less @@ -0,0 +1,146 @@ +/* ======================================== + 首页样式 + ======================================== */ + +.home-page { + min-height: 100vh; + background: #f7f8fa; +} + +/* ========== 自定义导航栏 (毛玻璃) ========== */ +.custom-navbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 999; + background: rgba(255, 255, 255, 0.72); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); +} + +.navbar-content { + display: flex; + align-items: center; + padding: 0 24px; + + .navbar-search { + flex: 1; + } +} + +/* ========== 滚动区域 ========== */ +.page-scroll { + height: 100vh; +} + +/* ========== 轮播图区域 ========== */ +.swiper-section { + padding: 20px 24px 0; + + .banner-swiper { + height: 320px; + border-radius: 12px; + overflow: hidden; + } + + .swiper-card { + position: relative; + width: 100%; + height: 100%; + border-radius: 12px; + overflow: hidden; + + .banner-image { + width: 100%; + height: 100%; + } + + .banner-title { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 24px 20px; + font-size: 30px; + font-weight: 500; + color: #fff; + background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.5) 100%); + border-radius: 0 0 12px 12px; + } + } +} + +/* ========== 导航组 ========== */ +.nav-section { + margin: 24px 24px; + background: #fff; + border-radius: 16px; + padding: 24px 12px 12px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04); +} + +/* ========== 标签区域 ========== */ +.tabs-section { + background: #fff; + border-radius: 16px; + overflow: hidden; + margin: 0 24px 20px; + + .van-tabs__wrap { + border-radius: 16px 16px 0 0; + } +} + +/* ========== 文章列表 ========== */ +.article-list { + padding: 0 24px; + + .article-item { + background: #fff; + border-radius: 16px; + padding: 24px; + margin-bottom: 16px; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04); + transition: transform 0.2s; + + &:active { + transform: scale(0.98); + } + } + + .empty-tip { + text-align: center; + padding: 80px 0; + font-size: 28px; + color: #969799; + } +} + +/* 底部安全距离 */ +.bottom-safe { + height: 40px; +} + +/* ========== 文章卡片通用样式 ========== */ +.article-card { + .card-meta { + display: flex; + align-items: center; + font-size: 24px; + color: #969799; + + .meta-source { + margin-right: 16px; + } + + .meta-time { + margin-right: 16px; + } + + .meta-read { + flex: 1; + text-align: right; + } + } +} diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index d7fa857..42d5f84 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -1,34 +1,168 @@ -import { View } from '@tarojs/components' -import { Button } from '@antmjs/vantui' +import { useState, useMemo } from 'react' +import Taro from '@tarojs/taro' +import { View, ScrollView } from '@tarojs/components' +import { Search, Swiper, SwiperItem, Grid, GridItem, Tabs, Tab, Image as VantImage } from '@antmjs/vantui' +import ArticleCard from '@/components/ArticleCard' +import { banners, navItems, articles } from '@/mock/articles' +import type { ArticleCategory } from '@/types/article' import './index.less' +/** 获取状态栏和导航栏高度 */ +function getNavBarHeight() { + const systemInfo = Taro.getSystemInfoSync() + const statusBarHeight = systemInfo.statusBarHeight || 20 + // 微信小程序导航栏高度一般为 44px,总高度 = 状态栏 + 导航栏 + const navBarHeight = 44 + return { + statusBarHeight, + navBarHeight, + totalHeight: statusBarHeight + navBarHeight, + } +} + +/** 分类标签映射 */ +const TAB_LIST = [ + { title: '最新', value: 'latest' as ArticleCategory }, + { title: '推荐', value: 'recommend' as ArticleCategory }, + { title: '热点', value: 'hot' as ArticleCategory }, +] + export default function Index() { + const [activeTab, setActiveTab] = useState(0) + const navBarHeight = useMemo(() => getNavBarHeight(), []) + + /** 根据当前 tab 筛选文章 */ + const filteredArticles = useMemo(() => { + const category = TAB_LIST[activeTab]?.value || 'latest' + return articles.filter((a) => a.category === category) + }, [activeTab]) + + /** 搜索 */ + const handleSearch = () => { + Taro.navigateTo({ url: '/pages/search/index' }) + } + + /** 导航项点击 */ + const handleNavClick = (item: { path: string; label: string }) => { + if (item.path) { + Taro.navigateTo({ url: item.path }) + } else { + Taro.showToast({ title: `${item.label}即将上线`, icon: 'none' }) + } + } + + /** 文章点击 */ + const handleArticleClick = (id: string) => { + Taro.navigateTo({ url: `/pages/article/index?id=${id}` }) + } + return ( - - - 上面的按钮的颜色已经通过全局主题重写覆盖了,参见src/styles/index.less + + {/* ========== 自定义导航栏 (毛玻璃) ========== */} + + + + + + + + + {/* 占位,补偿固定导航栏高度 */} + + + {/* ========== 可滚动内容区 ========== */} + + {/* ========== 卡片轮播图 ========== */} + + + {banners.map((banner) => ( + + + + {banner.title} + + + ))} + + + + {/* ========== 导航组 2行 x 5列 ========== */} + + + {navItems.map((item) => ( + handleNavClick(item)} + /> + ))} + + + + {/* ========== 文章标签导航 (最新 / 推荐 / 热点) ========== */} + + setActiveTab(e.detail.index)} + sticky + offsetTop={navBarHeight.totalHeight} + color='#1989fa' + titleActiveColor='#1989fa' + titleInactiveColor='#646566' + > + {TAB_LIST.map((tab) => ( + + ))} + + + + {/* ========== 文章列表 ========== */} + + {filteredArticles.map((article) => ( + handleArticleClick(article.id)} + > + + + ))} + {filteredArticles.length === 0 && ( + 暂无文章 + )} + + + {/* 底部安全距离 */} + + ) } - -// export default class Index extends Component { - -// componentWillMount () { } - -// componentDidMount () { } - -// componentWillUnmount () { } - -// componentDidShow () { } - -// componentDidHide () { } - -// render () { -// return ( -// -// -// 上面的按钮的颜色已经通过全局主题重写覆盖了,参见src/style/index.less -// -// ) -// } -// } diff --git a/src/types/article.ts b/src/types/article.ts new file mode 100644 index 0000000..fcd3a2d --- /dev/null +++ b/src/types/article.ts @@ -0,0 +1,34 @@ +/** 文章卡片类型 */ +export type ArticleCardType = 'text' | 'image-text' | 'image-grid' + +/** 文章分类 */ +export type ArticleCategory = 'latest' | 'recommend' | 'hot' + +/** 文章数据接口 */ +export interface Article { + id: string + title: string + excerpt: string + source: string + time: string + readCount: number + images: string[] + type: ArticleCardType + category: ArticleCategory +} + +/** 导航项 */ +export interface NavItem { + id: string + label: string + icon: string + path: string +} + +/** 轮播项 */ +export interface BannerItem { + id: string + image: string + title: string + link: string +} diff --git a/tsconfig.json b/tsconfig.json index 0fc6d47..c5d3a09 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,9 @@ "strictNullChecks": true, "sourceMap": true, "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, "rootDir": ".", "jsx": "react-jsx", "allowJs": true,