feat: first commit
This commit is contained in:
37
src/components/product-dialog/const.ts
Normal file
37
src/components/product-dialog/const.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export const PREFIX = 'product-dialog';
|
||||
|
||||
export enum DialogStatus {
|
||||
// 加载中
|
||||
LOADING = 'loading',
|
||||
// 直接联系通告主
|
||||
JOB_CONTACT_DIRECT = 'job_contact_direct',
|
||||
// 联系客服去联系通告主 -> 订阅通知
|
||||
JOB_CONTACT_CS = 'job_contact_customer_service',
|
||||
// 需要解锁
|
||||
JOB_NEED_UNLOCK = 'job_need_unlock',
|
||||
// 解锁次数已用完
|
||||
JOB_UNABLE_UNLOCK = 'job_unable_unlock',
|
||||
// 通告解锁次数用完,购买界面
|
||||
JOB_BUY = 'job_buy',
|
||||
// 加群二维码
|
||||
GROUP_QR_CODE = 'group_qr_code',
|
||||
// 确定加群
|
||||
GROUP_CONFIRM_ADD = 'group_confirm_add',
|
||||
// 加群次数用完
|
||||
GROUP_NEED_BUY_ADD = 'group_need_buy_add',
|
||||
// 购买群数,需要购买
|
||||
GROUP_BUY = 'group_buy',
|
||||
GROUP_BUY_SUCCESS = 'group_buy_success',
|
||||
// 去群内联系发布人
|
||||
// JOB_CONTACT_GO_GROUP = 'job_contact_go_group',
|
||||
// 群内联系发布人,解锁加群
|
||||
JOB_CONTACT_INVITE_GROUP = 'job_contact_invite_group',
|
||||
// 群内联系发布人,次数用完,需要购买
|
||||
JOB_CONTACT_NEED_BUY_GROUP = 'job_contact_need_buy_group',
|
||||
// 企业发布通告会员
|
||||
PUBLISH_JOB_BUY = 'publish_job_buy',
|
||||
// 企业购买单次发布通告
|
||||
COMPANY_PUBLISH_JOB_BUY = 'company_publish_job_buy',
|
||||
// 发布通告联系客服二维码
|
||||
PUBLISH_QR_CODE = 'publish_qr_code',
|
||||
}
|
127
src/components/product-dialog/group/index.tsx
Normal file
127
src/components/product-dialog/group/index.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Dialog } from '@taroify/core';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
|
||||
import QrCodeContent from '@/components/product-dialog/steps-ui/common-qr-code';
|
||||
import GroupBuy from '@/components/product-dialog/steps-ui/group-buy';
|
||||
import GroupBuySuccess from '@/components/product-dialog/steps-ui/group-buy-success';
|
||||
import ConfirmContent from '@/components/product-dialog/steps-ui/group-confirm';
|
||||
import GroupNeedBuyContent from '@/components/product-dialog/steps-ui/group-need-buy';
|
||||
import { ProductType, QrCodeType } from '@/constants/product';
|
||||
import { GroupDetail } from '@/types/group';
|
||||
import { copy } from '@/utils/common';
|
||||
import { getInviteGroupText, requestGroupDetail } from '@/utils/group';
|
||||
import { requestProductBalance, requestProductUseRecord, requestUseProduct } from '@/utils/product';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
import '../index.less';
|
||||
|
||||
interface IProps {
|
||||
blGroupId: string;
|
||||
style?: React.CSSProperties;
|
||||
onClose: (opened: boolean) => void;
|
||||
}
|
||||
|
||||
const PRODUCT_CODE = ProductType.AddGroup;
|
||||
|
||||
function ProductGroupDialog(props: IProps) {
|
||||
const { style, blGroupId, onClose } = props;
|
||||
const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
|
||||
const [unlockTime, setUnlockTime] = useState(0);
|
||||
const [groupDetail, setGroupDetail] = useState<GroupDetail | null>(null);
|
||||
const initRef = useRef(() => {});
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
onClose(false);
|
||||
}, [onClose]);
|
||||
|
||||
const handleClickUnable = useCallback(async () => setStatus(DialogStatus.GROUP_BUY), []);
|
||||
|
||||
const handleClickConfirm = useCallback(async () => {
|
||||
if (!groupDetail) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const text = getInviteGroupText(groupDetail);
|
||||
await Promise.all([
|
||||
await copy(text),
|
||||
await requestUseProduct(PRODUCT_CODE, { blGroupId: groupDetail.blGroupId }),
|
||||
]);
|
||||
setStatus(DialogStatus.GROUP_QR_CODE);
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
}
|
||||
}, [groupDetail]);
|
||||
|
||||
const handleClickBuy = useCallback(async (time: number) => {
|
||||
setUnlockTime(time);
|
||||
setStatus(DialogStatus.GROUP_BUY_SUCCESS);
|
||||
}, []);
|
||||
|
||||
const handleClickBuySuccess = useCallback(async () => {
|
||||
setStatus(DialogStatus.GROUP_CONFIRM_ADD);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current = async () => {
|
||||
// if (1 < 2) {
|
||||
// setStatus(DialogStatus.GROUP_BUY);
|
||||
// return;
|
||||
// }
|
||||
try {
|
||||
Taro.showLoading();
|
||||
// 当前群之前解锁过,直接显示二维码页面
|
||||
const result = await requestProductUseRecord(PRODUCT_CODE, { blGroupId });
|
||||
if (result) {
|
||||
const detail = await requestGroupDetail(blGroupId);
|
||||
const text = getInviteGroupText(detail);
|
||||
await copy(text);
|
||||
setStatus(DialogStatus.GROUP_QR_CODE);
|
||||
return;
|
||||
}
|
||||
// 否则:如果有解锁次数,显示是否确定消费。无解锁次数,显示不无次数 UI
|
||||
const [time, detail] = await Promise.all([requestProductBalance(PRODUCT_CODE), requestGroupDetail(blGroupId)]);
|
||||
setGroupDetail(detail);
|
||||
if (time <= 0) {
|
||||
setStatus(DialogStatus.GROUP_NEED_BUY_ADD);
|
||||
} else {
|
||||
setUnlockTime(time);
|
||||
setStatus(DialogStatus.GROUP_CONFIRM_ADD);
|
||||
}
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
handleCloseDialog();
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
}, [blGroupId, handleCloseDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current();
|
||||
}, []);
|
||||
|
||||
if (status === DialogStatus.LOADING) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} style={style} open>
|
||||
<Dialog.Content>
|
||||
{status === DialogStatus.GROUP_NEED_BUY_ADD && <GroupNeedBuyContent onConfirm={handleClickUnable} />}
|
||||
{status === DialogStatus.GROUP_CONFIRM_ADD && (
|
||||
<ConfirmContent unlockTime={unlockTime} onConfirm={handleClickConfirm} />
|
||||
)}
|
||||
{status === DialogStatus.GROUP_QR_CODE && <QrCodeContent type={QrCodeType.Group} />}
|
||||
{status === DialogStatus.GROUP_BUY && <GroupBuy source="group-list" onConfirm={handleClickBuy} />}
|
||||
{status === DialogStatus.GROUP_BUY_SUCCESS && (
|
||||
<GroupBuySuccess unlockTime={unlockTime} onConfirm={handleClickBuySuccess} />
|
||||
)}
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductGroupDialog;
|
663
src/components/product-dialog/index.less
Normal file
663
src/components/product-dialog/index.less
Normal file
@ -0,0 +1,663 @@
|
||||
@import '@/styles/common.less';
|
||||
@import '@/styles/variables.less';
|
||||
|
||||
.product-dialog {
|
||||
|
||||
.layout() {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-font {
|
||||
font-size: 36px;
|
||||
line-height: 58px;
|
||||
color: @blColor;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.describe-font {
|
||||
font-size: 28px;
|
||||
line-height: 48px;
|
||||
color: @blColorG2;
|
||||
}
|
||||
|
||||
.button() {
|
||||
width: 360px;
|
||||
height: 72px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
line-height: 72px;
|
||||
border-radius: 44px;
|
||||
color: #FFFFFF;
|
||||
background: @blHighlightColor;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.highlight-container() {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 24px;
|
||||
line-height: 48px;
|
||||
color: @blHighlightColor;
|
||||
background: #6D3DF514;
|
||||
border-radius: 8px;
|
||||
padding: 32px 72px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
// common
|
||||
&__qr-code,
|
||||
&__group-confirm,
|
||||
&__group-need-buy,
|
||||
&__job-contact-with-group,
|
||||
&__group-buy,
|
||||
&__group-buy_success,
|
||||
&__publish-job-buy,
|
||||
&__company-publish-job-buy {
|
||||
.layout();
|
||||
}
|
||||
|
||||
// ============================================= 通告 ================================================= //
|
||||
// 通告已经解锁,直接联系
|
||||
&__job-contact_direct,
|
||||
// 通告已经解锁,等待播络联系
|
||||
&__job-contact_cs {
|
||||
.layout();
|
||||
|
||||
&__header {
|
||||
.header-font();
|
||||
}
|
||||
|
||||
&__describe {
|
||||
.describe-font();
|
||||
margin-top: 24px
|
||||
}
|
||||
|
||||
&__content {
|
||||
.highlight-container();
|
||||
}
|
||||
|
||||
&__button {
|
||||
.button();
|
||||
}
|
||||
|
||||
&__report {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
line-height: 40px;
|
||||
color: @blHighlightColor;
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
// 通告不可解锁
|
||||
&__job-unable {
|
||||
.layout();
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.header-font();
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&__describe {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 28px;
|
||||
line-height: 48px;
|
||||
color: @blColor;
|
||||
margin-top: 32px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
.button();
|
||||
}
|
||||
}
|
||||
|
||||
// 通告购买
|
||||
&__job-buy {
|
||||
.layout();
|
||||
|
||||
&__header {
|
||||
.flex-row();
|
||||
.header-font();
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&__describe {
|
||||
.flex-row();
|
||||
.describe-font();
|
||||
margin-top: 24px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__container {
|
||||
.flex-row();
|
||||
justify-content: space-around;
|
||||
margin-top: 56px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
position: relative;
|
||||
width: 170px;
|
||||
height: 192px;
|
||||
.flex-column();
|
||||
justify-content: center;
|
||||
border: 2px solid @blHighlightColor;
|
||||
border-radius: 8px;
|
||||
margin-right: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border-color: #E0E0E0;
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: @blHighlightBg;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&.free {
|
||||
font-size: 24px;
|
||||
line-height: 36px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
&__price {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 500;
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
|
||||
&__badge {
|
||||
transform: translate3d(10px, -50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
.button();
|
||||
}
|
||||
|
||||
&__tips {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
color: @blColorG2;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ============================================= 群 ================================================= //
|
||||
|
||||
// 群 common
|
||||
&__qr-code__tips,
|
||||
&__group-confirm__tips,
|
||||
&__group-need-buy__top-tips,
|
||||
&__group-buy__tips,
|
||||
&__group-buy_success__tips {
|
||||
font-size: 24px;
|
||||
line-height: 34px;
|
||||
font-weight: 400;
|
||||
color: @blColorG1;
|
||||
|
||||
&.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
// 群解锁
|
||||
&__group-confirm__header {
|
||||
.header-font();
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 24px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__group-confirm__button {
|
||||
.button();
|
||||
}
|
||||
|
||||
// 群扫描二维码
|
||||
&__qr-code__header {
|
||||
.header-font();
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__qr-code__copy-button {
|
||||
.button();
|
||||
}
|
||||
|
||||
&__qr-code__copy-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&__qr-code__copy-success {
|
||||
font-size: 32px;
|
||||
line-height: 40px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
}
|
||||
|
||||
&__qr-code__steps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__qr-code__step {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&__qr-code__step-number {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #E0E0E0;
|
||||
}
|
||||
|
||||
&__qr-code__step-title {
|
||||
margin-left: 20px;
|
||||
|
||||
&.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__qr-code__step-line {
|
||||
position: relative;
|
||||
width: 2px;
|
||||
height: 40px;
|
||||
background: #E0E0E0;
|
||||
margin: 4px 0;
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
&__qr-code__image {
|
||||
width: 304px;
|
||||
height: 304px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__qr-code__tips {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__qr-code__footer {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
color: @blHighlightColor;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
&__qr-code__tips-footer {
|
||||
.divider {
|
||||
width: 540px;
|
||||
height: 1px;
|
||||
background: #E0E0E0;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
color: @blColorG1;
|
||||
}
|
||||
}
|
||||
|
||||
// 群解锁次数已用完
|
||||
&__group-need-buy__header {
|
||||
.header-font();
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 16px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__group-need-buy__button-container {
|
||||
position: relative;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__group-need-buy__button {
|
||||
.button();
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
// ============================================= 通告+群 ================================================= //
|
||||
// 去群内联系发布人
|
||||
&__job-contact-with-group__header {
|
||||
.header-font();
|
||||
}
|
||||
|
||||
&__job-contact-with-group__describe {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 36px;
|
||||
line-height: 56px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
margin-top: 40px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor
|
||||
}
|
||||
}
|
||||
|
||||
&__job-contact-with-group__content {
|
||||
.highlight-container();
|
||||
}
|
||||
|
||||
&__job-contact-with-group__button-container {
|
||||
width: fit-content;
|
||||
position: relative;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__job-contact-with-group__button {
|
||||
.button();
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
// ============================================= 购买群 ================================================= //
|
||||
&__group-buy__header {
|
||||
.header-font();
|
||||
}
|
||||
|
||||
&__group-buy__container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&__group-buy__item {
|
||||
position: relative;
|
||||
width: 170px;
|
||||
height: 156px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2px solid @blHighlightColor;
|
||||
border-radius: 8px;
|
||||
margin-right: 24px;
|
||||
|
||||
&.selected {
|
||||
background: @blHighlightBg;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__group-buy__item-title {
|
||||
font-size: 40px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
}
|
||||
|
||||
&__group-buy__item-price {
|
||||
font-size: 28px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
color: @blHighlightColor;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
&__group-buy__button {
|
||||
.button();
|
||||
}
|
||||
|
||||
&__group-buy__tips {
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
// ============================================= 购买成功 ================================================= //
|
||||
&__group-buy_success__tips-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&__group-buy_success__icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
&__group-buy_success__tips {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&__group-buy_success__header {
|
||||
.header-font();
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 24px;
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__group-buy_success__button {
|
||||
.button();
|
||||
}
|
||||
|
||||
|
||||
// ============================================= 发布通告的企业会员 ================================================= //
|
||||
&__publish-job-buy__header {
|
||||
.header-font();
|
||||
}
|
||||
|
||||
&__publish-job-buy__price-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 500;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
&__publish-job-buy__price {
|
||||
font-size: 80px;
|
||||
line-height: 80px;
|
||||
}
|
||||
|
||||
&__publish-job-buy__badge {
|
||||
transform: translate3d(50%, -90%, 0);
|
||||
}
|
||||
|
||||
&__publish-job-buy__tips {
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
color: @blColorG1;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
&__publish-job-buy__button {
|
||||
.button();
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
// ============================================= 企业购买单次发布通告 ================================================= //
|
||||
&__company-publish-job-buy {
|
||||
&__header {
|
||||
.header-font();
|
||||
}
|
||||
|
||||
&__price-container {
|
||||
.flex-row();
|
||||
justify-content: space-between;
|
||||
margin-top: 54px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
position: relative;
|
||||
width: 230px;
|
||||
height: 156px;
|
||||
.flex-column();
|
||||
justify-content: center;
|
||||
border: 2px solid @blHighlightColor;
|
||||
border-radius: 8px;
|
||||
margin-right: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border-color: #E0E0E0;
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: @blHighlightBg;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
color: @blColor;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&.free {
|
||||
font-size: 24px;
|
||||
line-height: 36px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&__price {
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
font-weight: 500;
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
|
||||
&__badge {
|
||||
transform: translate3d(10px, -50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
&__divider {
|
||||
.flex-row();
|
||||
justify-content: center;
|
||||
margin-top: 24px;
|
||||
|
||||
&__left-line,
|
||||
&__right-line {
|
||||
width: 206px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&__left-line {
|
||||
background: linear-gradient(270deg, #E0E0E0 0%, #FFFFFF 100%);
|
||||
}
|
||||
|
||||
&__right-line {
|
||||
background: linear-gradient(90deg, #E0E0E0 0%, #FFFFFF 100%);
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
color: @blColorG1;
|
||||
}
|
||||
}
|
||||
|
||||
&__contents {
|
||||
.flex-column();
|
||||
align-items: flex-start;
|
||||
align-self: flex-start;
|
||||
margin-top: 12px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
&__content {
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
color: @blColorG1;
|
||||
|
||||
&.highlight {
|
||||
color: @blHighlightColor;
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
.button();
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
178
src/components/product-dialog/job-with-group/index.tsx
Normal file
178
src/components/product-dialog/job-with-group/index.tsx
Normal file
@ -0,0 +1,178 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Dialog } from '@taroify/core';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
|
||||
import QrCodeContent from '@/components/product-dialog/steps-ui/common-qr-code';
|
||||
import GroupBuy from '@/components/product-dialog/steps-ui/group-buy';
|
||||
import GroupBuySuccess from '@/components/product-dialog/steps-ui/group-buy-success';
|
||||
import ContactWithGroup from '@/components/product-dialog/steps-ui/job-contact-with-group';
|
||||
import UnableUnlockContent from '@/components/product-dialog/steps-ui/job-unable';
|
||||
import { ProductType, QrCodeType } from '@/constants/product';
|
||||
import { GroupDetail } from '@/types/group';
|
||||
import { JobDetails } from '@/types/job';
|
||||
import { copy, logWithPrefix } from '@/utils/common';
|
||||
import { getConnectCustomerServiceText, requestGroupDetail } from '@/utils/group';
|
||||
import { requestProductUseRecord, requestProductBalance, requestUseProduct } from '@/utils/product';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
import '../index.less';
|
||||
|
||||
interface IProps {
|
||||
jobDetail: JobDetails;
|
||||
onClose: (opened: boolean) => void;
|
||||
}
|
||||
|
||||
const log = logWithPrefix('product-job-with-group');
|
||||
|
||||
function ProductJobWithGroupDialog(props: Omit<IProps, 'visible'>) {
|
||||
const { jobDetail, onClose } = props;
|
||||
const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
|
||||
const [addGroupTime, setAddGroupTime] = useState(0);
|
||||
const [groupDetail, setGroupDetail] = useState<GroupDetail | null>(null);
|
||||
const initRef = useRef(() => {});
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
onClose(false);
|
||||
}, [onClose]);
|
||||
|
||||
const handleCopyText = useCallback(async () => {
|
||||
if (!groupDetail) {
|
||||
return;
|
||||
}
|
||||
const text = getConnectCustomerServiceText(jobDetail, groupDetail);
|
||||
await copy(text);
|
||||
}, [jobDetail, groupDetail]);
|
||||
|
||||
const handleWithGroupConfirm = useCallback(
|
||||
async (dialogStatus: DialogStatus) => {
|
||||
if (!groupDetail) {
|
||||
return;
|
||||
}
|
||||
switch (dialogStatus) {
|
||||
case DialogStatus.JOB_CONTACT_INVITE_GROUP: {
|
||||
try {
|
||||
const text = getConnectCustomerServiceText(jobDetail, groupDetail);
|
||||
await Promise.all([
|
||||
copy(text),
|
||||
requestUseProduct(ProductType.AddGroup, { blGroupId: groupDetail.blGroupId }),
|
||||
]);
|
||||
setStatus(DialogStatus.GROUP_QR_CODE);
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogStatus.JOB_CONTACT_NEED_BUY_GROUP: {
|
||||
setStatus(DialogStatus.GROUP_BUY);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
[jobDetail, groupDetail]
|
||||
);
|
||||
|
||||
const handleClickBuy = useCallback(async (time: number) => {
|
||||
setAddGroupTime(time);
|
||||
setStatus(DialogStatus.GROUP_BUY_SUCCESS);
|
||||
}, []);
|
||||
|
||||
const handleClickBuySuccess = useCallback(async () => {
|
||||
setStatus(DialogStatus.JOB_CONTACT_INVITE_GROUP);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current = async () => {
|
||||
const handleGroup = async () => {
|
||||
const detail = await requestGroupDetail(jobDetail.blGroupId);
|
||||
setGroupDetail(detail);
|
||||
// if (1 < 2) {
|
||||
// setStatus(DialogStatus.JOB_CONTACT_INVITE_GROUP);
|
||||
// return;
|
||||
// }
|
||||
// 当前群之前解锁过,直接显示二维码页面
|
||||
const result = await requestProductUseRecord(ProductType.AddGroup, { blGroupId: jobDetail.blGroupId });
|
||||
if (result) {
|
||||
const text = getConnectCustomerServiceText(jobDetail, detail);
|
||||
await copy(text);
|
||||
setStatus(DialogStatus.GROUP_QR_CODE);
|
||||
return;
|
||||
}
|
||||
// 否则:如果有解锁次数,显示是否确定消费。无解锁次数,显示不无次数 UI
|
||||
const time = await requestProductBalance(ProductType.AddGroup);
|
||||
if (time <= 0) {
|
||||
setStatus(DialogStatus.JOB_CONTACT_NEED_BUY_GROUP);
|
||||
} else {
|
||||
setAddGroupTime(time);
|
||||
setStatus(DialogStatus.JOB_CONTACT_INVITE_GROUP);
|
||||
}
|
||||
};
|
||||
const handleJob = async () => {
|
||||
// 通告是否已经报单过
|
||||
const result = await requestProductUseRecord(ProductType.GetJob, { jobId: jobDetail.id });
|
||||
if (result) {
|
||||
// 报单过走加群流程
|
||||
await handleGroup();
|
||||
return;
|
||||
}
|
||||
// 自动报单
|
||||
const time = await requestProductBalance(ProductType.GetJob);
|
||||
if (time <= 0) {
|
||||
setStatus(DialogStatus.JOB_UNABLE_UNLOCK);
|
||||
} else {
|
||||
await requestUseProduct(ProductType.GetJob, { jobId: jobDetail.id });
|
||||
// 报单后走加群流程
|
||||
await handleGroup();
|
||||
}
|
||||
};
|
||||
try {
|
||||
Taro.showLoading();
|
||||
await handleJob();
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
handleCloseDialog();
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
}, [jobDetail, handleCloseDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current();
|
||||
}, []);
|
||||
|
||||
log('render status', status);
|
||||
|
||||
if (status === DialogStatus.LOADING) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} open>
|
||||
<Dialog.Content>
|
||||
{status === DialogStatus.JOB_UNABLE_UNLOCK && <UnableUnlockContent onConfirm={handleCloseDialog} />}
|
||||
{status === DialogStatus.GROUP_QR_CODE && (
|
||||
<QrCodeContent type={QrCodeType.ConnectCustomerService} onClickCopy={handleCopyText} />
|
||||
)}
|
||||
{[DialogStatus.JOB_CONTACT_INVITE_GROUP, DialogStatus.JOB_CONTACT_NEED_BUY_GROUP].includes(status) && (
|
||||
<ContactWithGroup
|
||||
status={status}
|
||||
publisherAcctNo={jobDetail.publisher}
|
||||
inviteTime={addGroupTime}
|
||||
imGroupNick={groupDetail?.imGroupNick || ''}
|
||||
onConfirm={handleWithGroupConfirm}
|
||||
/>
|
||||
)}
|
||||
{status === DialogStatus.GROUP_BUY && <GroupBuy source="job-detail" onConfirm={handleClickBuy} />}
|
||||
{status === DialogStatus.GROUP_BUY_SUCCESS && (
|
||||
<GroupBuySuccess unlockTime={addGroupTime} onConfirm={handleClickBuySuccess} />
|
||||
)}
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductJobWithGroupDialog;
|
125
src/components/product-dialog/job/index.tsx
Normal file
125
src/components/product-dialog/job/index.tsx
Normal file
@ -0,0 +1,125 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Dialog } from '@taroify/core';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
|
||||
import JobBuy from '@/components/product-dialog/steps-ui/job-buy';
|
||||
import ContactCustomerService from '@/components/product-dialog/steps-ui/job-contact-customer';
|
||||
import ContactDirect from '@/components/product-dialog/steps-ui/job-contact-direct';
|
||||
import UnableUnlockContent from '@/components/product-dialog/steps-ui/job-unable';
|
||||
import { DeclarationType, ProductType } from '@/constants/product';
|
||||
import { JobDetails } from '@/types/job';
|
||||
import { ProductInfo } from '@/types/product';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
import {
|
||||
requestProductUseRecord,
|
||||
requestProductBalance,
|
||||
requestUseProduct,
|
||||
requestAllBuyProduct,
|
||||
} from '@/utils/product';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
import '../index.less';
|
||||
|
||||
interface IProps {
|
||||
data: JobDetails;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const PRODUCT_CODE = ProductType.VIP;
|
||||
const log = logWithPrefix('product-job-dialog');
|
||||
|
||||
function ProductJobDialog(props: Omit<IProps, 'visible'>) {
|
||||
const { data, onClose } = props;
|
||||
const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
|
||||
const [publisherAcctNo, setPublisherAcctNo] = useState<string>('');
|
||||
const initRef = useRef(() => {});
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
const handleAfterBuy = useCallback(async () => {
|
||||
const time = await requestProductBalance(PRODUCT_CODE);
|
||||
if (time <= 0) {
|
||||
Toast.error('发生错误请重试');
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
const productInfo = await requestUseProduct(PRODUCT_CODE, { jobId: data.id });
|
||||
const declarationTypeResult = productInfo.declarationTypeResult;
|
||||
if (declarationTypeResult?.type === DeclarationType.Direct && declarationTypeResult.publisherAcctNo) {
|
||||
setStatus(DialogStatus.JOB_CONTACT_DIRECT);
|
||||
setPublisherAcctNo(declarationTypeResult.publisherAcctNo);
|
||||
} else {
|
||||
setStatus(DialogStatus.JOB_CONTACT_CS);
|
||||
}
|
||||
}, [data, onClose]);
|
||||
|
||||
const handleReport = useCallback(() => {
|
||||
log('report', data.id);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current = async () => {
|
||||
const handleContact = (declarationTypeResult?: ProductInfo['declarationTypeResult']) => {
|
||||
if (declarationTypeResult?.type === DeclarationType.Direct && declarationTypeResult.publisherAcctNo) {
|
||||
setStatus(DialogStatus.JOB_CONTACT_DIRECT);
|
||||
setPublisherAcctNo(declarationTypeResult.publisherAcctNo);
|
||||
} else {
|
||||
setStatus(DialogStatus.JOB_CONTACT_CS);
|
||||
}
|
||||
};
|
||||
try {
|
||||
Taro.showLoading();
|
||||
// if (1 < 2) {
|
||||
// setStatus(DialogStatus.JOB_CONTACT_CS);
|
||||
// return;
|
||||
// }
|
||||
const result = await requestProductUseRecord(PRODUCT_CODE, { jobId: data.id });
|
||||
log('requestProductUseRecord result', result);
|
||||
if (result) {
|
||||
handleContact(result.declarationTypeResult);
|
||||
return;
|
||||
}
|
||||
const time = await requestProductBalance(PRODUCT_CODE);
|
||||
if (time <= 0) {
|
||||
const allowBuy = await requestAllBuyProduct(PRODUCT_CODE);
|
||||
setStatus(allowBuy ? DialogStatus.JOB_BUY : DialogStatus.JOB_UNABLE_UNLOCK);
|
||||
} else {
|
||||
const productInfo = await requestUseProduct(PRODUCT_CODE, { jobId: data.id });
|
||||
handleContact(productInfo.declarationTypeResult);
|
||||
}
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
handleCloseDialog();
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
}, [data, handleCloseDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current();
|
||||
}, []);
|
||||
|
||||
if (status === DialogStatus.LOADING) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} open>
|
||||
<Dialog.Content>
|
||||
{status === DialogStatus.JOB_CONTACT_CS && <ContactCustomerService onAfterConfirm={handleCloseDialog} />}
|
||||
{status === DialogStatus.JOB_CONTACT_DIRECT && (
|
||||
<ContactDirect publisherAcctNo={publisherAcctNo} onAfterConfirm={handleCloseDialog} onReport={handleReport} />
|
||||
)}
|
||||
{status === DialogStatus.JOB_BUY && <JobBuy onConfirm={handleAfterBuy} />}
|
||||
{status === DialogStatus.JOB_UNABLE_UNLOCK && <UnableUnlockContent onConfirm={handleCloseDialog} />}
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProductJobDialog;
|
149
src/components/product-dialog/publish-job/index.tsx
Normal file
149
src/components/product-dialog/publish-job/index.tsx
Normal file
@ -0,0 +1,149 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Dialog } from '@taroify/core';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
|
||||
import QrCodeContent from '@/components/product-dialog/steps-ui/common-qr-code';
|
||||
import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
|
||||
import PublishJobBuy from '@/components/product-dialog/steps-ui/publish-job-buy';
|
||||
import { PageUrl } from '@/constants/app';
|
||||
import { ProductType, QrCodeType } from '@/constants/product';
|
||||
import { UserInfo } from '@/types/user';
|
||||
import { requestProductBalance } from '@/utils/product';
|
||||
import { navigateTo } from '@/utils/route';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
import '../index.less';
|
||||
|
||||
interface IProps {
|
||||
userInfo: UserInfo;
|
||||
onClose: (opened: boolean) => void;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
export default function PublishJobDialog(props: IProps) {
|
||||
const { userInfo, onClose } = props;
|
||||
const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
|
||||
const initRef = useRef(() => {});
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
onClose(false);
|
||||
}, [onClose]);
|
||||
|
||||
const handleNext = useCallback(async () => {
|
||||
setStatus(DialogStatus.PUBLISH_QR_CODE);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current = async () => {
|
||||
// if (1 < 2) {
|
||||
// setStatus(DialogStatus.PUBLISH_QR_CODE);
|
||||
// return;
|
||||
// }
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const isVip = userInfo.isBoss && !userInfo.userBoss?.isExpire;
|
||||
if (isVip) {
|
||||
setStatus(DialogStatus.PUBLISH_QR_CODE);
|
||||
} else {
|
||||
setStatus(DialogStatus.PUBLISH_JOB_BUY);
|
||||
}
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
handleCloseDialog();
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
}, [userInfo, handleCloseDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current();
|
||||
}, []);
|
||||
|
||||
if (status === DialogStatus.LOADING) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} open>
|
||||
<Dialog.Content>
|
||||
{status === DialogStatus.PUBLISH_JOB_BUY && <PublishJobBuy onNext={handleNext} />}
|
||||
{status === DialogStatus.PUBLISH_QR_CODE && <QrCodeContent type={QrCodeType.PublishJob} />}
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function PublishJobQrCodeDialog(props: Omit<IProps, 'userInfo'>) {
|
||||
const { onClose, open = true } = props;
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} open={open}>
|
||||
<Dialog.Content>
|
||||
<QrCodeContent type={QrCodeType.PublishJob} />
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function CompanyPublishJobDialog(props: IProps) {
|
||||
const { userInfo, onClose } = props;
|
||||
const [status, setStatus] = useState<DialogStatus>(DialogStatus.LOADING);
|
||||
const initRef = useRef(() => {});
|
||||
|
||||
const handleCloseDialog = useCallback(() => {
|
||||
onClose(false);
|
||||
}, [onClose]);
|
||||
|
||||
const handleNext = useCallback(async () => {
|
||||
onClose(true);
|
||||
if (userInfo.bossAuthStatus) {
|
||||
navigateTo(PageUrl.JobPublish);
|
||||
} else {
|
||||
navigateTo(PageUrl.CertificationStart);
|
||||
}
|
||||
}, [userInfo, onClose]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current = async () => {
|
||||
// if (1 < 2) {
|
||||
// setStatus(DialogStatus.COMPANY_PUBLISH_JOB_BUY);
|
||||
// return;
|
||||
// }
|
||||
try {
|
||||
const productCode = ProductType.CompanyPublishJob;
|
||||
Taro.showLoading();
|
||||
const time = await requestProductBalance(productCode);
|
||||
if (time <= 0) {
|
||||
setStatus(DialogStatus.COMPANY_PUBLISH_JOB_BUY);
|
||||
return;
|
||||
}
|
||||
// 之前购买的次数还没用完
|
||||
handleNext();
|
||||
} catch (e) {
|
||||
Toast.error('出错了,请重试');
|
||||
handleCloseDialog();
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
}, [userInfo, handleCloseDialog, handleNext]);
|
||||
|
||||
useEffect(() => {
|
||||
initRef.current();
|
||||
}, []);
|
||||
|
||||
if (status === DialogStatus.LOADING) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog className={PREFIX} onClose={onClose} open>
|
||||
<Dialog.Content>
|
||||
{status === DialogStatus.COMPANY_PUBLISH_JOB_BUY && <CompanyPublishJobBuy onNext={handleNext} />}
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
71
src/components/product-dialog/steps-ui/common-qr-code.tsx
Normal file
71
src/components/product-dialog/steps-ui/common-qr-code.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import { Button, Image } from '@tarojs/components';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import QrCode from '@/components/qr-code';
|
||||
import { QrCodeType } from '@/constants/product';
|
||||
|
||||
interface IProps {
|
||||
type: QrCodeType;
|
||||
onClickCopy?: () => void;
|
||||
}
|
||||
|
||||
export default function QrCodeContent(props: IProps) {
|
||||
const { type, onClickCopy } = props;
|
||||
|
||||
let header: ReactElement | string | null = null;
|
||||
let describe: ReactElement | string | null = null;
|
||||
let footer: ReactElement | string | null = null;
|
||||
|
||||
if (type === QrCodeType.ConnectCustomerService) {
|
||||
header = <div className="highlight">复制对接信息,发送给小二</div>;
|
||||
describe = (
|
||||
<Button className={`${PREFIX}__qr-code__copy-button`} onClick={onClickCopy}>
|
||||
复制对接信息
|
||||
</Button>
|
||||
);
|
||||
footer = '在微信聊天框长按即可粘贴已复制内容';
|
||||
} else if (type === QrCodeType.PublishJob) {
|
||||
header = (
|
||||
<>
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
className={`${PREFIX}__qr-code__copy-icon`}
|
||||
src={require('@/statics/svg/success-circle-fill.svg')}
|
||||
/>
|
||||
<div className={`${PREFIX}__qr-code__copy-success`}>您已支付</div>
|
||||
</>
|
||||
);
|
||||
describe = (
|
||||
<div className={`${PREFIX}__qr-code__steps`}>
|
||||
<div className={`${PREFIX}__qr-code__step`}>
|
||||
<div className={`${PREFIX}__qr-code__step-number`}>1</div>
|
||||
<div className={`${PREFIX}__qr-code__step-title`}>扫码二维码联系专属客服</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__qr-code__step-line`} />
|
||||
<div className={`${PREFIX}__qr-code__step`}>
|
||||
<div className={`${PREFIX}__qr-code__step-number`}>2</div>
|
||||
<div className={classNames(`${PREFIX}__qr-code__step-title`, 'highlight')}>发送付款截图</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
footer = (
|
||||
<div className={`${PREFIX}__qr-code__tips-footer`}>
|
||||
<div className="divider" />
|
||||
<div className="tips">{`客服工作时间:工作日9:30-18:00\n上班后会第一时间为您处理`}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__qr-code`}>
|
||||
<div className={`${PREFIX}__qr-code__header`}>{header}</div>
|
||||
{describe}
|
||||
<QrCode className={`${PREFIX}__qr-code__image`} type={type} />
|
||||
<div className={`${PREFIX}__qr-code__tips`}>长按并识别二维码,添加好友</div>
|
||||
<div className={`${PREFIX}__qr-code__footer`}>{footer}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { CollectEventName, ReportEventId } from '@/constants/event';
|
||||
import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product';
|
||||
import { SubscribeTempId } from '@/constants/subscribe';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
import { collectEvent, reportEvent } from '@/utils/event';
|
||||
import { getOrderPrice, isCancelPay, requestCreatePayInfo, requestOrderInfo, requestPayment } from '@/utils/product';
|
||||
import { postSubscribe, subscribeMessage } from '@/utils/subscribe';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
interface IProps {
|
||||
onNext: () => void;
|
||||
}
|
||||
|
||||
const log = logWithPrefix('company-publish-job-buy');
|
||||
const TEMP_IDS = [SubscribeTempId.UNREAD_MESSAGE_REMINDER, SubscribeTempId.NEW_MESSAGE_REMINDER];
|
||||
interface Item {
|
||||
id: ProductSpecId;
|
||||
title: string;
|
||||
price: string;
|
||||
amt: number;
|
||||
contents: { content: string; highlight?: boolean }[];
|
||||
badge?: string;
|
||||
}
|
||||
|
||||
const LIST: Item[] = [
|
||||
{
|
||||
id: ProductSpecId.BOSS_VIP_NEW_1,
|
||||
title: '展示一周',
|
||||
price: '480播豆',
|
||||
amt: 48,
|
||||
badge: '限时体验',
|
||||
contents: [
|
||||
{ content: '-1个通告' },
|
||||
{ content: '-每天可查看20个主播详情' },
|
||||
{ content: '-每天可自主联系10个主播' },
|
||||
// { content: '-播络可代为联系20个主播(高成功率)', highlight: true },
|
||||
{ content: '-有效期一周' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: ProductSpecId.BOSS_VIP_NEW_2,
|
||||
title: '展示一月',
|
||||
price: '960播豆',
|
||||
amt: 96,
|
||||
badge: '五折',
|
||||
contents: [
|
||||
{ content: '-1个通告' },
|
||||
{ content: '-每天可查看20个主播详情' },
|
||||
{ content: '-每天可自主联系10个主播' },
|
||||
// { content: '-播络可代为联系20个主播(高成功率)', highlight: true },
|
||||
{ content: '-有效期一个月' },
|
||||
],
|
||||
},
|
||||
// {
|
||||
// id: ProductSpecId.BOSS_VIP_NEW_3,
|
||||
// title: '季会员',
|
||||
// price: '2680播豆',
|
||||
// amt: 268,
|
||||
// badge: '7折',
|
||||
// contents: [
|
||||
// { content: '-1个通告' },
|
||||
// { content: '-每天可查看20个主播详情' },
|
||||
// { content: '-每天可自主联系10个主播' },
|
||||
// { content: '-播络可代为联系60个主播(高成功率)', highlight: true },
|
||||
// { content: '-有效期3个月' },
|
||||
// ],
|
||||
// },
|
||||
];
|
||||
|
||||
const subscribe = async () => {
|
||||
const result = await subscribeMessage(TEMP_IDS);
|
||||
const successIds: SubscribeTempId[] = [];
|
||||
TEMP_IDS.forEach(id => {
|
||||
result[id] === 'accept' && successIds.push(id);
|
||||
});
|
||||
postSubscribe(TEMP_IDS, successIds);
|
||||
};
|
||||
|
||||
export default function CompanyPublishJobBuy(props: IProps) {
|
||||
const { onNext } = props;
|
||||
const [selectItem, setSelectItem] = useState(LIST[0]);
|
||||
|
||||
const handleClickItem = useCallback((newSelectItem: Item) => setSelectItem(newSelectItem), []);
|
||||
|
||||
const handleBuy = useCallback(async () => {
|
||||
log('handleBuy');
|
||||
reportEvent(ReportEventId.CLICK_PAY_PUBLISH_JOB);
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const { payOrderNo, createPayInfo } = await requestCreatePayInfo({
|
||||
type: OrderType.CompanyVip,
|
||||
amt: getOrderPrice(selectItem.amt),
|
||||
productCode: ProductType.BOSS_VIP_NEW,
|
||||
productSpecId: selectItem.id,
|
||||
});
|
||||
log('handleBuy payInfo', payOrderNo, createPayInfo);
|
||||
await requestPayment({
|
||||
timeStamp: createPayInfo.timeStamp,
|
||||
nonceStr: createPayInfo.nonceStr,
|
||||
package: createPayInfo.packageVal,
|
||||
signType: createPayInfo.signType,
|
||||
paySign: createPayInfo.paySign,
|
||||
success: () => subscribe(),
|
||||
});
|
||||
const { status } = await requestOrderInfo({ payOrderNo });
|
||||
log('handleBuy orderInfo', status);
|
||||
if (status !== OrderStatus.Success) {
|
||||
throw new Error('order status error');
|
||||
}
|
||||
Taro.hideLoading();
|
||||
onNext();
|
||||
} catch (e) {
|
||||
Taro.hideLoading();
|
||||
Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试');
|
||||
log('handleBuy error', e);
|
||||
}
|
||||
}, [selectItem, onNext]);
|
||||
|
||||
useEffect(() => {
|
||||
collectEvent(CollectEventName.CREATE_ORDER_VIEW, { orderType: OrderType.BossVip, source: 'user-page' });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__company-publish-job-buy`}>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__header`}>发认证通告限时折扣</div>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__price-container`}>
|
||||
{LIST.map(item => (
|
||||
<div
|
||||
key={item.price}
|
||||
className={classNames(`${PREFIX}__company-publish-job-buy__item`, {
|
||||
selected: item.amt === selectItem.amt,
|
||||
disabled: item.amt === 0,
|
||||
})}
|
||||
onClick={item.amt === 0 ? undefined : () => handleClickItem(item)}
|
||||
>
|
||||
<div className={classNames(`${PREFIX}__company-publish-job-buy__item__title`, { free: item.amt === 0 })}>
|
||||
{item.title}
|
||||
</div>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__item__price`}>{item.price}</div>
|
||||
{item.badge && <Badge className={`${PREFIX}__company-publish-job-buy__item__badge`} text={item.badge} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__divider`}>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__divider__left-line`} />
|
||||
<div className={`${PREFIX}__company-publish-job-buy__divider__title`}>包含</div>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__divider__right-line`} />
|
||||
</div>
|
||||
<div className={`${PREFIX}__company-publish-job-buy__contents`}>
|
||||
{selectItem.contents.map(i => (
|
||||
<div
|
||||
className={classNames(`${PREFIX}__company-publish-job-buy__content`, { highlight: i.highlight })}
|
||||
key={i.content}
|
||||
>
|
||||
{i.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button className={`${PREFIX}__company-publish-job-buy__button`} onClick={handleBuy}>
|
||||
{`支付${selectItem.amt}元`}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
32
src/components/product-dialog/steps-ui/group-buy-success.tsx
Normal file
32
src/components/product-dialog/steps-ui/group-buy-success.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { Image } from '@tarojs/components';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
|
||||
interface IProps {
|
||||
unlockTime: number;
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
export default function GroupBuySuccess(props: IProps) {
|
||||
return (
|
||||
<div className={`${PREFIX}__group-buy_success`}>
|
||||
<div className={`${PREFIX}__group-buy_success__tips-container`}>
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
className={`${PREFIX}__group-buy_success__icon`}
|
||||
src={require('@/statics/svg/success-circle-fill.svg')}
|
||||
/>
|
||||
<div className={`${PREFIX}__group-buy_success__tips`}>购买成功</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__group-buy_success__header`}>
|
||||
<div>当前剩余人工对接次数</div>
|
||||
<div className="highlight">{` ${props.unlockTime}次`}</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__group-buy_success__button`} onClick={props.onConfirm}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
110
src/components/product-dialog/steps-ui/group-buy.tsx
Normal file
110
src/components/product-dialog/steps-ui/group-buy.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { CollectEventName } from '@/constants/event';
|
||||
import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
import { collectEvent } from '@/utils/event';
|
||||
import {
|
||||
getOrderPrice,
|
||||
requestCreatePayInfo,
|
||||
requestOrderInfo,
|
||||
requestPayment,
|
||||
requestProductBalance,
|
||||
} from '@/utils/product';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
interface IProps {
|
||||
source: 'group-list' | 'job-detail';
|
||||
onConfirm: (time: number) => void;
|
||||
}
|
||||
|
||||
interface Item {
|
||||
id: ProductSpecId;
|
||||
num: number;
|
||||
price: number;
|
||||
badge?: string;
|
||||
}
|
||||
|
||||
const LIST: Item[] = [
|
||||
{ id: ProductSpecId.AddGroup1, num: 1, price: 2 },
|
||||
{ id: ProductSpecId.AddGroup2, num: 2, price: 3, badge: '7.5折' },
|
||||
{ id: ProductSpecId.AddGroup3, num: 5, price: 6, badge: '6折' },
|
||||
];
|
||||
|
||||
const log = logWithPrefix('group-buy');
|
||||
|
||||
export default function GroupBuy(props: IProps) {
|
||||
const { source, onConfirm } = props;
|
||||
const [selectItem, setSelectItem] = useState(LIST[2]);
|
||||
|
||||
const handleClickItem = useCallback((newSelectItem: Item) => setSelectItem(newSelectItem), []);
|
||||
|
||||
const handleBuy = useCallback(async () => {
|
||||
log('handleBuy', selectItem);
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const { payOrderNo, createPayInfo } = await requestCreatePayInfo({
|
||||
type: OrderType.Group,
|
||||
amt: getOrderPrice(selectItem.price),
|
||||
// amt: selectItem.price,
|
||||
// amt: 1,
|
||||
productCode: ProductType.AddGroup,
|
||||
productSpecId: selectItem.id,
|
||||
});
|
||||
log('handleBuy payInfo', payOrderNo, createPayInfo);
|
||||
await requestPayment({
|
||||
timeStamp: createPayInfo.timeStamp,
|
||||
nonceStr: createPayInfo.nonceStr,
|
||||
package: createPayInfo.packageVal,
|
||||
signType: createPayInfo.signType,
|
||||
paySign: createPayInfo.paySign,
|
||||
});
|
||||
const { status } = await requestOrderInfo({ payOrderNo });
|
||||
log('handleBuy orderInfo', status);
|
||||
if (status !== OrderStatus.Success) {
|
||||
throw new Error('order status error');
|
||||
}
|
||||
const time = await requestProductBalance(ProductType.AddGroup);
|
||||
log('handleBuy new addGroupTime', time);
|
||||
onConfirm(time);
|
||||
} catch (e) {
|
||||
Toast.error('购买失败!');
|
||||
log('handleBuy error', e);
|
||||
} finally {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
}, [selectItem, onConfirm]);
|
||||
|
||||
useEffect(() => {
|
||||
collectEvent(CollectEventName.CREATE_ORDER_VIEW, { orderType: OrderType.Group, source });
|
||||
}, [source]);
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__group-buy`}>
|
||||
<div className={`${PREFIX}__group-buy__header`}>购买对接次数</div>
|
||||
<div className={`${PREFIX}__group-buy__container`}>
|
||||
{LIST.map(item => (
|
||||
<div
|
||||
key={item.price}
|
||||
className={classNames(`${PREFIX}__group-buy__item`, { selected: item.price === selectItem.price })}
|
||||
onClick={() => handleClickItem(item)}
|
||||
>
|
||||
<div className={`${PREFIX}__group-buy__item-title`}>{`${item.num} 个`}</div>
|
||||
<div className={`${PREFIX}__group-buy__item-price`}>{`${item.price} 元`}</div>
|
||||
{item.badge && <Badge text={item.badge} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button className={`${PREFIX}__group-buy__button`} onClick={handleBuy}>
|
||||
{`支付 ${selectItem.price} 元`}
|
||||
</Button>
|
||||
<div className={`${PREFIX}__group-buy__tips`}>{`已选:${selectItem.num} 次`}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
26
src/components/product-dialog/steps-ui/group-confirm.tsx
Normal file
26
src/components/product-dialog/steps-ui/group-confirm.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
|
||||
interface IConfirmContentProps {
|
||||
unlockTime: number;
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
export default function ConfirmContent(props: IConfirmContentProps) {
|
||||
const { unlockTime, onConfirm } = props;
|
||||
return (
|
||||
<div className={`${PREFIX}__group-confirm`}>
|
||||
<div className={classNames(`${PREFIX}__group-confirm__tips`, 'highlight')}>如您不在群里,可让播络邀请</div>
|
||||
<div className={`${PREFIX}__group-confirm__header`}>
|
||||
<div>您还剩</div>
|
||||
<div className="highlight">{`${unlockTime}次邀请`}</div>
|
||||
<div>机会</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__group-confirm__button`} onClick={onConfirm}>
|
||||
邀我进群
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
27
src/components/product-dialog/steps-ui/group-need-buy.tsx
Normal file
27
src/components/product-dialog/steps-ui/group-need-buy.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
|
||||
interface IUnableContentProp {
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
export default function GroupNeedBuyContent(props: IUnableContentProp) {
|
||||
return (
|
||||
<div className={`${PREFIX}__group-need-buy`}>
|
||||
<div className={classNames(`${PREFIX}__group-need-buy__top-tips`, 'highlight')}>如您不在群里,可让播络邀请</div>
|
||||
<div className={`${PREFIX}__group-need-buy__header`}>
|
||||
<div>您的邀请机会</div>
|
||||
<div className="highlight">已用完</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__group-need-buy__button-container`}>
|
||||
<Button className={`${PREFIX}__group-need-buy__button`} onClick={props.onConfirm}>
|
||||
购买邀请群数
|
||||
</Button>
|
||||
<Badge text="限时折扣" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
142
src/components/product-dialog/steps-ui/job-buy.tsx
Normal file
142
src/components/product-dialog/steps-ui/job-buy.tsx
Normal file
@ -0,0 +1,142 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { CollectEventName } from '@/constants/event';
|
||||
import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product';
|
||||
import { SubscribeTempId } from '@/constants/subscribe';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
import { collectEvent } from '@/utils/event';
|
||||
import { getOrderPrice, isCancelPay, requestCreatePayInfo, requestOrderInfo, requestPayment } from '@/utils/product';
|
||||
import { postSubscribe, subscribeMessage } from '@/utils/subscribe';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
interface IProps {
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
interface Item {
|
||||
id: ProductSpecId;
|
||||
title: string;
|
||||
content: string;
|
||||
price: string;
|
||||
amt: number;
|
||||
badge?: string;
|
||||
}
|
||||
|
||||
const LIST: Item[] = [
|
||||
{ id: ProductSpecId.WeeklyVIP, title: '非会员', content: '每日2次', price: '免费', amt: 0 },
|
||||
{
|
||||
id: ProductSpecId.WeeklyVIP,
|
||||
title: '周会员',
|
||||
content: '每日5次',
|
||||
price: '60播豆',
|
||||
amt: 6,
|
||||
badge: '限时体验',
|
||||
},
|
||||
{
|
||||
id: ProductSpecId.NewMonthlyVIP,
|
||||
title: '月会员',
|
||||
content: '每日5次',
|
||||
price: '180播豆',
|
||||
amt: 18,
|
||||
badge: ' 超值',
|
||||
},
|
||||
];
|
||||
|
||||
const log = logWithPrefix('job-buy');
|
||||
const SUBSCRIBE_ID = SubscribeTempId.SUBSCRIBE_VIP;
|
||||
|
||||
const subscribe = async () => {
|
||||
const result = await subscribeMessage([SUBSCRIBE_ID]);
|
||||
const success = result[SUBSCRIBE_ID] === 'accept';
|
||||
if (!success) {
|
||||
postSubscribe([SUBSCRIBE_ID], []);
|
||||
return;
|
||||
}
|
||||
postSubscribe([SUBSCRIBE_ID], [SUBSCRIBE_ID]);
|
||||
};
|
||||
|
||||
export default function JobBuy(props: IProps) {
|
||||
const { onConfirm } = props;
|
||||
const [selectItem, setSelectItem] = useState(LIST[1]);
|
||||
|
||||
const handleClickItem = useCallback((newSelectItem: Item) => setSelectItem(newSelectItem), []);
|
||||
|
||||
const handleBuy = useCallback(async () => {
|
||||
log('handleBuy', selectItem);
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const { payOrderNo, createPayInfo } = await requestCreatePayInfo({
|
||||
type: OrderType.VIP,
|
||||
amt: getOrderPrice(selectItem.amt),
|
||||
productCode: ProductType.VIP,
|
||||
productSpecId: selectItem.id,
|
||||
});
|
||||
log('handleBuy payInfo', payOrderNo, createPayInfo);
|
||||
await requestPayment({
|
||||
timeStamp: createPayInfo.timeStamp,
|
||||
nonceStr: createPayInfo.nonceStr,
|
||||
package: createPayInfo.packageVal,
|
||||
signType: createPayInfo.signType,
|
||||
paySign: createPayInfo.paySign,
|
||||
success: () => subscribe(),
|
||||
});
|
||||
const { status } = await requestOrderInfo({ payOrderNo });
|
||||
log('handleBuy orderInfo', status);
|
||||
if (status !== OrderStatus.Success) {
|
||||
throw new Error('order status error');
|
||||
}
|
||||
Taro.hideLoading();
|
||||
onConfirm();
|
||||
} catch (e) {
|
||||
Taro.hideLoading();
|
||||
Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试');
|
||||
log('handleBuy error', e);
|
||||
}
|
||||
}, [selectItem, onConfirm]);
|
||||
|
||||
useEffect(() => {
|
||||
collectEvent(CollectEventName.CREATE_ORDER_VIEW, { orderType: OrderType.VIP });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__job-buy`}>
|
||||
<div className={`${PREFIX}__job-buy__header`}>
|
||||
<div>今日通告对接次数</div>
|
||||
<div className="highlight">已用完</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__job-buy__describe`}>
|
||||
<div>请</div>
|
||||
<div className="highlight">明日</div>
|
||||
<div>再来 或 </div>
|
||||
<div className="highlight">升级会员</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__job-buy__container`}>
|
||||
{LIST.map(item => (
|
||||
<div
|
||||
key={item.price}
|
||||
className={classNames(`${PREFIX}__job-buy__item`, {
|
||||
selected: item.amt === selectItem.amt,
|
||||
disabled: item.amt === 0,
|
||||
})}
|
||||
onClick={item.amt === 0 ? undefined : () => handleClickItem(item)}
|
||||
>
|
||||
<div className={classNames(`${PREFIX}__job-buy__item__title`, { free: item.amt === 0 })}>{item.title}</div>
|
||||
<div className={`${PREFIX}__job-buy__item__content`}>{item.content}</div>
|
||||
<div className={`${PREFIX}__job-buy__item__price`}>{item.price}</div>
|
||||
{item.badge && <Badge className={`${PREFIX}__job-buy__item__badge`} text={item.badge} />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button className={`${PREFIX}__job-buy__button`} onClick={handleBuy}>
|
||||
{`支付 ${selectItem.amt} 元`}
|
||||
</Button>
|
||||
{/* <div className={`${PREFIX}__job-buy__tips`}>{`已选:${selectItem.title},含进本地群服务`}</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { SubscribeTempId } from '@/constants/subscribe';
|
||||
import { postSubscribe, subscribeMessage } from '@/utils/subscribe';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
interface IContactCSProps {
|
||||
onAfterConfirm: () => void;
|
||||
}
|
||||
|
||||
const SUBSCRIBE_ID = SubscribeTempId.SUBSCRIBE_JOB;
|
||||
|
||||
export default function ContactCustomerService(props: IContactCSProps) {
|
||||
const { onAfterConfirm } = props;
|
||||
|
||||
const handleClick = async () => {
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const result = await subscribeMessage([SUBSCRIBE_ID]);
|
||||
const success = result[SUBSCRIBE_ID] === 'accept';
|
||||
Taro.hideLoading();
|
||||
if (!success) {
|
||||
Toast.error('拒绝订阅');
|
||||
postSubscribe([SUBSCRIBE_ID], []);
|
||||
return;
|
||||
}
|
||||
Toast.success('订阅成功');
|
||||
postSubscribe([SUBSCRIBE_ID], [SUBSCRIBE_ID]);
|
||||
onAfterConfirm();
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__job-contact_cs`}>
|
||||
<div className={`${PREFIX}__job-contact_cs__header`}>您已报名本通告</div>
|
||||
<div className={`${PREFIX}__job-contact_cs__describe`}>本通告尚未维护联系方式</div>
|
||||
<div className={`${PREFIX}__job-contact_cs__content`}>{`本通告不消耗对接次数,\n联系上立马通知您`}</div>
|
||||
<div className={`${PREFIX}__job-contact_cs__describe`}>联系上后会通知您,请点击下方订阅通知</div>
|
||||
<Button className={`${PREFIX}__job-contact_cs__button`} onClick={handleClick}>
|
||||
订阅通知
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { Button } from '@taroify/core';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { copy } from '@/utils/common';
|
||||
|
||||
interface IContactDirectProps {
|
||||
publisherAcctNo: string;
|
||||
onAfterConfirm: () => void;
|
||||
onReport: () => void;
|
||||
}
|
||||
|
||||
export default function ContactDirect(props: IContactDirectProps) {
|
||||
const { publisherAcctNo, onAfterConfirm, onReport } = props;
|
||||
|
||||
const handleCopyAndContact = async () => {
|
||||
await copy(publisherAcctNo);
|
||||
onAfterConfirm();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__job-contact_direct`}>
|
||||
<div className={`${PREFIX}__job-contact_direct__header`}>您已报名本通告</div>
|
||||
<div className={`${PREFIX}__job-contact_direct__describe`}>通告发布人微信</div>
|
||||
<div className={`${PREFIX}__job-contact_direct__content`}>{publisherAcctNo}</div>
|
||||
<div className={`${PREFIX}__job-contact_direct__describe`}>请添加对方好友,并备注:播络主播报单</div>
|
||||
<Button className={`${PREFIX}__job-contact_direct__button`} onClick={handleCopyAndContact}>
|
||||
复制微信号
|
||||
</Button>
|
||||
{/* <div className={`${PREFIX}__job-contact_direct__report`} onClick={onReport}>
|
||||
上报:微信加不上
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
import { Button } from '@taroify/core';
|
||||
import classNames from 'classnames';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { DialogStatus, PREFIX } from '@/components/product-dialog/const';
|
||||
|
||||
interface IContactDirectProps {
|
||||
status: DialogStatus;
|
||||
publisherAcctNo: string;
|
||||
imGroupNick: string;
|
||||
inviteTime?: number;
|
||||
onConfirm: (status: DialogStatus) => void;
|
||||
}
|
||||
|
||||
export default function ContactWithGroup(props: IContactDirectProps) {
|
||||
const { status, publisherAcctNo, inviteTime, onConfirm } = props;
|
||||
|
||||
const handleConfirm = async () => {
|
||||
onConfirm(status);
|
||||
};
|
||||
|
||||
let describe: ReactElement | null = null;
|
||||
let buttonText = '确定';
|
||||
let badge: ReactElement | null = null;
|
||||
if (status === DialogStatus.JOB_CONTACT_INVITE_GROUP) {
|
||||
describe = (
|
||||
<div className={classNames(`${PREFIX}__job-contact-with-group__describe`)}>
|
||||
<div>您还剩</div>
|
||||
<div className="highlight">{`${inviteTime}次对接`}</div>
|
||||
<div>机会</div>
|
||||
</div>
|
||||
);
|
||||
} else if (status === DialogStatus.JOB_CONTACT_NEED_BUY_GROUP) {
|
||||
describe = (
|
||||
<div className={classNames(`${PREFIX}__job-contact-with-group__describe`)}>
|
||||
<div>您的人工对接机会</div>
|
||||
<div className="highlight">已用完</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (status === DialogStatus.JOB_CONTACT_INVITE_GROUP) {
|
||||
buttonText = '帮我对接';
|
||||
} else if (status === DialogStatus.JOB_CONTACT_NEED_BUY_GROUP) {
|
||||
buttonText = '购买对接次数';
|
||||
}
|
||||
|
||||
if (status === DialogStatus.JOB_CONTACT_NEED_BUY_GROUP) {
|
||||
badge = <Badge text="限时折扣" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__job-contact-with-group`}>
|
||||
<div className={`${PREFIX}__job-contact-with-group__header`}>该通告需要播络帮你对接</div>
|
||||
<div className={`${PREFIX}__job-contact-with-group__content`}>
|
||||
<div>{`发布人昵称: ${publisherAcctNo}`}</div>
|
||||
</div>
|
||||
{describe}
|
||||
<div className={`${PREFIX}__job-contact-with-group__button-container`}>
|
||||
<Button className={`${PREFIX}__job-contact-with-group__button`} onClick={handleConfirm}>
|
||||
{buttonText}
|
||||
</Button>
|
||||
{badge}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
26
src/components/product-dialog/steps-ui/job-unable.tsx
Normal file
26
src/components/product-dialog/steps-ui/job-unable.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { Button } from '@taroify/core';
|
||||
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
|
||||
interface IUnableUnlockContentProp {
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
export default function UnableUnlockContent(props: IUnableUnlockContentProp) {
|
||||
return (
|
||||
<div className={`${PREFIX}__job-unable`}>
|
||||
<div className={`${PREFIX}__job-unable__header`}>
|
||||
<div>今日通告对接次数</div>
|
||||
<div className="highlight">已用完</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__job-unable__describe`}>
|
||||
<div>请</div>
|
||||
<div className="highlight">明日</div>
|
||||
<div>再来</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__job-unable__button`} onClick={props.onConfirm}>
|
||||
确定
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
78
src/components/product-dialog/steps-ui/publish-job-buy.tsx
Normal file
78
src/components/product-dialog/steps-ui/publish-job-buy.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Button } from '@taroify/core';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import Badge from '@/components/badge';
|
||||
import { PREFIX } from '@/components/product-dialog/const';
|
||||
import { CollectEventName } from '@/constants/event';
|
||||
import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
import { collectEvent } from '@/utils/event';
|
||||
import { getOrderPrice, isCancelPay, requestCreatePayInfo, requestOrderInfo, requestPayment } from '@/utils/product';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
interface IProps {
|
||||
onNext: () => void;
|
||||
}
|
||||
|
||||
const log = logWithPrefix('publish-job-buy');
|
||||
const PRICE = 48;
|
||||
|
||||
export default function PublishJobBuy(props: IProps) {
|
||||
const { onNext } = props;
|
||||
|
||||
const handleBuy = useCallback(async () => {
|
||||
log('handleBuy');
|
||||
try {
|
||||
Taro.showLoading();
|
||||
const { payOrderNo, createPayInfo } = await requestCreatePayInfo({
|
||||
type: OrderType.BossVip,
|
||||
amt: getOrderPrice(PRICE),
|
||||
// amt: PRICE,
|
||||
// amt: 1,
|
||||
productCode: ProductType.BossVip,
|
||||
productSpecId: ProductSpecId.BossVip,
|
||||
});
|
||||
log('handleBuy payInfo', payOrderNo, createPayInfo);
|
||||
await requestPayment({
|
||||
timeStamp: createPayInfo.timeStamp,
|
||||
nonceStr: createPayInfo.nonceStr,
|
||||
package: createPayInfo.packageVal,
|
||||
signType: createPayInfo.signType,
|
||||
paySign: createPayInfo.paySign,
|
||||
});
|
||||
const { status } = await requestOrderInfo({ payOrderNo });
|
||||
log('handleBuy orderInfo', status);
|
||||
if (status !== OrderStatus.Success) {
|
||||
throw new Error('order status error');
|
||||
}
|
||||
Taro.hideLoading();
|
||||
onNext();
|
||||
} catch (e) {
|
||||
Taro.hideLoading();
|
||||
Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试');
|
||||
log('handleBuy error', e);
|
||||
}
|
||||
}, [onNext]);
|
||||
|
||||
useEffect(() => {
|
||||
collectEvent(CollectEventName.CREATE_ORDER_VIEW, { orderType: OrderType.BossVip, source: 'user-page' });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`${PREFIX}__publish-job-buy`}>
|
||||
<div className={`${PREFIX}__publish-job-buy__header`}>发通告限时折扣</div>
|
||||
|
||||
<div className={`${PREFIX}__publish-job-buy__price-container`}>
|
||||
<div className={`${PREFIX}__publish-job-buy__price`}>{PRICE}</div>
|
||||
<div>元</div>
|
||||
<Badge className={`${PREFIX}__publish-job-buy__badge`} text="7.1折" />
|
||||
</div>
|
||||
<div className={`${PREFIX}__publish-job-buy__tips`}>原价:68元/月</div>
|
||||
<Button className={`${PREFIX}__publish-job-buy__button`} onClick={handleBuy}>
|
||||
立即支付
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user