chenrong 1 year ago
parent
commit
732d16ed02

+ 2 - 1
src/App.vue

@@ -37,6 +37,7 @@ export default  {
 .pageContent {
   width: calc(100% - 72px);
   height: 100%;
-  overflow-y: auto;
+  overflow: visible;
+  // overflow-y: auto;
 }
 </style>

+ 20 - 2
src/api/create.js

@@ -1,10 +1,28 @@
 import request from '@/utils/request'
 
-// 获取标签列表
+// 创建角色
 export function addCharacterApi(data) {
   return request({
     url: `/appUser/addCharacter`,
     method: 'post',
     data
   })
-}
+}
+
+// 创建场景
+export function addSceneApi(data) {
+  return request({
+    url: `/appUser/addScene`,
+    method: 'post',
+    data
+  })
+}
+
+// export function personalityListApi(params) {
+//   return request({
+//     url: `/system/personality/list`,
+//     method: 'get',
+//     params
+//   })
+// }
+

+ 4 - 3
src/api/login.js

@@ -25,10 +25,11 @@ export function register(data) {
 }
 
 // 获取用户详细信息
-export function getInfo() {
+export function getInfo(params) {
   return request({
-    url: '/getInfo',
-    method: 'get'
+    url: '/appUser/userInfo',
+    method: 'get',
+    params
   })
 }
 

+ 11 - 0
src/api/profile.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+
+// 获取用户创建的角色场景等
+export function queryCharacterAndSceneApi(params) {
+  return request({
+    url: `/appUser/queryCharacterAndScene`,
+    method: 'get',
+    params
+  })
+}

+ 5 - 2
src/assets/styles/index.scss

@@ -122,8 +122,12 @@ aside {
 //main-container全局样式
 .app-container {
   padding: 20px;
+  
+}
+.app-pageContainer {
+  height: 100vh;
+  overflow-y: auto;
 }
-
 .components-container {
   margin: 30px 50px;
   position: relative;
@@ -211,7 +215,6 @@ button, input, optgroup, select, textarea {
 .fontH5 {
   font-size: 12px;
 }
-
 :root {
   --bg-color1: #7262f6;
   --bg-color2: hsla(0, 0%, 83%, 0.24);

+ 18 - 2
src/router/index.js

@@ -41,6 +41,7 @@ export const constantRoutes = [
     component: () => import("@/views/home"),
     name: "Home",
   },
+  // 角色详情界面
   {
     path: "/detail",
     component: () => import("@/views/detail"),
@@ -51,6 +52,7 @@ export const constantRoutes = [
     component: () => import("@/views/detail/indexH5.vue"),
     name: "DetailH5",
   },
+  // 对话界面
   {
     path: "/chat",
     component: () => import("@/views/chat"),
@@ -61,7 +63,7 @@ export const constantRoutes = [
     component: () => import("@/views/chat/indexH5"),
     name: "ChatH5",
   },
-  
+  // 创建角色
   {
     path: "/create",
     component: () => import("@/views/create"),
@@ -72,16 +74,25 @@ export const constantRoutes = [
     component: () => import("@/views/create/indexH5"),
     name: "CreateH5",
   },
+  // 创建场景
+  {
+    path: "/createScene",
+    component: () => import("@/views/create/createScene"),
+    name: "CreateScene",
+  },
+  // 注册移动端
   {
     path: "/registerH5",
     component: () => import("@/views/loginAndRegister/registerH5"),
     name: "RegisterH5",
   },
+  // 登录移动端
   {
     path: "/loginH5",
     component: () => import("@/views/loginAndRegister/loginH5"),
     name: "LoginH5",
   },
+  // 会员中心
   {
     path: "/vip",
     component: () => import("@/views/vip/index"),
@@ -93,7 +104,12 @@ export const constantRoutes = [
     component: () => import("@/views/profile/index"),
     name: "profile",
   },
-  
+  // 账户详情
+  {
+    path: "/user",
+    component: () => import("@/views/user/index"),
+    name: "user",
+  },
 ];
 
 // 动态路由,基于用户权限动态去加载

+ 22 - 10
src/store/modules/user.js

@@ -3,6 +3,7 @@ import { getToken, setToken, removeToken } from '@/utils/auth'
 
 const user = {
   state: {
+    userId: '',
     token: getToken(),
     name: '',
     avatar: '',
@@ -11,6 +12,9 @@ const user = {
   },
 
   mutations: {
+    SET_USERID: (state, value) => {
+      state.userId = value
+    },
     SET_TOKEN: (state, token) => {
       state.token = token
     },
@@ -46,7 +50,11 @@ const user = {
     // 获取用户信息
     GetInfo({ commit, state }) {
       return new Promise((resolve, reject) => {
-        getInfo().then(res => {
+        let params = {
+          userId: state.userId
+        }
+        getInfo(params).then(res => {
+          console.log(res, 'resUserInfo')
           const user = res.user
           const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
           if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
@@ -67,15 +75,19 @@ const user = {
     // 退出系统
     LogOut({ commit, state }) {
       return new Promise((resolve, reject) => {
-        logout(state.token).then(() => {
-          commit('SET_TOKEN', '')
-          commit('SET_ROLES', [])
-          commit('SET_PERMISSIONS', [])
-          removeToken()
-          resolve()
-        }).catch(error => {
-          reject(error)
-        })
+        commit('SET_TOKEN', '')
+        commit('SET_USERID', '')
+        removeToken()
+        resolve()
+        // logout(state.token).then(() => {
+        //   commit('SET_TOKEN', '')
+        //   commit('SET_ROLES', [])
+        //   commit('SET_PERMISSIONS', [])
+        //   removeToken()
+        //   resolve()
+        // }).catch(error => {
+        //   reject(error)
+        // })
       })
     },
 

+ 1 - 1
src/utils/request.js

@@ -119,7 +119,7 @@ service.interceptors.response.use(
           .then(() => {
             isRelogin.show = false;
             store.dispatch("LogOut").then(() => {
-              location.href = "/";
+              store.commit('app/TOGGLE_POPUP', true)
             });
           })
           .catch(() => {

+ 402 - 66
src/views/chat/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="chat bg-white">
-    <div class="flex items-center justify-center h-screen">
-      <div class="leftInfo relative">
+    <div class="flex items-center h-screen relative" >
+      <div class="leftInfo relative" v-show="!showNodata" >
         <div class="history">
           <!-- historyActive -->
           <div class="historyBox" v-for="(item, index) in allRecords" :key="index">
@@ -20,13 +20,31 @@
             </div>
             <!-- <transition name="el-zoom-in-top"> -->
               <div class="dialogueList mt-4" v-show="item.open">
+                <div class="flex justify-between mb-2">
+                  <el-button type="primary" class="flex-1" round @click="newStart_juese(item)">新的对话</el-button>
+                  <el-dropdown 
+                    class="flex justify-end items-center ml-2"
+                    trigger="click" 
+                    @command="handleCommand2($event, item)" 
+                  >
+                    <div class=" w-8 h-8 bg-gray-100 rounded flex justify-center items-center cursor-pointer">
+                      <i slot="reference" class="el-icon-more"></i>
+                    </div>
+                    <el-dropdown-menu slot="dropdown" >
+                      <el-dropdown-item command="2">删除</el-dropdown-item>
+                    </el-dropdown-menu>
+                  </el-dropdown>
+                </div>
                 <div class="dialogue flex justify-between items-center w-full h-16 rounded-md px-2 mb-2 cursor-pointer relative"
                   :class="info.id == item.id && index2 == recordsIndex && 'historyActive'"
                   v-for="(item2, index2) in item.chatCharacterList"
                   :key="index2"
                   @click.self="clickDialogue(item, item2, index2)"
-                >
-                  <span @click.self="clickDialogue(item, item2, index2)">{{ item2.chatTitle }}</span>
+                > 
+                  <span @click.self="clickDialogue(item, item2, index2)">
+                    <i v-if="item2.sceneId || item2.sceneIcon" class="el-icon-video-camera"></i>
+                    {{ item2.chatTitle }}
+                  </span>
                   <span @click.self="clickDialogue(item, item2, index2)" class=" text-sm text-gray-500">{{ item2.createTime }}</span>
                   <el-dropdown 
                     class="dialogueIconBg absolute h-16 w-20 right-0 flex justify-end items-center pr-4"
@@ -46,11 +64,12 @@
             <!-- </transition> -->
           </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="chatInfo absolute top-0 left-0 w-full h-full z-30 bg-white" v-show="showInfo == 1">
+          <div class="flex flex-col p-4 h-full">
             <div class="flex justify-between items-center text-base mb-3">
               <div>角色详情</div>
-              <i class="el-icon-close cursor-pointer" @click="showInfo = false"></i>
+              <i class="el-icon-close cursor-pointer" @click="showInfoChange(0)"></i>
             </div>
             <div class="flex">
               <span class="chatInfo_photo">
@@ -64,7 +83,7 @@
             <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>
+                <span class="ml-1">{{ info.hotCount }}</span>
               </div>
             </div>
             <div class="flex justify-around mt-4">
@@ -76,7 +95,7 @@
                 <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 }}
@@ -111,22 +130,39 @@
                 </div>
               </div>
             </transition>
-            <div class="mt-5 text-base pb-3">
+            <div class="mt-5 text-base pb-3 flex-1 flex flex-col">
               <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 v-if="info.sceneList && info.sceneList.length > 0" class="grid grid-cols-2 gap-2 mb-4 cursor-pointer">
+                  <div class="flex flex-col justify-center" v-for="(item, index) in info.sceneList" :key="index"  @click="sceneChange(item)">
+                    <img class=" rounded w-full h-24 object-cover" :src="baseApi + item.background" alt="">
+                    <div>{{ item.sceneName }}</div>
+                    <div class=" text-gray-400">{{ item.sceneDescription }}</div>
+                  </div>
+                </div>
+                <el-empty v-else description="暂无场景"></el-empty>
+                <div class="flex justify-center mt-10">
+                  <el-button type="primary" round @click="toCreateScene">创建场景</el-button>
                 </div>
               </div>
             </div>
           </div>
         </div>
+        <!-- 场景详情 -->
+        <div class="absolute top-0 left-0 w-full h-full z-30 bg-white overflow-hidden" v-show="showInfo == 2">
+          <div class="flex flex-col p-4 h-full">
+            <div class="flex justify-between items-center text-base mb-3">
+              <div>场景详情</div>
+              <i class="el-icon-close cursor-pointer" @click="showInfoChange(0)"></i>
+            </div>
+            <div class=" text-gray-500">{{ sceneInfo.sceneDescription }}</div>
+          </div>
+        </div>
       </div>
-      <div class="content">
+      <div class="content" :class="fullScreen && 'contentFull'" v-show="!showNodata" :style="{ backgroundImage: `url(${baseApi}${sceneInfo.background})`}">
         <!-- <div class="leftImg">
           <img :src="baseApi + info.picture" alt="">
           <div class="aiInfo">
@@ -144,13 +180,37 @@
             </div>
           </div>
         </div> -->
-        
-        <div class="chat-box">
+        <div class="fullScreenButton rounded-full border border-gray-200" @click="clickFullScreen">
+          <i class="el-icon-arrow-left" v-if="!fullScreen"></i>
+          <i class="el-icon-arrow-right" v-else></i>
+        </div>
+        <div class="chat-box" >
           <div class="chatBoxTitle absolute top-0">
             <div>
               {{ info.characterName }}
+              <el-dropdown
+                v-if="sceneId"
+                class="flex justify-end items-center"
+                trigger="click"
+                @command="handleCommand3"
+                @visible-change="dropdown3Show = !dropdown3Show"
+              >
+                <div>
+                  <div slot="reference" class="flex justify-center items-center cursor-pointer text-white">
+                    已进入场景:{{ sceneInfo.sceneName }}
+                    <i class="el-icon-arrow-up ml-2" style="font-size: 16px;" v-if="dropdown3Show"></i>
+                    <i  class="el-icon-arrow-down ml-2" style="font-size: 16px;" v-else></i>
+                  </div>
+                  
+                </div>
+                <el-dropdown-menu slot="dropdown" >
+                  <el-dropdown-item command="1">场景详情</el-dropdown-item>
+                  <el-dropdown-item command="2">新场景对话</el-dropdown-item>
+                  <el-dropdown-item command="3">回到常规对话</el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
             </div>
-            <div class="flex w-60 justify-between">
+            <div class="flex w-60 justify-end">
               <el-tooltip effect="dark" content="设定" placement="bottom">
                 <el-popover
                   placement="bottom"
@@ -159,26 +219,26 @@
                   <div class="p-2">
                     <div class="flex justify-between mb-4">
                       <span>语音自动播放</span>
-                      <el-switch v-model="value1">
+                      <el-switch v-model="setting.value1">
                       </el-switch>
                     </div>
                     <div class="flex justify-between">
                       <span>全屏幕</span>
-                      <el-switch v-model="value1">
+                      <el-switch v-model="setting.value2">
                       </el-switch>
                     </div>
                   </div>
-                  <i slot="reference" class="fa-solid fa-sliders cursor-pointer text-xl"></i>
+                  <i slot="reference" class="fa-solid fa-sliders cursor-pointer text-xl mr-6"></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>
+                <i class="fa-solid fa-file-invoice cursor-pointer text-xl mr-6" @click="showInfoChange(1)"></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 v-if="!sceneId" effect="dark" content="开始新的对话" placement="bottom">
+                <i class="fa-solid fa-comment-medical cursor-pointer text-xl mr-6" @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>
+                <i class="fa-solid fa-clock-rotate-left cursor-pointer text-xl" @click="showInfoChange(0)"></i>
               </el-tooltip>
             </div>
           </div>
@@ -197,7 +257,7 @@
                   <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)">
+                      <img v-else class="yyPlay" src="@/assets/images/播放/yyPlay.png" alt="" @click="playAudio(index)">
                       <!-- <svg-icon class="icon" class-name="speech-icon" icon-class="speech" @click.stop="click" /> -->
                     </div>
                     <div v-show="!item.content" class="loadingMessage" >
@@ -246,13 +306,17 @@
                 <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'">
+              <button @click.prevent="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>
+      <div v-show="showNodata" class=" w-full h-full flex flex-col justify-center items-center">
+        <el-empty description="暂无聊天记录,点击按钮并探索新角色。"></el-empty>
+        <el-button type="primary" round @click="$router.push('/')">寻找一个角色</el-button>
+      </div>
       <el-dialog
         title="配置"
         :visible.sync="showConfig"
@@ -318,6 +382,8 @@ export default {
   },
   data() {
     return {
+      // 是否全屏
+      fullScreen: false,
       // 角色所有聊天列表
       allRecords: [],
       // 聊天记录id
@@ -327,7 +393,7 @@ export default {
       recordsIndex: null,
       showDetail: false,
       showConfig: false,
-      showInfo: false,
+      showInfo: 0,
       messageOptions: [],
       info: {},
       messageLoading: false,
@@ -339,11 +405,27 @@ export default {
         radio2: null,
         radio3: null,
       },
+      // 对话接口是否返回错误状态
+      resError: false,
       // 模型列表
       modelList: [],
-      value1: '',
+      setting: {
+        value1: false,
+        value2: false,
+      },
+      
       //音频地址
-      audioUrl: ''
+      audioUrl: '',
+      //场景下拉菜单
+      dropdown3Show: false,
+      // 场景对话相关
+      sceneId: null,
+      sceneInfo: {}
+    }
+  },
+  computed: {
+    showNodata() {
+      return this.allRecords.length == 0 && !this.$route.query.characterId
     }
   },
   mounted() {
@@ -366,7 +448,10 @@ export default {
       await this.getChatCharacterRecords()
       // 如果用角色id获取角色详情
       if (this.$route.query.characterId) {
-        this.showInfo = true
+        if (this.$route.query.sceneId) {
+          this.sceneId = this.$route.query.sceneId
+        }
+        this.showInfoChange(1)
         await this.getDetail(this.$route.query.characterId)
       } else {
         this.allRecords[0].open = true
@@ -377,20 +462,107 @@ export default {
       // 获取模型列表
       this.getModelList()
     },
+    // 左侧面板变化
+    showInfoChange(index) {
+      this.fullScreen = false
+      this.showInfo = index
+    },
+    // 全屏
+    clickFullScreen() {
+      this.fullScreen = !this.fullScreen
+    },
+    // 点击聊天记录切换聊天
     async clickDialogue(value1, value2, index) {
+      console.log(value2, 'value2');
+      let _this = this
       this.audioUrl = ""
       this.messageOptions = []
       this.returnMessage = []
-      // 点击聊天记录切换聊天
       if (this.$route.query.characterId) {
         this.$route.query.characterId = value1.id
       }
-      await this.getDetail(value1.id)
-
+      if (!value2) {
+        return
+      }
+      // 如果点击的是场景聊天
+      if (value2.sceneId) {
+        this.sceneId = value2.sceneId
+        await this.getDetail(value1.id)
+        // 从角色详情中获取场景列表
+        let sceneList = this.info.sceneList
+        // 获取当前聊天对应的场景
+        for (let i = 0; i < sceneList.length; i++) {
+          const element = sceneList[i];
+          if (element.sceneId == value2.sceneId) {
+            _this.sceneInfo = element
+          }
+        }
+      } else {
+        this.sceneId = null
+        this.sceneInfo = {}
+        await this.getDetail(value1.id)
+      }
+      
       this.recordId = value2.id
       this.getChatRecord(value2.id)
       this.recordsIndex = index
     },
+    // 场景下拉菜单
+    handleCommand3(value) {
+      if (value == 1) {
+        this.showInfoChange(2)
+      } else if (value == 2) {
+        // 情况聊天记录
+        this.returnMessage = []
+        // 新建场景对话
+        this.newStart()
+        // 增加开场白
+        this.returnMessage.push({
+          role: 'assistant',
+          content: this.sceneInfo.sceneWelcome
+        })
+      } else if (value == 3) {
+        // 回到常规对话
+        // 遍历当前聊天记录是否有常规对话
+        let messages = null
+        for (let i = 0; i < this.allRecords.length; i++) {
+          const element = this.allRecords[i];
+          if (element.id == this.info.id) {
+            messages = element
+          }
+        }
+        console.log(messages, 'messages');
+        let flag = false
+        for (let i = 0; i < messages.chatCharacterList.length; i++) {
+          const element = messages.chatCharacterList[i];
+          console.log(element, 'element');
+          if (!element.sceneId) {
+            flag = true
+            this.clickDialogue(messages, element, i)
+            break
+          }
+        }
+        // 如果聊天记录里没有常规对话,则新增一个常规对话
+        if (!flag) {
+          this.sceneId = null
+          this.sceneInfo = {}
+          this.newStart()
+        }
+      }
+    },
+    // 聊天记录列表-角色下拉菜单
+    handleCommand2(value, value1) {
+      if (value == 2) {
+        this.$confirm('此操作将永久删除该角色所有聊天记录, 是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          this.clearRecord(value1)
+        })
+      }
+    },
+    // 聊天记录列表-角色-聊天记录下拉菜单
     handleCommand(value, value1, value2) {
       console.log(value, 'value');
       if (value == 1) {
@@ -405,6 +577,30 @@ export default {
         })
       }
     },
+    // 聊天记录新增对话
+    async newStart_juese(value) {
+      console.log(value, 'value');
+      this.audioUrl = ""
+      this.messageOptions = []
+      this.returnMessage = []
+      // 点击聊天记录切换聊天
+      if (this.$route.query.characterId) {
+        this.$route.query.characterId = value.id
+      }
+      await this.getDetail(value.id)
+      this.recordId = await this.addChat()
+      for (let i = 0; i < this.allRecords.length; i++) {
+        const element = this.allRecords[i];
+        if (element.id == this.info.id) {
+          element.chatCharacterList.push({
+            chatTitle: "常规聊天",
+            createTime: '',
+            id: this.recordId
+          })
+          this.recordsIndex = element.chatCharacterList.length - 1
+        } 
+      }
+    },
     // 修改聊天记录标题
     editDialogueTitle(value1, value2) {
       this.$prompt('新标题名称', '修改标题', {
@@ -428,7 +624,9 @@ export default {
     clearRecord(value1, value2) {
       let params = {
         characterId: value1.id,
-        recordId: value2.id
+      }
+      if (value2) {
+        params.recordId = value2.id
       }
       clearRecordApi(params).then(res => {
         this.$message({
@@ -438,7 +636,7 @@ export default {
         this.getChatCharacterRecords()
       })
     },
-    getChatRecord(recordId) {
+    async getChatRecord(recordId) {
       let params = {
         characterId: this.info.id,
         recordId: recordId
@@ -457,19 +655,48 @@ export default {
     searchHistory(characterId) {
       // 查看对话记录是否有选中的角色
       // console.log('查看对话记录是否有选中的角色');
-      console.log(this.allRecords, 'searchHistory');
       let flg = false
       for (let i = 0; i < this.allRecords.length; i++) {
         const element = this.allRecords[i];
         // 如果有则选中角色的最新一条记录并获取对话聊天记录
         if (element.id == characterId) {
-          flg = true
           console.log(element, '查看对话记录是否有选中的角色');
+          flg = true
           element.open = true
-          this.recordsIndex = element.chatCharacterList.length - 1
-          let recordId = element.chatCharacterList[element.chatCharacterList.length - 1].id
-          this.recordId = recordId
-          this.getChatRecord(recordId)
+          // 二级对话判断当前是普通对话还是场景对话
+          // 取对应的最后一条消息记录
+          let chatCharacterList = element.chatCharacterList
+          let chatCharacter = null
+          let index = null
+          for (let i = 0; i < chatCharacterList.length; i++) {
+            const element2 = chatCharacterList[i];
+            if (this.$route.query.sceneId == element2.sceneId) {
+              chatCharacter = element2
+              index = i
+            } else if (!this.$route.query.sceneId && !element2.sceneId) {
+              chatCharacter = element2
+              index = i
+            }
+          }
+          // 如果有聊天记录则点击
+          if (chatCharacter) {
+            this.clickDialogue(element, chatCharacter, index)
+          } else {
+            // 如果没有场景聊天记录则新增场景聊天
+            // 从角色详情中获取场景列表
+            let sceneList = this.info.sceneList
+            // 获取当前聊天对应的场景
+            for (let i = 0; i < sceneList.length; i++) {
+              const element = sceneList[i];
+              if (element.sceneId == this.$route.query.sceneId) {
+                this.sceneInfo = element
+              }
+            }
+          }
+          // this.recordsIndex = element.chatCharacterList.length - 1
+          // let recordId = element.chatCharacterList[element.chatCharacterList.length - 1].id
+          // this.recordId = recordId
+          // this.getChatRecord(recordId)
         }
       }
       // 如果没有聊天记录,则增加开场聊天引导
@@ -482,7 +709,11 @@ export default {
       console.log(res, '聊天记录');
       for (let i = 0; i < res.data.length; i++) {
         const element = res.data[i];
-        element.open = false
+        if(this.info.id == element.id) {
+          element.open = true
+        } else {
+          element.open = false
+        }
       }
       this.allRecords = res.data
     },
@@ -492,6 +723,9 @@ export default {
         characterId: this.info.id,
         chatTitle: ""
       }
+      if (this.sceneId) {
+        params.sceneId = this.sceneId
+      }
       let res = await addChatApi(params)
       console.log(res, '新增对话记录');
       return res.data
@@ -503,7 +737,6 @@ export default {
       })
     },
     inputBoxClick() {
-      console.log(this.$refs.input, 'this.$refs.input');
       this.$refs.input.focus()
     },
     async getDetail(id) {
@@ -521,10 +754,23 @@ export default {
       //   })
       //   localStorage.setItem(`[userId:${123},aiId:${this.info.id}]`, JSON.stringify(this.returnMessage));
       // }
-      this.returnMessage.push({
-        role: 'assistant',
-        content: this.info.firstContent
-      })
+      if (this.sceneId) {
+        let sceneList = this.info.sceneList
+        for (let i = 0; i < sceneList.length; i++) {
+          const element = sceneList[i];
+          if (element.sceneId == this.sceneId) {
+            this.returnMessage.push({
+              role: 'assistant',
+              content: element.sceneWelcome
+            })
+          }
+        }
+      } else {
+        this.returnMessage.push({
+          role: 'assistant',
+          content: this.info.firstContent
+        })
+      }
     },
     getGuidance(id) {
       getGuidanceApi(id).then(res => {
@@ -541,11 +787,20 @@ export default {
       for (let i = 0; i < this.allRecords.length; i++) {
         const element = this.allRecords[i];
         if (element.id == this.info.id) {
-          element.chatCharacterList.push({
-            chatTitle: "常规聊天",
-            createTime: '',
-            id: this.recordId
-          })
+          if (this.sceneId) {
+            element.chatCharacterList.push({
+              chatTitle: "场景聊天",
+              createTime: '',
+              id: this.recordId,
+              sceneIcon: true
+            })
+          } else {
+            element.chatCharacterList.push({
+              chatTitle: "常规聊天",
+              createTime: '',
+              id: this.recordId
+            })
+          }
           this.recordsIndex = element.chatCharacterList.length - 1
         } 
       }
@@ -563,6 +818,17 @@ export default {
         this.getStreamChatWithWeb()
       }
     },
+    // 前往创建场景
+    toCreateScene() {
+      this.$router.push({
+        name: 'CreateScene',
+        query: {
+          id: this.info.id,
+          picture: this.info.picture,
+          characterName: this.info.characterName,
+        }
+      })
+    },
     async getStreamChatWithWeb_old() {
       this.messageLoading = true
       if (!this.content) {
@@ -626,6 +892,8 @@ export default {
       }, 50)
     },
     async getStreamChatWithWeb() {
+      this.textCache = ''
+      this.resError = false
       this.messageLoading = true
       if (!this.content) {
         return
@@ -639,16 +907,21 @@ export default {
         content: this.content
       })
       let HistoryMessage = this.returnMessage
+      
       // 历史记录取最新的20条传给后端
       if (HistoryMessage && HistoryMessage.length > 20) {
         HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
       }
       let params = {
-        historyMessage: HistoryMessage || [],
+        historyMessage: HistoryMessage,
         characterId: this.info.id,
         prompt: this.content,
         modelId: this.configForm.radio2,
-        recordId: this.recordId
+        recordId: this.recordId,
+      }
+      // 如果当前是场景对话则需要传sceneId
+      if (this.sceneId) {
+        params.sceneId = this.sceneId
       }
       // 新增一条ai信息
       this.returnMessage.push({
@@ -674,15 +947,24 @@ export default {
         const {done, value} = await reader.read()
         // console.log(done, 'done');
         if(done){
-          console.log(value, 'value');
+          console.log(value, '结束value');
           // if (typeof(value) == "undefined") {
           //   this.$message.error('错误')
           //   this.returnMessage.splice(this.returnMessage.length - 1, 1)
           // }
           // 每次对话完刷新聊天记录
           this.getChatCharacterRecords()
-          this.returnMessage = []
-          this.getChatRecord(this.recordId)
+          let params = {
+            characterId: this.info.id,
+            recordId: this.recordId
+          }
+          let historyRes = await getChatRecordApi(params)
+          this.historyRes = historyRes.data
+          // 如果开启自动播放,则查询并播放语音
+          if (this.setting.value1 && !this.resError) {
+            let index = this.historyRes.length * 2
+            this.playAudio(index)
+          }
           console.log('结束');
           break;
         }
@@ -712,8 +994,10 @@ export default {
             break;
           }
           if(JSON.parse(element).code == 500) {
+            console.log(JSON.parse(element), 'JSON.parse(element)');
             this.returnMessage.splice(this.returnMessage.length - 1, 1)
-            this.$message.error('系统错误请联系管理员')
+            this.$message.error(JSON.parse(element).content || '系统错误请联系管理员')
+            this.resError = true
             break;
           }
           let txt = JSON.parse(element).content
@@ -760,40 +1044,79 @@ export default {
       this.getStreamChatWithWeb()
     },
     // 播放聊天语音
-    playAudio(value, index) {
+    playAudio(index) {
       console.log(index, 'index');
       console.log(this.historyRes, 'this.historyRes');
-      let history = this.historyRes[(index - 1) / 2]
+      let history = this.historyRes[ index / 2 - 1]
       console.log(history, 'history');
       this.audioPlayIndex = index
       this.audioUrl = history.voiceFilePosition
       console.log(this.audioUrl, 'this.audioUrl');
+      console.log(this.$refs.audio, 'this.$refs.audio');
       this.$refs.audio.volume = 1
-      this.$refs.audio.play()
+      setTimeout(() => {
+        this.$refs.audio.play()
+      }, 1000)
     },
     audioEnd() {
       // console.log('播放结束');
       this.audioPlayIndex = null
+    },
+    // 场景业务相关↓
+    async sceneChange(item) { 
+      console.log(item, 'item');
+      this.$message({
+        message: `已进入场景${item.sceneName}`,
+        type: 'success'
+      });
+      // 当用户选中场景
+      this.sceneInfo = item
+      // 切换当前场景id
+      this.sceneId = item.sceneId
+      // 情况聊天记录
+      this.returnMessage = []
+      // 新建场景对话
+      this.newStart()
+      // 增加开场白
+      // this.returnMessage.push({
+      //   role: 'assistant',
+      //   content: item.sceneWelcome
+      // })
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
-
+.fullScreenButton {
+  position: absolute;
+  top: 50%;
+  left: 0;
+  transform: translateX(-50%) translateY(-50%);
+  z-index: 50;
+  background: #fff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 1.6rem;
+  height: 1.6rem;
+  cursor: pointer;
+}
 .chat {
-  min-height: 100vh;
+  height: 100vh;
 }
 .leftInfo {
   width: 375px;
   height: 100%;
   padding: 32px 24px;
+  
 
   >.history {
     width: 100%;
     height: 100%;
     display: flex;
     flex-direction: column;
+    overflow: hidden;
     >.historyBox {
       padding: 8px;
       border-radius: 15px;
@@ -819,6 +1142,7 @@ export default {
     }
   }
   >.chatInfo {
+    overflow: hidden;
     .chatInfo_photo {
       >img {
 
@@ -841,17 +1165,24 @@ export default {
     }
   }
 }
+
 .content {
-  background-size: 100% 100%;
+  z-index: 40;
+  position: absolute;
+  right: 0;
+  background-repeat: no-repeat;
+  background-attachment: fixed;
+  background-size: cover;
+  background-color: #fff;
   display: flex;
   height: 100%;
   justify-content: center;
   width: calc(100% - 375px);
   border-left: solid 1px var(--color1);
-  
+  transition: width 0.5s ease;
   >.chat-box {
     position: relative;
-    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: linear-gradient(to bottom, rgba(0, 0, 0, 0.4) 0%, rgba(255, 255, 255, 0) 20%, rgba(255, 255, 255, 0) 75%, rgba(0, 0, 0, 0.4) 100%);
     background-size: auto;
     // border: 1px solid #635677 !important;
     box-sizing: border-box;
@@ -871,6 +1202,9 @@ export default {
     }
   }
 }
+.contentFull {
+  width: 100%;
+}
 .historyActive {
   background: var(--color1);
 }
@@ -970,6 +1304,8 @@ export default {
   border-radius: 10px;
   padding: 24px;
   background: #fff;
+  max-width: 900px;
+  margin: 0 auto;
 }
 .planeColor {
   color: var(--bg-color1);

+ 2 - 2
src/views/chat/indexH5.vue

@@ -4,7 +4,7 @@
       <img class="absolute h-full" :src="baseApi + info.picture" alt="">
       <!-- onClick={() => navigate('/')} -->
       <div class="top">
-        <button class="tm_button absolute text-xs bg-none py-1 px-3 rounded flex" @click="goBack">
+        <button class="tm_button absolute text-xs bg-none py-1 px-3 rounded flex" @click.prevent="goBack">
           <i class="el-icon-arrow-left"></i>
         </button>
       </div>
@@ -74,7 +74,7 @@
                 v-model="content"
                 @keydown="Enterkey"
               />
-              <button @click="getStreamChatWithWeb" class="buttonBg1 text-white px-4 rounded-r-lg text-sm">
+              <button @click.prevent="getStreamChatWithWeb" class="buttonBg1 text-white px-4 rounded-r-lg text-sm">
                 发送
               </button>
               

+ 56 - 10
src/views/components/NavMenu.vue

@@ -16,25 +16,57 @@
           <i class="icon el-icon-discover"></i>
           <div class="text">发现</div>
         </div>
-        <div v-if="haveToken" class="menu" :class="$route.path == '/chat' && 'menuActive'" @click="routeTo('/chat')">
+        <div v-show="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 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 v-if="haveToken" class="menu" :class="$route.path == '/profile' && 'menuActive'" @click="routeTo('/profile')">
+        <el-popover
+          placement="right"
+          width="160"
+          v-model="popoverVisible">
+          <div class="flex flex-col">
+            <div class="submenu w-full text-gray-600 text-center py-2 rounded cursor-pointer"
+              @click="() => {
+                popoverVisible = false
+                routeTo('/createScene')
+              }"
+            >
+              创建场景
+            </div>
+            <div class="submenu w-full text-gray-600 text-center py-2 rounded cursor-pointer" 
+              @click="() => {
+                popoverVisible = false
+                routeTo('/create')
+              }"
+            >
+              创建角色
+            </div>
+          </div>
+          <div slot="reference" v-show="haveToken" class="menu" 
+            :class="($route.path == '/create' || $route.path == '/createScene') && 'menuActive'"
+          >
+            <i class="icon el-icon-plus"></i>
+            <div class="text">创建</div>
+          </div>
+        </el-popover>
+
+        
+        <div v-show="haveToken" class="menu" :class="$route.path == '/profile' && 'menuActive'" @click="routeTo('/profile')">
           <i class="icon el-icon-files"></i>
           <div class="text">个人中心</div>
         </div>
       </div>
     </div>
     <div class="flex flex-col justify-center items-center cursor-pointer">
-      <v-icon name="crown" class="my-2" scale="1.5"/>
-      <div class="photo my-2 cursor-pointer">
-        <img class="img" src="@/assets/images/default_avatar_user.png" alt="">
-      </div>
+      <el-tooltip class="item" effect="dark" content="会员" placement="right">
+        <v-icon name="crown" class="my-2" scale="1.5"/>
+      </el-tooltip>
+      <el-tooltip class="item" effect="dark" content="账户" placement="right">
+        <div class="photo my-2 cursor-pointer" @click="toUser">
+          <img class="img" src="@/assets/images/default_avatar_user.png" alt="">
+        </div>
+      </el-tooltip>
+      
     </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>
@@ -53,6 +85,7 @@ import 'vue-awesome/icons/crown'
 export default {
   data() {
     return {
+      popoverVisible: false,
       haveToken: false,
       getToken, 
     }
@@ -75,6 +108,14 @@ export default {
     }
   },
   methods: {
+    toUser() {
+      if (this.getToken()) {
+        this.$router.push('/user')
+      } else {
+        this.showLogin()
+      }
+      
+    },
     routeTo(url) {
       this.$router.push(url)
     },
@@ -87,6 +128,7 @@ export default {
 
 <style lang="scss" scoped>
 .nav-menu {
+  position: relative;
   padding-top: 20px;
   padding-bottom: 48px;
   font-size: 14px;
@@ -130,4 +172,8 @@ export default {
 .loginTip {
   box-shadow: 1px 1px 4px #bfbfbf;
 }
+.submenu:hover {
+  color: #fff;
+  background: var(--bg-color1);
+}
 </style>

+ 330 - 0
src/views/create/createScene.vue

@@ -0,0 +1,330 @@
+<template>
+  <div class=" w-full h-full app-pageContainer" style="overflow: hidden;">
+    <div class=" w-full py-3 px-10 border-b border-gray-200">
+      创建场景
+    </div>
+     <!-- 第一步场景基本信息 -->
+    <div v-show="active == 1" class="px-6 py-8 mx-auto" style="height: calc(100% - 49px - 80px); width: 1000px;">
+      <div>
+        <div class="py-4 flex flex-col">
+          <div class="w-20 h-20">
+            <div
+              v-if="!character.id"
+              @click="showPopup1 = true"
+              class="w-20 h-20 bg-gray-100 rounded-full cursor-pointer flex flex-col justify-center items-center text-sm hover:bg-gray-200">
+              <p>选择</p>
+              <p>角色</p>
+            </div>
+            <img v-else class="w-20 h-20 rounded-full cursor-pointer object-cover shadow" @click="showPopup1 = true" :src="baseApi + character.picture" alt="">
+          </div>
+          <div class="mt-1.5 text-2xl">{{character.id ? character.characterName : '请选择角色'}}</div>
+          <div class="mt-1 text-gray-400 text-sm">定义角色所属的上下文,为角色补充创作的故事或设定。</div>
+        </div>
+
+        <div class="py-4">
+          <div>场景名称</div>
+          <div class="mt-1 text-gray-400 text-sm">场景的标题</div>
+          <el-input class="mt-4" v-model="form.sceneName" placeholder="例如:第一次约会" maxlength="10" show-word-limit></el-input>
+        </div>
+
+        <div class="py-4">
+          <div>场景描述</div>
+          <div class="mt-1 text-gray-400 text-sm">
+            详细的场景描述,可以为角色补充创作的故事或设定,可以指定互动发生的位置和时间。
+          </div>
+          <el-input class="mt-4" v-model="form.sceneDescription" placeholder="例:{char} 成为 {user} 的女朋友已有一段時間了,今天你们决定开始同居。"
+            type="textarea" maxlength="400" :autosize="{ minRows: 4 }" show-word-limit></el-input>
+        </div>
+        <div class="py-4">
+          <div>欢迎语</div>
+          <div class="mt-1 text-gray-400 text-sm">
+            请填写欢迎语和指定的发言角色,這将会是进入场景时收到的第一句话,将会印象场景的剧情走向
+          </div>
+          <el-input class="mt-4" v-model="form.sceneWelcome" placeholder="例如:他的声音里充满了恼怒,问道: “你是我新來的保姆吗?”" type="textarea"
+            maxlength="400" :autosize="{ minRows: 4 }" show-word-limit></el-input>
+        </div>
+        <div class="py-4">
+          <div>模型</div>
+          <div class="flex items-start py-3">
+            <el-radio-group class="radio" v-model="form.modelId">
+              <el-radio-button v-for="(item, index) in modelList" :key="index" :label="item.id">
+                {{ item.model}}
+              </el-radio-button>
+            </el-radio-group>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 第二步背景 -->
+    <div v-show="active == 2" class="w-full relative" style="height: calc(100% - 49px - 80px);">
+      <img v-if="uploadList.length > 0" class=" w-full h-full object-cover" :src="baseApi + uploadList[bgActive].url" alt="">
+      <div 
+        class="absolute bg-white p-4 bottom-1/2 right-1/2 transform translate-x-1/2 translate-y-1/2 rounded-lg border border-gray-200" 
+        style="width: 700px; height: 582px;"
+      >
+      <el-tabs v-model="tabActive2">
+        <el-tab-pane label="上传背景" name="1">
+          <div class="flex flex-col">
+            <div>直接使用上传的图像</div>
+            <div class="mt-1 text-gray-400 text-sm">直接使用上传的图像</div>
+            <el-upload
+              class=" w-full text-center mt-4"
+              drag
+              :action="uploadUrl"
+              :headers="headers"
+              :before-upload="handleBeforeUpload"
+              :on-success="handleUploadSuccess"
+              :on-error="handleUploadError"
+              :show-file-list="false"
+              :limit="10"
+            >
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+              <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过5M</div>
+            </el-upload>
+            <div>背景</div>
+            <div class="mt-2 grid grid-cols-5 gap-y-2">
+              <div v-for="(item, index) in uploadList" :key="index" @click="bgActive = index">
+                <img class=" rounded object-cover cursor-pointer" :class="bgActive === index ? 'bgActive' : ''" style="width: 120px; height: 90px;" :src="baseApi + item.url" alt="">
+              </div>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+      </div>
+    </div>
+    <div class="bottom flex justify-end items-center pr-6">
+      <el-button v-if="active == 1" type="primary" :disabled="nextDisabled" @click="next()">下一步</el-button>
+      <el-button v-if="active == 2" @click="active--">上一步</el-button>
+
+      <el-dropdown @command="handleCommand" trigger="click">
+        <el-button class="mx-2 w-28 " v-show="active == 2">
+          {{ this.form.type == 0?'公开':'非公开' }}
+          <i class="el-icon-arrow-up el-icon--right"></i>
+        </el-button>
+        <el-dropdown-menu slot="dropdown">
+          <el-dropdown-item command="0">公开</el-dropdown-item>
+          <el-dropdown-item command="1">非公开</el-dropdown-item>
+        </el-dropdown-menu>
+      </el-dropdown>
+      <el-button v-if="active == 2" :disabled="uploadList.length == 0" type="primary" @click="submit">发布</el-button>
+    </div>
+    <!-- 选择角色对话框 -->
+    <el-dialog
+      class="dialog"
+      title="选择角色"
+      :visible.sync="showPopup1"
+      width="600"
+    >
+      <div>
+        <span>选择要在哪个角色上新增场景?</span>
+        <el-tabs v-model="tabActive" @tab-click="handleClickTab">
+          <el-tab-pane label="我的角色" name="1">
+            <div class=" grid grid-cols-5 gap-8">
+              <!-- <div v-for="(item, index) in 7" :key="index">
+                <img class="rounded-full object-cover cursor-pointer" src="@/assets/images/1.png" alt="">
+              </div> -->
+            </div>
+          </el-tab-pane>
+          <el-tab-pane label="热门角色" name="2">
+            <div class=" grid grid-cols-5 gap-8 justify-items-center">
+              <div v-for="(item, index) in characterList" :key="index" @click="selectCharacter(item)">
+                <img class="rounded-full object-cover cursor-pointer w-20 h-20" :src="baseApi + item.picture" alt="">
+                <div class="characterName text-center w-20">{{ item.characterName }}</div>
+              </div>
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+      
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getToken } from "@/utils/auth";
+import {
+  getModelListApi,
+} from "@/api/chat.js"
+import { characterListApi } from "@/api/home.js"
+import { addSceneApi } from "@/api/create.js"
+export default {
+  data() {
+    return {
+      active: 1,
+      showPopup1: false,
+      tabActive: '1',
+      tabActive2: '1',
+      form: {
+        // 角色id
+        characterId: '',
+        // 场景名称
+        sceneName: '',
+        // 场景描述
+        sceneDescription: '',
+        // 欢迎语
+        sceneWelcome: '',
+        // 模型
+        modelId: '',
+        // 背景图
+        background: '',
+        //公开非公开
+        type: 0
+      },
+      // 模型列表
+      modelList: [],
+      bagImg: '',
+      // 热门角色列表
+      characterList: [],
+      // 选中的角色对象
+      character: {},
+      // 上传图片相关↓
+      uploadUrl: process.env.VUE_APP_BASE_API + "/system/app/upload", // 上传的图片服务器地址
+      headers: {
+        UserToken: getToken()
+      },
+      uploadList: [],
+      fileSize: 5,
+      bgActive: 0
+    }
+  },
+  mounted() {
+    this.getModelList()
+    this.getCharacterList()
+    if (this.$route.query.id) {
+      this.character = {
+        id: this.$route.query.id,
+        picture: this.$route.query.picture,
+        characterName: this.$route.query.characterName,
+      }
+      this.form.characterId = this.$route.query.id
+    }
+  },
+  computed: {
+    nextDisabled() {
+      return this.form.sceneName == '' || this.form.sceneDescription == '' || this.form.sceneWelcome == '' || this.form.modelId == ''
+    }
+  },
+  methods: {
+    getCharacterList(query) {
+      let params = {
+        pageSize: 10,
+        pageNum: 1
+      }
+      if (query) {
+        params = {...params, ...query}
+      }
+      characterListApi(params).then(res => {
+        // console.log(res, '角色列表');
+        this.characterList = res.rows
+      })
+    },
+    getModelList() {
+      getModelListApi().then(res => {
+        console.log(res, '模型列表');
+        this.modelList = res.data
+      })
+    },
+    // 选择角色
+    selectCharacter(value) {
+      console.log(value, 'value');
+      this.character = value
+      this.form.characterId = value.id
+      this.showPopup1 = false
+    },
+    handleCommand(value) {
+      this.form.type = value
+    },
+    // 下一步
+    next() {
+      this.active++
+    },
+    submit() {
+      this.form.background = this.uploadList[this.bgActive].url
+      addSceneApi(this.form).then(res => {
+        console.log(res, 'res>>>>>');
+        this.$message({
+          type: 'success',
+          message: '发布成功!'
+        });
+        this.$router.push('/profile')
+      })
+    },
+    handleClickTab(tab, event) {
+
+    },
+    // 上传背景相关业务
+    // 上传前校检格式和大小
+    handleBeforeUpload(file) {
+      // 校检文件大小
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      return true;
+    },
+    // 上传成功回调
+    handleUploadSuccess(res, file) {
+      if (res.code === 200) {
+        this.uploadList.push({ name: res.originalFilename, url: res.fileName });
+        this.$message({
+          type: 'success',
+          message: '上传成功!'
+        });
+      } else {
+        this.$message({
+          type: 'error',
+          message: res.msg
+        });
+      }
+    },
+    // 上传结束处理
+    uploadedSuccessfully() {
+      console.log(this.uploadList, 'this.uploadList');
+      // this.$emit("input", this.listToString(this.fileList));
+      // this.$modal.closeLoading();
+    },
+    // 上传失败
+    handleUploadError() {
+      this.$modal.msgError("上传图片失败,请重试");
+    },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.bottom {
+  height: 80px;
+}
+.characterName {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.bgActive {
+  border: solid 2px var(--bg-color1);
+}
+</style>
+<style scoped>
+.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>

+ 105 - 13
src/views/create/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="create" style="min-height: 100vh;">
+  <div class="create app-pageContainer" style="min-height: 100vh;">
     <!-- <Header /> -->
     
     <div class="mx-auto" style="width: 60%;">
@@ -60,6 +60,23 @@
 
             <div class="text-xl font-medium my-6">机器人制作</div>
             <div class="p-5 rounded-lg">
+              <el-form-item label="模型" prop="modelId" label-width="80px" style="margin-bottom: 20px;">
+                <el-radio-group class="radio" v-model="form.modelId">
+                  <el-radio-button v-for="(item, index) in modelList" :key="index" :label="item.id">
+                    {{ item.model}}
+                  </el-radio-button>
+                </el-radio-group>
+                </el-form-item>
+                <!-- <div class="py-4">
+                  <div>模型</div>
+                  <div class="flex items-start py-3">
+                    <el-radio-group class="radio" v-model="form.modelId">
+                      <el-radio-button v-for="(item, index) in modelList" :key="index" :label="item.id">
+                        {{ item.model}}
+                      </el-radio-button>
+                    </el-radio-group>
+                  </div>
+                </div> -->
               <el-form-item label="开场白" prop="firstContent" label-width="80px" style="margin-bottom: 20px;">
                 <el-input 
                   v-model="form.firstContent" 
@@ -68,7 +85,7 @@
                   placeholder="帮您的机器人设计一段开场白吧"
                 ></el-input>
               </el-form-item>
-              <el-form-item label="角色描述" prop="characterIntroduction" label-width="80px">
+              <el-form-item label="角色描述" prop="characterIntroduction" label-width="80px" style="margin-bottom: 20px;">
                 <el-input 
                   v-model="form.characterIntroduction" 
                   type="textarea"
@@ -76,17 +93,32 @@
                   placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
                 ></el-input>
               </el-form-item>
-              <!-- <div class="flex flex-col gap-4">
-                <div class="text-sm">描述</div>
-                <textarea
-                  class="bg-gray-600 p-2 rounded-lg text-sm w-full h-16 focus:outline-none focus:ring focus:border-blue-300"
-                  placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
-                ></textarea>
-              </div> -->
+              <el-collapse class="collapse">
+                <el-collapse-item title="更多设置" name="1">
+                  <el-form-item label="场景" prop="scene" label-width="80px" style="margin-bottom: 20px;">
+                    <el-input 
+                      v-model="form.scene" 
+                      type="textarea"
+                      :autosize="{ minRows: 4, maxRows: 4}"
+                      placeholder="输入您的角色所处的场景,例如:{char}和{user}现在已经交往一个月了。"
+                    ></el-input>
+                  </el-form-item>
+
+                  <el-form-item label="对话范例" prop="dialogue" label-width="80px">
+                    <el-input 
+                      v-model="form.dialogue" 
+                      type="textarea"
+                      :autosize="{ minRows: 4, maxRows: 4}"
+                      :placeholder="'例如\n<START>\n{user}:嗨,我听说你喜欢在酒吧消磨时间。\n{char}:*兴奋*天呐,是的!'"
+                    ></el-input>
+                  </el-form-item>
+                </el-collapse-item>
+              </el-collapse>
             </div>
           </el-form>
+
           <div class="flex justify-center">
-            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click="submitForm">
+            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click.prevent="submitForm">
               提交
             </button>
           </div>
@@ -98,19 +130,24 @@
 
 <script>
 import Header from "@/views/homeComponents/Header.vue"
-import { addCharacterApi } from "@/api/create.js"
+import { addCharacterApi, personalityListApi } from "@/api/create.js"
 import { labelListApi } from "@/api/home.js"
+import {
+  getModelListApi,
+} from "@/api/chat.js"
 export default {
   components: {
     Header,
   },
   data() {
     return {
+      modelList: [],
       labelData: [],
       form: {
+        modelId: null,
         characterName: "",// 人物名称
         characterIntroduction: "", //人物角色描述
-        characterPersonalityTags: "", //人物性格标签
+        characterPersonalityTags: [], //人物性格标签
         firstContent: "", //首次聊天内容
         labelId: "", //标签id
         picture: "", //人物图片
@@ -143,14 +180,35 @@ export default {
         type: [
           { required: true, message: "请选择类型", trigger: "change" },
         ],
+        modelId: [
+          { required: true, message: "请选择模型", trigger: "change" },
+        ],
       }
     }
   },
   mounted() {
+    this.getModelList()
     this.getLabelList()
+    this.getPersonalityList()
     // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');
   },
   methods: {
+    getPersonalityList() {
+      let params = {
+        pageSize: 9999,
+        pageNum: 1
+      }
+      personalityListApi(params).then(res => {
+        console.log(res, '人物性格标签');
+      })
+    },
+    getModelList() {
+      getModelListApi().then(res => {
+        console.log(res, '模型列表');
+        this.modelList = res.data
+        this.form.modelId = this.modelList[0].id
+      })
+    },
     async addCharacter() {
       let data = {
         name: this.form.name,
@@ -182,6 +240,7 @@ export default {
               type: 'success'
             });
             this.$refs.form.resetFields()
+            this.$router.push('/profile')
           })
         }
       })
@@ -238,4 +297,37 @@ export default {
 .imgUp >>> .el-upload-list__item {
   /* border-radius: 50%; */
 }
-</style>
+
+.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);
+}
+.collapse {
+  border: solid 1px #DCDFE6;
+  background: #fff;
+  border-radius: 10px;
+  box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.12);
+  overflow: hidden;
+}
+.collapse >>> .el-collapse-item__header {
+  padding: 0 10px;
+}
+.collapse >>> .el-collapse-item__content {
+  padding: 20px 10px;
+}
+</style>
+

+ 1 - 1
src/views/create/indexH5.vue

@@ -85,7 +85,7 @@
             </div>
           </el-form>
           <div class="flex justify-center">
-            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click="submitForm">
+            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click.prevent="submitForm">
               提交
             </button>
           </div>

+ 1 - 1
src/views/detail/index.vue

@@ -49,7 +49,7 @@
             <button
               style="width: 150px;"
               class="bg-pink-600 text-xs py-1 px-4 rounded w-24 h-10"
-              @click="toChat"
+              @click.prevent="toChat"
             >
               隐私聊天
             </button>

+ 1 - 1
src/views/detail/indexH5.vue

@@ -85,7 +85,7 @@
       <button
         class="bg-pink-600 text-xs py-1 px-4 w-10/12 h-10 text-white font-semibold"
         style="border-radius: 2.5rem;"
-        @click="toChat"
+        @click.prevent="toChat"
       >
         隐私聊天
       </button>

+ 1 - 1
src/views/home.vue

@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div class="app-pageContainer">
     <HomePC v-if="!isMobile" />
     <HomeH5 v-else />
   </div>

+ 3 - 3
src/views/homeComponents/Header.vue

@@ -30,7 +30,7 @@
           <button
             class="text-white text-sm mr-3 cursor-pointer px-3 py-2 rounded-md"
             style="background-color: var(--bg-color1);"
-            @click="goCreate"
+            @click.prevent="goCreate"
           >
             创建机器人
           </button>
@@ -49,14 +49,14 @@
           <button
             class="text-white text-sm mr-3 cursor-pointer px-3 py-2 rounded-md"
             style="background-color: var(--bg-color1);"
-            @click="showLogin"
+            @click.prevent="showLogin"
           >
             登录
           </button>
           <button
             class="text-white text-sm mr-3 cursor-pointer px-3 py-2 rounded-md"
             style="background-color: var(--bg-color1);"
-            @click="showRegister"
+            @click.prevent="showRegister"
           >
             注册
           </button>

+ 1 - 1
src/views/homeComponents/HeaderH5.vue

@@ -33,7 +33,7 @@
       <button
         class="text-white ml-2 cursor-pointer px-2 rounded-md"
         style="background-color: var(--bg-color1); font-size: 11px;"
-        @click="goCreate"
+        @click.prevent="goCreate"
       >
         <p>创建</p>
         <p>机器人</p>

+ 18 - 8
src/views/homeComponents/HomePC.vue

@@ -36,7 +36,7 @@
           />
         </div>
       </div>
-      <div class="grid grid-cols-5 gap-4 mt-4">
+      <div class="list mt-4">
         <div
           v-for="(item, index) in characterList"
           :key="index"
@@ -60,15 +60,19 @@
             </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">
+            <div></div>
+            <div class="flex items-center box1 text-red-500">
+              <v-icon name="fire" scale="1"/>
+              <span class="ml-1">{{ item.hotCount||0 }}</span>
+            </div>
+            <!-- <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> -->
+            </div> -->
+            <!-- <div class="flex items-center box1">
               <v-icon name="star" scale="1"/>
               <span class="ml-1">{{ item.collections }}</span>
-            </div>
+            </div> -->
             <!-- <div class="flex items-center">
               <v-icon name="share" scale="1.5"/>
               <span>{{ item.likeNum }}</span>
@@ -87,6 +91,7 @@ import { labelListApi, characterListApi } from "@/api/home.js"
 import 'vue-awesome/icons/heart'
 // import 'vue-awesome/icons/comment'
 import 'vue-awesome/icons/star'
+import 'vue-awesome/icons/fire'
 
 export default {
   name: "HomePC",
@@ -289,9 +294,8 @@ export default {
 .box2 {
   background: #ffffff0f; 
   border: 1px solid #ffffff2e;
-  min-width: 200px;
   height: 35vw;
-  min-height: 300px;
+  min-height: 480px;
   max-height: 500px;
 }
 .box2:hover {
@@ -360,4 +364,10 @@ export default {
 .historysBox >>> .el-carousel__arrow {
   background: var(--bg-color1);
 }
+.list {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
+  grid-auto-rows: minmax(480px, auto);
+  grid-gap: 20px;
+}
 </style>

+ 7 - 4
src/views/homeComponents/login.vue

@@ -24,10 +24,9 @@
       </el-form-item> -->
       <el-form-item label="">
         <button
-          
           class="formButton text-white text-lg mr-3 cursor-pointer px-3 py-2 rounded-md w-full"
           style="background-color: var(--bg-color1);"
-          @click="clickLogin"
+          @click.prevent="clickLogin"
         >
           登录
         </button>
@@ -54,7 +53,7 @@ export default {
     return {
       codeTime: -1,
       codeInterval: null,
-      checked: false,
+      checked: true,
       formLogin: {
         account: null,
         password: null,
@@ -66,7 +65,7 @@ export default {
         ],
         code: [
           { required: true, message: '请输入验证码', trigger: 'blur' },
-          { pattern: /^[0-9]{6}$/, message: '请输入正确的验证码', trigger: 'blur' },
+          // { pattern: /^[0-9]{6}$/, message: '请输入正确的验证码', trigger: 'blur' },
         ],
         password: [
           { required: true, message: '请输入用户密码', trigger: 'blur' },
@@ -141,11 +140,15 @@ export default {
             console.log(res, '手机登录成功');
             setToken(res.data.userToken)
             this.$store.commit('SET_TOKEN', res.data.userToken)
+            this.$store.commit('SET_USERID', res.data.id)
+            console.log(this.$store.state.user.userId, 'userId>>>>');
             this.$message({
               message: '登录成功',
               type: 'success'
             });
             this.$store.commit('app/TOGGLE_POPUP', false)
+            this.$router.push({ path: '/' })
+            // this.$store.dispatch("GetInfo")
           })
           // this.$store.dispatch('Login', this.formLogin).then(() => {
           //   this.$message({

+ 118 - 23
src/views/profile/index.vue

@@ -1,7 +1,7 @@
 <!-- 个人中心 -->
 <template>
   <div class=" h-full w-full">
-    <div class="h-72 bg-blue-500 relative text-white">
+    <div class="h-72 relative text-white bg">
       <div class="flex absolute bottom-0 w-full px-28 justify-between items-end">
         <div class=" h-36 ">
           <div class="flex justify-center">
@@ -39,13 +39,15 @@
         <div class="flex justify-center">
           <div 
             class="labelButton flex justify-center items-center rounded-full mr-4 w-28 h-10 cursor-pointer"
-            :class="active == 1 && 'buttonBg1'"
+            :class="active == 0 && 'buttonBg1'"
+            @click="tabChange(0)"
           >
             公开内容
           </div>
           <div 
             class="labelButton flex justify-center items-center rounded-full w-28 h-10 cursor-pointer"
-            :class="active == 2 && 'buttonBg1'"
+            :class="active == 1 && 'buttonBg1'"
+            @click="tabChange(1)"
           >
             <i class="el-icon-lock"></i>
             非公开
@@ -62,18 +64,23 @@
           </div>
         </div>
       </div>
-      <div class="grid grid-cols-5 gap-4 mt-4">
+      <div class="list 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="w-full overflow-hidden h-3/5">
+            <img class="w-full img h-full" :src="baseApi + item.picture" />
           </div>
           <div class="p-2">
-            <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+            <h3 class="text-lg font-bold">
+              <i v-if="item.scene == 1" class="el-icon-video-camera"></i>
+              {{ item.name }}
+            </h3>
             <p class="prologue text-sm">
-              {{ item.prologue }}
+              {{ item.description }}
             </p>
 
             <div class="labels flex my-1 flex-wrap">
@@ -84,19 +91,11 @@
             </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 class="flex items-center box1 text-red-500">
+              <v-icon name="fire" scale="1"/>
+              <span class="ml-1">{{ item.hotCount||0 }}</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>
@@ -105,23 +104,88 @@
 </template>
 
 <script>
+import { queryCharacterAndSceneApi } from "@/api/profile.js"
+import { labelListApi, characterListApi } from "@/api/home.js"
+import 'vue-awesome/icons/fire'
 export default {
   data() {
     return {
-      active: 1
+      active: 0,
+      characterList: []
     }
   },
   mounted() {
-    
+    this.getCharacterList()
   },
   methods: {
     
+    toDetail(item) {
+      let query = {}
+      if (item.scene == 0) {
+        // 点击是角色
+        query.characterId = item.id
+      } else if (item.scene == 1) {
+        // 点击是场景
+        query.characterId = item.characterId
+        query.sceneId = item.id
+      }
+      this.$router.push({
+        path: '/chat',
+        query: query
+      })
+    },
+    tabChange(index) {
+      this.active = index
+      this.getCharacterList()
+    },
+    getCharacterList(query) {
+      let params = {
+        pageSize: 20,
+        pageNum: 1,
+        type: this.active
+      }
+      if (query) {
+        params = {
+          ...params,
+          ...query
+        }
+      }
+      queryCharacterAndSceneApi(params).then(res => {
+        console.log(res, '角色列表');
+        // let characterList = res.data.characterList
+        // characterList.map((item) => { item.mType = 1 })
+        // let sceneList = res.data.sceneList
+        // sceneList.map((item) => { item.mType = 2 })
+        // let arr = [
+        //   ...res.data.characterList,
+        //   ...res.data.sceneList,
+        // ]
+        // arr.sort(this.sortByTime('createTime', -1))
+        this.characterList = res.rows
+      })
+    },
+    sortByTime(attr, rev){
+      //attr:根据该属性排序;rev:升序1或降序-1,不填则默认为1
+      if( rev==undefined ){ rev=1 }else{ (rev)?1:-1; }
+        return function (a,b){
+          a = new Date(a[attr]).getTime();
+          b = new Date(b[attr]).getTime();
+          if(a<b){ return rev*-1}
+          if(a>b){ return rev* 1 }
+          return 0;
+      }
+    }
   }
 }
 </script>
 
 <style lang="scss" scoped>
-
+.list {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+  grid-auto-rows: minmax(100px, auto);
+  grid-gap: 20px;
+}
 .button {
   // background-color: #fff;
   color: #fff;
@@ -136,4 +200,35 @@ export default {
   background: var(--bg-color1);
   color: #fff;
 }
+.box2 {
+  background: #ffffff0f; 
+  border: 1px solid #ffffff2e;
+  min-width: 200px;
+  height: 35vw;
+  min-height: 260px;
+  max-height: 400px;
+}
+.box2:hover {
+  border: solid 1px var(--bg-color1);
+}
+.img {
+  // height: 230px;
+  object-fit: cover;
+  object-position: top;
+  transition: transform .2s
+}
+.img:hover {
+  transform: scale(1.1);
+}
+.bg {
+  background: url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png) no-repeat;
+  background-size: 100% 100%;
+}
+.prologue {
+  overflow:hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 4;
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+}
 </style>

+ 100 - 0
src/views/user/index.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="w-full h-full flex">
+    <div class="p-5 flex flex-col h-full border-r border-gray-200" style="width: 300px;">
+      <div class=" text-xl py-3">
+        账户
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '1' ? 'bg-gray-100' : ''"
+        @click="menuClick('1')"
+      >
+        <i class="el-icon-user text-xl mr-2"></i>
+        用户信息
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '2' ? 'bg-gray-100' : ''"
+        @click="menuClick('2')"
+      >
+        <i class="el-icon-setting text-xl mr-2"></i>
+        用户偏好设定
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '3' ? 'bg-gray-100' : ''"
+        @click="menuClick('3')"
+      >
+        <i class="el-icon-medal text-xl mr-2"></i>
+        会员
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '4' ? 'bg-gray-100' : ''"
+        @click="menuClick('4')"
+      >
+        <i class="el-icon-present text-xl mr-2"></i>
+        邀请有礼
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '5' ? 'bg-gray-100' : ''"
+        @click="menuClick('5')"
+      >
+        <i class="el-icon-message text-xl mr-2"></i>
+        意见反馈
+      </div>
+      <div 
+        class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === '6' ? 'bg-gray-100' : ''"
+        @click="menuClick('6')"
+      >
+        <i class="fa-solid fa-arrow-right-from-bracket text-xl mr-2"></i>
+        退出登录
+      </div>
+      <div class=" text-gray-500 mt-2 text-sm">
+        © 2024 Rochat
+        <a href="https://upro.ai/terms" target="_blank" class="underline mx-1">服務條款</a>
+        &amp;
+        <a href="https://upro.ai/privacy" target="_blank" class="underline mx-1">隱私政策</a>
+        v1.8.1
+      </div>
+    </div>
+    <div class=" flex-1 h-full bg-gray-50"></div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  data() {
+    return {
+      active: '1',
+      userInfo: {
+        name: '张三',
+        avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
+      }
+    }
+  },
+  methods: {
+    menuClick(i) {
+      this.active = i
+      switch (i) {
+        case '1':
+          this.$router.push('/')
+          break
+        case '6':
+          this.$store.dispatch('LogOut').then(() => {
+            this.$router.push('/')
+          })
+          
+          break
+      }
+    }
+  }
+}
+</script>
+
+<style>
+
+</style>

+ 1 - 1
vue.config.js

@@ -37,7 +37,7 @@ module.exports = {
     proxy: {
       [process.env.VUE_APP_BASE_API]: {
         target: `http://aitest.api.rongcyl.cn`,
-        // target: `http://192.168.0.104:8086`,
+        // target: `http://192.168.0.106:8086`,
         changeOrigin: true,
         pathRewrite: {
           ["^" + process.env.VUE_APP_BASE_API]: "",