|
|
@ -81,6 +81,12 @@ import type { |
|
|
AboutInfo, |
|
|
AboutInfo, |
|
|
UpdateTogglePayload, |
|
|
UpdateTogglePayload, |
|
|
PrivacyCenter, |
|
|
PrivacyCenter, |
|
|
|
|
|
AccountCancelData, |
|
|
|
|
|
DeleteAllData, |
|
|
|
|
|
DndSetting, |
|
|
|
|
|
KeywordBlockSetting, |
|
|
|
|
|
LegalDocument, |
|
|
|
|
|
PrivacyDetailSetting, |
|
|
PersonalDataExport, |
|
|
PersonalDataExport, |
|
|
CandidateAbility, |
|
|
CandidateAbility, |
|
|
CandidateDetail, |
|
|
CandidateDetail, |
|
|
@ -1447,7 +1453,50 @@ export async function fetchRankData(jobId: string): Promise<RankOverview> { |
|
|
// 当前为 mock 阶段,jobId 仅用于标注真实接口入参,避免未使用参数告警
|
|
|
// 当前为 mock 阶段,jobId 仅用于标注真实接口入参,避免未使用参数告警
|
|
|
void jobId; |
|
|
void jobId; |
|
|
return mockRequest({ |
|
|
return mockRequest({ |
|
|
hasData: false, |
|
|
hasData: true, |
|
|
|
|
|
rankData: { |
|
|
|
|
|
rank: 127, |
|
|
|
|
|
jobTitle: '高级前端工程师', |
|
|
|
|
|
company: '字节跳动', |
|
|
|
|
|
totalCandidates: 1286, |
|
|
|
|
|
percentile: 90.1, |
|
|
|
|
|
overallScore: 88, |
|
|
|
|
|
scoreLevel: '优秀', |
|
|
|
|
|
rankPosition: '前 9.9%', |
|
|
|
|
|
}, |
|
|
|
|
|
dimensions: [ |
|
|
|
|
|
{ id: 'skill', name: '专业技能', percentile: '前 15%', score: 92 }, |
|
|
|
|
|
{ id: 'experience', name: '工作经历', percentile: '前 22%', score: 86 }, |
|
|
|
|
|
{ id: 'education', name: '教育背景', percentile: '前 30%', score: 80 }, |
|
|
|
|
|
{ id: 'project', name: '项目经验', percentile: '前 12%', score: 94 }, |
|
|
|
|
|
{ id: 'match', name: '技能匹配', percentile: '前 18%', score: 89 }, |
|
|
|
|
|
{ id: 'completeness', name: '简历完整度', percentile: '前 25%', score: 84 }, |
|
|
|
|
|
], |
|
|
|
|
|
candidates: [ |
|
|
|
|
|
{ id: 'c1', name: '候选人 A', score: 96, tags: ['清华硕士', '5 年大厂'] }, |
|
|
|
|
|
{ id: 'c2', name: '候选人 B', score: 93, tags: ['浙大本科', '3 年独角兽'] }, |
|
|
|
|
|
{ id: 'c3', name: '候选人 C', score: 91, tags: ['海归硕士', '4 年外企'] }, |
|
|
|
|
|
], |
|
|
|
|
|
tips: [ |
|
|
|
|
|
{ |
|
|
|
|
|
id: 't1', |
|
|
|
|
|
title: '补充项目经历可提升 5-8 个百分位', |
|
|
|
|
|
description: '完善你的项目经历描述,突出技术选型与业务成果', |
|
|
|
|
|
type: 'action', |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
id: 't2', |
|
|
|
|
|
title: '添加技能标签提升匹配度', |
|
|
|
|
|
description: '补充 TypeScript、性能优化等岗位高频技能关键词', |
|
|
|
|
|
type: 'tip', |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
id: 't3', |
|
|
|
|
|
title: '你的教育背景处于中位区间', |
|
|
|
|
|
description: '可通过突出工作经历与项目成果弥补学历竞争力', |
|
|
|
|
|
type: 'tip', |
|
|
|
|
|
}, |
|
|
|
|
|
], |
|
|
emptyState: { |
|
|
emptyState: { |
|
|
title: '暂无排名数据', |
|
|
title: '暂无排名数据', |
|
|
subtitle: '完善简历和测评信息后,系统将为你计算竞争力排名', |
|
|
subtitle: '完善简历和测评信息后,系统将为你计算竞争力排名', |
|
|
@ -3109,7 +3158,7 @@ export async function fetchEnterpriseCommunication(): Promise<EnterpriseCommunic |
|
|
/* ===================== 岗位评价管理空状态 ===================== */ |
|
|
/* ===================== 岗位评价管理空状态 ===================== */ |
|
|
|
|
|
|
|
|
const MOCK_JOB_EVALUATION_EMPTY: JobEvaluationEmptyState = { |
|
|
const MOCK_JOB_EVALUATION_EMPTY: JobEvaluationEmptyState = { |
|
|
hasData: false, |
|
|
hasData: true, |
|
|
tabs: [ |
|
|
tabs: [ |
|
|
{ key: 'all', label: '全部', count: 0 }, |
|
|
{ key: 'all', label: '全部', count: 0 }, |
|
|
{ key: 'positive', label: '好评', count: 0 }, |
|
|
{ key: 'positive', label: '好评', count: 0 }, |
|
|
@ -3926,6 +3975,502 @@ export async function updatePrivacyCenterSetting( |
|
|
return mockRequest(MOCK_PRIVACY_CENTER); |
|
|
return mockRequest(MOCK_PRIVACY_CENTER); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 隐私二级设置页 ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 6 个开关类二级页的数据,键为页面 id(对应路由 /settings/privacy/[id]) |
|
|
|
|
|
* 【待确认】各页细选项的文案与默认开关状态,需产品与法务复核 |
|
|
|
|
|
*/ |
|
|
|
|
|
const MOCK_PRIVACY_DETAILS: Record<string, PrivacyDetailSetting> = { |
|
|
|
|
|
'real-name': { |
|
|
|
|
|
id: 'real-name', |
|
|
|
|
|
title: '真实姓名可见性', |
|
|
|
|
|
intro: '控制企业查看你的简历时能否看到真实姓名。关闭后将展示为「张先生」「李女士」等脱敏形式。', |
|
|
|
|
|
master: { id: 'real-name-master', title: '向企业展示真实姓名', enabled: true }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'rn-delivered', title: '已投递的企业可见', enabled: true }, |
|
|
|
|
|
{ id: 'rn-verified', title: '已完成企业认证的公司可见', enabled: true }, |
|
|
|
|
|
{ id: 'rn-masked', title: '未投递企业展示脱敏姓名', description: '如「张先生」', enabled: true }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '无论是否展示真实姓名,企业在发出 offer 前均需经过你的明示同意才能获取完整身份信息。', |
|
|
|
|
|
}, |
|
|
|
|
|
contact: { |
|
|
|
|
|
id: 'contact', |
|
|
|
|
|
title: '联系方式可见性', |
|
|
|
|
|
intro: '控制手机号、邮箱等联系方式的可见范围。建议进入面试环节后再向企业开放。', |
|
|
|
|
|
master: { id: 'contact-master', title: '向企业展示联系方式', enabled: true }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'ct-phone', title: '手机号', enabled: true }, |
|
|
|
|
|
{ id: 'ct-email', title: '邮箱', enabled: true }, |
|
|
|
|
|
{ id: 'ct-wechat', title: '微信号', enabled: false }, |
|
|
|
|
|
{ id: 'ct-after-interview', title: '仅进入面试后自动开放', enabled: true }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '开启「仅进入面试后自动开放」后,企业需将你推进至面试环节才能查看完整联系方式。', |
|
|
|
|
|
}, |
|
|
|
|
|
algo: { |
|
|
|
|
|
id: 'algo', |
|
|
|
|
|
title: '数据用于算法训练', |
|
|
|
|
|
intro: '开启后,你的匿名化行为数据将用于优化岗位匹配与推荐算法。训练数据经过去标识化处理,不含可识别身份的信息。', |
|
|
|
|
|
master: { id: 'algo-master', title: '数据用于算法训练', description: '匿名数据用于提升匹配效果', enabled: false }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'ag-browse', title: '使用浏览行为', enabled: false }, |
|
|
|
|
|
{ id: 'ag-delivery', title: '使用投递记录', enabled: false }, |
|
|
|
|
|
{ id: 'ag-chat', title: '使用沟通记录', description: '不含聊天正文,仅使用结构化结果', enabled: false }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '关闭后你仍可正常使用全部功能,但推荐精准度可能下降。你可随时重新开启。', |
|
|
|
|
|
}, |
|
|
|
|
|
'third-party': { |
|
|
|
|
|
id: 'third-party', |
|
|
|
|
|
title: '允许第三方数据分析', |
|
|
|
|
|
intro: '第三方数据分析用于生成行业薪酬报告与人才流动趋势。分析结果均为聚合统计,不含个人身份信息,且不会用于向你推送广告。', |
|
|
|
|
|
master: { id: 'tp-master', title: '允许第三方数据分析', enabled: false }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'tp-salary', title: '薪酬水平分析', enabled: false }, |
|
|
|
|
|
{ id: 'tp-flow', title: '人才流动趋势', enabled: false }, |
|
|
|
|
|
{ id: 'tp-skill', title: '技能需求统计', enabled: false }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '我们仅向具备数据安全资质的合作方提供聚合结果,并签署数据处理协议。', |
|
|
|
|
|
}, |
|
|
|
|
|
location: { |
|
|
|
|
|
id: 'location', |
|
|
|
|
|
title: '位置信息授权', |
|
|
|
|
|
intro: '位置信息仅用于为你推荐附近岗位与计算通勤时间。关闭后,推荐结果将按你填写的期望城市计算。', |
|
|
|
|
|
master: { id: 'loc-master', title: '位置信息授权', description: '仅用于岗位推荐', enabled: true }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'loc-precise', title: '使用精确定位', enabled: true }, |
|
|
|
|
|
{ id: 'loc-background', title: '允许后台获取位置', description: '关闭后仅在使用应用时获取', enabled: false }, |
|
|
|
|
|
{ id: 'loc-commute', title: '用于通勤时间计算', enabled: true }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '我们不会持续上传你的位置轨迹,位置信息仅在本地完成距离计算后即被丢弃。', |
|
|
|
|
|
}, |
|
|
|
|
|
contacts: { |
|
|
|
|
|
id: 'contacts', |
|
|
|
|
|
title: '通讯录权限', |
|
|
|
|
|
intro: '授权通讯录后,你可以快速发现已在平台的好友,也能邀请同事加入。我们仅在本地比对通讯录,不会上传或存储你的联系人信息。', |
|
|
|
|
|
master: { id: 'cnt-master', title: '通讯录权限', enabled: false }, |
|
|
|
|
|
options: [ |
|
|
|
|
|
{ id: 'cnt-discover', title: '发现通讯录好友', enabled: false }, |
|
|
|
|
|
{ id: 'cnt-invite', title: '向好友推荐岗位', enabled: false }, |
|
|
|
|
|
{ id: 'cnt-network', title: '同步人脉关系', description: '用于展示可能认识的同行', enabled: false }, |
|
|
|
|
|
], |
|
|
|
|
|
note: '通讯录比对通过本地哈希完成,服务端无法还原你的联系人姓名与号码。', |
|
|
|
|
|
}, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取隐私二级设置页数据(开关类) |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/privacy/:id |
|
|
|
|
|
* @param id { string } 页面 id,如 real-name / contact / algo |
|
|
|
|
|
* @returns Promise<PrivacyDetailSetting | null> 找不到时返回 null |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchPrivacyDetailSetting( |
|
|
|
|
|
id: string, |
|
|
|
|
|
): Promise<PrivacyDetailSetting | null> { |
|
|
|
|
|
// TODO: const res = await fetch(`${API_BASE_URL}/api/settings/privacy/${id}`, { method: 'GET' }); return res.json();
|
|
|
|
|
|
const detail = MOCK_PRIVACY_DETAILS[id]; |
|
|
|
|
|
return mockRequest(detail ? { ...detail } : null); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 更新隐私二级设置页的开关(主开关或细选项) |
|
|
|
|
|
* @method PATCH |
|
|
|
|
|
* @url /api/settings/privacy/:id |
|
|
|
|
|
* @param id { string } 页面 id |
|
|
|
|
|
* @param optionId { string } 主开关或细选项 id |
|
|
|
|
|
* @param enabled { boolean } 目标状态 |
|
|
|
|
|
* @returns Promise<PrivacyDetailSetting | null> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function updatePrivacyDetailSetting( |
|
|
|
|
|
id: string, |
|
|
|
|
|
optionId: string, |
|
|
|
|
|
enabled: boolean, |
|
|
|
|
|
): Promise<PrivacyDetailSetting | null> { |
|
|
|
|
|
// TODO: await fetch(`${API_BASE_URL}/api/settings/privacy/${id}`, {
|
|
|
|
|
|
// method: 'PATCH', headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
// body: JSON.stringify({ optionId, enabled }),
|
|
|
|
|
|
// });
|
|
|
|
|
|
const detail = MOCK_PRIVACY_DETAILS[id]; |
|
|
|
|
|
if (!detail) return mockRequest(null); |
|
|
|
|
|
if (detail.master.id === optionId) { |
|
|
|
|
|
detail.master.enabled = enabled; |
|
|
|
|
|
} else { |
|
|
|
|
|
const option = detail.options.find((item) => item.id === optionId); |
|
|
|
|
|
if (option) option.enabled = enabled; |
|
|
|
|
|
} |
|
|
|
|
|
return mockRequest({ ...detail }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 勿扰模式 ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
const MOCK_DND_SETTING: DndSetting = { |
|
|
|
|
|
enabled: true, |
|
|
|
|
|
startTime: '22:00', |
|
|
|
|
|
endTime: '08:00', |
|
|
|
|
|
allowUrgent: true, |
|
|
|
|
|
blockedCount: 128, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取勿扰模式设置 |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/privacy/dnd |
|
|
|
|
|
* @returns Promise<DndSetting> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchDndSetting(): Promise<DndSetting> { |
|
|
|
|
|
return mockRequest({ ...MOCK_DND_SETTING }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 更新勿扰模式设置 |
|
|
|
|
|
* @method PATCH |
|
|
|
|
|
* @url /api/settings/privacy/dnd |
|
|
|
|
|
* @param payload { Partial<DndSetting> } 需更新的字段 |
|
|
|
|
|
* @returns Promise<DndSetting> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function updateDndSetting(payload: Partial<DndSetting>): Promise<DndSetting> { |
|
|
|
|
|
Object.assign(MOCK_DND_SETTING, payload); |
|
|
|
|
|
return mockRequest({ ...MOCK_DND_SETTING }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 关键词屏蔽 ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
const MOCK_KEYWORD_BLOCK: KeywordBlockSetting = { |
|
|
|
|
|
keywords: ['外包', '兼职', '刷单'], |
|
|
|
|
|
blockedCount: 3, |
|
|
|
|
|
suggestions: ['无责底薪', '日结', '在家兼职', '急招临时工'], |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取关键词屏蔽设置 |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/privacy/keywords |
|
|
|
|
|
* @returns Promise<KeywordBlockSetting> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchKeywordBlock(): Promise<KeywordBlockSetting> { |
|
|
|
|
|
return mockRequest({ ...MOCK_KEYWORD_BLOCK, keywords: [...MOCK_KEYWORD_BLOCK.keywords] }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 添加屏蔽关键词 |
|
|
|
|
|
* @method POST |
|
|
|
|
|
* @url /api/settings/privacy/keywords |
|
|
|
|
|
* @param keyword { string } 待屏蔽的关键词 |
|
|
|
|
|
* @returns Promise<KeywordBlockSetting> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function addBlockKeyword(keyword: string): Promise<KeywordBlockSetting> { |
|
|
|
|
|
const value = keyword.trim(); |
|
|
|
|
|
if (value && !MOCK_KEYWORD_BLOCK.keywords.includes(value)) { |
|
|
|
|
|
MOCK_KEYWORD_BLOCK.keywords.push(value); |
|
|
|
|
|
} |
|
|
|
|
|
return mockRequest({ ...MOCK_KEYWORD_BLOCK, keywords: [...MOCK_KEYWORD_BLOCK.keywords] }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 移除屏蔽关键词 |
|
|
|
|
|
* @method DELETE |
|
|
|
|
|
* @url /api/settings/privacy/keywords/:keyword |
|
|
|
|
|
* @param keyword { string } 待移除的关键词 |
|
|
|
|
|
* @returns Promise<KeywordBlockSetting> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function removeBlockKeyword(keyword: string): Promise<KeywordBlockSetting> { |
|
|
|
|
|
MOCK_KEYWORD_BLOCK.keywords = MOCK_KEYWORD_BLOCK.keywords.filter((item) => item !== keyword); |
|
|
|
|
|
return mockRequest({ ...MOCK_KEYWORD_BLOCK, keywords: [...MOCK_KEYWORD_BLOCK.keywords] }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 账号注销 ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
const MOCK_ACCOUNT_CANCEL: AccountCancelData = { |
|
|
|
|
|
title: '账号注销', |
|
|
|
|
|
consequences: [ |
|
|
|
|
|
'账号将无法登录,平台内所有数据将被永久删除且无法恢复', |
|
|
|
|
|
'正在进行的投递、面试邀约与沟通记录将全部终止', |
|
|
|
|
|
'已获得的会员权益、优惠券、成长值与勋章将失效且不予退还', |
|
|
|
|
|
'若你已完成企业认证,认证信息与关联招聘流程将一并注销', |
|
|
|
|
|
], |
|
|
|
|
|
checklist: [ |
|
|
|
|
|
{ id: 'balance', label: '账户余额已清零', resolved: false, actionText: '去提现' }, |
|
|
|
|
|
{ id: 'orders', label: '无进行中的付费订单', resolved: true }, |
|
|
|
|
|
{ id: 'delivery', label: '无进行中的投递与面试', resolved: true }, |
|
|
|
|
|
{ id: 'enterprise', label: '企业认证已解除', resolved: true }, |
|
|
|
|
|
], |
|
|
|
|
|
reasons: ['已找到工作', '不再需要该服务', '隐私担忧', '使用体验不佳', '其他'], |
|
|
|
|
|
canCancel: false, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取账号注销前置信息 |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/account-cancel |
|
|
|
|
|
* @returns Promise<AccountCancelData> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchAccountCancel(): Promise<AccountCancelData> { |
|
|
|
|
|
return mockRequest({ |
|
|
|
|
|
...MOCK_ACCOUNT_CANCEL, |
|
|
|
|
|
canCancel: MOCK_ACCOUNT_CANCEL.checklist.every((item) => item.resolved), |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 提交账号注销申请 |
|
|
|
|
|
* @method POST |
|
|
|
|
|
* @url /api/settings/account-cancel |
|
|
|
|
|
* @param reason { string } 注销原因 |
|
|
|
|
|
* @returns Promise<{ success: boolean; message: string }> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function submitAccountCancel( |
|
|
|
|
|
_reason: string, |
|
|
|
|
|
): Promise<{ success: boolean; message: string }> { |
|
|
|
|
|
// TODO: await fetch(`${API_BASE_URL}/api/settings/account-cancel`, {
|
|
|
|
|
|
// method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
// body: JSON.stringify({ reason }),
|
|
|
|
|
|
// });
|
|
|
|
|
|
return mockRequest({ |
|
|
|
|
|
success: true, |
|
|
|
|
|
message: '注销申请已提交,我们将在 7 个工作日内完成审核并以短信通知你', |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 删除全部数据 ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
const MOCK_DELETE_ALL_DATA: DeleteAllData = { |
|
|
|
|
|
intro: '你可以选择删除部分或全部个人数据。删除操作不可撤销,请在确认前仔细阅读各项说明。', |
|
|
|
|
|
categories: [ |
|
|
|
|
|
{ id: 'resume', label: '简历数据', description: '简历正文、附件与历史版本', count: '12 条' }, |
|
|
|
|
|
{ id: 'delivery', label: '投递记录', description: '历史投递与进展状态', count: '128 条' }, |
|
|
|
|
|
{ id: 'chat', label: '沟通记录', description: '与企业 HR 的聊天消息', count: '1,024 条' }, |
|
|
|
|
|
{ id: 'assessment', label: '测评结果', description: '能力测评与职业兴趣测评', count: '8 条' }, |
|
|
|
|
|
{ id: 'behavior', label: '行为数据', description: '浏览、搜索与点击记录', count: '约 5,000 条' }, |
|
|
|
|
|
], |
|
|
|
|
|
warning: '删除后数据将无法恢复,并可能影响岗位推荐准确度与竞争力排名的计算结果。', |
|
|
|
|
|
confirmPlaceholder: '请输入「删除全部数据」以确认', |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取可删除的数据分类 |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/delete-data |
|
|
|
|
|
* @returns Promise<DeleteAllData> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchDeleteAllData(): Promise<DeleteAllData> { |
|
|
|
|
|
return mockRequest({ ...MOCK_DELETE_ALL_DATA }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 提交删除数据请求 |
|
|
|
|
|
* @method POST |
|
|
|
|
|
* @url /api/settings/delete-data |
|
|
|
|
|
* @param categoryIds { string[] } 待删除的分类 id 列表 |
|
|
|
|
|
* @returns Promise<{ success: boolean; message: string }> |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function submitDeleteData( |
|
|
|
|
|
categoryIds: string[], |
|
|
|
|
|
): Promise<{ success: boolean; message: string }> { |
|
|
|
|
|
// TODO: await fetch(`${API_BASE_URL}/api/settings/delete-data`, {
|
|
|
|
|
|
// method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
// body: JSON.stringify({ categoryIds }),
|
|
|
|
|
|
// });
|
|
|
|
|
|
return mockRequest({ |
|
|
|
|
|
success: true, |
|
|
|
|
|
message: `已提交删除申请,涉及 ${categoryIds.length} 项数据,预计 3 个工作日内处理完成`, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* ===================== 法律文档(隐私政策 / 用户协议) ===================== */ |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 隐私政策正文 |
|
|
|
|
|
* 【待确认】文中公司全称、联系邮箱、客服电话、数据存储地等需法务确认后替换占位内容 |
|
|
|
|
|
*/ |
|
|
|
|
|
const MOCK_PRIVACY_POLICY: LegalDocument = { |
|
|
|
|
|
id: 'privacy-policy', |
|
|
|
|
|
title: '隐私政策', |
|
|
|
|
|
version: 'V1.0', |
|
|
|
|
|
updatedAt: '2026-08-31', |
|
|
|
|
|
effectiveAt: '2026-08-31', |
|
|
|
|
|
preamble: |
|
|
|
|
|
'职来(以下简称「我们」)深知个人信息对你的重要性,并会尽全力保护你的个人信息安全可靠。我们致力于维持你对我们的信任,恪守以下原则保护你的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则。本政策适用于你通过职来平台(含移动客户端、网站及关联服务)所进行的全部活动。', |
|
|
|
|
|
sections: [ |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '一、我们收集的信息', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'在您注册账号或使用平台服务时,我们会收集您主动提供的信息,包括手机号码、验证码、密码等注册信息;以及您后续完善简历时填写的姓名、性别、出生日期、教育经历、工作经历、项目经历、技能标签、期望岗位与期望薪资等。', |
|
|
|
|
|
'在您使用服务过程中,我们会收集设备信息(设备型号、操作系统版本、唯一设备标识符)、日志信息(浏览记录、搜索关键词、点击记录、IP 地址、访问时间)以及位置信息(仅在您授权后收集,用于推荐附近岗位)。', |
|
|
|
|
|
'若您使用企业端服务,我们还将收集企业工商信息、营业执照、招聘联系人身份信息及认证材料,用于完成企业资质审核。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '二、我们如何使用信息', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'我们收集的信息将用于:为您创建并维护账号、展示与匹配岗位、生成竞争力排名与测评报告、处理您的投递与沟通请求、向您发送面试邀约与重要通知。', |
|
|
|
|
|
'为提升推荐的准确性,我们会在您授权的前提下使用匿名化、去标识化后的行为数据优化算法模型。您可在「设置 - 隐私中心」中随时关闭该授权,关闭后您仍可正常使用全部功能。', |
|
|
|
|
|
'我们不会将您的个人信息用于本政策未载明的其他目的。如确需变更使用目的,我们将重新征得您的明示同意。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '三、信息的共享、转让与公开披露', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'我们不会向任何第三方出售您的个人信息。除下列情形外,我们不会与第三方共享您的信息:(1)获得您的明示同意;(2)您主动向企业投递简历后,向该企业提供您授权范围内的简历内容;(3)为实现「岗位推荐」等功能而向合作的服务供应商提供必要信息,且该等供应商受保密义务约束;(4)根据法律法规或主管部门的强制性要求。', |
|
|
|
|
|
'我们仅在聚合、匿名化后向第三方提供行业薪酬报告与人才流动趋势等统计分析结果,该等结果无法识别到特定个人。', |
|
|
|
|
|
'如因合并、分立、重组等导致信息转移,我们将告知您接收方的名称与联系方式,并要求其继续受本政策约束;若接收方变更原有处理目的,将重新征求您的同意。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '四、信息的存储与保护', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'我们在中华人民共和国境内收集和产生的个人信息将存储于境内。我们仅在本政策所述目的所必需的期间内保留您的个人信息,超出保留期限后将进行删除或匿名化处理。', |
|
|
|
|
|
'我们已采取符合业界标准的安全防护措施保护您的个人信息,包括传输层加密、存储加密、访问权限控制、安全审计与应急预案。但请您理解,任何安全措施都无法做到绝对无懈可击,我们将持续努力提升防护水平。', |
|
|
|
|
|
'若不幸发生个人信息泄露等安全事件,我们将按照法律法规要求,及时以站内信、短信或邮件等方式告知您事件的基本情况、影响范围、已采取的措施及您的应对建议。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '五、您的权利', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'您对自己的个人信息享有查询、更正、补充、删除、复制、撤回同意以及注销账号的权利。您可直接在「设置 - 隐私中心」或「设置 - 个人数据导出」中行使上述权利,我们将在 15 个工作日内予以响应。', |
|
|
|
|
|
'您可随时在隐私中心调整真实姓名可见性、联系方式可见性、个性化推荐、算法训练授权、第三方数据分析、位置与通讯录授权等开关。关闭相应授权后,我们将停止对应的信息处理活动。', |
|
|
|
|
|
'如您认为我们的处理行为损害了您的合法权益,您可通过本政策载明的联系方式向我们投诉,我们会在收到投诉后 15 个工作日内作出答复;您也可向有关主管部门举报或提起诉讼。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '六、未成年人保护', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'本平台主要面向具有劳动能力的成年人提供求职招聘服务。若您未满 18 周岁,请在监护人的陪同下阅读本政策,并在取得监护人明示同意后再使用本平台服务。', |
|
|
|
|
|
'我们不会主动收集未满 18 周岁用户的个人信息。若我们是未事先获得监护人同意而收集了未成年人的个人信息,我们会尽快删除相关数据。', |
|
|
|
|
|
'如您对您所监护的未成年人的个人信息有疑问,请通过本政策载明的联系方式与我们联系。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '七、Cookie 与同类技术', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'为保障产品正常运转、提升使用体验,我们会在您的设备上存储名为 Cookie 的小型数据文件。您可根据自己的偏好管理或删除 Cookie。', |
|
|
|
|
|
'我们使用 Cookie 主要用于:记住您的登录状态、保存您的筛选偏好、分析页面访问情况以优化产品。关闭 Cookie 后,部分功能可能无法正常使用。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '八、本政策的更新', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'我们的隐私政策可能适时修订。未经您明示同意,我们不会削减您依据本政策所享有的权利。', |
|
|
|
|
|
'当政策发生重大变更时,我们会在版本更新后通过站内推送、弹窗或短信等显著方式向您提示,您可查阅最新版本。重大变更包括但不限于:服务模式发生重大变化、个人信息处理目的与方式发生重大变化、您参与个人信息处理方面的权利及其行使方式发生重大变化。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '九、联系我们', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'如您对本政策或您的个人信息处理有任何疑问、意见或建议,可通过以下方式与我们联系:【待确认:客服邮箱 / 客服电话 / 个人信息保护负责人邮箱】。', |
|
|
|
|
|
'公司名称:【待确认:公司全称】。注册地址:【待确认:注册地址】。我们将在收到您的请求后 15 个工作日内答复。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
], |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 用户协议正文 |
|
|
|
|
|
* 【待确认】文中公司全称、争议解决管辖法院、违约金条款等需法务确认后替换占位内容 |
|
|
|
|
|
*/ |
|
|
|
|
|
const MOCK_USER_AGREEMENT: LegalDocument = { |
|
|
|
|
|
id: 'user-agreement', |
|
|
|
|
|
title: '用户协议', |
|
|
|
|
|
version: 'V1.0', |
|
|
|
|
|
updatedAt: '2026-08-31', |
|
|
|
|
|
effectiveAt: '2026-08-31', |
|
|
|
|
|
preamble: |
|
|
|
|
|
'本协议是你与职来平台运营方【待确认:公司全称】(以下简称「平台」)之间就使用职来平台服务所订立的协议。在使用平台各项服务前,请你务必审慎阅读、充分理解本协议各条款内容,特别是以粗体或下划线标注的免责条款、责任限制条款与争议解决条款。如你未满 18 周岁,请在法定监护人的陪同下阅读并决定是否同意本协议。', |
|
|
|
|
|
sections: [ |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '一、协议的范围与接受', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'本协议适用于你使用职来平台提供的全部服务,包括但不限于职位浏览与搜索、简历创建与投递、在线沟通、能力测评、竞争力排名、AI 模拟面试、求职进度管理以及企业端的职位发布、人才搜索与招聘管理功能。', |
|
|
|
|
|
'你通过点击「同意」「注册」或以其他任何方式实际使用平台服务,即视为你已阅读并同意受本协议约束。若你不同意本协议,请立即停止使用平台服务。', |
|
|
|
|
|
'平台有权在必要时修订本协议并在平台上公布。修订后的协议自公布之日起生效。若你继续使用平台服务,即视为你已接受修订后的协议。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '二、账号注册与使用', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'你需要使用本人真实手机号码完成注册,并保证所提供的注册信息真实、准确、完整,且及时更新。因你提供的信息不实导致的全部后果由你自行承担。', |
|
|
|
|
|
'账号的所有权归平台所有,你仅享有账号的使用权。未经平台书面同意,你不得以任何形式出借、转让、出租或售卖账号。', |
|
|
|
|
|
'你应妥善保管账号与密码,因你主动泄露、遗失或被他人盗用而导致的损失由你自行承担。发现账号异常时,你应立即通过平台提供的渠道申请冻结并修改密码。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '三、用户行为规范', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'你承诺在使用平台服务时遵守中华人民共和国法律法规、社会主义制度、国家利益、公民合法权益、公共秩序、社会道德风尚与信息真实性等「七条底线」。', |
|
|
|
|
|
'你不得利用平台服务制作、复制、发布、传播如下内容:反对宪法所确定的基本原则的;危害国家安全、泄露国家秘密、颠覆国家政权、破坏国家统一的;损害国家荣誉和利益的;歪曲、丑化、亵渎、否定英雄烈士事迹和精神的;宣扬恐怖主义、极端主义或者煽动实施恐怖活动、极端主义活动的;煽动民族仇恨、民族歧视、破坏民族团结的;破坏国家宗教政策,宣扬邪教和封建迷信的;散布谣言,扰乱经济秩序和社会秩序的;散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;侮辱或者诽谤他人,侵害他人名誉、隐私和其他合法权益的;以及含有其他违反法律法规禁止性内容的信息。', |
|
|
|
|
|
'你不得利用平台服务从事以下行为:使用任何插件、外挂、系统或第三方工具干扰平台正常运行;批量注册账号、批量投递或恶意刷取数据;爬取、抓取或以其他技术手段获取平台数据;发布虚假职位或虚假简历;冒用他人身份或企业名义;以及损害平台或第三方合法权益的其他行为。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '四、求职者服务规则', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'你应确保所填写的简历信息真实、准确,不得虚构学历、工作经历、项目经历或技能水平。因简历信息不实导致企业拒绝录用、解除劳动关系或产生其他争议的,由你自行承担全部责任。', |
|
|
|
|
|
'平台提供的岗位信息由企业自行发布,平台已尽合理努力对企业资质与职位真实性进行审核,但不对职位的具体内容、薪酬实际发放、劳动条件及后续履约承担保证责任。你在应聘过程中应保持审慎,注意甄别招聘诈骗风险。', |
|
|
|
|
|
'平台的竞争力排名、匹配度、测评结果等均为基于现有数据的参考性分析,不构成对你求职结果或录用概率的承诺或保证。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '五、企业服务规则', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'企业用户须提供真实、合法、有效的营业执照与认证材料,并确保所发布的职位信息真实、合法、准确,不存在就业歧视(包括但不限于性别、民族、宗教信仰、地域、年龄、健康状况等)内容。', |
|
|
|
|
|
'企业用户不得发布虚假职位、以招聘为名实施培训贷、收取押金、扣押证件、传销或其他违法活动。一经发现,平台有权立即下架职位、冻结或注销账号,并保留向有关主管部门报告的权利。', |
|
|
|
|
|
'企业用户应依法保护所获取的求职者个人信息,仅可将简历用于自身招聘目的,不得转售、泄露或用于其他商业用途。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '六、知识产权', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'平台及平台所使用的软件、技术、商标、材料等所有知识产权归平台或相关权利人所有。未经许可,任何人不得擅自使用、修改、复制、传播、反向工程或创造衍生作品。', |
|
|
|
|
|
'你在使用平台服务期间发布上传的文字、图片、视频、音频等均由你原创或已获合法授权。你同意授予平台为提供服务之目的在全球范围内免费、非独占的使用许可。', |
|
|
|
|
|
'你发布的原创内容著作权仍归你所有,但你的发布行为视为同意平台在本平台内外进行展示、推广及其他合法使用。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '七、免责声明与责任限制', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'鉴于网络服务的特殊性,你同意平台有权随时变更、中断或终止部分或全部服务(包括收费服务)。如因服务器维护、网络拥塞、黑客攻击、电信部门技术调整或故障、第三方网站或页面原因造成服务中断或数据丢失,平台不承担责任。', |
|
|
|
|
|
'平台不对下列情形承担责任:你因第三方(包括其他用户、企业用户、外部链接指向的网站)的行为而遭受的损失;你自行泄露账号密码或授权他人使用而造成的损失;因不可抗力导致的损失。', |
|
|
|
|
|
'在法律允许的最大范围内,平台就本协议所承担的赔偿责任总额,不超过你因使用该服务而向平台支付的费用总额;如你未支付费用,则平台不承担赔偿责任。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '八、违约处理', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'若你违反本协议任一条款,平台有权独立判断并立即采取以下一项或多项措施:警告并要求限期改正;删除违规内容;限制或禁止使用部分或全部功能;暂停或终止账号服务;注销账号并清除全部数据;以及追究法律责任。', |
|
|
|
|
|
'因你的违约行为给平台或第三方造成损失的,你应承担全部赔偿责任,赔偿范围包括但不限于直接经济损失、商誉损失、律师费、诉讼费、公证费以及平台为处理投诉而支出的合理费用。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '九、协议变更与终止', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'平台有权在必要时修订本协议。协议修订后,平台将在相关页面公布修订后的协议。你继续使用平台服务即视为你已接受修订后的协议。', |
|
|
|
|
|
'你有权随时停止使用平台服务并注销账号。账号注销后,本协议终止,但你在使用服务期间的既有义务(包括但不限于赔偿责任、保密义务)不因协议终止而免除。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
heading: '十、法律适用与争议解决', |
|
|
|
|
|
paragraphs: [ |
|
|
|
|
|
'本协议的订立、执行与解释以及争议的解决均适用中华人民共和国大陆地区法律(不含冲突法)。', |
|
|
|
|
|
'如双方就本协议内容或其执行发生任何争议,应尽量友好协商解决;协商不成时,任何一方均可向【待确认:管辖法院所在地】有管辖权的人民法院提起诉讼。', |
|
|
|
|
|
'本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议涵义解释的依据。', |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
|
|
|
], |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取法律文档(隐私政策 / 用户协议) |
|
|
|
|
|
* @method GET |
|
|
|
|
|
* @url /api/settings/legal-document/:id |
|
|
|
|
|
* @param id { string } 文档 id,privacy-policy 或 user-agreement |
|
|
|
|
|
* @returns Promise<LegalDocument | null> 找不到时返回 null |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function fetchLegalDocument(id: string): Promise<LegalDocument | null> { |
|
|
|
|
|
// TODO: const res = await fetch(`${API_BASE_URL}/api/settings/legal-document/${id}`, { method: 'GET' }); return res.json();
|
|
|
|
|
|
if (id === 'privacy-policy') return mockRequest({ ...MOCK_PRIVACY_POLICY }); |
|
|
|
|
|
if (id === 'user-agreement') return mockRequest({ ...MOCK_USER_AGREEMENT }); |
|
|
|
|
|
return mockRequest(null); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* ===================== 个人数据导出 ===================== */ |
|
|
/* ===================== 个人数据导出 ===================== */ |
|
|
|
|
|
|
|
|
const MOCK_PERSONAL_DATA_EXPORT: PersonalDataExport = { |
|
|
const MOCK_PERSONAL_DATA_EXPORT: PersonalDataExport = { |
|
|
|