chenrong пре 9 месеци
родитељ
комит
7a5cb20e99

+ 26 - 18
public/index.html

@@ -1,16 +1,19 @@
 <!DOCTYPE html>
 <html>
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-    <meta name="renderer" content="webkit">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-    <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
-    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
-    <title><%= webpackConfig.name %></title>
-    <script src="https://kit.fontawesome.com/7c98163d58.js" crossorigin="anonymous"></script>
-    <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
-	  <style>
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="renderer" content="webkit">
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+  <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
+  <link rel="icon" type="image/svg+xml" href="/logo.png" />
+  <title>
+    <%= webpackConfig.name %>
+  </title>
+  <script src="https://kit.fontawesome.com/7c98163d58.js" crossorigin="anonymous"></script>
+  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
+  <style>
     html,
     body,
     #app {
@@ -18,6 +21,7 @@
       margin: 0px;
       padding: 0px;
     }
+
     .chromeframe {
       margin: 0.2em 0;
       background: #ccc;
@@ -94,6 +98,7 @@
         -ms-transform: rotate(0deg);
         transform: rotate(0deg);
       }
+
       100% {
         -webkit-transform: rotate(360deg);
         -ms-transform: rotate(360deg);
@@ -107,6 +112,7 @@
         -ms-transform: rotate(0deg);
         transform: rotate(0deg);
       }
+
       100% {
         -webkit-transform: rotate(360deg);
         -ms-transform: rotate(360deg);
@@ -196,15 +202,17 @@
       opacity: 0.5;
     }
   </style>
-  </head>
-  <body>
-    <div id="app">
-	    <!-- <div id="loader-wrapper">
+</head>
+
+<body>
+  <div id="app">
+    <!-- <div id="loader-wrapper">
 		    <div id="loader"></div>
 		    <div class="loader-section section-left"></div>
 		    <div class="loader-section section-right"></div>
 		    <div class="load_title">正在加载系统资源,请耐心等待</div>
       </div> -->
-	</div>
-  </body>
-</html>
+  </div>
+</body>
+
+</html>


+ 19 - 6
src/App.vue

@@ -10,21 +10,33 @@
 <script>
 import NavMenu from '@/views/components/NavMenu'
 import loginPopup from '@/views/homeComponents/loginPopup'
-export default  {
+export default {
   name: 'App',
   components: {
     loginPopup,
     NavMenu
   },
   metaInfo() {
-      return {
-          title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
-          titleTemplate: title => {
-              return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
-          }
+    return {
+      title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
+      titleTemplate: title => {
+        return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
       }
+    }
   },
   mounted() {
+    //首先我们获得视口高度并将其乘以1%以获得1vh单位的值
+    let vh = window.innerHeight * 0.01
+    // 然后,我们将——vh自定义属性中的值设置为文档的根
+    document.documentElement.style.setProperty('--vh', `${vh}px`)
+
+    // 我们监听resize事件 视图大小发生变化就重新计算1vh的值
+    window.addEventListener('resize', () => {
+      // 我们执行与前面相同的脚本
+      let vh = window.innerHeight * 0.01
+      console.log(vh);
+      document.documentElement.style.setProperty('--vh', `${vh}px`)
+    })
     this.pdIsMobile()
     let _this = this
     window.onresize = () => {
@@ -53,6 +65,7 @@ export default  {
 #app {
   // padding-bottom: 50px;
 }
+
 .pageContent {
   width: calc(100% - 72px);
   height: 100%;

+ 10 - 1
src/api/detail.js

@@ -1,9 +1,18 @@
 import request from '@/utils/request'
 
-// 获取标签列表
+// 获取角色详情
 export function detailApi(id) {
   return request({
     url: `/appUser/system/app/${id}`,
     method: 'get',
   })
+}
+
+// 获取角色详情(全部,需要登录校验)
+
+export function detailUserApi(id) {
+  return request({
+    url: `/appUser/system/app/isLoginUser/${id}`,
+    method: 'get',
+  })
 }

BIN
src/assets/images/default_AI.jpeg


BIN
src/assets/images/logo.png


BIN
src/assets/images/userBg.png


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

@@ -254,4 +254,14 @@ textarea {
 
 .bgColor1 {
   background-color: var(--bg-color1);
+}
+
+.userPhoto {
+  background: url(~@/assets/images/default_avatar_user.png) no-repeat;
+  background-size: 100% 100%;
+}
+
+.defaultAi {
+  background: url(~@/assets/images/default_AI.jpeg) no-repeat;
+  background-size: 100% 100%;
 }

+ 7 - 1
src/main.js

@@ -35,7 +35,10 @@ import {
   selectDictLabels,
   handleTree,
 } from "@/utils/rcBase";
-
+import {
+  userPohotoError,
+  AIPohotoError
+} from "@/utils/index.js";
 import Icon from 'vue-awesome/components/Icon'
 
 Vue.component('v-icon', Icon)
@@ -72,6 +75,9 @@ Vue.prototype.resetForm = resetForm;
 Vue.prototype.addDateRange = addDateRange;
 Vue.prototype.selectDictLabel = selectDictLabel;
 Vue.prototype.selectDictLabels = selectDictLabels;
+Vue.prototype.$userPohotoError = userPohotoError;
+Vue.prototype.$AIPohotoError = AIPohotoError;
+
 Vue.prototype.download = download;
 Vue.prototype.handleTree = handleTree;
 

+ 8 - 0
src/utils/index.js

@@ -392,3 +392,11 @@ export function camelCase(str) {
 export function isNumberStr(str) {
   return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
 }
+let defaultUserImg = require("@/assets/images/default_avatar_user.png");
+export function userPohotoError(e) {
+  e.srcElement.src = defaultUserImg
+}
+let defaultAIImg = require("@/assets/images/default_AI.jpeg");
+export function AIPohotoError(e) {
+  e.srcElement.src = defaultAIImg
+}

+ 19 - 9
src/views/chat/ChatH5.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="chat bg-white">
-    <div class="flex flex-col items-center justify-start h-screen">
+    <div class="flex flex-col items-center justify-start h-screen"
+      style="height: 100vh; height: calc(var(--vh, 1vh) * 100);">
       <!-- <img class="absolute h-full" :src="baseApi + info.picture" alt=""> -->
       <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>
@@ -37,25 +38,27 @@
             </div>
           </div>
         </div> -->
-        <div class="chat-box relative">
+        <div class="chat-box relative " :class="sceneId && 'mask'">
           <div class="messages" ref="messages">
             <template v-for="(item, index) in returnMessage ">
               <div v-if="item.role == 'assistant'" class="text-white mb-4 flex" :key="index">
                 <!-- ai返回的信息 -->
                 <div class="pt-2 photo">
-                  <img :src="baseApi + info.picture" class="rounded-full w-12 h-12 object-cover" @click="toDetail" />
+                  <img :src="baseApi + info.picture" class="rounded-full w-12 h-12 object-cover" @click="toDetail"
+                    @error="$AIPohotoError" />
                 </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 v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
                   </div>
-                  <p v-show="item.content">{{ item.content }} </p>
+                  <p style="white-space: pre-line;" v-show="item.content">{{ item.content }} </p>
                 </div>
               </div>
               <!-- 用户发送的信息 -->
               <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" @error="$userPohotoError"
+                    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>
@@ -65,7 +68,7 @@
           </div>
         </div>
       </div>
-      <div class="absolute bottom-0 bg-white w-full px-2 pt-2 pb-4 border-t border-gray-100">
+      <div class="fixed 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> -->
@@ -74,7 +77,8 @@
             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 @click.prevent="getStreamChatWithWeb" class="bgColor1 text-white px-4 rounded-r-lg text-sm"
+            style="width: 60px;">
             发送
           </button>
         </div>
@@ -82,7 +86,7 @@
       <el-dialog :visible.sync="showBottomPopup" :show-close="false" width="100%" class="phoneBottomPopup">
         <transition name="el-zoom-in-bottom">
           <div class="popupContent popup1" v-show="showBottomPopup">
-            <div class="configForm wf-full h-full flex flex-col">
+            <div class="configForm w-full flex flex-col overflow-y-auto" style="height: calc(100% - 75px)">
               <div class="row">
                 <p class="text-base mt-3">选择模型</p>
                 <p class="text-sm text-gray-200">每个模型可能有不同的效果,仅对当前对话有影响</p>
@@ -966,6 +970,7 @@ export default {
           clearTimeout(this.timeOut)
           this.timeOut = setTimeout(() => {
             this.returnMessage[this.returnMessage.length - 1].content = 'AI智能累得打起了小盹儿,咱们让他缓一缓,再来试试!'
+            this.chatLoading = false
           }, 10000)
         }
         // console.log(txt, 'txt');
@@ -1279,7 +1284,7 @@ export default {
   height: calc(100% - 50px - 63px);
   justify-content: center;
   width: 100vw;
-  margin-bottom: 63px;
+  // margin-bottom: 63px;
 
   >.leftImg {
     border-radius: 16px 16px 16px 16px;
@@ -1378,6 +1383,7 @@ export default {
 
   >.chat-box {
     position: relative;
+
     // background: linear-gradient(rgba(255, 255, 255, 0) 75%, rgb(34, 34, 34));
     background-position: 50%;
     background-repeat: no-repeat;
@@ -1392,6 +1398,10 @@ export default {
     width: 100%;
     padding: 10px;
   }
+
+  >.mask {
+    background: rgba(0, 0, 0, 0.5);
+  }
 }
 
 .messages {

+ 35 - 14
src/views/chat/ChatPC.vue

@@ -7,7 +7,7 @@
           <div class="historyBox" v-for="(item, index) in allRecords" :key="index">
             <div class="top flex w-full cursor-pointer" @click="item.open = !item.open">
               <div class="photo">
-                <img class="object-cover" :src="baseApi + item.picture" alt="">
+                <img class="object-cover" :src="baseApi + item.picture" @error="$AIPohotoError" alt="">
               </div>
               <div class="info flex-1 ml-2 flex flex-col justify-around">
                 <div class="text-sm font-semibold">{{ item.characterName }}</div>
@@ -71,7 +71,8 @@
             </div>
             <div class="flex">
               <span class="chatInfo_photo">
-                <img class="w-16 h-16 rounded-full overflow-hidden object-cover" :src="baseApi + info.picture">
+                <img class="w-16 h-16 rounded-full overflow-hidden object-cover" :src="baseApi + info.picture"
+                  @error="$AIPohotoError">
               </span>
               <div class="w-0 flex-1 ml-2">
                 <div class="text-xl font-medium">{{ info.characterName }}</div>
@@ -189,7 +190,7 @@
           <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" :class="sceneId && 'mask'">
           <div class="chatBoxTitle absolute top-0">
             <div>
               {{ info.characterName }}
@@ -245,7 +246,8 @@
               <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"
+                    @error="$AIPohotoError" />
                 </div>
                 <div class="messageRight">
                   <div v-show="!item.edit" :ref="`message${index}`"
@@ -259,7 +261,7 @@
                     <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>
+                    <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)">
@@ -291,7 +293,8 @@
               <!-- 用户发送的信息 -->
               <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"
+                    @error="$userPohotoError" />
                 </div>
                 <div class="messageRight">
                   <div :ref="`message${index}`" v-show="!item.edit"
@@ -412,6 +415,8 @@ export default {
   },
   data() {
     return {
+      // 对话请求超时参数
+      timeOut: null,
       // 聊天等待
       chatLoading: false,
       // 是否全屏
@@ -1178,6 +1183,14 @@ export default {
 
         //txt就是一个一个的字 然后添加到页面上就可以了
         const txt = decoder.decode(value).split('data:')
+        // 超时处理
+        if (this.timeOut) {
+          clearTimeout(this.timeOut)
+          this.timeOut = setTimeout(() => {
+            this.returnMessage[this.returnMessage.length - 1].content = 'AI智能累得打起了小盹儿,咱们让他缓一缓,再来试试!'
+            this.chatLoading = false
+          }, 10000)
+        }
         // const txt = decoder.decode(value)
         this.addMessage(txt)
         // let data = JSON.parse(txt).message.content
@@ -1318,11 +1331,12 @@ export default {
         return
       }
       this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
-      console.log(this.audioUrl, 'this.audioUrl');
-      setTimeout(() => {
 
-        if (this.audioUrl) {
+      setTimeout(() => {
+        if (this.audioUrl && this.audioUrl != 'false') {
           this.$refs.audio.play()
+        } else {
+          this.audioClose()
         }
       }, 1000)
     },
@@ -1418,17 +1432,20 @@ export default {
         }
         this.audioUrl = this.audioUrlArr[this.audioUrlArrIndx].voiceAddress
         setTimeout(() => {
-          if (this.audioUrl) {
+          if (this.audioUrl && this.audioUrl != 'false') {
             this.$refs.audio.play()
+          } else {
+            this.audioClose()
           }
         }, 100)
       } else {
-        this.audioUrlArrIndx = []
-        this.audioUrlArrIndx = 0
-        console.log('播放结束');
-        this.audioPlayIndex = null
+        this.audioClose()
       }
     },
+    audioClose() {
+      this.audioUrlArrIndx = 0
+      this.audioPlayIndex = null
+    },
     ChangeSettingValue1(value) {
       console.log(value, 'value');
       if (value) {
@@ -1597,6 +1614,10 @@ export default {
       align-items: center;
     }
   }
+
+  >.mask {
+    background: rgba(0, 0, 0, 0.5);
+  }
 }
 
 .contentFull {

+ 38 - 35
src/views/components/NavMenu.vue

@@ -1,15 +1,18 @@
 <template>
   <div class="nav-menu h-full bg-white" style="width: 72px">
     <div>
-      <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" class="mb-1.5">
-        <g clip-path="url(#clip0_11765_56929)">
-          <path d="M47.8504 31.9362L47.8139 31.8724L47.8112 31.8684L46.4692 29.5327L46.1376 28.9551L43.1691 23.7904L42.5349 22.6857L41.2428 20.5195L40.1181 18.6344C39.3285 17.3117 37.8522 16.4941 36.2523 16.4941H26.0108C23.9317 16.4941 22.1304 17.8641 21.6751 19.7923L21.4411 20.7814L21.1081 22.1872L21.0543 22.4145L20.6369 24.2723L20.3524 25.6103L16.0346 45.9259L16.0226 45.9797C16.0219 45.9824 16.0219 45.9844 16.0213 45.987C16.0073 46.0628 16 46.1413 16 46.2217C16 46.9309 16.575 47.5059 17.2842 47.5059H24.4335C25.0544 47.5059 25.5721 47.0658 25.6918 46.4809L30.2967 24.8174L30.5899 23.4368L30.9574 21.708C31.0179 21.4235 31.2692 21.2201 31.5603 21.2201C31.7817 21.2201 31.985 21.3377 32.0954 21.5292L33.0718 23.2288L33.8229 24.5362L36.3613 28.9551L38.035 31.8691C38.0457 31.887 38.0563 31.905 38.0663 31.9229C38.1653 32.105 38.2211 32.3137 38.2211 32.5351C38.2211 33.2443 37.6462 33.8193 36.937 33.8193H30.9408C30.2316 33.8193 29.6566 34.3942 29.6566 35.1034C29.6566 35.3254 29.7125 35.5335 29.8115 35.7156L29.8428 35.7695L36.1998 46.8339L36.2311 46.8877C36.4564 47.2579 36.8638 47.5059 37.3291 47.5059H44.1435C44.8527 47.5059 45.4277 46.9309 45.4277 46.2217C45.4277 46.003 45.3732 45.7976 45.2768 45.6175L45.2402 45.553L41.4296 38.9214L39.6196 35.7695C39.6083 35.7522 39.5984 35.7342 39.5884 35.7156C39.4894 35.5342 39.4335 35.3254 39.4335 35.1034C39.4335 34.4088 39.9845 33.8432 40.6738 33.8206H46.7816C47.4603 33.7867 48 33.2257 48 32.5384C48 32.3204 47.9462 32.1157 47.8504 31.9362Z" fill="#7262F6"></path>
-        </g>
-        <defs>
-          <clipPath id="clip0_11765_56929">
-            <rect width="32" height="31.0117" fill="white" transform="translate(16 16.4941)"></rect>
-          </clipPath>
-        </defs>
+      <img width="40" height="40" style="margin: 0 auto; margin-bottom: 20px;" src="@/assets/images/logo.png" alt="">
+      <!-- <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" class="mb-1.5"> -->
+      <g clip-path="url(#clip0_11765_56929)">
+        <path
+          d="M47.8504 31.9362L47.8139 31.8724L47.8112 31.8684L46.4692 29.5327L46.1376 28.9551L43.1691 23.7904L42.5349 22.6857L41.2428 20.5195L40.1181 18.6344C39.3285 17.3117 37.8522 16.4941 36.2523 16.4941H26.0108C23.9317 16.4941 22.1304 17.8641 21.6751 19.7923L21.4411 20.7814L21.1081 22.1872L21.0543 22.4145L20.6369 24.2723L20.3524 25.6103L16.0346 45.9259L16.0226 45.9797C16.0219 45.9824 16.0219 45.9844 16.0213 45.987C16.0073 46.0628 16 46.1413 16 46.2217C16 46.9309 16.575 47.5059 17.2842 47.5059H24.4335C25.0544 47.5059 25.5721 47.0658 25.6918 46.4809L30.2967 24.8174L30.5899 23.4368L30.9574 21.708C31.0179 21.4235 31.2692 21.2201 31.5603 21.2201C31.7817 21.2201 31.985 21.3377 32.0954 21.5292L33.0718 23.2288L33.8229 24.5362L36.3613 28.9551L38.035 31.8691C38.0457 31.887 38.0563 31.905 38.0663 31.9229C38.1653 32.105 38.2211 32.3137 38.2211 32.5351C38.2211 33.2443 37.6462 33.8193 36.937 33.8193H30.9408C30.2316 33.8193 29.6566 34.3942 29.6566 35.1034C29.6566 35.3254 29.7125 35.5335 29.8115 35.7156L29.8428 35.7695L36.1998 46.8339L36.2311 46.8877C36.4564 47.2579 36.8638 47.5059 37.3291 47.5059H44.1435C44.8527 47.5059 45.4277 46.9309 45.4277 46.2217C45.4277 46.003 45.3732 45.7976 45.2768 45.6175L45.2402 45.553L41.4296 38.9214L39.6196 35.7695C39.6083 35.7522 39.5984 35.7342 39.5884 35.7156C39.4894 35.5342 39.4335 35.3254 39.4335 35.1034C39.4335 34.4088 39.9845 33.8432 40.6738 33.8206H46.7816C47.4603 33.7867 48 33.2257 48 32.5384C48 32.3204 47.9462 32.1157 47.8504 31.9362Z"
+          fill="#7262F6"></path>
+      </g>
+      <defs>
+        <clipPath id="clip0_11765_56929">
+          <rect width="32" height="31.0117" fill="white" transform="translate(16 16.4941)"></rect>
+        </clipPath>
+      </defs>
       </svg>
       <div class="menus">
         <div class="menu " :class="$route.path == '/home' && 'menuActive'" @click="routeTo('/home')">
@@ -20,36 +23,29 @@
           <i class="icon el-icon-chat-line-round"></i>
           <div class="text">对话</div>
         </div>
-        <el-popover
-          placement="right"
-          width="160"
-          v-model="popoverVisible">
+        <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 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>
-          <div slot="reference" v-show="haveToken" class="menu" 
-            :class="($route.path == '/create' || $route.path == '/createScene') && 'menuActive'"
-          >
+          <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')">
+        <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>
@@ -57,14 +53,14 @@
     </div>
     <div class="flex flex-col justify-center items-center cursor-pointer">
       <el-tooltip class="item" effect="dark" content="会员" placement="right">
-        <v-icon name="crown" class="my-2" scale="1.5"/>
+        <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="$store.state.user.avatar" alt="">
+          <img class="img" :src="$store.state.user.avatar" alt="" @error="$userPohotoError">
         </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>
@@ -85,7 +81,7 @@ export default {
     return {
       popoverVisible: false,
       haveToken: false,
-      getToken, 
+      getToken,
     }
   },
   created() {
@@ -100,7 +96,7 @@ export default {
     }
   },
   watch: {
-    '$store.state.user.token': function(newVal, oldVal) {
+    '$store.state.user.token': function (newVal, oldVal) {
       console.log(newVal, '登录状态变化');
       if (newVal) {
         this.haveToken = true
@@ -116,7 +112,7 @@ export default {
       } else {
         this.showLogin()
       }
-      
+
     },
     routeTo(url) {
       this.$router.push(url)
@@ -145,25 +141,30 @@ export default {
     display: flex;
     flex-direction: column;
     cursor: pointer;
+
     .menu {
       display: flex;
       flex-direction: column;
       align-items: center;
       margin: 10px 0;
+
       .icon {
         font-size: 26px;
       }
     }
+
     .menuActive {
       color: var(--bg-color1);
     }
   }
+
   .photo {
     width: 30px;
     height: 30px;
     border-radius: 50%;
     background: var(--bg-color1);
     border: solid 1px #e5e7eb;
+
     .img {
       width: 100%;
       height: 100%;
@@ -171,9 +172,11 @@ export default {
     }
   }
 }
+
 .loginTip {
   box-shadow: 1px 1px 4px #bfbfbf;
 }
+
 .submenu:hover {
   color: #fff;
   background: var(--bg-color1);

+ 29 - 29
src/views/components/NavMenu_H5.vue

@@ -9,31 +9,23 @@
         <i class="icon el-icon-chat-line-round"></i>
         <div class="text">对话</div>
       </div>
-      <el-popover
-        placement="top"
-        width="160"
-        v-model="popoverVisible">
+      <el-popover placement="top" 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>
-        <div slot="reference" class="menu p-2 rounded-full bgColor1" 
-          :class="($route.path == '/create' || $route.path == '/createScene') && 'menuActive'"
-        >
+        <div slot="reference" class="menu p-2 rounded-full bgColor1" style="height: 42px; width: 42px;"
+          :class="($route.path == '/create' || $route.path == '/createScene') && 'menuActive'">
           <i class="icon el-icon-plus text-white"></i>
           <!-- <div class="text">创建</div> -->
         </div>
@@ -66,10 +58,10 @@ export default {
     return {
       docmHeight: document.documentElement.clientHeight,  //默认屏幕高度
       showHeight: document.documentElement.clientHeight,   //实时屏幕高度
-      hideshow:true,  //显示或者隐藏footer
+      hideshow: true,  //显示或者隐藏footer
       popoverVisible: false,
       haveToken: false,
-      getToken, 
+      getToken,
     }
   },
   created() {
@@ -83,7 +75,7 @@ export default {
     })
   },
   watch: {
-    '$store.state.user.token': function(newVal, oldVal) {
+    '$store.state.user.token': function (newVal, oldVal) {
       console.log(newVal, '登录状态变化');
       if (newVal) {
         this.haveToken = true
@@ -91,11 +83,11 @@ export default {
         this.haveToken = false
       }
     },
-    showHeight:function() {
-      if(this.docmHeight > this.showHeight){
-        this.hideshow=false
-      }else{
-        this.hideshow=true
+    showHeight: function () {
+      if (this.docmHeight > this.showHeight) {
+        this.hideshow = false
+      } else {
+        this.hideshow = true
       }
     }
   },
@@ -106,7 +98,7 @@ export default {
       } else {
         this.showLogin()
       }
-      
+
     },
     routeTo(url) {
       this.$router.push(url)
@@ -120,7 +112,7 @@ export default {
 
 <style lang="scss" scoped>
 .nav-menu {
-  position: absolute;
+  position: fixed;
   bottom: 0;
   height: 60px;
   font-size: 14px;
@@ -138,25 +130,31 @@ export default {
     width: 100%;
     justify-content: space-around;
     align-items: center;
+
     .menu {
       display: flex;
       flex-direction: column;
       align-items: center;
+      width: 56px;
+
       // margin: 10px 0;
       .icon {
         font-size: 26px;
       }
     }
+
     .menuActive {
       color: var(--bg-color1);
     }
   }
+
   .photo {
     width: 30px;
     height: 30px;
     border-radius: 50%;
     background: var(--bg-color1);
     border: solid 1px #e5e7eb;
+
     .img {
       width: 100%;
       height: 100%;
@@ -164,9 +162,11 @@ export default {
     }
   }
 }
+
 .loginTip {
   box-shadow: 1px 1px 4px #bfbfbf;
 }
+
 .submenu:hover {
   color: #fff;
   background: var(--bg-color1);

+ 16 - 10
src/views/create/createH5.vue

@@ -1,7 +1,7 @@
 <template>
-  <div class="create bg-white" style="min-height: 100vh;">
+  <div class="create bg-white" style="height: 100vh; height: calc(var(--vh, 1vh) * 100);">
     <TitleH5 titleName="创建角色" />
-    <div class=" mx-auto">
+    <div class=" mx-auto h-full">
       <div class="container containerH5 mx-auto p-4 ">
         <div class="flex flex-col h-full w-full">
           <el-form :model="form" :rules="rules" ref="form" label-position="top" label-width="60px" class="form">
@@ -109,7 +109,7 @@
 
 <script>
 import TitleH5 from "@/views/components/titleH5.vue"
-import { detailApi } from "@/api/detail.js"
+import { detailUserApi } from "@/api/detail.js"
 import { addCharacterApi, personalityListApi, updateCharacterApi } from "@/api/create.js"
 import {
   getModelListApi,
@@ -126,6 +126,7 @@ export default {
       personalityList: [],
       modelList: [],
       form: {
+        modelId: null,
         characterName: "",// 人物名称
         characterIntroduction: "", //人物角色描述
         characterPersonalityTags: "", //人物性格标签
@@ -161,6 +162,9 @@ export default {
         type: [
           { required: true, message: "请选择类型", trigger: "change" },
         ],
+        characterPersonalityTags: [
+          { required: true, message: "请选择性格标签", trigger: "change" },
+        ],
       }
     }
   },
@@ -170,14 +174,16 @@ export default {
     this.getModelList()
     // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');
     if (this.$route.query.id) {
-      detailApi(this.$route.query.id).then(res => {
+      detailUserApi(this.$route.query.id).then(res => {
         console.log(res, '详情');
         let data = res.data
-        let characterPersonalityTags = data.characterPersonalityTags.split(',')
-        for (let i = 0; i < characterPersonalityTags.length; i++) {
-          characterPersonalityTags[i] = parseInt(characterPersonalityTags[i])
+        if (data.characterPersonalityTags) {
+          let characterPersonalityTags = data.characterPersonalityTags.split(',')
+          for (let i = 0; i < characterPersonalityTags.length; i++) {
+            characterPersonalityTags[i] = parseInt(characterPersonalityTags[i])
+          }
+          data.characterPersonalityTags = characterPersonalityTags
         }
-        data.characterPersonalityTags = characterPersonalityTags
         console.log(data, 'data');
         this.form = data
 
@@ -282,14 +288,14 @@ export default {
 
 <style lang="scss" scoped>
 .containerH5 {
-  height: calc(100vh - 40px - 60px);
+  height: calc(100% - 40px - 60px);
   overflow-y: auto;
   display: flex;
 }
 
 .bottom {
   // height: 80px;
-  margin-bottom: 20px;
+  // margin-bottom: 20px;
 }
 </style>
 <style scoped>

+ 14 - 3
src/views/create/createPC.vue

@@ -111,7 +111,7 @@
 <script>
 import { addCharacterApi, personalityListApi, updateCharacterApi } from "@/api/create.js"
 import { labelListApi } from "@/api/home.js"
-import { detailApi } from "@/api/detail.js"
+import { detailUserApi } from "@/api/detail.js"
 
 import {
   getModelListApi,
@@ -164,6 +164,9 @@ export default {
         modelId: [
           { required: true, message: "请选择模型", trigger: "change" },
         ],
+        characterPersonalityTags: [
+          { required: true, message: "请选择性格标签", trigger: "change" },
+        ],
       }
     }
   },
@@ -174,9 +177,17 @@ export default {
     this.getPersonalityList()
     console.log(this.$route.query.id, 'this.$route.query.id');
     if (this.$route.query.id) {
-      detailApi(this.$route.query.id).then(res => {
+      detailUserApi(this.$route.query.id).then(res => {
         console.log(res, '详情');
-        this.form = res.data
+        let data = res.data
+        if (data.characterPersonalityTags) {
+          let characterPersonalityTags = data.characterPersonalityTags.split(',')
+          for (let i = 0; i < characterPersonalityTags.length; i++) {
+            characterPersonalityTags[i] = parseInt(characterPersonalityTags[i])
+          }
+          data.characterPersonalityTags = characterPersonalityTags
+        }
+        this.form = data
       })
     }
     // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');

+ 94 - 89
src/views/create/createSceneH5.vue

@@ -1,105 +1,106 @@
 <template>
-  <div class=" w-full h-full app-pageContainer" style="overflow: hidden;">
-    <TitleH5 titleName="创建场景" />
+  <div class=" w-full app-pageContainer relative" style="overflow: hidden; height: calc(var(--vh, 1vh) * 100);">
+    <TitleH5 titleName=" 创建场景" />
     <!-- 第一步场景基本信息 -->
-    <div v-show="active == 1" class="px-6 pb-8 mx-auto overflow-y-auto w-full"
-      style="height: calc(100% - 49px - 80px - 60px);">
-      <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 class="overflow-y-auto" style="height: calc(100% - 49px);">
+      <div v-show="active == 1" class="px-6 pb-4 mx-auto  w-full">
+        <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>
-            <img v-else class="w-20 h-20 rounded-full cursor-pointer object-cover shadow" @click="showPopup1 = true"
-              :src="baseApi + character.picture" alt="">
+            <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="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.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 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>
-          <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 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>
-          <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 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>
-    <!-- 第二步背景 -->
-    <div v-show="active == 2" class="w-full relative" style="height: calc(100% - 49px - 80px - 60px);">
-      <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="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-4 gap-1 gap-y-2">
-                <div v-for="(item, index) in uploadList" :key="index" @click="bgActive = index">
-                  <img class=" rounded object-cover cursor-pointer border" :class="bgActive === index ? 'bgActive' : ''"
-                    style="width: 120px; height: 90px;" :src="baseApi + item.url" alt="">
+      <!-- 第二步背景 -->
+      <div v-show="active == 2" class="w-full">
+        <img v-if="uploadList.length > 0" class=" w-full h-full object-cover" :src="baseApi + uploadList[bgActive].url"
+          alt="">
+        <div
+          class="absolute h-full 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">
+          <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-4 gap-1 gap-y-2">
+                  <div v-for="(item, index) in uploadList" :key="index" @click="bgActive = index">
+                    <img class=" rounded object-cover cursor-pointer border" :class="bgActive === index ? 'bgActive' : ''"
+                      style="width: 120px; height: 90px;" :src="baseApi + item.url" alt="">
+                  </div>
                 </div>
               </div>
-            </div>
-          </el-tab-pane>
-        </el-tabs>
+            </el-tab-pane>
+          </el-tabs>
+        </div>
       </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>
+      <div class="bottomA 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>
+        <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>
     </div>
     <!-- 选择角色对话框 -->
     <el-dialog class="dialog" title="选择角色" :visible.sync="showPopup1" fullscreen>
@@ -335,8 +336,12 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-.bottom {
-  height: 80px;
+.bottomA {
+  width: 100%;
+  height: 40px;
+  position: relative;
+  // bottom: 60px;
+  background: #fff;
 }
 
 .characterName {

+ 3 - 2
src/views/detail/indexH5.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="detail bg-gray-900 w-full overflow-hidden relative">
-    <img :src="baseApi + info.picture" class="bgImg absolute" />
+    <img :src="baseApi + info.picture" @error="$AIPohotoError" class="bgImg absolute" />
     <div class="topTool">
       <div class="tm_button rounded-full text-white" @click="goBack">
         <i class="el-icon-arrow-left"></i>
@@ -12,7 +12,8 @@
     <div class="content">
       <div class="info w-full px-4 text-white" style="height: 30%; margin-top: 60px;">
         <div class="flex pt-4">
-          <img class="w-16 h-16 rounded-full object-cover border-2 border-white mr-2" :src="baseApi + info.picture">
+          <img class="w-16 h-16 rounded-full object-cover border-2 border-white mr-2" :src="baseApi + info.picture"
+            @error="$AIPohotoError">
           <div class="flex flex-col text-white justify-center">
             <div class=" text-lg font-semibold">{{ info.characterName }}</div>
             <div class=" text-xs">Xchat No.{{ info.id }}</div>

+ 80 - 35
src/views/homeComponents/HomeH5.vue

@@ -8,12 +8,7 @@
       <div class="tabDiv flex px-4 overflow-scroll">
         <el-tabs v-model="tabsActive" @tab-click="tabsClick">
           <el-tab-pane label="全部" name="all"></el-tab-pane>
-          <el-tab-pane 
-            v-for="(item, index) in labelData" 
-            :key="index" 
-            :label="item.labelName" 
-            :name="`${item.id}`"
-          >
+          <el-tab-pane v-for="(item, index) in labelData" :key="index" :label="item.labelName" :name="`${item.id}`">
           </el-tab-pane>
         </el-tabs>
         <!-- <div class="w-30/12">
@@ -27,37 +22,30 @@
         </div> -->
       </div>
     </div>
-    <div class="lietRom flex-1 overflow-auto" 
-      v-infinite-scroll="load"
-      infinite-scroll-disabled="disabled"
-    >
+    <div class="lietRom flex-1 overflow-auto" v-infinite-scroll="load" infinite-scroll-disabled="disabled">
       <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">
-            <img :src="baseApi + item.picture" class="w-full img" />
+            <img :src="baseApi + item.picture" class="w-full img" @error="$AIPohotoError" />
           </div>
           <div class="p-2">
-            <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+            <h3 class="name text-lg font-bold">{{ item.characterName }}</h3>
             <p class="prologue text-sm">
               {{ item.prologue }}
             </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">
-                <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
+            <!-- <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">
                 {{ item2 }}
               </div>
-            </div>
+            </div> -->
           </div>
           <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-2 pb-2">
             <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>
+              <v-icon name="fire" scale="1" />
+              <span class="ml-1">{{ item.hotCount || 0 }}</span>
             </div>
           </div>
         </div>
@@ -79,7 +67,7 @@ import 'vue-awesome/icons/fire'
 export default {
   name: "HomePC",
   components: {
-    
+
   },
   data() {
     return {
@@ -107,7 +95,7 @@ export default {
     }
   },
   computed: {
-    disabled () {
+    disabled() {
       return this.loading || this.noMore
     }
   },
@@ -226,18 +214,21 @@ export default {
 <style scoped lang="scss">
 .home {
   font-size: 17.5px;
+
   blockquote {
     padding: 10px 20px;
     margin: 0 0 20px;
     font-size: 17.5px;
     border-left: 5px solid #eee;
   }
+
   hr {
     margin-top: 20px;
     margin-bottom: 20px;
     border: 0;
     border-top: 1px solid #eee;
   }
+
   .col-item {
     margin-bottom: 20px;
   }
@@ -247,7 +238,11 @@ export default {
     margin: 0;
   }
 
-  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: "open sans",
+  "Helvetica Neue",
+  Helvetica,
+  Arial,
+  sans-serif;
   font-size: 16px;
   // color: #676a6c;
   overflow-x: hidden;
@@ -279,17 +274,21 @@ export default {
     }
   }
 }
+
 .textButton {
   // color: #eee;
   margin-left: 5px;
 }
+
 .textButton:hover {
   color: #9333ea;
 }
+
 .labelButton {
   border: solid 1px #e6e6e6;
   background: var(--bg-color2);
 }
+
 .buttonBg1 {
   background: var(--bg-color1);
   color: #fff;
@@ -298,9 +297,11 @@ export default {
 .topActive {
   background: var(--bg-color1);
 }
+
 .tag {
   background: var(--bg-color2);
 }
+
 .box1 {
   border: 1px solid #ffffff4d;
   height: 30px;
@@ -309,94 +310,138 @@ export default {
   // width: 68px;
   font-size: 14px;
 }
+
 .box2 {
-  background: #ffffff0f; 
+  background: #ffffff0f;
   border: 1px solid #ffffff2e;
-  height: 380px;
+  height: 325px;
+
+  .name {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 1;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+  }
 }
+
 .box2:hover {
   border: solid 1px var(--bg-color1);
 }
+
 .img {
   height: 200px;
   object-fit: cover;
   object-position: top;
   transition: transform .2s
 }
+
 .img:hover {
   transform: scale(1.1);
 }
+
 .labels {
   max-height: 56px;
   overflow-y: auto;
 }
+
 .prologue {
-  overflow:hidden;
+  overflow: hidden;
   text-overflow: ellipsis;
   -webkit-line-clamp: 2;
   display: -webkit-box;
   -webkit-box-orient: vertical;
 }
+
 .historysBox {
   .historys {
     display: grid;
     grid-gap: 10px;
     grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
   }
-  .historys::-webkit-scrollbar { 
-    width: 0; /* 隐藏滚动条 */
+
+  .historys::-webkit-scrollbar {
+    width: 0;
+    /* 隐藏滚动条 */
   }
+
   .history {
     position: relative;
     overflow: hidden;
     justify-self: center;
+
     .historyImg {
       position: relative;
       object-fit: cover;
       object-position: top;
-      
+
     }
+
     .infoBg {
       background: rgba(0, 0, 0, 0.5);
       transition: bottom 0.2s;
       bottom: -6rem;
     }
   }
+
   .history:hover {
     .infoBg {
       bottom: 0;
     }
   }
 }
+
 .searchInput {
   background-color: var(--bg-color2);
   // border: 1px solid #b6b6b6;
 }
+
 .searchInput:focus {
   border: 1px solid #b6b6b6;
 }
 </style>
 <style scoped>
-.historysBox >>> .el-carousel__arrow {
+.historysBox>>>.el-carousel__arrow {
   background: var(--bg-color1);
 }
+
 .list {
   display: grid;
   grid-template-columns: 1fr 1fr;
   /* grid-auto-rows: minmax(280px, 280px); */
   grid-gap: 10px;
 }
+
 .lietRom {
   padding: 5px;
   padding-bottom: 60px;
 }
+
 .lietRom::-webkit-scrollbar {
   display: none;
 }
+
 .tabDiv {
   scrollbar-width: none;
 }
-.tabDiv >>> .el-tabs__header {
+
+.tabDiv>>>.el-tabs__header {
   margin-bottom: 0;
 }
+
+.tabDiv::-webkit-scrollbar,
+.tabDiv>>>.el-tabs__nav::-webkit-scrollbar {
+  display: none;
+  /* Chrome Safari */
+}
+
+.tabDiv,
+.tabDiv>>>.el-tabs__nav {
+  scrollbar-width: none;
+  /* firefox */
+  -ms-overflow-style: none;
+  /* IE 10+ */
+  overflow-x: auto;
+  overflow-y: hidden;
+}
 </style>

+ 61 - 48
src/views/homeComponents/HomePC.vue

@@ -6,50 +6,32 @@
       </div>
       <div class="flex">
         <div class="flex flex-wrap w-9/12">
-          <div 
-            @click="clickLabelAll"
-            :class="[
-              selectLabel.length == 0 && 'buttonBg1',
-              'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
-            ]">
+          <div @click="clickLabelAll" :class="[
+            selectLabel.length == 0 && 'buttonBg1',
+            'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
+          ]">
             全部
           </div>
-          <div
-            v-for="(item, index) in labelData"
-            :key="index"
-            :class="[
-              selectLabel.indexOf(item.id) != -1 && 'buttonBg1',
-              'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
-            ]" 
-            @click="clickLabel(item)"
-          >
-            {{ item.labelName }}({{item.num}})
+          <div v-for="(item, index) in labelData" :key="index" :class="[
+            selectLabel.indexOf(item.id) != -1 && 'buttonBg1',
+            'labelButton px-4 py-1 mx-1 mb-2 rounded-md flex items-center cursor-pointer text-gray-500'
+          ]" @click="clickLabel(item)">
+            {{ item.labelName }}({{ item.num }})
           </div>
         </div>
         <div class="w-30/12">
-          <input
-            type="text"
-            placeholder="搜索"
+          <input type="text" placeholder="搜索"
             class="searchInput mr-2 px-3 py-2 rounded-md w-full focus:border-gray-300 focus:outline-none"
-            v-model="searchName"
-            @keydown="Enterkey"
-          />
+            v-model="searchName" @keydown="Enterkey" />
         </div>
       </div>
     </div>
-    <div class="lietRom flex-1 overflow-auto" 
-      v-infinite-scroll="load"
-      infinite-scroll-disabled="disabled"
-    >
+    <div class="lietRom flex-1 overflow-auto" v-infinite-scroll="load" infinite-scroll-disabled="disabled">
       <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" style="height: 250px;">
-            <img :src="baseApi + item.picture" class="w-full img" />
+            <img :src="baseApi + item.picture" class="w-full img" @error="$AIPohotoError" />
           </div>
           <div class="p-2">
             <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
@@ -57,7 +39,8 @@
               {{ item.prologue }}
             </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>
@@ -66,8 +49,8 @@
           <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-3 pb-3">
             <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>
+              <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"/>
@@ -87,8 +70,8 @@
       <p class="w-full py-4 text-gray-400 text-center" v-if="loading">加载中...</p>
       <p class="w-full py-4 text-gray-400 text-center" v-if="noMore">没有更多了</p>
     </div>
-    
-    
+
+
     <!-- <div class="my-4 flex justify-center">
       <el-pagination
         background
@@ -139,7 +122,7 @@ export default {
     }
   },
   computed: {
-    disabled () {
+    disabled() {
       return this.loading || this.noMore
     }
   },
@@ -257,18 +240,21 @@ export default {
 <style scoped lang="scss">
 .home {
   font-size: 17.5px;
+
   blockquote {
     padding: 10px 20px;
     margin: 0 0 20px;
     font-size: 17.5px;
     border-left: 5px solid #eee;
   }
+
   hr {
     margin-top: 20px;
     margin-bottom: 20px;
     border: 0;
     border-top: 1px solid #eee;
   }
+
   .col-item {
     margin-bottom: 20px;
   }
@@ -278,7 +264,11 @@ export default {
     margin: 0;
   }
 
-  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: "open sans",
+  "Helvetica Neue",
+  Helvetica,
+  Arial,
+  sans-serif;
   font-size: 16px;
   // color: #676a6c;
   overflow-x: hidden;
@@ -310,17 +300,21 @@ export default {
     }
   }
 }
+
 .textButton {
   // color: #eee;
   margin-left: 5px;
 }
+
 .textButton:hover {
   color: #9333ea;
 }
+
 .labelButton {
   border: solid 1px #e6e6e6;
   background: var(--bg-color2);
 }
+
 .buttonBg1 {
   background: var(--bg-color1);
   color: #fff;
@@ -329,9 +323,11 @@ export default {
 .topActive {
   background: var(--bg-color1);
 }
+
 .tag {
   background: var(--bg-color2);
 }
+
 .box1 {
   border: 1px solid #ffffff4d;
   height: 30px;
@@ -340,88 +336,105 @@ export default {
   width: 68px;
   font-size: 14px;
 }
+
 .box2 {
-  background: #ffffff0f; 
+  background: #ffffff0f;
   border: 1px solid #ffffff2e;
   height: 35vw;
   height: 480px;
 }
+
 .box2:hover {
   border: solid 1px var(--bg-color1);
 }
+
 .img {
   height: 250px;
   object-fit: cover;
   object-position: top;
   transition: transform .2s
 }
+
 .img:hover {
   transform: scale(1.1);
 }
+
 .labels {
   max-height: 84px;
   overflow-y: auto;
 }
+
 .prologue {
-  overflow:hidden;
+  overflow: hidden;
   text-overflow: ellipsis;
   -webkit-line-clamp: 4;
   display: -webkit-box;
   -webkit-box-orient: vertical;
 }
+
 .historysBox {
   .historys {
     display: grid;
     grid-gap: 10px;
     grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
   }
-  .historys::-webkit-scrollbar { 
-    width: 0; /* 隐藏滚动条 */
+
+  .historys::-webkit-scrollbar {
+    width: 0;
+    /* 隐藏滚动条 */
   }
+
   .history {
     position: relative;
     overflow: hidden;
     justify-self: center;
+
     .historyImg {
       position: relative;
       object-fit: cover;
       object-position: top;
-      
+
     }
+
     .infoBg {
       background: rgba(0, 0, 0, 0.5);
       transition: bottom 0.2s;
       bottom: -6rem;
     }
   }
+
   .history:hover {
     .infoBg {
       bottom: 0;
     }
   }
 }
+
 .searchInput {
   background-color: var(--bg-color2);
   // border: 1px solid #b6b6b6;
 }
+
 .searchInput:focus {
   border: 1px solid #b6b6b6;
 }
 </style>
 <style scoped>
-.historysBox >>> .el-carousel__arrow {
+.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;
 }
+
 .lietRom {
   padding: 5px;
 }
+
 .lietRom::-webkit-scrollbar {
   display: none;
-}
-</style>
+}</style>

+ 13 - 6
src/views/homeComponents/searchH5.vue

@@ -10,20 +10,19 @@
         <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">
-            <img :src="baseApi + item.picture" class="w-full img" />
+            <img :src="baseApi + item.picture" class="w-full img" @error="$AIPohotoError" />
           </div>
           <div class="p-2">
-            <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+            <h3 class="name text-lg font-bold">{{ item.characterName }}</h3>
             <p class="prologue text-sm">
               {{ item.prologue }}
             </p>
-            <div class="labels flex my-1 flex-wrap">
+            <!-- <div class="labels flex my-1 flex-wrap">
               <div v-for="(item2, index2) in item.labelArr" :key="index2"
                 class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs text-gray-500">
-                <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
                 {{ item2 }}
               </div>
-            </div>
+            </div> -->
           </div>
           <div class="absolute w-full bottom-0 flex items-center justify-between mt-3 px-2 pb-2">
             <div></div>
@@ -121,7 +120,15 @@ export default {
 .box2 {
   background: #ffffff0f;
   border: 1px solid #ffffff2e;
-  height: 380px;
+  height: 325px;
+
+  .name {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 1;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+  }
 }
 
 .box2:hover {

+ 24 - 6
src/views/profile/profileH5.vue

@@ -12,16 +12,17 @@
         <div v-for="(item, index) in characterList" :key="index"
           class="box2 relative rounded-lg overflow-hidden shadow-lg cursor-pointer" @click="clickShowPopup(item)">
           <div class="w-full overflow-hidden">
-            <img :src="baseApi + item.picture" class="w-full img" />
+            <!-- <div v-if="item.type == 0" class="type2">审核中...</div> -->
+            <img :src="baseApi + item.picture" class="w-full img" @error="$AIPohotoError" />
           </div>
           <div class="p-2">
             <h3 class="text-lg font-bold flex items-center">
-              <div style="max-width: calc(100% - 18px);">{{ item.name }}</div>
+              <div class="name" style="max-width: calc(100% - 18px);">{{ item.name }}</div>
               <i v-if="item.scene == 1" class="el-icon-video-camera-solid"></i>
               <i v-if="item.scene == 0" class="el-icon-user-solid"></i>
             </h3>
             <p class="prologue text-sm">
-              {{ item.description }}
+              {{ item.prologue }}
             </p>
             <div class="labels flex my-1 flex-wrap">
               <div v-for="(item2, index2) in item.labelArr" :key="index2"
@@ -74,7 +75,7 @@ export default {
       selectObj: {},
       query: {
         pageSize: 10,
-        pageNum: 2,
+        pageNum: 1,
         type: 0
       },
       total: 0,
@@ -116,7 +117,6 @@ export default {
         if (res.rows.length == 0) {
           this.noMore = true
         }
-        // this.characterList = res.rows
         this.characterList = [...this.characterList, ...res.rows]
         if (this.characterList.length >= res.total) {
           this.noMore = true
@@ -292,7 +292,15 @@ export default {
 .box2 {
   background: #ffffff0f;
   border: 1px solid #ffffff2e;
-  height: 380px;
+  height: 325px;
+
+  .name {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 1;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+  }
 }
 
 .box2:hover {
@@ -340,4 +348,14 @@ export default {
   padding: 0;
   text-align: center;
 }
+
+.type2 {
+  padding: 2px 4px;
+  background: rgba(0, 0, 0, 0.4);
+  color: #fff;
+  position: absolute;
+  top: 0;
+  right: 0;
+  font-size: 12px;
+}
 </style>

+ 74 - 41
src/views/profile/profilePC.vue

@@ -41,11 +41,11 @@
       <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)">
+            :class="query.type == 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)">
+            :class="query.type == 1 && 'buttonBg1'" @click="tabChange(1)">
             <i class="el-icon-lock"></i>
             非公开
           </div>
@@ -78,36 +78,40 @@
 
         </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 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">
-              <i v-if="item.scene == 1" class="el-icon-video-camera"></i>
-              {{ item.name }}
-            </h3>
-            <p class="prologue text-sm">
-              {{ item.description }}
-            </p>
+      <div class="lietRom flex-1 overflow-auto" v-infinite-scroll="load" infinite-scroll-disabled="disabled">
+        <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 h-3/5">
+              <!-- <div v-if="item.type == 0" class="type2">审核中...</div> -->
+              <img class="w-full img h-full" :src="baseApi + item.picture" @error="$AIPohotoError" />
+            </div>
+            <div class="p-2">
+              <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 }}
+              </p>
 
-            <div class="labels flex my-1 flex-wrap">
+              <!-- <div class="labels flex my-1 flex-wrap">
               <div v-for="(item2, index2) in item.labelArr" :key="index2"
                 class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs text-gray-500">
-                <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
                 {{ item2 }}
               </div>
+            </div> -->
             </div>
-          </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>
+            <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>
+              </div>
             </div>
           </div>
         </div>
+        <p class="w-full py-4 text-gray-400 text-center" v-if="loading">加载中...</p>
+        <p class="w-full py-4 text-gray-400 text-center" v-if="noMore">没有更多了</p>
       </div>
     </div>
     <el-dialog title="提示" :visible.sync="dialogVisible" width="500px">
@@ -152,6 +156,14 @@ import 'vue-awesome/icons/fire'
 export default {
   data() {
     return {
+      query: {
+        pageSize: 10,
+        pageNum: 1,
+        type: 0
+      },
+      total: 0,
+      loading: false,
+      noMore: false,
       userInfo: {},
       popoverVisible: false,
       dialogVisible: false,
@@ -160,6 +172,11 @@ export default {
       characterList: []
     }
   },
+  computed: {
+    disabled() {
+      return this.loading || this.noMore
+    }
+  },
   mounted() {
     this.getUserInfo()
     this.getCharacterList()
@@ -291,33 +308,39 @@ export default {
       }
     },
     tabChange(index) {
-      this.active = index
+      this.query.pageNum = 1
+      this.characterList = []
+      this.query.type = index
+      this.getCharacterList()
+    },
+    load() {
+      this.query.pageNum += 1
       this.getCharacterList()
     },
     getCharacterList(query) {
-      let params = {
-        pageSize: 20,
-        pageNum: 1,
-        type: this.active
-      }
+      let type = this.active
+      // if (type == 0) {
+      //   type = '0,2'
+      // }
+      let params = this.query
       if (query) {
         params = {
           ...params,
-          ...query
+          ...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
+        if (res.rows.length == 0) {
+          this.noMore = true
+        }
+        this.characterList = [...this.characterList, ...res.rows]
+        if (this.characterList.length >= res.total) {
+          this.noMore = true
+        }
+        this.total = res.total
+        this.loading = false
       })
     },
     sortByTime(attr, rev) {
@@ -386,7 +409,7 @@ export default {
 
 .bg {
   background-color: var(--bg-color1);
-  background-image: url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png);
+  background-image: url(~@/assets/images/userBg.png);
   background-repeat: no-repeat;
   background-size: 100% 100%;
 }
@@ -398,4 +421,14 @@ export default {
   display: -webkit-box;
   -webkit-box-orient: vertical;
 }
+
+.type2 {
+  padding: 2px 4px;
+  background: rgba(0, 0, 0, 0.4);
+  color: #fff;
+  position: absolute;
+  top: 0;
+  right: 0;
+  font-size: 12px;
+}
 </style>

+ 5 - 4
src/views/user/componentH5.vue

@@ -66,12 +66,13 @@ export default {
 <style lang="scss" scoped>
 .content {
   width: 100%;
-  height: calc(100% - 30px - 40px - 5px);
-  padding: 10px 15px;
+  height: calc(100% - 30px - 40px - 6px);
+  // display: flex;
+  overflow-y: auto;
 
   >div {
-    padding: 10px !important;
-    border: solid 1px #ccc;
+    padding: 2px !important;
+    // border: solid 1px #ccc;
     border-radius: 20px;
     height: calc(100% - 20px);
     overflow-y: auto;

+ 15 - 42
src/views/user/components/consume.vue

@@ -5,7 +5,7 @@
         当前余额:<span class=" text-indigo-600">¥{{ balance || 0 }}</span>
       </div>
     </div>
-    
+
     <div class=" w-full rounded-xl w-full overflow-hidden">
       <div class="p-6 bg-white form">
         <div class=" text-lg mb-4">消费明细</div>
@@ -16,14 +16,8 @@
             </el-select>
           </el-form-item>
           <el-form-item label="时间范围">
-            <el-date-picker
-              v-model="times"
-              value-format="yyyy-MM-dd HH:mm:ss"
-              type="datetimerange"
-              range-separator="至"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
-              align="right">
+            <el-date-picker v-model="times" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="至"
+              start-placeholder="开始日期" end-placeholder="结束日期" align="right">
             </el-date-picker>
           </el-form-item>
           <el-form-item>
@@ -31,28 +25,14 @@
             <el-button @click="reset">重置</el-button>
           </el-form-item>
         </el-form>
-        <el-table
-          :data="tableData"
-          style="width: 100%"
-          height="540"
-        >
-          <el-table-column
-            prop="createTime"
-            label="时间"
-            width="180">
+        <el-table :data="tableData" style="width: 100%" height="540">
+          <el-table-column prop="createTime" label="时间" width="180">
           </el-table-column>
-          <el-table-column
-            prop="modelName"
-            label="模型"
-          >
+          <el-table-column prop="modelName" label="模型">
           </el-table-column>
-          <el-table-column
-            prop="consumeToken"
-            label="tokens">
+          <el-table-column prop="consumeToken" label="tokens">
           </el-table-column>
-          <el-table-column
-            prop="consumeFee"
-            label="金额">
+          <el-table-column prop="consumeFee" label="金额">
           </el-table-column>
           <!-- <el-table-column
             prop="afterFee"
@@ -60,12 +40,7 @@
           </el-table-column> -->
         </el-table>
         <div class="w-full pt-4 flex justify-center">
-          <el-pagination
-            background
-            layout="prev, pager, next"
-            :total="total"
-            @current-change="currentChange"
-          >
+          <el-pagination background layout="prev, pager, next" :total="total" @current-change="currentChange">
           </el-pagination>
         </div>
       </div>
@@ -126,7 +101,7 @@ export default {
       this.queryRecord()
     },
     search() {
-      if(this.times.length > 0) {
+      if (this.times.length > 0) {
         this.params.startTime = this.times[0]
         this.params.endTime = this.times[1]
       } else {
@@ -142,16 +117,14 @@ export default {
         this.total = res.total
       })
     }
-    
+
   }
 }
 </script>
 
 <style lang="scss" scoped>
-  .top {
-    background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png) center center / cover no-repeat;
-  }
+.top {
+  background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(~@/assets/images/userBg.png) center center / cover no-repeat;
+}
 </style>
-<style scoped>
-
-</style>
+<style scoped></style>

+ 15 - 31
src/views/user/components/invite.vue

@@ -2,41 +2,27 @@
   <div class="user-info py-10 px-20 w-full h-full overflow-auto">
     <div class=" w-full rounded-xl w-full p-4 bg-white mb-4">
       <div class=" text-lg ">
-        每邀请一个用户,平台奖励:<i class="el-icon-coin text-yellow-500"></i> <span class=" text-yellow-500">{{ inviteUserBalance }}</span>
+        每邀请一个用户,平台奖励:<i class="el-icon-coin text-yellow-500"></i> <span class=" text-yellow-500">{{ inviteUserBalance
+        }}</span>
       </div>
       <div class="text-sm flex items-center">
         邀请链接:<span class=" text-indigo-600" id="code">{{ url }}{{ code }}</span>
         <el-button class=" ml-2" size="mini" @click="copy">复制</el-button>
       </div>
-      
+
     </div>
-    
+
     <div class=" w-full rounded-xl w-full overflow-hidden">
       <div class="p-6 bg-white form">
         <div class=" text-lg mb-4">已邀请用户</div>
-        <el-table
-          :data="tableData"
-          style="width: 100%"
-          height="540"
-        >
-          <el-table-column
-            prop="createTime"
-            label="时间"
-          >
+        <el-table :data="tableData" style="width: 100%" height="540">
+          <el-table-column prop="createTime" label="时间">
           </el-table-column>
-          <el-table-column
-            prop="userId"
-            label="用户ID"
-          >
+          <el-table-column prop="userId" label="用户ID">
           </el-table-column>
         </el-table>
         <div class="w-full pt-4 flex justify-center">
-          <el-pagination
-            background
-            layout="prev, pager, next"
-            :total="total"
-            @current-change="currentChange"
-          >
+          <el-pagination background layout="prev, pager, next" :total="total" @current-change="currentChange">
           </el-pagination>
         </div>
       </div>
@@ -97,7 +83,7 @@ export default {
           document.execCommand('copy');
         }
         document.body.removeChild(textarea);
-        
+
         this.$message({
           message: '复制成功',
           type: 'success'
@@ -108,7 +94,7 @@ export default {
           type: 'error'
         });
       }
-      
+
     },
     reset() {
       this.params = {
@@ -131,7 +117,7 @@ export default {
       this.queryRecord()
     },
     search() {
-      if(this.times.length > 0) {
+      if (this.times.length > 0) {
         this.params.startTime = this.times[0]
         this.params.endTime = this.times[1]
       } else {
@@ -152,10 +138,8 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-  .top {
-    background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png) center center / cover no-repeat;
-  }
+.top {
+  background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(~@/assets/images/userBg.png) center center / cover no-repeat;
+}
 </style>
-<style scoped>
-
-</style>
+<style scoped></style>

+ 29 - 19
src/views/user/components/userInfo.vue

@@ -1,13 +1,13 @@
 <template>
-  <div class="user-info py-10 px-20 w-full h-full">
+  <div class="user-info py-10 px-20 w-full h-full" :class="$store.state.app.isMobile && 'mobile'">
     <div class="max-w-5xl mx-auto">
       <div class=" text-xl mb-4">用户信息</div>
       <div class="  rounded-xl w-full overflow-hidden">
         <div class=" w-full h-52 top flex items-end relative overflow-hidden">
           <img class=" absolute object-cover w-full h-full" v-if="userInfo.cover" :src="baseApi + userInfo.cover" alt="">
           <div class="p-6 flex relative">
-            <div class="w-20 h-20 border-2 border-gray-50 rounded-full">
-              <img class="w-full h-full rounded-full" :src="$store.state.user.avatar" alt="">
+            <div class="w-20 h-20 border-2 border-gray-50 rounded-full userPhoto">
+              <img class="w-full h-full rounded-full" :src="$store.state.user.avatar" @error="$userPohotoError">
             </div>
             <div class=" flex flex-col ml-4 justify-center">
               <div class=" text-2xl text-white">{{ userInfo.userName }}</div>
@@ -26,7 +26,8 @@
           </div>
           <div class="flex justify-between border-b border-gray-200 py-6">
             <div class="w-52">个人简介</div>
-            <el-input @focus="showButton = true" v-model="form.selfIntroduction" type="textarea" placeholder="请输入内容" maxlength="30" :autosize="{ minRows: 4, maxRows: 4}"></el-input>
+            <el-input @focus="showButton = true" v-model="form.selfIntroduction" type="textarea" placeholder="请输入内容"
+              maxlength="30" :autosize="{ minRows: 4, maxRows: 4 }"></el-input>
           </div>
           <div class="flex justify-between items-center border-b border-gray-200 py-6">
             <div class="w-52">更换头像</div>
@@ -46,13 +47,14 @@
         </div>
       </div>
     </div>
-    
-    <el-dialog :title="uploadTitle" :visible.sync="dialogVisible" width="30%">
+
+    <el-dialog :title="uploadTitle" :visible.sync="dialogVisible" width="30%"
+      :class="$store.state.app.isMobile && 'mobilePupup'">
       <div>
         <ImageUpload v-model="picture" class="imgUp" :limit="1" />
       </div>
       <div class="mt-4 flex justify-end">
-        <el-button  @click="dialogVisible = true">取消</el-button>
+        <el-button @click="dialogVisible = true">取消</el-button>
         <el-button type="primary" @click="imgConfirm">确认</el-button>
       </div>
     </el-dialog>
@@ -138,18 +140,26 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-  .top {
-    background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png) center center / cover no-repeat;
-  }
+.top {
+  background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(~@/assets/images/userBg.png) center center / cover no-repeat;
+}
 </style>
 <style scoped>
-  .form >>> .el-input__inner {
-    height: 50px;
-  }
-  .imgUp >>> .upload {
-    text-align: center;
-  }
-  .imgUp >>> .el-upload__tip {
-    text-align: center;
-  }
+.mobilePupup>>>.el-dialog {
+  width: 90% !important;
+}
+
+.mobile>>> {}
+
+.form>>>.el-input__inner {
+  height: 50px;
+}
+
+.imgUp>>>.upload {
+  text-align: center;
+}
+
+.imgUp>>>.el-upload__tip {
+  text-align: center;
+}
 </style>

+ 4 - 4
src/views/user/userH5.vue

@@ -4,8 +4,8 @@
       <img class=" absolute object-cover w-full h-full" v-if="userInfo.cover" :src="baseApi + userInfo.cover" alt="">
     </div>
     <div class="px-6 flex justify-between relative w-full">
-      <div class="w-20 h-20 border-2 bg-white border-gray-50 rounded-full" style="transform: translateY(-50%);">
-        <img class="w-full h-full rounded-full" :src="$store.state.user.avatar" alt="">
+      <div class="w-20 h-20 border-2 bg-white border-gray-50 rounded-full userPhoto" style="transform: translateY(-50%);">
+        <img class="w-full h-full rounded-full" :src="$store.state.user.avatar" alt="" @error="$userPohotoError">
       </div>
       <div
         class="text-gray-700 mt-4 w-20 h-8 text-sm flex justify-center items-center border border-gray-700 rounded-full"
@@ -34,7 +34,7 @@
     <van-cell class=" py-6 text-gray-700" title="邀请有礼" icon="friends-o" is-link @click="toPage('invite')" />
     <!-- <van-cell class=" py-6 text-gray-700" title="签到" is-link @click="toPage('signIn')" /> -->
     <van-cell class=" py-6 text-gray-700" title="意见反馈" icon="envelop-o" is-link @click="toPage('opinion')" />
-    <van-cell class=" py-6 text-gray-700" title="退出登录" is-link @click="toPage('logOut')">
+    <van-cell class=" py-6 text-gray-700" title="退出登录" is-link @click="menuClick('logOut')">
       <template #title>
         <i class="fa-solid fa-arrow-right-from-bracket mr-1"></i>
         <span>退出登录</span>
@@ -102,7 +102,7 @@ export default {
 
 <style lang="scss" scoped>
 .top {
-  background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(https://cdn-az.rochat.tech/avatar/131__c9103616-e103-11ee-bef2-66a40ff97e79.png) center center / cover no-repeat;
+  background: linear-gradient(rgba(0, 0, 0, 0) 23.28%, rgba(0, 0, 0, 0.72) 100%), url(~@/assets/images/userBg.png) center center / cover no-repeat;
 }
 
 .UserInfo {