Kaynağa Gözat

6-05样式修改

chenrong 1 yıl önce
ebeveyn
işleme
106112f250

+ 1 - 0
public/index.html

@@ -8,6 +8,7 @@
     <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <title><%= webpackConfig.name %></title>
+    <script src="https://kit.fontawesome.com/7c98163d58.js" crossorigin="anonymous"></script>
     <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
 	  <style>
     html,

+ 10 - 1
src/api/chat.js

@@ -5,13 +5,22 @@ import { getToken } from "@/utils/auth";
 // const controller = new AbortController();
 // setAbortController(controller)
 // const signal = controller.signal;
-
+// 获取初始聊天引导
 export function getGuidanceApi(id) {
   return request({
     url: `/system/app/guidance/${id}`,
     method: 'get',
   })
 }
+// 获取模型列表
+export function getModelListApi(data) {
+  return request({
+    url: `/system/app/modelList`,
+    method: 'get',
+    params: data
+  })
+}
+
 // ai对话AXIOS
 // export function streamChatWithWebApi(data) {
 //   return request({

+ 23 - 0
src/api/login.js

@@ -50,4 +50,27 @@ export function getCodeImg() {
     method: 'get',
     timeout: 20000
   })
+}
+// 获取手机验证码
+export function getSendVerificationCode(data) {
+  return request({
+    url: '/system/app/sendVerificationCode',
+    headers: {
+      isToken: false
+    },
+    data,
+    method: 'post',
+    timeout: 20000
+  })
+}
+
+export function phoneLogin(data) {
+  return request({
+    url: '/system/app/register',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data: data
+  })
 }

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
src/assets/icons/svg/speech.svg


BIN
src/assets/icons/新聊天.png


+ 10 - 0
src/assets/styles/element-ui.scss

@@ -89,4 +89,14 @@
   > .el-submenu__title
   .el-submenu__icon-arrow {
   display: none;
+}
+.el-button--primary {
+  color: #FFFFFF;
+  background-color: var(--bg-color1);
+  border-color: var(--bg-color1);
+}
+.el-button--primary:hover, .el-button--primary:focus {
+  background: var(--bg-color4);
+  border-color: var(--bg-color4);
+  color: #FFFFFF;
 }

+ 4 - 0
src/assets/styles/index.scss

