Browse Source

登录页面修改 图标

zhaohan 7 months ago
parent
commit
71bbdea4cf

+ 5 - 2
index.html

@@ -5,8 +5,11 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
     <meta name="renderer" content="webkit" />
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
-    <link rel="icon" href="/favicon.ico" />
-    <title>RuoYi-Vue-Plus多租户管理系统</title>
+    <meta name="description" content="A Modern Back-end Management System" />
+    <meta name="keywords" content="EMOON AI Management System" />
+    <meta name="author" content="EMOON" />
+    <link rel="icon" href="/favicon.png" />
+    <title>EMOON AI</title>
     <!--[if lt IE 11
       ]><script>
         window.location.href = '/html/ie.html';

BIN
public/favicon.png


File diff suppressed because it is too large
+ 0 - 0
public/logo.svg


+ 0 - 7
src/layout/components/Navbar.vue

@@ -42,13 +42,6 @@
             </el-popover>
           </div>
         </el-tooltip>
-        <el-tooltip content="Github" effect="dark" placement="bottom">
-          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
-        </el-tooltip>
-
-        <el-tooltip :content="proxy.$t('navbar.document')" effect="dark" placement="bottom">
-          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
-        </el-tooltip>
 
         <el-tooltip :content="proxy.$t('navbar.full')" effect="dark" placement="bottom">
           <screenfull id="screenfull" class="right-menu-item hover-effect" />

+ 11 - 13
src/layout/components/Sidebar/Logo.vue

@@ -7,15 +7,9 @@
     <transition :enter-active-class="proxy?.animate.logoAnimate.enter" mode="out-in">
       <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
-          {{ title }}
-        </h1>
       </router-link>
       <router-link v-else key="expand" class="sidebar-logo-link" to="/">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
-          {{ title }}
-        </h1>
       </router-link>
     </transition>
   </div>
@@ -23,7 +17,7 @@
 
 <script setup lang="ts">
 import variables from '@/assets/styles/variables.module.scss';
-import logo from '@/assets/logo/logo.png';
+import logo from '/logo.svg';
 import { useSettingsStore } from '@/store/modules/settings';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
@@ -34,7 +28,7 @@ defineProps({
   }
 });
 
-const title = ref('RuoYi-Vue-Plus');
+const title = ref('EMOON AI');
 const settingsStore = useSettingsStore();
 const sideTheme = computed(() => settingsStore.sideTheme);
 </script>
