Răsfoiți Sursa

修改底色及登录页面

yangg 9 luni în urmă
părinte
comite
bb0f9f171c
36 a modificat fișierele cu 515 adăugiri și 147 ștergeri
  1. 1 1
      .env.development
  2. 1 1
      .env.production
  3. 0 0
      dist/index.html
  4. 0 0
      dist/static/css/app.fe3a9886.css
  5. 0 1
      dist/static/css/chunk-2043d8d9.1fa507b0.css
  6. 0 0
      dist/static/css/chunk-499732b2.e29bc68e.css
  7. 0 0
      dist/static/css/chunk-5a48219c.2ce6a6ea.css
  8. 0 0
      dist/static/css/chunk-d92339e6.cf6b7d77.css
  9. BIN
      dist/static/img/login-head.4ebecb6f.png
  10. BIN
      dist/static/img/微信图片_20240924181537.b3b964bd.png
  11. 0 0
      dist/static/js/app.5038c26f.js
  12. 0 0
      dist/static/js/app.f8ad23cd.js
  13. 0 0
      dist/static/js/chunk-2043d8d9.19e22885.js
  14. 0 0
      dist/static/js/chunk-499732b2.57a8856b.js
  15. 0 0
      dist/static/js/chunk-52f685c2.05e02703.js
  16. 0 0
      dist/static/js/chunk-52f685c2.f81e8e2c.js
  17. 0 0
      dist/static/js/chunk-5a48219c.8dcc0a17.js
  18. 0 0
      dist/static/js/chunk-76bddf0f.16f2b225.js
  19. 0 0
      dist/static/js/chunk-76bddf0f.e6487fc2.js
  20. 0 0
      dist/static/js/chunk-d92339e6.e52b7b30.js
  21. 0 0
      dist/static/js/chunk-libs.17877a52.js
  22. BIN
      src/assets/images/bgimg.jpg
  23. BIN
      src/assets/images/人工智能.png
  24. BIN
      src/assets/images/微信图片_20240924181537.png
  25. 36 4
      src/components/webAi/css/ChatBox.css
  26. 45 21
      src/components/webAi/index.vue
  27. 86 21
      src/components/webAi/js/ChatBox.js
  28. 2 1
      src/layout/components/Navbar.vue
  29. 2 2
      src/layout/components/Sidebar/Logo.vue
  30. 5 0
      src/router/index.js
  31. 1 1
      src/styles/variables.scss
  32. 7 3
      src/views/knowledgeMenu/index.scss
  33. 5 2
      src/views/knowledgeMenu/knowledgeList.vue
  34. 39 20
      src/views/login/index.scss
  35. 246 69
      src/views/login/index.vue
  36. 39 0
      src/views/login/superLogin.vue

+ 1 - 1
.env.development

@@ -2,5 +2,5 @@
 ENV = 'development'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://120.46.190.49:8084'
+VUE_APP_BASE_API = 'http://183.195.216.54:8084'
 #192.168.1.178

+ 1 - 1
.env.production

@@ -2,7 +2,7 @@
 ENV = 'production'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://183.195.216.54:23068'
+VUE_APP_BASE_API = 'http://183.195.216.54:8084'
 #客户:58.246.234.210:8084
 #域名 docapi.shqlsy.com
 #访问ip 192.168.100.6:8083

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/index.html


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/css/app.fe3a9886.css


+ 0 - 1
dist/static/css/chunk-2043d8d9.1fa507b0.css

