上线版: 产品表单统一+form嵌套修复+用户管理+部署+三套叙事
- 产品编辑入口统一走 ProductFormFull(卖点/风格/人群/品牌词全字段); 修复开任务页 <form> 套 <form> 致"编辑产品"报错、改不了、跳回首个产品 - dashboard 入口卡片对齐实际路由: 系统管理(/config) 与 工作配置(/settings) 分开; settings ?tab=products 直达改用挂载后读 URL, 消除 hydration mismatch - 新增用户管理(users API/admin service/改密页) + alembic 022/023/024 - 上线部署: Dockerfile / docker-compose.prod+https / nginx https / .env.example - A8 三套正交叙事(痛点/场景/成分背书) + beige 调色去AI化 + 飞轮 text_import 高权重信号 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,11 @@ async function refreshToken(): Promise<string | null> {
|
||||
try {
|
||||
// 走 /auth/refresh(二期实现),一期降级跳登录
|
||||
clearToken();
|
||||
window.location.href = '/login';
|
||||
// 带提示跳登录,避免“弹窗一闪就被踢、看不清原因”
|
||||
if (typeof window !== 'undefined') {
|
||||
const back = encodeURIComponent(window.location.pathname);
|
||||
window.location.href = `/login?reason=expired&from=${back}`;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
refreshPromise = null;
|
||||
@@ -67,7 +71,13 @@ async function request<T>(
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
const apiError = new Error(err.message || `请求失败(${err.code || res.status})`) as Error & {
|
||||
code?: number;
|
||||
status?: number;
|
||||
};
|
||||
apiError.code = err.code;
|
||||
apiError.status = res.status;
|
||||
throw apiError;
|
||||
}
|
||||
|
||||
// ─── 公开方法 ────────────────────────────────────────────────
|
||||
|
||||
@@ -70,11 +70,18 @@ export class SseClient {
|
||||
// SSE 必须直连后端,绕过 Next dev rewrite 代理——后者会缓冲/吞掉 EventSource 的
|
||||
// 流式事件(实测:经代理 EventSource 只触发 open,零事件;直连后端事件正常)。
|
||||
// NEXT_PUBLIC_SSE_BASE_URL 缺省时退回 NEXT_PUBLIC_API_BASE_URL,再退回相对路径。
|
||||
const sseBase = (
|
||||
let sseBase = (
|
||||
process.env.NEXT_PUBLIC_SSE_BASE_URL ||
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ||
|
||||
''
|
||||
).replace(/\/$/, '');
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
process.env.NODE_ENV === 'development' &&
|
||||
(window.location.hostname === '127.0.0.1' || window.location.hostname === 'localhost')
|
||||
) {
|
||||
sseBase = `http://${window.location.hostname}:8000`;
|
||||
}
|
||||
const url = `${sseBase}/api/v1/tasks/${this.taskId}/stream?ticket=${ticket}&last_seq=${lastSeq}`;
|
||||
this.es = new EventSource(url);
|
||||
this.es.onopen = () => this.options.onStatusChange('connected');
|
||||
|
||||
Reference in New Issue
Block a user