artalk 2.1.0 → 2.1.4

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 (45) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +3895 -3106
  3. package/dist/Artalk.iife.js +1 -266
  4. package/dist/Artalk.js +1 -266
  5. package/package.json +19 -21
  6. package/src/api/index.ts +6 -7
  7. package/src/artalk.ts +11 -4
  8. package/src/components/action-btn.ts +1 -1
  9. package/src/components/comment.ts +102 -27
  10. package/src/components/editor-plugs/_example-plug.ts.txt +2 -7
  11. package/src/components/editor-plugs/editor-plug.ts +3 -3
  12. package/src/components/editor-plugs/emoticons-plug.less +21 -11
  13. package/src/components/editor-plugs/emoticons-plug.ts +199 -79
  14. package/src/components/editor-plugs/preview-plug.less +1 -1
  15. package/src/components/editor-plugs/preview-plug.ts +2 -7
  16. package/src/components/editor.ts +75 -34
  17. package/src/components/html/comment.html +6 -13
  18. package/src/components/html/editor.html +9 -10
  19. package/src/components/html/list.html +1 -1
  20. package/src/components/layer.ts +33 -14
  21. package/src/components/list-lite.ts +218 -235
  22. package/src/components/list.ts +11 -9
  23. package/src/components/pagination.ts +2 -2
  24. package/src/components/read-more-btn.ts +27 -10
  25. package/src/components/sidebar-views/comments-view.ts +12 -5
  26. package/src/components/sidebar-views/sites-view.ts +0 -6
  27. package/src/components/sidebar.ts +7 -2
  28. package/src/{default-conf.ts → defaults.ts} +7 -7
  29. package/src/lib/utils.ts +41 -12
  30. package/src/style/_color.less +19 -23
  31. package/src/style/_extend.less +3 -3
  32. package/src/style/_variables.less +0 -24
  33. package/src/style/comment.less +191 -197
  34. package/src/style/editor.less +78 -103
  35. package/src/style/item-text-editor.less +2 -2
  36. package/src/style/list.less +14 -13
  37. package/src/style/main.less +35 -31
  38. package/src/style/page-list.less +4 -4
  39. package/src/style/pagination.less +6 -6
  40. package/src/style/sidebar.less +35 -35
  41. package/src/style/site-list.less +13 -13
  42. package/types/artalk-config.d.ts +13 -10
  43. package/types/artalk-data.d.ts +10 -5
  44. package/types/event.d.ts +10 -1
  45. package/src/assets/emoticons.json +0 -100
@@ -9,50 +9,45 @@ import Pagination from './pagination'
9
9
  import ReadMoreBtn from './read-more-btn'
10
10
 
