maven
2025-08-07 fbae37b91f88bb547e1ffb7215b3b495894ebec0
yys  新增ai模块
已修改1个文件
已添加48个文件
835 ■■■■■ 文件已修改
src/assets/img/emoji/clown-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/face-screaming-in-fear.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/face-vomiting.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/face-with-tongue.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/face-without-mouth.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/ghost.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/hibiscus.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/jack-o-lantern.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/lips.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/loudly-crying-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/money-bag.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/money-mouth-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/new-moon-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/ok-hand-yellow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/pile-of-poo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/pouting-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/rainbow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/rocket.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/shamrock.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/shangchuan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/slightly-smiling-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/smiling-face-with-heart-eyes.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/smiling-face-with-horns.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/smiling-face-with-sunglasses.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/smiling-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/sparkles.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/star.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/thinking-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/thought-balloon.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/thumbs-up-yellow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/tired-face.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/two-hearts.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/victory-hand-yellow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/取消.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/excel.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/pdf.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/ppt.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/txt.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/unknowfile.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/word.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/fileImg/zpi.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/head_portrait.jpg 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/head_portrait1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FileCard.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/util.js 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/chatHome/chatHomeIndex/MobileChat.vue 457 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/chatHome/chatHomeIndex/home.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/emoji/clown-face.png
src/assets/img/emoji/face-screaming-in-fear.png
src/assets/img/emoji/face-vomiting.png
src/assets/img/emoji/face-with-tongue.png
src/assets/img/emoji/face-without-mouth.png
src/assets/img/emoji/ghost.png
src/assets/img/emoji/hibiscus.png
src/assets/img/emoji/jack-o-lantern.png
src/assets/img/emoji/lips.png
src/assets/img/emoji/loudly-crying-face.png
src/assets/img/emoji/money-bag.png
src/assets/img/emoji/money-mouth-face.png
src/assets/img/emoji/new-moon-face.png
src/assets/img/emoji/ok-hand-yellow.png
src/assets/img/emoji/pile-of-poo.png
src/assets/img/emoji/pouting-face.png
src/assets/img/emoji/rainbow.png
src/assets/img/emoji/rocket.png
src/assets/img/emoji/shamrock.png
src/assets/img/emoji/shangchuan.png
src/assets/img/emoji/slightly-smiling-face.png
src/assets/img/emoji/smiling-face-with-heart-eyes.png
src/assets/img/emoji/smiling-face-with-horns.png
src/assets/img/emoji/smiling-face-with-sunglasses.png
src/assets/img/emoji/smiling-face.png
src/assets/img/emoji/sparkles.png
src/assets/img/emoji/star.png
src/assets/img/emoji/thinking-face.png
src/assets/img/emoji/thought-balloon.png
src/assets/img/emoji/thumbs-up-yellow.png
src/assets/img/emoji/tired-face.png
src/assets/img/emoji/two-hearts.png
src/assets/img/emoji/victory-hand-yellow.png
src/assets/img/emoji/È¡Ïû.png
src/assets/img/fileImg/excel.png
src/assets/img/fileImg/pdf.png
src/assets/img/fileImg/ppt.png
src/assets/img/fileImg/txt.png
src/assets/img/fileImg/unknowfile.png
src/assets/img/fileImg/word.png
src/assets/img/fileImg/zpi.png
src/assets/img/head_portrait.jpg
src/assets/img/head_portrait1.png
src/assets/img/logo.png
src/components/FileCard.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
<template>
  <div class="file-card">
    <img src="@/assets/img/fileImg/unknowfile.png" alt="" v-if="fileType == 0"/>
    <img src="@/assets/img/fileImg/word.png" alt="" v-else-if="fileType == 1"/>
    <img src="@/assets/img/fileImg/excel.png" alt="" v-else-if="fileType == 2"/>
    <img src="@/assets/img/fileImg/ppt.png" alt="" v-else-if="fileType == 3"/>
    <img src="@/assets/img/fileImg/pdf.png" alt="" v-else-if="fileType == 4"/>
    <img src="@/assets/img/fileImg/zpi.png" alt="" v-else-if="fileType == 5"/>
    <img src="@/assets/img/fileImg/txt.png" alt="" v-else/>
    <div class="word">
      <span
        >{{file.name || '未知'}}</span
      >
      <span>154kb</span>
    </div>
  </div>
