artalk 2.6.4 → 2.7.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 (300) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +7794 -7483
  3. package/dist/Artalk.iife.js +1 -1
  4. package/dist/Artalk.js +1 -1
  5. package/dist/ArtalkLite.css +1 -1
  6. package/dist/ArtalkLite.es.js +5587 -5276
  7. package/dist/ArtalkLite.iife.js +1 -1
  8. package/dist/ArtalkLite.js +1 -1
  9. package/dist/src/api/{api-base.d.ts → _base.d.ts} +3 -7
  10. package/dist/src/api/_options.d.ts +19 -0
  11. package/dist/src/api/{request.d.ts → _request.d.ts} +3 -3
  12. package/dist/src/api/admin.d.ts +1 -1
  13. package/dist/src/api/captcha.d.ts +1 -1
  14. package/dist/src/api/comment.d.ts +2 -2
  15. package/dist/src/api/index.d.ts +2 -4
  16. package/dist/src/api/page.d.ts +3 -3
  17. package/dist/src/api/site.d.ts +2 -2
  18. package/dist/src/api/system.d.ts +13 -3
  19. package/dist/src/api/upload.d.ts +1 -1
  20. package/dist/src/api/user.d.ts +2 -2
  21. package/dist/src/artalk.d.ts +14 -37
  22. package/dist/src/comment/actions.d.ts +1 -1
  23. package/dist/src/comment/comment.d.ts +3 -4
  24. package/dist/src/comment/render.d.ts +21 -3
  25. package/dist/src/comment/renders/actions.d.ts +2 -2
  26. package/dist/src/comment/renders/avatar.d.ts +2 -2
  27. package/dist/src/comment/renders/content.d.ts +2 -2
  28. package/dist/src/comment/renders/header.d.ts +2 -2
  29. package/dist/src/comment/renders/index.d.ts +2 -2
  30. package/dist/src/comment/renders/pending.d.ts +2 -2
  31. package/dist/src/comment/renders/reply-at.d.ts +2 -2
  32. package/dist/src/comment/renders/reply-to.d.ts +2 -2
  33. package/dist/src/components/action-btn.d.ts +3 -5
  34. package/dist/src/{lib → components}/checker/admin.d.ts +1 -1
  35. package/dist/src/{lib → components}/checker/captcha-renders.d.ts +1 -1
  36. package/dist/src/{lib → components}/checker/captcha.d.ts +1 -1
  37. package/dist/src/{lib → components}/checker/index.d.ts +10 -7
  38. package/dist/src/components/dark-mode.d.ts +2 -0
  39. package/dist/src/components/dialog.d.ts +1 -3
  40. package/dist/src/components/error-dialog.d.ts +8 -0
  41. package/dist/src/components/pagination.d.ts +4 -3
  42. package/dist/src/components/read-more-btn.d.ts +3 -3
  43. package/dist/src/config.d.ts +24 -8
  44. package/dist/src/context.d.ts +16 -35
  45. package/dist/src/data.d.ts +27 -0
  46. package/dist/src/defaults.d.ts +1 -1
  47. package/dist/src/editor/editor.d.ts +14 -61
  48. package/dist/src/editor/state.d.ts +20 -0
  49. package/dist/src/i18n/zh-CN.d.ts +1 -1
  50. package/dist/src/layer/index.d.ts +4 -3
  51. package/dist/src/layer/layer-manager.d.ts +9 -0
  52. package/dist/src/layer/layer.d.ts +8 -28
  53. package/dist/src/layer/scrollbar-helper.d.ts +5 -0
  54. package/dist/src/layer/sidebar-layer.d.ts +6 -6
  55. package/dist/src/layer/wrap.d.ts +13 -0
  56. package/dist/src/lib/component.d.ts +3 -8
  57. package/dist/src/lib/event-manager.d.ts +28 -0
  58. package/dist/src/lib/highlight.d.ts +1 -0
  59. package/dist/src/lib/marked-renderer.d.ts +4 -0
  60. package/dist/src/lib/marked.d.ts +4 -2
  61. package/dist/src/lib/sanitizer.d.ts +1 -0
  62. package/dist/src/lib/ui.d.ts +3 -2
  63. package/dist/src/lib/user.d.ts +8 -5
  64. package/dist/src/lib/utils.d.ts +11 -5
  65. package/dist/src/list/comment.d.ts +3 -0
  66. package/dist/src/list/layout.d.ts +23 -0
  67. package/dist/src/list/list.d.ts +13 -25
  68. package/dist/src/list/{list-nest.d.ts → nest.d.ts} +1 -1
  69. package/dist/src/list/page.d.ts +2 -0
  70. package/dist/src/list/paginator/index.d.ts +22 -7
  71. package/dist/src/list/paginator/read-more.d.ts +18 -0
  72. package/dist/src/list/paginator/up-down.d.ts +14 -0
  73. package/dist/src/main.d.ts +2 -0
  74. package/dist/src/plugins/admin-only-elem.d.ts +2 -0
  75. package/dist/src/plugins/conf-remoter.d.ts +2 -0
  76. package/dist/src/plugins/dark-mode.d.ts +2 -0
  77. package/dist/src/plugins/editor/_kit.d.ts +27 -0
  78. package/dist/src/plugins/editor/_plug.d.ts +29 -0
  79. package/dist/src/plugins/editor/_sample.d.ts +5 -0
  80. package/dist/src/plugins/editor/closable.d.ts +7 -0
  81. package/dist/src/{editor/plugs/emoticons-plug.d.ts → plugins/editor/emoticons.d.ts} +10 -16
  82. package/dist/src/plugins/editor/header-event.d.ts +6 -0
  83. package/dist/src/plugins/editor/header-link.d.ts +6 -0
  84. package/dist/src/plugins/editor/header-user.d.ts +16 -0
  85. package/dist/src/plugins/editor/index.d.ts +6 -0
  86. package/dist/src/plugins/editor/local-storage.d.ts +6 -0
  87. package/dist/src/plugins/editor/mover.d.ts +6 -0
  88. package/dist/src/plugins/editor/preview.d.ts +7 -0
  89. package/dist/src/plugins/editor/state-edit.d.ts +11 -0
  90. package/dist/src/plugins/editor/state-reply.d.ts +8 -0
  91. package/dist/src/plugins/editor/submit-add.d.ts +18 -0
  92. package/dist/src/plugins/editor/submit-btn.d.ts +5 -0
  93. package/dist/src/plugins/editor/submit.d.ts +17 -0
  94. package/dist/src/plugins/editor/textarea.d.ts +8 -0
  95. package/dist/src/plugins/editor/upload.d.ts +9 -0
  96. package/dist/src/plugins/editor-kit.d.ts +42 -0
  97. package/dist/src/plugins/index.d.ts +2 -0
  98. package/dist/src/plugins/list/copyright.d.ts +2 -0
  99. package/dist/src/plugins/list/count.d.ts +2 -0
  100. package/dist/src/plugins/list/dropdown.d.ts +2 -0
  101. package/dist/src/plugins/list/error-dialog.d.ts +2 -0
  102. package/dist/src/plugins/list/fetch.d.ts +2 -0
  103. package/dist/src/plugins/list/goto-first.d.ts +3 -0
  104. package/dist/src/plugins/list/goto.d.ts +2 -0
  105. package/dist/src/plugins/list/index.d.ts +3 -0
  106. package/dist/src/plugins/list/loading.d.ts +2 -0
  107. package/dist/src/plugins/list/no-comment.d.ts +2 -0
  108. package/dist/src/plugins/list/reach-bottom.d.ts +2 -0
  109. package/dist/src/plugins/list/sidebar-btn.d.ts +2 -0
  110. package/dist/src/plugins/list/time-ticking.d.ts +3 -0
  111. package/dist/src/plugins/list/unread-badge.d.ts +2 -0
  112. package/dist/src/plugins/list/unread.d.ts +2 -0
  113. package/dist/src/plugins/list/with-editor.d.ts +2 -0
  114. package/dist/src/plugins/markdown.d.ts +2 -0
  115. package/dist/src/plugins/stat.d.ts +13 -0
  116. package/dist/src/plugins/version-check.d.ts +2 -0
  117. package/dist/src/service.d.ts +19 -23
  118. package/dist/tests/e2e/comment-add.spec.d.ts +1 -0
  119. package/dist/types/config.d.ts +110 -0
  120. package/dist/types/context.d.ts +56 -136
  121. package/dist/types/data.d.ts +194 -0
  122. package/dist/types/editor.d.ts +76 -0
  123. package/dist/types/event.d.ts +36 -25
  124. package/dist/types/index.d.ts +7 -0
  125. package/dist/types/plugin.d.ts +2 -0
  126. package/dist/types/sidebar.d.ts +3 -0
  127. package/package.json +5 -2
  128. package/src/api/_base.ts +18 -0
  129. package/src/api/_options.ts +25 -0
  130. package/src/api/{request.ts → _request.ts} +19 -18
  131. package/src/api/admin.ts +1 -1
  132. package/src/api/captcha.ts +1 -1
  133. package/src/api/comment.ts +4 -4
  134. package/src/api/index.ts +3 -12
  135. package/src/api/page.ts +5 -5
  136. package/src/api/site.ts +2 -2
  137. package/src/api/system.ts +19 -7
  138. package/src/api/upload.ts +3 -3
  139. package/src/api/user.ts +3 -3
  140. package/src/artalk.ts +49 -97
  141. package/src/comment/actions.ts +1 -4
  142. package/src/comment/comment.ts +9 -6
  143. package/src/comment/render.ts +27 -5
  144. package/src/comment/renders/actions.ts +45 -45
  145. package/src/comment/renders/avatar.ts +7 -7
  146. package/src/comment/renders/content.ts +18 -18
  147. package/src/comment/renders/header.ts +13 -13
  148. package/src/comment/renders/index.ts +3 -3
  149. package/src/comment/renders/pending.ts +5 -5
  150. package/src/comment/renders/reply-at.ts +8 -8
  151. package/src/comment/renders/reply-to.ts +13 -13
  152. package/src/components/action-btn.ts +11 -13
  153. package/src/{lib → components}/checker/admin.ts +6 -6
  154. package/src/{lib → components}/checker/captcha-renders.ts +7 -6
  155. package/src/{lib → components}/checker/captcha.ts +1 -1
  156. package/src/{lib → components}/checker/index.ts +21 -26
  157. package/src/components/dark-mode.ts +30 -0
  158. package/src/components/dialog.ts +4 -9
  159. package/src/components/error-dialog.ts +35 -0
  160. package/src/components/pagination.ts +10 -6
  161. package/src/components/read-more-btn.ts +7 -7
  162. package/src/config.ts +60 -6
  163. package/src/context.ts +39 -144
  164. package/src/data.ts +110 -0
  165. package/src/defaults.ts +1 -1
  166. package/src/editor/editor.ts +39 -152
  167. package/src/editor/state.ts +52 -0
  168. package/src/i18n/zh-CN.ts +1 -1
  169. package/src/layer/index.ts +4 -4
  170. package/src/layer/layer-manager.ts +32 -0
  171. package/src/layer/layer.ts +20 -144
  172. package/src/layer/scrollbar-helper.ts +24 -0
  173. package/src/layer/sidebar-layer.ts +74 -64
  174. package/src/layer/wrap.ts +77 -0
  175. package/src/lib/component.ts +4 -11
  176. package/src/lib/detect.ts +1 -1
  177. package/src/lib/event-manager.ts +47 -0
  178. package/src/lib/highlight.ts +5 -0
  179. package/src/lib/marked-renderer.ts +32 -0
  180. package/src/lib/marked.ts +43 -104
  181. package/src/lib/sanitizer.ts +57 -0
  182. package/src/lib/ui.ts +22 -15
  183. package/src/lib/user.ts +21 -16
  184. package/src/lib/utils.ts +29 -18
  185. package/src/list/comment.ts +20 -0
  186. package/src/list/layout.ts +120 -0
  187. package/src/list/list.html +3 -1
  188. package/src/list/list.ts +56 -200
  189. package/src/list/{list-nest.ts → nest.ts} +1 -1
  190. package/src/list/page.ts +97 -0
  191. package/src/list/paginator/index.ts +20 -8
  192. package/src/list/paginator/read-more.ts +67 -0
  193. package/src/list/paginator/up-down.ts +51 -0
  194. package/src/main.ts +2 -0
  195. package/src/plugins/admin-only-elem.ts +40 -0
  196. package/src/plugins/conf-remoter.ts +54 -0
  197. package/src/plugins/dark-mode.ts +12 -0
  198. package/src/plugins/editor/_kit.ts +57 -0
  199. package/src/plugins/editor/_plug.ts +60 -0
  200. package/src/plugins/editor/_sample.ts +8 -0
  201. package/src/plugins/editor/closable.ts +44 -0
  202. package/src/{editor/plugs/emoticons-plug.ts → plugins/editor/emoticons.ts} +51 -52
  203. package/src/plugins/editor/header-event.ts +35 -0
  204. package/src/plugins/editor/header-link.ts +31 -0
  205. package/src/plugins/editor/header-user.ts +98 -0
  206. package/src/plugins/editor/index.ts +40 -0
  207. package/src/plugins/editor/local-storage.ts +36 -0
  208. package/src/plugins/editor/mover.ts +29 -0
  209. package/src/plugins/editor/preview.ts +41 -0
  210. package/src/plugins/editor/state-edit.ts +116 -0
  211. package/src/plugins/editor/state-reply.ts +91 -0
  212. package/src/plugins/editor/submit-add.ts +33 -0
  213. package/src/plugins/editor/submit-btn.ts +25 -0
  214. package/src/plugins/editor/submit.ts +73 -0
  215. package/src/plugins/editor/textarea.ts +55 -0
  216. package/src/plugins/editor/upload.ts +145 -0
  217. package/src/plugins/editor-kit.ts +161 -0
  218. package/src/plugins/index.ts +16 -0
  219. package/src/plugins/list/copyright.ts +16 -0
  220. package/src/plugins/list/count.ts +31 -0
  221. package/src/plugins/list/dropdown.ts +95 -0
  222. package/src/plugins/list/error-dialog.ts +22 -0
  223. package/src/plugins/list/fetch.ts +64 -0
  224. package/src/plugins/list/goto-first.ts +23 -0
  225. package/src/plugins/list/goto.ts +72 -0
  226. package/src/plugins/list/index.ts +25 -0
  227. package/src/plugins/list/loading.ts +17 -0
  228. package/src/plugins/list/no-comment.ts +25 -0
  229. package/src/plugins/list/reach-bottom.ts +46 -0
  230. package/src/plugins/list/sidebar-btn.ts +39 -0
  231. package/src/plugins/list/time-ticking.ts +22 -0
  232. package/src/plugins/list/unread-badge.ts +26 -0
  233. package/src/plugins/list/unread.ts +38 -0
  234. package/src/plugins/list/with-editor.ts +59 -0
  235. package/src/plugins/markdown.ts +10 -0
  236. package/src/plugins/stat.ts +79 -0
  237. package/src/plugins/version-check.ts +37 -0
  238. package/src/service.ts +34 -61
  239. package/src/style/comment.scss +5 -7
  240. package/src/style/editor.scss +5 -0
  241. package/src/style/list.scss +1 -1
  242. package/types/{artalk-config.d.ts → config.ts} +16 -2
  243. package/types/context.ts +84 -0
  244. package/types/{artalk-data.d.ts → data.ts} +41 -0
  245. package/types/editor.ts +95 -0
  246. package/types/event.ts +40 -0
  247. package/types/index.ts +7 -0
  248. package/types/plugin.ts +3 -0
  249. package/types/sidebar.ts +3 -0
  250. package/dist/src/comment/render-ctx.d.ts +0 -23
  251. package/dist/src/editor/edit-mode.d.ts +0 -9
  252. package/dist/src/editor/funcs.d.ts +0 -2
  253. package/dist/src/editor/index.d.ts +0 -2
  254. package/dist/src/editor/mover.d.ts +0 -8
  255. package/dist/src/editor/plug-manager.d.ts +0 -17
  256. package/dist/src/editor/plugs/editor-plug.d.ts +0 -38
  257. package/dist/src/editor/plugs/header-input-plug.d.ts +0 -13
  258. package/dist/src/editor/plugs/preview-plug.d.ts +0 -10
  259. package/dist/src/editor/plugs/upload-plug.d.ts +0 -10
  260. package/dist/src/editor/reply.d.ts +0 -9
  261. package/dist/src/editor/submit.d.ts +0 -16
  262. package/dist/src/lib/dark-mode.d.ts +0 -4
  263. package/dist/src/lib/stat.d.ts +0 -15
  264. package/dist/src/list/index.d.ts +0 -2
  265. package/dist/src/list/list-lite.d.ts +0 -77
  266. package/dist/src/list/list-ui.d.ts +0 -16
  267. package/dist/src/list/paginator/adaptors/index.d.ts +0 -12
  268. package/dist/src/list/paginator/adaptors/pagination.d.ts +0 -9
  269. package/dist/src/list/paginator/adaptors/read-more.d.ts +0 -10
  270. package/dist/src/list/paginator/holder.d.ts +0 -16
  271. package/dist/types/artalk-config.d.ts +0 -139
  272. package/dist/types/artalk-data.d.ts +0 -230
  273. package/dist/types/plug.d.ts +0 -4
  274. package/src/api/api-base.ts +0 -27
  275. package/src/comment/render-ctx.ts +0 -30
  276. package/src/editor/edit-mode.ts +0 -105
  277. package/src/editor/funcs.ts +0 -150
  278. package/src/editor/index.ts +0 -3
  279. package/src/editor/mover.ts +0 -43
  280. package/src/editor/plug-manager.ts +0 -172
  281. package/src/editor/plugs/editor-plug.ts +0 -69
  282. package/src/editor/plugs/header-input-plug.ts +0 -79
  283. package/src/editor/plugs/preview-plug.ts +0 -44
  284. package/src/editor/plugs/upload-plug.ts +0 -122
  285. package/src/editor/reply.ts +0 -62
  286. package/src/editor/submit.ts +0 -99
  287. package/src/lib/dark-mode.ts +0 -48
  288. package/src/lib/stat.ts +0 -71
  289. package/src/list/index.ts +0 -3
  290. package/src/list/list-lite.ts +0 -424
  291. package/src/list/list-ui.ts +0 -137
  292. package/src/list/paginator/adaptors/index.ts +0 -21
  293. package/src/list/paginator/adaptors/pagination.ts +0 -42
  294. package/src/list/paginator/adaptors/read-more.ts +0 -56
  295. package/src/list/paginator/holder.ts +0 -56
  296. package/types/context.d.ts +0 -142
  297. package/types/event.d.ts +0 -28
  298. package/types/plug.d.ts +0 -4
  299. /package/src/{editor/plugs/emoticons-plug.scss → plugins/editor/emoticons.scss} +0 -0
  300. /package/src/{editor/plugs/preview-plug.scss → plugins/editor/preview.scss} +0 -0
