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
@@ -0,0 +1,425 @@
1
+ import '../style/comment.less'
2
+
3
+ import * as Utils from '../lib/utils'
4
+ import * as Ui from '../lib/ui'
5
+ import ActionBtn from '../components/action-btn'
6
+ import CommentHTML from './comment.html?raw'
7
+ import Comment from './comment'
8
+
9
+ export default class CommentRender {
10
+ private comment: Comment
11
+
12
+ private get ctx() { return this.comment.ctx }
13
+ private get data() { return this.comment.getData() }
14
+ private get cConf() { return this.comment.getConf() }
15
+
16
+ public $el!: HTMLElement
17
+ public $main!: HTMLElement
18
+ public $header!: HTMLElement
19
+ public $headerNick!: HTMLElement
20
+ public $headerBadgeWrap!: HTMLElement
21
+ public $body!: HTMLElement
22
+ public $content!: HTMLElement
23
+ private $childrenWrap!: HTMLElement|null
24
+ public $actions!: HTMLElement
25
+ public voteBtnUp?: ActionBtn
26
+ public voteBtnDown?: ActionBtn
27
+
28
+ public $replyTo?: HTMLElement // 回复评论内容 (平铺下显示)
29
+ public $replyAt?: HTMLElement // 回复 AT(层级嵌套下显示)
30
+
31
+ public constructor(comment: Comment) {
32
+ this.comment = comment
33
+ }
34
+
35
+ public render() {
36
+ this.$el = Utils.createElement(CommentHTML)
37
+
38
+ this.$main = this.$el.querySelector('.atk-main')!
39
+ this.$header = this.$el.querySelector('.atk-header')!
40
+ this.$body = this.$el.querySelector('.atk-body')!
41
+ this.$content = this.$body.querySelector('.atk-content')!
42
+ this.$actions = this.$el.querySelector('.atk-actions')!
43
+
44
+ this.$el.setAttribute('data-comment-id', `${this.data.id}`)
45
+
46
+ this.renderAvatar()
47
+ this.renderHeader()
48
+ this.renderContent()
49
+ this.renderReplyAt()
50
+ this.renderReplyTo()
51
+ this.renderPending()
52
+ this.renderActionBtn()
53
+
54
+ this.recoveryChildrenWrap()
55
+
56
+ return this.$el
57
+ }
58
+
59
+ /** 初始化 - 评论头像 */
60
+ private renderAvatar() {
61
+ const $avatar = this.$el.querySelector<HTMLElement>('.atk-avatar')!
62
+ const $avatarImg = Utils.createElement<HTMLImageElement>('<img />')
63
+ $avatarImg.src = this.comment.getGravatarURL()
64
+ if (this.data.link) {
65
+ const $avatarA = Utils.createElement<HTMLLinkElement>('<a target="_blank" rel="noreferrer noopener nofollow"></a>')
66
+ $avatarA.href = this.data.link
67
+ $avatarA.append($avatarImg)
68
+ $avatar.append($avatarA)
69
+ } else {
70
+ $avatar.append($avatarImg)
71
+ }
72
+ }
73
+
74
+ /** 初始化 - 评论信息 */
75
+ private renderHeader() {
76
+ this.$headerNick = this.$el.querySelector<HTMLElement>('.atk-nick')!
77
+
78
+ if (this.data.link) {
79
+ const $nickA = Utils.createElement<HTMLLinkElement>('<a target="_blank" rel="noreferrer noopener nofollow"></a>')
80
+ $nickA.innerText = this.data.nick
81
+ $nickA.href = this.data.link
82
+ this.$headerNick.append($nickA)
83
+ } else {
84
+ this.$headerNick.innerText = this.data.nick
85
+ }
86
+
87
+ this.$headerBadgeWrap = this.$el.querySelector<HTMLElement>('.atk-badge-wrap')!
88
+ this.$headerBadgeWrap.innerHTML = ''
89
+
90
+ const badgeText = this.data.badge_name
91
+ const badgeColor = this.data.badge_color
92
+ if (badgeText) {
93
+ const $badge = Utils.createElement(`<span class="atk-badge"></span>`)
94
+ $badge.innerText = badgeText.replace('管理员', this.ctx.$t('admin')) // i18n patch
95
+ $badge.style.backgroundColor = badgeColor || ''
96
+ this.$headerBadgeWrap.append($badge)
97
+ }
98
+
99
+ if (this.data.is_pinned) {
100
+ const $pinnedBadge = Utils.createElement(`<span class="atk-pinned-badge">${this.ctx.$t('pin')}</span>`) // 置顶徽章
101
+ this.$headerBadgeWrap.append($pinnedBadge)
102
+ }
103
+
104
+ const $date = this.$el.querySelector<HTMLElement>('.atk-date')!
105
+ $date.innerText = this.comment.getDateFormatted()
106
+ $date.setAttribute('data-atk-comment-date', String(+new Date(this.data.date)))
107
+
108
+ if (this.ctx.conf.uaBadge) {
109
+ let $uaWrap = this.$header.querySelector('atk-ua-wrap')
110
+ if (!$uaWrap) {
111
+ $uaWrap = Utils.createElement(`<span class="atk-ua-wrap"></span>`)
112
+ this.$header.append($uaWrap)
113
+ }
114
+
115
+ $uaWrap.innerHTML = ''
116
+ const $uaBrowser = Utils.createElement(`<span class="atk-ua ua-browser"></span>`)
117
+ const $usOS = Utils.createElement(`<span class="atk-ua ua-os"></span>`)
118
+ $uaBrowser.innerText = this.comment.getUserUaBrowser()
119
+ $usOS.innerText = this.comment.getUserUaOS()
120
+ $uaWrap.append($uaBrowser)
121
+ $uaWrap.append($usOS)
122
+ }
123
+ }
124
+
125
+ /** 初始化 - 评论内容 */
126
+ private renderContent() {
127
+ if (!this.data.is_collapsed) {
128
+ this.$content.innerHTML = this.comment.getContentMarked()
129
+ this.$content.classList.remove('atk-hide', 'atk-collapsed')
130
+ return
131
+ }
132
+
133
+ // 内容 & 折叠
134
+ this.$content.classList.add('atk-hide', 'atk-type-collapsed')
135
+ const collapsedInfoEl = Utils.createElement(`
136
+ <div class="atk-collapsed">
137
+ <span class="atk-text">${this.ctx.$t('collapsedMsg')}</span>
138
+ <span class="atk-show-btn">${this.ctx.$t('expand')}</span>
139
+ </div>`)
140
+ this.$body.insertAdjacentElement('beforeend', collapsedInfoEl)
141
+
142
+ const contentShowBtn = collapsedInfoEl.querySelector('.atk-show-btn')!
143
+ contentShowBtn.addEventListener('click', (e) => {
144
+ e.stopPropagation() // 防止穿透
145
+
146
+ if (this.$content.classList.contains('atk-hide')) {
147
+ this.$content.innerHTML = this.comment.getContentMarked()
148
+ this.$content.classList.remove('atk-hide')
149
+ Ui.playFadeInAnim(this.$content)
150
+ contentShowBtn.innerHTML = this.ctx.$t('collapse')
151
+ } else {
152
+ this.$content.innerHTML = ''
153
+ this.$content.classList.add('atk-hide')
154
+ contentShowBtn.innerHTML = this.ctx.$t('expand')
155
+ }
156
+ })
157
+ }
158
+
159
+ /** 初始化 - 层级嵌套模式显示 At */
160
+ private renderReplyAt() {
161
+ if (this.cConf.isFlatMode || this.data.rid === 0) return // not 平铺模式 或 根评论
162
+ if (!this.cConf.replyTo) return
163
+
164
+ this.$replyAt = Utils.createElement(`<span class="atk-item atk-reply-at"><span class="atk-arrow"></span><span class="atk-nick"></span></span>`)
165
+ this.$replyAt.querySelector<HTMLElement>('.atk-nick')!.innerText = `${this.cConf.replyTo.nick}`
166
+ this.$replyAt.onclick = () => { this.comment.getActions().goToReplyComment() }
167
+
168
+ this.$headerBadgeWrap.insertAdjacentElement('afterend', this.$replyAt)
169
+ }
170
+
171
+ /** 初始化 - 回复的对象 */
172
+ private renderReplyTo() {
173
+ if (!this.cConf.isFlatMode) return // 仅平铺模式显示
174
+ if (!this.cConf.replyTo) return
175
+
176
+ this.$replyTo = Utils.createElement(`
177
+ <div class="atk-reply-to">
178
+ <div class="atk-meta">${this.ctx.$t('reply')} <span class="atk-nick"></span>:</div>
179
+ <div class="atk-content"></div>
180
+ </div>`)
181
+ const $nick = this.$replyTo.querySelector<HTMLElement>('.atk-nick')!
182
+ $nick.innerText = `@${this.cConf.replyTo.nick}`
183
+ $nick.onclick = () => { this.comment.getActions().goToReplyComment() }
184
+ let replyContent = Utils.marked(this.ctx, this.cConf.replyTo.content)
185
+ if (this.cConf.replyTo.is_collapsed) replyContent = `[${this.ctx.$t('collapsed')}]`
186
+ this.$replyTo.querySelector<HTMLElement>('.atk-content')!.innerHTML = replyContent
187
+ this.$body.prepend(this.$replyTo)
188
+ }
189
+
190
+ /** 初始化 - 待审核状态 */
191
+ private renderPending() {
192
+ if (!this.data.is_pending) return
193
+
194
+ const pendingEl = Utils.createElement(`<div class="atk-pending">${this.ctx.$t('pendingMsg')}</div>`)
195
+ this.$body.prepend(pendingEl)
196
+ }
197
+
198
+ /** 初始化 - 评论操作按钮 */
199
+ private renderActionBtn() {
200
+ // 投票功能
201
+ if (this.ctx.conf.vote) {
202
+ // 赞同按钮
203
+ this.voteBtnUp = new ActionBtn(this.ctx, () => `${this.ctx.$t('voteUp')} (${this.data.vote_up || 0})`).appendTo(this.$actions)
204
+ this.voteBtnUp.setClick(() => {
205
+ this.comment.getActions().vote('up')
206
+ })
207
+
208
+ // 反对按钮
209
+ if (this.ctx.conf.voteDown) {
210
+ this.voteBtnDown = new ActionBtn(this.ctx, () => `${this.ctx.$t('voteDown')} (${this.data.vote_down || 0})`).appendTo(this.$actions)
211
+ this.voteBtnDown.setClick(() => {
212
+ this.comment.getActions().vote('down')
213
+ })
214
+ }
215
+ }
216
+
217
+ // 绑定回复按钮事件
218
+ if (this.data.is_allow_reply) {
219
+ const replyBtn = Utils.createElement(`<span>${this.ctx.$t('reply')}</span>`)
220
+ this.$actions.append(replyBtn)
221
+ replyBtn.addEventListener('click', (e) => {
222
+ e.stopPropagation() // 防止穿透
223
+ if (!this.cConf.onReplyBtnClick) {
224
+ this.ctx.replyComment(this.data, this.$el)
225
+ } else {
226
+ this.cConf.onReplyBtnClick()
227
+ }
228
+ })
229
+ }
230
+
231
+ // 绑定折叠按钮事件
232
+ const collapseBtn = new ActionBtn(this.ctx, {
233
+ text: () => (this.data.is_collapsed ? this.ctx.$t('expand') : this.ctx.$t('collapse')),
234
+ adminOnly: true
235
+ })
236
+ collapseBtn.appendTo(this.$actions)
237
+ collapseBtn.setClick(() => {
238
+ this.comment.getActions().adminEdit('collapsed', collapseBtn)
239
+ })
240
+
241
+ // 绑定待审核按钮事件
242
+ const pendingBtn = new ActionBtn(this.ctx, {
243
+ text: () => (this.data.is_pending ? this.ctx.$t('pending') : this.ctx.$t('approved')),
244
+ adminOnly: true
245
+ })
246
+ pendingBtn.appendTo(this.$actions)
247
+ pendingBtn.setClick(() => {
248
+ this.comment.getActions().adminEdit('pending', pendingBtn)
249
+ })
250
+
251
+ // 绑定删除按钮事件
252
+ const delBtn = new ActionBtn(this.ctx, {
253
+ text: this.ctx.$t('delete'),
254
+ confirm: true,
255
+ confirmText: this.ctx.$t('deleteConfirm'),
256
+ adminOnly: true,
257
+ })
258
+ delBtn.appendTo(this.$actions)
259
+ delBtn.setClick(() => {
260
+ this.comment.getActions().adminDelete(delBtn)
261
+ })
262
+
263
+ // 绑定置顶按钮事件
264
+ const pinnedBtn = new ActionBtn(this.ctx, {
265
+ text: () => (this.data.is_pinned ? this.ctx.$t('unpin') : this.ctx.$t('pin')),
266
+ adminOnly: true
267
+ })
268
+ pinnedBtn.appendTo(this.$actions)
269
+ pinnedBtn.setClick(() => {
270
+ this.comment.getActions().adminEdit('pinned', pendingBtn)
271
+ })
272
+ }
273
+
274
+ /** 内容限高检测 */
275
+ public checkHeightLimit() {
276
+ this.checkHeightLimitArea('content') // 评论内容限高
277
+ this.checkHeightLimitArea('children') // 子评论部分限高(嵌套模式)
278
+ }
279
+
280
+ /** 目标内容限高检测 */
281
+ public checkHeightLimitArea(area: 'children'|'content') {
282
+ // 参数准备
283
+ const childrenMaxH = this.ctx.conf.heightLimit.children
284
+ const contentMaxH = this.ctx.conf.heightLimit.content
285
+
286
+ if (area === 'children' && !childrenMaxH) return
287
+ if (area === 'content' && !contentMaxH) return
288
+
289
+ // 限高
290
+ let maxHeight: number
291
+ if (area === 'children') maxHeight = childrenMaxH!
292
+ if (area === 'content') maxHeight = contentMaxH!
293
+
294
+ // 检测指定元素
295
+ const checkEl = ($el?: HTMLElement|null) => {
296
+ if (!$el) return
297
+
298
+ // 是否超过高度
299
+ if (Utils.getHeight($el) > maxHeight) {
300
+ this.heightLimitAdd($el, maxHeight)
301
+ }
302
+ }
303
+
304
+ // 执行限高检测
305
+ if (area === 'children') {
306
+ checkEl(this.$childrenWrap)
307
+ } else if (area === 'content') {
308
+ checkEl(this.$content)
309
+ checkEl(this.$replyTo)
310
+
311
+ // 若有图片 · 图片加载完后再检测一次
312
+ Utils.onImagesLoaded(this.$content, () => {
313
+ checkEl(this.$content)
314
+ })
315
+ if (this.$replyTo) {
316
+ Utils.onImagesLoaded(this.$replyTo, () => {
317
+ checkEl(this.$replyTo)
318
+ })
319
+ }
320
+ }
321
+ }
322
+
323
+ /** 移除限高 */
324
+ private heightLimitRemove($el: HTMLElement) {
325
+ if (!$el) return
326
+ if (!$el.classList.contains('atk-height-limit')) return
327
+
328
+ $el.classList.remove('atk-height-limit')
329
+ Array.from($el.children).forEach((e) => {
330
+ if (e.classList.contains('atk-height-limit-btn')) e.remove()
331
+ })
332
+ $el.style.height = ''
333
+ $el.style.overflow = ''
334
+ }
335
+
336
+ /** 子评论区域移除限高 */
337
+ public heightLimitRemoveForChildren() {
338
+ if (!this.$childrenWrap) return
339
+ this.heightLimitRemove(this.$childrenWrap)
340
+ }
341
+
342
+ /** 内容限高区域新增 */
343
+ private heightLimitAdd($el: HTMLElement, maxHeight: number) {
344
+ if (!$el) return
345
+ if ($el.classList.contains('atk-height-limit')) return
346
+
347
+ $el.classList.add('atk-height-limit')
348
+ $el.style.height = `${maxHeight}px`
349
+ $el.style.overflow = 'hidden'
350
+ const $hideMoreOpenBtn = Utils.createElement(`<div class="atk-height-limit-btn">${this.ctx.$t('readMore')}</span>`)
351
+ $hideMoreOpenBtn.onclick = (e) => {
352
+ e.stopPropagation()
353
+ this.heightLimitRemove($el)
354
+
355
+ // 子评论数等于 1,直接取消限高
356
+ const children = this.comment.getChildren()
357
+ if (children.length === 1) children[0].getRender().heightLimitRemove(children[0].getRender().$content)
358
+ }
359
+ $el.append($hideMoreOpenBtn)
360
+ }
361
+
362
+ /** 渐出动画 */
363
+ playFadeAnim() {
364
+ Ui.playFadeInAnim(this.comment.getRender().$el)
365
+ }
366
+
367
+ /** 渐出动画 · 评论内容区域 */
368
+ playFadeAnimForBody() {
369
+ Ui.playFadeInAnim(this.comment.getRender().$body)
370
+ }
371
+
372
+ /** 获取子评论 Wrap */
373
+ public getChildrenWrap() {
374
+ return this.$childrenWrap
375
+ }
376
+
377
+ /** 初始化子评论区域 Wrap */
378
+ public renderChildrenWrap() {
379
+ if (!this.$childrenWrap) {
380
+ this.$childrenWrap = Utils.createElement('<div class="atk-comment-children"></div>')
381
+ this.$main.append(this.$childrenWrap)
382
+ }
383
+
384
+ return this.$childrenWrap
385
+ }
386
+
387
+ /** 恢复原有的子评论区域 Wrap */
388
+ public recoveryChildrenWrap() {
389
+ if (this.$childrenWrap) {
390
+ this.$main.append(this.$childrenWrap)
391
+ }
392
+ }
393
+
394
+ /** 设置已读 */
395
+ public setUnread(val: boolean) {
396
+ if (val) this.$el.classList.add('atk-unread')
397
+ else this.$el.classList.remove('atk-unread')
398
+ }
399
+
400
+ /** 设置为可点击的评论 */
401
+ public setOpenable(val: boolean) {
402
+ if (val) this.$el.classList.add('atk-openable')
403
+ else this.$el.classList.remove('atk-openable')
404
+ }
405
+
406
+ /** 设置点击评论打开置顶 URL */
407
+ public setOpenURL(url: string) {
408
+ this.setOpenable(true)
409
+ this.$el.onclick = (evt) => {
410
+ evt.preventDefault()
411
+ window.open(url)
412
+
413
+ if (this.cConf.openEvt) this.cConf.openEvt()
414
+ }
415
+ }
416
+
417
+ /** 设置点击评论时的操作 */
418
+ public setOpenAction(action: () => void) {
419
+ this.setOpenable(true)
420
+ this.$el.onclick = (evt) => {
421
+ evt.preventDefault()
422
+ action()
423
+ }
424
+ }
425
+ }
@@ -1,3 +1,4 @@
1
+ import Context from '~/types/context'
1
2
  import * as Utils from '../lib/utils'
