feat(ECR-012–016): 合规、题库、时辰刷新、头像、MBTI OEJTS 与埋点

落地输入合规、探索题库、报告日/时辰刷新、账号头像、OEJTS 量表,并补齐 H5 埋点与 Admin 漏斗;同步 ESS 工件、切至自建 Git、清理 GitHub Actions。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-13 01:27:58 +08:00
co-authored by Cursor
parent 13860bf1ef
commit 89756f65b4
227 changed files with 7405 additions and 1407 deletions
+57 -3
View File
@@ -92,6 +92,11 @@ export function createClient(opts: CreateClientOptions) {
authMe: () => call<AuthUser>('/api/v1/auth/me'),
authUpdateMe: (body: { nickname: string }) =>
call<AuthUser>('/api/v1/auth/me', { method: 'PATCH', body }),
authUploadAvatar: (file: Blob, filename = 'avatar.jpg') => {
const fd = new FormData()
fd.append('file', file, filename)
return call<AuthUser>('/api/v1/auth/me/avatar', { method: 'POST', body: fd })
},
listProfiles: () => call<{ items: Profile[] }>('/api/v1/profiles'),
createProfile: (body: CreateProfileBody) =>
call<Profile>('/api/v1/profiles', { method: 'POST', body }),
@@ -142,7 +147,7 @@ export function createClient(opts: CreateClientOptions) {
listGrowthPlans: () => call<{ items: GrowthPlan[] }>('/api/v1/growth/plans'),
createGrowthPlan: (body: { title: string; focus?: string }) =>
call<GrowthPlan>('/api/v1/growth/plans', { method: 'POST', body }),
growthCheckin: (planId: string, body?: { note?: string }) =>
createGrowthCheckin: (planId: string, body?: { note?: string }) =>
call<{ id: string; day: string }>(`/api/v1/growth/plans/${planId}/checkin`, {
method: 'POST',
body: body || {},
@@ -162,7 +167,55 @@ export function createClient(opts: CreateClientOptions) {
body: { profile_a_id, profile_b_id },
}),
listScales: () => call<{ items: ScaleSummary[] }>('/api/v1/scales'),
getScaleBankCatalog: () =>
call<{
featured: {
slug: string
title: string
description: string
category_key: string
icon: string
path: string
}[]
categories: {
key: string
title: string
description: string
icon: string
count: number
featured: {
slug: string
title: string
description: string
category_key: string
icon: string
path: string
}[]
path: string
}[]
}>('/api/v1/scale-bank/catalog'),
getScaleBankCategory: (key: string) =>
call<{
category: {
key: string
title: string
description: string
icon: string
count: number
path: string
}
items: {
slug: string
title: string
description: string
icon?: string
question_count: number
path: string
}[]
}>(`/api/v1/scale-bank/categories/${key}`),
getScale: (slug: string) => call<ScaleDetail>(`/api/v1/scales/${slug}`),
getScaleResult: (slug: string) =>
call<ScaleSubmitResult>(`/api/v1/scales/${slug}/result`),
submitScale: (slug: string, profile_id: string, answers: Record<string, string>) =>
call<ScaleSubmitResult>(`/api/v1/scales/${slug}/result`, {
method: 'POST',
@@ -334,13 +387,14 @@ export function createBrowserAdapters(): ClientAdapters {
const deviceKeyStorage = 'yxg_device_key'
return {
request: async <T>({ method = 'GET', path, body, headers, keepalive }: RequestOptions) => {
const isForm = typeof FormData !== 'undefined' && body instanceof FormData
const res = await fetch(path, {
method,
headers: {
'Content-Type': 'application/json',
...(isForm ? {} : { 'Content-Type': 'application/json' }),
...(headers || {}),
},
body: body === undefined ? undefined : JSON.stringify(body),
body: body === undefined ? undefined : isForm ? (body as FormData) : JSON.stringify(body),
keepalive: keepalive === true,
})
const text = await res.text()