Browse Source

feat: 鉴权态新增分端标记 + 求职意向接口/hook

- AuthContext 增加 candidateSetupDone/enterpriseVerified 标记及 completeCandidateSetup/completeEnterpriseVerify
- api.saveJobPreference + useJobPreference hook,统一从 index 导出
- 形成『身份 → 分端设置 → 对应端』漏斗的持久判定位
master
doublex001 2 months ago
parent
commit
1e242da714
  1. 11
      src/api/api.ts
  2. 1
      src/api/index.ts
  3. 54
      src/context/AuthContext.tsx
  4. 1
      src/hooks/index.ts
  5. 29
      src/hooks/useJobPreference.ts

11
src/api/api.ts

@ -4886,3 +4886,14 @@ export function loginByPhone(phone: string, code: string): Promise<LoginResult>
} }
return mockRequest<LoginResult>({ token: `mock_token_${phone}`, phone }); return mockRequest<LoginResult>({ token: `mock_token_${phone}`, phone });
} }
/**
* 保存求职意向(求职者选择身份后的必经设置步骤,用于岗位推荐匹配)。
* @method POST
* @url /api/user/job-preference
* @param preference 求职意向(期望职位/城市/薪资/工作类型/求职状态)
* @returns 保存后的求职意向
*/
export function saveJobPreference(preference: JobPreference): Promise<JobPreference> {
return mockRequest<JobPreference>(preference);
}

1
src/api/index.ts

@ -48,6 +48,7 @@ export {
fetchOfferCompareData, fetchOfferCompareData,
fetchJobOverallScore, fetchJobOverallScore,
fetchJobPreference, fetchJobPreference,
saveJobPreference,
fetchJobProgress, fetchJobProgress,
fetchMatchResult, fetchMatchResult,
fetchMenuItems, fetchMenuItems,

54
src/context/AuthContext.tsx

@ -3,7 +3,10 @@ import { createContext, useContext, useState, type ReactNode } from 'react';
/* ===================== 鉴权(引导/登录)上下文 ===================== /* ===================== 鉴权(引导/登录)上下文 =====================
* 管理「引导页是否看过」「是否已登录」「登录令牌」。 * 管理「引导页是否看过」「是否已登录」「登录令牌」。
* 与 RoleContext 配合形成完整漏斗: * 与 RoleContext 配合形成完整漏斗:
* 首次启动 → 引导页 → 登录页 → 选择身份(identity-select) → 对应端。 * 首次启动 → 引导页 → 登录页 → 选择身份(identity-select) → 分端设置 → 对应端
* - 求职者:求职意向设置(job-preference) → 求职端 (tabs)
* - 招聘者:企业认证(enterprise-certification) → 企业端 (enterprise)
* 两个分端设置步骤均允许跳过,设置完成后置位对应标记,不再重复强制。
* *
* 持久化:当前为会话级(内存)实现,App 重启后回到初始态, * 持久化:当前为会话级(内存)实现,App 重启后回到初始态,
* 需重新引导/登录。若已安装 @react-native-async-storage/async-storage, * 需重新引导/登录。若已安装 @react-native-async-storage/async-storage,
@ -17,12 +20,20 @@ export interface AuthContextValue {
isLoggedIn: boolean; isLoggedIn: boolean;
/** 登录令牌(mock 态为占位串) */ /** 登录令牌(mock 态为占位串) */
token: string | null; token: string | null;
/** 求职端:求职意向是否已设置(设置后不再强制进入设置页) */
candidateSetupDone: boolean;
/** 企业端:是否已提交/完成企业认证(走完该步骤后不再强制) */
enterpriseVerified: boolean;
/** 标记引导页已看完 */ /** 标记引导页已看完 */
completeOnboarding: () => void; completeOnboarding: () => void;
/** 登录成功,写入 token */ /** 登录成功,写入 token */
login: (token: string) => void; login: (token: string) => void;
/** 退出登录,清空令牌 */ /** 退出登录,清空令牌 */
logout: () => void; logout: () => void;
/** 标记求职意向已设置 */
completeCandidateSetup: () => void;
/** 标记企业认证已提交/完成 */
completeEnterpriseVerify: () => void;
} }
const AuthContext = createContext<AuthContextValue | undefined>(undefined); const AuthContext = createContext<AuthContextValue | undefined>(undefined);
@ -31,10 +42,18 @@ interface MemoryAuth {
onboardingSeen: boolean; onboardingSeen: boolean;
isLoggedIn: boolean; isLoggedIn: boolean;
token: string | null; 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 }) { export function AuthProvider({ children }: { children: ReactNode }) {
const [state, setState] = useState<MemoryAuth>(memoryAuth); const [state, setState] = useState<MemoryAuth>(memoryAuth);
@ -52,13 +71,40 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}; };
const logout = () => { 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; memoryAuth = next;
setState(next); setState(next);
}; };
return ( return (
<AuthContext.Provider value={{ ...state, completeOnboarding, login, logout }}> <AuthContext.Provider
value={{
...state,
completeOnboarding,
login,
logout,
completeCandidateSetup,
completeEnterpriseVerify,
}}
>
{children} {children}
</AuthContext.Provider> </AuthContext.Provider>
); );

1
src/hooks/index.ts

@ -29,6 +29,7 @@ export { useJobEvaluationEmptyState } from './useJobEvaluationEmptyState';
export { useJobEvaluations } from './useJobEvaluations'; export { useJobEvaluations } from './useJobEvaluations';
export { useJobList } from './useJobList'; export { useJobList } from './useJobList';
export { useJobManagement } from './useJobManagement'; export { useJobManagement } from './useJobManagement';
export { useJobPreference } from './useJobPreference';
export { useJobProgress } from './useJobProgress'; export { useJobProgress } from './useJobProgress';
export { useJobPublish } from './useJobPublish'; export { useJobPublish } from './useJobPublish';
export { useKeywordBlock } from './useKeywordBlock'; export { useKeywordBlock } from './useKeywordBlock';

29
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<JobPreference>;
}
/**
* 求职意向 hook:取数 + 保存。
* 用于求职者选择身份后的「求职意向设置」步骤。
*/
export function useJobPreference(): UseJobPreferenceReturn {
const fetcher = useCallback(() => fetchJobPreference(), []);
const { data, loading, error, refresh } = useAsyncData<JobPreference>(fetcher);
const save = useCallback(async (preference: JobPreference) => {
return saveJobPreference(preference);
}, []);
return { preference: data, loading, error, refresh, save };
}
Loading…
Cancel
Save