@@ -214,4 +214,8 @@ button, input, optgroup, select, textarea {
 
 :root {
   --bg-color1: #7262f6;
+  --bg-color2: hsla(0, 0%, 83%, 0.24);
+  --bg-color3: rgba(109, 94, 227, 0.9);
+  --bg-color4: #9387ff;
+  --color1: #e2e2e2;
 }

+ 350 - 159
src/views/chat/index.vue

@@ -1,18 +1,100 @@
 <template>
-  <div class="chat bg-gray-900 comBg">
-    <Header ref="Header" v-show="false" />
-    <div class="flex flex-col items-center justify-center h-screen px-4">
-      <!-- onClick={() => navigate('/')} -->
-      <div
-        class="text-white px-3 py-2 rounded-lg mb-4 absolute top-2 left-2"
-        style="background-color: var(--bg-color1);"
-        @click="goBack"
-      >
-        <!-- <i class="fas fa-chevron-left mr-2"></i> -->
-        返回
+  <div class="chat bg-white">
+    <div class="flex items-center justify-center h-screen">
+      <div class="leftInfo relative">
+        <div class="history">
+          <div class="historyBox flex historyActive">
+            <div class="photo">
+              <img class="object-cover" src="@/assets/images/1.png" alt="">
+            </div>
+            <div class="info flex-1 ml-2 flex flex-col justify-around">
+              <div class="text-sm font-semibold">角色名称</div>
+              <div class="text-sm text-gray-400">角色的聊天信息xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</div>
+            </div>
+          </div>
+        </div>
+        <div class="chatInfo absolute top-0 left-0 w-full h-full z-30 bg-white" v-show="showInfo">
+          <div class="flex flex-col p-4">
+            <div class="flex justify-between items-center text-base mb-3">
+              <div>角色详情</div>
+              <i class="el-icon-close cursor-pointer" @click="showInfo = false"></i>
+            </div>
+            <div class="flex">
+              <span class="chatInfo_photo">
+                <img class="w-16 h-16 rounded-full overflow-hidden object-cover" :src="baseApi + info.picture">
+              </span>
+              <div class="w-0 flex-1 ml-2">
+                <div class="text-xl font-medium">{{ info.characterName }}</div>
+                <div class="mt-1 text-gray-500 text-sm">Rochat No.75680</div>
+              </div>
+            </div>
+            <div class="flex mt-4">
+              <div class="hot flex w-auto items-center px-2 py-1 text-sm mr-2 rounded-full">
+                <v-icon name="fire" scale="1"/>
+                <span class="ml-1">855.8k</span>
+              </div>
+            </div>
+            <div class="flex justify-around mt-4">
+              <div class=" rounded-full w-32 text-center py-2 text-sm cursor-pointer" style="border: solid 1px #000">分享</div>
+              <div class=" rounded-full w-32 text-center py-2 text-sm cursor-pointer" style="border: solid 1px #000" @click="showDetail = !showDetail">角色详情</div>
+            </div>
+            <transition name="el-zoom-in-top">
+              <div v-show="showDetail" >
+                <div class="mt-5 text-base pb-3 border-b border-gray-200">
+                  <div>
+                    <i class="el-icon-document"></i>
+                    描述
+                  </div>
+                  <div class="mt-3 text-sm max-h-48">
+                    {{ info.prologue }}
+                  </div>
+                </div>
+                <div class="flex justify-between items-center  mt-5 text-base pb-3 border-b border-gray-200">
+                  <div>
+                    <i class="el-icon-user"></i>
+                    创作人
+                  </div>
+                  <div class="text-sm max-h-48">
+                    {{ info.prologue }}
+                  </div>
+                </div>
+                <div class="flex justify-between items-center  mt-5 text-base pb-3 border-b border-gray-200">
+                  <div>
+                    <i class="el-icon-time"></i>
+                    创建时间
+                  </div>
+                  <div class="text-sm max-h-48">
+                    2024-06-20
+                  </div>
+                </div>
+                <div class="mt-5 text-base">
+                  <i class="el-icon-discount"></i>
+                  特征
+                </div>
+                <div class="tags mt-4 pb-3">
+                  <span class="tag" v-for="(item, index) in info.labelArr" :key="index">
+                    {{ item }}
+                  </span>
+                </div>
+              </div>
+            </transition>
+            <div class="mt-5 text-base pb-3">
+              <div>
+                <!-- <i class="el-icon-document"></i> -->
+                查看场景
+              </div>
+              <div class="mt-3 text-sm max-h-48">
+                <el-empty description="暂无场景"></el-empty>
+                <div class="flex justify-center">
+                  <el-button type="primary" round>创建场景</el-button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
       </div>
       <div class="content">
-        <div class="leftImg">
+        <!-- <div class="leftImg">
           <img :src="baseApi + info.picture" alt="">
           <div class="aiInfo">
             <span class="photo">
@@ -28,12 +110,49 @@
               <div class="infoContent">{{ info.prologue }}</div>
             </div>
           </div>
-        </div>
+        </div> -->
+        
         <div class="chat-box">
+          <div class="chatBoxTitle absolute top-0">
+            <div>
+              {{ info.characterName }}
+            </div>
+            <div class="flex w-60 justify-between">
+              <el-tooltip effect="dark" content="设定" placement="bottom">
+                <el-popover
+                  placement="bottom"
+                  width="400"
+                  trigger="click">
+                  <div class="p-2">
+                    <div class="flex justify-between mb-4">
+                      <span>语音自动播放</span>
+                      <el-switch v-model="value1">
+                      </el-switch>
+                    </div>
+                    <div class="flex justify-between">
+                      <span>全屏幕</span>
+                      <el-switch v-model="value1">
+                      </el-switch>
+                    </div>
+                  </div>
+                  <i slot="reference" class="fa-solid fa-sliders cursor-pointer text-xl"></i>
+                </el-popover>
+              </el-tooltip>
+              <el-tooltip effect="dark" content="角色详情" placement="bottom">
+                <i class="fa-solid fa-file-invoice cursor-pointer text-xl" @click="showInfo = true"></i>
+              </el-tooltip>
+              <el-tooltip effect="dark" content="开始新的对话" placement="bottom">
+                <i class="fa-solid fa-comment-medical cursor-pointer text-xl" @click="newStart"></i>
+              </el-tooltip>
+              <el-tooltip effect="dark" content="历史对话" placement="bottom">
+                <i class="fa-solid fa-clock-rotate-left cursor-pointer text-xl" @click="showInfo = false"></i>
+              </el-tooltip>
+            </div>
+          </div>
           <audio ref="audio" v-show="false" src="@/assets/file/我将在黎明出发.mp3" @ended="audioEnd" controls></audio>
           <div class="messages" ref="messages">
             <template v-for="(item, index) in returnMessage">
-              <div v-if="item.role == 'assistant'" class="text-white mb-4 flex" :key="index">
+              <div v-if="item.role == 'assistant'" class="mb-4 flex" :key="index">
                 <!-- ai返回的信息 -->
                 <div class="pt-2 photo">
                   <img
@@ -41,13 +160,13 @@
                     class="rounded-full w-14 h-14 object-cover"
                   />
                 </div>
-                <div class="messageRight">
-                  <!-- <div class="yyPlay ml-4"></div> -->
-                  <div class="yyPlayBg mt-1 ml-6 w-16 p-1 cursor-pointer" @click="playAudio(item, index)">
-                    <img v-if="audioPlayIndex == index" class="yyPlay" src="@/assets/images/播放/yyPlay1.png" alt="" >
-                    <img v-else class="yyPlay" src="@/assets/images/播放/yyPlay.png" alt="" >
-                  </div>
-                  <div class="message mt-4 ml-4 p-3 rounded-r-md rounded-bl-md text-xs" >
+                <div class="messageRight">                  
+                  <div class="message mt-4 ml-4 p-2 rounded-r-md rounded-bl-md text-xs" >
+                    <div class="yyPlayBg mb-2 w-16 p-1 cursor-pointer" >
+                      <img v-if="audioPlayIndex == index" class="yyPlay" src="@/assets/images/播放/yyPlay1.png" alt="" >
+                      <img v-else class="yyPlay" src="@/assets/images/播放/yyPlay.png" alt="" @click="playAudio(item, index)">
+                      <!-- <svg-icon class="icon" class-name="speech-icon" icon-class="speech" @click.stop="click" /> -->
+                    </div>
                     <div v-show="!item.content" class="loadingMessage" >
                       <div v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
                     </div>
@@ -62,7 +181,7 @@
                 
               </div>
               <!-- 用户发送的信息 -->
-              <div v-if="item.role == 'user'" class="text-white mb-4 flex me" :key="index">
+              <div v-if="item.role == 'user'" class="mb-4 flex me" :key="index">
                 <div class="pt-2 photo">
                   <img
                     src="@/assets/images/default_avatar_user.png"
@@ -70,8 +189,8 @@
                   />
                 </div>
                 <div class="messageRight">
-                  <div class="message mr-4 mt-4 p-3 rounded-l-md rounded-br-md text-xs">
-                    <p>{{ item.content }}</p>
+                  <div class="messageUser mr-4 mt-4 p-2 rounded-l-md rounded-br-md text-xs">
+                    {{ item.content }}
                   </div>
                 </div>
                 
@@ -79,55 +198,108 @@
             </template>
           </div>
           
-          <div class="absolute left-2 right-2 bottom-4 ">
-            <!-- <div class="flex items-center text-gray-400 text-xs mb-4 ">
-              <span>@Leon S Kennedy - Resident Evil</span>
-            </div> -->
-            <div class="flex">
-              <el-button class="buttonBg1 mButton" @click="newStart" style="margin-right: 5px;" type="primary" round icon="el-icon-plus"></el-button>
-              <input
+          <div class="inputBox absolute left-2 right-2 bottom-4 " @click="inputBoxClick">
+            <input
+                ref="input"
                 type="text"
                 placeholder="输入消息..."
-                class="flex-1 py-2 px-4 rounded-l-lg text-sm text-white focus:outline-none"
-                style="background: #ffffff0f; border: 1px solid #5b5b5e;"
+                class="w-full flex-1 py-2 px-4 rounded-l-lg text-sm  focus:outline-none"
                 v-model="content"
                 @keydown="Enterkey"
               />
-              <button @click="getStreamChatWithWeb" class="buttonBg1 text-white px-4 rounded-r-lg text-sm">
-                发送
+            <div class="flex pt-6 justify-between">
+              <div class="tools w-36 flex justify-between">
+                <i class="el-icon-setting text-2xl cursor-pointer" @click="showConfig = true"></i>
+                <i class="el-icon-picture-outline text-2xl cursor-pointer"></i>
+                <i class="el-icon-s-opportunity text-2xl cursor-pointer"></i>
+              </div>
+              <button @click="getStreamChatWithWeb" class="px-4 rounded-r-lg text-sm text-gray-400" :class="content && 'planeColor'">
+                <v-icon name="paper-plane" scale="1.5"/>
               </button>
-              
             </div>
           </div>
         </div>
       </div>
-      
+      <el-dialog
+        title="配置"
+        :visible.sync="showConfig"
+        width="500px"
+      >
+        <p class="text-base">身分</p>
+        <p class="text-sm text-gray-400">选择你和角色聊天的身份</p>
+        <div class="flex items-start py-3 border-b border-gray-200">
+          <el-radio-group class="radio" v-model="configForm.radio1">
+            <el-radio-button label="上海"></el-radio-button>
+          </el-radio-group>
+          <el-button>
+            <i class="el-icon-sort" style="transform: rotate(90deg);"></i>
+          </el-button>
+        </div>
+        <p class="text-base mt-3">选择模型</p>
+        <p class="text-sm text-gray-400">每个模型可能有不同的效果,仅对当前对话有影响</p>
+        <div class="flex items-start py-3 border-b border-gray-200">
+          <el-radio-group class="radio" v-model="configForm.radio2">
+            <el-radio-button v-for="(item, index) in modelList" :key="index" :label="item.id">{{ item.model }}</el-radio-button>
+
+          </el-radio-group>
+        </div>
+        <p class="text-base mt-3">角色语言</p>
+        <p class="text-sm text-gray-400">请选择角色的回复语言</p>
+        <div class="flex items-start py-3">
+          <el-radio-group class="radio" v-model="configForm.radio3">
+            <el-radio-button label="自动"></el-radio-button>
+            <el-radio-button label="简体中文"></el-radio-button>
+            <el-radio-button label="繁體中文"></el-radio-button>
+            <el-radio-button label="English"></el-radio-button>
+            <el-radio-button label="Español"></el-radio-button>
+          </el-radio-group>
+        </div>
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="showConfig = false">取 消</el-button>
+          <el-button type="primary" @click="showConfig = false">确 定</el-button>
+        </span>
+      </el-dialog>
     </div>
-  </div>
+</div>
 </template>
 
 <script>
 import Header from "@/views/homeComponents/Header.vue"
-import { streamChatWithWebApi, getGuidanceApi } from "@/api/chat.js"
+import { streamChatWithWebApi, getGuidanceApi, getModelListApi } from "@/api/chat.js"
 import { detailApi } from "@/api/detail.js"
 import { Message, MessageBox, Notification, Loading } from 'element-ui'
+import 'vue-awesome/icons/paper-plane'
+import 'vue-awesome/icons/fire'
+
 export default {
   components: {
     Header
   },
   data() {
     return {
+      showDetail: false,
+      showConfig: false,
+      showInfo: false,
       messageOptions: [],
       info: {},
       messageLoading: false,
       returnMessage: [],
       content: '',
-      audioPlayIndex: null
+      audioPlayIndex: null,
+      configForm: {
+        radio1: null,
+        radio2: null,
+        radio3: null,
+      },
+      // 模型列表
+      modelList: []
     }
   },
   mounted() {
     console.log(this.$refs.Header, 'this.$refs.Header');
+    this.getModelList()
     if (this.$route.query.characterId) {
+      this.showInfo = true
       this.getDetail(this.$route.query.characterId)
     }
   },
@@ -143,10 +315,21 @@ export default {
     }
   },
   methods: {
+    getModelList() {
+      getModelListApi().then(res => {
+        console.log(res, '模型列表');
+        this.modelList = res.data
+      })
+    },
+    inputBoxClick() {
+      console.log(this.$refs.input, 'this.$refs.input');
+      this.$refs.input.focus()
+    },
     getDetail(id) {
       detailApi(id).then(res => {
         console.log(res, '角色详情');
         this.info = res.data
+        this.configForm.radio2 = this.info.modelId
         let HistoryMessage = JSON.parse(localStorage.getItem(`[userId:${123},aiId:${this.info.id}]`));
         if (HistoryMessage) {
           this.returnMessage = HistoryMessage
@@ -259,7 +442,8 @@ export default {
       let params = {
         historyMessage: HistoryMessage || [],
         characterId: this.info.id,
-        prompt: this.content
+        prompt: this.content,
+        modelId: this.configForm.radio2
       }
       // 新增一条ai信息
       this.returnMessage.push({
@@ -394,120 +578,92 @@ export default {
 .chat {
   min-height: 100vh;
 }
-.content {
-  margin-top: 30px;
-  background-size: 100% 100%;
-  display: flex;
-  height: 90vh;
-  justify-content: center;
-  width: 100vw;
-  
-  >.leftImg {
-      border-radius: 16px 16px 16px 16px;
-      height: 95%;
-      position: relative;
-      width: 380px;
-
-      >img {
-        border: 6px solid;
-        border-image: linear-gradient(180deg, #b48733, #e8cf97, #b48733) 6 6;
-        height: 99%;
-        margin-right: 5px;
-        object-fit: cover;
-      }
-      >.aiInfo {
-        background-color: #ffffff1a;
-        border-radius: 24px 24px 24px 24px;
-        bottom: -70px;
-        display: flex;
-        height: 193px;
-        justify-content: center;
-        left: 50%;
-        position: absolute;
-        transform: translate(-50%, -50%);
-        width: 100%;
+.leftInfo {
+  width: 375px;
+  height: 100%;
+  padding: 32px 24px;
 
-        >.photo {
-          width: 64px;
-          height: 64px;
-          font-size: 18px;
-          position: absolute;
-          top: -20px;
-          box-sizing: border-box;
-          margin: 0;
-          padding: 0;
-          color: #fff;
-          line-height: 1.5714285714285714;
-          list-style: none;
-          font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
-          display: inline-flex;
-          justify-content: center;
-          align-items: center;
-          overflow: hidden;
-          white-space: nowrap;
-          text-align: center;
-          vertical-align: middle;
-          background: rgba(0, 0, 0, 0.25);
-          border: 1px solid transparent;
+  >.history {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    >.historyBox {
+      padding: 8px;
+      border-radius: 15px;
+      border: solid 1px var(--color1);
+      >.photo {
+        >img {
           border-radius: 50%;
         }
-        >.info {
-          padding-top: 50px;
-          width: 80%;
-          >.name {
-            color: #fff;
-            font-size: 22px;
-            font-style: normal;
-            font-weight: 700;
-            line-height: 31px;
-            text-align: center;
-            text-transform: none;
-          }
-          >.tags {
-            padding-bottom: 8px;
-            text-align: center;
-            >.tag {
-              margin-right: 4px;
-              background: #ffffff1a;
-              border-radius: 4px 4px 4px 4px;
-              color: #fff;
-              font-size: 12px;
-              font-weight: 500;
-              line-height: 17px;
-              border-color: transparent;
-            }
-          }
-          >.infoContent {
-            color: #fff;
-            font-size: 16px;
-            font-style: normal;
-            font-weight: 500;
-            height: 80px;
-            line-height: 22px;
-            overflow-y: auto;
-            text-align: center;
-            text-transform: none;
-          }
+      }
+      >.info {
+        width: calc(100% - 60px);
+        >div {
+          overflow: hidden; /* 确保超出容器的文本被裁剪 */
+          white-space: nowrap; /* 确保文本在一行内显示 */
+          text-overflow: ellipsis; /* 使用省略号表示文本超出 */
         }
       }
+    }
+    .historyBox:hover {
+      background: var(--color1);
+    }
+    >.historyActive {
+      background: var(--color1);
+    }
+  }
+  >.chatInfo {
+    .chatInfo_photo {
+      >img {
+
+      }
+    }
+    .hot {
+      color: #f03d3d;
+      background: #fff1f1;
+    }
+    .tags {
+      margin-top: 10px;
+      .tag {
+        display: inline-flex;
+        justify-content: center;
+        padding: 5px 10px;
+        border-radius: 4px;
+        border: solid 1px var(--color1);
+        margin-right: 5px;
+      }
+    }
   }
+}
+.content {
+  background-size: 100% 100%;
+  display: flex;
+  height: 100%;
+  justify-content: center;
+  width: calc(100% - 375px);
+  border-left: solid 1px var(--color1);
+  
   >.chat-box {
-    margin-left: 5px;
     position: relative;
-    background-color: #ffffff1a;
-    background-position: 50%;
-    background-repeat: no-repeat;
+    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.4) 0%, rgb(255, 255, 255) 20%, rgb(255, 255, 255) 75%, rgba(0, 0, 0, 0.4) 100%);
     background-size: auto;
-    border: 1px solid #635677 !important;
-    border-radius: 20px;
+    // border: 1px solid #635677 !important;
     box-sizing: border-box;
-    color: #fff !important;
     display: flex;
     flex-direction: column;
-    height: 95%;
-    // margin: 0 auto;
-    width: 1010px;
-    padding: 25px;
+    height: 100%;
+    width: 100%;
+    padding: 55px 25px 25px 25px;
+    >.chatBoxTitle {
+      color: #fff;
+      margin-top: 15px;
+      width: calc(100% - 50px);
+      height: 30px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
   }
 }
 
@@ -520,17 +676,22 @@ export default {
 }
 .messageRight {
   max-width: calc(100% - 72px);
-  min-width: 400px;
+  // min-width: 400px;
 }
 .yyPlayBg {
-  background: rgba(103, 103, 168, 1);
-  border-radius: 999px;
-  position: absolute;
+  // background: rgba(103, 103, 168, 1);
+  // border-radius: 999px;
+  // position: absolute;
+
+  .icon {
+    height: 24px;
+    width: 96px;
+  }
 }
 
 .yyPlay {
-  width: 12px;
-  height: 12px;
+  width: 15px;
+  height: 15px;
   // background: url('../../assets/images/播放/yyPlay.gif') no-repeat;
   // background-size: 170% 170%;
   // background-position: 50% 50%;
@@ -540,17 +701,21 @@ export default {
   // background: #fff;
 }
 .message {
-  background: #ffffff0f;
-  border: 1px solid #5b5b5e;
-  
+  // background: #ffffff0f;
+  // border: 1px solid #5b5b5e;
+  background: var(--bg-color3);
+  color: #fff;
+  font-size: 14px;
   // flex: 1;
   
 }
 .messageUser {
-  background: #ffffff0f;
-  border: 1px solid #5b5b5e;
-  max-width: calc(100% - 72px);
-  min-width: 400px;
+  background: rgba(255, 255, 255, 0.9);
+  border: 1px solid var(--color1);
+  // max-width: calc(100% - 72px);
+  font-size: 14px;
+  width: auto;
+  // min-width: 400px;
 }
 .photo {
   width: 56px;
@@ -562,17 +727,18 @@ export default {
   position: relative;
   // display: flex;
   // justify-content: center;
-  width: 100%;
-  height: 100%;
+  width: 120px;
+  height: 64px;
 }
 .messageOptions {
   // margin-top: 20px;
   display: flex;
   flex-wrap: wrap;
   justify-content: space-around;
+  min-width: 400px;
   .option {
     background: #ade4ff32;
-    border: 1px solid #5b5b5e;
+    // border: 1px solid #5b5b5e;
     border-radius: 10px;
     padding: 10px;
     width: 40%;
@@ -581,6 +747,15 @@ export default {
     cursor: pointer;
   }
 }
+.inputBox {
+  border: solid 1px var(--color1);
+  border-radius: 10px;
+  padding: 24px;
+  background: #fff;
+}
+.planeColor {
+  color: var(--bg-color1);
+}
 </style>
 <style scoped>
   .loadingMessage >>> .el-loading-parent--relative {
@@ -595,4 +770,20 @@ export default {
   .mButton {
     border: solid 0px;
   }
+  .radio >>> .el-radio-button {
+    margin-bottom: 5px;
+    margin-right: 10px;
+    /* border-left: solid 1px #DCDFE6; */
+  }
+  .radio >>> .el-radio-button__inner {
+    border-left: solid 1px #DCDFE6;
+    border-radius: 4px;
+  }
+  .radio >>> .el-radio-button__orig-radio:checked + .el-radio-button__inner {
+    border-left: solid 1px var(--bg-color1);
+    background-color: var(--bg-color1);
+    border-color: var(--bg-color1);
+    -webkit-box-shadow: -1px 0 0 0 var(--bg-color1);
+    box-shadow: -1px 0 0 0 var(--bg-color1);
+  }
 </style>

+ 34 - 6
src/views/components/NavMenu.vue

@@ -12,19 +12,19 @@
         </defs>
       </svg>
       <div class="menus">
-        <div class="menu " :class="$route.path == '/home' && 'menuActive'">
+        <div class="menu " :class="$route.path == '/home' && 'menuActive'" @click="routeTo('/home')">
           <i class="icon el-icon-discover"></i>
           <div class="text">发现</div>
         </div>
-        <div class="menu" :class="$route.path == '/chat' && 'menuActive'">
+        <div v-if="haveToken" class="menu" :class="$route.path == '/chat' && 'menuActive'" @click="routeTo('/chat')">
           <i class="icon el-icon-chat-line-round"></i>
           <div class="text">对话</div>
         </div>
-        <div class="menu" :class="$route.path == '/create' && 'menuActive'">
+        <div v-if="haveToken" class="menu" :class="$route.path == '/create' && 'menuActive'" @click="routeTo('/create')">
           <i class="icon el-icon-plus"></i>
           <div class="text">创建</div>
         </div>
-        <div class="menu">
+        <div v-if="haveToken" class="menu">
           <i class="icon el-icon-files"></i>
           <div class="text">个人中心</div>
         </div>
@@ -36,15 +36,41 @@
         <img class="img" src="@/assets/images/default_avatar_user.png" alt="">
       </div>
     </div>
+    <div v-if="!haveToken" class="loginTip fixed w-56 h-32 bg-white left-20 bottom-6 z-50 p-3 rounded flex flex-col">
+      <div class=" text-base text-black font-semibold">欢迎来到《元宇宙》</div>
+      <div class=" text-gray-400">登录畅享所有服务</div>
+      <el-button class="w-full mt-6" @click="showLogin">登录</el-button>
+    </div>
   </div>
 </template>
 
 <script>
 // 引入需要的图标
+import { getToken, setToken, removeToken } from '@/utils/auth'
 import 'vue-awesome/icons/crown'
 
-export default {
 
+export default {
+  data() {
+    return {
+      getToken, 
+    }
+  },
+  mounted() {
+  },
+  computed: {
+    haveToken() {
+      return this.$store.state.user.token != null
+    }
+  },
+  methods: {
+    routeTo(url) {
+      this.$router.push(url)
+    },
+    showLogin() {
+      this.$store.commit('app/TOGGLE_POPUP', true)
+    },
+  }
 }
 </script>
 
@@ -90,5 +116,7 @@ export default {
     }
   }
 }
-
+.loginTip {
+  box-shadow: 1px 1px 4px #bfbfbf;
+}
 </style>

+ 59 - 58
src/views/create/index.vue

@@ -1,64 +1,65 @@
 <template>
-  <div class="create bg-gray-900 comBg" style="min-height: 100vh;">
-    <Header />
-    <div class="text-white mx-auto" style="width: 60%;">
+  <div class="create" style="min-height: 100vh;">
+    <!-- <Header /> -->
+    
+    <div class="mx-auto" style="width: 60%;">
       <div class="container mx-auto p-4">
         <div class="flex flex-col gap-6">
+          <div class="text-2xl mt-6 font-semibold">创建角色</div>
           <div class="text-xl font-medium">基本信息</div>
           <div class="text-xs text-gray-400">
             这些信息在机器人描述中供其他用户查看
           </div>
           <el-form :model="form" :rules="rules" ref="form" label-width="60px" class="form" >
-            <div class="bg-gray-700 p-5 rounded-lg">
-              <div class="flex gap-4">
-                <div class="w-1/3 flex justify-center">
-                  <el-form-item label="" prop="picture" label-width="0">
-                    <ImageUpload v-model="form.picture" class="imgUp" :limit="1" />
-                  </el-form-item>
-                  
-                  <!-- <div class="bg-gray-600 p-4 rounded-lg flex items-center justify-center">
+            <div class="flex gap-4">
+              <div class="w-1/3 flex justify-center">
+                <el-form-item label="" prop="picture" label-width="0">
+                  <ImageUpload v-model="form.picture" class="imgUp" :limit="1" />
+                </el-form-item>
+                
+                <!-- <div class="bg-gray-600 p-4 rounded-lg flex items-center justify-center">
 
-                  </div> -->
-                  <!-- <div class="text-sm mt-2 text-center">
-                    支持PNG、JPG、JPEG、WebP及GIF格式的图片大小不超过10MB。
-                  </div> -->
-                </div>
-                <div class="flex-1">
-                  <div class="flex flex-col gap-4 ml-6 pb-4">
-                    <el-form-item label="名称" prop="characterName">
-                      <el-input v-model="form.characterName" placeholder="填写名称"></el-input>
-                    </el-form-item>
-                    <el-form-item label="简介" prop="prologue">
-                      <el-input 
-                        v-model="form.prologue" 
-                        type="textarea"
-                        :autosize="{ minRows: 3, maxRows: 3}"
-                        placeholder="介绍一下你要值造的这个机器人。应段介绍只会是示在机器人的角色详情信息中,不会出现在提示词中,也不会影响到你的机器人。"
-                      ></el-input>
-                    </el-form-item>
-                    <el-form-item label="性别" prop="sex">
-                      <el-radio-group v-model="form.sex">
-                        <el-radio label="0">男</el-radio>
-                        <el-radio label="1">女</el-radio>
-                      </el-radio-group>
-                    </el-form-item>
-                    <el-form-item label="类型" prop="type">
-                      <el-radio-group v-model="form.type">
-                        <el-radio :label="0">公开</el-radio>
-                        <el-radio :label="1">私密</el-radio>
-                      </el-radio-group>
-                    </el-form-item>
-                    <el-form-item label="标签" prop="labelId">
-                      <el-select v-model="form.labelId" multiple filterable placeholder="搜索并选择与你的机器人相关的标签">
-                        <el-option :label="item.labelName" :value="item.id" v-for="(item, index) in labelData" :key="index"></el-option>
-                      </el-select>
-                    </el-form-item>
-                  </div>
+                </div> -->
+                <!-- <div class="text-sm mt-2 text-center">
+                  支持PNG、JPG、JPEG、WebP及GIF格式的图片大小不超过10MB。
+                </div> -->
+              </div>
+              <div class="flex-1">
+                <div class="flex flex-col gap-4 ml-6 pb-4">
+                  <el-form-item label="名称" prop="characterName">
+                    <el-input v-model="form.characterName" placeholder="填写名称"></el-input>
+                  </el-form-item>
+                  <el-form-item label="简介" prop="prologue">
+                    <el-input 
+                      v-model="form.prologue" 
+                      type="textarea"
+                      :autosize="{ minRows: 3, maxRows: 3}"
+                      placeholder="介绍一下你要值造的这个机器人。应段介绍只会是示在机器人的角色详情信息中,不会出现在提示词中,也不会影响到你的机器人。"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label="性别" prop="sex">
+                    <el-radio-group v-model="form.sex">
+                      <el-radio label="0">男</el-radio>
+                      <el-radio label="1">女</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="类型" prop="type">
+                    <el-radio-group v-model="form.type">
+                      <el-radio :label="0">公开</el-radio>
+                      <el-radio :label="1">私密</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="标签" prop="labelId">
+                    <el-select v-model="form.labelId" multiple filterable placeholder="搜索并选择与你的机器人相关的标签">
+                      <el-option :label="item.labelName" :value="item.id" v-for="(item, index) in labelData" :key="index"></el-option>
+                    </el-select>
+                  </el-form-item>
                 </div>
               </div>
             </div>
+
             <div class="text-xl font-medium my-6">机器人制作</div>
-            <div class="bg-gray-700 p-5 rounded-lg">
+            <div class="p-5 rounded-lg">
               <el-form-item label="开场白" prop="firstContent" label-width="80px" style="margin-bottom: 20px;">
                 <el-input 
                   v-model="form.firstContent" 
@@ -199,7 +200,7 @@ export default {
 }
 .form >>> .el-form-item__label,
 .form >>> .el-radio {
-  color: #fff;
+  /* color: #fff; */
 }
 .form >>> .el-select {
   width: 100%;
@@ -209,32 +210,32 @@ export default {
 .form >>> .el-select__input
  {
   width: 100%;
-  background-color: rgba(75, 85, 99, 1);
-  color: #fff;
+  /* background-color: rgba(75, 85, 99, 1); */
+  /* color: #fff; */
   border-radius: 0.5rem;
-  border-color: rgba(75, 85, 99, 0);
+  /* border-color: rgba(75, 85, 99, 0); */
 }
 .imgUp {
   
 }
 .imgUp >>> .el-upload__tip {
-  color: #b8b8b8;
+  /* color: #b8b8b8; */
   text-align: center;
 }
 .imgUp >>> .upload {
-  width: 100%;
   display: flex;
   flex-direction: column;
   justify-content: center;
   align-items: center;
-  padding: 20px;
+  width: 100%;
+  /* padding: 20px;
   background: rgba(75, 85, 99, 1);
-  border-radius: 10px;
+  border-radius: 10px; */
 }
 .imgUp >>> .el-upload {
-  border-radius: 50%;
+  /* border-radius: 50%; */
 }
 .imgUp >>> .el-upload-list__item {
-  border-radius: 50%;
+  /* border-radius: 50%; */
 }
 </style>

+ 102 - 120
src/views/homeComponents/HomePC.vue

@@ -1,109 +1,78 @@
 <template>
-  <div class="home bg-gray-900 comBg">
-    <Header @search="searchChange" :searchName="searchName" />
-    <div class="min-h-screen text-white">
-      <div class="container mx-auto py-3">
-        <div class="historysBox w-full mb-4">
-          <div class="mb-2 text-xl">继续聊天</div>
-          <el-carousel :autoplay="false" arrow="always" height="10rem" indicator-position="none">
-            <el-carousel-item v-for="item in 4" :key="item">
-              <div class="historys px-20 w-full whitespace-nowrap overflow-x-auto">
-                <div class="history w-full overflow-hidden rounded cursor-pointer inline-block" v-for="(item, index) in 5" :key="index">
-                  <img src="@/assets/images/1.png" class="historyImg w-full h-40" />
-                  <div class="absolute infoBg w-full h-24">
-                    <p class="text-center">聊天信息1</p>
-                    <p class="text-center">聊天信息2</p>
-                  </div>
-                </div>
-              </div>
-            </el-carousel-item>
-          </el-carousel>
-          
-        </div>
-        <div class="flex mb-3">
-          <div class="flex space-x-4">
-            <button class="px-3 py-2 rounded topActive">热门</button>
-            <button class="bg-gray-800 px-3 py-2 rounded">趋势</button>
-            <button class="bg-gray-800 px-3 py-2 rounded">最新</button>
-          </div>
-        </div>
-        <div class="flex flex-grow mb-3 items-center">
-          <input
-            type="text"
-            placeholder="搜索标签"
-            class="searchInput mr-2 px-3 py-2 rounded w-1/4 focus:border-blue-300 focus:outline-none focus:ring"
-          />
-          <div
-            v-for="(item, index) in selectLabelObj"
-            :key="index"
-            class="px-3 py-1 mx-1 rounded flex items-center cursor-pointer buttonBg1"
-            @click="clickLabel(item)"
-          >
-            {{ item.labelName }}
-            <i class="fas el-icon-close text-white"></i>
+  <div class="home bg-white px-28">
+    <div class=" text-3xl font-semibold pt-12 px-2 pb-6">
+      发现
+    </div>
+    <div class="min-h-screen">
+      <div class="flex">
+        <div class="flex flex-wrap w-9/12">
+          <div 
+            @click="clickLabelAll"
+            :class="[
+              selectLabel.length == 0 && 'buttonBg1',
+              'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
+            ]">
+            全部
           </div>
-          <el-button v-show="selectLabelObj.length > 0" class="textButton" type="text" @click="clearSelectLabel">移除所有</el-button>
-        </div>
-        <div class="flex flex-wrap">
           <div
-            v-for="(item, index) in labelData.slice(0, labelLength)"
+            v-for="(item, index) in labelData"
             :key="index"
             :class="[
-              selectLabel.indexOf(item.id) != -1 ? 'buttonBg1' : 'labelButton',
-              'labelButton px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer'
+              selectLabel.indexOf(item.id) != -1 && 'buttonBg1',
+              'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
             ]" 
             @click="clickLabel(item)"
           >
-            <i class="fas fa-fire text-yellow-500 mr-2"></i>
             {{ item.labelName }}({{item.num}})
           </div>
-          <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length"  class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            ....
-          </div>
-          <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length" class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            显示更多
-          </div>
-          <div v-show="labelData.length > 8 && labelLength > 8" @click="labelLength = 8" class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            隐藏
-          </div>
         </div>
-
-        <div class="grid grid-cols-5 gap-4 mt-4">
-          <div
-            v-for="(item, index) in characterList"
-            :key="index"
-            class="box2 relative rounded-lg overflow-hidden shadow-lg cursor-pointer"
-            @click="toDetail(item)"
-          >
+        <div class="w-30/12">
+          <input
+            type="text"
+            placeholder="搜索"
+            class="searchInput mr-2 px-3 py-2 rounded-md w-full focus:border-gray-300 focus:outline-none"
+            v-model="searchName"
+            @keydown="Enterkey"
+          />
+        </div>
+      </div>
+      <div class="grid grid-cols-5 gap-4 mt-4">
+        <div
+          v-for="(item, index) in characterList"
+          :key="index"
+          class="box2 relative rounded-lg overflow-hidden shadow-lg cursor-pointer"
+          @click="toDetail(item)"
+        > 
+          <div class="w-full overflow-hidden" style="height: 250px;">
             <img :src="baseApi + item.picture" class="w-full img" />
-            <div class="p-3">
-              <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
-              <p class="prologue text-sm">
-                {{ item.prologue }}
-              </p>
+          </div>
+          <div class="p-2">
+            <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+            <p class="prologue text-sm">
+              {{ item.prologue }}
+            </p>
 
-              <div class="labels flex my-2 flex-wrap">
-                <div v-for="(item2, index2) in item.labelArr" :key="index2" class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs">
-                  <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
-                  {{ item2 }}
-                </div>
+            <div class="labels flex my-1 flex-wrap">
+              <div v-for="(item2, index2) in item.labelArr" :key="index2" class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs text-gray-500">
+                <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
+                {{ item2 }}
               </div>
             </div>
-            <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-3 pb-3">
-              <div class="flex items-center box1">
-                <v-icon name="heart" scale="1"/>
-                <span class="ml-1">{{ item.likeNum }}</span>
-              </div>
-              <div class="flex items-center box1">
-                <!-- <i class="fas fa-comment mr-1"></i> -->
-                <v-icon name="star" scale="1"/>
-                <span class="ml-1">{{ item.collections }}</span>
-              </div>
-              <!-- <div class="flex items-center">
-                <v-icon name="share" scale="1.5"/>
-                <span>{{ item.likeNum }}</span>
-              </div> -->
+          </div>
+          <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-3 pb-3">
+            <div class="flex items-center box1">
+              <v-icon name="heart" scale="1"/>
+              <span class="ml-1">{{ item.likeNum }}</span>
             </div>
+            <div class="flex items-center box1">
+              <!-- <i class="fas fa-comment mr-1"></i> -->
+              <v-icon name="star" scale="1"/>
+              <span class="ml-1">{{ item.collections }}</span>
+            </div>
+            <!-- <div class="flex items-center">
+              <v-icon name="share" scale="1.5"/>
+              <span>{{ item.likeNum }}</span>
+            </div> -->
           </div>
         </div>
       </div>
@@ -145,19 +114,23 @@ export default {
     // 获取标签
     this.getLabelList()
     // 获取角色列表
-    if (this.$route.params.searchValue) {
-      // 有查询条件,做查询处理
-      this.searchChange(this.$route.params.searchValue)
-    } else {
-      // 没有查询条件则直接调用默认查询
-      this.getCharacterList()
-    }
-    
+    this.getCharacterList()
   },
   methods: {
-    searchChange(value) {
-      // console.log('查询条件', value);
-      this.searchName = value
+    Enterkey(e) {
+      if (e.keyCode == 13) {
+        this.searchChange()
+      }
+    },
+    clickLabelAll() {
+      this.selectLabel = []
+      let query = {
+        characterName: this.searchName,
+        labelId: this.selectLabel
+      }
+      this.getCharacterList(query)
+    },
+    searchChange() {
       let query = {
         characterName: this.searchName,
         labelId: this.selectLabel
@@ -191,6 +164,7 @@ export default {
       })
     },
     clickLabel(item) {
+      this.selectLabel = []
       let index = this.selectLabel.indexOf(item.id)
       if (index == -1) {
         this.selectLabel.push(item.id)
@@ -216,9 +190,9 @@ export default {
     },
     toDetail(item) {
       this.$router.push({
-        path: '/detail',
+        path: '/chat',
         query: {
-          id: item.id
+          characterId: item.id
         }
       })
     }
@@ -252,7 +226,7 @@ export default {
 
   font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
   font-size: 16px;
-  color: #676a6c;
+  // color: #676a6c;
   overflow-x: hidden;
 
   ul {
@@ -269,13 +243,6 @@ export default {
     font-weight: 100;
   }
 
-  p {
-    margin-top: 10px;
-
-    b {
-      font-weight: 700;
-    }
-  }
 
   .update-log {
     ol {
@@ -290,28 +257,26 @@ export default {
   }
 }
 .textButton {
-  color: #eee;
+  // color: #eee;
   margin-left: 5px;
 }
 .textButton:hover {
   color: #9333ea;
 }
 .labelButton {
-  background: #ffffff1a;
+  border: solid 1px #e6e6e6;
+  background: var(--bg-color2);
 }
 .buttonBg1 {
-  background: linear-gradient(270deg, #5ea1f9, #d287f1);
+  background: var(--bg-color1);
+  color: #fff;
 }
 
 .topActive {
   background: var(--bg-color1);
 }
 .tag {
-  background: rgba(245, 174, 67, 0.2);
-}
-.searchInput {
-  background: #ffffff00;
-  border: 1px solid #ffffff4d;
+  background: var(--bg-color2);
 }
 .box1 {
   border: 1px solid #ffffff4d;
@@ -324,12 +289,22 @@ export default {
 .box2 {
   background: #ffffff0f; 
   border: 1px solid #ffffff2e;
-  height: 540px;
+  min-width: 200px;
+  height: 35vw;
+  min-height: 300px;
+  max-height: 500px;
+}
+.box2:hover {
+  border: solid 1px var(--bg-color1);
 }
 .img {
   height: 250px;
   object-fit: cover;
   object-position: top;
+  transition: transform .2s
+}
+.img:hover {
+  transform: scale(1.1);
 }
 .labels {
   max-height: 84px;
@@ -373,6 +348,13 @@ export default {
     }
   }
 }
+.searchInput {
+  background-color: var(--bg-color2);
+  // border: 1px solid #b6b6b6;
+}
+.searchInput:focus {
+  border: 1px solid #b6b6b6;
+}
 </style>
 <style scoped>
 .historysBox >>> .el-carousel__arrow {

+ 381 - 0
src/views/homeComponents/HomePC_lod.vue

@@ -0,0 +1,381 @@
+<template>
+  <div class="home bg-white">
+    <!-- <Header @search="searchChange" :searchName="searchName" /> -->
+    <div class="min-h-screen text-white">
+      <!-- <div class="container mx-auto py-3">
+        <div class="historysBox w-full mb-4">
+          <div class="mb-2 text-xl">继续聊天</div>
+          <el-carousel :autoplay="false" arrow="always" height="10rem" indicator-position="none">
+            <el-carousel-item v-for="item in 4" :key="item">
+              <div class="historys px-20 w-full whitespace-nowrap overflow-x-auto">
+                <div class="history w-full overflow-hidden rounded cursor-pointer inline-block" v-for="(item, index) in 5" :key="index">
+                  <img src="@/assets/images/1.png" class="historyImg w-full h-40" />
+                  <div class="absolute infoBg w-full h-24">
+                    <p class="text-center">聊天信息1</p>
+                    <p class="text-center">聊天信息2</p>
+                  </div>
+                </div>
+              </div>
+            </el-carousel-item>
+          </el-carousel> 
+        </div> -->
+        <!-- <div class="flex mb-3">
+          <div class="flex space-x-4">
+            <button class="px-3 py-2 rounded topActive">热门</button>
+            <button class="bg-gray-800 px-3 py-2 rounded">趋势</button>
+            <button class="bg-gray-800 px-3 py-2 rounded">最新</button>
+          </div>
+        </div> -->
+        <!-- <div class="flex flex-grow mb-3 items-center">
+          <input
+            type="text"
+            placeholder="搜索标签"
+            class="searchInput mr-2 px-3 py-2 rounded w-1/4 focus:border-blue-300 focus:outline-none focus:ring"
+          />
+          <div
+            v-for="(item, index) in selectLabelObj"
+            :key="index"
+            class="px-3 py-1 mx-1 rounded flex items-center cursor-pointer buttonBg1"
+            @click="clickLabel(item)"
+          >
+            {{ item.labelName }}
+            <i class="fas el-icon-close text-white"></i>
+          </div>
+          <el-button v-show="selectLabelObj.length > 0" class="textButton" type="text" @click="clearSelectLabel">移除所有</el-button>
+        </div> -->
+        <div class="flex flex-wrap">
+          <div
+            v-for="(item, index) in labelData.slice(0, labelLength)"
+            :key="index"
+            :class="[
+              selectLabel.indexOf(item.id) != -1 && 'buttonBg1',
+              'labelButton px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer text-gray-600'
+            ]" 
+            @click="clickLabel(item)"
+          >
+            <i class="fas fa-fire text-yellow-500 mr-2"></i>
+            {{ item.labelName }}({{item.num}})
+          </div>
+          <!-- <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length"  class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+            ....
+          </div>
+          <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length" class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+            显示更多
+          </div>
+          <div v-show="labelData.length > 8 && labelLength > 8" @click="labelLength = 8" class="labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+            隐藏
+          </div> -->
+        </div>
+
+        <div class="grid grid-cols-5 gap-4 mt-4">
+          <div
+            v-for="(item, index) in characterList"
+            :key="index"
+            class="box2 relative rounded-lg overflow-hidden shadow-lg cursor-pointer"
+            @click="toDetail(item)"
+          >
+            <img :src="baseApi + item.picture" class="w-full img" />
+            <div class="p-3">
+              <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+              <p class="prologue text-sm">
+                {{ item.prologue }}
+              </p>
+
+              <div class="labels flex my-2 flex-wrap">
+                <div v-for="(item2, index2) in item.labelArr" :key="index2" class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs">
+                  <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
+                  {{ item2 }}
+                </div>
+              </div>
+            </div>
+            <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-3 pb-3">
+              <div class="flex items-center box1">
+                <v-icon name="heart" scale="1"/>
+                <span class="ml-1">{{ item.likeNum }}</span>
+              </div>
+              <div class="flex items-center box1">
+                <!-- <i class="fas fa-comment mr-1"></i> -->
+                <v-icon name="star" scale="1"/>
+                <span class="ml-1">{{ item.collections }}</span>
+              </div>
+              <!-- <div class="flex items-center">
+                <v-icon name="share" scale="1.5"/>
+                <span>{{ item.likeNum }}</span>
+              </div> -->
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Header from "@/views/homeComponents/Header.vue"
+import { labelListApi, characterListApi } from "@/api/home.js"
+// 引入需要的图标
+import 'vue-awesome/icons/heart'
+// import 'vue-awesome/icons/comment'
+import 'vue-awesome/icons/star'
+
+export default {
+  name: "HomePC",
+  components: {
+    Header
+  },
+  data() {
+    return {
+      historys: [],
+      labelLength: 8,
+      searchName: '',
+      labelData: [],
+      selectLabel: [],
+      selectLabelObj: [],
+      characterList: [],
+      url: [
+        require('@/assets/images/1.png'),
+        require('@/assets/images/2.png'),
+        require('@/assets/images/3.png'),
+        require('@/assets/images/4.png'),
+      ]
+    }
+  },
+  mounted() {
+    // 获取标签
+    this.getLabelList()
+    // 获取角色列表
+    if (this.$route.params.searchValue) {
+      // 有查询条件,做查询处理
+      this.searchChange(this.$route.params.searchValue)
+    } else {
+      // 没有查询条件则直接调用默认查询
+      this.getCharacterList()
+    }
+    
+  },
+  methods: {
+    searchChange(value) {
+      // console.log('查询条件', value);
+      this.searchName = value
+      let query = {
+        characterName: this.searchName,
+        labelId: this.selectLabel
+      }
+      this.getCharacterList(query)
+    },
+    getLabelList() {
+      let params = {
+        pageSize: 20,
+        pageNum: 1
+      }
+      labelListApi(params).then(res => {
+        // console.log(res, '标签列表');
+        this.labelData = res.rows
+      })
+    },
+    getCharacterList(query) {
+      let params = {
+        pageSize: 20,
+        pageNum: 1
+      }
+      if (query) {
+        params = {
+          ...params,
+          ...query
+        }
+      }
+      characterListApi(params).then(res => {
+        // console.log(res, '角色列表');
+        this.characterList = res.rows
+      })
+    },
+    clickLabel(item) {
+      let index = this.selectLabel.indexOf(item.id)
+      if (index == -1) {
+        this.selectLabel.push(item.id)
+        this.selectLabelObj.push(item)
+      } else {
+        this.selectLabel.splice(index, 1)
+        this.selectLabelObj.splice(index, 1)
+      }
+      let query = {
+        characterName: this.searchName,
+        labelId: this.selectLabel
+      }
+      this.getCharacterList(query)
+    },
+    clearSelectLabel() {
+      this.selectLabel = []
+      this.selectLabelObj = []
+      let query = {
+        characterName: this.searchName,
+        labelId: this.selectLabel
+      }
+      this.getCharacterList(query)
+    },
+    toDetail(item) {
+      this.$router.push({
+        path: '/detail',
+        query: {
+          id: item.id
+        }
+      })
+    }
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.home {
+  font-size: 17.5px;
+  blockquote {
+    padding: 10px 20px;
+    margin: 0 0 20px;
+    font-size: 17.5px;
+    border-left: 5px solid #eee;
+  }
+  hr {
+    margin-top: 20px;
+    margin-bottom: 20px;
+    border: 0;
+    border-top: 1px solid #eee;
+  }
+  .col-item {
+    margin-bottom: 20px;
+  }
+
+  ul {
+    padding: 0;
+    margin: 0;
+  }
+
+  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 16px;
+  color: #676a6c;
+  overflow-x: hidden;
+
+  ul {
+    list-style-type: none;
+  }
+
+  h4 {
+    margin-top: 0px;
+  }
+
+  h2 {
+    margin-top: 10px;
+    font-size: 26px;
+    font-weight: 100;
+  }
+
+  p {
+    margin-top: 10px;
+
+    b {
+      font-weight: 700;
+    }
+  }
+
+  .update-log {
+    ol {
+      display: block;
+      list-style-type: decimal;
+      margin-block-start: 1em;
+      margin-block-end: 1em;
+      margin-inline-start: 0;
+      margin-inline-end: 0;
+      padding-inline-start: 40px;
+    }
+  }
+}
+.textButton {
+  color: #eee;
+  margin-left: 5px;
+}
+.textButton:hover {
+  color: #9333ea;
+}
+.labelButton {
+  border: solid 1px #e6e6e6;
+  background: hsla(0,0%,83%,.24);
+}
+.buttonBg1 {
+  background: linear-gradient(270deg, #5ea1f9, #d287f1);
+}
+
+.topActive {
+  background: var(--bg-color1);
+}
+.tag {
+  background: rgba(245, 174, 67, 0.2);
+}
+.searchInput {
+  background: #ffffff00;
+  border: 1px solid #ffffff4d;
+}
+.box1 {
+  border: 1px solid #ffffff4d;
+  height: 30px;
+  padding: 0 10px;
+  border-radius: 18px;
+  width: 68px;
+  font-size: 14px;
+}
+.box2 {
+  background: #ffffff0f; 
+  border: 1px solid #ffffff2e;
+  height: 540px;
+}
+.img {
+  height: 250px;
+  object-fit: cover;
+  object-position: top;
+}
+.labels {
+  max-height: 84px;
+  overflow-y: auto;
+}
+.prologue {
+  overflow:hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 4;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+}
+.historysBox {
+  .historys {
+    display: grid;
+    grid-gap: 10px;
+    grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
+  }
+  .historys::-webkit-scrollbar { 
+    width: 0; /* 隐藏滚动条 */
+  }
+  .history {
+    position: relative;
+    overflow: hidden;
+    justify-self: center;
+    .historyImg {
+      position: relative;
+      object-fit: cover;
+      object-position: top;
+      
+    }
+    .infoBg {
+      background: rgba(0, 0, 0, 0.5);
+      transition: bottom 0.2s;
+      bottom: -6rem;
+    }
+  }
+  .history:hover {
+    .infoBg {
+      bottom: 0;
+    }
+  }
+}
+</style>
+<style scoped>
+.historysBox >>> .el-carousel__arrow {
+  background: var(--bg-color1);
+}
+</style>

+ 50 - 5
src/views/homeComponents/login.vue

@@ -2,8 +2,8 @@
   <div class="login">
     <!-- 登录表单 -->
     <el-form class="form" :rules="loginRules" ref="formLogin" :model="formLogin" label-width="0">
-      <el-form-item label="" prop="account">
-        <el-input v-model="formLogin.account" placeholder="手机号">
+      <el-form-item label="" prop="mobile">
+        <el-input v-model="formLogin.mobile" placeholder="手机号">
           <template slot="prepend">+86</template>
         </el-input>
       </el-form-item>
@@ -47,6 +47,8 @@
 </template>
 
 <script>
+import { getSendVerificationCode, phoneLogin } from '@/api/login'
+import { getToken, setToken, removeToken } from '@/utils/auth'
 export default {
   data() {
     return {
@@ -58,8 +60,13 @@ export default {
         password: null,
       },
       loginRules: {
-        account: [
+        mobile: [
           { required: true, message: '请输入手机号', trigger: 'blur' },
+          { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' },
+        ],
+        code: [
+          { required: true, message: '请输入验证码', trigger: 'blur' },
+          { pattern: /^[0-9]{6}$/, message: '请输入正确的验证码', trigger: 'blur' },
         ],
         password: [
           { required: true, message: '请输入用户密码', trigger: 'blur' },
@@ -81,6 +88,8 @@ export default {
       }
     }
   },
+  mounted() {
+  },
   methods: {
     getCode() {
       this.codeTime = 60
@@ -90,6 +99,32 @@ export default {
           clearInterval(this.codeInterval)
         }
       }, 1000)
+      let params = {
+        mobile: this.formLogin.mobile
+      }
+      getSendVerificationCode(params).then(res =>{
+        if (res.code === 200) {
+          this.$message({
+            message: '验证码发送成功',
+            type: 'success'
+          });
+        } else {
+          clearInterval(this.codeInterval)
+          this.codeTime = -1
+          this.$message({
+            message: res.msg,
+            type: 'error'
+          });
+        }
+      })
+      .catch((err) => {
+        clearInterval(this.codeInterval)
+        this.codeTime = -1
+        this.$message({
+          message: res.msg,
+          type: 'error'
+        });
+      })
     },
     clickLogin() {
       this.$refs.formLogin.validate((valid) => {
@@ -102,13 +137,23 @@ export default {
             }).then(() => {})
             return
           }
-          this.$store.dispatch('Login', this.formLogin).then(() => {
+          phoneLogin(this.formLogin).then((res) => {
+            console.log(res, '手机登录成功');
+            setToken(res.data.userToken)
+            this.$store.commit('SET_TOKEN', res.data.userToken)
             this.$message({
               message: '登录成功',
               type: 'success'
             });
-            this.showPopup = false
+            this.$store.commit('app/TOGGLE_POPUP', false)
           })
+          // this.$store.dispatch('Login', this.formLogin).then(() => {
+          //   this.$message({
+          //     message: '登录成功',
+          //     type: 'success'
+          //   });
+          //   this.showPopup = false
+          // })
         }
       })
     },

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor