chenrong 10 månader sedan
förälder
incheckning
91b130651e

+ 2 - 2
package.json

@@ -2,7 +2,7 @@
   "name": "rcBase",
   "version": "3.8.3",
   "description": "元宇宙",
-  "author": "榕创",
+  "author": "xx公司",
   "license": "MIT",
   "scripts": {
     "dev": "vue-cli-service serve",
@@ -95,4 +95,4 @@
     "> 1%",
     "last 2 versions"
   ]
-}
+}

+ 3 - 6
src/api/chat.js

@@ -8,14 +8,14 @@ import { getToken } from "@/utils/auth";
 // 获取初始聊天引导
 export function getGuidanceApi(id) {
   return request({
-    url: `/system/app/guidance/${id}`,
+    url: `/appUser/system/app/guidance/${id}`,
     method: 'get',
   })
 }
 // 获取模型列表
 export function getModelListApi(data) {
   return request({
-    url: `/system/app/modelList`,
+    url: `/appUser/system/app/modelList`,
     method: 'get',
     params: data
   })
@@ -89,7 +89,7 @@ export function streamChatWithWebApi(data) {
   if (getToken()) {
     headers['UserToken'] = getToken()
   }
-  return fetch(`${process.env.VUE_APP_BASE_API}/system/chat/localAiStream`, {
+  return fetch(`${process.env.VUE_APP_BASE_API}/appUser/system/chat/localAiStream`, {
     headers: {
       ...headers,
       returnData: true,
@@ -117,6 +117,3 @@ export function deleteRecordApi(data) {
     data
   })
 }
-// /system/chat/qwenChatHistory
-// /system/test/auth/localAi
-// system/chat/localAiStream

+ 1 - 1
src/api/create.js

@@ -65,7 +65,7 @@ export function deleteSceneApi(sceneId) {
 }
 export function personalityListApi() {
   return request({
-    url: `/system/app/characterPersonalList`,
+    url: `/appUser/system/app/characterPersonalList`,
     method: 'get',
   })
 }

+ 1 - 1
src/api/detail.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 获取标签列表
 export function detailApi(id) {
   return request({
-    url: `/system/app/${id}`,
+    url: `/appUser/system/app/${id}`,
     method: 'get',
   })
 }

+ 2 - 2
src/api/home.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 获取标签列表
 export function labelListApi(data) {
   return request({
-    url: '/system/app/labelList',
+    url: '/appUser/system/app/labelList',
     headers: {
       isToken: false
     },
@@ -14,7 +14,7 @@ export function labelListApi(data) {
 // 获取角色列表
 export function characterListApi(data) {
   return request({
-    url: '/system/app/characterList',
+    url: '/appUser/system/app/characterList',
     headers: {
       isToken: false
     },

+ 6 - 6
src/api/login.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 登录方法
 export function login(data) {
   return request({
-    url: '/system/app/loginByAccount',
+    url: '/appUser/system/app/loginByAccount',
     headers: {
       isToken: false
     },
@@ -15,7 +15,7 @@ export function login(data) {
 // 注册方法
 export function register(data) {
   return request({
-    url: '/system/app/account',
+    url: '/appUser/system/app/account',
     headers: {
       isToken: false
     },
@@ -36,7 +36,7 @@ export function getInfo(params) {
 // 退出方法
 export function logout() {
   return request({
-    url: '/logout',
+    url: '/appUser/logout',
     method: 'post'
   })
 }
@@ -44,7 +44,7 @@ export function logout() {
 // 获取验证码
 export function getCodeImg() {
   return request({
-    url: '/captchaImage',
+    url: '/appUser/captchaImage',
     headers: {
       isToken: false
     },
@@ -55,7 +55,7 @@ export function getCodeImg() {
 // 获取手机验证码
 export function getSendVerificationCode(data) {
   return request({
-    url: '/system/app/sendVerificationCode',
+    url: '/appUser/system/app/sendVerificationCode',
     headers: {
       isToken: false
     },
@@ -67,7 +67,7 @@ export function getSendVerificationCode(data) {
 
 export function phoneLogin(data) {
   return request({
-    url: '/system/app/register',
+    url: '/appUser/system/app/register',
     headers: {
       isToken: false
     },

+ 1 - 1
src/api/menu.js

@@ -3,7 +3,7 @@ import request from '@/utils/request'
 // 获取路由
 export const getRouters = () => {
   return request({
-    url: '/getRouters',
+    url: '/appUser/getRouters',
     method: 'get'
   })
 }

+ 1 - 1
src/api/user.js

@@ -35,7 +35,7 @@ export function queryUserBalanceApi(params) {
 // 查询邀请用户列表
 export function getInviteUserListApi(params) {
   return request({
-    url: `/system/app/getInviteUserList`,
+    url: `/appUser/system/app/getInviteUserList`,
     method: 'get',
     params
   })

+ 29 - 9
src/assets/styles/index.scss

@@ -4,15 +4,24 @@
 @import './element-ui.scss';
 @import './sidebar.scss';
 @import './btn.scss';
+
 * {
-  -webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* iOS Safari */
-  -webkit-user-select: none; /* Safari */
-  -khtml-user-select: none; /* Konqueror HTML */
-  -moz-user-select: none; /* Firefox */
-  -ms-user-select: none; /* Internet Explorer/Edge */
-  user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
-  outline: none; /* Remove outline in all browsers */
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+  /* iOS Safari */
+  -webkit-user-select: none;
+  /* Safari */
+  -khtml-user-select: none;
+  /* Konqueror HTML */
+  -moz-user-select: none;
+  /* Firefox */
+  -ms-user-select: none;
+  /* Internet Explorer/Edge */
+  user-select: none;
+  /* Non-prefixed version, currently supported by Chrome and Opera */
+  outline: none;
+  /* Remove outline in all browsers */
 }
+
 body {
   height: 100%;
   -moz-osx-font-smoothing: grayscale;
@@ -130,12 +139,14 @@ aside {
 //main-container全局样式
 .app-container {
   padding: 20px;
-  
+
 }
+
 .app-pageContainer {
   height: 100vh;
   overflow-y: auto;
 }
+
 .components-container {
   margin: 30px 50px;
   position: relative;
@@ -201,12 +212,19 @@ aside {
 .multiselect--active {
   z-index: 1000 !important;
 }
+
 .bg-purple-600 {
   background-color: rgb(147 51 234) !important;
 }
-button, input, optgroup, select, textarea {
+
+button,
+input,
+optgroup,
+select,
+textarea {
   font-size: 16px;
 }
+
 .fa-icon {
   fill: currentColor;
 }
@@ -223,11 +241,13 @@ button, input, optgroup, select, textarea {
 .fontH5 {
   font-size: 12px;
 }
+
 :root {
   --bg-color1: #7262f6;
   --bg-color2: hsla(0, 0%, 83%, 0.24);
   --bg-color3: rgba(109, 94, 227, 0.9);
   --bg-color4: #9387ff;
+  --bg-color5: #3f3f3f;
   --color1: #e2e2e2;
   --color2: #8f8f8f;
 }

+ 248 - 148
src/views/chat/ChatH5.vue

@@ -5,7 +5,7 @@
       <div class="top bg-white px-2 flex justify-between">
         <el-button class="tm_button" type="info" icon="el-icon-arrow-left" circle @click="goBack"></el-button>
         <div class="flex">
-          <el-button class="tm_button" type="info" circle @click="goBack">
+          <el-button class="tm_button" type="info" circle>
             <i class="fa-solid fa-volume-high text-sm"></i>
             <!-- <i class="fa-solid fa-volume-xmark text-sm"></i> -->
           </el-button>
@@ -15,11 +15,10 @@
               <el-dropdown-item icon="el-icon-warning-outline">查看详情</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
-          
         </div>
       </div>
       <audio ref="audio" muted v-show="false" :src="audioUrl" autoplay="" @ended="audioEnd" controls></audio>
-      <div class="chatContent"> 
+      <div class="chatContent">
         <!-- <div class="leftImg">
           <img :src="baseApi + info.picture" alt="">
           <div class="aiInfo">
@@ -37,19 +36,16 @@
             </div>
           </div>
         </div> -->
-        <div class="chat-box relative"> 
+        <div class="chat-box relative">
           <div class="messages" ref="messages">
-            <template v-for="(item, index) in returnMessage">
+            <template v-for="(item, index) in  returnMessage ">
               <div v-if="item.role == 'assistant'" class="text-white mb-4 flex" :key="index">
                 <!-- ai返回的信息 -->
                 <div class="pt-2 photo">
-                  <img
-                    :src="baseApi + info.picture"
-                    class="rounded-full w-12 h-12 object-cover"
-                  />
+                  <img :src="baseApi + info.picture" class="rounded-full w-12 h-12 object-cover" />
                 </div>
-                <div class="message fex-1 ml-2 mt-3 p-2 rounded-r-md rounded-bl-md text-base" >
-                  <div v-show="!item.content" class="loadingMessage" >
+                <div class="message fex-1 ml-2 mt-3 p-2 rounded-r-md rounded-bl-md text-base">
+                  <div v-show="!item.content" class="loadingMessage">
                     <div v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
                   </div>
                   <p v-show="item.content">{{ item.content }} </p>
@@ -58,10 +54,7 @@
               <!-- 用户发送的信息 -->
               <div v-if="item.role == 'user'" class="text-white mb-4 flex me" :key="index">
                 <div class="pt-2 photo">
-                  <img
-                    src="@/assets/images/default_avatar_user.png"
-                    class="rounded-full w-12 h-12 object-cover"
-                  />
+                  <img src="@/assets/images/default_avatar_user.png" class="rounded-full w-12 h-12 object-cover" />
                 </div>
                 <div class="message2 fex-1 mr-2 mt-3 p-2 rounded-l-md rounded-br-md text-base">
                   <p>{{ item.content }}</p>
@@ -71,25 +64,44 @@
           </div>
         </div>
       </div>
-      <div class="absolute bottom-0 w-full px-2 pt-2 pb-4 border-t border-gray-100">
+      <div class="absolute bottom-0 bg-white w-full px-2 pt-2 pb-4 border-t border-gray-100">
         <!-- <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="bgColor1 mButton" @click="newStart" style="margin-right: 5px;" type="primary" round icon="el-icon-plus"></el-button>
-          <input
-            type="text"
-            placeholder="输入消息..."
-            class="flex-1 py-2 px-4 rounded-l-lg text-sm focus:outline-none"
-            style="background: #ffffff0f; border: 1px solid #5b5b5e;"
-            v-model="content"
-            @keydown="Enterkey"
-          />
+          <el-button class="bgColor1 mButton" @click="showBottomPopup = true" style="margin-right: 5px;" type="primary"
+            round icon="el-icon-plus"></el-button>
+          <input type="text" placeholder="输入消息..." class="flex-1 py-2 px-4 rounded-l-lg text-sm focus:outline-none"
+            style="background: #ffffff0f; border: 1px solid #5b5b5e;" v-model="content" @keydown="Enterkey" />
           <button @click.prevent="getStreamChatWithWeb" class="bgColor1 text-white px-4 rounded-r-lg text-sm">
             发送
           </button>
         </div>
       </div>
+      <el-dialog :visible.sync="showBottomPopup" :show-close="false" width="100%" class="phoneBottomPopup">
+        <transition name="el-zoom-in-bottom">
+          <div class="content" v-show="showBottomPopup">
+            <div class="configForm wf-full h-full flex flex-col">
+              <div class="row">
+                <p class="text-base mt-3">选择模型</p>
+                <p class="text-sm text-gray-200">每个模型可能有不同的效果,仅对当前对话有影响</p>
+                <div class="flex items-start py-3 border-b border-gray-200">
+                  <el-radio-group class="radio" v-model="configForm.radio2" @input="formModelChange">
+                    <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 class="bottom px-4">
+              <div class="flex justify-between">
+
+              </div>
+            </div>
+          </div>
+        </transition>
+      </el-dialog>
+
     </div>
   </div>
 </template>
@@ -119,6 +131,7 @@ export default {
   },
   data() {
     return {
+      showBottomPopup: true,
       // 聊天等待
       chatLoading: false,
       // 是否全屏
@@ -226,6 +239,10 @@ export default {
       // 查找当前角色是否有对话记录
       this.searchHistory(this.info.id)
     },
+    formModelChange() {
+      // 在浏览器缓存用户的配置
+      Cookies.set(`userConfig_${this.$store.state.user.userId}_${this.info.id}`, JSON.stringify(this.configForm))
+    },
     // 全屏
     clickFullScreen() {
       this.fullScreen = !this.fullScreen
@@ -343,7 +360,7 @@ export default {
         // 编辑
         let height = this.$refs[`message${value3}`][0].offsetHeight
         let width = this.$refs[`message${value3}`][0].offsetWidth
-        
+
         value2.edit = true
         this.$nextTick(() => {
           this.$refs[`messageEditInput${value3}`][0].$el.children[0].style.height = height + 'px'
@@ -392,7 +409,7 @@ export default {
         value.edit = false
         this.getChatRecord(this.recordId)
       })
-      
+
     },
     // 删除单条聊天记录
     deleteRecord(value, index) {
@@ -408,7 +425,7 @@ export default {
         this.getChatRecord(this.recordId)
       })
     },
-    
+
     // 聊天记录新增对话
     async newStart_juese(value) {
       console.log(value, 'value');
@@ -565,7 +582,7 @@ export default {
       if (res.data) {
         for (let i = 0; i < res.data.length; i++) {
           const element = res.data[i];
-          if(this.info.id == element.id) {
+          if (this.info.id == element.id) {
             element.open = true
           } else {
             element.open = false
@@ -600,7 +617,13 @@ export default {
       let res = await detailApi(id)
       console.log(res, '角色详情');
       this.info = res.data
+      // 模型选中角色默认模型
       this.configForm.radio2 = this.info.modelId
+      // 如果用户有设置过模型使用用户设置模型
+      let userConfig = JSON.parse(Cookies.get(`userConfig_${this.$store.state.user.userId}_${this.info.id}`))
+      if (userConfig.radio2) {
+        this.configForm.radio2 = userConfig.radio2
+      }
       // let HistoryMessage = JSON.parse(localStorage.getItem(`[userId:${123},aiId:${this.info.id}]`));
       // if (HistoryMessage) {
       //   this.returnMessage = HistoryMessage
@@ -821,11 +844,11 @@ export default {
         return
       }
       const reader = res.body.getReader()
-      const decoder=new TextDecoder()
-      while(1){
-        const {done, value} = await reader.read()
+      const decoder = new TextDecoder()
+      while (1) {
+        const { done, value } = await reader.read()
         // console.log(done, 'done');
-        if(done){
+        if (done) {
           console.log(value, '结束value');
           this.chatLoading = false
           // if (typeof(value) == "undefined") {
@@ -843,15 +866,17 @@ export default {
           // 如果开启自动播放,则查询并播放语音
           // this.audioUrl = ""
           // if (!this.resError) {
-          
+
           // }
           console.log('结束');
           break;
         }
 
         //txt就是一个一个的字 然后添加到页面上就可以了
+
         const txt = decoder.decode(value).split('data:')
         // const txt = decoder.decode(value)
+        console.log(txt, 'txt');
         this.addMessage(txt)
         // let data = JSON.parse(txt).message.content
         // console.log(txt, 'txt');
@@ -867,16 +892,16 @@ export default {
       // console.log(value, 'value');
       for (let i = 0; i < value.length; i++) {
         const element = value[i];
-        
+
         if (this.isJSON(element)) {
           let value = JSON.parse(element)
-          if(value.code == 401) {
+          if (value.code == 401) {
             this.returnMessage.splice(this.returnMessage.length - 1, 1)
             this.noLogin(element)
             this.chatLoading = false
             break;
           }
-          if(value.code == 500) {
+          if (value.code == 500) {
             console.log(value, 'JSON.parse(element)');
             this.returnMessage.splice(this.returnMessage.length - 2, 2)
             this.$message.error(value.content || '系统错误请联系管理员')
@@ -921,24 +946,24 @@ export default {
           type: "warning",
         }
       )
-      .then(() => {
-        // isRelogin.show = false;
-        this.$store.dispatch("LogOut").then(() => {
-          // location.href = "/";
+        .then(() => {
+          // isRelogin.show = false;
+          this.$store.dispatch("LogOut").then(() => {
+            // location.href = "/";
 
-          _this.$refs.Header.showLogin()
+            _this.$refs.Header.showLogin()
+          });
+        })
+        .catch(() => {
+          // isRelogin.show = false;
         });
-      })
-      .catch(() => {
-        // isRelogin.show = false;
-      });
     },
     isJSON(str) {
       if (typeof str == 'string') {
         try {
           JSON.parse(str);
           return true;
-        } catch(e) {
+        } catch (e) {
           // console.log(e);
           return false;
         }
@@ -993,7 +1018,7 @@ export default {
       this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
       console.log(this.audioUrl, 'this.audioUrl');
       setTimeout(() => {
-        
+
         if (this.audioUrl) {
           this.$refs.audio.play()
         }
@@ -1107,7 +1132,7 @@ export default {
       if (value) {
         queryUserBalanceApi().then(res => {
           console.log(res, '用户余额');
-          if (res.data <= 0 ) {
+          if (res.data <= 0) {
             this.setting.value1 = false
             this.$message({
               message: '余额不足,无法开启次功能',
@@ -1142,10 +1167,10 @@ export default {
 }
 </script>
 <style lang="scss" scoped>
-
 .chat {
   min-height: 100vh;
 }
+
 .top {
   position: relative;
   width: 100%;
@@ -1153,102 +1178,111 @@ export default {
   display: flex;
   align-items: center;
 }
+
 .chatContent {
   // margin-top: 30px;
   background-size: 100% 100%;
   display: flex;
-  height: calc(100% - 50px);
+  height: calc(100% - 50px - 63px);
   justify-content: center;
   width: 100vw;
-  
+  margin-bottom: 63px;
+
   >.leftImg {
-      border-radius: 16px 16px 16px 16px;
-      height: 95%;
-      position: relative;
-      min-width: 380px;
+    border-radius: 16px 16px 16px 16px;
+    height: 95%;
+    position: relative;
+    min-width: 380px;
 
-      >img {
-        border: 6px solid;
-        border-image: linear-gradient(180deg, #b48733, #e8cf97, #b48733) 6 6;
-        height: 99%;
-        margin-right: 5px;
-      }
-      >.aiInfo {
-        background-color: #ffffff1a;
-        border-radius: 24px 24px 24px 24px;
-        bottom: -70px;
-        display: flex;
-        height: 193px;
-        justify-content: center;
-        left: 50%;
+    >img {
+      border: 6px solid;
+      border-image: linear-gradient(180deg, #b48733, #e8cf97, #b48733) 6 6;
+      height: 99%;
+      margin-right: 5px;
+    }
+
+    >.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%;
+
+      >.photo {
+        width: 64px;
+        height: 64px;
+        font-size: 18px;
         position: absolute;
-        transform: translate(-50%, -50%);
-        width: 100%;
+        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;
+        border-radius: 50%;
+      }
+
+      >.info {
+        padding-top: 50px;
+        width: 80%;
 
-        >.photo {
-          width: 64px;
-          height: 64px;
-          font-size: 18px;
-          position: absolute;
-          top: -20px;
-          box-sizing: border-box;
-          margin: 0;
-          padding: 0;
+        >.name {
           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;
+          font-size: 22px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: 31px;
           text-align: center;
-          vertical-align: middle;
-          background: rgba(0, 0, 0, 0.25);
-          border: 1px solid transparent;
-          border-radius: 50%;
+          text-transform: none;
         }
-        >.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 {
+
+        >.tags {
+          padding-bottom: 8px;
+          text-align: center;
+
+          >.tag {
+            margin-right: 4px;
+            background: #ffffff1a;
+            border-radius: 4px 4px 4px 4px;
             color: #fff;
-            font-size: 16px;
-            font-style: normal;
+            font-size: 12px;
             font-weight: 500;
-            height: 80px;
-            line-height: 22px;
-            overflow-y: auto;
-            text-align: center;
-            text-transform: none;
+            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;
+        }
       }
+    }
   }
+
   >.chat-box {
     position: relative;
     // background: linear-gradient(rgba(255, 255, 255, 0) 75%, rgb(34, 34, 34));
@@ -1268,12 +1302,14 @@ export default {
 }
 
 .messages {
-  height: calc(100% - 68px );
+  // height: calc(100% - 68px );
   overflow-y: auto;
 }
+
 .messages::-webkit-scrollbar {
   width: 0px;
 }
+
 .message {
   background: var(--bg-color3);
   // border: 1px solid #5b5b5e;
@@ -1282,6 +1318,7 @@ export default {
   min-width: 80px;
   height: max-content;
 }
+
 .message2 {
   color: #000;
   background: rgba(200, 200, 200, 0.6);
@@ -1291,38 +1328,101 @@ export default {
   min-width: 80px;
   height: max-content;
 }
+
 .photo {
   width: 56px;
 }
+
 .me {
   flex-direction: row-reverse;
 }
+
 .loadingMessage {
   position: relative;
   // display: flex;
   // justify-content: center;
-  width: 100%;
-  height: 100%;
+  width: 60px;
+  height: 32px;
 }
 </style>
 <style scoped>
+.loadingMessage>>>.el-loading-parent--relative {
+  width: 100%;
+  height: 100%;
 
-  .loadingMessage >>> .el-loading-parent--relative {
-    width: 100%;
-    height: 100%;
-    
-  }
-  .loadingMessage >>> .el-loading-spinner {
-    display: flex;
-    justify-content: center;
-  }
-  .mButton {
-    border: solid 0px;
-  }
-  .tm_button {
-    width: 26px;
-    height: 26px;
-    font-size: 20px;
-    padding: 0px;
-  }
+}
+
+.loadingMessage>>>.el-loading-spinner {
+  display: flex;
+  justify-content: center;
+}
+
+.mButton {
+  border: solid 0px;
+}
+
+.tm_button {
+  width: 26px;
+  height: 26px;
+  font-size: 20px;
+  padding: 0px;
+}
+
+.phoneBottomPopup>>>.el-dialog {
+  margin-top: 0 !important;
+  position: absolute;
+  bottom: 0;
+  /* height: 70%; */
+  background: rgba(255, 255, 255, 0);
+}
+
+.phoneBottomPopup>>>.el-dialog__header {
+  padding: 0;
+}
+
+.phoneBottomPopup>>>.el-dialog__body {
+  color: #fff;
+  padding: 0;
+  width: 100%;
+  height: 100%;
+}
+
+.phoneBottomPopup .content {
+  background: var(--bg-color5);
+  color: #fff;
+  width: 100%;
+  height: 100%;
+  padding: 10px 15px;
+}
+
+.phoneBottomPopup .configForm {
+  margin-bottom: 60px;
+}
+
+.phoneBottomPopup .bottom {
+  height: 60px;
+
+}
+
+.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;
+  background-color: var(--bg-color5);
+  border-radius: 4px;
+  color: #fff;
+}
+
+.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>

+ 236 - 204
src/views/chat/ChatPC.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="chat bg-white">
-    <div class="flex items-center h-screen relative" >
-      <div class="leftInfo relative" v-show="!showNodata" >
+    <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">
@@ -19,51 +19,46 @@
               </div>
             </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 v-if="item.isDelete == 0" type="primary" class="flex-1" round @click="newStart_juese(item)">新的对话</el-button>
-                  <div v-else class="flex-1 rounded border border-gray-200 text-sm p-2 text-gray-600">
-                    {{item.characterName}}已经被设定为私有或被创建者删除。
-                  </div>
-                  <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)">
-                    <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"
-                    trigger="click"
-                    @command="handleCommand($event, item, item2 )"
-                  >
-                    <div >
-                      <i slot="reference" class="el-icon-more"></i>
-                    </div>
-                    <el-dropdown-menu slot="dropdown" >
-                      <el-dropdown-item command="1">修改标题</el-dropdown-item>
-                      <el-dropdown-item command="2">删除</el-dropdown-item>
-                    </el-dropdown-menu>
-                  </el-dropdown>
+            <div class="dialogueList mt-4" v-show="item.open">
+              <div class="flex justify-between mb-2">
+                <el-button v-if="item.isDelete == 0" type="primary" class="flex-1" round
+                  @click="newStart_juese(item)">新的对话</el-button>
+                <div v-else class="flex-1 rounded border border-gray-200 text-sm p-2 text-gray-600">
+                  {{ item.characterName }}已经被设定为私有或被创建者删除。
                 </div>
+                <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)">
+                  <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"
+                  trigger="click" @command="handleCommand($event, item, item2)">
+                  <div>
+                    <i slot="reference" class="el-icon-more"></i>
+                  </div>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item command="1">修改标题</el-dropdown-item>
+                    <el-dropdown-item command="2">删除</el-dropdown-item>
+                  </el-dropdown-menu>
+                </el-dropdown>
               </div>
+            </div>
             <!-- </transition> -->
           </div>
         </div>
@@ -80,21 +75,23 @@
               </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 class="mt-1 text-gray-500 text-sm">Xchat No.{{ info.id }}</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"/>
+                <v-icon name="fire" scale="1" />
                 <span class="ml-1">{{ info.hotCount }}</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 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 v-show="showDetail">
                 <div class="mt-5 text-base pb-3 border-b border-gray-200">
                   <div>
                     <i class="el-icon-document"></i>
@@ -139,9 +136,11 @@
                 查看场景
               </div>
               <div class="mt-3 text-sm max-h-48">
-                <div v-if="info.sceneList && info.sceneList.length > 0" class="grid grid-cols-2 gap-2 mb-4 cursor-pointer">
-                  <template v-for="(item, index) in info.sceneList" >
-                    <div v-if="item.isDelete == 0" class="flex flex-col justify-center" :key="index" @click="sceneChange(item)">
+                <div v-if="info.sceneList && info.sceneList.length > 0"
+                  class="grid grid-cols-2 gap-2 mb-4 cursor-pointer">
+                  <template v-for="(item, index) in info.sceneList">
+                    <div v-if="item.isDelete == 0" class="flex flex-col justify-center" :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>
@@ -167,7 +166,8 @@
           </div>
         </div>
       </div>
-      <div class="content" :class="fullScreen && 'contentFull'" v-show="!showNodata" :style="{ backgroundImage: `url(${baseApi}${sceneInfo.background})`}">
+      <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">
@@ -189,26 +189,21 @@
           <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="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"
-              >
+              <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>
+                    <i class="el-icon-arrow-down ml-2" style="font-size: 16px;" v-else></i>
                   </div>
 
                 </div>
-                <el-dropdown-menu slot="dropdown" >
+                <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>
@@ -217,10 +212,7 @@
             </div>
             <div class="flex w-60 justify-end">
               <el-tooltip effect="dark" content="设定" placement="bottom">
-                <el-popover
-                  placement="bottom"
-                  width="400"
-                  trigger="click">
+                <el-popover placement="bottom" width="400" trigger="click">
                   <div class="p-2">
                     <div class="flex justify-between mb-4">
                       <span>语音自动播放</span>
@@ -253,28 +245,29 @@
               <div v-if="item.role == 'assistant'" class="mb-4 flex" :key="index">
                 <!-- ai返回的信息 -->
                 <div class="pt-2 photo">
-                  <img
-                    :src="baseApi + info.picture"
-                    class="rounded-full w-14 h-14 object-cover"
-                  />
+                  <img :src="baseApi + info.picture" class="rounded-full w-14 h-14 object-cover" />
                 </div>
                 <div class="messageRight">
-                  <div v-show="!item.edit" :ref="`message${index}`" class="message mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative" >
-                    <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="historyGetVoice(item, index)">
+                  <div v-show="!item.edit" :ref="`message${index}`"
+                    class="message mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative">
+                    <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="historyGetVoice(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-show="!item.content" class="loadingMessage">
                       <div v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
                     </div>
                     <p style="white-space: pre-line;" v-show="item.content">{{ item.content }} </p>
                     <div class="messageOptions" v-show="returnMessage.length == 1">
-                      <div class="option" v-for="(item, index) in messageOptions" :key="index" @click="messageOptionClick(item.chatGuidance)">
+                      <div class="option" v-for="(item, index) in messageOptions" :key="index"
+                        @click="messageOptionClick(item.chatGuidance)">
                         {{ item.chatGuidance }}
                       </div>
                     </div>
-                    <el-dropdown v-if="index != 0" class="messageDropdown" @command="handleCommand4($event, item, index)" placement="top-end">
+                    <el-dropdown v-if="index != 0" class="messageDropdown" @command="handleCommand4($event, item, index)"
+                      placement="top-end">
                       <el-button class="messageButton" icon="el-icon-more" circle></el-button>
                       <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item command="1">编辑</el-dropdown-item>
@@ -283,12 +276,9 @@
                       </el-dropdown-menu>
                     </el-dropdown>
                   </div>
-                  <div :ref="`messageEdit${index}`" v-show="item.edit" class="message messageEdit mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative" >
-                    <el-input
-                      class="eidtTextarea"
-                      :ref="`messageEditInput${index}`"
-                      type="textarea"
-                      resize="none"
+                  <div :ref="`messageEdit${index}`" v-show="item.edit"
+                    class="message messageEdit mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative">
+                    <el-input class="eidtTextarea" :ref="`messageEditInput${index}`" type="textarea" resize="none"
                       v-model="item.editContent">
                     </el-input>
                     <div class="flex justify-end mt-2">
@@ -301,15 +291,14 @@
               <!-- 用户发送的信息 -->
               <div v-if="item.role == 'user'" class="mb-4 flex me" :key="index">
                 <div class="pt-2 photo">
-                  <img
-                    :src="$store.state.user.avatar"
-                    class="rounded-full w-14 h-14 object-cover"
-                  />
+                  <img :src="$store.state.user.avatar" class="rounded-full w-14 h-14 object-cover" />
                 </div>
                 <div class="messageRight">
-                  <div :ref="`message${index}`" v-show="!item.edit" class="messageUser mr-4 mt-4 p-4 rounded-l-md rounded-br-md text-xs relative">
+                  <div :ref="`message${index}`" v-show="!item.edit"
+                    class="messageUser mr-4 mt-4 p-4 rounded-l-md rounded-br-md text-xs relative">
                     {{ item.content }}
-                    <el-dropdown v-if="index != 0" class="messageDropdown" @command="handleCommand4($event, item, index)" placement="top-end">
+                    <el-dropdown v-if="index != 0" class="messageDropdown" @command="handleCommand4($event, item, index)"
+                      placement="top-end">
                       <el-button class="messageButton" icon="el-icon-more" circle></el-button>
                       <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item command="1">编辑</el-dropdown-item>
@@ -317,12 +306,9 @@
                       </el-dropdown-menu>
                     </el-dropdown>
                   </div>
-                  <div :ref="`messageEdit${index}`" v-show="item.edit" class="messageUser messageEdit mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative" >
-                    <el-input
-                      class="eidtTextarea"
-                      :ref="`messageEditInput${index}`"
-                      type="textarea"
-                      resize="none"
+                  <div :ref="`messageEdit${index}`" v-show="item.edit"
+                    class="messageUser messageEdit mt-4 ml-4 p-4 rounded-r-md rounded-bl-md text-xs relative">
+                    <el-input class="eidtTextarea" :ref="`messageEditInput${index}`" type="textarea" resize="none"
                       v-model="item.editContent">
                     </el-input>
                     <div class="flex justify-end mt-2">
@@ -337,23 +323,18 @@
           </div>
 
           <div class="inputBox absolute left-2 right-2 bottom-4 " @click="inputBoxClick">
-            <input
-                v-if="canChat"
-                ref="input"
-                type="text"
-                placeholder="输入消息..."
-                class="w-full flex-1 py-2 px-4 rounded-l-lg text-sm  focus:outline-none"
-                v-model="content"
-                @keydown="Enterkey"
-              />
+            <input v-if="canChat" ref="input" type="text" placeholder="输入消息..."
+              class="w-full flex-1 py-2 px-4 rounded-l-lg text-sm  focus:outline-none" v-model="content"
+              @keydown="Enterkey" />
             <div class="flex pt-6 justify-between" v-if="canChat" style="height: 70px;">
               <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>
-              <el-button type="text" :disabled="!content" :loading="notChatSend" @click.prevent="getStreamChatWithWeb" class="px-4 rounded-r-lg text-sm text-gray-400" :class="content && 'planeColor'">
-                <v-icon v-show="!notChatSend" name="paper-plane" scale="1.5"/>
+              <el-button type="text" :disabled="!content" :loading="notChatSend" @click.prevent="getStreamChatWithWeb"
+                class="px-4 rounded-r-lg text-sm text-gray-400" :class="content && 'planeColor'">
+                <v-icon v-show="!notChatSend" name="paper-plane" scale="1.5" />
               </el-button>
             </div>
             <div v-if="!canChat" class=" flex w-full text-sm text-gray-400">
@@ -366,11 +347,7 @@
         <el-empty description="暂无聊天记录,点击按钮并探索新角色。"></el-empty>
         <el-button type="primary" round @click="$router.push('/')">寻找一个角色</el-button>
       </div>
-      <el-dialog
-        title="配置"
-        :visible.sync="showConfig"
-        width="500px"
-      >
+      <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">
@@ -385,7 +362,8 @@
         <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-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>
@@ -401,14 +379,15 @@
         </div> -->
         <span slot="footer" class="dialog-footer">
           <el-button @click="showConfig = false">取 消</el-button>
-          <el-button type="primary" @click="showConfig = false">确 定</el-button>
+          <el-button type="primary" @click="configConfirm">确 定</el-button>
         </span>
       </el-dialog>
     </div>
-</div>
+  </div>
 </template>
 
 <script>
+import Cookies from 'js-cookie'
 import {
   streamChatWithWebApi,
   getGuidanceApi,
@@ -679,7 +658,7 @@ export default {
         // 编辑
         let height = this.$refs[`message${value3}`][0].offsetHeight
         let width = this.$refs[`message${value3}`][0].offsetWidth
-        
+
         value2.edit = true
         this.$nextTick(() => {
           this.$refs[`messageEditInput${value3}`][0].$el.children[0].style.height = height + 'px'
@@ -728,7 +707,7 @@ export default {
         value.edit = false
         this.getChatRecord(this.recordId)
       })
-      
+
     },
     // 删除单条聊天记录
     deleteRecord(value, index) {
@@ -744,7 +723,7 @@ export default {
         this.getChatRecord(this.recordId)
       })
     },
-    
+
     // 聊天记录新增对话
     async newStart_juese(value) {
       console.log(value, 'value');
@@ -834,6 +813,7 @@ export default {
           this.returnMessage = [...this.returnMessage, ...history]
         }
         this.configForm.radio2 = this.modelList[0].id
+
         this.modelList.map(item => {
           if (item.id == array[array.length - 1].modelId) {
             this.configForm.radio2 = item.id
@@ -899,7 +879,7 @@ export default {
       if (res.data) {
         for (let i = 0; i < res.data.length; i++) {
           const element = res.data[i];
-          if(this.info.id == element.id) {
+          if (this.info.id == element.id) {
             element.open = true
           } else {
             element.open = false
@@ -934,7 +914,13 @@ export default {
       let res = await detailApi(id)
       console.log(res, '角色详情');
       this.info = res.data
+      // 模型选中角色默认模型
       this.configForm.radio2 = this.info.modelId
+      // 如果用户有设置过模型使用用户设置模型
+      let userConfig = JSON.parse(Cookies.get(`userConfig_${this.$store.state.user.userId}_${this.info.id}`))
+      if (userConfig.radio2) {
+        this.configForm.radio2 = userConfig.radio2
+      }
       // let HistoryMessage = JSON.parse(localStorage.getItem(`[userId:${123},aiId:${this.info.id}]`));
       // if (HistoryMessage) {
       //   this.returnMessage = HistoryMessage
@@ -1019,6 +1005,13 @@ export default {
         this.getStreamChatWithWeb()
       }
     },
+    // 设置用户配置
+    configConfirm() {
+      console.log(this.info, 'this.info');
+      // 在浏览器缓存用户的配置
+      Cookies.set(`userConfig_${this.$store.state.user.userId}_${this.info.id}`, JSON.stringify(this.configForm))
+      this.showConfig = false
+    },
     // 前往创建场景
     toCreateScene() {
       this.$router.push({
@@ -1155,11 +1148,11 @@ export default {
         return
       }
       const reader = res.body.getReader()
-      const decoder=new TextDecoder()
-      while(1){
-        const {done, value} = await reader.read()
+      const decoder = new TextDecoder()
+      while (1) {
+        const { done, value } = await reader.read()
         // console.log(done, 'done');
-        if(done){
+        if (done) {
           console.log(value, '结束value');
           this.chatLoading = false
           // if (typeof(value) == "undefined") {
@@ -1177,7 +1170,7 @@ export default {
           // 如果开启自动播放,则查询并播放语音
           // this.audioUrl = ""
           // if (!this.resError) {
-          
+
           // }
           console.log('结束');
           break;
@@ -1201,16 +1194,16 @@ export default {
       // console.log(value, 'value');
       for (let i = 0; i < value.length; i++) {
         const element = value[i];
-        
+
         if (this.isJSON(element)) {
           let value = JSON.parse(element)
-          if(value.code == 401) {
+          if (value.code == 401) {
             this.returnMessage.splice(this.returnMessage.length - 1, 1)
             this.noLogin(element)
             this.chatLoading = false
             break;
           }
-          if(value.code == 500) {
+          if (value.code == 500) {
             console.log(value, 'JSON.parse(element)');
             this.returnMessage.splice(this.returnMessage.length - 2, 2)
             this.$message.error(value.content || '系统错误请联系管理员')
@@ -1255,24 +1248,24 @@ export default {
           type: "warning",
         }
       )
-      .then(() => {
-        // isRelogin.show = false;
-        this.$store.dispatch("LogOut").then(() => {
-          // location.href = "/";
+        .then(() => {
+          // isRelogin.show = false;
+          this.$store.dispatch("LogOut").then(() => {
+            // location.href = "/";
 
-          _this.$refs.Header.showLogin()
+            _this.$refs.Header.showLogin()
+          });
+        })
+        .catch(() => {
+          // isRelogin.show = false;
         });
-      })
-      .catch(() => {
-        // isRelogin.show = false;
-      });
     },
     isJSON(str) {
       if (typeof str == 'string') {
         try {
           JSON.parse(str);
           return true;
-        } catch(e) {
+        } catch (e) {
           // console.log(e);
           return false;
         }
@@ -1327,7 +1320,7 @@ export default {
       this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
       console.log(this.audioUrl, 'this.audioUrl');
       setTimeout(() => {
-        
+
         if (this.audioUrl) {
           this.$refs.audio.play()
         }
@@ -1441,7 +1434,7 @@ export default {
       if (value) {
         queryUserBalanceApi().then(res => {
           console.log(res, '用户余额');
-          if (res.data <= 0 ) {
+          if (res.data <= 0) {
             this.setting.value1 = false
             this.$message({
               message: '余额不足,无法开启次功能',
@@ -1491,9 +1484,11 @@ export default {
   height: 1.6rem;
   cursor: pointer;
 }
+
 .chat {
   height: 100vh;
 }
+
 .leftInfo {
   width: 375px;
   height: 100%;
@@ -1511,6 +1506,7 @@ export default {
       border-radius: 15px;
       border: solid 1px var(--color1);
       margin-bottom: 10px;
+
       .top {
         >.photo {
           >img {
@@ -1519,30 +1515,38 @@ export default {
             border-radius: 50%;
           }
         }
+
         >.info {
           width: calc(100% - 60px - 16px);
+
           >div {
-            overflow: hidden; /* 确保超出容器的文本被裁剪 */
-            white-space: nowrap; /* 确保文本在一行内显示 */
-            text-overflow: ellipsis; /* 使用省略号表示文本超出 */
+            overflow: hidden;
+            /* 确保超出容器的文本被裁剪 */
+            white-space: nowrap;
+            /* 确保文本在一行内显示 */
+            text-overflow: ellipsis;
+            /* 使用省略号表示文本超出 */
           }
         }
       }
     }
   }
+
   >.chatInfo {
     overflow: hidden;
-    .chatInfo_photo {
-      >img {
 
-      }
+    .chatInfo_photo {
+      >img {}
     }
+
     .hot {
       color: #f03d3d;
       background: #fff1f1;
     }
+
     .tags {
       margin-top: 10px;
+
       .tag {
         display: inline-flex;
         justify-content: center;
@@ -1570,6 +1574,7 @@ export default {
   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%, rgba(255, 255, 255, 0) 20%, rgba(255, 255, 255, 0) 75%, rgba(0, 0, 0, 0.4) 100%);
@@ -1581,6 +1586,7 @@ export default {
     height: 100%;
     width: 100%;
     padding: 55px 25px 170px 25px;
+
     >.chatBoxTitle {
       color: #fff;
       margin-top: 15px;
@@ -1592,14 +1598,18 @@ export default {
     }
   }
 }
+
 .contentFull {
   width: 100%;
 }
+
 .historyActive {
   background: var(--color1);
 }
+
 .dialogue:hover {
   background: var(--color1);
+
   .dialogueIconBg {
     display: flex;
   }
@@ -1609,17 +1619,21 @@ export default {
   display: none;
   background: linear-gradient(90deg, rgba(0, 0, 0, 0) 10%, var(--color1) 50%, var(--color1) 100%);
 }
+
 .messages {
-  height: calc(100% - 68px );
+  height: calc(100% - 68px);
   overflow-y: auto;
 }
+
 .messages::-webkit-scrollbar {
   width: 0px;
 }
+
 .messageRight {
   max-width: calc(100% - 72px);
   // min-width: 400px;
 }
+
 .yyPlayBg {
   // background: rgba(103, 103, 168, 1);
   // border-radius: 999px;
@@ -1642,6 +1656,7 @@ export default {
   // height: 50px;
   // background: #fff;
 }
+
 .message {
   // background: #ffffff0f;
   // border: 1px solid #5b5b5e;
@@ -1651,6 +1666,7 @@ export default {
   // flex: 1;
 
 }
+
 .messageUser {
   background: rgba(255, 255, 255, 0.9);
   border: 1px solid var(--color1);
@@ -1659,12 +1675,15 @@ export default {
   width: auto;
   // min-width: 400px;
 }
+
 .photo {
   width: 56px;
 }
+
 .me {
   flex-direction: row-reverse;
 }
+
 .loadingMessage {
   position: relative;
   // display: flex;
@@ -1672,12 +1691,14 @@ export default {
   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;
@@ -1689,6 +1710,7 @@ export default {
     cursor: pointer;
   }
 }
+
 .inputBox {
   border: solid 1px var(--color1);
   border-radius: 10px;
@@ -1697,67 +1719,77 @@ export default {
   max-width: 900px;
   margin: 0 auto;
 }
+
 .planeColor {
   color: var(--bg-color1);
 }
-
 </style>
 <style scoped>
-  .loadingMessage >>> .el-loading-parent--relative {
-    width: 100%;
-    height: 100%;
+.loadingMessage>>>.el-loading-parent--relative {
+  width: 100%;
+  height: 100%;
 
-  }
-  .loadingMessage >>> .el-loading-spinner {
-    display: flex;
-    justify-content: center;
-  }
-  .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);
-  }
-  .message:hover >>> .messageButton,
-  .messageUser:hover >>> .messageButton {
-    display: block;
-  }
-  .messageButton {
-    display: none;
-    
-    width: 25px;
-    height: 25px;
-    padding: 0;
-  }
-  .messageDropdown {
-    position: absolute;
-    bottom: -12px;
-    right: 10px;
-  }
-  
-  .eidtTextarea >>> .el-textarea__inner {
-    padding: 0;
-    background: none;
-    border: 0;
-    color: #fff;
-  }
-  .messageUser >>> .el-textarea__inner {
-    color: #000;
-  }
-  .messageEdit {
-    min-width: 400px;
-  }
+}
+
+.loadingMessage>>>.el-loading-spinner {
+  display: flex;
+  justify-content: center;
+}
+
+.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);
+}
+
+.message:hover>>>.messageButton,
+.messageUser:hover>>>.messageButton {
+  display: block;
+}
+
+.messageButton {
+  display: none;
+
+  width: 25px;
+  height: 25px;
+  padding: 0;
+}
+
+.messageDropdown {
+  position: absolute;
+  bottom: -12px;
+  right: 10px;
+}
+
+.eidtTextarea>>>.el-textarea__inner {
+  padding: 0;
+  background: none;
+  border: 0;
+  color: #fff;
+}
+
+.messageUser>>>.el-textarea__inner {
+  color: #000;
+}
+
+.messageEdit {
+  min-width: 400px;
+}
 </style>

+ 56 - 64
src/views/create/index.vue

@@ -1,22 +1,22 @@
 <template>
   <div class="create app-pageContainer" 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">{{$route.query.id ? '编辑角色' : '创建角色'}}</div>
+          <div class="text-2xl mt-6 font-semibold">{{ $route.query.id ? '编辑角色' : '创建角色' }}</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" >
+          <el-form :model="form" :rules="rules" ref="form" label-width="60px" class="form">
             <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> -->
@@ -30,12 +30,8 @@
                     <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-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">
@@ -51,7 +47,8 @@
                   </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-option :label="item.labelName" :value="item.id" v-for="(item, index) in labelData"
+                        :key="index"></el-option>
                     </el-select>
                   </el-form-item>
                 </div>
@@ -61,53 +58,39 @@
             <div class="text-xl font-medium my-6">机器人制作</div>
             <div class="p-5 rounded-lg">
               <el-form-item label="性格" label-width="80px" prop="characterPersonalityTags" style="margin-bottom: 20px;">
-                <el-select :multiple-limit="3" v-model="form.characterPersonalityTags" multiple filterable placeholder="搜索并选择与你的机器人性格(最多三个)">
-                  <el-option :label="item.personalityName" :value="item.id" v-for="(item, index) in personalityList" :key="index"></el-option>
+                <el-select :multiple-limit="3" v-model="form.characterPersonalityTags" multiple filterable
+                  placeholder="搜索并选择与你的机器人性格(最多三个)">
+                  <el-option :label="item.personalityName" :value="item.id" v-for="(item, index) in personalityList"
+                    :key="index"></el-option>
                 </el-select>
               </el-form-item>
 
               <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}}
+                    {{ item.model }}
                   </el-radio-button>
                 </el-radio-group>
               </el-form-item>
-                
+
               <el-form-item label="开场白" prop="firstContent" label-width="80px" style="margin-bottom: 20px;">
-                <el-input 
-                  v-model="form.firstContent" 
-                  type="textarea"
-                  :autosize="{ minRows: 4, maxRows: 4}"
-                  placeholder="帮您的机器人设计一段开场白吧"
-                ></el-input>
+                <el-input v-model="form.firstContent" type="textarea" :autosize="{ minRows: 4, maxRows: 4 }"
+                  placeholder="帮您的机器人设计一段开场白吧"></el-input>
               </el-form-item>
               <el-form-item label="角色描述" prop="characterIntroduction" label-width="80px" style="margin-bottom: 20px;">
-                <el-input 
-                  v-model="form.characterIntroduction" 
-                  type="textarea"
-                  :autosize="{ minRows: 4, maxRows: 4}"
-                  placeholder="请在此处提供该角色的背景资讯。 使用'{char}'來指代您的角色。 例如:{char}是一个从小娇生惯养的大小姐。"
-                ></el-input>
+                <el-input v-model="form.characterIntroduction" type="textarea" :autosize="{ minRows: 4, maxRows: 4 }"
+                  placeholder="请在此处提供该角色的背景资讯。 使用'{char}'來指代您的角色。 例如:{char}是一个从小娇生惯养的大小姐。"></el-input>
               </el-form-item>
               <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-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-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>
@@ -185,7 +168,7 @@ export default {
     }
   },
   mounted() {
-    
+
     this.getModelList()
     this.getLabelList()
     this.getPersonalityList()
@@ -199,7 +182,7 @@ export default {
     // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');
   },
   methods: {
-    
+
     getPersonalityList() {
       let params = {
         pageSize: 9999,
@@ -240,7 +223,7 @@ export default {
       })
     },
     submitForm() {
-      this.$refs.form.validate((valid) => {
+      this.$refs.form.validate((valid, object) => {
         if (valid) {
           if (this.form.id) {
             updateCharacterApi(this.form).then(() => {
@@ -261,7 +244,11 @@ export default {
               this.$router.push('/profile')
             })
           }
-          
+
+        } else {
+          console.log(object, 'object.keys() ');
+          let keys = Object.keys(object)
+          this.$modal.msgError(object[keys[0]][0].message);
         }
       })
     },
@@ -269,39 +256,39 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
-
-
-</style>
+<style lang="scss" scoped></style>
 <style scoped>
-.form >>> .el-form-item {
+.form>>>.el-form-item {
   margin-bottom: 0px;
 }
-.form >>> .el-form-item__label,
-.form >>> .el-radio {
+
+.form>>>.el-form-item__label,
+.form>>>.el-radio {
   /* color: #fff; */
 }
-.form >>> .el-select {
+
+.form>>>.el-select {
   width: 100%;
 }
-.form >>> .el-input__inner,
-.form >>> .el-textarea__inner,
-.form >>> .el-select__input
- {
+
+.form>>>.el-input__inner,
+.form>>>.el-textarea__inner,
+.form>>>.el-select__input {
   width: 100%;
   /* background-color: rgba(75, 85, 99, 1); */
   /* color: #fff; */
   border-radius: 0.5rem;
   /* border-color: rgba(75, 85, 99, 0); */
 }
-.imgUp {
-  
-}
-.imgUp >>> .el-upload__tip {
+
+.imgUp {}
+
+.imgUp>>>.el-upload__tip {
   /* color: #b8b8b8; */
   text-align: center;
 }
-.imgUp >>> .upload {
+
+.imgUp>>>.upload {
   display: flex;
   flex-direction: column;
   justify-content: center;
@@ -311,10 +298,12 @@ export default {
   background: rgba(75, 85, 99, 1);
   border-radius: 10px; */
 }
-.imgUp >>> .el-upload {
+
+.imgUp>>>.el-upload {
   /* border-radius: 50%; */
 }
-.imgUp >>> .el-upload-list__item {
+
+.imgUp>>>.el-upload-list__item {
   /* border-radius: 50%; */
 }
 
@@ -336,6 +325,7 @@ export default {
   -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;
@@ -343,10 +333,12 @@ export default {
   box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.12);
   overflow: hidden;
 }
-.collapse >>> .el-collapse-item__header {
+
+.collapse>>>.el-collapse-item__header {
   padding: 0 10px;
 }
-.collapse >>> .el-collapse-item__content {
+
+.collapse>>>.el-collapse-item__content {
   padding: 20px 10px;
 }
 </style>

+ 53 - 61
src/views/profile/index.vue

@@ -12,7 +12,7 @@
             <div class="flex flex-col justify-center ml-3">
               <div class="font-medium text-2xl ">{{ userInfo.userName }}</div>
               <div class="text-base">账号:{{ userInfo.account }}</div>
-              <div class=" text-base">UID:1231235 <i class="el-icon-copy-document text-base"></i></div>
+              <div class=" text-base">UID:{{ userInfo.id }} <i class="el-icon-copy-document text-base"></i></div>
             </div>
           </div>
           <div class="flex mt-3">
@@ -28,7 +28,8 @@
           <div class=" w-10 h-10 rounded-full button flex justify-center items-center cursor-pointer mr-4">
             <i class="el-icon-share text-xl"></i>
           </div>
-          <div class="w-32 h-10 flex justify-center items-center rounded-full button cursor-pointer" @click="$router.push({ name: 'user' })">
+          <div class="w-32 h-10 flex justify-center items-center rounded-full button cursor-pointer"
+            @click="$router.push({ name: 'user' })">
             <i class="el-icon-edit"></i>
             编辑资料
           </div>
@@ -39,18 +40,12 @@
     <div class="px-28 py-10">
       <div class="h-18 flex justify-between pb-4 border-b border-gray-200">
         <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 == 0 && 'buttonBg1'"
-            @click="tabChange(0)"
-          >
+          <div class="labelButton flex justify-center items-center rounded-full mr-4 w-28 h-10 cursor-pointer"
+            :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 == 1 && 'buttonBg1'"
-            @click="tabChange(1)"
-          >
+          <div class="labelButton flex justify-center items-center rounded-full w-28 h-10 cursor-pointer"
+            :class="active == 1 && 'buttonBg1'" @click="tabChange(1)">
             <i class="el-icon-lock"></i>
             非公开
           </div>
@@ -60,26 +55,18 @@
             <i class="el-icon-question"></i>
             操作指南
           </div>
-          <el-popover
-            placement="bottom"
-            width="160"
-            v-model="popoverVisible"
-          >
+          <el-popover placement="bottom" 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 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 class="submenu w-full text-gray-600 text-center py-2 rounded cursor-pointer" @click="() => {
+                popoverVisible = false
+                routeTo('/create')
+              }">
                 创建角色
               </div>
             </div>
@@ -88,16 +75,12 @@
               创建
             </div>
           </el-popover>
-          
+
         </div>
       </div>
       <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 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 h-3/5">
             <img class="w-full img h-full" :src="baseApi + item.picture" />
           </div>
@@ -111,7 +94,8 @@
             </p>
 
             <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">
+              <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>
@@ -119,18 +103,14 @@
           </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 text-red-500">
-              <v-icon name="fire" scale="1"/>
-              <span class="ml-1">{{ item.hotCount||0 }}</span>
+              <v-icon name="fire" scale="1" />
+              <span class="ml-1">{{ item.hotCount || 0 }}</span>
             </div>
           </div>
         </div>
       </div>
     </div>
-    <el-dialog
-      title="提示"
-      :visible.sync="dialogVisible"
-      width="500px"
-    >
+    <el-dialog title="提示" :visible.sync="dialogVisible" width="500px">
       <div class="flex justify-between px-2 py-3 border-b border-gray-200" v-if="selectObj.scene == 1">
         <div>场景</div>
         <div>{{ selectObj.name }}</div>
@@ -155,17 +135,18 @@
         <el-button class="flex-1" round type="primary" @click="toCreate">编 辑</el-button>
       </span>
     </el-dialog>
-    
+
   </div>
 </template>
 
 <script>
 import { getInfo } from '@/api/login'
 import { queryCharacterAndSceneApi } from "@/api/profile.js"
-import { deleteSceneApi, 
+import {
+  deleteSceneApi,
   deleteCharacterApi,
   setCharacterShowApi,
-  editSceneApi 
+  editSceneApi
 } from "@/api/create.js"
 import 'vue-awesome/icons/fire'
 export default {
@@ -222,7 +203,7 @@ export default {
           }
         })
       }
-      
+
     },
     // 前往聊天页面
     toChat() {
@@ -307,7 +288,7 @@ export default {
             this.getCharacterList()
           })
         })
-        
+
       }
     },
     tabChange(index) {
@@ -340,15 +321,15 @@ export default {
         this.characterList = res.rows
       })
     },
-    sortByTime(attr, rev){
+    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;
+      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;
       }
     }
   }
@@ -362,46 +343,57 @@ export default {
   grid-auto-rows: minmax(100px, auto);
   grid-gap: 20px;
 }
+
 .button {
   // background-color: #fff;
   color: #fff;
   border: 1px solid #fff;
 }
+
 .labelButton {
   // border: solid 1px #e6e6e6;
   background: var(--bg-color2);
   color: var(--color2);
-} 
+}
+
 .buttonBg1 {
   background: var(--bg-color1);
   color: #fff;
 }
+
 .box2 {
-  background: #ffffff0f; 
+  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-color: var(--bg-color1);
+  background-image: url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png);
+  background-repeat: no-repeat;
   background-size: 100% 100%;
 }
+
 .prologue {
-  overflow:hidden;
+  overflow: hidden;
   text-overflow: ellipsis;
   -webkit-line-clamp: 4;
   display: -webkit-box;

+ 18 - 38
src/views/user/index.vue

@@ -4,19 +4,13 @@
       <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 === 'userInfo' ? 'bg-gray-100' : ''"
-        @click="menuClick('userInfo')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'userInfo' ? 'bg-gray-100' : ''" @click="menuClick('userInfo')">
         <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 === 'consume' ? 'bg-gray-100' : ''"
-        @click="menuClick('consume')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'consume' ? 'bg-gray-100' : ''" @click="menuClick('consume')">
         <i class="el-icon-setting text-xl mr-2"></i>
         消费明细
       </div>
@@ -36,40 +30,28 @@
         <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 === 'invite' ? 'bg-gray-100' : ''"
-        @click="menuClick('invite')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'invite' ? 'bg-gray-100' : ''" @click="menuClick('invite')">
         <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 === 'signIn' ? 'bg-gray-100' : ''"
-        @click="menuClick('signIn')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'signIn' ? 'bg-gray-100' : ''" @click="menuClick('signIn')">
         <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 === 'opinion' ? 'bg-gray-100' : ''"
-        @click="menuClick('opinion')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'opinion' ? 'bg-gray-100' : ''" @click="menuClick('opinion')">
         <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 === 'logOut' ? 'bg-gray-100' : ''"
-        @click="menuClick('logOut')"
-      >
+      <div class="w-full px-2 py-2 mb-2 flex items-center rounded-md cursor-pointer"
+        :class="active === 'logOut' ? 'bg-gray-100' : ''" @click="menuClick('logOut')">
         <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
+        © 2024 Xchat
         <a :href="`${baseURL}/#/termOfUse`" target="_blank" class="underline mx-1">用户协议</a>
         &amp;
         <a :href="`${baseURL}/#/privacyPolicy`" target="_blank" class="underline mx-1">隐私政策</a>
@@ -78,10 +60,10 @@
     </div>
     <div class=" flex-1 h-full bg-gray-50">
       <UserInfo v-if="active == 'userInfo'" />
-      <Consume  v-if="active == 'consume'" />
-      <Invite  v-if="active == 'invite'" />
-      <Opinion  v-if="active == 'opinion'" />
-      <SignIn  v-if="active == 'signIn'" />
+      <Consume v-if="active == 'consume'" />
+      <Invite v-if="active == 'invite'" />
+      <Opinion v-if="active == 'opinion'" />
+      <SignIn v-if="active == 'signIn'" />
     </div>
   </div>
 </template>
@@ -132,6 +114,4 @@ export default {
 }
 </script>
 
-<style>
-
-</style>
+<style></style>

+ 6 - 5
vue.config.js

@@ -38,7 +38,8 @@ module.exports = {
       [process.env.VUE_APP_BASE_API]: {
         // target: `http://192.168.0.105:8086`,
         // target: `http://aitest.api.rongcyl.cn`,
-        target: `http://192.168.0.103:8086`,
+        target: `http://192.168.0.115:8086/`,
+        // target: `http://192.168.0.108:8086/`,
         changeOrigin: true,
         pathRewrite: {
           ["^" + process.env.VUE_APP_BASE_API]: "",
@@ -125,10 +126,10 @@ module.exports = {
         },
       });
       config.optimization.runtimeChunk("single"),
-        {
-          from: path.resolve(__dirname, "./public/robots.txt"), //防爬虫文件
-          to: "./", //到根目录下
-        };
+      {
+        from: path.resolve(__dirname, "./public/robots.txt"), //防爬虫文件
+        to: "./", //到根目录下
+      };
     });
   },
 };