Browse Source

Merge branch 'dev_suwenjiang' into follow

# Conflicts:
#	src/pages/test/index.vue
qinyuyue 2 months ago
parent
commit
2248380bab

+ 23 - 3
.env.development

@@ -3,14 +3,34 @@ VITE_APP_ENV=development
 # VITE_APP_BASE_URL=https://service.xiaoyaotravel.com/api/
 # VITE_APP_BASE_URL=http://101.126.146.250:8082/
 # 测试服
-# 黄文
+
+# 黄文本地
 # VITE_APP_BASE_URL=http://192.168.1.44:8082/
-# 畅哥
+
+# 畅哥本地
 # VITE_APP_BASE_URL=http://192.168.1.38:8082/
 
-# 张维
+# 张维本地
 VITE_APP_BASE_URL=http://192.168.1.73:8082/
 
+# 张维本地socoket
+VITE_APP_IM_URL=ws://192.168.1.73:8082/system/message
+
+# 李忠畅本地socoket
+# VITE_APP_IM_URL=ws://192.168.1.38:8082/system/message
+
+
+# 黄雯花生壳
+# VITE_APP_BASE_URL=http://q9943037p3.goho.co
+
+# 黄雯本地socoket
+# VITE_APP_IM_URL=ws://192.168.1.44:8082/system/message
+# VITE_APP_IM_URL=ws://q9943037p3.goho.co/system/message
+
+
+# 李忠畅花生壳
+# VITE_APP_BASE_URL=http://cilicli.qicp.vip
+
 # VITE_APP_BASE_URL=http://192.168.1.204:8082
 VITE_APP_EMOJI_API=https://v.xiaoyaotravel.com/emoji/
 VITE_APP_IM_USER_SUFFIX=dev

+ 1 - 0
nuxt.config.ts

