This commit is contained in:
2025-09-07 22:00:47 +08:00
parent 0a8b20e450
commit c2b2e84416
63 changed files with 1939 additions and 1343 deletions

View File

@@ -13,7 +13,7 @@
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/epic`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s-api.viki.moe/v2/epic'];
this.endpoints = ['https://60s.api.shumengya.top/v2/epic'];
}
},
// 获取当前接口URL

View File

@@ -1,7 +1,7 @@
// 公网IP地址查询应用
class IPQueryApp {
constructor() {
this.apiEndpoint = 'https://60s.viki.moe/v2/ip';
this.apiEndpoint = 'https://60s.api.shumengya.top/v2/ip';
this.init();
}

View File

@@ -1,3 +1,3 @@
[
"https://60s.viki.moe/v2/ip"
"https://60s.api.shumengya.top/v2/ip"
]

View File

@@ -1,10 +1,6 @@
// API接口列表
const API_ENDPOINTS = [
"https://60s-cf.viki.moe",
"https://60s.viki.moe",
"https://60s.b23.run",
"https://60s.114128.xyz",
"https://60s-cf.114128.xyz"
"https://60s.api.shumengya.top",
];
// 当前使用的API索引
@@ -118,7 +114,7 @@ function displayLunarInfo(lunarData) {
<div class="item-value">${lunarData.solar.week_desc}</div>
</div>
<div class="info-item">
<div class="item-icon"><EFBFBD></div>
<div class="item-icon">🍂</div>
<div class="item-label">季节</div>
<div class="item-value">${lunarData.solar.season_name_desc}</div>
</div>
@@ -147,7 +143,7 @@ function displayLunarInfo(lunarData) {
<div class="item-value">${lunarData.zodiac.year}年</div>
</div>
<div class="info-item">
<div class="item-icon"></div>
<div class="item-icon">☯️</div>
<div class="item-label">天干地支</div>
<div class="item-value">${lunarData.sixty_cycle.year.name}</div>
</div>
@@ -161,27 +157,27 @@ function displayLunarInfo(lunarData) {
<div class="info-card">
<div class="card-header">
<div class="card-icon">🌸</div>
<div class="card-icon">🌾</div>
<div class="card-title">节气节日</div>
</div>
<div class="card-content">
<div class="info-item">
<div class="item-icon">🍃</div>
<div class="item-icon">🌱</div>
<div class="item-label">当前节气</div>
<div class="item-value">${lunarData.term.stage ? lunarData.term.stage.name : '无节气'}</div>
</div>
<div class="info-item">
<div class="item-icon">🎊</div>
<div class="item-icon">🎉</div>
<div class="item-label">法定假日</div>
<div class="item-value">${lunarData.legal_holiday ? lunarData.legal_holiday.name : '无假日'}</div>
</div>
<div class="info-item">
<div class="item-icon"><EFBFBD></div>
<div class="item-icon">🎊</div>
<div class="item-label">传统节日</div>
<div class="item-value">${lunarData.festival.both_desc || '无特殊节日'}</div>
</div>
<div class="info-item">
<div class="item-icon">🔢</div>
<div class="item-icon">📊</div>
<div class="item-label">一年第几天</div>
<div class="item-value">第${lunarData.stats.day_of_year}天</div>
</div>
@@ -200,12 +196,12 @@ function displayLunarInfo(lunarData) {
<div class="item-value">${lunarData.lunar.hour_desc}</div>
</div>
<div class="info-item">
<div class="item-icon"></div>
<div class="item-icon">☯️</div>
<div class="item-label">时辰干支</div>
<div class="item-value">${lunarData.sixty_cycle.hour.name}</div>
</div>
<div class="info-item">
<div class="item-icon">🐓</div>
<div class="item-icon">🐾</div>
<div class="item-label">时辰生肖</div>
<div class="item-value">${lunarData.zodiac.hour}</div>
</div>
@@ -219,7 +215,7 @@ function displayLunarInfo(lunarData) {
<div class="info-card">
<div class="card-header">
<div class="card-icon">🔮</div>
<div class="card-icon">📖</div>
<div class="card-title">黄历宜忌</div>
</div>
<div class="card-content">
@@ -253,7 +249,7 @@ function displayLunarInfo(lunarData) {
</div>
<div class="card-content">
<div class="info-item">
<div class="item-icon">🎯</div>
<div class="item-icon">🍀</div>
<div class="item-label">今日运势</div>
<div class="item-value">${lunarData.fortune.today_luck}</div>
</div>
@@ -268,7 +264,7 @@ function displayLunarInfo(lunarData) {
<div class="item-value">${lunarData.fortune.money}</div>
</div>
<div class="info-item">
<div class="item-icon">💕</div>
<div class="item-icon">💖</div>
<div class="item-label">感情运</div>
<div class="item-value">${lunarData.fortune.love}</div>
</div>
@@ -277,12 +273,12 @@ function displayLunarInfo(lunarData) {
<div class="info-card">
<div class="card-header">
<div class="card-icon">📊</div>
<div class="card-icon">📈</div>
<div class="card-title">年度统计</div>
</div>
<div class="card-content">
<div class="info-item">
<div class="item-icon">📈</div>
<div class="item-icon">📊</div>
<div class="item-label">年度进度</div>
<div class="item-value">${lunarData.stats.percents_formatted.year}</div>
</div>

View File

@@ -1,5 +1,5 @@
// API配置
const API_BASE_URL = 'https://60s.viki.moe/v2/hash';
const API_BASE_URL = 'https://60s.api.shumengya.top/v2/hash';
// DOM元素
const elements = {

View File

@@ -162,95 +162,6 @@ body {
font-size: 14px;
}
/* 天气详情 */
.weather-details {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.detail-item {
background: rgba(168, 213, 186, 0.1);
padding: 15px;
border-radius: 12px;
text-align: center;
border: 1px solid rgba(168, 213, 186, 0.2);
}
.detail-item .label {
display: block;
color: #666;
font-size: 12px;
margin-bottom: 5px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.detail-item span:last-child {
color: #2d5a3d;
font-weight: 600;
font-size: 16px;
}
/* 生活指数 */
.life-index {
margin-top: 30px;
}
.life-index h3 {
color: #2d5a3d;
font-size: 1.5rem;
margin-bottom: 20px;
text-align: center;
}
.index-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.index-item {
display: flex;
align-items: center;
background: rgba(168, 213, 186, 0.05);
padding: 20px;
border-radius: 15px;
border: 1px solid rgba(168, 213, 186, 0.2);
transition: all 0.3s ease;
}
.index-item:hover {
background: rgba(168, 213, 186, 0.1);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(168, 213, 186, 0.2);
}
.index-icon {
font-size: 2rem;
margin-right: 15px;
width: 50px;
text-align: center;
}
.index-content h4 {
color: #2d5a3d;
font-size: 16px;
margin-bottom: 5px;
}
.index-content p {
color: #6bb77b;
font-weight: 600;
margin-bottom: 3px;
}
.index-content span {
color: #666;
font-size: 13px;
line-height: 1.4;
}
/* 更新时间 */
.update-time {
text-align: center;
@@ -285,10 +196,6 @@ body {
font-size: 3.5rem;
}
.weather-details {
grid-template-columns: repeat(3, 1fr);
}
.index-grid {
grid-template-columns: repeat(2, 1fr);
}
@@ -308,10 +215,6 @@ body {
justify-content: space-around;
}
.weather-details {
grid-template-columns: repeat(6, 1fr);
}
.index-grid {
grid-template-columns: repeat(3, 1fr);
}
@@ -355,15 +258,6 @@ body {
font-size: 3rem;
}
.weather-details {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.detail-item {
padding: 12px;
}
.index-grid {
grid-template-columns: 1fr;
gap: 15px;
@@ -398,12 +292,121 @@ body {
.temperature {
font-size: 2.5rem;
}
.weather-details {
grid-template-columns: 1fr;
}
/* 预报区域样式 */
.forecast-section {
margin-top: 30px;
padding: 20px;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
backdrop-filter: blur(10px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.forecast-section h3 {
color: #2d5a3d;
font-size: 1.5rem;
margin-bottom: 20px;
text-align: center;
}
.forecast-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.forecast-item {
background: rgba(255, 255, 255, 0.8);
border-radius: 15px;
padding: 15px;
text-align: center;
border: 1px solid rgba(168, 213, 186, 0.3);
transition: all 0.3s ease;
}
.forecast-item:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.forecast-date {
font-weight: bold;
color: #2d5a3d;
margin-bottom: 10px;
font-size: 1.1rem;
}
.forecast-weather {
margin-bottom: 10px;
}
.weather-day {
color: #666;
font-size: 0.9rem;
}
.weather-night {
color: #888;
font-size: 0.85rem;
}
.forecast-temp {
margin-bottom: 10px;
display: flex;
justify-content: center;
gap: 10px;
}
.temp-high {
color: #ff6b6b;
font-weight: bold;
font-size: 1.2rem;
}
.temp-low {
color: #4ecdc4;
font-size: 1rem;
}
.forecast-wind {
color: #666;
font-size: 0.85rem;
margin-bottom: 5px;
}
.forecast-humidity {
color: #888;
font-size: 0.8rem;
}
/* 预报区域响应式设计 */
@media (max-width: 768px) {
.forecast-grid {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
}
.detail-item {
padding: 10px;
.forecast-item {
padding: 12px;
}
.forecast-date {
font-size: 1rem;
}
.temp-high {
font-size: 1.1rem;
}
}
@media (max-width: 480px) {
.forecast-section {
padding: 15px;
}
.forecast-grid {
grid-template-columns: repeat(2, 1fr);
}
}

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气预报</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/background.css">
</head>
<body>
<div class="container">
<header class="header">
<h1>天气预报</h1>
</header>
<div class="search-section">
<div class="search-box">
<input type="text" id="cityInput" placeholder="请输入城市名称(如:北京)" value="北京">
<button id="searchBtn">查询天气</button>
</div>
</div>
<div class="loading" id="loading" style="display: none;">
<div class="spinner"></div>
<p>正在获取天气信息...</p>
</div>
<div class="weather-container" id="weatherContainer" style="display: none;">
<div class="location-info">
<h2 id="locationName"></h2>
<p id="locationDetail"></p>
</div>
<div class="current-weather">
<div class="weather-main">
<div class="temperature">
<span id="temperature"></span>
<span class="unit">°C</span>
</div>
<div class="weather-desc">
<p id="weatherCondition"></p>
<p id="feelsLike"></p>
</div>
</div>
</div>
<div class="forecast-section">
<h3>未来天气预报</h3>
<div class="forecast-grid" id="forecastGrid">
<!-- 预报数据将通过JavaScript动态生成 -->
</div>
</div>
<div class="update-time">
<p>更新时间:<span id="updateTime"></span></p>
</div>
</div>
<div class="error-message" id="errorMessage" style="display: none;">
<p>获取天气信息失败,请稍后重试</p>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>

View File

@@ -2,11 +2,7 @@
class WeatherApp {
constructor() {
this.apiEndpoints = [
'https://60s-cf.viki.moe',
'https://60s.viki.moe',
'https://60s.b23.run',
'https://60s.114128.xyz',
'https://60s-cf.114128.xyz'
"https://60s.api.shumengya.top/v2/weather/forecast"
];
this.currentEndpointIndex = 0;
this.init();
@@ -74,7 +70,7 @@ class WeatherApp {
}
async fetchWeatherData(endpoint, city) {
const url = `${endpoint}/v2/weather?query=${encodeURIComponent(city)}`;
const url = `${endpoint}?query=${encodeURIComponent(city)}`;
const response = await fetch(url, {
method: 'GET',
@@ -93,90 +89,61 @@ class WeatherApp {
}
displayWeatherData(data) {
const { location, realtime } = data;
const { location, forecast } = data;
// 显示位置信息
document.getElementById('locationName').textContent = location.formatted;
document.getElementById('locationDetail').textContent =
`${location.province} ${location.city} | 邮编: ${location.zip_code}`;
// 显示当前天气
document.getElementById('temperature').textContent = realtime.temperature;
document.getElementById('weatherCondition').textContent = realtime.weather;
// 使用第一天的预报数据作为当前天气(今天的天气)
const todayWeather = forecast[0];
// 体感温度转换API返回的是华氏度需要转换为摄氏度)
const feelsLikeCelsius = this.fahrenheitToCelsius(realtime.temperature_feels_like);
// 显示当前天气(使用今天的最高温度)
document.getElementById('temperature').textContent = todayWeather.temperature_high;
document.getElementById('weatherCondition').textContent =
`${todayWeather.weather_day}${todayWeather.weather_night}`;
// 体感温度(使用温度范围)
document.getElementById('feelsLike').textContent =
`体感温度 ${feelsLikeCelsius}°C`;
`温度范围 ${todayWeather.temperature_low}°C - ${todayWeather.temperature_high}°C`;
// 显示天气详情
document.getElementById('humidity').textContent = `${realtime.humidity}%`;
document.getElementById('windDirection').textContent = realtime.wind_direction;
document.getElementById('windStrength').textContent = realtime.wind_strength;
document.getElementById('pressure').textContent = `${realtime.pressure} hPa`;
document.getElementById('visibility').textContent = realtime.visibility;
// 空气质量显示
const aqiElement = document.getElementById('aqi');
aqiElement.textContent = `${realtime.aqi} (PM2.5: ${realtime.pm25})`;
aqiElement.className = this.getAQIClass(realtime.aqi);
// 显示生活指数
const lifeIndex = realtime.life_index;
this.displayLifeIndex('comfort', lifeIndex.comfort);
this.displayLifeIndex('clothing', lifeIndex.clothing);
this.displayLifeIndex('umbrella', lifeIndex.umbrella);
this.displayLifeIndex('uv', lifeIndex.uv);
this.displayLifeIndex('travel', lifeIndex.travel);
this.displayLifeIndex('sport', lifeIndex.sport);
// 显示更新时间
// 显示更新时间(使用当前时间)
document.getElementById('updateTime').textContent =
`${realtime.updated} (${realtime.updated_at})`;
`${this.formatDate(new Date())} (基于预报数据)`;
// 显示天气预报
this.displayForecast(forecast);
this.showWeatherContainer();
}
displayLifeIndex(type, indexData) {
const levelElement = document.getElementById(`${type}Level`);
const descElement = document.getElementById(`${type}Desc`);
displayForecast(forecast) {
const forecastGrid = document.getElementById('forecastGrid');
forecastGrid.innerHTML = '';
if (levelElement && descElement && indexData) {
levelElement.textContent = indexData.level;
descElement.textContent = indexData.desc;
forecast.forEach((day, index) => {
const forecastItem = document.createElement('div');
forecastItem.className = 'forecast-item';
// 根据指数级别设置颜色
levelElement.className = this.getIndexLevelClass(indexData.level);
}
}
getAQIClass(aqi) {
if (aqi <= 50) return 'aqi-good';
if (aqi <= 100) return 'aqi-moderate';
if (aqi <= 150) return 'aqi-unhealthy-sensitive';
if (aqi <= 200) return 'aqi-unhealthy';
if (aqi <= 300) return 'aqi-very-unhealthy';
return 'aqi-hazardous';
}
getIndexLevelClass(level) {
const levelMap = {
'优': 'level-excellent',
'良': 'level-good',
'适宜': 'level-suitable',
'舒适': 'level-comfortable',
'较适宜': 'level-fairly-suitable',
'不宜': 'level-unsuitable',
'较不宜': 'level-fairly-unsuitable',
'带伞': 'level-bring-umbrella',
'最弱': 'level-weakest',
'弱': 'level-weak',
'中等': 'level-moderate',
'强': 'level-strong',
'很强': 'level-very-strong'
};
return levelMap[level] || 'level-default';
forecastItem.innerHTML = `
<div class="forecast-date">${day.date_desc}</div>
<div class="forecast-weather">
<div class="weather-day">${day.weather_day}</div>
<div class="weather-night">${day.weather_night}</div>
</div>
<div class="forecast-temp">
<span class="temp-high">${day.temperature_high}°</span>
<span class="temp-low">${day.temperature_low}°</span>
</div>
<div class="forecast-wind">
<div>${day.wind_direction_day} ${day.wind_strength_day}</div>
</div>
<div class="forecast-humidity">湿度: ${day.humidity}%</div>
`;
forecastGrid.appendChild(forecastItem);
});
}
// 华氏度转摄氏度
@@ -185,6 +152,18 @@ class WeatherApp {
return Math.round(celsius * 10) / 10; // 保留一位小数
}
// 格式化时间
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
showLoading() {
document.getElementById('loading').style.display = 'block';
document.getElementById('weatherContainer').style.display = 'none';
@@ -206,26 +185,6 @@ class WeatherApp {
}
}
// 添加生活指数级别样式
const style = document.createElement('style');
style.textContent = `
.aqi-good { color: #52c41a; }
.aqi-moderate { color: #faad14; }
.aqi-unhealthy-sensitive { color: #fa8c16; }
.aqi-unhealthy { color: #f5222d; }
.aqi-very-unhealthy { color: #a0206e; }
.aqi-hazardous { color: #722ed1; }
.level-excellent, .level-suitable, .level-comfortable { color: #52c41a; }
.level-good, .level-fairly-suitable { color: #1890ff; }
.level-bring-umbrella, .level-moderate { color: #faad14; }
.level-unsuitable, .level-fairly-unsuitable { color: #f5222d; }
.level-weakest, .level-weak { color: #52c41a; }
.level-strong, .level-very-strong { color: #fa8c16; }
.level-default { color: #666; }
`;
document.head.appendChild(style);
// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', () => {
new WeatherApp();

View File

@@ -0,0 +1,3 @@
[
"https://60s.api.shumengya.top/v2/weather/forecast"
]

View File

@@ -0,0 +1,101 @@
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"location": {
"province": "北京",
"city": "北京",
"town": "北京",
"formatted": "北京",
"location_id": "101010100",
"detail_url": "http://www.weather.com.cn/weather/101010100.shtml",
"is_province": true,
"is_city": false,
"is_town": false,
"area_code": "10",
"zip_code": "100000"
},
"forecast": [
{
"date": "9/4",
"date_desc": "今天",
"weather_day": "多云",
"weather_night": "阴",
"weather_code_day": "01",
"weather_code_night": "02",
"temperature_high": 31,
"temperature_low": 21,
"wind_direction_day": "南风",
"wind_direction_night": "南风",
"wind_strength_day": "\u003C3级",
"wind_strength_night": "\u003C3级",
"rainfall": 96.1,
"humidity": 83
},
{
"date": "9/5",
"date_desc": "星期五",
"weather_day": "中雨",
"weather_night": "多云",
"weather_code_day": "08",
"weather_code_night": "01",
"temperature_high": 23,
"temperature_low": 19,
"wind_direction_day": "西南风",
"wind_direction_night": "北风",
"wind_strength_day": "\u003C3级",
"wind_strength_night": "\u003C3级",
"rainfall": 100,
"humidity": 68
},
{
"date": "9/6",
"date_desc": "星期六",
"weather_day": "多云",
"weather_night": "晴",
"weather_code_day": "01",
"weather_code_night": "00",
"temperature_high": 30,
"temperature_low": 19,
"wind_direction_day": "南风",
"wind_direction_night": "西南风",
"wind_strength_day": "\u003C3级",
"wind_strength_night": "\u003C3级",
"rainfall": 85.2,
"humidity": 36
},
{
"date": "9/7",
"date_desc": "星期日",
"weather_day": "多云",
"weather_night": "晴",
"weather_code_day": "01",
"weather_code_night": "00",
"temperature_high": 29,
"temperature_low": 20,
"wind_direction_day": "北风",
"wind_direction_night": "北风",
"wind_strength_day": "\u003C3级",
"wind_strength_night": "\u003C3级",
"rainfall": 87.3,
"humidity": 27
},
{
"date": "9/8",
"date_desc": "星期一",
"weather_day": "多云",
"weather_night": "多云",
"weather_code_day": "01",
"weather_code_night": "01",
"temperature_high": 28,
"temperature_low": 20,
"wind_direction_day": "南风",
"wind_direction_night": "南风",
"wind_strength_day": "\u003C3级",
"wind_strength_night": "\u003C3级",
"rainfall": 84.8,
"humidity": 41
}
]
}
}

View File

@@ -1,140 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实时天气查询</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/background.css">
</head>
<body>
<div class="container">
<header class="header">
<h1>实时天气查询</h1>
</header>
<div class="search-section">
<div class="search-box">
<input type="text" id="cityInput" placeholder="请输入城市名称(如:北京)" value="北京">
<button id="searchBtn">查询天气</button>
</div>
</div>
<div class="loading" id="loading" style="display: none;">
<div class="spinner"></div>
<p>正在获取天气信息...</p>
</div>
<div class="weather-container" id="weatherContainer" style="display: none;">
<div class="location-info">
<h2 id="locationName"></h2>
<p id="locationDetail"></p>
</div>
<div class="current-weather">
<div class="weather-main">
<div class="temperature">
<span id="temperature"></span>
<span class="unit">°C</span>
</div>
<div class="weather-desc">
<p id="weatherCondition"></p>
<p id="feelsLike"></p>
</div>
</div>
<div class="weather-details">
<div class="detail-item">
<span class="label">湿度</span>
<span id="humidity"></span>
</div>
<div class="detail-item">
<span class="label">风向</span>
<span id="windDirection"></span>
</div>
<div class="detail-item">
<span class="label">风力</span>
<span id="windStrength"></span>
</div>
<div class="detail-item">
<span class="label">气压</span>
<span id="pressure"></span>
</div>
<div class="detail-item">
<span class="label">能见度</span>
<span id="visibility"></span>
</div>
<div class="detail-item">
<span class="label">空气质量</span>
<span id="aqi"></span>
</div>
</div>
</div>
<div class="life-index">
<h3>生活指数</h3>
<div class="index-grid">
<div class="index-item">
<div class="index-icon comfort">🌡️</div>
<div class="index-content">
<h4>舒适度</h4>
<p id="comfortLevel"></p>
<span id="comfortDesc"></span>
</div>
</div>
<div class="index-item">
<div class="index-icon clothing">👕</div>
<div class="index-content">
<h4>穿衣指数</h4>
<p id="clothingLevel"></p>
<span id="clothingDesc"></span>
</div>
</div>
<div class="index-item">
<div class="index-icon umbrella">☂️</div>
<div class="index-content">
<h4>雨伞指数</h4>
<p id="umbrellaLevel"></p>
<span id="umbrellaDesc"></span>
</div>
</div>
<div class="index-item">
<div class="index-icon uv">☀️</div>
<div class="index-content">
<h4>紫外线</h4>
<p id="uvLevel"></p>
<span id="uvDesc"></span>
</div>
</div>
<div class="index-item">
<div class="index-icon travel">🚗</div>
<div class="index-content">
<h4>出行指数</h4>
<p id="travelLevel"></p>
<span id="travelDesc"></span>
</div>
</div>
<div class="index-item">
<div class="index-icon sport">🏃</div>
<div class="index-content">
<h4>运动指数</h4>
<p id="sportLevel"></p>
<span id="sportDesc"></span>
</div>
</div>
</div>
</div>
<div class="update-time">
<p>更新时间:<span id="updateTime"></span></p>
</div>
</div>
<div class="error-message" id="errorMessage" style="display: none;">
<p>获取天气信息失败,请稍后重试</p>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>

View File

@@ -1,3 +0,0 @@
[
"https://60s.api.shumengya.top"
]

View File

@@ -1,68 +0,0 @@
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"location": {
"province": "北京",
"city": "北京",
"town": "北京",
"formatted": "北京",
"location_id": "101010100",
"detail_url": "http://www.weather.com.cn/weather/101010100.shtml",
"is_province": true,
"is_city": false,
"is_town": false,
"area_code": "10",
"zip_code": "100000"
},
"realtime": {
"weather": "小雨转多云",
"weather_desc": "未知",
"weather_code": "d7",
"temperature": 26,
"temperature_feels_like": 81.1,
"humidity": 78,
"wind_direction": "南风转北风",
"wind_strength": "\u003C3级",
"wind_speed": "5km/h",
"pressure": 1008,
"visibility": "8km",
"aqi": 37,
"pm25": 37,
"rainfall": 0,
"rainfall_24h": 0,
"updated": "2025-08-29 08:00:00",
"updated_at": "15:10",
"life_index": {
"comfort": {
"level": "舒适",
"desc": "白天温度宜人,风力不大。"
},
"clothing": {
"level": "舒适",
"desc": "建议穿长袖衬衫单裤等服装。"
},
"umbrella": {
"level": "带伞",
"desc": "有降水,带雨伞,短期外出可收起雨伞。"
},
"uv": {
"level": "最弱",
"desc": "辐射弱涂擦SPF8-12防晒护肤品。"
},
"car_wash": {
"level": "不宜",
"desc": "有雨,雨水和泥水会弄脏爱车。"
},
"travel": {
"level": "适宜",
"desc": "较弱降水和微风将伴您共赴旅程。"
},
"sport": {
"level": "较不宜",
"desc": "有降水,推荐您在室内进行休闲运动。"
}
}
}
}
}

View File

@@ -16,8 +16,10 @@ class QRCodeGenerator {
// 加载API接口列表
async loadApiEndpoints() {
try {
const response = await fetch('./接口集合.json');
this.apiEndpoints = await response.json();
// 直接在代码中配置API接口避免CORS问题
this.apiEndpoints = [
"https://60s.api.shumengya.top"
];
console.log('已加载API接口:', this.apiEndpoints);
} catch (error) {
console.error('加载API接口失败:', error);
@@ -32,16 +34,26 @@ class QRCodeGenerator {
const downloadBtn = document.querySelector('.download-btn');
const copyBtn = document.querySelector('.copy-btn');
const newBtn = document.querySelector('.new-btn');
form.addEventListener('submit', (e) => this.handleSubmit(e));
retryBtn.addEventListener('click', () => this.retryGeneration());
downloadBtn.addEventListener('click', () => this.downloadQRCode());
copyBtn.addEventListener('click', () => this.copyImageLink());
newBtn.addEventListener('click', () => this.resetForm());
// 实时字符计数
const textArea = document.getElementById('text');
textArea.addEventListener('input', () => this.updateCharCount());
if (form) {
form.addEventListener('submit', (e) => this.handleSubmit(e));
}
if (retryBtn) {
retryBtn.addEventListener('click', () => this.retryGeneration());
}
if (downloadBtn) {
downloadBtn.addEventListener('click', () => this.downloadQRCode());
}
if (copyBtn) {
copyBtn.addEventListener('click', () => this.copyImageLink());
}
if (newBtn) {
newBtn.addEventListener('click', () => this.resetForm());
}
if (textArea) {
textArea.addEventListener('input', () => this.updateCharCount());
}
}
// 设置表单验证
@@ -162,7 +174,7 @@ class QRCodeGenerator {
// 添加查询参数
Object.entries(params).forEach(([key, value]) => {
if (value) {
if (value !== null && value !== undefined && value !== '') {
url.searchParams.append(key, value);
}
});
@@ -188,20 +200,44 @@ class QRCodeGenerator {
}
// 根据返回格式处理
if (params.encoding === 'image') {
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
return {
success: true,
data: {
imageUrl: imageUrl,
text: params.text,
size: params.size,
level: params.level,
format: 'image'
if (params.encoding === 'image' || !params.encoding) {
// 默认返回图片格式
const contentType = response.headers.get('content-type');
if (contentType && contentType.startsWith('image/')) {
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
return {
success: true,
data: {
imageUrl: imageUrl,
text: params.text,
size: params.size,
level: params.level,
format: 'image'
}
};
} else {
// 如果返回的不是图片尝试解析JSON
const jsonData = await response.json();
if (jsonData.code === 0 && jsonData.data && jsonData.data.data_uri) {
return {
success: true,
data: {
imageUrl: jsonData.data.data_uri,
text: params.text,
size: params.size,
level: params.level,
format: 'json',
base64: jsonData.data.base64,
mimeType: jsonData.data.mime_type
}
};
} else {
throw new Error(jsonData.message || '生成失败');
}
};
}
} else {
// JSON或text格式
const jsonData = await response.json();
if (jsonData.code === 0 && jsonData.data) {
return {
@@ -211,7 +247,7 @@ class QRCodeGenerator {
text: params.text,
size: params.size,
level: params.level,
format: 'json',
format: params.encoding,
base64: jsonData.data.base64,
mimeType: jsonData.data.mime_type
}

View File

@@ -1,10 +0,0 @@
{
"code": 0,
"message": "success",
"data": {
"base64": "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7Z15fBTV...",
"data_uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7Z15fBTV...",
"mime_type": "image/png",
"text": "https://example.com"
}
}

View File

@@ -3,11 +3,7 @@ class BaikeApp {
constructor() {
// API接口列表
this.apiEndpoints = [
'https://60s-cf.viki.moe',
'https://60s.viki.moe',
'https://60s.b23.run',
'https://60s.114128.xyz',
'https://60s-cf.114128.xyz'
'https://60s.api.shumengya.top',
];
this.currentApiIndex = 0;

View File

@@ -3,7 +3,7 @@
class OGAnalyzer {
constructor() {
this.apiUrl = 'https://60s.viki.moe/v2/og';
this.apiUrl = 'https://60s.api.shumengya.top/v2/og';
this.isAnalyzing = false;
this.currentUrl = '';
this.animationFrameId = null;