From 1e242da71494afd7c90a8f352e4265d025a9a68f Mon Sep 17 00:00:00 2001 From: doublex001 <16157008+doublex001@user.noreply.gitee.com> Date: Tue, 1 Sep 2026 11:53:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=89=B4=E6=9D=83=E6=80=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=88=86=E7=AB=AF=E6=A0=87=E8=AE=B0=20+=20=E6=B1=82?= =?UTF-8?q?=E8=81=8C=E6=84=8F=E5=90=91=E6=8E=A5=E5=8F=A3/hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AuthContext 增加 candidateSetupDone/enterpriseVerified 标记及 completeCandidateSetup/completeEnterpriseVerify - api.saveJobPreference + useJobPreference hook,统一从 index 导出 - 形成『身份 → 分端设置 → 对应端』漏斗的持久判定位 --- src/api/api.ts | 11 +++++++ src/api/index.ts | 1 + src/context/AuthContext.tsx | 54 ++++++++++++++++++++++++++++++++--- src/hooks/index.ts | 1 + src/hooks/useJobPreference.ts | 29 +++++++++++++++++++ 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/hooks/useJobPreference.ts diff --git a/src/api/api.ts b/src/api/api.ts index 6c7f32b..21130ed 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -4886,3 +4886,14 @@ export function loginByPhone(phone: string, code: string): Promise } return mockRequest({ token: `mock_token_${phone}`, phone }); } + +/** + * 保存求职意向(求职者选择身份后的必经设置步骤,用于岗位推荐匹配)。 + * @method POST + * @url /api/user/job-preference + * @param preference 求职意向(期望职位/城市/薪资/工作类型/求职状态) + * @returns 保存后的求职意向 + */ +export function saveJobPreference(preference: JobPreference): Promise { + return mockRequest(preference); +} diff --git a/src/api/index.ts b/src/api/index.ts index 3e745d8..3efaa45 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -48,6 +48,7 @@ export { fetchOfferCompareData, fetchJobOverallScore, fetchJobPreference, + saveJobPreference, fetchJobProgress, fetchMatchResult, fetchMenuItems, diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx index cf883e3..8a8a601 100644 --- a/src/context/AuthContext.tsx +++ b/src/context/AuthContext.tsx @@ -3,7 +3,10 @@ import { createContext, useContext, useState, type ReactNode } from 'react'; /* ===================== 鉴权(引导/登录)上下文 ===================== * 管理「引导页是否看过」「是否已登录」「登录令牌」。 * 与 RoleContext 配合形成完整漏斗: - * 首次启动 → 引导页 → 登录页 → 选择身份(identity-select) → 对应端。 + * 首次启动 → 引导页 → 登录页 → 选择身份(identity-select) → 分端设置 → 对应端 + * - 求职者:求职意向设置(job-preference) → 求职端 (tabs) + * - 招聘者:企业认证(enterprise-certification) → 企业端 (enterprise) + * 两个分端设置步骤均允许跳过,设置完成后置位对应标记,不再重复强制。 * * 持久化:当前为会话级(内存)实现,App 重启后回到初始态, * 需重新引导/登录。若已安装 @react-native-async-storage/async-storage, @@ -17,12 +20,20 @@ export interface AuthContextValue { isLoggedIn: boolean; /** 登录令牌(mock 态为占位串) */ token: string | null; + /** 求职端:求职意向是否已设置(设置后不再强制进入设置页) */ + candidateSetupDone: boolean; + /** 企业端:是否已提交/完成企业认证(走完该步骤后不再强制) */ + enterpriseVerified: boolean; /** 标记引导页已看完 */ completeOnboarding: () => void; /** 登录成功,写入 token */ login: (token: string) => void; /** 退出登录,清空令牌 */ logout: () => void; + /** 标记求职意向已设置 */ + completeCandidateSetup: () => void; + /** 标记企业认证已提交/完成 */ + completeEnterpriseVerify: () => void; } const AuthContext = createContext(undefined); @@ -31,10 +42,18 @@ interface MemoryAuth { onboardingSeen: boolean; isLoggedIn: boolean; token: string | null; + candidateSetupDone: boolean; + enterpriseVerified: boolean; } /** 会话级内存状态(重启即重置) */ -let memoryAuth: MemoryAuth = { onboardingSeen: false, isLoggedIn: false, token: null }; +let memoryAuth: MemoryAuth = { + onboardingSeen: false, + isLoggedIn: false, + token: null, + candidateSetupDone: false, + enterpriseVerified: false, +}; export function AuthProvider({ children }: { children: ReactNode }) { const [state, setState] = useState(memoryAuth); @@ -52,13 +71,40 @@ export function AuthProvider({ children }: { children: ReactNode }) { }; const logout = () => { - const next = { ...state, isLoggedIn: false, token: null }; + const next = { + ...state, + isLoggedIn: false, + token: null, + candidateSetupDone: false, + enterpriseVerified: false, + }; + memoryAuth = next; + setState(next); + }; + + const completeCandidateSetup = () => { + const next = { ...state, candidateSetupDone: true }; + memoryAuth = next; + setState(next); + }; + + const completeEnterpriseVerify = () => { + const next = { ...state, enterpriseVerified: true }; memoryAuth = next; setState(next); }; return ( - + {children} ); diff --git a/src/hooks/index.ts b/src/hooks/index.ts index a9770ba..43f123e 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -29,6 +29,7 @@ export { useJobEvaluationEmptyState } from './useJobEvaluationEmptyState'; export { useJobEvaluations } from './useJobEvaluations'; export { useJobList } from './useJobList'; export { useJobManagement } from './useJobManagement'; +export { useJobPreference } from './useJobPreference'; export { useJobProgress } from './useJobProgress'; export { useJobPublish } from './useJobPublish'; export { useKeywordBlock } from './useKeywordBlock'; diff --git a/src/hooks/useJobPreference.ts b/src/hooks/useJobPreference.ts new file mode 100644 index 0000000..16fe6ca --- /dev/null +++ b/src/hooks/useJobPreference.ts @@ -0,0 +1,29 @@ +import { useCallback } from 'react'; +import { fetchJobPreference, saveJobPreference } from '../api'; +import type { JobPreference } from '../types'; +import { useAsyncData } from './useAsyncData'; + +export interface UseJobPreferenceReturn { + /** 当前求职意向 */ + preference: JobPreference | null; + loading: boolean; + error: Error | null; + refresh: () => void; + /** 保存求职意向 */ + save: (preference: JobPreference) => Promise; +} + +/** + * 求职意向 hook:取数 + 保存。 + * 用于求职者选择身份后的「求职意向设置」步骤。 + */ +export function useJobPreference(): UseJobPreferenceReturn { + const fetcher = useCallback(() => fetchJobPreference(), []); + const { data, loading, error, refresh } = useAsyncData(fetcher); + + const save = useCallback(async (preference: JobPreference) => { + return saveJobPreference(preference); + }, []); + + return { preference: data, loading, error, refresh, save }; +}