artalk 2.2.11 → 2.3.1
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 +1872 -1143
- 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 +5 -3
- package/package.json +7 -5
- package/src/api/index.ts +24 -4
- package/src/api/request.ts +50 -81
- package/src/artalk.ts +131 -127
- 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 +15 -4
- 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 +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 +83 -111
- 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 -18
- 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 -604
- 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,25 +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.
|
|
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
|
+
})
|
|
297
320
|
|
|
298
|
-
|
|
299
|
-
comment.
|
|
300
|
-
comment.afterRender = () => {
|
|
301
|
-
if (this.renderComment) this.renderComment(comment)
|
|
302
|
-
}
|
|
303
|
-
comment.onDelete = (c) => {
|
|
304
|
-
this.deleteComment(c)
|
|
305
|
-
this.refreshUI()
|
|
306
|
-
}
|
|
321
|
+
// 渲染元素
|
|
322
|
+
comment.render()
|
|
307
323
|
|
|
308
|
-
//
|
|
309
|
-
|
|
324
|
+
// 放入 comment 总表中
|
|
325
|
+
this.ctx.getCommentList().push(comment)
|
|
310
326
|
|
|
311
327
|
return comment
|
|
312
328
|
}
|
|
@@ -328,14 +344,10 @@ export default class ListLite extends Component {
|
|
|
328
344
|
const rootNodes = ListNest.makeNestCommentNodeList(srcData, this.nestSortBy, this.conf.nestMax)
|
|
329
345
|
rootNodes.forEach((rootNode: ListNest.CommentNode) => {
|
|
330
346
|
const rootC = this.createComment(rootNode.comment, srcData)
|
|
331
|
-
rootC.render()
|
|
332
347
|
|
|
333
348
|
// 显示并播放渐入动画
|
|
334
349
|
this.$commentsWrap.appendChild(rootC.getEl())
|
|
335
|
-
rootC.
|
|
336
|
-
|
|
337
|
-
// 评论放入 comments 总表中
|
|
338
|
-
this.commentList.push(rootC)
|
|
350
|
+
rootC.getRender().playFadeAnim()
|
|
339
351
|
|
|
340
352
|
// 加载子评论
|
|
341
353
|
const that = this
|
|
@@ -343,20 +355,17 @@ export default class ListLite extends Component {
|
|
|
343
355
|
parentNode.children.forEach((node: ListNest.CommentNode) => {
|
|
344
356
|
const childD = node.comment
|
|
345
357
|
const childC = that.createComment(childD, srcData)
|
|
346
|
-
childC.render()
|
|
347
358
|
|
|
348
359
|
// 插入到父评论中
|
|
349
360
|
parentC.putChild(childC)
|
|
350
361
|
|
|
351
|
-
that.commentList.push(childC)
|
|
352
|
-
|
|
353
362
|
// 递归加载子评论
|
|
354
363
|
loadChildren(childC, node)
|
|
355
364
|
})
|
|
356
365
|
})(rootC, rootNode)
|
|
357
366
|
|
|
358
367
|
// 限高检测
|
|
359
|
-
rootC.checkHeightLimit()
|
|
368
|
+
rootC.getRender().checkHeightLimit()
|
|
360
369
|
})
|
|
361
370
|
}
|
|
362
371
|
|
|
@@ -364,21 +373,17 @@ export default class ListLite extends Component {
|
|
|
364
373
|
private putCommentFlatMode(cData: CommentData, ctxData: CommentData[], insertMode: 'append'|'prepend') {
|
|
365
374
|
if (cData.is_collapsed) cData.is_allow_reply = false
|
|
366
375
|
const comment = this.createComment(cData, ctxData)
|
|
367
|
-
comment.render()
|
|
368
|
-
|
|
369
|
-
// 将评论导入 comments 总表中
|
|
370
|
-
this.commentList.push(comment)
|
|
371
376
|
|
|
372
377
|
// 可见评论添加到界面
|
|
373
378
|
// 注:不可见评论用于显示 “引用内容”
|
|
374
379
|
if (cData.visible) {
|
|
375
380
|
if (insertMode === 'append') this.$commentsWrap.append(comment.getEl())
|
|
376
381
|
if (insertMode === 'prepend') this.$commentsWrap.prepend(comment.getEl())
|
|
377
|
-
comment.
|
|
382
|
+
comment.getRender().playFadeAnim()
|
|
378
383
|
}
|
|
379
384
|
|
|
380
385
|
// 平铺评论插入后 · 内容限高检测
|
|
381
|
-
comment.checkHeightLimit()
|
|
386
|
+
comment.getRender().checkHeightLimit()
|
|
382
387
|
|
|
383
388
|
return comment
|
|
384
389
|
}
|
|
@@ -391,30 +396,27 @@ export default class ListLite extends Component {
|
|
|
391
396
|
|
|
392
397
|
if (commentData.rid === 0) {
|
|
393
398
|
// root评论 新增
|
|
394
|
-
comment.render()
|
|
395
399
|
this.$commentsWrap.prepend(comment.getEl())
|
|
396
|
-
this.commentList.push(comment)
|
|
397
400
|
} else {
|
|
398
401
|
// 子评论 新增
|
|
399
|
-
const parent = this.findComment(commentData.rid)
|
|
402
|
+
const parent = this.ctx.findComment(commentData.rid)
|
|
400
403
|
if (parent) {
|
|
401
|
-
comment.render()
|
|
402
404
|
parent.putChild(comment, (this.nestSortBy === 'DATE_ASC' ? 'append' : 'prepend'))
|
|
403
405
|
|
|
404
406
|
// 若父评论存在 “子评论部分” 限高,取消限高
|
|
405
407
|
comment.getParents().forEach((p) => {
|
|
406
|
-
|
|
408
|
+
p.getRender().heightLimitRemoveForChildren()
|
|
407
409
|
})
|
|
408
410
|
}
|
|
409
411
|
}
|
|
410
412
|
|
|
411
|
-
comment.checkHeightLimit()
|
|
413
|
+
comment.getRender().checkHeightLimit()
|
|
412
414
|
|
|
413
415
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
|
|
414
|
-
comment.
|
|
416
|
+
comment.getRender().playFadeAnim() // 播放评论渐出动画
|
|
415
417
|
} else {
|
|
416
418
|
// 平铺模式
|
|
417
|
-
const comment = this.putCommentFlatMode(commentData, this.
|
|
419
|
+
const comment = this.putCommentFlatMode(commentData, this.ctx.getCommentDataList(), 'prepend')
|
|
418
420
|
Ui.scrollIntoView(comment.getEl()) // 滚动到可见
|
|
419
421
|
}
|
|
420
422
|
|
|
@@ -423,36 +425,8 @@ export default class ListLite extends Component {
|
|
|
423
425
|
|
|
424
426
|
// 评论新增后
|
|
425
427
|
this.refreshUI()
|
|
426
|
-
this.ctx.trigger('
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
/** 查找评论项 */
|
|
430
|
-
protected findComment(id: number): Comment|undefined {
|
|
431
|
-
return this.commentList.find(c => c.data.id === id)
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/** 删除评论 */
|
|
435
|
-
public deleteComment(_comment: number|Comment) {
|
|
436
|
-
let comment: Comment
|
|
437
|
-
if (typeof _comment === 'number') {
|
|
438
|
-
const findComment = this.findComment(_comment)
|
|
439
|
-
if (!findComment) throw Error(`未找到评论 ${_comment}`)
|
|
440
|
-
comment = findComment
|
|
441
|
-
} else comment = _comment
|
|
442
|
-
|
|
443
|
-
comment.getEl().remove()
|
|
444
|
-
this.commentList.splice(this.commentList.indexOf(comment), 1)
|
|
445
|
-
|
|
446
|
-
if (this.data) this.data.total -= 1 // 评论数减 1
|
|
447
|
-
|
|
448
|
-
this.refreshUI()
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/** 清空所有评论 */
|
|
452
|
-
public clearAllComments() {
|
|
453
|
-
this.$commentsWrap.innerHTML = ''
|
|
454
|
-
this.data = undefined
|
|
455
|
-
this.commentList = []
|
|
428
|
+
this.ctx.trigger('list-loaded')
|
|
429
|
+
this.ctx.trigger('list-inserted', commentData)
|
|
456
430
|
}
|
|
457
431
|
|
|
458
432
|
/** 更新未读数据 */
|
|
@@ -461,33 +435,31 @@ export default class ListLite extends Component {
|
|
|
461
435
|
|
|
462
436
|
// 高亮评论
|
|
463
437
|
if (this.unreadHighlight === true) {
|
|
464
|
-
this.
|
|
465
|
-
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())
|
|
466
440
|
if (notify) {
|
|
467
|
-
comment.setUnread(true)
|
|
468
|
-
comment.
|
|
469
|
-
|
|
470
|
-
this.unread = this.unread.filter(o => o.comment_id !== comment.
|
|
471
|
-
this.ctx.
|
|
472
|
-
|
|
473
|
-
})
|
|
474
|
-
}
|
|
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
|
+
})
|
|
475
447
|
} else {
|
|
476
|
-
comment.setUnread(false)
|
|
448
|
+
comment.getRender().setUnread(false)
|
|
477
449
|
}
|
|
478
450
|
})
|
|
479
451
|
}
|
|
480
452
|
}
|
|
481
453
|
|
|
482
454
|
/** 版本检测 */
|
|
483
|
-
public versionCheck(name: '
|
|
455
|
+
public versionCheck(name: 'frontend'|'backend', needVersion: string, curtVersion: string): boolean {
|
|
484
456
|
const needUpdate = Utils.versionCompare(needVersion, curtVersion) === 1
|
|
485
457
|
if (needUpdate) {
|
|
486
458
|
// 需要更新
|
|
487
|
-
const errEl = Utils.createElement(`<div>Artalk ${name}版本已过时,请更新以获得完整体验<br/>`
|
|
459
|
+
const errEl = Utils.createElement(`<div>Artalk ${this.$t(name)}版本已过时,请更新以获得完整体验<br/>`
|
|
488
460
|
+ `如果你是管理员,请前往 “<a href="https://artalk.js.org/" target="_blank">官方文档</a>” 获得帮助`
|
|
489
461
|
+ `<br/><br/>`
|
|
490
|
-
+ `<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/>`
|
|
491
463
|
+ `</div>`)
|
|
492
464
|
const ignoreBtn = Utils.createElement('<span style="cursor:pointer;">忽略</span>')
|
|
493
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
|
}
|