@jx3box/jx3box-vue3-ui 0.6.8 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ .c-jx3box-reply {
2
+ .u-reference {
3
+ cursor: pointer;
4
+ position: relative;
5
+ top: 8px;
6
+ margin-left: 10px;
7
+ }
8
+ }
9
+ .c-jx3box-reply-pop {
10
+ padding: 0;
11
+ width: 280px;
12
+ }
13
+
14
+ .c-jx3box-reply-pop__content {
15
+ position: relative;
16
+
17
+ .u-title {
18
+ font-size: 14px;
19
+ padding: 10px;
20
+ }
21
+ .u-close {
22
+ position: absolute;
23
+ top: 10px;
24
+ right: 10px;
25
+ cursor: pointer;
26
+ font-size: 16px;
27
+ }
28
+
29
+ .m-reply-list {
30
+ padding: 0 10px 10px 10px;
31
+ max-height: 300px;
32
+ overflow-y: auto;
33
+ }
34
+ .m-reply-list__item {
35
+ cursor: pointer;
36
+ padding: 5px;
37
+ border: 1px solid #eee;
38
+ border-radius: 4px;
39
+ margin-bottom: 5px;
40
+ .u-name {
41
+ font-size: 12px;
42
+ color: #999;
43
+ }
44
+ .u-content {
45
+ font-size: 14px;
46
+ margin-top: 5px;
47
+ }
48
+
49
+ &:hover {
50
+ color: #fff;
51
+ background-color: #409eff;
52
+ border-color: #409eff;
53
+ transition: all 0.3s;
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,6 @@
1
+ [
2
+ "真不错,谢谢楼主#胜利#笨猪#胜利",
3
+ "辛苦了,感谢楼主的付出",
4
+ "谢谢楼主,很有用",
5
+ "剑三真好玩,魔盒真好用"
6
+ ]
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M44 6H4V36H13V41L23 36H44V6Z" fill="none" stroke="#666" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/><path d="M14 19.5V22.5" stroke="#666" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/><path d="M24 19.5V22.5" stroke="#666" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/><path d="M34 19.5V22.5" stroke="#666" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>
@@ -0,0 +1 @@
1
+ <svg id="Layer_1" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path fill="#0366d6" d="m256 436a54.62 54.62 0 0 1 -29.53-8.64c-25-16.07-73.08-49.05-113.75-89.32-49.91-49.46-75.22-96.04-75.22-138.48 0-29.49 8.72-56.51 25.22-78.13a115.2 115.2 0 0 1 137.89-35.75c21.18 9.14 40.07 24.55 55.39 45 15.32-20.5 34.21-35.91 55.39-45a115.2 115.2 0 0 1 137.89 35.75c16.5 21.62 25.22 48.64 25.22 78.13 0 42.44-25.31 89-75.22 138.44-40.67 40.27-88.73 73.25-113.75 89.32a54.62 54.62 0 0 1 -29.53 8.68zm-101.84-334.94a89.41 89.41 0 0 0 -23.42 3.1 90.93 90.93 0 0 0 -48.15 32.44c-13.14 17.22-20.09 39-20.09 63 0 35.52 22.81 76.12 67.81 120.68 39 38.66 85.47 70.5 109.67 86a29.72 29.72 0 0 0 32 0c24.2-15.54 70.63-47.38 109.67-86 45-44.56 67.81-85.16 67.81-120.68 0-24-6.95-45.74-20.09-63a90.93 90.93 0 0 0 -48.15-32.44c-34.17-9.28-82.18.42-114.48 55.48a12.49 12.49 0 0 1 -21.56 0c-25.38-43.34-60.54-58.58-91.02-58.58z"/></svg>
@@ -0,0 +1 @@
1
+ <svg id="Layer_1" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m449.28 121.43a115.2 115.2 0 0 0 -137.89-35.75c-21.18 9.14-40.07 24.55-55.39 45-15.32-20.5-34.21-35.91-55.39-45a115.2 115.2 0 0 0 -137.89 35.75c-16.5 21.62-25.22 48.64-25.22 78.13 0 42.44 25.31 89 75.22 138.44 40.67 40.27 88.73 73.25 113.75 89.32a54.78 54.78 0 0 0 59.06 0c25-16.07 73.08-49.05 113.75-89.32 49.91-49.42 75.22-96 75.22-138.44 0-29.49-8.72-56.51-25.22-78.13z" fill="#f9595f"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728=""><path fill="#0366d6" d="M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2zM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z"></path><path fill="#0366d6" d="M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z"></path></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728=""><path fill="#0366d6" d="M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352m0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288zm0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448m0 64a160.192 160.192 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160"></path></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx3box/jx3box-vue3-ui",
3
- "version": "0.6.8",
3
+ "version": "0.7.0",
4
4
  "description": "JX3BOX Vue3 UI",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -26,8 +26,8 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@element-plus/icons-vue": "^2.1.0",
29
- "@jx3box/jx3box-common": "^8.2.7",
30
- "@jx3box/jx3box-data": "^3.5.6",
29
+ "@jx3box/jx3box-common": "^8.2.9",
30
+ "@jx3box/jx3box-data": "^3.5.8",
31
31
  "@jx3box/jx3box-emotion": "^1.2.6",
32
32
  "@jx3box/jx3box-macro": "^1.0.1",
33
33
  "@jx3box/jx3box-talent": "^1.2.7",
package/src/App.vue CHANGED
@@ -67,7 +67,7 @@
67
67
  :postId="57260"
68
68
  :allowGift="true"
69
69
  />
70
- <Comment category="post" id="19382"></Comment>
70
+ <Comment category="post" id="54842"></Comment>
71
71
  <RightSidebar :show-toggle="true">
72
72
  <PostTopic type="bps" :id="48857"></PostTopic>
73
73
  <div id="directory"></div>
@@ -109,7 +109,7 @@ export default {
109
109
  },
110
110
  data() {
111
111
  return {
112
- post_id: "69014",
112
+ post_id: "54842",
113
113
  post: "",
114
114
  client: location.href.includes("origin") ? "origin" : "std",
115
115
  tag: "",
@@ -3,7 +3,7 @@
3
3
  <div
4
4
  class="u-text"
5
5
  v-if="content != ''"
6
- v-html="formatContent(content)"
6
+ v-html="renderContent"
7
7
  ></div>
8
8
  <div class="u-attachements" v-if="attachments.length">
9
9
  <el-image
@@ -14,70 +14,136 @@
14
14
  lazy
15
15
  ></el-image>
16
16
  </div>
17
- <div class="u-toolbar">
18
- <el-button
19
- class="u-admin"
20
- link
21
- size="small"
22
- icon="ChatRound"
23
- @click="showForm = !showForm"
24
- type="primary"
25
- >回复</el-button
26
- >
27
- <el-button
28
- class="u-admin"
29
- v-if="canDelete"
30
- link
31
- icon="Delete"
32
- size="small"
33
- @click="deleteComment()"
34
- type="danger"
35
- >删除</el-button
36
- >
37
- <el-button
38
- class="u-admin"
39
- v-if="canSetTop"
40
- link
41
- icon="Top"
42
- size="small"
43
- @click="topComment(true)"
44
- type="primary"
45
- >置顶</el-button
46
- >
47
- <el-button
48
- class="u-admin"
49
- v-if="canCancelTop"
50
- link
51
- icon="Top"
52
- size="small"
53
- @click="topComment(false)"
54
- type="primary"
55
- >取消置顶</el-button
56
- >
57
- <el-button
58
- class="u-admin"
59
- v-if="canSetStar"
60
- link
61
- icon="Star"
62
- size="small"
63
- @click="starComment(true)"
64
- type="primary"
65
- >加精</el-button
66
- >
67
- <el-button
68
- class="u-admin"
69
- v-if="canCancelStar"
70
- link
71
- icon="StarFilled"
72
- size="small"
73
- @click="starComment(false)"
74
- type="primary"
75
- >取消加精</el-button
76
- >
77
- <time class="u-date">
78
- <i class="Clock"></i>
79
- {{ dataFormat(date) }}
80
- </time>
17
+ <div class="u-toolbar u-toolbar--primary">
18
+ <div class="u-toolbar-left">
19
+ <el-button
20
+ class="u-admin"
21
+ v-if="!currentUserHadLike"
22
+ type="text"
23
+ size="small"
24
+ @click="doLike(true)"
25
+ ><img
26
+ class="u-up"
27
+ src="../../assets/img/heart_1.svg"
28
+ alt=""
29
+ />点赞<span class="u-like-count">{{ likesFormat(hasLikeCount) }}</span></el-button
30
+ >
31
+ <el-button
32
+ class="u-admin"
33
+ type="text"
34
+ size="small"
35
+ v-if="currentUserHadLike"
36
+ @click="doLike(false)"
37
+ ><img
38
+ class="u-up"
39
+ src="../../assets/img/heart_2.svg"
40
+ alt=""
41
+ />已赞<span class="u-like-count">{{
42
+ likesFormat(hasLikeCount)
43
+ }}</span></el-button
44
+ >
45
+ <el-button
46
+ class="u-admin"
47
+ link
48
+ size="small"
49
+ icon="ChatRound"
50
+ @click="showForm = !showForm"
51
+ type="primary"
52
+ >回复</el-button
53
+ >
54
+ <el-button
55
+ class="u-admin"
56
+ v-if="canDelete"
57
+ link
58
+ icon="Delete"
59
+ size="small"
60
+ @click="deleteComment()"
61
+ type="danger"
62
+ >删除</el-button
63
+ >
64
+ <el-button
65
+ class="u-admin"
66
+ type="text"
67
+ size="small"
68
+ icon="Delete"
69
+ v-if="canHide"
70
+ @click="hideComment()"
71
+ title="拉入黑洞后,仅评论者自己独自可见"
72
+ >黑洞</el-button
73
+ >
74
+ <el-button
75
+ class="u-admin"
76
+ v-if="canSetTop"
77
+ link
78
+ icon="Top"
79
+ size="small"
80
+ @click="topComment(true)"
81
+ type="primary"
82
+ >置顶</el-button
83
+ >
84
+ <el-button
85
+ class="u-admin"
86
+ v-if="canCancelTop"
87
+ link
88
+ icon="Top"
89
+ size="small"
90
+ @click="topComment(false)"
91
+ type="primary"
92
+ >取消置顶</el-button
93
+ >
94
+ <el-button
95
+ class="u-admin"
96
+ v-if="canSetStar"
97
+ link
98
+ icon="Star"
99
+ size="small"
100
+ @click="starComment(true)"
101
+ type="primary"
102
+ >加精</el-button
103
+ >
104
+ <el-button
105
+ class="u-admin"
106
+ v-if="canCancelStar"
107
+ link
108
+ icon="StarFilled"
109
+ size="small"
110
+ @click="starComment(false)"
111
+ type="primary"
112
+ >取消加精</el-button
113
+ >
114
+ <time class="u-date">
115
+ <i class="Clock"></i>
116
+ {{ dataFormat(date) }}
117
+ </time>
118
+ </div>
119
+ <div class="u-toolbar-right">
120
+ <el-button
121
+ class="u-admin u-filter"
122
+ v-if="canAddWhite"
123
+ type="text"
124
+ size="small"
125
+ @click="setWhiteComment(true)"
126
+ >
127
+ <img
128
+ class="u-icon-filter"
129
+ src="../../assets/img/view.svg"
130
+ alt="显示"
131
+ />
132
+ 显示</el-button
133
+ >
134
+ <el-button
135
+ class="u-admin u-filter"
136
+ v-if="canRemoveWhite"
137
+ type="text"
138
+ size="small"
139
+ @click="setWhiteComment(false)"
140
+ ><img
141
+ class="u-icon-filter"
142
+ src="../../assets/img/hide.svg"
143
+ alt="隐藏"
144
+ />隐藏</el-button
145
+ >
146
+ </div>
81
147
  </div>
82
148
  <el-form
83
149
  v-if="showForm"
@@ -137,16 +203,21 @@ function fillZero(num) {
137
203
  }
138
204
  export default {
139
205
  props: [
140
- "content",
206
+ "content",
141
207
  "date",
142
208
  "hasReply",
143
209
  "canDelete",
144
210
  "canSetTop",
145
211
  "canCancelTop",
212
+ "canHide",
213
+ "isLike", // 是否已点赞
214
+ "likes", // 点赞数
146
215
  "canSetStar",
147
216
  "canCancelStar",
148
217
  "attachments",
149
218
  "commentId",
219
+ "canAddWhite", // 是否可以添加到过滤白名单, 因为对于一般用户,它看不到非白名单的评论,所以“可以添加到白名单”的权限不要在加一次用户层面的权限判定
220
+ "canRemoveWhite", // 是否可以从过滤白名单移除
150
221
  ],
151
222
  components: {
152
223
  Uploader,
@@ -162,6 +233,10 @@ export default {
162
233
  showUploader: false,
163
234
  inputId: "",
164
235
  previewList: [],
236
+ currentUserHadLike: this.isLike,
237
+ hasLikeCount: this.likes,
238
+
239
+ renderContent: "",
165
240
  };
166
241
  },
167
242
  mounted() {
@@ -174,13 +249,34 @@ export default {
174
249
  });
175
250
  },
176
251
  },
252
+ watch: {
253
+ content: {
254
+ handler: function (val) {
255
+ this.formatContent(val);
256
+ },
257
+ immediate: true,
258
+ },
259
+ },
177
260
  methods: {
261
+ doLike(setLike) {
262
+ if (setLike === this.currentUserHadLike) {
263
+ return;
264
+ }
265
+ this.currentUserHadLike = setLike;
266
+ this.hasLikeCount = setLike
267
+ ? this.hasLikeCount + 1
268
+ : this.hasLikeCount - 1;
269
+ this.$emit("setLikeComment", setLike);
270
+ },
178
271
  topComment(setTop) {
179
272
  this.$emit("setTopComment", setTop);
180
273
  },
181
274
  starComment(setStar) {
182
275
  this.$emit("setStarComment", setStar);
183
276
  },
277
+ setWhiteComment(white) {
278
+ this.$emit("setWhiteComment", white);
279
+ },
184
280
  deleteComment() {
185
281
  this.$confirm("确定删除该评论吗?", "提示", {
186
282
  confirmButtonText: "确定",
@@ -192,6 +288,17 @@ export default {
192
288
  })
193
289
  .catch(() => {});
194
290
  },
291
+ hideComment() {
292
+ this.$confirm("确定隐藏该评论吗?", "提示", {
293
+ confirmButtonText: "确定",
294
+ cancelButtonText: "取消",
295
+ type: "warning",
296
+ })
297
+ .then(() => {
298
+ this.$emit("hide", this.commentId);
299
+ })
300
+ .catch(() => {});
301
+ },
195
302
  dataFormat(str) {
196
303
  let d = new Date(str);
197
304
  return (
@@ -208,7 +315,9 @@ export default {
208
315
  fillZero(d.getSeconds())
209
316
  );
210
317
  },
211
-
318
+ likesFormat(count) {
319
+ return count > 0 ? count : "";
320
+ },
212
321
  attachmentUploadFinish(data) {
213
322
  this.disableSubmitBtn = false;
214
323
  this.$emit("addNewReply", {
@@ -233,7 +342,9 @@ export default {
233
342
  }
234
343
  },
235
344
  hideForm() {},
236
- formatContent,
345
+ async formatContent(str) {
346
+ this.renderContent = await formatContent(str);
347
+ },
237
348
  async handleEmotionSelected(emotionVal) {
238
349
  const myField = document.querySelector(`#id${this.inputId}`);
239
350
  const value = emotionVal.key;
@@ -273,9 +384,29 @@ export default {
273
384
  position: relative;
274
385
  .u-toolbar {
275
386
  font-size: 12px;
387
+
276
388
  .el-button + .el-button {
277
389
  margin-left: 20px;
278
390
  }
391
+
392
+ &.u-toolbar--primary {
393
+ display: flex;
394
+ justify-content: space-between;
395
+
396
+ .u-toolbar-right {
397
+ padding-right: 5px;
398
+ }
399
+ }
400
+
401
+ .u-filter span {
402
+ display: flex;
403
+ align-items: center;
404
+ gap: 5px;
405
+ }
406
+ .u-icon-filter {
407
+ width: 16px;
408
+ height: 16px;
409
+ }
279
410
  }
280
411
  .u-date {
281
412
  color: #c0c4cc;
@@ -286,6 +417,7 @@ export default {
286
417
  }
287
418
  .u-cmt {
288
419
  padding: 5px 0 10px 0;
420
+ position: relative;
289
421
  .u-text {
290
422
  line-height: 1.715;
291
423
  img {
@@ -303,12 +435,33 @@ export default {
303
435
  }
304
436
  }
305
437
  }
438
+ .u-up {
439
+ width: 12px;
440
+ height: 12px;
441
+ position: relative;
442
+ top: 1px;
443
+ margin-right: 5px;
444
+ }
445
+ .u-like-count {
446
+ margin-left: 3px;
447
+ // &:before {
448
+ // content: "(";
449
+ // }
450
+ // &:after {
451
+ // content: ")";
452
+ // }
453
+ color: #999;
454
+ }
306
455
  }
307
456
  @media screen and (max-width: 767px) {
308
457
  .c-comment-cmt {
309
458
  .u-toolbar {
310
459
  position: static;
311
460
  margin-top: 10px;
461
+
462
+ &.u-toolbar--primary {
463
+ display: block !important;
464
+ }
312
465
  }
313
466
  }
314
467
  }
@@ -8,7 +8,7 @@
8
8
  >
9
9
  :
10
10
  </span>
11
- <div class="u-reply-text" v-html="formatContent(content)"></div>
11
+ <div class="u-reply-text" v-html="renderContent"></div>
12
12
  <!--<div class="u-reply-text" v-html="content"></div>-->
13
13
  <!-- <p v-for="(p, index) in getPList(content)" :key="index" v-html="formatContent(p)"></p> -->
14
14
  </div>
@@ -22,13 +22,41 @@
22
22
  ></el-image>
23
23
  </div>
24
24
  <div class="u-toolbar">
25
+ <el-button
26
+ class="u-admin"
27
+ v-if="!currentUserHadLike"
28
+ type="text"
29
+ size="mini"
30
+ @click="doLike(true)"
31
+ ><img
32
+ class="u-up"
33
+ src="../../assets/img/heart_1.svg"
34
+ alt=""
35
+ />点赞<span class="u-like-count">{{
36
+ likesFormat(hasLikeCount)
37
+ }}</span></el-button
38
+ >
39
+ <el-button
40
+ class="u-admin"
41
+ type="text"
42
+ size="mini"
43
+ v-if="currentUserHadLike"
44
+ @click="doLike(false)"
45
+ ><img
46
+ class="u-up"
47
+ src="../../assets/img/heart_2.svg"
48
+ alt=""
49
+ />已赞<span class="u-like-count">{{
50
+ likesFormat(hasLikeCount)
51
+ }}</span></el-button
52
+ >
25
53
  <el-button
26
54
  class="u-admin"
27
55
  v-if="canReply"
28
56
  link
29
57
  icon="ChatLineRound"
30
58
  size="small"
31
- @click="showReplyForReplyInput()"
59
+ @click="showReplyForReplyInput"
32
60
  type="primary"
33
61
  >回复</el-button
34
62
  >
@@ -39,9 +67,20 @@
39
67
  icon="Delete"
40
68
  size="small"
41
69
  type="danger"
42
- @click="deleteComment()"
70
+ @click="deleteComment"
43
71
  >删除</el-button
44
72
  >
73
+ <el-button
74
+ class="u-admin"
75
+ type="text"
76
+ size="mini"
77
+ icon="Delete"
78
+ v-if="canHide"
79
+ @click="hideComment"
80
+ title="拉入黑洞后,仅评论者自己独自可见"
81
+ >
82
+ 黑洞</el-button
83
+ >
45
84
  <time class="u-date">
46
85
  <i class="Clock"></i>
47
86
  {{ dataFormat(date) }}
@@ -58,13 +97,16 @@ function fillZero(num) {
58
97
  }
59
98
  export default {
60
99
  props: [
61
- "commentId",
100
+ "commentId",
62
101
  "content",
63
102
  "attachments",
64
103
  "date",
65
104
  "hasReply",
66
105
  "canDelete",
106
+ "canHide",
67
107
  "canReply",
108
+ "isLike", // 是否已点赞
109
+ "likes", // 点赞数
68
110
  "userHref",
69
111
  "replyForUsername",
70
112
  "replyForUserId",
@@ -72,6 +114,10 @@ export default {
72
114
  data: function () {
73
115
  return {
74
116
  showInput: false,
117
+ currentUserHadLike: this.isLike,
118
+ hasLikeCount: this.likes,
119
+
120
+ renderContent: "",
75
121
  };
76
122
  },
77
123
  computed: {
@@ -81,6 +127,14 @@ export default {
81
127
  });
82
128
  },
83
129
  },
130
+ watch: {
131
+ content: {
132
+ handler: function (val) {
133
+ this.formatContent(val);
134
+ },
135
+ immediate: true,
136
+ },
137
+ },
84
138
  methods: {
85
139
  profileLink: function (uid) {
86
140
  return authorLink(uid);
@@ -88,10 +142,22 @@ export default {
88
142
  showAttachment: function (val) {
89
143
  return resolveImagePath(val) + "?x-oss-process=style/comment_thumb";
90
144
  },
91
- formatContent,
145
+ async formatContent(str) {
146
+ this.renderContent = await formatContent(str);
147
+ },
92
148
  getPList(content) {
93
149
  return content.split("\n");
94
150
  },
151
+ doLike(setLike) {
152
+ if (setLike === this.currentUserHadLike) {
153
+ return;
154
+ }
155
+ this.currentUserHadLike = setLike;
156
+ this.hasLikeCount = setLike
157
+ ? this.hasLikeCount + 1
158
+ : this.hasLikeCount - 1;
159
+ this.$emit("setLikeComment", setLike);
160
+ },
95
161
  deleteComment() {
96
162
  this.$confirm("确定删除该评论吗?", "提示", {
97
163
  confirmButtonText: "确定",
@@ -103,6 +169,20 @@ export default {
103
169
  })
104
170
  .catch(() => {});
105
171
  },
172
+ hideComment() {
173
+ this.$confirm("确定隐藏该评论吗?", "提示", {
174
+ confirmButtonText: "确定",
175
+ cancelButtonText: "取消",
176
+ type: "warning",
177
+ })
178
+ .then(() => {
179
+ this.$emit("hide", this.commentId);
180
+ })
181
+ .catch(() => {});
182
+ },
183
+ likesFormat(count) {
184
+ return count > 0 ? count : "";
185
+ },
106
186
  dataFormat(str) {
107
187
  let d = new Date(str);
108
188
  return (
@@ -18,6 +18,12 @@
18
18
  type="pop"
19
19
  :max="6">
20
20
  </Emotion>
21
+ <quickReply @reply="onQuickReply"></quickReply>
22
+ <div class="c-comment-secret">
23
+ <el-checkbox class="u-secret" v-model="is_secret" border size="small">悄悄话
24
+ <el-tooltip class="item" effect="dark" content="勾选悄悄话后仅作者和你可见,并且不可再变更状态" placement="top">
25
+ <el-icon><InfoFilled></InfoFilled></el-icon> </el-tooltip></el-checkbox>
26
+ </div>
21
27
  </div>
22
28
  <Uploader
23
29
  class="u-uploader"
@@ -42,11 +48,13 @@
42
48
  <script>
43
49
  import Uploader from "./Upload.vue";
44
50
  import Emotion from "@jx3box/jx3box-emotion/src/Emotion2.vue";
51
+ import QuickReply from "./QuickReply.vue";
45
52
 
46
53
  export default {
47
54
  components: {
48
55
  Uploader,
49
- Emotion
56
+ Emotion,
57
+ QuickReply
50
58
  },
51
59
  props: {
52
60
  // 用于判定该评论组件是否在底部
@@ -65,7 +73,8 @@ export default {
65
73
  newComment: {
66
74
  content: ""
67
75
  },
68
- inputId: "textarea-top"
76
+ inputId: "textarea-top",
77
+ is_secret: false,
69
78
  };
70
79
  },
71
80
  methods: {
@@ -77,6 +86,13 @@ export default {
77
86
  this.attachmentUploadFinish([]);
78
87
  }
79
88
  },
89
+ onQuickReply(item) {
90
+ this.$emit("submit", {
91
+ content: item,
92
+ attachmentList: [],
93
+ is_template: 1,
94
+ });
95
+ },
80
96
  // 文件上传完成后,进行数据提交
81
97
  attachmentUploadFinish(data) {
82
98
  this.$emit("submit", {
@@ -127,3 +143,17 @@ export default {
127
143
  }
128
144
  };
129
145
  </script>
146
+
147
+ <style lang="less">
148
+ .c-comment-secret {
149
+ margin-left: 15px;
150
+
151
+ .u-secret {
152
+ display: flex;
153
+ align-items: center;
154
+ .el-checkbox__inner{
155
+ display:block;
156
+ }
157
+ }
158
+ }
159
+ </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="c-comment-cmt">
3
- <div>
3
+ <div class="c-comment-cmt__author">
4
4
  <el-link
5
5
  class="u-name"
6
6
  type="primary"
@@ -9,26 +9,37 @@
9
9
  >{{ username || "人字榜800线无名小侠" }}</el-link
10
10
  >
11
11
  <span class="u-mark u-top" v-if="item.is_top"
12
- ><i class="Download"></i>置顶</span
12
+ ><el-icon><Download></Download></el-icon>置顶</span
13
13
  >
14
14
  <span class="u-mark u-star" v-if="item.is_star"
15
- ><i class="Star"></i>精华</span
15
+ ><el-icon><Star></Star></el-icon>精华</span
16
+ >
17
+ <span class="u-mark u-secret" v-if="item.is_secret"
18
+ ><el-icon><Cherry></Cherry></el-icon>悄悄话</span
16
19
  >
17
20
  </div>
18
21
  <CommentContent
19
- :date="item.commentDate"
22
+ :date="item.commentDate"
20
23
  :content="item.content"
21
24
  :comment-id="item.id"
22
25
  :attachments="stringToArray(item.attachments)"
23
- :can-delete="power.allow || power.uid == item.userId"
24
- :can-set-top="power.is_author && !item.is_top"
25
- :can-cancel-top="power.is_author && item.is_top"
26
- :can-set-star="!item.is_star && power.group >= 64"
27
- :can-cancel-star="item.is_star && power.group >= 64"
26
+ :can-delete="power.can_del || power.uid == item.userId"
27
+ :can-set-top="(power.is_author || power.is_editor) && !item.is_top"
28
+ :can-cancel-top="(power.is_author || power.is_editor) && item.is_top"
29
+ :can-set-star="!item.is_star && (power.is_author || power.is_editor)"
30
+ :can-cancel-star="item.is_star &&(power.is_author || power.is_editor)"
31
+ :can-add-white="!item.is_white && power.article_open_white == 1"
32
+ :can-remove-white="item.is_white && (power.is_author == 1 || power.is_editor == 1)"
33
+ :can-hide="(power.is_author == 1 || power.is_editor == 1)"
34
+ :is-like="item.is_likes == 1"
35
+ :likes="~~item.likes"
28
36
  @addNewReply="addNewReply"
29
37
  @deleteComment="deleteComment"
30
38
  @setTopComment="setTopComment"
31
39
  @setStarComment="setStarComment"
40
+ @setLikeComment="setLikeComment"
41
+ @setWhiteComment="setWhiteComment"
42
+ @hide="hideComment"
32
43
  />
33
44
  <ReplyList
34
45
  :data="replyList"
@@ -38,6 +49,8 @@
38
49
  @deleteReply="deleteReply"
39
50
  @goto="gotoReplyListIndex"
40
51
  @resetReply="resetReply"
52
+ @setLikeComment="setLikeReply"
53
+ @hide="hideComment"
41
54
  />
42
55
  </div>
43
56
  </template>
@@ -86,12 +99,24 @@ export default {
86
99
  deleteComment() {
87
100
  this.$emit("deleteComment", this.item.id);
88
101
  },
102
+ hideComment(){
103
+ this.$emit("hide", this.item.id);
104
+ },
89
105
  setTopComment(setTop) {
90
106
  this.$emit("setTopComment", this.item.id, setTop);
91
107
  },
92
108
  setStarComment(setStar) {
93
109
  this.$emit("setStarComment", this.item.id, setStar);
94
110
  },
111
+ setLikeComment(setLike) {
112
+ this.$emit("setLikeComment", this.item.id, setLike);
113
+ },
114
+ setLikeReply(id, setLike) {
115
+ this.$emit("setLikeComment", id, setLike);
116
+ },
117
+ setWhiteComment( white) {
118
+ this.$emit("setWhiteComment", this.item.id, white);
119
+ },
95
120
  addNewReply(data) {
96
121
  POST(`${this.baseApi}/comment/${this.item.id}/reply`, null, data)
97
122
  .then(() => {
@@ -147,6 +172,9 @@ export default {
147
172
 
148
173
  <style lang="less">
149
174
  .c-comment-cmt {
175
+ .u-name{
176
+ margin-right: 6px;
177
+ }
150
178
  .u-mark {
151
179
  font-style: normal;
152
180
  font-size: 12px;
@@ -168,5 +196,8 @@ export default {
168
196
  margin-right: 2px;
169
197
  }
170
198
  }
199
+ .u-secret{
200
+ background-color:#ff99cc;
201
+ }
171
202
  }
172
203
  </style>
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <div class="c-jx3box-reply">
3
+ <el-popover
4
+ :visible-arrow="true"
5
+ placement="top"
6
+ ref="quickReply"
7
+ trigger="click"
8
+ popper-class="c-jx3box-reply-pop"
9
+ >
10
+ <div class="c-jx3box-reply-pop__content">
11
+ <el-icon class="u-close" @click="closePop"><Close></Close></el-icon>
12
+ <div class="u-title">快捷回复</div>
13
+ <div class="m-reply-list">
14
+ <div
15
+ class="m-reply-list__item"
16
+ v-for="(item, index) in replyTemplate"
17
+ :key="index"
18
+ @click="reply(item)"
19
+ >
20
+ {{ item }}
21
+ </div>
22
+ </div>
23
+ </div>
24
+ <template #reference>
25
+ <img
26
+ class="u-reference"
27
+ width="24"
28
+ height="24"
29
+ src="../../assets/img/comment.svg"
30
+ alt="comment"
31
+ />
32
+ </template>
33
+ </el-popover>
34
+ </div>
35
+ </template>
36
+
37
+ <script>
38
+ import replyTemplate from "../../assets/data/reply_template.json";
39
+ export default {
40
+ name: "QuickReply",
41
+ data() {
42
+ return {
43
+ replyTemplate,
44
+ };
45
+ },
46
+ emits: ["reply"],
47
+ methods: {
48
+ // 关闭弹窗
49
+ closePop() {
50
+ if (this.$refs.quickReply) {
51
+ this.$refs.quickReply.doClose();
52
+ }
53
+ },
54
+ reply(item) {
55
+ this.$emit("reply", item);
56
+ this.closePop();
57
+ },
58
+ }
59
+ };
60
+ </script>
61
+
62
+ <style lang="less">
63
+ @import "../../assets/css/quick-reply.less";
64
+ </style>
@@ -18,12 +18,12 @@
18
18
  <el-form-item>
19
19
  <div class="c-comment-tools">
20
20
  <el-icon class="u-upload-icon" @click="showUploader = !showUploader"><Picture /></el-icon>
21
- <!--<Emotion-->
22
- <!-- class="c-comment-emotion"-->
23
- <!-- @selected="handleEmotionSelected"-->
24
- <!-- type="pop"-->
25
- <!-- :max="6"-->
26
- <!--&gt;</Emotion>-->
21
+ <Emotion
22
+ class="c-comment-emotion"
23
+ @selected="handleEmotionSelected"
24
+ type="pop"
25
+ :max="6">
26
+ </Emotion>
27
27
  </div>
28
28
  <Uploader
29
29
  v-if="showUploader"
@@ -49,7 +49,7 @@
49
49
 
50
50
  <script>
51
51
  import Uploader from "./Upload.vue";
52
- // import Emotion from "@jx3box/jx3box-emotion/src/Emotion2.vue";
52
+ import Emotion from "@jx3box/jx3box-emotion/src/Emotion2.vue";
53
53
  export default {
54
54
  props: ["username", "userHref", "currentId"],
55
55
  data: function () {
@@ -62,7 +62,7 @@ export default {
62
62
  },
63
63
  components: {
64
64
  Uploader,
65
- // Emotion,
65
+ Emotion,
66
66
  },
67
67
  mounted() {
68
68
  if (this.currentId) this.inputId = this.currentId;
@@ -10,17 +10,22 @@
10
10
  />
11
11
  <!--评论主体内容-->
12
12
  <CommentContentSimple
13
- :comment-id="reply.id"
13
+ :comment-id="reply.id"
14
14
  :date="reply.commentDate"
15
15
  :content="reply.content"
16
16
  :attachments="stringToArray(reply.attachments)"
17
- :can-delete="power.allow || power.uid == reply.userId"
17
+ :can-delete="power.can_del || power.uid == reply.userId"
18
+ :can-hide="(power.is_author == 1 || power.is_editor == 1)"
18
19
  :can-reply="power.uid != reply.userId"
19
20
  :user-href="profileLink(reply.replyForUID)"
20
21
  :reply-for-username="reply.replyForUsername"
21
22
  :reply-for-user-id="reply.replyForUID"
23
+ :is-like="reply.is_likes == 1"
24
+ :likes="~~reply.likes"
22
25
  @delete="deleteReply"
23
26
  @showReplyInput="showReplyForReplyFrom = !showReplyForReplyFrom"
27
+ @setLikeComment="setLikeComment"
28
+ @hide="hideReply"
24
29
  />
25
30
  <!--隐藏起来的回复评论的评论表单-->
26
31
  <ReplyForReply
@@ -68,6 +73,12 @@ export default {
68
73
  deleteReply(id) {
69
74
  this.$emit("deleteReply", id);
70
75
  },
76
+ hideReply(id) {
77
+ this.$emit("hide", id);
78
+ },
79
+ setLikeComment(setLike) {
80
+ this.$emit("setLikeComment", this.reply.id, setLike);
81
+ },
71
82
  doReply(replyData) {
72
83
  (replyData.replyForUID = this.reply.userId),
73
84
  (replyData.replyForCommentId = this.reply.id),
@@ -1,13 +1,15 @@
1
1
  <template>
2
2
  <div class="c-comment-replylist" v-if="data.length">
3
3
  <reply-item
4
- class="c-comment-reply"
4
+ class="c-comment-reply"
5
5
  v-for="reply in data"
6
6
  :key="reply.id"
7
7
  :reply="reply"
8
8
  :power="power"
9
9
  @deleteReply="deleteReply"
10
10
  @addReply="addReply"
11
+ @setLikeComment="setLikeComment"
12
+ @hide="hideReply"
11
13
  />
12
14
  <!-- 分页 -->
13
15
  <el-row v-if="data.length >= 3 || showPager">
@@ -42,7 +44,7 @@ export default {
42
44
  showPager: false,
43
45
  };
44
46
  },
45
- emits: ["goto", "resetReply", "deleteReply", "addNewReply"],
47
+ emits: ["goto", "resetReply", "deleteReply", "addNewReply", "setLikeComment", "hide"],
46
48
  methods: {
47
49
  showMore() {
48
50
  this.showPager = true;
@@ -58,6 +60,12 @@ export default {
58
60
  deleteReply(id) {
59
61
  this.$emit("deleteReply", id);
60
62
  },
63
+ hideReply(id) {
64
+ this.$emit("hide", id);
65
+ },
66
+ setLikeComment(id, isLike) {
67
+ this.$emit("setLikeComment", id, isLike);
68
+ },
61
69
  addReply(data) {
62
70
  this.$emit("addNewReply", data);
63
71
  },
@@ -2,16 +2,36 @@
2
2
  <el-container class="c-comment" v-loading="loading">
3
3
  <el-main>
4
4
  <CommentInputForm @submit="userSubmitInputForm" />
5
- <div class="c-comment-order">
6
- <span class="u-label">排序模式:</span>
7
- <el-radio-group
8
- v-model="isDesc"
9
- @change="changeOrder"
10
- size="small"
11
- >
12
- <el-radio-button label="DESC">最后靠前</el-radio-button>
13
- <el-radio-button label="ASC">最早靠前</el-radio-button>
14
- </el-radio-group>
5
+ <div class="c-comment-panel">
6
+ <div class="u-order">
7
+ <span class="u-label">排序模式:</span>
8
+ <el-radio-group
9
+ v-model="isDesc"
10
+ @change="changeOrder"
11
+ size="small"
12
+ >
13
+ <el-radio-button label="DESC">最后靠前</el-radio-button>
14
+ <el-radio-button label="ASC">最早靠前</el-radio-button>
15
+ </el-radio-group>
16
+ </div>
17
+ <div class="u-op">
18
+ <el-switch
19
+ class="c-comment-panel-likes"
20
+ v-model="orderByLikes"
21
+ @change="changeOrderByLikes"
22
+ active-text="获赞靠前"
23
+ >
24
+ </el-switch>
25
+ <el-switch
26
+ class="c-comment-panel-likes"
27
+ v-model="openWhiteList"
28
+ @change="changeWhiteList"
29
+ v-if="commentPower.is_author || commentPower.is_editor"
30
+ active-text="开启过滤"
31
+ title="开启过滤后,仅设为显示的评论可被其他人所见"
32
+ >
33
+ </el-switch>
34
+ </div>
15
35
  </div>
16
36
  <template v-if="isNormal">
17
37
  <div
@@ -37,6 +57,9 @@
37
57
  @setStarComment="setStarComment"
38
58
  :user-href="profileLink(item.userId)"
39
59
  :username="item.displayName"
60
+ @setWhiteComment="setWhiteComment"
61
+ @setLikeComment="setLikeComment"
62
+ @hide="hideComment"
40
63
  />
41
64
  </div>
42
65
 
@@ -106,6 +129,10 @@ export default {
106
129
  this.reloadCommentList(this.pager.index);
107
130
  setOrderMode(this.isDesc ? "DESC" : "ASC");
108
131
  },
132
+ changeOrderByLikes() {
133
+ this.reloadCommentList(this.pager.index);
134
+ // setOrderMode(this.orderByLikes ? false : true);
135
+ },
109
136
  setTopComment(id, setTop) {
110
137
  const action = setTop ? "set" : "cancel";
111
138
  PUT(`${this.baseAPI}/comment/${id}/top/${action}`)
@@ -114,6 +141,28 @@ export default {
114
141
  })
115
142
  .catch(() => {});
116
143
  },
144
+ changeWhiteList() {
145
+ PUT(
146
+ `${this.baseAPI}/meta/white-list/${
147
+ this.openWhiteList ? "open" : "close"
148
+ }`
149
+ ).then(()=>{
150
+ return this.reloadPower()
151
+ })
152
+ .then(() => {
153
+ this.commentPower.is_white = this.openWhiteList;
154
+ this.reloadCommentList(this.pager.index);
155
+ })
156
+ .catch(() => {});
157
+ },
158
+ setLikeComment(id, isLike) {
159
+ var action = isLike ? "like" : "unlike";
160
+ PUT(`${this.baseAPI}/comment/${id}/${action}`)
161
+ .then(() => {
162
+ // this.reloadCommentList(this.pager.index);
163
+ })
164
+ .catch(() => {});
165
+ },
117
166
  setStarComment(id, setStar) {
118
167
  const action = setStar ? "set" : "cancel";
119
168
  PUT(`${this.baseAPI}/comment/${id}/star/${action}`)
@@ -122,6 +171,15 @@ export default {
122
171
  })
123
172
  .catch(() => {});
124
173
  },
174
+ setWhiteComment(id, setWhite) {
175
+ // 设置某个评论为精选
176
+ var action = setWhite ? "add" : "remove";
177
+ PUT(`${this.baseAPI}/comment/${id}/white-list/${action}`)
178
+ .then(() => {
179
+ this.reloadCommentList(this.pager.index);
180
+ })
181
+ .catch(() => {});
182
+ },
125
183
  deleteComment(id) {
126
184
  DELETE(`${this.baseAPI}/comment/${id}`)
127
185
  .then(() => {
@@ -136,6 +194,20 @@ export default {
136
194
  })
137
195
  .catch(() => {});
138
196
  },
197
+ hideComment(id) {
198
+ PUT(`${this.baseAPI}/comment/${id}/hide`)
199
+ .then(() => {
200
+ this.$notify({
201
+ title: "",
202
+ message: "操作成功!",
203
+ type: "success",
204
+ duration: 3000,
205
+ position: "bottom-right",
206
+ });
207
+ this.reloadCommentList(this.pager.index);
208
+ })
209
+ .catch(() => {});
210
+ },
139
211
  reloadCommentList(index) {
140
212
  this.loading = true;
141
213
  let orderQuery = {};
@@ -188,6 +260,14 @@ export default {
188
260
  showAvatar: function (val) {
189
261
  return showAvatar(val, 144);
190
262
  },
263
+ reloadPower(){
264
+ GET(`${this.baseAPI}/i-am-author`)
265
+ .then((power) => {
266
+ this.commentPower = power;
267
+ this.openWhiteList = power.is_white;
268
+ })
269
+ .catch(() => {});
270
+ }
191
271
  },
192
272
  created() {
193
273
  this.baseAPI = `/api/next2/comment/${this.category}/article/${this.id}`;
@@ -323,14 +403,15 @@ export default {
323
403
  } */
324
404
  }
325
405
  }
326
- .c-comment-order {
406
+ .c-comment-panel {
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: space-between;
327
410
  background-color: #fafbfc;
328
411
  padding: 8px 10px;
329
412
  border-radius: 3px;
330
413
  border: 1px solid #eee;
331
414
  margin: 10px 0;
332
- .flex;
333
- align-items: center;
334
415
  .u-label {
335
416
  color: #666;
336
417
  margin-right: 10px;
@@ -343,4 +424,19 @@ export default {
343
424
  max-height: 168px;
344
425
  overflow: auto;
345
426
  }
427
+ .c-comment-panel-likes {
428
+ margin-left: 10px;
429
+ }
430
+ .c-comment-alert {
431
+ color: #e6a23c;
432
+ margin-left: 10px;
433
+ font-size: 12px;
434
+ }
435
+ @media screen and (max-width: 720px) {
436
+ .c-comment-panel {
437
+ .u-op{
438
+ display: none;
439
+ }
440
+ }
441
+ }
346
442
  </style>
package/utils/emotion.js CHANGED
@@ -1,10 +1,21 @@
1
- import JX3_EMOTION from '@jx3box/jx3box-emotion'
2
-
3
- function formatContent(val) {
4
- const ins = new JX3_EMOTION(val)
5
- return ins.code
1
+ import JX3_EMOTION from "@jx3box/jx3box-emotion";
2
+ function escapeHtml(str) {
3
+ return str.replace(/[<>"']/g, function (match) {
4
+ switch (match) {
5
+ case "<":
6
+ return "&lt;";
7
+ case ">":
8
+ return "&gt;";
9
+ case '"':
10
+ return "&quot;";
11
+ case "'":
12
+ return "&#39;";
13
+ }
14
+ });
6
15
  }
7
-
8
- export {
9
- formatContent
16
+ async function formatContent(val) {
17
+ const ins = new JX3_EMOTION(escapeHtml(val));
18
+ return await ins._renderHTML();
10
19
  }
20
+
21
+ export { formatContent };