添加Mock数据和API服务层
- 创建完整的Mock数据(非遗项目、传承人、资讯、活动等) - 实现API服务函数(列表查询、详情获取、筛选排序等) - 支持分页和多条件筛选功能
This commit is contained in:
parent
cb195382eb
commit
f7a1c8b580
348
src/services/api.ts
Normal file
348
src/services/api.ts
Normal file
@ -0,0 +1,348 @@
|
||||
/**
|
||||
* 非遗文化传承网站 - API 服务层
|
||||
* 提供数据获取接口(当前使用 Mock 数据)
|
||||
*/
|
||||
|
||||
import type {
|
||||
HeritageItem,
|
||||
Inheritor,
|
||||
NewsArticle,
|
||||
Event,
|
||||
Statistics,
|
||||
Comment,
|
||||
User,
|
||||
PaginationParams,
|
||||
PaginationResult,
|
||||
FilterParams,
|
||||
} from '@types/index'
|
||||
import { mockData } from './mockData'
|
||||
|
||||
// 模拟网络延迟
|
||||
const delay = (ms: number = 300) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
// ===== 统计数据接口 =====
|
||||
export const getStatistics = async (): Promise<Statistics> => {
|
||||
await delay()
|
||||
return mockData.statistics
|
||||
}
|
||||
|
||||
// ===== 非遗项目接口 =====
|
||||
export const getHeritageList = async (
|
||||
params?: FilterParams & PaginationParams
|
||||
): Promise<PaginationResult<HeritageItem>> => {
|
||||
await delay()
|
||||
|
||||
let items = [...mockData.heritageItems]
|
||||
|
||||
// 应用筛选
|
||||
if (params?.category) {
|
||||
const categories = Array.isArray(params.category) ? params.category : [params.category]
|
||||
items = items.filter((item) => categories.includes(item.category))
|
||||
}
|
||||
|
||||
if (params?.level) {
|
||||
const levels = Array.isArray(params.level) ? params.level : [params.level]
|
||||
items = items.filter((item) => levels.includes(item.level))
|
||||
}
|
||||
|
||||
if (params?.province) {
|
||||
const provinces = Array.isArray(params.province) ? params.province : [params.province]
|
||||
items = items.filter((item) => provinces.includes(item.province))
|
||||
}
|
||||
|
||||
if (params?.search) {
|
||||
const search = params.search.toLowerCase()
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
item.name.toLowerCase().includes(search) ||
|
||||
item.description.toLowerCase().includes(search) ||
|
||||
item.tags.some((tag) => tag.toLowerCase().includes(search))
|
||||
)
|
||||
}
|
||||
|
||||
// 应用排序
|
||||
if (params?.sortBy) {
|
||||
const order = params.sortOrder === 'desc' ? -1 : 1
|
||||
items.sort((a, b) => {
|
||||
const aVal = a[params.sortBy as keyof HeritageItem]
|
||||
const bVal = b[params.sortBy as keyof HeritageItem]
|
||||
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
||||
return (aVal - bVal) * order
|
||||
}
|
||||
return String(aVal).localeCompare(String(bVal)) * order
|
||||
})
|
||||
}
|
||||
|
||||
// 分页
|
||||
const page = params?.page || 1
|
||||
const pageSize = params?.pageSize || 12
|
||||
const total = items.length
|
||||
const totalPages = Math.ceil(total / pageSize)
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
|
||||
return {
|
||||
data: items.slice(start, end),
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages,
|
||||
}
|
||||
}
|
||||
|
||||
export const getHeritageById = async (id: string): Promise<HeritageItem | null> => {
|
||||
await delay()
|
||||
return mockData.heritageItems.find((item) => item.id === id) || null
|
||||
}
|
||||
|
||||
export const getFeaturedHeritage = async (limit: number = 6): Promise<HeritageItem[]> => {
|
||||
await delay()
|
||||
return mockData.heritageItems
|
||||
.sort((a, b) => b.viewCount - a.viewCount)
|
||||
.slice(0, limit)
|
||||
}
|
||||
|
||||
// ===== 传承人接口 =====
|
||||
export const getInheritorList = async (
|
||||
params?: FilterParams & PaginationParams
|
||||
): Promise<PaginationResult<Inheritor>> => {
|
||||
await delay()
|
||||
|
||||
let items = [...mockData.inheritors]
|
||||
|
||||
// 应用筛选
|
||||
if (params?.province) {
|
||||
const provinces = Array.isArray(params.province) ? params.province : [params.province]
|
||||
items = items.filter((item) => provinces.includes(item.province))
|
||||
}
|
||||
|
||||
if (params?.search) {
|
||||
const search = params.search.toLowerCase()
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
item.name.toLowerCase().includes(search) ||
|
||||
item.bio.toLowerCase().includes(search) ||
|
||||
item.title.toLowerCase().includes(search)
|
||||
)
|
||||
}
|
||||
|
||||
// 分页
|
||||
const page = params?.page || 1
|
||||
const pageSize = params?.pageSize || 12
|
||||
const total = items.length
|
||||
const totalPages = Math.ceil(total / pageSize)
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
|
||||
return {
|
||||
data: items.slice(start, end),
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages,
|
||||
}
|
||||
}
|
||||
|
||||
export const getInheritorById = async (id: string): Promise<Inheritor | null> => {
|
||||
await delay()
|
||||
return mockData.inheritors.find((item) => item.id === id) || null
|
||||
}
|
||||
|
||||
export const getFeaturedInheritors = async (limit: number = 4): Promise<Inheritor[]> => {
|
||||
await delay()
|
||||
return mockData.inheritors
|
||||
.sort((a, b) => b.followers - a.followers)
|
||||
.slice(0, limit)
|
||||
}
|
||||
|
||||
// ===== 资讯接口 =====
|
||||
export const getNewsList = async (
|
||||
params?: FilterParams & PaginationParams
|
||||
): Promise<PaginationResult<NewsArticle>> => {
|
||||
await delay()
|
||||
|
||||
let items = [...mockData.news]
|
||||
|
||||
// 应用筛选
|
||||
if (params?.category) {
|
||||
const categories = Array.isArray(params.category) ? params.category : [params.category]
|
||||
items = items.filter((item) => categories.includes(item.category))
|
||||
}
|
||||
|
||||
if (params?.search) {
|
||||
const search = params.search.toLowerCase()
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
item.title.toLowerCase().includes(search) ||
|
||||
item.summary.toLowerCase().includes(search)
|
||||
)
|
||||
}
|
||||
|
||||
// 分页
|
||||
const page = params?.page || 1
|
||||
const pageSize = params?.pageSize || 10
|
||||
const total = items.length
|
||||
const totalPages = Math.ceil(total / pageSize)
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
|
||||
return {
|
||||
data: items.slice(start, end),
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages,
|
||||
}
|
||||
}
|
||||
|
||||
export const getNewsById = async (id: string): Promise<NewsArticle | null> => {
|
||||
await delay()
|
||||
return mockData.news.find((item) => item.id === id) || null
|
||||
}
|
||||
|
||||
export const getLatestNews = async (limit: number = 5): Promise<NewsArticle[]> => {
|
||||
await delay()
|
||||
return mockData.news
|
||||
.sort((a, b) => new Date(b.publishDate).getTime() - new Date(a.publishDate).getTime())
|
||||
.slice(0, limit)
|
||||
}
|
||||
|
||||
// ===== 活动接口 =====
|
||||
export const getEventList = async (
|
||||
params?: FilterParams & PaginationParams
|
||||
): Promise<PaginationResult<Event>> => {
|
||||
await delay()
|
||||
|
||||
let items = [...mockData.events]
|
||||
|
||||
// 应用筛选
|
||||
if (params?.type) {
|
||||
const types = Array.isArray(params.type) ? params.type : [params.type]
|
||||
items = items.filter((item) => types.includes(item.type))
|
||||
}
|
||||
|
||||
if (params?.status) {
|
||||
const statuses = Array.isArray(params.status) ? params.status : [params.status]
|
||||
items = items.filter((item) => statuses.includes(item.status))
|
||||
}
|
||||
|
||||
if (params?.search) {
|
||||
const search = params.search.toLowerCase()
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
item.title.toLowerCase().includes(search) ||
|
||||
item.description.toLowerCase().includes(search)
|
||||
)
|
||||
}
|
||||
|
||||
// 分页
|
||||
const page = params?.page || 1
|
||||
const pageSize = params?.pageSize || 10
|
||||
const total = items.length
|
||||
const totalPages = Math.ceil(total / pageSize)
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
|
||||
return {
|
||||
data: items.slice(start, end),
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
totalPages,
|
||||
}
|
||||
}
|
||||
|
||||
export const getEventById = async (id: string): Promise<Event | null> => {
|
||||
await delay()
|
||||
return mockData.events.find((item) => item.id === id) || null
|
||||
}
|
||||
|
||||
export const getUpcomingEvents = async (limit: number = 4): Promise<Event[]> => {
|
||||
await delay()
|
||||
return mockData.events
|
||||
.filter((event) => event.status === 'upcoming')
|
||||
.sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime())
|
||||
.slice(0, limit)
|
||||
}
|
||||
|
||||
// ===== 评论接口 =====
|
||||
export const getCommentsByTarget = async (
|
||||
targetType: 'heritage' | 'inheritor' | 'news',
|
||||
targetId: string
|
||||
): Promise<Comment[]> => {
|
||||
await delay()
|
||||
return mockData.comments.filter(
|
||||
(comment) => comment.targetType === targetType && comment.targetId === targetId
|
||||
)
|
||||
}
|
||||
|
||||
export const addComment = async (comment: Omit<Comment, 'id' | 'createdAt' | 'updatedAt'>): Promise<Comment> => {
|
||||
await delay()
|
||||
const newComment: Comment = {
|
||||
...comment,
|
||||
id: `cm${Date.now()}`,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
}
|
||||
mockData.comments.push(newComment)
|
||||
return newComment
|
||||
}
|
||||
|
||||
// ===== 用户接口 =====
|
||||
export const getUserById = async (id: string): Promise<User | null> => {
|
||||
await delay()
|
||||
return mockData.users.find((user) => user.id === id) || null
|
||||
}
|
||||
|
||||
export const login = async (username: string, password: string): Promise<User | null> => {
|
||||
await delay()
|
||||
// Mock 登录逻辑
|
||||
const user = mockData.users.find((u) => u.username === username)
|
||||
return user || null
|
||||
}
|
||||
|
||||
export const register = async (userData: Partial<User>): Promise<User> => {
|
||||
await delay()
|
||||
const newUser: User = {
|
||||
id: `u${Date.now()}`,
|
||||
username: userData.username || '',
|
||||
nickname: userData.nickname || '',
|
||||
avatar: userData.avatar || 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=100',
|
||||
email: userData.email || '',
|
||||
favorites: [],
|
||||
followedInheritors: [],
|
||||
enrolledCourses: [],
|
||||
registeredEvents: [],
|
||||
points: 0,
|
||||
level: 1,
|
||||
createdAt: new Date().toISOString().split('T')[0],
|
||||
}
|
||||
mockData.users.push(newUser)
|
||||
return newUser
|
||||
}
|
||||
|
||||
// ===== 搜索接口 =====
|
||||
export const searchAll = async (keyword: string): Promise<any> => {
|
||||
await delay()
|
||||
|
||||
const heritages = mockData.heritageItems.filter((item) =>
|
||||
item.name.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
item.description.toLowerCase().includes(keyword.toLowerCase())
|
||||
)
|
||||
|
||||
const inheritors = mockData.inheritors.filter((item) =>
|
||||
item.name.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
item.bio.toLowerCase().includes(keyword.toLowerCase())
|
||||
)
|
||||
|
||||
const news = mockData.news.filter((item) =>
|
||||
item.title.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
item.summary.toLowerCase().includes(keyword.toLowerCase())
|
||||
)
|
||||
|
||||
return {
|
||||
heritages,
|
||||
inheritors,
|
||||
news,
|
||||
}
|
||||
}
|
||||
1594
src/services/mockData.ts
Normal file
1594
src/services/mockData.ts
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user