Files
yunzerwebsiteallinone/go/views/auth/register.tpl
T
2026-10-08 15:30:37 +08:00

572 lines
29 KiB
Smarty
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<title>统一认证中心 - 注册</title>
<style>
:root {
--primary: #3973ff;
--primary-dark: #2560a9;
--text: #1f2b48;
--text-sub: #5b6780;
--muted: #8a94ad;
--border: #e3e9f5;
--radius: 12px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
color: var(--text);
background: linear-gradient(120deg, #eef4ff 0%, #f7fbff 55%, #eaf3ff 100%);
min-height: 100vh;
display: flex; align-items: center; justify-content: center;
padding: 32px 20px;
position: relative; overflow-x: hidden;
-webkit-font-smoothing: antialiased;
}
.glow { position: fixed; border-radius: 50%; filter: blur(60px); pointer-events: none; z-index: 0; }
.glow-1 { width: 380px; height: 380px; top: -120px; left: -100px; background: rgba(82, 168, 255, 0.28); }
.glow-2 { width: 320px; height: 320px; bottom: -120px; right: -80px; background: rgba(57, 115, 255, 0.20); }
.auth-card {
position: relative; z-index: 1;
width: 100%; max-width: 860px;
background: #fff; border-radius: 22px;
box-shadow: 0 18px 50px 0 rgba(37, 96, 169, 0.14), 0 2px 6px 0 rgba(31, 43, 72, 0.04);
padding: 40px 48px 32px;
}
.brand { text-align: center; margin-bottom: 22px; }
.brand h1 { font-size: 22px; font-weight: 700; letter-spacing: 1px; }
.brand p { color: var(--muted); font-size: 13px; margin-top: 6px; }
/* 步骤条 */
.steps { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 28px; }
.step { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 14px; }
.step .dot {
width: 26px; height: 26px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
background: #eef2fb; color: var(--muted); font-size: 13px; font-weight: 600;
transition: all .25s;
}
.step.active { color: var(--text); font-weight: 600; }
.step.active .dot { background: var(--primary); color: #fff; }
.step.done .dot { background: #34b96f; color: #fff; }
.step-line { width: 70px; height: 2px; background: var(--border); border-radius: 2px; }
.panel { display: none; }
.panel.active { display: block; animation: fade .25s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* 第一步:方式切换 */
.mode-tabs { display: flex; background: #f2f5fb; border-radius: 12px; padding: 5px; margin-bottom: 22px; }
.mode-tab {
flex: 1; text-align: center; padding: 10px 0; border-radius: 9px;
font-size: 14px; color: var(--text-sub); cursor: pointer; user-select: none;
transition: all .2s;
}
.mode-tab.on { background: #fff; color: var(--primary); font-weight: 600; box-shadow: 0 2px 8px rgba(31,43,72,.08); }
.mode-pane { display: none; }
.mode-pane.on { display: block; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; color: var(--text-sub); margin-bottom: 6px; }
.field label .req { color: #e5484d; margin-left: 2px; }
.input-row { display: flex; gap: 10px; }
.ipt {
flex: 1; width: 100%; height: 44px; padding: 0 14px;
border: 1px solid var(--border); border-radius: 10px;
font-size: 14px; color: var(--text); outline: none; background: #fbfcff;
transition: border-color .2s, box-shadow .2s;
}
.ipt:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(57,115,255,.12); background: #fff; }
.btn {
height: 44px; padding: 0 20px; border: none; border-radius: 10px;
font-size: 14px; cursor: pointer; transition: all .2s;
background: #eef2fb; color: var(--text-sub);
}
.btn:hover { background: #e2e9f8; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-primary {
width: 100%; height: 46px; margin-top: 6px;
background: linear-gradient(135deg, #3973ff, #5a8bff);
color: #fff; font-size: 15px; font-weight: 600;
box-shadow: 0 8px 20px -6px rgba(57,115,255,.5);
}
.btn-primary:hover { filter: brightness(1.05); }
.btn-ghost { background: #fff; border: 1px solid var(--border); color: var(--text-sub); }
.btn-ghost:hover { border-color: var(--primary); color: var(--primary); background: #fff; }
.code-btn { min-width: 118px; }
.hint { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.6; }
/* 账号注册二维码区 */
.wechat-box { display: none; text-align: center; margin-bottom: 16px; padding: 16px; border: 1px dashed var(--border); border-radius: 12px; background: #fbfcff; }
.wechat-box.show { display: block; }
.wechat-box img { width: 168px; height: 168px; object-fit: contain; }
.wechat-box .scan-tip { font-size: 13px; color: var(--text-sub); margin-top: 8px; }
.wechat-box .scan-tip.ok { color: #34b96f; font-weight: 600; }
.wechat-box .mp-notice { font-size: 12px; color: #d08700; margin-top: 6px; }
/* 第二步:两个卡片 */
.cards { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 760px) { .cards { grid-template-columns: 1fr; } .auth-card { padding: 28px 20px; } }
.choice-card {
border: 1px solid var(--border); border-radius: 14px; padding: 20px;
background: #fbfcff; transition: border-color .2s, box-shadow .2s;
}
.choice-card:hover { border-color: rgba(57,115,255,.45); box-shadow: 0 8px 24px -10px rgba(57,115,255,.25); }
.choice-card h3 { font-size: 15px; display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.choice-card .desc { font-size: 12px; color: var(--muted); margin-bottom: 14px; line-height: 1.6; }
.choice-card .field { margin-bottom: 12px; }
.search-list { max-height: 168px; overflow-y: auto; border: 1px solid var(--border); border-radius: 10px; margin-top: 8px; background: #fff; }
.search-item { padding: 10px 12px; font-size: 13px; cursor: pointer; border-bottom: 1px solid #f0f3fa; display: flex; justify-content: space-between; gap: 8px; }
.search-item:last-child { border-bottom: none; }
.search-item:hover { background: #f4f8ff; }
.search-item.sel { background: #ecf2ff; color: var(--primary); font-weight: 600; }
.search-item .code { color: var(--muted); font-size: 12px; }
.search-empty { padding: 12px; font-size: 12px; color: var(--muted); text-align: center; }
.file-row { display: flex; align-items: center; gap: 10px; }
.file-name { font-size: 12px; color: var(--text-sub); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-name.ok { color: #34b96f; }
.card-submit { width: 100%; margin-top: 4px; }
.skip-row { text-align: center; margin-top: 20px; }
.skip-link { font-size: 13px; color: var(--muted); cursor: pointer; background: none; border: none; text-decoration: underline; }
.skip-link:hover { color: var(--primary); }
.msg { display: none; margin-bottom: 16px; padding: 10px 14px; border-radius: 10px; font-size: 13px; line-height: 1.6; }
.msg.show { display: block; }
.msg-err { background: #fdf0f0; color: #d54941; border: 1px solid #f5d4d2; }
.msg-ok { background: #eefaf2; color: #2e9e5b; border: 1px solid #cdeeda; }
.foot { text-align: center; margin-top: 22px; font-size: 13px; color: var(--muted); }
.foot a { color: var(--primary); text-decoration: none; }
.foot a:hover { text-decoration: underline; }
/* 成功浮层 */
.done-mask { display: none; position: fixed; inset: 0; background: rgba(23,32,54,.45); z-index: 50; align-items: center; justify-content: center; }
.done-mask.show { display: flex; }
.done-box { width: 380px; max-width: 92vw; background: #fff; border-radius: 18px; padding: 32px 28px; text-align: center; }
.done-box .icon { width: 56px; height: 56px; border-radius: 50%; background: #eefaf2; color: #34b96f; font-size: 28px; display: flex; align-items: center; justify-content: center; margin: 0 auto 14px; }
.done-box h3 { font-size: 17px; margin-bottom: 8px; }
.done-box p { font-size: 13px; color: var(--text-sub); line-height: 1.7; margin-bottom: 18px; }
</style>
</head>
<body>
<div class="glow glow-1"></div>
<div class="glow glow-2"></div>
<div class="auth-card" id="app"
data-client-id="{{.ClientID}}"
data-redirect="{{.Redirect}}">
<div class="brand">
<h1>创建账号</h1>
<p>注册统一认证账号,一个账号密码通行所有企业</p>
</div>
<div class="steps">
<div class="step active" id="stepDot1"><span class="dot">1</span><span>核验身份</span></div>
<div class="step-line"></div>
<div class="step" id="stepDot2"><span class="dot">2</span><span>企业归属</span></div>
</div>
<div class="msg msg-err" id="globalMsg"></div>
<!-- ================= 第一步:核验身份 ================= -->
<div class="panel active" id="panelStep1">
<div class="mode-tabs">
<div class="mode-tab on" data-mode="phone">手机号注册</div>
<div class="mode-tab" data-mode="account">账号注册</div>
</div>
<!-- 手机号注册 -->
<div class="mode-pane on" id="panePhone">
<div class="field">
<label>手机号<span class="req">*</span></label>
<input class="ipt" id="phone" type="tel" maxlength="11" placeholder="请输入手机号(作为登录账号)">
</div>
<div class="field">
<label>短信验证码<span class="req">*</span></label>
<div class="input-row">
<input class="ipt" id="phoneCode" maxlength="6" placeholder="请输入短信验证码">
<button class="btn code-btn" id="sendPhoneCode" type="button">获取验证码</button>
</div>
</div>
<div class="field">
<label>设置密码<span class="req">*</span></label>
<input class="ipt" id="phonePwd" type="password" placeholder="密码长度不少于6位">
</div>
<div class="field">
<label>确认密码<span class="req">*</span></label>
<input class="ipt" id="phonePwd2" type="password" placeholder="请再次输入密码">
</div>
<button class="btn btn-primary" id="btnVerifyPhone" type="button">验证并下一步</button>
</div>
<!-- 账号注册 -->
<div class="mode-pane" id="paneAccount">
<div class="field">
<label>账号名<span class="req">*</span></label>
<input class="ipt" id="account" maxlength="32" placeholder="4-32位,字母开头,可含数字、下划线、中划线">
</div>
<div class="field">
<label>设置密码<span class="req">*</span></label>
<input class="ipt" id="accountPwd" type="password" placeholder="密码长度不少于6位">
</div>
<div class="field">
<label>确认密码<span class="req">*</span></label>
<input class="ipt" id="accountPwd2" type="password" placeholder="请再次输入密码">
</div>
<div class="field">
<label>微信身份核验<span class="req">*</span></label>
<div class="wechat-box" id="wechatBox">
<img id="wechatQr" alt="公众号二维码" style="display:none">
<div class="scan-tip" id="scanTip">正在获取二维码…</div>
<div class="mp-notice" id="mpNotice"></div>
</div>
<div class="input-row">
<input class="ipt" id="accountCode" maxlength="6" placeholder="公众号下发的 6 位验证码">
<button class="btn code-btn" id="btnQr" type="button">获取二维码</button>
</div>
<div class="hint">用微信扫码关注公众号后,验证码将通过公众号自动发送;无法扫码时可在公众号内直接发送「注册」获取验证码。</div>
</div>
<button class="btn btn-primary" id="btnVerifyAccount" type="button">验证并下一步</button>
</div>
<div class="foot">已有账号?<a href="/auth/login" id="toLogin">直接登录</a> · <a href="/auth/forgot" id="toForgot">忘记密码</a></div>
</div>
<!-- ================= 第二步:企业归属 ================= -->
<div class="panel" id="panelStep2">
<div class="cards">
<!-- 卡片一:绑定企业 -->
<div class="choice-card">
<h3>🏢 绑定企业</h3>
<div class="desc">你的账号已由企业创建/企业管理员已开通企业,搜索并申请加入,由企业管理员审核。</div>
<div class="field">
<label>企业名称 / 编码<span class="req">*</span></label>
<div class="input-row">
<input class="ipt" id="tenantKeyword" placeholder="输入企业名称或编码搜索">
<button class="btn" id="btnSearchTenant" type="button">搜索</button>
</div>
<div class="search-list" id="tenantList" style="display:none"></div>
</div>
<button class="btn btn-primary card-submit" id="btnJoin" type="button" disabled>确定加入</button>
</div>
<!-- 卡片二:创建企业 -->
<div class="choice-card">
<h3>🏗️ 创建企业</h3>
<div class="desc">没有现成企业?填写企业资料创建新企业,由平台审核,通过后你将成为企业管理员。</div>
<div class="field"><label>公司名称<span class="req">*</span></label><input class="ipt" id="cName" maxlength="128" placeholder="营业执照上的公司全称"></div>
<div class="field"><label>统一社会信用代码<span class="req">*</span></label><input class="ipt" id="cCredit" maxlength="18" placeholder="18 位统一社会信用代码"></div>
<div class="field"><label>法定代表人姓名<span class="req">*</span></label><input class="ipt" id="cLegal" maxlength="64" placeholder="法定代表人姓名"></div>
<div class="field">
<label>营业执照电子档<span class="req">*</span>(PDF / JPG / PNG,≤5MB)</label>
<div class="file-row">
<button class="btn btn-ghost" id="btnPickFile" type="button">选择文件</button>
<span class="file-name" id="licenseName">未选择文件</span>
</div>
<input type="file" id="licenseFile" accept=".pdf,.jpg,.jpeg,.png" style="display:none">
</div>
<div class="field"><label>联系人<span class="req">*</span></label><input class="ipt" id="cContact" maxlength="64" placeholder="联系人姓名"></div>
<div class="field"><label>联系电话<span class="req">*</span></label><input class="ipt" id="cPhone" maxlength="11" placeholder="联系电话"></div>
<div class="field"><label>电子邮箱<span class="req">*</span></label><input class="ipt" id="cEmail" maxlength="128" placeholder="电子邮箱"></div>
<div class="field"><label>公司地址<span class="req">*</span></label><input class="ipt" id="cAddress" maxlength="255" placeholder="公司地址"></div>
<button class="btn btn-primary card-submit" id="btnCreate" type="button">确定创建</button>
</div>
</div>
<div class="skip-row">
<button class="skip-link" id="btnSkip" type="button">暂不加入企业,直接完成注册 →</button>
</div>
</div>
</div>
<!-- 成功浮层 -->
<div class="done-mask" id="doneMask">
<div class="done-box">
<div class="icon">✓</div>
<h3 id="doneTitle">注册成功</h3>
<p id="doneText"></p>
<button class="btn btn-primary" id="btnGoLogin" type="button" style="width:100%">前往登录</button>
</div>
</div>
<script>
(function () {
var app = document.getElementById('app');
var CLIENT_ID = app.getAttribute('data-client-id') || '';
var REDIRECT = app.getAttribute('data-redirect') || '';
var state = { mode: 'phone', token: '', scene: '', qrTimer: null, selectedTid: 0 };
// ---------- 工具 ----------
function $(id) { return document.getElementById(id); }
function showMsg(text, ok) {
var el = $('globalMsg');
el.className = 'msg show ' + (ok ? 'msg-ok' : 'msg-err');
el.textContent = text;
if (!ok) { clearTimeout(showMsg._t); showMsg._t = setTimeout(function(){ el.className = 'msg'; }, 5000); }
}
function post(url, data, cb) {
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data || {})
}).then(function (r) { return r.json(); }).then(function (res) { cb(res); })
.catch(function () { cb({ code: 500, msg: '网络异常,请稍后重试' }); });
}
function buildLoginURL(redirect) {
var qs = [];
if (CLIENT_ID) qs.push('client_id=' + encodeURIComponent(CLIENT_ID));
if (REDIRECT) qs.push('redirect=' + encodeURIComponent(REDIRECT));
var warn = '';
try { var u = new URL(redirect || '/auth/login', location.origin); warn = u.searchParams.get('warn') || ''; } catch (e) {}
if (warn) qs.push('warn=' + encodeURIComponent(warn));
return (qs.length ? '/auth/login?' + qs.join('&') : '/auth/login');
}
function goStep(n) {
$('panelStep1').classList.toggle('active', n === 1);
$('panelStep2').classList.toggle('active', n === 2);
$('stepDot1').className = 'step ' + (n === 1 ? 'active' : 'done');
$('stepDot1').querySelector('.dot').textContent = n === 1 ? '1' : '✓';
$('stepDot2').className = 'step ' + (n === 2 ? 'active' : '');
window.scrollTo(0, 0);
}
function done(title, text, redirect) {
$('doneTitle').textContent = title;
$('doneText').textContent = text;
$('btnGoLogin').onclick = function () { location.href = redirect || buildLoginURL(''); };
$('doneMask').classList.add('show');
}
// ---------- 第一步:方式切换 ----------
document.querySelectorAll('.mode-tab').forEach(function (tab) {
tab.addEventListener('click', function () {
document.querySelectorAll('.mode-tab').forEach(function (t) { t.classList.remove('on'); });
tab.classList.add('on');
state.mode = tab.getAttribute('data-mode');
$('panePhone').classList.toggle('on', state.mode === 'phone');
$('paneAccount').classList.toggle('on', state.mode === 'account');
});
});
// ---------- 手机号注册 ----------
var sendBtn = $('sendPhoneCode'), sendTimer = null;
sendBtn.addEventListener('click', function () {
var phone = $('phone').value.trim();
if (!/^1[3-9]\d{9}$/.test(phone)) { showMsg('请输入正确的手机号'); return; }
sendBtn.disabled = true;
post('/auth/register/send-code', { phone: phone }, function (res) {
if (res.code !== 200) {
showMsg(res.msg || '验证码发送失败');
sendBtn.disabled = false;
return;
}
showMsg('验证码已发送,请查收短信', true);
var sec = 60;
sendBtn.textContent = sec + 's 后重发';
sendTimer = setInterval(function () {
sec--;
if (sec <= 0) { clearInterval(sendTimer); sendBtn.textContent = '获取验证码'; sendBtn.disabled = false; }
else { sendBtn.textContent = sec + 's 后重发'; }
}, 1000);
});
});
$('btnVerifyPhone').addEventListener('click', function () {
var phone = $('phone').value.trim(), code = $('phoneCode').value.trim();
var pwd = $('phonePwd').value, pwd2 = $('phonePwd2').value;
if (!/^1[3-9]\d{9}$/.test(phone)) { showMsg('请输入正确的手机号'); return; }
if (!code) { showMsg('请输入短信验证码'); return; }
if (pwd.length < 6) { showMsg('密码长度不能少于6位'); return; }
if (pwd !== pwd2) { showMsg('两次输入的密码不一致'); return; }
var btn = this; btn.disabled = true;
post('/auth/register/verify', { mode: 'phone', phone: phone, code: code, password: pwd, confirm: pwd2 }, function (res) {
btn.disabled = false;
if (res.code !== 200) { showMsg(res.msg || '验证失败'); return; }
state.token = res.data.register_token;
showMsg('身份核验通过', true);
goStep(2);
});
});
// ---------- 账号注册 ----------
$('btnQr').addEventListener('click', function () {
var btn = this; btn.disabled = true;
$('wechatBox').classList.add('show');
$('wechatQr').style.display = 'none';
$('scanTip').textContent = '正在获取二维码…';
$('scanTip').className = 'scan-tip';
$('mpNotice').textContent = '';
fetch('/auth/register/wechat/start').then(function (r) { return r.json(); }).then(function (res) {
btn.disabled = false;
if (res.code !== 200) { $('scanTip').textContent = res.msg || '获取二维码失败'; return; }
state.scene = res.data.scene || '';
if (res.data.qr_url) {
$('wechatQr').src = res.data.qr_url;
$('wechatQr').style.display = '';
$('scanTip').textContent = '请用微信扫码并关注公众号';
} else {
$('scanTip').textContent = '无法展示二维码:请在公众号内直接发送「注册」获取验证码';
}
if (res.data.notice) { $('mpNotice').textContent = res.data.notice; }
startQrPolling();
}).catch(function () { btn.disabled = false; $('scanTip').textContent = '网络异常,请重试'; });
});
function startQrPolling() {
if (state.qrTimer) clearInterval(state.qrTimer);
if (!state.scene) return;
state.qrTimer = setInterval(function () {
fetch('/auth/register/wechat/status?scene=' + encodeURIComponent(state.scene))
.then(function (r) { return r.json(); })
.then(function (res) {
if (res.code === 200 && res.data && res.data.scanned) {
$('scanTip').textContent = '已扫码,验证码已发送到公众号,请填入下方输入框';
$('scanTip').className = 'scan-tip ok';
clearInterval(state.qrTimer);
}
}).catch(function () {});
}, 2000);
}
$('btnVerifyAccount').addEventListener('click', function () {
var account = $('account').value.trim(), code = $('accountCode').value.trim();
var pwd = $('accountPwd').value, pwd2 = $('accountPwd2').value;
if (!/^[A-Za-z][A-Za-z0-9_-]{3,31}$/.test(account)) { showMsg('账号需 4-32 位,字母开头,仅含字母/数字/下划线/中划线'); return; }
if (pwd.length < 6) { showMsg('密码长度不能少于6位'); return; }
if (pwd !== pwd2) { showMsg('两次输入的密码不一致'); return; }
if (!code) { showMsg('请输入公众号下发的验证码'); return; }
var btn = this; btn.disabled = true;
post('/auth/register/verify', { mode: 'account', account: account, scene: state.scene, code: code, password: pwd, confirm: pwd2 }, function (res) {
btn.disabled = false;
if (res.code !== 200) { showMsg(res.msg || '验证失败'); return; }
state.token = res.data.register_token;
if (state.qrTimer) clearInterval(state.qrTimer);
showMsg('身份核验通过', true);
goStep(2);
});
});
// ---------- 第二步:绑定企业 ----------
$('btnSearchTenant').addEventListener('click', function () {
var kw = $('tenantKeyword').value.trim();
if (!kw) { showMsg('请输入企业名称或编码'); return; }
var list = $('tenantList');
list.style.display = '';
list.innerHTML = '<div class="search-empty">搜索中…</div>';
state.selectedTid = 0;
$('btnJoin').disabled = true;
fetch('/auth/register/tenant/search?keyword=' + encodeURIComponent(kw))
.then(function (r) { return r.json(); })
.then(function (res) {
if (res.code !== 200 || !res.data || !res.data.list || !res.data.list.length) {
list.innerHTML = '<div class="search-empty">未找到匹配企业,请确认名称或编码</div>';
return;
}
list.innerHTML = '';
res.data.list.forEach(function (t) {
var item = document.createElement('div');
item.className = 'search-item';
item.innerHTML = '<span>' + t.tenant_name.replace(/</g, '&lt;') + '</span><span class="code">' + t.tenant_code + '</span>';
item.addEventListener('click', function () {
list.querySelectorAll('.search-item').forEach(function (x) { x.classList.remove('sel'); });
item.classList.add('sel');
state.selectedTid = t.tid;
$('btnJoin').disabled = false;
});
list.appendChild(item);
});
}).catch(function () { list.innerHTML = '<div class="search-empty">搜索失败,请重试</div>'; });
});
$('btnJoin').addEventListener('click', function () {
if (!state.selectedTid) { showMsg('请先选择企业'); return; }
var btn = this; btn.disabled = true;
post('/auth/register/apply-join', { token: state.token, tid: state.selectedTid }, function (res) {
btn.disabled = false;
if (res.code !== 200) { showMsg(res.msg || '提交失败'); return; }
done('申请已提交', '加入企业的申请已提交,请等待企业管理员在后台审核,审核通过后即可登录。', res.redirect || buildLoginURL(''));
});
});
// ---------- 第二步:创建企业 ----------
$('btnPickFile').addEventListener('click', function () { $('licenseFile').click(); });
$('licenseFile').addEventListener('change', function () {
var f = this.files && this.files[0];
if (!f) return;
if (!/\.(pdf|jpg|jpeg|png)$/i.test(f.name)) { showMsg('仅支持 PDF、JPG、PNG 格式'); this.value = ''; return; }
if (f.size > 5 * 1024 * 1024) { showMsg('文件大小不能超过 5MB'); this.value = ''; return; }
var nameEl = $('licenseName');
nameEl.textContent = '上传中:' + f.name;
nameEl.className = 'file-name';
var fd = new FormData();
fd.append('file', f);
fetch('/auth/register/upload-license', { method: 'POST', body: fd })
.then(function (r) { return r.json(); })
.then(function (res) {
if (res.code !== 200) { nameEl.textContent = '未选择文件'; showMsg(res.msg || '上传失败'); return; }
nameEl.textContent = '已上传:' + res.data.name;
nameEl.className = 'file-name ok';
nameEl.setAttribute('data-url', res.data.url);
}).catch(function () { nameEl.textContent = '未选择文件'; showMsg('上传失败,请重试'); });
});
$('btnCreate').addEventListener('click', function () {
var form = {
tenant_name: $('cName').value.trim(),
credit_code: $('cCredit').value.trim(),
legal_person: $('cLegal').value.trim(),
license_file: $('licenseName').getAttribute('data-url') || '',
contact_person: $('cContact').value.trim(),
contact_phone: $('cPhone').value.trim(),
contact_email: $('cEmail').value.trim(),
address: $('cAddress').value.trim()
};
if (!form.tenant_name) { showMsg('请填写公司名称'); return; }
if (!/^[0-9A-Z]{18}$/.test(form.credit_code.toUpperCase())) { showMsg('请填写 18 位统一社会信用代码'); return; }
form.credit_code = form.credit_code.toUpperCase();
if (!form.legal_person) { showMsg('请填写法定代表人姓名'); return; }
if (!form.license_file) { showMsg('请上传营业执照电子档'); return; }
if (!form.contact_person) { showMsg('请填写联系人'); return; }
if (!/^1[3-9]\d{9}$/.test(form.contact_phone)) { showMsg('请填写正确的联系电话'); return; }
if (!form.contact_email || form.contact_email.indexOf('@') < 0) { showMsg('请填写正确的电子邮箱'); return; }
if (!form.address) { showMsg('请填写公司地址'); return; }
if (!confirm('提交后,当前注册账号将成为「' + form.tenant_name + '」的管理员账号,该绑定不可更改。确定提交并等待平台审核吗?')) return;
var btn = this; btn.disabled = true;
post('/auth/register/apply-create', form, function (res) {
btn.disabled = false;
if (res.code !== 200) { showMsg(res.msg || '提交失败'); return; }
done('申请已提交', '创建企业的申请已提交,请等待平台审核;审核通过后当前账号将成为企业管理员账号。', res.redirect || buildLoginURL(''));
});
});
// ---------- 暂不加入 ----------
$('btnSkip').addEventListener('click', function () {
if (!confirm('暂不加入企业将直接完成注册,之后可在登录后申请加入。确定吗?')) return;
post('/auth/register/finish', { token: state.token }, function (res) {
if (res.code !== 200) { showMsg(res.msg || '操作失败'); return; }
done('注册成功', '账号已创建。你当前未加入任何企业,可稍后申请加入。', res.redirect || buildLoginURL(''));
});
});
// 回登录页时透传 client_id/redirect
(function keepOAuthParams() {
if (!CLIENT_ID && !REDIRECT) return;
var suffix = (CLIENT_ID ? 'client_id=' + encodeURIComponent(CLIENT_ID) : '') +
(REDIRECT ? (CLIENT_ID ? '&' : '') + 'redirect=' + encodeURIComponent(REDIRECT) : '');
['toLogin', 'toForgot'].forEach(function (id) {
var a = $(id);
if (a) a.href = a.getAttribute('href') + (a.getAttribute('href').indexOf('?') >= 0 ? '&' : '?') + suffix;
});
})();
})();
</script>
</body>
</html>