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.
Files changed (73) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +3216 -2883
  3. package/dist/Artalk.iife.js +1 -1
  4. package/dist/Artalk.js +1 -1
  5. package/dist/ArtalkLite.css +1 -0
  6. package/dist/ArtalkLite.es.js +5096 -0
  7. package/dist/ArtalkLite.iife.js +1 -0
  8. package/dist/ArtalkLite.js +1 -0
  9. package/index.html +2 -2
  10. package/package.json +6 -5
  11. package/src/api/index.ts +20 -1
  12. package/src/api/request.ts +7 -7
  13. package/src/artalk.ts +68 -50
  14. package/src/comment/actions.ts +87 -0
  15. package/src/{components/html → comment}/comment.html +1 -1
  16. package/src/comment/comment.ts +191 -0
  17. package/src/comment/index.ts +3 -0
  18. package/src/comment/render.ts +425 -0
  19. package/src/components/action-btn.ts +6 -3
  20. package/src/components/dialog.ts +7 -3
  21. package/src/components/read-more-btn.ts +6 -2
  22. package/src/context.ts +200 -13
  23. package/src/defaults.ts +16 -5
  24. package/src/editor/editor.html +18 -0
  25. package/src/editor/editor.ts +420 -0
  26. package/src/editor/index.ts +3 -0
  27. package/src/editor/plugs/editor-plug.ts +51 -0
  28. package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.less +1 -0
  29. package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.ts +65 -63
  30. package/src/editor/plugs/header-input-plug.ts +79 -0
  31. package/src/{components/editor-plugs → editor/plugs}/preview-plug.less +0 -0
  32. package/src/editor/plugs/preview-plug.ts +40 -0
  33. package/src/editor/plugs/upload-plug.ts +125 -0
  34. package/src/i18n/en.ts +77 -0
  35. package/src/i18n/index.ts +21 -0
  36. package/src/i18n/zh-CN.ts +81 -0
  37. package/src/layer/index.ts +4 -0
  38. package/src/{components → layer}/layer.ts +9 -9
  39. package/src/{components/html → layer}/sidebar-layer.html +0 -0
  40. package/src/{components → layer}/sidebar-layer.ts +17 -46
  41. package/src/lib/checker/admin-checker.ts +7 -6
  42. package/src/lib/checker/captcha-checker.ts +5 -5
  43. package/src/lib/checker/index.ts +22 -17
  44. package/src/lib/component.ts +7 -2
  45. package/src/lib/ui.ts +3 -10
  46. package/src/lib/user.ts +20 -3
  47. package/src/lib/utils.ts +23 -9
  48. package/src/list/index.ts +3 -0
  49. package/src/{components → list}/list-lite.ts +80 -99
  50. package/src/{components → list}/list-nest.ts +0 -0
  51. package/src/{components/html → list}/list.html +3 -6
  52. package/src/{components → list}/list.ts +37 -35
  53. package/src/style/comment.less +23 -10
  54. package/src/style/editor.less +16 -10
  55. package/src/style/list.less +4 -7
  56. package/src/style/main.less +3 -1
  57. package/src/style/pagination.less +1 -1
  58. package/test/ArtalkLite.html +15 -0
  59. package/types/artalk-config.d.ts +50 -32
  60. package/types/context.d.ts +128 -0
  61. package/types/event.d.ts +6 -66
  62. package/types/global.d.ts +1 -0
  63. package/{vite-common.config.ts → vite-base.config.ts} +6 -4
  64. package/vite-demo.config.ts +2 -4
  65. package/vite-lite.config.ts +22 -0
  66. package/vite.config.ts +9 -12
  67. package/src/components/_component.ts.txt +0 -10
  68. package/src/components/comment.ts +0 -605
  69. package/src/components/editor-plugs/_example-plug.ts.txt +0 -29
  70. package/src/components/editor-plugs/editor-plug.ts +0 -20
  71. package/src/components/editor-plugs/preview-plug.ts +0 -48
  72. package/src/components/editor.ts +0 -607
  73. package/src/components/html/editor.html +0 -18
