From 68bfaf7d97a85499fa4bd542658b2be736b4aeef Mon Sep 17 00:00:00 2001 From: Xiang Silian Date: Fri, 28 Nov 2025 15:54:34 +0800 Subject: [PATCH] init --- .gitignore | 24 ++++ App.tsx | 215 ++++++++++++++++++++++++++++++++++ README.md | 20 ++++ components/ExperienceList.tsx | 63 ++++++++++ components/LanguageToggle.tsx | 23 ++++ components/ProjectCard.tsx | 83 +++++++++++++ components/Section.tsx | 26 ++++ constants.ts | 205 ++++++++++++++++++++++++++++++++ index.html | 30 +++++ index.tsx | 15 +++ metadata.json | 5 + package.json | 22 ++++ tsconfig.json | 29 +++++ types.ts | 48 ++++++++ vite.config.ts | 23 ++++ 15 files changed, 831 insertions(+) create mode 100644 .gitignore create mode 100644 App.tsx create mode 100644 README.md create mode 100644 components/ExperienceList.tsx create mode 100644 components/LanguageToggle.tsx create mode 100644 components/ProjectCard.tsx create mode 100644 components/Section.tsx create mode 100644 constants.ts create mode 100644 index.html create mode 100644 index.tsx create mode 100644 metadata.json create mode 100644 package.json create mode 100644 tsconfig.json create mode 100644 types.ts create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/App.tsx b/App.tsx new file mode 100644 index 0000000..740c679 --- /dev/null +++ b/App.tsx @@ -0,0 +1,215 @@ +import React, { useState } from 'react'; +import { Language } from './types'; +import { RESUME_DATA } from './constants'; +import LanguageToggle from './components/LanguageToggle'; +import Section from './components/Section'; +import ExperienceList from './components/ExperienceList'; +import ProjectCard from './components/ProjectCard'; +import { Mail, Phone, MessageSquare, Download, Linkedin, GraduationCap, Code2, ChevronDown, Award, Globe2 } from 'lucide-react'; + +const App: React.FC = () => { + const [lang, setLang] = useState('zh'); + + const { name, title, summary, contact, skills, experience, projects, education } = RESUME_DATA; + + // Background images from Unsplash + const heroBgImage = "https://images.unsplash.com/photo-1519389950473-47ba0277781c?q=80&w=2670&auto=format&fit=crop"; + const footerBgImage = "https://images.unsplash.com/photo-1451187580459-43490279c0fa?q=80&w=2000&auto=format&fit=crop"; + + return ( +
+ {/* Navigation / Header */} +
+
+
+
+ {name['en'].split(' ')[0][0]} +
+ {lang === 'en' ? 'Resume' : '个人简历'} +
+
+ +
+ + + +
+
+
+ + {/* Hero Section with Rich Background Image */} +
+
+ {/* Background Image */} +
+ + {/* Overlay - White gradient for clean text readability */} +
+ +
+
+
+ + + + + {lang === 'en' ? 'Available for new opportunities' : '正在寻找新机会'} +
+ +

+ {name[lang]} +

+ +

+ {title[lang]} +

+ +

+ {summary[lang]} +

+ + {/* Contact Buttons */} + +
+
+ + {/* Scroll Indicator */} +
+ +
+
+ + {/* Skills Section (Dark Band) */} +
+ {/* Abstract BG pattern */} +
+ +
+
+

+ {lang === 'en' ? 'Technical Expertise' : '技能特长'} +

+

+ {lang === 'en' ? 'Core Competencies' : '核心技术栈'} +

+
+ +
+ {skills.map((skill, idx) => ( +
+
+ {skill[lang]} +
+ ))} +
+
+
+ + {/* Experience Section */} +
+ +
+ + {/* Projects Section */} +
+
+ {projects.map((project, index) => ( + + ))} +
+
+ + {/* Education Section */} +
+
+ {education.map((edu, index) => ( +
+
+ +
+
+

{edu.school[lang]}

+

{edu.major[lang]}

+
+ {edu.degree[lang]} + + {edu.period} +
+
+
+ ))} +
+
+ + {/* Contact / Footer CTA Area */} +
+
+
+ +
+

+ {lang === 'en' ? 'Let\'s work together' : '期待与您的合作'} +

+

+ {lang === 'en' + ? 'I am currently open to new opportunities in autonomous driving, simulation, and game development.' + : '我目前正在寻找自动驾驶、仿真及游戏开发领域的新机会。'} +

+
+ + + {lang === 'en' ? 'Email Me' : '发送邮件'} + +
+ + WeChat: {contact.wechat} +
+
+
+
+
+ + {/* Footer */} +
+
+
+

{name[lang]}

+

+ © {new Date().getFullYear()} All rights reserved. +

+
+ +
+ + + +
+
+
+
+ ); +}; + +export default App; \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0b2ef0f --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +
+GHBanner +
+ +# Run and deploy your AI Studio app + +This contains everything you need to run your app locally. + +View your app in AI Studio: https://ai.studio/apps/drive/1WUmEnnlP32ZAV4EvpNu8RLOKs9siv2ez + +## Run Locally + +**Prerequisites:** Node.js + + +1. Install dependencies: + `npm install` +2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key +3. Run the app: + `npm run dev` diff --git a/components/ExperienceList.tsx b/components/ExperienceList.tsx new file mode 100644 index 0000000..d6092e4 --- /dev/null +++ b/components/ExperienceList.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { ExperienceItem, Language } from '../types'; +import { Calendar } from 'lucide-react'; + +interface Props { + experience: ExperienceItem[]; + lang: Language; +} + +const ExperienceList: React.FC = ({ experience, lang }) => { + return ( +
+ {/* Central Line */} +
+ + {experience.map((job, index) => ( +
+ + {/* Timeline Dot */} +
+ + {/* Date for Desktop (Opposite side) */} +
+
+ {index % 2 !== 0 && {job.period}} + + {index % 2 === 0 && {job.period}} +
+
+ + {/* Content Card */} +
+
+ {/* Mobile Date */} +
+ + {job.period} +
+ +

+ {job.company[lang]} +

+
+ {job.role[lang]} +
+ +
    + {job.description.map((desc, i) => ( +
  • + + {desc[lang]} +
  • + ))} +
+
+
+
+ ))} +
+ ); +}; + +export default ExperienceList; \ No newline at end of file diff --git a/components/LanguageToggle.tsx b/components/LanguageToggle.tsx new file mode 100644 index 0000000..4727a9a --- /dev/null +++ b/components/LanguageToggle.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Language } from '../types'; +import { Globe } from 'lucide-react'; + +interface Props { + lang: Language; + setLang: (lang: Language) => void; +} + +const LanguageToggle: React.FC = ({ lang, setLang }) => { + return ( + + ); +}; + +export default LanguageToggle; \ No newline at end of file diff --git a/components/ProjectCard.tsx b/components/ProjectCard.tsx new file mode 100644 index 0000000..94098b2 --- /dev/null +++ b/components/ProjectCard.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { ProjectItem, Language } from '../types'; +import { ExternalLink, Code, Gamepad2, Car, BarChart3 } from 'lucide-react'; + +interface Props { + project: ProjectItem; + lang: Language; +} + +const ProjectCard: React.FC = ({ project, lang }) => { + // Select a placeholder icon fallback + const getIcon = () => { + switch (project.imageType) { + case 'car': return ; + case 'game': return ; + case 'chart': return ; + default: return ; + } + }; + + return ( +
+ {/* Image Area - Increased height for "Rich" feel */} +
+ {project.imageUrl ? ( + {project.title[lang]} + ) : ( +
+ {getIcon()} +
+ )} + + {/* Dark Gradient Overlay for text readability at bottom */} +
+ + {/* Type badge */} +
+ + {project.imageType || 'Dev'} + +
+
+ + {/* Content Area */} +
+

+ {project.title[lang]} +

+

+ {project.description[lang]} +

+ +
+
+ {/* Decorative dots representing tech stack */} +
+
+
+
+ + {project.link && ( + + {project.linkText ? project.linkText[lang] : (lang === 'en' ? 'View details' : '查看详情')} + + + )} +
+
+
+ ); +}; + +export default ProjectCard; \ No newline at end of file diff --git a/components/Section.tsx b/components/Section.tsx new file mode 100644 index 0000000..67bf038 --- /dev/null +++ b/components/Section.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +interface Props { + title: string; + children: React.ReactNode; + className?: string; + id?: string; +} + +const Section: React.FC = ({ title, children, className = "", id }) => { + return ( +
+
+
+

+ {title} +

+
+
+ {children} +
+
+ ); +}; + +export default Section; \ No newline at end of file diff --git a/constants.ts b/constants.ts new file mode 100644 index 0000000..d9fb719 --- /dev/null +++ b/constants.ts @@ -0,0 +1,205 @@ +import { ResumeData } from './types'; + +export const RESUME_DATA: ResumeData = { + name: { + en: "Xiang, Silian", + zh: "项思炼" + }, + title: { + en: "Senior Developer / Simulation Expert", + zh: "高级开发工程师 / 仿真专家" + }, + summary: { + en: "10+ years of experience. 4 years in autonomous driving simulation engine development and management. 6 years in mobile game development (Unity, Cocos2d, 3D graphics). 2 years in data visualization using React. Master of Engineering.", + zh: "10年以上工作经验。4年自动驾驶HMI、仿真开发管理经验。6年Unity、Cocos2d游戏开发管理经验。3年Linux后端开发及大数据Docker部署经验。" + }, + contact: { + mobile: "13810215419", + email: "youmiss@163.com", + wechat: "13810215419" + }, + skills: [ + { en: "Autonomous Driving Simulation (LGSVL, World Sim)", zh: "自动驾驶仿真 (LGSVL, World Sim)" }, + { en: "Unity 3D / Cocos2d Development", zh: "Unity 3D / Cocos2d 开发" }, + { en: "HMI Development (Android/PC)", zh: "HMI 开发 (Android/PC)" }, + { en: "Backend (C++, Java, Python, WebRTC)", zh: "后端 (C++, Java, Python, WebRTC)" }, + { en: "Graphics Programming (OpenGL, Shaders)", zh: "图形编程 (OpenGL, Shaders)" }, + { en: "Frontend (React, TypeScript)", zh: "前端 (React, TypeScript)" } + ], + experience: [ + { + company: { en: "Yi Hai Lan", zh: "亿海蓝" }, + role: { en: "Software Development Engineer", zh: "软件开发工程师" }, + period: "2024/05 - Present", + description: [ + { + en: "Ship Autonomous Driving HMI System: Frontend using Unity (PC/Android), Backend on Orin using C++.", + zh: "轮船自动驾驶HMI系统开发:前端采用Unity(支持PC和Android),后端为Orin采用C++开发。" + }, + { + en: "Remote Driving System Development: WebRTC low-latency video, KCP protocol control integration, multi-platform server architecture.", + zh: "远程驾驶系统开发:WebRTC低延时视频,KCP协议控制指令集成,多端服务器架构设计。" + } + ] + }, + { + company: { en: "He Duo Technology (HoloMatic)", zh: "禾多科技" }, + role: { en: "Lead Developer of Simulation Engine", zh: "可视化、仿真开发负责人" }, + period: "2020/10 - 2024/04", + description: [ + { + en: "LGSVL Secondary Development: Built initial sim engine supporting ground truth perception testing and Python-based PNC scenarios.", + zh: "基于LGSVL进行二次开发,完成仿真引擎初版。支持感知结果真值的自动驾驶仿真测试,通过Python搭建测试场景进行PNC测试。" + }, + { + en: "Sim Engine 2.0 Refactor: Implemented Unity real-time rendering for raw camera input simulation (closed-loop). Full data recording for replay. Decoupled logic from game engine (white-box testing). RL for NPC motion.", + zh: "重构仿真引擎升级到2.0:Unity实时渲染仿真摄像头原始图像(闭环测试);全数据记录与重放;逻辑纯代码实现(白盒化);强化学习控制NPC运动。" + }, + { + en: "Developed in-house OpenScenario parsing engine.", + zh: "自研OpenScenario解析引擎,支持标准化的仿真测试。" + }, + { + en: "Log Sim & World Sim: HIL bench testing, Perception CI/CD, Cloud Docker large-scale concurrency testing.", + zh: "Log Sim回灌测试(Hil台架,感知CI/CD);World Sim仿真测试(云端Docker大规模并发测试)。" + }, + { + en: "HMI Rendering: Optimization for TDA4 platform, proprietary UI framework on 8155 chip.", + zh: "HMI渲染开发:TDA4平台3D实时流畅渲染,自研交互框架在8155芯片实现高清渲染。" + } + ] + }, + { + company: { en: "Independent Game", zh: "独立游戏开发" }, + role: { en: "Game Producer", zh: "独立游戏制作人" }, + period: "2019/11 - 2020/09", + description: [ + { + en: "Smart TV Game: 'Soldier vs. Monster' (Unity). Optimized for low-end hardware.", + zh: "智能电视游戏:《士兵打怪兽》(体感游戏,山寨健身环大冒险),硬件软件全栈开发。" + }, + { + en: "Mobile Education: 'Solid Geometry' AR teaching software.", + zh: "手机教育软件:《立体几何》AR增强现实教学软件。" + } + ] + }, + { + company: { en: "HappyElement (Beijing)", zh: "乐元互动(北京)" }, + role: { en: "AI Engineer", zh: "AI工程师" }, + period: "2018/01 - 2019/04", + description: [ + { + en: "Full stack development, Big Data Analysis & Visualization using React and Druid.", + zh: "全栈开发,大数据分析&可视化(React)。AI驱动游戏运营。" + } + ] + }, + { + company: { en: "Beijing Youyi Mr. Technology", zh: "北京游艺先生科技" }, + role: { en: "Technical Manager / Partner", zh: "技术合伙人" }, + period: "2014/05 - 2017/12", + description: [ + { + en: "Built tech team from scratch. Developed 'Ice and Fire Fantasy' (Cocos2dx + Lua, Java/Redis/MySQL).", + zh: "从零开始搭建技术团队。开发手机游戏《冰火幻想》(客户端Cocos2dx+Lua,服务器Java+Redis+MySQL)。" + }, + { + en: "Virtual Idol Development (UE4 + Motion Capture).", + zh: "虚拟偶像开发(UE4 + 洛伊滕动捕),数值人直播。" + } + ] + }, + { + company: { en: "HappyElement (Beijing)", zh: "乐元互动(北京)" }, + role: { en: "Technical Manager / Main Programmer", zh: "主程序" }, + period: "2011/03 - 2014/05", + description: [ + { + en: "Participated in 'Aquarium', 'Happy Fish'. Main programmer for 'Dragon Legend', 'Warrior World'.", + zh: "参与《开心水族馆》《开心消消乐》开发。《巨龙传说》《指尖英雄》《战姬天下》前后端开发。" + } + ] + }, + { + company: { en: "Tencent", zh: "腾讯" }, + role: { en: "Game Developer (C++)", zh: "C++ 程序" }, + period: "2010/03 - 2011/03", + description: [ + { + en: "Participated in 'Happy Landlord'. Main programmer for 'QQ Matching'.", + zh: "参与《欢乐斗地主》开发,《QQ连连看》主程序。" + } + ] + }, + { + company: { en: "Gameloft", zh: "Gameloft" }, + role: { en: "Lead Mobile Game Programmer", zh: "手机游戏主程序" }, + period: "2008/08 - 2010/03", + description: [ + { + en: "Programmed 'Real Football' and 'Chess' games (Java/Lua).", + zh: "《脑白金》主机游戏Lua,《真实足球》Java,《棒球》C++。" + } + ] + } + ], + education: [ + { + school: { en: "Guizhou University", zh: "贵州大学 (211)" }, + degree: { en: "Master of Engineering", zh: "硕士" }, + major: { en: "Computer Application Technology", zh: "计算机应用技术" }, + period: "2005/09 - 2008/07" + }, + { + school: { en: "Guizhou University", zh: "贵州大学 (211)" }, + degree: { en: "Bachelor of Engineering", zh: "本科" }, + major: { en: "Automation", zh: "自动化" }, + period: "1999/09 - 2003/07" + } + ], + projects: [ + { + title: { en: "U3D Software Rendering Engine", zh: "U3D 软渲染引擎" }, + description: { + en: "Deep dive into Unity rendering pipeline. Implemented Simple_lit and Physically Based Rendering (PBR) shaders in pure C++.", + zh: "深入理解Unity引擎渲染细节。复刻Unity URP Shader效果,实现simple_lit及物理渲染Lit shader。" + }, + link: "https://zhuanlan.zhihu.com/p/688850501", + linkText: { en: "View Article (Zhihu)", zh: "知乎专栏" }, + imageType: "code", + imageUrl: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2564&auto=format&fit=crop" // Abstract 3D + }, + { + title: { en: "Surround View Camera Simulation", zh: "环视摄像头仿真" }, + description: { + en: "Solved 180+ degree FOV rendering issues using spherical projection instead of pinhole models, improving efficiency by 6x. High fidelity fisheye simulation.", + zh: "环视全景相机实时渲染。弃用传统视锥体投影,采用球视体模型统一处理坐标变换和畸变,效率提升6倍。" + }, + link: "https://www.bilibili.com/video/BV16z421f7xH", + linkText: { en: "View Video (Bilibili)", zh: "B站视频" }, + imageType: "car", + imageUrl: "https://images.unsplash.com/photo-1492144534655-ae79c964c9d7?q=80&w=2304&auto=format&fit=crop" // Car + }, + { + title: { en: "LiDAR Point Cloud Visualization", zh: "激光雷达点云数据可视化" }, + description: { + en: "Unity URP pipeline. Encoded point cloud data to GPU via texture. Used Compute Shaders for vertex transformation and coloring, supporting 10M+ points on integrated graphics.", + zh: "采用Unity URP管线。编写Computer shader进行点云可视化,支持集成显卡上千万级点云实时渲染。" + }, + imageType: "chart", + imageUrl: "https://images.unsplash.com/photo-1558494949-ef526b0042a0?q=80&w=2600&auto=format&fit=crop" // Tech/Data + }, + { + title: { en: "AR Solid Geometry", zh: "AR 立体几何" }, + description: { + en: "Augmented Reality teaching software using physical object visual features (no markers required). Occlusion rendering for realistic 3D geometry.", + zh: "不用特定特征图片,直接采用实物视觉效果。采用空间透明遮挡渲染模型来渲染立体几何效果。" + }, + link: "http://www.bilibili.com/video/BV1jW421A7mM", + linkText: { en: "View Video", zh: "B站视频" }, + imageType: "code", + imageUrl: "https://images.unsplash.com/photo-1531297461136-82lwDe43q5DL?q=80&w=2600&auto=format&fit=crop" // AR/Geometry + } + ] +}; \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..8cd384c --- /dev/null +++ b/index.html @@ -0,0 +1,30 @@ + + + + + + Xiang Silian - Resume + + + + + + +
+ + + \ No newline at end of file diff --git a/index.tsx b/index.tsx new file mode 100644 index 0000000..6ca5361 --- /dev/null +++ b/index.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +const rootElement = document.getElementById('root'); +if (!rootElement) { + throw new Error("Could not find root element to mount to"); +} + +const root = ReactDOM.createRoot(rootElement); +root.render( + + + +); \ No newline at end of file diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..c763177 --- /dev/null +++ b/metadata.json @@ -0,0 +1,5 @@ +{ + "name": "Xiang Silian Resume", + "description": "Interactive bilingual resume for Xiang Silian featuring work experience, skills, and portfolio.", + "requestFramePermissions": [] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..8c520e9 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "xiang-silian-resume", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "lucide-react": "^0.555.0", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@types/node": "^22.14.0", + "@vitejs/plugin-react": "^5.0.0", + "typescript": "~5.8.2", + "vite": "^6.2.0" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2c6eed5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "experimentalDecorators": true, + "useDefineForClassFields": false, + "module": "ESNext", + "lib": [ + "ES2022", + "DOM", + "DOM.Iterable" + ], + "skipLibCheck": true, + "types": [ + "node" + ], + "moduleResolution": "bundler", + "isolatedModules": true, + "moduleDetection": "force", + "allowJs": true, + "jsx": "react-jsx", + "paths": { + "@/*": [ + "./*" + ] + }, + "allowImportingTsExtensions": true, + "noEmit": true + } +} \ No newline at end of file diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..5248617 --- /dev/null +++ b/types.ts @@ -0,0 +1,48 @@ +export type Language = 'en' | 'zh'; + +export interface LocalizedString { + en: string; + zh: string; +} + +export interface ExperienceItem { + company: LocalizedString; + role: LocalizedString; + period: string; + description: LocalizedString[]; + location?: LocalizedString; +} + +export interface ProjectItem { + title: LocalizedString; + description: LocalizedString; + link?: string; + linkText?: LocalizedString; + techStack?: string[]; + imageUrl?: string; // Added field for project images + imageType?: 'code' | 'car' | 'game' | 'chart'; // For placeholder selection fallback +} + +export interface EducationItem { + school: LocalizedString; + degree: LocalizedString; + period: string; + major: LocalizedString; +} + +export interface ContactInfo { + mobile: string; + email: string; + wechat: string; +} + +export interface ResumeData { + name: LocalizedString; + title: LocalizedString; + summary: LocalizedString; + contact: ContactInfo; + skills: LocalizedString[]; + experience: ExperienceItem[]; + projects: ProjectItem[]; + education: EducationItem[]; +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..ee5fb8d --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,23 @@ +import path from 'path'; +import { defineConfig, loadEnv } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, '.', ''); + return { + server: { + port: 3000, + host: '0.0.0.0', + }, + plugins: [react()], + define: { + 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY), + 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY) + }, + resolve: { + alias: { + '@': path.resolve(__dirname, '.'), + } + } + }; +});