This commit is contained in:
张成
2025-12-19 15:54:52 +08:00
parent 4db1f77536
commit cfbcbc39fd
8 changed files with 1097 additions and 456 deletions

762
admin/public/register.html Normal file
View File

@@ -0,0 +1,762 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邀请注册</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.register-container {
background: #ffffff;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
padding: 40px 50px;
width: 100%;
max-width: 600px;
max-height: 95vh;
overflow-y: auto;
}
.register-header {
text-align: center;
margin-bottom: 20px;
}
.register-header h1 {
color: #333;
font-size: 24px;
font-weight: 600;
margin-bottom: 6px;
}
.register-header p {
color: #666;
font-size: 14px;
}
.invite-code-badge {
display: inline-block;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 13px;
margin-bottom: 20px;
font-weight: 500;
}
.invite-code-badge.hidden {
display: none;
}
.form-group {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 12px;
}
.form-label {
display: inline-block;
color: #333;
font-size: 15px;
font-weight: 500;
margin-bottom: 0;
margin-right: 15px;
min-width: 100px;
flex-shrink: 0;
}
.form-input {
flex: 1;
padding: 12px 16px;
border: 2px solid #e0e0e0;
border-radius: 10px;
font-size: 15px;
background: #fafafa;
}
.form-input:focus {
outline: none;
border-color: #667eea;
background: #fff;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-input.error {
border-color: #ff4757;
background: #fff5f5;
}
.sms-code-wrapper {
display: flex;
align-items: center;
flex: 1;
}
.form-group .sms-code-wrapper .form-input {
margin-right: 10px;
}
.send-code-btn {
padding: 12px 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
white-space: nowrap;
min-width: 120px;
}
.send-code-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.error-message {
color: #ff4757;
font-size: 13px;
margin-top: 6px;
margin-left: 0;
width: 100%;
flex-basis: 100%;
display: none;
padding-left: 115px;
line-height: 1.4;
}
.error-message.show {
display: block;
}
.submit-btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 10px;
position: relative;
overflow: hidden;
}
.submit-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.submit-btn.loading {
color: transparent;
}
.submit-btn.loading::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
top: 50%;
left: 50%;
margin-left: -10px;
margin-top: -10px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.success-message {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
display: none;
text-align: center;
font-size: 14px;
}
.success-message.show {
display: block;
}
.error-alert {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
display: none;
text-align: center;
font-size: 14px;
}
.error-alert.show {
display: block;
}
.register-tips {
margin-top: 15px;
padding: 12px 15px;
background: #f8f9fa;
border-radius: 10px;
border-left: 4px solid #667eea;
}
.register-tips h3 {
color: #333;
font-size: 13px;
font-weight: 600;
margin-bottom: 8px;
}
.register-tips ul {
list-style: none;
padding: 0;
margin: 0;
}
.register-tips li {
color: #666;
font-size: 12px;
line-height: 1.6;
padding-left: 18px;
position: relative;
margin-bottom: 3px;
}
.register-tips li::before {
content: '✓';
position: absolute;
left: 0;
color: #667eea;
font-weight: bold;
}
@media (max-width: 480px) {
.register-container {
padding: 30px 20px;
}
.register-header h1 {
font-size: 24px;
}
}
</style>
</head>
<body>
<div class="register-container">
<div class="register-header">
<h1>🎉 邀请注册</h1>
<p>填写信息完成注册,邀请人将获得奖励</p>
<div id="inviteCodeBadge" class="invite-code-badge hidden"></div>
</div>
<div id="successMessage" class="success-message"></div>
<div id="errorAlert" class="error-alert"></div>
<form id="registerForm">
<div class="form-group">
<label class="form-label" for="email">邮箱地址</label>
<input
type="email"
id="email"
class="form-input"
placeholder="请输入您的邮箱地址"
required
autocomplete="email"
/>
<div class="error-message" id="emailError"></div>
</div>
<div class="form-group">
<label class="form-label" for="emailCode">验证码</label>
<div class="sms-code-wrapper">
<input
type="text"
id="emailCode"
class="form-input"
placeholder="请输入邮箱验证码"
required
maxlength="6"
style="flex: 1; margin-right: 10px;"
/>
<button
type="button"
id="sendCodeBtn"
class="send-code-btn"
>
发送验证码
</button>
</div>
<div class="error-message" id="emailCodeError"></div>
</div>
<div class="form-group">
<label class="form-label" for="password">密码</label>
<input
type="password"
id="password"
class="form-input"
placeholder="请输入密码至少6位"
required
autocomplete="new-password"
minlength="6"
/>
<div class="error-message" id="passwordError"></div>
</div>
<div class="form-group">
<label class="form-label" for="confirmPassword">确认密码</label>
<input
type="password"
id="confirmPassword"
class="form-input"
placeholder="请再次输入密码"
required
autocomplete="new-password"
minlength="6"
/>
<div class="error-message" id="confirmPasswordError"></div>
</div>
<div class="form-group">
<label class="form-label" for="inviteCode">邀请码(选填)</label>
<input
type="text"
id="inviteCode"
class="form-input"
placeholder="请输入邀请码(可选)"
/>
<div class="error-message" id="inviteCodeError"></div>
</div>
<button type="submit" class="submit-btn" id="submitBtn">
立即注册
</button>
</form>
<div class="register-tips">
<h3>注册说明</h3>
<ul>
<li>邮箱将作为您的登录账号</li>
<li>密码长度至少6位建议使用字母+数字组合</li>
<li>邮箱验证码有效期为5分钟</li>
<li>邀请码为选填填写邀请码注册成功后邀请人将获得3天试用期奖励</li>
<li>请妥善保管您的账号信息</li>
</ul>
</div>
</div>
<script>
// 配置 API 地址(根据环境自动判断)
const API_BASE_URL = window.location.hostname === 'localhost'
? 'http://localhost:9097/admin_api'
: 'https://work.light120.com/admin_api';
// 获取 URL 参数中的邀请码
function getInviteCodeFromUrl() {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('code') || '';
}
// 倒计时状态
let countdownTimer = null;
let countdownSeconds = 0;
// 显示/隐藏消息
function showMessage(elementId, message, isError = false) {
const element = document.getElementById(elementId);
element.textContent = message;
element.className = isError ? 'error-alert show' : 'success-message show';
// 3秒后自动隐藏
setTimeout(() => {
element.className = isError ? 'error-alert' : 'success-message';
}, 3000);
}
// 显示邀请码徽章
function displayInviteCodeBadge(code) {
if (code) {
const badge = document.getElementById('inviteCodeBadge');
badge.textContent = `邀请码: ${code}`;
badge.classList.remove('hidden');
}
}
// 自动填充邀请码
function autoFillInviteCode(code) {
if (code) {
const inviteCodeInput = document.getElementById('inviteCode');
inviteCodeInput.value = code;
}
}
// 发送邮箱验证码
async function sendEmailCode(email) {
try {
const response = await fetch(`${API_BASE_URL}/invite/send-email-code`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email
})
});
const data = await response.json();
return data;
} catch (error) {
console.error('发送验证码失败:', error);
throw new Error('网络请求失败,请检查网络连接');
}
}
// 开始倒计时
function startCountdown(seconds = 60) {
const sendBtn = document.getElementById('sendCodeBtn');
countdownSeconds = seconds;
sendBtn.disabled = true;
const updateCountdown = () => {
if (countdownSeconds > 0) {
sendBtn.textContent = `${countdownSeconds}秒后重新发送`;
countdownSeconds--;
countdownTimer = setTimeout(updateCountdown, 1000);
} else {
sendBtn.disabled = false;
sendBtn.textContent = '发送验证码';
if (countdownTimer) {
clearTimeout(countdownTimer);
countdownTimer = null;
}
}
};
updateCountdown();
}
// 验证邮箱格式
function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// 显示字段错误
function showFieldError(fieldId, message) {
const input = document.getElementById(fieldId);
const errorDiv = document.getElementById(fieldId + 'Error');
input.classList.add('error');
errorDiv.textContent = message;
errorDiv.classList.add('show');
}
// 清除字段错误
function clearFieldError(fieldId) {
const input = document.getElementById(fieldId);
const errorDiv = document.getElementById(fieldId + 'Error');
input.classList.remove('error');
errorDiv.classList.remove('show');
}
// 验证表单
function validateForm() {
const inviteCode = document.getElementById('inviteCode').value.trim();
const email = document.getElementById('email').value.trim();
const emailCode = document.getElementById('emailCode').value.trim();
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
let isValid = true;
// 邀请码为选填,无需验证
// 验证邮箱
if (!email) {
showFieldError('email', '请输入邮箱地址');
isValid = false;
} else if (!validateEmail(email)) {
showFieldError('email', '邮箱格式不正确');
isValid = false;
} else {
clearFieldError('email');
}
// 验证邮箱验证码
if (!emailCode) {
showFieldError('emailCode', '请输入邮箱验证码');
isValid = false;
} else if (!/^\d{6}$/.test(emailCode)) {
showFieldError('emailCode', '验证码为6位数字');
isValid = false;
} else {
clearFieldError('emailCode');
}
// 验证密码
if (!password) {
showFieldError('password', '请输入密码');
isValid = false;
} else if (password.length < 6) {
showFieldError('password', '密码长度不能少于6位');
isValid = false;
} else {
clearFieldError('password');
}
// 验证确认密码
if (!confirmPassword) {
showFieldError('confirmPassword', '请再次输入密码');
isValid = false;
} else if (password !== confirmPassword) {
showFieldError('confirmPassword', '两次输入的密码不一致');
isValid = false;
} else {
clearFieldError('confirmPassword');
}
return isValid;
}
// 注册请求
async function register(email, emailCode, password, inviteCode) {
try {
const requestBody = {
email: email,
email_code: emailCode,
password: password
};
// 如果邀请码不为空,则添加到请求中
if (inviteCode) {
requestBody.invite_code = inviteCode;
}
const response = await fetch(`${API_BASE_URL}/invite/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody)
});
const data = await response.json();
return data;
} catch (error) {
console.error('注册请求失败:', error);
throw new Error('网络请求失败,请检查网络连接');
}
}
// 处理表单提交
async function handleSubmit(e) {
e.preventDefault();
// 清除之前的错误信息
document.getElementById('errorAlert').classList.remove('show');
document.getElementById('successMessage').classList.remove('show');
// 验证表单
if (!validateForm()) {
return;
}
const inviteCode = document.getElementById('inviteCode').value.trim();
const email = document.getElementById('email').value.trim();
const emailCode = document.getElementById('emailCode').value.trim();
const password = document.getElementById('password').value;
// 邀请码为选填,可以为空
// 禁用提交按钮
const submitBtn = document.getElementById('submitBtn');
submitBtn.disabled = true;
submitBtn.classList.add('loading');
try {
const result = await register(email, emailCode, password, inviteCode);
if (result.code === 0 || result.success) {
showMessage('successMessage', '注册成功!请使用邮箱和密码登录系统。');
// 清空表单
document.getElementById('registerForm').reset();
// 3秒后可以提示跳转如果需要
setTimeout(() => {
// 可以在这里添加跳转到登录页的逻辑
// window.location.href = '/login.html';
}, 3000);
} else {
showMessage('errorAlert', result.message || '注册失败,请重试', true);
}
} catch (error) {
showMessage('errorAlert', error.message || '注册失败,请稍后重试', true);
} finally {
submitBtn.disabled = false;
submitBtn.classList.remove('loading');
}
}
// 初始化
document.addEventListener('DOMContentLoaded', function() {
const inviteCodeFromUrl = getInviteCodeFromUrl();
// 自动填充邀请码
autoFillInviteCode(inviteCodeFromUrl);
// 显示邀请码徽章
if (inviteCodeFromUrl) {
displayInviteCodeBadge(inviteCodeFromUrl);
}
// 绑定表单提交事件
document.getElementById('registerForm').addEventListener('submit', handleSubmit);
// 发送验证码按钮事件
document.getElementById('sendCodeBtn').addEventListener('click', async function() {
const email = document.getElementById('email').value.trim();
// 验证邮箱
if (!email) {
showFieldError('email', '请先输入邮箱地址');
return;
}
if (!validateEmail(email)) {
showFieldError('email', '邮箱格式不正确');
return;
}
clearFieldError('email');
// 禁用按钮
const sendBtn = document.getElementById('sendCodeBtn');
sendBtn.disabled = true;
sendBtn.textContent = '发送中...';
try {
const result = await sendEmailCode(email);
if (result.code === 0 || result.success) {
showMessage('successMessage', '验证码已发送到您的邮箱,请查收');
startCountdown(60);
} else {
showMessage('errorAlert', result.message || '发送验证码失败,请重试', true);
sendBtn.disabled = false;
sendBtn.textContent = '发送验证码';
}
} catch (error) {
showMessage('errorAlert', error.message || '发送验证码失败,请稍后重试', true);
sendBtn.disabled = false;
sendBtn.textContent = '发送验证码';
}
});
// 实时验证
document.getElementById('email').addEventListener('blur', function() {
const email = this.value.trim();
if (email && !validateEmail(email)) {
showFieldError('email', '邮箱格式不正确');
} else {
clearFieldError('email');
}
});
document.getElementById('password').addEventListener('blur', function() {
const password = this.value;
if (password && password.length < 6) {
showFieldError('password', '密码长度不能少于6位');
} else {
clearFieldError('password');
}
});
document.getElementById('confirmPassword').addEventListener('blur', function() {
const password = document.getElementById('password').value;
const confirmPassword = this.value;
if (confirmPassword && password !== confirmPassword) {
showFieldError('confirmPassword', '两次输入的密码不一致');
} else {
clearFieldError('confirmPassword');
}
});
// 输入时清除错误
document.getElementById('email').addEventListener('input', function() {
if (!this.classList.contains('error')) return;
const email = this.value.trim();
if (email && validateEmail(email)) {
clearFieldError('email');
}
});
document.getElementById('password').addEventListener('input', function() {
if (!this.classList.contains('error')) return;
const password = this.value;
if (password && password.length >= 6) {
clearFieldError('password');
}
// 如果确认密码已输入,重新验证
const confirmPassword = document.getElementById('confirmPassword').value;
if (confirmPassword) {
if (password === confirmPassword) {
clearFieldError('confirmPassword');
} else {
showFieldError('confirmPassword', '两次输入的密码不一致');
}
}
});
document.getElementById('confirmPassword').addEventListener('input', function() {
if (!this.classList.contains('error')) return;
const password = document.getElementById('password').value;
const confirmPassword = this.value;
if (confirmPassword && password === confirmPassword) {
clearFieldError('confirmPassword');
}
});
document.getElementById('emailCode').addEventListener('input', function() {
if (!this.classList.contains('error')) return;
const emailCode = this.value.trim();
if (emailCode && /^\d{6}$/.test(emailCode)) {
clearFieldError('emailCode');
}
});
});
</script>
</body>
</html>

View File

@@ -25,8 +25,6 @@ import JobTypes from '@/views/work/job_types.vue'
// 首页模块
import HomeIndex from '@/views/home/index.vue'
// 邀请注册模块
import InviteRegister from '@/views/invite/invite_register.vue'
@@ -56,7 +54,8 @@ const componentMap = {
'system/version': Version,
'work/job_types': JobTypes,
'home/index': HomeIndex,
'invite/invite_register': InviteRegister,
}
export default componentMap

View File

@@ -1,359 +0,0 @@
<template>
<div class="invite-register-page">
<div class="register-container">
<Card class="register-card">
<div slot="title" class="card-title">
<Icon type="ios-person-add" size="24" />
<span>邀请注册</span>
</div>
<div class="register-form">
<!-- 邀请码提示 -->
<Alert v-if="inviteCode" type="success" show-icon style="margin-bottom: 20px;">
<span slot="desc">您正在通过邀请码 <strong>{{ inviteCode }}</strong> 进行注册</span>
</Alert>
<Alert v-else type="warning" show-icon style="margin-bottom: 20px;">
<span slot="desc">未检测到邀请码请通过邀请链接访问</span>
</Alert>
<Form ref="registerForm" :model="formData" :rules="formRules" :label-width="100">
<!-- 手机号 -->
<FormItem label="手机号" prop="phone">
<Input
v-model="formData.phone"
placeholder="请输入手机号"
:maxlength="11"
@on-blur="validatePhone"
>
<Icon type="ios-phone-portrait" slot="prefix" />
</Input>
</FormItem>
<!-- 密码 -->
<FormItem label="密码" prop="password">
<Input
v-model="formData.password"
type="password"
placeholder="请输入密码至少6位"
:maxlength="50"
password
>
<Icon type="ios-lock" slot="prefix" />
</Input>
</FormItem>
<!-- 确认密码 -->
<FormItem label="确认密码" prop="confirmPassword">
<Input
v-model="formData.confirmPassword"
type="password"
placeholder="请再次输入密码"
:maxlength="50"
password
>
<Icon type="ios-lock" slot="prefix" />
</Input>
</FormItem>
<!-- 短信验证码 -->
<FormItem label="短信验证码" prop="sms_code">
<div class="sms-code-wrapper">
<Input
v-model="formData.sms_code"
placeholder="请输入短信验证码"
:maxlength="6"
style="width: 200px;"
>
<Icon type="ios-keypad" slot="prefix" />
</Input>
<Button
:disabled="smsCodeDisabled"
:loading="smsCodeLoading"
@click="handleSendSmsCode"
style="margin-left: 10px;"
>
{{ smsCodeButtonText }}
</Button>
</div>
</FormItem>
<!-- 提交按钮 -->
<FormItem>
<Button
type="primary"
size="large"
:loading="registerLoading"
@click="handleRegister"
style="width: 100%;"
>
注册
</Button>
</FormItem>
</Form>
<!-- 注册说明 -->
<div class="register-tips">
<p><strong>注册说明</strong></p>
<ul>
<li>手机号将作为您的登录账号</li>
<li>密码长度至少6位建议使用字母+数字组合</li>
<li>短信验证码有效期为5分钟</li>
<li>注册成功后邀请人将获得3天试用期奖励</li>
</ul>
</div>
</div>
</Card>
</div>
</div>
</template>
<script>
import inviteRegisterServer from '@/api/invite/invite_register_server.js';
export default {
name: 'InviteRegister',
data() {
// 验证确认密码
const validateConfirmPassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请再次输入密码'));
} else if (value !== this.formData.password) {
callback(new Error('两次输入的密码不一致'));
} else {
callback();
}
};
return {
inviteCode: '', // 邀请码从URL参数获取
formData: {
phone: '',
password: '',
confirmPassword: '',
sms_code: ''
},
formRules: {
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '请再次输入密码', trigger: 'blur' },
{ validator: validateConfirmPassword, trigger: 'blur' }
],
sms_code: [
{ required: true, message: '请输入短信验证码', trigger: 'blur' },
{ pattern: /^\d{6}$/, message: '验证码为6位数字', trigger: 'blur' }
]
},
smsCodeLoading: false,
smsCodeDisabled: false,
smsCodeCountdown: 0,
registerLoading: false
};
},
computed: {
smsCodeButtonText() {
if (this.smsCodeCountdown > 0) {
return `${this.smsCodeCountdown}秒后重新获取`;
}
return '获取验证码';
}
},
mounted() {
// 从URL参数获取邀请码
this.getInviteCodeFromUrl();
},
methods: {
/**
* 从URL参数获取邀请码
*/
getInviteCodeFromUrl() {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
if (code) {
this.inviteCode = code;
} else {
this.$Message.warning('未检测到邀请码,请通过邀请链接访问');
}
},
/**
* 验证手机号
*/
validatePhone() {
this.$refs.registerForm.validateField('phone');
},
/**
* 发送短信验证码
*/
async handleSendSmsCode() {
// 先验证手机号
this.$refs.registerForm.validateField('phone', async (valid) => {
if (!valid) {
return;
}
if (!this.formData.phone) {
this.$Message.error('请先输入手机号');
return;
}
// 验证手机号格式
const phoneRegex = /^1[3-9]\d{9}$/;
if (!phoneRegex.test(this.formData.phone)) {
this.$Message.error('手机号格式不正确');
return;
}
this.smsCodeLoading = true;
try {
const result = await inviteRegisterServer.sendSmsCode(this.formData.phone);
if (result.code === 0) {
this.$Message.success('短信验证码已发送,请注意查收');
// 开始倒计时
this.startCountdown();
} else {
this.$Message.error(result.message || '发送短信验证码失败');
}
} catch (error) {
const errorMessage = error.response?.data?.message || error.message || '发送短信验证码失败';
this.$Message.error(errorMessage);
} finally {
this.smsCodeLoading = false;
}
});
},
/**
* 开始倒计时
*/
startCountdown() {
this.smsCodeCountdown = 60;
this.smsCodeDisabled = true;
const timer = setInterval(() => {
this.smsCodeCountdown--;
if (this.smsCodeCountdown <= 0) {
clearInterval(timer);
this.smsCodeDisabled = false;
}
}, 1000);
},
/**
* 注册
*/
async handleRegister() {
// 验证表单
this.$refs.registerForm.validate(async (valid) => {
if (!valid) {
return;
}
if (!this.inviteCode) {
this.$Message.error('邀请码不能为空,请通过邀请链接访问');
return;
}
this.registerLoading = true;
try {
const result = await inviteRegisterServer.register({
phone: this.formData.phone,
password: this.formData.password,
sms_code: this.formData.sms_code,
invite_code: this.inviteCode
});
if (result.code === 0) {
this.$Message.success('注册成功!');
// 延迟跳转到登录页面或提示用户登录
setTimeout(() => {
this.$Message.info('请使用注册的手机号和密码登录');
// 可以跳转到登录页面
// this.$router.push('/login');
}, 2000);
} else {
this.$Message.error(result.message || '注册失败');
}
} catch (error) {
const errorMessage = error.response?.data?.message || error.message || '注册失败';
this.$Message.error(errorMessage);
} finally {
this.registerLoading = false;
}
});
}
}
};
</script>
<style scoped>
.invite-register-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.register-container {
width: 100%;
max-width: 500px;
}
.register-card {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
border-radius: 8px;
overflow: hidden;
}
.card-title {
display: flex;
align-items: center;
gap: 10px;
font-size: 20px;
font-weight: 600;
color: #2d8cf0;
}
.register-form {
padding: 20px 0;
}
.sms-code-wrapper {
display: flex;
align-items: center;
}
.register-tips {
margin-top: 30px;
padding: 15px;
background: #f8f8f9;
border-radius: 4px;
border-left: 4px solid #2d8cf0;
}
.register-tips p {
margin: 0 0 10px 0;
font-weight: 600;
color: #515a6e;
}
.register-tips ul {
margin: 0;
padding-left: 20px;
color: #808695;
}
.register-tips ul li {
margin-bottom: 5px;
line-height: 1.6;
}
</style>

View File

@@ -7,7 +7,9 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const is_production = process.env.NODE_ENV === 'production' || process.argv.includes('--mode=production')
module.exports = {
entry: './src/main.js',
entry: {
main: './src/main.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash:8].js',
@@ -50,9 +52,30 @@ module.exports = {
},
plugins: [
new VueLoaderPlugin(),
// 主应用 HTML
new HtmlWebpackPlugin({
template: './public/index.html',
title: 'Admin Framework Demo'
title: 'Admin Framework Demo',
filename: 'index.html',
chunks: ['main']
}),
// 注册页面 HTML独立页面不依赖 webpack
new HtmlWebpackPlugin({
template: './public/register.html',
title: '邀请注册',
filename: 'register.html',
inject: false, // 不注入 webpack 生成的脚本
minify: is_production ? {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true
} : false
}),
...(is_production ? [
new MiniCssExtractPlugin({