9c8d5f2cad
订单佣金只认关联用户;合伙人备注写入独立表;H5 增加用户管理与首页统计。 Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.5 KiB
TypeScript
97 lines
3.5 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import PageHeader from '@dukang/shared-ui/PageHeader';
|
|
import type { PartnerAssocSummary } from '@dukang/shared-types';
|
|
import { request } from '../lib/api';
|
|
import { toastError, toastSuccess } from '../lib/toast';
|
|
import { isWechatEnv } from '../lib/weixin';
|
|
import { usePartnerPageView } from '../lib/usePageView';
|
|
|
|
export default function AssocQrcodePage() {
|
|
usePartnerPageView('partner_assoc_qrcode_view');
|
|
const navigate = useNavigate();
|
|
const [summary, setSummary] = useState<PartnerAssocSummary | null>(null);
|
|
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
request<PartnerAssocSummary>('PARTNER_H5', '/partner/assoc')
|
|
.then(setSummary)
|
|
.catch((e) => toastError(e instanceof Error ? e.message : '加载失败'))
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
useEffect(() => () => {
|
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
}, [previewUrl]);
|
|
|
|
async function downloadQr() {
|
|
const token = localStorage.getItem('accessToken');
|
|
try {
|
|
const res = await fetch('/api/v1/partner/assoc/qrcode', {
|
|
headers: {
|
|
Authorization: token ? `Bearer ${token}` : '',
|
|
'X-Client-App': 'PARTNER_H5',
|
|
},
|
|
});
|
|
if (!res.ok) throw new Error('下载失败');
|
|
const blob = await res.blob();
|
|
const url = URL.createObjectURL(blob);
|
|
if (isWechatEnv()) {
|
|
setPreviewUrl(url);
|
|
toastSuccess('请长按图片保存到相册');
|
|
return;
|
|
}
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `partner-assoc-${summary?.partnerId || 'qr'}.png`;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
toastSuccess('已开始下载');
|
|
} catch (e) {
|
|
if (summary?.qrcodeUrl) {
|
|
setPreviewUrl(summary.qrcodeUrl);
|
|
toastSuccess('请长按图片保存到相册');
|
|
return;
|
|
}
|
|
toastError(e instanceof Error ? e.message : '下载失败');
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<PageHeader title="关联码" onBack={() => navigate(-1)} />
|
|
{loading && <div className="empty">加载中…</div>}
|
|
{!loading && (
|
|
<section className="partner-bill-card" style={{ margin: 16 }}>
|
|
<div style={{ padding: 24, textAlign: 'center' }}>
|
|
<p className="body-md text-muted" style={{ marginBottom: 16 }}>
|
|
用户扫码后首次锁定本合伙人,后续酒单按订单佣金结算
|
|
</p>
|
|
{summary?.qrcodeUrl ? (
|
|
<img
|
|
src={previewUrl || summary.qrcodeUrl}
|
|
alt="关联码"
|
|
style={{ width: 220, height: 220, background: '#fff' }}
|
|
/>
|
|
) : (
|
|
<p className="body-md text-muted">关联码尚未生成,请稍后重试或联系总部补发</p>
|
|
)}
|
|
<p className="label-md text-muted" style={{ marginTop: 12 }}>
|
|
已关联 {summary?.userCount ?? 0} 人
|
|
</p>
|
|
<button type="button" className="partner-btn-primary" style={{ marginTop: 20 }} onClick={() => void downloadQr()}>
|
|
下载二维码
|
|
</button>
|
|
{previewUrl && isWechatEnv() && (
|
|
<p className="label-md text-muted" style={{ marginTop: 12 }}>
|
|
微信内请长按上方图片保存
|
|
</p>
|
|
)}
|
|
</div>
|
|
</section>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|