</template>
<script>
export default {
  // props: ["fileType", "file"],
  props: {
    fileType: Number,
    file: File,
    default() {
      return {};
    },
  },
  watch: {
    file() {
      console.log(this.file);
    },
  },
  mounted() {
    console.log(this.file);
    console.log(this.fileType);
  }
};
</script>
<style lang="scss" scoped>
.file-card {
  width: 250px;
  height: 100px;
  background-color: rgb(45, 48, 63);
  border-radius: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  box-sizing: border-box;
  cursor: pointer;
  &:hover {
    background-color: rgb(33, 36, 54);
  }
  img {
    width: 60px;
    height: 60px;
  }
  .word {
    width: 60%;
    margin-left: 10px;
    overflow: hidden;
    span {
      width: 90%;
      display: inline-block;
      color: #fff;
    }
    span:first-child {
      font-size: 14px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    span:last-child {
      font-size: 12px;
      color: rgb(180, 180, 180);
    }
  }
}
</style>
src/router/index.js
@@ -57,6 +57,7 @@
    component: () => import('@/views/error/401'),
    hidden: true
  },
  {
    path: '',
    component: Layout,
@@ -71,6 +72,20 @@
    ]
  },
  {
    path: '/main/MobileChat',
    component: Layout,
    redirect: '',
    hidden: true,
    children: [
      {
        path: '',
        component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'),
        name: 'MobileChat',
        meta: { title: 'AI对话', icon: 'dashboard', affix: true}
      }
    ]
  },
  {
    path: '/user',
    component: Layout,
    hidden: true,
src/utils/util.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
//防抖
export  function debounce(fn) {
    console.log(1)
    let t = null //只会执行一次
    debugger
    return function (){
        if(t){
            clearTimeout(t)
        }
        t = setTimeout(()=>{
            console.log(temp);  //可以获取
            // console.log(arguments[0]) //undefined
            fn.apply(this,arguments)
            //在这个回调函数里面的argument是这个回调函数的参数,因为没有参数所以undefined,可以通过外面的函数赋值来进行访问
            //也可以改变成箭头函数,箭头函数的this是指向定义函数的那一层的,所以访问到的arguments是上一层函数的arguments
        },1000)
    }
}
//节流
export function throttle(fn, delay = 200) {
    let timer = null
    console.log(fn);
    debugger
    return function () {
        if(timer) return
        timer = setTimeout(() => {
            debugger
          fn.apply(this,arguments)
          timer = null
        })
    }
 }
//下拉动画
 export function animation(obj, target, fn1) {
    // console.log(fn1);
    // fn是一个回调函数,在定时器结束的时候添加
    // æ¯æ¬¡å¼€å®šæ—¶å™¨ä¹‹å‰å…ˆæ¸…除掉定时器
    clearInterval(obj.timer);
    obj.timer = setInterval(function () {
      // æ­¥é•¿è®¡ç®—公式  è¶Šæ¥è¶Šå°
      // æ­¥é•¿å–æ•´
      var step = (target - obj.scrollTop) / 10;
      step = step > 0 ? Math.ceil(step) : Math.floor(step);
      if (obj.scrollTop >= target) {
        clearInterval(obj.timer);
        // å¦‚æžœfn1存在,调用fn
        if (fn1) {
          fn1();
        }
      } else {
        // æ¯30毫秒就将新的值给obj.left
        obj.scrollTop = obj.scrollTop + step;
      }
    }, 10);
  }
  //判断文件类型
  export function judgeFileType(file) {
    if (file == null||file == ""){
         alert("请选择要上传的图片!");
         return false;
    }
    if (file.lastIndexOf('.')==-1){    //如果不存在"."
        alert("路径不正确!");
        return false;
    }
    var AllImgExt=".jpg|.jpeg|.gif|.bmp|.png|";
    var extName = file.substring(file.lastIndexOf(".")).toLowerCase();//(把路径中的所有字母全部转换为小写)
    if(AllImgExt.indexOf(extName+"|")==-1)
    {
        ErrMsg="该文件类型不允许上传。请上传 "+AllImgExt+" ç±»åž‹çš„æ–‡ä»¶ï¼Œå½“前文件类型为"+extName;
        alert(ErrMsg);
        return false;
    }
  }
  //文件类型
  export function fileType() {
    return {
      'application/msword': 'word',
      'application/pdf': 'pdf',
      'application/vnd.ms-powerpoint': 'ppt',
      'application/vnd.ms-excel': 'excel',
      'aplication/zip': 'zpi',
    }
  }
  export function filterArr(arr) {
      return arr.filter(item => item.flag !== false);
  }
src/views/chatHome/chatHomeIndex/MobileChat.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,457 @@
<template>
  <div class="mobile-chat-wrapper" style="height: 91vh;">
    <div class="chat-history">
      <div class="chat-content" ref="chatContent">
        <div class="chat-wrapper" v-for="(item, index) in chatList" :key="index">
          <div class="chat-friend" v-if="item.uid !== '1001'">
            <div class="info-time">
              <img :src="item.headImg" alt="" />
              <span>{{ item.name }}</span>
              <span>{{ item.time }}</span>
            </div>
            <div class="chat-text" v-if="item.chatType == 0">
              <template v-if="isSend && index === chatList.length - 1">
                <span class="flash_cursor"></span>
              </template>
              <template v-else>
                <pre>{{ item.msg }}</pre>
              </template>
            </div>
            <div class="chat-img" v-if="item.chatType == 1">
              <img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
              <el-image :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
            </div>
            <div class="chat-img" v-if="item.chatType == 2">
              <div class="word-file">
                <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
              </div>
            </div>
          </div>
          <div class="chat-me" v-else>
            <div class="info-time">
              <span>{{ item.name }}</span>
              <span>{{ item.time }}</span>
              <img :src="item.headImg" alt="" />
            </div>
            <div class="chat-text" v-if="item.chatType == 0">
              {{ item.msg }}
            </div>
            <div class="chat-img" v-if="item.chatType == 1">
              <img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
              <el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
            </div>
            <div class="chat-img" v-if="item.chatType == 2">
              <div class="word-file">
                <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
<!--    <div class="chat-input-wrapper">-->
<!--      <div style="display: flex; align-items: center">-->
<!--          <input v-model="inputMsg" @change="sendText" class="input-text" autofocus placeholder="给DeepSeek发送消息" />-->
<!--          <img class="send-icon" src="@/assets/img/emoji/rocket.png" alt="" @click="sendText" />-->
<!--      </div>-->
<!--    </div>-->
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, nextTick,onActivated } from 'vue'
import { useRoute } from 'vue-router'
import { animation } from '@/utils/util'
import chatGPTHeadImg from '@/assets/img/head_portrait1.png'
import headPortrait from '@/assets/img/head_portrait.jpg'
import FileCard from '@/components/FileCard.vue'
import { ElMessage } from "element-plus"
// å®šä¹‰å“åº”式数据
const route = useRoute()
const chatContent = ref(null)
const ws = ref(null)
const chatList = ref([
  {
    headImg: chatGPTHeadImg,
    name: '小智',
    time: new Date().toLocaleTimeString(),
    msg: ' å°æ™ºä¸ºæ‚¨æœåŠ¡',
    chatType: 0,
    uid: '1002'
  }
])
const inputMsg = ref('')
const isSend = ref(false)
const fileList = ref([])
const isProcessing = ref(false)
const loading = ref(false)
const srcImgList = ref([])
// åˆ é™¤å›¾ç‰‡
const deleteImg = (index) => {
  if (index >= 0 && index < fileList.value.length) {
    fileList.value.splice(index, 1)
  }
}
// WebSocket消息接收
const websocketonmessage = (e) => {
  const redata = JSON.parse(e.data)
  //数据接收
  let chatGPT = {
    headImg: headPortrait,
    name: 'DeepSeek',
    time: new Date().toLocaleTimeString(),
    msg: redata[0].text,
    chatType: 0, //信息类型,0文字,1图片
    uid: '1002' //uid
  }
  sendMsg(chatGPT)
  isSend.value = false
}
// WebSocket发送消息
const websocketsend = (Data) => {
  console.log("即将发送消息", Data)
  if (ws.value && ws.value.readyState === WebSocket.OPEN) {
    console.log("发送消息", ws.value)
    console.log("发送消息", Data)
    let fileUrls = fileList.value.map(item => item.file.fileUrl)
    //数据发送
    ws.value.send(Data + ":" + fileUrls.join(","))
    fileList.value = []
    inputMsg.value = ''
  }
}
// å‘送文本消息
const sendText = () => {
  if (inputMsg.value) {
    let chatMsg = {
      headImg: headPortrait,
      name: '卧龙',
      time: new Date().toLocaleTimeString(),
      msg: inputMsg.value,
      chatType: 0, //信息类型,0文字,1图片
      uid: '1001' //uid
    }
    sendMsg(chatMsg)
    let chatGPT = {
      headImg: headPortrait,
      name: 'DeepSeek',
      time: new Date().toLocaleTimeString(),
      msg: "",
      chatType: 0, //信息类型,0文字,1图片
      uid: '1002' //uid
    }
    chatList.value.push(chatGPT) // å°†æŽ¥æ”¶åˆ°çš„æ¶ˆæ¯å­˜å‚¨åˆ° messages æ•°ç»„
    inputMsg.value = ''
    loading.value = true
    isSend.value = true
    websocketsend(chatMsg.msg)
  } else {
    ElMessage({
      message: '消息不能为空哦~',
      type: 'warning'
    })
  }
}
// å‘送信息
const sendMsg = (msgList) => {
  chatList.value.push(msgList)
  scrollBottom()
}
// èŽ·å–çª—å£é«˜åº¦å¹¶æ»šåŠ¨è‡³æœ€åº•å±‚
const scrollBottom = () => {
  nextTick(() => {
    const scrollDom = chatContent.value
    animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight)
  })
}
// ç»„件挂载时执行
onActivated(() => {
  chatList.value = []
  chatList.value.push({
    headImg: chatGPTHeadImg,
    name: '小智',
    time: new Date().toLocaleTimeString(),
    msg: '小智为您服务',
    chatType: 0,
    uid: '1002'
  })
  chatList.value.push({
    headImg: chatGPTHeadImg,
    name: '卧龙',
    time: new Date().toLocaleTimeString(),
    msg: route.query.keyWord,
    chatType: 0,
    uid: '1001'
  })
  // æ·»åŠ ä¸€ä¸ªç©ºçš„å›žå¤æ¶ˆæ¯å ä½
  const replyMsg = {
    headImg: chatGPTHeadImg,
    name: '小智',
    time: new Date().toLocaleTimeString(),
    msg: '',
    chatType: 0,
    uid: '1002'
  }
  chatList.value.push(replyMsg)
  scrollBottom()
  // å¦‚果有查询关键字,则模拟流式输出
  if (route.query.keyWord) {
    simulateStreamingOutput(replyMsg)
  }
})
// æ¨¡æ‹Ÿæµå¼è¾“出
const simulateStreamingOutput = (msgObj) => {
  // ç”Ÿæˆ0.8-1.8秒之间的随机延迟
  const delay = Math.random() * 1000 + 800
  // æ¨¡æ‹Ÿå›žå¤å†…容(实际应用中应从API获取)
  const responseText = `关于"${route.query.keyWord}"的问题,我来为您解答:\n\n这是一个示例回复内容,展示流式输出效果。在实际应用中,这里会是来自AI的真实回复内容。\n\n请稍等,我正在整理相关信息...`
  isSend.value = true
  let index = 0
  const interval = setInterval(() => {
    isSend.value = true
    if (index < responseText.length) {
      msgObj.msg += responseText.charAt(index)
      index++
      isSend.value = false
      scrollBottom()
    } else {
      clearInterval(interval)
      isSend.value = false
    }
  }, 50) // æ¯50ms输出一个字符,模拟流式效果
}
</script>
<style lang="scss" scoped>
.mobile-chat-wrapper {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: 91vh;
  position: relative;
  background-color: white;
  .chat-history {
    flex: 1 1 0;
    overflow-y: auto;
  }
  .chat-input-wrapper {
    padding: 8px 16px 8px 8px;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
      .file-tt{
          flex-direction: column;
          width: 200px;
          display: flex;
          padding: 5px;
          border-radius: 5px;
          margin-right: 5px;
          background: #cacaca;
          .file-item{
              width: 200px;
              overflow:hidden;
              word-wrap: break-word;
              text-overflow:ellipsis;
              display:-webkit-box;
              -webkit-box-orient:vertical;
              -webkit-line-clamp:2;
          }
      }
    .send-icon {
      height: 40px;
      margin-left: 16px;
    }
      .input-text{
          font-size: 18px;
          width: 100%;
          border-radius: 20px;
          height: 80px;
          padding-left: 10px;
          //padding-top: 10px;
          border: none;
          color: black;                 /* ä¿®æ”¹æ–‡æœ¬é¢œè‰²ä¸ºç™½è‰² */
          background-color: #f5f4f4;   /* ä¿®æ”¹èƒŒæ™¯é¢œè‰²ä¸ºæ·±ç°è‰² */
      }
  }
  .chat-content {
    width: 100%;
    height: 80%;
    overflow-y: scroll;
    padding: 20px;
    box-sizing: border-box;
    &::-webkit-scrollbar {
      width: 0;
      /* Safari,Chrome éšè—æ»šåŠ¨æ¡ */
      height: 0;
      /* Safari,Chrome éšè—æ»šåŠ¨æ¡ */
      display: none;
      /* ç§»åŠ¨ç«¯ã€pad ä¸ŠSafari,Chrome,隐藏滚动条 */
    }
    .chat-wrapper {
      position: relative;
      word-break: break-all;
      .chat-friend {
        width: 100%;
        float: left;
        margin-bottom: 20px;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: flex-start;
        .chat-text {
          max-width: 90%;
          padding: 20px;
          border-radius: 20px 20px 20px 5px;
          background-color: rgb(245, 248, 248);
          color: black;
          &:hover {
            background-color: rgb(232, 232, 232);
          }
          pre {
            white-space: break-spaces;
          }
        }
        .chat-img {
          img {
            width: 100px;
            height: 100px;
          }
        }
        .info-time {
          margin: 10px 0;
          color: black;
          font-size: 14px;
          img {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            vertical-align: middle;
            margin-right: 10px;
          }
          span:last-child {
            color: rgb(101, 104, 115);
            margin-left: 10px;
            vertical-align: middle;
          }
        }
      }
      .chat-me {
        width: 100%;
        float: right;
        margin-bottom: 20px;
        position: relative;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        align-items: flex-end;
        .chat-text {
          float: right;
          max-width: 90%;
          padding: 20px;
          border-radius: 20px 20px 5px 20px;
          background-color: rgb(29, 144, 245);
          color: #fff;
          &:hover {
            background-color: rgb(26, 129, 219);
          }
        }
        .chat-img {
          img {
            max-width: 300px;
            max-height: 200px;
            border-radius: 10px;
          }
        }
        .info-time {
          margin: 10px 0;
          color: black;
          font-size: 14px;
          display: flex;
          justify-content: flex-end;
          img {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            vertical-align: middle;
            margin-left: 10px;
          }
          span {
            line-height: 30px;
          }
          span:first-child {
            color: rgb(101, 104, 115);
            margin-right: 10px;
            vertical-align: middle;
          }
        }
      }
    }
  }
  .flash_cursor {
    width: 20px;
    height: 30px;
    display: inline-block;
    background: #d6e3f5;
    opacity: 1;
    animation: glow 800ms ease-out infinite alternate;
  }
  @keyframes glow {
    0% {
      opacity: 1;
    }
    25% {
      opacity: 0.5;
    }
    50% {
      opacity: 0;
    }
    75% {
      opacity: 0.5;
    }
    100% {
      opacity: 1;
    }
  }
}
</style>
src/views/chatHome/chatHomeIndex/home.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,190 @@
<template>
<div class="home">
    <div style="background: white;color: black;font-size: 30px;" class="logo">
        <div class="logo-one" style="font-weight: bold">
