登录、注册页样式修改
This commit is contained in:
15
fixHeader.js
15
fixHeader.js
@@ -1,7 +1,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require("fs");
|
||||||
const path = 'D:/骅锋/mall/layouts/admin/components/AdminHeader.uvue';
|
const path = "D:/骅锋/mall/layouts/admin/components/AdminHeader.uvue";
|
||||||
|
|
||||||
let text = fs.readFileSync(path, 'utf-8');
|
let text = fs.readFileSync(path, "utf-8");
|
||||||
|
|
||||||
const targetScript = `<script setup lang="uts">
|
const targetScript = `<script setup lang="uts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
@@ -63,7 +63,10 @@ function handleLogout() {
|
|||||||
|
|
||||||
const props = defineProps<{`;
|
const props = defineProps<{`;
|
||||||
|
|
||||||
text = text.replace(/<script setup lang=["']uts["']>[\s\S]*?const props = defineProps</, targetScript + "");
|
text = text.replace(
|
||||||
|
/<script setup lang=["']uts["']>[\s\S]*?const props = defineProps</,
|
||||||
|
targetScript + "",
|
||||||
|
);
|
||||||
|
|
||||||
fs.writeFileSync(path, text, 'utf-8');
|
fs.writeFileSync(path, text, "utf-8");
|
||||||
console.log('Done');
|
console.log("Done");
|
||||||
|
|||||||
15
fixUser.js
15
fixUser.js
@@ -1,7 +1,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require("fs");
|
||||||
const path = 'D:/骅锋/mall/pages/mall/admin/userCenter/index.uvue';
|
const path = "D:/骅锋/mall/pages/mall/admin/userCenter/index.uvue";
|
||||||
|
|
||||||
let text = fs.readFileSync(path, 'utf-8');
|
let text = fs.readFileSync(path, "utf-8");
|
||||||
|
|
||||||
const targetScript = `<script setup lang="uts">
|
const targetScript = `<script setup lang="uts">
|
||||||
import { reactive, computed, onMounted } from 'vue'
|
import { reactive, computed, onMounted } from 'vue'
|
||||||
@@ -135,9 +135,12 @@ const onSubmit = async () => {
|
|||||||
}
|
}
|
||||||
</script>`;
|
</script>`;
|
||||||
|
|
||||||
text = text.replace(/<script setup lang=["']uts["']>[\s\S]*?<\/script>/, targetScript);
|
text = text.replace(
|
||||||
|
/<script setup lang=["']uts["']>[\s\S]*?<\/script>/,
|
||||||
|
targetScript,
|
||||||
|
);
|
||||||
text = text.replace(/value="demo"/, ':value="userAccount"');
|
text = text.replace(/value="demo"/, ':value="userAccount"');
|
||||||
text = text.replace(/src="\/static\/logo\.png"/, ':src="avatarUrl"');
|
text = text.replace(/src="\/static\/logo\.png"/, ':src="avatarUrl"');
|
||||||
|
|
||||||
fs.writeFileSync(path, text, 'utf-8');
|
fs.writeFileSync(path, text, "utf-8");
|
||||||
console.log('Done');
|
console.log("Done");
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ onMounted(async () => {
|
|||||||
await ensureSupabaseReady()
|
await ensureSupabaseReady()
|
||||||
const mId = uni.getStorageSync('merchant_id') as string | null
|
const mId = uni.getStorageSync('merchant_id') as string | null
|
||||||
if (!mId) {
|
if (!mId) {
|
||||||
uni.showToast({ title: '未获取到商家信息,请重新登录', icon: 'none' })
|
uni.showToast({ title: '商家未获取到信息,请重新登录', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
formData.value.merchant_id = mId
|
formData.value.merchant_id = mId
|
||||||
|
|||||||
@@ -60,14 +60,18 @@
|
|||||||
@input="(e: any) => account = e.detail.value"
|
@input="(e: any) => account = e.detail.value"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="field">
|
<view class="field password-field">
|
||||||
<input
|
<input
|
||||||
class="input"
|
class="input"
|
||||||
type="password"
|
:type="isPasswordVisible ? 'text' : 'password'"
|
||||||
placeholder="密码"
|
placeholder="密码"
|
||||||
:value="password"
|
:value="password"
|
||||||
@input="(e: any) => password = e.detail.value"
|
@input="(e: any) => password = e.detail.value"
|
||||||
/>
|
/>
|
||||||
|
<view class="eye-btn" @click="isPasswordVisible = !isPasswordVisible">
|
||||||
|
<!-- 睁眼表示可见(type='text'), 闭眼表示不可见(type='password') -->
|
||||||
|
<text class="eye-icon">{{ isPasswordVisible ? '👁️' : '🙈' }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -163,6 +167,7 @@ const loginType = ref<number>(0)
|
|||||||
const account = ref<string>('')
|
const account = ref<string>('')
|
||||||
const password = ref<string>('')
|
const password = ref<string>('')
|
||||||
const captcha = ref<string>('')
|
const captcha = ref<string>('')
|
||||||
|
const isPasswordVisible = ref<boolean>(false)
|
||||||
|
|
||||||
const isLoading = ref<boolean>(false)
|
const isLoading = ref<boolean>(false)
|
||||||
|
|
||||||
@@ -170,32 +175,38 @@ const isLoading = ref<boolean>(false)
|
|||||||
* 【核心函数】:登录成功后,多条件校验是否为商家角色
|
* 【核心函数】:登录成功后,多条件校验是否为商家角色
|
||||||
* 优先级: session_uid (auth_id) -> id -> normalized email
|
* 优先级: session_uid (auth_id) -> id -> normalized email
|
||||||
*/
|
*/
|
||||||
const checkMerchantAccess = async (uid: string, rawEmail: string) : Promise<boolean> => {
|
const checkMerchantAccess = async (uid: string, rawEmail: string) : Promise<string | null> => {
|
||||||
const email = rawEmail.trim().toLowerCase()
|
const email = rawEmail.trim().toLowerCase()
|
||||||
console.log(`🔍 开始校验商家端角色 -> UID: ${uid}, Email: ${email}`)
|
console.log(`🔍 开始校验商家端角色 -> UID: ${uid}, Email: ${email}`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. 尝试按 auth_id 查询
|
// 1. 尝试按 auth_id 查询
|
||||||
let res = await supa.from('ak_users').select('role').eq('auth_id', uid).execute()
|
let res = await supa.from('ak_users').select('id, role').eq('auth_id', uid).execute()
|
||||||
let dataArray = res.data
|
let dataArray = res.data
|
||||||
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
||||||
const role = (dataArray[0] as UTSJSONObject).getString('role')
|
const obj = dataArray[0] as UTSJSONObject
|
||||||
|
const role = obj.getString('role')
|
||||||
|
const id = obj.getString('id')
|
||||||
console.log('✅ 按 auth_id 匹配成功,role:', role)
|
console.log('✅ 按 auth_id 匹配成功,role:', role)
|
||||||
return role === 'merchant'
|
if (role === 'merchant' && id != null) return id
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 尝试按 id 查询 (兼容老数据)
|
// 2. 尝试按 id 查询 (兼容老数据)
|
||||||
res = await supa.from('ak_users').select('role').eq('id', uid).execute()
|
res = await supa.from('ak_users').select('id, role').eq('id', uid).execute()
|
||||||
dataArray = res.data
|
dataArray = res.data
|
||||||
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
||||||
const role = (dataArray[0] as UTSJSONObject).getString('role')
|
const obj = dataArray[0] as UTSJSONObject
|
||||||
|
const role = obj.getString('role')
|
||||||
|
const id = obj.getString('id')
|
||||||
console.log('✅ 按 id 匹配成功,role:', role)
|
console.log('✅ 按 id 匹配成功,role:', role)
|
||||||
return role === 'merchant'
|
if (role === 'merchant' && id != null) return id
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 尝试按 email 兜底查询
|
// 3. 尝试按 email 兜底查询
|
||||||
if (email !== '') {
|
if (email !== '') {
|
||||||
res = await supa.from('ak_users').select('role').eq('email', email).execute()
|
res = await supa.from('ak_users').select('id, role').eq('email', email).execute()
|
||||||
dataArray = res.data
|
dataArray = res.data
|
||||||
|
|
||||||
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
if (Array.isArray(dataArray) && dataArray.length > 0) {
|
||||||
@@ -203,9 +214,12 @@ const checkMerchantAccess = async (uid: string, rawEmail: string) : Promise<bool
|
|||||||
if (dataArray.length > 1) {
|
if (dataArray.length > 1) {
|
||||||
console.error('⚠️ 警告: 按 email 查到多条 ak_users 记录,取第一条校验。Email:', email)
|
console.error('⚠️ 警告: 按 email 查到多条 ak_users 记录,取第一条校验。Email:', email)
|
||||||
}
|
}
|
||||||
const role = (dataArray[0] as UTSJSONObject).getString('role')
|
const obj = dataArray[0] as UTSJSONObject
|
||||||
|
const role = obj.getString('role')
|
||||||
|
const id = obj.getString('id')
|
||||||
console.log('✅ 按 email 匹配成功,role:', role)
|
console.log('✅ 按 email 匹配成功,role:', role)
|
||||||
return role === 'merchant'
|
if (role === 'merchant' && id != null) return id
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,6 +350,7 @@ const handleLogin = async () => {
|
|||||||
class_id: ''
|
class_id: ''
|
||||||
} as UserProfile
|
} as UserProfile
|
||||||
setUserProfile(adminProfile)
|
setUserProfile(adminProfile)
|
||||||
|
uni.setStorageSync('merchant_id', 'admin') // mock
|
||||||
|
|
||||||
uni.showToast({ title: '管理员登录成功', icon: 'success' })
|
uni.showToast({ title: '管理员登录成功', icon: 'success' })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -385,12 +400,15 @@ const handleLogin = async () => {
|
|||||||
const sessionUser = result.user
|
const sessionUser = result.user
|
||||||
let sessionUid = sessionUser?.getString('id') ?? ''
|
let sessionUid = sessionUser?.getString('id') ?? ''
|
||||||
|
|
||||||
const isMerchant = await checkMerchantAccess(sessionUid, account.value)
|
const merchantId = await checkMerchantAccess(sessionUid, account.value)
|
||||||
if (!isMerchant) {
|
if (merchantId == null) {
|
||||||
await supa.signOut()
|
await supa.signOut()
|
||||||
logout()
|
logout()
|
||||||
throw new Error('您还没有注册商家端账户,快去注册一个')
|
throw new Error('您还没有注册商家端账户,快去注册一个')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 存入商家ID
|
||||||
|
uni.setStorageSync('merchant_id', merchantId)
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: '手机号密码登录功能开发中', icon: 'none' })
|
uni.showToast({ title: '手机号密码登录功能开发中', icon: 'none' })
|
||||||
return
|
return
|
||||||
@@ -619,6 +637,24 @@ const handleQQLogin = () => uni.showToast({ title: 'QQ登录开发中', icon: 'n
|
|||||||
/* Form */
|
/* Form */
|
||||||
.form{ margin-top: 10px; }
|
.form{ margin-top: 10px; }
|
||||||
.field{ margin-bottom: 14px; }
|
.field{ margin-bottom: 14px; }
|
||||||
|
.password-field {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.eye-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 14px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
.eye-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
.input{
|
.input{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
|
|||||||
@@ -1,86 +1,97 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="register-wrapper">
|
<view class="page">
|
||||||
<!-- Header Logo -->
|
<!-- Header Logo -->
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<image :src="logoUrl" mode="aspectFit" class="logo" />
|
<view class="header-inner">
|
||||||
|
<image :src="logoUrl" mode="aspectFit" class="logo" />
|
||||||
|
<!-- 已有账号 -->
|
||||||
|
<view class="header-right">
|
||||||
|
<text class="tips-text">已有账号?</text>
|
||||||
|
<text class="tips-link" @click="navigateToLogin">立即登录</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 注册表单区域 -->
|
<!-- 注册表单区域 -->
|
||||||
<view class="register-box">
|
<view class="main">
|
||||||
<view class="title">注册账号</view>
|
<view class="register-box">
|
||||||
|
<text class="title">注册账号</text>
|
||||||
|
|
||||||
<!-- 注册表单 -->
|
<!-- 注册表单 -->
|
||||||
<view class="form-content">
|
<view class="form-content">
|
||||||
<!-- 邮箱 -->
|
<!-- 邮箱 -->
|
||||||
<view class="input-group">
|
<view class="input-group">
|
||||||
<view class="input-wrapper">
|
<view class="input-wrapper">
|
||||||
<image src="/static/user/phone_1.png" class="input-icon" />
|
<image src="/static/user/phone_1.png" class="input-icon" />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="输入邮箱"
|
placeholder="输入邮箱"
|
||||||
:value="email"
|
:value="email"
|
||||||
@input="(e: any) => email = e.detail.value"
|
@input="(e: any) => email = e.detail.value"
|
||||||
class="input-field"
|
class="input-field"
|
||||||
/>
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 密码 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<view class="input-wrapper">
|
||||||
|
<image src="/static/user/code_1.png" class="input-icon" />
|
||||||
|
<input
|
||||||
|
:type="isPasswordVisible ? 'text' : 'password'"
|
||||||
|
placeholder="填写密码"
|
||||||
|
:value="password"
|
||||||
|
@input="(e: any) => password = e.detail.value"
|
||||||
|
class="input-field"
|
||||||
|
/>
|
||||||
|
<view class="eye-btn" @click="isPasswordVisible = !isPasswordVisible">
|
||||||
|
<!-- 睁眼表示可见, 闭眼表示不可见 -->
|
||||||
|
<text class="eye-icon">{{ isPasswordVisible ? '👁️' : '🙈' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 确认密码 -->
|
||||||
|
<view class="input-group">
|
||||||
|
<view class="input-wrapper">
|
||||||
|
<image src="/static/user/code_1.png" class="input-icon" />
|
||||||
|
<input
|
||||||
|
:type="isConfirmPasswordVisible ? 'text' : 'password'"
|
||||||
|
placeholder="确认密码"
|
||||||
|
:value="confirmPassword"
|
||||||
|
@input="(e: any) => confirmPassword = e.detail.value"
|
||||||
|
class="input-field"
|
||||||
|
/>
|
||||||
|
<view class="eye-btn" @click="isConfirmPasswordVisible = !isConfirmPasswordVisible">
|
||||||
|
<text class="eye-icon">{{ isConfirmPasswordVisible ? '👁️' : '🙈' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 密码 -->
|
<!-- 注册按钮 -->
|
||||||
<view class="input-group">
|
<view class="register-btn" @click="handleRegister" :class="{ 'disabled': isLoading }">
|
||||||
<view class="input-wrapper">
|
<text class="btn-text">注册</text>
|
||||||
<image src="/static/user/code_1.png" class="input-icon" />
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
placeholder="填写密码"
|
|
||||||
:value="password"
|
|
||||||
@input="(e: any) => password = e.detail.value"
|
|
||||||
class="input-field"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 确认密码 -->
|
<!-- 协议勾选 -->
|
||||||
<view class="input-group">
|
<view class="protocol">
|
||||||
<view class="input-wrapper">
|
<checkbox-group class="protocol-group" @change="handleProtocolChange">
|
||||||
<image src="/static/user/code_1.png" class="input-icon" />
|
<checkbox
|
||||||
<input
|
:checked="protocol"
|
||||||
type="password"
|
class="protocol-checkbox"
|
||||||
placeholder="确认密码"
|
:class="{ 'trembling': inAnimation }"
|
||||||
:value="confirmPassword"
|
@animationend="inAnimation = false"
|
||||||
@input="(e: any) => confirmPassword = e.detail.value"
|
|
||||||
class="input-field"
|
|
||||||
/>
|
/>
|
||||||
</view>
|
<text class="protocol-text">
|
||||||
|
已阅读并同意
|
||||||
|
<text class="main-color" @click="navigateToTerms(3)">《用户协议》</text>
|
||||||
|
与
|
||||||
|
<text class="main-color" @click="navigateToTerms(4)">《隐私协议》</text>
|
||||||
|
</text>
|
||||||
|
</checkbox-group>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 注册按钮 -->
|
|
||||||
<view class="register-btn" @click="handleRegister" :class="{ 'disabled': isLoading }">
|
|
||||||
注册
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 已有账号 -->
|
|
||||||
<view class="tips">
|
|
||||||
<text class="tips-text">已有账号?</text>
|
|
||||||
<text class="tips-link" @click="navigateToLogin">立即登录</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 协议勾选 -->
|
|
||||||
<view class="protocol">
|
|
||||||
<checkbox-group @change="handleProtocolChange">
|
|
||||||
<checkbox
|
|
||||||
:checked="protocol"
|
|
||||||
:class="{ 'trembling': inAnimation }"
|
|
||||||
@animationend="inAnimation = false"
|
|
||||||
/>
|
|
||||||
<text class="protocol-text">
|
|
||||||
已阅读并同意
|
|
||||||
<text class="main-color" @click="navigateToTerms(3)">《用户协议》</text>
|
|
||||||
与
|
|
||||||
<text class="main-color" @click="navigateToTerms(4)">《隐私协议》</text>
|
|
||||||
</text>
|
|
||||||
</checkbox-group>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 底部版权信息 -->
|
<!-- 底部版权信息 -->
|
||||||
@@ -101,6 +112,8 @@
|
|||||||
const protocol = ref<boolean>(false)
|
const protocol = ref<boolean>(false)
|
||||||
const inAnimation = ref<boolean>(false)
|
const inAnimation = ref<boolean>(false)
|
||||||
const isLoading = ref<boolean>(false)
|
const isLoading = ref<boolean>(false)
|
||||||
|
const isPasswordVisible = ref<boolean>(false)
|
||||||
|
const isConfirmPasswordVisible = ref<boolean>(false)
|
||||||
const logoUrl = ref<string>('/static/logo.png')
|
const logoUrl = ref<string>('/static/logo.png')
|
||||||
|
|
||||||
// 处理协议勾选变化
|
// 处理协议勾选变化
|
||||||
@@ -314,176 +327,208 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
page {
|
/* Base Layout */
|
||||||
background: #F5F5F5;
|
.page {
|
||||||
}
|
|
||||||
|
|
||||||
.register-wrapper {
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: #F5F5F5;
|
background-color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header Logo */
|
/* Header Area */
|
||||||
.header {
|
.header {
|
||||||
padding: 40rpx 0 0 60rpx;
|
width: 100%;
|
||||||
background: #F5F5F5;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-inner {
|
||||||
|
width: min(1200px, 92vw);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 200rpx;
|
width: 180px;
|
||||||
height: 80rpx;
|
height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 注册表单区域 */
|
.header-right {
|
||||||
.register-box {
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips-text {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips-link {
|
||||||
|
font-size: 15px;
|
||||||
|
color: var(--view-theme, #FF4D4F);
|
||||||
|
margin-left: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main Form Area */
|
||||||
|
.main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: #FFFFFF;
|
display: flex;
|
||||||
margin: 60rpx 40rpx 0;
|
flex-direction: row;
|
||||||
border-radius: 8rpx;
|
justify-content: center;
|
||||||
padding: 60rpx 50rpx 40rpx;
|
align-items: flex-start;
|
||||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
padding-top: 80px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-box {
|
||||||
|
width: 420px;
|
||||||
|
max-width: 92vw;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 40rpx;
|
font-size: 26px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 50rpx;
|
margin-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 表单内容 */
|
/* Form Content */
|
||||||
.form-content {
|
.form-content {
|
||||||
margin-bottom: 40rpx;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-group {
|
.input-group {
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 24px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-wrapper {
|
.input-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 20rpx;
|
height: 48px;
|
||||||
height: 88rpx;
|
border: 1px solid #D9D9D9;
|
||||||
border: 1rpx solid #E0E0E0;
|
border-radius: 4px;
|
||||||
border-radius: 4rpx;
|
background-color: #FFFFFF;
|
||||||
background: #FFFFFF;
|
padding: 0 16px;
|
||||||
|
transition-property: border-color, box-shadow;
|
||||||
|
transition-duration: 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-wrapper:focus-within {
|
.input-wrapper:focus-within {
|
||||||
border-color: var(--view-theme, #FF4D4F);
|
border-color: var(--view-theme, #FF4D4F);
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-icon {
|
.input-icon {
|
||||||
width: 32rpx;
|
width: 22px;
|
||||||
height: 32rpx;
|
height: 22px;
|
||||||
flex-shrink: 0;
|
margin-right: 12px;
|
||||||
margin-right: 20rpx;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 28rpx;
|
height: 100%;
|
||||||
height: 88rpx;
|
font-size: 15px;
|
||||||
line-height: 88rpx;
|
|
||||||
color: #333333;
|
color: #333333;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-input {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 20rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: var(--view-theme, #FF4D4F);
|
|
||||||
font-size: 26rpx;
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
outline: none;
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-btn.disabled {
|
.input-field::placeholder {
|
||||||
|
color: #BFBFBF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Eye Button */
|
||||||
|
.eye-btn {
|
||||||
|
padding: 0 8px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eye-icon {
|
||||||
|
font-size: 18px;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 注册按钮 */
|
/* Register Button */
|
||||||
.register-btn {
|
.register-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
height: 48px;
|
||||||
margin-top: 50rpx;
|
margin-top: 10px;
|
||||||
background: linear-gradient(135deg, #FF4D4F 0%, #FF7A45 100%);
|
background: linear-gradient(90deg, var(--view-theme, #FF4D4F) 0%, #FF7A45 100%);
|
||||||
border-radius: 4rpx;
|
border-radius: 4px;
|
||||||
color: #FFFFFF;
|
cursor: pointer;
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
box-shadow: 0 4rpx 12rpx rgba(255, 77, 79, 0.3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-btn.disabled {
|
.register-btn.disabled {
|
||||||
background: #D9D9D9;
|
|
||||||
box-shadow: none;
|
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: #D9D9D9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 已有账号提示 */
|
.btn-text {
|
||||||
.tips {
|
color: #FFFFFF;
|
||||||
margin-top: 30rpx;
|
font-size: 16px;
|
||||||
display: flex;
|
font-weight: 500;
|
||||||
flex-direction: row;
|
letter-spacing: 2px;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips-text {
|
/* Protocol */
|
||||||
font-size: 28rpx;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-link {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: var(--view-theme, #FF4D4F);
|
|
||||||
margin-left: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 协议区域 */
|
|
||||||
.protocol {
|
.protocol {
|
||||||
margin-top: 40rpx;
|
margin-top: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol checkbox-group {
|
.protocol-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol checkbox {
|
.protocol-checkbox {
|
||||||
margin-right: 10rpx;
|
transform: scale(0.8);
|
||||||
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol-text {
|
.protocol-text {
|
||||||
font-size: 24rpx;
|
font-size: 13px;
|
||||||
color: #999999;
|
color: #666666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-color {
|
.main-color {
|
||||||
|
font-size: 13px;
|
||||||
color: var(--view-theme, #FF4D4F);
|
color: var(--view-theme, #FF4D4F);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trembling {
|
.trembling {
|
||||||
@@ -491,20 +536,43 @@ page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shake {
|
@keyframes shake {
|
||||||
0%, 100% { transform: translateX(0); }
|
0%, 100% { transform: translateX(0) scale(0.8); }
|
||||||
10%, 30%, 50%, 70%, 90% { transform: translateX(-10rpx); }
|
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px) scale(0.8); }
|
||||||
20%, 40%, 60%, 80% { transform: translateX(10rpx); }
|
20%, 40%, 60%, 80% { transform: translateX(4px) scale(0.8); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 底部版权 */
|
/* Footer */
|
||||||
.footer {
|
.footer {
|
||||||
padding: 40rpx 0;
|
padding: 40px 0;
|
||||||
text-align: center;
|
display: flex;
|
||||||
background: #F5F5F5;
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-text {
|
.footer-text {
|
||||||
font-size: 22rpx;
|
font-size: 13px;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.header-inner {
|
||||||
|
padding: 16px 20px;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
width: 140px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
.register-box {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user