Ver código fonte

使用 gemini 优化登录页面, 注册页面和忘记密码页面

reghao 17 horas atrás
pai
commit
9dd13bfed0

+ 1 - 2
.env.development

@@ -1,2 +1 @@
-VUE_APP_SERVER_URL=//reghao.cn
-VUE_APP_DEVOPS=0
+VUE_APP_SERVER_URL=//reghao.cn

+ 1 - 2
.env.production

@@ -1,2 +1 @@
-VUE_APP_SERVER_URL=//reghao.cn
-VUE_APP_DEVOPS=0
+VUE_APP_SERVER_URL=//reghao.cn

+ 0 - 18
build_devopsapp.sh

@@ -1,18 +0,0 @@
-#!/bin/bash
-
-#######################################################################################################################
-# 构建 devops 前端应用
-#######################################################################################################################
-
-# devops 后端域名
-# sed 替换字符串时使用 \ 对 . 字符进行转义
-backend_domain='devops\.alpha\.iquizoo\.com'
-sed -i "s/reghao\.cn/${backend_domain}/g" .env.production
-sed -i "s/VUE_APP_DEVOPS=0/VUE_APP_DEVOPS=1/g" .env.production
-
-commit_id=`git rev-parse HEAD | cut -c 1-8`
-npm run build
-docker build -t registry.cn-chengdu.aliyuncs.com/tnb028/devopsapp:${commit_id} .
-docker push registry.cn-chengdu.aliyuncs.com/tnb028/devopsapp:${commit_id}
-rm -rf dist
-git checkout .env.production

+ 0 - 8
src/assets/js/mixin.js

@@ -168,14 +168,6 @@ export const userMixin = {
         return
       }
 
-      const devops = process.env.VUE_APP_DEVOPS
-      if (!devops) {
-        if (this.userLogin.captchaCode === '' || this.userLogin.captchaCode === null) {
-          this.$message.warning('图形验证码不能为空')
-          return
-        }
-      }
-
       const credential = this.userLogin.credential
       this.userLogin.credential = this.encryptPassword(credential, this.pubkey, this.pubkeyR)
       // 显示加载效果

+ 103 - 44
src/components/layout/LoginBar.vue

@@ -1,39 +1,21 @@
 <template>
-  <el-row class="el-menu-demo">
-    <el-col :md="2">
-      <ul role="menubar" class="el-menu--horizontal el-menu">
-        <li role="menuitem" class="el-menu-item">
-          <a href="/" style="color: #007bff;text-decoration-line: none">
-            <img src="@/assets/img/logo.png" class="logo" alt="img">
-            tnbapp
-          </a>
-        </li>
-      </ul>
-    </el-col>
-    <el-col v-if="!devops" :md="8">
-      <el-menu
-        mode="horizontal"
-      >
-        <el-menu-item index="1">
-          <a href="/blog" style="text-decoration-line: none">
-            <span style="color: #007bff">Blog</span>
-          </a>
-        </el-menu-item>
-      </el-menu>
-    </el-col>
-<!--    <el-col :md="16">
-      <ul class="el-menu&#45;&#45;horizontal el-menu">
-        <li class="el-menu-item">
-        </li>
-      </ul>
-    </el-col>
-    <el-col :md="6">
-      <ul class="el-menu&#45;&#45;horizontal el-menu">
-        <li class="el-menu-item">
-        </li>
-      </ul>
-    </el-col>-->
-  </el-row>
+  <nav class="nav-container">
+    <div class="nav-content">
+      <div class="logo-wrapper">
+        <a href="/" class="logo-link">
+          <img src="@/assets/img/logo.png" class="logo-img" alt="logo">
+          <span class="brand-name hidden-xs">TNBAPP</span>
+        </a>
+      </div>
+
+      <div v-if="!devops" class="menu-wrapper">
+        <a href="/blog" class="nav-link">
+          <i class="el-icon-document"></i>
+          <span class="link-text hidden-xs">Blog</span>
+        </a>
+      </div>
+    </div>
+  </nav>
 </template>
 
 <script>
@@ -43,21 +25,98 @@ export default {
     return {
       devops: false
     }
-  },
-  created() {
-    this.devops = parseInt(process.env.VUE_APP_DEVOPS) === 1
-  },
-  methods: {
   }
 }
 </script>
 
 <style scoped>