<!--            <img src="/src/assets/img/logo.png" style="width: 50px;height: 50px;margin: 0 10px" />-->
            <div><i>淮南东方医院集团DeepSeek应用平台</i></div>
        </div>
        <div class="input">
            <input type="text" v-model="keyWord" class="input-text" placeholder="给DeepSeek发送消息"  @keyup.enter="sendMsg" />
            <div style="font-size: 13px;color: #808080;display: flex;justify-content: space-between;padding: 10px;">
                <div style="display: flex;justify-content: center;align-items: center;">
<!--                    <div style="display: flex;justify-content: center;align-items: center;">-->
<!--                        <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />-->
<!--                        <span>深度思考(R1)</span>-->
<!--                    </div>-->
<!--                    <div style="display: flex;justify-content: center;align-items: center;">-->
<!--                        <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />-->
<!--                        <span>联网搜索</span>-->
<!--                    </div>-->
                </div>
                <div style="display: flex;justify-content: center;align-items: center;margin-right: 5px;">
<!--                    <img src="/src/assets/img/logo.png" style="width: 25px;height: 25px;margin: 0 5px" />-->
                    <img src="@/assets/img/emoji/rocket.png" style="width: 25px;height: 25px;margin: 0 5px" @click="sendMsg"/>
                </div>
            </div>
        </div>
        <div style="width: 780px;">
            <div style="font-weight: bold;margin: 30px 0;">热门推荐</div>
            <div class="keywords">
                <div class="keywordss" @click="sendMsgDefault(keyWordOne)">
                    <p class="fontSize aaa">{{keyWordOne}}</p>
                    <p class="fontSize">选择科空:根据病情选择相应的科室(如内科、外科、儿科等)</p>
                    <p class="fontSize">挂号方式:现场挂号:在医院挂号窗口排队办理。线上挂号:通过医院官网、微</p>
                    <p class="fontSize">信公众号或第三方平台预约...</p>
                </div>
                <div class="keywordss" @click="sendMsgDefault(keyWordTwo)">
                    <p class="fontSize aaa">{{keyWordTwo}}</p>
                    <p class="fontSize">普通病房:探视时问一般为每天上午10:00-12:00,下午14:00-20.00。每次探视人</p>
                    <p class="fontSize">数不超过2人,探视时间不超过30分钟。</p>
                    <p class="fontSize">重症监护室(1CU):探视时问较短,通常为每天15:00-16:00。探视人数.</p>
                </div>
            </div>
            <div class="keywords">
                <div class="keywordss" @click="sendMsgDefault(keyWordFive)">
                    <p class="fontSize aaa">{{keyWordFive}}</p>
                    <p class="fontSize">选择体检套餐:根据个人需求选择基础套轻或专项检杏套。</p>
                    <p class="fontSize">预约方式:线上预约:通过医院官网、微信公众号或第三方平台预约。电话豫</p>
                    <p class="fontSize">约:拨打医院体检中心电话进行预约。现场预约:直接到体检中心</p>
                </div>
                <div class="keywordss" @click="sendMsgDefault(keyWordSix)">
                    <p class="fontSize aaa">{{keyWordSix}}</p>
                    <p class="fontSize">医生确认出院:主治医生评估患者病情后,开具出院。</p>
                    <p class="fontSize">结算费用:患者或家属携带住院押金单、医保卡等材料到出院结算窗口办理。核</p>
                    <p class="fontSize">对费用明细,支付自费部分或办理医保报销..</p>
                </div>
            </div>
            <div class="keywords">
                <div class="keywordss" @click="sendMsgDefault(keyWordServen)">
                    <p class="fontSize aaa">{{keyWordServen}}</p>
                    <p class="fontSize">院内投诉:直接向医院医务科或患者服务中心反映问题。填写投诉表,提供详细</p>
                    <p class="fontSize">情况和证据(如病历、录音等)。</p>
                    <p class="fontSize">上级部门投诉:向当地卫生能康委员会或医疗纠纷调解委员会投诉。拨打…</p>
                </div>
                <div class="keywordss" @click="sendMsgDefault(keyWordEight)">
                    <p class="fontSize aaa">{{keyWordEight}}</p>
                    <p class="fontSize">申请转院:患者或家属向主治医生提出转院申请。医生评估病情,确认是否需要</p>
                    <p class="fontSize">转院。</p>
                    <p class="fontSize">开具转院证明:主治医生开具转院证明,说明转院原因和病情..…</p>
                </div>
            </div>
        </div>
    </div>
    <div></div>
