diff --git a/src/components/partner-entry/index.less b/src/components/partner-entry/index.less index c9e4311..1f48207 100644 --- a/src/components/partner-entry/index.less +++ b/src/components/partner-entry/index.less @@ -46,16 +46,31 @@ } &__kanban { - min-height: 280px; - box-sizing: border-box; border-radius: 16px; margin-bottom: 24px; - padding: 36px 40px; position: relative; background: #6d3df5; color: #fff; + + &-bg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + &-content { + position: relative; + min-height: 280px; + box-sizing: border-box; + padding: 36px 40px; + z-index: 1; + } + &-button { position: absolute; + z-index: 2; top: 44px; right: 56px; font-size: 24px; diff --git a/src/components/partner-entry/index.tsx b/src/components/partner-entry/index.tsx index 6f0d6fe..8229586 100644 --- a/src/components/partner-entry/index.tsx +++ b/src/components/partner-entry/index.tsx @@ -1,49 +1,93 @@ -import { Button, Image } from '@tarojs/components'; +import { BaseEventOrig, Button, ButtonProps, Image } from '@tarojs/components'; -import { useState } from 'react'; +import { useCallback, useState } from 'react'; + +import { PageUrl } from '@/constants/app'; +import useUserInfo from '@/hooks/use-user-info'; +import { navigateTo } from '@/utils/route'; +import Toast from '@/utils/toast'; +import { requestUserInfo, setPhoneNumber } from '@/utils/user'; import './index.less'; const PREFIX = 'partner-fragment-entry'; -function JoinEntry() { +type JoinEntryProps = { + onBindSuccess: () => void; +}; +function JoinEntry({ onBindSuccess }: JoinEntryProps) { + const userInfo = useUserInfo(); + + const hasPhone = !!userInfo.phone; + + const handleGetPhoneNumber = useCallback(async (e: BaseEventOrig) => { + const encryptedData = e.detail.encryptedData; + const iv = e.detail.iv; + if (!encryptedData || !iv) { + return Toast.error('取消授权'); + } + + try { + await setPhoneNumber({ encryptedData, iv }); + await requestUserInfo(); + Toast.success('绑定成功'); + onBindSuccess(); + } catch (err) { + Toast.error('绑定失败'); + } + }, []); return (
加入播络合伙人,高达75%分成
模式简单,分成比例高,欢迎各位群主、经纪人或机构
- + {hasPhone && ( + + )} + {!hasPhone && ( + + )}
); } function PartnerKanban() { + const handleNavigate = useCallback(() => { + navigateTo(PageUrl.Partner); + }, []); return (
-
- 查看详情 - -
-
-
总收益(元)
-
1666.66
-
-
-
-
可提现(元)
-
666.23
+ +
+
+ 查看详情 +
-
-
提现中(元)
-
666.23
+
+
总收益(元)
+
1666.66
-
-
待分账(元)
-
666.23
+
+
+
可提现(元)
+
666.23
+
+
+
提现中(元)
+
666.23
+
+
+
待分账(元)
+
666.23
+
@@ -51,10 +95,14 @@ function PartnerKanban() { } export default function PartnerEntry() { - const [state] = useState(1); + const [state, setState] = useState(1); + // TODO: 开通状态检查 + const handleBindSuccess = useCallback(() => { + setState(0); + }, []); if (state === 0) { - return ; + return ; } return ; } diff --git a/src/components/partner-intro/index.less b/src/components/partner-intro/index.less new file mode 100644 index 0000000..da7034f --- /dev/null +++ b/src/components/partner-intro/index.less @@ -0,0 +1,123 @@ +@import '@/styles/variables.less'; +@import '@/styles/common.less'; + +.partner-intro { + padding-top: 112px; + padding-bottom: calc(112px + constant(safe-area-inset-bottom)); + padding-bottom: calc(112px + env(safe-area-inset-bottom)); + + &__banner { + background: fade(@blHighlightBg, 8); + height: 88px; + line-height: 88px; + text-align: center; + font-size: 28px; + position: absolute; + top: 0; + left: 0; + right: 0; + width: 100vw; + } + + &__main { + padding-left: 24px; + padding-right: 24px; + } + + &__highlight { + color: @blHighlightColor; + font-family: 'DIN Alternate'; + padding: 0 8px; + font-weight: 700; + display: inline-block; + font-size: 40px; + } + + &__block { + margin-bottom: 40px; + } + + + &__card { + background: #fff; + border-radius: 24px; + padding: 24px 32px; + } + + &__h1 { + font-weight: 500; + font-size: 32px; + line-height: 40px; + color: #1d2129; + margin-bottom: 16px; + margin-top: 32px; + + &:first-child { + margin-top: 0; + } + } + + &__body { + font-weight: 400; + font-size: 28px; + line-height: 40px; + } + + &__title { + margin-bottom: 24px; + font-weight: 500; + font-size: 32px; + line-height: 32px; + + color: #1d2129; + } + + &__special { + padding: 32px; + .flex-column(); + + .partner-intro__body { + text-align: center; + } + } + + &__service { + .button(@height: 72px; @width: 384px; @fontSize: 28px; @fontWeight: 400; @borderRadius: 44px; @highlight: 0); + margin-top: 32px; + } + + &__tip { + margin-top: 24px; + font-size: 24px; + line-height: 40px; + color: #999999; + } + + &__footer { + position: fixed; + bottom: 0; + width: 100vw; + background: #ffffff; + padding: 12px 32px; + padding-bottom: calc(constant(safe-area-inset-bottom) + 12px); + /* 兼容 iOS < 11.2 */ + padding-bottom: calc(env(safe-area-inset-bottom) + 12px); + /* 兼容 iOS >= 11.2 */ + box-shadow: 0px -4px 20px 0px #00000014; + + display: flex; + flex-direction: row; + box-sizing: border-box; + } + + &__download-button { + flex: 1 1; + .button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px; @highlight: 0); + } + + &__share-button { + flex: 2 2; + .button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px;); + margin-left: 32px; + } +} diff --git a/src/components/partner-intro/index.tsx b/src/components/partner-intro/index.tsx new file mode 100644 index 0000000..6ae4965 --- /dev/null +++ b/src/components/partner-intro/index.tsx @@ -0,0 +1,61 @@ +import { Button } from '@tarojs/components'; + +import { useCallback } from 'react'; + +import { openCustomerServiceChat } from '@/utils/common'; +import './index.less'; + +const PREFIX = 'partner-intro'; +export default function PartnerIntro() { + const handleOpenService = useCallback(() => { + openCustomerServiceChat('https://work.weixin.qq.com/kfid/kfc4fcf6b109b3771d7'); + }, []); + return ( +
+
+ 邀请朋友加入播络,高达75%分成 +
+
+
+
+
收益一
+
+ 直接获得被邀请人付款金额的20% +
+
收益二
+
+ 邀请的主播创建模卡,被企业开聊,每日可获得收益,分成比例高达 + 50% +
+
收益三
+
+ 邀请朋友加入合伙人,可额外获得所邀合伙人收益的5% +
+
+
+
+
群主特别通道
+
+
如果您是主播群群主,请务必添加播络小伙计
+
我们会为您提供专属服务,让您的收益最大化
+ +
+
注:收益不设时限,可重复享有,播络保留活动最终解释权
+
+
+
+ ); +} + +export function PartnerIntroFooter() { + return ( +
+ + +
+ ); +} diff --git a/src/constants/cache-key.ts b/src/constants/cache-key.ts index ed08768..b0af3c0 100644 --- a/src/constants/cache-key.ts +++ b/src/constants/cache-key.ts @@ -8,4 +8,5 @@ export enum CacheKey { APP_MODE = '__bl_app_mode__', APP_MODE_NEW = '__bl_app_mode_2__', LAST_SELECT_MY_JOB = '__last_select_my_job__', + CLOSE_PARTNER_BANNER = '__last_close_partner_banner__', } diff --git a/src/fragments/job/base/index.less b/src/fragments/job/base/index.less index 8ff784e..bf7b481 100644 --- a/src/fragments/job/base/index.less +++ b/src/fragments/job/base/index.less @@ -1,4 +1,5 @@ @import '@/styles/variables.less'; +@import '@/styles/common.less'; .all-job-fragment { &__container { @@ -76,7 +77,7 @@ flex-direction: row; align-items: center; justify-content: center; - border-left: solid 2px #E0E0E0; + border-left: solid 2px #e0e0e0; font-size: 28px; line-height: 32px; @@ -118,7 +119,7 @@ &__empty-box { width: 386px; height: 278px; - } + } &__tips-title { font-size: 28px; @@ -138,10 +139,29 @@ &__add-group-button { font-size: 28px; line-height: 40px; - color: #FFFFFF; + color: #ffffff; background-color: @blHighlightColor; border-radius: 48px; padding: 20px 30px; margin-top: 30px; } } + +.partner-banner { + width: 100%; + height: 90px; + position: relative; + + &__image { + width: 100%; + height: 100%; + } + + &__close { + width: 64px; + height: 38px; + position: absolute; + right: 0; + top: 0; + } +} diff --git a/src/fragments/job/base/index.tsx b/src/fragments/job/base/index.tsx index a9c12e3..9d7c532 100644 --- a/src/fragments/job/base/index.tsx +++ b/src/fragments/job/base/index.tsx @@ -4,7 +4,7 @@ import { NodesRef, useDidHide } from '@tarojs/taro'; import { Tabs } from '@taroify/core'; import { ArrowUp, ArrowDown } from '@taroify/icons'; import classNames from 'classnames'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useState, MouseEvent } from 'react'; import JobList, { IJobListProps } from '@/components/job-list'; import Overlay from '@/components/overlay'; @@ -18,6 +18,7 @@ import { SalaryRange } from '@/types/job'; import { Coordinate } from '@/types/location'; import { logWithPrefix } from '@/utils/common'; import { navigateTo } from '@/utils/route'; +import { getPartnerBannerClose, setPartnerBannerClose } from '@/utils/partner'; import './index.less'; @@ -42,6 +43,18 @@ const CALC_LIST_PROPS: IUseListHeightProps = { const log = logWithPrefix(PREFIX); +const PartnerBanner = (props: { onClose: (e: MouseEvent) => void }) => { + const handleClick = useCallback(() => { + navigateTo(PageUrl.Partner); + }, []); + return ( +
+ +
+
+ ); +}; + const NoGroupTips = (props: { className?: string; height?: number }) => { const { className, height } = props; return ( @@ -80,6 +93,7 @@ function JobFragment(props: IProps) { const [salaryRange, setSalaryRange] = useState(); const [showSalarySelect, setShowSalarySelect] = useState(false); const { latitude, longitude } = coordinate; + const [bannerClose, setBannerClose] = useState(getPartnerBannerClose()); const handleClickSearch = useCallback(() => navigateTo(PageUrl.JobSearch, { city: cityCode }), [cityCode]); @@ -103,6 +117,13 @@ function JobFragment(props: IProps) { [setTabType] ); + const handlePartnerBannerClose = useCallback(e => { + e.preventDefault(); + e.stopPropagation(); + setBannerClose(true); + setPartnerBannerClose(); + }, []); + useDidHide(() => setShowSalarySelect(false)); return ( @@ -132,6 +153,7 @@ function JobFragment(props: IProps) { {JOB_TABS.map(tab => ( + {!bannerClose && } { export default function Certification() { const { phone } = useUserInfo(); - const [revisedPhone, setRevisedPhone] = useState('') + const [revisedPhone, setRevisedPhone] = useState(''); const [leftIdCardUrl, setLeftIdCardUrl] = useState(''); const [rightIdCardUrl, setRightIdCardUrl] = useState(''); const [name, setName] = useState(''); @@ -171,9 +171,8 @@ export default function Certification() { const handleGetPhoneNumber = async (e: BaseEventOrig) => { if (e.detail.code) { try { - const { phoneNumber } = await getPhone(e.detail.code); - setRevisedPhone(phoneNumber) + setRevisedPhone(phoneNumber); } catch (e) { Toast.error('获取手机号失败'); } @@ -237,9 +236,17 @@ export default function Certification() { - +
- +
diff --git a/src/pages/partner/index.tsx b/src/pages/partner/index.tsx index 41c07df..64cb79e 100644 --- a/src/pages/partner/index.tsx +++ b/src/pages/partner/index.tsx @@ -1,15 +1,26 @@ -import { Tabs } from '@taroify/core'; +import { useShareAppMessage } from '@tarojs/taro'; +import { Tabs } from '@taroify/core'; +import { useState } from 'react'; + +import PartnerIntro, { PartnerIntroFooter } from '@/components/partner-intro'; +import { getCommonShareMessage } from '@/utils/share'; import './index.less'; const PREFIX = 'partner'; export default function Partner() { + const [tab, setTab] = useState(0); + + useShareAppMessage(() => { + return getCommonShareMessage(false); + }); + return (
- + - 简介 + 邀请名单 @@ -18,6 +29,7 @@ export default function Partner() { 我的收益 + {tab === 0 && }
); } diff --git a/src/pages/user/index.tsx b/src/pages/user/index.tsx index d2b3d99..d3a262b 100644 --- a/src/pages/user/index.tsx +++ b/src/pages/user/index.tsx @@ -69,7 +69,7 @@ export default function User() { />
- + {roleType === RoleType.Anchor && } {roleType === RoleType.Anchor && } {roleType === RoleType.Company && }
diff --git a/src/statics/png/partner_banner.png b/src/statics/png/partner_banner.png new file mode 100644 index 0000000..a16e598 Binary files /dev/null and b/src/statics/png/partner_banner.png differ diff --git a/src/statics/png/partner_bg.png b/src/statics/png/partner_bg.png new file mode 100644 index 0000000..314a9d7 Binary files /dev/null and b/src/statics/png/partner_bg.png differ diff --git a/src/utils/company.ts b/src/utils/company.ts index c4f46ab..7dccf01 100644 --- a/src/utils/company.ts +++ b/src/utils/company.ts @@ -9,7 +9,6 @@ export const postCertification = async (data: ICertificationRequest) => { return result; }; -export const getPhone = async (code: string): Promise<{ code: string }> => { - const result = await http.post<{ code: string }>(API.GET_PHONE, { data: { code } }); - return result; +export const getPhone = async (code: string) => { + return await http.post<{ phoneNumber: string }>(API.GET_PHONE, { data: { code } }); }; diff --git a/src/utils/job.ts b/src/utils/job.ts index cd89e15..c167a95 100644 --- a/src/utils/job.ts +++ b/src/utils/job.ts @@ -27,12 +27,12 @@ import { collectEvent } from '@/utils/event'; import { getCityValues } from '@/utils/location'; export const isFullTimePriceRequired = (employType?: JobDetails['employType']) => { - return employType === EmployType.Full || employType === EmployType.All -} + return employType === EmployType.Full || employType === EmployType.All; +}; export const isPartTimePriceRequired = (employType?: JobDetails['employType']) => { - return employType === EmployType.Part || employType === EmployType.All -} + return employType === EmployType.Part || employType === EmployType.All; +}; export const getJobSalary = (data: Partial) => { const { salary, employType, lowPriceForFullTime, highPriceForFullTime, lowPriceForPartyTime, highPriceForPartyTime } = diff --git a/src/utils/partner.ts b/src/utils/partner.ts new file mode 100644 index 0000000..5d4a257 --- /dev/null +++ b/src/utils/partner.ts @@ -0,0 +1,7 @@ +import Taro from '@tarojs/taro'; + +import { CacheKey } from '@/constants/cache-key'; + +export const getPartnerBannerClose = (): boolean => Taro.getStorageSync(CacheKey.CLOSE_PARTNER_BANNER); + +export const setPartnerBannerClose = () => Taro.setStorageSync(CacheKey.CLOSE_PARTNER_BANNER, true);