|
@@ -1,129 +1,177 @@
|
|
|
<template>
|
|
|
<div>
|
|
|
<div v-if="['success'].includes(status)" @click="pageClick">
|
|
|
+ <van-cell center size="large" :title="userInfo.showName">
|
|
|
+ <template #icon>
|
|
|
+ <div class="w-30 h-30 rounded-full mr-8 overflow-hidden">
|
|
|
+ <img
|
|
|
+ v-if="userInfo.headImageUrl"
|
|
|
+ class="w-full h-full object-cover"
|
|
|
+ :src="userInfo.headImageUrl"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <img v-else class="w-full h-full object-cover" :src="defaultAvatar" alt="" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #label>
|
|
|
+ <span class="mr-8">{{ detailData?.endPlaceDictMap?.name || '' }}</span>
|
|
|
+ <span>{{ detailData?.endPlaceDictMap?.name || '' }}</span>
|
|
|
+ </template>
|
|
|
+ <template #value>
|
|
|
+ <div
|
|
|
+ :class="`mr-7 inline-block h-28 box-border rounded-full px-14 py-3 text-base font-semibold border ${followState(detailData.status).color}`"
|
|
|
+ >
|
|
|
+ {{ followState(detailData.status).text }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #right-icon>
|
|
|
+ <span
|
|
|
+ @click="
|
|
|
+ () => {
|
|
|
+ let origin = location.origin
|
|
|
+ let url = `${origin}/yj/${id}`
|
|
|
+
|
|
|
+ navigator.clipboard.writeText(url).then(
|
|
|
+ () => {
|
|
|
+ showNotify({ type: 'success', message: '链接已复制' })
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ showNotify({ message: '链接复制失败' })
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ "
|
|
|
+ class="iconfont icon-share text-black-9"
|
|
|
+ style="font-size: 26px"
|
|
|
+ ></span>
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <div class="relative w-full">
|
|
|
+ <van-swipe
|
|
|
+ @change="(i) => (swipeItemIndex = i + 1)"
|
|
|
+ :autoplay="3000"
|
|
|
+ indicator-color="#FF9300"
|
|
|
+ style="--van-swipe-indicator-margin: 8px"
|
|
|
+ >
|
|
|
+ <template v-if="detailData?.imgUrls && detailData?.imgUrls.length">
|
|
|
+ <van-swipe-item
|
|
|
+ v-for="image in detailData?.imgUrls"
|
|
|
+ :key="image"
|
|
|
+ @click="
|
|
|
+ showImagePreview({
|
|
|
+ images: detailData?.imgUrls,
|
|
|
+ startPosition: swipeItemIndex
|
|
|
+ })
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div class="aspect-[375/502] w-full">
|
|
|
+ <img class="w-full h-full object-cover" :src="image" />
|
|
|
+ </div>
|
|
|
+ </van-swipe-item>
|
|
|
+ </template>
|
|
|
+ <van-swipe-item v-else>
|
|
|
+ <img
|
|
|
+ src="~/assets/img/note-create/note_create_banner_bg.png"
|
|
|
+ class="aspect-[375/502] w-full object-cover"
|
|
|
+ />
|
|
|
+ </van-swipe-item>
|
|
|
+ </van-swipe>
|
|
|
+ <div
|
|
|
+ v-if="detailData?.imgUrls.length"
|
|
|
+ class="absolute top-10 right-20 z-1 w-37 h-24 rounded-full bg-black/[0.3] text-white flex justify-center items-center text-sm"
|
|
|
+ >
|
|
|
+ {{ swipeItemIndex }}/{{ detailData?.imgUrls.length }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div class="p-10">
|
|
|
- <img v-if="Array.isArray(detailData?.tourismUrlsAfterConvert)" :src="detailData?.tourismUrlsAfterConvert[0]" class="aspect-[316/204] w-full object-cover rounded" />
|
|
|
- <div class="flex mt-10">
|
|
|
- <img src="~/assets/img/article_title.png" class="w-[32px] h-[32px] shrink-0" alt="">
|
|
|
+ <div class="flex">
|
|
|
+ <img src="~/assets/img/article_title.png" class="w-[32px] h-[32px] shrink-0" alt="" />
|
|
|
<div class="ml-10 text-[16px] text-[#333] leading-[28px] font-bold">
|
|
|
<span v-if="detailData.isOrigin == 1" class="text-[#FD9A00]">【原创】</span>
|
|
|
{{ detailData.projectTitle }}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="flex justify-end text-[#999] text-[12px]">
|
|
|
- {{ detailData.createTime }}
|
|
|
- </div>
|
|
|
- <div class="relative pt-15 pb-15 mt-8 rounded pl-20 text-[#4B99EA] text-[12px]"
|
|
|
- :style="{ background: `url(${dashBorder2})`, backgroundSize: '100% 100%' }">
|
|
|
- <div class="">
|
|
|
- <van-row>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/date.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">出发时间/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.departureTime || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/time.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">出发天数/</div>
|
|
|
- <div class="leading-[20px] flex-1 ">{{ detailData?.countTimes || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- </van-row>
|
|
|
|
|
|
- </div>
|
|
|
- <div class="mt-24">
|
|
|
- <van-row>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/relationship.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">人物关系/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.role || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/money.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">人均费用/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.averageCost || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- </van-row>
|
|
|
- </div>
|
|
|
- <div class="mt-24">
|
|
|
- <van-row>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/plan.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">出行方式/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.travelModeDictMap?.name || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/target.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">目的地/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.endPlaceDictMap?.name || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- </van-row>
|
|
|
- </div>
|
|
|
- <div class="mt-24">
|
|
|
- <van-row>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/person.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">游玩人数/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.travelNumber || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- <van-col span="12">
|
|
|
- <div class="w-[90%] flex text-[#FD9A00]">
|
|
|
- <img class="w-[20px] h-[20px] mr-5" src="~/assets/img/yj/star.png" alt="">
|
|
|
- <div class="font-bold leading-[20px]">推荐指数/</div>
|
|
|
- <div class="leading-[20px] flex-1">{{ detailData?.recommendationRate || '' }}</div>
|
|
|
- </div>
|
|
|
- </van-col>
|
|
|
- </van-row>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
<div class="mt-10 w-full" v-for="con in detailData.travelNotesContent" :key="con.id">
|
|
|
<template v-if="con.type == 'image'">
|
|
|
- <img :src="con.content" class="w-full rounded-xl" alt="">
|
|
|
+ <img :src="con.content" class="w-full rounded-xl" alt="" />
|
|
|
</template>
|
|
|
<template v-else>
|
|
|
<div class="w-full" style="word-wrap: break-word" v-html="con.content"></div>
|
|
|
</template>
|
|
|
</div>
|
|
|
|
|
|
- <div class="flex justify-end items-center text-[14px] text-[#999] mt-10 ">
|
|
|
+ <div class="text-sm text-black-6 py-12 box-border">
|
|
|
+ <span class="mr-8">出发时间{{ contentIsEmpty(detailData?.departureTime) }}</span>
|
|
|
+ <span class="mr-8">出行方式{{ contentIsEmpty(detailData?.travelMode) }}</span>
|
|
|
+ <span class="mr-8">出发天数{{ contentIsEmpty(detailData?.countTimes) }}</span>
|
|
|
+ <span class="mr-8">游玩人数{{ contentIsEmpty(detailData?.travelNumber) }}</span>
|
|
|
+ <span class="mr-8">人物关系{{ contentIsEmpty(detailData?.role) }}</span>
|
|
|
+ <span class="mr-8">人均费用{{ contentIsEmpty(detailData?.averageCost) }}</span>
|
|
|
+ <span class="mr-8">推荐指数{{ contentIsEmpty(detailData?.recommendationRate) }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <van-cell
|
|
|
+ style="--van-cell-background: #f5f5f5"
|
|
|
+ center
|
|
|
+ is-link
|
|
|
+ class="rounded-lg"
|
|
|
+ value="45人"
|
|
|
+ >
|
|
|
+ <template #icon>
|
|
|
+ <div class="w-30 h-30 overflow-hidden rounded-full mr-8">
|
|
|
+ <img class="w-full h-full object-cover" src="" alt="" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #title>
|
|
|
+ <h1 class="text-sm text-black-3">{{ '群聊' }}</h1>
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+
|
|
|
+ <div v-if="detailData.createTime" class="text-black-9 text-sm py-12 border-b-[1px]">
|
|
|
+ {{ detailData.createTime }} 发布
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="flex justify-end items-center text-[14px] text-[#999] mt-10">
|
|
|
<div class="flex items-center mr-10">
|
|
|
- <van-icon name="eye-o" class="mr-5" />{{ detailData.pageViewCount }}
|
|
|
+ <van-icon name="eye-o" class="mr-5" />
|
|
|
+ {{ detailData.pageViewCount }}
|
|
|
</div>
|
|
|
- <div @click="doStar" class="flex items-center mr-10" :style="{ color: detailData.isLike ? '#FD9A00' : '' }">
|
|
|
+ <div
|
|
|
+ @click="doStar"
|
|
|
+ class="flex items-center mr-10"
|
|
|
+ :style="{ color: detailData.isLike ? '#FD9A00' : '' }"
|
|
|
+ >
|
|
|
<van-icon v-if="detailData.isLike" name="good-job" class="mr-5" />
|
|
|
<van-icon v-else name="good-job-o" class="mr-5" />
|
|
|
{{ detailData.likeCount }}
|
|
|
</div>
|
|
|
- <div class="flex items-center mr-10" @click="handleCollect" :style="{ color: isCollect ? '#FD9A00' : '' }">
|
|
|
+ <div
|
|
|
+ class="flex items-center mr-10"
|
|
|
+ @click="handleCollect"
|
|
|
+ :style="{ color: isCollect ? '#FD9A00' : '' }"
|
|
|
+ >
|
|
|
<van-icon v-if="isCollect" name="star" class="mr-5" />
|
|
|
<van-icon v-else name="star-o" class="mr-5" />
|
|
|
收藏
|
|
|
</div>
|
|
|
|
|
|
<div @click="share" class="flex items-center">
|
|
|
- <img src="~/assets/img/yj/share.png" alt="" class="w-[12px] h-[12px] mr-5">分享
|
|
|
+ <img src="~/assets/img/yj/share.png" alt="" class="w-[12px] h-[12px] mr-5" />
|
|
|
+ 分享
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div v-if="detailData?.contactCodeConvert"
|
|
|
- class="flex items-center h-[112px] border rounded-[20px] overflow-hidden mt-10">
|
|
|
- <div class="w-[112px] h-full bg-[#F5F5F5] flex items-center justify-center rounded-[20px]">
|
|
|
- <img class="h-[80%] aspect-[1/1] " :src="detailData?.contactCodeConvert" alt="">
|
|
|
+ <div
|
|
|
+ v-if="detailData?.contactCodeConvert"
|
|
|
+ class="flex items-center h-[112px] border rounded-[20px] overflow-hidden mt-10"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="w-[112px] h-full bg-[#F5F5F5] flex items-center justify-center rounded-[20px]"
|
|
|
+ >
|
|
|
+ <img class="h-[80%] aspect-[1/1]" :src="detailData?.contactCodeConvert" alt="" />
|
|
|
</div>
|
|
|
<div class="flex items-center ml-15">
|
|
|
- <img src="~/assets/img/yj/leftArrow.png" class="w-[28px]" alt="">
|
|
|
+ <img src="~/assets/img/yj/leftArrow.png" class="w-[28px]" alt="" />
|
|
|
<div class="text-[#666666] text-[12px]">长按保存图片,扫码添加好友</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -131,40 +179,81 @@
|
|
|
<template v-for="item in commentList" :key="item.id">
|
|
|
<div class="flex mt-10 justify-between" id="commentsBox">
|
|
|
<div class="w-[32px] h-[32px] bg-[#ddd] rounded-full shrink-0">
|
|
|
- <img v-if="item?.headImageUrlDictMap?.name" class="w-full h-full object-cover rounded-full"
|
|
|
- :src="item?.headImageUrlDictMap?.name" alt="">
|
|
|
- <img v-else class="w-full h-full object-cover rounded-full"
|
|
|
- src="https://www.xiaoyaotravel.com/_nuxt/default_avatar.gSq5JxK1.png" alt="">
|
|
|
+ <img
|
|
|
+ v-if="item?.headImageUrlDictMap?.name"
|
|
|
+ class="w-full h-full object-cover rounded-full"
|
|
|
+ :src="item?.headImageUrlDictMap?.name"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else
|
|
|
+ class="w-full h-full object-cover rounded-full"
|
|
|
+ src="https://www.xiaoyaotravel.com/_nuxt/default_avatar.gSq5JxK1.png"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
</div>
|
|
|
<div class="flex-1 pl-10 flex justify-between">
|
|
|
<div>
|
|
|
<div>
|
|
|
- <span class="text-[#f40] text-[12px]">{{ item?.commentUserIdDictMap?.name }}:</span>
|
|
|
- <span class="text-[14px] text-[#333]" v-html="coveredContent(item?.commentContent)"></span>
|
|
|
+ <span class="text-[#f40] text-[12px]">
|
|
|
+ {{ item?.commentUserIdDictMap?.name }}:
|
|
|
+ </span>
|
|
|
+ <span
|
|
|
+ class="text-[14px] text-[#333]"
|
|
|
+ v-html="coveredContent(item?.commentContent)"
|
|
|
+ ></span>
|
|
|
</div>
|
|
|
<div class="text-[#666] text-[10px]">{{ item?.createTime }}</div>
|
|
|
</div>
|
|
|
<div class="mt-3 shrink-0">
|
|
|
- <van-icon @click="deleteComment(item.id)" v-if="item.self" class="mr-15" name="delete-o" size="20px"
|
|
|
- color="#666" />
|
|
|
- <van-icon @click.stop="addReply(item)" name="comment-o" size="20px" color="#666" />
|
|
|
+ <van-icon
|
|
|
+ @click="deleteComment(item.id)"
|
|
|
+ v-if="item.self"
|
|
|
+ class="mr-15"
|
|
|
+ name="delete-o"
|
|
|
+ size="20px"
|
|
|
+ color="#666"
|
|
|
+ />
|
|
|
+ <van-icon
|
|
|
+ @click.stop="addReply(item)"
|
|
|
+ name="comment-o"
|
|
|
+ size="20px"
|
|
|
+ color="#666"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<template v-if="Array.isArray(item.childrenList) && item.childrenList.length">
|
|
|
<div class="pl-[32px] mt-10">
|
|
|
- <div class="pl-12" style="border-left:1px solid #ccc">
|
|
|
+ <div class="pl-12" style="border-left: 1px solid #ccc">
|
|
|
<div v-for="subItem in item.childrenList" :key="subItem.id">
|
|
|
<div class="flex justify-between items-start">
|
|
|
<div>
|
|
|
- <span class="text-[#f40] text-[12px]">{{ subItem?.commentUserIdDictMap?.name }}<span
|
|
|
- class="text-[#333]">回复</span>{{ subItem?.replyUserIdDictMap?.name }}:</span>
|
|
|
- <span class="text-[14px] text-[#333]" v-html="coveredContent(subItem?.commentContent)"></span>
|
|
|
+ <span class="text-[#f40] text-[12px]">
|
|
|
+ {{ subItem?.commentUserIdDictMap?.name }}
|
|
|
+ <span class="text-[#333]">回复</span>
|
|
|
+ {{ subItem?.replyUserIdDictMap?.name }}:
|
|
|
+ </span>
|
|
|
+ <span
|
|
|
+ class="text-[14px] text-[#333]"
|
|
|
+ v-html="coveredContent(subItem?.commentContent)"
|
|
|
+ ></span>
|
|
|
</div>
|
|
|
<div class="flex items-center mt-3">
|
|
|
- <van-icon v-if="subItem.self" @click="deleteComment(subItem.id)" class="mr-15" name="delete-o"
|
|
|
- size="20px" color="#666" />
|
|
|
- <van-icon @click.stop="addReply(subItem, item.id)" name="comment-o" size="20px" color="#666" />
|
|
|
+ <van-icon
|
|
|
+ v-if="subItem.self"
|
|
|
+ @click="deleteComment(subItem.id)"
|
|
|
+ class="mr-15"
|
|
|
+ name="delete-o"
|
|
|
+ size="20px"
|
|
|
+ color="#666"
|
|
|
+ />
|
|
|
+ <van-icon
|
|
|
+ @click.stop="addReply(subItem, item.id)"
|
|
|
+ name="comment-o"
|
|
|
+ size="20px"
|
|
|
+ color="#666"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="text-[#666] text-[10px]">{{ subItem.createTime }}</div>
|
|
@@ -178,27 +267,45 @@
|
|
|
<div class="bg-[#F5F5F5] rounded-[20px] flex items-center justify-center h-[140px] mt-10">
|
|
|
<div>
|
|
|
<div>
|
|
|
- <img class="w-[84px]" src="~/assets/img/yj/no-comments.png" alt="">
|
|
|
- </div>
|
|
|
- <div class="text-center text-[#999]">
|
|
|
- 暂无评论
|
|
|
+ <img class="w-[84px]" src="~/assets/img/yj/no-comments.png" alt="" />
|
|
|
</div>
|
|
|
+ <div class="text-center text-[#999]">暂无评论</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<div class="mt-20">
|
|
|
<div class="flex items-center space-x-10">
|
|
|
- <img src="~/assets/img/yj/recomend_travel_note_icon.png" class="h-[27px] w-[36px] object-cover" alt="" srcset="" />
|
|
|
+ <img
|
|
|
+ src="~/assets/img/yj/recomend_travel_note_icon.png"
|
|
|
+ class="h-[27px] w-[36px] object-cover"
|
|
|
+ alt=""
|
|
|
+ srcset=""
|
|
|
+ />
|
|
|
<div class="text-[16px] font-bold text-black-3">热门游记</div>
|
|
|
</div>
|
|
|
<div class="">
|
|
|
- <NuxtLink :to="`/yj/${item.id}`" class="group flex cursor-pointer items-center space-x-10 py-10 border-b" v-for="(item, index) in dataList.dataList
|
|
|
-" :key="item.id">
|
|
|
- <div v-if="index<4" class="w-[15px] h-[15px] bg-[#000] text-[#fff] rounded flex items-center justify-center" :style="{background:['#FD9A00','#33B724','#F02626','#CACACA'][index]}" >
|
|
|
+ <NuxtLink
|
|
|
+ :to="`/yj/${item.id}`"
|
|
|
+ class="group flex cursor-pointer items-center space-x-10 py-10 border-b"
|
|
|
+ v-for="(item, index) in dataList.dataList"
|
|
|
+ :key="item.id"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ v-if="index < 4"
|
|
|
+ class="w-[15px] h-[15px] bg-[#000] text-[#fff] rounded flex items-center justify-center"
|
|
|
+ :style="{ background: ['#FD9A00', '#33B724', '#F02626', '#CACACA'][index] }"
|
|
|
+ >
|
|
|
{{ index + 1 }}
|
|
|
</div>
|
|
|
- <img :src="item?.homeHotPicturesAfterConvert?.length ? item.homeHotPicturesAfterConvert[0] : ''"
|
|
|
- class="h-65 w-65 shrink-0 rounded-xl object-cover" alt="" />
|
|
|
+ <img
|
|
|
+ :src="
|
|
|
+ item?.homeHotPicturesAfterConvert?.length
|
|
|
+ ? item.homeHotPicturesAfterConvert[0]
|
|
|
+ : ''
|
|
|
+ "
|
|
|
+ class="h-65 w-65 shrink-0 rounded-xl object-cover"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
<div class="w-0 flex-1">
|
|
|
<div class="truncate text-xl font-semibold text-black-3 group-hover:text-linkHover">
|
|
|
{{ item.projectTitle }}
|
|
@@ -215,37 +322,62 @@
|
|
|
<div class="h-[100px]"></div>
|
|
|
<div @click.stop="" class="fixed bottom-0 left-0 w-full bg-[#fff] pt-10 pb-30 border">
|
|
|
<div v-if="replyComment.id" class="text-center relative">
|
|
|
- 回复 <span class="text-[#f40]">{{ replyComment?.commentUserIdDictMap?.name }}:</span>
|
|
|
+ 回复
|
|
|
+ <span class="text-[#f40]">{{ replyComment?.commentUserIdDictMap?.name }}:</span>
|
|
|
<div class="absolute right-10 top-0">
|
|
|
<van-icon name="cross" />
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="flex items-center ">
|
|
|
+ <div class="flex items-center">
|
|
|
<div class="rounded-full overflow-hidden w-[32px] h-[32px] shrink-0 ml-5">
|
|
|
- <img v-if="userInfo?.headImageUrl" class="w-full h-full object-cover rounded-full"
|
|
|
- :src="userInfo?.headImageUrl" alt="" />
|
|
|
- <img v-else class="w-full h-full object-cover rounded-full"
|
|
|
- src="https://www.xiaoyaotravel.com/_nuxt/default_avatar.gSq5JxK1.png" alt="" />
|
|
|
+ <img
|
|
|
+ v-if="userInfo?.headImageUrl"
|
|
|
+ class="w-full h-full object-cover rounded-full"
|
|
|
+ :src="userInfo?.headImageUrl"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ v-else
|
|
|
+ class="w-full h-full object-cover rounded-full"
|
|
|
+ src="https://www.xiaoyaotravel.com/_nuxt/default_avatar.gSq5JxK1.png"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
</div>
|
|
|
<div
|
|
|
- class="relative flex-1 ml-5 mr-5 pl-5 pr-5 pt-4 pb-4 rounded-full h-[50px] border border-[#FD9A00] flex items-center justify-between">
|
|
|
- <textarea v-model="commentValue" ref="textareaRef" :placeholder="replyComment.id ? '回复:' : '发布您的评论'"
|
|
|
- @focus="textareaFocus" class="ml-8 flex-1 h-full" style="resize: none;"></textarea>
|
|
|
- <img @click="openEmoji" src="~/assets/img/yj/emoji.png" class="w-[22px] h-[22px]" alt="">
|
|
|
-
|
|
|
+ class="relative flex-1 ml-5 mr-5 pl-5 pr-5 pt-4 pb-4 rounded-full h-[50px] border border-[#FD9A00] flex items-center justify-between"
|
|
|
+ >
|
|
|
+ <textarea
|
|
|
+ v-model="commentValue"
|
|
|
+ ref="textareaRef"
|
|
|
+ :placeholder="replyComment.id ? '回复:' : '发布您的评论'"
|
|
|
+ @focus="textareaFocus"
|
|
|
+ class="ml-8 flex-1 h-full"
|
|
|
+ style="resize: none"
|
|
|
+ ></textarea>
|
|
|
+ <img
|
|
|
+ @click="openEmoji"
|
|
|
+ src="~/assets/img/yj/emoji.png"
|
|
|
+ class="w-[22px] h-[22px]"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
</div>
|
|
|
- <div @click="addComment"
|
|
|
- class="pt-6 pb-6 pl-20 pr-20 mr-5 bg-[#FD9A00] text-[#fff] flex items-center justify-center rounded-full shrink-0">
|
|
|
+ <div
|
|
|
+ @click="addComment"
|
|
|
+ class="pt-6 pb-6 pl-20 pr-20 mr-5 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 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
|
|
|
+ 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>
|
|
@@ -253,11 +385,9 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<div v-if="['error'].includes(status)">
|
|
|
- <div class="text-center">
|
|
|
- 不好意思,找不到这篇游记了~
|
|
|
- </div>
|
|
|
+ <div class="text-center">不好意思,找不到这篇游记了~</div>
|
|
|
<div @click="goBack" class="text-center underline mt-10 cursor-pointer text-[#4B99EA]">
|
|
|
返回
|
|
|
</div>
|
|
@@ -267,13 +397,12 @@
|
|
|
|
|
|
<script setup>
|
|
|
import dashBorder2 from '~/assets/img/dash-border.png'
|
|
|
-import emojiArr from './emoji'
|
|
|
import emojiJson from './emoji.json'
|
|
|
const userInfoStore = useUserInfoStore()
|
|
|
const authStore = useAuthStore()
|
|
|
const { token } = storeToRefs(authStore)
|
|
|
|
|
|
-const id = useRouteParam("id")
|
|
|
+const id = useRouteParam('id')
|
|
|
const router = useRouter()
|
|
|
const textareaRef = ref(null)
|
|
|
|
|
@@ -291,7 +420,9 @@ const { data: dataList } = await useMyFetch(
|
|
|
const isCollect = ref(false)
|
|
|
async function isCollectTravelNotes() {
|
|
|
if (!token.value) return
|
|
|
- const { data } = await request(`website/tourism/projectTravelNotes/isCollectTravelNotes?travelNotesId=${id.value}`)
|
|
|
+ const { data } = await request(
|
|
|
+ `website/tourism/projectTravelNotes/isCollectTravelNotes?travelNotesId=${id.value}`
|
|
|
+ )
|
|
|
isCollect.value = data
|
|
|
}
|
|
|
|
|
@@ -302,23 +433,30 @@ async function handleCollect() {
|
|
|
showConfirmDialog: true,
|
|
|
title: '提示',
|
|
|
message: '登录后可以收藏游记',
|
|
|
- theme: 'round-button',
|
|
|
- }).then(async () => { navigateTo({ path: '/login' }) })
|
|
|
+ theme: 'round-button'
|
|
|
+ }).then(async () => {
|
|
|
+ navigateTo({ path: '/login' })
|
|
|
+ })
|
|
|
return
|
|
|
}
|
|
|
const type = isCollect.value ? 0 : 1
|
|
|
showLoadingToast({
|
|
|
forbidClick: true,
|
|
|
- duration: 0,
|
|
|
+ duration: 0
|
|
|
})
|
|
|
- await request(`/website/tourism/projectTravelNotes/userCollectTravelNotesUpdate`, { method: 'post', body: { type, travelNotesId: id.value } }).finally(() => closeToast())
|
|
|
+ await request(`/website/tourism/projectTravelNotes/userCollectTravelNotesUpdate`, {
|
|
|
+ method: 'post',
|
|
|
+ body: { type, travelNotesId: id.value }
|
|
|
+ }).finally(() => closeToast())
|
|
|
isCollectTravelNotes()
|
|
|
showToast(type == 1 ? '收藏成功' : '已取消收藏')
|
|
|
}
|
|
|
|
|
|
// 获取点赞数量
|
|
|
async function getStars() {
|
|
|
- const { data } = await request(`/website/tourism/projectTravelNotes/getLikeCount?travelNotesId=${id.value}`)
|
|
|
+ const { data } = await request(
|
|
|
+ `/website/tourism/projectTravelNotes/getLikeCount?travelNotesId=${id.value}`
|
|
|
+ )
|
|
|
if (isNaN(data)) return
|
|
|
detailData.value.likeCount = data
|
|
|
}
|
|
@@ -331,23 +469,57 @@ async function doStar() {
|
|
|
request(`/website/tourism/projectTravelNotes/userLikeTravelNotesUpdate`, {
|
|
|
method: 'post',
|
|
|
body: { travelNotesId: id.value }
|
|
|
- }).then(() => {
|
|
|
- detailData.value.isLike = true
|
|
|
- getStars()
|
|
|
- }).finally(() => canDoStar.value = true)
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ detailData.value.isLike = true
|
|
|
+ getStars()
|
|
|
+ })
|
|
|
+ .finally(() => (canDoStar.value = true))
|
|
|
}
|
|
|
|
|
|
// 获取用户信息
|
|
|
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 = {}
|
|
|
- })
|
|
|
+ if (!token.value) return (userInfo.value = {})
|
|
|
+ request('/website/tourism/user/view').then(
|
|
|
+ (res) => {
|
|
|
+ userInfo.value = res.data || {}
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ userInfo.value = {}
|
|
|
+ }
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// 关注状态
|
|
|
+function followState(params) {
|
|
|
+ if (!params) {
|
|
|
+ return {
|
|
|
+ color: 'text-[#FD9A00] border-[#FD9A00]',
|
|
|
+ text: '关注'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (params == 1) {
|
|
|
+ return {
|
|
|
+ color: 'text-black-9 border-black-9',
|
|
|
+ text: '已关注'
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 内容是否为空
|
|
|
+function contentIsEmpty(content) {
|
|
|
+ if (content) {
|
|
|
+ return `/${content}`
|
|
|
+ } else {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+// 游记详情得轮播图下标
|
|
|
+const swipeItemIndex = ref(1)
|
|
|
+
|
|
|
// 评论内容
|
|
|
const commentValue = ref('')
|
|
|
|
|
@@ -362,8 +534,10 @@ function textareaFocus() {
|
|
|
// 获取评论列表
|
|
|
const commentList = ref([])
|
|
|
async function getComments() {
|
|
|
- const { data } = await request("/website/comment/tourTravelNotesComment/list?travelNoteId=" + id.value)
|
|
|
- if (!Array.isArray(data) || !data.length) return commentList.value = []
|
|
|
+ const { data } = await request(
|
|
|
+ '/website/comment/tourTravelNotesComment/list?travelNoteId=' + id.value
|
|
|
+ )
|
|
|
+ if (!Array.isArray(data) || !data.length) return (commentList.value = [])
|
|
|
commentList.value = data
|
|
|
}
|
|
|
|
|
@@ -383,11 +557,11 @@ async function deleteComment(id) {
|
|
|
if (!id) return
|
|
|
showConfirmDialog({
|
|
|
message: '确认要删除这条评论吗?',
|
|
|
- theme: 'round-button',
|
|
|
+ theme: 'round-button'
|
|
|
}).then(async () => {
|
|
|
showLoadingToast({
|
|
|
forbidClick: true,
|
|
|
- duration: 0,
|
|
|
+ duration: 0
|
|
|
})
|
|
|
await request('/website/comment/tourTravelNotesComment/delete', {
|
|
|
method: 'post',
|
|
@@ -395,7 +569,7 @@ async function deleteComment(id) {
|
|
|
}).finally(() => closeToast())
|
|
|
showToast('删除成功')
|
|
|
getComments()
|
|
|
- });
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
const cursorIndex = ref(0)
|
|
@@ -416,7 +590,10 @@ function closeEmojiBox() {
|
|
|
// 选择表情
|
|
|
function selectEmoji(emojiStr = '') {
|
|
|
const length = emojiStr.length
|
|
|
- commentValue.value = commentValue.value.slice(0, cursorIndex.value) + emojiStr + commentValue.value.slice(cursorIndex.value)
|
|
|
+ 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)
|
|
@@ -431,16 +608,17 @@ function addReply(item, parentId) {
|
|
|
showConfirmDialog: true,
|
|
|
title: '提示',
|
|
|
message: '登录后可以发布评论',
|
|
|
- theme: 'round-button',
|
|
|
- }).then(async () => { navigateTo({ path: '/login' }) })
|
|
|
+ theme: 'round-button'
|
|
|
+ }).then(async () => {
|
|
|
+ navigateTo({ path: '/login' })
|
|
|
+ })
|
|
|
return
|
|
|
}
|
|
|
textareaRef.value.focus()
|
|
|
- replyComment.value = item
|
|
|
- parentId && (replyComment.value.parentId = parentId)
|
|
|
+ replyComment.value = item
|
|
|
+ parentId && (replyComment.value.parentId = parentId)
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 发布评论
|
|
|
const canAddComment = ref(true)
|
|
|
async function addComment() {
|
|
@@ -450,8 +628,10 @@ async function addComment() {
|
|
|
showConfirmDialog: true,
|
|
|
title: '提示',
|
|
|
message: '登录后可以发布评论',
|
|
|
- theme: 'round-button',
|
|
|
- }).then(async () => { navigateTo({ path: '/login' }) })
|
|
|
+ theme: 'round-button'
|
|
|
+ }).then(async () => {
|
|
|
+ navigateTo({ path: '/login' })
|
|
|
+ })
|
|
|
return
|
|
|
}
|
|
|
if (!commentValue.value.trim()) {
|
|
@@ -465,16 +645,18 @@ async function addComment() {
|
|
|
body.replyUserId = replyComment.value.createUserId
|
|
|
body.parentId = replyComment.value.parentId
|
|
|
}
|
|
|
- request('website/comment/tourTravelNotesComment/add', { method: 'post', body }).then(() => {
|
|
|
- commentValue.value = ''
|
|
|
- showToast('评论发布成功')
|
|
|
- getComments()
|
|
|
- showEmoji.value = false
|
|
|
- document.querySelector('#commentsBox').scrollIntoView({
|
|
|
- behavior: 'smooth',
|
|
|
- block: 'start'
|
|
|
+ request('website/comment/tourTravelNotesComment/add', { method: 'post', body })
|
|
|
+ .then(() => {
|
|
|
+ commentValue.value = ''
|
|
|
+ showToast('评论发布成功')
|
|
|
+ getComments()
|
|
|
+ showEmoji.value = false
|
|
|
+ document.querySelector('#commentsBox').scrollIntoView({
|
|
|
+ behavior: 'smooth',
|
|
|
+ block: 'start'
|
|
|
+ })
|
|
|
})
|
|
|
- }).finally(() => canAddComment.value = true, replyComment.value = {}, cursorIndex.value = 0)
|
|
|
+ .finally(() => (canAddComment.value = true), (replyComment.value = {}), (cursorIndex.value = 0))
|
|
|
}
|
|
|
function pageClick() {
|
|
|
nextTick(() => {
|
|
@@ -486,23 +668,26 @@ function pageClick() {
|
|
|
}
|
|
|
// 分享
|
|
|
function share() {
|
|
|
- navigator.clipboard.writeText(location.href).then(() => {
|
|
|
- showNotify({ type: 'success', message: '游记链接已复制成功,快去分享给好友吧!' });
|
|
|
- }, (err) => {
|
|
|
- showNotify({ message: '游记链接分享失败' });
|
|
|
- })
|
|
|
+ navigator.clipboard.writeText(location.href).then(
|
|
|
+ () => {
|
|
|
+ showNotify({ type: 'success', message: '游记链接已复制成功,快去分享给好友吧!' })
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ showNotify({ message: '游记链接分享失败' })
|
|
|
+ }
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
function goBack() {
|
|
|
router.back()
|
|
|
}
|
|
|
useSeoMeta({
|
|
|
- title: "游记详情",
|
|
|
+ title: '游记详情',
|
|
|
ogTitle: detailData?.projectTitle || '精美热门游记',
|
|
|
description: '逍遥游,乐逍遥,自由自在',
|
|
|
ogDescription: detailData?.projectTitle || '精美热门游记',
|
|
|
- ogImage: '',
|
|
|
-});
|
|
|
+ ogImage: ''
|
|
|
+})
|
|
|
onMounted(() => {
|
|
|
getComments()
|
|
|
getUserInfo()
|
|
@@ -510,4 +695,4 @@ onMounted(() => {
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
+<style lang="scss" scoped></style>
|