artalk 2.2.12 → 2.3.2
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 +1535 -1175
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -0
- package/dist/ArtalkLite.es.js +5123 -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 +117 -121
- package/src/comment/actions.ts +86 -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 +204 -13
- package/src/defaults.ts +16 -5
- package/src/editor/editor.html +18 -0
- package/src/editor/editor.ts +419 -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 +2 -1
- package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.ts +65 -63
- package/src/editor/plugs/header-input-plug.ts +78 -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 +124 -0
- package/src/i18n/en.ts +78 -0
- package/src/i18n/index.ts +21 -0
- package/src/i18n/zh-CN.ts +82 -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 -47
- package/src/lib/checker/admin-checker.ts +7 -7
- package/src/lib/checker/captcha-checker.ts +5 -6
- package/src/lib/checker/index.ts +22 -17
- package/src/lib/component.ts +7 -2
- package/src/lib/stat.ts +63 -0
- package/src/lib/ui.ts +6 -12
- 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 -100
- package/src/{components → list}/list-nest.ts +0 -0
- package/src/{components/html → list}/list.html +3 -6
- package/src/{components → list}/list.ts +44 -42
- package/src/style/_variables.less +1 -2
- package/src/style/comment.less +26 -13
- package/src/style/editor.less +22 -14
- package/src/style/list.less +6 -9
- package/src/style/main.less +9 -8
- package/src/style/pagination.less +1 -1
- package/test/ArtalkCount.html +16 -0
- package/test/ArtalkI18n.html +15 -0
- 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/types/plug.d.ts +4 -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,21 @@
|
|
|
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
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import ReadMoreBtn from './read-more-btn'
|
|
6
|
+
import Comment from '../comment'
|
|
7
|
+
import Pagination from '../components/pagination'
|
|
8
|
+
import ReadMoreBtn from '../components/read-more-btn'
|
|
10
9
|
import * as ListNest from './list-nest'
|
|
11
10
|
import { backendMinVersion } from '../../package.json'
|
|
12
11
|
|
|
13
12
|
export default class ListLite extends Component {
|
|
14
13
|
protected $commentsWrap: HTMLElement
|
|
15
14
|
|
|
16
|
-
protected commentList: Comment[] = [] // Note: 无层级结构 + 无须排列
|
|
17
|
-
protected get commentDataList() { return this.commentList.map(c => c.data) }
|
|
18
|
-
|
|
19
15
|
protected data?: ListData
|
|
20
16
|
protected isLoading: boolean = false
|
|
21
17
|
|
|
22
|
-
public noCommentText
|
|
18
|
+
public noCommentText: string // 无评论时显示
|
|
23
19
|
|
|
24
20
|
/** 平铺模式 */
|
|
25
21
|
public flatMode = false
|
|
@@ -56,7 +52,7 @@ export default class ListLite extends Component {
|
|
|
56
52
|
this.$commentsWrap = this.$el.querySelector('.atk-list-comments-wrap')!
|
|
57
53
|
|
|
58
54
|
// 评论为空时显示字符
|
|
59
|
-
|
|
55
|
+
this.noCommentText = ctx.conf.noComment || ctx.$t('noComment')
|
|
60
56
|
|
|
61
57
|
// 嵌套排序方式
|
|
62
58
|
this.nestSortBy = this.ctx.conf.nestSort || 'DATE_ASC'
|
|
@@ -65,12 +61,21 @@ export default class ListLite extends Component {
|
|
|
65
61
|
window.setInterval(() => {
|
|
66
62
|
this.$el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
|
|
67
63
|
const date = el.getAttribute('data-atk-comment-date')
|
|
68
|
-
el.innerText = Utils.timeAgo(new Date(Number(date)))
|
|
64
|
+
el.innerText = Utils.timeAgo(new Date(Number(date)), this.ctx)
|
|
69
65
|
})
|
|
70
66
|
}, 30 * 1000) // 30s 更新一次
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public getData() {
|
|
70
|
+
return this.data
|
|
71
|
+
}
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
this.
|
|
73
|
+
public clearData() {
|
|
74
|
+
this.data = undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public getCommentsWrapEl() {
|
|
78
|
+
return this.$commentsWrap
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
/** 评论获取 */
|
|
@@ -93,15 +98,15 @@ export default class ListLite extends Component {
|
|
|
93
98
|
showLoading()
|
|
94
99
|
|
|
95
100
|
// 事件通知(开始加载评论)
|
|
96
|
-
this.ctx.trigger('
|
|
101
|
+
this.ctx.trigger('list-load')
|
|
97
102
|
|
|
98
103
|
// 清空评论(加载按钮)
|
|
99
|
-
if (this.pageMode === 'read-more' && offset === 0) { this.clearAllComments() }
|
|
104
|
+
if (this.pageMode === 'read-more' && offset === 0) { this.ctx.clearAllComments() }
|
|
100
105
|
|
|
101
106
|
// 请求评论数据
|
|
102
107
|
let listData: ListData
|
|
103
108
|
try {
|
|
104
|
-
listData = await
|
|
109
|
+
listData = await this.ctx.getApi().get(offset, this.pageSize, this.flatMode, this.paramsEditor)
|
|
105
110
|
} catch (e: any) {
|
|
106
111
|
this.onError(e.msg || String(e), offset, e.data)
|
|
107
112
|
throw e
|
|
@@ -125,14 +130,14 @@ export default class ListLite extends Component {
|
|
|
125
130
|
|
|
126
131
|
protected onLoad(data: ListData, offset: number) {
|
|
127
132
|
// 清空评论(分页条)
|
|
128
|
-
if (this.pageMode === 'pagination') { this.clearAllComments() }
|
|
133
|
+
if (this.pageMode === 'pagination') { this.ctx.clearAllComments() }
|
|
129
134
|
|
|
130
135
|
this.data = data
|
|
131
136
|
|
|
132
137
|
// 版本检测
|
|
133
138
|
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('
|
|
139
|
+
if (this.ctx.conf.versionCheck && this.versionCheck('frontend', feMinVersion, ARTALK_VERSION)) return
|
|
140
|
+
if (this.ctx.conf.versionCheck && this.versionCheck('backend', backendMinVersion, data.api_version?.version)) return
|
|
136
141
|
|
|
137
142
|
// 图片上传功能
|
|
138
143
|
if (data.conf && typeof data.conf.img_upload === "boolean") {
|
|
@@ -148,8 +153,8 @@ export default class ListLite extends Component {
|
|
|
148
153
|
// 加载后事件
|
|
149
154
|
this.refreshUI()
|
|
150
155
|
|
|
151
|
-
this.ctx.
|
|
152
|
-
this.ctx.trigger('
|
|
156
|
+
this.ctx.updateNotifies(data.unread || [])
|
|
157
|
+
this.ctx.trigger('list-loaded')
|
|
153
158
|
this.ctx.trigger('conf-updated')
|
|
154
159
|
|
|
155
160
|
if (this.onAfterLoad) this.onAfterLoad(data)
|
|
@@ -179,11 +184,12 @@ export default class ListLite extends Component {
|
|
|
179
184
|
onClick: async (o) => {
|
|
180
185
|
await this.fetchComments(o)
|
|
181
186
|
},
|
|
187
|
+
text: this.ctx.$t('loadMore'),
|
|
182
188
|
})
|
|
183
189
|
this.$el.append(this.readMoreBtn.$el)
|
|
184
190
|
|
|
185
191
|
// 滚动到底部自动加载
|
|
186
|
-
if (this.conf.pagination
|
|
192
|
+
if (this.conf.pagination.autoLoad) {
|
|
187
193
|
// 添加滚动事件监听
|
|
188
194
|
const at = this.scrollListenerAt || document
|
|
189
195
|
if (this.autoLoadScrollEvent) at.removeEventListener('scroll', this.autoLoadScrollEvent) // 解除原有
|
|
@@ -210,7 +216,7 @@ export default class ListLite extends Component {
|
|
|
210
216
|
pageSize: this.pageSize,
|
|
211
217
|
onChange: async (o) => {
|
|
212
218
|
if (this.ctx.conf.editorTravel === true) {
|
|
213
|
-
this.ctx.
|
|
219
|
+
this.ctx.editorTravelBack() // 防止评论框被吞
|
|
214
220
|
}
|
|
215
221
|
|
|
216
222
|
await this.fetchComments(o)
|
|
@@ -237,14 +243,14 @@ export default class ListLite extends Component {
|
|
|
237
243
|
|
|
238
244
|
// 加载更多按钮显示错误
|
|
239
245
|
if (offset !== 0 && this.pageMode === 'read-more') {
|
|
240
|
-
this.readMoreBtn?.showErr(
|
|
246
|
+
this.readMoreBtn?.showErr(this.$t('loadFail'))
|
|
241
247
|
return
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
// 显示错误对话框
|
|
245
|
-
const $err = Utils.createElement(`<span>${msg}
|
|
251
|
+
const $err = Utils.createElement(`<span>${msg},${this.$t('listLoadFailMsg')}<br/></span>`)
|
|
246
252
|
|
|
247
|
-
const $retryBtn = Utils.createElement(
|
|
253
|
+
const $retryBtn = Utils.createElement(`<span style="cursor:pointer;">${this.$t('listRetry')}</span>`)
|
|
248
254
|
$retryBtn.onclick = () => (this.fetchComments(0))
|
|
249
255
|
$err.appendChild($retryBtn)
|
|
250
256
|
|
|
@@ -264,9 +270,9 @@ export default class ListLite extends Component {
|
|
|
264
270
|
sidebarView = `sites|${JSON.stringify(viewLoadParam)}`
|
|
265
271
|
}
|
|
266
272
|
|
|
267
|
-
adminBtn.onclick = () =>
|
|
268
|
-
view: sidebarView
|
|
269
|
-
})
|
|
273
|
+
adminBtn.onclick = () => this.ctx.showSidebar({
|
|
274
|
+
view: sidebarView as any
|
|
275
|
+
})
|
|
270
276
|
|
|
271
277
|
Ui.setError(this.$el, $err)
|
|
272
278
|
}
|
|
@@ -274,7 +280,7 @@ export default class ListLite extends Component {
|
|
|
274
280
|
/** 刷新界面 */
|
|
275
281
|
public refreshUI() {
|
|
276
282
|
// 无评论
|
|
277
|
-
const isNoComment = this.
|
|
283
|
+
const isNoComment = this.ctx.getCommentList().length <= 0
|
|
278
284
|
let $noComment = this.$commentsWrap.querySelector<HTMLElement>('.atk-list-no-comment')
|
|
279
285
|
|
|
280
286
|
if (isNoComment) {
|
|
@@ -288,31 +294,35 @@ export default class ListLite extends Component {
|
|
|
288
294
|
}
|
|
289
295
|
|
|
290
296
|
// 仅管理员显示控制
|
|
291
|
-
this.ctx.
|
|
297
|
+
this.ctx.checkAdminShowEl()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** 重新加载列表 */
|
|
301
|
+
public reload() {
|
|
302
|
+
this.fetchComments(0)
|
|
292
303
|
}
|
|
293
304
|
|
|
294
305
|
/** 创建新评论 */
|
|
295
306
|
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)
|
|
307
|
+
if (!ctxData) ctxData = this.ctx.getCommentDataList()
|
|
308
|
+
|
|
309
|
+
const comment = new Comment(this.ctx, cData, {
|
|
310
|
+
isFlatMode: this.flatMode,
|
|
311
|
+
afterRender: () => {
|
|
312
|
+
if (this.renderComment) this.renderComment(comment)
|
|
313
|
+
},
|
|
314
|
+
onDelete: (c: Comment) => {
|
|
315
|
+
this.ctx.deleteComment(c)
|
|
316
|
+
this.refreshUI()
|
|
317
|
+
},
|
|
318
|
+
replyTo: (cData.rid ? ctxData.find(c => c.id === cData.rid) : undefined)
|
|
319
|
+
})
|
|
310
320
|
|
|
311
321
|
// 渲染元素
|
|
312
322
|
comment.render()
|
|
313
323
|
|
|
314
324
|
// 放入 comment 总表中
|
|
315
|
-
this.
|
|
325
|
+
this.ctx.getCommentList().push(comment)
|
|
316
326
|
|
|
317
327
|
return comment
|
|
318
328
|
}
|
|
@@ -337,7 +347,7 @@ export default class ListLite extends Component {
|
|
|
337
347
|
|
|
338
348
|
// 显示并播放渐入动画
|
|
339
349
|
this.$commentsWrap.appendChild(rootC.getEl())
|
|
340
|
-
rootC.
|
|
350
|
+
rootC.getRender().playFadeAnim()
|
|
341
351
|
|
|
342
352
|
// 加载子评论
|
|
343
353
|
const that = this
|
|
@@ -355,7 +365,7 @@ export default class ListLite extends Component {
|
|
|
355
365
|
})(rootC, rootNode)
|
|
356
366
|
|
|
357
367
|
// 限高检测
|
|
358
|
-
rootC.checkHeightLimit()
|
|
368
|
+
rootC.getRender().checkHeightLimit()
|
|
359
369
|
})
|
|
360
370
|
}
|
|
361
371
|
|
|
@@ -369,11 +379,11 @@ export default class ListLite extends Component {
|
|
|
369
379
|
if (cData.visible) {
|
|
370
380
|
if (insertMode === 'append') this.$commentsWrap.append(comment.getEl())
|
|
371
381
|
if (insertMode === 'prepend') this.$commentsWrap.prepend(comment.getEl())
|
|
372
|
-
comment.
|
|
382
|
+
comment.getRender().playFadeAnim()
|
|
373
383
|
}
|
|
374
384
|
|
|
375
385
|
// 平铺评论插入后 · 内容限高检测
|
|
376
|
-
comment.checkHeightLimit()
|
|
386
|
+
comment.getRender().checkHeightLimit()
|
|
377
387
|
|
|
378
388
|
return comment
|
|
379
389
|
}
|
|
@@ -389,24 +399,24 @@ export default class ListLite extends Component {
|
|
|
389
399
|
this.$commentsWrap.prepend(comment.getEl())
|
|
390
400
|
} else {
|
|
391
401
|
// 子评论 新增
|
|
392
|
-
const parent = this.findComment(commentData.rid)
|
|
402
|
+
const parent = this.ctx.findComment(commentData.rid)
|
|
393
403
|
if (parent) {
|
|
394
404
|
parent.putChild(comment, (this.nestSortBy === 'DATE_ASC' ? 'append' : 'prepend'))
|
|
395
405
|
|
|
396
406
|
// 若父评论存在 “子评论部分” 限高,取消限高
|
|
397
407
|
comment.getParents().forEach((p) => {
|
|
398
|
-
|
|
408
|
+
p.getRender().heightLimitRemoveForChildren()
|
|
399
409
|
})
|
|
400
410
|
}
|
|
401
411
|
}
|
|
402
412
|
|
|
403
|
-
comment.checkHeightLimit()
|
|
413
|
+
comment.getRender().checkHeightLimit()
|
|
404
414
|
|
|
405
415
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
|
|
406
|
-
comment.
|
|
416
|
+
comment.getRender().playFadeAnim() // 播放评论渐出动画
|
|
407
417
|
} else {
|
|
408
418
|
// 平铺模式
|
|
409
|
-
const comment = this.putCommentFlatMode(commentData, this.
|
|
419
|
+
const comment = this.putCommentFlatMode(commentData, this.ctx.getCommentDataList(), 'prepend')
|
|
410
420
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可见
|
|
411
421
|
}
|
|
412
422
|
|
|
@@ -415,36 +425,8 @@ export default class ListLite extends Component {
|
|
|
415
425
|
|
|
416
426
|
// 评论新增后
|
|
417
427
|
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 = []
|
|
428
|
+
this.ctx.trigger('list-loaded')
|
|
429
|
+
this.ctx.trigger('list-inserted', commentData)
|
|
448
430
|
}
|
|
449
431
|
|
|
450
432
|
/** 更新未读数据 */
|
|
@@ -453,33 +435,31 @@ export default class ListLite extends Component {
|
|
|
453
435
|
|
|
454
436
|
// 高亮评论
|
|
455
437
|
if (this.unreadHighlight === true) {
|
|
456
|
-
this.
|
|
457
|
-
const notify = this.unread.find(o => o.comment_id === comment.
|
|
438
|
+
this.ctx.getCommentList().forEach((comment) => {
|
|
439
|
+
const notify = this.unread.find(o => o.comment_id === comment.getID())
|
|
458
440
|
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
|
-
}
|
|
441
|
+
comment.getRender().setUnread(true)
|
|
442
|
+
comment.getRender().setOpenAction(() => {
|
|
443
|
+
window.open(notify.read_link)
|
|
444
|
+
this.unread = this.unread.filter(o => o.comment_id !== comment.getID()) // remove
|
|
445
|
+
this.ctx.updateNotifies(this.unread)
|
|
446
|
+
})
|
|
467
447
|
} else {
|
|
468
|
-
comment.setUnread(false)
|
|
448
|
+
comment.getRender().setUnread(false)
|
|
469
449
|
}
|
|
470
450
|
})
|
|
471
451
|
}
|
|
472
452
|
}
|
|
473
453
|
|
|
474
454
|
/** 版本检测 */
|
|
475
|
-
public versionCheck(name: '
|
|
455
|
+
public versionCheck(name: 'frontend'|'backend', needVersion: string, curtVersion: string): boolean {
|
|
476
456
|
const needUpdate = Utils.versionCompare(needVersion, curtVersion) === 1
|
|
477
457
|
if (needUpdate) {
|
|
478
458
|
// 需要更新
|
|
479
|
-
const errEl = Utils.createElement(`<div>Artalk ${name}版本已过时,请更新以获得完整体验<br/>`
|
|
459
|
+
const errEl = Utils.createElement(`<div>Artalk ${this.$t(name)}版本已过时,请更新以获得完整体验<br/>`
|
|
480
460
|
+ `如果你是管理员,请前往 “<a href="https://artalk.js.org/" target="_blank">官方文档</a>” 获得帮助`
|
|
481
461
|
+ `<br/><br/>`
|
|
482
|
-
+ `<span style="color: var(--at-color-meta);">当前${name}版本 ${curtVersion},需求版本 >= ${needVersion}</span><br/><br/>`
|
|
462
|
+
+ `<span style="color: var(--at-color-meta);">当前${this.$t(name)}版本 ${curtVersion},需求版本 >= ${needVersion}</span><br/><br/>`
|
|
483
463
|
+ `</div>`)
|
|
484
464
|
const ignoreBtn = Utils.createElement('<span style="cursor:pointer;">忽略</span>')
|
|
485
465
|
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,10 @@
|
|
|
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
|
-
import
|
|
8
|
-
import ListHTML from './html/list.html?raw'
|
|
7
|
+
import ListHTML from './list.html?raw'
|
|
9
8
|
import ListLite from './list-lite'
|
|
10
9
|
|
|
11
10
|
export default class List extends ListLite {
|
|
@@ -13,6 +12,7 @@ export default class List extends ListLite {
|
|
|
13
12
|
private $openSidebarBtn!: HTMLElement
|
|
14
13
|
private $unreadBadge!: HTMLElement
|
|
15
14
|
private $commentCount!: HTMLElement
|
|
15
|
+
private $commentCountNum!: HTMLElement
|
|
16
16
|
private $dropdownWrap?: HTMLElement
|
|
17
17
|
|
|
18
18
|
constructor (ctx: Context) {
|
|
@@ -25,24 +25,29 @@ export default class List extends ListLite {
|
|
|
25
25
|
this.$el = el
|
|
26
26
|
|
|
27
27
|
// 平铺模式
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
if (this.ctx.conf.flatMode === true) {
|
|
29
|
+
this.flatMode = true // 遵循配置总是开启平铺模式
|
|
30
|
+
} else if (this.conf.nestMax && this.conf.nestMax <= 1) {
|
|
31
|
+
this.flatMode = true // 嵌套层数值无效时,强制开启平铺模式
|
|
32
|
+
} else if (this.ctx.conf.flatMode === 'auto') {
|
|
33
|
+
// 自动判断启用平铺模式
|
|
30
34
|
if (window.matchMedia("(max-width: 768px)").matches)
|
|
31
|
-
flatMode = true
|
|
32
|
-
} else if (this.ctx.conf.flatMode === true) {
|
|
33
|
-
flatMode = true
|
|
35
|
+
this.flatMode = true
|
|
34
36
|
}
|
|
35
|
-
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
|
}
|