11
11
  export default class ListLite extends Component {
12
- private $parent: HTMLElement
12
+ protected $commentsWrap: HTMLElement
13
+ protected comments: Comment[] = []
13
14
 
14
- private $commentsWrap: HTMLElement
15
- public comments: Comment[] = []
15
+ protected data?: ListData
16
+ protected isLoading: boolean = false
16
17
 
17
- public data?: ListData
18
- private pageSize: number = 15 // 每次请求获取量
19
- private offset: number = 0
20
- public type?: 'all'|'mentions'|'mine'|'pending'
18
+ public noCommentText = '无内容' // 无评论时显示
21
19
 
22
- public noCommentText: string
23
- public renderComment?: (comment: Comment) => void
24
- public paramsEditor?: (params: any) => void
25
- public onAfterLoad?: (data: ListData) => void
20
+ /** 平铺模式 */
21
+ public flatMode = false
26
22
 
27
- private isLoading: boolean = false
28
- public isFirstLoad = true
23
+ /** 分页 */
24
+ public pageMode: 'pagination'|'read-more' = 'pagination'
25
+ public pageSize: number = 20 // 每次请求获取量
26
+ public scrollListenerAt?: HTMLElement // 监听指定元素上的滚动
27
+ public repositionAt?: HTMLElement // 翻页归位到指定元素
29
28
 
30
- public flatMode?: boolean
29
+ protected pagination?: Pagination // 分页条
30
+ protected readMoreBtn?: ReadMoreBtn // 阅读更多
31
+ protected autoLoadScrollEvent?: any // 自动加载滚动事件
31
32
 
32
- public pageMode: 'pagination'|'read-more' = 'pagination'
33
- public pagination?: Pagination
34
- public readMoreBtn?: ReadMoreBtn
35
- public autoLoadScrollEvent?: any
36
- public autoLoadListenerAt?: HTMLElement
33
+ public renderComment?: (comment: Comment) => void
34
+ public paramsEditor?: (params: any) => void
35
+ public onAfterLoad?: (data: ListData) => void
37
36
 
38
- public unread: NotifyData[] = []
39
- public unreadHighlight = false
37
+ // 未读标记
38
+ protected unread: NotifyData[] = []
39
+ public unreadHighlight?: boolean // 高亮未读
40
40
 
41
- constructor (ctx: Context, $parent: HTMLElement) {
41
+ constructor (ctx: Context) {
42
42
  super(ctx)
43
43
 
44
- this.$parent = $parent
44
+ // 初始化元素
45
45
  this.$el = Utils.createElement(
46
46
  `<div class="atk-list-lite">
47
47
  <div class="atk-list-comments-wrap"></div>
48
48
  </div>`)
49
49
  this.$commentsWrap = this.$el.querySelector('.atk-list-comments-wrap')!
50
50
 
51
- // 查看更多
52
- this.pageSize = this.conf.pagination ? (this.conf.pagination.pageSize || this.pageSize) : this.pageSize
53
-
54
- this.noCommentText = this.conf.noComment || '无评论'
55
-
56
51
  // 评论时间自动更新
57
52
  window.setInterval(() => {
58
53
  this.$el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
@@ -61,13 +56,15 @@ export default class ListLite extends Component {
61
56
  })
62
57
  }, 30 * 1000) // 30s 更新一次
63
58
 
59
+ // 事件监听
64
60
  this.ctx.on('unread-update', (data) => (this.updateUnread(data.notifies)))
65
61
  }
66
62
 
67
- public async reqComments(offset: number = 0) {
68
- if (offset === 0 && this.pageMode !== 'pagination') { this.clearAllComments() }
63
+ /** 评论获取 */
64
+ public async fetchComments(offset: number) {
65
+ if (this.isLoading) return
69
66
 
70
- // set loading
67
+ // 加载动画
71
68
  const showLoading = () => {
72
69
  this.isLoading = true
73
70
  if (offset === 0) Ui.showLoading(this.$el)
@@ -80,182 +77,186 @@ export default class ListLite extends Component {
80
77
  else if (this.pageMode === 'read-more') this.readMoreBtn!.setLoading(false)
81
78
  else if (this.pageMode === 'pagination') this.pagination!.setLoading(false)
82
79
  }
83
-
84
80
  showLoading()
81
+
82
+ // 事件通知(开始加载评论)
85
83
  this.ctx.trigger('comments-load')
86
84
 
85
+ // 清空评论(加载按钮)
86
+ if (this.pageMode === 'read-more' && offset === 0) { this.clearAllComments() }
87
+
88
+ // 请求评论数据
87
89
  let listData: ListData
88
90
  try {
89
- listData = await new Api(this.ctx).get(offset, this.type, this.flatMode, this.paramsEditor)
91
+ listData = await new Api(this.ctx).get(offset, this.pageSize, this.flatMode, this.paramsEditor)
90
92
  } catch (e: any) {
91
- this.onError(e.msg || String(e))
93
+ this.onError(e.msg || String(e), offset)
92
94
  throw e
93
95
  } finally {
94
96
  hideLoading()
95
97
  }
96
98
 
97
- // version check
98
- if (this.ctx.conf.versionCheck) {
99
- const needUpdate = this.apiVersionCheck(listData.api_version || {})
100
- if (needUpdate) return
101
- }
102
-
103
- // load data
104
- this.offset = offset
99
+ // 清除原有错误
100
+ Ui.setError(this.$el, null)
105
101
 
102
+ // 装载数据
106
103
  try {
107
104
  this.onLoad(listData, offset)
108
-
109
- if (this.onAfterLoad) {
110
- this.onAfterLoad(listData)
111
- }
112
105
  } catch (e: any) {
113
- this.onError(String(e))
106
+ this.onError(String(e), offset)
114
107
  throw e
115
108
  } finally {
116
109
  hideLoading()
117
110
  }
118
111
  }
119
112
 
120
- public onLoad(data: ListData, offset: number) {
121
- Ui.setError(this.$el, null)
122
-
123
- if (this.pageMode === 'pagination') {
124
- this.clearAllComments()
125
- }
113
+ protected onLoad(data: ListData, offset: number) {
114
+ // 清空评论(分页条)
115
+ if (this.pageMode === 'pagination') { this.clearAllComments() }
126
116
 
127
117
  this.data = data
118
+
119
+ // 版本检测
120
+ if (this.ctx.conf.versionCheck && this.versionCheck(data.api_version)) return
121
+
122
+ // 导入数据
128
123
  this.importComments(data.comments)
129
124
 
130
- // onLoad 时初始化
131
- if (this.isFirstLoad) {
132
- this.onLoadInit()
133
- }
125
+ // 分页方式
126
+ this.refreshPagination(offset, (this.flatMode ? data.total : data.total_roots)) // 初始化
134
127
 
135
- if (this.pageMode === 'pagination') {
136
- this.pagination!.update(offset, this.data?.total_parents || 0)
137
- }
138
- if (this.pageMode === 'read-more') {
139
- if (this.hasMoreComments) this.readMoreBtn!.show()
140
- else this.readMoreBtn!.hide()
141
- }
128
+ // 加载后事件
129
+ this.refreshUI()
142
130
 
143
131
  this.ctx.trigger('unread-update', { notifies: data.unread || [] })
132
+ this.ctx.trigger('comments-loaded')
144
133
 
145
- this.isFirstLoad = false
134
+ if (this.onAfterLoad) this.onAfterLoad(data)
146
135
  }
147
136
 
148
- /** 初始化加载更多 */
149
- onLoadInit() {
150
- if (this.autoLoadScrollEvent) {
151
- const at = this.autoLoadListenerAt || document
152
- at.removeEventListener('scroll', this.autoLoadScrollEvent)
137
+ /** 分页模式 */
138
+ private refreshPagination(offset: number, total: number) {
139
+ const modePagination = (this.pageMode === 'pagination')
140
+ const modeReadMoreBtn = (this.pageMode === 'read-more')
141
+ const initialized = (modePagination) ? !!this.pagination : !!this.readMoreBtn
142
+
143
+ // 初始化
144
+ if (!initialized) {
145
+ this.initPagination()
153
146
  }
154
147
 
148
+ // 更新
149
+ if (modePagination) this.pagination!.update(offset, total)
150
+ if (modeReadMoreBtn) this.readMoreBtn!.update(offset, total)
151
+ }
152
+
153
+ private initPagination() {
154
+ // 加载更多按钮
155
155
  if (this.pageMode === 'read-more') {
156
- // 阅读更多按钮
157
- const readMoreBtn = new ReadMoreBtn({
156
+ this.readMoreBtn = new ReadMoreBtn({
158
157
  pageSize: this.pageSize,
159
- total: 0,
160
- onClick: async () => {
161
- const offset = this.offset + this.pageSize
162
- await this.reqComments(offset)
158
+ onClick: async (o) => {
159
+ await this.fetchComments(o)
163
160
  },
164
161
  })
165
- if (this.readMoreBtn) this.readMoreBtn.$el.replaceWith(readMoreBtn.$el)
166
- else this.$el.append(readMoreBtn.$el)
167
- this.readMoreBtn = readMoreBtn
162
+ this.$el.append(this.readMoreBtn.$el)
168
163
 
169
164
  // 滚动到底部自动加载
170
165
  if (this.conf.pagination?.autoLoad) {
166
+ // 添加滚动事件监听
167
+ const at = this.scrollListenerAt || document
168
+ if (this.autoLoadScrollEvent) at.removeEventListener('scroll', this.autoLoadScrollEvent) // 解除原有
171
169
  this.autoLoadScrollEvent = () => {
172
170
  if (this.pageMode !== 'read-more') return
173
- if (!this.hasMoreComments) return
171
+ if (!this.readMoreBtn) return
172
+
173
+ if (!this.readMoreBtn.hasMore) return
174
174
  if (this.isLoading) return
175
175
 
176
176
  const $target = this.$el.querySelector<HTMLElement>('.atk-list-comments-wrap > .atk-comment-wrap:nth-last-child(3)') // 获取倒数第3个评论元素
177
177
  if (!$target) return
178
- if (Ui.isVisible($target, this.autoLoadListenerAt)) {
179
- // 加载更多
180
- this.readMoreBtn!.click()
178
+ if (Ui.isVisible($target, this.scrollListenerAt)) {
179
+ this.readMoreBtn.click() // 自动点击加载更多按钮
181
180
  }
182
181
  }
183
- const at = this.autoLoadListenerAt || document
184
182
  at.addEventListener('scroll', this.autoLoadScrollEvent)
185
183
  }
186
- } else if (this.pageMode === 'pagination') {
187
- // 分页条
188
- const pagination = new Pagination(this.parentCommentsCount, {
184
+ }
185
+
186
+ // 分页条
187
+ if (this.pageMode === 'pagination') {
188
+ this.pagination = new Pagination((!this.flatMode ? this.data!.total_roots : this.data!.total), {
189
189
  pageSize: this.pageSize,
190
- onChange: async (offset) => {
191
- await this.reqComments(offset)
190
+ onChange: async (o) => {
191
+ if (this.ctx.conf.editorTravel === true) {
192
+ this.ctx.trigger('editor-travel-back') // 防止评论框被吞
193
+ }
194
+
195
+ await this.fetchComments(o)
196
+
192
197
  // 滚动到第一个评论的位置
193
- if (this.$parent) {
194
- let topPos = 0
195
- if (!this.autoLoadListenerAt && this.$parent) {
196
- topPos = Utils.getOffset(this.$parent).top
197
- }
198
- const at = this.autoLoadListenerAt || window
198
+ if (this.repositionAt) {
199
+ const at = this.scrollListenerAt || window
199
200
  at.scroll({
200
- top: topPos,
201
+ top: this.repositionAt ? Utils.getOffset(this.repositionAt).top : 0,
201
202
  left: 0,
202
203
  })
203
204
  }
204
205
  }
205
206
  })
206
- if (this.pagination) this.pagination.$el.replaceWith(pagination.$el)
207
- else this.$el.append(pagination.$el)
208
- this.pagination = pagination
207
+
208
+ this.$el.append(this.pagination.$el)
209
209
  }
210
210
  }
211
211
 
212
- public onError(msg: any) {
212
+ /** 错误处理 */
213
+ protected onError(msg: any, offset: number) {
213
214
  msg = String(msg)
214
215
  console.error(msg)
215
- if (this.isFirstLoad || this.pageMode === 'pagination') {
216
- const errEl = Utils.createElement(`<span>${msg},无法获取评论列表数据<br/></span>`)
217
- const retryBtn = Utils.createElement('<span style="cursor:pointer;">点击重新获取</span>')
218
- retryBtn.onclick = () => {
219
- this.reqComments(this.offset)
220
- }
221
- errEl.appendChild(retryBtn)
222
- const adminBtn = Utils.createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>')
223
- adminBtn.onclick = () => {
224
- this.ctx.trigger('sidebar-show')
225
- }
226
- if (!this.ctx.user.data.isAdmin) {
227
- adminBtn.classList.add('atk-hide')
228
- }
229
- errEl.appendChild(adminBtn)
230
- Ui.setError(this.$el, errEl)
231
- } else {
216
+
217
+ // 加载更多按钮显示错误
218
+ if (offset !== 0 && this.pageMode === 'read-more') {
232
219
  this.readMoreBtn?.showErr(`获取失败`)
220
+ return
233
221
  }
222
+
223
+ // 显示错误对话框
224
+ const $err = Utils.createElement(`<span>${msg},无法获取评论列表数据<br/></span>`)
225
+
226
+ const $retryBtn = Utils.createElement('<span style="cursor:pointer;">点击重新获取</span>')
227
+ $retryBtn.onclick = () => (this.fetchComments(0))
228
+ $err.appendChild($retryBtn)
229
+
230
+ const adminBtn = Utils.createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>')
231
+ adminBtn.onclick = () => (this.ctx.trigger('sidebar-show'))
232
+ if (!this.ctx.user.data.isAdmin) adminBtn.classList.add('atk-hide')
233
+ $err.appendChild(adminBtn)
234
+
235
+ Ui.setError(this.$el, $err)
234
236
  }
235
237
 
236
238
  /** 刷新界面 */
237
239
  public refreshUI() {
238
- // 评论为空界面
239
- const noComment = this.comments.length <= 0
240
- let noCommentEl = this.$commentsWrap.querySelector<HTMLElement>('.atk-list-no-comment')
241
-
242
- if (noComment) {
243
- if (!noCommentEl) {
244
- noCommentEl = Utils.createElement('<div class="atk-list-no-comment"></div>')
245
- this.$commentsWrap.appendChild(noCommentEl)
246
- noCommentEl.innerHTML = this.noCommentText
240
+ // 无评论
241
+ const isNoComment = this.comments.length <= 0
242
+ let $noComment = this.$commentsWrap.querySelector<HTMLElement>('.atk-list-no-comment')
243
+
244
+ if (isNoComment) {
245
+ if (!$noComment) {
246
+ $noComment = Utils.createElement('<div class="atk-list-no-comment"></div>')
247
+ $noComment.innerHTML = this.noCommentText
248
+ this.$commentsWrap.appendChild($noComment)
247
249
  }
250
+ } else {
251
+ $noComment?.remove()
248
252
  }
249
253
 
250
- if (!noComment && noCommentEl)
251
- noCommentEl.remove()
252
-
253
254
  // 仅管理员显示控制
254
255
  this.ctx.trigger('check-admin-show-el')
255
256
  }
256
257
 
257
258
  /** 创建新评论 */
258
- public createComment(data: CommentData) {
259
+ protected createComment(data: CommentData) {
259
260
  const comment = new Comment(this.ctx, data)
260
261
  comment.afterRender = () => {
261
262
  if (this.renderComment) this.renderComment(comment)
@@ -269,141 +270,126 @@ export default class ListLite extends Component {
269
270
  }
270
271
 
271
272
  /** 导入评论 · 通过请求数据 */
272
- public importComments(rawData: CommentData[]) {
273
- // 查找并导入所有子评论
274
- const queryImportChildren = (parentC: Comment) => {
275
- const children = rawData.filter(o => o.rid === parentC.data.id)
276
- if (children.length === 0) return
273
+ public importComments(srcData: CommentData[]) {
274
+ if (this.flatMode) {
275
+ srcData.forEach((commentData: CommentData) => {
276
+ this.putCommentFlatMode(commentData, srcData, 'append')
277
+ })
278
+ } else {
279
+ this.importCommentsNesting(srcData)
280
+ }
281
+ }
277
282
 
278
- children.forEach((itemData: CommentData) => {
279
- itemData.is_allow_reply = parentC.data.is_allow_reply
280
- const childC = this.createComment(itemData)
283
+ // 导入评论 · 嵌套模式
284
+ private importCommentsNesting(srcData: CommentData[]) {
285
+ // 查找并导入所有子评论
286
+ const loadChildren = (parentC: Comment) => {
287
+ const children = srcData.filter(o => o.rid === parentC.data.id)
288
+ children.forEach((childData: CommentData) => {
289
+ const childC = this.createComment(childData)
281
290
  childC.render()
291
+
292
+ // 插入到父评论中
282
293
  parentC.putChild(childC)
283
- queryImportChildren(childC) // 递归
294
+
295
+ // 递归加载子评论
296
+ loadChildren(childC)
284
297
  })
285
298
  }
286
299
 
287
- // 开始处理 rawData
288
- if (!this.flatMode) {
289
- rawData.filter((o) => o.rid === 0).forEach((rootCommentData: CommentData) => {
290
- if (rootCommentData.is_collapsed) rootCommentData.is_allow_reply = false
291
- const rootComment = this.createComment(rootCommentData)
292
- rootComment.render()
293
- this.comments.push(rootComment) // 将评论导入 comments 总表中
300
+ // 遍历 root 评论
301
+ const rootComments = srcData.filter((o) => o.rid === 0)
302
+ rootComments.forEach((rootData: CommentData) => {
303
+ const rootC = this.createComment(rootData)
304
+ rootC.render()
294
305
 
295
- this.$commentsWrap.appendChild(rootComment.getEl())
296
- rootComment.playFadeInAnim()
306
+ // 显示并播放渐入动画
307
+ this.$commentsWrap.appendChild(rootC.getEl())
308
+ rootC.playFadeInAnim()
297
309
 
298
- queryImportChildren(rootComment)
299
- })
300
- } else {
301
- // 平铺模式
302
- rawData.forEach((commentData: CommentData) => {
303
- this.putCommentFlatMode(commentData, rawData, 'append')
304
- })
305
- }
310
+ // 评论放入 comments 总表中
311
+ this.comments.push(rootC)
306
312
 
307
- this.eachComment(this.comments, (c) => {
308
- this.checkMoreHide(c)
309
- })
313
+ // 加载子评论
314
+ loadChildren(rootC)
310
315
 
311
- this.refreshUI()
312
- this.ctx.trigger('comments-loaded')
316
+ // 限高检测
317
+ rootC.checkHeightLimit()
318
+ })
313
319
  }
314
320
 
315
321
  /** 导入评论 · 平铺模式 */
316
- private putCommentFlatMode(commentItem: CommentData, comments: CommentData[], insertMode: 'append'|'prepend') {
317
- if (commentItem.is_collapsed) commentItem.is_allow_reply = false
318
- const comment = this.createComment(commentItem)
319
- if (commentItem.rid !== 0) {
320
- const rComment = comments.find(o => o.id === commentItem.rid)
322
+ private putCommentFlatMode(cData: CommentData, srcData: CommentData[], insertMode: 'append'|'prepend') {
323
+ if (cData.is_collapsed) cData.is_allow_reply = false
324
+ const comment = this.createComment(cData)
325
+ if (cData.rid !== 0) {
326
+ const rComment = srcData.find(o => o.id === cData.rid)
321
327
  if (rComment) comment.replyTo = rComment
322
328
  }
323
329
  comment.render()
324
330
 
325
331
  // 将评论导入 comments 总表中
326
- if (insertMode === 'append') {
327
- this.comments.push(comment)
328
- } else {
329
- this.comments.unshift(comment)
330
- }
331
-
332
- if (commentItem.visible) {
333
- if (insertMode === 'append') {
334
- this.$commentsWrap.appendChild(comment.getEl())
335
- } else {
336
- this.$commentsWrap.prepend(comment.getEl())
337
- }
332
+ if (insertMode === 'append') this.comments.push(comment)
333
+ if (insertMode === 'prepend') this.comments.unshift(comment)
334
+
335
+ // 可见评论添加到界面
336
+ // 注:不可见评论用于显示 “引用内容”
337
+ if (cData.visible) {
338
+ if (insertMode === 'append') this.$commentsWrap.append(comment.getEl())
339
+ if (insertMode === 'prepend') this.$commentsWrap.prepend(comment.getEl())
338
340
  comment.playFadeInAnim()
339
341
  }
340
342
 
341
- this.checkMoreHide(comment)
343
+ // 平铺评论插入后 · 内容限高检测
344
+ comment.checkHeightLimit()
345
+
346
+ return comment
342
347
  }
343
348
 
344
- /** 插入评论 · 首部添加 */
349
+ /** 新增评论 · 首部添加 */
345
350
  public insertComment(commentData: CommentData) {
346
351
  if (!this.flatMode) {
352
+ // 嵌套模式
347
353
  const comment = this.createComment(commentData)
348
354
  comment.render()
349
355
 
350
- if (commentData.rid !== 0) {
351
- this.findComment(commentData.rid)?.putChild(comment)
352
- } else {
356
+ if (commentData.rid === 0) {
357
+ // root评论 新增
353
358
  this.$commentsWrap.prepend(comment.getEl())
354
359
  this.comments.unshift(comment)
360
+ } else {
361
+ // 子评论 新增
362
+ const parent = this.findComment(commentData.rid)
363
+ if (parent) {
364
+ parent.putChild(comment)
365
+
366
+ // 若父评论存在 “子评论部分” 限高,取消限高
367
+ comment.getParents().forEach((p) => {
368
+ if (p.$children) p.heightLimitRemove(p.$children)
369
+ })
370
+ }
355
371
  }
356
372
 
373
+ comment.checkHeightLimit()
374
+
357
375
  Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
358
376
  comment.playFadeInAnim() // 播放评论渐出动画
359
-
360
- this.checkMoreHide(comment)
361
377
  } else {
362
- this.putCommentFlatMode(commentData, this.comments.map(c => c.data), 'prepend')
363
- }
364
-
365
- if (this.data) this.data.total += 1 // 评论数增加 1
366
- this.refreshUI() // 更新 list 界面
367
- this.ctx.trigger('comments-loaded')
368
- }
369
-
370
- checkMoreHide(c: Comment) {
371
- const childrenH = this.ctx.conf.heightLimit?.children
372
- const contentH = this.ctx.conf.heightLimit?.content
373
- const isChildrenLimit = typeof childrenH === 'number' && childrenH > 0
374
- const isContentLimit = typeof contentH === 'number' && contentH > 0
375
-
376
- // 子评论内容过多隐藏
377
- if (isChildrenLimit && c.getIsRoot()) {
378
- c.checkMoreHide(c.$children, childrenH || 300)
379
- }
380
-
381
- // 评论内容过多隐藏
382
- if (isContentLimit) {
383
- c.checkMoreHide(c.$content, contentH || 200)
384
- if (c.$replyTo) c.checkMoreHide(c.$replyTo, contentH || 200) // 平铺模式回复内容
378
+ // 平铺模式
379
+ const comment = this.putCommentFlatMode(commentData, this.comments.map(c => c.data), 'prepend')
380
+ Ui.scrollIntoView(comment.getEl()) // 滚动到可见
385
381
  }
386
- }
387
-
388
- /** 获取评论总数 (包括子评论) */
389
- get commentsCount(): number {
390
- let count = 0
391
- this.eachComment(this.comments, () => { count++ })
392
- return count
393
- }
394
382
 
395
- /** 是否还有更多的评论 */
396
- get hasMoreComments(): boolean {
397
- if (!this.data) return false
398
- return this.data.total_parents > (this.offset + this.pageSize)
399
- }
383
+ // 评论数增加 1
384
+ if (this.data) this.data.total += 1
400
385
 
401
- get parentCommentsCount() {
402
- return this.comments.length
386
+ // 评论新增后
387
+ this.refreshUI()
388
+ this.ctx.trigger('comments-loaded')
403
389
  }
404
390
 
405
391
  /** 遍历操作 Comment (包括子评论) */
406
- public eachComment(commentList: Comment[], action: (comment: Comment, levelList: Comment[]) => boolean|void) {
392
+ protected eachComment(commentList: Comment[], action: (comment: Comment, levelList: Comment[]) => boolean|void) {
407
393
  if (commentList.length === 0) return
408
394
  commentList.every((item) => {
409
395
  if (action(item, commentList) === false) return false
@@ -413,7 +399,7 @@ export default class ListLite extends Component {
413
399
  }
414
400
 
415
401
  /** 查找评论项 */
416
- public findComment(id: number, src?: Comment[]): Comment|null {
402
+ protected findComment(id: number, src?: Comment[]): Comment|null {
417
403
  if (!src) src = this.comments
418
404
  let comment: Comment|null = null
419
405
  this.eachComment(src, (item) => {
@@ -427,13 +413,6 @@ export default class ListLite extends Component {
427
413
  return comment
428
414
  }
429
415
 
430
- /** 获取评论总数 */
431
- public getCommentCount(): number {
432
- let count = 0
433
- this.eachComment(this.comments, () => { count++ })
434
- return count
435
- }
436
-
437
416
  /** 删除评论 */
438
417
  public deleteComment(comment: number|Comment) {
439
418
  let findComment: Comment|null
@@ -451,6 +430,8 @@ export default class ListLite extends Component {
451
430
  return true
452
431
  })
453
432
 
433
+ if (this.data) this.data.total -= 1 // 评论数减 1
434
+
454
435
  this.refreshUI()
455
436
  }
456
437
 
@@ -461,11 +442,12 @@ export default class ListLite extends Component {
461
442
  this.comments = []
462
443
  }
463
444
 
445
+ /** 更新未读数据 */
464
446
  public updateUnread(notifies: NotifyData[]) {
465
447
  this.unread = notifies
466
448
 
467
449
  // 高亮评论
468
- if (this.unreadHighlight) {
450
+ if (this.unreadHighlight === true) {
469
451
  this.eachComment(this.comments, (comment) => {
470
452
  const notify = this.unread.find(o => o.comment_id === comment.data.id)
471
453
  if (notify) {
@@ -484,7 +466,8 @@ export default class ListLite extends Component {
484
466
  }
485
467
  }
486
468
 
487
- public apiVersionCheck(versionData: ApiVersionData): boolean {
469
+ /** 前端版本检测 */
470
+ public versionCheck(versionData: ApiVersionData): boolean {
488
471
  const needVersion = versionData?.fe_min_version || '0.0.0'
489
472
  const needUpdate = Utils.versionCompare(needVersion, ARTALK_VERSION) === 1
490
473
  if (needUpdate) {
@@ -498,7 +481,7 @@ export default class ListLite extends Component {
498
481
  ignoreBtn.onclick = () => {
499
482
  Ui.setError(this.ctx, null)
500
483
  this.ctx.conf.versionCheck = false
501
- this.reqComments(0)
484
+ this.fetchComments(0)
502
485
  }
503
486
  errEl.append(ignoreBtn)
504
487
  Ui.setError(this.ctx, errEl, '<span class="atk-warn-title">Artalk Warn</span>')