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.
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +3895 -3106
- package/dist/Artalk.iife.js +1 -266
- package/dist/Artalk.js +1 -266
- package/package.json +19 -21
- package/src/api/index.ts +6 -7
- package/src/artalk.ts +11 -4
- package/src/components/action-btn.ts +1 -1
- package/src/components/comment.ts +102 -27
- package/src/components/editor-plugs/_example-plug.ts.txt +2 -7
- package/src/components/editor-plugs/editor-plug.ts +3 -3
- package/src/components/editor-plugs/emoticons-plug.less +21 -11
- package/src/components/editor-plugs/emoticons-plug.ts +199 -79
- package/src/components/editor-plugs/preview-plug.less +1 -1
- package/src/components/editor-plugs/preview-plug.ts +2 -7
- package/src/components/editor.ts +75 -34
- package/src/components/html/comment.html +6 -13
- package/src/components/html/editor.html +9 -10
- package/src/components/html/list.html +1 -1
- package/src/components/layer.ts +33 -14
- package/src/components/list-lite.ts +218 -235
- package/src/components/list.ts +11 -9
- package/src/components/pagination.ts +2 -2
- package/src/components/read-more-btn.ts +27 -10
- package/src/components/sidebar-views/comments-view.ts +12 -5
- package/src/components/sidebar-views/sites-view.ts +0 -6
- package/src/components/sidebar.ts +7 -2
- package/src/{default-conf.ts → defaults.ts} +7 -7
- package/src/lib/utils.ts +41 -12
- package/src/style/_color.less +19 -23
- package/src/style/_extend.less +3 -3
- package/src/style/_variables.less +0 -24
- package/src/style/comment.less +191 -197
- package/src/style/editor.less +78 -103
- package/src/style/item-text-editor.less +2 -2
- package/src/style/list.less +14 -13
- package/src/style/main.less +35 -31
- package/src/style/page-list.less +4 -4
- package/src/style/pagination.less +6 -6
- package/src/style/sidebar.less +35 -35
- package/src/style/site-list.less +13 -13
- package/types/artalk-config.d.ts +13 -10
- package/types/artalk-data.d.ts +10 -5
- package/types/event.d.ts +10 -1
- 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
|
-
|
|
12
|
+
protected $commentsWrap: HTMLElement
|
|
13
|
+
protected comments: Comment[] = []
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
protected data?: ListData
|
|
16
|
+
protected isLoading: boolean = false
|
|
16
17
|
|
|
17
|
-
public
|
|
18
|
-
private pageSize: number = 15 // 每次请求获取量
|
|
19
|
-
private offset: number = 0
|
|
20
|
-
public type?: 'all'|'mentions'|'mine'|'pending'
|
|
18
|
+
public noCommentText = '无内容' // 无评论时显示
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
public
|
|
24
|
-
public paramsEditor?: (params: any) => void
|
|
25
|
-
public onAfterLoad?: (data: ListData) => void
|
|
20
|
+
/** 平铺模式 */
|
|
21
|
+
public flatMode = false
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
public
|
|
23
|
+
/** 分页 */
|
|
24
|
+
public pageMode: 'pagination'|'read-more' = 'pagination'
|
|
25
|
+
public pageSize: number = 20 // 每次请求获取量
|
|
26
|
+
public scrollListenerAt?: HTMLElement // 监听指定元素上的滚动
|
|
27
|
+
public repositionAt?: HTMLElement // 翻页归位到指定元素
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
protected pagination?: Pagination // 分页条
|
|
30
|
+
protected readMoreBtn?: ReadMoreBtn // 阅读更多
|
|
31
|
+
protected autoLoadScrollEvent?: any // 自动加载滚动事件
|
|
31
32
|
|
|
32
|
-
public
|
|
33
|
-
public
|
|
34
|
-
public
|
|
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
|
-
|
|
39
|
-
|
|
37
|
+
// 未读标记
|
|
38
|
+
protected unread: NotifyData[] = []
|
|
39
|
+
public unreadHighlight?: boolean // 高亮未读
|
|
40
40
|
|
|
41
|
-
constructor (ctx: Context
|
|
41
|
+
constructor (ctx: Context) {
|
|
42
42
|
super(ctx)
|
|
43
43
|
|
|
44
|
-
|
|
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
|
-
|
|
68
|
-
|
|
63
|
+
/** 评论获取 */
|
|
64
|
+
public async fetchComments(offset: number) {
|
|
65
|
+
if (this.isLoading) return
|
|
69
66
|
|
|
70
|
-
//
|
|
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.
|
|
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
|
-
//
|
|
98
|
-
|
|
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
|
-
|
|
121
|
-
|
|
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
|
-
//
|
|
131
|
-
|
|
132
|
-
this.onLoadInit()
|
|
133
|
-
}
|
|
125
|
+
// 分页方式
|
|
126
|
+
this.refreshPagination(offset, (this.flatMode ? data.total : data.total_roots)) // 初始化
|
|
134
127
|
|
|
135
|
-
|
|
136
|
-
|
|
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.
|
|
134
|
+
if (this.onAfterLoad) this.onAfterLoad(data)
|
|
146
135
|
}
|
|
147
136
|
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
160
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
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 (
|
|
191
|
-
|
|
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
|
|
194
|
-
|
|
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:
|
|
201
|
+
top: this.repositionAt ? Utils.getOffset(this.repositionAt).top : 0,
|
|
201
202
|
left: 0,
|
|
202
203
|
})
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
})
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
this.pagination = pagination
|
|
207
|
+
|
|
208
|
+
this.$el.append(this.pagination.$el)
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
/** 错误处理 */
|
|
213
|
+
protected onError(msg: any, offset: number) {
|
|
213
214
|
msg = String(msg)
|
|
214
215
|
console.error(msg)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
|
240
|
-
let
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
this
|
|
246
|
-
|
|
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
|
-
|
|
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(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
294
|
+
|
|
295
|
+
// 递归加载子评论
|
|
296
|
+
loadChildren(childC)
|
|
284
297
|
})
|
|
285
298
|
}
|
|
286
299
|
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
|
|
296
|
-
|
|
306
|
+
// 显示并播放渐入动画
|
|
307
|
+
this.$commentsWrap.appendChild(rootC.getEl())
|
|
308
|
+
rootC.playFadeInAnim()
|
|
297
309
|
|
|
298
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
})
|
|
313
|
+
// 加载子评论
|
|
314
|
+
loadChildren(rootC)
|
|
310
315
|
|
|
311
|
-
|
|
312
|
-
|
|
316
|
+
// 限高检测
|
|
317
|
+
rootC.checkHeightLimit()
|
|
318
|
+
})
|
|
313
319
|
}
|
|
314
320
|
|
|
315
321
|
/** 导入评论 · 平铺模式 */
|
|
316
|
-
private putCommentFlatMode(
|
|
317
|
-
if (
|
|
318
|
-
const comment = this.createComment(
|
|
319
|
-
if (
|
|
320
|
-
const rComment =
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
if (insertMode === '
|
|
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
|
-
|
|
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
|
|
351
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
402
|
-
|
|
386
|
+
// 评论新增后
|
|
387
|
+
this.refreshUI()
|
|
388
|
+
this.ctx.trigger('comments-loaded')
|
|
403
389
|
}
|
|
404
390
|
|
|
405
391
|
/** 遍历操作 Comment (包括子评论) */
|
|
406
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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>')
|