-@media screen and (max-width: 768px) {
+.nav-container {
+  width: 100%;
+  height: 60px;
+  background-color: transparent;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 0 20px;
+  /* 默认保持绝对定位,在 PC 端悬浮感更强 */
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 100;
+  box-sizing: border-box;
+}
+
+.nav-content {
+  width: 100%;
+  max-width: 1200px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.logo-link {
+  display: flex;
+  align-items: center;
+  text-decoration: none;
+}
+
+.logo-img {
+  width: 32px;
+  height: 32px;
+  transition: transform 0.3s;
+}
+
+.brand-name {
+  font-size: 18px;
+  font-weight: 700;
+  color: #303133;
+  margin-left: 10px;
+  letter-spacing: 0.5px;
+}
+
+.nav-link {
+  text-decoration: none;
+  color: #606266;
+  font-size: 14px;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 12px;
+  border-radius: 20px;
+  transition: all 0.3s;
 }
 
-.logo {
-  width: 30px;
-  position: relative;
+.nav-link:hover {
+  background-color: rgba(64, 158, 255, 0.1);
+  color: #409EFF;
+}
+
+/* 适配逻辑 */
+@media screen and (max-width: 768px) {
+  .nav-container {
+    height: 54px;
+    /* 移动端改为相对定位,避免盖住下方的 Login 卡片 */
+    position: relative;
+    background-color: #fff; /* 移动端给个白底,更清晰 */
+    box-shadow: 0 1px 4px rgba(0,0,0,0.05);
+  }
+
+  .hidden-xs {
+    display: none; /* 核心适配:在手机端隐藏文字 */
+  }
+
+  .logo-img {
+    width: 28px;
+    height: 28px;
+  }
+
+  .nav-link {
+    padding: 6px; /* 缩小点击区域边距 */
+  }
+
+  .nav-link i {
+    font-size: 20px; /* 图标稍微加大,方便手指点击 */
+  }
 }
 </style>

+ 182 - 85
src/views/Forgot.vue

@@ -1,66 +1,84 @@
 <template>
-  <el-container>
-    <el-main>
-      <login-bar />
-      <router-view />
-      <el-row class="movie-list">
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-          <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px; text-align: center">
-            <el-card class="box-card">
-              <div slot="header" class="clearfix">
-                <span>找回密码</span>
-              </div>
-              <div class="text item">
-                <el-form ref="form" :model="userForgot" label-width="100px">
-                  <el-form-item label="邮箱/手机号" label-width="100px">
-                    <el-input
-                      v-model="userForgot.principal"
-                      placeholder="请输入邮箱或手机号"
-                      style="width: 45%; padding-right: 10px"
-                    />
-                    <el-button :disabled="isBtn" @click="forgotVerifyCode">{{ code }}</el-button>
-                  </el-form-item>
-                  <el-form-item label="验证码" label-width="90px">
-                    <el-input
-                      v-model="userForgot.verifyCode"
-                      placeholder="请输入短信验证码"
-                      style="padding-right: 1px"
-                    />
-                  </el-form-item>
-                  <el-form-item label="新密码">
-                    <el-input
-                      v-model="userForgot.newCredential"
-                      type="password"
-                      placeholder="请输入新密码"
-                      style="padding-right: 1px"
-                    />
-                  </el-form-item>
-                  <el-form-item label="图形验证码" label-width="90px">
-                    <el-image :src="captchaCode" @click="getCaptcha" />
-                    <el-input
-                      v-model="userForgot.captchaCode"
-                      placeholder="请输入图形验证码"
-                      style="width: 50%; padding-right: 10px"
-                    />
-                  </el-form-item>
-                  <el-form-item>
-                    <el-button
-                      type="primary"
-                      :loading="isLoading"
-                      @click.native="forgotBtn"
-                    >找回</el-button>
-                    <el-button type="plain" @click="login">返回登入</el-button>
-                  </el-form-item>
-                </el-form>
-              </div>
-            </el-card>
-          </el-row>
-        </el-col>
-      </el-row>
-    </el-main>
-  </el-container>
+  <div class="forgot-wrapper">
+    <login-bar />
+
+    <div class="forgot-container">
+      <el-card class="forgot-card" shadow="always">
+        <div class="forgot-title">找回密码</div>
+        <p class="forgot-subtitle">验证身份以重置您的登录密码</p>
+
+        <el-form ref="forgotForm" :model="userForgot" label-position="top" class="mt-20">
+          <el-form-item label="邮箱/手机号">
+            <div class="input-with-btn">
+              <el-input
+                  v-model="userForgot.principal"
+                  prefix-icon="el-icon-mobile-phone"
+                  placeholder="请输入邮箱或手机号"
+                  clearable
+              />
+              <el-button
+                  class="code-btn"
+                  :disabled="isBtn"
+                  @click="forgotVerifyCode"
+              >
+                {{ isBtn ? code + 's' : '获取验证码' }}
+              </el-button>
+            </div>
+          </el-form-item>
+
+          <el-form-item label="身份验证码">
+            <el-input
+                v-model="userForgot.verifyCode"
+                prefix-icon="el-icon-chat-dot-round"
+                placeholder="请输入 6 位数字验证码"
+                clearable
+            />
+          </el-form-item>
+
+          <el-form-item label="设置新密码">
+            <el-input
+                v-model="userForgot.newCredential"
+                prefix-icon="el-icon-key"
+                type="password"
+                placeholder="请输入新密码"
+                show-password
+                clearable
+            />
+          </el-form-item>
+
+          <el-form-item label="安全验证">
+            <div class="captcha-box">
+              <el-input
+                  v-model="userForgot.captchaCode"
+                  placeholder="图形验证码"
+                  @keyup.enter.native="forgotBtn"
+              />
+              <el-image
+                  class="captcha-img"
+                  :src="captchaCode"
+                  title="点击刷新"
+                  @click="getCaptcha"
+              />
+            </div>
+          </el-form-item>
+
+          <div class="action-buttons">
+            <el-button
+                type="primary"
+                class="submit-btn"
+                :loading="isLoading"
+                @click.native="forgotBtn"
+            >
+              提交重置
+            </el-button>
+            <div class="footer-link">
+              <el-button type="text" icon="el-icon-back" @click="login">返回登录</el-button>
+            </div>
+          </div>
+        </el-form>
+      </el-card>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -69,23 +87,12 @@ import LoginBar from 'components/layout/LoginBar'
 
 export default {
   name: 'Forgot',
-  components: {
-    LoginBar
-  },
+  components: { LoginBar },
   mixins: [userMixin],
-  watch: {
-    $route() {
-      this.$router.go()
-    }
-  },
   created() {
     document.title = '找回密码'
     this.fetchPubkey(3)
   },
-  data() {
-    return {
-    }
-  },
   methods: {
     login() {
       this.$router.push('/login')
@@ -94,19 +101,109 @@ export default {
 }
 </script>
 
-<style>
-/*处于手机屏幕时*/
-@media screen and (max-width: 768px){
-  .movie-list {
-    padding-top: 8px;
-    padding-left: 0.5%;
-    padding-right: 0.5%;
+<style scoped>
+.forgot-wrapper {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+  display: flex;
+  flex-direction: column;
+}
+
+.forgot-container {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+}
+
+.forgot-card {
+  width: 100%;
+  max-width: 420px;
+  border-radius: 12px;
+  border: none;
+  padding: 10px 15px;
+}
+
+.forgot-title {
+  text-align: center;
+  font-size: 24px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 8px;
+}
+
+.forgot-subtitle {
+  text-align: center;
+  color: #909399;
+  font-size: 14px;
+  margin-bottom: 20px;
+}
+
+.mt-20 { margin-top: 20px; }
+
+/* 布局辅助 */
+.input-with-btn {
+  display: flex;
+  gap: 10px;
+}
+
+.code-btn {
+  width: 120px;
+  flex-shrink: 0;
+}
+
+.captcha-box {
+  display: flex;
+  gap: 10px;
+  align-items: center;
+}
+
+.captcha-img {
+  width: 110px;
+  height: 40px;
+  cursor: pointer;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+}
+
+/* 按钮区 */
+.action-buttons {
+  margin-top: 30px;
+}
+
+.submit-btn {
+  width: 100%;
+  padding: 12px;
+  font-size: 16px;
+  border-radius: 8px;
+  letter-spacing: 2px;
+}
+
+.footer-link {
+  text-align: center;
+  margin-top: 15px;
+}
+
+/* 移动端特殊处理 */
+@media screen and (max-width: 480px) {
+  .forgot-card {
+    box-shadow: none;
+    background: transparent;
+  }
+  .forgot-container {
+    align-items: flex-start;
+    padding-top: 40px;
   }
 }
 
-.movie-list {
-  padding-top: 15px;
-  padding-left: 6%;
-  padding-right: 6%;
+/* 覆盖 ElementUI 默认边距 */
+/deep/ .el-form-item {
+  margin-bottom: 18px;
+}
+/deep/ .el-form-item__label {
+  line-height: 1;
+  padding-bottom: 8px;
+  font-weight: 500;
 }
 </style>

+ 213 - 170
src/views/Login.vue

@@ -1,141 +1,109 @@
 <template>
-  <el-container>
-    <el-main>
-      <login-bar />
-      <router-view />
-      <el-row v-if="devops" class="movie-list">
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-          <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px; text-align: center">
-            <el-card class="box-card">
-              <el-tabs v-model="activeName" @tab-click="tabClick">
-                <el-tab-pane name="login1">
-                  <span slot="label">密码登入</span>
-                  <div class="text item">
-                    <el-form ref="form" :model="userLogin" label-width="80px">
-                      <el-form-item label="帐号">
-                        <el-input
-                          v-model="userLogin.principal"
-                          placeholder="请输入帐号"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                      </el-form-item>
-                      <el-form-item label="密码">
-                        <el-input
-                          v-model="userLogin.credential"
-                          type="password"
-                          placeholder="请输入密码"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                      </el-form-item>
-                      <el-form-item>
-                        <el-button type="primary" size="mini" :loading="isLoading" @click.native="loginBtn">登 入</el-button>
-                        <el-button type="plain" size="mini" @click="forgot">忘记密码</el-button>
-                      </el-form-item>
-                    </el-form>
-                  </div>
-                </el-tab-pane>
-              </el-tabs>
-            </el-card>
-          </el-row>
-        </el-col>
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-      </el-row>
-      <el-row v-else class="movie-list">
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-          <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px; text-align: center">
-            <el-card class="box-card">
-              <el-tabs v-model="activeName" @tab-click="tabClick">
-                <el-tab-pane name="login1">
-                  <span slot="label">密码登入</span>
-                  <div class="text item">
-                    <el-form ref="form" :model="userLogin" label-width="80px">
-                      <el-form-item label="帐号">
-                        <el-input
-                          v-model="userLogin.principal"
-                          placeholder="请输入手机号或邮箱"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                      </el-form-item>
-                      <el-form-item label="密码">
-                        <el-input
-                          v-model="userLogin.credential"
-                          type="password"
-                          placeholder="请输入密码"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                      </el-form-item>
-                      <el-form-item label="图形验证码" label-width="90px">
-                        <el-image :src="captchaCode" @click="getCaptcha" />
-                        <el-input
-                          v-model="userLogin.captchaCode"
-                          placeholder="请输入图形验证码"
-                          style="width: 50%; padding-right: 1px"
-                          clearable
-                          @keyup.enter.native="loginBtn"
-                        />
-                      </el-form-item>
-                      <el-form-item>
-                        <el-button type="primary" size="mini" :loading="isLoading" @click.native="loginBtn">登 入</el-button>
-                        <el-button type="plain" size="mini" @click="register">注册帐号</el-button>
-                        <el-button type="plain" size="mini" @click="forgot">忘记密码</el-button>
-                      </el-form-item>
-                    </el-form>
-                  </div>
-                </el-tab-pane>
-                <el-tab-pane name="login2">
-                  <span slot="label">验证码登入</span>
-                  <div class="text item">
-                    <el-form ref="form" :model="userLogin" label-width="80px">
-                      <el-input v-model="userLogin.loginType" type="hidden" value="1" />
-                      <el-form-item label="帐号">
-                        <el-input
-                          v-model="userLogin.principal"
-                          placeholder="请输入手机号"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                        <el-button :disabled="isBtn" @click="loginVerifyCode">{{ code }}</el-button>
-                      </el-form-item>
-                      <el-form-item label="验证码">
-                        <el-input
-                          v-model="userLogin.credential"
-                          placeholder="请输入验证码"
-                          style="padding-right: 1px"
-                          clearable
-                        />
-                      </el-form-item>
-                      <el-form-item label="图形验证码" label-width="90px">
-                        <el-image :src="captchaCode" @click="getCaptcha" />
-                        <el-input
-                          v-model="userLogin.captchaCode"
-                          placeholder="请输入图形验证码"
-                          style="width: 50%; padding-right: 1px"
-                          clearable
-                          @keyup.enter.native="loginBtn"
-                        />
-                      </el-form-item>
-                      <el-form-item>
-                        <el-button type="primary" size="mini" :loading="isLoading" @click.native="loginByVerifyCode">登 入</el-button>
-                        <el-button type="plain" size="mini" @click="register">注册帐号</el-button>
-                        <el-button type="plain" size="mini" @click="forgot">忘记密码</el-button>
-                      </el-form-item>
-                    </el-form>
-                  </div>
-                </el-tab-pane>
-              </el-tabs>
-            </el-card>
-          </el-row>
-        </el-col>
-      </el-row>
-    </el-main>
-  </el-container>
+  <div class="login-wrapper">
+    <login-bar />
+
+    <div class="login-container">
+      <el-card class="login-card" shadow="always">
+        <div class="login-title">欢迎回来</div>
+
+        <el-tabs v-model="activeName" stretch @tab-click="tabClick">
+          <el-tab-pane label="密码登录" name="login1">
+            <el-form ref="loginForm" :model="userLogin" label-position="top">
+              <el-form-item label="账号">
+                <el-input
+                    v-model="userLogin.principal"
+                    prefix-icon="el-icon-user"
+                    placeholder="手机号或邮箱"
+                    clearable
+                />
+              </el-form-item>
+
+              <el-form-item label="密码">
+                <el-input
+                    v-model="userLogin.credential"
+                    prefix-icon="el-icon-lock"
+                    type="password"
+                    placeholder="请输入密码"
+                    show-password
+                    clearable
+                />
+              </el-form-item>
+
+              <el-form-item label="验证码">
+                <div class="captcha-box">
+                  <el-input
+                      v-model="userLogin.captchaCode"
+                      placeholder="图形验证码"
+                      @keyup.enter.native="loginBtn"
+                  />
+                  <el-image
+                      class="captcha-img"
+                      :src="captchaCode"
+                      title="点击刷新"
+                      @click="getCaptcha"
+                  />
+                </div>
+              </el-form-item>
+
+              <div class="action-buttons">
+                <el-button type="primary" class="submit-btn" :loading="isLoading" @click="loginBtn">登 录</el-button>
+                <div class="sub-actions">
+                  <el-button type="text" size="mini" @click="register">注册账号</el-button>
+                  <el-button type="text" size="mini" @click="forgot" class="forgot-link">忘记密码?</el-button>
+                </div>
+              </div>
+            </el-form>
+          </el-tab-pane>
+
+          <el-tab-pane label="验证码登录" name="login2">
+            <el-form ref="smsForm" :model="userLogin" label-position="top">
+              <el-form-item label="手机号">
+                <div class="sms-box">
+                  <el-input
+                      v-model="userLogin.principal"
+                      prefix-icon="el-icon-mobile-phone"
+                      placeholder="请输入手机号"
+                      clearable
+                  />
+                  <el-button class="sms-btn" :disabled="isBtn" @click="loginVerifyCode">
+                    {{ isBtn ? code + 's' : '获取验证码' }}
+                  </el-button>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="短信验证码">
+                <el-input
+                    v-model="userLogin.credential"
+                    prefix-icon="el-icon-chat-dot-round"
+                    placeholder="请输入验证码"
+                    clearable
+                />
+              </el-form-item>
+
+              <el-form-item label="验证码">
+                <div class="captcha-box">
+                  <el-input
+                      v-model="userLogin.captchaCode"
+                      placeholder="图形验证码"
+                      @keyup.enter.native="loginBtn"
+                  />
+                  <el-image class="captcha-img" :src="captchaCode" @click="getCaptcha" />
+                </div>
+              </el-form-item>
+
+              <div class="action-buttons">
+                <el-button type="primary" class="submit-btn" :loading="isLoading" @click="loginByVerifyCode">登 录</el-button>
+                <div class="sub-actions">
+                  <el-button type="text" size="mini" @click="register">注册账号</el-button>
+                  <el-button type="text" size="mini" @click="forgot">忘记密码?</el-button>
+                </div>
+              </div>
+            </el-form>
+          </el-tab-pane>
+        </el-tabs>
+      </el-card>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -144,57 +112,132 @@ import LoginBar from 'components/layout/LoginBar'
 
 export default {
   name: 'Login',
-  components: {
-    LoginBar
-  },
+  components: { LoginBar },
   mixins: [userMixin],
   data() {
     return {
-      devops: false,
       activeName: 'login1'
     }
   },
-  watch: {
-    $route() {
-      this.$router.go()
-    }
-  },
   created() {
-    this.devops = parseInt(process.env.VUE_APP_DEVOPS) === 1
-    document.title = '用户登入'
+    document.title = '用户登录'
     this.fetchPubkey(1)
   },
   methods: {
     tabClick(tab) {
       this.activeName = tab.name
     },
-    register() {
-      this.$router.push('/register')
-    },
-    forgot() {
-      if (this.devops) {
-        this.$message.info('联系管理员')
-      } else {
-        this.$router.push('/forgot')
-      }
-    }
+    register() { this.$router.push('/register') },
+    forgot() { this.$router.push('/forgot') }
   }
 }
 </script>
 
-<style>
-/*处于手机屏幕时*/
-@media screen and (max-width: 768px){
-  .movie-list {
-    padding-top: 8px;
-    padding-left: 0.5%;
-    padding-right: 0.5%;
-  }
+<style scoped>
+.login-wrapper {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+  display: flex;
+  flex-direction: column;
+}
+
+.login-container {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
 }
 
-.movie-list {
-  padding-top: 15px;
-  padding-left: 6%;
-  padding-right: 6%;
+.login-card {
+  width: 100%;
+  max-width: 400px;
+  border-radius: 12px;
+  border: none;
+  padding: 10px;
+}
+
+.login-title {
+  text-align: center;
+  font-size: 24px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 20px;
+  letter-spacing: 1px;
+}
+
+/* 覆盖 Tabs 样式 */
+/deep/ .el-tabs__item {
+  font-size: 16px;
+  height: 50px;
+  line-height: 50px;
+}
+
+/deep/ .el-form-item__label {
+  padding-bottom: 4px;
+  font-weight: 500;
+}
+
+/* 验证码布局 */
+.captcha-box {
+  display: flex;
+  gap: 12px;
+  align-items: center;
+}
+
+.captcha-img {
+  width: 120px;
+  height: 40px;
+  cursor: pointer;
+  border-radius: 4px;
+  flex-shrink: 0;
+  border: 1px solid #dcdfe6;
+}
+
+/* 短信验证码布局 */
+.sms-box {
+  display: flex;
+  gap: 8px;
+}
+
+.sms-btn {
+  width: 110px;
+  padding: 12px 0;
+  text-align: center;
+}
+
+/* 按钮区 */
+.action-buttons {
+  margin-top: 30px;
+}
+
+.submit-btn {
+  width: 100%;
+  font-size: 16px;
+  padding: 12px;
+  border-radius: 8px;
+  letter-spacing: 4px;
+}
+
+.sub-actions {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 15px;
+}
+
+.forgot-link {
+  color: #909399;
+}
+
+/* 手机端适配 */
+@media screen and (max-width: 480px) {
+  .login-card {
+    box-shadow: none;
+    background: transparent;
+  }
+  .login-container {
+    align-items: flex-start;
+    padding-top: 40px;
+  }
 }
 </style>

+ 206 - 83
src/views/Register.vue

@@ -1,67 +1,94 @@
 <template>
-  <el-container>
-    <el-main>
-      <login-bar />
-      <router-view />
-      <el-row class="movie-list">
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px" />
-        <el-col :md="8" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-          <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px; text-align: center">
-            <el-card class="box-card">
-              <div slot="header" class="clearfix">
-                <span>注册帐号</span>
+  <div class="register-wrapper">
+    <login-bar />
+
+    <div class="register-container">
+      <el-card class="register-card" shadow="always">
+        <div class="register-title">创建账号</div>
+        <p class="register-subtitle">加入 TNBAPP,开启您的精彩之旅</p>
+
+        <div v-if="registryEnable" class="form-content">
+          <el-form ref="registerForm" :model="userRegistry" label-position="top">
+
+            <el-form-item label="账号">
+              <div class="input-with-btn">
+                <el-input
+                    v-model="userRegistry.principal"
+                    prefix-icon="el-icon-user"
+                    placeholder="手机号或邮箱"
+                    clearable
+                />
+                <el-button
+                    class="code-btn"
+                    :disabled="isBtn"
+                    @click="registerVerifyCode"
+                >
+                  {{ isBtn ? code + 's' : '获取验证码' }}
+                </el-button>
+              </div>
+            </el-form-item>
+
+            <el-form-item label="身份验证码">
+              <el-input
+                  v-model="userRegistry.verifyCode"
+                  prefix-icon="el-icon-chat-dot-round"
+                  placeholder="请输入 6 位验证码"
+                  clearable
+              />
+            </el-form-item>
+
+            <el-form-item label="设置密码">
+              <el-input
+                  v-model="userRegistry.credential"
+                  prefix-icon="el-icon-lock"
+                  type="password"
+                  placeholder="请输入密码"
+                  show-password
+                  clearable
+              />
+            </el-form-item>
+
+            <el-form-item label="安全验证">
+              <div class="captcha-box">
+                <el-input
+                    v-model="userRegistry.captchaCode"
+                    placeholder="图形验证码"
+                    @keyup.enter.native="registerBtn"
+                />
+                <el-image
+                    class="captcha-img"
+                    :src="captchaCode"
+                    title="点击刷新"
+                    @click="getCaptcha"
+                />
               </div>
-              <div class="text item">
-                <el-form v-if="registryEnable" ref="form" :model="userRegistry" label-width="100px">
-                  <el-form-item label="帐号" label-width="90px">
-                    <el-input
-                      v-model="userRegistry.principal"
-                      placeholder="请输入邮箱或手机号"
-                      style="width: 45%; padding-right: 5px"
-                      clearable
-                    />
-                    <el-button :disabled="isBtn" @click="registerVerifyCode">{{ code }}</el-button>
-                  </el-form-item>
-                  <el-form-item label="验证码" label-width="90px">
-                    <el-input
-                      v-model="userRegistry.verifyCode"
-                      placeholder="请输入短信验证码"
-                      style="padding-right: 1px"
-                      clearable
-                    />
-                  </el-form-item>
-                  <el-form-item label="密码" label-width="90px">
-                    <el-input
-                      v-model="userRegistry.credential"
-                      type="password"
-                      placeholder="请输入密码"
-                      style="padding-right: 1px"
-                      clearable
-                    />
-                  </el-form-item>
-                  <el-form-item label="图形验证码" label-width="90px">
-                    <el-image :src="captchaCode" @click="getCaptcha" />
-                    <el-input
-                      v-model="userRegistry.captchaCode"
-                      placeholder="请输入图形验证码"
-                      style="width: 50%; padding-right: 10px"
-                      clearable
-                    />
-                  </el-form-item>
-                </el-form>
-                <div v-else class="text item">
-                  <span>系统当前未开放注册</span>
-                </div>
-                <el-button v-if="registryEnable" type="primary" :loading="isLoading" @click.native="registerBtn">注册</el-button>
-                <el-button type="plain" @click="login">返回登入</el-button>
+            </el-form-item>
+
+            <div class="action-buttons">
+              <el-button
+                  type="primary"
+                  class="submit-btn"
+                  :loading="isLoading"
+                  @click.native="registerBtn"
+              >
+                立即注册
+              </el-button>
+              <div class="footer-link">
+                <span>已有账号?</span>
+                <el-button type="text" @click="login">返回登录</el-button>
               </div>
-            </el-card>
-          </el-row>
-        </el-col>
-      </el-row>
-    </el-main>
-  </el-container>
+            </div>
+          </el-form>
+        </div>
+
+        <div v-else class="disabled-status">
+          <i class="el-icon-warning-outline"></i>
+          <p>抱歉,系统当前未开放注册</p>
+          <el-button type="primary" plain round @click="login" class="mt-20">返回登录</el-button>
+        </div>
+      </el-card>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -71,25 +98,16 @@ import { getRegistryStatus } from '@/api/account'
 
 export default {
   name: 'Register',
-  components: {
-    LoginBar
-  },
+  components: { LoginBar },
   mixins: [userMixin],
   data() {
     return {
       registryEnable: false
     }
   },
-  watch: {
-    $route() {
-      this.$router.go()
-    }
-  },
-  mounted() {
-    this.getData()
-  },
   created() {
     document.title = '注册帐号'
+    this.getData()
   },
   methods: {
     getData() {
@@ -109,19 +127,124 @@ export default {
 }
 </script>
 
-<style>
-/*处于手机屏幕时*/
-@media screen and (max-width: 768px){
-  .movie-list {
-    padding-top: 8px;
-    padding-left: 0.5%;
-    padding-right: 0.5%;
+<style scoped>
+.register-wrapper {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+  display: flex;
+  flex-direction: column;
+}
+
+.register-container {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+}
+
+.register-card {
+  width: 100%;
+  max-width: 440px;
+  border-radius: 12px;
+  border: none;
+  padding: 10px 15px;
+}
+
+.register-title {
+  text-align: center;
+  font-size: 24px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 8px;
+}
+
+.register-subtitle {
+  text-align: center;
+  color: #909399;
+  font-size: 14px;
+  margin-bottom: 25px;
+}
+
+/* 布局辅助 */
+.input-with-btn {
+  display: flex;
+  gap: 10px;
+}
+
+.code-btn {
+  width: 120px;
+  flex-shrink: 0;
+}
+
+.captcha-box {
+  display: flex;
+  gap: 10px;
+  align-items: center;
+}
+
+.captcha-img {
+  width: 110px;
+  height: 40px;
+  cursor: pointer;
+  border-radius: 4px;
+  border: 1px solid #dcdfe6;
+}
+
+/* 按钮区 */
+.action-buttons {
+  margin-top: 30px;
+}
+
+.submit-btn {
+  width: 100%;
+  padding: 12px;
+  font-size: 16px;
+  border-radius: 8px;
+  letter-spacing: 2px;
+}
+
+.footer-link {
+  text-align: center;
+  margin-top: 15px;
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 禁用状态样式 */
+.disabled-status {
+  text-align: center;
+  padding: 40px 0;
+}
+
+.disabled-status i {
+  font-size: 48px;
+  color: #E6A23C;
+  margin-bottom: 15px;
+}
+
+.disabled-status p {
+  color: #606266;
+  font-size: 16px;
+}
+
+.mt-20 { margin-top: 20px; }
+
+/* 移动端适配 */
+@media screen and (max-width: 480px) {
+  .register-card {
+    box-shadow: none;
+    background: transparent;
+  }
+  .register-container {
+    align-items: flex-start;
+    padding-top: 40px;
   }
 }
 
-.movie-list {
-  padding-top: 15px;
-  padding-left: 6%;
-  padding-right: 6%;
+/* Element UI 样式覆盖 */
+::v-deep .el-form-item__label {
+  padding-bottom: 4px;
+  font-weight: 500;
 }
 </style>

+ 1 - 134
src/views/admin/Dashboard.vue

@@ -13,122 +13,7 @@
           {{ item }}
         </el-button>
       </div>
-      <div v-if="devops">
-        <h3>Dashboard</h3>
-        <el-row style="padding: 5px">
-          <el-card>
-            <div slot="header" class="clearfix">
-              <span>CI/CD 流程</span>
-            </div>
-            <div>
-              <el-steps :active="0" finish-status="success" simple style="margin-top: 20px">
-                <el-step title="更新代码" icon="el-icon-loading" />
-                <el-step title="编译代码" icon="el-icon-loading" />
-                <el-step title="应用打包" icon="el-icon-loading" />
-                <el-step title="推送应用" icon="el-icon-upload" />
-                <el-step title="拉取应用" icon="el-icon-download" />
-                <el-step title="部署应用" icon="el-icon-loading" />
-              </el-steps>
-            </div>
-          </el-card>
-        </el-row>
-        <el-row style="padding: 5px">
-          <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-            <el-card class="box-card">
-              <div slot="header" class="clearfix">
-                <span>机器节点</span>
-              </div>
-              <div class="text item">
-                <el-table
-                  :data="machineStatList"
-                  style="width: 100%"
-                >
-                  <el-table-column
-                    prop="env"
-                    label="环境"
-                  />
-                  <el-table-column
-                    prop="total"
-                    label="总数"
-                  />
-                  <el-table-column
-                    prop="onlineCount"
-                    label="在线"
-                  >
-                    <template slot-scope="scope">
-                      <span style="color: green">{{ scope.row.onlineCount }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="offlineCount"
-                    label="离线"
-                  >
-                    <template slot-scope="scope">
-                      <span style="color: red">{{ scope.row.offlineCount }}</span>
-                    </template>
-                  </el-table-column>
-                </el-table>
-              </div>
-            </el-card>
-          </el-col>
-          <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
-            <el-card class="box-card">
-              <div slot="header" class="clearfix">
-                <span>系统信息</span>
-              </div>
-              <div class="text item">
-                <el-descriptions v-if="sysInfo !== null" class="margin-top" :column="1" border>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-user" />
-                      应用版本
-                    </template>
-                    <a target="_blank" :href="`https://git.reghao.cn/reghao/bnt/commit/${sysInfo.commitId}`" style="text-decoration-line: none">
-                      {{ sysInfo.commitId }}
-                    </a>
-                  </el-descriptions-item>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-mobile-phone" />
-                      机器地址
-                    </template>
-                    {{ sysInfo.ipv4 }}
-                  </el-descriptions-item>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-location-outline" />
-                      操作系统
-                    </template>
-                    {{ sysInfo.osInfo }}
-                  </el-descriptions-item>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-tickets" />
-                      JVM
-                    </template>
-                    {{ sysInfo.jvmInfo }}
-                  </el-descriptions-item>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-office-building" />
-                      启动时间
-                    </template>
-                    {{ sysInfo.startAt }}
-                  </el-descriptions-item>
-                  <el-descriptions-item>
-                    <template slot="label">
-                      <i class="el-icon-office-building" />
-                      PID
-                    </template>
-                    {{ sysInfo.pid }}
-                  </el-descriptions-item>
-                </el-descriptions>
-              </div>
-            </el-card>
-          </el-col>
-        </el-row>
-      </div>
-      <div v-else>
+      <div>
         <h3>Dashboard</h3>
         <el-button icon="el-icon-files" style="padding: 5px" @click="goToDisk">Disk</el-button>
         <el-button icon="el-icon-film" style="padding: 5px" @click="goToVod">VOD</el-button>
@@ -139,7 +24,6 @@
 </template>
 
 <script>
-import { getDashboard } from '@/api/devops'
 import { getAuthedUser } from '@/utils/auth'
 
 export default {
@@ -147,7 +31,6 @@ export default {
   data() {
     return {
       roles: [],
-      devops: false,
       machineStatList: [],
       sysInfo: null
     }
@@ -155,27 +38,11 @@ export default {
   created() {
     const { roles } = getAuthedUser()
     this.roles = roles
-    this.devops = parseInt(process.env.VUE_APP_DEVOPS) === 1
     document.title = 'Dashboard'
     this.getData()
   },
   methods: {
     getData() {
-      if (this.devops) {
-        this.getDevopsDashboard()
-      }
-    },
-    getDevopsDashboard() {
-      getDashboard().then(resp => {
-        if (resp.code === 0) {
-          this.sysInfo = resp.data.sysInfo
-          this.machineStatList = resp.data.machineStatList
-        } else {
-          this.$message.error(resp.msg)
-        }
-      }).catch(error => {
-        this.$message.error(error.message)
-      })
     },
     goToRole(data) {
       this.$message.info('role -> ' + data)