artalk 2.2.12 → 2.3.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.
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +3216 -2883
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -0
- package/dist/ArtalkLite.es.js +5096 -0
- package/dist/ArtalkLite.iife.js +1 -0
- package/dist/ArtalkLite.js +1 -0
- package/index.html +2 -2
- package/package.json +6 -5
- package/src/api/index.ts +20 -1
- package/src/api/request.ts +7 -7
- package/src/artalk.ts +68 -50
- package/src/comment/actions.ts +87 -0
- package/src/{components/html → comment}/comment.html +1 -1
- package/src/comment/comment.ts +191 -0
- package/src/comment/index.ts +3 -0
- package/src/comment/render.ts +425 -0
- package/src/components/action-btn.ts +6 -3
- package/src/components/dialog.ts +7 -3
- package/src/components/read-more-btn.ts +6 -2
- package/src/context.ts +200 -13
- package/src/defaults.ts +16 -5
- package/src/editor/editor.html +18 -0
- package/src/editor/editor.ts +420 -0
- package/src/editor/index.ts +3 -0
- package/src/editor/plugs/editor-plug.ts +51 -0
- package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.less +1 -0
- package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.ts +65 -63
- package/src/editor/plugs/header-input-plug.ts +79 -0
- package/src/{components/editor-plugs → editor/plugs}/preview-plug.less +0 -0
- package/src/editor/plugs/preview-plug.ts +40 -0
- package/src/editor/plugs/upload-plug.ts +125 -0
- package/src/i18n/en.ts +77 -0
- package/src/i18n/index.ts +21 -0
- package/src/i18n/zh-CN.ts +81 -0
- package/src/layer/index.ts +4 -0
- package/src/{components → layer}/layer.ts +9 -9
- package/src/{components/html → layer}/sidebar-layer.html +0 -0
- package/src/{components → layer}/sidebar-layer.ts +17 -46
- package/src/lib/checker/admin-checker.ts +7 -6
- package/src/lib/checker/captcha-checker.ts +5 -5
- package/src/lib/checker/index.ts +22 -17
- package/src/lib/component.ts +7 -2
- package/src/lib/ui.ts +3 -10
- package/src/lib/user.ts +20 -3
- package/src/lib/utils.ts +23 -9
- package/src/list/index.ts +3 -0
- package/src/{components → list}/list-lite.ts +80 -99
- package/src/{components → list}/list-nest.ts +0 -0
- package/src/{components/html → list}/list.html +3 -6
- package/src/{components → list}/list.ts +37 -35
- package/src/style/comment.less +23 -10
- package/src/style/editor.less +16 -10
- package/src/style/list.less +4 -7
- package/src/style/main.less +3 -1
- package/src/style/pagination.less +1 -1
- package/test/ArtalkLite.html +15 -0
- package/types/artalk-config.d.ts +50 -32
- package/types/context.d.ts +128 -0
- package/types/event.d.ts +6 -66
- package/types/global.d.ts +1 -0
- package/{vite-common.config.ts → vite-base.config.ts} +6 -4
- package/vite-demo.config.ts +2 -4
- package/vite-lite.config.ts +22 -0
- package/vite.config.ts +9 -12
- package/src/components/_component.ts.txt +0 -10
- package/src/components/comment.ts +0 -605
- package/src/components/editor-plugs/_example-plug.ts.txt +0 -29
- package/src/components/editor-plugs/editor-plug.ts +0 -20
- package/src/components/editor-plugs/preview-plug.ts +0 -48
- package/src/components/editor.ts +0 -607
- package/src/components/html/editor.html +0 -18
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
import { ListData, CommentData, NotifyData
|
|
2
|
-
import Context from '
|
|
1
|
+
import { ListData, CommentData, NotifyData } from '~/types/artalk-data'
|
|
2
|
+
import Context from '~/types/context'
|
|
3
3
|
import Component from '../lib/component'
|
|
4
4
|
import * as Utils from '../lib/utils'
|
|
5
5
|
import * as Ui from '../lib/ui'
|
|
6
6
|
import Api from '../api'
|
|
7
|
-
import Comment from '
|
|
8
|
-
import Pagination from '
|
|
9
|
-
import ReadMoreBtn from '
|
|
7
|
+
import Comment from '../comment'
|
|
8
|
+
import Pagination from '../components/pagination'
|
|
9
|
+
import ReadMoreBtn from '../components/read-more-btn'
|
|
10
10
|
import * as ListNest from './list-nest'
|
|
11
11
|
import { backendMinVersion } from '../../package.json'
|
|
12
12
|
|
|
13
13
|
export default class ListLite extends Component {
|
|
14
14
|
protected $commentsWrap: HTMLElement
|
|
15
15
|
|
|
16
|
-
protected commentList: Comment[] = [] // Note: 无层级结构 + 无须排列
|
|
17
|
-
protected get commentDataList() { return this.commentList.map(c => c.data) }
|
|
18
|
-
|
|
19
16
|
protected data?: ListData
|
|
20
17
|
protected isLoading: boolean = false
|
|
21
18
|
|
|
22
|
-
public noCommentText
|
|
19
|
+
public noCommentText: string // 无评论时显示
|
|
23
20
|
|
|
24
21
|
/** 平铺模式 */
|
|
25
22
|
public flatMode = false
|
|
@@ -56,7 +53,7 @@ export default class ListLite extends Component {
|
|
|
56
53
|
this.$commentsWrap = this.$el.querySelector('.atk-list-comments-wrap')!
|
|
57
54
|
|
|
58
55
|
// 评论为空时显示字符
|
|
59
|
-
|
|
56
|
+
this.noCommentText = ctx.conf.noComment || ctx.$t('noComment')
|
|
60
57
|
|
|
61
58
|
// 嵌套排序方式
|
|
62
59
|
this.nestSortBy = this.ctx.conf.nestSort || 'DATE_ASC'
|
|
@@ -65,12 +62,21 @@ export default class ListLite extends Component {
|
|
|
65
62
|
window.setInterval(() => {
|
|
66
63
|
this.$el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
|
|
67
64
|
const date = el.getAttribute('data-atk-comment-date')
|
|
68
|
-
el.innerText = Utils.timeAgo(new Date(Number(date)))
|
|
65
|
+
el.innerText = Utils.timeAgo(new Date(Number(date)), this.ctx)
|
|
69
66
|
})
|
|
70
67
|
}, 30 * 1000) // 30s 更新一次
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public getData() {
|
|
71
|
+
return this.data
|
|
72
|
+
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
this.
|
|
74
|
+
public clearData() {
|
|
75
|
+
this.data = undefined
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public getCommentsWrapEl() {
|
|
79
|
+
return this.$commentsWrap
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
/** 评论获取 */
|
|
@@ -93,15 +99,15 @@ export default class ListLite extends Component {
|
|
|
93
99
|
showLoading()
|
|
94
100
|
|
|
95
101
|
// 事件通知(开始加载评论)
|
|
96
|
-
this.ctx.trigger('
|
|
102
|
+
this.ctx.trigger('list-load')
|
|
97
103
|
|
|
98
104
|
// 清空评论(加载按钮)
|
|
99
|
-
if (this.pageMode === 'read-more' && offset === 0) { this.clearAllComments() }
|
|
105
|
+
if (this.pageMode === 'read-more' && offset === 0) { this.ctx.clearAllComments() }
|
|
100
106
|
|
|
101
107
|
// 请求评论数据
|
|
102
108
|
let listData: ListData
|
|
103
109
|
try {
|
|
104
|
-
listData = await
|
|
110
|
+
listData = await this.ctx.getApi().get(offset, this.pageSize, this.flatMode, this.paramsEditor)
|
|
105
111
|
} catch (e: any) {
|
|
106
112
|
this.onError(e.msg || String(e), offset, e.data)
|
|
107
113
|
throw e
|
|
@@ -125,14 +131,14 @@ export default class ListLite extends Component {
|
|
|
125
131
|
|
|
126
132
|
protected onLoad(data: ListData, offset: number) {
|
|
127
133
|
// 清空评论(分页条)
|
|
128
|
-
if (this.pageMode === 'pagination') { this.clearAllComments() }
|
|
134
|
+
if (this.pageMode === 'pagination') { this.ctx.clearAllComments() }
|
|
129
135
|
|
|
130
136
|
this.data = data
|
|
131
137
|
|
|
132
138
|
// 版本检测
|
|
133
139
|
const feMinVersion = data.api_version?.fe_min_version || '0.0.0'
|
|
134
|
-
if (this.ctx.conf.versionCheck && this.versionCheck('
|
|
135
|
-
if (this.ctx.conf.versionCheck && this.versionCheck('
|
|
140
|
+
if (this.ctx.conf.versionCheck && this.versionCheck('frontend', feMinVersion, ARTALK_VERSION)) return
|
|
141
|
+
if (this.ctx.conf.versionCheck && this.versionCheck('backend', backendMinVersion, data.api_version?.version)) return
|
|
136
142
|
|
|
137
143
|
// 图片上传功能
|
|
138
144
|
if (data.conf && typeof data.conf.img_upload === "boolean") {
|
|
@@ -148,8 +154,8 @@ export default class ListLite extends Component {
|
|
|
148
154
|
// 加载后事件
|
|
149
155
|
this.refreshUI()
|
|
150
156
|
|
|
151
|
-
this.ctx.
|
|
152
|
-
this.ctx.trigger('
|
|
157
|
+
this.ctx.updateNotifies(data.unread || [])
|
|
158
|
+
this.ctx.trigger('list-loaded')
|
|
153
159
|
this.ctx.trigger('conf-updated')
|
|
154
160
|
|
|
155
161
|
if (this.onAfterLoad) this.onAfterLoad(data)
|
|
@@ -179,11 +185,12 @@ export default class ListLite extends Component {
|
|
|
179
185
|
onClick: async (o) => {
|
|
180
186
|
await this.fetchComments(o)
|
|
181
187
|
},
|
|
188
|
+
text: this.ctx.$t('loadMore'),
|
|
182
189
|
})
|
|
183
190
|
this.$el.append(this.readMoreBtn.$el)
|
|
184
191
|
|
|
185
192
|
// 滚动到底部自动加载
|
|
186
|
-
if (this.conf.pagination
|
|
193
|
+
if (this.conf.pagination.autoLoad) {
|
|
187
194
|
// 添加滚动事件监听
|
|
188
195
|
const at = this.scrollListenerAt || document
|
|
189
196
|
if (this.autoLoadScrollEvent) at.removeEventListener('scroll', this.autoLoadScrollEvent) // 解除原有
|
|
@@ -210,7 +217,7 @@ export default class ListLite extends Component {
|
|
|
210
217
|
pageSize: this.pageSize,
|
|
211
218
|
onChange: async (o) => {
|
|
212
219
|
if (this.ctx.conf.editorTravel === true) {
|
|
213
|
-
this.ctx.
|
|
220
|
+
this.ctx.editorTravelBack() // 防止评论框被吞
|
|
214
221
|
}
|
|
215
222
|
|
|
216
223
|
await this.fetchComments(o)
|
|
@@ -237,14 +244,14 @@ export default class ListLite extends Component {
|
|
|
237
244
|
|
|
238
245
|
// 加载更多按钮显示错误
|
|
239
246
|
if (offset !== 0 && this.pageMode === 'read-more') {
|
|
240
|
-
this.readMoreBtn?.showErr(
|
|
247
|
+
this.readMoreBtn?.showErr(this.$t('loadFail'))
|
|
241
248
|
return
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
// 显示错误对话框
|
|
245
|
-
const $err = Utils.createElement(`<span>${msg}
|
|
252
|
+
const $err = Utils.createElement(`<span>${msg},${this.$t('listLoadFailMsg')}<br/></span>`)
|
|
246
253
|
|
|
247
|
-
const $retryBtn = Utils.createElement(
|
|
254
|
+
const $retryBtn = Utils.createElement(`<span style="cursor:pointer;">${this.$t('listRetry')}</span>`)
|
|
248
255
|
$retryBtn.onclick = () => (this.fetchComments(0))
|
|
249
256
|
$err.appendChild($retryBtn)
|
|
250
257
|
|
|
@@ -264,9 +271,9 @@ export default class ListLite extends Component {
|
|
|
264
271
|
sidebarView = `sites|${JSON.stringify(viewLoadParam)}`
|
|
265
272
|
}
|
|
266
273
|
|
|
267
|
-
adminBtn.onclick = () =>
|
|
268
|
-
view: sidebarView
|
|
269
|
-
})
|
|
274
|
+
adminBtn.onclick = () => this.ctx.showSidebar({
|
|
275
|
+
view: sidebarView as any
|
|
276
|
+
})
|
|
270
277
|
|
|
271
278
|
Ui.setError(this.$el, $err)
|
|
272
279
|
}
|
|
@@ -274,7 +281,7 @@ export default class ListLite extends Component {
|
|
|
274
281
|
/** 刷新界面 */
|
|
275
282
|
public refreshUI() {
|
|
276
283
|
// 无评论
|
|
277
|
-
const isNoComment = this.
|
|
284
|
+
const isNoComment = this.ctx.getCommentList().length <= 0
|
|
278
285
|
let $noComment = this.$commentsWrap.querySelector<HTMLElement>('.atk-list-no-comment')
|
|
279
286
|
|
|
280
287
|
if (isNoComment) {
|
|
@@ -288,31 +295,35 @@ export default class ListLite extends Component {
|
|
|
288
295
|
}
|
|
289
296
|
|
|
290
297
|
// 仅管理员显示控制
|
|
291
|
-
this.ctx.
|
|
298
|
+
this.ctx.checkAdminShowEl()
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** 重新加载列表 */
|
|
302
|
+
public reload() {
|
|
303
|
+
this.fetchComments(0)
|
|
292
304
|
}
|
|
293
305
|
|
|
294
306
|
/** 创建新评论 */
|
|
295
307
|
protected createComment(cData: CommentData, ctxData?: CommentData[]) {
|
|
296
|
-
if (!ctxData) ctxData = this.
|
|
297
|
-
|
|
298
|
-
const comment = new Comment(this.ctx, cData
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
comment.replyTo = (cData.rid ? ctxData.find(c => c.id === cData.rid) : undefined)
|
|
308
|
+
if (!ctxData) ctxData = this.ctx.getCommentDataList()
|
|
309
|
+
|
|
310
|
+
const comment = new Comment(this.ctx, cData, {
|
|
311
|
+
isFlatMode: this.flatMode,
|
|
312
|
+
afterRender: () => {
|
|
313
|
+
if (this.renderComment) this.renderComment(comment)
|
|
314
|
+
},
|
|
315
|
+
onDelete: (c: Comment) => {
|
|
316
|
+
this.ctx.deleteComment(c)
|
|
317
|
+
this.refreshUI()
|
|
318
|
+
},
|
|
319
|
+
replyTo: (cData.rid ? ctxData.find(c => c.id === cData.rid) : undefined)
|
|
320
|
+
})
|
|
310
321
|
|
|
311
322
|
// 渲染元素
|
|
312
323
|
comment.render()
|
|
313
324
|
|
|
314
325
|
// 放入 comment 总表中
|
|
315
|
-
this.
|
|
326
|
+
this.ctx.getCommentList().push(comment)
|
|
316
327
|
|
|
317
328
|
return comment
|
|
318
329
|
}
|
|
@@ -337,7 +348,7 @@ export default class ListLite extends Component {
|
|
|
337
348
|
|
|
338
349
|
// 显示并播放渐入动画
|
|
339
350
|
this.$commentsWrap.appendChild(rootC.getEl())
|
|
340
|
-
rootC.
|
|
351
|
+
rootC.getRender().playFadeAnim()
|
|
341
352
|
|
|
342
353
|
// 加载子评论
|
|
343
354
|
const that = this
|
|
@@ -355,7 +366,7 @@ export default class ListLite extends Component {
|
|
|
355
366
|
})(rootC, rootNode)
|
|
356
367
|
|
|
357
368
|
// 限高检测
|
|
358
|
-
rootC.checkHeightLimit()
|
|
369
|
+
rootC.getRender().checkHeightLimit()
|
|
359
370
|
})
|
|
360
371
|
}
|
|
361
372
|
|
|
@@ -369,11 +380,11 @@ export default class ListLite extends Component {
|
|
|
369
380
|
if (cData.visible) {
|
|
370
381
|
if (insertMode === 'append') this.$commentsWrap.append(comment.getEl())
|
|
371
382
|
if (insertMode === 'prepend') this.$commentsWrap.prepend(comment.getEl())
|
|
372
|
-
comment.
|
|
383
|
+
comment.getRender().playFadeAnim()
|
|
373
384
|
}
|
|
374
385
|
|
|
375
386
|
// 平铺评论插入后 · 内容限高检测
|
|
376
|
-
comment.checkHeightLimit()
|
|
387
|
+
comment.getRender().checkHeightLimit()
|
|
377
388
|
|
|
378
389
|
return comment
|
|
379
390
|
}
|
|
@@ -389,24 +400,24 @@ export default class ListLite extends Component {
|
|
|
389
400
|
this.$commentsWrap.prepend(comment.getEl())
|
|
390
401
|
} else {
|
|
391
402
|
// 子评论 新增
|
|
392
|
-
const parent = this.findComment(commentData.rid)
|
|
403
|
+
const parent = this.ctx.findComment(commentData.rid)
|
|
393
404
|
if (parent) {
|
|
394
405
|
parent.putChild(comment, (this.nestSortBy === 'DATE_ASC' ? 'append' : 'prepend'))
|
|
395
406
|
|
|
396
407
|
// 若父评论存在 “子评论部分” 限高,取消限高
|
|
397
408
|
comment.getParents().forEach((p) => {
|
|
398
|
-
|
|
409
|
+
p.getRender().heightLimitRemoveForChildren()
|
|
399
410
|
})
|
|
400
411
|
}
|
|
401
412
|
}
|
|
402
413
|
|
|
403
|
-
comment.checkHeightLimit()
|
|
414
|
+
comment.getRender().checkHeightLimit()
|
|
404
415
|
|
|
405
416
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
|
|
406
|
-
comment.
|
|
417
|
+
comment.getRender().playFadeAnim() // 播放评论渐出动画
|
|
407
418
|
} else {
|
|
408
419
|
// 平铺模式
|
|
409
|
-
const comment = this.putCommentFlatMode(commentData, this.
|
|
420
|
+
const comment = this.putCommentFlatMode(commentData, this.ctx.getCommentDataList(), 'prepend')
|
|
410
421
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可见
|
|
411
422
|
}
|
|
412
423
|
|
|
@@ -415,36 +426,8 @@ export default class ListLite extends Component {
|
|
|
415
426
|
|
|
416
427
|
// 评论新增后
|
|
417
428
|
this.refreshUI()
|
|
418
|
-
this.ctx.trigger('
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
/** 查找评论项 */
|
|
422
|
-
protected findComment(id: number): Comment|undefined {
|
|
423
|
-
return this.commentList.find(c => c.data.id === id)
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/** 删除评论 */
|
|
427
|
-
public deleteComment(_comment: number|Comment) {
|
|
428
|
-
let comment: Comment
|
|
429
|
-
if (typeof _comment === 'number') {
|
|
430
|
-
const findComment = this.findComment(_comment)
|
|
431
|
-
if (!findComment) throw Error(`未找到评论 ${_comment}`)
|
|
432
|
-
comment = findComment
|
|
433
|
-
} else comment = _comment
|
|
434
|
-
|
|
435
|
-
comment.getEl().remove()
|
|
436
|
-
this.commentList.splice(this.commentList.indexOf(comment), 1)
|
|
437
|
-
|
|
438
|
-
if (this.data) this.data.total -= 1 // 评论数减 1
|
|
439
|
-
|
|
440
|
-
this.refreshUI()
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/** 清空所有评论 */
|
|
444
|
-
public clearAllComments() {
|
|
445
|
-
this.$commentsWrap.innerHTML = ''
|
|
446
|
-
this.data = undefined
|
|
447
|
-
this.commentList = []
|
|
429
|
+
this.ctx.trigger('list-loaded')
|
|
430
|
+
this.ctx.trigger('list-inserted', commentData)
|
|
448
431
|
}
|
|
449
432
|
|
|
450
433
|
/** 更新未读数据 */
|
|
@@ -453,33 +436,31 @@ export default class ListLite extends Component {
|
|
|
453
436
|
|
|
454
437
|
// 高亮评论
|
|
455
438
|
if (this.unreadHighlight === true) {
|
|
456
|
-
this.
|
|
457
|
-
const notify = this.unread.find(o => o.comment_id === comment.
|
|
439
|
+
this.ctx.getCommentList().forEach((comment) => {
|
|
440
|
+
const notify = this.unread.find(o => o.comment_id === comment.getID())
|
|
458
441
|
if (notify) {
|
|
459
|
-
comment.setUnread(true)
|
|
460
|
-
comment.
|
|
461
|
-
|
|
462
|
-
this.unread = this.unread.filter(o => o.comment_id !== comment.
|
|
463
|
-
this.ctx.
|
|
464
|
-
|
|
465
|
-
})
|
|
466
|
-
}
|
|
442
|
+
comment.getRender().setUnread(true)
|
|
443
|
+
comment.getRender().setOpenAction(() => {
|
|
444
|
+
window.open(notify.read_link)
|
|
445
|
+
this.unread = this.unread.filter(o => o.comment_id !== comment.getID()) // remove
|
|
446
|
+
this.ctx.updateNotifies(this.unread)
|
|
447
|
+
})
|
|
467
448
|
} else {
|
|
468
|
-
comment.setUnread(false)
|
|
449
|
+
comment.getRender().setUnread(false)
|
|
469
450
|
}
|
|
470
451
|
})
|
|
471
452
|
}
|
|
472
453
|
}
|
|
473
454
|
|
|
474
455
|
/** 版本检测 */
|
|
475
|
-
public versionCheck(name: '
|
|
456
|
+
public versionCheck(name: 'frontend'|'backend', needVersion: string, curtVersion: string): boolean {
|
|
476
457
|
const needUpdate = Utils.versionCompare(needVersion, curtVersion) === 1
|
|
477
458
|
if (needUpdate) {
|
|
478
459
|
// 需要更新
|
|
479
|
-
const errEl = Utils.createElement(`<div>Artalk ${name}版本已过时,请更新以获得完整体验<br/>`
|
|
460
|
+
const errEl = Utils.createElement(`<div>Artalk ${this.$t(name)}版本已过时,请更新以获得完整体验<br/>`
|
|
480
461
|
+ `如果你是管理员,请前往 “<a href="https://artalk.js.org/" target="_blank">官方文档</a>” 获得帮助`
|
|
481
462
|
+ `<br/><br/>`
|
|
482
|
-
+ `<span style="color: var(--at-color-meta);">当前${name}版本 ${curtVersion},需求版本 >= ${needVersion}</span><br/><br/>`
|
|
463
|
+
+ `<span style="color: var(--at-color-meta);">当前${this.$t(name)}版本 ${curtVersion},需求版本 >= ${needVersion}</span><br/><br/>`
|
|
483
464
|
+ `</div>`)
|
|
484
465
|
const ignoreBtn = Utils.createElement('<span style="cursor:pointer;">忽略</span>')
|
|
485
466
|
ignoreBtn.onclick = () => {
|
|
File without changes
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
<div class="atk-list">
|
|
2
2
|
<div class="atk-list-header">
|
|
3
3
|
<div class="atk-comment-count">
|
|
4
|
-
<div class="atk-text">
|
|
5
|
-
<span class="atk-comment-count-num">0</span>
|
|
6
|
-
条评论
|
|
7
|
-
</div>
|
|
4
|
+
<div class="atk-text"></div>
|
|
8
5
|
</div>
|
|
9
6
|
<div class="atk-right-action">
|
|
10
|
-
<span data-action="admin-close-comment" class="atk-hide" atk-only-admin-show
|
|
7
|
+
<span data-action="admin-close-comment" class="atk-hide" atk-only-admin-show></span>
|
|
11
8
|
<span data-action="open-sidebar" class="atk-hide atk-on">
|
|
12
9
|
<span class="atk-unread-badge" style="display: none;"></span>
|
|
13
|
-
<div class="atk-text"
|
|
10
|
+
<div class="atk-text"></div>
|
|
14
11
|
</span>
|
|
15
12
|
</div>
|
|
16
13
|
</div>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import '../style/list.less'
|
|
2
2
|
|
|
3
|
-
import { ListData } from '~/types/artalk-data'
|
|
4
|
-
import Context from '
|
|
3
|
+
import { ListData, NotifyData } from '~/types/artalk-data'
|
|
4
|
+
import Context from '~/types/context'
|
|
5
5
|
import * as Utils from '../lib/utils'
|
|
6
6
|
import * as Ui from '../lib/ui'
|
|
7
7
|
import Api from '../api'
|
|
8
|
-
import ListHTML from './
|
|
8
|
+
import ListHTML from './list.html?raw'
|
|
9
9
|
import ListLite from './list-lite'
|
|
10
10
|
|
|
11
11
|
export default class List extends ListLite {
|
|
@@ -13,6 +13,7 @@ export default class List extends ListLite {
|
|
|
13
13
|
private $openSidebarBtn!: HTMLElement
|
|
14
14
|
private $unreadBadge!: HTMLElement
|
|
15
15
|
private $commentCount!: HTMLElement
|
|
16
|
+
private $commentCountNum!: HTMLElement
|
|
16
17
|
private $dropdownWrap?: HTMLElement
|
|
17
18
|
|
|
18
19
|
constructor (ctx: Context) {
|
|
@@ -35,14 +36,18 @@ export default class List extends ListLite {
|
|
|
35
36
|
this.flatMode = flatMode
|
|
36
37
|
|
|
37
38
|
// 分页模式
|
|
38
|
-
this.pageMode = this.conf.pagination
|
|
39
|
-
this.pageSize = this.conf.pagination
|
|
39
|
+
this.pageMode = this.conf.pagination.readMore ? 'read-more' : 'pagination'
|
|
40
|
+
this.pageSize = this.conf.pagination.pageSize || 20
|
|
40
41
|
this.repositionAt = this.$el
|
|
41
42
|
|
|
42
43
|
// 操作按钮
|
|
43
44
|
this.initListActionBtn()
|
|
44
45
|
|
|
45
46
|
this.$commentCount = this.$el.querySelector('.atk-comment-count')!
|
|
47
|
+
this.$commentCount.innerHTML = this.$t('counter', {
|
|
48
|
+
count: '<span class="atk-comment-count-num">0</span>',
|
|
49
|
+
})
|
|
50
|
+
this.$commentCountNum = this.$commentCount.querySelector('.atk-comment-count-num')!
|
|
46
51
|
|
|
47
52
|
// 评论列表排序 Dropdown 下拉选择层
|
|
48
53
|
if (this.ctx.conf.listSort) {
|
|
@@ -53,13 +58,6 @@ export default class List extends ListLite {
|
|
|
53
58
|
this.$el.querySelector<HTMLElement>('.atk-copyright')!.innerHTML = `Powered By <a href="https://artalk.js.org" target="_blank" title="Artalk v${ARTALK_VERSION}">Artalk</a>`
|
|
54
59
|
|
|
55
60
|
// event listen
|
|
56
|
-
this.ctx.on('list-reload', () => (this.fetchComments(0))) // 刷新评论
|
|
57
|
-
this.ctx.on('list-refresh-ui', () => (this.refreshUI()))
|
|
58
|
-
this.ctx.on('list-import', (data) => (this.importComments(data)))
|
|
59
|
-
this.ctx.on('list-insert', (data) => (this.insertComment(data)))
|
|
60
|
-
this.ctx.on('list-delete', (comment) => (this.deleteComment(comment.id)))
|
|
61
|
-
this.ctx.on('list-update', (updateData) => { updateData(this.data);this.refreshUI() } )
|
|
62
|
-
this.ctx.on('unread-update', (data) => (this.showUnreadBadge(data.notifies?.length || 0)))
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
private initListActionBtn() {
|
|
@@ -69,7 +67,7 @@ export default class List extends ListLite {
|
|
|
69
67
|
this.$unreadBadge = this.$el.querySelector('.atk-unread-badge')!
|
|
70
68
|
|
|
71
69
|
this.$openSidebarBtn.addEventListener('click', () => {
|
|
72
|
-
this.ctx.
|
|
70
|
+
this.ctx.showSidebar()
|
|
73
71
|
})
|
|
74
72
|
|
|
75
73
|
// 关闭评论按钮
|
|
@@ -85,7 +83,7 @@ export default class List extends ListLite {
|
|
|
85
83
|
public refreshUI() {
|
|
86
84
|
super.refreshUI()
|
|
87
85
|
|
|
88
|
-
this.$
|
|
86
|
+
this.$commentCountNum.innerText = String(Number(this.data?.total) || 0)
|
|
89
87
|
|
|
90
88
|
// 已输入个人信息
|
|
91
89
|
if (!!this.ctx.user.data.nick && !!this.ctx.user.data.email) {
|
|
@@ -95,16 +93,17 @@ export default class List extends ListLite {
|
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
// 仅管理员显示控制
|
|
98
|
-
this.ctx.
|
|
99
|
-
this.$openSidebarBtn.querySelector<HTMLElement>('.atk-text')
|
|
96
|
+
this.ctx.checkAdminShowEl()
|
|
97
|
+
this.$openSidebarBtn.querySelector<HTMLElement>('.atk-text')!
|
|
98
|
+
.innerText = (!this.ctx.user.data.isAdmin) ? this.$t('msgCenter') : this.$t('ctrlCenter')
|
|
100
99
|
|
|
101
100
|
// 关闭评论
|
|
102
101
|
if (!!this.data && !!this.data.page && this.data.page.admin_only === true) {
|
|
103
|
-
this.ctx.
|
|
104
|
-
this.$closeCommentBtn.innerHTML = '
|
|
102
|
+
this.ctx.editorClose()
|
|
103
|
+
this.$closeCommentBtn.innerHTML = this.$t('openComment')
|
|
105
104
|
} else {
|
|
106
|
-
this.ctx.
|
|
107
|
-
this.$closeCommentBtn.innerHTML = '
|
|
105
|
+
this.ctx.editorOpen()
|
|
106
|
+
this.$closeCommentBtn.innerHTML = this.$t('closeComment')
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
|
|
@@ -116,7 +115,7 @@ export default class List extends ListLite {
|
|
|
116
115
|
|
|
117
116
|
// 防止评论框被吞
|
|
118
117
|
if (this.ctx.conf.editorTravel === true) {
|
|
119
|
-
this.ctx.
|
|
118
|
+
this.ctx.editorTravelBack()
|
|
120
119
|
}
|
|
121
120
|
}
|
|
122
121
|
|
|
@@ -133,7 +132,7 @@ export default class List extends ListLite {
|
|
|
133
132
|
}
|
|
134
133
|
if (!commentId) return
|
|
135
134
|
|
|
136
|
-
const comment = this.findComment(commentId)
|
|
135
|
+
const comment = this.ctx.findComment(commentId)
|
|
137
136
|
if (!comment) { // 若找不到评论
|
|
138
137
|
// 自动翻页
|
|
139
138
|
if (this.readMoreBtn) this.readMoreBtn.click()
|
|
@@ -144,18 +143,16 @@ export default class List extends ListLite {
|
|
|
144
143
|
// 已阅 API
|
|
145
144
|
const notifyKey = Utils.getQueryParam('atk_notify_key')
|
|
146
145
|
if (notifyKey) {
|
|
147
|
-
|
|
146
|
+
this.ctx.getApi().markRead(notifyKey)
|
|
148
147
|
.then(() => {
|
|
149
148
|
this.unread = this.unread.filter(o => o.comment_id !== commentId)
|
|
150
|
-
this.
|
|
151
|
-
notifies: this.unread
|
|
152
|
-
})
|
|
149
|
+
this.updateUnread(this.unread)
|
|
153
150
|
})
|
|
154
151
|
}
|
|
155
152
|
|
|
156
153
|
// 若父评论存在 “子评论部分” 限高,取消限高
|
|
157
154
|
comment.getParents().forEach((p) => {
|
|
158
|
-
|
|
155
|
+
p.getRender().heightLimitRemoveForChildren()
|
|
159
156
|
})
|
|
160
157
|
|
|
161
158
|
const goTo = () => {
|
|
@@ -177,18 +174,18 @@ export default class List extends ListLite {
|
|
|
177
174
|
public adminPageEditSave () {
|
|
178
175
|
if (!this.data || !this.data.page) return
|
|
179
176
|
|
|
180
|
-
this.ctx.
|
|
181
|
-
|
|
177
|
+
this.ctx.editorShowLoading()
|
|
178
|
+
this.ctx.getApi().pageEdit(this.data.page)
|
|
182
179
|
.then((page) => {
|
|
183
180
|
if (this.data)
|
|
184
181
|
this.data.page = { ...page }
|
|
185
182
|
this.refreshUI()
|
|
186
183
|
})
|
|
187
184
|
.catch(err => {
|
|
188
|
-
this.ctx.
|
|
185
|
+
this.ctx.editorShowNotify(`${this.$t('editFail')}: ${err.msg || String(err)}`, 'e')
|
|
189
186
|
})
|
|
190
187
|
.finally(() => {
|
|
191
|
-
this.ctx.
|
|
188
|
+
this.ctx.editorHideLoading()
|
|
192
189
|
})
|
|
193
190
|
}
|
|
194
191
|
|
|
@@ -216,10 +213,10 @@ export default class List extends ListLite {
|
|
|
216
213
|
|
|
217
214
|
// 下拉列表
|
|
218
215
|
const dropdownList = [
|
|
219
|
-
['
|
|
220
|
-
['
|
|
221
|
-
['
|
|
222
|
-
['
|
|
216
|
+
[this.$t('sortLatest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'date_desc' }) }],
|
|
217
|
+
[this.$t('sortBest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'vote' }) }],
|
|
218
|
+
[this.$t('sortOldest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'date_asc' }) }],
|
|
219
|
+
[this.$t('sortAuthor'), () => { reloadUseParamsEditor(p => { p.view_only_admin = true }) }],
|
|
223
220
|
]
|
|
224
221
|
|
|
225
222
|
// 列表项点击事件
|
|
@@ -254,4 +251,9 @@ export default class List extends ListLite {
|
|
|
254
251
|
|
|
255
252
|
this.$dropdownWrap.append($dropdown)
|
|
256
253
|
}
|
|
254
|
+
|
|
255
|
+
public updateUnread(notifies: NotifyData[]): void {
|
|
256
|
+
super.updateUnread(notifies)
|
|
257
|
+
this.showUnreadBadge(notifies?.length || 0)
|
|
258
|
+
}
|
|
257
259
|
}
|