</div>
</template>
<script setup>
import { ref,onMounted } from "vue";
import {useRoute,useRouter} from "vue-router"
const route = useRoute();
const router = useRouter();
const keyWord = ref('');
const keyWordOne = ref('医院挂号流程是怎样的?');
const keyWordTwo = ref('医院探视时问有哪些规定?');
const keyWordFive = ref('医院如何预约体检?');
const keyWordSix = ref('医院如何办理出院手续?');
const keyWordServen = ref('医院如何投诉医疗服务质量?');
const keyWordEight = ref('医院如何办理转院手续?');
onMounted(() => {
    // const script = document.createElement('script');
    // script.src = '/src/assets/js/index.js';
    // // script.type = 'module'
    // script.onload = () => {
    //     console.log('index.js å·²åŠ è½½');
    // };
    // document.head.appendChild(script);
});
const sendMsg = () => {
    router.push({ path: '/main/MobileChat',query:{ keyWord: keyWord.value} })
}
const sendMsgDefault = (value) => {
    router.push({ path: '/main/MobileChat',query:{ keyWord: value} })
}
</script>
<style lang="scss" scoped>
.home {
  width: 100%;
  height: 91vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  .logo {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    z-index: 99;
    width: 100%;
    height: 100%;
    color: #fff;
    cursor: pointer;
    overflow: hidden;
    background-color: #F0F6F9;
    .keywords {
      display: flex;
      width: 100%;
      height: 90px;
      line-height: 80px;
      justify-content: space-between;
      margin: 10px 0;
      .keywordss {
        box-shadow: 0px 2px 5px #b8b8b8;
        width: 48%;
        background: #e0edfc;
        border-radius: 10px;
        .aaa {
          font-weight: bold;
          font-size: 12px;
        }
        .fontSize {
          font-size: 10px;
          height: 15px;
          line-height: 15px;
          margin: 6px;
        }
      }
    }
    .logo-one {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-bottom: 20px;
    }
    .input {
      width: 780px;
      height: 150px;
      background: #f5f4f4;
      border-radius: 20px;
      .input-text {
        font-size: 18px;
        width: 568px;
        border-radius: 20px 20px 0 0;
        height: 90px;
        padding-left: 10px;
        border: none;
        color: black;
        background-color: #f5f4f4;
      }
      .input-text:focus {
        outline: none;
        border: none;
      }
    }
  }
}
</style>