guanwei 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/assets/{index-CjLUvkh9.js → index-O2O9peYE.js} +21 -21
- package/dist/assets/index-O2O9peYE.js.map +1 -0
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/server/src/data/db.json +265 -208
- package/server/src/data/guanwei.db +0 -0
- package/server/src/index.ts +31 -15
- package/server/src/routes/ai.ts +36 -5
- package/server/src/routes/divine.ts +61 -82
- package/server/src/routes/users.ts +12 -3
- package/server/src/services/orchestrator.ts +106 -0
- package/server/src/services/promptBuilder.ts +2 -2
- package/shared/core/engine/chart.ts +76 -0
- package/src/services/api.ts +19 -6
- package/dist/assets/index-CjLUvkh9.js.map +0 -1
package/src/services/api.ts
CHANGED
|
@@ -3,6 +3,16 @@ import type { InterpretationResult } from '@core/engine/tarotEngine';
|
|
|
3
3
|
|
|
4
4
|
// 开发环境直连后端(规避 proxy/IPv6 组合的 SSE 不确定性);生产同域 /api
|
|
5
5
|
const API_BASE = (import.meta.env.VITE_API_BASE as string | undefined) || '/api';
|
|
6
|
+
|
|
7
|
+
// 云同步 token(登录后 localStorage 会话中保存):所有需要归属校验的请求带上,
|
|
8
|
+
// 后端有 token 即以 token 解析用户,堵「自报 username」越权(H-NEW1 修复)
|
|
9
|
+
function authHeaders(): Record<string, string> {
|
|
10
|
+
try {
|
|
11
|
+
const sess = JSON.parse(localStorage.getItem('guanwei_session') || 'null');
|
|
12
|
+
if (sess?.token) return { 'X-Guanwei-Token': sess.token };
|
|
13
|
+
} catch { /* ignore */ }
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
6
16
|
// 诊断:全局暴露当前 API 基址
|
|
7
17
|
if (typeof window !== 'undefined') { (window as any).__API_BASE__ = API_BASE; }
|
|
8
18
|
console.log('[观微] API_BASE =', API_BASE);
|
|
@@ -11,6 +21,7 @@ async function request<T>(endpoint: string, options: RequestInit = {}): Promise<
|
|
|
11
21
|
const res = await fetch(`${API_BASE}${endpoint}`, {
|
|
12
22
|
headers: {
|
|
13
23
|
'Content-Type': 'application/json',
|
|
24
|
+
...authHeaders(),
|
|
14
25
|
...options.headers,
|
|
15
26
|
},
|
|
16
27
|
...options,
|
|
@@ -169,7 +180,7 @@ export async function aiInterpretStream(
|
|
|
169
180
|
try {
|
|
170
181
|
const res = await fetch(API_BASE + '/ai/interpret/stream', {
|
|
171
182
|
method: 'POST',
|
|
172
|
-
headers: { 'Content-Type': 'application/json' },
|
|
183
|
+
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
173
184
|
body: JSON.stringify(params),
|
|
174
185
|
signal: controller.signal,
|
|
175
186
|
});
|
|
@@ -238,12 +249,14 @@ export interface DivineResult {
|
|
|
238
249
|
divineId: string;
|
|
239
250
|
resultRaw: unknown;
|
|
240
251
|
display?: unknown;
|
|
252
|
+
/** 起占建档返回的 claimToken(本地占位账号注册升级用,L-NEW1) */
|
|
253
|
+
claimToken?: string;
|
|
241
254
|
}
|
|
242
255
|
|
|
243
256
|
export async function apiDivine(username: string, artId: string, inputs: unknown, profile?: unknown, question?: string, _profileId?: string): Promise<DivineResult> {
|
|
244
257
|
const res = await fetch(API_BASE + '/divine', {
|
|
245
258
|
method: 'POST',
|
|
246
|
-
headers: { 'Content-Type': 'application/json' },
|
|
259
|
+
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
247
260
|
body: JSON.stringify({ username, artId, inputs, profile, question }),
|
|
248
261
|
});
|
|
249
262
|
if (!res.ok) {
|
|
@@ -264,19 +277,19 @@ export interface DivineHistoryItem {
|
|
|
264
277
|
}
|
|
265
278
|
|
|
266
279
|
export async function apiDivineHistory(username: string, page = 1, pageSize = 20, profileId?: string): Promise<{ list: DivineHistoryItem[]; total: number }> {
|
|
267
|
-
const res = await fetch(API_BASE + '/divine?username=' + encodeURIComponent(username) + '&page=' + page + '&pageSize=' + pageSize + (profileId ? '&profileId=' + encodeURIComponent(profileId) : ''));
|
|
280
|
+
const res = await fetch(API_BASE + '/divine?username=' + encodeURIComponent(username) + '&page=' + page + '&pageSize=' + pageSize + (profileId ? '&profileId=' + encodeURIComponent(profileId) : ''), { headers: authHeaders() });
|
|
268
281
|
if (!res.ok) return { list: [], total: 0 };
|
|
269
282
|
return res.json();
|
|
270
283
|
}
|
|
271
284
|
|
|
272
285
|
export async function apiDivineDetail(id: string, username: string): Promise<Record<string, unknown> | null> {
|
|
273
|
-
const res = await fetch(API_BASE + '/divine/' + id + '?username=' + encodeURIComponent(username));
|
|
286
|
+
const res = await fetch(API_BASE + '/divine/' + id + '?username=' + encodeURIComponent(username), { headers: authHeaders() });
|
|
274
287
|
if (!res.ok) return null;
|
|
275
288
|
return res.json();
|
|
276
289
|
}
|
|
277
290
|
|
|
278
291
|
export async function apiDivineDelete(id: string, username: string): Promise<boolean> {
|
|
279
|
-
const res = await fetch(API_BASE + '/divine/' + id + '?username=' + encodeURIComponent(username), { method: 'DELETE' });
|
|
292
|
+
const res = await fetch(API_BASE + '/divine/' + id + '?username=' + encodeURIComponent(username), { method: 'DELETE', headers: authHeaders() });
|
|
280
293
|
return res.ok;
|
|
281
294
|
}
|
|
282
295
|
|
|
@@ -330,7 +343,7 @@ export async function apiHourInfer(params: {
|
|
|
330
343
|
}): Promise<HourInferResult> {
|
|
331
344
|
const res = await fetch(API_BASE + '/hour-infer', {
|
|
332
345
|
method: 'POST',
|
|
333
|
-
headers: { 'Content-Type': 'application/json' },
|
|
346
|
+
headers: { 'Content-Type': 'application/json', ...authHeaders() },
|
|
334
347
|
body: JSON.stringify(params),
|
|
335
348
|
});
|
|
336
349
|
if (!res.ok) {
|