瀏覽代碼

前端修改

chenrong 1 年之前
父節點
當前提交
2490506420

+ 8 - 1
src/App.vue

@@ -1,12 +1,14 @@
 <template>
   <div id="app">
     <router-view />
+    
   </div>
 </template>
 
 <script>
+
 export default  {
-  name:  'App',
+  name: 'App',
     metaInfo() {
         return {
             title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
@@ -17,3 +19,8 @@ export default  {
     }
 }
 </script>
+<style lang="scss" scoped>
+#app {
+  // padding-bottom: 50px;
+}
+</style>

+ 6 - 1
src/api/chat.js

@@ -1,4 +1,5 @@
 import request from '@/utils/request'
+import { getToken } from "@/utils/auth";
 
 // 设置终止信号
 // const controller = new AbortController();
@@ -20,9 +21,13 @@ import request from '@/utils/request'
 // }
 // ai对话
 export function streamChatWithWebApi(data) {
+  let headers = {}
+  if (getToken()) {
+    headers['UserToken'] = getToken()
+  }
   return fetch(`${process.env.VUE_APP_BASE_API}/system/chat/localAiStream`, {
     headers: {
-      isToken: false,
+      ...headers,
       returnData: true,
       'Content-Type': 'application/json'
     },

+ 10 - 0
src/api/create.js

@@ -0,0 +1,10 @@
+import request from '@/utils/request'
+
+// 获取标签列表
+export function addCharacterApi(data) {
+  return request({
+    url: `/appUser/addCharacter`,
+    method: 'post',
+    data
+  })
+}

+ 1 - 1
src/components/Editor/index.vue

@@ -62,7 +62,7 @@ export default {
     return {
       uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
       headers: {
-        Authorization: "Bearer " + getToken()
+        UserToken: getToken()
       },
       Quill: null,
       currentValue: "",

+ 1 - 1
src/components/FileUpload/index.vue

@@ -75,7 +75,7 @@ export default {
       baseUrl: process.env.VUE_APP_BASE_API,
       uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
       headers: {
-        Authorization: "Bearer " + getToken(),
+        UserToken: getToken(),
       },
       fileList: [],
     };

+ 23 - 22
src/components/ImageUpload/index.vue

@@ -1,25 +1,26 @@
 <template>
   <div class="component-upload-image">
-    <el-upload
-      multiple
-      :action="uploadImgUrl"
-      list-type="picture-card"
-      :on-success="handleUploadSuccess"
-      :before-upload="handleBeforeUpload"
-      :limit="limit"
-      :on-error="handleUploadError"
-      :on-exceed="handleExceed"
-      ref="imageUpload"
-      :on-remove="handleDelete"
-      :show-file-list="true"
-      :headers="headers"
-      :file-list="fileList"
-      :on-preview="handlePictureCardPreview"
-      :class="{ hide: this.fileList.length >= this.limit }"
-    >
-      <i class="el-icon-plus"></i>
-    </el-upload>
-
+    <div class="upload">
+      <el-upload
+        multiple
+        :action="uploadImgUrl"
+        list-type="picture-card"
+        :on-success="handleUploadSuccess"
+        :before-upload="handleBeforeUpload"
+        :limit="limit"
+        :on-error="handleUploadError"
+        :on-exceed="handleExceed"
+        ref="imageUpload"
+        :on-remove="handleDelete"
+        :show-file-list="true"
+        :headers="headers"
+        :file-list="fileList"
+        :on-preview="handlePictureCardPreview"
+        :class="{ hide: this.fileList.length >= this.limit }"
+      >
+        <i class="el-icon-plus"></i>
+      </el-upload>
+    </div>
     <!-- 上传提示 -->
     <div class="el-upload__tip" slot="tip" v-if="showTip">
       请上传
@@ -81,9 +82,9 @@ export default {
       dialogVisible: false,
       hideUpload: false,
       baseUrl: process.env.VUE_APP_BASE_API,
-      uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
+      uploadImgUrl: process.env.VUE_APP_BASE_API + "/system/app/upload", // 上传的图片服务器地址
       headers: {
-        Authorization: "Bearer " + getToken(),
+        UserToken: getToken(),
       },
       fileList: [],
     };

+ 3 - 3
src/plugins/download.js

@@ -19,7 +19,7 @@ export default {
       method: "get",
       url: url,
       responseType: "blob",
-      headers: { Authorization: "Bearer " + getToken() },
+      headers: { UserToken: getToken() },
     }).then(async (res) => {
       const isLogin = await blobValidate(res.data);
       if (isLogin) {
@@ -37,7 +37,7 @@ export default {
       method: "get",
       url: url,
       responseType: "blob",
-      headers: { Authorization: "Bearer " + getToken() },
+      headers: { UserToken: getToken() },
     }).then(async (res) => {
       const isLogin = await blobValidate(res.data);
       if (isLogin) {
@@ -54,7 +54,7 @@ export default {
       method: "get",
       url: url,
       responseType: "blob",
-      headers: { Authorization: "Bearer " + getToken() },
+      headers: { UserToken: getToken() },
     }).then(async (res) => {
       const isLogin = await blobValidate(res.data);
       if (isLogin) {

+ 5 - 0
src/router/index.js

@@ -67,6 +67,11 @@ export const constantRoutes = [
     component: () => import("@/views/create"),
     name: "Create",
   },
+  {
+    path: "/createH5",
+    component: () => import("@/views/create/indexH5"),
+    name: "CreateH5",
+  },
   {
     path: "/registerH5",
     component: () => import("@/views/loginAndRegister/registerH5"),

+ 2 - 1
src/utils/request.js

@@ -35,7 +35,8 @@ service.interceptors.request.use(
     // 是否需要防止数据重复提交
     const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
     if (getToken() && !isToken) {
-      config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
+      console.log(getToken(), '请求拦截')
+      config.headers["UserToken"] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
     }
     // get请求映射params参数
     if (config.method === "get" && config.params) {

+ 4 - 3
src/views/chat/index.vue

@@ -189,7 +189,7 @@ export default {
           } else {
             HistoryMessage = JSON.stringify(this.returnMessage)
           }
-          localStorage.setItem(`[${123},${this.info.id}]`, HistoryMessage);
+          localStorage.setItem(`['userId:${123}',${this.info.id}]`, HistoryMessage);
 
           clearInterval(messageInterval)
           return
@@ -224,7 +224,7 @@ export default {
         HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
       }
       let params = {
-        HistoryMessage: HistoryMessage || [],
+        historyMessage: HistoryMessage || [],
         characterId: this.info.id,
         prompt: this.content
       }
@@ -325,13 +325,14 @@ export default {
       border-radius: 16px 16px 16px 16px;
       height: 95%;
       position: relative;
-      min-width: 380px;
+      width: 380px;
 
       >img {
         border: 6px solid;
         border-image: linear-gradient(180deg, #b48733, #e8cf97, #b48733) 6 6;
         height: 99%;
         margin-right: 5px;
+        object-fit: cover;
       }
       >.aiInfo {
         background-color: #ffffff1a;

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

@@ -249,8 +249,9 @@ export default {
       while(1){
         const {done, value} = await reader.read()
         // console.log(done, 'done');
-        if(done){
-          console.log(value, 'value');
+        if(done){ 
+          const txt = decoder.decode(value).split('data:')
+          console.log(txt, '错误text');
           // if (typeof(value) == "undefined") {
           //   this.$message.error('错误')
           //   this.returnMessage.splice(this.returnMessage.length - 1, 1)
@@ -270,6 +271,7 @@ export default {
         
         //txt就是一个一个的字 然后添加到页面上就可以了
         const txt = decoder.decode(value).split('data:')
+        console.log(txt, 'txt');
         // const txt = decoder.decode(value)
         this.addMessage(txt)
         // let data = JSON.parse(txt).message.content

+ 201 - 67
src/views/create/index.vue

@@ -8,80 +8,84 @@
           <div class="text-xs text-gray-400">
             这些信息在机器人描述中供其他用户查看
           </div>
-          <div class="bg-gray-700 p-4 rounded-lg">
-            <div class="flex gap-4">
-              <div class="w-1/3">
-                <div class="bg-gray-600 p-4 rounded-lg flex items-center justify-center">
-                  <img
-                    src="https://placehold.co/150x150"
-                    alt="Placeholder profile image"
-                    class="rounded-full"
-                  />
-                </div>
-                <div class="text-sm mt-2 text-center">
-                  支持PNG、JPG、JPEG、WebP及GIF格式的图片大小不超过10MB。
-                </div>
-              </div>
-              <div class="flex-1">
-                <div class="flex flex-col gap-4 ml-10">
-                  <div class="flex items-center justify-between">
-                    <div class="text-sm font-medium">名称</div>
-                    <input
-                      type="textarea"
-                      class="bg-gray-600 p-2 rounded-lg text-sm flex-1 ml-4 focus:outline-none focus:ring focus:border-blue-300"
-                      placeholder="填写名称"
-                    />
-                  </div>
+          <el-form :model="form" :rules="rules" ref="form" label-width="60px" class="form" >
+            <div class="bg-gray-700 p-5 rounded-lg">
+              <div class="flex gap-4">
+                <div class="w-1/3 flex justify-center">
+                  <el-form-item label="" prop="picture" label-width="0">
+                    <ImageUpload v-model="form.picture" class="imgUp" :limit="1" />
+                  </el-form-item>
+                  
+                  <!-- <div class="bg-gray-600 p-4 rounded-lg flex items-center justify-center">
 
-                  <div class="flex items-center justify-between">
-                    <div class="text-sm font-medium">标语</div>
-                    <textarea
-                      class=" flex-1  ml-4 bg-gray-600 p-2 rounded-lg text-sm w-full h-16  focus:outline-none focus:ring focus:border-blue-300"
-                      placeholder="介绍一下你要值造的这个机器人。应段介绍只会是示在机器人的角色详情信息中,不会出现在提示词中,也不会影响到你的机器人。"
-                    ></textarea>
-                  </div>
-                  <div class="flex items-center justify-start">
-                    <div class="text-sm font-medium">类型</div>
-                    <div class="flex items-center gap-2 ml-6">
-                      <span class="text-xs bg-red-500 px-2 py-1 rounded-full">
-                        公开
-                      </span>
-                      <span class="text-xs bg-gray-500 px-2 py-1 rounded-full">
-                        私密
-                      </span>
-                    </div>
-                  </div>
-                  <div class="flex items-center justify-between">
-                    <div class="text-sm font-medium">标签</div>
-                    <input
-                      type="textarea"
-                      class="bg-gray-600 p-2 rounded-lg text-sm flex-1 ml-4 focus:outline-none focus:ring focus:border-blue-300"
-                      placeholder="搜索并选择与你的机器人相关的标签"
-                    />
+                  </div> -->
+                  <!-- <div class="text-sm mt-2 text-center">
+                    支持PNG、JPG、JPEG、WebP及GIF格式的图片大小不超过10MB。
+                  </div> -->
+                </div>
+                <div class="flex-1">
+                  <div class="flex flex-col gap-4 ml-6 pb-4">
+                    <el-form-item label="名称" prop="characterName">
+                      <el-input v-model="form.characterName" placeholder="填写名称"></el-input>
+                    </el-form-item>
+                    <el-form-item label="简介" prop="prologue">
+                      <el-input 
+                        v-model="form.prologue" 
+                        type="textarea"
+                        :autosize="{ minRows: 3, maxRows: 3}"
+                        placeholder="介绍一下你要值造的这个机器人。应段介绍只会是示在机器人的角色详情信息中,不会出现在提示词中,也不会影响到你的机器人。"
+                      ></el-input>
+                    </el-form-item>
+                    <el-form-item label="性别" prop="sex">
+                      <el-radio-group v-model="form.sex">
+                        <el-radio label="0">男</el-radio>
+                        <el-radio label="1">女</el-radio>
+                      </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="类型" prop="type">
+                      <el-radio-group v-model="form.type">
+                        <el-radio :label="0">公开</el-radio>
+                        <el-radio :label="1">私密</el-radio>
+                      </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="标签" prop="labelId">
+                      <el-select v-model="form.labelId" multiple filterable placeholder="搜索并选择与你的机器人相关的标签">
+                        <el-option :label="item.labelName" :value="item.id" v-for="(item, index) in labelData" :key="index"></el-option>
+                      </el-select>
+                    </el-form-item>
                   </div>
                 </div>
               </div>
             </div>
-          </div>
-          <div class="text-xl font-medium">机器人制作</div>
-          <div class="bg-gray-700 p-4 rounded-lg">
-            <div class="flex flex-col gap-4">
-              <div class="text-sm">描述</div>
-              <textarea
-                class="bg-gray-600 p-2 rounded-lg text-sm w-full h-16 focus:outline-none focus:ring focus:border-blue-300"
-                placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
-              ></textarea>
-            </div>
-            <div class="flex flex-col gap-4">
-              <div class="text-sm mt-2">性格</div>
-              <textarea
-                class="bg-gray-600 p-2 rounded-lg text-sm w-full h-16 focus:outline-none focus:ring focus:border-blue-300"
-                placeholder="性格简述"
-              ></textarea>
+            <div class="text-xl font-medium my-6">机器人制作</div>
+            <div class="bg-gray-700 p-5 rounded-lg">
+              <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-form-item>
+              <el-form-item label="角色描述" prop="characterIntroduction" label-width="80px">
+                <el-input 
+                  v-model="form.characterIntroduction" 
+                  type="textarea"
+                  :autosize="{ minRows: 4, maxRows: 4}"
+                  placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
+                ></el-input>
+              </el-form-item>
+              <!-- <div class="flex flex-col gap-4">
+                <div class="text-sm">描述</div>
+                <textarea
+                  class="bg-gray-600 p-2 rounded-lg text-sm w-full h-16 focus:outline-none focus:ring focus:border-blue-300"
+                  placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
+                ></textarea>
+              </div> -->
             </div>
-          </div>
+          </el-form>
           <div class="flex justify-center">
-            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg">
+            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click="submitForm">
               提交
             </button>
           </div>
@@ -93,14 +97,144 @@
 
 <script>
 import Header from "@/views/homeComponents/Header.vue"
+import { addCharacterApi } from "@/api/create.js"
+import { labelListApi } from "@/api/home.js"
 export default {
   components: {
     Header,
   },
+  data() {
+    return {
+      labelData: [],
+      form: {
+        characterName: "",// 人物名称
+        characterIntroduction: "", //人物角色描述
+        characterPersonalityTags: "", //人物性格标签
+        firstContent: "", //首次聊天内容
+        labelId: "", //标签id
+        picture: "", //人物图片
+        prologue: "", //人物简介
+        sex: "", //性别(0男 1女)
+        type: "", //公开或私密(0公开 1私密)
+      },
+      rules: {
+        characterName: [
+          { required: true, message: "请输入名称", trigger: "change" },
+        ],
+        characterIntroduction: [
+          { required: true, message: "请输入人物描述", trigger: "change" },
+        ],
+        firstContent: [
+          { required: true, message: "请输入开场白", trigger: "change" },
+        ],
+        labelId: [
+          { required: true, message: "请选择标签", trigger: "change" },
+        ],
+        picture: [
+          { required: true, message: "请上传人物图片", trigger: "change" },
+        ],
+        prologue: [
+          { required: true, message: "请输入人物简介", trigger: "change" },
+        ],
+        sex: [
+          { required: true, message: "请选择性别", trigger: "change" },
+        ],
+        type: [
+          { required: true, message: "请选择类型", trigger: "change" },
+        ],
+      }
+    }
+  },
+  mounted() {
+    this.getLabelList()
+    // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');
+  },
+  methods: {
+    async addCharacter() {
+      let data = {
+        name: this.form.name,
+        description: this.form.description,
+        character: this.form.character,
+        tags: this.form.tags,
+        image: this.form.image,
+        type: this.form.type,
+      }
+      let res = await addCharacterApi(data)
+      console.log(res, 'res');
+    },
+    getLabelList() {
+      let params = {
+        pageSize: 9999,
+        pageNum: 1
+      }
+      labelListApi(params).then(res => {
+        console.log(res, '标签列表');
+        this.labelData = res.rows
+      })
+    },
+    submitForm() {
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          addCharacterApi(this.form).then(() => {
+            this.$message({
+              message: '创建成功',
+              type: 'success'
+            });
+            this.$refs.form.resetFields()
+          })
+        }
+      })
+    },
+  }
 }
 </script>
 
 <style lang="scss" scoped>
 
 
+</style>
+<style scoped>
+.form >>> .el-form-item {
+  margin-bottom: 0px;
+}
+.form >>> .el-form-item__label,
+.form >>> .el-radio {
+  color: #fff;
+}
+.form >>> .el-select {
+  width: 100%;
+}
+.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 {
+  color: #b8b8b8;
+  text-align: center;
+}
+.imgUp >>> .upload {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+  background: rgba(75, 85, 99, 1);
+  border-radius: 10px;
+}
+.imgUp >>> .el-upload {
+  border-radius: 50%;
+}
+.imgUp >>> .el-upload-list__item {
+  border-radius: 50%;
+}
 </style>

+ 240 - 0
src/views/create/indexH5.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="create bg-gray-900 comBg" style="min-height: 100vh;">
+    <div class="text-white mx-auto">
+      <div class="container mx-auto p-4">
+        <div class="flex flex-col gap-6">
+          
+          <el-form :model="form" :rules="rules" ref="form" label-width="60px" class="form" >
+            <div class="bg-gray-700 p-3 rounded-lg">
+              <div class="text-lg font-medium">基本信息</div>
+              <div class="text-xs text-gray-400 mb-2">
+                这些信息在机器人描述中供其他用户查看
+              </div>
+              <div class="flex flex-col gap-4">
+                <div class="flex justify-center">
+                  <el-form-item label="" prop="picture" label-width="0">
+                    <ImageUpload v-model="form.picture" class="imgUp" :limit="1" />
+                  </el-form-item>
+                  
+                  <!-- <div class="bg-gray-600 p-4 rounded-lg flex items-center justify-center">
+
+                  </div> -->
+                  <!-- <div class="text-sm mt-2 text-center">
+                    支持PNG、JPG、JPEG、WebP及GIF格式的图片大小不超过10MB。
+                  </div> -->
+                </div>
+                <div class="flex-1">
+                  <div class="flex flex-col gap-4 pb-4">
+                    <el-form-item label="名称" prop="characterName">
+                      <el-input v-model="form.characterName" placeholder="填写名称"></el-input>
+                    </el-form-item>
+                    <el-form-item label="简介" prop="prologue">
+                      <el-input 
+                        v-model="form.prologue" 
+                        type="textarea"
+                        :autosize="{ minRows: 3, maxRows: 3}"
+                        placeholder="介绍一下你要值造的这个机器人。应段介绍只会是示在机器人的角色详情信息中,不会出现在提示词中,也不会影响到你的机器人。"
+                      ></el-input>
+                    </el-form-item>
+                    <el-form-item label="性别" prop="sex">
+                      <el-radio-group v-model="form.sex">
+                        <el-radio label="0">男</el-radio>
+                        <el-radio label="1">女</el-radio>
+                      </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="类型" prop="type">
+                      <el-radio-group v-model="form.type">
+                        <el-radio :label="0">公开</el-radio>
+                        <el-radio :label="1">私密</el-radio>
+                      </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="标签" prop="labelId">
+                      <el-select v-model="form.labelId" multiple filterable placeholder="搜索并选择与你的机器人相关的标签">
+                        <el-option :label="item.labelName" :value="item.id" v-for="(item, index) in labelData" :key="index"></el-option>
+                      </el-select>
+                    </el-form-item>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="bg-gray-700 p-3 rounded-lg mt-2">
+              <div class="text-gl font-medium mb-2">机器人制作</div>
+              <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-form-item>
+              <el-form-item label="角色描述" prop="characterIntroduction" label-width="80px">
+                <el-input 
+                  v-model="form.characterIntroduction" 
+                  type="textarea"
+                  :autosize="{ minRows: 4, maxRows: 4}"
+                  placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
+                ></el-input>
+              </el-form-item>
+              <!-- <div class="flex flex-col gap-4">
+                <div class="text-sm">描述</div>
+                <textarea
+                  class="bg-gray-600 p-2 rounded-lg text-sm w-full h-16 focus:outline-none focus:ring focus:border-blue-300"
+                  placeholder="通过设置机器人的指令和反馈,机器人在玩家互动时即时回复,增强玩家的互动,有什么较好的指令。我们会对指令的使用情况进行了解,确保指令的正常使用。"
+                ></textarea>
+              </div> -->
+            </div>
+          </el-form>
+          <div class="flex justify-center">
+            <button class="bg-blue-600 text-white px-4 py-2 rounded-lg" @click="submitForm">
+              提交
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Header from "@/views/homeComponents/Header.vue"
+import { addCharacterApi } from "@/api/create.js"
+import { labelListApi } from "@/api/home.js"
+export default {
+  components: {
+    Header,
+  },
+  data() {
+    return {
+      labelData: [],
+      form: {
+        characterName: "",// 人物名称
+        characterIntroduction: "", //人物角色描述
+        characterPersonalityTags: "", //人物性格标签
+        firstContent: "", //首次聊天内容
+        labelId: "", //标签id
+        picture: "", //人物图片
+        prologue: "", //人物简介
+        sex: "", //性别(0男 1女)
+        type: "", //公开或私密(0公开 1私密)
+      },
+      rules: {
+        characterName: [
+          { required: true, message: "请输入名称", trigger: "change" },
+        ],
+        characterIntroduction: [
+          { required: true, message: "请输入人物描述", trigger: "change" },
+        ],
+        firstContent: [
+          { required: true, message: "请输入开场白", trigger: "change" },
+        ],
+        labelId: [
+          { required: true, message: "请选择标签", trigger: "change" },
+        ],
+        picture: [
+          { required: true, message: "请上传人物图片", trigger: "change" },
+        ],
+        prologue: [
+          { required: true, message: "请输入人物简介", trigger: "change" },
+        ],
+        sex: [
+          { required: true, message: "请选择性别", trigger: "change" },
+        ],
+        type: [
+          { required: true, message: "请选择类型", trigger: "change" },
+        ],
+      }
+    }
+  },
+  mounted() {
+    this.getLabelList()
+    // console.log(this.$route.params.searchValue, 'this.$route.params.searchValue');
+  },
+  methods: {
+    async addCharacter() {
+      let data = {
+        name: this.form.name,
+        description: this.form.description,
+        character: this.form.character,
+        tags: this.form.tags,
+        image: this.form.image,
+        type: this.form.type,
+      }
+      let res = await addCharacterApi(data)
+      console.log(res, 'res');
+    },
+    getLabelList() {
+      let params = {
+        pageSize: 9999,
+        pageNum: 1
+      }
+      labelListApi(params).then(res => {
+        console.log(res, '标签列表');
+        this.labelData = res.rows
+      })
+    },
+    submitForm() {
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          addCharacterApi(this.form).then(() => {
+            this.$message({
+              message: '创建成功',
+              type: 'success'
+            });
+            this.$refs.form.resetFields()
+          })
+        }
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+
+</style>
+<style scoped>
+.form >>> .el-form-item {
+  margin-bottom: 10px;
+}
+.form >>> .el-form-item__label,
+.form >>> .el-radio {
+  color: #fff;
+}
+.form >>> .el-select {
+  width: 100%;
+}
+.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 {
+  color: #b8b8b8;
+  text-align: center;
+}
+/* .imgUp >>> .upload {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+  background: rgba(75, 85, 99, 1);
+  border-radius: 10px;
+} */
+/* .imgUp >>> .el-upload {
+  border-radius: 50%;
+} */
+/* .imgUp >>> .el-upload-list__item {
+  border-radius: 50%;
+} */
+</style>

+ 11 - 13
src/views/homeComponents/Header.vue

@@ -26,20 +26,18 @@
     </div>
     <div class="flex items-center justify-between px-4 py-2">
       <div class="flex items-center">
-        <button
-          class="text-white text-sm mr-3 cursor-pointer px-3 py-2 rounded-md"
-          style="background-color: var(--bg-color1);"
-          @click="goCreate"
-        >
-          创建机器人
-        </button>
-        <button class="text-yellow-400 p-2 w-18 mr-3 flex justify-center items-center">
-          <v-icon name="coins" scale="1"/>
-          <span class="text-yellow-400 text-lg ml-2">{{ 0 }}</span>
-        </button>
-        
-
         <div class="flex justify-center" v-if="getToken()">
+          <button
+            class="text-white text-sm mr-3 cursor-pointer px-3 py-2 rounded-md"
+            style="background-color: var(--bg-color1);"
+            @click="goCreate"
+          >
+            创建机器人
+          </button>
+          <button class="text-yellow-400 p-2 w-18 mr-3 flex justify-center items-center">
+            <v-icon name="coins" scale="1"/>
+            <span class="text-yellow-400 text-lg ml-2">{{ 0 }}</span>
+          </button>
           <button class="text-white p-2">
             <i class="fas el-icon-message-solid"></i>
           </button>

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

@@ -86,7 +86,7 @@ export default {
       }
     },
     goCreate() {
-      this.$router.push('/create')
+      this.$router.push('/createH5')
     }
   }
 }

+ 116 - 83
src/views/homeComponents/HomeH5.vue

@@ -1,105 +1,108 @@
 <template>
-  <div class="home bg-gray-900 comBg">
-    <HeaderH5 @search="searchChange" :searchName="searchName" />
+  <div class="home bg-gray-900 comBg" ref="home">
     <div class="min-h-screen text-white px-4">
-      <div class="container mx-auto py-2">
-        <div class="flex mb-3">
-          <div class="flex space-x-4">
-            <button class="px-3 py-2 rounded topActive fontH5">热门</button>
-            <button class="bg-gray-800 px-3 py-2 rounded fontH5">趋势</button>
-            <button class="bg-gray-800 px-3 py-2 rounded fontH5">最新</button>
-          </div>
-        </div>
-        <div class="flex flex-wrap flex-grow mb-3 items-center">
-          <input
-            type="text"
-            placeholder="搜索标签"
-            class="searchInput fontH5 w-full mr-2 px-3 py-2 mb-1 rounded focus:border-blue-300 focus:outline-none "
-          />
-          <div
-            v-for="(item, index) in selectLabelObj"
-            :key="index"
-            class="fontH5 px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer buttonBg1"
-            @click="clickLabel(item)"
-          >
-            {{ item.labelName }}
-            <i class="fas el-icon-close text-white"></i>
-          </div>
-          <el-button v-show="selectLabelObj.length > 0" class="textButton mx-1" type="text" @click="clearSelectLabel">移除所有</el-button>
-        </div>
-        <div class="flex flex-wrap">
-          <div
-            v-for="(item, index) in labelData.slice(0, labelLength)"
-            :key="index"
-            :class="[
-              selectLabel.indexOf(item.id) != -1 ? 'buttonBg1' : 'labelButton',
-              'fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer'
-            ]" 
-            @click="clickLabel(item)"
-          >
-            <i class="fas fa-fire text-yellow-500 mr-2"></i>
-            {{ item.labelName }}({{item.num}})
-          </div>
-          <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length"  class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            ....
+      <div class="top" ref="top">
+        <HeaderH5 @search="searchChange" :searchName="searchName" />
+        <div class="container mx-auto py-2" ref="container">
+          <div class="flex mb-3">
+            <div class="flex space-x-4">
+              <button class="px-3 py-2 rounded topActive fontH5">热门</button>
+              <button class="bg-gray-800 px-3 py-2 rounded fontH5">趋势</button>
+              <button class="bg-gray-800 px-3 py-2 rounded fontH5">最新</button>
+            </div>
           </div>
-          <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length" class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            显示更多
+          <div class="flex flex-wrap flex-grow mb-3 items-center">
+            <input
+              type="text"
+              placeholder="搜索标签"
+              class="searchInput fontH5 w-full mr-2 px-3 py-2 mb-1 rounded focus:border-blue-300 focus:outline-none "
+            />
+            <div
+              v-for="(item, index) in selectLabelObj"
+              :key="index"
+              class="fontH5 px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer buttonBg1"
+              @click="clickLabel(item)"
+            >
+              {{ item.labelName }}
+              <i class="fas el-icon-close text-white"></i>
+            </div>
+            <el-button v-show="selectLabelObj.length > 0" class="textButton mx-1" type="text" @click="clearSelectLabel">移除所有</el-button>
           </div>
-          <div v-show="labelData.length > 8 && labelLength > 8" @click="labelLength = 8" class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
-            隐藏
+          <div class="flex flex-wrap">
+            <div
+              v-for="(item, index) in labelData.slice(0, labelLength)"
+              :key="index"
+              :class="[
+                selectLabel.indexOf(item.id) != -1 ? 'buttonBg1' : 'labelButton',
+                'fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded flex items-center cursor-pointer'
+              ]" 
+              @click="clickLabel(item)"
+            >
+              <i class="fas fa-fire text-yellow-500 mr-2"></i>
+              {{ item.labelName }}({{item.num}})
+            </div>
+            <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length"  class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+              ....
+            </div>
+            <div v-show="labelData.length > 8 && labelLength == 8" @click="labelLength = labelData.length" class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+              显示更多
+            </div>
+            <div v-show="labelData.length > 8 && labelLength > 8" @click="labelLength = 8" class="fontH5 labelButton px-3 py-1 mx-1 mb-1 rounded cursor-pointer">
+              隐藏
+            </div>
           </div>
         </div>
-
-        <div class="mt-4">
-          <div
-            v-for="(item, index) in characterList"
-            :key="index"
-            class="box2 rounded-lg overflow-hidden shadow-lg cursor-pointer mb-3"
-            @click="toDetail(item)"
-          >
-            
-            <div class="p-3 flex justify-between">
-              <img :src="baseApi + item.picture" class="w-24 h-24 img rounded" />
-              <div class="info ml-3 flex-1">
-                <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
-                <div class="flex flex-wrap labels">
-                  <div v-for="(item2, index2) in item.labelArr" :key="index2" class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs">
-                    <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
-                    {{ item2 }}
-                  </div>
+      </div>
+      <div class="list" :style="{height: `${listHeight}px`}">
+        <div
+          v-for="(item, index) in characterList"
+          :key="index"
+          class="box2 rounded-lg overflow-hidden shadow-lg cursor-pointer mb-3"
+          @click="toDetail(item)"
+        >
+          
+          <div class="p-3 flex justify-between">
+            <img :src="baseApi + item.picture" class="w-24 h-24 img rounded" />
+            <div class="info ml-3 flex-1">
+              <h3 class="text-lg font-bold">{{ item.characterName }}</h3>
+              <div class="flex flex-wrap labels">
+                <div v-for="(item2, index2) in item.labelArr" :key="index2" class="m-0.5 tag px-2 py-1 rounded flex items-center text-xs">
+                  <!-- <i class="fas fa-smile text-yellow-400 mr-2"></i> -->
+                  {{ item2 }}
                 </div>
-                <p class="text-sm prologue">
-                  {{ item.prologue }}
-                </p>
               </div>
-              
+              <p class="text-sm prologue">
+                {{ item.prologue }}
+              </p>
             </div>
-            <div class="flex items-center justify-between px-3 pb-3">
-              <div class="flex items-center box1">
-                <v-icon name="heart" scale="1"/>
-                <span class="ml-1">{{ item.likeNum }}</span>
-              </div>
-              <div class="flex items-center box1">
-                <!-- <i class="fas fa-comment mr-1"></i> -->
-                <v-icon name="star" scale="1"/>
-                <span class="ml-1">{{ item.collections }}</span>
-              </div>
-              <!-- <div class="flex items-center">
-                <v-icon name="share" scale="1.5"/>
-                <span>{{ item.likeNum }}</span>
-              </div> -->
+            
+          </div>
+          <div class="flex items-center justify-between px-3 pb-3">
+            <div class="flex items-center box1">
+              <v-icon name="heart" scale="1"/>
+              <span class="ml-1">{{ item.likeNum }}</span>
             </div>
+            <div class="flex items-center box1">
+              <!-- <i class="fas fa-comment mr-1"></i> -->
+              <v-icon name="star" scale="1"/>
+              <span class="ml-1">{{ item.collections }}</span>
+            </div>
+            <!-- <div class="flex items-center">
+              <v-icon name="share" scale="1.5"/>
+              <span>{{ item.likeNum }}</span>
+            </div> -->
           </div>
         </div>
       </div>
     </div>
+    <BottomH5 />
   </div>
 </template>
 
 <script>
 import HeaderH5 from "@/views/homeComponents/HeaderH5.vue"
 import { labelListApi, characterListApi } from "@/api/home.js"
+import BottomH5 from '@/views/homeComponents/bottom'
 // 引入需要的图标
 import 'vue-awesome/icons/heart'
 // import 'vue-awesome/icons/comment'
@@ -108,10 +111,12 @@ import 'vue-awesome/icons/star'
 export default {
   name: "HomeH5",
   components: {
-    HeaderH5
+    HeaderH5,
+    BottomH5
   },
   data() {
     return {
+      listHeight: 0,
       labelLength: 8,
       searchName: '',
       labelData: [],
@@ -127,6 +132,22 @@ export default {
     }
   },
   mounted() {
+    const resizeObserver = new ResizeObserver((entries) => {
+      // 当DOM元素的宽高发生变化时执行回调函数
+      console.log(entries, 'ssssssssssss');
+      this.$nextTick(() => {
+        console.log(this.$refs.top.offsetHeight, 'this.$refs.top.offsetHeight');
+        let height = this.$refs.home.offsetHeight - this.$refs.top.offsetHeight
+        console.log(height, 'height');
+        this.listHeight = height - 50
+      })
+      // 组件销毁时停止观察
+      this.$once("hook:beforeDestroy", () => {
+        console.log('销毁');
+        resizeObserver.disconnect();
+      });
+    });
+    resizeObserver.observe(this.$refs.top);
     // 获取标签
     this.getLabelList()
     // 获取角色列表
@@ -157,6 +178,8 @@ export default {
       labelListApi(params).then(res => {
         // console.log(res, '标签列表');
         this.labelData = res.rows
+
+        
       })
     },
     getCharacterList(query) {
@@ -214,6 +237,8 @@ export default {
 <style scoped lang="scss">
 .home {
   font-size: 17.5px;
+  // padding-bottom: 50px;
+  height: 100vh;
   blockquote {
     padding: 10px 20px;
     margin: 0 0 20px;
@@ -330,4 +355,12 @@ export default {
   display: -webkit-box;
   -webkit-box-orient: vertical;
 }
+.top {
+  // position: fixed;
+  // width: calc(100vw - 2rem);
+}
+.list {
+  overflow-y: auto;
+  // height: calc(100vh - 50px - 84px - 34px);
+}
 </style>

+ 87 - 0
src/views/homeComponents/bottom.vue

@@ -0,0 +1,87 @@
+<template>
+  <div class="h5Bottom bg-gray-800">
+    <div class="tab" :class="active == 1 && 'active'" @click="clickTab(1)">
+      <i class="icon el-icon-s-home"></i>
+      <div class="text">首页</div>
+    </div>
+    <div class="tab" :class="active == 2 && 'active'" @click="clickTab(2)">
+      <i class="icon el-icon-chat-round"></i>
+      <div class="text">聊天</div>
+    </div>
+    <div class="tab" :class="active == 3 && 'active'" @click="clickTab(3)">
+      <i class="icon el-icon-user-solid"></i>
+      <div class="text">我的</div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      active: 1
+    }
+  },
+  watch: {
+    'this.$route': function(newVal, oldVal) {
+      if (newVal.path == '/home') {
+        this.active = 1
+      }
+    }
+  },
+  mounted() {
+    // if (newVal.path == '/home') {
+    //   this.active = 1
+    // }
+  },
+  methods: {
+    clickTab(index) {
+      this.active = index
+      switch (index) {
+        case 1:
+          this.$router.push('/home')
+          break;
+        case 2:
+          // this.$router.push('/chat')
+          break;
+        case 3:
+          // this.$router.push('/my')
+          break;
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+.h5Bottom {
+  position: fixed;
+  bottom: 0;
+  height: 50px;
+  width: 100%;
+  // background: #fff;
+  padding: 0 20px;
+  display: flex;
+  justify-content: space-around;
+  >.tab {
+    margin-top: 5px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    color: #fff;
+    // justify-content: center;
+    // cursor: pointer;
+    >.icon {
+      font-size: 18px;
+    }
+    >.text {
+      font-size: 10px;
+    }
+  }
+  .active {
+    color: var(--bg-color1);
+  }
+}
+
+</style>

+ 41 - 17
src/views/loginAndRegister/loginH5.vue

@@ -4,19 +4,25 @@
       <img class="logoImg" src="@/assets/images/logo.webp" alt="">
     </div>
     <div class="loginForm">
-      <el-input
-        v-model="form.account"
-        type="text"
-        placeholder="用户账号"
-        class="imput focus:outline-none "
-      />
-      <el-input
-        v-model="form.password"
-        type="text"
-        placeholder="用户密码"
-        show-password
-        class="imput focus:outline-none "
-      />
+      <el-form style="width: 280px;" :rules="registerRules" ref="form" :model="form" label-width="0">
+        <el-form-item label="" prop="account">
+          <el-input
+            v-model="form.account"
+            type="text"
+            placeholder="用户账号"
+            class="imput focus:outline-none "
+          />
+        </el-form-item>
+        <el-form-item label="" prop="password">
+          <el-input
+            v-model="form.password"
+            type="text"
+            placeholder="用户密码"
+            show-password
+            class="imput focus:outline-none "
+          />
+        </el-form-item>
+      </el-form>
       <button
         class="bg-pink-600 text-xs py-1 px-4 w-4/5 h-10 text-white font-semibold"
         style="border-radius: 2.5rem; letter-spacing: 4px;"
@@ -24,10 +30,10 @@
       >
         登录
       </button>
-      <div class="text">
+      <div class="text mt-2">
         还没有账号吗?<span class="text-blue-500" @click="goRegister">前往注册</span>
       </div>
-      <div class="text">
+      <div class="text mt-2">
         <el-checkbox class="checkbox" v-model="checked"></el-checkbox>
         登录即代表您已同意<span class="text-blue-500">《用户协议》</span>和<span class="text-blue-500">《隐私政策》</span>
       </div>
@@ -44,6 +50,14 @@ export default {
         account: null,
         password: null,
       },
+      loginRules: {
+        account: [
+          { required: true, message: '请输入用户账号', trigger: 'blur' },
+        ],
+        password: [
+          { required: true, message: '请输入用户密码', trigger: 'blur' },
+        ]
+      },
     }
   },
   methods: {
@@ -54,8 +68,18 @@ export default {
       this.$router.push('/registerH5')
     },
     clickLogin() {
-      
-    }
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          this.$store.dispatch('Login', this.form).then(() => {
+            this.$message({
+              message: '登录成功',
+              type: 'success'
+            });
+            this.$router.push('/home')
+          })
+        }
+      })
+    },
   }
 }
 </script>

+ 66 - 21
src/views/loginAndRegister/registerH5.vue

@@ -4,26 +4,41 @@
       <img class="logoImg" src="@/assets/images/logo.webp" alt="">
     </div>
     <div class="loginForm">
-      <el-input
-        v-model="form.account"
-        type="text"
-        placeholder="用户账号"
-        class="imput focus:outline-none "
-      />
-      <el-input
-        v-model="form.password"
-        type="text"
-        placeholder="用户密码"
-        show-password
-        class="imput focus:outline-none "
-      />
-      <el-input
-        v-model="form.repeatPassword"
-        type="text"
-        placeholder="确认用户密码"
-        show-repeatPassword
-        class="imput focus:outline-none "
-      />
+      <el-form style="width: 280px;" :rules="registerRules" ref="form" :model="form" label-width="0">
+        <el-form-item label="" prop="account">
+          <el-input
+            v-model="form.account"
+            type="text"
+            placeholder="用户账号"
+            class="imput focus:outline-none "
+          />
+        </el-form-item>
+        <el-form-item label="" prop="password">
+          <el-input
+            v-model="form.password"
+            type="text"
+            placeholder="用户密码"
+            show-password
+            class="imput focus:outline-none "
+          />
+        </el-form-item>
+        <el-form-item label="" prop="repeatPassword">
+          <el-input
+            v-model="form.repeatPassword"
+            type="text"
+            placeholder="确认用户密码"
+            show-repeatPassword
+            class="imput focus:outline-none "
+          />
+        </el-form-item>
+      </el-form>
+      <button
+        class="bg-pink-600 text-xs py-1 px-4 w-4/5 h-10 text-white font-semibold"
+        style="border-radius: 2.5rem; letter-spacing: 4px;"
+        @click="clickRegister"
+      >
+        注册
+      </button>
       <div class="text">
         <el-checkbox class="checkbox" v-model="checked"></el-checkbox>
         注册即代表您已同意<span class="text-blue-500">《用户协议》</span>和<span class="text-blue-500">《隐私政策》</span>
@@ -33,6 +48,8 @@
 </template>
 
 <script>
+import { register } from "@/api/login.js"
+import { getToken, setToken, removeToken } from '@/utils/auth'
 export default {
   data() {
     return {
@@ -40,7 +57,19 @@ export default {
       form: {
         account: null,
         password: null,
+        repeatPassword: null,
       },
+      registerRules: {
+        account: [
+          { required: true, message: '请输入用户账号', trigger: 'blur' },
+        ],
+        password: [
+          { required: true, message: '请输入用户密码', trigger: 'blur' },
+        ],
+        repeatPassword: [
+          { required: true, message: '请输入确认用户密码', trigger: 'blur' },
+        ],
+      }
     }
   },
   methods: {
@@ -49,7 +78,23 @@ export default {
     },
     goRegister() {
       this.$router.push('/registerH5')
-    }
+    },
+    clickRegister() {
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          register(this.form).then(res => {
+            console.log(res, '注册结果');
+            setToken(res.data.userToken)
+            this.$store.commit('SET_TOKEN', res.data.userToken)
+            this.$message({
+              message: '注册成功',
+              type: 'success'
+            });
+            this.$router.push('/home')
+          })
+        }
+      })
+    },
   }
 }
 </script>