@@ -1 +0,0 @@
-.ledge_box .data-search[data-v-26c5e21c]{padding:20px 10px 0 10px}.ledge_box .data-list[data-v-26c5e21c]{padding:10px;min-height:200px;position:relative}.ledge_box .data-list .time[data-v-26c5e21c]{font-size:13px;color:#999}.ledge_box .data-list .bottom[data-v-26c5e21c]{margin-top:13px;line-height:12px}.ledge_box .data-list .button[data-v-26c5e21c]{padding:0;float:right}.ledge_box .data-list .image[data-v-26c5e21c]{width:100%;display:block}.ledge_box .data-list .clearfix[data-v-26c5e21c]:after,.ledge_box .data-list .clearfix[data-v-26c5e21c]:before{display:table;content:""}.ledge_box .data-list .clearfix[data-v-26c5e21c]:after{clear:both}.ledge_box .data-list .card_box[data-v-26c5e21c]{padding:20px}.ledge_box .data-list .card_box .header[data-v-26c5e21c]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ledge_box .data-list .card-col[data-v-26c5e21c]{margin-bottom:30px}.ledge_box .data-list .card-col .card_box[data-v-26c5e21c]{height:235px}.ledge_box .data-list .card-col .card_box .box_content[data-v-26c5e21c]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;height:100%}.ledge_box .data-list .card-col .card_box .box_content .content[data-v-26c5e21c]{font-size:24px;line-height:32px;font-weight:600;cursor:pointer;color:rgba(0,0,0,.8784313725490196);word-break:break-all}.ledge_box .data-list .card-col .card_box .box_content .footer[data-v-26c5e21c]{font-size:12px;font-weight:600;color:rgba(0,0,0,.6509803921568628);vertical-align:middle}

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/css/chunk-499732b2.e29bc68e.css


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/css/chunk-5a48219c.2ce6a6ea.css


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/css/chunk-d92339e6.cf6b7d77.css


BIN
dist/static/img/login-head.4ebecb6f.png


BIN
dist/static/img/微信图片_20240924181537.b3b964bd.png


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/app.5038c26f.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/app.f8ad23cd.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-2043d8d9.19e22885.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-499732b2.57a8856b.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-52f685c2.05e02703.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-52f685c2.f81e8e2c.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-5a48219c.8dcc0a17.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-76bddf0f.16f2b225.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-76bddf0f.e6487fc2.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-d92339e6.e52b7b30.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/static/js/chunk-libs.17877a52.js


BIN
src/assets/images/bgimg.jpg


BIN
src/assets/images/人工智能.png


BIN
src/assets/images/微信图片_20240924181537.png


+ 36 - 4
src/components/webAi/css/ChatBox.css

@@ -24,9 +24,30 @@
         margin-bottom: 120px;
     }
 }
-
+.user-message {
+    display: flex;
+    flex-direction: column !important;
+    align-items: flex-end !important;
+  }
+  
+  .user-message .message-content {
+    order: 1;
+    text-align: right;
+  }
+  
+  .user-message .avatar {
+    order: 2;
+    margin-left: 10px;
+    margin-right: 0;
+  }
+  
+  .message-text {
+    margin-top: 5px;
+  }
 .messages li {
     display: flex;
+    flex-direction: column;
+
     align-items: flex-start; /* 这将确保所有子元素对齐到容器的顶部 */
     margin-bottom: 10px;
 }
@@ -66,6 +87,17 @@
     }
 }
 
