feat: first commit

This commit is contained in:
eleanor.mao
2025-03-31 22:34:22 +08:00
commit d25187c9c8
390 changed files with 57031 additions and 0 deletions

View File

@ -0,0 +1,134 @@
import { Button } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import SafeBottomPadding from '@/components/safe-bottom-padding';
import { EventName } from '@/constants/app';
import { CollectEventName } from '@/constants/event';
import { ProfileGroupType, ProfileTitleMap } from '@/constants/material';
import ProfileAdvantagesFragment from '@/fragments/profile/advantages';
import ProfileBasicFragment from '@/fragments/profile/basic';
import ProfileExperienceFragment from '@/fragments/profile/experience';
import ProfileIntentionFragment from '@/fragments/profile/intention';
import { MaterialProfile } from '@/types/material';
import { logWithPrefix } from '@/utils/common';
import { collectEvent } from '@/utils/event';
import { isFullTimePriceRequired, isPartTimePriceRequired } from '@/utils/job';
import { updateProfile, subscribeMaterialMessage } from '@/utils/material';
import { navigateBack } from '@/utils/route';
import Toast from '@/utils/toast';
import './index.less';
const PREFIX = 'page-material-create-profile';
const log = logWithPrefix(PREFIX);
const REQUIRE_KEYS = {
[ProfileGroupType.Basic]: ['name', 'gender', 'age', 'height', 'weight'],
[ProfileGroupType.Intention]: [
'cityCodes',
'employType',
'acceptWorkForSit',
'fullTimeMinPrice',
'fullTimeMaxPrice',
'partyTimeMinPrice',
'partyTimeMaxPrice',
],
[ProfileGroupType.Experience]: ['workedYear'],
[ProfileGroupType.Advantages]: [],
};
const CONDITIONAL_REQUIRED_KEYS = {
[ProfileGroupType.Intention]: [
['fullTimeMinPrice', (data) => isFullTimePriceRequired(data.employType)],
['fullTimeMaxPrice', (data) => isFullTimePriceRequired(data.employType)],
['partyTimeMinPrice', (data) => isPartTimePriceRequired(data.employType)],
['partyTimeMaxPrice', (data) => isPartTimePriceRequired(data.employType)],
],
}
const getNextStepGroupType = (curType: ProfileGroupType) => {
switch (curType) {
case ProfileGroupType.Basic:
return ProfileGroupType.Advantages;
case ProfileGroupType.Intention:
return ProfileGroupType.Experience;
case ProfileGroupType.Experience:
return ProfileGroupType.Basic;
default:
return null;
}
};
const isValidFormData = (type: ProfileGroupType, data: Partial<MaterialProfile>) => {
const requireKeys = REQUIRE_KEYS[type] || [];
const conditionalKeys = CONDITIONAL_REQUIRED_KEYS[type] || []
const requiredValidator = (key: any) => typeof data[key] !== 'undefined' && data[key] !== ''
return requireKeys.every(requiredValidator) && conditionalKeys.every(([key, validator]) => {
return !validator(data) || requiredValidator(key)
});
};
export default function MaterialCreateProfile() {
const [groupType, setGroupType] = useState<ProfileGroupType>(ProfileGroupType.Intention);
const ref = useRef<{ getData: () => Partial<MaterialProfile> } | null>(null);
const ProfileFragment =
groupType === ProfileGroupType.Basic
? ProfileBasicFragment
: groupType === ProfileGroupType.Intention
? ProfileIntentionFragment
: groupType === ProfileGroupType.Experience
? ProfileExperienceFragment
: groupType === ProfileGroupType.Advantages
? ProfileAdvantagesFragment
: Fragment;
const handleSubmit = useCallback(async () => {
try {
const data = ref.current?.getData();
log('handleSubmit data:', data);
if (!data) {
throw new Error('数据异常');
}
if (!isValidFormData(groupType, data)) {
Toast.error('重要选项必填!');
return;
}
const nextType = getNextStepGroupType(groupType);
log('handleSubmit nextType:', nextType);
if (nextType) {
await updateProfile(data);
} else {
// 发起订阅不能在异步任务中,保证是第一个
await Promise.all([subscribeMaterialMessage(), updateProfile(data)]);
}
Taro.eventCenter.trigger(EventName.CREATE_PROFILE);
nextType ? setGroupType(nextType) : navigateBack(2);
} catch (e) {
Toast.error('保存失败请重试');
collectEvent(CollectEventName.CREATE_MATERIAL_FAILED, e);
}
}, [ref, groupType]);
useEffect(() => {
const title = ProfileTitleMap[groupType];
Taro.setNavigationBarTitle({ title });
}, [groupType]);
return (
<div className={PREFIX}>
<ProfileFragment ref={ref} profile={{}} />
<SafeBottomPadding />
<div className={`${PREFIX}__footer`}>
<Button className={`${PREFIX}__submit-btn`} onClick={handleSubmit}>
{groupType === ProfileGroupType.Advantages ? '完成' : '下一步'}
</Button>
<SafeBottomPadding />
</div>
</div>
);
}