feat(web): 新增「任务」菜单 + 任务广场页(接入任务系统,展示待接单)

- services/tasks.js:/opc/tasks(待接单广场) /opc/my-tasks(我的接单) /opc/tasks/{id}/grab(抢单),带 Bearer
- user/Tasks.jsx:OPC 端登录墙 + 待接单/我的接单 两个 tab;任务卡(分类/mode/预算/截止/标签/交付天数/人数) + 抢单
- App.jsx 加路由 'tasks';site.js NAV 加「任务」项
- styles/tasks.css 浅色 token 卡片(圆角24/软阴影/悬浮上移)
This commit is contained in:
Pine
2026-08-27 18:14:56 +08:00
parent 56f10e65b9
commit 9ae938d87d
5 changed files with 193 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
/** 任务系统(OPC 端):任务广场(待接单) / 我的接单 / 抢单。走平台 /opc 端点,需登录(opc_member)。 */
import { getToken } from '@/services/auth';
const API_BASE = 'https://opc.pinesound.cn';
function authHeaders() {
const t = getToken();
return { 'Content-Type': 'application/json', ...(t ? { Authorization: `Bearer ${t}` } : {}) };
}
/** 任务广场(已发布待接单任务) */
export async function listTasks() {
try {
const res = await fetch(`${API_BASE}/opc/tasks`, { headers: authHeaders() });
if (!res.ok) return { ok: false, status: res.status };
const d = await res.json().catch(() => ({}));
return { ok: true, items: Array.isArray(d.items) ? d.items : [] };
} catch {
return { ok: false, status: 0 };
}
}
/** 我的任务看板 */
export async function myTasks() {
try {
const res = await fetch(`${API_BASE}/opc/my-tasks`, { headers: authHeaders() });
if (!res.ok) return { ok: false, status: res.status };
const d = await res.json().catch(() => ({}));
return { ok: true, items: Array.isArray(d.items) ? d.items : [] };
} catch {
return { ok: false, status: 0 };
}
}
/** 抢单 */
export async function grabTask(id) {
try {
const res = await fetch(`${API_BASE}/opc/tasks/${encodeURIComponent(id)}/grab`, {
method: 'POST', headers: authHeaders(),
});
const d = await res.json().catch(() => ({}));
if (!res.ok) return { ok: false, error: d.detail || d.message || '抢单失败' };
return { ok: true, task: d };
} catch {
return { ok: false, error: '网络异常' };
}
}