子账号登录微信授权

This commit is contained in:
2026-07-10 11:03:11 +08:00
parent f4f4f1b4aa
commit 9c5cb69730
11 changed files with 535 additions and 251 deletions
@@ -1,4 +1,4 @@
import { useEffect, useId, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { uploadFileToOss, type OssMediaType } from '../lib/upload';
import { toastError } from '../lib/toast';
import {
@@ -33,11 +33,15 @@ function formatWechatUploadError(e: unknown): string {
const formatted = formatChooseImageFailMessage(msg);
if (formatted) return formatted;
if (/invalid signature/i.test(msg)) {
return '微信 JSSDK 签名校验失败:请确认公众号已配置 JS 接口安全域名为 user.runxian.top,并刷新页面后重试';
return '微信 JSSDK 签名校验失败:请确认公众号已配置 JS 接口安全域名,并刷新页面后重试';
}
return msg;
}
function acceptsImages(accept: string) {
return accept.includes('image');
}
export default function OssUploadField({
value,
onChange,
@@ -50,7 +54,6 @@ export default function OssUploadField({
wechatReady,
onWechatReadyChange,
}: OssUploadFieldProps) {
const inputId = useId();
const inputRef = useRef<HTMLInputElement>(null);
const [uploading, setUploading] = useState(false);
const [authorizing, setAuthorizing] = useState(false);
@@ -60,7 +63,9 @@ export default function OssUploadField({
const resolvedAccept =
accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? 'image/*,.pdf' : 'image/*');
const useWechatPicker = isWechatEnv() && mediaType === 'IMAGE';
const inWechat = isWechatEnv();
const useWechatPicker =
inWechat && (mediaType === 'IMAGE' || (mediaType === 'FILE' && acceptsImages(resolvedAccept)));
const needsAuth = useWechatPicker && needsWechatAuth(profile, clientConfig) && wechatReady !== true;
useEffect(() => {
@@ -124,7 +129,7 @@ export default function OssUploadField({
await weixinSdk.init();
const files = await weixinSdk.chooseImages({
count: 1,
sourceType: ['album'],
sourceType: ['album', 'camera'],
});
if (files?.[0]) {
await uploadSelectedFile(files[0]);
@@ -161,6 +166,7 @@ export default function OssUploadField({
const isImage = mediaType === 'IMAGE' && value;
const isFile = mediaType === 'FILE' && value;
const busy = uploading || authorizing;
const pickerLabel = label ?? (useWechatPicker ? '拍照 / 从相册选择' : '点击上传');
const triggerProps = {
type: 'button' as const,
@@ -172,7 +178,7 @@ export default function OssUploadField({
<div className="partner-oss-upload">
{needsAuth && (
<div className="partner-wechat-auth-hint" role="status">
<p className="body-md"></p>
<p className="body-md"></p>
<button
type="button"
className="partner-btn-outline"
@@ -180,23 +186,23 @@ export default function OssUploadField({
disabled={authorizing}
onClick={() => void startWechatAuth()}
>
{authorizing ? '跳转授权中…' : '微信授权'}
{authorizing ? '跳转授权中…' : '微信授权绑定'}
</button>
</div>
)}
<input
id={inputId}
ref={inputRef}
type="file"
accept={resolvedAccept}
capture={mediaType === 'FILE' && isWechatEnv() ? 'environment' : undefined}
className="partner-oss-upload-input"
disabled={busy}
onChange={(e) => {
const file = e.target.files?.[0];
if (file) void uploadSelectedFile(file);
}}
/>
{!useWechatPicker && (
<input
ref={inputRef}
type="file"
accept={resolvedAccept}
className="partner-oss-upload-input"
disabled={busy}
onChange={(e) => {
const file = e.target.files?.[0];
if (file) void uploadSelectedFile(file);
}}
/>
)}
{isImage ? (
<button {...triggerProps} className={`partner-upload-preview${wide ? ' partner-upload-preview--wide' : ''}`}>
<img src={value} alt={label ?? '已上传'} />
@@ -224,7 +230,7 @@ export default function OssUploadField({
{busy ? 'hourglass_top' : 'add_a_photo'}
</span>
<span className="text-primary" style={{ fontWeight: 500 }}>
{uploading ? '上传中…' : needsAuth ? '请先微信授权' : (label ?? (useWechatPicker ? '从相册选择' : '点击上传'))}
{uploading ? '上传中…' : needsAuth ? '请先微信授权' : pickerLabel}
</span>
</button>
)}