Compare commits
2 Commits
feat/share
...
828e9b7512
| Author | SHA1 | Date | |
|---|---|---|---|
| 828e9b7512 | |||
| 1d8a0d7a33 |
@ -5,34 +5,19 @@ import { isEqual } from 'lodash-es';
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import PickerToolbar from '@/components/picker-toolbar';
|
import PickerToolbar from '@/components/picker-toolbar';
|
||||||
import {
|
import { FULL_PRICE_OPTIONS, PART_PRICE_OPTIONS } from '@/constants/job';
|
||||||
EmployType,
|
import { ALL_ANCHOR_READ_TYPES, ANCHOR_READ_TITLE_MAP, AnchorReadType } from '@/constants/material';
|
||||||
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 { IAnchorFilters } from '@/types/material';
|
import { IAnchorFilters } from '@/types/material';
|
||||||
import { isUndefined } from '@/utils/common';
|
|
||||||
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
|
type MoreFilter = Omit<IAnchorFilters, 'employType' | 'gender'>;
|
||||||
interface IProps {
|
interface IProps {
|
||||||
value: IAnchorFilters;
|
value: MoreFilter;
|
||||||
onConfirm: (newValue: IAnchorFilters) => void;
|
onConfirm: (newValue: MoreFilter) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PREFIX = 'anchor-picker';
|
const PREFIX = 'anchor-picker';
|
||||||
const getDefaultGender = (value: IAnchorFilters) => value.gender;
|
|
||||||
const getDefaultEmploy = (value: IAnchorFilters) => value.employType;
|
|
||||||
const getDefaultReadType = (value: IAnchorFilters) => value.readType;
|
const getDefaultReadType = (value: IAnchorFilters) => value.readType;
|
||||||
const getDefaultCategory = (value: IAnchorFilters) => value.category || '';
|
const getDefaultCategory = (value: IAnchorFilters) => value.category || '';
|
||||||
const getSalaryValue = (value: IAnchorFilters, full: boolean) => {
|
const getSalaryValue = (value: IAnchorFilters, full: boolean) => {
|
||||||
@ -47,9 +32,7 @@ const getSalaryValue = (value: IAnchorFilters, full: boolean) => {
|
|||||||
|
|
||||||
function AnchorPicker(props: IProps) {
|
function AnchorPicker(props: IProps) {
|
||||||
const { value, onConfirm } = props;
|
const { value, onConfirm } = props;
|
||||||
const [gender, setGender] = useState<GenderType | undefined>(getDefaultGender(value));
|
|
||||||
const [readType, setReadType] = useState<AnchorReadType | undefined>(getDefaultReadType(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 [fullSalary, setFullSalary] = useState(getSalaryValue(value, true));
|
||||||
const [partSalary, setPartSalary] = useState(getSalaryValue(value, false));
|
const [partSalary, setPartSalary] = useState(getSalaryValue(value, false));
|
||||||
const [category, setCategory] = useState(getDefaultCategory(value));
|
const [category, setCategory] = useState(getDefaultCategory(value));
|
||||||
@ -59,9 +42,7 @@ function AnchorPicker(props: IProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleClickReset = useCallback(() => {
|
const handleClickReset = useCallback(() => {
|
||||||
setGender(undefined);
|
|
||||||
setReadType(undefined);
|
setReadType(undefined);
|
||||||
setEmployType(undefined);
|
|
||||||
setFullSalary(null);
|
setFullSalary(null);
|
||||||
setPartSalary(null);
|
setPartSalary(null);
|
||||||
setCategory('');
|
setCategory('');
|
||||||
@ -83,10 +64,6 @@ function AnchorPicker(props: IProps) {
|
|||||||
|
|
||||||
const handleClickConfirm = useCallback(() => {
|
const handleClickConfirm = useCallback(() => {
|
||||||
const filters: IAnchorFilters = {};
|
const filters: IAnchorFilters = {};
|
||||||
if (!isUndefined(gender)) {
|
|
||||||
filters.gender = gender === GenderType.All ? undefined : gender;
|
|
||||||
}
|
|
||||||
employType && (filters.employType = employType);
|
|
||||||
readType && (filters.readType = readType);
|
readType && (filters.readType = readType);
|
||||||
category && (filters.category = category);
|
category && (filters.category = category);
|
||||||
if (fullSalary) {
|
if (fullSalary) {
|
||||||
@ -98,34 +75,10 @@ function AnchorPicker(props: IProps) {
|
|||||||
filters.highPriceForPartyTime = partSalary.maxSalary;
|
filters.highPriceForPartyTime = partSalary.maxSalary;
|
||||||
}
|
}
|
||||||
onConfirm(filters);
|
onConfirm(filters);
|
||||||
}, [gender, employType, readType, category, fullSalary, partSalary, onConfirm]);
|
}, [readType, category, fullSalary, partSalary, onConfirm]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={PREFIX}>
|
<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}__title`}>已读/未读</div>
|
||||||
<div className={`${PREFIX}__container`}>
|
<div className={`${PREFIX}__container`}>
|
||||||
{ALL_ANCHOR_READ_TYPES.map(type => (
|
{ALL_ANCHOR_READ_TYPES.map(type => (
|
||||||
|
|||||||
13
src/components/gender-select/index.tsx
Normal file
13
src/components/gender-select/index.tsx
Normal 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;
|
||||||
@ -61,7 +61,7 @@ export default function PartnerBanner() {
|
|||||||
<div className={`${PREFIX}__close`} onClick={handlePartnerBannerClose} />
|
<div className={`${PREFIX}__close`} onClick={handlePartnerBannerClose} />
|
||||||
</div>
|
</div>
|
||||||
{visible && (
|
{visible && (
|
||||||
<LoginDialog onCancel={() => setVisible(false)} onSuccess={handleBind} needPhone={needPhone} />
|
<LoginDialog disableCheck onCancel={() => setVisible(false)} onSuccess={handleBind} needPhone={needPhone} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
import { Button, Canvas } from '@tarojs/components';
|
import { Button, Canvas } from '@tarojs/components';
|
||||||
import Taro from '@tarojs/taro';
|
import Taro from '@tarojs/taro';
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { openCustomerServiceChat } from '@/utils/common';
|
import { openCustomerServiceChat } from '@/utils/common';
|
||||||
import { getCouponQrCode, generateMembershipCoupon } from '@/utils/coupon';
|
import { getPartnerQrcode } from '@/utils/partner';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
const PREFIX = 'partner-intro';
|
const PREFIX = 'partner-intro';
|
||||||
|
|
||||||
export default function PartnerIntro() {
|
export default function PartnerIntro() {
|
||||||
|
const [posterPath, setPosterPath] = useState('');
|
||||||
const getQrcode = async () => {
|
const getQrcode = async () => {
|
||||||
try {
|
try {
|
||||||
const { code } = await generateMembershipCoupon();
|
const data = await getPartnerQrcode(); // 假设 getPartnerQrcode 返回 ArrayBuffer
|
||||||
const data = await getCouponQrCode(code);
|
|
||||||
const base64 = Taro.arrayBufferToBase64(data);
|
const base64 = Taro.arrayBufferToBase64(data);
|
||||||
return `data:image/png;base64,${base64}`;
|
return `data:image/png;base64,${base64}`;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -36,9 +36,11 @@ export default function PartnerIntro() {
|
|||||||
height: 2668, // 实际绘制高度
|
height: 2668, // 实际绘制高度
|
||||||
destWidth: 750, // 目标显示宽度
|
destWidth: 750, // 目标显示宽度
|
||||||
destHeight: 1334, // 目标显示高度
|
destHeight: 1334, // 目标显示高度
|
||||||
fileType: 'png',
|
fileType: 'jpg',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setPosterPath(tempFilePath.tempFilePath);
|
||||||
|
|
||||||
resolve(tempFilePath.tempFilePath);
|
resolve(tempFilePath.tempFilePath);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -55,21 +57,21 @@ export default function PartnerIntro() {
|
|||||||
const canvas = res[0].node;
|
const canvas = res[0].node;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
canvas.width = 550 * 2;
|
canvas.width = 1500;
|
||||||
canvas.height = 918 * 2;
|
canvas.height = 2668;
|
||||||
ctx.scale(2, 2);
|
ctx.scale(2, 2);
|
||||||
|
|
||||||
// 绘制背景图片
|
// 绘制背景图片
|
||||||
const bgImage = canvas.createImage();
|
const bgImage = canvas.createImage();
|
||||||
const poster = 'https://publiccdn.neighbourhood.com.cn/img/share-coupon-poster.png';
|
const poster = 'https://publiccdn.neighbourhood.com.cn/img/poster.png'
|
||||||
bgImage.src = poster;
|
bgImage.src = poster;
|
||||||
bgImage.onload = () => {
|
bgImage.onload = () => {
|
||||||
ctx.drawImage(bgImage, 0, 0, 550, 918);
|
ctx.drawImage(bgImage, 0, 0, 750, 1334);
|
||||||
|
|
||||||
const qrCodeImage = canvas.createImage();
|
const qrCodeImage = canvas.createImage();
|
||||||
qrCodeImage.src = qrCode; // 假设 getQrcode() 返回的是二维码图片的路径
|
qrCodeImage.src = qrCode; // 假设 getQrcode() 返回的是二维码图片的路径
|
||||||
qrCodeImage.onload = () => {
|
qrCodeImage.onload = () => {
|
||||||
ctx.drawImage(qrCodeImage, 196, 600, 160, 160); // 绘制二维码,位置和大小
|
ctx.drawImage(qrCodeImage, 235, 894, 280, 280); // 绘制二维码,位置和大小
|
||||||
saveCanvasToTempFile().then(tempPath => {
|
saveCanvasToTempFile().then(tempPath => {
|
||||||
resolve(tempPath);
|
resolve(tempPath);
|
||||||
});
|
});
|
||||||
@ -82,10 +84,13 @@ export default function PartnerIntro() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
const savePoster = async () => {
|
const savePoster = async () => {
|
||||||
Taro.showLoading({ title: '正在生成海报' });
|
let filePath = posterPath;
|
||||||
const qrCode = await getQrcode();
|
if (!filePath) {
|
||||||
const filePath = await drawCanvas(qrCode);
|
Taro.showLoading({ title: '正在生成海报' });
|
||||||
Taro.hideLoading();
|
const qrCode = await getQrcode();
|
||||||
|
filePath = await drawCanvas(qrCode);
|
||||||
|
Taro.hideLoading();
|
||||||
|
}
|
||||||
|
|
||||||
const res = await Taro.getSetting();
|
const res = await Taro.getSetting();
|
||||||
const hasPermission = res.authSetting['scope.writePhotosAlbum'];
|
const hasPermission = res.authSetting['scope.writePhotosAlbum'];
|
||||||
@ -139,9 +144,7 @@ export default function PartnerIntro() {
|
|||||||
<div className={`${PREFIX}__block`}>
|
<div className={`${PREFIX}__block`}>
|
||||||
<div className={`${PREFIX}__title`}>分享方法</div>
|
<div className={`${PREFIX}__title`}>分享方法</div>
|
||||||
<div className={`${PREFIX}__card`}>
|
<div className={`${PREFIX}__card`}>
|
||||||
<div className={`${PREFIX}__body`}>
|
<div className={`${PREFIX}__body`}>分享小程序任意页面到群、朋友圈、好友即可</div>
|
||||||
点击底部按钮向好友群友赠送会员,或者分享通告列表、通告详情等页面给朋友即可
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${PREFIX}__block`}>
|
<div className={`${PREFIX}__block`}>
|
||||||
@ -160,10 +163,10 @@ export default function PartnerIntro() {
|
|||||||
|
|
||||||
<div className={`${PREFIX}__footer`}>
|
<div className={`${PREFIX}__footer`}>
|
||||||
<Button className={`${PREFIX}__download-button`} onClick={savePoster}>
|
<Button className={`${PREFIX}__download-button`} onClick={savePoster}>
|
||||||
朋友圈海报
|
下载海报
|
||||||
</Button>
|
</Button>
|
||||||
<Button className={`${PREFIX}__share-button`} openType="share">
|
<Button className={`${PREFIX}__share-button`} openType="share">
|
||||||
赠送会员给好友
|
分享邀请
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
|
flex: 0 0 96px;
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
color: @blHighlightColor;
|
color: @blHighlightColor;
|
||||||
@ -45,4 +46,4 @@
|
|||||||
border-top-left-radius: 24px;
|
border-top-left-radius: 24px;
|
||||||
border-top-right-radius: 24px;
|
border-top-right-radius: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/components/top-category-select/index.tsx
Normal file
13
src/components/top-category-select/index.tsx
Normal 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;
|
||||||
@ -7,6 +7,7 @@ export enum JobType {
|
|||||||
Jewelry = 'JEWELRY', // 珠宝
|
Jewelry = 'JEWELRY', // 珠宝
|
||||||
Appliance = 'APPLIANCE', // 家电
|
Appliance = 'APPLIANCE', // 家电
|
||||||
Furniture = 'FURNITURE', // 日用家具
|
Furniture = 'FURNITURE', // 日用家具
|
||||||
|
OutdoorSports = 'OUTDOOR_SPORTS',
|
||||||
PetFamily = 'PET_FAMILY', // 母婴宠物
|
PetFamily = 'PET_FAMILY', // 母婴宠物
|
||||||
Luxury = 'LUXURY', // 奢品
|
Luxury = 'LUXURY', // 奢品
|
||||||
LocalLive = 'LOCAL_LIVE', // 本地生活
|
LocalLive = 'LOCAL_LIVE', // 本地生活
|
||||||
@ -87,6 +88,7 @@ export const JOB_TYPE_TITLE_MAP: { [key in JobType]: string } = {
|
|||||||
[JobType.Jewelry]: '珠宝',
|
[JobType.Jewelry]: '珠宝',
|
||||||
[JobType.Appliance]: '家电',
|
[JobType.Appliance]: '家电',
|
||||||
[JobType.Furniture]: '日用家具',
|
[JobType.Furniture]: '日用家具',
|
||||||
|
[JobType.OutdoorSports]: '户外运动',
|
||||||
[JobType.PetFamily]: '母婴宠物',
|
[JobType.PetFamily]: '母婴宠物',
|
||||||
[JobType.Luxury]: '奢品',
|
[JobType.Luxury]: '奢品',
|
||||||
[JobType.LocalLive]: '本地生活',
|
[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.Jewelry], value: JobType.Jewelry },
|
||||||
{ label: JOB_TYPE_TITLE_MAP[JobType.Appliance], value: JobType.Appliance },
|
{ 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.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.PetFamily], value: JobType.PetFamily },
|
||||||
{ label: JOB_TYPE_TITLE_MAP[JobType.Luxury], value: JobType.Luxury },
|
{ label: JOB_TYPE_TITLE_MAP[JobType.Luxury], value: JobType.Luxury },
|
||||||
{ label: JOB_TYPE_TITLE_MAP[JobType.LocalLive], value: JobType.LocalLive },
|
{ 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 },
|
{ 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;
|
const MAX_SALARY = 10000000;
|
||||||
export const PART_EMPLOY_SALARY_OPTIONS = [
|
export const PART_EMPLOY_SALARY_OPTIONS = [
|
||||||
{ label: '不限' },
|
{ label: '不限' },
|
||||||
|
|||||||
@ -84,14 +84,25 @@ export const WORK_YEAR_OPTIONS = [
|
|||||||
{ label: WORK_YEAR_LABELS[WorkedYears.MoreThreeYear], value: WorkedYears.MoreThreeYear },
|
{ 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 = {
|
export const GENDER_TYPE_TITLE_MAP = {
|
||||||
[GenderType.All]: '不限',
|
[GenderType.All]: '不限',
|
||||||
[GenderType.WOMEN]: '女',
|
[GenderType.WOMEN]: '女',
|
||||||
[GenderType.MEN]: '男',
|
[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 ALL_ANCHOR_READ_TYPES = Object.values(AnchorReadType);
|
||||||
|
|
||||||
export const ANCHOR_READ_TITLE_MAP = {
|
export const ANCHOR_READ_TITLE_MAP = {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// export const DOMAIN = 'http://192.168.60.116:8082';
|
// export const DOMAIN = 'http://192.168.60.191:8082';
|
||||||
export const DOMAIN = process.env.BRAND === 'dev' ? 'https://dev.neighbourhood.cn' : 'https://neighbourhood.cn';
|
export const DOMAIN = process.env.BRAND === 'dev' ? 'https://dev.neighbourhood.cn' : 'https://neighbourhood.cn';
|
||||||
// export const DOMAIN = 'https://dev.neighbourhood.cn';
|
// export const DOMAIN = 'https://dev.neighbourhood.cn';
|
||||||
export const BASE_URL = `${DOMAIN}/api`;
|
export const BASE_URL = `${DOMAIN}/api`;
|
||||||
@ -85,7 +85,4 @@ export enum API {
|
|||||||
GET_PROFIT_STAT = '/user/profits',
|
GET_PROFIT_STAT = '/user/profits',
|
||||||
WITHDRAW = '/user/withdraw',
|
WITHDRAW = '/user/withdraw',
|
||||||
GET_WITHDRAW_LIST = '/user/withdraw/records',
|
GET_WITHDRAW_LIST = '/user/withdraw/records',
|
||||||
GENERATE_MEMBERSHIP_COUPON = '/coupon/membership/generate',
|
|
||||||
CLAIM_MEMBERSHIP_COUPON = '/coupon/membership/claim',
|
|
||||||
GET_VIP_QRCODE = '/user/getVipQrCode',
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,11 @@
|
|||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
color: @blColor;
|
color: @blColor;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
.title {
|
.title {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
@ -61,11 +65,17 @@
|
|||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
}
|
}
|
||||||
&__overlay-outer {
|
&__overlay-outer {
|
||||||
top: 82px;
|
top: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__overlay-inner {
|
&__overlay-inner {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
.bl-select__items-container {
|
||||||
|
max-height: calc(100vh - 610rpx);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__tips-container {
|
&__tips-container {
|
||||||
@ -91,8 +101,6 @@
|
|||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
&__popup {
|
&__popup {
|
||||||
&-content {
|
&-content {
|
||||||
.flex-column();
|
.flex-column();
|
||||||
|
|||||||
@ -5,11 +5,13 @@ import { Popup } from '@taroify/core';
|
|||||||
import { ArrowDown, ArrowUp } from '@taroify/icons';
|
import { ArrowDown, ArrowUp } from '@taroify/icons';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isEqual } from 'lodash-es';
|
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 AnchorList, { IAnchorListProps } from '@/components/anchor-list';
|
||||||
import AnchorPicker from '@/components/anchor-picker';
|
import AnchorPicker from '@/components/anchor-picker';
|
||||||
import CustomNavigationBar from '@/components/custom-navigation-bar';
|
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 HomePage from '@/components/home-page';
|
||||||
import Overlay from '@/components/overlay';
|
import Overlay from '@/components/overlay';
|
||||||
import PageLoading from '@/components/page-loading';
|
import PageLoading from '@/components/page-loading';
|
||||||
@ -17,8 +19,8 @@ import PartnerBanner from '@/components/partner-banner';
|
|||||||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
||||||
import SwitchBar from '@/components/switch-bar';
|
import SwitchBar from '@/components/switch-bar';
|
||||||
import { APP_TAB_BAR_ID, EventName, OpenSource, PageType, PageUrl, RoleType } from '@/constants/app';
|
import { APP_TAB_BAR_ID, EventName, OpenSource, PageType, PageUrl, RoleType } from '@/constants/app';
|
||||||
import { EmployType } from '@/constants/job';
|
import { EmployType, JobType } from '@/constants/job';
|
||||||
import { ALL_ANCHOR_SORT_TYPES, ANCHOR_SORT_TYPE_TITLE_MAP, AnchorSortType } from '@/constants/material';
|
import { ALL_ANCHOR_SORT_TYPES, ANCHOR_SORT_TYPE_TITLE_MAP, AnchorSortType, GenderType } from '@/constants/material';
|
||||||
import useInviteCode from '@/hooks/use-invite-code';
|
import useInviteCode from '@/hooks/use-invite-code';
|
||||||
import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height';
|
import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height';
|
||||||
import useLocation from '@/hooks/use-location';
|
import useLocation from '@/hooks/use-location';
|
||||||
@ -36,6 +38,7 @@ import { getCommonShareMessage } from '@/utils/share';
|
|||||||
import Toast from '@/utils/toast';
|
import Toast from '@/utils/toast';
|
||||||
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
import TopCategorySelect from '@/components/top-category-select';
|
||||||
|
|
||||||
const PREFIX = 'page-anchor';
|
const PREFIX = 'page-anchor';
|
||||||
const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`;
|
const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`;
|
||||||
@ -78,12 +81,22 @@ function ListWrapper(props: IAnchorListProps) {
|
|||||||
return <AnchorList listHeight={listHeight} {...props} onListEmpty={handleListEmpty} />;
|
return <AnchorList listHeight={listHeight} {...props} onListEmpty={handleListEmpty} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum FilterType {
|
||||||
|
gender,
|
||||||
|
employType,
|
||||||
|
topCategory,
|
||||||
|
more,
|
||||||
|
}
|
||||||
|
|
||||||
export default function AnchorPage() {
|
export default function AnchorPage() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [selectJob, setSelectJob] = useState<JobManageInfo | undefined>();
|
const [selectJob, setSelectJob] = useState<JobManageInfo | undefined>();
|
||||||
const [filters, setFilters] = useState<IAnchorFilters>({ employType: EmployType.All });
|
const [moreFilters, setMoreFilters] = useState<IAnchorFilters>({});
|
||||||
const [showFilter, setShowFilter] = useState<boolean>(false);
|
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 [sortType, setSortType] = useState<AnchorSortType>(AnchorSortType.Active);
|
||||||
const [openPopup, setOpenPopup] = useState<boolean>(false);
|
const [openPopup, setOpenPopup] = useState<boolean>(false);
|
||||||
const [coordinate, setCoordinate] = useState<Coordinate>({
|
const [coordinate, setCoordinate] = useState<Coordinate>({
|
||||||
@ -106,20 +119,35 @@ export default function AnchorPage() {
|
|||||||
[selectJob]
|
[selectJob]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClickSalarySelect = useCallback(() => {
|
const handleClickFilterSelect = (type: FilterType) => () => {
|
||||||
setShowFilter(!showFilter);
|
setShowFilter(type === showFilter ? null : type);
|
||||||
}, [showFilter]);
|
};
|
||||||
|
|
||||||
const handleHideFilter = useCallback(() => setShowFilter(false), []);
|
const handleHideFilter = useCallback(() => setShowFilter(null), []);
|
||||||
|
|
||||||
const handleFilterChange = useCallback(
|
const handleFilterChange = useCallback(
|
||||||
(newFilters: IAnchorFilters) => {
|
(newFilters: IAnchorFilters) => {
|
||||||
!isEqual(newFilters, filters) && setFilters(newFilters);
|
!isEqual(newFilters, moreFilters) && setMoreFilters(newFilters);
|
||||||
setShowFilter(false);
|
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 handleClickSortType = useCallback(async (type: AnchorSortType) => setSortType(type), []);
|
||||||
|
|
||||||
const handleJobChange = useCallback(
|
const handleJobChange = useCallback(
|
||||||
@ -205,6 +233,15 @@ export default function AnchorPage() {
|
|||||||
|
|
||||||
useDidShow(() => requestUnreadMessageCount());
|
useDidShow(() => requestUnreadMessageCount());
|
||||||
|
|
||||||
|
const filters = useMemo(
|
||||||
|
() => ({
|
||||||
|
...moreFilters,
|
||||||
|
topCategory,
|
||||||
|
gender: gender === -1 ? undefined : gender,
|
||||||
|
employType,
|
||||||
|
}),
|
||||||
|
[moreFilters, gender, employType, topCategory]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<HomePage type={PageType.Anchor}>
|
<HomePage type={PageType.Anchor}>
|
||||||
{!!loading && <PageLoading className={`${PREFIX}__loading`} />}
|
{!!loading && <PageLoading className={`${PREFIX}__loading`} />}
|
||||||
@ -224,9 +261,23 @@ export default function AnchorPage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className={classNames(`${PREFIX}__filter`)} onClick={handleClickSalarySelect}>
|
<div className={classNames(`${PREFIX}__filter`)}>
|
||||||
<div className="title">筛选</div>
|
<div className={`${PREFIX}__filter-item`} onClick={handleClickFilterSelect(FilterType.gender)}>
|
||||||
{showFilter ? <ArrowUp /> : <ArrowDown />}
|
<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>
|
</div>
|
||||||
<div className={`${PREFIX}__banner`}>
|
<div className={`${PREFIX}__banner`}>
|
||||||
@ -243,12 +294,36 @@ export default function AnchorPage() {
|
|||||||
className={LIST_CONTAINER_CLASS}
|
className={LIST_CONTAINER_CLASS}
|
||||||
/>
|
/>
|
||||||
<Overlay
|
<Overlay
|
||||||
visible={showFilter}
|
visible={showFilter === FilterType.gender}
|
||||||
onClickOuter={handleHideFilter}
|
onClickOuter={handleHideFilter}
|
||||||
outerClassName={`${PREFIX}__overlay-outer`}
|
outerClassName={`${PREFIX}__overlay-outer`}
|
||||||
innerClassName={`${PREFIX}__overlay-inner`}
|
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>
|
</Overlay>
|
||||||
</div>
|
</div>
|
||||||
<Popup
|
<Popup
|
||||||
|
|||||||
@ -1,130 +1 @@
|
|||||||
@import '@/styles/variables.less';
|
.give-vip {}
|
||||||
@import '@/styles/common.less';
|
|
||||||
|
|
||||||
.give-vip {
|
|
||||||
padding: 40px 24px 200px 24px;
|
|
||||||
&__hint {
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 48px;
|
|
||||||
color: @blColorG2;
|
|
||||||
gap: 12px;
|
|
||||||
.flex-row();
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
&__icon {
|
|
||||||
width: 65px;
|
|
||||||
height: 65px;
|
|
||||||
}
|
|
||||||
&__title {
|
|
||||||
margin-top: 24px;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 40px;
|
|
||||||
line-height: 48px;
|
|
||||||
color: @blColor;
|
|
||||||
text-align: center;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
gap: 12px;
|
|
||||||
.flex-row();
|
|
||||||
justify-content: center;
|
|
||||||
.highlight {
|
|
||||||
margin-left: -12px;
|
|
||||||
display: inline-block;
|
|
||||||
color: @blHighlightColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__bg {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
&__info {
|
|
||||||
&-block {
|
|
||||||
margin-top: 48px;
|
|
||||||
}
|
|
||||||
&-title {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
color: #1d2129;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
&-card {
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 24px;
|
|
||||||
padding: 32px;
|
|
||||||
}
|
|
||||||
&-body {
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 40px;
|
|
||||||
color: #333333;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
&-img {
|
|
||||||
width: 100%;
|
|
||||||
height: 614px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&__footer {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 32px;
|
|
||||||
box-shadow: 0px -4px 20px 0px #00000014;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__footer-body {
|
|
||||||
.flex-row();
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
&__button {
|
|
||||||
.button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px;);
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
&__coupon {
|
|
||||||
&-info {
|
|
||||||
position: relative;
|
|
||||||
margin-top: 32px;
|
|
||||||
padding: 24px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 24px;
|
|
||||||
|
|
||||||
.flex-column();
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-title {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 32px;
|
|
||||||
line-height: 48px;
|
|
||||||
color: @blHighlightColor;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
&-intro {
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 40px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
color: @blColor;
|
|
||||||
gap: 4px;
|
|
||||||
.flex-row();
|
|
||||||
.highlight {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 32px;
|
|
||||||
line-height: 56px;
|
|
||||||
color: @blHighlightColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&-valid {
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 40px;
|
|
||||||
|
|
||||||
color: @blColorG2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,103 +1,12 @@
|
|||||||
import { Image, Button } from '@tarojs/components';
|
import { Button } from '@taroify/core';
|
||||||
import { useLoad } from '@tarojs/taro';
|
|
||||||
|
|
||||||
import { Fragment, useCallback, useState } from 'react';
|
|
||||||
|
|
||||||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
|
||||||
import { PageUrl } from '@/constants/app';
|
|
||||||
import { logWithPrefix } from '@/utils/common';
|
import { logWithPrefix } from '@/utils/common';
|
||||||
import { claimMembershipCoupon, getCouponCodeFromQuery } from '@/utils/coupon';
|
|
||||||
import { getPageQuery, switchTab } from '@/utils/route';
|
|
||||||
import { formatTime } from '@/utils/time';
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
const PREFIX = 'give-vip';
|
const PREFIX = 'give-vip';
|
||||||
const log = logWithPrefix(PREFIX);
|
const log = logWithPrefix(PREFIX);
|
||||||
|
|
||||||
enum State {
|
|
||||||
PENDING,
|
|
||||||
SUCCESS,
|
|
||||||
FAILED,
|
|
||||||
}
|
|
||||||
export default function GiveVip() {
|
export default function GiveVip() {
|
||||||
const [state, setState] = useState<State>(State.PENDING);
|
return <div className={PREFIX}></div>;
|
||||||
const [expireAt, setExpireAt] = useState('');
|
|
||||||
const [usedBefore, setUsedBefore] = useState(false);
|
|
||||||
const handleNavigate = useCallback(() => {
|
|
||||||
switchTab(PageUrl.Job);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useLoad(() => {
|
|
||||||
const query = getPageQuery<{ d: string }>();
|
|
||||||
const code = getCouponCodeFromQuery(query);
|
|
||||||
claimMembershipCoupon(code!)
|
|
||||||
.then(res => {
|
|
||||||
setUsedBefore(res.usedBefore);
|
|
||||||
setExpireAt(res.usageExpireAt);
|
|
||||||
setState(Date.now() > new Date(res.usageExpireAt).getTime() ? State.FAILED : State.SUCCESS);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err);
|
|
||||||
setState(State.FAILED);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={PREFIX}>
|
|
||||||
{state === State.SUCCESS && (
|
|
||||||
<Fragment>
|
|
||||||
<div className={`${PREFIX}__title`}>
|
|
||||||
<Image src="https://publiccdn.neighbourhood.com.cn/img/partner-yes.svg" className={`${PREFIX}__icon`} />
|
|
||||||
<div>{usedBefore ? '宝子,你已经领过了,下周再来' : '宝子,播络会员领取成功'}</div>
|
|
||||||
</div>
|
|
||||||
<div className={`${PREFIX}__coupon-info`}>
|
|
||||||
<Image src="https://publiccdn.neighbourhood.com.cn/img/parnet-share-bg.png" className={`${PREFIX}__bg`} />
|
|
||||||
<div className={`${PREFIX}__coupon-title`}>播络日会员</div>
|
|
||||||
<div className={`${PREFIX}__coupon-intro`}>
|
|
||||||
会员有效期内可增加<div className="highlight">10次</div>报单机会
|
|
||||||
</div>
|
|
||||||
<div className={`${PREFIX}__coupon-valid`}>
|
|
||||||
有效期至:{formatTime(expireAt, 'YYYY/MM/DD HH:mm:ss', false)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
|
||||||
)}
|
|
||||||
{state === State.FAILED && (
|
|
||||||
<Fragment>
|
|
||||||
<div className={`${PREFIX}__hint`}>
|
|
||||||
<Image
|
|
||||||
src="https://publiccdn.neighbourhood.com.cn/img/link-invalid.svg"
|
|
||||||
mode="aspectFit"
|
|
||||||
className={`${PREFIX}__icon`}
|
|
||||||
/>
|
|
||||||
<div className={`${PREFIX}__hint-title`}>宝子,链接已失效</div>
|
|
||||||
</div>
|
|
||||||
<div className={`${PREFIX}__title`}>
|
|
||||||
请联系分享人<div className="highlight">再次分享</div>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
|
||||||
)}
|
|
||||||
<div className={`${PREFIX}__info-block`}>
|
|
||||||
<div className={`${PREFIX}__info-title`}>播络简介</div>
|
|
||||||
<div className={`${PREFIX}__info-card`}>
|
|
||||||
<div className={`${PREFIX}__info-body`}>
|
|
||||||
播络通告整理汇集了本地每日新增带货主播通告,方便大家及时找到高薪工作
|
|
||||||
</div>
|
|
||||||
<Image
|
|
||||||
className={`${PREFIX}__info-img`}
|
|
||||||
src="https://publiccdn.neighbourhood.com.cn/img/partner-share-coupon-img.png"
|
|
||||||
mode="heightFix"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={`${PREFIX}__footer`}>
|
|
||||||
<div className={`${PREFIX}__footer-body`}>
|
|
||||||
<Button className={`${PREFIX}__button`} onClick={handleNavigate}>
|
|
||||||
立即使用
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<SafeBottomPadding />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,13 +9,17 @@ import PageLoading from '@/components/page-loading';
|
|||||||
import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
|
import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
|
||||||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
||||||
import { EventName, OpenSource, PageUrl, RoleType } from '@/constants/app';
|
import { EventName, OpenSource, PageUrl, RoleType } from '@/constants/app';
|
||||||
|
import { CertificationStatusType } from '@/constants/company';
|
||||||
import { CollectEventName } from '@/constants/event';
|
import { CollectEventName } from '@/constants/event';
|
||||||
import { JobManageStatus } from '@/constants/job';
|
import { JobManageStatus } from '@/constants/job';
|
||||||
import { MaterialViewSource } from '@/constants/material';
|
import { MaterialViewSource } from '@/constants/material';
|
||||||
import ProfileViewFragment from '@/fragments/profile/view';
|
import ProfileViewFragment from '@/fragments/profile/view';
|
||||||
import useInviteCode from '@/hooks/use-invite-code';
|
import useInviteCode from '@/hooks/use-invite-code';
|
||||||
|
import useUserInfo from '@/hooks/use-user-info';
|
||||||
import { RESPONSE_ERROR_CODE } from '@/http/constant';
|
import { RESPONSE_ERROR_CODE } from '@/http/constant';
|
||||||
import { HttpError } from '@/http/error';
|
import { HttpError } from '@/http/error';
|
||||||
|
import store from '@/store';
|
||||||
|
import { cacheJobId } from '@/store/actions';
|
||||||
import { JobManageInfo } from '@/types/job';
|
import { JobManageInfo } from '@/types/job';
|
||||||
import { MaterialProfile } from '@/types/material';
|
import { MaterialProfile } from '@/types/material';
|
||||||
import { IJobMessage } from '@/types/message';
|
import { IJobMessage } from '@/types/message';
|
||||||
@ -29,10 +33,6 @@ import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner';
|
|||||||
import { getPageQuery, navigateBack, navigateTo, redirectTo } from '@/utils/route';
|
import { getPageQuery, navigateBack, navigateTo, redirectTo } from '@/utils/route';
|
||||||
import Toast from '@/utils/toast';
|
import Toast from '@/utils/toast';
|
||||||
import './index.less';
|
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';
|
const PREFIX = 'page-material-view';
|
||||||
|
|
||||||
|
|||||||
@ -6,9 +6,7 @@ import { useState } from 'react';
|
|||||||
import PartnerIntro from '@/components/partner-intro';
|
import PartnerIntro from '@/components/partner-intro';
|
||||||
import PartnerInviteList from '@/components/partner-invite-list';
|
import PartnerInviteList from '@/components/partner-invite-list';
|
||||||
import PartnerProfit from '@/components/partner-profit';
|
import PartnerProfit from '@/components/partner-profit';
|
||||||
import { PageUrl } from '@/constants/app';
|
|
||||||
import useInviteCode from '@/hooks/use-invite-code';
|
import useInviteCode from '@/hooks/use-invite-code';
|
||||||
import { generateMembershipCoupon } from '@/utils/coupon';
|
|
||||||
import { getCommonShareMessage } from '@/utils/share';
|
import { getCommonShareMessage } from '@/utils/share';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
@ -20,17 +18,9 @@ export default function Partner() {
|
|||||||
const handleChange = v => {
|
const handleChange = v => {
|
||||||
setTab(v);
|
setTab(v);
|
||||||
};
|
};
|
||||||
useShareAppMessage(async () => {
|
useShareAppMessage(() => {
|
||||||
console.log('Partner inviteCode', inviteCode);
|
console.log('Partner inviteCode', inviteCode);
|
||||||
const { code } = await generateMembershipCoupon();
|
return getCommonShareMessage({ useCapture: false, inviteCode });
|
||||||
return getCommonShareMessage({
|
|
||||||
useCapture: false,
|
|
||||||
inviteCode,
|
|
||||||
title: '宝子,送你个播络会员,免费找主播工作',
|
|
||||||
path: PageUrl.GiveVip,
|
|
||||||
params: { d: code },
|
|
||||||
imageUrl: 'https://publiccdn.neighbourhood.com.cn/img/share-coupon1.png',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
export type ClaimMembershipCouponResponse = {
|
|
||||||
code: string;
|
|
||||||
usedBefore: boolean;
|
|
||||||
usageExpireAt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GenerateMembershipCouponResponse = {
|
|
||||||
code: string;
|
|
||||||
linkExpireAt: string;
|
|
||||||
shareUrl: string;
|
|
||||||
};
|
|
||||||
@ -101,6 +101,7 @@ export interface IAnchorFilters {
|
|||||||
lowPriceForPartyTime?: number;
|
lowPriceForPartyTime?: number;
|
||||||
highPriceForPartyTime?: number;
|
highPriceForPartyTime?: number;
|
||||||
category?: string;
|
category?: string;
|
||||||
|
topCategory?: string;
|
||||||
readType?: AnchorReadType;
|
readType?: AnchorReadType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
import http from '@/http';
|
|
||||||
import { API } from '@/http/api';
|
|
||||||
import { ClaimMembershipCouponResponse, GenerateMembershipCouponResponse } from '@/types/coupon';
|
|
||||||
|
|
||||||
export const generateMembershipCoupon = async () => {
|
|
||||||
return await http.post<GenerateMembershipCouponResponse>(API.GENERATE_MEMBERSHIP_COUPON);
|
|
||||||
};
|
|
||||||
export const claimMembershipCoupon = async (code: string) => {
|
|
||||||
return await http.post<ClaimMembershipCouponResponse>(API.CLAIM_MEMBERSHIP_COUPON, {
|
|
||||||
contentType: 'application/x-www-form-urlencoded',
|
|
||||||
data: { code },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export const getCouponQrCode = async (code: string) => {
|
|
||||||
return await http.post(API.GET_VIP_QRCODE, {
|
|
||||||
contentType: 'application/x-www-form-urlencoded',
|
|
||||||
responseType: 'arraybuffer',
|
|
||||||
data: { code },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export const getCouponCodeFromQuery = (query: Record<string, string>): string | undefined => {
|
|
||||||
if (query) {
|
|
||||||
if (query.scene) {
|
|
||||||
return query.scene.replace('d%3D', '');
|
|
||||||
}
|
|
||||||
if (query.d) {
|
|
||||||
return query.d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
@ -20,7 +20,6 @@ interface ShareAppProps {
|
|||||||
inviteCode?: string;
|
inviteCode?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
path?: PageUrl;
|
path?: PageUrl;
|
||||||
imageUrl?: string;
|
|
||||||
params?: Record<string, BL.Anything>;
|
params?: Record<string, BL.Anything>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +28,6 @@ export const getCommonShareMessage = ({
|
|||||||
inviteCode,
|
inviteCode,
|
||||||
title,
|
title,
|
||||||
path,
|
path,
|
||||||
imageUrl: _imageUrl,
|
|
||||||
params = {},
|
params = {},
|
||||||
}: ShareAppProps = {}): ShareAppMessageReturn => {
|
}: ShareAppProps = {}): ShareAppMessageReturn => {
|
||||||
const inviteParams = inviteCode ? { c: inviteCode } : undefined;
|
const inviteParams = inviteCode ? { c: inviteCode } : undefined;
|
||||||
@ -38,6 +36,6 @@ export const getCommonShareMessage = ({
|
|||||||
return {
|
return {
|
||||||
title: title || `昨天新增了${getRandomCount()}条主播通告,宝子快来看看`,
|
title: title || `昨天新增了${getRandomCount()}条主播通告,宝子快来看看`,
|
||||||
path: sharePath,
|
path: sharePath,
|
||||||
imageUrl: useCapture ? undefined : _imageUrl || imageUrl,
|
imageUrl: useCapture ? undefined : imageUrl,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
export function formatTime(time: number | string, template = 'YYYY-MM-DD', toNum = true): string {
|
export function formatTime(time: number | string, template = 'YYYY-MM-DD'): string {
|
||||||
if (!time) {
|
if (!time) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (toNum) {
|
time = Number(time);
|
||||||
time = Number(time);
|
|
||||||
}
|
|
||||||
return dayjs(time).format(template);
|
return dayjs(time).format(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user