@@ -1,424 +0,0 @@
1
- import { ListData, CommentData, NotifyData } from '~/types/artalk-data'
2
- import Context from '~/types/context'
3
- import Component from '../lib/component'
4
- import * as Utils from '../lib/utils'
5
- import * as Ui from '../lib/ui'
6
- import Comment from '../comment'
7
- import PgHolder, { TPgMode } from './paginator'
8
- import * as ListNest from './list-nest'
9
- import * as ListUi from './list-ui'
10
- import { version as ARTALK_VERSION } from '../../package.json'
11
- import { handleBackendRefConf } from '../config'
12
-
13
- export default class ListLite extends Component {
14
- /** 列表评论集区域元素 */
15
- protected $commentsWrap: HTMLElement
16
-
17
- /** 最后一次请求得到的列表数据 */
18
- protected data?: ListData
19
-
20
- /** 是否处于加载中状态 */
21
- protected isLoading: boolean = false
22
-
23
- /** 配置是否已加载 */
24
- private confLoaded = false
25
-
26
- /** 无评论显示文字 */
27
- public noCommentText?: string
28
-
29
- /** 嵌套模式下的排序方式 */
30
- private _nestSortBy?: ListNest.SortByType
31
- public get nestSortBy() {
32
- return this._nestSortBy || this.ctx.conf.nestSort || 'DATE_ASC'
33
- }
34
- public set nestSortBy(val: ListNest.SortByType) {
35
- this._nestSortBy = val
36
- }
37
-
38
- /** 平铺模式 */
39
- private _flatMode?:boolean
40
- public get flatMode() {
41
- if (this._flatMode !== undefined)
42
- return this._flatMode
43
-
44
- // 配置开启平铺模式
45
- if (this.ctx.conf.flatMode === true || Number(this.ctx.conf.nestMax) <= 1)
46
- return true
47
-
48
- // 自动判断启用平铺模式
49
- if (this.ctx.conf.flatMode === 'auto' && window.matchMedia("(max-width: 768px)").matches)
50
- return true
51
-
52
- return false
53
- }
54
- public set flatMode(val: boolean) {
55
- this._flatMode = val
56
- }
57
-
58
- /** 分页方式 */
59
- public _pageMode?: TPgMode
60
- public get pageMode() {
61
- return this._pageMode || (this.conf.pagination.readMore ? 'read-more' : 'pagination')
62
- }
63
- public set pageMode(val: 'pagination'|'read-more') {
64
- this._pageMode = val
65
- this.pgHolder?.setMode(this._pageMode)
66
- }
67
-
68
- /** 分页方式持有者 */
69
- public pgHolder?: PgHolder
70
-
71
- /** 每页数量 (每次请求获取量) */
72
- private _pageSize?: number
73
- public get pageSize() {
74
- return this._pageSize || this.conf.pagination.pageSize
75
- }
76
- public set pageSize(val: number) {
77
- this._pageSize = val
78
- }
79
-
80
- /** 监听指定元素上的滚动 */
81
- public scrollListenerAt?: HTMLElement
82
- /** 翻页归位到指定元素 */
83
- public repositionAt?: HTMLElement
84
-
85
- // 一些 Hook 函数
86
- public renderComment?: (comment: Comment) => void
87
- public paramsEditor?: (params: any) => void
88
- public onAfterLoad?: (data: ListData) => void
89
-
90
- /** 未读标记 */
91
- protected unread: NotifyData[] = []
92
- public unreadHighlight?: boolean // 高亮未读
93
-
94
- constructor (ctx: Context) {
95
- super(ctx)
96
-
97
- // 初始化元素
98
- this.$el = Utils.createElement(
99
- `<div class="atk-list-lite">
100
- <div class="atk-list-comments-wrap"></div>
101
- </div>`)
102
- this.$commentsWrap = this.$el.querySelector('.atk-list-comments-wrap')!
103
-
104
- // 评论时间自动更新
105
- window.setInterval(() => {
106
- this.$el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
107
- const date = el.getAttribute('data-atk-comment-date')
108
- el.innerText = Utils.timeAgo(new Date(Number(date)), this.ctx)
109
- })
110
- }, 30 * 1000) // 30s 更新一次
111
-
112
- // 事件监听
113
- this.ctx.on('conf-loaded', () => {
114
- })
115
- }
116
-
117
- public getData() {
118
- return this.data
119
- }
120
-
121
- public clearData() {
122
- this.data = undefined
123
- }
124
-
125
- public getLoading() {
126
- return this.isLoading
127
- }
128
-
129
- public getCommentsWrapEl() {
130
- return this.$commentsWrap
131
- }
132
-
133
- /** 设置加载状态 */
134
- public setLoading(val: boolean, isFirstLoad: boolean = false) {
135
- this.isLoading = val
136
- if (isFirstLoad) {
137
- Ui.setLoading(val, this.$el)
138
- return
139
- }
140
-
141
- this.pgHolder?.setLoading(val)
142
- }
143
-
144
- /** 评论获取 */
145
- public async fetchComments(offset: number) {
146
- if (this.isLoading) return
147
-
148
- const isFirstLoad = (offset === 0)
149
- const setLoading = (val: boolean) => this.setLoading(val, isFirstLoad)
150
-
151
- // 加载动画
152
- setLoading(true)
153
-
154
- // 事件通知(开始加载评论)
155
- this.ctx.trigger('list-load')
156
-
157
- // 清空评论(按钮加载更多的第一页、每次加载分页页面)
158
- if ((this.pageMode === 'read-more' && isFirstLoad) || this.pageMode === 'pagination') {
159
- this.ctx.clearAllComments()
160
- }
161
-
162
- // 请求评论数据
163
- let listData: ListData
164
- try {
165
- // 执行请求
166
- listData = await this.ctx.getApi().comment
167
- .get(offset, this.pageSize, this.flatMode, this.paramsEditor)
168
- } catch (e: any) {
169
- this.onError(e.msg || String(e), offset, e.data)
170
- throw e
171
- } finally {
172
- setLoading(false)
173
- }
174
-
175
- // 清除原有错误
176
- Ui.setError(this.$el, null)
177
-
178
- // 装载数据
179
- try {
180
- this.onLoad(listData, offset)
181
- } catch (e: any) {
182
- this.onError(String(e), offset)
183
- throw e
184
- } finally {
185
- setLoading(false)
186
- }
187
- }
188
-
189
- protected onLoad(data: ListData, offset: number) {
190
- this.data = data
191
-
192
- // 装载后端提供的配置
193
- if (!this.confLoaded) {
194
- // 仅应用一次配置
195
- const backendRefConf = handleBackendRefConf(data.conf.frontend_conf)
196
- if (this.conf.useBackendConf) this.ctx.updateConf(backendRefConf)
197
- else this.ctx.updateConf({}) // 让事件监听 `on('conf-loaded')` 有效,与前者保持相同生命周期环节
198
- this.confLoaded = true
199
- }
200
-
201
- // 前后端版本一致性检测
202
- if (this.ctx.conf.versionCheck && ListUi.versionCheckDialog(this, ARTALK_VERSION, data.api_version.version)) return
203
-
204
- // 导入数据
205
- this.importComments(data.comments)
206
-
207
- // 分页功能
208
- this.refreshPagination(offset, (this.flatMode ? data.total : data.total_roots))
209
-
210
- // 加载后事件
211
- this.refreshUI()
212
-
213
- // 未读消息提示功能
214
- this.ctx.updateNotifies(data.unread || [])
215
-
216
- // 事件触发,列表已加载
217
- this.ctx.trigger('list-loaded')
218
-
219
- // Hook 函数调用
220
- if (this.onAfterLoad) this.onAfterLoad(data)
221
- }
222
-
223
- /** 分页模式 */
224
- private refreshPagination(offset: number, total: number) {
225
- // 初始化
226
- if (!this.pgHolder) {
227
- this.pgHolder = new PgHolder({
228
- list: this,
229
- mode: this.pageMode,
230
- pageSize: this.pageSize,
231
- total
232
- })
233
- }
234
-
235
- // 更新
236
- this.pgHolder?.update(offset, total)
237
- }
238
-
239
- /** 错误处理 */
240
- protected onError(msg: any, offset: number, errData?: any) {
241
- if (!this.confLoaded) {
242
- this.ctx.updateConf({})
243
- }
244
-
245
- msg = String(msg)
246
- console.error(msg)
247
-
248
- // 加载更多按钮显示错误
249
- if (offset !== 0 && this.pageMode === 'read-more') {
250
- this.pgHolder?.showErr(this.$t('loadFail'))
251
- return
252
- }
253
-
254
- // 显示错误对话框
255
- Ui.setError(this.$el, ListUi.renderErrorDialog(this, msg, errData))
256
- }
257
-
258
- /** 刷新界面 */
259
- public refreshUI() {
260
- ListUi.refreshUI(this)
261
- }
262
-
263
- /** 重新加载列表 */
264
- public reload() {
265
- this.fetchComments(0)
266
- }
267
-
268
- /** 创建新评论 */
269
- protected createComment(cData: CommentData, ctxData?: CommentData[]) {
270
- if (!ctxData) ctxData = this.ctx.getCommentDataList()
271
-
272
- const comment = new Comment(this.ctx, cData, {
273
- isFlatMode: this.flatMode,
274
- afterRender: () => {
275
- if (this.renderComment) this.renderComment(comment)
276
- },
277
- onDelete: (c: Comment) => {
278
- this.ctx.deleteComment(c)
279
- this.refreshUI()
280
- },
281
- replyTo: (cData.rid ? ctxData.find(c => c.id === cData.rid) : undefined)
282
- })
283
-
284
- // 渲染元素
285
- comment.render()
286
-
287
- // 放入 comment 总表中
288
- this.ctx.getCommentList().push(comment)
289
-
290
- return comment
291
- }
292
-
293
- /** 导入评论 · 通过请求数据 */
294
- public importComments(srcData: CommentData[]) {
295
- if (this.flatMode) {
296
- srcData.forEach((commentData: CommentData) => {
297
- this.putCommentFlatMode(commentData, srcData, 'append')
298
- })
299
- } else {
300
- this.importCommentsNest(srcData)
301
- }
302
- }
303
-
304
- // 导入评论 · 嵌套模式
305
- private importCommentsNest(srcData: CommentData[]) {
306
- // 遍历 root 评论
307
- const rootNodes = ListNest.makeNestCommentNodeList(srcData, this.nestSortBy, this.conf.nestMax)
308
- rootNodes.forEach((rootNode: ListNest.CommentNode) => {
309
- const rootC = this.createComment(rootNode.comment, srcData)
310
-
311
- // 显示并播放渐入动画
312
- this.$commentsWrap.appendChild(rootC.getEl())
313
- rootC.getRender().playFadeAnim()
314
-
315
- // 加载子评论
316
- const that = this
317
- ;(function loadChildren(parentC: Comment, parentNode: ListNest.CommentNode) {
318
- parentNode.children.forEach((node: ListNest.CommentNode) => {
319
- const childD = node.comment
320
- const childC = that.createComment(childD, srcData)
321
-
322
- // 插入到父评论中
323
- parentC.putChild(childC)
324
-
325
- // 递归加载子评论
326
- loadChildren(childC, node)
327
- })
328
- })(rootC, rootNode)
329
-
330
- // 限高检测
331
- rootC.getRender().checkHeightLimit()
332
- })
333
- }
334
-
335
- /** 导入评论 · 平铺模式 */
336
- private putCommentFlatMode(cData: CommentData, ctxData: CommentData[], insertMode: 'append'|'prepend') {
337
- if (cData.is_collapsed) cData.is_allow_reply = false
338
- const comment = this.createComment(cData, ctxData)
339
-
340
- // 可见评论添加到界面
341
- // 注:不可见评论用于显示 “引用内容”
342
- if (cData.visible) {
343
- if (insertMode === 'append') this.$commentsWrap.append(comment.getEl())
344
- if (insertMode === 'prepend') this.$commentsWrap.prepend(comment.getEl())
345
- comment.getRender().playFadeAnim()
346
- }
347
-
348
- // 平铺评论插入后 · 内容限高检测
349
- comment.getRender().checkHeightLimit()
350
-
351
- return comment
352
- }
353
-
354
- /** 新增评论 · 首部添加 */
355
- public insertComment(commentData: CommentData) {
356
- if (!this.flatMode) {
357
- // 嵌套模式
358
- const comment = this.createComment(commentData)
359
-
360
- if (commentData.rid === 0) {
361
- // root评论 新增
362
- this.$commentsWrap.prepend(comment.getEl())
363
- } else {
364
- // 子评论 新增
365
- const parent = this.ctx.findComment(commentData.rid)
366
- if (parent) {
367
- parent.putChild(comment, (this.nestSortBy === 'DATE_ASC' ? 'append' : 'prepend'))
368
-
369
- // 若父评论存在 “子评论部分” 限高,取消限高
370
- comment.getParents().forEach((p) => {
371
- p.getRender().heightLimitRemoveForChildren()
372
- })
373
- }
374
- }
375
-
376
- comment.getRender().checkHeightLimit()
377
-
378
- Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
379
- comment.getRender().playFadeAnim() // 播放评论渐出动画
380
- } else {
381
- // 平铺模式
382
- const comment = this.putCommentFlatMode(commentData, this.ctx.getCommentDataList(), 'prepend')
383
- Ui.scrollIntoView(comment.getEl()) // 滚动到可见
384
- }
385
-
386
- // 评论数增加 1
387
- if (this.data) this.data.total += 1
388
-
389
- // 评论新增后
390
- this.refreshUI()
391
- this.ctx.trigger('list-loaded')
392
- this.ctx.trigger('list-inserted', commentData)
393
- }
394
-
395
- /** 更新评论 */
396
- public updateComment(commentData: CommentData) {
397
- const comment = this.ctx.findComment(commentData.id)
398
- if (comment) {
399
- comment.setData(commentData)
400
- }
401
- }
402
-
403
- /** 更新未读数据 */
404
- public updateUnread(notifies: NotifyData[]) {
405
- this.unread = notifies
406
-
407
- // 高亮评论
408
- if (this.unreadHighlight === true) {
409
- this.ctx.getCommentList().forEach((comment) => {
410
- const notify = this.unread.find(o => o.comment_id === comment.getID())
411
- if (notify) {
412
- comment.getRender().setUnread(true)
413
- comment.getRender().setOpenAction(() => {
414
- window.open(notify.read_link)
415
- this.unread = this.unread.filter(o => o.comment_id !== comment.getID()) // remove
416
- this.ctx.updateNotifies(this.unread)
417
- })
418
- } else {
419
- comment.getRender().setUnread(false)
420
- }
421
- })
422
- }
423
- }
424
- }
@@ -1,137 +0,0 @@
1
- import ListLite from './list-lite'
2
- import * as Utils from '../lib/utils'
3
- import * as Ui from '../lib/ui'
4
- import User from '../lib/user'
5
- import $t from '../i18n'
6
-
7
- /** 界面刷新 */
8
- export function refreshUI(list: ListLite) {
9
- // 无评论
10
- const isNoComment = list.ctx.getCommentList().length <= 0
11
- let $noComment = list.getCommentsWrapEl().querySelector<HTMLElement>('.atk-list-no-comment')
12
-
13
- if (isNoComment) {
14
- if (!$noComment) {
15
- $noComment = Utils.createElement('<div class="atk-list-no-comment"></div>')
16
- $noComment.innerHTML = list.noCommentText || list.ctx.conf.noComment || list.ctx.$t('noComment')
17
- list.getCommentsWrapEl().appendChild($noComment)
18
- }
19
- } else {
20
- $noComment?.remove()
21
- }
22
-
23
- // 仅管理员显示控制
24
- list.ctx.checkAdminShowEl()
25
- }
26
-
27
- /** 构建错误提示界面 */
28
- export function renderErrorDialog(list: ListLite, errMsg: string, errData?: any): HTMLElement {
29
- const errEl = Utils.createElement(`<span>${errMsg},${$t('listLoadFailMsg')}<br/></span>`)
30
-
31
- const $retryBtn = Utils.createElement(`<span style="cursor:pointer;">${$t('listRetry')}</span>`)
32
- $retryBtn.onclick = () => (list.fetchComments(0))
33
- errEl.appendChild($retryBtn)
34
-
35
- const adminBtn = Utils.createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>')
36
- errEl.appendChild(adminBtn)
37
- if (!User.data.isAdmin) adminBtn.classList.add('atk-hide')
38
-
39
- let sidebarView = ''
40
-
41
- // 找不到站点错误,打开侧边栏并填入创建站点表单
42
- if (errData?.err_no_site) {
43
- const viewLoadParam = {
44
- create_name: list.ctx.conf.site,
45
- create_urls: `${window.location.protocol}//${window.location.host}`
46
- }
47
- sidebarView = `sites|${JSON.stringify(viewLoadParam)}`
48
- }
49
-
50
- adminBtn.onclick = () => list.ctx.showSidebar({
51
- view: sidebarView as any
52
- })
53
-
54
- return errEl
55
- }
56
-
57
- /** 版本检测弹窗 */
58
- export function versionCheckDialog(list: ListLite, feVer: string, beVer: string): boolean {
59
- const comp = Utils.versionCompare(feVer, beVer)
60
- const notSameVer = (comp !== 0)
61
- if (notSameVer) {
62
- const errEl = Utils.createElement(
63
- `<div>请更新 Artalk ${comp < 0 ? $t('frontend') : $t('backend')}以获得完整体验 ` +
64
- `(<a href="https://artalk.js.org/" target="_blank">帮助文档</a>)` +
65
- `<br/><br/><span style="color: var(--at-color-meta);">` +
66
- `当前版本:${$t('frontend')} ${feVer} / ${$t('backend')} ${beVer}` +
67
- `</span><br/><br/></div>`)
68
- const ignoreBtn = Utils.createElement('<span style="cursor:pointer">忽略</span>')
69
- ignoreBtn.onclick = () => {
70
- Ui.setError(list.$el.parentElement!, null)
71
- list.ctx.conf.versionCheck = false
72
- list.fetchComments(0)
73
- }
74
- errEl.append(ignoreBtn)
75
- Ui.setError(list.$el.parentElement!, errEl, '<span class="atk-warn-title">Artalk Warn</span>')
76
- return true
77
- }
78
-
79
- return false
80
- }
81
-
82
- /** 评论排序方式选择下拉菜单 */
83
- export function renderDropdown(conf: {
84
- $dropdownWrap: HTMLElement,
85
- dropdownList: [string, () => void][]
86
- }) {
87
- const { $dropdownWrap, dropdownList } = conf
88
- if ($dropdownWrap.querySelector('.atk-dropdown')) return
89
-
90
- // 修改 class
91
- $dropdownWrap.classList.add('atk-dropdown-wrap')
92
-
93
- // 插入图标
94
- $dropdownWrap.append(Utils.createElement(`<span class="atk-arrow-down-icon"></span>`))
95
-
96
- // 列表项点击事件
97
- let curtActive = 0 // 当前选中
98
- const onItemClick = (i: number, $item: HTMLElement, name: string, action: Function) => {
99
- action()
100
-
101
- // set active
102
- curtActive = i
103
- $dropdown.querySelectorAll('.active').forEach((e) => { e.classList.remove('active') })
104
- $item.classList.add('active')
105
-
106
- // 关闭层 (临时消失,取消 :hover)
107
- $dropdown.style.display = 'none'
108
- setTimeout(() => { $dropdown.style.display = '' }, 80)
109
- }
110
-
111
- // 生成列表元素
112
- const $dropdown = Utils.createElement(`<ul class="atk-dropdown atk-fade-in"></ul>`)
113
- dropdownList.forEach((item, i) => {
114
- const name = item[0] as string
115
- const action = item[1] as Function
116
-
117
- const $item = Utils.createElement(`<li class="atk-dropdown-item"><span></span></li>`)
118
- const $link = $item.querySelector<HTMLElement>('span')!
119
- $link.innerText = name
120
- $link.onclick = () => { onItemClick(i, $item, name, action) }
121
- $dropdown.append($item)
122
-
123
- if (i === curtActive) $item.classList.add('active') // 默认选中项
124
- })
125
-
126
- $dropdownWrap.append($dropdown)
127
- }
128
-
129
- /** 删除评论排序方式选择下拉菜单 */
130
- export function removeDropdown(conf: {
131
- $dropdownWrap: HTMLElement
132
- }) {
133
- const { $dropdownWrap } = conf
134
- $dropdownWrap.classList.remove('atk-dropdown-wrap')
135
- $dropdownWrap.querySelector('.atk-arrow-down-icon')?.remove()
136
- $dropdownWrap.querySelector('.atk-dropdown')?.remove()
137
- }
@@ -1,21 +0,0 @@
1
- import { IPgHolderConf, TPgMode } from '../index'
2
- import PaginationAdaptor from './pagination'
3
- import ReadMoreAdaptor from './read-more'
4
-
5
- // 分页方式适配器
6
- const Adaptors: Record<TPgMode, IPgAdaptor<any>> = {
7
- 'pagination': PaginationAdaptor,
8
- 'read-more': ReadMoreAdaptor
9
- }
10
-
11
- export default Adaptors
12
-
13
- export interface IPgAdaptor<T> {
14
- instance: T
15
- el: HTMLElement
16
- createInstance(conf: IPgHolderConf): [T, HTMLElement]
17
- setLoading(val: boolean): void
18
- update(offset: number, total: number): void
19
- next(): void
20
- showErr?(msg: string): void
21
- }
@@ -1,42 +0,0 @@
1
- import Pagination from '@/components/pagination'
2
- import * as Utils from '@/lib/utils'
3
- import { IPgAdaptor } from '.'
4
-
5
- interface IPaginationAdaptor extends IPgAdaptor<Pagination> {}
6
-
7
- /**
8
- * 翻页形式的分页
9
- */
10
- export default <IPaginationAdaptor>{
11
- createInstance(conf) {
12
- const instance = new Pagination(conf.total, {
13
- pageSize: conf.pageSize,
14
- onChange: async (o) => {
15
- if (conf.list.conf.editorTravel === true)
16
- conf.list.ctx.editorTravelBack() // 防止评论框被吞
17
-
18
- await conf.list.fetchComments(o)
19
-
20
- // 滚动到第一个评论的位置
21
- if (conf.list.repositionAt) {
22
- const at = conf.list.scrollListenerAt || window
23
- at.scroll({
24
- top: conf.list.repositionAt ? Utils.getOffset(conf.list.repositionAt).top : 0,
25
- left: 0,
26
- })
27
- }
28
- }
29
- })
30
-
31
- return [instance, instance.$el]
32
- },
33
- setLoading(val) {
34
- this.instance.setLoading(val)
35
- },
36
- update(offset, total) {
37
- this.instance.update(offset, total)
38
- },
39
- next() {
40
- this.instance.next()
41
- }
42
- }
@@ -1,56 +0,0 @@
1
- import ReadMoreBtn from '@/components/read-more-btn'
2
- import $t from '@/i18n'
3
- import * as Ui from '@/lib/ui'
4
- import { IPgAdaptor } from '.'
5
-
6
- interface IReadMoreAdaptor extends IPgAdaptor<ReadMoreBtn> {
7
- autoLoadScrollEvent?: () => void
8
- }
9
-
10
- /**
11
- * 阅读更多形式的分页
12
- */
13
- export default <IReadMoreAdaptor>{
14
- createInstance(conf) {
15
- const readMoreBtn = new ReadMoreBtn({
16
- pageSize: conf.pageSize,
17
- onClick: async (o) => {
18
- await conf.list.fetchComments(o)
19
- },
20
- text: $t('loadMore'),
21
- })
22
-
23
- // 滚动到底部自动加载
24
- if (conf.list.conf.pagination.autoLoad) {
25
- // 添加滚动事件监听
26
- const at = conf.list.scrollListenerAt || document
27
- if (this.autoLoadScrollEvent) at.removeEventListener('scroll', this.autoLoadScrollEvent) // 解除原有
28
- this.autoLoadScrollEvent = () => {
29
- if (conf.mode !== 'read-more'
30
- || !readMoreBtn?.hasMore
31
- || conf.list.getLoading()
32
- ) return
33
-
34
- const $target = conf.list.$el.querySelector<HTMLElement>('.atk-list-comments-wrap > .atk-comment-wrap:nth-last-child(3)') // 获取倒数第3个评论元素
35
- if ($target && Ui.isVisible($target, conf.list.scrollListenerAt)) {
36
- readMoreBtn.click() // 自动点击加载更多按钮
37
- }
38
- }
39
- at.addEventListener('scroll', this.autoLoadScrollEvent)
40
- }
41
-
42
- return [readMoreBtn, readMoreBtn.$el]
43
- },
44
- setLoading(val) {
45
- this.instance.setLoading(val)
46
- },
47
- update(offset, total) {
48
- this.instance.update(offset, total)
49
- },
50
- showErr(msg) {
51
- this.instance.showErr(msg)
52
- },
53
- next() {
54
- this.instance.click()
55
- }
56
- }