detail.uvue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <template>
  2. <cl-page>
  3. <cl-sticky>
  4. <cl-topbar fixed safe-area-top :height="isMp() ? null : 50">
  5. <view class="flex flex-row items-center w-full pl-[36px] pr-3">
  6. <cl-avatar
  7. rounded
  8. :size="30"
  9. src="https://unix.cool-js.com/images/demo/avatar.jpg"
  10. ></cl-avatar>
  11. <cl-text :pt="{ className: 'mx-3' }">神仙都没用</cl-text>
  12. <cl-button
  13. text
  14. border
  15. size="small"
  16. rounded
  17. :pt="{ className: parseClass(['!px-3', [!isMp(), 'ml-auto']]) }"
  18. >立即关注</cl-button
  19. >
  20. </view>
  21. </cl-topbar>
  22. </cl-sticky>
  23. <view class="banner">
  24. <cl-banner
  25. height="500px"
  26. :list="bannerList"
  27. :pt="{
  28. className: '!rounded-none',
  29. image: {
  30. className: '!rounded-none'
  31. }
  32. }"
  33. ></cl-banner>
  34. </view>
  35. <view class="bg-white dark:bg-surface-800 mb-3">
  36. <view
  37. class="p-4 border border-solid border-t-0 border-l-0 border-r-0 border-b-surface-200 dark:border-surface-600"
  38. >
  39. <cl-text :size="17" :pt="{ className: 'mb-2 font-bold' }"
  40. >雪地旅行商务团价格表</cl-text
  41. >
  42. <cl-text :size="15" :pt="{ className: 'mb-3' }">
  43. 对于不想做攻略的小伙伴来说定制团真的是最佳选择。雪地自驾没有经验的真心不建议。费用清晰明了。预算很准确,收费很合理。</cl-text
  44. >
  45. <view class="flex-row items-center justify-between">
  46. <view
  47. class="flex-row items-center border border-solid border-surface-300 dark:border-surface-600 rounded-lg px-2 py-1"
  48. >
  49. <cl-text :size="12" color="info">哈尔滨 · 圣 · 索菲亚教堂</cl-text>
  50. </view>
  51. <cl-text :size="10" color="info">编辑于2天前</cl-text>
  52. </view>
  53. </view>
  54. <!-- 评论 -->
  55. <view class="p-4">
  56. <cl-text :size="12" :pt="{ className: 'mb-4' }">共 10 条评论</cl-text>
  57. <!-- 评论输入框 -->
  58. <view class="flex-row reply items-center mb-5" @tap="openReply()">
  59. <cl-avatar
  60. :size="34"
  61. rounded
  62. :pt="{ className: 'mr-2' }"
  63. src="https://unix.cool-js.com/images/demo/avatar.jpg"
  64. ></cl-avatar>
  65. <view
  66. class="h-[35px] flex-1 flex-row items-center bg-surface-100 dark:bg-surface-700 rounded-full px-4"
  67. >
  68. <cl-text color="info" :pt="{ className: 'flex-1' }">说点什么...</cl-text>
  69. <cl-icon name="user-smile-line" :size="20"></cl-icon>
  70. <cl-icon
  71. name="image-circle-line"
  72. :pt="{ className: 'ml-2' }"
  73. :size="20"
  74. ></cl-icon>
  75. </view>
  76. </view>
  77. <view class="list">
  78. <view class="flex-row mb-6" v-for="item in commentList" :key="item.id">
  79. <cl-avatar :size="34" rounded :src="item.avatar"></cl-avatar>
  80. <view class="ml-3 flex-1">
  81. <!-- 评论者信息 -->
  82. <view class="flex-row items-center mb-1">
  83. <cl-text :size="12" color="info">{{ item.name }}</cl-text>
  84. <cl-tag
  85. plain
  86. rounded
  87. :pt="{
  88. className: '!px-1 ml-2 !h-[18px]',
  89. text: { className: '!text-[10px]' }
  90. }"
  91. v-if="item.isAuthor"
  92. >作者</cl-tag
  93. >
  94. </view>
  95. <!-- 评论内容 -->
  96. <cl-text :pt="{ className: 'mb-2' }">{{ item.content }}</cl-text>
  97. <view class="flex-row items-center">
  98. <!-- 评论时间 -->
  99. <cl-text :size="10" :pt="{ className: 'text-surface-400' }">
  100. {{ item.time }}
  101. </cl-text>
  102. </view>
  103. <!-- 回复列表 -->
  104. <view class="flex-row mt-3" v-for="reply in item.reply" :key="reply.id">
  105. <cl-avatar :size="25" rounded :src="reply.avatar"> </cl-avatar>
  106. <view class="ml-3 flex-1">
  107. <view class="flex-row items-center mb-1">
  108. <cl-text :size="12" color="info">{{ reply.name }}</cl-text>
  109. <cl-tag
  110. plain
  111. rounded
  112. :pt="{
  113. className: '!px-1 ml-2 !h-[18px]',
  114. text: { className: '!text-[10px]' }
  115. }"
  116. v-if="reply.isAuthor"
  117. >作者</cl-tag
  118. >
  119. </view>
  120. <cl-text :pt="{ className: 'mb-2' }">{{
  121. reply.content
  122. }}</cl-text>
  123. <view class="flex-row items-center mb-1">
  124. <cl-text :size="10" :pt="{ className: 'text-surface-400' }">
  125. {{ reply.time }}
  126. </cl-text>
  127. </view>
  128. </view>
  129. </view>
  130. </view>
  131. </view>
  132. </view>
  133. </view>
  134. </view>
  135. <cl-footer>
  136. <view class="flex flex-row h-[34px]">
  137. <view
  138. class="flex-row items-center bg-surface-100 dark:bg-surface-700 rounded-full px-3 py-2 mr-6 w-[130px] h-full"
  139. @tap="openReply"
  140. >
  141. <cl-icon name="edit-line" color="info" :size="16"></cl-icon>
  142. <cl-text color="info" :pt="{ className: 'ml-2' }">说点什么...</cl-text>
  143. </view>
  144. <view class="flex flex-row flex-1 justify-end h-full items-center">
  145. <view class="flex-row justify-center items-center mr-6">
  146. <cl-icon name="heart-line" :size="20"></cl-icon>
  147. <cl-text :pt="{ className: 'ml-2' }">700</cl-text>
  148. </view>
  149. <view class="flex-row justify-center items-center">
  150. <cl-icon name="chat-3-line" :size="20"></cl-icon>
  151. <cl-text :pt="{ className: 'ml-2' }">59</cl-text>
  152. </view>
  153. </view>
  154. </view>
  155. </cl-footer>
  156. <!-- 回复弹窗 -->
  157. <cl-popup v-model="replyVisible" direction="bottom" ref="replyPopupRef">
  158. <view class="p-4 pt-0">
  159. <view class="bg-surface-100 dark:bg-surface-800 rounded-2xl p-[4px] h-[84px]">
  160. <cl-textarea
  161. placeholder="说点什么..."
  162. :border="false"
  163. :pt="{
  164. className: parseClass(['!bg-transparent'])
  165. }"
  166. autofocus
  167. v-if="isApp() ? true : replyPopupRef?.isOpened == true"
  168. ></cl-textarea>
  169. </view>
  170. <view class="flex-row items-center mt-3 pl-2">
  171. <cl-icon
  172. name="image-circle-line"
  173. :pt="{ className: 'mr-4' }"
  174. :size="22"
  175. ></cl-icon>
  176. <cl-icon
  177. name="user-smile-line"
  178. :pt="{ className: 'mr-4' }"
  179. :size="22"
  180. ></cl-icon>
  181. <cl-button :pt="{ className: 'ml-auto !px-4' }" rounded>发送</cl-button>
  182. </view>
  183. </view>
  184. </cl-popup>
  185. </cl-page>
  186. </template>
  187. <script lang="ts" setup>
  188. import { isApp, isMp, parseClass } from "@/.cool";
  189. import { ref } from "vue";
  190. const bannerList = ref<string[]>([
  191. "https://unix.cool-js.com/images/demo/bg1.png",
  192. "https://unix.cool-js.com/images/demo/bg2.png",
  193. "https://unix.cool-js.com/images/demo/bg3.png"
  194. ]);
  195. type Comment = {
  196. id: number;
  197. avatar: string;
  198. name: string;
  199. content: string;
  200. time: string;
  201. isAuthor: boolean;
  202. order: number;
  203. reply: Comment[];
  204. };
  205. const commentList = ref<Comment[]>([
  206. {
  207. id: 1,
  208. avatar: "https://unix.cool-js.com/images/demo/avatar-1.jpg",
  209. name: "李明",
  210. content: "导游讲解很专业,风景绝美,是一次难忘的旅行体验!",
  211. time: "06-20 10:15",
  212. isAuthor: false,
  213. order: 1,
  214. reply: []
  215. },
  216. {
  217. id: 2,
  218. avatar: "https://unix.cool-js.com/images/demo/avatar-2.jpg",
  219. name: "小芳",
  220. content: "酒店干净卫生,位置也很方便,强烈推荐给大家!",
  221. time: "06-20 11:08",
  222. isAuthor: false,
  223. order: 2,
  224. reply: [
  225. {
  226. id: 201,
  227. avatar: "https://unix.cool-js.com/images/demo/avatar.jpg",
  228. name: "神仙都没用",
  229. content: "感谢您的推荐,欢迎再次光临哦~",
  230. time: "06-20 12:00",
  231. isAuthor: true,
  232. order: 1,
  233. reply: []
  234. }
  235. ]
  236. },
  237. {
  238. id: 3,
  239. avatar: "https://unix.cool-js.com/images/demo/avatar-3.jpg",
  240. name: "王科",
  241. content: "行程安排合理,吃住都很满意,导游态度超级好。",
  242. time: "06-19 09:22",
  243. isAuthor: false,
  244. order: 3,
  245. reply: []
  246. },
  247. {
  248. id: 4,
  249. avatar: "https://unix.cool-js.com/images/demo/avatar-4.jpg",
  250. name: "艳艳",
  251. content: "第一次带父母出游,家人都开心,下次还会选择这里~",
  252. time: "06-18 15:40",
  253. isAuthor: false,
  254. order: 4,
  255. reply: []
  256. },
  257. {
  258. id: 5,
  259. avatar: "https://unix.cool-js.com/images/demo/avatar-5.jpg",
  260. name: "孙强",
  261. content: "车程舒适,时间安排紧凑但不赶,非常不错,非常棒!",
  262. time: "06-17 17:05",
  263. isAuthor: false,
  264. order: 5,
  265. reply: [
  266. {
  267. id: 501,
  268. avatar: "https://unix.cool-js.com/images/demo/avatar.jpg",
  269. name: "神仙都没用",
  270. content: "您的好评就是我们最大的动力,谢谢支持~",
  271. time: "06-17 17:45",
  272. isAuthor: true,
  273. order: 1,
  274. reply: []
  275. }
  276. ]
  277. },
  278. {
  279. id: 6,
  280. avatar: "https://unix.cool-js.com/images/demo/avatar-6.jpg",
  281. name: "导游小陈",
  282. content: "很高兴大家玩的开心,有问题随时联系我们。",
  283. time: "06-17 18:20",
  284. isAuthor: false,
  285. order: 6,
  286. reply: []
  287. },
  288. {
  289. id: 7,
  290. avatar: "https://unix.cool-js.com/images/demo/avatar-7.jpg",
  291. name: "Grace",
  292. content: "风景如画,照片拍了一堆,朋友都夸赞说好美!",
  293. time: "06-16 14:10",
  294. isAuthor: false,
  295. order: 7,
  296. reply: []
  297. },
  298. {
  299. id: 8,
  300. avatar: "https://unix.cool-js.com/images/demo/avatar-8.jpg",
  301. name: "阿伟",
  302. content: "活动内容丰富,小朋友特别喜欢,下次会再来~",
  303. time: "06-15 19:28",
  304. isAuthor: false,
  305. order: 8,
  306. reply: []
  307. },
  308. {
  309. id: 9,
  310. avatar: "https://unix.cool-js.com/images/demo/avatar-9.jpg",
  311. name: "小虎",
  312. content: "天气晴朗,安排贴心,吃到了很多特色美食,值了!",
  313. time: "06-14 13:52",
  314. isAuthor: false,
  315. order: 9,
  316. reply: []
  317. },
  318. {
  319. id: 10,
  320. avatar: "https://unix.cool-js.com/images/demo/avatar-10.jpg",
  321. name: "Julia",
  322. content: "贴心的讲解和服务,体验很棒,感谢本次旅行团队!",
  323. time: "06-13 16:34",
  324. isAuthor: false,
  325. order: 10,
  326. reply: []
  327. }
  328. ]);
  329. const replyPopupRef = ref<ClPopupComponentPublicInstance | null>(null);
  330. const replyVisible = ref(false);
  331. function openReply() {
  332. replyVisible.value = true;
  333. }
  334. function closeReply() {
  335. replyVisible.value = false;
  336. }
  337. </script>
  338. <style lang="scss" scoped></style>