@@ -27,6 +27,7 @@ export default defineNuxtConfig({
   runtimeConfig: {
     public: {
       baseApi: process.env.VITE_APP_BASE_URL,
+      baseIM:process.env.VITE_APP_IM_URL
     },
   },
   imports: {

+ 1 - 2
src/components/Chat/Search.vue

@@ -8,10 +8,9 @@
         class="ml-5 w-[80%] h-full pl-10 text-[13px]"
         :placeholder="placeholder"
         @keydown.enter="$emit('search')"
-        @change="$emit('search')"
         style="outline: none; background: none"
       />
-
+      <!--  @change="$emit('search')" -->
       <button
         @click="$emit('search')"
         class="h-full border-l-[1px] flex justify-center items-center w-66 shrink-0 rounded-r-full"

+ 19 - 53
src/components/Profile/News/GroupChat.vue

@@ -1,66 +1,33 @@
 <template>
   <van-swipe-cell>
+    <!-- {{ itemData?.unreadMessageCount }}
+    {{ itemData?.dfGroupImage }} -->
     <div
       @click="$emit('onChatPage')"
       class="w-full relative h-82 flex justify-start items-center px-16"
     >
       <div class="w-48 h-48">
-        <van-badge v-if="messagesNumber > 0" v-bind="messageNumber(messagesNumber)" max="99">
-          <!-- v-if="itemData?.avatar" -->
-          <div
-            v-if="itemData?.avatar"
-            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
-          >
-            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.avatar" alt="" />
-          </div>
-          <div
-            v-else
-            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
-          >
-            <img
-              class="w-full h-full shrink-0 object-cover"
-              src="~/assets/img/chat/group-avatar.svg"
-              alt=""
-            />
-          </div>
+        <van-badge
+          v-if="itemData?.unreadMessageCount > 0"
+          v-bind="messageNumber(itemData?.unreadMessageCount)"
+          max="99"
+        >
+          <MultiHeader :imgUrls="itemData?.dfGroupImage" />
         </van-badge>
-
-        <template v-else>
-          <div
-            v-if="itemData?.avatar"
-            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center flex-wrap"
-          >
-            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.avatar" alt="" />
-            <img
-              class="w-full h-full shrink-0 object-cover"
-              src="~/assets/img/chat/group-avatar.svg"
-              alt=""
-            />
-          </div>
-          <div
-            v-else
-            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
-          >
-            <img
-              class="w-full h-full shrink-0 object-cover"
-              src="~/assets/img/chat/group-avatar.svg"
-              alt=""
-            />
-          </div>
-        </template>
+        <MultiHeader v-else :imgUrls="itemData?.dfGroupImage" />
       </div>
 
       <div class="h-48 w-245 ml-12 flex flex-wrap">
         <h1 class="line-clamp-1 mb-8 w-full text-xl text-black-3 font-semibold">
-          群聊{{ itemData?.title }}
+          {{ itemData?.groupName }}
         </h1>
         <p class="line-clamp-1 w-full h-20 text-base text-black/[0.6] leading-3xl">
-          你吃饭了么 {{ itemData?.message }}
+          {{ itemData?.lastMessage?.messageContent }}
         </p>
       </div>
 
       <div class="w-35 h-48 shrink-0">
-        <p class="text-black/[0.6] mb-12 text-sm text-end">02:06{{ itemData?.time }}</p>
+        <p class="text-black/[0.6] mb-12 text-sm text-end">{{ itemData?.updateTime }}</p>
 
         <div v-if="itemData?.isNotDisturb == 1" class="w-full shrink-0 flex justify-end">
           <span class="iconfont icon-close-remind text-black-6" style="font-size: 16px"></span>
@@ -68,13 +35,12 @@
       </div>
       <div class="absolute bottom-0 right-0 w-[96%] h-1 border-b-[1px]"></div>
     </div>
-
     <template #right>
       <div class="pl-2 h-full">
         <van-button
           style="height: 100%"
           square
-          text="设为免打扰"
+          :text="itemData?.isNotDisturb == 1 ? '取消免打扰' : '设为免打扰'"
           @click="$emit('onNoBother')"
           type="danger"
           color="#FF9300"
@@ -83,8 +49,8 @@
         <van-button
           style="height: 100%"
           square
-          text="不显示聊天"
-          @click="$emit('onNoBother')"
+          :text="itemData?.isTop == 1 ? '取消置顶' : '置顶聊天'"
+          @click="$emit('onIsTop')"
           type="danger"
           color="#E37318"
           class="delete-button"
@@ -92,9 +58,10 @@
         <van-button
           style="height: 100%"
           square
-          text="删除聊天"
+          :text="itemData?.isShow == 1 ? '不显示聊天' : '显示聊天'"
           @click="$emit('onConvDelete')"
           type="danger"
+          color="#D54941"
           class="delete-button"
         />
       </div>
@@ -103,15 +70,14 @@
 </template>
 
 <script setup>
+import { messageContentParse } from '~/utils/detalTime.js'
 defineProps({
   itemData: {
     type: Object,
     default: () => ({})
   }
 })
-defineEmits(['onNoBother', 'onConvDelete', 'onChatPage'])
-
-const messagesNumber = ref(10)
+defineEmits(['onNoBother', 'onIsTop', 'onConvDelete', 'onChatPage'])
 
 // 消息数量通知的展示  需要动态的展示
 const messageNumber = (content) => {

+ 24 - 24
src/components/Profile/News/SingleChat.vue

@@ -5,20 +5,24 @@
       class="w-full h-82 relative flex justify-start items-center px-16 mb-20"
     >
       <div class="w-48 h-48">
-        <van-badge v-if="messagesNumber > 0" v-bind="messageNumber(messagesNumber)" max="99">
+        <van-badge
+          v-if="itemData?.unreadMessageCount > 0"
+          v-bind="messageNumber(itemData?.unreadMessageCount)"
+          max="99"
+        >
           <div
-            v-if="itemData?.avatar"
+            v-if="itemData?.headImage"
             class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
           >
-            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.avatar" alt="" />
+            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.headImage" alt="" />
           </div>
           <div
             v-else
-            class="w-48 h-48 bg-[#E7E7E7] rounded-full overflow-hidden flex justify-center items-center"
+            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
           >
             <img
               class="w-24 h-24 shrink-0 object-cover"
-              src="~/assets/img/chat/user-grey.svg"
+              src="~/assets/img/default_avatar.png"
               alt=""
             />
           </div>
@@ -26,18 +30,18 @@
 
         <template v-else>
           <div
-            v-if="itemData?.avatar"
+            v-if="itemData?.headImage"
             class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
           >
-            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.avatar" alt="" />
+            <img class="w-full h-full shrink-0 object-cover" :src="itemData?.headImage" alt="" />
           </div>
           <div
             v-else
-            class="w-48 h-48 bg-[#E7E7E7] rounded-full overflow-hidden flex justify-center items-center"
+            class="w-48 h-48 rounded-full overflow-hidden flex justify-center items-center"
           >
             <img
               class="w-24 h-24 shrink-0 object-cover"
-              src="~/assets/img/chat/user-grey.svg"
+              src="~/assets/img/default_avatar.png"
               alt=""
             />
           </div>
@@ -50,15 +54,11 @@
       </div>
 
       <div class="w-35 h-48 shrink-0">
-        <p class="text-black/[0.6] text-sm text-end">02:06{{ itemData?.time }}</p>
+        <p class="text-black/[0.6] text-sm text-end">{{ itemData?.updateTime }}</p>
 
+        <!-- <span class="iconfont icon-close-remind text-black-6" style="font-size: 16px"></span> -->
         <div v-if="itemData?.isNotDisturb == 1" class="w-full h-16 shrink-0 mt-12 flex justify-end">
-          <img
-            class="w-16 h-16 object-cover"
-            src="~/assets/img/chat/close-remind.svg
-            "
-            alt=""
-          />
+          <span class="iconfont icon-close-remind text-black-6" style="font-size: 16px"></span>
         </div>
       </div>
       <div class="absolute bottom-0 right-0 w-[96%] h-1 border-b-[1px]"></div>
@@ -69,7 +69,7 @@
         <van-button
           style="height: 100%"
           square
-          text="设为免打扰"
+          :text="itemData?.isNotDisturb == 1 ? '取消免打扰' : '设为免打扰'"
           @click="$emit('onNoBother')"
           type="danger"
           color="#FF9300"
@@ -78,18 +78,20 @@
         <van-button
           style="height: 100%"
           square
-          text="不显示聊天"
-          @click="$emit('onNoBother')"
+          :text="itemData?.isTop == 1 ? '取消置顶' : '置顶聊天'"
+          @click="$emit('onIsTop')"
           type="danger"
-          color="#E37318"
+          color="#FF9300"
           class="delete-button"
         />
+
         <van-button
           style="height: 100%"
           square
-          text="删除聊天"
+          :text="itemData?.isShow == 1 ? '不显示聊天' : '显示聊天'"
           @click="$emit('onConvDelete')"
           type="danger"
+          color="#D54941"
           class="delete-button"
         />
       </div>
@@ -104,9 +106,7 @@ defineProps({
     default: () => ({})
   }
 })
-defineEmits(['onNoBother', 'onConvDelete', 'onChatPage'])
-
-const messagesNumber = ref(10)
+defineEmits(['onNoBother', 'onIsTop', 'onConvDelete', 'onChatPage'])
 
 // 消息数量通知的展示  需要动态的展示
 const messageNumber = (content) => {

+ 122 - 113
src/pages/chat/group-add.vue

@@ -5,37 +5,48 @@
     <ChatSearch v-model:searchString="showName" @search="search" placeholder="请输入关键词" />
 
     <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
-      <Empty v-if="!addDataList?.length && !loading" title="暂无数据" top="100" />
+      <ChatEmpty
+        image="search"
+        v-if="!addDataList?.length && !loading"
+        title="暂无数据"
+        top="100"
+      />
 
       <van-list
-        v-else-if="addDataList.length"
         v-model:loading="loading"
         error-text="获取失败"
         finished-text="-- 没有更多了 --"
         :finished="finished"
         :immediate-check="false"
       >
-        <!--    @load="getLoadList"  -->
         <div style="height: calc(100vh - 170px)">
           <van-checkbox-group v-model="checked">
-            <!-- <van-index-bar highlight-color="#FD9A00" index-list :sticky="false"> -->
-            <template v-for="(item, index) in addDataList" :key="item?.attentionIdDictMap?.userId">
-              <!-- <van-index-anchor index="A" /> -->
-              <van-cell center clickable @click="toggle(item?.attentionIdDictMap?.userId)" disabled>
+            <!-- <van-index-bar
+              highlight-color="#FD9A00"
+              :index-list="sortStringToAZ.sortIndex"
+              :sticky="false"
+            > -->
+            <!-- <template v-for="(el, index) in addDataList" :key="index"> -->
+            <!-- <van-index-anchor v-if="el[1].length" :index="el[0]" /> -->
+            <!-- <template v-for="(el, index) in addDataList" :key="index"> -->
+            <!-- <van-index-anchor  :index="el[0]" /> -->
+
+            <template v-for="item in addDataList" :key="item.userId">
+              <van-cell center clickable @click.stop="toggle(item)">
                 <template #icon>
                   <div class="flex justify-start">
                     <van-checkbox
                       checked-color="#FD9A00"
-                      :name="item?.attentionIdDictMap?.userId"
-                      :ref="(el) => (checkboxRefs[item?.attentionIdDictMap?.userId] = el)"
-                      @click.stop
+                      :name="item?.userId"
+                      :ref="(el) => (checkboxRefs[item?.userId] = el)"
+                      @click.stop="toggle(item)"
                     />
 
                     <div class="w-40 h-40 ml-13 mr-12 rounded-full overflow-hidden">
                       <img
-                        v-if="item?.attentionIdDictMap?.headImageUrl"
+                        v-if="item?.headImageUrl"
                         class="w-full h-full shrink-0 object-cover"
-                        :src="item?.attentionIdDictMap?.headImageUrl"
+                        :src="item?.headImageUrl"
                         alt=""
                       />
 
@@ -50,7 +61,7 @@
                 <template #title>
                   <div class="flex items-center">
                     <h1 class="text-xl text-black-3">
-                      {{ item?.attentionIdDictMap?.showName }}
+                      {{ item?.showName }}
                     </h1>
                     <van-tag
                       v-if="item.fansStatus == 2"
@@ -64,16 +75,60 @@
                 </template>
               </van-cell>
             </template>
+            <!-- </template> -->
+            <!-- </template> -->
             <!-- </van-index-bar> -->
           </van-checkbox-group>
         </div>
       </van-list>
     </van-pull-refresh>
+
+    <div
+      class="w-full box-border p-16 pb-40 bg-white fixed bottom-0 left-0 flex justify-between items-center shadow-[0px_-4px_4px_0px_rgba(0,0,0,0.1)]"
+    >
+      <div class="shrink-0 flex justify-start items-center">
+        <div class="w-118 shrink-0 flex justify-start items-center overflow-hidden">
+          <div
+            v-for="(item, index) in checkedList.slice(0, 5)"
+            :key="index + 'avatar'"
+            :class="`w-36 h-36  ${index == 0 ? '' : '-ml-16'} shrink-0 rounded-full overflow-hidden`"
+          >
+            <img
+              v-if="item?.headImageUrl"
+              class="w-full h-full object-cover"
+              :src="item?.headImageUrl"
+              alt=""
+            />
+            <img
+              v-else
+              class="w-full h-full shrink-0 object-cover"
+              src="~/assets/img/default_avatar.png"
+              alt=""
+            />
+          </div>
+        </div>
+
+        <div v-if="checkedList.length > 5" class="shrink-0 w-24 h-24 ml-8">
+          <img class="w-full h-full object-cover" src="~/assets/img/chat/ellipsis.svg" alt="" />
+        </div>
+      </div>
+      <van-button
+        :disabled="checkedList.length > 0 ? false : true"
+        @click="handleCreateGroup"
+        style="width: 160px"
+        class="shrink-0"
+        block
+        size="large"
+        color="#FD9A00"
+        round
+      >
+        完成
+        <span v-if="checkedList.length">({{ checkedList.length }})</span>
+      </van-button>
+    </div>
   </div>
 </template>
 <script setup>
-import { pinyin } from 'pinyin-pro'
-
 const route = useRoute()
 
 definePageMeta({
@@ -91,13 +146,7 @@ const finished = ref(false)
 const checked = ref([])
 const showName = ref('')
 const checkboxRefs = ref([])
-
-// 字母的数组
-const letterList = ref([])
-
-const toggle = (index) => {
-  checkboxRefs.value[index].toggle()
-}
+const checkedList = ref([])
 
 const queryParams = reactive({
   pageNum: 1,
@@ -105,67 +154,38 @@ const queryParams = reactive({
   flagPage: 1
 })
 
+// const _addDataList = ref(new Map([]))
 const addDataList = ref([])
 const filterDataList = ref([])
 
 useSeoMeta({
-  title: '添加成员'
+  title: '群聊'
 })
 
+// 选中要邀请的人
+const toggle = (item) => {
+  let index = checkedList.value.findIndex((el) => el?.userId == item?.userId)
+
+  if (index != -1) {
+    checkedList.value.splice(index, 1)
+  } else {
+    checkedList.value.push(item)
+  }
+
+  checkboxRefs.value[item.userId].toggle()
+}
+// 搜索
 const search = () => {
   finished.value = true
   if (showName.value) {
     addDataList.value = filterDataList.value.filter((item) =>
-      item.attentionIdDictMap.name.includes(showName.value)
+      item.showName.includes(showName.value)
     )
   } else {
     addDataList.value = filterDataList.value
   }
 }
 
-// 获取全局搜索的用户
-// const getAllList = async () => {
-//   try {
-//     loading.value = true
-
-//     const {
-//       data: { dataList, totalCount }
-//     } = await request('/website/tourism/fans/getUserListByNickname', {
-//       query: {
-//         ...queryParams,
-//         showName: showName.value
-//       }
-//     })
-
-//     if (Array.isArray(dataList) && dataList?.length) {
-//       addDataList.value = dataList
-//       // arr = addDataList.value
-//       // arr = arr.map((item, index) => {
-//       //   let letter = pinyin(item?.visaTitle, { pattern: 'first', toneType: 'none' })
-//       //   console.log(letter, '123')
-
-//       //   item.letter = letter
-//       //   return item
-//       // })
-//       // console.log(arr, 'addDataList.value .value')
-//     } else {
-//       addDataList.value = []
-//     }
-
-//     loading.value = false
-//     refreshing.value = false
-//     if (addDataList.value.length >= totalCount) {
-//       finished.value = true
-//     } else {
-//       finished.value = false
-//     }
-//   } catch (err) {
-//   } finally {
-//     refreshing.value = false
-//     loading.value = false
-//   }
-// }
-
 // 刷新
 const onRefresh = () => {
   queryParams.pageNum = 1
@@ -174,38 +194,23 @@ const onRefresh = () => {
   getList()
 }
 
-// 触底加载
-// const getLoadList = () => {
-//   queryParams.pageNum++
-//   finished.value = true
-//   showName.value ? search() : getList()
-// }
-
 // 获取数据
 const getList = async () => {
   try {
-    let url = `/website/tourism/fans/getFriends`
+    let url = `/website/tourMember/memberLit`
 
     loading.value = true
-    let {
-      data: { dataList, totalCount }
-    } = await request(url, {
+    let { data } = await request(url, {
       query: {
-        ...queryParams
+        groupId: route.query.groupId
       }
     })
-    let arr = []
-    if (Array.isArray(dataList) && dataList?.length) {
-      addDataList.value = dataList
-      arr = addDataList.value
-      arr = arr.map((item, index) => {
-        let letter = pinyin(item?.visaTitle, { pattern: 'first', toneType: 'none' })
-        console.log(letter, '123')
-
-        item.letter = letter
-        return item
-      })
-      console.log(arr, 'addDataList.value .value')
+
+    if (Array.isArray(data) && data?.length) {
+      // const { sortListMap } = sortStringToAZ.sort(data, 'showName')
+
+      addDataList.value = data
+      filterDataList.value = data
     } else {
       addDataList.value = []
     }
@@ -224,27 +229,31 @@ const getList = async () => {
   }
 }
 
-// // 数据转化
-// const changeInitials = (list) => {
-//   console.log(list)
-
-//   let letter = []
-//   let listArr = []
-// listArr = list.map((item, index) => {
-//   item.letter = pinyin(item?.visaTitle, { pattern: 'first', toneType: 'none' })
-//     .map((pinyin) => pinyin[0].toUpperCase()) // 获取拼音的首字母并转换为大写
-//     .join('')
-
-//     letter.push(item.letter)
-//     return item
-//   })
-//   console.log(list, '21')
-//   console.log(listArr, '444')
-
-//   return {
-//     letter,
-//     listArr
-//   }
-// }
+// 创建多人聊天
+async function handleCreateGroup() {
+  try {
+    showLoadingToast({
+      message: '准备开始群聊...',
+      duration: 100000
+    })
+    let { data } = request('/website/tourMember/invite', {
+      method: 'post',
+      body: {
+        groupId: route.query.groupId,
+        ids: checked.value
+      }
+    })
+    if (data) {
+      navigateTo({
+        path: '/chat/group',
+        query: data,
+        replace: true
+      })
+    }
+  } catch (error) {
+  } finally {
+    closeToast()
+  }
+}
 </script>
 <style lang="scss" scoped></style>

+ 14 - 12
src/pages/chat/group-member.vue

@@ -1,15 +1,16 @@
 <template>
   <div class="w-full h-[100vh]">
     <ChatHeader title="群成员" />
-    <ChatSearch v-model:searchString="searchString" @search="search" />
+    <ChatSearch v-model:searchString="showName" @search="search" />
 
-    <Empty
+    <ChatEmpty
       v-if="!groupMember?.length && !loading"
-      :title="`没有找到&quot;${searchString}&quot;相关成员`"
+      image="search"
+      :title="`没有找到&quot;${showName}&quot;相关成员`"
     />
 
     <div
-      v-if="groupMember?.length && !searchString"
+      v-if="groupMember?.length && !showName"
       class="box-border w-full min-h-400 mt-16 mb-12 pt-12 pl-12"
     >
       <van-row>
@@ -44,7 +45,7 @@
       </van-row>
     </div>
     <!-- 搜索后的结果 -->
-    <div v-if="searchMember?.length && searchString" class="w-full border-box min-h-400 pl-16">
+    <div v-if="searchMember?.length && showName" class="w-full border-box min-h-400 pl-16">
       <van-cell
         v-for="(item, index) in searchMember"
         :key="item?.id"
@@ -70,7 +71,7 @@ const queryParams = reactive({
 })
 
 const loading = ref(false)
-const searchString = ref('')
+const showName = ref('')
 
 onMounted(() => {
   getList()
@@ -95,15 +96,16 @@ const getList = async () => {
     loading.value = true
     let {
       data: { dataList, totalCount }
-    } = await request('/website/tourism/visa/list/page')
-    // // query: {
-    //   groupId: '0'
-    // }
+    } = await request('/website/tourMember/getTourMemberInfoList', {
+      query: {
+        groupId: '0'
+      }
+    })
 
     if (Array.isArray(dataList) && dataList?.length) {
-      searchString.value ? (searchMember.value = dataList) : (groupMember.value = dataList)
+      showName.value ? (searchMember.value = dataList) : (groupMember.value = dataList)
     } else {
-      searchString.value ? (searchMember.value = []) : (groupMember.value = [])
+      showName.value ? (searchMember.value = []) : (groupMember.value = [])
     }
 
     loading.value = false

+ 1 - 1
src/pages/chat/group.vue

@@ -39,7 +39,7 @@
       </div>
     </van-pull-refresh>
 
-    <!-- <ProfileNewsChatInput></ProfileNewsChatInput> -->
+    <ProfileNewsChatInput></ProfileNewsChatInput>
   </div>
 </template>
 <script setup>

+ 0 - 194
src/pages/chat/interrelation-friend.vue

@@ -1,194 +0,0 @@
-<template>
-  <div class="w-full h-[100vh]">
-    <ChatHeaderBar title="选择互关好友" />
-
-    <ChatSearch v-model:searchString="searchString" @search="search" placeholder="请输入关键词" />
-
-    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
-      <ChatEmpty v-if="!friendList?.length && !loading" title="请输入关键词,没有找到相关结果" />
-      <van-list
-        v-else-if="friendList.length"
-        v-model:loading="loading"
-        error-text="获取失败"
-        finished-text="-- 没有更多了 --"
-        :finished="finished"
-        :immediate-check="false"
-        @load="getLoadList"
-      >
-        <van-checkbox-group v-model="checked">
-          <!-- <van-index-bar highlight-color="#FD9A00" index-list :sticky="false"> -->
-          <template v-for="(item, index) in friendList" :key="item?.id">
-            <!-- <van-index-anchor index="A" /> -->
-            <van-cell
-              v-for="(item, index) in friendList"
-              :key="item?.id"
-              center
-              size="large"
-              clickable
-              @click="toggle(index)"
-              disabled
-            >
-              <template #icon>
-                <div class="flex justify-start">
-                  <van-checkbox
-                    checked-color="#FD9A00"
-                    :name="item.id"
-                    :ref="(el) => (checkboxRefs[index] = el)"
-                    @click.stop
-                  />
-
-                  <div class="w-40 h-40 ml-13 mr-12 rounded-full overflow-hidden">
-                    <img class="w-full h-full shrink-0 object-cover" :src="item?.img" alt="" />
-                  </div>
-                </div>
-              </template>
-              <template #title>
-                <div class="flex items-center">
-                  <h1 class="text-xl text-black-3 line-clamp-1">{{ item?.visaTitle }}</h1>
-                </div>
-              </template>
-            </van-cell>
-          </template>
-          <!-- </van-index-bar> -->
-        </van-checkbox-group>
-      </van-list>
-      <!-- <div class="relative">
-        <van-cell center size="large" clickable title="123546" disabled></van-cell>
-        <div class="w-full h-46 bg-white/[0.3] absolute top-0 left-0"></div>
-      </div> -->
-    </van-pull-refresh>
-
-    <div
-      class="w-full box-border p-16 pb-40 bg-white fixed bottom-0 left-0 flex justify-between items-center shadow-[0px_-4px_4px_0px_rgba(0,0,0,0.1)]"
-    >
-      <div class="shrink-0 flex justify-start items-center">
-        <div
-          v-for="(item, index) in 5"
-          :key="index + 'avatar'"
-          :class="`w-36 h-36  ${index == 0 ? '' : '-ml-16'} shrink-0 rounded-full overflow-hidden`"
-        >
-          <img class="w-full h-full object-cover" src="../../assets/img/chat/search.svg" alt="" />
-        </div>
-
-        <div v-if="checked.length > 5" class="shrink-0 w-24 h-24 ml-8">
-          <img class="w-full h-full object-cover" src="~/assets/img/chat/ellipsis.svg" alt="" />
-        </div>
-      </div>
-      <van-button
-        @click="handleCreateGroup"
-        style="width: 160px"
-        class="shrink-0"
-        block
-        size="large"
-        color="#FD9A00"
-        round
-      >
-        新建
-        <span v-if="checked.length">(16{{ checked.length }})</span>
-      </van-button>
-    </div>
-  </div>
-</template>
-<script setup>
-const userInfoStore = useUserInfoStore()
-const { userInfo } = storeToRefs(userInfoStore)
-
-definePageMeta({
-  layout: false
-})
-
-useSeoMeta({
-  title: '我的消息'
-})
-
-const refreshing = ref(false)
-const loading = ref(false)
-const finished = ref(false)
-
-const checked = ref([])
-const searchString = ref('')
-const checkboxRefs = ref([])
-
-const friendList = ref([])
-
-const queryParams = reactive({
-  pageNum: 1,
-  pageSize: 10,
-  searchString: ''
-})
-
-const toggle = (index) => {
-  checkboxRefs.value[index].toggle()
-}
-
-const search = () => {
-  friendList.value = []
-  queryParams.pageNum = 1
-  queryParams.searchString = searchString.value
-  getList()
-}
-
-const onRefresh = () => {
-  queryParams.pageNum = 1
-  friendList.value = []
-  getList()
-}
-
-// 触底加载
-const getLoadList = () => {
-  queryParams.pageNum++
-  finished.value = true
-  getList()
-}
-
-// 获取互关好友列表
-const getList = () => {
-  try {
-    let {
-      data: { dataList }
-    } = request('/tourMember/memberLit', {
-      query: {
-        userId: userInfo?.value?.userInfo
-      }
-    })
-
-    if (Array.isArray(dataList) && dataList?.length) {
-      friendList.value = friendList.value.concat(dataList)
-    } else {
-      friendList.value = []
-    }
-  } catch (error) {}
-}
-
-// 创建多人聊天
-async function handleCreateGroup() {
-  try {
-    showLoadingToast({
-      message: '准备开始群聊...',
-      duration: 100000
-    })
-    let { data } = request('/tourGroup/createGroup', {
-      method: 'post',
-      body: {
-        createType: 2,
-        creatUserId: userInfo.value.userId
-      }
-    })
-    if (data) {
-      navigateTo('/chat/group', {
-        query: data?.groupId,
-        replace: true
-      })
-    }
-  } catch (error) {
-  } finally {
-    closeToast()
-  }
-}
-
-onMounted(() => {
-  getList()
-})
-</script>
-
-<style lang="scss" scoped></style>

+ 5 - 1
src/pages/chat/qr-results.vue

@@ -2,7 +2,8 @@
   <div class="w-full h-[100vh]">
     <ChatHeaderBar title="扫码结果" />
     <div class="h-250"></div>
-    <ChatGroupAvatar class="mx-auto"></ChatGroupAvatar>
+    <!-- <ChatGroupAvatar class="mx-auto"></ChatGroupAvatar> -->
+    <MultiHeader :size="60" :imgUrls="imgUrls" />
     <h1 class="w-220 text-center text-black-3 font-semibold text-xl mb-27 mt-16 mx-auto">
       {{ itemData?.groupName }}
     </h1>
@@ -126,6 +127,7 @@ const userInfoStore = useUserInfoStore()
 const { userInfo } = storeToRefs(userInfoStore)
 
 const itemData = ref({})
+const imgUrls = ref([])
 const loading = ref(false)
 // 是否存在
 const showIsExist = ref(false)
@@ -156,6 +158,8 @@ async function getGroupInfo() {
 
     if (typeof data == 'object') {
       itemData.value = data
+      // imgUrls.value = data.groupAvatar ? [] : ['~/assets/img/default_avatar.png']
+
       if (data.bannedStatus) {
         // showIsExist.value = data?.memberList.some((item) => item?.userId == userInfo.value.userId)
 

+ 1 - 1
src/pages/chat/set-single.vue

@@ -18,7 +18,7 @@
         </van-col>
         <van-col style="width: 54px" span="4" class="mb-12 mr-10">
           <div
-            @click="navigateTo('/chat/interrelation-friend')"
+            @click="navigateTo('/chat/single-add')"
             class="w-40 h-40 flex justify-center items-center bg-[#F3F3F3] rounded-full mx-auto overflow-hidden mb-4"
           >
             <span class="iconfont icon-plus text-black-6" style="font-size: 24px"></span>

+ 18 - 1
src/pages/chat/set.vue

@@ -34,7 +34,18 @@
               {{ item.groupNickname ? item.groupNickname : userInfo.showName }}
             </p>
           </van-col>
-          <van-col span="4" class="mb-12 mr-10" @click="navigateTo('/chat/group-add')">
+          <van-col
+            span="4"
+            class="mb-12 mr-10"
+            @click="
+              navigateTo({
+                path: '/chat/group-add',
+                query: {
+                  groupId: setData?.id
+                }
+              })
+            "
+          >
             <div
               class="w-40 h-40 rounded-full flex justify-center items-center bg-[#F3F3F3] border mx-auto overflow-hidden mb-4"
             >
@@ -44,6 +55,12 @@
           </van-col>
           <van-col v-if="isRankAndFiler(userGroupData?.groupRole)" span="4 mb-12 mr-10">
             <div
+              @click="
+                navigateTo({
+                  path: '/chat/group-member',
+                  query: setData?.id
+                })
+              "
               class="w-40 h-40 rounded-full flex justify-center items-center bg-[#F3F3F3] border mx-auto overflow-hidden mb-4"
             >
               <van-icon name="minus" size="24" color="#666666" />

+ 254 - 0
src/pages/chat/single-add.vue

@@ -0,0 +1,254 @@
+<template>
+  <div class="w-full h-[100vh]">
+    <ChatHeaderBar title="选择互关好友" />
+
+    <ChatSearch v-model:searchString="showName" @search="search" placeholder="请输入关键词" />
+
+    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
+      <ChatEmpty
+        image="search"
+        v-if="!addDataList?.length && !loading"
+        title="暂无数据"
+        top="100"
+      />
+
+      <van-list
+        v-else-if="addDataList.length"
+        v-model:loading="loading"
+        error-text="获取失败"
+        finished-text="-- 没有更多了 --"
+        :finished="finished"
+        :immediate-check="false"
+      >
+        <!--    @load="getLoadList"  -->
+        <div style="height: calc(100vh - 170px)">
+          <van-checkbox-group v-model="checked">
+            <!-- <van-index-bar highlight-color="#FD9A00" index-list :sticky="false"> -->
+            <template v-for="(item, index) in addDataList" :key="item?.attentionIdDictMap?.userId">
+              <!-- <van-index-anchor index="A" /> -->
+              <van-cell center clickable @click="toggle(item)">
+                <template #icon>
+                  <div class="flex justify-start">
+                    <van-checkbox
+                      checked-color="#FD9A00"
+                      :name="item?.attentionIdDictMap?.userId"
+                      :ref="(el) => (checkboxRefs[item?.attentionIdDictMap?.userId] = el)"
+                      @click.stop="toggle(item)"
+                    />
+
+                    <div class="w-40 h-40 ml-13 mr-12 rounded-full overflow-hidden">
+                      <img
+                        v-if="item?.attentionIdDictMap?.headImageUrl"
+                        class="w-full h-full shrink-0 object-cover"
+                        :src="item?.attentionIdDictMap?.headImageUrl"
+                        alt=""
+                      />
+
+                      <img
+                        class="w-full h-full shrink-0 object-cover"
+                        src="~/assets/img/default_avatar.png"
+                        alt=""
+                      />
+                    </div>
+                  </div>
+                </template>
+                <template #title>
+                  <div class="flex items-center">
+                    <h1 class="text-xl text-black-3">
+                      {{ item?.attentionIdDictMap?.showName }}
+                    </h1>
+                    <van-tag
+                      v-if="item.fansStatus == 2"
+                      style="margin-left: 5px; padding: 3px 6px"
+                      color="#F7F8FA"
+                      text-color="#666666"
+                    >
+                      相互关注
+                    </van-tag>
+                  </div>
+                </template>
+              </van-cell>
+            </template>
+            <!-- </van-index-bar> -->
+          </van-checkbox-group>
+        </div>
+      </van-list>
+    </van-pull-refresh>
+    <div
+      class="w-full box-border p-16 pb-40 bg-white fixed bottom-0 left-0 flex justify-between items-center shadow-[0px_-4px_4px_0px_rgba(0,0,0,0.1)]"
+    >
+      <div class="shrink-0 flex justify-start items-center">
+        <div class="w-118 shrink-0 flex justify-start items-center overflow-hidden">
+          <div
+            v-for="(item, index) in checkedList.slice(0, 5)"
+            :key="index + 'avatar'"
+            :class="`w-36 h-36  ${index == 0 ? '' : '-ml-16'} shrink-0 rounded-full overflow-hidden`"
+          >
+            <img
+              v-if="item?.attentionIdDictMap?.headImageUrl"
+              class="w-full h-full object-cover"
+              :src="item?.attentionIdDictMap?.headImageUrl"
+              alt=""
+            />
+            <img
+              v-else
+              class="w-full h-full shrink-0 object-cover"
+              src="~/assets/img/default_avatar.png"
+              alt=""
+            />
+          </div>
+        </div>
+
+        <div v-if="checkedList.length > 5" class="shrink-0 w-24 h-24 ml-8">
+          <img class="w-full h-full object-cover" src="~/assets/img/chat/ellipsis.svg" alt="" />
+        </div>
+      </div>
+      <van-button
+        :disabled="checkedList.length > 0 ? false : true"
+        @click="handleCreateGroup"
+        style="width: 160px"
+        class="shrink-0"
+        block
+        size="large"
+        color="#FD9A00"
+        round
+      >
+        新建
+        <span v-if="checkedList.length">({{ checkedList.length }})</span>
+      </van-button>
+    </div>
+  </div>
+</template>
+<script setup>
+import { pinyin } from 'pinyin-pro'
+
+const route = useRoute()
+
+definePageMeta({
+  layout: false
+})
+
+onMounted(() => {
+  getList()
+})
+
+const refreshing = ref(false)
+const loading = ref(false)
+const finished = ref(false)
+
+const checked = ref([])
+const checkedList = ref([])
+const showName = ref('')
+const checkboxRefs = ref([])
+
+// 字母的数组
+const letterList = ref([])
+
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  flagPage: 1
+})
+
+const addDataList = ref([])
+const filterDataList = ref([])
+
+useSeoMeta({
+  title: '我的消息'
+})
+
+// 选中要邀请的人
+const toggle = (item) => {
+  let index = checkedList.value.findIndex(
+    (el) => el?.attentionIdDictMap?.userId == item?.attentionIdDictMap?.userId
+  )
+
+  if (index != -1) {
+    checkedList.value.splice(index, 1)
+  } else {
+    checkedList.value.push(item)
+  }
+  checkboxRefs.value[item?.attentionIdDictMap?.userId].toggle()
+}
+
+const search = () => {
+  finished.value = true
+  if (showName.value) {
+    addDataList.value = filterDataList.value.filter((item) =>
+      item.attentionIdDictMap.name.includes(showName.value)
+    )
+  } else {
+    addDataList.value = filterDataList.value
+  }
+}
+
+// 刷新
+const onRefresh = () => {
+  queryParams.pageNum = 1
+  addDataList.value = []
+  filterDataList.value = []
+  getList()
+}
+
+// 获取数据
+const getList = async () => {
+  try {
+    let url = `/website/tourism/fans/getFriends`
+
+    loading.value = true
+    let {
+      data: { dataList, totalCount }
+    } = await request(url, {
+      query: {
+        ...queryParams
+      }
+    })
+
+    if (Array.isArray(dataList) && dataList?.length) {
+      addDataList.value = dataList
+    } else {
+      addDataList.value = []
+    }
+
+    loading.value = false
+    refreshing.value = false
+    if (addDataList.value.length >= totalCount) {
+      finished.value = true
+    } else {
+      finished.value = false
+    }
+  } catch (err) {
+  } finally {
+    refreshing.value = false
+    loading.value = false
+  }
+}
+
+// 创建多人聊天
+async function handleCreateGroup() {
+  try {
+    showLoadingToast({
+      message: '准备开始群聊...',
+      duration: 100000
+    })
+    let { data } = request('/website/tourGroup/createGroup', {
+      method: 'post',
+      body: {
+        createType: 2,
+        ids: checked.value
+      }
+    })
+    if (data) {
+      navigateTo({
+        path: '/chat/group',
+        query: data,
+        replace: true
+      })
+    }
+  } catch (error) {
+  } finally {
+    closeToast()
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 1 - 3
src/pages/chat/single.vue

@@ -44,9 +44,7 @@ const onClickRight = () => {
   navigateTo({
     path: '/chat/set-single',
     query: {
-      ...{
-        userId: '2'
-      }
+      userId: route.query.userId
     }
   })
 }

+ 143 - 84
src/pages/chat/user-add.vue

@@ -5,88 +5,111 @@
     <ChatSearch v-model:searchString="showName" @search="search" placeholder="请输入关键词" />
 
     <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
-      <ChatEmpty
-        v-if="!list?.length && !loading"
-        image="search"
-        title="请输入关键词,没有找到关结果"
-        top="100"
-      />
-
-      <van-list
-        v-else-if="list.length"
-        v-model:loading="loading"
-        error-text="获取失败"
-        finished-text="-- 没有更多了 --"
-        :finished="finished"
-        :immediate-check="false"
-        @load="getLoadList"
-      >
-        <template v-for="(item, index) in list" :key="item?.userId">
-          <van-cell center disabled>
-            <template #icon>
-              <div class="w-40 h-40 ml-13 mr-12 rounded-full overflow-hidden">
-                <img class="w-full h-full shrink-0 object-cover" :src="item?.headImageUrl" alt="" />
-              </div>
-            </template>
-            <template #title>
-              <h1 class="text-xl line-clamp-1 text-black-3">{{ item?.tourUserVo?.showName }}</h1>
-
-              <p class="line-clamp-1 text-black-3 text-sm">粉丝 {{ transNum(item?.fansCount) }}</p>
-            </template>
-            <template #value>
-              <van-button
-                v-if="item.fansStatus == '0'"
-                style="width: 60px"
-                size="mini"
-                type="primary"
-                color="#FF9300"
-                round
-                plain
-                @click="handleFollow(item, index)"
-              >
-                关注
-              </van-button>
-              <van-button
-                style="width: 60px"
-                v-if="item.fansStatus == '1'"
-                size="mini"
-                type="primary"
-                color="#999999"
-                round
-                plain
-                @click="handleFollow(item, index)"
-              >
-                已关注
-              </van-button>
-              <van-button
-                style="width: 72px"
-                v-if="item.fansStatus == '2'"
-                size="mini"
-                type="primary"
-                color="#999999"
-                round
-                plain
-                @click="handleFollow(item, index)"
-              >
-                互相关注
-              </van-button>
-              <template v-if="item.fansStatus == '4'"></template>
-              <van-button
-                style="width: 60px"
-                v-if="item.fansStatus == '4'"
-                size="mini"
-                type="primary"
-                color="#FF9300"
-                round
-                plain
-                @click="handleFollow(item, index)"
-              >
-                回关
-              </van-button>
-            </template>
-          </van-cell>
-        </template>
-      </van-list>
+      <div style="height: calc(100vh - 150px)" class="w-full min-h-500">
+        <ChatEmpty
+          v-if="!list?.length && !loading"
+          image="search"
+          title="请输入关键词,没有找到关结果"
+          top="100"
+        />
+
+        <van-list
+          v-else-if="list?.length"
+          v-model:loading="loading"
+          error-text="获取失败"
+          finished-text="-- 没有更多了 --"
+          :finished="finished"
+          :immediate-check="false"
+          @load="getLoadList"
+        >
+          <template v-for="(item, index) in list" :key="item?.tourUserVo?.userId">
+            <van-cell center disabled>
+              <template #icon>
+                <div
+                  @click="
+                    createSingle({
+                      getUserId: item?.tourUserVo?.userId,
+                      noticeType: 1
+                    })
+                  "
+                  class="w-40 h-40 ml-13 mr-12 rounded-full overflow-hidden"
+                >
+                  <img
+                    v-if="item?.headImageUrl"
+                    class="w-full h-full shrink-0 object-cover"
+                    :src="item?.headImageUrl"
+                    alt=""
+                  />
+                  <img
+                    v-else
+                    class="w-full h-full shrink-0 object-cover"
+                    src="~/assets/img/default_avatar.png"
+                    alt=""
+                  />
+                </div>
+              </template>
+              <template #title>
+                <h1 class="text-xl line-clamp-1 text-black-3">{{ item?.tourUserVo?.showName }}</h1>
+
+                <p class="line-clamp-1 text-black-3 text-sm">
+                  粉丝 {{ transNum(item?.fansCount) }}
+                </p>
+              </template>
+              <template #value>
+                <van-button
+                  v-if="item.fansStatus == '0'"
+                  style="width: 60px"
+                  size="mini"
+                  type="primary"
+                  color="#FF9300"
+                  round
+                  plain
+                  @click="handleFollow(item, index)"
+                >
+                  关注
+                </van-button>
+                <van-button
+                  style="width: 60px"
+                  v-if="item.fansStatus == '1'"
+                  size="mini"
+                  type="primary"
+                  color="#999999"
+                  round
+                  plain
+                  @click="handleFollow(item, index)"
+                >
+                  已关注
+                </van-button>
+                <van-button
+                  style="width: 72px"
+                  v-if="item.fansStatus == '2'"
+                  size="mini"
+                  type="primary"
+                  color="#999999"
+                  round
+                  plain
+                  @click="handleFollow(item, index)"
+                >
+                  互相关注
+                </van-button>
+                <template v-if="item.fansStatus == '4'"></template>
+                <van-button
+                  style="width: 60px"
+                  v-if="item.fansStatus == '4'"
+                  size="mini"
+                  type="primary"
+                  color="#FF9300"
+                  round
+                  plain
+                  @click="handleFollow(item, index)"
+                >
+                  回关
+                </van-button>
+              </template>
+            </van-cell>
+          </template>
+        </van-list>
+      </div>
     </van-pull-refresh>
   </div>
 </template>
@@ -94,8 +117,12 @@
 definePageMeta({
   layout: false
 })
+const userInfoStore = useUserInfoStore()
+const { userInfo } = storeToRefs(userInfoStore)
 
-onMounted(() => {})
+onMounted(() => {
+  userInfoStore.getUserInfo()
+})
 
 const refreshing = ref(false)
 const loading = ref(false)
@@ -116,9 +143,10 @@ useSeoMeta({
 })
 
 const search = () => {
-  list.value = []
   queryParams.pageNum = 1
   queryParams.showName = showName.value
+  finished.value = false
+  list.value = []
   getList()
 }
 
@@ -142,6 +170,7 @@ const handleFollow = async (item, i) => {
 
 // 刷新
 const onRefresh = () => {
+  refreshing.value = true
   queryParams.pageNum = 1
   list.value = []
   getList()
@@ -168,6 +197,8 @@ const getList = async () => {
       }
     })
 
+    console.log(dataList.length, '  length')
+
     if (Array.isArray(dataList) && dataList?.length) {
       list.value = list.value.concat(dataList)
     } else {
@@ -177,8 +208,11 @@ const getList = async () => {
     loading.value = false
     refreshing.value = false
     if (list.value.length >= totalCount) {
+      console.log('111')
+
       finished.value = true
     } else {
+      console.log('2222')
       finished.value = false
     }
   } catch (err) {
@@ -188,6 +222,31 @@ const getList = async () => {
   }
 }
 
+// 随机生成的唯一id
+function getLocalId() {
+  const random = Math.floor(Math.random() * 10000)
+  return Date.now() + '' + random
+}
+
+// 创建单聊的会话
+const createSingle = async (body) => {
+  body.groupId = getLocalId()
+  console.log(userInfo.value, 'userInfo.value')
+
+  body.sendUserId = userInfo.value.userId
+  const { data } = await request('/website/tourGroup/createMember', {
+    method: 'post',
+    body
+  })
+  if (data) {
+    navigateTo('/chat/single', {
+      groupId: data,
+      replace: true
+    })
+  }
+}
+
+// 数量转换
 function transNum(num) {
   if (isNaN(num)) return 0
   if (num < 10000) return num

+ 227 - 117
src/pages/profile/my-news/index.vue

@@ -1,5 +1,12 @@
 <template>
   <div class="w-full">
+    <audio
+      class="fixed top-0 left-0"
+      ref="audioRef"
+      :src="audioTips"
+      style="opacity: 0; z-index: -1"
+    ></audio>
+
     <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
       <van-sticky :offset-top="50">
         <div
@@ -32,7 +39,11 @@
         @click="onChatPage('/profile/system-message', {})"
         class="w-full relative h-82 flex justify-start items-center px-16"
       >
-        <van-badge v-if="messagesNumber > 0" v-bind="messageNumber(messagesNumber)" max="99">
+        <van-badge
+          v-if="chatList[0]?.unreadMessageCount"
+          v-bind="messageNumber(chatList[0]?.unreadMessageCount)"
+          max="99"
+        >
           <div
             class="w-48 h-48 bg-[#0052D9] rounded-full overflow-hidden flex justify-center items-center"
           >
@@ -48,27 +59,35 @@
           v-else
           class="w-48 h-48 bg-[#0052D9] rounded-full overflow-hidden flex justify-center items-center"
         >
-          <img class="w-24 h-24 shrink-0 object-cover" src="~/assets/img/chat/user.svg" alt="" />
+          <img class="w-24 h-24 shrink-0 object-cover" src="~/assets/img/chat/remind.svg" alt="" />
         </div>
 
         <div class="h-48 w-245 shrink-0 ml-12 flex flex-wrap items-end">
-          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">系统消息</h1>
+          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">
+            {{ chatList[0]?.groupName }}
+          </h1>
           <p class="line-clamp-1 h-20 text-sm text-black-6 leading-3xl">
-            你吃饭了么wwwwwdasdasdasdwwwwwwwwwwwwwwwwwwwwwwwssssssssssssssssssssssssssssss
+            {{ messageContentParse(chatList[0]?.lastMessage?.messageContent) }}
           </p>
         </div>
 
         <div class="w-35 h-48 shrink-0">
-          <p class="text-black/[0.6] text-sm text-end">02:06</p>
+          <p class="text-black/[0.6] text-sm text-end">
+            {{ createTimeSplit(chatList[0]?.lastMessage?.createTime) }}
+          </p>
         </div>
         <div class="absolute bottom-0 right-0 w-[96%] h-1 border-b-[1px]"></div>
       </div>
 
       <div
-        @click="onChatPage('/', {})"
+        @click="navigateTo('/follow?listType=fans')"
         class="w-full relative h-82 flex justify-start items-center px-16"
       >
-        <van-badge v-if="messagesNumber > 0" v-bind="messageNumber(messagesNumber)" max="99">
+        <van-badge
+          v-if="chatList[1]?.unreadMessageCount"
+          v-bind="messageNumber(chatList[1]?.unreadMessageCount)"
+          max="99"
+        >
           <div
             class="w-48 h-48 bg-[#FF9300] rounded-full overflow-hidden flex justify-center items-center"
           >
@@ -78,20 +97,25 @@
 
         <div
           v-else
+          @click="navigateTo('/follow?listType=fans')"
           class="w-48 h-48 bg-[#0052D9] rounded-full overflow-hidden flex justify-center items-center"
         >
           <img class="w-24 h-24 shrink-0 object-cover" src="~/assets/img/chat/user.svg" alt="" />
         </div>
 
         <div class="h-48 w-245 shrink-0 ml-12 flex flex-wrap items-end">
-          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">新增粉丝</h1>
+          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">
+            {{ chatList[1]?.groupName }}
+          </h1>
           <p class="line-clamp-1 h-20 text-sm text-black-6 leading-3xl">
-            你吃饭了么wwwwwdasdasdasdwwwwwwwwwwwwwwwwwwwwwwwssssssssssssssssssssssssssssss
+            {{ messageContentParse(chatList[1]?.lastMessage?.messageContent) }}
           </p>
         </div>
 
         <div class="w-35 h-48 shrink-0">
-          <p class="text-black/[0.6] text-sm text-end">02:06</p>
+          <p class="text-black/[0.6] text-sm text-end">
+            {{ createTimeSplit(chatList[1]?.lastMessage?.createTime) }}
+          </p>
         </div>
         <div class="absolute bottom-0 right-0 w-[96%] h-1 border-b-[1px]"></div>
       </div>
@@ -101,47 +125,84 @@
       >
         <van-badge v-if="messagesNumber > 0" v-bind="messageNumber(messagesNumber)" max="99">
           <div
-            class="w-48 h-48 bg-[#FF9300] rounded-full overflow-hidden flex justify-center items-center"
+            class="w-48 h-48 bg-[#FF476A] rounded-full overflow-hidden flex justify-center items-center"
           >
-            <img class="w-24 h-24 shrink-0 object-cover" src="~/assets/img/chat/user.svg" alt="" />
+            <img
+              class="w-24 h-24 shrink-0 object-cover"
+              src="~/assets/img/chat/weixin-shake.svg"
+              alt=""
+            />
           </div>
         </van-badge>
 
         <div
           v-else
-          class="w-48 h-48 bg-[#0052D9] rounded-full overflow-hidden flex justify-center items-center"
+          class="w-48 h-48 bg-[#FF476A] rounded-full overflow-hidden flex justify-center items-center"
         >
-          <img class="w-24 h-24 shrink-0 object-cover" src="~/assets/img/chat/user.svg" alt="" />
+          <img
+            class="w-24 h-24 shrink-0 object-cover"
+            src="~/assets/img/chat/weixin-shake.svg"
+            alt=""
+          />
         </div>
 
         <div class="h-48 w-245 shrink-0 ml-12 flex flex-wrap items-end">
-          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">互动消息</h1>
-          <p class="line-clamp-1 h-20 text-sm text-black-6 leading-3xl">收藏了你的游记</p>
+          <h1 class="line-clamp-1 w-full text-base text-black-3 font-semibold mb-4">
+            {{ chatList[2]?.groupName }}
+          </h1>
+          <p class="line-clamp-1 h-20 text-sm text-black-6 leading-3xl">
+            {{ messageContentParse(chatList[2]?.lastMessage?.messageContent) }}
+          </p>
         </div>
 
         <div class="w-35 h-48 shrink-0">
-          <p class="text-black/[0.6] text-sm text-end">02:06</p>
+          <p class="text-black/[0.6] text-sm text-end">
+            {{ createTimeSplit(chatList[2]?.lastMessage?.createTime) }}
+          </p>
         </div>
         <div class="absolute bottom-0 right-0 w-[96%] h-1 border-b-[1px]"></div>
       </div>
 
-      <!-- 置顶绘画列表 -->
-
-      <div v-if="activeNames" class="w-full">
-        <template v-for="(item, index) in pinnedList" :key="index">
-          <ProfileNewsGroupChat
-            :item-data="{ title: item }"
-            @on-chat-page="
-              onChatPage('/chat/group', { userId: userInfo.userId, groupId: '1877696775305945089' })
-            "
-            @on-no-bother="noBother(item)"
-            @on-conv-delete="convDelete()"
-          />
+      <!-- 置顶绘画列表  "-->
+      <div v-if="isTopList?.length && activeNames" class="w-full">
+        <template v-for="(item, index) in isTopList" :key="item?.id">
+          <template v-if="index > 2">
+            <!-- 单聊会话 -->
+            <ProfileNewsGroupChat
+              v-if="item?.noticeType == 2"
+              :item-data="{
+                ...item,
+                updateTime: createTimeSplit(item?.lastMessage?.updateTime)
+              }"
+              @on-chat-page="
+                onChatPage('/chat/group', { userId: user.userId, groupId: item?.groupId })
+              "
+              @on-no-bother="noBother(item)"
+              @on-is-top="onIsTop(item)"
+              @on-conv-delete="onIsShow(item)"
+            />
+
+            <!-- 群聊会话 -->
+            <ProfileNewsSingleChat
+              v-if="item?.noticeType == 1"
+              :item-data="{
+                ...item,
+                updateTime: createTimeSplit(item?.lastMessage?.updateTime)
+              }"
+              @on-chat-page="
+                onChatPage('/chat/single', { userId: userInfo.userId, groupId: item?.groupId })
+              "
+              @on-no-bother="noBother(item)"
+              @on-is-top="onIsTop(item)"
+              @on-conv-delete="onIsShow(item)"
+            />
+          </template>
+          <template v-else></template>
         </template>
       </div>
 
       <div
-        v-if="pinnedList.length >= 6"
+        v-if="isTopList.length >= 6"
         @click="activeNames = !activeNames"
         class="flex justify-between border items-center h-20 w-full p-16 box-border"
       >
@@ -151,22 +212,36 @@
         </div>
         <div class="w-16 h-16 shrink-0">
           <van-icon name="arrow" size="16" />
-          <!-- <img class="w-full h-full object-cover" src="" alt="" /> -->
         </div>
       </div>
 
-      <ProfileNewsGroupChat
-        @on-chat-page="
-          onChatPage('/chat/group', { userId: userInfo.userId, groupId: '1877349481146540033' })
-        "
-        @on-no-bother="noBother()"
-        @on-conv-delete="convDelete()"
-      />
-      <ProfileNewsSingleChat
-        @on-chat-page="onChatPage('/chat/single', { userId: userInfo.userId, singleId: '2' })"
-        @on-no-bother="noBother()"
-        @on-conv-delete="convDelete()"
-      />
+      <!-- 不置顶的会话列表 -->
+      <template v-for="(item, index) in pinnedList" :key="item?.id">
+        <ProfileNewsGroupChat
+          v-if="item?.noticeType == 2"
+          :item-data="{
+            ...item,
+            updateTime: createTimeSplit(item?.lastMessage?.updateTime)
+          }"
+          @on-chat-page="onChatPage('/chat/group', { userId: user.userId, groupId: item?.groupId })"
+          @on-no-bother="noBother(item)"
+          @on-is-top="onIsTop(item)"
+          @on-conv-delete="onIsShow(item)"
+        />
+        <ProfileNewsSingleChat
+          v-if="item?.noticeType == 1"
+          :item-data="{
+            ...item,
+            updateTime: createTimeSplit(item?.lastMessage?.updateTime)
+          }"
+          @on-chat-page="
+            onChatPage('/chat/single', { userId: user.userId, groupId: item?.groupId })
+          "
+          @on-no-bother="noBother(item)"
+          @on-is-top="onIsTop(item)"
+          @on-conv-delete="onIsShow(item)"
+        />
+      </template>
     </van-pull-refresh>
   </div>
 </template>
@@ -176,6 +251,8 @@ import comments from '~/assets/img/chat/comments-white.svg'
 import plaza from '~/assets/img/chat/guangchang.svg'
 import userAdd from '~/assets/img/chat/user-add.svg'
 
+import { messageContentParse } from '~/utils/detalTime.js'
+
 const actionsList = [
   { text: '创建群聊', icon: comments },
   { text: '群聊广场', icon: plaza },
@@ -184,58 +261,19 @@ const actionsList = [
 ]
 const userInfoStore = useUserInfoStore()
 const { userInfo } = storeToRefs(userInfoStore)
-const uploadUrl = `${import.meta.env.VITE_APP_BASE_URL}/website/tourMessage/upload`
+// const uploadUrl = `${import.meta.env.VITE_APP_BASE_URL}/website/tourMessage/upload`
 const chatStore = useChatStore()
-const { ws, curConversiton, receive, receiveGetter, connectSta, onNewMessage } =
+const { messages, user, connectSta, chatList, curConversiton, onNewMessage } =
   storeToRefs(chatStore)
-const user = computed(() => chatStore.user)
-
-// 消息接收者的用户id
-const getUserId = computed(() => curConversiton.value.toUserId)
-
-// 消息发送者:当前登录用户的加密id
-const sendUserId = computed(() => user.value.pass)
-
-// 会话id
-const groupId = computed(() => curConversiton.value.groupId)
-
-// 用户在群聊中艾特的人
-const specialUserId = ref('')
-
-// 用户输入的文本消息
-const messageContent = ref('')
-
-// 聊天类型 1单聊 2群聊 3系统消息 4关注信息
-const noticeType = computed(() => curConversiton.value.noticeType)
 
-onMounted(() => {
-  userInfoStore.getUserInfo()
-})
-
-useSeoMeta({
-  title: '我的消息'
-})
-
-// 获取连接状态
-const isConnected = computed(() => chatStore.isConnected)
-
-// 连接 WebSocket
-// const connectSocket = () => {
-//   chatStore.connect(`?userId=${userInfo.value.userId}`)
-// }
+// const user = computed(() => chatStore.user)
 
-// 发送测试消息
-// const sendTestMessage = () => {
-//   chatStore.sendMessage({ message: 'Hello WebSocket!' })
-// }
+// // 聊天类型 1单聊 2群聊 3系统消息 4关注信息
+// const noticeType = computed(() => curConversiton.value.noticeType)
 
-// 断开 WebSocket
-// const disconnectSocket = () => {
-//   chatStore.disconnect()
-// }
+const wsConnect = computed(() => connectSta.value)
 
-// 消息历史
-// const messages = computed(() => chatStore.wsService.value?.messages || [])
+const audioRef = ref(null)
 
 const finished = ref(false)
 
@@ -248,7 +286,9 @@ const showPopover = ref(false)
 const messagesNumber = ref(10)
 
 // 置顶列表
-const pinnedList = ref([1, 2, 3, 4, 5, 6, 7])
+const isTopList = ref([])
+const pinnedList = ref([])
+const pinnedSystemList = ref([]) //三个固定的消息
 
 // 个置顶聊天
 const collapse_text = '折叠置顶聊天'
@@ -259,40 +299,122 @@ const collapseTitle = ref(collapse_text)
 
 // 刷新
 const refreshing = ref(false)
+
+// 建立链接
+async function getUserInfo() {
+  const { data } = await request('/website/tourism/user/view')
+  chatStore.user = data
+  user.value = data
+  console.log(data, 'createConnection')
+
+  await chatStore.createConnection(data.pass)
+  chatStore.reqChatList()
+
+  console.log('用户信息:', chatStore.user)
+
+  // console.log('会话列表:', chatStore.chatList.value)
+}
+
+onMounted(() => {
+  getUserInfo()
+  if (wsConnect == 0) {
+    showToast('聊天网络连接中...')
+  } else if (wsConnect == 1) {
+    showToast(' 聊天正在连接中...')
+  } else if (wsConnect == 3) {
+    showToast(' 聊天连接已断开,请刷新页面重新连接,或稍后重试!')
+  } else if (wsConnect == 2) {
+  }
+
+  // chatStore.reqChatList()
+})
+
+useSeoMeta({
+  title: '我的消息'
+})
+
+watch(
+  chatList.value,
+  (newList, oldList) => {
+    // pinnedSystemList.value = newList.filter((el) => el.noticeType == 3)
+    pinnedList.value = newList.filter((el) => el.isTop != 1)
+    isTopList.value = newList.filter((el) => el.isTop == 1)
+
+    console.log(pinnedList.value, 'pinnedList')
+    console.log(isTopList.value, 'isTopList')
+    // console.log(newList, 'newList')
+    console.log(oldList, 'oldList')
+  },
+  { immediate: true }
+)
+
+// 时间的转换
+const createTimeSplit = (timer) => {
+  if (timer) {
+    return timer.split(' ')[1]
+  }
+}
 // 下拉刷新
 const onRefresh = () => {
   refreshing.value = true
-  //   getVisaOrderList()
+  chatStore.reqChatList()
 }
 
 // 打扰和免打扰得
 const noBother = (parmas) => {
-  if (parmas?.bother == false) {
-    parmas.bother = true
-  } else {
-    parmas.bother = false
-  }
+  handleBoolean({ groupId: parmas.groupId, isNotDisturb: parmas.isNotDisturb })
 }
 
-// 会话的删除
-const convDelete = (parmas) => {}
+// 是否置顶
+const onIsTop = (parmas) => {
+  handleBoolean({ groupId: parmas.groupId, isTop: parmas.isTop })
+}
+
+// 是否显示会话
+const onIsShow = (parmas) => {
+  handleBoolean({ groupId: parmas.groupId, isShow: parmas.isShow })
+}
+
+// 是否免打扰和 是否置顶 公共
+const handleBoolean = async (body) => {
+  try {
+    let { data } = await request('/website/tourMember/updateSingleTourMember', {
+      method: 'post',
+      body
+    })
+    if (data) {
+      chatStore.reqChatList()
+    }
+  } catch (error) {}
+}
 
 // 消息数量通知的展示  需要动态的展示
 const messageNumber = (content) => {
   let messageNumberObj = {}
-  if (content <= 1) {
+
+  if (content != null || content != undefined || content != '') {
+    if (content <= 1) {
+      messageNumberObj = {
+        offset: [-5, 4],
+        dot: true,
+        content
+      }
+    }
+    if (content > 1) {
+      messageNumberObj = {
+        offset: [-10, 7],
+        content
+      }
+    }
+  } else {
+    content = 0
     messageNumberObj = {
       offset: [-5, 4],
       dot: true,
       content
     }
   }
-  if (content > 1) {
-    messageNumberObj = {
-      offset: [-10, 7],
-      content
-    }
-  }
+
   return messageNumberObj
 }
 
@@ -311,18 +433,6 @@ const onSelect = (action) => {
   if (action.text == '加入群聊') onChatPage('/scan', {})
   if (action.text == '添加用户') onChatPage('/chat/user-add', {})
 }
-
-async function getList() {
-  try {
-    let {
-      data: { dataList }
-    } = await request('/website/tourism/fans/getTourMemberList')
-  } catch (error) {}
-}
-
-onMounted(() => {
-  getList()
-})
 </script>
 
 <style lang="scss" scoped></style>

+ 9 - 5
src/pages/profile/system-message/details.vue

@@ -1,6 +1,7 @@
 <template>
   <div class="box-border p-16 mb-8">
-    <h1 class="font-medium mb-8 text-2xl text-black-3 leading-7xl">
+    <ChatHeaderBar title="系统消息详情" />
+    <h1 class="font-medium pt-50 mb-8 text-2xl text-black-3 leading-7xl">
       在克鲁舍瓦茨停留半天,于是就去了这家新开的柴犬餐馆,非常好吃推荐给大家
     </h1>
 
@@ -13,8 +14,12 @@
 <script setup>
 const id = useRouteQuery('id')
 
+definePageMeta({
+  layout: false
+})
+
 useSeoMeta({
-  title: '系统消息详情'
+  title: '系统消息'
 })
 
 onMounted(() => {
@@ -25,10 +30,9 @@ const itemData = ref(null)
 
 const loading = ref(false)
 
-const getData = () => {
-  // async
-  //  const {data}= await request()
+// const { data } = await useMyFetch(`website/basic/directoryList?isHotspot=1`)
 
+const getData = () => {
   itemData.value = {
     content:
       '这家餐馆位于老城区一条安静的小巷里,门口挂着一块简单的木制招牌,写着“柴犬餐馆”。听到这个名字,我顿时被吸引住了——这会是一家以柴犬为主题的餐厅吗?推门进去,果然映入眼帘的是几张柴犬的照片和玩偶装饰,整体环境散发出一种温馨的氛围,仿佛是来到了一家好友的家中。 我点了一份推荐的招牌菜,是一道用当地香料腌制的烤肉,搭配着新鲜的蔬菜和自制的酱料。食物端上来时,满室飘散着烤肉的香气,外焦里嫩的口感配合着独特的酱料,让人一口咬下去便沉浸在美味之中。桌旁的小柴犬时不时抬头看看我,好像在询问我是否喜欢这里的食物。 虽然只是短短的半天停留,但在这里,我感受到了克鲁舍瓦茨的另一面——不仅是历史的厚重感,更有着现代与温馨的碰撞。这家柴犬餐馆成为了这段旅途中温暖的回忆,不仅仅因为食物的美味,还因为这里的氛围带给人一种轻松和快乐。口咬下去便沉浸在美味之中。桌旁的小柴犬时不时抬头看看我,好像在询问我是否喜欢这里的食物。 虽然只是短短的半天停留,但在这里,我感受到了克鲁舍瓦茨的另一面——不仅是历史的厚重感,更有着现代与温馨的碰撞。这家柴犬餐馆成为了这段旅途中温暖的回忆,不仅仅因为食物的美味,还因为这里的氛围带给人一种轻松和快乐。口咬下去便沉浸在美味之中。桌旁的小柴犬时不时抬头看看我,好像在询问我是否喜欢这里的食物。 虽然只是短短的半天停留,但在这里,我感受到了克鲁舍瓦茨的另一面——不仅是历史的厚重感,更有着现代与温馨的碰撞。'

+ 30 - 5
src/pages/profile/system-message/index.vue

@@ -1,14 +1,17 @@
 <template>
-  <div style="height: calc(100vh - 50px)" class="w-full bg-[#F7F8FA]">
-    <div v-for="(item, index) in [1, 2, 3, 5]" @click="onChatPage('0')" :key="index" class="w-full">
-      <p class="w-full pt-16 mb-12 text-center text-black-9 text-sm">{{ '2001/09/24 20:22' }}</p>
+  <div style="height: calc(100vh - 40px)" class="w-full bg-[#F7F8FA]">
+    <ChatHeaderBar title="系统消息列表" />
+
+    <div v-for="item in listData" @click="onChatPage(item?.id)" :key="item.id" class="w-full pt-40">
+      <p class="w-full pt-16 mb-12 text-center text-black-9 text-sm">
+        {{ formatTimestamp(item?.createTime) }}
+      </p>
       <div class="w-[91.2%] box-border h-103 mx-16 bg-white p-16">
         <h1 class="text-black w-full line-clamp-1 text-2xl font-semibold mb-8">
           {{ item?.title ? item?.title : '标题标题' }}
         </h1>
         <p class="line-clamp-2 w-full leading-3xl text-black-9 text-sm">
-          {{ 'ssss' }}
-          大苏打实打实科技大厦十八号大家开始电话卡设计的哈克阿坎德哈吉斯等哈考试大纲啊大噶说的话噶是售价高达九十
+          {{ item?.messageContent }}
         </p>
       </div>
     </div>
@@ -25,6 +28,28 @@ const onChatPage = (query) => {
     path: `/profile/system-message/details?id=${query}`
   })
 }
+
+definePageMeta({
+  layout: false
+})
+
+const listData = ref([])
+
+onMounted(() => {
+  getList()
+})
+
+const getList = async () => {
+  const { data } = await request('/website/tourMessage/getsListSystemMessages', {
+    query: {
+      TypeId: 3
+    }
+  })
+
+  if (Array.isArray(data) && data.length) {
+    listData.value = data
+  }
+}
 </script>
 
 <style lang="scss" scoped></style>

+ 111 - 39
src/utils/detalTime.js

@@ -1,55 +1,127 @@
 /*
  * 创建时间和现在时间作对比
  * @param time 时间戳
- * 
+ *
  * */
 export function beforeTime(time) {
-    let way = Date.parse(new Date()) / 1000 - time;
-    let r = '';
-    if (way < 60) {
-        r = '刚刚';
-    } else if (way >= 60 && way < 3600) {
-        r = Math.floor(way / 60) + '分钟前';
-    } else if (way >= 3600 && way < 86400) {
-        r = Math.floor(way / 3600) + '小时前';
-    } else if (way >= 86400 && way < 2592000) {
-        r = Math.floor(way / 86400) + '天前';
-    } else if (way >= 2592000 && way < 15552000) {
-        r = Math.floor(way / 2592000) + '个月前';
-    } else if (time === 0 || !time) {
-        r = '暂无';
-    } else {
-        r = dateChange('Y-m-d', time);
-    }
-    return r;
+  let way = Date.parse(new Date()) / 1000 - time
+  let r = ''
+  if (way < 60) {
+    r = '刚刚'
+  } else if (way >= 60 && way < 3600) {
+    r = Math.floor(way / 60) + '分钟前'
+  } else if (way >= 3600 && way < 86400) {
+    r = Math.floor(way / 3600) + '小时前'
+  } else if (way >= 86400 && way < 2592000) {
+    r = Math.floor(way / 86400) + '天前'
+  } else if (way >= 2592000 && way < 15552000) {
+    r = Math.floor(way / 2592000) + '个月前'
+  } else if (time === 0 || !time) {
+    r = '暂无'
+  } else {
+    r = dateChange('Y-m-d', time)
+  }
+  return r
 }
 
 /*
  * 返回时间年月日时分秒
  * @param {date}  时间戳
  * @param {fmt}   转换格式  'yyyy-MM-dd hh:mm:ss'
- * 
+ *
  * */
 export function formatDate(date, fmt) {
-    if (/(y+)/.test(fmt)) {
-        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
-    }
-    var o = {
-        'M+': date.getMonth() + 1,
-        'd+': date.getDate(),
-        'h+': date.getHours(),
-        'm+': date.getMinutes(),
-        's+': date.getSeconds()
-    };
-    for (let k in o) {
-        if (new RegExp(`(${k})`).test(fmt)) {
-            let str = o[k] + '';
-            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
-        }
+  if (/(y+)/.test(fmt)) {
+    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+  }
+  var o = {
+    'M+': date.getMonth() + 1,
+    'd+': date.getDate(),
+    'h+': date.getHours(),
+    'm+': date.getMinutes(),
+    's+': date.getSeconds()
+  }
+  for (let k in o) {
+    if (new RegExp(`(${k})`).test(fmt)) {
+      let str = o[k] + ''
+      fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
     }
-    return fmt;
-};
+  }
+  return fmt
+}
 
 function padLeftZero(str) {
-    return ('00' + str).substr(str.length);
-}
+  return ('00' + str).substr(str.length)
+}
+
+export function formatTimestamp(timestamp) {
+  const now = new Date()
+  const targetDate = new Date(timestamp)
+
+  // 时间差
+  const timeDifference = now - targetDate
+
+  if (isNaN(timeDifference)) {
+    return ''
+  }
+
+  // 年月日时分
+  const minutes = Math.floor(timeDifference / 1000 / 60)
+  const hours = targetDate.getHours()
+  const day = targetDate.getDate()
+  const month = targetDate.getMonth() + 1 // 月份从0开始,所以加1
+  const year = targetDate.getFullYear()
+
+  // 获取当前日期的年月日
+  const currentYear = now.getFullYear()
+  const currentMonth = now.getMonth() + 1
+  const currentDay = now.getDate()
+
+  // 补零函数
+  const padZero = (num) => num.toString().padStart(2, '0')
+
+  // 小于1分钟
+  if (minutes < 1) {
+    return '刚刚'
+  }
+
+  // 同一天的不同时间段
+  if (year === currentYear && targetDate.getDate() === currentDay) {
+    const formattedHour = padZero(hours)
+    const formattedMinute = padZero(targetDate.getMinutes())
+
+    if (hours < 6) {
+      return `凌晨 ${formattedHour}:${formattedMinute}`
+    } else if (hours < 12) {
+      return `上午 ${formattedHour}:${formattedMinute}`
+    } else if (hours < 18) {
+      return `下午 ${formattedHour - 12}:${formattedMinute}`
+    } else {
+      return `晚上 ${formattedHour - 12}:${formattedMinute}`
+    }
+  }
+
+  // 昨天
+  const yesterday = new Date(now)
+  yesterday.setDate(now.getDate() - 1)
+  if (year === currentYear && targetDate.getDate() === yesterday.getDate()) {
+    return '昨天'
+  }
+
+  // 同年
+  if (year === currentYear) {
+    return `${month}月${day}日`
+  }
+
+  // 大于一年
+  return `${year}年${padZero(month)}月${padZero(day)}日`
+}
+
+// 消息的内容转换
+export function messageContentParse(messageContent) {
+  let content = ''
+  if (messageContent) {
+    content = JSON.parse(messageContent)
+  }
+  return content?.messageContent
+}