index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <route lang="yaml">
  2. style:
  3. navigationBarTitleText: '详情'
  4. navigationBarBackgroundColor: '#fff'
  5. </route>
  6. <script setup lang="ts">
  7. import Tag from '@/components/tag.vue'
  8. import {
  9. createCircleReview,
  10. getCircle,
  11. getCircleReviews,
  12. getMoment,
  13. } from '../../../core/libs/requests'
  14. import { handleUpvoteClick } from '../../../core/libs/actions'
  15. import { thumbsUp } from '../../../core/libs/svgs'
  16. import CommentItem from '../components/comment-item.vue'
  17. import AvatarGroupCasual from '@/components/avatar-group-casual/avatar-group-casual.vue'
  18. import { useUserStore } from '../../../store'
  19. import { storeToRefs } from 'pinia'
  20. const userStore = useUserStore()
  21. const { userInfo } = storeToRefs(userStore)
  22. const id = ref()
  23. const { data, run } = useRequest(() => getCircle(id.value), { initialData: {} })
  24. const { data: reviews, run: runGetReviews } = useRequest(
  25. () => getCircleReviews({ circleId: id.value }),
  26. {
  27. initialData: {
  28. list: [],
  29. },
  30. },
  31. )
  32. const current = ref(0)
  33. const swiperSizes = ref()
  34. const swiperStyle = ref()
  35. const reviewContent = ref('')
  36. const handleChange = ({ detail: { current } }) => {
  37. swiperStyle.value = {
  38. height: swiperSizes.value[current].height + 'px',
  39. }
  40. }
  41. const setSwiperStyle = async () => {
  42. const { screenWidth } = await uni.getSystemInfo()
  43. swiperSizes.value = (
  44. await Promise.all(data.value.bannerUrls.map((src) => uni.getImageInfo({ src })))
  45. ).map(({ width, height }) => ({ width: screenWidth, height: height / (width / screenWidth) }))
  46. swiperStyle.value = {
  47. height: swiperSizes.value[0].height + 'px',
  48. }
  49. }
  50. const handleSend = async () => {
  51. const { code, msg } = await createCircleReview({
  52. circleId: id.value,
  53. userId: userInfo.value.userId,
  54. userName: userInfo.value.nickname,
  55. reviewContent: reviewContent.value,
  56. })
  57. if (code !== 0) {
  58. uni.showToast({ title: msg, icon: 'none' })
  59. } else {
  60. reviewContent.value = ''
  61. uni.showToast({ title: '评论成功', icon: 'none' })
  62. }
  63. }
  64. onMounted(async () => {})
  65. onLoad(async (query: { id: string }) => {
  66. id.value = query.id
  67. await run()
  68. await runGetReviews()
  69. await setSwiperStyle()
  70. })
  71. </script>
  72. <template>
  73. <view class="bg-white flex-grow">
  74. <!-- <div class="my-4 text-black/90 text-lg font-normal font-['PingFang SC'] leading-[10.18px]">
  75. {{ data?.content }}
  76. </div> -->
  77. <template v-if="swiperSizes">
  78. <swiper :style="swiperStyle" @change="handleChange">
  79. <template v-for="it of data?.bannerUrls" :key="it">
  80. <swiper-item>
  81. <wd-img width="100%" :src="it" mode="widthFix"></wd-img>
  82. </swiper-item>
  83. </template>
  84. </swiper>
  85. </template>
  86. <!-- <wd-swiper
  87. v-model="current"
  88. custom-class="my-1"
  89. autoplay="false"
  90. :list="data?.images"
  91. :indicator="{ type: 'fraction' }"
  92. indicatorPosition="top-right"
  93. imageMode="widthFix"
  94. ></wd-swiper> -->
  95. <view class="m-3.5">
  96. <div class="text-black/90 text-base font-normal font-['PingFang SC'] leading-[10.18px]">
  97. {{ data?.circleDesc }}
  98. </div>
  99. <view class="my-5.5 flex gap-3.5">
  100. <!-- <TiltedButton>按钮</TiltedButton> -->
  101. <template v-if="data?.tagName !== ''">
  102. <template v-for="it of data?.tagName?.split(',')" :key="it">
  103. <Tag>{{ it }}</Tag>
  104. </template>
  105. </template>
  106. </view>
  107. <div class="text-black/30 text-xs font-normal font-['PingFang SC'] leading-[10.18px]">
  108. 2024-5-31 10:06
  109. </div>
  110. <view class="flex items-center my-4">
  111. <view class="flex items-center">
  112. <avatar-group-casual
  113. :show-number="3"
  114. :urls="[
  115. 'https://via.placeholder.com/20x20',
  116. 'https://via.placeholder.com/20x20',
  117. 'https://via.placeholder.com/20x20',
  118. ]"
  119. ></avatar-group-casual>
  120. <div
  121. class="ml-1 text-black/60 text-sm font-normal font-['PingFang SC'] leading-[10.18px]"
  122. >
  123. 40人赞过
  124. </div>
  125. </view>
  126. <view class="flex-1"></view>
  127. <view><wd-icon class="text-black/65" name="arrow-right" size="22px"></wd-icon></view>
  128. </view>
  129. <!-- <SectionHeading :title="`评论 ${data.comments}`"></SectionHeading> -->
  130. <view class="flex items-center my-8">
  131. <div class="text-black/90 text-base font-normal font-['PingFang SC'] leading-[10.18px]">
  132. <span>评论</span>
  133. <!-- <span v-if="data?.comments">{{ data?.comments }}</span> -->
  134. </div>
  135. <view class="flex-1"></view>
  136. <view v-if="reviews?.list" class="flex">
  137. <div class="text-black/90 text-xs font-normal font-['PingFang SC'] leading-[10.18px]">
  138. 按热度
  139. </div>
  140. <div
  141. class="mx-2 text-black/40 text-xs font-normal font-['PingFang SC'] leading-[10.18px]"
  142. >
  143. |
  144. </div>
  145. <div class="text-black/40 text-xs font-normal font-['PingFang SC'] leading-[10.18px]">
  146. 按时间
  147. </div>
  148. </view>
  149. </view>
  150. <view>
  151. <template v-if="reviews?.list.length">
  152. <template v-for="it of reviews?.list" :key="it.id">
  153. <CommentItem :options="it" :isChild="false" @upvote="runGetReviews()"></CommentItem>
  154. <template v-for="child of it.childrens" :key="child.id">
  155. <CommentItem :options="child" :isChild="true"></CommentItem>
  156. </template>
  157. </template>
  158. </template>
  159. <template v-else>
  160. <view class="flex items-center justify-center mt-26 mb-36">
  161. <div class="text-black/40 text-xs font-normal font-['PingFang SC'] leading-[10.18px]">
  162. 这里空空的
  163. </div>
  164. <div
  165. class="ml-1.5 text-[#2f4471]/90 text-xs font-normal font-['PingFang SC'] leading-[10.18px]"
  166. >
  167. 点击评论~
  168. </div>
  169. </view>
  170. </template>
  171. </view>
  172. </view>
  173. <div
  174. class="fixed bottom-0 left-0 right-0 border-t border-t-solid border-[#ececec] h-[54px] bg-white flex items-center px-3.5"
  175. >
  176. <div class="w-[168px] bg-[#f6f6f6] rounded-[60px] px-3.5 py-2 flex items-center">
  177. <wd-input
  178. custom-class="bg-transparent!"
  179. no-border
  180. confirm-type="send"
  181. v-model="reviewContent"
  182. @confirm="handleSend"
  183. ></wd-input>
  184. </div>
  185. <view class="flex justify-around flex-1">
  186. <view
  187. class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
  188. >
  189. <wd-img width="15" height="15" src="/static/svgs/share.svg"></wd-img>
  190. <view class="">{{ data?.shareCount }}</view>
  191. </view>
  192. <view
  193. class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
  194. >
  195. <wd-img width="15" height="15" src="/static/svgs/comment.svg"></wd-img>
  196. <view class="">{{ data?.reviewCount }}</view>
  197. </view>
  198. <view
  199. class="flex flex-col items-center text-[rgba(0,0,0,0.85)] text-3.5 font-400 line-height-5.5"
  200. @click="
  201. handleUpvoteClick(
  202. {
  203. upvote: data.ownUpvote,
  204. circleId: data.id,
  205. userId: userInfo.userId,
  206. userName: userInfo.nickname,
  207. },
  208. () => run(),
  209. )
  210. "
  211. >
  212. <wd-img width="15" height="15" :src="thumbsUp"></wd-img>
  213. <view>{{ data.upvoteCount }}</view>
  214. </view>
  215. </view>
  216. </div>
  217. </view>
  218. </template>