diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.module.scss b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.module.scss index ecda04dc..ed82753e 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.module.scss +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.module.scss @@ -498,6 +498,166 @@ color: #fa8c16; } +// 渠道登录入口卡片 +.loginEntryCard { + margin: 16px 16px 8px; + padding: 12px 16px; + border-radius: 12px; + background: #f7f9fc; + border: 1px solid #e5e6eb; + display: flex; + flex-direction: column; + gap: 8px; +} + +.loginEntryHeader { + display: flex; + align-items: center; + justify-content: space-between; +} + +.loginEntryTitle { + display: flex; + align-items: center; + gap: 6px; +} + +.loginEntryDot { + width: 6px; + height: 6px; + border-radius: 50%; + background: #1890ff; +} + +.loginEntryText { + font-size: 14px; + font-weight: 600; + color: #1f2933; +} + +.loginEntryTypeTabs { + display: flex; + gap: 4px; + background: #edf2ff; + padding: 2px; + border-radius: 999px; +} + +.loginEntryTypeTab { + border: none; + outline: none; + padding: 4px 10px; + border-radius: 999px; + font-size: 12px; + background: transparent; + color: #4b5563; + cursor: pointer; + + &.active { + background: #ffffff; + color: #1890ff; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.2); + } +} + +.loginEntryContent { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 4px; +} + +.loginEntryDesc { + font-size: 12px; + color: #6b7280; + max-width: 70%; +} + +// 登录二维码弹窗 +.loginQrDialog { + padding: 16px 16px 24px; + background: #fff; + border-top-left-radius: 16px; + border-top-right-radius: 16px; +} + +.loginQrHeader { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; + + h3 { + margin: 0; + font-size: 16px; + font-weight: 600; + } +} + +.loginQrTypeSelector { + display: flex; + justify-content: center; + gap: 8px; + margin-bottom: 16px; +} + +.loginQrContent { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; +} + +.loginQrLoading { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 32px 0; + font-size: 14px; + color: #6b7280; +} + +.loginQrImage { + width: 200px; + height: 200px; + border-radius: 12px; + border: 1px solid #e5e6eb; + padding: 8px; + background: #fff; +} + +.loginQrLinkSection { + width: 100%; + margin-top: 8px; +} + +.loginQrLinkLabel { + font-size: 13px; + color: #4b5563; + margin-bottom: 6px; +} + +.loginQrLinkWrapper { + display: flex; + align-items: center; + gap: 8px; +} + +.loginQrLinkInput { + font-size: 12px; +} + +.loginQrError { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 24px 0; + font-size: 14px; + color: #9ca3af; +} + // 加载和空状态 .loading { text-align: center; diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx index 27f91544..b1658bef 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx @@ -9,7 +9,7 @@ import { Select, Modal, } from "antd"; -import { Tabs, DatePicker, InfiniteScroll, SpinLoading } from "antd-mobile"; +import { Tabs, DatePicker, InfiniteScroll, SpinLoading, Popup } from "antd-mobile"; import NavCommon from "@/components/NavCommon"; const { TextArea } = Input; @@ -70,6 +70,7 @@ import { fetchWithdrawalList, reviewWithdrawal, markAsPaid, + generateLoginQRCode, } from "./api"; import type { Channel, @@ -130,6 +131,16 @@ const DistributionManagement: React.FC = () => { const [showDatePicker, setShowDatePicker] = useState(false); const [withdrawalKeyword, setWithdrawalKeyword] = useState(""); + // 渠道登录入口二维码相关状态 + const [loginQrVisible, setLoginQrVisible] = useState(false); + const [loginQrType, setLoginQrType] = useState<"h5" | "miniprogram">("h5"); + const [loginQrLoading, setLoginQrLoading] = useState(false); + const [loginQrData, setLoginQrData] = useState<{ + qrCode: string; + url: string; + type: "h5" | "miniprogram"; + } | null>(null); + useEffect(() => { loadData(); }, []); @@ -164,6 +175,35 @@ const DistributionManagement: React.FC = () => { } }; + // 生成渠道登录二维码(每次调用都重新请求) + const handleGenerateLoginQRCode = async (type: "h5" | "miniprogram") => { + setLoginQrLoading(true); + try { + const res = await generateLoginQRCode(type); + setLoginQrData(res); + } catch (e: any) { + const errorMsg = e?.message || e?.msg || "生成登录二维码失败"; + message.error(errorMsg); + setLoginQrData(null); + } finally { + setLoginQrLoading(false); + } + }; + + // 打开登录入口弹窗(默认用当前类型重新请求一次) + const handleOpenLoginQrDialog = async () => { + setLoginQrVisible(true); + setLoginQrData(null); + await handleGenerateLoginQRCode(loginQrType); + }; + + // 切换登录二维码类型(H5 / 小程序),每次都重新请求接口生成 + const handleLoginQrTypeChange = async (type: "h5" | "miniprogram") => { + setLoginQrType(type); + setLoginQrData(null); + await handleGenerateLoginQRCode(type); + }; + const loadChannelList = async () => { setLoading(true); try { @@ -551,6 +591,46 @@ const DistributionManagement: React.FC = () => { + {/* 渠道登录入口 */} +