0
点赞
收藏
分享

微信扫一扫

agent实现:通过prompt方式实现agent自定义使用

迎月兮 2024-10-14 阅读 21

仿新版QQ的聊天小软件

文章说明

核心源码

<script setup>
import {defineExpose, defineProps, onBeforeMount, reactive} from "vue";
import {fillImagePrefix, formatDate, getRequest, message} from "@/util";

const props = defineProps({
  setReceiverUserInfo: {
    type: Function,
    required: true,
  },
});

const data = reactive({
  chatList: [],
  originChatList: [],
  currentChatId: 0,
});

onBeforeMount(() => {
  getRelList();
});

function getRelList() {
  const user = JSON.parse(localStorage.getItem("user"));
  getRequest("/rel/list", {
    userId: user.userId,
  }).then(async (res) => {
    if (res.data.code === 200) {
      const relList = res.data.data;
      for (let i = 0; i < relList.length; i++) {
        const chatItem = {
          id: i + 1,
          username: "",
          nickname: "",
          avatarUrl: "",
          time: "",
          content: "",
          friendUserId: relList[i].friendUserId
        };
        await getUserInfo(chatItem, relList[i]);
        await getChatLogInfo(chatItem, relList[i]);
        data.chatList.push(chatItem);
        data.originChatList.push(chatItem);
      }
    } else if (res.data.code === 500) {
      message(res.data.msg, "error");
    }
  });
}

async function getChatLogInfo(chatItem, relItem) {
  const user = JSON.parse(localStorage.getItem("user"));
  const res = await getRequest("/chat-log/getLastChatLog", {
    userId: user.userId,
    friendUserId: relItem.friendUserId,
  });
  if (res.data.code === 200) {
    if (res.data.data) {
      chatItem.time = formatDate(new Date(res.data.data["createTime"]));
      const chatLogId = res.data.data.chatLogId;
      await getChatLogContentInfo(chatItem, chatLogId);
    }
  } else if (res.data.code === 500) {
    message(res.data.msg, "error");
  }
}

async function getChatLogContentInfo(chatItem, chatLogId) {
  const res = await getRequest("/chat-log-content/getContent", {
    chatLogId: chatLogId,
  });
  if (res.data.code === 200) {
    chatItem.content = res.data.data.chatLogContent;
  } else if (res.data.code === 500) {
    message(res.data.msg, "error");
  }
}

async function getUserInfo(chatItem, relItem) {
  const res = await getRequest("/user/getUserInfo", {
    userId: relItem["friendUserId"],
  });
  if (res.data.code === 200) {
    chatItem.username = res.data.data.username;
    chatItem.nickname = res.data.data.nickname;
    chatItem.avatarUrl = fillImagePrefix(res.data.data.avatarUrl);
  } else if (res.data.code === 500) {
    message(res.data.msg, "error");
  }
}

function setFriendUserId(item) {
  data.currentChatId = item.id;
  props.setReceiverUserInfo(item);
}

function filterChatList(searchNickname, receiverUserId) {
  data.chatList = [];
  for (let i = 0; i < data.originChatList.length; i++) {
    if (data.originChatList[i].nickname.indexOf(searchNickname) > -1) {
      data.chatList.push(data.originChatList[i]);
    }
  }
  for (let i = 0; i < data.chatList.length; i++) {
    if (data.chatList[i].friendUserId === receiverUserId) {
      return true;
    }
  }
  data.currentChatId = 0;
  return false;
}

function addChatItem(newChatItem) {
  newChatItem.id = data.originChatList.length + 1;
  newChatItem.avatarUrl = fillImagePrefix(newChatItem.avatarUrl);
  data.chatList.push(newChatItem);
  data.originChatList.push(newChatItem);
}

defineExpose({
  getChatLogInfo,
  filterChatList,
  addChatItem
});
</script>

<template>
  <div class="container">
    <template v-for="item in data.chatList" :key="item.id">
      <div :class="data.currentChatId === item.id ? ' active-chat' : ''" class="chat-item"
           @dblclick="setFriendUserId(item)">
        <div style="display: flex; padding: 10px; height: 70px; align-items: center">
          <div style="margin-right: 10px; display: flex; align-items: center; justify-content: center">
            <img :src="item.avatarUrl" alt=""/>
          </div>
          <div style="flex: 1; overflow: hidden; margin-top: -5px">
            <div style="display: flex; align-items: center">
              <p class="nickname">{{ item.nickname }}</p>
              <p class="time">{{ item.time }}</p>
            </div>
            <div class="content">{{ item.content }}</div>
          </div>
        </div>
      </div>
    </template>
  </div>