@@ -1,25 +1,22 @@
1
- import { ListData, CommentData, NotifyData, ApiVersionData } from '~/types/artalk-data'
2
- import Context from '../context'
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 './comment'
8
- import Pagination from './pagination'
9
- import ReadMoreBtn from './read-more-btn'
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
- if (ctx.conf.noComment) this.noCommentText = ctx.conf.noComment
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.ctx.on('unread-update', (data) => (this.updateUnread(data.notifies)))
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('comments-load')
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 new Api(this.ctx).get(offset, this.pageSize, this.flatMode, this.paramsEditor)
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('前端', feMinVersion, ARTALK_VERSION)) return
135
- if (this.ctx.conf.versionCheck && this.versionCheck('后端', backendMinVersion, data.api_version?.version)) return
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.trigger('unread-update', { notifies: data.unread || [] })
152
- this.ctx.trigger('comments-loaded')
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?.autoLoad) {
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.trigger('editor-travel-back') // 防止评论框被吞
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},无法获取评论列表数据<br/></span>`)
252
+ const $err = Utils.createElement(`<span>${msg},${this.$t('listLoadFailMsg')}<br/></span>`)
246
253
 
247
- const $retryBtn = Utils.createElement('<span style="cursor:pointer;">点击重新获取</span>')
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 = () => (this.ctx.trigger('sidebar-show', {
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.commentList.length <= 0
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.trigger('check-admin-show-el')
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.commentDataList
297
-
298
- const comment = new Comment(this.ctx, cData)
299
- comment.flatMode = this.flatMode
300
- comment.afterRender = () => {
301
- if (this.renderComment) this.renderComment(comment)
302
- }
303
- comment.onDelete = (c) => {
304
- this.deleteComment(c)
305
- this.refreshUI()
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.commentList.push(comment)
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.playFadeInAnim()
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.playFadeInAnim()
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
- if (p.$children) p.heightLimitRemove(p.$children)
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.playFadeInAnim() // 播放评论渐出动画
417
+ comment.getRender().playFadeAnim() // 播放评论渐出动画
407
418
  } else {
408
419
  // 平铺模式
409
- const comment = this.putCommentFlatMode(commentData, this.commentDataList, 'prepend')
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('comments-loaded')
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.commentList.forEach((comment) => {
457
- const notify = this.unread.find(o => o.comment_id === comment.data.id)
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.setOpenURL(notify.read_link)
461
- comment.openEvt = () => {
462
- this.unread = this.unread.filter(o => o.comment_id !== comment.data.id) // remove
463
- this.ctx.trigger('unread-update', {
464
- notifies: this.unread
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: '前端'|'后端', needVersion: string, curtVersion: string): boolean {
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>关闭评论</span>
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">通知中心</div>
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 '../context'
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 './html/list.html?raw'
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?.readMore ? 'read-more' : 'pagination'
39
- this.pageSize = this.conf.pagination?.pageSize || 20
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.trigger('sidebar-show')
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.$el.querySelector<HTMLElement>('.atk-comment-count-num')!.innerText = String(Number(this.data?.total) || 0)
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.trigger('check-admin-show-el')
99
- this.$openSidebarBtn.querySelector<HTMLElement>('.atk-text')!.innerText = (!this.ctx.user.data.isAdmin) ? '通知中心' : '控制中心'
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.trigger('editor-close')
104
- this.$closeCommentBtn.innerHTML = '打开评论'
102
+ this.ctx.editorClose()
103
+ this.$closeCommentBtn.innerHTML = this.$t('openComment')
105
104
  } else {
106
- this.ctx.trigger('editor-open')
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.trigger('editor-travel-back')
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
- new Api(this.ctx).markRead(notifyKey)
146
+ this.ctx.getApi().markRead(notifyKey)
148
147
  .then(() => {
149
148
  this.unread = this.unread.filter(o => o.comment_id !== commentId)
150
- this.ctx.trigger('unread-update', {
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
- if (p.$children) p.heightLimitRemove(p.$children)
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.trigger('editor-show-loading')
181
- new Api(this.ctx).pageEdit(this.data.page)
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.trigger('editor-notify', { msg: `修改页面数据失败:${err.msg || String(err)}`, type: 'e'})
185
+ this.ctx.editorShowNotify(`${this.$t('editFail')}: ${err.msg || String(err)}`, 'e')
189
186
  })
190
187
  .finally(() => {
191
- this.ctx.trigger('editor-hide-loading')
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
- ['最新', () => { reloadUseParamsEditor(p => { p.sort_by = 'date_desc' }) }],
220
- ['最热', () => { reloadUseParamsEditor(p => { p.sort_by = 'vote' }) }],
221
- ['最早', () => { reloadUseParamsEditor(p => { p.sort_by = 'date_asc' }) }],
222
- ['作者', () => { reloadUseParamsEditor(p => { p.view_only_admin = true }) }],
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
  }