This commit is contained in:
chashaobao
2025-08-31 22:43:00 +08:00
parent 61686950bd
commit aea8323d95
7 changed files with 122 additions and 49 deletions

View File

@ -1,19 +1,19 @@
import { Button, Canvas } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useCallback, useState } from 'react';
import { useCallback } from 'react';
import { openCustomerServiceChat } from '@/utils/common';
import { getPartnerQrcode } from '@/utils/partner';
import { getCouponQrCode, generateMembershipCoupon } from '@/utils/coupon';
import './index.less';
const PREFIX = 'partner-intro';
export default function PartnerIntro() {
const [posterPath, setPosterPath] = useState('');
const getQrcode = async () => {
try {
const data = await getPartnerQrcode(); // 假设 getPartnerQrcode 返回 ArrayBuffer
const { code } = await generateMembershipCoupon();
const data = await getCouponQrCode(code);
const base64 = Taro.arrayBufferToBase64(data);
return `data:image/png;base64,${base64}`;
} catch (error) {
@ -39,8 +39,6 @@ export default function PartnerIntro() {
fileType: 'jpg',
});
setPosterPath(tempFilePath.tempFilePath);
resolve(tempFilePath.tempFilePath);
});
} catch (error) {
@ -84,13 +82,10 @@ export default function PartnerIntro() {
});
};
const savePoster = async () => {
let filePath = posterPath;
if (!filePath) {
Taro.showLoading({ title: '正在生成海报' });
const qrCode = await getQrcode();
filePath = await drawCanvas(qrCode);
const filePath = await drawCanvas(qrCode);
Taro.hideLoading();
}
const res = await Taro.getSetting();
const hasPermission = res.authSetting['scope.writePhotosAlbum'];

View File

@ -1,4 +1,4 @@
// export const DOMAIN = 'http://192.168.60.191:8082';
// export const DOMAIN = 'http://192.168.60.116:8082';
export const DOMAIN = process.env.BRAND === 'dev' ? 'https://dev.neighbourhood.cn' : 'https://neighbourhood.cn';
// export const DOMAIN = 'https://dev.neighbourhood.cn';
export const BASE_URL = `${DOMAIN}/api`;
@ -85,4 +85,7 @@ export enum API {
GET_PROFIT_STAT = '/user/profits',
WITHDRAW = '/user/withdraw',
GET_WITHDRAW_LIST = '/user/withdraw/records',
GENERATE_MEMBERSHIP_COUPON = '/coupon/membership/generate',
CLAIM_MEMBERSHIP_COUPON = '/coupon/membership/claim',
GET_VIP_QRCODE = '/user/getVipQrCode',
}

View File

@ -1,23 +1,48 @@
import { Image, Button } from '@tarojs/components';
import { useLoad } from '@tarojs/taro';
import { Fragment, useCallback } from 'react';
import { Fragment, useCallback, useState } from 'react';
import SafeBottomPadding from '@/components/safe-bottom-padding';
import { PageUrl } from '@/constants/app';
import { logWithPrefix } from '@/utils/common';
import { switchTab } from '@/utils/route';
import { claimMembershipCoupon, getCouponCodeFromQuery } from '@/utils/coupon';
import { getPageQuery, switchTab } from '@/utils/route';
import { formatTime } from '@/utils/time';
import './index.less';
const PREFIX = 'give-vip';
const log = logWithPrefix(PREFIX);
enum State {
PENDING,
SUCCESS,
FAILED,
}
export default function GiveVip() {
const [state, setState] = useState<State>(State.PENDING);
const [expireAt, setExpireAt] = useState('');
const handleNavigate = useCallback(() => {
switchTab(PageUrl.Job);
}, []);
useLoad(() => {
const query = getPageQuery<{ d: string }>();
const code = getCouponCodeFromQuery(query);
claimMembershipCoupon(code!)
.then(res => {
setExpireAt(res.usageExpireAt);
setState(Date.now() > new Date(res.usageExpireAt).getTime() ? State.FAILED : State.SUCCESS);
})
.catch(err => {
console.error(err);
setState(State.FAILED);
});
});
return (
<div className={PREFIX}>
{state === State.SUCCESS && (
<Fragment>
<div className={`${PREFIX}__title`}>
<Image src="https://publiccdn.neighbourhood.com.cn/img/partner-yes.svg" className={`${PREFIX}__icon`} />
@ -29,9 +54,13 @@ export default function GiveVip() {
<div className={`${PREFIX}__coupon-intro`}>
<div className="highlight">10</div>
</div>
<div className={`${PREFIX}__coupon-valid`}>2025/8/26 22:23:56</div>
<div className={`${PREFIX}__coupon-valid`}>
{formatTime(expireAt, 'YYYY/MM/DD HH:mm:ss', false)}
</div>
</div>
</Fragment>
)}
{state === State.FAILED && (
<Fragment>
<div className={`${PREFIX}__hint`}>
<Image
@ -45,6 +74,7 @@ export default function GiveVip() {
<div className="highlight"></div>
</div>
</Fragment>
)}
<div className={`${PREFIX}__info-block`}>
<div className={`${PREFIX}__info-title`}></div>
<div className={`${PREFIX}__info-card`}>

View File

@ -8,10 +8,10 @@ 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';
const PREFIX = 'partner';
export default function Partner() {
@ -20,13 +20,15 @@ export default function Partner() {
const handleChange = v => {
setTab(v);
};
useShareAppMessage(() => {
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-coupon.png',
});
});

10
src/types/coupon.ts Normal file
View File

@ -0,0 +1,10 @@
export type ClaimMembershipCouponResponse = {
code: string;
usageExpireAt: string;
};
export type GenerateMembershipCouponResponse = {
code: string;
linkExpireAt: string;
shareUrl: string;
};

31
src/utils/coupon.ts Normal file
View File

@ -0,0 +1,31 @@
import http from '@/http';
import { API } from '@/http/api';
import { ClaimMembershipCouponResponse, GenerateMembershipCouponResponse } from '@/types/coupon';
export const generateMembershipCoupon = async () => {
return await http.post<GenerateMembershipCouponResponse>(API.GENERATE_MEMBERSHIP_COUPON);
};
export const claimMembershipCoupon = async (code: string) => {
return await http.post<ClaimMembershipCouponResponse>(API.CLAIM_MEMBERSHIP_COUPON, {
contentType: 'application/x-www-form-urlencoded',
data: { code },
});
};
export const getCouponQrCode = async (code: string) => {
return await http.post(API.GET_VIP_QRCODE, {
contentType: 'application/x-www-form-urlencoded',
responseType: 'arraybuffer',
data: { code },
});
};
export const getCouponCodeFromQuery = (query: Record<string, string>): string | undefined => {
if (query) {
if (query.scene) {
return query.scene.replace('d%3D', '');
}
if (query.d) {
return query.d;
}
}
return undefined;
};

View File

@ -1,10 +1,12 @@
import dayjs from 'dayjs';
export function formatTime(time: number | string, template = 'YYYY-MM-DD'): string {
export function formatTime(time: number | string, template = 'YYYY-MM-DD', toNum = true): string {
if (!time) {
return '';
}
if (toNum) {
time = Number(time);
}
return dayjs(time).format(template);
}