123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- <template>
- <div class="w-full">
- <van-dropdown-menu fixed ref="interactionDropdownMenuRef" active-color="#FF9300">
- <van-dropdown-item
- v-model="interactionIndex"
- @change="onInteractionFilterClose"
- :options="
- interactionDropdownMenuList.map((item, index) => {
- if (item.value == interactionIndex) {
- item.icon = item.iconO
- return item
- } else {
- item.icon = item.iconM
- return item
- }
- })
- "
- ref="interactionItemRef"
- >
- <template #title class="relative" active-color="#FF9300">
- <div class="font-semibold text-base">
- <NuxtLink :to="'/profile/my-news'" class="absolute top-0 -left-135">
- <van-icon name="arrow-left" size="24" color="#000000" />
- </NuxtLink>
- {{ interactionTitle }}
- </div>
- </template>
- </van-dropdown-item>
- </van-dropdown-menu>
- <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
- <div class="w-full h-[100vh] pt-10">
- <ChatEmpty
- v-if="!interactionList.length && !loading"
- image="conment"
- :title="`暂无${interactionTitle}`"
- />
- <van-list
- v-if="interactionList.length"
- v-model:loading="loading"
- :finished="finished"
- :immediate-check="false"
- finished-text=""
- @load="handleCurrentChange"
- >
- <template v-for="item in interactionList" :key="item?.id">
- <!-- 点赞与收藏 -->
- <ProfileInteractionMessageLikesandFavorites
- v-if="item.noticeType == 5 || item.noticeType == 7"
- :item-data="{
- ...item,
- messageContent:
- actionTypeList[item.noticeType].text + businessTypeList[item.businessType].text
- }"
- ></ProfileInteractionMessageLikesandFavorites>
- <!-- 艾特 -->
- <ProfileInteractionMessageEit
- v-if="item.noticeType == 10"
- :item-data="{
- ...item,
- messageContent:
- actionTypeList[item.noticeType].text + businessTypeList[item.businessType].text
- }"
- ></ProfileInteractionMessageEit>
- <!-- 收到的评论 是评论还是 回复 -->
- <ProfileInteractionMessageReceiveComment
- v-if="
- (item.noticeType == 6 && interactionIndex == 7) ||
- (item.noticeType == 12 && interactionIndex == 7)
- "
- :item-data="{
- ...item,
- messageContent: messageContentParse(item?.messageContent).messageContent
- }"
- :user-info="userInfo"
- @on-add-reply="addReply(item, item.reviewId)"
- />
- <!-- 发出的评论 -->
- <ProfileInteractionMessageSendComment
- v-if="
- (item.noticeType == 6 && interactionIndex == 8) ||
- (item.noticeType == 12 && interactionIndex == 8)
- "
- :item-data="{
- ...item,
- messageContent: messageContentParse(item?.messageContent)
- }"
- />
- </template>
- </van-list>
- <!-- <div
- v-if="showInput"
- @click="handleBlur"
- class="w-[100vw] h-[100vh] fixed top-0 border-[#000] left-0 z-100 bg-[#000]/[0.1]"
- >
- <div @click.stop="" class="fixed bottom-0 left-0 w-full bg-[#fff] pt-10 pb-30 z-52">
- <div class="flex items-start">
- <div
- class="relative bg-[#F3F3F3] flex-1 ml-12 mr-12 pl-5 pr-5 pt-4 pb-4 rounded-[4px] h-50 border flex items-center justify-between"
- >
- <textarea
- v-model="commentValue"
- ref="textareaRef"
- :placeholder="
- replyComment?.id ? `回复:${replyComment?.commentUserIdDictMap?.name}` : ''
- "
- @focus="textareaFocus"
- class="ml-8 flex-1 h-full bg-black/[0]"
- maxlength="5000"
- style="resize: none"
- ></textarea>
- <img @click="openEmoji" src="~/assets/img/yj/emoji.png" class="w-22 h-22" alt="" />
- </div>
- <div
- @click="addComment"
- class="py-6 px-16 mr-12 bg-[#FD9A00] text-[#fff] flex items-center justify-center rounded-full shrink-0"
- >
- 发送
- </div>
- </div>
- <div v-if="showEmoji" class="h-[300px] bg-[#fff] overflow-auto">
- <div @click="closeEmojiBox" class="flex justify-end pr-15 text-[#999] text-[12px]">
- 收起表情
- </div>
- <div class="flex items-center flex-wrap">
- <div
- v-for="(item, index) in emojiJson"
- :key="index"
- class="hover:bg-[#ddd] text-[22px] w-[10%] aspect-[1/1] flex items-center justify-center"
- >
- <div @click="selectEmoji(index)" v-html="coveredContent(index)"></div>
- </div>
- </div>
- </div>
- </div>
- </div> -->
- </div>
- </van-pull-refresh>
- </div>
- </template>
- <script setup>
- import { messageContentParse } from '~/utils/detalTime'
- import defaultImg from '~/assets/img/comment/H5_default.png'
- import commentsBlack from '~/assets/img/chat/comments-black.svg'
- import commentsOrange from '~/assets/img/chat/comments-orange.svg'
- import like from '~/assets/img/chat/like.svg'
- import likeOrange from '~/assets/img/chat/like-orange.svg'
- import eit from '~/assets/img/chat/tiji.svg'
- import eitOrange from '~/assets/img/chat/tiji-orange.svg'
- import comment from '~/assets/img/chat/comment.svg'
- import commentOrange from '~/assets/img/chat/comment-orange.svg'
- import medicalFiles from '~/assets/img/chat/medical-files.svg'
- import medicalFilesOrange from '~/assets/img/chat/medical-files-orange.svg'
- import send from '~/assets/img/chat/send.svg'
- import sendOrange from '~/assets/img/chat/send-orange.svg'
- import emojiJson from '../../yj/emoji.json'
- const authStore = useAuthStore()
- const { token } = storeToRefs(authStore)
- onMounted(() => {
- getUserInfo()
- getList()
- })
- // noticeType 6 是评论 12 是回复
- // 1单聊 2群聊 3系统消息 4关注消息 5点赞通知 6评论通知 7收藏通知 8浏览通知 9访问主页通知 10评论区艾特通知 11文章内艾特通知 12回复评论通知
- const actionTypeList = {
- 4: { text: '关注了你' },
- 5: { text: '赞了你的' },
- 6: { text: '评论' },
- 7: { text: '收藏了你的' },
- 8: { text: '浏览了你的' },
- 9: { text: '访问你' },
- 10: { text: '提到了你' },
- 11: { text: '提到了你' },
- 12: { text: '回复' }
- }
- // 1 游记
- const businessTypeList = {
- 1: { text: '游记' },
- 2: { text: '评论' }
- }
- definePageMeta({
- layout: false
- })
- // 0未关注 1已关注 2已经互关 3我自己 4被关注 focusStatus字段
- // 条件查询 互动消息--> 5赞与收藏 6提及 7收到的评论 8发出的评论
- const interactionDropdownMenuList = [
- {
- text: '全部消息',
- value: '-1',
- icon: commentsBlack,
- iconM: commentsBlack,
- iconO: commentsOrange
- },
- { text: '赞与收藏', value: 5, icon: like, iconM: like, iconO: likeOrange },
- {
- text: '提及',
- value: 6,
- icon: eit,
- iconM: eit,
- iconO: eitOrange
- },
- // { text: '我的评论', value: 0, icon: comment, iconM: comment, iconO: commentOrange },
- {
- text: '收到的评论',
- value: 7,
- icon: medicalFiles,
- iconM: medicalFiles,
- iconO: medicalFilesOrange
- },
- { text: '发出的评论', value: 8, icon: send, iconM: send, iconO: sendOrange }
- ]
- const pageNum = ref(1)
- const finished = ref(false)
- const loading = ref(false)
- const refreshing = ref(false)
- // 互动消息的索引
- const interactionIndex = ref('-1')
- const interactionTitle = ref('全部消息')
- const interactionDropdownMenuRef = ref(null)
- const interactionItemRef = ref(null)
- // 评论的列表
- const interactionList = ref([])
- // 下拉菜单的方法
- function onInteractionFilterClose(value) {
- interactionIndex.value = value
- interactionTitle.value = interactionDropdownMenuList.find((item) => item.value == value).text
- interactionList.value = []
- getList()
- }
- useSeoMeta({
- title: '互动消息'
- })
- // 获取用户信息
- const userInfo = ref({})
- async function getUserInfo() {
- if (!token.value) return (userInfo.value = {})
- request('/website/tourism/user/view').then(
- (res) => {
- userInfo.value = res.data || {}
- },
- () => {
- userInfo.value = {}
- }
- )
- }
- // 转换评论中的一些非字符emoji
- function coveredContent(val) {
- if (!val) return ''
- return val.replace(/\[.*?]/g, function (str) {
- const baseApi = import.meta.env.VITE_APP_EMOJI_API
- const emojiName = emojiJson[str]
- if (!emojiName) return str
- return `<img src=${baseApi}${emojiJson[str]} style="width: 20px; height: 20px;display: inline-block; vertical-align: middle"/>`
- })
- }
- // 获取互动的全部消息
- const getList = async () => {
- try {
- loading.value = true
- const {
- data: { dataList, totalCount }
- } = await request(`/website/tourMessage/getInteractionList`, {
- query: {
- pageNum: pageNum.value,
- pageSize: 10,
- noticeType: interactionIndex.value
- }
- })
- if (!Array.isArray(dataList) || !dataList.length) return (interactionList.value = [])
- interactionList.value = interactionList.value.concat(dataList)
- refreshing.value = false
- if (interactionList.value.length >= totalCount) {
- finished.value = true
- } else {
- finished.value = false
- }
- } finally {
- refreshing.value = false
- loading.value = false
- }
- }
- // 点赞的的方法
- const textareaRef = ref(null)
- // 评论内容
- const commentValue = ref('')
- // 是否展示表情
- const showEmoji = ref(false)
- // 回复评论
- const replyComment = ref({})
- // 显示输入框
- const showInput = ref(false)
- // 发布评论
- const canAddComment = ref(true)
- function addReply(item, reviewId) {
- if (!token.value) {
- showConfirmDialog({
- showConfirmDialog: true,
- title: '提示',
- message: '登录后可以回复评论',
- theme: 'round-button'
- }).then(async () => {
- navigateTo({ path: '/login' })
- })
- return
- }
- showInput.value = true
- nextTick(() => {
- textareaRef.value?.focus()
- })
- replyComment.value = item
- if (item.businessType == 1) {
- // 业务是游记
- replyComment.value.travelNoteId = item.businessId
- }
- reviewId && (replyComment.value.reviewId = item.reviewId)
- }
- // 文本域失焦
- function handleBlur() {
- showEmoji.value = false
- textareaRef.value?.blur()
- showInput.value = false
- replyComment.value = {}
- }
- const cursorIndex = ref(0)
- // 打开表情
- function openEmoji() {
- nextTick(() => {
- textareaRef.value.selectionStart && (cursorIndex.value = textareaRef.value.selectionStart)
- showEmoji.value = true
- })
- }
- // 收起表情
- function closeEmojiBox() {
- showEmoji.value = false
- nextTick(() => {
- textareaRef.value.focus()
- })
- }
- // 选择表情
- function selectEmoji(emojiStr = '') {
- const length = emojiStr.length
- commentValue.value =
- commentValue.value.slice(0, cursorIndex.value) +
- emojiStr +
- commentValue.value.slice(cursorIndex.value)
- nextTick(() => {
- cursorIndex.value += length
- textareaRef.value.setSelectionRange(cursorIndex.value, cursorIndex.value)
- })
- }
- // 回复评论
- async function addComment() {
- if (!canAddComment.value) return
- if (!token.value) {
- showConfirmDialog({
- showConfirmDialog: true,
- title: '提示',
- message: '登录后可以发布评论',
- theme: 'round-button'
- }).then(async () => {
- navigateTo({ path: '/login' })
- })
- return
- }
- if (!commentValue.value.trim()) {
- showToast('评论内容不能为空!')
- return
- }
- canAddComment.value = false
- const body = { travelNoteId: replyComment.value.travelNoteId, commentContent: commentValue.value }
- if (replyComment.value.id) {
- body.replyCommentId = replyComment.value.id
- }
- request('/website/comment/tourTravelNotesComment/add', { method: 'post', body })
- .then(() => {
- commentValue.value = ''
- showToast('评论成功')
- // getList()
- showInput.value = false
- showEmoji.value = false
- })
- .finally(() => (canAddComment.value = true), (replyComment.value = {}), (cursorIndex.value = 0))
- }
- // 下拉刷新
- const onRefresh = () => {
- refreshing.value = true
- interactionList.value = []
- getList()
- }
- // 改变页数
- const handleCurrentChange = () => {
- finished.value = true
- pageNum.value += 1
- getList()
- }
- </script>
- <style lang="scss" scoped>
- ::v-deep .van-cell__left-icon {
- display: flex;
- align-items: center;
- }
- </style>
|