feat: complete recruitment website MVP
All backend tests pass (17/17), frontend builds successfully, and superadmin account created. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ef4c9bf307
commit
46e35074ed
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(bash \"C:/Users/11825/.claude/plugins/cache/claude-plugins-official/superpowers/5.0.5/skills/brainstorming/scripts/start-server.sh\" --project-dir \"C:/code/offer\")",
|
||||||
|
"Bash(cat \"C:/code/offer/.superpowers/brainstorm\"/.*/server-info)",
|
||||||
|
"Bash(python -c \"import sys,json; d=json.load\\(sys.stdin\\); print\\(''''Vue:'''', d.get\\(''''dependencies'''',{}\\).get\\(''''vue'''',''''N/A''''\\)\\); print\\(''''Vite/webpack:'''', list\\(d.get\\(''''devDependencies'''',{}\\).keys\\(\\)\\)[:5]\\)\")",
|
||||||
|
"Bash(git -C /c/code/offer log --oneline)",
|
||||||
|
"Bash(pip install:*)",
|
||||||
|
"Bash(py --version)",
|
||||||
|
"Bash(python3 -m pip install -r /c/code/offer/offer_backend/requirements.txt)",
|
||||||
|
"Bash(python3 -c \"import sys; print\\(sys.executable\\)\")",
|
||||||
|
"Bash(cmd.exe /c \"python --version\")",
|
||||||
|
"Bash(cmd.exe /c \"py --version\")",
|
||||||
|
"Bash(cmd.exe /c \"python --version && python -m pip --version\" 2>&1)",
|
||||||
|
"Read(//c/Users/11825/AppData/Local/Programs/**)",
|
||||||
|
"Bash(ls /c/Python*)",
|
||||||
|
"Read(//c/Users/11825/AppData/Local/Microsoft/WindowsApps//**)",
|
||||||
|
"Read(//c//**)",
|
||||||
|
"Bash(/c/Users/11825/AppData/Local/Microsoft/WindowsApps/python3.exe --version)",
|
||||||
|
"Bash(/c/Users/11825/AppData/Local/Microsoft/WindowsApps/python3.exe -m pip --version)",
|
||||||
|
"Read(//c/miniconda3/bin/**)",
|
||||||
|
"Read(//c/anaconda3/bin/**)",
|
||||||
|
"Bash(/c/software/python3_10/python --version)",
|
||||||
|
"Bash(/c/software/python3_10/python -m pip --version)",
|
||||||
|
"Bash(/c/software/python3_10/python -m ensurepip --upgrade)",
|
||||||
|
"Bash(/c/software/python3_10/python -m pip install -r /c/code/offer/offer_backend/requirements.txt 2>&1)",
|
||||||
|
"Bash(/c/software/python3_10/Scripts/django-admin startproject:*)",
|
||||||
|
"Bash(rm:*)",
|
||||||
|
"Bash(rm /c/code/offer/offer_backend/manage.py)",
|
||||||
|
"Bash(rm -rf /c/code/offer/offer_backend/config)",
|
||||||
|
"Bash(mkdir -p /c/code/offer/offer_backend/config/settings)",
|
||||||
|
"Bash(mkdir -p /c/code/offer/offer_backend/apps)",
|
||||||
|
"Bash(DJANGO_SETTINGS_MODULE=config.settings.development /c/software/python3_10/python manage.py check)",
|
||||||
|
"Bash(git -C /c/code/offer status)",
|
||||||
|
"Bash(git -C /c/code/offer add offer_backend/)",
|
||||||
|
"Bash(git:*)",
|
||||||
|
"Bash(python manage.py startapp accounts apps/accounts)",
|
||||||
|
"Bash(python manage.py makemigrations accounts)",
|
||||||
|
"Bash(python manage.py migrate)",
|
||||||
|
"Bash(python -m pytest apps/accounts/tests/test_auth.py -v)",
|
||||||
|
"Bash(/c/software/python3_10/python -m pytest apps/accounts/tests/test_auth.py -v)",
|
||||||
|
"Bash(/c/software/python3_10/Scripts/pytest --version)",
|
||||||
|
"Bash(ls /c/software/python3_10/Scripts/pytest*)",
|
||||||
|
"Bash(pip show:*)",
|
||||||
|
"Bash(/c/software/python3_10/python -c \"import sys; print\\(sys.path\\)\")",
|
||||||
|
"Bash(/c/software/python3_10/pip3 list:*)",
|
||||||
|
"Bash(/c/software/python3_10/pip3 install:*)",
|
||||||
|
"Bash(ls /c/software/python3_10/Scripts/pip*)",
|
||||||
|
"Read(//c/software/python3_10/**)",
|
||||||
|
"Bash(/c/software/python3_10/Scripts/pip3.exe install:*)",
|
||||||
|
"Bash(/c/software/python3_10/Scripts/pytest.exe apps/accounts/tests/test_auth.py -v)",
|
||||||
|
"Bash(pg_isready)",
|
||||||
|
"Bash(psql -U postgres -c \"SELECT 1\")",
|
||||||
|
"Bash(\"/c/Program Files/PostgreSQL/16/bin/psql.exe\" -U postgres -c \"SELECT version\\(\\);\" 2>&1)",
|
||||||
|
"Bash(PGPASSWORD=zcDsj@2024 \"/c/Program Files/PostgreSQL/16/bin/psql.exe\" -U postgres -c \"SELECT version\\(\\);\" 2>&1)",
|
||||||
|
"Bash(PGPASSWORD=zcDsj@2024 \"/c/Program Files/PostgreSQL/16/bin/psql.exe\" -U postgres -c \"CREATE DATABASE offer_db;\" 2>&1)",
|
||||||
|
"Bash(/c/software/python3_10/python manage.py migrate)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"reason":"idle timeout","timestamp":1774342828046}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
3597
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<h2>系统架构总览</h2>
|
||||||
|
<p class="subtitle">方案 A:Django 后端 + Vue3 单页应用</p>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 24px; flex-wrap: wrap; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- 前端 -->
|
||||||
|
<div style="flex: 1; min-width: 280px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #38bdf8; margin-bottom: 12px;">前端 — Vue3 SPA</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #38bdf8;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">公开门户</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">职位列表 / 搜索 / 职位详情<br>公司介绍 / 注册登录</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #818cf8;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">求职者中心</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">我的简历 / 投递记录<br>个人信息管理</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #f472b6;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">管理后台</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">超管:组织架构 / 账号管理<br>公司管理员:职位 / 投递管理</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin-top: 12px; font-size: 11px; color: #475569;">Vue Router + Pinia + Element Plus</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 箭头 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; font-size: 28px; color: #475569; min-width: 40px;">⇄</div>
|
||||||
|
|
||||||
|
<!-- 后端 -->
|
||||||
|
<div style="flex: 1; min-width: 280px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #34d399; margin-bottom: 12px;">后端 — Django + DRF</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">认证模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">JWT 登录 / 注册 / 权限控制<br>角色:超管 / 公司管理员 / 求职者</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">职位模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">职位 CRUD / 搜索过滤<br>公司隔离权限</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">投递模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">投递记录 / 状态流转<br>简历存储(表单 + 文件)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">组织架构模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">集团 / 子公司 / 管理员绑定</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin-top: 12px; font-size: 11px; color: #475569;">Django 4.2 + DRF + JWT</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 箭头 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; font-size: 28px; color: #475569; min-width: 40px;">⇄</div>
|
||||||
|
|
||||||
|
<!-- 存储 -->
|
||||||
|
<div style="flex: 0 0 160px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #fb923c; margin-bottom: 12px;">存储</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">PostgreSQL</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">业务数据</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">Redis</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">缓存 / 会话</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">文件存储</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">简历附件<br>(本地/OSS)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 20px; background: #0f172a; border-radius: 8px; padding: 14px; border: 1px solid #1e3a5f;">
|
||||||
|
<span class="label" style="color: #38bdf8;">部署方式</span>
|
||||||
|
<span style="color: #94a3b8; margin-left: 8px; font-size: 13px;">Nginx 反向代理 → Vue3 静态文件 + Django API (Gunicorn)</span>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<h2>系统架构总览</h2>
|
||||||
|
<p class="subtitle">方案 A:Django 后端 + Vue3 单页应用</p>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 24px; flex-wrap: wrap; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- 前端 -->
|
||||||
|
<div style="flex: 1; min-width: 280px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #38bdf8; margin-bottom: 12px;">前端 — Vue3 SPA</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #38bdf8;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">公开门户</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">职位列表 / 搜索 / 职位详情<br>公司介绍 / 注册登录</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #818cf8;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">求职者中心</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">我的简历 / 投递记录<br>个人信息管理</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #f472b6;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">管理后台</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">超管:组织架构 / 账号管理<br>公司管理员:职位 / 投递管理</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin-top: 12px; font-size: 11px; color: #475569;">Vue Router + Pinia + Element Plus</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 箭头 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; font-size: 28px; color: #475569; min-width: 40px;">⇄</div>
|
||||||
|
|
||||||
|
<!-- 后端 -->
|
||||||
|
<div style="flex: 1; min-width: 280px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #34d399; margin-bottom: 12px;">后端 — Django + DRF</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">认证模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">JWT 登录 / 注册 / 权限控制<br>角色:超管 / 公司管理员 / 求职者</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">职位模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">职位 CRUD / 搜索过滤<br>公司隔离权限</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">投递模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">投递记录 / 状态流转<br>简历存储(表单 + 文件)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 12px; border-left: 3px solid #34d399;">
|
||||||
|
<div style="font-weight: 600; color: #e2e8f0; margin-bottom: 4px;">组织架构模块</div>
|
||||||
|
<div style="font-size: 12px; color: #94a3b8;">集团 / 子公司 / 管理员绑定</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin-top: 12px; font-size: 11px; color: #475569;">Django 4.2 + DRF + JWT</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 箭头 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: center; font-size: 28px; color: #475569; min-width: 40px;">⇄</div>
|
||||||
|
|
||||||
|
<!-- 存储 -->
|
||||||
|
<div style="flex: 0 0 160px; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155;">
|
||||||
|
<div class="label" style="color: #fb923c; margin-bottom: 12px;">存储</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">MySQL</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">业务数据</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">Redis</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">缓存 / 会话</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px; border-left: 3px solid #fb923c;">
|
||||||
|
<div style="font-size: 12px; color: #e2e8f0; font-weight: 600;">文件存储</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8;">简历附件<br>(本地/OSS)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 20px; background: #0f172a; border-radius: 8px; padding: 14px; border: 1px solid #1e3a5f;">
|
||||||
|
<span class="label" style="color: #38bdf8;">部署方式</span>
|
||||||
|
<span style="color: #94a3b8; margin-left: 8px; font-size: 13px;">Nginx 反向代理 → Vue3 静态文件 + Django API (Gunicorn)</span>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
<h2>数据模型设计</h2>
|
||||||
|
<p class="subtitle">核心表结构与关联关系</p>
|
||||||
|
|
||||||
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- Organization -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #0c4a6e; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">🏢</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Organization 组织架构</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">name</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">parent</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → self(集团/子公司)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">logo</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司 Logo</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">description</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司简介</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">email</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司联系邮箱 ✨</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">is_active</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">是否启用</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- User -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #312e81; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">👤</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">User 用户</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">username</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">登录账号</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">email</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">用户邮箱 ✨</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">phone</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">手机号</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">role</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">superadmin / admin / seeker</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">organization</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Organization(admin 用)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">is_active</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">账号状态</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Job -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #14532d; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">💼</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Job 职位</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">organization</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Organization</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">title</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">category</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位类别</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">location / salary</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">地点 / 薪资</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">description</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位描述(富文本)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">status</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">draft / published / closed</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">created_at</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">发布时间</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Resume -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #78350f; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">📄</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Resume 简历</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">user</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → User(求职者)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">name / gender / birthday</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">基本信息</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">education (JSONB)</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">教育经历列表</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">experience (JSONB)</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">工作经历列表</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">attachment</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">简历附件(PDF/Word)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Application -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #7f1d1d; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">📨</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Application 投递记录</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">job</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Job</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">applicant</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → User</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">resume</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Resume(投递时快照)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">status</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">待查看 → 已查看 → 面试 → 录用/拒绝</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">note</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">HR 备注</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">applied_at</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">投递时间</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 16px; background: #0f172a; border-radius: 8px; padding: 14px; border: 1px solid #334155; font-size: 12px; color: #94a3b8;">
|
||||||
|
<strong style="color: #e2e8f0;">关键设计说明:</strong>
|
||||||
|
<ul style="margin: 8px 0 0 16px; line-height: 2;">
|
||||||
|
<li>Organization 自关联支持集团→子公司层级</li>
|
||||||
|
<li>User.role 控制权限:superadmin 管全局,admin 只能操作本公司数据</li>
|
||||||
|
<li>Resume.education / experience 用 PostgreSQL JSONB 存储,灵活应对结构差异</li>
|
||||||
|
<li>Application 投递时关联当前简历,保证历史记录不受简历修改影响</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
<h2>数据模型设计</h2>
|
||||||
|
<p class="subtitle">核心表结构与关联关系</p>
|
||||||
|
|
||||||
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- Organization -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #0c4a6e; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">🏢</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Organization 组织架构</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">name</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">parent</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → self(集团/子公司)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">logo</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司 Logo</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">description</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">公司简介</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">is_active</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">是否启用</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- User -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #312e81; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">👤</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">User 用户</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">username / email</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">登录账号</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">phone</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">手机号</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">role</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">superadmin / admin / seeker</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">organization</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Organization(admin 用)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">is_active</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">账号状态</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Job -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #14532d; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">💼</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Job 职位</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">organization</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Organization</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">title</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">category</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位类别</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">location / salary</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">地点 / 薪资</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">description</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">职位描述(富文本)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">status</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">draft / published / closed</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">created_at</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">发布时间</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Resume -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #78350f; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">📄</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Resume 简历</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">user</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → User(求职者)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">name / gender / birthday</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">基本信息</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">education (JSON)</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">教育经历列表</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">experience (JSON)</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">工作经历列表</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">attachment</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">简历附件(PDF/Word)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Application -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155; grid-column: span 1;">
|
||||||
|
<div style="background: #7f1d1d; padding: 10px 14px; display: flex; align-items: center; gap: 8px;">
|
||||||
|
<span style="font-size: 16px;">📨</span>
|
||||||
|
<span style="font-weight: 700; color: #e2e8f0;">Application 投递记录</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px;">
|
||||||
|
<table style="width: 100%; font-size: 12px; border-collapse: collapse;">
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #fbbf24; font-weight: 600;">id</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">PK</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">job</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Job</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">applicant</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → User</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">resume</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">FK → Resume(投递时快照)</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #34d399; font-weight: 600;">status</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">待查看 → 已查看 → 面试 → 录用/拒绝</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-bottom: 1px solid #1e3a5f;">
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">note</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">HR 备注</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 5px 0; color: #e2e8f0;">applied_at</td>
|
||||||
|
<td style="padding: 5px 0; color: #94a3b8;">投递时间</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 16px; background: #0f172a; border-radius: 8px; padding: 14px; border: 1px solid #334155; font-size: 12px; color: #94a3b8;">
|
||||||
|
<strong style="color: #e2e8f0;">关键设计说明:</strong>
|
||||||
|
<ul style="margin: 8px 0 0 16px; line-height: 2;">
|
||||||
|
<li>Organization 自关联支持集团→子公司层级</li>
|
||||||
|
<li>User.role 控制权限:superadmin 管全局,admin 只能操作本公司数据</li>
|
||||||
|
<li>Resume.education / experience 用 PostgreSQL JSONB 存储,灵活应对结构差异</li>
|
||||||
|
<li>Application 投递时关联当前简历,保证历史记录不受简历修改影响</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
<h2>关键业务流程</h2>
|
||||||
|
<p class="subtitle">三条核心流程的状态流转</p>
|
||||||
|
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 20px; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- 流程1:求职者投递 -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #0c4a6e; padding: 10px 16px;">
|
||||||
|
<span style="font-weight: 700; color: #38bdf8;">流程 1:求职者投递简历</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 16px; overflow-x: auto;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 0; min-width: 600px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 100px; border: 1px solid #1e3a5f;">
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-bottom: 4px;">求职者</div>
|
||||||
|
<div style="color: #e2e8f0; font-size: 13px; font-weight: 600;">浏览职位</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 100px; border: 1px solid #1e3a5f;">
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-bottom: 4px;">检查</div>
|
||||||
|
<div style="color: #e2e8f0; font-size: 13px; font-weight: 600;">是否已登录</div>
|
||||||
|
<div style="font-size: 11px; color: #fbbf24; margin-top: 4px;">未登录→跳注册</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 110px; border: 1px solid #1e3a5f;">
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-bottom: 4px;">检查</div>
|
||||||
|
<div style="color: #e2e8f0; font-size: 13px; font-weight: 600;">简历是否完善</div>
|
||||||
|
<div style="font-size: 11px; color: #fbbf24; margin-top: 4px;">未完善→提示填写</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 110px; border: 1px solid #1e3a5f;">
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-bottom: 4px;">确认</div>
|
||||||
|
<div style="color: #e2e8f0; font-size: 13px; font-weight: 600;">投递弹窗</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-top: 4px;">选简历版本</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #14532d; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 100px; border: 1px solid #166534;">
|
||||||
|
<div style="font-size: 11px; color: #86efac; margin-bottom: 4px;">完成</div>
|
||||||
|
<div style="color: #4ade80; font-size: 13px; font-weight: 600;">投递成功</div>
|
||||||
|
<div style="font-size: 11px; color: #86efac; margin-top: 4px;">状态:待查看</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 流程2:投递状态流转 -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #7f1d1d; padding: 10px 16px;">
|
||||||
|
<span style="font-weight: 700; color: #fca5a5;">流程 2:HR 处理投递(状态流转)</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 16px; overflow-x: auto;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 0; min-width: 640px;">
|
||||||
|
<div style="background: #374151; border-radius: 8px; padding: 10px 16px; text-align: center; min-width: 90px; border: 1px solid #4b5563;">
|
||||||
|
<div style="color: #9ca3af; font-size: 13px; font-weight: 600;">待查看</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 8px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #1e3a5f; border-radius: 8px; padding: 10px 16px; text-align: center; min-width: 90px; border: 1px solid #1d4ed8;">
|
||||||
|
<div style="color: #60a5fa; font-size: 13px; font-weight: 600;">已查看</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-top: 3px;">HR 打开简历</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 8px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #1e293b; border-radius: 8px; padding: 10px 16px; text-align: center; min-width: 90px; border: 1px solid #7c3aed;">
|
||||||
|
<div style="color: #a78bfa; font-size: 13px; font-weight: 600;">面试中</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-top: 3px;">HR 手动更新</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px; padding: 0 8px;">
|
||||||
|
<div style="color: #475569; font-size: 18px;">→</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||||
|
<div style="background: #14532d; border-radius: 8px; padding: 8px 16px; text-align: center; min-width: 90px; border: 1px solid #166534;">
|
||||||
|
<div style="color: #4ade80; font-size: 13px; font-weight: 600;">已录用</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #450a0a; border-radius: 8px; padding: 8px 16px; text-align: center; min-width: 90px; border: 1px solid #7f1d1d;">
|
||||||
|
<div style="color: #f87171; font-size: 13px; font-weight: 600;">已拒绝</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 12px; font-size: 12px; color: #64748b;">
|
||||||
|
* 每次状态变更自动发送邮件通知求职者
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 流程3:公司管理员发布职位 -->
|
||||||
|
<div style="background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #14532d; padding: 10px 16px;">
|
||||||
|
<span style="font-weight: 700; color: #86efac;">流程 3:公司管理员发布职位</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 16px; overflow-x: auto;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 0; min-width: 560px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 90px; border: 1px solid #1e3a5f;">
|
||||||
|
<div style="color: #e2e8f0; font-size: 13px; font-weight: 600;">填写职位</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-top: 3px;">标题/描述/薪资等</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #374151; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 90px; border: 1px solid #4b5563;">
|
||||||
|
<div style="color: #9ca3af; font-size: 13px; font-weight: 600;">保存草稿</div>
|
||||||
|
<div style="font-size: 11px; color: #94a3b8; margin-top: 3px;">status: draft</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #14532d; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 90px; border: 1px solid #166534;">
|
||||||
|
<div style="color: #4ade80; font-size: 13px; font-weight: 600;">发布上线</div>
|
||||||
|
<div style="font-size: 11px; color: #86efac; margin-top: 3px;">status: published</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #475569; padding: 0 6px; font-size: 18px;">→</div>
|
||||||
|
<div style="background: #450a0a; border-radius: 8px; padding: 10px 14px; text-align: center; min-width: 90px; border: 1px solid #7f1d1d;">
|
||||||
|
<div style="color: #f87171; font-size: 13px; font-weight: 600;">关闭招聘</div>
|
||||||
|
<div style="font-size: 11px; color: #fca5a5; margin-top: 3px;">status: closed</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 12px; font-size: 12px; color: #64748b;">
|
||||||
|
* 管理员只能操作本公司职位;超管可查看所有公司职位但不能代发
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
<h2>页面结构与路由设计</h2>
|
||||||
|
<p class="subtitle">三个区域的页面划分</p>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 16px; flex-wrap: wrap; margin-top: 16px;">
|
||||||
|
|
||||||
|
<!-- 公开门户 -->
|
||||||
|
<div style="flex: 1; min-width: 240px; background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #0c4a6e; padding: 10px 14px;">
|
||||||
|
<span style="font-weight: 700; color: #38bdf8;">公开门户</span>
|
||||||
|
<span style="font-size: 11px; color: #7dd3fc; margin-left: 8px;">无需登录</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px; font-size: 12px;">
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">首页(职位推荐 + 公司展示 + 搜索入口)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/jobs</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">职位列表(搜索 + 筛选:公司/地点/薪资/类别)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/jobs/:id</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">职位详情(描述 + 要求 + 投递按钮)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/companies</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">公司列表</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/companies/:id</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">公司详情 + 该公司在招职位</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #38bdf8; font-family: monospace;">/login /register</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">求职者登录 / 注册</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 求职者中心 -->
|
||||||
|
<div style="flex: 1; min-width: 240px; background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #312e81; padding: 10px 14px;">
|
||||||
|
<span style="font-weight: 700; color: #a5b4fc;">求职者中心</span>
|
||||||
|
<span style="font-size: 11px; color: #c7d2fe; margin-left: 8px;">需登录(seeker)</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px; font-size: 12px;">
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #a5b4fc; font-family: monospace;">/seeker/resume</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">我的简历(填写/编辑在线简历 + 上传附件)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #a5b4fc; font-family: monospace;">/seeker/applications</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">我的投递(投递记录 + 状态跟踪)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #a5b4fc; font-family: monospace;">/seeker/profile</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">账号设置(修改密码/邮箱/手机)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 管理后台 -->
|
||||||
|
<div style="flex: 1; min-width: 240px; background: #1e293b; border-radius: 10px; overflow: hidden; border: 1px solid #334155;">
|
||||||
|
<div style="background: #4a1d96; padding: 10px 14px;">
|
||||||
|
<span style="font-weight: 700; color: #ddd6fe;">管理后台</span>
|
||||||
|
<span style="font-size: 11px; color: #ede9fe; margin-left: 8px;">需登录(admin / superadmin)</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px 14px; font-size: 12px;">
|
||||||
|
|
||||||
|
<div style="color: #f472b6; font-size: 11px; font-weight: 600; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.05em;">公司管理员</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #f9a8d4; font-family: monospace;">/admin/jobs</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">职位管理(列表 / 新建 / 编辑 / 上下架)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #f9a8d4; font-family: monospace;">/admin/applications</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">投递管理(查看简历 / 更新状态 / 备注)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="color: #fb923c; font-size: 11px; font-weight: 600; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.05em;">超管专属</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #fdba74; font-family: monospace;">/admin/organizations</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">组织架构管理(增删改查子公司)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #fdba74; font-family: monospace;">/admin/users</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">用户管理(创建公司管理员 / 禁用账号)</div>
|
||||||
|
</div>
|
||||||
|
<div style="background: #0f172a; border-radius: 6px; padding: 8px 10px;">
|
||||||
|
<div style="color: #fdba74; font-family: monospace;">/admin/jobs (全局视图)</div>
|
||||||
|
<div style="color: #94a3b8; margin-top: 2px;">查看所有公司的职位</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 16px; background: #0f172a; border-radius: 8px; padding: 14px; border: 1px solid #334155; font-size: 12px; color: #94a3b8;">
|
||||||
|
<strong style="color: #e2e8f0;">路由守卫规则:</strong>
|
||||||
|
<ul style="margin: 8px 0 0 16px; line-height: 2;">
|
||||||
|
<li>未登录访问 /seeker/* → 跳转登录页,登录后返回原页面</li>
|
||||||
|
<li>未登录访问 /admin/* → 跳转管理员登录页</li>
|
||||||
|
<li>admin 角色访问超管页面 → 403 提示</li>
|
||||||
|
<li>seeker 角色访问 /admin/* → 403 提示</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
@ -382,7 +382,7 @@ git commit -m "chore: add pytest configuration for Django tests"
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Task 4: accounts app — 自定义用户模型
|
## Task 3: accounts app — 自定义用户模型
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `offer_backend/apps/accounts/models.py`
|
- Create: `offer_backend/apps/accounts/models.py`
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
| 认证 | djangorestframework-simplejwt(JWT) |
|
| 认证 | djangorestframework-simplejwt(JWT) |
|
||||||
| 数据库 | PostgreSQL |
|
| 数据库 | PostgreSQL |
|
||||||
| 缓存 | Redis |
|
| 缓存 | Redis |
|
||||||
| 文件存储 | 本地存储 / 对象存储(OSS) |
|
| 文件存储 | 本地存储(初期),后期可切换至对象存储(OSS) |
|
||||||
| 部署 | Nginx + Gunicorn |
|
| 部署 | Nginx + Gunicorn |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -113,7 +113,7 @@ Nginx
|
||||||
| id | PK | 主键 |
|
| id | PK | 主键 |
|
||||||
| job | FK(Job) | 投递的职位 |
|
| job | FK(Job) | 投递的职位 |
|
||||||
| applicant | FK(User) | 求职者 |
|
| applicant | FK(User) | 求职者 |
|
||||||
| resume | FK(Resume) | 投递时关联的简历(快照) |
|
| resume_snapshot | JSONField | 投递时将简历内容序列化复制存储,与 Resume 主表解耦 |
|
||||||
| status | CharField | pending / viewed / interviewing / hired / rejected |
|
| status | CharField | pending / viewed / interviewing / hired / rejected |
|
||||||
| note | TextField | HR 备注 |
|
| note | TextField | HR 备注 |
|
||||||
| applied_at | DateTimeField | 投递时间 |
|
| applied_at | DateTimeField | 投递时间 |
|
||||||
|
|
@ -130,7 +130,7 @@ Nginx
|
||||||
| `/jobs/:id` | 职位详情 | 职位描述、要求、投递按钮 |
|
| `/jobs/:id` | 职位详情 | 职位描述、要求、投递按钮 |
|
||||||
| `/companies` | 公司列表 | 所有子公司展示 |
|
| `/companies` | 公司列表 | 所有子公司展示 |
|
||||||
| `/companies/:id` | 公司详情 | 公司介绍 + 在招职位 |
|
| `/companies/:id` | 公司详情 | 公司介绍 + 在招职位 |
|
||||||
| `/login` | 求职者登录 | - |
|
| `/login` | 求职者登录 | 管理员也使用此页面登录,通过 role 跳转不同后台 |
|
||||||
| `/register` | 求职者注册 | - |
|
| `/register` | 求职者注册 | - |
|
||||||
|
|
||||||
### 求职者中心(seeker 登录后可访问)
|
### 求职者中心(seeker 登录后可访问)
|
||||||
|
|
@ -170,7 +170,7 @@ Nginx
|
||||||
待查看(pending) → 已查看(viewed) → 面试中(interviewing) → 已录用(hired)
|
待查看(pending) → 已查看(viewed) → 面试中(interviewing) → 已录用(hired)
|
||||||
→ 已拒绝(rejected)
|
→ 已拒绝(rejected)
|
||||||
```
|
```
|
||||||
- 每次状态变更自动发送邮件通知求职者
|
- 每次状态变更通过 Django 内置邮件后端(SMTP)同步发送通知邮件给求职者
|
||||||
- HR 可在任意阶段填写备注
|
- HR 可在任意阶段填写备注
|
||||||
|
|
||||||
### 流程 3:公司管理员发布职位
|
### 流程 3:公司管理员发布职位
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue