diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..b3c5919 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,41 @@ +name: Deploy Resume + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: aliyun + steps: + - name: Setup Environment + run: | + sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories + apk add --no-cache docker-cli + + - name: Checkout + run: | + rm -rf /tmp/resume + git clone --depth 1 -b main \ + http://47.121.181.112:3000/wonder/resume.git \ + /tmp/resume + + - name: Build Docker Image + run: | + docker build \ + -t resume-site:latest \ + /tmp/resume + + - name: Deploy Container + run: | + docker stop resume-site 2>/dev/null || true + docker rm resume-site 2>/dev/null || true + docker run -d \ + --name resume-site \ + --restart unless-stopped \ + -p 8080:80 \ + resume-site:latest + + - name: Cleanup Dangling Images + run: docker image prune -f diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e1472c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM nginx:alpine + +# 复制 Nginx 配置 +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# 复制静态资源 +COPY css/ /usr/share/nginx/html/css/ +COPY img/ /usr/share/nginx/html/img/ +COPY resume/ /usr/share/nginx/html/resume/ +COPY other/ /usr/share/nginx/html/other/ + +# 暴露端口 +EXPOSE 80 + +# 启动 Nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md index e69de29..1e30809 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,49 @@ +# 何朝晖 - 简历项目 + +在线简历部署项目,支持多岗位简历,使用 Docker + Nginx 部署,Gitea Actions 自动化 CI/CD。 + +## 目录结构 + +``` +resume/ +├── .gitea/workflows/deploy.yml # Gitea Actions CI/CD 配置 +├── Dockerfile # Docker 构建文件 +├── nginx.conf # Nginx 路由配置 +├── css/ +│ └── resume.css # 全局样式(所有简历共享) +├── img/ # 公共图片资源(所有简历共享) +├── resume/ +│ └── index.html # 主简历 → /resume +└── other/ + ├── index.html # 导航页 → /other + ├── infra-engineer/ + │ └── index.html # 基础架构工程师简历 → /other/infra-engineer + └── security-engineer/ + └── index.html # 网络安全工程师简历 → /other/security-engineer +``` + +## 访问地址 + +| 页面 | 地址 | +|------|------| +| 主简历 | http://47.121.181.112:8080/resume/ | +| 导航页 | http://47.121.181.112:8080/other/ | +| 基础架构工程师 | http://47.121.181.112:8080/other/infra-engineer/ | +| 网络安全工程师 | http://47.121.181.112:8080/other/security-engineer/ | + +## 添加新岗位简历 + +1. 在 `other/` 下新建目录,如 `other/frontend-dev/` +2. 复制任意一份已有简历作为模板 +3. 修改目标职位、技术栈标签、线上简历链接等 +4. 更新 `other/index.html` 导航页,添加新简历链接 +5. 更新 `nginx.conf`,添加对应的 location 块 +6. 推送到 main 分支,自动部署 + +## 部署方式 + +推送到 `main` 分支后,Gitea Actions 自动执行: +1. 克隆仓库 +2. 构建 Docker 镜像(nginx:alpine) +3. 停止旧容器,启动新容器 +4. 映射端口 8080 → 80 diff --git a/convert.js b/convert.js deleted file mode 100644 index 3093f66..0000000 --- a/convert.js +++ /dev/null @@ -1,42 +0,0 @@ -const { chromium } = require('playwright'); -const path = require('path'); - -async function htmlToJpg() { - // Launch browser with custom library path - const browser = await chromium.launch({ - env: { - ...process.env, - LD_LIBRARY_PATH: '/tmp/libs/usr/lib/x86_64-linux-gnu:' + (process.env.LD_LIBRARY_PATH || '') - } - }); - const page = await browser.newPage(); - - // Set viewport to A4 size (210mm x 297mm at 96dpi) - await page.setViewportSize({ width: 794, height: 1123 }); - - // Load the HTML file - const htmlPath = path.join(__dirname, 'resume.html'); - await page.goto(`file://${htmlPath}`, { waitUntil: 'networkidle' }); - - // Get the actual page height - const bodyHeight = await page.evaluate(() => document.body.scrollHeight); - - // Set viewport to full page height - await page.setViewportSize({ width: 794, height: bodyHeight }); - - // Take a full-page screenshot - const outputPath = path.join(__dirname, 'resume_output.jpg'); - await page.screenshot({ - path: outputPath, - fullPage: true, - type: 'jpeg', - quality: 95, - }); - - console.log(`Screenshot saved to: ${outputPath}`); - console.log(`Page dimensions: 794 x ${bodyHeight}`); - - await browser.close(); -} - -htmlToJpg().catch(console.error); diff --git a/convert.py b/convert.py deleted file mode 100644 index e891afd..0000000 --- a/convert.py +++ /dev/null @@ -1,63 +0,0 @@ -import subprocess -import sys - -# Install required packages -def install_packages(): - packages = ['imgkit', 'Pillow'] - for package in packages: - try: - __import__(package.lower().replace('-', '_')) - except ImportError: - print(f"Installing {package}...") - subprocess.check_call([sys.executable, "-m", "pip", "install", package]) - -install_packages() - -import imgkit -from PIL import Image -import os - -def html_to_jpg(html_file, output_file, width=2478): - """Convert HTML file to high-quality JPG""" - - # First, check if wkhtmltopdf/wkhtmltoimage is installed - try: - subprocess.run(['wkhtmltoimage', '--version'], capture_output=True, check=True) - except FileNotFoundError: - print("wkhtmltoimage not found. Please install it:") - print("sudo apt-get install wkhtmltopdf") - print("Or download from: https://wkhtmltopdf.org/downloads.html") - return False - - # Convert HTML to JPG using imgkit - options = { - 'format': 'jpg', - 'quality': 100, - 'width': width, - 'enable-local-file-access': '', - 'encoding': 'UTF-8', - 'no-stop-slow-scripts': '', - } - - try: - imgkit.from_file(html_file, output_file, options=options) - print(f"Successfully converted {html_file} to {output_file}") - - # Verify the output - with Image.open(output_file) as img: - print(f"Output image size: {img.size}") - print(f"Output image mode: {img.mode}") - - return True - except Exception as e: - print(f"Error converting HTML to JPG: {e}") - return False - -if __name__ == "__main__": - html_file = "/home/wonder/code/resume/resume.html" - output_file = "/home/wonder/code/resume/resume_output.jpg" - - if html_to_jpg(html_file, output_file): - print(f"\nOutput saved to: {output_file}") - else: - print("Conversion failed!") diff --git a/resume.css b/css/resume.css similarity index 100% rename from resume.css rename to css/resume.css diff --git a/download_font.js b/download_font.js deleted file mode 100644 index 40314fb..0000000 --- a/download_font.js +++ /dev/null @@ -1,38 +0,0 @@ -const https = require('https'); -const fs = require('fs'); -const path = require('path'); - -function downloadFile(url, dest) { - return new Promise((resolve, reject) => { - const file = fs.createWriteStream(dest); - https.get(url, (response) => { - response.pipe(file); - file.on('finish', () => { - file.close(); - resolve(); - }); - }).on('error', (err) => { - fs.unlink(dest, () => {}); - reject(err); - }); - }); -} - -async function downloadFonts() { - const fontsDir = path.join(__dirname, 'fonts'); - - // Download Noto Sans SC Regular - const regularUrl = 'https://fonts.gstatic.com/s/notosanssc/v37/k3kCo84MPvpLmixcA63oeAL7Iqp5IZJF9bmaG9_FnYxNbPzS5HE.ttf'; - const boldUrl = 'https://fonts.gstatic.com/s/notosanssc/v37/k3kCo84MPvpLmixcA63oeAL7Iqp5IZJF9bmaG9_EnYxNbPzS5HE.ttf'; - - try { - await downloadFile(regularUrl, path.join(fontsDir, 'NotoSansSC-Regular.ttf')); - console.log('Downloaded NotoSansSC-Regular.ttf'); - await downloadFile(boldUrl, path.join(fontsDir, 'NotoSansSC-Bold.ttf')); - console.log('Downloaded NotoSansSC-Bold.ttf'); - } catch (err) { - console.error('Error downloading fonts:', err); - } -} - -downloadFonts(); diff --git a/img/lark.svg b/img/lark.svg new file mode 100644 index 0000000..73925dc --- /dev/null +++ b/img/lark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/飞书.svg:Zone.Identifier b/img/飞书.svg:Zone.Identifier new file mode 100644 index 0000000..d6c1ec6 Binary files /dev/null and b/img/飞书.svg:Zone.Identifier differ diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..93bb937 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,35 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # 主简历 + location /resume/ { + alias /usr/share/nginx/html/resume/; + try_files $uri $uri/ /resume/index.html; + } + + # 其他简历导航 + location /other/ { + alias /usr/share/nginx/html/other/; + try_files $uri $uri/ /other/index.html; + } + + # 基础架构工程师简历 + location /other/infra-engineer/ { + alias /usr/share/nginx/html/other/infra-engineer/; + try_files $uri $uri/ /other/infra-engineer/index.html; + } + + # 网络安全工程师简历 + location /other/security-engineer/ { + alias /usr/share/nginx/html/other/security-engineer/; + try_files $uri $uri/ /other/security-engineer/index.html; + } + + # 默认路由(重定向到主简历) + location / { + return 301 /resume/; + } +} diff --git a/other/index.html b/other/index.html new file mode 100644 index 0000000..979f308 --- /dev/null +++ b/other/index.html @@ -0,0 +1,114 @@ + + +
+ + +