You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.2 KiB
170 lines
6.2 KiB
import { useState } from 'react';
|
|
import { Image, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
|
|
import { colors, spacing } from '../../../src/theme';
|
|
import {
|
|
useEnterpriseCertification,
|
|
useIdentitySwitch,
|
|
useImagePick,
|
|
useOnboarding,
|
|
useRegisterFinish,
|
|
} from '../../../src/hooks';
|
|
import { ScreenShell } from '../ui/ScreenShell';
|
|
import { Illustration } from '../ui/Illustration';
|
|
import { PrimaryButton } from '../ui/PrimaryButton';
|
|
|
|
export function B3Recruiter() {
|
|
const { data, setData, back } = useOnboarding();
|
|
const finish = useRegisterFinish();
|
|
const { pick, picking, error: pickError } = useImagePick();
|
|
const { submit, submitting } = useEnterpriseCertification();
|
|
const { switchTo, switching } = useIdentitySwitch();
|
|
const [submitFailed, setSubmitFailed] = useState(false);
|
|
/** 服务端返回的失败原因(身份选择或认证提交),比「提交失败」四个字有用 */
|
|
const [failReason, setFailReason] = useState<string | null>(null);
|
|
|
|
// 三项都是认证必需,缺一项不放行:没有营业执照的「企业认证」提交不出有意义的结果
|
|
const canSubmit =
|
|
data.recruiterCompany.trim().length > 0 &&
|
|
data.recruiterContact.trim().length > 0 &&
|
|
data.recruiterLicenseUri !== null;
|
|
|
|
const pickLicense = async () => {
|
|
// 营业执照是文档,方形裁剪会把内容切掉,用 4:3
|
|
const result = await pick('library', { aspect: [4, 3] });
|
|
if (result.status === 'picked') setData({ recruiterLicenseUri: result.uri });
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
if (!canSubmit || submitting || switching) return;
|
|
setSubmitFailed(false);
|
|
setFailReason(null);
|
|
try {
|
|
/*
|
|
* 第一步:先让服务端确认这个账号是企业身份。
|
|
* 契约 POST /auth/identity/select 要求选 COMPANY 时必须带 company 资料;
|
|
* 这一步成功后才拿得到企业角色,后面的认证提交才有意义 —— 顺序不能反。
|
|
* 「提交认证」也**不等于**「认证通过」:认证结果由审核决定,本地不做任何置位。
|
|
*/
|
|
const identityOutcome = await switchTo('COMPANY', {
|
|
name: data.recruiterCompany.trim(),
|
|
industry: '',
|
|
description: '',
|
|
website: '',
|
|
address: '',
|
|
});
|
|
if (!identityOutcome.ok) {
|
|
setSubmitFailed(true);
|
|
setFailReason(identityOutcome.message ?? '企业身份创建失败,请稍后重试');
|
|
return;
|
|
}
|
|
|
|
// 第二步:提交企业认证资料,审核状态由接口返回驱动
|
|
const res = await submit({
|
|
companyName: data.recruiterCompany.trim(),
|
|
// B3 不采集统一社会信用代码,由企业端「企业认证」页补全(该页已存在且有入口)
|
|
creditCode: '',
|
|
licenseUrl: data.recruiterLicenseUri ?? undefined,
|
|
contactName: data.recruiterContact.trim(),
|
|
// 联系人手机号用注册时登录的手机号,避免再问一次
|
|
contactPhone: data.phone,
|
|
});
|
|
if (!res.success) {
|
|
setSubmitFailed(true);
|
|
setFailReason('认证提交未通过,请核对资料后重试');
|
|
return;
|
|
}
|
|
|
|
// 落地前 useRegisterFinish 会 flushSave,把认证资料一起落库
|
|
await finish('enterprise');
|
|
} catch (e) {
|
|
setSubmitFailed(true);
|
|
setFailReason((e as Error).message || '网络异常,请稍后重试');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<ScreenShell title="企业认证" showBack onBack={back}>
|
|
<Text style={styles.tip}>请完成企业认证,开启招聘之旅</Text>
|
|
|
|
<Text style={styles.label}>公司名称</Text>
|
|
<TextInput
|
|
style={styles.input}
|
|
value={data.recruiterCompany}
|
|
onChangeText={(t) => setData({ recruiterCompany: t })}
|
|
placeholder="请输入公司全称"
|
|
placeholderTextColor={colors.textHint}
|
|
/>
|
|
|
|
<Text style={styles.label}>营业执照</Text>
|
|
<Pressable
|
|
style={[styles.upload, picking && styles.dim]}
|
|
disabled={picking}
|
|
onPress={() => void pickLicense()}
|
|
>
|
|
{data.recruiterLicenseUri ? (
|
|
<Image source={{ uri: data.recruiterLicenseUri }} style={styles.licensePreview} resizeMode="cover" />
|
|
) : (
|
|
<Illustration name="businessLicense" size={96} radius={12} />
|
|
)}
|
|
<Text style={styles.uploadText}>
|
|
{data.recruiterLicenseUri ? '已选择,点击可重新选择' : '点击上传营业执照'}
|
|
</Text>
|
|
</Pressable>
|
|
|
|
{pickError ? <Text style={styles.error}>{pickError}</Text> : null}
|
|
|
|
<Text style={styles.label}>联系人</Text>
|
|
<TextInput
|
|
style={styles.input}
|
|
value={data.recruiterContact}
|
|
onChangeText={(t) => setData({ recruiterContact: t })}
|
|
placeholder="请输入联系人姓名"
|
|
placeholderTextColor={colors.textHint}
|
|
/>
|
|
|
|
{submitFailed ? (
|
|
<Text style={styles.error}>{failReason ?? '认证提交失败,请稍后重试'}</Text>
|
|
) : null}
|
|
|
|
<View style={styles.footer}>
|
|
<PrimaryButton
|
|
label="提交认证"
|
|
active={canSubmit && !submitting && !switching}
|
|
loading={submitting || switching}
|
|
onPress={() => void handleSubmit()}
|
|
/>
|
|
</View>
|
|
</ScreenShell>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
tip: { fontSize: 13, color: colors.textHint, marginBottom: spacing.block },
|
|
label: { fontSize: 14, fontWeight: '700', color: colors.textPrimary, marginTop: 16, marginBottom: 8 },
|
|
input: {
|
|
height: 50,
|
|
borderRadius: 12,
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
backgroundColor: colors.white,
|
|
paddingHorizontal: 14,
|
|
fontSize: 15,
|
|
color: colors.textPrimary,
|
|
},
|
|
upload: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 8,
|
|
paddingVertical: spacing.block,
|
|
borderRadius: 12,
|
|
borderWidth: 1,
|
|
borderStyle: 'dashed',
|
|
borderColor: colors.borderStrong,
|
|
backgroundColor: colors.white,
|
|
},
|
|
dim: { opacity: 0.5 },
|
|
licensePreview: { width: 160, height: 120, borderRadius: 12 },
|
|
uploadText: { fontSize: 13, color: colors.textHint },
|
|
error: { fontSize: 12, color: colors.dangerText, marginTop: spacing.sm },
|
|
footer: { marginTop: 28 },
|
|
});
|
|
|