</template>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  background-color: #ffffff;

  .chat-item {
    cursor: default;
    user-select: none;

    &:hover {
      background-color: #f5f5f5;
    }

    img {
      width: 40px;
      height: 40px;
      border-radius: 50%;
    }

    .nickname {
      flex: 1;
      font-size: 14px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .time {
      width: fit-content;
      font-size: 10px;
      color: #a39999;
      margin-left: 5px;
    }

    .content {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      font-size: 12px;
      color: #a39999;
      margin-top: 5px;
    }
  }

  .active-chat {
    background-color: #ccebff;

    &:hover {
      background-color: #ccebff;
    }
  }
}
</style>
<script setup>
import {defineProps, reactive} from "vue";
import {message, postRequest, TEXT} from "@/util";

const props = defineProps({
  receiverUserId: {
    type: Number,
    required: true,
  },
  updateStatusAfterSendMessage: {
    type: Function,
    required: true,
  }
});

const data = reactive({
  text: "",
});

function sendText() {
  const user = JSON.parse(localStorage.getItem("user"));
  postRequest("/chat-log/send", null, {
    chatLogType: TEXT,
    senderUserId: user.userId,
    receiverUserId: props.receiverUserId,
  }).then((res) => {
    if (res.data.code === 200) {
      const chatLog = res.data.data;
      saveContent(chatLog.chatLogId);
    } else if (res.data.code === 500) {
      message(res.data.msg, "error");
    }
  });
}

function saveContent(chatLogId) {
  postRequest("/chat-log-content/saveContent", null, {
    chatLogId: chatLogId,
    chatLogContent: data.text,
  }).then((res) => {
    if (res.data.code === 200) {
      const chatLogItem = {
        chatLogId: chatLogId,
        chatLogType: TEXT,
        chatLogContent: data.text,
      };
      props.updateStatusAfterSendMessage(chatLogItem);
      document.getElementById("text").textContent = "";
      data.text = "";
    } else if (res.data.code === 500) {
      message(res.data.msg, "error");
    }
  });
}

function getContent(e) {
  data.text = e.target.textContent;
}
</script>

<template>
  <div class="input-container">
    <div class="tool-container">
      <div class="tool-item">
        <i class="iconfont icon-emoji"></i>
      </div>
      <div class="tool-item">
        <i class="iconfont icon-file"></i>
      </div>
      <div class="tool-item">
        <i class="iconfont icon-image"></i>
      </div>
    </div>
    <div class="input-elem-container">
      <div contenteditable="true" @input="getContent($event)" id="text"></div>
    </div>
    <div class="send-btn-container">
      <button @click="sendText">发送</button>
    </div>
  </div>
</template>

<style lang="scss" scoped>
@import "@/css/iconfont.css";

.input-container {
  width: 100%;
  height: 100%;
  background-color: transparent;
  border-top: 1px solid #dbe4f5;
  display: flex;
  flex-direction: column;

  .tool-container {
    height: 30px;
    width: 100%;

    .tool-item {
      float: left;
      margin: 3px 10px;

      .iconfont::before {
        font-size: 24px;
      }

      .iconfont:hover {
        color: crimson;
        cursor: default;
      }
    }
  }

  .input-elem-container {
    flex: 1;
    width: 100%;
    overflow: auto;

    &::-webkit-scrollbar {
      height: 6px;
      width: 6px;
    }

    &::-webkit-scrollbar-thumb {
      background-color: #d0d5db;
      border-radius: 6px;
    }

    &::-webkit-scrollbar-track {
      background-color: transparent;
    }

    div {
      border: none;
      outline: none;
      background-color: transparent;
      font-size: 16px;
      word-break: break-all;
      padding-left: 10px;
      width: 100%;
      height: 100%;
    }
  }

  .send-btn-container {
    height: 50px;
    width: 100%;
    position: relative;

    button {
      width: fit-content;
      height: 30px;
      line-height: 30px;
      text-align: center;
      border: none;
      outline: none;
      background-color: #0099ff;
      color: white;
      padding: 0 15px;
      border-radius: 5px;
      position: absolute;
      bottom: 10px;
      right: 20px;
      font-size: 14px;

      &:hover {
        background-color: #0093f5;
      }

      &:active {
        background-color: #0086e0;
      }
    }
  }
}
</style>
<script setup>
import {defineExpose, defineProps, onBeforeMount, reactive, watch} from "vue";
import {fillImagePrefix, formatDate, getRequest, message} from "@/util";

