Quellcode durchsuchen

登录注册修改

“陈博论” vor 9 Monaten
Ursprung
Commit
c0e7be2d4a
3 geänderte Dateien mit 436 neuen und 483 gelöschten Zeilen
  1. 68 82
      web/src/views/frontend/Register.vue
  2. 20 35
      web/src/views/frontend/Reset.vue
  3. 348 366
      web/src/views/frontend/user/login.vue

+ 68 - 82
web/src/views/frontend/Register.vue

@@ -10,13 +10,8 @@
           已有账号?<router-link to="/user/login">立即登录</router-link>
         </div>
       </div>
-      <el-form
-        ref="registerFormRef"
-        :model="registerForm"
-        :rules="registerRules"
-        label-position="top"
-        class="client-register__form"
-      >
+      <el-form ref="registerFormRef" :model="registerForm" :rules="registerRules" label-position="top"
+        class="client-register__form">
         <el-form-item label="联系人姓名" prop="name">
           <el-input v-model.trim="registerForm.name" placeholder="请输入联系人姓名" clearable />
         </el-form-item>
@@ -27,19 +22,10 @@
 
         <el-form-item label="邮箱验证码" prop="emailCode">
           <div class="client-register__code-row">
-            <el-input
-              class="client-register__code-input"
-              v-model.trim="registerForm.emailCode"
-              placeholder="请输入6位验证码"
-              maxlength="6"
-            />
-            <el-button
-              class="client-register__code-btn"
-              type="primary"
-              :loading="sendingCode"
-              :disabled="codeDisabled"
-              @click="handleSendEmailCode"
-            >
+            <el-input class="client-register__code-input" v-model.trim="registerForm.emailCode" placeholder="请输入6位验证码"
+              maxlength="6" />
+            <el-button class="client-register__code-btn" type="primary" :loading="sendingCode" :disabled="codeDisabled"
+              @click="handleSendEmailCode">
               {{ codeButtonText }}
             </el-button>
           </div>
@@ -63,7 +49,7 @@
           </el-button>
         </el-form-item>
         <p class="client-register__agreement">
-          @2019-2025 成都聚德鼎盛文化传播有限公司 蜀ICP备19030658号-1
+          @2019-2026 成都聚德鼎盛文化传播有限公司 蜀ICP备19030658号-1
         </p>
       </el-form>
     </div>
@@ -201,7 +187,7 @@ const handleSendEmailCode = () => {
     ElMessage.warning('请输入邮箱地址')
     return
   }
