diff --git a/miniprogram/src/components/PrivacyAgree.jsx b/miniprogram/src/components/PrivacyAgree.jsx new file mode 100644 index 0000000..715ae40 --- /dev/null +++ b/miniprogram/src/components/PrivacyAgree.jsx @@ -0,0 +1,22 @@ +import { View, Text } from '@tarojs/components'; +import Taro from '@tarojs/taro'; +import './PrivacyAgree.scss'; + +/** + * 协议授权同意勾选(审核合规):未同意前禁止登录/绑定手机号等收集用户信息操作。 + * 复用组件,保证所有登录入口一致提供《用户服务协议》《隐私政策》入口。 + */ +export default function PrivacyAgree({ agreed, onToggle, label }) { + const open = (url) => { Taro.navigateTo({ url }); }; + return ( + + {agreed ? '✓' : ''} + + {label || '我已阅读并同意'} + { e.stopPropagation(); open('/pages-extra/agreement/index'); }}>《用户服务协议》 + 与 + { e.stopPropagation(); open('/pages-extra/privacy/index'); }}>《隐私政策》 + + + ); +} diff --git a/miniprogram/src/components/PrivacyAgree.scss b/miniprogram/src/components/PrivacyAgree.scss new file mode 100644 index 0000000..c4f65b6 --- /dev/null +++ b/miniprogram/src/components/PrivacyAgree.scss @@ -0,0 +1,5 @@ +.pa-agree { display: flex; align-items: flex-start; gap: 12rpx; margin-top: 18rpx; width: 100%; box-sizing: border-box; } +.pa-box { width: 34rpx; height: 34rpx; border-radius: 8rpx; border: 2rpx solid #b8c0dd; display: flex; align-items: center; justify-content: center; font-size: 22rpx; color: #fff; flex-shrink: 0; background: #fff; margin-top: 2rpx; } +.pa-box.on { background: linear-gradient(135deg, #6b8bff, #8f7bff); border-color: transparent; } +.pa-txt { font-size: 24rpx; color: #7a86b0; line-height: 1.6; } +.pa-link { color: #6b8bff; } diff --git a/miniprogram/src/pages-extra/event-detail/index.jsx b/miniprogram/src/pages-extra/event-detail/index.jsx index 0c23258..9896191 100644 --- a/miniprogram/src/pages-extra/event-detail/index.jsx +++ b/miniprogram/src/pages-extra/event-detail/index.jsx @@ -19,6 +19,7 @@ import { isAuthed, getUser, wxLogin, wxPhoneBind, phoneLogin, bindPhone, sendCod import coverWide from '@/assets/huodong-wide.png'; import Skeleton from '@/components/skeleton'; import './index.scss'; +import PrivacyAgree from '@/components/PrivacyAgree'; import { PageHeader } from '@/components/TopInset'; /* 活动报名状态(5 态) */ @@ -70,6 +71,7 @@ export default function EventDetail() { /* 登录态 & 我的报名状态:登录/绑号后需重渲染,故用 state 而非渲染期一次性读取 */ const [myBook, setMyBook] = useState(null); // {booked, auditStatus, checkinAt} const [authed, setAuthed] = useState(isAuthed()); + const [agree, setAgree] = useState(false); // 协议/隐私同意(登录与绑定手机号前必勾) const [phoneBound, setPhoneBound] = useState(() => !!(getUser() && getUser().phoneBound)); const [showSms, setShowSms] = useState(false); // 短信兜底开关 const [gatePhone, setGatePhone] = useState(''); @@ -103,6 +105,7 @@ export default function EventDetail() { /* 微信一键登录:wx.login + 昵称头像 → 后端建/查 wxid 账号 */ const onWxLogin = async () => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } setErr(''); setBusy(true); try { let nickName = '', avatarUrl = ''; @@ -117,6 +120,7 @@ export default function EventDetail() { /* 微信一键绑定手机号(getPhoneNumber 回调 code) */ const onWxPhone = async (e) => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } const pcode = e.detail && e.detail.code; if (!pcode) { setErr('已取消授权绑定'); return; } setErr(''); setBusy(true); @@ -130,6 +134,7 @@ export default function EventDetail() { /* 短信兜底:未登录 → phoneLogin(登录即绑号);已登录未绑号 → bindPhone */ const gateSmsLogin = async () => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } setErr(''); if (!/^1\d{10}$/.test(gatePhone)) { setErr('请输入正确的 11 位手机号'); return; } if (!gateCode) { setErr('请输入验证码'); return; } @@ -336,6 +341,7 @@ export default function EventDetail() { 登录后报名 报名需登录并绑定手机号,用于接收活动通知。 + setAgree(!agree)} /> {!showSms && ( )} @@ -360,6 +366,7 @@ export default function EventDetail() { 绑定手机号 绑定后即可报名,用于接收活动通知。 + setAgree(!agree)} /> {!showSms && ( )} diff --git a/miniprogram/src/pages/mine/index.jsx b/miniprogram/src/pages/mine/index.jsx index 2060b21..5be2b00 100644 --- a/miniprogram/src/pages/mine/index.jsx +++ b/miniprogram/src/pages/mine/index.jsx @@ -7,6 +7,7 @@ import { getMyBookings, parseIso } from '@/utils/booking'; import { API_BASE } from '@/utils/api'; import { ensureUploadSize } from '@/utils/upload'; import CountdownBox from '@/components/CountdownBox'; +import PrivacyAgree from '@/components/PrivacyAgree'; import './index.scss'; import { PageHeader } from '@/components/TopInset'; @@ -37,6 +38,7 @@ export default function Mine() { /* 手机号登录 */ const [showPhone, setShowPhone] = useState(false); + const [agree, setAgree] = useState(false); // 协议/隐私同意(登录与绑定手机号前必勾) const [pPhone, setPPhone] = useState(''); const [pCode, setPCode] = useState(''); const [pCd, setPCd] = useState(0); @@ -69,6 +71,7 @@ export default function Mine() { /* 微信一键登录 */ const onWxLogin = async () => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } setErr(''); setBusy(true); try { @@ -121,6 +124,7 @@ export default function Mine() { /* 微信官方一键绑定手机号(getPhoneNumber 回调) */ const onWxPhone = async (e) => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } const detail = (e.detail && e.detail) || {}; const pcode = detail.code; if (!pcode) { Taro.showToast({ title: '已取消授权', icon: 'none' }); return; } @@ -150,6 +154,7 @@ export default function Mine() { }; const doPhoneLogin = async () => { + if (!agree) { Taro.showToast({ title: '请先阅读并同意《用户服务协议》和《隐私政策》', icon: 'none' }); return; } if (!/^1\d{10}$/.test(pPhone)) { setErr('请输入正确的 11 位手机号'); return; } if (!pCode) { setErr('请输入验证码'); return; } setErr(''); setBusy(true); @@ -242,10 +247,11 @@ export default function Mine() { if (!user || !isAuthed()) { return ( - + + setAgree(!agree)} /> 登录后可绑定手机、查看报名场次与活动签到 setShowPhone(!showPhone)}>{showPhone ? '收起手机号登录' : '或用手机号登录'} @@ -269,7 +275,7 @@ export default function Mine() { {err && {err}} 云南省首个由政府主办的免费大学生创业服务平台 - 云南派音人工智能科技有限公司 && 云南汇浙青创科技有限公司 + 昆明市大学生创业园 · 云超服 YunOPC-Hub 像素字体 BubbledotICG-FinePos · CC BY 4.0 @@ -280,7 +286,7 @@ export default function Mine() { /* ============ 已登录:资料 + 我的报名 ============ */ return ( - + {/* 资料卡 */}