/* about.js - Aurora Nexus Core */ $(document).ready(function() { // 启动应用核心 const app = new AppCore(); }); class AppCore { constructor() { this.i18n = new I18nManager(); this.theme = new ThemeManager(); this.data = new DataManager(); this.ui = new UIManager(); } } /* =========================== 1. I18n (Language) =========================== */ class I18nManager { constructor() { this.lang = localStorage.getItem('lang') || (navigator.language.startsWith('zh') ? 'zh' : 'en'); this.dict = { zh: { "nav.home": "首页", "nav.about": "关于", "nav.blog": "博客", "status.online": "在线", "profile.name": "Honesty", "profile.role": "Java后端 & AI探索者", "profile.location": "上海, 中国", "bio.label": "关于我", "bio.text": "我是一名充满热情的Java后端开发工程师,专注于AI技术的探索与应用。来自湖南,现在上海工作,享受在这座充满活力的城市中追求技术梦想。", "bio.quote": "我追求技术的深度理解而非广度堆砌,每一项技术的学习都源于解决实际问题的内在驱动。", "stats.exp": "编程年限", "stats.repos": "开源项目", "stats.followers": "关注者", "mbti.name": "提倡者", "mbti.desc": "理想主义与道德感,果断决绝的行动力。深度洞察与创意,关怀与同理心。", "mbti.tag1": "理想主义", "mbti.tag2": "深度洞察", "mbti.tag3": "同理心", "tech.title": "技术栈宇宙", "interest.title": "个人兴趣", "interest.cycling": "骑行", "interest.cycling_desc": "用车轮丈量世界", "interest.reading": "阅读", "interest.reading_desc": "记录思考的轨迹", "interest.opensource": "开源", "interest.opensource_desc": "分享代码与力量", "interest.learning": "持续学习", "interest.learning_desc": "保持好奇心", "github.title": "开源贡献", "blog.title": "最新文章", "blog.more": "查看更多", "comment.title": "留言板", "modal.wechat": "微信公众号", "modal.desc": "扫码关注获取干货" }, en: { "nav.home": "Home", "nav.about": "About", "nav.blog": "Blog", "status.online": "Available", "profile.name": "Honesty", "profile.role": "Java Backend & AI Dev", "profile.location": "Shanghai, China", "bio.label": "About Me", "bio.text": "I am a passionate Java Backend Engineer focused on AI exploration. Based in Shanghai, originally from Hunan, I enjoy pursuing my technical dreams in this vibrant city.", "bio.quote": "I seek deep understanding over broad stacking. Every skill I learn is driven by the need to solve real problems.", "stats.exp": "Years Exp", "stats.repos": "Projects", "stats.followers": "Followers", "mbti.name": "Advocate", "mbti.desc": "Idealism and morality, decisive action. Deep insight and creativity, care and empathy.", "mbti.tag1": "Idealism", "mbti.tag2": "Insight", "mbti.tag3": "Empathy", "tech.title": "Tech Universe", "interest.title": "Interests", "interest.cycling": "Cycling", "interest.cycling_desc": "Measuring the world", "interest.reading": "Reading", "interest.reading_desc": "Tracks of thought", "interest.opensource": "Open Source", "interest.opensource_desc": "Sharing power", "interest.learning": "Learning", "interest.learning_desc": "Stay curious", "github.title": "Open Source", "blog.title": "Latest Posts", "blog.more": "View All", "comment.title": "Message Board", "modal.wechat": "WeChat Account", "modal.desc": "Scan for tech insights" } }; this.init(); } init() { this.apply(); $('#lang-btn').on('click', () => { this.lang = this.lang === 'zh' ? 'en' : 'zh'; localStorage.setItem('lang', this.lang); this.apply(); }); } apply() { const t = this.dict[this.lang]; $('[data-i18n]').each(function() { const k = $(this).data('i18n'); if(t[k]) $(this).text(t[k]); }); } } /* =========================== 2. Theme Manager =========================== */ class ThemeManager { constructor() { this.root = document.documentElement; this.init(); } init() { const saved = localStorage.getItem('theme') || 'day'; if(saved === 'night') this.root.setAttribute('data-theme', 'night'); $('#theme-btn').on('click', () => { const curr = this.root.getAttribute('data-theme'); const next = curr === 'night' ? 'day' : 'night'; if(next === 'night') this.root.setAttribute('data-theme', 'night'); else this.root.removeAttribute('data-theme'); localStorage.setItem('theme', next); // 更新Artalk主题 if (typeof Artalk !== 'undefined') { Artalk.reload(); } }); } } /* =========================== 3. Data Manager (Robust) =========================== */ class DataManager { constructor() { // Fallback Data if APIs fail this.defaults = { repos: [ {name: "yunxiao-LLM-reviewer", desc: "AI Code Reviewer based on LLM", stars: 9, url: "#"}, {name: "hexo-theme-stellar", desc: "Comprehensive Hexo theme", stars: 5, url: "#"}, {name: "Universal-IoT-Java", desc: "IoT Platform Demo", stars: 2, url: "#"} ], posts: [ {title: "Vector Database Guide", date: "2025-01-02", cat: "Tech", url: "#"}, {title: "Spring Boot 3.0 Features", date: "2024-12-30", cat: "Java", url: "#"}, {title: "Microservices Patterns", date: "2024-12-28", cat: "Arch", url: "#"} ], user: { repos: 165, followers: 6, created: "2018-05-14" } }; this.init(); } init() { this.fetchGithub(); this.fetchBlog(); } // 优先缓存 -> API -> 默认值 async fetchGithub() { const user = (window.SiteConfig?.github?.username) || 'listener-He'; const cacheKey = 'gh_data_v2'; const cached = JSON.parse(localStorage.getItem(cacheKey)); const now = Date.now(); // Check Cache (1 hour) if(cached && (now - cached.time < 3600000)) { this.renderUser(cached.user); this.renderRepos(cached.repos); return; } try { // Parallel Fetch const [uRes, rRes] = await Promise.allSettled([ fetch(`https://api.github.com/users/${user}`), fetch(`https://api.github.com/users/${user}/repos?sort=stars&per_page=100`) ]); const userData = uRes.status === 'fulfilled' ? await uRes.value.json() : this.defaults.user; let repoData = rRes.status === 'fulfilled' ? await rRes.value.json() : this.defaults.repos; // 过滤掉fork项目并按星数排序 if (Array.isArray(repoData)) { repoData = repoData .filter(repo => !repo.fork && (repo.stargazers_count > 0 || repo.forks_count > 0)) .sort((a, b) => (b.stargazers_count || 0) - (a.stargazers_count || 0)) .slice(0, 12); // 只取前12个 } // Cache & Render localStorage.setItem(cacheKey, JSON.stringify({ user: userData, repos: repoData, time: now })); this.renderUser(userData); this.renderRepos(repoData); } catch (e) { console.warn("GH API Fail", e); this.renderUser(this.defaults.user); this.renderRepos(this.defaults.repos); } } renderUser(data) { const years = new Date().getFullYear() - new Date(data.created_at || this.defaults.user.created).getFullYear(); $('#coding-years').text(years + "+"); $('#github-repos').text(data.public_repos || this.defaults.user.repos); $('#github-followers').text(data.followers || this.defaults.user.followers); } renderRepos(list) { if(!Array.isArray(list)) list = this.defaults.repos; let html = ''; list.slice(0, 5).forEach(repo => { // Fix: API field compatibility const stars = repo.stargazers_count !== undefined ? repo.stargazers_count : (repo.stars || 0); const forks = repo.forks_count !== undefined ? repo.forks_count : (repo.forks || 0); const desc = repo.description || repo.desc || 'No description.'; const url = repo.html_url || repo.url || '#'; html += `