2
3
 
3
4
  interface ActionBtnConf {
@@ -18,6 +19,7 @@ interface ActionBtnConf {
18
19
  * 通用操作按钮
19
20
  */
20
21
  export default class ActionBtn {
22
+ private ctx: Context
21
23
  private conf: ActionBtnConf
22
24
  public $el: HTMLElement
23
25
 
@@ -31,7 +33,8 @@ export default class ActionBtn {
31
33
  public confirmRecTimer?: number // 确认消息复原定时器
32
34
 
33
35
  /** 构造函数 */
34
- constructor(conf: ActionBtnConf|string|(() => string)) {
36
+ constructor(ctx: Context, conf: ActionBtnConf|string|(() => string)) {
37
+ this.ctx = ctx
35
38
  this.$el = Utils.createElement(`<span class="atk-common-action-btn"></span>`)
36
39
 
37
40
  this.conf = (typeof conf !== 'object') ? ({ text: conf }) : conf
@@ -73,7 +76,7 @@ export default class ActionBtn {
73
76
  if (!this.isConfirming) {
74
77
  this.isConfirming = true
75
78
  this.$el.classList.add('atk-btn-confirm')
76
- this.$el.innerText = this.conf.confirmText || '确认操作'
79
+ this.$el.innerText = this.conf.confirmText || this.ctx.$t('actionConfirm')
77
80
  this.confirmRecTimer = window.setTimeout(() => confirmRestore(), 5000)
78
81
  return
79
82
  }
@@ -107,7 +110,7 @@ export default class ActionBtn {
107
110
  this.isLoading = value
108
111
  if (value) {
109
112
  this.$el.classList.add('atk-btn-loading')
110
- this.$el.innerText = loadingText || '加载中...'
113
+ this.$el.innerText = loadingText || `${this.ctx.$t('loading')}...`
111
114
  } else {
112
115
  this.$el.classList.remove('atk-btn-loading')
113
116
  this.$el.innerText = this.getText()
@@ -1,3 +1,4 @@
1
+ import Context from '~/types/context'
1
2
  import * as Utils from '../lib/utils'
2
3
 
3
4
  type BtnClickHandler = (btnEl: HTMLElement, dialog: Dialog) => boolean|void
@@ -6,11 +7,14 @@ type BtnClickHandler = (btnEl: HTMLElement, dialog: Dialog) => boolean|void
6
7
  * 对话框
7
8
  */
8
9
  export default class Dialog {
10
+ public ctx: Context
9
11
  public $el: HTMLElement
10
12
  public $content: HTMLElement
11
13
  public $actions: HTMLElement
12
14
 
13
- constructor (contentEl: HTMLElement) {
15
+ constructor (ctx: Context, contentEl: HTMLElement) {
16
+ this.ctx = ctx
17
+
14
18
  this.$el = Utils.createElement(
15
19
  `<div class="atk-layer-dialog-wrap">
16
20
  <div class="atk-layer-dialog">
@@ -33,7 +37,7 @@ export default class Dialog {
33
37
  /** 按钮 · 确定 */
34
38
  public setYes(handler: BtnClickHandler) {
35
39
  const btn = Utils.createElement<HTMLButtonElement>(
36
- '<button data-action="confirm">确定</button>'
40
+ `<button data-action="confirm">${this.ctx.$t('confirm')}</button>`
37
41
  )
38
42
  btn.onclick = this.onBtnClick(handler)
39
43
  this.$actions.appendChild(btn)
@@ -44,7 +48,7 @@ export default class Dialog {
44
48
  /** 按钮 · 取消 */
45
49
  public setNo(handler: BtnClickHandler) {
46
50
  const btn = Utils.createElement<HTMLButtonElement>(
47
- '<button data-action="cancel">取消</button>'
51
+ `<button data-action="cancel">${this.ctx.$t('cancel')}</button>`
48
52
  )
49
53
  btn.onclick = this.onBtnClick(handler)
50
54
  this.$actions.appendChild(btn)
@@ -5,6 +5,8 @@ export interface ReadMoreBtnConf {
5
5
  onClick: (offset: number) => void
6
6
 
7
7
  pageSize: number
8
+
9
+ text?: string
8
10
  }
9
11
 
10
12
  /**
@@ -17,6 +19,7 @@ export default class ReadMoreBtn {
17
19
  private $text: HTMLElement
18
20
  private offset: number = 0
19
21
  private total: number = 0
22
+ private origText: string = 'Load More'
20
23
 
21
24
  /** 是否有更多内容 */
22
25
  get hasMore() {
@@ -25,12 +28,13 @@ export default class ReadMoreBtn {
25
28
 
26
29
  public constructor(conf: ReadMoreBtnConf) {
27
30
  this.conf = conf
31
+ this.origText = this.conf.text || this.origText
28
32
 
29
33
  this.$el = Utils.createElement(
30
34
  `<div class="atk-list-read-more" style="display: none;">
31
35
  <div class="atk-list-read-more-inner">
32
36
  <div class="atk-loading-icon" style="display: none;"></div>
33
- <span class="atk-text">加载更多</span>
37
+ <span class="atk-text">${this.origText}</span>
34
38
  </div>
35
39
  </div>`)
36
40
 
@@ -68,7 +72,7 @@ export default class ReadMoreBtn {
68
72
  this.$text.innerText = errMsg
69
73
  this.$el.classList.add('atk-err')
70
74
  window.setTimeout(() => {
71
- this.$text.innerText = '查看更多'
75
+ this.$text.innerText = this.origText
72
76
  this.$el.classList.remove('atk-err')
73
77
  }, 2000) // 2s后错误提示复原
74
78
  }