
通勤2小时+996?用Docker一键部署「工作性价比计算器」,算算你的窝囊费还剩多少价值!
哥们儿/姐妹儿,你们有没有对着工资条想过:你的工作到底值不值?每天两小时通勤、加班加到灵魂出窍、办公室氛围还贼压抑、偶尔只能靠“摸鱼”回血的灵魂… 它到底还值几个钱? 反正我是算不清这笔老板给的“窝囊费”换“生命值”的糊涂账了!
别纠结了!这篇教程手把手教你用 Docker 一键部署一个开源神器 —— Job Worth Calculator (工作性价比计算器)!这可不是简单看工资高低,它能帮你全面分析工作价值:把你的月薪/年薪、工作时长、通勤地狱、摸鱼回血时间、甚至工作环境系数(比如有没有养眼同事?)通通塞进科学公式,噼里啪啦算出个硬核性价比得分!
Docker 部署有啥爽的? 简单!快速!省心!告别复杂环境配置,几条命令就能让你的专属“工作价值评估师”上线。算完你就知道,是老板在“合理定价”你的付出,还是你该考虑让“性价比上班”成为现实了!
花几分钟部署,算个明白账。你的时间和才华,值得被更精准地衡量!👇
📦 项目介绍:工作不止薪水,更看性价比!
📊 工作性价比计算器
这是一款基于 Next.js 构建的开源工具,通过多维度数据模型,科学评估你的工作值不值上。
在线体验地址:
https://job.aabcc.top/
✨ 项目亮点
💰 全面评估:综合薪资、工时、通勤、环境等多个维度
🌏 PPP换算:支持全球 190+ 国家薪资购买力对比
👩🎓 个性化因素:学历和经验会影响得分结果
📱 详细报告:自动生成图文分析结果,可分享/下载
🌐 双语支持:界面支持中英文切换
📱 移动友好:响应式页面,手机也能舒服测
🧮 计算方式一览:数据背后的逻辑
Job Worth Calculator 不是凭空“估价”,而是有一套成熟的评分公式支撑:
✅ 标准化日薪:会根据购买力平价(PPP)调整不同国家的实际薪资水平
✅ 生活平衡指数:考虑工作时间、通勤长度、远程选项等变量
✅ 环境评价加权:如城市环境、工作氛围、团队支持等因素
✅ 学历加分:你的教育背景越好,预期值越高
✅ 经验校准:结合工作年限优化评估模型
🖥️ 如何使用:简单几步,测算你的“打工值”
部署完成后,你可以在浏览器中访问这个计算器,使用步骤如下:
输入你的年薪(税前/税后)
选择工作国家或地区
填写详细信息:
每周工作天数
每天工作时长
通勤单程时长
是否远程办公
指定工作环境:
所在城市
办公条件(如是否拥挤、氛围友好等)
团队协作程度
输入个人背景:
学历(如大专、本科、硕士等)
工作经验(年限)
查看结果:
得到一个“工作性价比分数”
并附带详细解释 + 建议
生成报告:
一键生成 PDF 报告
支持复制链接或下载保存
Docker部署 Job Worth Calculator 教程
以下示例基于飞牛NAS系统演示,其他系统请确保已安装最新版本 Docker 和 Docker Compose。
1. 连接 NAS 并准备目录
开启飞牛NAS的 SSH 功能,用终端连接,并切换为 root 用户。
新建项目文件夹,复制完整路径。
终端内进入该目录(请替换为实际路径):
# 将 /vol1/1000/job 换成你自己实际的文件夹路径 cd /vol1/1000/job
2. 获取项目代码
git clone https://github.com/Zippland/worth-calculator.git
3. 编写 Dockerfile
编辑 Dockerfile:
vi Dockerfile
按字母
i
键进入编辑模式,复制下面的配置文件,粘贴到终端,按Esc
键退出编辑模式,输入:wq
保存并退出。# 基础镜像:Node.js 18 + Alpine FROM node:18-alpine # 工作目录 WORKDIR /app # 复制依赖文件并安装依赖 COPY package*.json ./ RUN npm install # 复制全部代码 COPY . . # 构建生产版本 RUN npm run build # 暴露端口 EXPOSE 3000 # 启动 Next.js CMD ["npm", "start"]
4. 编写 docker-compose.yml
编辑 docker-compose.yml:
vi docker-compose.yml
按字母
i
键进入编辑模式,复制并修改下面的配置文件,粘贴到终端,按Esc
键退出编辑模式,输入:wq
保存并退出。(排版太挤的就先粘贴到文本文件内,修改后再使用,灵活应变。)
services: worth-calculator: build: . container_name: worth-calculator ports: - "3000:3000" # 左侧的3000端口是容器外部访问端口,可自行修改。 restart: always
5. 关闭自动跳转限制
在该项目中作者设置了自动跳转到作者的域名,我们想要本地搭建自己的,所以需要禁用/改成我们自己的域名。
编辑
components/calculator.tsx
:vi components/calculator.tsx
在
components/calculator.tsx
第 402-404 行(20250716这个日期内的版本),这段代码强制将你跳转到 https://worthjob.zippland.com,只允许本地调试。找到约第 400 行附近的以下代码,注释或删除(演示是已经注释掉了),想对外发布并跳转到自己的域名可以自行修改。
按字母i
键进入编辑模式,修改默认的配置文件,按Esc
键退出编辑模式,输入:wq
保存并退出。// const hostname = window.location.hostname; // if (hostname !== 'worthjob.zippland.com' && hostname !== 'localhost' && !hostname.includes('127.0.0.1')) { // window.location.href = 'https://worthjob.zippland.com' + window.location.pathname; // }
6. 构建并启动容器
在项目根目录执行(当前路径下):
docker compose up -d --build
构建过程可能较长,请耐心等待。
7. 查看运行状态
查看正在运行的项目容器:
docker compose ps 或 docker-compose ps
查看正在运行的项目容器实时日志,按
Ctrl+C
中断查看:docker compose logs -f 或 docker-compose logs -f
8. 访问Job Worth Calculator应用
打开浏览器,以NAS的IP+设置的端口号进行访问。
以本机为例:http://192.168.2.5:3000/该工具当前支持多种语言,按照提示我们来试一下,计算一下牛马的工作性价比。
拉到底部点击 查看我的工作性价比报告
不忍直视啊兄弟们,要不提桶跑路吧。
自定义修改指南
🔄 每一次修改完后,别忘了重建项目,改造出属于自己的工作价值计算!
🛠 修改弹窗广告
这个是页面打开的弹窗广告区域,你可以直接改这里的内容:
文件路径:
components/VerticalAd.tsx
下面是加上详细注释的文件内容,方便你手动修改。
'use client'; import { useState, useEffect } from 'react'; import Image from 'next/image'; import { X } from 'lucide-react'; // 引入关闭图标 import { isAdEnabled, getAdLink } from '@/utils/adConfig'; // 获取广告启用状态和跳转地址 export default function VerticalAd() { const [isVisible, setIsVisible] = useState(false); // 控制是否显示弹窗 const [imageExists, setImageExists] = useState(false); // 检查广告图是否存在 // 加载图片并检查是否存在 useEffect(() => { const img = new window.Image(); img.onload = () => setImageExists(true); img.onerror = () => setImageExists(false); img.src = '/mainpage.png'; // ✅ 替换这里即可更换图片,比如 '/myad.jpg' 或网络图 'https://xx.com/ad.jpg' }, []); // 检查是否启用广告 + 图片存在才显示 useEffect(() => { if (!isAdEnabled() || !imageExists) { return; } // 延迟 1000ms 后显示弹窗广告 const timer = setTimeout(() => { setIsVisible(true); }, 1000); return () => clearTimeout(timer); }, [imageExists]); // 点击关闭按钮逻辑 const handleClose = () => { setIsVisible(false); }; // 广告不显示则返回 null if (!isVisible) return null; return ( <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4"> <div className="relative"> {/* 关闭按钮 */} <button onClick={handleClose} className="absolute -top-2 -right-2 z-10 rounded-full bg-white p-1 shadow-lg hover:bg-gray-100 transition-colors" aria-label="关闭广告" > <X className="h-5 w-5 text-gray-700" /> </button> {/* 广告区域,宽高比 3:5 */} <a href={getAdLink()} // ✅ 修改广告跳转地址:修改 utils/adConfig.ts 中的 getAdLink 函数 target="_blank" rel="noopener noreferrer" className="block relative bg-gray-200 rounded-lg overflow-hidden shadow-xl hover:shadow-2xl transition-shadow duration-300 cursor-pointer" style={{ width: 'min(300px, 60vw)', aspectRatio: '3/5' }} > {/* 弹窗广告图片 */} <Image src="/mainpage.png" // ✅ 替换为你自己的图片路径(public 文件夹内或网络地址) alt="广告" fill className="object-cover" priority /> </a> </div> </div> ); }
✏️ 如何手动替换广告内容?
✅ 最终效果
弹窗广告将在页面加载 1 秒后显示
点击广告图跳转到你设置的推广地址
你可随时手动关闭或修改图片路径、延迟时间
🛠 修改页面顶部广告
这个是页面最上方的横幅区域,你可以直接改这里的内容:
文件路径:
components/HorizontalBanner.tsx
下面是加上详细注释的文件内容,方便你手动修改。
'use client'; // 启用 Next.js 的客户端组件模式(才能使用 useEffect) import { useState, useEffect } from 'react'; import Image from 'next/image'; import { isAdEnabled, getAdLink } from '@/utils/adConfig'; // 从广告配置文件引入控制函数 // 顶部横幅广告组件 export default function HorizontalBanner() { const [imageExists, setImageExists] = useState(false); // 控制是否显示广告图 useEffect(() => { // 加载图片,判断是否存在 banner.png const img = new window.Image(); img.onload = () => setImageExists(true); // 加载成功 img.onerror = () => setImageExists(false); // 加载失败 img.src = '/banner.png'; // ✅ 你只需要替换这个路径为你自己的图片,例如 '/mybanner.jpg' }, []); // 如果广告功能未开启(比如设置为 false),则不显示 if (!isAdEnabled()) { return null; } // 如果图片加载失败,也不显示 if (!imageExists) { return null; } return ( <div className="w-full bg-gray-50 dark:bg-gray-900 py-2"> <div className="max-w-4xl mx-auto px-4"> {/* 横幅容器,点击后跳转到广告链接 */} <a href={getAdLink()} // ✅ 广告跳转地址:你只需要修改 utils/adConfig.ts 中的 getAdLink() 返回值 target="_blank" rel="noopener noreferrer" className="block relative w-full bg-gray-200 dark:bg-gray-800 overflow-hidden hover:opacity-90 transition-opacity duration-300 cursor-pointer rounded-lg shadow-sm" style={{ aspectRatio: '7/1' // 设置为横向长条比例(7:1) }} > {/* 显示广告图片 */} <Image src="/banner.png" // ✅ 你也可以替换为如 'https://yourdomain.com/ad.jpg' alt="横幅广告" fill // 全覆盖模式 className="object-cover" priority // 提前加载 /> </a> </div> </div> ); }
🛠 页面的标签标题
这个是页面的标签标题,你可以直接改这里的内容:
文件路径:
app/layout.tsx
请将
app/layout.tsx
中这段原始代码:export const metadata: Metadata = { title: { default: "Job Worth Calculator", template: "%s | Job Worth Calculator" }, ... };
参考以下内容修改(含详细中文注释):
export const metadata: Metadata = { title: { // 设置默认标签标题,当页面没有单独指定 title 时使用 default: "Job Worth Calculator", // 设置标题模板,会将页面单独设置的 title 插入到 %s 位置 // 例如:子页面 title 为 "城市对比",最终显示为 "城市对比 | Job Worth Calculator" // 如果希望所有页面统一显示同一个标题,可删除这一项(template) template: "%s | Job Worth Calculator" }, // 配置不同语言对应的路径(用于多语言切换,SEO) alternates: { languages: { "en-US": "/en", // 英文路径映射为 /en "zh-CN": "/", // 中文默认路径为 / }, }, // 页面描述,供搜索引擎/社交媒体预览使用 description: "这b班上得值不值 - 计算你的工作性价比 | Job Worth Calculator - Calculate your job's value", // Google Search Console 的站点验证代码(用来验证你拥有这个网站) // 如果不使用 Google 站长工具,可以删除这部分 verification: { google: "_OQGiIpYz87USAsgJV2C07-JJhQ8myV_4GoM1kDjFic", }, };
或者改成下面的符合SEO优化的内容
// 设置页面基础的 SEO 元数据 export const metadata: Metadata = { // 浏览器标签标题(统一显示,不拼接模板) title: "我的收入价值评估器", // 页面描述:用于搜索引擎摘要展示 description: "这b班上得值不值 - 计算你的工作性价比", // 支持多语言 URL(可选) alternates: { languages: { "en-US": "/en", "zh-CN": "/", }, }, // Google 搜索站长平台的验证字符串(如无需求可删除) verification: { google: "_OQGiIpYz87USAsgJV2C07-JJhQ8myV_4GoM1kDjFic", }, };
🔄 修改后效果
浏览器标签统一显示:
我的收入价值评估器
子页面不会再拼接
%s | Job Worth Calculator
保留了 SEO 描述和语言切换支持
可随时扩展
openGraph
、twitter
等字段来提升分享效果
🛠 页面的页脚跳转图标
这个是页面的页脚跳转图标,你可以直接改这里的内容:
文件路径:
app/layout.tsx
请将
app/layout.tsx
中的对应信息更改(贴出完整的带注释的原配置方便你修改)// 导入 Next.js 的类型定义 Metadata,用于页面元信息配置 import type { Metadata } from "next"; // 从本地引入字体功能 import localFont from "next/font/local"; // 引入全局样式 import "./globals.css"; // 引入语言上下文提供者,用于实现语言切换功能 import { LanguageProvider } from "@/components/LanguageContext"; // 引入 Vercel 分析组件(自动收集访问数据) import { Analytics } from "@vercel/analytics/next"; // 加载本地自定义字体 Geist Sans const geistSans = localFont({ src: "./fonts/GeistVF.woff", // 字体文件路径 variable: "--font-geist-sans", // 自定义 CSS 变量名,用于后续 className 应用 weight: "100 900", // 支持的字体粗细范围 }); // 加载本地自定义字体 Geist Mono(等宽字体) const geistMono = localFont({ src: "./fonts/GeistMonoVF.woff", variable: "--font-geist-mono", weight: "100 900", }); // 配置网站的元信息(SEO 相关)供 Next.js 使用 export const metadata: Metadata = { title: { default: "Job Worth Calculator", // 默认标题 template: "%s | Job Worth Calculator", // 页面标题模板(用于子页面) }, alternates: { languages: { "en-US": "/en", // 英文路径映射 "zh-CN": "/", // 中文路径映射 }, }, description: "这b班上得值不值 - 计算你的工作性价比 | Job Worth Calculator - Calculate your job's value", // 页面描述 verification: { google: "_OQGiIpYz87USAsgJV2C07-JJhQ8myV_4GoM1kDjFic", // Google 搜索站长平台的验证字符串(如无需求可删除) }, }; // 根布局组件,所有页面会包裹在这个 layout 中 export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; // 接收子组件 }>) { return ( <html lang="en"> {/* 设置 HTML 页面语言 */} <head> {/* Google 网站验证元标签 */} <meta name="google-site-verification" content="_OQGiIpYz87USAsgJV2C07-JJhQ8myV_4GoM1kDjFic" /> {/* 百度网站验证元标签 */} <meta name="baidu-site-verification" content="codeva-pEoMg5F0Cv" /> {/* Google AdSense 广告脚本(需替换为你自己的广告位 ID) */} <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7207313144293144" crossOrigin="anonymous"></script> {/* 不蒜子网页访问统计脚本 */} <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script> </head> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} // 应用自定义字体和抗锯齿优化 > {/* 多语言上下文提供者包裹整个页面 */} <LanguageProvider> {children} </LanguageProvider> {/* Vercel 网站访问分析组件 */} <Analytics /> {/* 用于页面底部预留空间(比如避免内容被 footer 遮挡) */} <div className="pb-8"></div> {/* 页面底部导航栏 */} <footer className="w-full py-3 border-t bg-white/90 dark:bg-gray-900/80 dark:border-gray-800/50"> <div className="max-w-4xl mx-auto px-4"> <div className="flex justify-center items-center gap-6 mb-2"> {/* 链接 1:OfferSelect 工具,工作比价工具 */} <a href="https://offerselect.zippland.com/" target="_blank" rel="noopener noreferrer" className="group relative flex flex-col items-center" > <div className="w-10 h-10 flex items-center justify-center rounded-full bg-gradient-to-br from-yellow-400 to-orange-500 shadow-sm transform transition-all duration-200 group-hover:scale-110"> {/* 图标 */} <svg ...>...</svg> </div> <span className="text-xs mt-1.5 text-gray-700 dark:text-gray-300 font-medium">OfferSelect</span> </a> {/* 链接 2:城市对比工具 */} <a href="https://citycompare.zippland.com/" ... > <div className="..."> {/* 图标背景及动画效果 */} </div> <span className="...">城市对比</span> </a> {/* 链接 3:SnapSolver,AI 自动笔试答题工具 */} <a href="https://snapsolver.zippland.com/" ... > <div className="..."> {/* 图标背景及动画效果 */} </div> <span className="...">AI笔试</span> </a> {/* 链接 4:拼豆图纸生成工具 */} <a href="https://perlerbeads.zippland.com/" ... > <div className="..."> {/* 图标背景及动画效果 */} </div> <span className="...">拼豆图纸</span> </a> </div> {/* 页脚底部文字:版权或宣传 */} <div className="text-center"> <span className="text-[10px] text-gray-400 dark:text-gray-500">更多实用工具 by zippland.com</span> </div> </div> </footer> </body> </html> ); }
🔄 修改后重新构建
每次修改完源码,确保你在项目根目录(
worth-calculator
)运行,这一步骤使用npm构建镜像需要的时间较长,耐心等待:docker compose up -d --build
查看正在运行的项目容器
docker compose ps 或 docker-compose ps
查看正在运行的项目容器实时日志,按
Ctrl+C
中断查看。docker compose logs -f
确保改动生效。
🪟转换为静态文件
如果你不想使用Docker运行它,或者觉得构建成docker镜像太麻烦,可以把它转变为静态文件,使用群晖NAS的Web Station进行创建网页。
简单描述一下逻辑
在群晖的套件中心安装Node.js(测试安装v22版本)
创建一个文件夹,将你修改后的源码放进去,终端内进入该文件夹的路径。
执行命令安装npm(需要的时间较长,取决于你的网络质量。)
npm install
执行命令,将源码转变成静态文件。
./node_modules/.bin/next build && ./node_modules/.bin/next export
查看并列出转变后的文件
ls -l out/
转变之后当前文件夹内会多出三个文件夹,修改源码后重新构建不需要删除.next和node_modules文件夹(免得重新下载工具,浪费时间。)
.next
和node_modules
是构建工具的文件out
是存放转变成静态文件的文件夹打开群晖的Web Station,创建网页服务>静态网页>文件位置选择out文件夹。
网络门户>设置指定的端口,然后访问即可>路由器端口映射,可建设网站。如果你不会修改源码可以下载cursor软件,进行AI编程,你说它改。
相关地址
GitHub项目地址:https://github.com/Zippland/worth-calculator
部署顺利,期待你用这个工具精确计算出自己的“打工值”!玩转工作价值计算!
文末
👇👇👇
- 感谢你赐予我前进的力量