diff --git a/miniprogram/src/app.config.js b/miniprogram/src/app.config.js index 1d6c4b1..9af9480 100644 --- a/miniprogram/src/app.config.js +++ b/miniprogram/src/app.config.js @@ -10,6 +10,8 @@ export default { 'pages/event-detail/index', 'pages/scan/index', 'pages/park-apply/index', + 'pages/cert-apply/index', + 'pages/park-transfer/index', 'pages/scan-login/index' ], window: { diff --git a/miniprogram/src/pages/cert-apply/index.config.js b/miniprogram/src/pages/cert-apply/index.config.js new file mode 100644 index 0000000..7590d70 --- /dev/null +++ b/miniprogram/src/pages/cert-apply/index.config.js @@ -0,0 +1 @@ +export default { navigationBarTitleText: 'OPC 认证' }; diff --git a/miniprogram/src/pages/cert-apply/index.jsx b/miniprogram/src/pages/cert-apply/index.jsx new file mode 100644 index 0000000..a3f9880 --- /dev/null +++ b/miniprogram/src/pages/cert-apply/index.jsx @@ -0,0 +1,184 @@ +import { View, Text, Input, Textarea, Button, Radio, RadioGroup } from '@tarojs/components'; +import Taro from '@tarojs/taro'; +import { useState, useEffect } from 'react'; +import { phoneLogin, bindPhone, isAuthed } from '@/utils/auth'; +import { submitOpCert, getOpCertMine } from '@/utils/profile'; +import { uploadParkDoc } from '@/utils/parks'; +import './index.scss'; + +const EMPTY = () => ({ real_name: '', gender: '', address: '', industry: '', ability: '', phone: '' }); +const GENDER_OPTS = ['男', '女']; + +/** OPC 认证申请(C端):提交认证资料 → 平台运营方审核。 */ +export default function CertApply() { + const [authed, setAuthed] = useState(isAuthed()); + const [gatePhone, setGatePhone] = useState(''); + const [gateCode, setGateCode] = useState(''); + const [gateErr, setGateErr] = useState(''); + const [busy, setBusy] = useState(false); + + const [form, setForm] = useState(EMPTY()); + const [docs, setDocs] = useState({}); + const [mine, setMine] = useState(null); // {certification_status, certification} + const [err, setErr] = useState(''); + const [done, setDone] = useState(false); + const [loaded, setLoaded] = useState(false); + + const up = (k, v) => setForm((f) => ({ ...f, [k]: v })); + + const reloadMine = async () => { + try { + const m = await getOpCertMine(); + setMine(m); + } catch { /* ignore */ } + finally { setLoaded(true); } + }; + useEffect(() => { if (isAuthed()) reloadMine(); else setLoaded(true); }, []); + + const gateSmsLogin = async () => { + setGateErr(''); + if (!/^1\d{10}$/.test(gatePhone)) { setGateErr('请输入正确的 11 位手机号'); return; } + if (!gateCode) { setGateErr('请输入验证码'); return; } + setBusy(true); + try { + if (authed) { + const b = await bindPhone(gatePhone, gateCode); + if (!b.ok) { setGateErr(b.error || '绑定失败'); return; } + } else { + await phoneLogin(gatePhone, gateCode); + } + setAuthed(true); + reloadMine(); + } catch (e) { setGateErr((e && e.message) || '登录失败'); } + finally { setBusy(false); } + }; + + const pickAndUpload = async (key) => { + let filePath = null; + try { + const res = await Taro.chooseMessageFile({ count: 1, type: 'file' }); + filePath = res.tempFiles && res.tempFiles[0] && res.tempFiles[0].path; + } catch (e) { + try { + const img = await Taro.chooseImage({ count: 1, sizeType: ['compressed'] }); + filePath = img.tempFilePaths && img.tempFilePaths[0]; + } catch (_) { return; } + } + if (!filePath) return; + setBusy(true); setErr(''); + try { + const url = await uploadParkDoc(filePath); + setDocs((d) => ({ ...d, [key]: url })); + } catch (e) { setErr((e && e.message) || '文件上传失败'); } + finally { setBusy(false); } + }; + + const statusText = (s) => ({ uncertified: '未认证', pending: '审核中', reviewing: '审核中', certified: '已认证', rejected: '未通过' }[s] || s || '未认证'); + + const submit = async () => { + setErr(''); + if (!form.real_name || !form.phone) { setErr('请填写真实姓名与联系电话'); return; } + const payload = { ...form, docs_json: JSON.stringify(docs) }; + setBusy(true); + try { + await submitOpCert(payload); + setDone(true); + await reloadMine(); + } catch (e) { setErr((e && e.message) || '提交失败,请稍后重试'); } + finally { setBusy(false); } + }; + + if (done) { + return ( + + + 认证申请已提交 + 平台将对您的资料进行审核,请留意认证状态。 + + + ); + } + + if (!loaded) return 加载中…; + + // 未登录/未绑手机 → 快捷门 + if (!authed) { + return ( + + + OPC 认证申请 + 请先用手机号登录(验证码 123456) + setGatePhone(e.detail.value)} /> + setGateCode(e.detail.value)} /> + {gateErr && {gateErr}} + + + + ); + } + + const st = mine?.certification_status || 'uncertified'; + const disabled = st === 'certified' || st === 'pending' || st === 'reviewing'; + + return ( + + + OPC 认证申请 + 当前认证状态:{statusText(st)} + + + + 一 · 基本信息 + up('real_name', v)} /> + 性别 + up('gender', e.detail.value)}> + {GENDER_OPTS.map((g) => {g})} + + + up('address', v)} /> + up('industry', v)} /> + up('phone', v)} /> + + + + 二 · 能力与成果 + 专业技能 / 代表作品 / 成果 +