Files
wzdj/app/admin/screen/_lib/services/static-data-service.ts

281 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export class StaticDataService {
private static instance: StaticDataService
private data: any = {}
private lastRealtimeData: any = null
private startTime: number = Date.now()
static getInstance(): StaticDataService {
if (!StaticDataService.instance) {
StaticDataService.instance = new StaticDataService()
}
return StaticDataService.instance
}
// 生成只增长的实时数据
static generateRealtimeData() {
const svc = StaticDataService.getInstance()
// 如果是第一次调用,初始化基础数据
if (!svc.lastRealtimeData) {
svc.lastRealtimeData = {
totalStalls: 350,
privateUsers: 12500,
stallOwners: 120,
dailyRevenue: 75000,
timestamp: new Date().toISOString(),
}
return svc.lastRealtimeData
}
// 计算时间差(秒)
const now = Date.now()
const timeDiff = (now - svc.startTime) / 1000
// 基于时间的增长率(每秒增长)
const hourlyGrowthRates = {
// 不同时段的增长速度
revenue: svc.getHourlyRevenueGrowthRate(),
users: 0.1, // 用户每秒增长0.1
stalls: 0.01, // 摊位每秒增长0.01
}
// 计算新的数值(只增长,不减少)
const revenueIncrease = Math.floor(timeDiff * hourlyGrowthRates.revenue)
const userIncrease = Math.floor(timeDiff * hourlyGrowthRates.users)
const stallIncrease = Math.floor(timeDiff * hourlyGrowthRates.stalls)
svc.lastRealtimeData = {
totalStalls: 350 + stallIncrease,
privateUsers: 12500 + userIncrease,
stallOwners: 120 + Math.floor(stallIncrease * 0.3),
dailyRevenue: 75000 + revenueIncrease,
timestamp: new Date().toISOString(),
}
return svc.lastRealtimeData
}
// 根据当前时间获取收益增长率
private getHourlyRevenueGrowthRate(): number {
const hour = new Date().getHours()
// 电商/数据大屏的收益时间分布
if (hour >= 9 && hour <= 11) {
return 15 // 上午高峰每秒15元
} else if (hour >= 12 && hour <= 14) {
return 25 // 午餐高峰每秒25元
} else if (hour >= 18 && hour <= 22) {
return 35 // 晚间高峰每秒35元
} else if (hour >= 6 && hour <= 23) {
return 8 // 其他营业时间每秒8元
} else {
return 2 // 夜间每秒2元
}
}
// 生成模拟统计数据(保持增长趋势)
generateStats() {
const baseTime = Date.now()
const dayProgress = (baseTime % (24 * 60 * 60 * 1000)) / (24 * 60 * 60 * 1000)
// 基础数据 + 当日累计增长
const baseUserCount = 12500
const baseStallCount = 350
const baseDailyRevenue = 75000
const baseActiveUsers = 4500
// 当日增长(基于时间进度)
const dailyUserGrowth = Math.floor(dayProgress * 200) // 每天最多增长200用户
const dailyStallGrowth = Math.floor(dayProgress * 10) // 每天最多增长10摊位
const dailyRevenueGrowth = Math.floor(dayProgress * 50000) // 每天最多增长5万收益
return {
userCount: baseUserCount + dailyUserGrowth,
stallCount: baseStallCount + dailyStallGrowth,
dailyRevenue: baseDailyRevenue + dailyRevenueGrowth,
activeUsers: baseActiveUsers + Math.floor(dailyUserGrowth * 0.6),
growthRate: Number((15.2 + dayProgress * 5).toFixed(1)), // 增长率也随时间提升
}
}
// 生成摊位统计数据
generateStallStats() {
const currentTime = Date.now()
const baseOccupancy = 85.1
const timeVariation = Math.sin(currentTime / 1000000) * 2 // 小幅波动
return {
totalStalls: 350,
activeStalls: 298,
occupancyRate: Math.max(80, baseOccupancy + timeVariation), // 确保不低于80%
averageRevenue: 3580 + Math.floor((currentTime % 10000) / 100), // 缓慢增长
topCategories: [
{ name: "餐饮", count: 120, percentage: 34.3 },
{ name: "服装", count: 85, percentage: 24.3 },
{ name: "数码", count: 65, percentage: 18.6 },
{ name: "其他", count: 80, percentage: 22.8 },
],
}
}
// 生成用户统计数据
generateUserStats() {
const stats = this.generateStats()
return {
totalUsers: stats.userCount,
activeUsers: stats.activeUsers,
newUsersToday: Math.floor((Date.now() % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)) + 50, // 基于小时数
userGrowthRate: stats.growthRate,
ageDistribution: [
{ range: "18-25", count: Math.floor(stats.userCount * 0.3), percentage: 30 },
{ range: "26-35", count: Math.floor(stats.userCount * 0.35), percentage: 35 },
{ range: "36-45", count: Math.floor(stats.userCount * 0.2), percentage: 20 },
{ range: "46+", count: Math.floor(stats.userCount * 0.15), percentage: 15 },
],
}
}
// 生成交易数据
generateDailyTransactions() {
const currentHour = new Date().getHours()
const hours = Array.from({ length: 24 }, (_, i) => {
const hour = i.toString().padStart(2, "0") + ":00"
let transactions = 0
// 已过去的小时显示累计数据未来小时显示0
if (i <= currentHour) {
// 模拟不同时段的交易量
if (i >= 9 && i <= 11)
transactions = Math.floor(Math.random() * 50) + 80 // 上午高峰
else if (i >= 12 && i <= 14)
transactions = Math.floor(Math.random() * 60) + 100 // 午餐高峰
else if (i >= 18 && i <= 21)
transactions = Math.floor(Math.random() * 70) + 120 // 晚餐高峰
else if (i >= 6 && i <= 23)
transactions = Math.floor(Math.random() * 30) + 20 // 其他营业时间
else transactions = Math.floor(Math.random() * 5) // 夜间
}
return { time: hour, transactions }
})
const completedHours = hours.filter((h) => h.transactions > 0)
return {
todayTotal: completedHours.reduce((sum, h) => sum + h.transactions, 0),
hourlyData: hours,
averagePerHour:
completedHours.length > 0
? Math.floor(completedHours.reduce((sum, h) => sum + h.transactions, 0) / completedHours.length)
: 0,
peakHour: completedHours.reduce((max, h) => (h.transactions > max.transactions ? h : max), {
time: "00:00",
transactions: 0,
}),
}
}
// 生成资产价值数据
generateAssetValue() {
const months = ["1月", "2月", "3月", "4月", "5月", "6月"]
const baseValue = 1000000
const currentMonth = new Date().getMonth()
const monthlyData = months.map((month, index) => ({
month,
value: baseValue + index * 80000 + Math.floor(Math.random() * 50000), // 确保每月都增长
}))
const currentValue = monthlyData[Math.min(currentMonth, monthlyData.length - 1)].value
return {
currentValue,
monthlyData,
growthRate: 12.5,
totalAssets: currentValue * 4.2, // 总资产是当前价值的4.2倍
}
}
// 生成增长趋势数据
generateGrowthTrend() {
const days = Array.from({ length: 30 }, (_, i) => {
const date = new Date()
date.setDate(date.getDate() - (29 - i))
// 确保数据呈增长趋势
const baseUsers = 12000
const baseRevenue = 120000
const baseTransactions = 800
return {
date: date.toISOString().split("T")[0],
users: baseUsers + i * 25 + Math.floor(Math.random() * 50), // 每天增长25-75用户
revenue: baseRevenue + i * 1500 + Math.floor(Math.random() * 2000), // 每天增长1500-3500收益
transactions: baseTransactions + i * 8 + Math.floor(Math.random() * 15), // 每天增长8-23交易
}
})
return {
dailyData: days,
userGrowth: 8.5,
revenueGrowth: 12.3,
transactionGrowth: 6.8,
}
}
// 生成电竞明星数据
generateEsportsStars() {
const baseEarnings = [1250000, 980000, 850000]
const timeBonus = Math.floor((Date.now() % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)) * 1000 // 每小时增长1000
return [
{
id: 1,
name: "Faker",
game: "英雄联盟",
team: "T1",
rank: 1,
winRate: 87.5,
earnings: baseEarnings[0] + timeBonus,
avatar: "/placeholder.svg?height=64&width=64",
},
{
id: 2,
name: "s1mple",
game: "CS:GO",
team: "NAVI",
rank: 2,
winRate: 82.3,
earnings: baseEarnings[1] + timeBonus,
avatar: "/placeholder.svg?height=64&width=64",
},
{
id: 3,
name: "Uzi",
game: "英雄联盟",
team: "RNG",
rank: 3,
winRate: 79.8,
earnings: baseEarnings[2] + timeBonus,
avatar: "/placeholder.svg?height=64&width=64",
},
]
}
// 获取所有数据
getAllData() {
return {
stats: this.generateStats(),
stallStats: this.generateStallStats(),
userStats: this.generateUserStats(),
dailyTransactions: this.generateDailyTransactions(),
assetValue: this.generateAssetValue(),
growthTrend: this.generateGrowthTrend(),
esportsStars: this.generateEsportsStars(),
}
}
}
export const staticDataService = StaticDataService.getInstance()