const props = defineProps({
  receiverUserInfo: {
    type: Object,
    required: true,
  },
});

const data = reactive({
  chatLogList: [],
});

onBeforeMount(() => {
  getChatLogList();
});

function getChatLogList() {
  const user = JSON.parse(localStorage.getItem("user"));
  getRequest("/chat-log/getChatLogList", {
    userId: user.userId,
    friendUserId: props.receiverUserInfo.userId,
  }).then(async (res) => {
    if (res.data.code === 200) {
      data.chatLogList = [];
      const chatLogList = res.data.data;
      for (let i = 0; i < chatLogList.length; i++) {
        chatLogList[i].createTime = formatDate(new Date(chatLogList[i].createTime));
        data.chatLogList.push(chatLogList[i]);
      }
      for (let i = 0; i < data.chatLogList.length; i++) {
        if (data.chatLogList[i].self) {
          data.chatLogList[i].avatarUrl = fillImagePrefix(user.avatarUrl);
        } else {
          data.chatLogList[i].avatarUrl = props.receiverUserInfo.avatarUrl;
        }
        data.chatLogList[i].chatLogContent = await getChatLogContentInfo(data.chatLogList[i].chatLogId);
      }
    } else if (res.data.code === 500) {
      message(res.data.msg, "error");
    }
  });
}

async function getChatLogContentInfo(chatLogId) {
  const res = await getRequest("/chat-log-content/getContent", {
    chatLogId: chatLogId,
  });
  if (res.data.code === 200) {
    return res.data.data.chatLogContent;
  } else if (res.data.code === 500) {
    message(res.data.msg, "error");
  }
  return "";
}

watch(() => props.receiverUserInfo.userId, () => {
  getChatLogList();
});

function updateChatLogList(chatLogItem) {
  const user = JSON.parse(localStorage.getItem("user"));
  data.chatLogList.push({
    chatLogId: chatLogItem.chatLogId,
    chatLogType: chatLogItem.chatLogType,
    chatLogContent: chatLogItem.chatLogContent,
    senderUserId: user.userId,
    receiverUserId: props.receiverUserInfo.userId,
    createTime: formatDate(new Date()),
    self: true,
    avatarUrl: fillImagePrefix(user.avatarUrl)
  });
}

defineExpose({
  updateChatLogList,
});
</script>

<template>
  <div class="chat-log-container">
    <div class="chat-log-list">
      <template v-for="item in data.chatLogList" :key="item.chatLogId">
        <div class="chat-log-item" v-if="!item.self">
          <img alt="" :src="item.avatarUrl"/>
          <span>{{ item.chatLogContent }}</span>
        </div>
        <div class="self-chat-log-item" v-if="item.self">
          <span>{{ item.chatLogContent }}</span>
          <img alt="" :src="item.avatarUrl"/>
        </div>
      </template>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.chat-log-container {
  width: 100%;
  height: 100%;
  background-color: transparent;

  .chat-log-list {
    font-size: 14px;

    .chat-log-item, .self-chat-log-item {
      width: 100%;
      min-height: 30px;
      padding: 10px;
      display: flex;

      img {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        margin: 0 10px;
      }

      span {
        display: inline-flex;
        align-items: center;
        background-color: #ffffff;
        border-radius: 10px;
        color: #000000;
        max-width: calc(100% - 150px);
        padding: 10px;
        line-height: 1.8;
      }
    }

    .self-chat-log-item {
      justify-content: right;

      span {
        background-color: #0099ff;
        color: #ffffff;
      }
    }
  }
}
</style>

效果展示

源码下载

举报

相关推荐

0 条评论