-  
+
   registerFormRef.value.validateField('email').then((valid) => {
     if (!valid) {
       // 验证失败,Element Plus 会自动显示错误信息
@@ -236,116 +222,116 @@ onBeforeUnmount(() => {
 
 <style scoped>
 .client-register {
-	min-height: 100vh;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	padding: 48px 16px;
-	background: url('/@/assets/images/login_bg.jpg') center center / cover no-repeat;
+  min-height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 48px 16px;
+  background: url('/@/assets/images/login_bg.jpg') center center / cover no-repeat;
 }
 
 .client-register__panel {
-	width: 520px;
-	max-width: 100%;
-	padding: 28px 36px 24px;
-	background: #fff;
-	border-radius: 16px;
-	box-shadow: 0 15px 35px rgba(0, 0, 0, 0.08);
+  width: 520px;
+  max-width: 100%;
+  padding: 28px 36px 24px;
+  background: #fff;
+  border-radius: 16px;
+  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.08);
 }
 
 .client-register__header {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 20px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
 }
 
 .client-register__header h2 {
-	margin: 0;
-	font-size: 22px;
-	color: #303133;
+  margin: 0;
+  font-size: 22px;
+  color: #303133;
 }
 
 .client-register__header p {
-	margin: 6px 0 0;
-	color: #909399;
+  margin: 6px 0 0;
+  color: #909399;
 }
 
 .client-register__header-link {
-	font-size: 14px;
-	color: #606266;
+  font-size: 14px;
+  color: #606266;
 }
 
 .client-register__header-link a {
-	color: #409eff;
-	margin-left: 4px;
+  color: #409eff;
+  margin-left: 4px;
 }
 
 .client-register__form ::v-deep .el-form-item__label {
-	font-weight: 500;
-	color: #303133;
+  font-weight: 500;
+  color: #303133;
 }
 
 .client-register__form :deep(.el-form-item) {
-	margin-bottom: 18px;
+  margin-bottom: 18px;
 }
 
 .client-register__form :deep(.el-input) {
-	width: 100%;
+  width: 100%;
 }
 
 .client-register__code-row {
-	display: flex;
-	align-items: stretch;
-	width: 100%;
+  display: flex;
+  align-items: stretch;
+  width: 100%;
 }
 
 .client-register__code-input {
-	flex: 1;
+  flex: 1;
 }
 
 .client-register__code-btn {
-	white-space: nowrap;
-	margin-left: -1px;
-	min-width: 128px;
-	border-radius: 0 8px 8px 0;
+  white-space: nowrap;
+  margin-left: -1px;
+  min-width: 128px;
+  border-radius: 0 8px 8px 0;
 }
 
 .client-register__code-input :deep(.el-input__wrapper) {
-	border-radius: 8px 0 0 8px;
+  border-radius: 8px 0 0 8px;
 }
 
 .client-register__submit {
-	width: 100%;
-	height: 44px;
-	font-size: 15px;
+  width: 100%;
+  height: 44px;
+  font-size: 15px;
 }
 
 .client-register__agreement {
-	margin: -8px 0 0;
-	font-size: 12px;
-	color: #909399;
-	text-align: center;
+  margin: -8px 0 0;
+  font-size: 12px;
+  color: #909399;
+  text-align: center;
 }
 
 .client-register__agreement a {
-	color: #409eff;
-	text-decoration: none;
+  color: #409eff;
+  text-decoration: none;
 }
 
 @media (max-width: 600px) {
-	.client-register {
-		padding: 24px 12px;
-	}
-
-	.client-register__panel {
-		padding: 24px 20px;
-	}
-
-	.client-register__header {
-		flex-direction: column;
-		align-items: flex-start;
-		gap: 6px;
-	}
+  .client-register {
+    padding: 24px 12px;
+  }
+
+  .client-register__panel {
+    padding: 24px 20px;
+  }
+
+  .client-register__header {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 6px;
+  }
 }
 </style>

+ 20 - 35
web/src/views/frontend/Reset.vue

@@ -11,32 +11,18 @@
         </div>
       </div>
 
-      <el-form
-        ref="resetFormRef"
-        :model="resetForm"
-        :rules="resetRules"
-        label-position="top"
-        class="client-reset__form"
-      >
+      <el-form ref="resetFormRef" :model="resetForm" :rules="resetRules" label-position="top"
+        class="client-reset__form">
         <el-form-item label="注册邮箱" prop="email">
           <el-input v-model.trim="resetForm.email" placeholder="请输入注册邮箱" clearable />
         </el-form-item>
 
         <el-form-item label="邮箱验证码" prop="emailCode">
           <div class="client-reset__code-row">
-            <el-input
-              class="client-reset__code-input"
-              v-model.trim="resetForm.emailCode"
-              placeholder="请输入6位验证码"
-              maxlength="6"
-            />
-            <el-button
-              class="client-reset__code-btn"
-              type="primary"
-              :loading="sendingCode"
-              :disabled="codeDisabled"
-              @click="handleSendEmailCode"
-            >
+            <el-input class="client-reset__code-input" v-model.trim="resetForm.emailCode" placeholder="请输入6位验证码"
+              maxlength="6" />
+            <el-button class="client-reset__code-btn" type="primary" :loading="sendingCode" :disabled="codeDisabled"
+              @click="handleSendEmailCode">
               {{ codeButtonText }}
             </el-button>
           </div>
@@ -56,7 +42,7 @@
           </el-button>
         </el-form-item>
         <p class="client-reset__tips">
-          @2019-2025 成都聚德鼎盛文化传播有限公司 蜀ICP备19030658号-1
+          @2019-2026 成都聚德鼎盛文化传播有限公司 蜀ICP备19030658号-1
         </p>
       </el-form>
     </div>
@@ -146,7 +132,7 @@ const handleReset = () => {
       // TODO: 接入后端重置密码接口
       await new Promise(resolve => setTimeout(resolve, 600))
       ElMessage.success('密码已重置,请使用新密码登录')
-      router.push({ path: '/user/login', query: { email: resetForm.email.trim() }})
+      router.push({ path: '/user/login', query: { email: resetForm.email.trim() } })
     } catch (error) {
       ElMessage.error(error?.message || '重置失败,请稍后重试')
     } finally {
@@ -162,7 +148,7 @@ const handleSendEmailCode = () => {
     ElMessage.warning('请输入邮箱地址')
     return
   }
-  
+
   resetFormRef.value.validateField('email').then(async (valid) => {
     if (!valid) {
       // 验证失败,Element Plus 会自动显示错误信息
@@ -240,32 +226,32 @@ onBeforeUnmount(() => {
 }
 
 .client-reset__form :deep(.el-form-item) {
-	margin-bottom: 18px;
+  margin-bottom: 18px;
 }
 
 .client-reset__form :deep(.el-input) {
-	width: 100%;
+  width: 100%;
 }
 
 .client-reset__code-row {
-	display: flex;
-	align-items: stretch;
-	width: 100%;
+  display: flex;
+  align-items: stretch;
+  width: 100%;
 }
 
 .client-reset__code-input {
-	flex: 1;
+  flex: 1;
 }
 
 .client-reset__code-btn {
-	white-space: nowrap;
-	margin-left: -1px;
-	min-width: 128px;
-	border-radius: 0 8px 8px 0;
+  white-space: nowrap;
+  margin-left: -1px;
+  min-width: 128px;
+  border-radius: 0 8px 8px 0;
 }
 
 .client-reset__code-input :deep(.el-input__wrapper) {
-	border-radius: 8px 0 0 8px;
+  border-radius: 8px 0 0 8px;
 }
 
 .client-reset__submit {
@@ -298,4 +284,3 @@ onBeforeUnmount(() => {
   }
 }
 </style>
-

+ 348 - 366
web/src/views/frontend/user/login.vue

@@ -1,379 +1,361 @@
 <template>
-    <div class="client-login">
-      <div class="client-login__panel">
-        <h1 class="client-login__title">用户登录</h1>
-        <p class="client-login__subtitle">探索并购买前沿AI工具,赋能您的效率与创意</p>
-        <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="client-login__form" @submit.prevent>
-          <el-form-item prop="username">
-            <el-input 
-              v-model="loginForm.username" 
-              placeholder="请输入账号" 
-              size="large"
-              clearable
-            >
-              <template #prefix>
-                <Icon name="fa fa-user" size="16" color="var(--el-input-icon-color)" />
-              </template>
-            </el-input>
-          </el-form-item>
-          <el-form-item prop="password">
-            <el-input 
-              v-model="loginForm.password" 
-              type="password" 
-              placeholder="请输入密码"
-              size="large"
-              show-password 
-              @keyup.enter="handleLogin"
-            >
-              <template #prefix>
-                <Icon name="fa fa-unlock-alt" size="16" color="var(--el-input-icon-color)" />
-              </template>
-            </el-input>
-          </el-form-item>
-          <el-form-item>
-            <el-button 
-              :loading="loading" 
-              type="primary" 
-              class="client-login__button" 
-              size="large"
-              round
-              @click="handleLogin"
-            >
-              登录
-            </el-button>
-          </el-form-item>
-        </el-form>
-        <div class="client-login__links">
-          <router-link to="/user/reset">
-            忘记密码?
-          </router-link>
-        </div>
-        <div class="client-login__actions">
-          <span>还没有账号?</span>
-          <router-link to="/user/register">立即注册</router-link>
-        </div>
+  <div class="client-login">
+    <div class="client-login__panel">
+      <h1 class="client-login__title">用户登录</h1>
+      <p class="client-login__subtitle">探索并购买前沿AI工具,赋能您的效率与创意</p>
+      <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="client-login__form" @submit.prevent>
+        <el-form-item prop="username">
+          <el-input v-model="loginForm.username" placeholder="请输入邮箱" size="large" clearable>
+            <template #prefix>
+              <Icon name="fa fa-user" size="16" color="var(--el-input-icon-color)" />
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input v-model="loginForm.password" type="password" placeholder="请输入密码" size="large" show-password
+            @keyup.enter="handleLogin">
+            <template #prefix>
+              <Icon name="fa fa-unlock-alt" size="16" color="var(--el-input-icon-color)" />
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button :loading="loading" type="primary" class="client-login__button" size="large" round
+            @click="handleLogin">
+            登录
+          </el-button>
+        </el-form-item>
+      </el-form>
+      <div class="client-login__links">
+        <router-link to="/user/reset">
+          忘记密码?
+        </router-link>
+      </div>
+      <div class="client-login__actions">
+        <span>还没有账号?</span>
+        <router-link to="/user/register">立即注册</router-link>
       </div>
     </div>
-  </template>
-  
-  <script setup>
-  import { ref, reactive, watch, onMounted } from 'vue'
-  import { useRouter, useRoute } from 'vue-router'
-  import { useUserInfo } from '/@/stores/userInfo'
-  import { checkIn } from '/@/api/frontend/user/index'
-  import { uuid } from '/@/utils/random'
-  import clickCaptcha from '/@/components/clickCaptcha'
-  import Icon from '/@/components/icon/index.vue'
-  
-  defineOptions({
-    name: 'ClientLogin'
-  })
-  
-  const router = useRouter()
-  const route = useRoute()
-  const userInfo = useUserInfo()
-  
-  const loginFormRef = ref(null)
-  const loading = ref(false)
-  const redirect = ref(undefined)
-  const otherQuery = ref({})
-  
-  // 验证码开关
-  const userLoginCaptchaSwitch = ref(true)
-  
-  // 登录成功后要跳转的URL
-  const to = ref(Array.isArray(route.query.to) ? route.query.to[0] : (route.query.to || ''))
-  
-  const loginForm = reactive({
-    username: '',
-    password: '',
-    keep: false,
-    captchaId: uuid(),
-    captchaInfo: ''
-  })
-  
-  const validateUsername = (rule, value, callback) => {
-    if (!value) {
-      callback(new Error('请输入账号'))
-    } else {
-      callback()
-    }
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, watch, onMounted } from 'vue'
+import { useRouter, useRoute } from 'vue-router'
+import { useUserInfo } from '/@/stores/userInfo'
+import { checkIn } from '/@/api/frontend/user/index'
+import { uuid } from '/@/utils/random'
+import clickCaptcha from '/@/components/clickCaptcha'
+import Icon from '/@/components/icon/index.vue'
+
+defineOptions({
+  name: 'ClientLogin'
+})
+
+const router = useRouter()
+const route = useRoute()
+const userInfo = useUserInfo()
+
+const loginFormRef = ref(null)
+const loading = ref(false)
+const redirect = ref(undefined)
+const otherQuery = ref({})
+
+// 验证码开关
+const userLoginCaptchaSwitch = ref(true)
+
+// 登录成功后要跳转的URL
+const to = ref(Array.isArray(route.query.to) ? route.query.to[0] : (route.query.to || ''))
+
+const loginForm = reactive({
+  username: '',
+  password: '',
+  keep: false,
+  captchaId: uuid(),
+  captchaInfo: ''
+})
+
+const validateUsername = (rule, value, callback) => {
+  if (!value) {
+    callback(new Error('请输入邮箱'))
+  } else {
+    callback()
+  }
+}
+
+const validatePassword = (rule, value, callback) => {
+  if (!value) {
+    callback(new Error('请输入密码'))
+  } else if (value.length < 6) {
+    callback(new Error('密码长度不能小于6位'))
+  } else {
+    callback()
   }
-  
-  const validatePassword = (rule, value, callback) => {
-    if (!value) {
-      callback(new Error('请输入密码'))
-    } else if (value.length < 6) {
-      callback(new Error('密码长度不能小于6位'))
+}
+
+const loginRules = reactive({
+  username: [{ required: true, trigger: 'blur', validator: validateUsername }],
+  password: [{ required: true, trigger: 'blur', validator: validatePassword }]
+})
+
+const getOtherQuery = (query) => {
+  return Object.keys(query).reduce((acc, cur) => {
+    if (cur !== 'redirect' && cur !== 'to') {
+      acc[cur] = query[cur]
+    }
+    return acc
+  }, {})
+}
+
+// 提交登录前的预处理(验证码检查)
+const handleLogin = () => {
+  if (!loginFormRef.value) return
+
+  loginFormRef.value.validate((valid) => {
+    if (!valid) return
+
+    // 如果启用了验证码,先进行验证码验证
+    if (userLoginCaptchaSwitch.value) {
+      clickCaptcha(loginForm.captchaId, (captchaInfo) => {
+        onSubmit(captchaInfo)
+      })
     } else {
-      callback()
+      onSubmit()
     }
-  }
-  
-  const loginRules = reactive({
-    username: [{ required: true, trigger: 'blur', validator: validateUsername }],
-    password: [{ required: true, trigger: 'blur', validator: validatePassword }]
   })
-  
-  const getOtherQuery = (query) => {
-    return Object.keys(query).reduce((acc, cur) => {
-      if (cur !== 'redirect' && cur !== 'to') {
-        acc[cur] = query[cur]
-      }
-      return acc
-    }, {})
-  }
-  
-  // 提交登录前的预处理(验证码检查)
-  const handleLogin = () => {
-    if (!loginFormRef.value) return
-    
-    loginFormRef.value.validate((valid) => {
-      if (!valid) return
-      
-      // 如果启用了验证码,先进行验证码验证
-      if (userLoginCaptchaSwitch.value) {
-        clickCaptcha(loginForm.captchaId, (captchaInfo) => {
-          onSubmit(captchaInfo)
-        })
-      } else {
-        onSubmit()
-      }
-    })
-  }
-  
-  // 提交登录
-  const onSubmit = (captchaInfo = '') => {
-    loading.value = true
-    loginForm.captchaInfo = captchaInfo
-    
-    checkIn('post', {
-      tab: 'login',
-      username: loginForm.username,
-      password: loginForm.password,
-      keep: loginForm.keep,
-      captchaId: loginForm.captchaId,
-      captchaInfo: loginForm.captchaInfo
-    }).then((res) => {
-      // 登录成功,更新用户信息
-      if (res.data && res.data.userInfo) {
-        userInfo.dataFill(res.data.userInfo, false)
-      }
-      
-      // 如果有指定的跳转URL,则跳转
-      if (to.value) {
-        location.href = to.value
-        return
-      }
-      
-      // 使用返回的routePath或redirect指定的页面
-      router.push({
-        path: res.data?.routePath || redirect.value || '/user/home',
-        query: otherQuery.value
-      })
-    }).catch(() => {
-      // 登录失败,错误信息由 axios 拦截器处理
-      // 如果验证失败,重新生成验证码ID
-      if (userLoginCaptchaSwitch.value) {
-        loginForm.captchaId = uuid()
-      }
-    }).finally(() => {
-      loading.value = false
-    })
-  }
-  
-  // 监听路由变化
-  watch(
-    () => route.query,
-    (query) => {
-      if (query) {
-        redirect.value = query.redirect
-        to.value = Array.isArray(query.to) ? query.to[0] : (query.to || '')
-        otherQuery.value = getOtherQuery(query)
-      }
-    },
-    { immediate: true }
-  )
-  
-  // 组件挂载时获取登录配置
-  onMounted(() => {
-    checkIn('get').then((res) => {
-      if (res.data) {
-        userLoginCaptchaSwitch.value = res.data.userLoginCaptchaSwitch !== undefined 
-          ? res.data.userLoginCaptchaSwitch 
-          : true
-      }
+}
+
+// 提交登录
+const onSubmit = (captchaInfo = '') => {
+  loading.value = true
+  loginForm.captchaInfo = captchaInfo
+
+  checkIn('post', {
+    tab: 'login',
+    username: loginForm.username,
+    password: loginForm.password,
+    keep: loginForm.keep,
+    captchaId: loginForm.captchaId,
+    captchaInfo: loginForm.captchaInfo
+  }).then((res) => {
+    // 登录成功,更新用户信息
+    if (res.data && res.data.userInfo) {
+      userInfo.dataFill(res.data.userInfo, false)
+    }
+
+    // 如果有指定的跳转URL,则跳转
+    if (to.value) {
+      location.href = to.value
+      return
+    }
+
+    // 使用返回的routePath或redirect指定的页面
+    router.push({
+      path: res.data?.routePath || redirect.value || '/',
+      query: otherQuery.value
     })
+  }).catch(() => {
+    // 登录失败,错误信息由 axios 拦截器处理
+    // 如果验证失败,重新生成验证码ID
+    if (userLoginCaptchaSwitch.value) {
+      loginForm.captchaId = uuid()
+    }
+  }).finally(() => {
+    loading.value = false
   })
-  </script>
-  
-  <style scoped>
-  .client-login {
-    min-height: 100vh;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    background: url('/@/assets/images/login_bg.jpg') center center / cover no-repeat;
-    position: relative;
-  }
-  
-  .client-login::before {
-    content: '';
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background: rgba(255, 255, 255, 0.1);
-    backdrop-filter: blur(2px);
-  }
-  
+}
+
+// 监听路由变化
+watch(
+  () => route.query,
+  (query) => {
+    if (query) {
+      redirect.value = query.redirect
+      to.value = Array.isArray(query.to) ? query.to[0] : (query.to || '')
+      otherQuery.value = getOtherQuery(query)
+    }
+  },
+  { immediate: true }
+)
+
+// 组件挂载时获取登录配置
+onMounted(() => {
+  checkIn('get').then((res) => {
+    if (res.data) {
+      userLoginCaptchaSwitch.value = res.data.userLoginCaptchaSwitch !== undefined
+        ? res.data.userLoginCaptchaSwitch
+        : true
+    }
+  })
+})
+</script>
+
+<style scoped>
+.client-login {
+  min-height: 100vh;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: url('/@/assets/images/login_bg.jpg') center center / cover no-repeat;
+  position: relative;
+}
+
+.client-login::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(255, 255, 255, 0.1);
+  backdrop-filter: blur(2px);
+}
+
+.client-login__panel {
+  width: 420px;
+  padding: 48px 40px 40px;
+  border-radius: 16px;
+  background: rgba(255, 255, 255, 0.98);
+  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+  backdrop-filter: blur(10px);
+  position: relative;
+  z-index: 1;
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+}
+
+.client-login__panel:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
+}
+
+.client-login__title {
+  margin: 0 0 8px 0;
+  font-size: 28px;
+  font-weight: 700;
+  text-align: center;
+  background: linear-gradient(135deg, #409eff 0%, #638fee 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+  letter-spacing: 0.5px;
+}
+
+.client-login__subtitle {
+  margin: 0 0 32px 0;
+  font-size: 14px;
+  text-align: center;
+  color: #909399;
+  line-height: 1.5;
+}
+
+.client-login__form {
+  margin-top: 8px;
+}
+
+.client-login__form :deep(.el-form-item) {
+  margin-bottom: 24px;
+}
+
+.client-login__form :deep(.el-input__wrapper) {
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+  transition: all 0.3s ease;
+}
+
+.client-login__form :deep(.el-input__wrapper:hover) {
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
+}
+
+.client-login__form :deep(.el-input.is-focus .el-input__wrapper) {
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.25);
+}
+
+.client-login__form :deep(.el-input__prefix) {
+  padding-left: 12px;
+}
+
+.client-login__actions {
+  margin-top: 20px;
+  font-size: 14px;
+  color: #606266;
+  text-align: center;
+}
+
+.client-login__actions a {
+  color: #409eff;
+  margin-left: 6px;
+  text-decoration: none;
+  transition: color 0.2s;
+  font-weight: 500;
+}
+
+.client-login__actions a:hover {
+  color: #66b1ff;
+}
+
+.client-login__button {
+  width: 100%;
+  height: 44px;
+  font-size: 16px;
+  font-weight: 600;
+  letter-spacing: 1px;
+  background: #409eff;
+  border: none;
+  transition: all 0.3s ease;
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
+}
+
+.client-login__button:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
+}
+
+.client-login__button:active {
+  transform: translateY(0);
+}
+
+.client-login__links {
+  margin-top: 8px;
+  margin-bottom: 8px;
+  display: flex;
+  justify-content: flex-end;
+  gap: 6px;
+  font-size: 13px;
+  color: #909399;
+}
+
+.client-login__links a {
+  display: inline-flex;
+  align-items: center;
+  gap: 4px;
+  color: #409eff;
+  text-decoration: none;
+  transition: all 0.2s;
+  font-weight: 500;
+}
+
+.client-login__links a:hover {
+  color: #66b1ff;
+  transform: translateX(2px);
+}
+
+.client-login__tips {
+  margin-top: 12px;
+  font-size: 12px;
+  color: #909399;
+  line-height: 1.6;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
   .client-login__panel {
-    width: 420px;
-    padding: 48px 40px 40px;
-    border-radius: 16px;
-    background: rgba(255, 255, 255, 0.98);
-    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
-    backdrop-filter: blur(10px);
-    position: relative;
-    z-index: 1;
-    transition: transform 0.3s ease, box-shadow 0.3s ease;
-  }
-  
-  .client-login__panel:hover {
-    transform: translateY(-2px);
-    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
+    width: 90%;
+    max-width: 420px;
+    padding: 36px 28px 32px;
   }
-  
+
   .client-login__title {
-    margin: 0 0 8px 0;
-    font-size: 28px;
-    font-weight: 700;
-    text-align: center;
-    background: linear-gradient(135deg, #409eff 0%, #638fee 100%);
-    -webkit-background-clip: text;
-    -webkit-text-fill-color: transparent;
-    background-clip: text;
-    letter-spacing: 0.5px;
-  }
-  
-  .client-login__subtitle {
-    margin: 0 0 32px 0;
-    font-size: 14px;
-    text-align: center;
-    color: #909399;
-    line-height: 1.5;
-  }
-  
-  .client-login__form {
-    margin-top: 8px;
-  }
-  
-  .client-login__form :deep(.el-form-item) {
-    margin-bottom: 24px;
-  }
-  
-  .client-login__form :deep(.el-input__wrapper) {
-    border-radius: 8px;
-    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
-    transition: all 0.3s ease;
-  }
-  
-  .client-login__form :deep(.el-input__wrapper:hover) {
-    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
-  }
-  
-  .client-login__form :deep(.el-input.is-focus .el-input__wrapper) {
-    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.25);
-  }
-  
-  .client-login__form :deep(.el-input__prefix) {
-    padding-left: 12px;
-  }
-  
-  .client-login__actions {
-    margin-top: 20px;
-    font-size: 14px;
-    color: #606266;
-    text-align: center;
-  }
-  
-  .client-login__actions a {
-    color: #409eff;
-    margin-left: 6px;
-    text-decoration: none;
-    transition: color 0.2s;
-    font-weight: 500;
-  }
-  
-  .client-login__actions a:hover {
-    color: #66b1ff;
-  }
-  
-  .client-login__button {
-    width: 100%;
-    height: 44px;
-    font-size: 16px;
-    font-weight: 600;
-    letter-spacing: 1px;
-    background: #409eff;
-    border: none;
-    transition: all 0.3s ease;
-    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
-  }
-  
-  .client-login__button:hover {
-    transform: translateY(-2px);
-    box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
-  }
-  
-  .client-login__button:active {
-    transform: translateY(0);
-  }
-  
-  .client-login__links {
-    margin-top: 8px;
-    margin-bottom: 8px;
-    display: flex;
-    justify-content: flex-end;
-    gap: 6px;
-    font-size: 13px;
-    color: #909399;
-  }
-  
-  .client-login__links a {
-    display: inline-flex;
-    align-items: center;
-    gap: 4px;
-    color: #409eff;
-    text-decoration: none;
-    transition: all 0.2s;
-    font-weight: 500;
-  }
-  
-  .client-login__links a:hover {
-    color: #66b1ff;
-    transform: translateX(2px);
-  }
-  
-  .client-login__tips {
-    margin-top: 12px;
-    font-size: 12px;
-    color: #909399;
-    line-height: 1.6;
-  }
-  
-  /* 响应式设计 */
-  @media (max-width: 768px) {
-    .client-login__panel {
-      width: 90%;
-      max-width: 420px;
-      padding: 36px 28px 32px;
-    }
-    
-    .client-login__title {
-      font-size: 24px;
-    }
+    font-size: 24px;
   }
-  </style>
-  
+}
+</style>