+.message_name{
+    display: flex;
+    align-items: center;
+    padding-top: 5px;
+    padding-bottom: 5px;
+}
+.name{
+    margin-left: 8px;
+    margin-bottom: 5px;
+}
+
 .message-content {
     background-color: #f0f0f0; /* 消息背景 */
     padding-left: 20px; /* 上下左右的内边距 */
@@ -73,7 +105,7 @@
     padding-top: 10px; /* 上下左右的内边距 */
     padding-bottom: 0px; /* 上下左右的内边距 */
     max-width: calc(90% - 10px); /* 计算头像和间距 */
-    border-radius: 15px; /* 边框圆角 */
+    border-radius: 7px; /* 边框圆角 */
     margin-bottom: 10px; /* 和下一条消息之间的间距 */
     /* 消息内容样式 */
     display: flex;
@@ -93,7 +125,7 @@
     margin: 5px 0 10px;
     padding: 0;
     font-size: inherit;
-    line-height: inherit;
+    line-height: 22px;
     font-weight: inherit;
   }
 .input-container {
@@ -143,7 +175,7 @@ textarea {
 .sender-name {
     font-weight: bold;
     color: #333;
-    
+    margin-left: -5px;
 }
 
 .btn {

+ 45 - 21
src/components/webAi/index.vue

@@ -1,31 +1,55 @@
 <template>
-    <div class="chat-container">
-      <div class="messages">
-        <ul>
-          <li v-for="message in messages" :key="message.id" :class="message.user">
-            <!-- 添加判断,如果是机器人的消息也显示头像 -->
-            <div class="avatar" :class="{ 'user-avatar': message.user === 'user', 'bot-avatar': message.user === 'bot' }"></div>
-            <div class="message-content">
-              <span class="sender-name" v-if="message.user === 'user'">你</span>
-              <span class="sender-name" v-if="message.user === 'bot'">轻良AI助理</span>
-              <!-- 使用 v-html 来渲染 Markdown 文本 -->
-              <div class="message-text" v-html="renderMarkdown(message.message)"></div>
+  <div class="chat-container">
+    <div class="messages">
+      <ul>
+        <li
+          v-for="message in messages"
+          :key="message.id"
+          :class="[message.user, message.user === 'user' ? 'user-message' : '']"
+        >
+          <!-- 添加判断,如果是机器人的消息也显示头像 -->
+          <div class="message_name">
+            <div
+              class="avatar"
+              :class="{
+                'user-avatar': message.user === 'user',
+                'bot-avatar': message.user === 'bot',
+              }"
+            ></div>
+            <div class="name">
+              <span class="sender-name" style="color: #666666;" v-if="message.user === 'user'">你</span>
+              <span class="sender-name" v-if="message.user === 'bot'"
+                >轻良AI助理</span
+              >
             </div>
-          </li>
-        </ul>
-      </div>
-      <div class="input-container">
-        <textarea v-model="userInput" rows="4" @keydown="handleKeydown" placeholder="Type a message..."></textarea>
-        <button @click="sendMessage" class="btn">发送</button>
-      </div>
-      <!-- 添加 LoginModal 组件 -->
+          </div>
+          <!-- 使用 v-html 来渲染 Markdown 文本 -->
+          <div class="message-content">
+            <div
+              class="message-text"
+              v-html="renderMarkdown(message.message)"
+            ></div>
+          </div>
+        </li>
+      </ul>
+    </div>
+    <div class="input-container">
+      <textarea
+        v-model="userInput"
+        rows="4"
+        @keydown="handleKeydown"
+        placeholder="发送消息..."
+      ></textarea>
+      <button @click="sendMessage" class="btn">发送</button>
+    </div>
+    <!-- 添加 LoginModal 组件 -->
     <LoginModal
       :visible.sync="showLoginModal"
       @close="showLoginModal = false"
       @login-success="handleLoginSuccess"
     />
-    </div>
-  </template>
+  </div>
+</template>
   
   <script src="./js/ChatBox.js"></script>
   <style src="./css/ChatBox.css" scoped></style>

+ 86 - 21
src/components/webAi/js/ChatBox.js

@@ -9,6 +9,8 @@ export default {
   },
   data() {
     return {
+      isThinking: false,
+      thinkingDots: '',
       messages: [
         {
           user: "bot",
@@ -22,14 +24,14 @@ export default {
       generating: false,
       userInput: "",
       websocket: null,
-      wsUrl:'http://58.246.234.210:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false',
+      wsUrl:'http://58.246.234.210:7860/api/v1/run/2f1faff2-99df-4821-87d6-43d693084c4b?stream=false',
       tweaks:{},
       showLoginModal: false,
       isLoggedIn: false, // 添加登录状态标志
     };
   },
   created() {
-    this.connectWebSocket();
+   // this.connectWebSocket();
   },
   mounted() {
     if(this.$route.name=='ai'){
@@ -66,15 +68,15 @@ export default {
       );
     },
     connectWebSocket() {
-      const wsUrl = this.wsUrl//'http://58.246.234.210:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false'
+      const wsUrl = 'http://58.246.234.210:7860/api/v1/run/2f1faff2-99df-4821-87d6-43d693084c4b?stream=false'
       // 这里做一个简单的鉴权,只有符合条件的鉴权才能握手成功
       // 移除这里的fetch调用,改用WebSocket
       this.websocket = new WebSocket(wsUrl);
     
-      this.websocket.onerror = (event) => {
+     /*  this.websocket.onerror = (event) => {
         console.error("WebSocket 连接错误:", event);
       };
-    
+     */
       this.websocket.onclose = (event) => {
         console.log("WebSocket 连接关闭:", event);
       };
@@ -86,7 +88,7 @@ export default {
         // 解析收到的消息
         const result = JSON.parse(event.data);
 
-        console.log(result.content);
+       
 
         // 检查消息是否完结
         if (result.done) {
@@ -119,7 +121,7 @@ export default {
         }
       }
       const chatId = this.getUuid();
-      const wsUrl =this.wsUrl//'http://58.246.234.210:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false'
+      const wsUrl =this.wsUrl//'http://58.246.234.210:7860/api/v1/run/2f1faff2-99df-4821-87d6-43d693084c4b?stream=false'
       let message = this.userInput.trim();
       if (message) {
         // Markdown换行:在每个换行符之前添加两个空格
@@ -133,7 +135,19 @@ export default {
           done: true,
         });
         this.userInput = "";
-        console.log(this.messages);
+       // 添加机器人的响应消息(初始为空)
+       const botMessage = {
+        user: "bot",
+        messageType: "TEXT",
+        message: "",
+        html: "",
+        time: Date.now(),
+        done: false,
+      };
+      this.messages.push(botMessage);
+
+      // 开始模拟思考
+      const thinkingPromise = this.simulateThinking(botMessage);
         // 通过 HTTP 发送消息
         try {
           ///send-message
@@ -168,21 +182,72 @@ export default {
           }
 
           const result = await response.json();
-          this.handleResponse(result);
-        } catch (error) {
-          console.error("Error sending message:", error);
-        }
+         // 等待思考动画完成
+         await thinkingPromise;
+          
+         this.handleResponse(result, botMessage);
+       } catch (error) {
+         console.error("Error sending message:", error);
+         // 如果发生错误,停止思考动画
+         botMessage.done = true;
+         botMessage.message = "抱歉,发生了错误,请稍后再试。";
+       }
       }
     },
-    handleResponse(value) {
-       const data =value.outputs[0].outputs[0].results.message
-      this.messages.push({
-        user: "bot",
-        messageType: data.text_key,
-        message: data.text,
-        html: "",
-        time: data.timestamp,
-        done: true,
+    async simulateThinking(message) {
+      this.isThinking = true;
+      const thinkingTime = Math.random() * 1000 + 500; // 思考时间为 0.5-1.5 秒
+      const dotInterval = 200; // 每 200ms 更新一次点
+      
+      const updateDots = () => {
+        this.thinkingDots += '.';
+        if (this.thinkingDots.length > 3) {
+          this.thinkingDots = '';
+        }
+        message.message =  this.thinkingDots;
+      };
+  
+      const intervalId = setInterval(updateDots, dotInterval);
+  
+      await new Promise(resolve => setTimeout(resolve, thinkingTime));
+      
+      clearInterval(intervalId);
+      this.isThinking = false;
+      this.thinkingDots = '';
+      message.message = '';
+    },
+  
+    async handleResponse(value, existingMessage) {
+      const data = value.outputs[0].outputs[0].results.message;
+      
+      // 更新现有的消息对象
+      existingMessage.messageType = data.text_key;
+      existingMessage.time = data.timestamp;
+      
+      // 移除思考动画
+      existingMessage.message = '';
+      
+      // 开始打字效果
+      await this.typeMessage(existingMessage, data.text);
+    },
+  
+    typeMessage(message, fullText) {
+      return new Promise(resolve => {
+        const delay = 30; // 每个字符之间的延迟时间(毫秒)
+        let i = 0;
+        
+        const typeChar = () => {
+          if (i < fullText.length) {
+            message.message += fullText[i];
+            i++;
+            setTimeout(typeChar, delay);
+          } else {
+            message.done = true;
+            resolve();
+          }
+        };
+        
+        typeChar();
       });
     },
     renderMarkdown(rawMarkdown) {

+ 2 - 1
src/layout/components/Navbar.vue

@@ -12,7 +12,8 @@
     <div class="right-menu">
       <template v-if="device !== 'mobile'">
         <div class="right-menu-item">
-          <svg-icon className="svg-style" size="120" icon-class="AI模块" @click="openChatDialog" />
+          <img src="../../assets/images/人工智能.png" alt="" style="cursor: pointer; margin-top: 14px;width: 25px;height: 25px" @click="openChatDialog">
+         <!--  <svg-icon className="svg-style" size="120" icon-class="AI模块"  /> -->
         </div>
         <search id="header-search" class="right-menu-item" />
         <error-log class="errLog-container right-menu-item hover-effect" />

+ 2 - 2
src/layout/components/Sidebar/Logo.vue

@@ -47,7 +47,7 @@ export default {
 .sidebar-logo-container {
   position: relative;
   width: 100%;
-  height: 70px;
+  height: 65px;
   line-height: 50px;
   background: $logo_bg;
   text-align: center;
@@ -60,7 +60,7 @@ export default {
     & .sidebar-logo {
       /* width: 32px; */
       margin-top: 10px;
-      height: 50px;
+      height: 40px;
       vertical-align: middle;
       margin-right: 12px;
     }

+ 5 - 0
src/router/index.js

@@ -96,6 +96,11 @@ export const constantRoutes = [
      
     ]
   },
+  {
+    path: '/',
+    redirect: '/knowledge/knowledgeMenu/index',
+    hidden: true
+  },
   /* {
     path: '/',
     component: Layout,

+ 1 - 1
src/styles/variables.scss

@@ -1,5 +1,5 @@
 // base color  颜色管理
-$logo_bg:#e42645;
+$logo_bg:#093d5b;
 $header_bg:#fff;/* 头部背景颜色 */
 $content_bg:#f4f4f4;/* 内容部分背景色 */
 $tag_bg:#3cbade;

+ 7 - 3
src/views/knowledgeMenu/index.scss

@@ -44,16 +44,18 @@
             }
           }
           .card-col{
+            border-radius: 10px;
             margin-bottom: 30px;
             .card_box{
-                height: 235px;
+              border-radius: 10px;
+                height:330px;
                 .box_content{
                     display: flex;
                     flex-direction: column;
                     justify-content: space-between;
                     height: 100%;
                     .content{
-                        font-size: 24px;
+                        font-size: 35px;
                         line-height: 32px;
                         font-weight: 600;
                         cursor: pointer;
@@ -61,7 +63,9 @@
                         word-break: break-all;
                     }
                     .footer{
-                        font-size: 12px;
+                      display: flex;
+                      justify-content: space-between;
+                        font-size: 14px;
                         font-weight: 600;
                         color: #000000a6;
                         vertical-align: middle;

+ 5 - 2
src/views/knowledgeMenu/knowledgeList.vue

@@ -34,10 +34,10 @@
     <div class="data-list" v-loading="loading" element-loading-text="加载中...">
       <el-row>
         <el-col
-          :span="4"
+          :span="5"
           v-for="(item, index) in buckList"
           :key="index"
-          :offset="index > 0 && index % 5 !== 0 ? 1 : 0"
+          :offset="index > 0 && index % 4 !== 0 ? 1 : 0"
           class="card-col"
         >
           <el-card :body-style="{ padding: '0px' }" shadow="never">
@@ -237,6 +237,9 @@ export default {
 };
 </script>
   <style lang="scss" scoped>
+  ::v-deep .el-card{
+    border-radius: 10px
+  }
 @import "./index.scss";
 </style>
   

+ 39 - 20
src/views/login/index.scss

@@ -45,39 +45,58 @@ $dark_gray:#333;
 $light_gray:#eee;
 
 .login-container {
+ 
+  background-image: url("../../assets/images/微信图片_20240924181537.png");
+  background-size: contain;
   min-height: 100%;
   width: 100%;
-  background-color: $bg;
+ /*  background-color: $bg; */
   overflow: hidden;
   display:flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
+  justify-content: flex-end;
+  .gradient-background {
+    position: absolute;
+    background: linear-gradient(to bottom, #4f46e5, #3b82f6); /* from-indigo-600 to-blue-500 */
+    opacity: 0.75;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    z-index: 0;
+  }
   .form-content{
-
-    .title-container{
+     background: linear-gradient(to bottom, #4f46e5, #3b82f6);
+    z-index: 999;
+     width: 40%;
+     .login_form{
+      display: flex;
+      overflow: hidden;
+      background: #FFF;
+      height: 100vh;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+    /* .title-container{
       background-color: #899fe1;
       .images{
         height:100px;
       }
+    } */
+      .login-form {
+
+        width: 60%;
+        position: relative;
+        background:#FFF;
+        padding:40px;
+        
+      }
     }
-    .login-form {
-      position: relative;
-      width: 350px;
-      
-      margin: 0 auto;
-      overflow: hidden;
-      background:#FFF;
-      padding:40px;
-
-    }
-
   }
 
   .tips {
     font-size: 14px;
-    color: #666;
-    margin-bottom: 10px;
+    color: #818cf8;
+    margin-bottom: 24px;
     width:100%;
     display: flex;
     justify-content: flex-end;
@@ -129,4 +148,4 @@ $light_gray:#eee;
       display: none;
     }
   }
-}
+}

+ 246 - 69
src/views/login/index.vue

@@ -1,78 +1,83 @@
 <template>
   <div class="login-container">
+    <div class="gradient-background"></div>
+    <canvas id="canvas1"></canvas>
     <div class="form-content">
-      <div class="title-container">
+      <!-- <div class="title-container">
         <img src="../../assets/images/login-head.png" class="images" />
-      </div>
-      <el-form
-        v-if="loginOrRetrieve == 'login'"
-        ref="loginForm"
-        :model="loginForm"
-        :rules="loginRules"
-        class="login-form"
-        autocomplete="on"
-        label-position="left"
-      >
-        <el-form-item prop="username">
-          <span class="svg-container">
-            <svg-icon icon-class="user" />
-          </span>
-          <el-input
-            ref="username"
-            v-model="loginForm.username"
-            placeholder="登录用户名"
-            name="username"
-            type="text"
-            tabindex="1"
-            autocomplete="on"
-          />
-        </el-form-item>
-
-        <el-tooltip
-          v-model="capsTooltip"
-          content="Caps lock is On"
-          placement="right"
-          manual
+      </div> -->
+      <div class="login_form" v-if="loginOrRetrieve == 'login'">
+        <h2>AI知识库管理</h2>
+        <el-form
+          ref="loginForm"
+          :model="loginForm"
+          :rules="loginRules"
+          class="login-form"
+          autocomplete="on"
+          label-position="left"
         >
-          <el-form-item prop="password">
+          <el-form-item prop="username">
             <span class="svg-container">
-              <svg-icon icon-class="password" />
+              <svg-icon icon-class="user" />
             </span>
             <el-input
-              :key="passwordType"
-              ref="password"
-              v-model="loginForm.password"
-              :type="passwordType"
-              placeholder="登录密码"
-              name="password"
-              tabindex="2"
+              ref="username"
+              v-model="loginForm.username"
+              placeholder="登录用户名"
+              name="username"
+              type="text"
+              tabindex="1"
               autocomplete="on"
-              @keyup.native="checkCapslock"
-              @blur="capsTooltip = false"
-              @keyup.enter.native="handleLogin"
             />
-            <span class="show-pwd" @click="showPwd">
-              <svg-icon
-                :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
-              />
-            </span>
           </el-form-item>
-        </el-tooltip>
 
-        <el-button
-          :loading="loading"
-          type="primary"
-          style="width: 100%; margin-bottom: 30px"
-          @click="handleLogin"
-          >立即登录</el-button
-        >
-        <div class="tips">
-          <div @click="Retrieve('retrieve')" style="cursor: pointer">
-            找回密码
+          <el-tooltip
+            v-model="capsTooltip"
+            content="Caps lock is On"
+            placement="right"
+            manual
+          >
+            <el-form-item prop="password">
+              <span class="svg-container">
+                <svg-icon icon-class="password" />
+              </span>
+              <el-input
+                :key="passwordType"
+                ref="password"
+                v-model="loginForm.password"
+                :type="passwordType"
+                placeholder="登录密码"
+                name="password"
+                tabindex="2"
+                autocomplete="on"
+                @keyup.native="checkCapslock"
+                @blur="capsTooltip = false"
+                @keyup.enter.native="handleLogin"
+              />
+              <span class="show-pwd" @click="showPwd">
+                <svg-icon
+                  :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
+                />
+              </span>
+            </el-form-item>
+          </el-tooltip>
+          <div class="tips">
+            <div @click="Retrieve('retrieve')" style="cursor: pointer">
+              找回密码?
+            </div>
           </div>
-        </div>
-      </el-form>
-      <div v-if="loginOrRetrieve == 'retrieve'">
+          <el-button
+            :loading="loading"
+            class="btns"
+            type="primary"
+            style="width: 100%; margin-bottom: 30px"
+            @click="handleLogin"
+            >立即登录</el-button
+          >
+        </el-form>
+      </div>
+      <div class="login_form" v-if="loginOrRetrieve == 'retrieve'">
+        <h2>AI知识库管理</h2>
         <el-form
           ref="RetrieveForm"
           :model="RetrieveForm"
@@ -109,7 +114,7 @@
                 autocomplete="on"
               />
               <span class="show-pwd">
-                <el-button :disabled="isDisabled" @click="getCode">
+                <el-button type="primary" :disabled="isDisabled" @click="getCode">
                   {{ buttonText }}
                 </el-button>
               </span>
@@ -176,17 +181,19 @@
               </span>
             </el-form-item>
           </el-tooltip>
-
+          <div class="tips">
+            <div @click="Retrieve('login')" style="cursor: pointer">
+              返回登录
+            </div>
+          </div>
           <el-button
             :loading="loading"
             type="primary"
+            class="btns"
             style="width: 100%; margin-bottom: 30px"
             @click="retPass"
             >重置密码</el-button
           >
-          <div class="tips">
-            <div @click="Retrieve('login')" style="cursor: pointer">返回登录</div>
-          </div>
         </el-form>
       </div>
     </div>
@@ -316,6 +323,7 @@ export default {
     } else if (this.loginForm.password === "") {
       this.$refs.password.focus();
     }
+    this.initParticles();
   },
   destroyed() {
     // window.removeEventListener('storage', this.afterQRScan)
@@ -403,7 +411,7 @@ export default {
             .dispatch("user/login", this.loginForm)
             .then(() => {
               this.$router.push({
-                path: "/knowledge/knowledgeMenu/index",/* this.redirect || */
+                path: this.redirect || "/",
                 query: this.otherQuery,
               });
               this.loading = false;
@@ -447,12 +455,181 @@ export default {
     Retrieve(val) {
       this.loginOrRetrieve = val;
     },
+
+    /* 粒子动画 */
+    initParticles() {
+      const canvas = document.getElementById("canvas1");
+      const ctx = canvas.getContext("2d");
+      canvas.width = window.innerWidth;
+      canvas.height = window.innerHeight;
+
+      let area = Math.sqrt(canvas.width * canvas.height);
+      let radiusLength = (canvas.width * canvas.height) / 8000;
+
+      let particlesArray;
+
+      let mouse = {
+        x: null,
+        y: null,
+        radius: radiusLength,
+      };
+
+      window.addEventListener("mousemove", function (event) {
+        mouse.x = event.x;
+        mouse.y = event.y;
+      });
+
+      window.addEventListener("mouseout", function (event) {
+        mouse.x = undefined;
+        mouse.y = undefined;
+      });
+
+      window.addEventListener("resize", function (event) {
+        canvas.width = innerWidth;
+        canvas.height = innerHeight;
+        radiusLength = (canvas.width * canvas.height) / 9000;
+        createParticles();
+      });
+
+      class Particle {
+        constructor(x, y, velX, velY, size, color) {
+          this.x = x;
+          this.y = y;
+          this.velX = velX;
+          this.velY = velY;
+          this.size = size;
+          this.color = color;
+        }
+
+        draw() {
+          ctx.beginPath();
+          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
+          ctx.fillStyle = "#ffffff";
+          ctx.fill();
+        }
+
+        update() {
+          if (this.x > canvas.width || this.x < 0) {
+            this.velX = -this.velX;
+          }
+          if (this.y > canvas.height || this.y < 0) {
+            this.velY = -this.velY;
+          }
+
+          let dx = mouse.x - this.x;
+          let dy = mouse.y - this.y;
+          let dist = Math.sqrt(dx * dx + dy * dy);
+          if (dist < mouse.radius + this.size) {
+            const buffer = this.size * 10;
+            if (mouse.x < this.x && this.x < canvas.width - buffer) {
+              this.x += 10;
+            }
+            if (mouse.x > this.x && this.x > buffer) {
+              this.x -= 10;
+            }
+            if (mouse.y < this.y && this.y < canvas.height - buffer) {
+              this.y += 10;
+            }
+            if (mouse.y > this.y && this.y > buffer) {
+              this.y -= 10;
+            }
+          }
+
+          this.x += this.velX;
+          this.y += this.velY;
+          this.draw();
+        }
+      }
+
+      function createParticles() {
+        particlesArray = [];
+        let noOfParticles = (canvas.width * canvas.height) / 10000;
+        for (let i = 0; i < noOfParticles; i++) {
+          let size = Math.random() * 5 + 1;
+          let x = Math.random() * (innerWidth - 2 * size) + 2 * size;
+          let y = Math.random() * (innerHeight - 2 * size) + 2 * size;
+          let velX = Math.random() * 2;
+          let velY = Math.random() * 2;
+          let color = "#ffffff";
+          particlesArray.push(new Particle(x, y, velX, velY, size, color));
+        }
+      }
+
+      function connect() {
+        let vicinityDist = (canvas.width * canvas.height) / 81;
+        for (let i = 0; i < particlesArray.length; i++) {
+          for (let j = i; j < particlesArray.length; j++) {
+            let distance =
+              Math.pow(particlesArray[i].x - particlesArray[j].x, 2) +
+              Math.pow(particlesArray[i].y - particlesArray[j].y, 2);
+            let opacity = 1 - distance / 25000;
+            if (distance < vicinityDist) {
+              ctx.strokeStyle = "rgba(255,255,255," + opacity + ")";
+              ctx.lineWidth = 1;
+              ctx.beginPath();
+              ctx.moveTo(particlesArray[i].x, particlesArray[i].y);
+              ctx.lineTo(particlesArray[j].x, particlesArray[j].y);
+              ctx.stroke();
+            }
+          }
+        }
+      }
+
+      function animate() {
+        requestAnimationFrame(animate);
+        ctx.clearRect(0, 0, innerWidth, innerHeight);
+        for (let i = 0; i < particlesArray.length; i++) {
+          particlesArray[i].update();
+        }
+        connect();
+      }
+
+      createParticles();
+      animate();
+    },
   },
 };
 </script>
 
-<style lang="scss">
+<style lang="scss" >
 /* 修复input 背景不协调 和光标变色 */
 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
 @import "./index.scss";
+.btns {
+  width: 100%;
+  font-size: 16px;
+  display: flex;
+  justify-content: center;
+  background-image: linear-gradient(to right, #6366f1, #2563eb);
+  color: #f3f4f6;
+  padding: 1rem;
+  border-radius: 9999px;
+  font-weight: 600;
+  cursor: pointer;
+  transition: all 0.5s ease-in;
+}
+.el-button {
+  border: none;
+  box-shadow: none;
+}
+.btns:hover {
+  background-image: linear-gradient(to left, #3b82f6, #6366f1) !important;
+}
+.btns:focus {
+  border-color: #3b82f6 !important;
+  background-image: linear-gradient(to left, #3b82f6, #6366f1) !important;
+}
+.login-container {
+  position: relative;
+  overflow: hidden;
+}
+
+#canvas1 {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1;
+  width: 100%;
+  height: 100%;
+}
 </style>

+ 39 - 0
src/views/login/superLogin.vue

@@ -0,0 +1,39 @@
+<template>
+   <div>
+    
+   </div>
+</template>
+
+<script>
+export default {
+  /*组件参数 接收来自父组件的数据*/
+  props: {},
+  /*局部注册的组件*/
+  components: {},
+  /*组件状态值*/
+   data () {
+      return {
+
+      };
+   },
+
+  /*计算属性*/
+  computed: {},
+
+  /*侦听器*/
+  watch: {},
+
+  /*
+  * el 被新创建的 vm.$ el 替换,并挂载到实例上去之后调用该钩子。
+  * 如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$ el 也在文档内。
+  */
+  mounted () {
+  },
+
+  /*组件方法*/
+   methods: {}
+}
+</script>
+<style lang='css' scoped>
+
+</style>

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff