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:
TianyangZhang 2026-03-25 08:43:50 +08:00
parent ef4c9bf307
commit 46e35074ed
11 changed files with 881 additions and 5 deletions

View File

@ -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)"
]
}
}

View File

@ -0,0 +1 @@
{"reason":"idle timeout","timestamp":1774342828046}

View File

@ -0,0 +1 @@
3597

View File

@ -0,0 +1,80 @@
<h2>系统架构总览</h2>
<p class="subtitle">方案 ADjango 后端 + 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>

View File

@ -0,0 +1,80 @@
<h2>系统架构总览</h2>
<p class="subtitle">方案 ADjango 后端 + 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>

View File

@ -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 → Organizationadmin 用)</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>

View File

@ -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 → Organizationadmin 用)</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>

View File

@ -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;">流程 2HR 处理投递(状态流转)</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>

View File

@ -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 &nbsp; /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 &nbsp;(全局视图)</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>

View File

@ -382,7 +382,7 @@ git commit -m "chore: add pytest configuration for Django tests"
---
## Task 4: accounts app — 自定义用户模型
## Task 3: accounts app — 自定义用户模型
**Files:**
- Create: `offer_backend/apps/accounts/models.py`

View File

@ -20,7 +20,7 @@
| 认证 | djangorestframework-simplejwtJWT |
| 数据库 | PostgreSQL |
| 缓存 | Redis |
| 文件存储 | 本地存储 / 对象存储OSS |
| 文件存储 | 本地存储(初期),后期可切换至对象存储OSS |
| 部署 | Nginx + Gunicorn |
---
@ -113,7 +113,7 @@ Nginx
| id | PK | 主键 |
| job | FK(Job) | 投递的职位 |
| applicant | FK(User) | 求职者 |
| resume | FK(Resume) | 投递时关联的简历(快照) |
| resume_snapshot | JSONField | 投递时将简历内容序列化复制存储,与 Resume 主表解耦 |
| status | CharField | pending / viewed / interviewing / hired / rejected |
| note | TextField | HR 备注 |
| applied_at | DateTimeField | 投递时间 |
@ -130,7 +130,7 @@ Nginx
| `/jobs/:id` | 职位详情 | 职位描述、要求、投递按钮 |
| `/companies` | 公司列表 | 所有子公司展示 |
| `/companies/:id` | 公司详情 | 公司介绍 + 在招职位 |
| `/login` | 求职者登录 | - |
| `/login` | 求职者登录 | 管理员也使用此页面登录,通过 role 跳转不同后台 |
| `/register` | 求职者注册 | - |
### 求职者中心seeker 登录后可访问)
@ -170,7 +170,7 @@ Nginx
待查看(pending) → 已查看(viewed) → 面试中(interviewing) → 已录用(hired)
→ 已拒绝(rejected)
```
- 每次状态变更自动发送邮件通知求职者
- 每次状态变更通过 Django 内置邮件后端SMTP同步发送通知邮件给求职者
- HR 可在任意阶段填写备注
### 流程 3公司管理员发布职位