hookehuyr

feat(评论模块): 优化评论列表样式并添加点赞功能

- 重构评论列表布局,增加评论数量显示和查看更多按钮
- 为评论添加点赞功能,支持切换点赞状态并更新点赞数
- 优化底部操作栏样式,调整输入框为多行文本区域
...@@ -51,24 +51,54 @@ ...@@ -51,24 +51,54 @@
51 <div class="h-2 bg-gray-100"></div> 51 <div class="h-2 bg-gray-100"></div>
52 52
53 <div id="comment" class="py-4 px-4 space-y-4"> 53 <div id="comment" class="py-4 px-4 space-y-4">
54 - <div v-for="comment in comments" :key="comment.id" class="bg-white rounded-lg p-4 shadow-sm"> 54 + <div class="flex justify-between items-center mb-4">
55 - <div class="flex items-center mb-2"> 55 + <div class="text-gray-900 font-medium text-sm">评论 ({{ comments.length }})</div>
56 - <img :src="comment.avatar" class="w-8 h-8 rounded-full mr-2" /> 56 + <div class="text-gray-500 cursor-pointer text-sm">查看更多</div>
57 - <div> 57 + </div>
58 - <div class="font-medium">{{ comment.username }}</div> 58 + <div v-for="comment in comments" :key="comment.id" class="border-b border-gray-100 last:border-b-0 py-4">
59 - <div class="text-gray-500 text-xs">{{ comment.time }}</div> 59 + <div class="flex">
60 + <!-- 左侧头像 -->
61 + <img :src="comment.avatar" class="w-10 h-10 rounded-full flex-shrink-0" style="margin-right: 0.5rem;" />
62 +
63 + <!-- 右侧内容 -->
64 + <div class="flex-1 ml-3">
65 + <!-- 第一行:用户名和点赞 -->
66 + <div class="flex justify-between items-center mb-1">
67 + <span class="font-medium text-gray-900">{{ comment.username }}</span>
68 + <div class="flex items-center space-x-1">
69 + <span class="text-sm text-gray-500">{{ comment.likes }}</span> &nbsp;
70 + <van-icon
71 + :name="comment.isLiked ? 'like' : 'like-o'"
72 + :class="{'text-red-500': comment.isLiked, 'text-gray-400': !comment.isLiked}"
73 + @click="toggleLike(comment)"
74 + class="text-lg cursor-pointer"
75 + />
76 + </div>
77 + </div>
78 +
79 + <!-- 第二行:评论内容 -->
80 + <p class="text-gray-700 text-sm mb-1">{{ comment.content }}</p>
81 +
82 + <!-- 第三行:时间 -->
83 + <div class="text-gray-400 text-xs">{{ comment.time }}</div>
60 </div> 84 </div>
61 </div> 85 </div>
62 - <div class="text-gray-700">{{ comment.content }}</div>
63 </div> 86 </div>
64 </div> 87 </div>
65 </div> 88 </div>
66 89
67 <!-- 底部操作栏 --> 90 <!-- 底部操作栏 -->
68 <div class="fixed bottom-0 left-0 right-0 bg-white border-t px-4 py-2 flex items-center space-x-4"> 91 <div class="fixed bottom-0 left-0 right-0 bg-white border-t px-4 py-2 flex items-center space-x-4">
69 - <van-button icon="bars" class="flex-none" @click="showCatalog = true">课程目录</van-button> 92 + <div class="flex-none flex flex-col items-center gap-1 cursor-pointer active:opacity-80" @click="showCatalog = true">
70 - <div class="flex-grow"> 93 + <van-icon name="bars" class="text-lg text-gray-600" />
71 - <van-field v-model="newComment" placeholder="说点什么吧~" class="bg-gray-100 rounded-full" /> 94 + <span class="text-xs text-gray-600">课程目录</span>
95 + </div>
96 + <div class="flex-grow flex-1 min-w-0">
97 + <van-field v-model="newComment" rows="1" autosize type="textarea" placeholder="请输入留言" class="bg-gray-100 rounded-lg !p-0">
98 + <template #input>
99 + <textarea v-model="newComment" rows="1" placeholder="请输入留言" class="w-full h-full bg-transparent outline-none resize-none" />
100 + </template>
101 + </van-field>
72 </div> 102 </div>
73 <van-button type="primary" size="small" @click="submitComment">发送</van-button> 103 <van-button type="primary" size="small" @click="submitComment">发送</van-button>
74 </div> 104 </div>
...@@ -115,21 +145,54 @@ const comments = ref([ ...@@ -115,21 +145,54 @@ const comments = ref([
115 username: '欢乐马', 145 username: '欢乐马',
116 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', 146 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
117 content: '教育的顶级传承,是你用什么样的心,传承智慧', 147 content: '教育的顶级传承,是你用什么样的心,传承智慧',
118 - time: '2024-12-04 18:51' 148 + time: '2024-12-04 18:51',
149 + likes: 12,
150 + isLiked: false
151 + },
152 + {
153 + id: 2,
154 + username: '欢乐马',
155 + avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
156 + content: '不要用战术上的勤奋,掩盖战略上的懒惰',
157 + time: '2024-12-04 08:01',
158 + likes: 8,
159 + isLiked: true
160 + },
161 + {
162 + id: 3,
163 + username: '欢乐马',
164 + avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
165 + content: '和老师积极互动,整个课堂像为你而讲',
166 + time: '2024-12-04 07:54',
167 + likes: 5,
168 + isLiked: false
169 + },
170 + {
171 + id: 1,
172 + username: '欢乐马',
173 + avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
174 + content: '教育的顶级传承,是你用什么样的心,传承智慧',
175 + time: '2024-12-04 18:51',
176 + likes: 12,
177 + isLiked: false
119 }, 178 },
120 { 179 {
121 id: 2, 180 id: 2,
122 username: '欢乐马', 181 username: '欢乐马',
123 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', 182 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
124 content: '不要用战术上的勤奋,掩盖战略上的懒惰', 183 content: '不要用战术上的勤奋,掩盖战略上的懒惰',
125 - time: '2024-12-04 08:01' 184 + time: '2024-12-04 08:01',
185 + likes: 8,
186 + isLiked: true
126 }, 187 },
127 { 188 {
128 id: 3, 189 id: 3,
129 username: '欢乐马', 190 username: '欢乐马',
130 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', 191 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
131 content: '和老师积极互动,整个课堂像为你而讲', 192 content: '和老师积极互动,整个课堂像为你而讲',
132 - time: '2024-12-04 07:54' 193 + time: '2024-12-04 07:54',
194 + likes: 5,
195 + isLiked: false
133 } 196 }
134 ]); 197 ]);
135 198
...@@ -164,6 +227,12 @@ onMounted(() => { ...@@ -164,6 +227,12 @@ onMounted(() => {
164 }) 227 })
165 228
166 // 提交评论 229 // 提交评论
230 +// 切换点赞状态
231 +const toggleLike = (comment) => {
232 + comment.isLiked = !comment.isLiked;
233 + comment.likes += comment.isLiked ? 1 : -1;
234 +};
235 +
167 const submitComment = () => { 236 const submitComment = () => {
168 if (!newComment.value.trim()) return; 237 if (!newComment.value.trim()) return;
169 238
...@@ -172,7 +241,9 @@ const submitComment = () => { ...@@ -172,7 +241,9 @@ const submitComment = () => {
172 username: '当前用户', 241 username: '当前用户',
173 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', 242 avatar: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
174 content: newComment.value, 243 content: newComment.value,
175 - time: new Date().toLocaleString() 244 + time: new Date().toLocaleString(),
245 + likes: 0,
246 + isLiked: false
176 }); 247 });
177 248
178 newComment.value = ''; 249 newComment.value = '';
...@@ -182,7 +253,7 @@ const submitComment = () => { ...@@ -182,7 +253,7 @@ const submitComment = () => {
182 const handleTabChange = (name) => { 253 const handleTabChange = (name) => {
183 nextTick(() => { 254 nextTick(() => {
184 const element = document.getElementById(name === 'intro' ? 'intro' : 'comment'); 255 const element = document.getElementById(name === 'intro' ? 'intro' : 'comment');
185 - if (element && container) { 256 + if (element) {
186 const topOffset = element.offsetTop - parseInt(topWrapperHeight.value); 257 const topOffset = element.offsetTop - parseInt(topWrapperHeight.value);
187 window.scrollTo({ 258 window.scrollTo({
188 top: topOffset, 259 top: topOffset,
...@@ -194,3 +265,9 @@ const handleTabChange = (name) => { ...@@ -194,3 +265,9 @@ const handleTabChange = (name) => {
194 265
195 266
196 </script> 267 </script>
268 +
269 +<style lang="less" scoped>
270 +:deep(.van-cell.van-field) {
271 + background-color: rgb(244, 244, 244);
272 +}
273 +</style>
......