关于地球Online

本系统是一款基于现代 Web 技术栈构建的玩家行为度量与成就追踪系统,旨在提供高性能、低延迟的数据可视化方案。

核心特色

  • 海量数据动态渲染,支持 999+ 成就卡片无缝无卡顿加载。
  • 支持浅色、深色与跟随系统,可自由调节强调色、背景氛围和动态效果。
  • 轻量化前端架构,纯原生高效交互,拒绝冗余依赖。

技术栈架构

Python 3.x
后端核心业务逻辑与数据路由
Flask 框架
微服务级路由与轻量化上下文管理
Jinja2
服务器端高性能安全模板渲染引擎
Modern CSS
基于硬件加速的毛玻璃与响应式布局

快速开始

# 克隆开源仓库
git clone https://github.com/L0r3Seeker/Earth-Online.git

# 安装依赖
pip install -r requirements.txt

# 启动本地开发服务器
python app.py
#!/usr/bin/env python3
"""
地球Online 玩家成就系统 - Web版
EarthOL Achievement System Web Edition
"""

from flask import Flask, render_template, jsonify, request
import json
import os
import random

app = Flask(__name__)
app.secret_key = 'earthol_secret_key_2026'

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = os.path.join(BASE_DIR, 'static', 'data')
ACHIEVEMENTS_FILE = os.path.join(DATA_DIR, 'achievements.json')
SAVE_FILE = os.path.join(DATA_DIR, 'progress.json')
SLOGANS_FILE = os.path.join(DATA_DIR, 'slogans.txt')

def load_achievements():
    if os.path.exists(ACHIEVEMENTS_FILE):
        with open(ACHIEVEMENTS_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    return []

def load_progress():
    if os.path.exists(SAVE_FILE):
        with open(SAVE_FILE, 'r', encoding='utf-8') as f:
            data = json.load(f)
            return set(data.get('completed', []))
    return set()

def save_progress(completed_ids):
    with open(SAVE_FILE, 'w', encoding='utf-8') as f:
        json.dump({'completed': list(completed_ids)}, f,
                  ensure_ascii=False, indent=2)

achievements = load_achievements()
completed_ids = load_progress()

@app.route('/')
def home():
    current_slogan = "你的一生,皆是成就。"
    completed_count = len(completed_ids)
    total_count = len(achievements)
    completion_rate = round(completed_count / total_count * 100, 1) if total_count else 0
    return render_template('home.html',
                          achievements=achievements,
                          completed_ids=completed_ids,
                          completed_count=completed_count,
                          total_count=total_count,
                          completion_rate=completion_rate,
                          current_slogan=current_slogan,
                          current_page='home')

@app.route('/api/toggle/', methods=['POST'])
def toggle_achievement(ach_id):
    global completed_ids
    if ach_id in completed_ids:
        completed_ids.remove(ach_id)
        status = False
    else:
        completed_ids.add(ach_id)
        status = True
    save_progress(completed_ids)
    return jsonify({
        'success': True,
        'status': status,
        'completed_count': len(completed_ids),
        'total_count': len(achievements),
        'completion_rate': round(len(completed_ids) / len(achievements) * 100, 1)
    })

@app.route('/source')
def source_code():
    return render_template('source.html', current_page='source')

@app.route('/style')
def style_page():
    return render_template('style.html', current_page='style')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

关键代码解析

1. 数据加载与持久化存储

def load_achievements():
    if os.path.exists(ACHIEVEMENTS_FILE):
        with open(ACHIEVEMENTS_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    return []
架构提示

核心业务采用哈希集合(Set)存储玩家已解锁的成就 ID,在 O(1) 时间复杂度下完成去重与解锁状态校验,确保在 999+ 全量高频并发下维持极低 CPU 占用。

2. 成就切换 API

@app.route('/api/toggle/', methods=['POST'])
def toggle_achievement(ach_id):
    global completed_ids
    if ach_id in completed_ids:
        completed_ids.remove(ach_id)
    else:
        completed_ids.add(ach_id)
    save_progress(completed_ids)
架构提示

使用 global 关键字修改全局变量;返回 JSON 包含完成数和完成率,前端可实时更新统计卡片。

3. 筛选与搜索逻辑

filter_type = request.args.get('filter', 'all')
search_text = request.args.get('search', '').lower()
if search_text and search_text not in ach['title'].lower() \
               and search_text not in ach['description'].lower():
    continue
架构提示

搜索统一转小写,避免大小写匹配差异;筛选与搜索可叠加使用,实现精准的数据过滤。

4. SVG 图标生成系统

const SVG_COLORS = {
    gold:   ["#FFD700", "#FFA500", "#B8860B"],
    silver: ["#C0C0C0", "#A9A9A9", "#808080"],
    copper: ["#CD7F32", "#B87333", "#8B4513"],
};

function generateSVG(iconName, rarity = 'silver') {
    const [c1, c2, c3] = SVG_COLORS[rarity] || SVG_COLORS.silver;
    const pattern = SVG_PATTERNS[iconName] || SVG_PATTERNS.star;
    return pattern.replace(/{c1}/g, c1)
                  .replace(/{c2}/g, c2)
                  .replace(/{c3}/g, c3);
}
架构提示

通过模板占位符替换颜色,实现"一套图案 + 多套配色"的灵活组合,确保图标系统与 .exe 版本完全一致。

web/
├── app.py                    # 后端主程序(Flask 路由 + 数据加载)
├── templates/
│   ├── base.html             # 基础模板(浮动导航、氛围背景)
│   ├── home.html             # 主页面:成就殿堂
│   ├── source.html           # 源码页:介绍 / 源码 / 解析
│   └── _appearance.html      # 全站外观设置面板
├── static/
│   ├── css/
│   │   └── glass.css         # 轻透玻璃视觉、明暗模式与响应式
│   ├── js/
│   │   ├── ui.js             # 前端交互(筛选 / 搜索 / 解锁)
│   │   ├── svg-icons.js      # SVG 图标系统(与 .exe 一致)
│   │   └── appearance.js     # 外观偏好、色调与动态效果
│   └── data/
│       ├── achievements.json # 成就数据(999 条)
│       ├── progress.json     # 用户进度
│       └── slogans.txt       # 标语列表
└── requirements.txt          # 依赖清单

成就数据结构

单条原始成就数据采用严格的 JSON Schema 规范进行定义,确保向后兼容性。

{
    "id": 1,
    "title": "永恒挚爱",
    "description": "在茫茫人海中,找到了那一束光 —— 向心爱之人成功求婚",
    "rarity": "gold",
    "unlock_rate": 3.2,
    "icon": "love"
}

稀有度评级说明

  • 金色评级 稀有度 < 1% 的骨灰级史诗成就
  • 银色评级 稀有度 1% - 10% 的高阶进阶成就
  • 铜色评级 稀有度 > 10% 的基础探索成就