chore: initialize frontend miniapp repository

This commit is contained in:
lyf
2026-06-09 21:08:45 +08:00
commit a90f63cef0
107 changed files with 60454 additions and 0 deletions

98
src/utils/dataLoader.ts Normal file
View File

@@ -0,0 +1,98 @@
/**
* Legacy demo data loader.
*
* 当前导览模块不要再从 src/assets/data 取数;室内导览、搜索、位置预览
* 统一使用 src/services/navAssets.ts 读取 clean nav assets。
* 这里保留给尚未重构的历史演示页面,避免删除造成不可控回归。
*/
// 加载楼层数据
export const loadFloors = async () => {
try {
const data = await import('@/assets/data/floors.json')
return data.default || data
} catch (error) {
console.error('加载楼层数据失败:', error)
return []
}
}
// 加载展厅数据
export const loadHalls = async () => {
try {
const data = await import('@/assets/data/halls.json')
return data.default || data
} catch (error) {
console.error('加载展厅数据失败:', error)
return []
}
}
// 加载展品数据
export const loadExhibits = async () => {
try {
const data = await import('@/assets/data/exhibits.json')
return data.default || data
} catch (error) {
console.error('加载展品数据失败:', error)
return []
}
}
// 加载设施数据
export const loadFacilities = async () => {
try {
const data = await import('@/assets/data/facilities.json')
return data.default || data
} catch (error) {
console.error('加载设施数据失败:', error)
return []
}
}
// 加载路线数据
export const loadRoutes = async () => {
try {
const data = await import('@/assets/data/routes.json')
return data.default || data
} catch (error) {
console.error('加载路线数据失败:', error)
return []
}
}
// 根据 ID 查找展品
export const findExhibitById = async (id: string) => {
const exhibits = await loadExhibits()
return exhibits.find((item: any) => item.id === id)
}
// 根据 ID 查找展厅
export const findHallById = async (id: string) => {
const halls = await loadHalls()
return halls.find((item: any) => item.id === id)
}
// 根据 ID 查找设施
export const findFacilityById = async (id: string) => {
const facilities = await loadFacilities()
return facilities.find((item: any) => item.id === id)
}
// 根据 ID 查找路线
export const findRouteById = async (id: string) => {
const routes = await loadRoutes()
return routes.find((item: any) => item.id === id)
}
// 根据楼层筛选展厅
export const filterHallsByFloor = async (floorId: string) => {
const halls = await loadHalls()
return halls.filter((item: any) => item.floor === floorId)
}
// 根据展厅筛选展品
export const filterExhibitsByHall = async (hallId: string) => {
const exhibits = await loadExhibits()
return exhibits.filter((item: any) => item.hallId === hallId)
}

90
src/utils/format.ts Normal file
View File

@@ -0,0 +1,90 @@
/**
* 格式化工具函数
*/
/**
* 格式化时间
* @param time 时间字符串
* @returns 格式化后的时间
*/
export const formatTime = (time: string): string => {
return time
}
/**
* 格式化距离
* @param distance 距离(米)
* @returns 格式化后的距离
*/
export const formatDistance = (distance: number): string => {
if (distance < 1000) {
return `${distance}`
}
return `${(distance / 1000).toFixed(1)}公里`
}
/**
* 格式化时长
* @param minutes 分钟数
* @returns 格式化后的时长
*/
export const formatDuration = (minutes: number): string => {
if (minutes < 60) {
return `${minutes}分钟`
}
const hours = Math.floor(minutes / 60)
const mins = minutes % 60
return mins > 0 ? `${hours}小时${mins}分钟` : `${hours}小时`
}
/**
* 截断文本
* @param text 文本
* @param maxLength 最大长度
* @returns 截断后的文本
*/
export const truncateText = (text: string, maxLength: number): string => {
if (text.length <= maxLength) {
return text
}
return text.substring(0, maxLength) + '...'
}
/**
* 防抖函数
* @param fn 函数
* @param delay 延迟时间(毫秒)
* @returns 防抖后的函数
*/
export const debounce = <T extends (...args: any[]) => any>(
fn: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let timer: ReturnType<typeof setTimeout> | null = null
return (...args: Parameters<T>) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn(...args)
}, delay)
}
}
/**
* 节流函数
* @param fn 函数
* @param delay 延迟时间(毫秒)
* @returns 节流后的函数
*/
export const throttle = <T extends (...args: any[]) => any>(
fn: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let lastTime = 0
return (...args: Parameters<T>) => {
const now = Date.now()
if (now - lastTime >= delay) {
fn(...args)
lastTime = now
}
}
}

81
src/utils/search.ts Normal file
View File

@@ -0,0 +1,81 @@
/**
* 搜索工具函数
*/
import type { Exhibit, Hall, Facility } from '@/types'
/**
* 搜索展品
* @param exhibits 展品列表
* @param keyword 关键词
* @returns 匹配的展品列表
*/
export const searchExhibits = (exhibits: Exhibit[], keyword: string): Exhibit[] => {
if (!keyword) return []
const lowerKeyword = keyword.toLowerCase()
return exhibits.filter(exhibit => {
return (
exhibit.name.toLowerCase().includes(lowerKeyword) ||
exhibit.artist?.toLowerCase().includes(lowerKeyword) ||
exhibit.description.toLowerCase().includes(lowerKeyword)
)
})
}
/**
* 搜索展厅
* @param halls 展厅列表
* @param keyword 关键词
* @returns 匹配的展厅列表
*/
export const searchHalls = (halls: Hall[], keyword: string): Hall[] => {
if (!keyword) return []
const lowerKeyword = keyword.toLowerCase()
return halls.filter(hall => {
return (
hall.name.toLowerCase().includes(lowerKeyword) ||
hall.description.toLowerCase().includes(lowerKeyword)
)
})
}
/**
* 搜索设施
* @param facilities 设施列表
* @param keyword 关键词
* @returns 匹配的设施列表
*/
export const searchFacilities = (facilities: Facility[], keyword: string): Facility[] => {
if (!keyword) return []
const lowerKeyword = keyword.toLowerCase()
return facilities.filter(facility => {
return (
facility.name.toLowerCase().includes(lowerKeyword) ||
facility.location.toLowerCase().includes(lowerKeyword)
)
})
}
/**
* 综合搜索
* @param exhibits 展品列表
* @param halls 展厅列表
* @param facilities 设施列表
* @param keyword 关键词
* @returns 搜索结果
*/
export const searchAll = (
exhibits: Exhibit[],
halls: Hall[],
facilities: Facility[],
keyword: string
) => {
return {
exhibits: searchExhibits(exhibits, keyword),
halls: searchHalls(halls, keyword),
facilities: searchFacilities(facilities, keyword)
}
}