5 Commits

Author SHA1 Message Date
828e9b7512 feat: update style 2025-09-19 23:53:17 +08:00
1d8a0d7a33 feat: update 2025-09-19 23:49:31 +08:00
8e42fef4f7 feat: ps 2025-09-11 21:28:01 +08:00
6f7e78896a feat: distance 2025-09-10 21:37:20 +08:00
b9cd0a3e6d feat: update material card 2025-09-08 23:28:17 +08:00
15 changed files with 261 additions and 155 deletions

View File

@ -9,7 +9,7 @@ import { PageUrl } from '@/constants/app';
import { MaterialViewSource, WORK_YEAR_LABELS } from '@/constants/material';
import { AnchorInfo } from '@/types/material';
import { calcDistance } from '@/utils/location';
import { getBasicInfo } from '@/utils/material';
import { getBasicInfo, getSalary } from '@/utils/material';
import { navigateTo } from '@/utils/route';
import { activeDate } from '@/utils/time';
@ -22,17 +22,6 @@ interface IProps {
}
const PREFIX = 'anchor-card';
const getSalary = (data: AnchorInfo) => {
const { fullTimeMinPrice, fullTimeMaxPrice, partyTimeMinPrice, partyTimeMaxPrice } = data;
const prices: string[] = [];
if (fullTimeMinPrice && fullTimeMaxPrice) {
prices.push(`${fullTimeMinPrice / 1000}-${fullTimeMaxPrice / 1000}K/月`);
}
if (partyTimeMinPrice && partyTimeMaxPrice) {
prices.push(`${partyTimeMinPrice}-${partyTimeMaxPrice}/小时`);
}
return prices.filter(Boolean).join(' ');
};
function AnchorCard(props: IProps) {
const { data, jobId, validator } = props;

View File

@ -5,34 +5,19 @@ import { isEqual } from 'lodash-es';
import { useCallback, useState } from 'react';
import PickerToolbar from '@/components/picker-toolbar';
import {
EmployType,
ALL_EMPLOY_TYPES,
FULL_PRICE_OPTIONS,
PART_PRICE_OPTIONS,
EMPLOY_TYPE_TITLE_MAP,
} from '@/constants/job';
import {
ALL_ANCHOR_READ_TYPES,
ALL_GENDER_TYPES,
ANCHOR_READ_TITLE_MAP,
AnchorReadType,
GENDER_TYPE_TITLE_MAP,
GenderType,
} from '@/constants/material';
import { FULL_PRICE_OPTIONS, PART_PRICE_OPTIONS } from '@/constants/job';
import { ALL_ANCHOR_READ_TYPES, ANCHOR_READ_TITLE_MAP, AnchorReadType } from '@/constants/material';
import { IAnchorFilters } from '@/types/material';
import { isUndefined } from '@/utils/common';
import './index.less';
type MoreFilter = Omit<IAnchorFilters, 'employType' | 'gender'>;
interface IProps {
value: IAnchorFilters;
onConfirm: (newValue: IAnchorFilters) => void;
value: MoreFilter;
onConfirm: (newValue: MoreFilter) => void;
}
const PREFIX = 'anchor-picker';
const getDefaultGender = (value: IAnchorFilters) => value.gender;
const getDefaultEmploy = (value: IAnchorFilters) => value.employType;
const getDefaultReadType = (value: IAnchorFilters) => value.readType;
const getDefaultCategory = (value: IAnchorFilters) => value.category || '';
const getSalaryValue = (value: IAnchorFilters, full: boolean) => {
@ -47,9 +32,7 @@ const getSalaryValue = (value: IAnchorFilters, full: boolean) => {
function AnchorPicker(props: IProps) {
const { value, onConfirm } = props;
const [gender, setGender] = useState<GenderType | undefined>(getDefaultGender(value));
const [readType, setReadType] = useState<AnchorReadType | undefined>(getDefaultReadType(value));
const [employType, setEmployType] = useState<EmployType | undefined>(getDefaultEmploy(value));
const [fullSalary, setFullSalary] = useState(getSalaryValue(value, true));
const [partSalary, setPartSalary] = useState(getSalaryValue(value, false));
const [category, setCategory] = useState(getDefaultCategory(value));
@ -59,9 +42,7 @@ function AnchorPicker(props: IProps) {
}, []);
const handleClickReset = useCallback(() => {
setGender(undefined);
setReadType(undefined);
setEmployType(undefined);
setFullSalary(null);
setPartSalary(null);
setCategory('');
@ -83,10 +64,6 @@ function AnchorPicker(props: IProps) {
const handleClickConfirm = useCallback(() => {
const filters: IAnchorFilters = {};
if (!isUndefined(gender)) {
filters.gender = gender === GenderType.All ? undefined : gender;
}
employType && (filters.employType = employType);
readType && (filters.readType = readType);
category && (filters.category = category);
if (fullSalary) {
@ -98,34 +75,10 @@ function AnchorPicker(props: IProps) {
filters.highPriceForPartyTime = partSalary.maxSalary;
}
onConfirm(filters);
}, [gender, employType, readType, category, fullSalary, partSalary, onConfirm]);
}, [readType, category, fullSalary, partSalary, onConfirm]);
return (
<div className={PREFIX}>
<div className={`${PREFIX}__title`}></div>
<div className={`${PREFIX}__container`}>
{ALL_GENDER_TYPES.map((type: GenderType) => (
<div
key={type}
onClick={() => setGender(type)}
className={classNames(`${PREFIX}__item`, { selected: type === gender })}
>
{GENDER_TYPE_TITLE_MAP[type]}
</div>
))}
</div>
<div className={`${PREFIX}__title`}>/</div>
<div className={`${PREFIX}__container`}>
{ALL_EMPLOY_TYPES.map(type => (
<div
key={type}
onClick={() => setEmployType(type)}
className={classNames(`${PREFIX}__item`, { selected: type === employType })}
>
{EMPLOY_TYPE_TITLE_MAP[type]}
</div>
))}
</div>
<div className={`${PREFIX}__title`}>/</div>
<div className={`${PREFIX}__container`}>
{ALL_ANCHOR_READ_TYPES.map(type => (

View File

@ -0,0 +1,13 @@
import Select, { ISelectProps } from '@/components/select';
import { GENDER_OPTIONS, GenderType } from '@/constants/material';
interface IProps extends Omit<ISelectProps<GenderType>, 'options'> {
value: GenderType;
}
function GenderSelect(props: IProps) {
const { value: selectValue, onSelect } = props;
return <Select options={GENDER_OPTIONS} title="性别" value={selectValue} onSelect={onSelect} />;
}
export default GenderSelect;

View File

@ -11,7 +11,7 @@ import { EMPLOY_TYPE_TITLE_MAP, EmployType } from '@/constants/job';
import { JobInfo } from '@/types/job';
// import { LocationInfo } from '@/types/location';
import { getJobSalary, getJobTitle } from '@/utils/job';
// import { calcDistance } from '@/utils/location';
import { calcDistance } from '@/utils/location';
import { navigateTo, redirectTo } from '@/utils/route';
import './index.less';
@ -45,7 +45,7 @@ function JobCard(props: IProps) {
publisher,
publisherAvatar,
jobLocation,
// distance,
distance,
isAuthed = false,
} = data;
@ -84,12 +84,12 @@ function JobCard(props: IProps) {
<div className={`${PREFIX}__summary`}>{jobDescription || sourceText}</div>
<div className={`${PREFIX}__distance-wrapper`}>
<div className={`${PREFIX}__detailed-address`}>{jobLocation?.address}</div>
{/*{distance && (*/}
{/* <>*/}
{/* <Image className={`${PREFIX}__distance-icon`} src={require('@/statics/svg/location.svg')} />*/}
{/* <div className={`${PREFIX}__distance`}>{calcDistance(distance)}</div>*/}
{/* </>*/}
{/*)}*/}
{distance && (
<>
<Image className={`${PREFIX}__distance-icon`} src={require('@/statics/svg/location.svg')} />
<div className={`${PREFIX}__distance`}>{calcDistance(distance)}</div>
</>
)}
</div>
</div>
<div className={`${PREFIX}__divider`} />

View File

@ -4,7 +4,7 @@
.material-card {
padding: 32px 24px;
border-radius: 16px;
background: #FFFFFF;
background: #ffffff;
box-sizing: border-box;
&__header {
@ -16,6 +16,10 @@
.flex-row();
}
&__right {
color: @blHighlightColor;
}
&__title {
font-size: 32px;
line-height: 40px;
@ -50,7 +54,7 @@
&__body {
width: 100%;
height: 156px;
height: 160px;
margin-top: 24px;
.flex-column();
justify-content: center;
@ -80,38 +84,44 @@
}
}
&__scroll-view {
position: relative;
&__info {
.flex-row();
gap: 24px;
width: 100%;
height: 100%;
.flex-row();
&::-webkit-scrollbar {
display: none;
&-left {
width: 125px;
height: 160px;
}
&::after {
content: '';
position: absolute;
right: 0;
width: 102px;
&-cover {
width: 100%;
height: 100%;
background: linear-gradient(91.41deg, rgba(255, 255, 255, 0) 1.86%, #FFFFFF 99.47%);
border-radius: 12px;
}
&-right {
.name {
font-style: normal;
font-weight: 500;
font-size: 28px;
line-height: 32px;
color: @blColor;
margin-bottom: 12px;
}
.info,
.worked {
font-weight: 400;
font-size: 24px;
line-height: 36px;
color: @blColorG2;
margin-bottom: 8px;
}
.salary {
font-weight: 500;
font-size: 24px;
line-height: 36px;
color: @blColor;
}
}
}
&__cover-list {
height: 100%;
.flex-row();
}
&__cover-image {
width: 120px;
height: 100%;
margin-right: 24px;
// 不知道为啥高度不对,可能 scroll-view 默认底部是滚动条高度?
margin-top: 38px;
border-radius: 8px;
}
}
}

View File

@ -1,4 +1,4 @@
import { Image, ScrollView } from '@tarojs/components';
import { Image } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { Loading } from '@taroify/core';
@ -9,11 +9,12 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import LoginButton from '@/components/login-button';
import { EventName, PageUrl } from '@/constants/app';
import { CollectEventName, ReportEventId } from '@/constants/event';
import { WORK_YEAR_LABELS } from '@/constants/material';
import useUserInfo from '@/hooks/use-user-info';
import { MaterialProfile } from '@/types/material';
import { logWithPrefix } from '@/utils/common';
import { collectEvent, reportEvent } from '@/utils/event';
import { requestProfileDetail, sortVideos } from '@/utils/material';
import { getBasicInfo, getSalary, requestProfileDetail, sortVideos } from '@/utils/material';
import { navigateTo } from '@/utils/route';
import Toast from '@/utils/toast';
import { isValidUserInfo } from '@/utils/user';
@ -34,8 +35,9 @@ function MaterialCard(props: IProps) {
const userInfo = useUserInfo();
const [loading, setLoading] = useState(true);
const [profile, setProfile] = useState<MaterialProfile | null>(null);
const refreshRef = useRef((_f?: boolean) => { });
const refreshRef = useRef((_f?: boolean) => {});
const hasMaterial = !!profile;
const firstCover = sortVideos(profile?.materialVideoInfoList || [])[0];
const handleGoCreateProfile = useCallback(() => {
reportEvent(ReportEventId.CLICK_GO_TO_CREATE_MATERIAL);
@ -44,7 +46,7 @@ function MaterialCard(props: IProps) {
const handleGoProfile = useCallback(() => {
if (!hasMaterial) {
realtimeLogger.info('handleGoProfile noMaterial')
realtimeLogger.info('handleGoProfile noMaterial');
return;
}
navigateTo(PageUrl.MaterialProfile).catch(err => {
@ -67,7 +69,7 @@ function MaterialCard(props: IProps) {
try {
const profileDetail = await requestProfileDetail();
if (!profileDetail) {
realtimeLogger.info('getProfileDetail no profileDetail')
realtimeLogger.info('getProfileDetail no profileDetail');
}
setProfile(profileDetail);
} catch (e) {
@ -90,8 +92,10 @@ function MaterialCard(props: IProps) {
refreshRef.current?.(true);
};
Taro.eventCenter.on(EventName.CREATE_PROFILE, callback);
Taro.eventCenter.on(EventName.UPDATE_PROFILE, callback);
return () => {
Taro.eventCenter.off(EventName.CREATE_PROFILE, callback);
Taro.eventCenter.on(EventName.UPDATE_PROFILE, callback);
};
}, [userInfo]);
@ -100,16 +104,11 @@ function MaterialCard(props: IProps) {
<div className={`${PREFIX}__header`}>
<div className={`${PREFIX}__header__left`}>
<div className={`${PREFIX}__header__title`}></div>
{/* {profile && (
<div
className={`${PREFIX}__header__progress`}
>{`完成度${Math.min((profile.progressBar || 0) * 100, 100)}%`}</div>
)} */}
</div>
{profile && (
<div className={`${PREFIX}__header__right`}>
{/* <div className={`${PREFIX}__header__status`}>{profile?.isOpen ? '开放中' : '关闭'}</div> */}
<ArrowRight className={`${PREFIX}__header__icon`} />
<div></div>
<ArrowRight color="#6D3DF5" className={`${PREFIX}__header__icon`} />
</div>
)}
</div>
@ -123,18 +122,21 @@ function MaterialCard(props: IProps) {
</div>
)}
{!loading && hasMaterial && (
<ScrollView className={`${PREFIX}__scroll-view`} showScrollbar={false} enableFlex enhanced scrollX>
<div className={`${PREFIX}__cover-list`}>
{sortVideos(profile?.materialVideoInfoList || []).map(video => (
<Image
className={`${PREFIX}__cover-image`}
mode="aspectFit"
key={video.coverUrl}
src={video.coverUrl}
/>
))}
<div className={`${PREFIX}__info`}>
{firstCover && (
<div className={`${PREFIX}__info-left`}>
<Image className={`${PREFIX}__info-cover`} mode="aspectFill" src={firstCover.coverUrl} />
</div>
)}
<div className={`${PREFIX}__info-right`}>
<div className="name">{profile?.name}</div>
<div className="info">
{WORK_YEAR_LABELS[profile?.workedYear] || ''}·{getBasicInfo({ ...profile, shoeSize: null })}
</div>
<div className="worked"> {profile?.workedSecCategoryStr}</div>
<div className="salary">{getSalary(profile)}</div>
</div>
</ScrollView>
</div>
)}
{loading && <Loading />}
</div>

View File

@ -28,6 +28,7 @@
justify-content: space-between;
box-sizing: border-box;
padding: 0 24px;
flex: 0 0 96px;
&.selected {
color: @blHighlightColor;
@ -45,4 +46,4 @@
border-top-left-radius: 24px;
border-top-right-radius: 24px;
}
}
}

View File

@ -0,0 +1,13 @@
import Select, { ISelectProps } from '@/components/select';
import { JOB_TYPE_SELECT_OPTIONS_WITH_ALL, JobType } from '@/constants/job';
interface IProps extends Omit<ISelectProps<JobType>, 'options'> {
value: JobType;
}
function TopCategorySelect(props: IProps) {
const { value: selectValue, onSelect } = props;
return <Select options={JOB_TYPE_SELECT_OPTIONS_WITH_ALL} title="品类" value={selectValue} onSelect={onSelect} />;
}
export default TopCategorySelect;

View File

@ -7,6 +7,7 @@ export enum JobType {
Jewelry = 'JEWELRY', // 珠宝
Appliance = 'APPLIANCE', // 家电
Furniture = 'FURNITURE', // 日用家具
OutdoorSports = 'OUTDOOR_SPORTS',
PetFamily = 'PET_FAMILY', // 母婴宠物
Luxury = 'LUXURY', // 奢品
LocalLive = 'LOCAL_LIVE', // 本地生活
@ -87,6 +88,7 @@ export const JOB_TYPE_TITLE_MAP: { [key in JobType]: string } = {
[JobType.Jewelry]: '珠宝',
[JobType.Appliance]: '家电',
[JobType.Furniture]: '日用家具',
[JobType.OutdoorSports]: '户外运动',
[JobType.PetFamily]: '母婴宠物',
[JobType.Luxury]: '奢品',
[JobType.LocalLive]: '本地生活',
@ -173,6 +175,7 @@ export const JOB_TYPE_SELECT_OPTIONS = [
{ label: JOB_TYPE_TITLE_MAP[JobType.Jewelry], value: JobType.Jewelry },
{ label: JOB_TYPE_TITLE_MAP[JobType.Appliance], value: JobType.Appliance },
{ label: JOB_TYPE_TITLE_MAP[JobType.Furniture], value: JobType.Furniture },
{ label: JOB_TYPE_TITLE_MAP[JobType.OutdoorSports], value: JobType.OutdoorSports },
{ label: JOB_TYPE_TITLE_MAP[JobType.PetFamily], value: JobType.PetFamily },
{ label: JOB_TYPE_TITLE_MAP[JobType.Luxury], value: JobType.Luxury },
{ label: JOB_TYPE_TITLE_MAP[JobType.LocalLive], value: JobType.LocalLive },
@ -181,6 +184,11 @@ export const JOB_TYPE_SELECT_OPTIONS = [
{ label: JOB_TYPE_TITLE_MAP[JobType.Other], value: JobType.Other },
];
export const JOB_TYPE_SELECT_OPTIONS_WITH_ALL = [
{ label: JOB_TYPE_TITLE_MAP[JobType.All], value: JobType.All },
...JOB_TYPE_SELECT_OPTIONS,
];
const MAX_SALARY = 10000000;
export const PART_EMPLOY_SALARY_OPTIONS = [
{ label: '不限' },

View File

@ -84,14 +84,25 @@ export const WORK_YEAR_OPTIONS = [
{ label: WORK_YEAR_LABELS[WorkedYears.MoreThreeYear], value: WorkedYears.MoreThreeYear },
];
export const ALL_GENDER_TYPES = [GenderType.All, GenderType.MEN, GenderType.WOMEN];
export const GENDER_TYPE_TITLE_MAP = {
[GenderType.All]: '不限',
[GenderType.WOMEN]: '女',
[GenderType.MEN]: '男',
};
export const GENDER_OPTIONS = [
{
value: GenderType.All,
label: GENDER_TYPE_TITLE_MAP[GenderType.All],
},
{
value: GenderType.WOMEN,
label: GENDER_TYPE_TITLE_MAP[GenderType.WOMEN],
},
{
value: GenderType.MEN,
label: GENDER_TYPE_TITLE_MAP[GenderType.MEN],
},
];
export const ALL_ANCHOR_READ_TYPES = Object.values(AnchorReadType);
export const ANCHOR_READ_TITLE_MAP = {

View File

@ -52,7 +52,11 @@
font-size: 28px;
line-height: 32px;
color: @blColor;
gap: 20px;
&-item {
display: flex;
}
.title {
margin-right: 5px;
}
@ -61,11 +65,17 @@
padding: 0 24px;
}
&__overlay-outer {
top: 82px;
top: 72px;
}
&__overlay-inner {
width: 100%;
max-height: 100%;
overflow: hidden;
.bl-select__items-container {
max-height: calc(100vh - 610rpx);
overflow-y: auto;
}
}
&__tips-container {
@ -91,8 +101,6 @@
margin-top: 50px;
}
&__popup {
&-content {
.flex-column();

View File

@ -5,11 +5,13 @@ import { Popup } from '@taroify/core';
import { ArrowDown, ArrowUp } from '@taroify/icons';
import classNames from 'classnames';
import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import AnchorList, { IAnchorListProps } from '@/components/anchor-list';
import AnchorPicker from '@/components/anchor-picker';
import CustomNavigationBar from '@/components/custom-navigation-bar';
import EmployTypeSelect from '@/components/employ-type-select';
import GenderSelect from '@/components/gender-select';
import HomePage from '@/components/home-page';
import Overlay from '@/components/overlay';
import PageLoading from '@/components/page-loading';
@ -17,8 +19,8 @@ import PartnerBanner from '@/components/partner-banner';
import SafeBottomPadding from '@/components/safe-bottom-padding';
import SwitchBar from '@/components/switch-bar';
import { APP_TAB_BAR_ID, EventName, OpenSource, PageType, PageUrl, RoleType } from '@/constants/app';
import { EmployType } from '@/constants/job';
import { ALL_ANCHOR_SORT_TYPES, ANCHOR_SORT_TYPE_TITLE_MAP, AnchorSortType } from '@/constants/material';
import { EmployType, JobType } from '@/constants/job';
import { ALL_ANCHOR_SORT_TYPES, ANCHOR_SORT_TYPE_TITLE_MAP, AnchorSortType, GenderType } from '@/constants/material';
import useInviteCode from '@/hooks/use-invite-code';
import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height';
import useLocation from '@/hooks/use-location';
@ -36,6 +38,7 @@ import { getCommonShareMessage } from '@/utils/share';
import Toast from '@/utils/toast';
import './index.less';
import TopCategorySelect from '@/components/top-category-select';
const PREFIX = 'page-anchor';
const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`;
@ -78,12 +81,22 @@ function ListWrapper(props: IAnchorListProps) {
return <AnchorList listHeight={listHeight} {...props} onListEmpty={handleListEmpty} />;
}
enum FilterType {
gender,
employType,
topCategory,
more,
}
export default function AnchorPage() {
const location = useLocation();
const [loading, setLoading] = useState(true);
const [selectJob, setSelectJob] = useState<JobManageInfo | undefined>();
const [filters, setFilters] = useState<IAnchorFilters>({ employType: EmployType.All });
const [showFilter, setShowFilter] = useState<boolean>(false);
const [moreFilters, setMoreFilters] = useState<IAnchorFilters>({});
const [gender, setGender] = useState<GenderType>(GenderType.All);
const [employType, setEmployType] = useState<EmployType>(EmployType.All);
const [topCategory, setTopCategory] = useState<JobType>(JobType.All);
const [showFilter, setShowFilter] = useState<FilterType | null>(null);
const [sortType, setSortType] = useState<AnchorSortType>(AnchorSortType.Active);
const [openPopup, setOpenPopup] = useState<boolean>(false);
const [coordinate, setCoordinate] = useState<Coordinate>({
@ -106,20 +119,35 @@ export default function AnchorPage() {
[selectJob]
);
const handleClickSalarySelect = useCallback(() => {
setShowFilter(!showFilter);
}, [showFilter]);
const handleClickFilterSelect = (type: FilterType) => () => {
setShowFilter(type === showFilter ? null : type);
};
const handleHideFilter = useCallback(() => setShowFilter(false), []);
const handleHideFilter = useCallback(() => setShowFilter(null), []);
const handleFilterChange = useCallback(
(newFilters: IAnchorFilters) => {
!isEqual(newFilters, filters) && setFilters(newFilters);
setShowFilter(false);
!isEqual(newFilters, moreFilters) && setMoreFilters(newFilters);
setShowFilter(null);
},
[filters]
[moreFilters]
);
const handleChangeSelectGender = useCallback((value: GenderType) => {
setGender(value);
setShowFilter(null);
}, []);
const handleChangeSelectEmployType = useCallback((value: EmployType) => {
setEmployType(value);
setShowFilter(null);
}, []);
const handleChangeSelectTopCategory = useCallback((value: JobType) => {
setTopCategory(value);
setShowFilter(null);
}, []);
const handleClickSortType = useCallback(async (type: AnchorSortType) => setSortType(type), []);
const handleJobChange = useCallback(
@ -205,6 +233,15 @@ export default function AnchorPage() {
useDidShow(() => requestUnreadMessageCount());
const filters = useMemo(
() => ({
...moreFilters,
topCategory,
gender: gender === -1 ? undefined : gender,
employType,
}),
[moreFilters, gender, employType, topCategory]
);
return (
<HomePage type={PageType.Anchor}>
{!!loading && <PageLoading className={`${PREFIX}__loading`} />}
@ -224,9 +261,23 @@ export default function AnchorPage() {
</div>
))}
</div>
<div className={classNames(`${PREFIX}__filter`)} onClick={handleClickSalarySelect}>
<div className="title"></div>
{showFilter ? <ArrowUp /> : <ArrowDown />}
<div className={classNames(`${PREFIX}__filter`)}>
<div className={`${PREFIX}__filter-item`} onClick={handleClickFilterSelect(FilterType.gender)}>
<div className="title"></div>
{showFilter === FilterType.gender ? <ArrowUp /> : <ArrowDown />}
</div>
<div className={`${PREFIX}__filter-item`} onClick={handleClickFilterSelect(FilterType.employType)}>
<div className="title"></div>
{showFilter === FilterType.employType ? <ArrowUp /> : <ArrowDown />}
</div>
<div className={`${PREFIX}__filter-item`} onClick={handleClickFilterSelect(FilterType.topCategory)}>
<div className="title"></div>
{showFilter === FilterType.topCategory ? <ArrowUp /> : <ArrowDown />}
</div>
<div className={`${PREFIX}__filter-item`} onClick={handleClickFilterSelect(FilterType.more)}>
<div className="title"></div>
{showFilter === FilterType.more ? <ArrowUp /> : <ArrowDown />}
</div>
</div>
</div>
<div className={`${PREFIX}__banner`}>
@ -243,12 +294,36 @@ export default function AnchorPage() {
className={LIST_CONTAINER_CLASS}
/>
<Overlay
visible={showFilter}
visible={showFilter === FilterType.gender}
onClickOuter={handleHideFilter}
outerClassName={`${PREFIX}__overlay-outer`}
innerClassName={`${PREFIX}__overlay-inner`}
>
<AnchorPicker value={filters} onConfirm={handleFilterChange} />
<GenderSelect value={gender} onSelect={handleChangeSelectGender} />
</Overlay>
<Overlay
visible={showFilter === FilterType.employType}
onClickOuter={handleHideFilter}
outerClassName={`${PREFIX}__overlay-outer`}
innerClassName={`${PREFIX}__overlay-inner`}
>
<EmployTypeSelect value={employType} onSelect={handleChangeSelectEmployType} />
</Overlay>
<Overlay
visible={showFilter === FilterType.topCategory}
onClickOuter={handleHideFilter}
outerClassName={`${PREFIX}__overlay-outer`}
innerClassName={`${PREFIX}__overlay-inner`}
>
<TopCategorySelect value={topCategory} onSelect={handleChangeSelectTopCategory} />
</Overlay>
<Overlay
visible={showFilter === FilterType.more}
onClickOuter={handleHideFilter}
outerClassName={`${PREFIX}__overlay-outer`}
innerClassName={`${PREFIX}__overlay-inner`}
>
<AnchorPicker value={moreFilters} onConfirm={handleFilterChange} />
</Overlay>
</div>
<Popup

View File

@ -9,13 +9,17 @@ import PageLoading from '@/components/page-loading';
import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
import SafeBottomPadding from '@/components/safe-bottom-padding';
import { EventName, OpenSource, PageUrl, RoleType } from '@/constants/app';
import { CertificationStatusType } from '@/constants/company';
import { CollectEventName } from '@/constants/event';
import { JobManageStatus } from '@/constants/job';
import { MaterialViewSource } from '@/constants/material';
import ProfileViewFragment from '@/fragments/profile/view';
import useInviteCode from '@/hooks/use-invite-code';
import useUserInfo from '@/hooks/use-user-info';
import { RESPONSE_ERROR_CODE } from '@/http/constant';
import { HttpError } from '@/http/error';
import store from '@/store';
import { cacheJobId } from '@/store/actions';
import { JobManageInfo } from '@/types/job';
import { MaterialProfile } from '@/types/material';
import { IJobMessage } from '@/types/message';
@ -29,10 +33,6 @@ import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner';
import { getPageQuery, navigateBack, navigateTo, redirectTo } from '@/utils/route';
import Toast from '@/utils/toast';
import './index.less';
import useUserInfo from '@/hooks/use-user-info';
import { CertificationStatusType } from '@/constants/company';
import store from '@/store';
import { cacheJobId } from '@/store/actions';
const PREFIX = 'page-material-view';

View File

@ -101,6 +101,7 @@ export interface IAnchorFilters {
lowPriceForPartyTime?: number;
highPriceForPartyTime?: number;
category?: string;
topCategory?: string;
readType?: AnchorReadType;
}

View File

@ -62,6 +62,28 @@ export const getBasicInfo = (profile: Pick<MaterialProfile, 'age' | 'height' | '
return result.join('·');
};
export const getSalary = (
data: Pick<MaterialProfile, 'fullTimeMaxPrice' | 'fullTimeMinPrice' | 'partyTimeMaxPrice' | 'partyTimeMinPrice'>
) => {
const { fullTimeMinPrice, fullTimeMaxPrice, partyTimeMinPrice, partyTimeMaxPrice } = data;
const prices: string[] = [];
if (fullTimeMinPrice && fullTimeMaxPrice) {
if (fullTimeMinPrice >= 50000) {
prices.push(`${fullTimeMinPrice / 1000}K以上/月`);
} else {
prices.push(`${fullTimeMinPrice / 1000}-${fullTimeMaxPrice / 1000}K/月`);
}
}
if (partyTimeMinPrice && partyTimeMaxPrice) {
if (partyTimeMinPrice >= 500) {
prices.push(`500以上/小时`);
} else {
prices.push(`${partyTimeMinPrice}-${partyTimeMaxPrice}/小时`);
}
}
return prices.filter(Boolean).join(' ');
};
export const chooseMedia = async (option: Taro.chooseMedia.Option = {}) => {
try {
const result = await Taro.chooseMedia({