@@ -61,12 +55,15 @@ const sideTheme = computed(() => settingsStore.sideTheme);
   & .sidebar-logo-link {
     height: 100%;
     width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
 
     & .sidebar-logo {
-      width: 32px;
-      height: 32px;
-      vertical-align: middle;
-      margin-right: 12px;
+      width: 90%;
+      height: 90%;
+      object-fit: contain;
+      filter: brightness(0) invert(1);
     }
 
     & .sidebar-title {
@@ -88,7 +85,8 @@ const sideTheme = computed(() => settingsStore.sideTheme);
 
   &.collapse {
     .sidebar-logo {
-      margin-right: 0px;
+      margin: 0 auto;
+      display: block;
     }
   }
 }

+ 1 - 1
src/settings.ts

@@ -4,7 +4,7 @@ const setting: DefaultSettings = {
   /**
    * 网页标题
    */
-  title: import.meta.env.VITE_APP_TITLE,
+  title: 'EMOON AI',
 
   theme: '#409EFF',
 

+ 1 - 1
src/utils/dynamicTitle.ts

@@ -7,7 +7,7 @@ import { useSettingsStore } from '@/store/modules/settings';
 export const useDynamicTitle = () => {
   const settingsStore = useSettingsStore();
   if (settingsStore.dynamicTitle) {
-    document.title = settingsStore.title + ' - ' + import.meta.env.VITE_APP_TITLE;
+    document.title = settingsStore.title + ' - EMOON AI';
   } else {
     document.title = defaultSettings.title as string;
   }

+ 118 - 73
src/views/index.vue

@@ -2,94 +2,106 @@
   <div class="app-container home">
     <el-row :gutter="20">
       <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>RuoYi-Vue-Plus多租户管理系统</h2>
+        <h2><strong>医梦AI管理系统</strong></h2>
         <p>
-          RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 分布式集群 场景升级(不兼容原框架)
-          <br />
-          * 前端开发框架 Vue3、TS、Element Plus<br />
-          * 后端开发框架 Spring Boot<br />
-          * 容器框架 Undertow 基于 Netty 的高性能容器<br />
-          * 权限认证框架 Sa-Token 支持多终端认证系统<br />
-          * 关系数据库 MySQL 适配 8.X 最低 5.7<br />
-          * 缓存数据库 Redis 适配 6.X 最低 4.X<br />
-          * 数据库框架 Mybatis-Plus 快速 CRUD 增加开发效率<br />
-          * 数据库框架 p6spy 更强劲的 SQL 分析<br />
-          * 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构<br />
-          * 序列化框架 Jackson 统一使用 jackson 高效可靠<br />
-          * Redis客户端 Redisson 性能强劲、API丰富<br />
-          * 分布式限流 Redisson 全局、请求IP、集群ID 多种限流<br />
-          * 分布式锁 Lock4j 注解锁、工具锁 多种多样<br />
-          * 分布式幂等 Lock4j 基于分布式锁实现<br />
-          * 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化<br />
-          * 分布式任务调度 SnailJob 高性能 高可靠 易扩展<br />
-          * 文件存储 Minio 本地存储<br />
-          * 文件存储 七牛、阿里、腾讯 云存储<br />
-          * 监控框架 SpringBoot-Admin 全方位服务监控<br />
-          * 校验框架 Validation 增强接口安全性 严谨性<br />
-          * Excel框架 FastExcel(原Alibaba EasyExcel) 性能优异 扩展性强<br />
-          * 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释<br />
-          * 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性<br />
-          * 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码<br />
-          * 部署方式 Docker 容器编排 一键部署业务集群<br />
-          * 国际化 SpringMessage Spring标准国际化方案<br />
+          基于先进的人工智能技术,为医疗行业提供智能化解决方案的管理平台。
         </p>
-        <p><b>当前版本:</b> <span>v5.4.1</span></p>
         <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
-            >更新日志</el-button
-          >
+          <el-tag type="success">AI驱动</el-tag>
+          <el-tag type="info">医疗专业</el-tag>
+          <el-tag type="warning">高效便捷</el-tag>
+          <el-tag type="danger">创新科技</el-tag>
         </p>
       </el-col>
 
       <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>
+        <h2><strong>团队介绍</strong></h2>
         <p>
-          RuoYi-Cloud-Plus 微服务通用权限管理系统 重写 RuoYi-Cloud 全方位升级(不兼容原框架)
-          <br />
-          * 前端开发框架 Vue3、TS、Element UI<br />
-          * 后端开发框架 Spring Boot<br />
-          * 微服务开发框架 Spring Cloud、Spring Cloud Alibaba<br />
-          * 容器框架 Undertow 基于 XNIO 的高性能容器<br />
-          * 权限认证框架 Sa-Token、Jwt 支持多终端认证系统<br />
-          * 关系数据库 MySQL 适配 8.X 最低 5.7<br />
-          * 关系数据库 Oracle 适配 11g 12c<br />
-          * 关系数据库 PostgreSQL 适配 13 14<br />
-          * 关系数据库 SQLServer 适配 2017 2019<br />
-          * 缓存数据库 Redis 适配 6.X 最低 5.X<br />
-          * 分布式注册中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
-          * 分布式配置中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
-          * 服务网关 Spring Cloud Gateway 响应式高性能网关<br />
-          * 负载均衡 Spring Cloud Loadbalancer 负载均衡处理<br />
-          * RPC远程调用 Apache Dubbo 原生态使用体验、高性能<br />
-          * 分布式限流熔断 Alibaba Sentinel 无侵入、高扩展<br />
-          * 分布式事务 Alibaba Seata 无侵入、高扩展 支持 四种模式<br />
-          * 分布式消息队列 Apache Kafka 高性能高速度<br />
-          * 分布式消息队列 Apache RocketMQ 高可用功能多样<br />
-          * 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />
-          * 分布式搜索引擎 ElasticSearch 业界知名<br />
-          * 分布式链路追踪 Apache SkyWalking 链路追踪、网格分析、度量聚合、可视化<br />
-          * 分布式日志中心 ELK 业界成熟解决方案<br />
-          * 分布式监控 Prometheus、Grafana 全方位性能监控<br />
-          * 其余与 Vue 版本一致<br />
+          努力的人,认真做事。
         </p>
-        <p><b>当前版本:</b> <span>v2.4.1</span></p>
         <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
+          我司(EnterLO|回车网络)算法核心团队由北京大学、阿姆斯特丹大学智能科学专业的博士组成。团队成员包括国际人工智能/自然语言学术会议ACL、EMNLP、ICLR的权威审稿人;WMT国际机器翻译竞赛冠军;微软、阿里等国内外科技公司的履历工程师们。
         </p>
         <p>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
-            >更新日志</el-button
-          >
+          · PhDs in Intelligent Science from globally top-ranked universities<br />
+          · Senior reviewers for top-tier international conferences (ACL/EMNLP/ICLR)<br />
+          · WMT Machine Translation Competition champion<br />
+          · Engineers from global tech giants
         </p>
       </el-col>
     </el-row>
+    
+    <!-- 分割线 -->
+    <el-divider style="margin: 50px 0 40px 0; border-color: #e0e0e0;" />
+    
+    <!-- AI生态标题 -->
+    <div style="margin-bottom: 30px; text-align: center">
+      <h2><strong>AI生态</strong></h2>
+    </div>
+    
+    <!-- AI生态卡片 -->
+    <el-row :gutter="20">
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="server" style="font-size: 32px; color: #409EFF" />
+          </div>
+          <h3><strong>GPUs</strong></h3>
+          <p>为模型训练及推理提供基础硬件算力。</p>
+        </el-card>
+      </el-col>
+      
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="redis" style="font-size: 32px; color: #67C23A" />
+          </div>
+          <h3><strong>数据蒸馏中心</strong></h3>
+          <p>将业务数据治理为可供模型训练用的数据集。</p>
+        </el-card>
+      </el-col>
+      
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="build" style="font-size: 32px; color: #E6A23C" />
+          </div>
+          <h3><strong>模型训练中心</strong></h3>
+          <p>训练本地专精模型。</p>
+        </el-card>
+      </el-col>
+      
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="component" style="font-size: 32px; color: #F56C6C" />
+          </div>
+          <h3><strong>模型开放平台</strong></h3>
+          <p>多模型与多业务对接的AI集成平台。</p>
+        </el-card>
+      </el-col>
+      
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="workflow" style="font-size: 32px; color: #909399" />
+          </div>
+          <h3><strong>智能体开放平台</strong></h3>
+          <p>为模型提供调用扩展APIs(查询、执行等)的能力。</p>
+        </el-card>
+      </el-col>
+      
+      <el-col :xs="24" :sm="12" :md="8" style="margin-bottom: 20px">
+        <el-card class="ai-ecosystem-card" shadow="hover">
+          <div class="card-icon">
+            <svg-icon icon-class="user" style="font-size: 32px; color: #9C27B0" />
+          </div>
+          <h3><strong>客户端</strong></h3>
+          <p>支持多模型、多模态、智能体的统一业务入口。</p>
+        </el-card>
+      </el-col>
+    </el-row>
+    
     <el-divider />
   </div>
 </template>
@@ -161,5 +173,38 @@ const goTarget = (url: string) => {
       padding-inline-start: 40px;
     }
   }
+
+  .ai-ecosystem-card {
+    height: 200px;
+    text-align: center;
+    transition: all 0.3s ease;
+    border: 1px solid #e4e7ed;
+    
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
+    }
+    
+    .card-icon {
+      margin-bottom: 16px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+    
+    h3 {
+      margin: 0 0 12px 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: #303133;
+    }
+    
+    p {
+      margin: 0;
+      font-size: 14px;
+      color: #606266;
+      line-height: 1.5;
+    }
+  }
 }
 </style>

+ 411 - 117
src/views/login.vue

@@ -1,79 +1,93 @@
 <template>
-  <div class="login">
-    <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
-      <div class="title-box">
-        <h3 class="title">{{ title }}</h3>
-        <lang-select />
-      </div>
-      <el-form-item v-if="tenantEnabled" prop="tenantId">
-        <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')" style="width: 100%">
-          <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
-          <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
-        </el-select>
-      </el-form-item>
-      <el-form-item prop="username">
-        <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')">
-          <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item prop="password">
-        <el-input
-          v-model="loginForm.password"
-          type="password"
-          size="large"
-          auto-complete="off"
-          :placeholder="proxy.$t('login.password')"
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item v-if="captchaEnabled" prop="code">
-        <el-input
-          v-model="loginForm.code"
-          size="large"
-          auto-complete="off"
-          :placeholder="proxy.$t('login.code')"
-          style="width: 63%"
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
-        </el-input>
-        <div class="login-code">
-          <img :src="codeUrl" class="login-code-img" @click="getCode" />
+  <div class="login-container">
+    <!-- 左侧背景面板 -->
+    <div class="left-panel">
+      <div class="background-overlay"></div>
+      <div class="content-wrapper">
+        <div class="logo-section">
+          <img src="/logo.svg" alt="Logo" class="logo animate-float" />
+        </div>
+        <div class="title-section">
+          <h1 class="main-title">医梦AI管理系统</h1>
+          <p class="subtitle">欢迎使用智能管理系统</p>
         </div>
-      </el-form-item>
-      <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
-      <el-form-item style="float: right">
-        <el-button circle :title="proxy.$t('login.social.wechat')" @click="doSocialLogin('wechat')">
-          <svg-icon icon-class="wechat" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.maxkey')" @click="doSocialLogin('maxkey')">
-          <svg-icon icon-class="maxkey" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.topiam')" @click="doSocialLogin('topiam')">
-          <svg-icon icon-class="topiam" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.gitee')" @click="doSocialLogin('gitee')">
-          <svg-icon icon-class="gitee" />
-        </el-button>
-        <el-button circle :title="proxy.$t('login.social.github')" @click="doSocialLogin('github')">
-          <svg-icon icon-class="github" />
-        </el-button>
-      </el-form-item>
-      <el-form-item style="width: 100%">
-        <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
-          <span v-if="!loading">{{ proxy.$t('login.login') }}</span>
-          <span v-else>{{ proxy.$t('login.logging') }}</span>
-        </el-button>
-        <div v-if="register" style="float: right">
-          <router-link class="link-type" :to="'/register'">{{ proxy.$t('login.switchRegisterPage') }}</router-link>
+      </div>
+    </div>
+
+    <!-- 右侧登录面板 -->
+    <div class="right-panel">
+      <div class="login-form-container">
+        <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
+          <div class="title-box">
+            <h3 class="form-title">登录</h3>
+            <lang-select />
+          </div>
+          
+          <el-form-item v-if="tenantEnabled" prop="tenantId" class="tenant-select-item">
+            <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')" class="tenant-select">
+              <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
+              <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
+            </el-select>
+          </el-form-item>
+          
+          <el-form-item prop="username">
+            <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')">
+              <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
+            </el-input>
+          </el-form-item>
+          
+          <el-form-item prop="password">
+            <el-input
+              v-model="loginForm.password"
+              type="password"
+              size="large"
+              auto-complete="off"
+              :placeholder="proxy.$t('login.password')"
+              @keyup.enter="handleLogin"
+            >
+              <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
+            </el-input>
+          </el-form-item>
+          
+          <el-form-item v-if="captchaEnabled" prop="code" class="captcha-item">
+            <div class="captcha-container">
+              <el-input
+                v-model="loginForm.code"
+                size="large"
+                auto-complete="off"
+                :placeholder="proxy.$t('login.code')"
+                class="captcha-input"
+                @keyup.enter="handleLogin"
+              >
+                <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
+              </el-input>
+              <div class="captcha-image">
+                <img :src="codeUrl" class="captcha-img" @click="getCode" />
+              </div>
+            </div>
+          </el-form-item>
+          
+          <div class="form-options">
+            <el-checkbox v-model="loginForm.rememberMe">{{ proxy.$t('login.rememberPassword') }}</el-checkbox>
+            <div v-if="register" class="register-link">
+              <router-link class="link-type" :to="'/register'">{{ proxy.$t('login.switchRegisterPage') }}</router-link>
+            </div>
+          </div>
+          
+          
+          <el-form-item class="login-button">
+            <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
+              <span v-if="!loading">{{ proxy.$t('login.login') }}</span>
+              <span v-else>{{ proxy.$t('login.logging') }}</span>
+            </el-button>
+          </el-form-item>
+        </el-form>
+        
+        <!-- 底部版权信息 -->
+        <div class="el-login-footer">
+          <span>© 2020-2025 回车网络 版权所有</span>
         </div>
-      </el-form-item>
-    </el-form>
-    <!--  底部  -->
-    <div class="el-login-footer">
-      <span>Copyright © 2018-2025 疯狂的狮子Li All Rights Reserved.</span>
+      </div>
     </div>
   </div>
 </template>
@@ -231,82 +245,362 @@ onMounted(() => {
 </script>
 
 <style lang="scss" scoped>
-.login {
+.login-container {
   display: flex;
+  min-height: 100vh;
+  width: 100%;
+}
+
+.left-panel {
+  flex: 1;
+  position: relative;
+  background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
+  display: flex;
+  align-items: center;
   justify-content: center;
+  overflow: hidden;
+}
+
+.background-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: linear-gradient(
+    154deg,
+    rgba(255, 255, 255, 0.3) 30%,
+    rgba(59, 130, 246, 0.2) 48%,
+    rgba(255, 255, 255, 0.3) 64%
+  );
+  filter: blur(100px);
+}
+
+.content-wrapper {
+  position: relative;
+  z-index: 2;
+  text-align: center;
+  color: white;
+  padding: 2rem;
+  display: flex;
+  flex-direction: column;
   align-items: center;
+  justify-content: center;
   height: 100%;
-  background-image: url('../assets/images/login-background.jpg');
-  background-size: cover;
+}
+
+.logo-section {
+  margin-bottom: 3rem;
+  
+  .logo {
+    width: 80%;
+    height: auto;
+    max-width: 600px;
+    filter: brightness(0) invert(0);
+    opacity: 0.8;
+  }
+}
+
+.title-section {
+  .main-title {
+    font-size: 2.5rem;
+    font-weight: 600;
+    margin: 0 0 0.8rem 0;
+    color: #1e3a8a;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+  }
+  
+  .subtitle {
+    font-size: 1.2rem;
+    margin: 0;
+    opacity: 0.8;
+    font-weight: 400;
+    color: #3b82f6;
+  }
+}
+
+.animate-float {
+  animation: float 6s ease-in-out infinite;
+}
+
+@keyframes float {
+  0%, 100% {
+    transform: translateY(0px);
+  }
+  50% {
+    transform: translateY(-20px);
+  }
+}
+
+.right-panel {
+  width: 34%;
+  min-height: 100vh;
+  background: #ffffff;
+  display: flex;
+  flex-direction: column;
+  position: relative;
+}
+
+.login-form-container {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  padding: 2rem;
+  position: relative;
+}
+
+.login-form {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  max-width: 400px;
+  margin: 0 auto;
+  width: 100%;
 }
 
 .title-box {
   display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 2rem;
 
-  .title {
-    margin: 0px auto 30px auto;
-    text-align: center;
-    color: #707070;
+  .form-title {
+    margin: 0;
+    font-size: 1.8rem;
+    font-weight: 600;
+    color: #1f2937;
   }
 
   :deep(.lang-select--style) {
     line-height: 0;
-    color: #7483a3;
+    color: #6b7280;
   }
 }
 
-.login-form {
-  border-radius: 6px;
-  background: #ffffff;
-  width: 400px;
-  padding: 25px 25px 5px 25px;
-  z-index: 1;
-  .el-input {
-    height: 40px;
-    input {
-      height: 40px;
+.form-options {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 1.5rem;
+  
+  .register-link {
+    .link-type {
+      color: #3b82f6;
+      text-decoration: none;
+      font-size: 0.875rem;
+      
+      &:hover {
+        text-decoration: underline;
+      }
     }
   }
+}
+
 
-  .input-icon {
-    height: 39px;
-    width: 14px;
-    margin-left: 0px;
+.login-button {
+  margin-bottom: 0;
+  
+  .el-button {
+    height: 40px;
+    font-size: 1rem;
+    font-weight: 500;
+    border-radius: 8px;
   }
 }
 
-.login-tip {
-  font-size: 13px;
-  text-align: center;
-  color: #bfbfbf;
+.el-input {
+  height: 40px;
+  
+  input {
+    height: 40px;
+    border-radius: 8px;
+    border: 1px solid #d1d5db;
+    font-size: 0.95rem;
+    
+    &:focus {
+      border-color: #3b82f6;
+      box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
+    }
+  }
+}
+
+.tenant-select-item {
+  .el-form-item__content {
+    width: 100%;
+  }
 }
 
-.login-code {
-  width: 33%;
+.tenant-select {
+  width: 100% !important;
   height: 40px;
-  float: right;
+  
+  .el-select__wrapper {
+    height: 40px !important;
+    min-height: 40px !important;
+    border-radius: 8px;
+    border: 1px solid #d1d5db;
+    width: 100%;
+    padding: 0 12px;
+    align-items: center;
+    
+    &:focus-within {
+      border-color: #3b82f6;
+      box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
+    }
+  }
+  
+  .el-select__prefix {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .el-select__selection {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+    flex: 1;
+  }
+  
+  .el-select__selected-item {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .el-select__input-wrapper {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .el-select__input {
+    height: 40px;
+    line-height: 40px;
+  }
+  
+  .el-select__placeholder {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .el-select__suffix {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .el-select__caret {
+    height: 40px;
+    line-height: 40px;
+    display: flex;
+    align-items: center;
+  }
+}
 
-  img {
-    cursor: pointer;
-    vertical-align: middle;
+.input-icon {
+  height: 20px;
+  width: 20px;
+  margin-left: 12px;
+  color: #6b7280;
+}
+
+.captcha-item {
+  .el-form-item__content {
+    display: flex;
+    align-items: stretch;
   }
 }
 
-.el-login-footer {
-  height: 40px;
-  line-height: 40px;
-  position: fixed;
-  bottom: 0;
+.captcha-container {
+  display: flex;
+  gap: 12px;
   width: 100%;
-  text-align: center;
-  color: #fff;
-  font-family: Arial, serif;
-  font-size: 12px;
-  letter-spacing: 1px;
+  align-items: stretch;
+}
+
+.captcha-input {
+  flex: 1;
+  
+  .el-input__wrapper {
+    height: 40px;
+    border-radius: 8px;
+    border: 1px solid #d1d5db;
+    
+    &:focus-within {
+      border-color: #3b82f6;
+      box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
+    }
+  }
 }
 
-.login-code-img {
+.captcha-image {
+  width: 120px;
   height: 40px;
-  padding-left: 12px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #f9fafb;
+  cursor: pointer;
+  transition: all 0.2s ease;
+  
+  &:hover {
+    background: #f0f9ff;
+  }
+  
+  .captcha-img {
+    max-width: 100%;
+    max-height: 100%;
+    object-fit: contain;
+  }
+}
+
+.el-login-footer {
+  position: absolute;
+  bottom: 1rem;
+  left: 0;
+  right: 0;
+  text-align: center;
+  color: #6b7280;
+  font-size: 0.75rem;
+  font-weight: 400;
+}
+
+
+// 响应式设计
+@media (max-width: 1024px) {
+  .left-panel {
+    display: none;
+  }
+  
+  .right-panel {
+    width: 100%;
+  }
+}
+
+@media (max-width: 768px) {
+  .login-form-container {
+    padding: 1rem;
+  }
+  
+  .login-form {
+    max-width: 100%;
+  }
+  
+  .title-section .main-title {
+    font-size: 2rem;
+  }
+  
+  .title-section .subtitle {
+    font-size: 1rem;
+  }
 }
 </style>

+ 1 - 1
vite.config.ts

@@ -24,7 +24,7 @@ export default defineConfig(({ mode, command }) => {
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          target: 'http://localhost:8080',
+          target: 'http://localhost:6776',
           changeOrigin: true,
           ws: true,
           rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')

Some files were not shown because too many files changed in this diff