feat: update
This commit is contained in:
@ -13,3 +13,8 @@ page {
|
||||
.base-bg();
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Alimama ShuHeiTi';
|
||||
src: url('https://publiccdn.neighbourhood.com.cn/font/almmheiti.ttf');
|
||||
}
|
||||
|
||||
42
src/app.tsx
42
src/app.tsx
@ -6,7 +6,7 @@ import { Provider } from 'react-redux';
|
||||
import { REFRESH_UNREAD_COUNT_TIME } from '@/constants/message';
|
||||
import http from '@/http';
|
||||
import store from '@/store';
|
||||
import { requestServiceUrls } from '@/utils/location';
|
||||
import { requestCityOperators } from '@/utils/location';
|
||||
import { requestUnreadMessageCount } from '@/utils/message';
|
||||
import { decryptOpenGid, getInviteCode, getInviteCodeFromQuery } from '@/utils/partner';
|
||||
import qiniuUpload from '@/utils/qiniu-upload';
|
||||
@ -30,28 +30,30 @@ function App({ children }: PropsWithChildren<BL.Anything>) {
|
||||
});
|
||||
|
||||
useDidShow(options => {
|
||||
requestServiceUrls();
|
||||
requestCityOperators();
|
||||
|
||||
console.log(options);
|
||||
Taro.getGroupEnterInfo()
|
||||
.then(info => {
|
||||
const inviteCode = getInviteCodeFromQuery(options?.query || {});
|
||||
const authCode = options?.query?.authCode;
|
||||
decryptOpenGid({
|
||||
inviteCode,
|
||||
authCode,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
iv: info.iv,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
encryptedData: info.encryptedData,
|
||||
const inviteCode = getInviteCodeFromQuery(options?.query || {});
|
||||
const authCode = options?.query?.authCode;
|
||||
if (inviteCode || authCode) {
|
||||
Taro.getGroupEnterInfo()
|
||||
.then(info => {
|
||||
decryptOpenGid({
|
||||
inviteCode,
|
||||
authCode,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
iv: info.iv,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
encryptedData: info.encryptedData,
|
||||
});
|
||||
console.log('哈哈哈', info);
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('没有解析到群', options?.scene);
|
||||
});
|
||||
console.log('哈哈哈', info);
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('没有解析到群', options?.scene);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return <Provider store={store}>{children}</Provider>;
|
||||
|
||||
@ -7,7 +7,7 @@ import { useCallback, useState } from 'react';
|
||||
import { RoleType } from '@/constants/app';
|
||||
import { CacheKey } from '@/constants/cache-key';
|
||||
import { CITY_CODE_TO_NAME_MAP } from '@/constants/city';
|
||||
import useServiceUrls from '@/hooks/use-service-urls';
|
||||
import useCityOperators from '@/hooks/use-city-operators';
|
||||
import { getRoleTypeWithDefault } from '@/utils/app';
|
||||
import { openCustomerServiceChat } from '@/utils/common';
|
||||
import { getCurrentCityCode } from '@/utils/location';
|
||||
@ -24,14 +24,14 @@ const DEFAULT_GROUP = {
|
||||
export function JoinGroupHint() {
|
||||
const cityCode = getCurrentCityCode();
|
||||
const roleType = getRoleTypeWithDefault();
|
||||
const serviceUrls = useServiceUrls();
|
||||
const group = serviceUrls.find(g => String(g.cityCode) === cityCode);
|
||||
const cityOperators = useCityOperators();
|
||||
const group = cityOperators.find(g => String(g.cityCode) === cityCode);
|
||||
const [clicked, setClicked] = useState(!!Taro.getStorageSync(CacheKey.JOIN_GROUP_CARD_CLICKED));
|
||||
const handleClick = useCallback(() => {
|
||||
if (group && !checkCityCode(cityCode)) {
|
||||
return;
|
||||
}
|
||||
openCustomerServiceChat(group ? group.serviceUrl : DEFAULT_GROUP.serviceUrl);
|
||||
openCustomerServiceChat(group ? group.groupLink : DEFAULT_GROUP.serviceUrl);
|
||||
Taro.setStorageSync(CacheKey.JOIN_GROUP_CARD_CLICKED, true);
|
||||
setClicked(true);
|
||||
}, [cityCode, group]);
|
||||
|
||||
@ -18,7 +18,7 @@ export default function LoginDialog(props: IProps) {
|
||||
const { title = '使用播络服务前,请先登录', needPhone, onSuccess, onCancel, onBindPhone } = props;
|
||||
|
||||
return (
|
||||
<Dialog open onClose={onCancel}>
|
||||
<Dialog open onClose={onCancel} className={PREFIX}>
|
||||
<Dialog.Content>
|
||||
<div className={`${PREFIX}__container`}>
|
||||
<div className={`${PREFIX}__title`}>{title}</div>
|
||||
|
||||
@ -12,7 +12,7 @@ import './index.less';
|
||||
|
||||
const PREFIX = 'partner-fragment-banner';
|
||||
|
||||
export default function PartnerBanner() {
|
||||
export default function PartnerBanner({ isBoss = false }) {
|
||||
const userInfo = useUserInfo();
|
||||
const needPhone = isNeedPhone(userInfo);
|
||||
const isPartner = userInfo.isPartner;
|
||||
@ -50,7 +50,11 @@ export default function PartnerBanner() {
|
||||
<div className={PREFIX} onClick={handleClick}>
|
||||
<Image
|
||||
className={`${PREFIX}__image`}
|
||||
src="https://publiccdn.neighbourhood.com.cn/img/partner_banner.png"
|
||||
src={
|
||||
isBoss
|
||||
? 'https://publiccdn.neighbourhood.com.cn/img/partner-banner-boss.png'
|
||||
: 'https://publiccdn.neighbourhood.com.cn/img/partner_banner.png'
|
||||
}
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
{needPhone && (
|
||||
@ -60,9 +64,7 @@ export default function PartnerBanner() {
|
||||
)}
|
||||
<div className={`${PREFIX}__close`} onClick={handlePartnerBannerClose} />
|
||||
</div>
|
||||
{visible && (
|
||||
<LoginDialog onCancel={() => setVisible(false)} onSuccess={handleBind} needPhone={needPhone} />
|
||||
)}
|
||||
{visible && <LoginDialog onCancel={() => setVisible(false)} onSuccess={handleBind} needPhone={needPhone} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,26 +2,53 @@
|
||||
@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));
|
||||
background: #eae5fb;
|
||||
padding-top: 271px;
|
||||
position: relative;
|
||||
padding-bottom: calc(142px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(142px + env(safe-area-inset-bottom));
|
||||
|
||||
&__banner {
|
||||
background: rgb(229, 225, 248);
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
position: fixed;
|
||||
top: 98px;
|
||||
&__bg {
|
||||
width: 100%;
|
||||
height: 705px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
}
|
||||
&__slogan {
|
||||
top: 66px;
|
||||
left: 44px;
|
||||
position: absolute;
|
||||
font-family: 'Alimama ShuHeiTi';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 44px;
|
||||
line-height: 62px;
|
||||
color: #333333;
|
||||
|
||||
> div {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
&-highlight {
|
||||
display: inline-block;
|
||||
padding-left: 12px;
|
||||
padding-right: 9px;
|
||||
font-size: 64px;
|
||||
line-height: 62px;
|
||||
background: linear-gradient(87.53deg, #683DE3 0.4%, #39227D 84.55%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&__main {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&__highlight {
|
||||
@ -34,15 +61,17 @@
|
||||
}
|
||||
|
||||
&__block {
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__swiper {
|
||||
margin-bottom: 48px;
|
||||
&-wrapper {
|
||||
margin-bottom: 8px;
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
position: relative;
|
||||
border: 1px solid #6d3df5;
|
||||
}
|
||||
|
||||
&-bg {
|
||||
@ -54,12 +83,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&__swiper-item {
|
||||
box-sizing: border-box;
|
||||
height: 130px;
|
||||
padding: 24px 32px;
|
||||
&-item {
|
||||
&-time {
|
||||
font-style: normal;
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
@ -98,7 +126,7 @@
|
||||
&__card {
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
padding: 24px 32px;
|
||||
padding: 68px 32px 44px;
|
||||
}
|
||||
|
||||
&__h1 {
|
||||
@ -108,10 +136,30 @@
|
||||
color: #1d2129;
|
||||
margin-bottom: 16px;
|
||||
margin-top: 32px;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
|
||||
&.no-dot {
|
||||
&:after {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #ffd236;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: -3px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
@ -130,12 +178,19 @@
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-bottom: 24px;
|
||||
margin-left: 48px;
|
||||
margin-right: 48px;
|
||||
font-weight: 500;
|
||||
font-size: 32px;
|
||||
line-height: 32px;
|
||||
|
||||
line-height: 80px;
|
||||
height: 80px;
|
||||
transform: translateY(50%);
|
||||
background: #ffd236;
|
||||
box-shadow: 0px 12px 0px #ffa35d;
|
||||
border-radius: 60px;
|
||||
color: #1d2129;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__recommend {
|
||||
@ -143,17 +198,19 @@
|
||||
line-height: 36px;
|
||||
padding: 0 8px;
|
||||
height: 36px;
|
||||
margin-left: 16px;
|
||||
background: rgba(255, 80, 81, 0.12);
|
||||
background: rgb(255, 80, 81);
|
||||
border-radius: 4px;
|
||||
font-size: 24px;
|
||||
color: #ff5051;
|
||||
color: #fff;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
gap: 6px;
|
||||
right: -25px;
|
||||
top: -18px;
|
||||
}
|
||||
|
||||
&__special {
|
||||
padding: 32px;
|
||||
padding-top: 75px;
|
||||
.flex-column();
|
||||
|
||||
.partner-intro__body {
|
||||
@ -176,6 +233,7 @@
|
||||
&__footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
width: 100vw;
|
||||
background: #ffffff;
|
||||
padding: 12px 32px;
|
||||
@ -188,17 +246,20 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__download-button {
|
||||
flex: 1 1;
|
||||
//flex: 1 1;
|
||||
.button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px; @highlight: 0);
|
||||
}
|
||||
|
||||
&__share-button {
|
||||
flex: 2 2;
|
||||
//flex: 2 2;
|
||||
flex: 0 0 406px;
|
||||
width: 406px;
|
||||
.button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px;);
|
||||
margin-left: 32px;
|
||||
//margin-left: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Button, Canvas, Image } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
import { Swiper } from '@taroify/core';
|
||||
import { GoodJob } from '@taroify/icons';
|
||||
@ -8,114 +7,14 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { PageUrl } from '@/constants/app';
|
||||
import { EarnType, UserProfitListItem } from '@/types/partner';
|
||||
import { openCustomerServiceChat } from '@/utils/common';
|
||||
import { generateMembershipCoupon, getCouponQrCode } from '@/utils/coupon';
|
||||
import { formatMoney, formatTimestamp, getLastProfitList } from '@/utils/partner';
|
||||
import { formatMoney, formatTimestamp, formatUserId, getLastProfitList } from '@/utils/partner';
|
||||
import { navigateTo } from '@/utils/route';
|
||||
|
||||
import './index.less';
|
||||
|
||||
const PREFIX = 'partner-intro';
|
||||
|
||||
export default function PartnerIntro() {
|
||||
const getQrcode = async () => {
|
||||
try {
|
||||
const { code } = await generateMembershipCoupon();
|
||||
const data = await getCouponQrCode(code);
|
||||
const base64 = Taro.arrayBufferToBase64(data);
|
||||
return `data:image/png;base64,${base64}`;
|
||||
} catch (error) {
|
||||
console.error('获取二维码失败', error);
|
||||
Taro.showToast({ title: '获取二维码失败', icon: 'none' });
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
const saveCanvasToTempFile = (): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const query = Taro.createSelectorQuery().select('#posterCanvas');
|
||||
query.fields({ node: true }).exec(async res => {
|
||||
const canvas = res[0].node;
|
||||
const tempFilePath = await Taro.canvasToTempFilePath({
|
||||
canvas,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1500, // 实际绘制宽度
|
||||
height: 2668, // 实际绘制高度
|
||||
destWidth: 750, // 目标显示宽度
|
||||
destHeight: 1334, // 目标显示高度
|
||||
fileType: 'png',
|
||||
});
|
||||
|
||||
resolve(tempFilePath.tempFilePath);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('保存 Canvas 到临时文件失败', error);
|
||||
Taro.showToast({ title: '保存 Canvas 失败', icon: 'none' });
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
const drawCanvas = (qrCode: string): Promise<string> => {
|
||||
const query = Taro.createSelectorQuery().select('#posterCanvas');
|
||||
return new Promise(resolve => {
|
||||
query.fields({ node: true, size: true }).exec(async res => {
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = 550 * 2;
|
||||
canvas.height = 918 * 2;
|
||||
ctx.scale(2, 2);
|
||||
|
||||
// 绘制背景图片
|
||||
const bgImage = canvas.createImage();
|
||||
const poster = 'https://publiccdn.neighbourhood.com.cn/img/share-coupon-poster2.png';
|
||||
bgImage.src = poster;
|
||||
bgImage.onload = () => {
|
||||
ctx.drawImage(bgImage, 0, 0, 550, 918);
|
||||
|
||||
const qrCodeImage = canvas.createImage();
|
||||
qrCodeImage.src = qrCode; // 假设 getQrcode() 返回的是二维码图片的路径
|
||||
qrCodeImage.onload = () => {
|
||||
ctx.drawImage(qrCodeImage, 196, 600, 180, 160); // 绘制二维码,位置和大小
|
||||
saveCanvasToTempFile().then(tempPath => {
|
||||
resolve(tempPath);
|
||||
});
|
||||
};
|
||||
};
|
||||
bgImage.onerror = err => {
|
||||
console.error(err);
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
const savePoster = async () => {
|
||||
Taro.showLoading({ title: '正在生成海报' });
|
||||
const qrCode = await getQrcode();
|
||||
const filePath = await drawCanvas(qrCode);
|
||||
Taro.hideLoading();
|
||||
|
||||
const res = await Taro.getSetting();
|
||||
const hasPermission = res.authSetting['scope.writePhotosAlbum'];
|
||||
if (hasPermission === false) {
|
||||
Taro.showModal({
|
||||
title: '提示',
|
||||
content: '需要访问相册权限才能保存图片,请前往设置开启权限',
|
||||
showCancel: false,
|
||||
success() {
|
||||
Taro.openSetting();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
await Taro.authorize({ scope: 'scope.writePhotosAlbum' });
|
||||
await Taro.saveImageToPhotosAlbum({ filePath });
|
||||
Taro.showToast({ title: '保存成功', icon: 'success' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Taro.showToast({ title: '保存失败', icon: 'none' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = useCallback(() => {
|
||||
navigateTo(PageUrl.GroupOwnerCertificate);
|
||||
}, []);
|
||||
@ -124,6 +23,10 @@ export default function PartnerIntro() {
|
||||
openCustomerServiceChat('https://work.weixin.qq.com/kfid/kfc4fcf6b109b3771d7');
|
||||
}, []);
|
||||
|
||||
const handleJump = useCallback(() => {
|
||||
navigateTo(PageUrl.PartnerShareVip);
|
||||
}, []);
|
||||
|
||||
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const [bannerList, setBannerList] = useState<UserProfitListItem[]>([]);
|
||||
|
||||
@ -134,7 +37,7 @@ export default function PartnerIntro() {
|
||||
}
|
||||
|
||||
const list = await getLastProfitList();
|
||||
setBannerList(s => [...s, ...list]);
|
||||
setBannerList(list);
|
||||
|
||||
timerRef.current = setTimeout(
|
||||
() => {
|
||||
@ -156,8 +59,16 @@ export default function PartnerIntro() {
|
||||
}, [getBannerList]);
|
||||
return (
|
||||
<div className={PREFIX}>
|
||||
<div className={`${PREFIX}__banner`}>
|
||||
邀请朋友加入播络,高达<span className={`${PREFIX}__highlight`}>75%</span>分成
|
||||
<Image
|
||||
src="https://publiccdn.neighbourhood.com.cn/img/partner-intro-bg.png"
|
||||
className={`${PREFIX}__bg`}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<div className={`${PREFIX}__slogan`}>
|
||||
<div>邀请朋友加入播络</div>
|
||||
<div>
|
||||
高达<div className={`${PREFIX}__slogan-highlight`}>75%</div>分成
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__main`}>
|
||||
<div className={`${PREFIX}__swiper-wrapper`}>
|
||||
@ -168,10 +79,10 @@ export default function PartnerIntro() {
|
||||
/>
|
||||
<Swiper className={`${PREFIX}__swiper`} autoplay={3000} touchable={false}>
|
||||
{bannerList.map((item, index) => (
|
||||
<Swiper.Item className={`${PREFIX}__swiper-item`} key={index}>
|
||||
<Swiper.Item className={`${PREFIX}__swiper-item`} key={`${item.userId}-${index}`}>
|
||||
<div className={`${PREFIX}__swiper-item-time`}>{formatTimestamp(item.updatedAt)}</div>
|
||||
<div className={`${PREFIX}__swiper-item-details`}>
|
||||
<div className={`${PREFIX}__swiper-item-id`}>{item.userId}</div>
|
||||
<div className={`${PREFIX}__swiper-item-id`}>{formatUserId(item.userId)}</div>
|
||||
<div className={`${PREFIX}__swiper-item-info`}>
|
||||
{[EarnType.CHAT_ACTIVITY_SHARE_L1, EarnType.CHAT_ACTIVITY_SHARE_L2].includes(item.earnType)
|
||||
? '主播被开聊'
|
||||
@ -187,6 +98,25 @@ export default function PartnerIntro() {
|
||||
</Swiper>
|
||||
</div>
|
||||
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>
|
||||
群主认证
|
||||
<div className={`${PREFIX}__recommend`}>
|
||||
<GoodJob />
|
||||
强烈推荐
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__card ${PREFIX}__special`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div className="center">
|
||||
完成群主认证后,群成员通过该群访问任何人分享的播络小程序进行注册,你都能获得分成
|
||||
</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__service`} onClick={handleConfirm}>
|
||||
立即认证
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>3重收益</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
@ -209,34 +139,17 @@ export default function PartnerIntro() {
|
||||
<div className={`${PREFIX}__title`}>邀请方法</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div>1.点击下方“赠送会员给好友”,给群员、好友送会员,每周可以送一次</div>
|
||||
<div>2.分享通告列表页、通告详情页等页面至群、好友</div>
|
||||
<div className={`${PREFIX}__h1`}>方法一:</div>
|
||||
<div>点击下方“赠送会员给好友”,给群员、好友送会员,每周可以送一次</div>
|
||||
<div className={`${PREFIX}__h1`}>方法二:</div>
|
||||
<div>分享通告列表页、通告详情页等页面至群、好友</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>
|
||||
群主认证
|
||||
<div className={`${PREFIX}__recommend`}>
|
||||
<GoodJob />
|
||||
强烈认证
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__card ${PREFIX}__special`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div className="center">
|
||||
完成群主认证后,群成员通过该群访问任何人分享的播络小程序进行注册,你都能获得分成
|
||||
</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__service`} onClick={handleConfirm}>
|
||||
立即认证
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>交流群</div>
|
||||
<div className={`${PREFIX}__card ${PREFIX}__special`}>
|
||||
<div className={`${PREFIX}__h1`}>加入播络合伙人交流群,分享经验</div>
|
||||
<div className={`${PREFIX}__h1 no-dot`}>加入播络合伙人交流群,分享经验</div>
|
||||
<Button className={`${PREFIX}__service`} onClick={handleOpenService}>
|
||||
点击加入
|
||||
</Button>
|
||||
@ -246,10 +159,7 @@ export default function PartnerIntro() {
|
||||
<Canvas id="posterCanvas" canvas-id="posterCanvas" type="2d" style="width: 750px; height: 1334px;" />
|
||||
|
||||
<div className={`${PREFIX}__footer`}>
|
||||
<Button className={`${PREFIX}__download-button`} onClick={savePoster}>
|
||||
朋友圈海报
|
||||
</Button>
|
||||
<Button className={`${PREFIX}__share-button`} openType="share">
|
||||
<Button className={`${PREFIX}__share-button`} onClick={handleJump}>
|
||||
赠送会员给好友
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,8 @@ import Taro from '@tarojs/taro';
|
||||
import { Search } from '@taroify/core';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST, GROUP_CITY_INDEXES_LIST } from '@/constants/city';
|
||||
import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST } from '@/constants/city';
|
||||
import useCityOperators from '@/hooks/use-city-operators';
|
||||
import { logWithPrefix } from '@/utils/common';
|
||||
|
||||
import './index.less';
|
||||
@ -68,8 +69,17 @@ export default function SearchCity({
|
||||
const [touchAnchor, setTouchAnchor] = useState<string | undefined>();
|
||||
const [touchMoving, setTouchMoving] = useState(false);
|
||||
const [searchResult, setSearchResult] = useState<Item[]>([]);
|
||||
const cityOperators = useCityOperators();
|
||||
const groupCityCodes = cityOperators.map(it => (it.groupLink ? it.cityCode : null)).filter(Boolean);
|
||||
const showSearchList = searchResult.length > 0;
|
||||
const CITY_LIST = forGroup ? GROUP_CITY_INDEXES_LIST : CITY_INDEXES_LIST;
|
||||
const CITY_LIST = forGroup
|
||||
? CITY_INDEXES_LIST.map(({ letter, data }) => {
|
||||
return {
|
||||
letter,
|
||||
data: data.filter(it => groupCityCodes.includes(it.cityCode)),
|
||||
};
|
||||
}).filter(item => item.data.length > 0)
|
||||
: CITY_INDEXES_LIST;
|
||||
|
||||
const handleSearchChange = useCallback((event: BaseEventOrig<InputProps.inputEventDetail>) => {
|
||||
const value = event.detail.value;
|
||||
|
||||
@ -79,6 +79,7 @@ export enum PageUrl {
|
||||
GroupDelegatePublish = 'pages/group-delegate-publish/index',
|
||||
GiveVip = 'pages/give-vip/index',
|
||||
GroupOwnerCertificate = 'pages/group-owner-certification/index',
|
||||
PartnerShareVip = 'pages/partner-share-vip/index',
|
||||
}
|
||||
|
||||
export enum PluginUrl {
|
||||
|
||||
10
src/hooks/use-city-operators.tsx
Normal file
10
src/hooks/use-city-operators.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { selectCityOperators } from '@/store/selector';
|
||||
|
||||
function useCityOperators() {
|
||||
const data = useSelector(selectCityOperators);
|
||||
return data || [];
|
||||
}
|
||||
|
||||
export default useCityOperators;
|
||||
@ -100,6 +100,7 @@ export const APP_CONFIG: AppConfigType = {
|
||||
PageUrl.GroupDelegatePublish,
|
||||
PageUrl.GiveVip,
|
||||
PageUrl.GroupOwnerCertificate,
|
||||
PageUrl.PartnerShareVip,
|
||||
// PageUrl.DevDebug,
|
||||
],
|
||||
window: {
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { selectServiceUrls } from '@/store/selector';
|
||||
|
||||
function useServiceUrls() {
|
||||
const data = useSelector(selectServiceUrls);
|
||||
return data || [];
|
||||
}
|
||||
|
||||
export default useServiceUrls;
|
||||
@ -291,7 +291,7 @@ export default function AnchorPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__banner`}>
|
||||
<PartnerBanner />
|
||||
<PartnerBanner isBoss />
|
||||
</div>
|
||||
<ListWrapper
|
||||
filters={filters}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-top: 48px;
|
||||
padding-bottom: calc(48px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(48px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
&__block {
|
||||
@ -50,7 +52,6 @@
|
||||
|
||||
.highlight {
|
||||
color: @blHighlightColor;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
&.center {
|
||||
@ -122,6 +123,7 @@
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
background: #6F7686;
|
||||
display: block;
|
||||
margin: auto auto 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export default function GroupOwnerCertification() {
|
||||
const { authCode } = await generateGroupAuthCode();
|
||||
return getCommonShareMessage({
|
||||
useCapture: false,
|
||||
title: `群主测试,${authCode}`,
|
||||
title: `群主测试 ${authCode}`,
|
||||
inviteCode,
|
||||
params: { authCode },
|
||||
path: PageUrl.GroupOwnerCertificate,
|
||||
@ -98,14 +98,21 @@ export default function GroupOwnerCertification() {
|
||||
<div className={`${PREFIX}__lined-wrapper`}>
|
||||
<div className={`${PREFIX}__lined-title`}>长按并识别二维码添加运营</div>
|
||||
</div>
|
||||
{staffInfo && <Image className={`${PREFIX}__qrcode`} src={staffInfo.staffQrCode} mode="aspectFill" />}
|
||||
{staffInfo && (
|
||||
<Image
|
||||
className={`${PREFIX}__qrcode`}
|
||||
src={staffInfo.staffQrCode}
|
||||
showMenuByLongpress
|
||||
mode="aspectFill"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className={`${PREFIX}__title`}>第二步</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
<div className={`${PREFIX}__h1 ${PREFIX}__bold`}>点击以下按钮分享小程序到群,并在群里打开小程序</div>
|
||||
<div className={`${PREFIX}__body center`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div className="highlight">1次分享只能认证一个群,有多个群请分享多次,不可在微信聊天里直接转发;</div>
|
||||
一般1天内完成,超时未完成认证请重新分享或者咨询运营
|
||||
<div>一般1天内完成,超时未完成认证请重新分享或者咨询运营</div>
|
||||
</div>
|
||||
<Button className={`${PREFIX}__share`} openType="share">
|
||||
分享小程序
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import Taro, { useLoad, useShareAppMessage } from '@tarojs/taro';
|
||||
import { useLoad, useShareAppMessage } from '@tarojs/taro';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import HomePage from '@/components/home-page';
|
||||
import SearchCity from '@/components/search-city';
|
||||
import { PageType, PageUrl, RoleType } from '@/constants/app';
|
||||
import useCityOperators from '@/hooks/use-city-operators';
|
||||
import useInviteCode from '@/hooks/use-invite-code';
|
||||
import useServiceUrls from '@/hooks/use-service-urls';
|
||||
import { switchRoleType } from '@/utils/app';
|
||||
import { openCustomerServiceChat } from '@/utils/common';
|
||||
import { getCurrentCityCode } from '@/utils/location';
|
||||
@ -20,7 +20,7 @@ const PREFIX = 'group-v2-page';
|
||||
|
||||
export default function GroupV2() {
|
||||
const inviteCode = useInviteCode();
|
||||
const serviceUrls = useServiceUrls();
|
||||
const cityOperators = useCityOperators();
|
||||
|
||||
useLoad(() => {
|
||||
switchRoleType(RoleType.Anchor);
|
||||
@ -29,10 +29,6 @@ export default function GroupV2() {
|
||||
getInviteCodeFromQueryAndUpdate(query);
|
||||
});
|
||||
|
||||
Taro.showShareMenu({
|
||||
withShareTicket: true,
|
||||
});
|
||||
|
||||
useShareAppMessage(() =>
|
||||
getCommonShareMessage({ inviteCode, title: '邀请你加入本地主播求职招聘群', path: PageUrl.GroupV2 })
|
||||
);
|
||||
@ -42,12 +38,12 @@ export default function GroupV2() {
|
||||
if (!checkCityCode(cityCode)) {
|
||||
return;
|
||||
}
|
||||
const group = serviceUrls.find(g => String(g.cityCode) === cityCode);
|
||||
const group = cityOperators.find(g => String(g.cityCode) === cityCode);
|
||||
if (group) {
|
||||
openCustomerServiceChat(group.serviceUrl);
|
||||
openCustomerServiceChat(group.groupLink);
|
||||
}
|
||||
},
|
||||
[serviceUrls]
|
||||
[cityOperators]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -23,5 +23,9 @@
|
||||
background-color: @blTabLineColor;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.taroify-dialog.taroify-popup {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import MaterialManagePopup from '@/components/material-manage-popup';
|
||||
import PageLoading from '@/components/page-loading';
|
||||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
||||
import { EventName, RoleType } from '@/constants/app';
|
||||
import { EventName } from '@/constants/app';
|
||||
import { CollectEventName } from '@/constants/event';
|
||||
import { MaterialStatus } from '@/constants/material';
|
||||
import ProfileViewFragment from '@/fragments/profile/view';
|
||||
@ -15,9 +15,7 @@ import { collectEvent } from '@/utils/event';
|
||||
import { getMaterialShareMessage, requestProfileDetail, updateProfileStatus } from '@/utils/material';
|
||||
import { getCommonShareMessage } from '@/utils/share';
|
||||
import Toast from '@/utils/toast';
|
||||
|
||||
import './index.less';
|
||||
import { switchRoleType } from '@/utils/app';
|
||||
|
||||
const PREFIX = 'page-material-profile';
|
||||
|
||||
@ -69,10 +67,6 @@ export default function MaterialProfilePage() {
|
||||
}
|
||||
});
|
||||
|
||||
Taro.showShareMenu({
|
||||
withShareTicket: true,
|
||||
});
|
||||
|
||||
useShareAppMessage(async () => {
|
||||
const shareMessage = await getMaterialShareMessage(profile, false);
|
||||
return shareMessage || getCommonShareMessage({ useCapture: false });
|
||||
|
||||
3
src/pages/partner-share-vip/index.config.ts
Normal file
3
src/pages/partner-share-vip/index.config.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '赠送会员',
|
||||
});
|
||||
182
src/pages/partner-share-vip/index.less
Normal file
182
src/pages/partner-share-vip/index.less
Normal file
@ -0,0 +1,182 @@
|
||||
@import '@/styles/variables.less';
|
||||
@import '@/styles/common.less';
|
||||
|
||||
.share-vip {
|
||||
background: #eae5fb;
|
||||
padding-top: 200px;
|
||||
position: relative;
|
||||
padding-bottom: calc(142px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(142px + env(safe-area-inset-bottom));
|
||||
|
||||
&__bg {
|
||||
width: 100%;
|
||||
height: 705px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&__slogan {
|
||||
top: 66px;
|
||||
left: 44px;
|
||||
position: absolute;
|
||||
font-family: 'Alimama ShuHeiTi';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 44px;
|
||||
line-height: 62px;
|
||||
color: #333333;
|
||||
|
||||
> div {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
&-highlight {
|
||||
display: inline-block;
|
||||
padding-left: 12px;
|
||||
padding-right: 9px;
|
||||
font-size: 64px;
|
||||
line-height: 62px;
|
||||
background: linear-gradient(87.53deg, #683DE3 0.4%, #39227D 84.55%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-fill-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&__main {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&__highlight {
|
||||
color: @blHighlightColor;
|
||||
font-family: 'DIN Alternate';
|
||||
padding: 0 8px;
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
&__block {
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__card {
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
padding: 68px 32px 44px;
|
||||
}
|
||||
|
||||
&__h1 {
|
||||
font-weight: 500;
|
||||
font-size: 32px;
|
||||
line-height: 40px;
|
||||
color: #1d2129;
|
||||
margin-bottom: 16px;
|
||||
margin-top: 32px;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #ffd236;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: -3px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
color: @blColor;
|
||||
|
||||
&.grey {
|
||||
color: @blColorG2;
|
||||
}
|
||||
|
||||
&.center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-left: 48px;
|
||||
margin-right: 48px;
|
||||
font-weight: 500;
|
||||
font-size: 32px;
|
||||
line-height: 80px;
|
||||
height: 80px;
|
||||
transform: translateY(50%);
|
||||
background: #ffd236;
|
||||
box-shadow: 0px 12px 0px #ffa35d;
|
||||
border-radius: 60px;
|
||||
color: #1d2129;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__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;
|
||||
z-index: 2;
|
||||
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;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__download-button {
|
||||
flex: 1 1;
|
||||
.button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px; @highlight: 0);
|
||||
}
|
||||
|
||||
&__share-button {
|
||||
flex: 2 2;
|
||||
width: 406px;
|
||||
.button(@height: 88px; @fontSize: 32px; @fontWeight: 500; @borderRadius: 44px;);
|
||||
margin-left: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
#posterCanvas {
|
||||
position: fixed;
|
||||
bottom: -99999px;
|
||||
left: -99999px;
|
||||
visibility: hidden;
|
||||
}
|
||||
191
src/pages/partner-share-vip/index.tsx
Normal file
191
src/pages/partner-share-vip/index.tsx
Normal file
@ -0,0 +1,191 @@
|
||||
import { Button, Canvas, Image } from '@tarojs/components';
|
||||
import Taro, { useShareAppMessage } from '@tarojs/taro';
|
||||
|
||||
import { PageUrl } from '@/constants/app';
|
||||
import useInviteCode from '@/hooks/use-invite-code';
|
||||
import { generateMembershipCoupon, getCouponQrCode } from '@/utils/coupon';
|
||||
import { getCommonShareMessage } from '@/utils/share';
|
||||
|
||||
import './index.less';
|
||||
|
||||
const PREFIX = 'share-vip';
|
||||
|
||||
export default function PartnerShareVip() {
|
||||
const inviteCode = useInviteCode();
|
||||
|
||||
Taro.showShareMenu({
|
||||
withShareTicket: true,
|
||||
});
|
||||
|
||||
useShareAppMessage(async () => {
|
||||
console.log('Partner inviteCode', inviteCode);
|
||||
const { code } = await generateMembershipCoupon();
|
||||
return getCommonShareMessage({
|
||||
useCapture: false,
|
||||
inviteCode,
|
||||
title: '宝子,送你个播络会员,免费找主播工作',
|
||||
path: PageUrl.GiveVip,
|
||||
params: { d: code },
|
||||
imageUrl: 'https://publiccdn.neighbourhood.com.cn/img/share-coupon1.png',
|
||||
});
|
||||
});
|
||||
|
||||
const getQrcode = async () => {
|
||||
try {
|
||||
const { code } = await generateMembershipCoupon();
|
||||
const data = await getCouponQrCode(code);
|
||||
const base64 = Taro.arrayBufferToBase64(data);
|
||||
return `data:image/png;base64,${base64}`;
|
||||
} catch (error) {
|
||||
console.error('获取二维码失败', error);
|
||||
Taro.showToast({ title: '获取二维码失败', icon: 'none' });
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
const saveCanvasToTempFile = (): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const query = Taro.createSelectorQuery().select('#posterCanvas');
|
||||
query.fields({ node: true }).exec(async res => {
|
||||
const canvas = res[0].node;
|
||||
const tempFilePath = await Taro.canvasToTempFilePath({
|
||||
canvas,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1500, // 实际绘制宽度
|
||||
height: 2668, // 实际绘制高度
|
||||
destWidth: 750, // 目标显示宽度
|
||||
destHeight: 1334, // 目标显示高度
|
||||
fileType: 'png',
|
||||
});
|
||||
|
||||
resolve(tempFilePath.tempFilePath);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('保存 Canvas 到临时文件失败', error);
|
||||
Taro.showToast({ title: '保存 Canvas 失败', icon: 'none' });
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
const drawCanvas = (qrCode: string): Promise<string> => {
|
||||
const query = Taro.createSelectorQuery().select('#posterCanvas');
|
||||
return new Promise(resolve => {
|
||||
query.fields({ node: true, size: true }).exec(async res => {
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
canvas.width = 550 * 2;
|
||||
canvas.height = 918 * 2;
|
||||
ctx.scale(2, 2);
|
||||
|
||||
// 绘制背景图片
|
||||
const bgImage = canvas.createImage();
|
||||
const poster = 'https://publiccdn.neighbourhood.com.cn/img/share-coupon-poster2.png';
|
||||
bgImage.src = poster;
|
||||
bgImage.onload = () => {
|
||||
ctx.drawImage(bgImage, 0, 0, 550, 918);
|
||||
|
||||
const qrCodeImage = canvas.createImage();
|
||||
qrCodeImage.src = qrCode; // 假设 getQrcode() 返回的是二维码图片的路径
|
||||
qrCodeImage.onload = () => {
|
||||
ctx.drawImage(qrCodeImage, 196, 600, 180, 160); // 绘制二维码,位置和大小
|
||||
saveCanvasToTempFile().then(tempPath => {
|
||||
resolve(tempPath);
|
||||
});
|
||||
};
|
||||
};
|
||||
bgImage.onerror = err => {
|
||||
console.error(err);
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
const savePoster = async () => {
|
||||
Taro.showLoading({ title: '正在生成海报' });
|
||||
const qrCode = await getQrcode();
|
||||
const filePath = await drawCanvas(qrCode);
|
||||
Taro.hideLoading();
|
||||
|
||||
const res = await Taro.getSetting();
|
||||
const hasPermission = res.authSetting['scope.writePhotosAlbum'];
|
||||
if (hasPermission === false) {
|
||||
Taro.showModal({
|
||||
title: '提示',
|
||||
content: '需要访问相册权限才能保存图片,请前往设置开启权限',
|
||||
showCancel: false,
|
||||
success() {
|
||||
Taro.openSetting();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
await Taro.authorize({ scope: 'scope.writePhotosAlbum' });
|
||||
await Taro.saveImageToPhotosAlbum({ filePath });
|
||||
Taro.showToast({ title: '保存成功', icon: 'success' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Taro.showToast({ title: '保存失败', icon: 'none' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={PREFIX}>
|
||||
<Image
|
||||
src="https://publiccdn.neighbourhood.com.cn/img/partner-share-vip-bg.png"
|
||||
className={`${PREFIX}__bg`}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<div className={`${PREFIX}__slogan`}>
|
||||
<div>
|
||||
会员可每日<div className={`${PREFIX}__slogan-highlight`}>免费查看</div>
|
||||
</div>
|
||||
<div>通告联系方式</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__main`}>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>赠送会员</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
<div className={`${PREFIX}__h1`}>方法一:</div>
|
||||
<div className={`${PREFIX}__body`}>点击下方"立即赠送"即可分享赠送卡片,对方点击卡片即可领取</div>
|
||||
<div className={`${PREFIX}__h1`}>方法二:</div>
|
||||
<div className={`${PREFIX}__body`}>点击"朋友圈海报"获得图片,分享到朋友圈,对方扫码即可领取</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>赠送规则</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div className={`${PREFIX}__h1`}>规则一:</div>
|
||||
<div>每次分享的赠送链接或者图片在7天内有效</div>
|
||||
<div className={`${PREFIX}__h1`}>规则二:</div>
|
||||
<div>每个用户一周最多只能领取一次会员</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${PREFIX}__block`}>
|
||||
<div className={`${PREFIX}__title`}>分享建议</div>
|
||||
<div className={`${PREFIX}__card`}>
|
||||
<div className={`${PREFIX}__body`}>
|
||||
<div className={`${PREFIX}__h1`}>建议一:</div>
|
||||
<div>每周在朋友圈或者群中分享一次,效果最佳 可以写明:新会员来啦</div>
|
||||
<div className={`${PREFIX}__h1`}>建议二:</div>
|
||||
<div>分享得越多,邀请的人会越多,也会更活跃,更容易获得分成</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Canvas id="posterCanvas" canvas-id="posterCanvas" type="2d" style="width: 750px; height: 1334px;" />
|
||||
|
||||
<div className={`${PREFIX}__footer`}>
|
||||
<Button className={`${PREFIX}__download-button`} onClick={savePoster}>
|
||||
朋友圈海报
|
||||
</Button>
|
||||
<Button className={`${PREFIX}__share-button`} openType="share">
|
||||
立即赠送
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -8,7 +8,6 @@ import PartnerInviteList from '@/components/partner-invite-list';
|
||||
import PartnerProfit from '@/components/partner-profit';
|
||||
import { PageUrl } from '@/constants/app';
|
||||
import useInviteCode from '@/hooks/use-invite-code';
|
||||
import { generateMembershipCoupon } from '@/utils/coupon';
|
||||
import { getCommonShareMessage } from '@/utils/share';
|
||||
import './index.less';
|
||||
|
||||
@ -27,14 +26,21 @@ export default function Partner() {
|
||||
|
||||
useShareAppMessage(async () => {
|
||||
console.log('Partner inviteCode', inviteCode);
|
||||
const { code } = await generateMembershipCoupon();
|
||||
// const { code } = await generateMembershipCoupon();
|
||||
// return getCommonShareMessage({
|
||||
// useCapture: false,
|
||||
// inviteCode,
|
||||
// title: '宝子,送你个播络会员,免费找主播工作',
|
||||
// path: PageUrl.GiveVip,
|
||||
// params: { d: code },
|
||||
// imageUrl: 'https://publiccdn.neighbourhood.com.cn/img/share-coupon1.png',
|
||||
// });
|
||||
return getCommonShareMessage({
|
||||
useCapture: false,
|
||||
inviteCode,
|
||||
title: '宝子,送你个播络会员,免费找主播工作',
|
||||
path: PageUrl.GiveVip,
|
||||
params: { d: code },
|
||||
imageUrl: 'https://publiccdn.neighbourhood.com.cn/img/share-coupon1.png',
|
||||
title: '播络专业主播招聘平台招募合伙人',
|
||||
path: PageUrl.Partner,
|
||||
imageUrl: 'https://publiccdn.neighbourhood.com.cn/img/share-partner.png',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ import { useCallback, useState } from 'react';
|
||||
import HomePage from '@/components/home-page';
|
||||
import SearchCity from '@/components/search-city';
|
||||
import { PageType, PageUrl, RoleType } from '@/constants/app';
|
||||
import useCityOperators from '@/hooks/use-city-operators';
|
||||
import useInviteCode from '@/hooks/use-invite-code';
|
||||
import useServiceUrls from '@/hooks/use-service-urls';
|
||||
import { switchRoleType } from '@/utils/app';
|
||||
import { openCustomerServiceChat } from '@/utils/common';
|
||||
import { getCurrentCityCode } from '@/utils/location';
|
||||
@ -23,7 +23,7 @@ const EXAMPLE_IMAGE = 'https://publiccdn.neighbourhood.com.cn/img/delegate-examp
|
||||
const COMMENT_IMAGE = 'https://publiccdn.neighbourhood.com.cn/img/delegate-comments.png';
|
||||
export default function BizService() {
|
||||
const inviteCode = useInviteCode();
|
||||
const serviceUrls = useServiceUrls();
|
||||
const cityOperators = useCityOperators();
|
||||
const [value, setValue] = useState('0');
|
||||
|
||||
const handleClickDelegate = useCallback(() => {
|
||||
@ -43,12 +43,12 @@ export default function BizService() {
|
||||
if (!checkCityCode(cityCode)) {
|
||||
return;
|
||||
}
|
||||
const group = serviceUrls.find(g => String(g.cityCode) === cityCode);
|
||||
const group = cityOperators.find(g => String(g.cityCode) === cityCode);
|
||||
if (group) {
|
||||
openCustomerServiceChat(group.serviceUrl);
|
||||
openCustomerServiceChat(group.groupLink);
|
||||
}
|
||||
},
|
||||
[serviceUrls]
|
||||
[cityOperators]
|
||||
);
|
||||
const handleChange = useCallback(v => {
|
||||
setValue(v);
|
||||
|
||||
@ -69,19 +69,23 @@
|
||||
}
|
||||
|
||||
&__header__contact {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: #0000004D;
|
||||
width: 76px;
|
||||
height: 81px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
&:after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__header__contact-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
width: 76px;
|
||||
height: 81px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Button, Image } from '@tarojs/components';
|
||||
import Taro, { useShareAppMessage } from '@tarojs/taro';
|
||||
import { useShareAppMessage } from '@tarojs/taro';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@ -38,10 +38,6 @@ export default function User() {
|
||||
[]
|
||||
);
|
||||
|
||||
Taro.showShareMenu({
|
||||
withShareTicket: true,
|
||||
});
|
||||
|
||||
useShareAppMessage(() => getCommonShareMessage({ useCapture: false }));
|
||||
|
||||
return (
|
||||
@ -69,7 +65,7 @@ export default function User() {
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
className={`${PREFIX}__header__contact-icon`}
|
||||
src={require('@/statics/svg/contact.svg')}
|
||||
src="https://publiccdn.neighbourhood.com.cn/img/kefu.svg"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@ -10,4 +10,4 @@ export const changeHomePage = (value: PageType) => ({ type: CHANGE_HOME_PAGE, va
|
||||
|
||||
export const setLocationInfo = (value: LocationInfo) => ({ type: SET_LOCATION_INFO, value });
|
||||
|
||||
export const setServiceUrls = (value: AppState['serviceUrls']) => ({ type: SET_SERVICE_URLS, value });
|
||||
export const setCityOperators = (value: AppState['cityOperators']) => ({ type: SET_SERVICE_URLS, value });
|
||||
|
||||
@ -23,7 +23,7 @@ const INIT_STATE: AppState = {
|
||||
roleType: defaultAppMode,
|
||||
homePageType: defaultAppMode === RoleType.Company ? PageType.Anchor : PageType.JOB,
|
||||
location: Taro.getStorageSync<LocationInfo>(CacheKey.CACHE_LOCATION_INFO) || DEFAULT_LOCATION,
|
||||
serviceUrls: [],
|
||||
cityOperators: [],
|
||||
};
|
||||
|
||||
const appState = (state: AppState = INIT_STATE, action: Action): AppState => {
|
||||
@ -35,7 +35,7 @@ const appState = (state: AppState = INIT_STATE, action: Action): AppState => {
|
||||
case CHANGE_HOME_PAGE:
|
||||
return { ...state, homePageType: value };
|
||||
case SET_SERVICE_URLS:
|
||||
return { ...state, serviceUrls: value };
|
||||
return { ...state, cityOperators: value };
|
||||
case SET_LOCATION_INFO:
|
||||
Taro.setStorageSync(CacheKey.CACHE_LOCATION_INFO, value);
|
||||
return { ...state, location: value };
|
||||
|
||||
@ -6,4 +6,4 @@ export const selectHomePageType = (state: IState) => state.appState.homePageType
|
||||
|
||||
export const selectLocation = (state: IState) => state.appState.location;
|
||||
|
||||
export const selectServiceUrls = (state: IState) => state.appState.serviceUrls || {};
|
||||
export const selectCityOperators = (state: IState) => state.appState.cityOperators || {};
|
||||
|
||||
@ -17,9 +17,8 @@ export interface AppState {
|
||||
roleType: RoleType;
|
||||
homePageType: PageType;
|
||||
location: LocationInfo;
|
||||
serviceUrls: Array<{
|
||||
title: string;
|
||||
cityCode: number;
|
||||
serviceUrl: string;
|
||||
cityOperators: Array<{
|
||||
cityCode: string;
|
||||
groupLink: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import { CITY_CODE_TO_NAME_MAP, COUNTY_CODE_TO_NAME_MAP, PROVINCE_CODE_TO_NAME_M
|
||||
import http from '@/http';
|
||||
import { API } from '@/http/api';
|
||||
import store from '@/store';
|
||||
import { setLocationInfo, setServiceUrls } from '@/store/actions';
|
||||
import { setLocationInfo, setCityOperators } from '@/store/actions';
|
||||
import { selectLocation } from '@/store/selector';
|
||||
import { CityOperatorListItem, GetCityCodeRequest, LocationInfo } from '@/types/location';
|
||||
|
||||
@ -135,14 +135,13 @@ export async function requestLocation(force: boolean = false) {
|
||||
return location;
|
||||
}
|
||||
|
||||
export async function requestServiceUrls() {
|
||||
const list = await http.post<CityOperatorListItem[]>(API.GET_ALL_CITY_OPERATOR);
|
||||
export async function requestCityOperators() {
|
||||
const list = await http.get<CityOperatorListItem[]>(API.GET_ALL_CITY_OPERATOR);
|
||||
store.dispatch(
|
||||
setServiceUrls(
|
||||
setCityOperators(
|
||||
(list || []).map(it => ({
|
||||
title: `【${it.cityName}】`,
|
||||
cityCode: Number(it.cityCode),
|
||||
serviceUrl: it.groupLink,
|
||||
cityCode: it.cityCode,
|
||||
groupLink: it.groupLink,
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
||||
@ -21,8 +21,8 @@ import {
|
||||
WithdrawRecord,
|
||||
WithdrawResponse,
|
||||
} from '@/types/partner';
|
||||
import { requestUserInfo } from '@/utils/user';
|
||||
import { buildUrl } from '@/utils/common';
|
||||
import { requestUserInfo } from '@/utils/user';
|
||||
|
||||
export const getInviteCodeFromQuery = (query: Record<string, string>): string | undefined => {
|
||||
if (query) {
|
||||
@ -134,7 +134,9 @@ export async function getWithdrawList(data: IPaginationRequest) {
|
||||
});
|
||||
}
|
||||
export async function getLastProfitList() {
|
||||
const result = await http.get<UserProfitListItem[]>(API.GET_PROFIT_LIST);
|
||||
const result = await http.get<UserProfitListItem[]>(API.GET_USER_PROFIT_LIST, {
|
||||
contentType: 'application/x-www-form-urlencoded',
|
||||
});
|
||||
return Array.isArray(result) ? result : [];
|
||||
}
|
||||
|
||||
@ -151,6 +153,6 @@ export async function decryptOpenGid(data: DecryptOpenGidBody) {
|
||||
});
|
||||
}
|
||||
export async function getStaffInfo(cityCode: string) {
|
||||
const result = await http.post<StaffInfo[]>(buildUrl(API.GET_STAFF_CODE, { cityCode }));
|
||||
const result = await http.get<StaffInfo[]>(buildUrl(API.GET_STAFF_CODE, { cityCode }));
|
||||
return Array.isArray(result) && result.length ? result[0] : null;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ export const getUserId = () => getUserInfo().userId;
|
||||
export const isValidUserInfo = (info: UserInfo) => !!info.userId;
|
||||
|
||||
export const isNeedLogin = (info: UserInfo) => !info.isBindPhone;
|
||||
// export const isNeedLogin = (info: UserInfo) => !info.isBindPhone || info.userId === '534740874077898752';
|
||||
// export const isNeedLogin = (info: UserInfo) => !info.isBindPhone || info.userId === '218396277145075712';
|
||||
|
||||
export const isNeedPhone = (info: UserInfo) => isNeedLogin(info) || !info.phone;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user