artalk 2.0.4 → 2.1.1
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/README.md +7 -60
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +5996 -1
- package/dist/Artalk.iife.js +266 -1
- package/dist/Artalk.js +266 -1
- package/package.json +3 -4
- package/src/api/index.ts +269 -0
- package/src/api/request.ts +125 -0
- package/src/artalk.ts +153 -0
- package/src/components/_component.ts.txt +10 -0
- package/src/components/action-btn.ts +169 -0
- package/src/components/admin/page-list.ts +194 -0
- package/src/components/admin/site-list-floater.ts +98 -0
- package/src/components/admin/site-list.ts +289 -0
- package/src/components/comment.ts +478 -0
- package/src/components/dialog.ts +63 -0
- package/src/components/editor-plugs/{_ExamplePlug.ts.txt → _example-plug.ts.txt} +0 -0
- package/src/components/editor-plugs/{EditorPlug.ts → editor-plug.ts} +3 -3
- package/src/components/editor-plugs/{EmoticonsPlug.less → emoticons-plug.less} +0 -0
- package/src/components/editor-plugs/{EmoticonsPlug.ts → emoticons-plug.ts} +9 -9
- package/src/components/editor-plugs/{PreviewPlug.less → preview-plug.less} +0 -0
- package/src/components/editor-plugs/{PreviewPlug.ts → preview-plug.ts} +10 -10
- package/src/components/{Editor.ts → editor.ts} +104 -102
- package/src/components/html/comment.html +2 -6
- package/src/components/html/list.html +0 -1
- package/src/components/html/sidebar.html +18 -4
- package/src/components/item-text-editor.ts +136 -0
- package/src/components/layer.ts +135 -0
- package/src/components/list-lite.ts +507 -0
- package/src/components/list.ts +172 -0
- package/src/components/pagination.ts +150 -0
- package/src/components/read-more-btn.ts +71 -0
- package/src/components/sidebar-view.ts +26 -0
- package/src/components/sidebar-views/comments-view.ts +66 -0
- package/src/components/sidebar-views/pages-view.ts +61 -0
- package/src/components/sidebar-views/setting-view.ts +21 -0
- package/src/components/sidebar-views/sites-view.ts +42 -0
- package/src/components/sidebar-views/transfer-view.ts +218 -0
- package/src/components/sidebar.ts +288 -0
- package/src/context.ts +42 -0
- package/src/default-conf.ts +42 -0
- package/src/lib/checker/admin-checker.ts +33 -0
- package/src/lib/checker/captcha-checker.ts +38 -0
- package/src/lib/checker/index.ts +134 -0
- package/src/lib/component.ts +3 -3
- package/src/lib/md5.js +6 -0
- package/src/lib/ui.ts +64 -74
- package/src/lib/user.ts +2 -8
- package/src/lib/utils.ts +30 -11
- package/src/main.ts +1 -1
- package/src/style/_color.less +8 -2
- package/src/style/_extend.less +81 -0
- package/src/style/_variables.less +3 -0
- package/src/style/comment.less +60 -24
- package/src/style/editor.less +3 -0
- package/src/style/item-text-editor.less +35 -0
- package/src/style/list.less +51 -32
- package/src/style/main.less +75 -1
- package/src/style/page-list.less +50 -0
- package/src/style/pagination.less +58 -0
- package/src/style/sidebar.less +274 -199
- package/src/style/site-list.less +208 -0
- package/tsconfig.json +27 -0
- package/types/artalk-config.d.ts +68 -51
- package/types/artalk-data.d.ts +38 -1
- package/types/event.d.ts +73 -0
- package/types/index.d.ts +1 -6
- package/.github/workflows/npm.yml +0 -31
- package/.github/workflows/pages.yml +0 -30
- package/dist/src/Event.d.ts +0 -59
- package/dist/types/artalk-config.d.ts +0 -79
- package/dist/types/artalk-data.d.ts +0 -153
- package/dist/types/global.d.ts +0 -1
- package/dist/types/index.d.ts +0 -8
- package/dist/types/vite-env.d.ts +0 -1
- package/example/pjax/res1.html +0 -41
- package/example/pjax/res2.html +0 -41
- package/src/Artalk.ts +0 -160
- package/src/Constant.ts +0 -6
- package/src/Context.ts +0 -34
- package/src/Event.d.ts +0 -59
- package/src/components/Comment.ts +0 -402
- package/src/components/Layer.ts +0 -138
- package/src/components/List.ts +0 -162
- package/src/components/ListLite.ts +0 -407
- package/src/components/Sidebar.ts +0 -141
- package/src/components/sidebar-views/AdminView.ts +0 -523
- package/src/components/sidebar-views/MessageView.ts +0 -48
- package/src/components/sidebar-views/SidebarView.ts +0 -24
- package/src/lib/api.ts +0 -380
- package/src/lib/checker.ts +0 -164
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
import '../style/editor.less'
|
|
2
2
|
|
|
3
|
-
import Context from '../
|
|
3
|
+
import Context from '../context'
|
|
4
4
|
import Component from '../lib/component'
|
|
5
5
|
import * as Utils from '../lib/utils'
|
|
6
6
|
import * as Ui from '../lib/ui'
|
|
7
7
|
import EditorHTML from './html/editor.html?raw'
|
|
8
8
|
|
|
9
|
-
import EmoticonsPlug from './editor-plugs/
|
|
10
|
-
import PreviewPlug from './editor-plugs/
|
|
9
|
+
import EmoticonsPlug from './editor-plugs/emoticons-plug'
|
|
10
|
+
import PreviewPlug from './editor-plugs/preview-plug'
|
|
11
11
|
import { CommentData } from '~/types/artalk-data'
|
|
12
|
-
import Api from '../
|
|
12
|
+
import Api from '../api'
|
|
13
13
|
|
|
14
14
|
export default class Editor extends Component {
|
|
15
15
|
private readonly LOADABLE_PLUG_LIST = [EmoticonsPlug, PreviewPlug]
|
|
16
16
|
public plugList: { [name: string]: any } = {}
|
|
17
17
|
|
|
18
|
-
public
|
|
19
|
-
|
|
20
|
-
public
|
|
21
|
-
public
|
|
22
|
-
public
|
|
23
|
-
public
|
|
24
|
-
public
|
|
25
|
-
public
|
|
26
|
-
public
|
|
27
|
-
public
|
|
28
|
-
public
|
|
29
|
-
public submitBtn: HTMLButtonElement
|
|
30
|
-
public notifyWrapEl: HTMLElement
|
|
18
|
+
public $header: HTMLElement
|
|
19
|
+
public $textareaWrap: HTMLElement
|
|
20
|
+
public $textarea: HTMLTextAreaElement
|
|
21
|
+
public $closeComment: HTMLTextAreaElement
|
|
22
|
+
public $plugWrap: HTMLElement
|
|
23
|
+
public $bottom: HTMLElement
|
|
24
|
+
public $bottomPartLeft: HTMLElement
|
|
25
|
+
public $plugSwitcherWrap: HTMLElement
|
|
26
|
+
public $bottomPartRight: HTMLElement
|
|
27
|
+
public $submitBtn: HTMLButtonElement
|
|
28
|
+
public $notifyWrap: HTMLElement
|
|
31
29
|
|
|
32
30
|
private replyComment: CommentData|null = null
|
|
33
|
-
private
|
|
31
|
+
private $sendReply: HTMLElement|null = null
|
|
34
32
|
|
|
35
33
|
private get user () {
|
|
36
34
|
return this.ctx.user
|
|
@@ -39,19 +37,19 @@ export default class Editor extends Component {
|
|
|
39
37
|
constructor (ctx: Context) {
|
|
40
38
|
super(ctx)
|
|
41
39
|
|
|
42
|
-
this
|
|
40
|
+
this.$el = Utils.createElement(EditorHTML)
|
|
43
41
|
|
|
44
|
-
this
|
|
45
|
-
this
|
|
46
|
-
this
|
|
47
|
-
this
|
|
48
|
-
this
|
|
49
|
-
this
|
|
50
|
-
this
|
|
51
|
-
this
|
|
52
|
-
this
|
|
53
|
-
this
|
|
54
|
-
this
|
|
42
|
+
this.$header = this.$el.querySelector('.atk-editor-header')!
|
|
43
|
+
this.$textareaWrap = this.$el.querySelector('.atk-editor-textarea-wrap')!
|
|
44
|
+
this.$textarea = this.$el.querySelector('.atk-editor-textarea')!
|
|
45
|
+
this.$closeComment = this.$el.querySelector('.atk-close-comment')!
|
|
46
|
+
this.$plugWrap = this.$el.querySelector('.atk-editor-plug-wrap')!
|
|
47
|
+
this.$bottom = this.$el.querySelector('.atk-editor-bottom')!
|
|
48
|
+
this.$bottomPartLeft = this.$el.querySelector('.atk-editor-bottom-part.atk-left')!
|
|
49
|
+
this.$plugSwitcherWrap = this.$el.querySelector('.atk-editor-plug-switcher-wrap')!
|
|
50
|
+
this.$bottomPartRight = this.$el.querySelector('.atk-editor-bottom-part.atk-right')!
|
|
51
|
+
this.$submitBtn = this.$el.querySelector('.atk-send-btn')!
|
|
52
|
+
this.$notifyWrap = this.$el.querySelector('.atk-editor-notify-wrap')!
|
|
55
53
|
|
|
56
54
|
this.initLocalStorage()
|
|
57
55
|
this.initHeader()
|
|
@@ -60,12 +58,12 @@ export default class Editor extends Component {
|
|
|
60
58
|
this.initBottomPart()
|
|
61
59
|
|
|
62
60
|
// 监听事件
|
|
63
|
-
this.ctx.
|
|
64
|
-
this.ctx.
|
|
65
|
-
this.ctx.
|
|
66
|
-
this.ctx.
|
|
67
|
-
this.ctx.
|
|
68
|
-
this.ctx.
|
|
61
|
+
this.ctx.on('editor-open', () => (this.open()))
|
|
62
|
+
this.ctx.on('editor-close', () => (this.close()))
|
|
63
|
+
this.ctx.on('editor-reply', (commentData) => (this.setReply(commentData)))
|
|
64
|
+
this.ctx.on('editor-show-loading', () => (Ui.showLoading(this.$el)))
|
|
65
|
+
this.ctx.on('editor-hide-loading', () => (Ui.hideLoading(this.$el)))
|
|
66
|
+
this.ctx.on('editor-notify', (f) => (this.showNotify(f.msg, f.type)))
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
initLocalStorage () {
|
|
@@ -74,7 +72,7 @@ export default class Editor extends Component {
|
|
|
74
72
|
this.showNotify('已自动恢复', 'i')
|
|
75
73
|
this.setContent(localContent)
|
|
76
74
|
}
|
|
77
|
-
this.
|
|
75
|
+
this.$textarea.addEventListener('input', () => {
|
|
78
76
|
this.saveContent()
|
|
79
77
|
})
|
|
80
78
|
}
|
|
@@ -91,7 +89,7 @@ export default class Editor extends Component {
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
getInputEl (field: string) {
|
|
94
|
-
const inputEl = this.
|
|
92
|
+
const inputEl = this.$header.querySelector<HTMLInputElement>(`[name="${field}"]`)
|
|
95
93
|
return inputEl
|
|
96
94
|
}
|
|
97
95
|
|
|
@@ -127,7 +125,7 @@ export default class Editor extends Component {
|
|
|
127
125
|
}
|
|
128
126
|
|
|
129
127
|
// 未读消息更新
|
|
130
|
-
this.ctx.
|
|
128
|
+
this.ctx.trigger('unread-update', { notifies: data.unread, })
|
|
131
129
|
|
|
132
130
|
// 若用户为管理员,执行登陆操作
|
|
133
131
|
if (this.user.checkHasBasicUserInfo() && !data.is_login && data.user && data.user.is_admin) {
|
|
@@ -150,7 +148,7 @@ export default class Editor extends Component {
|
|
|
150
148
|
}
|
|
151
149
|
|
|
152
150
|
showLoginDialog () {
|
|
153
|
-
this.ctx.
|
|
151
|
+
this.ctx.trigger('checker-admin', {
|
|
154
152
|
onSuccess: () => {
|
|
155
153
|
}
|
|
156
154
|
})
|
|
@@ -158,7 +156,7 @@ export default class Editor extends Component {
|
|
|
158
156
|
|
|
159
157
|
saveUser () {
|
|
160
158
|
this.user.save()
|
|
161
|
-
this.ctx.
|
|
159
|
+
this.ctx.trigger('user-changed', this.ctx.user.data)
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
saveContent () {
|
|
@@ -167,10 +165,10 @@ export default class Editor extends Component {
|
|
|
167
165
|
|
|
168
166
|
initTextarea () {
|
|
169
167
|
// 占位符
|
|
170
|
-
this.
|
|
168
|
+
this.$textarea.placeholder = this.ctx.conf.placeholder || ''
|
|
171
169
|
|
|
172
170
|
// 修复按下 Tab 输入的内容
|
|
173
|
-
this.
|
|
171
|
+
this.$textarea.addEventListener('keydown', (e) => {
|
|
174
172
|
const keyCode = e.keyCode || e.which
|
|
175
173
|
|
|
176
174
|
if (keyCode === 9) {
|
|
@@ -180,25 +178,25 @@ export default class Editor extends Component {
|
|
|
180
178
|
})
|
|
181
179
|
|
|
182
180
|
// 输入框高度随内容而变化
|
|
183
|
-
this.
|
|
181
|
+
this.$textarea.addEventListener('input', (evt) => {
|
|
184
182
|
this.adjustTextareaHeight()
|
|
185
183
|
})
|
|
186
184
|
}
|
|
187
185
|
|
|
188
186
|
adjustTextareaHeight () {
|
|
189
|
-
const diff = this.
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
187
|
+
const diff = this.$textarea.offsetHeight - this.$textarea.clientHeight
|
|
188
|
+
this.$textarea.style.height = '0px' // it's a magic. 若不加此行,内容减少,高度回不去
|
|
189
|
+
this.$textarea.style.height = `${this.$textarea.scrollHeight + diff}px`
|
|
192
190
|
}
|
|
193
191
|
|
|
194
192
|
openedPlugName: string|null = null
|
|
195
193
|
|
|
196
194
|
initEditorPlug () {
|
|
197
195
|
this.plugList = {}
|
|
198
|
-
this.
|
|
199
|
-
this.
|
|
196
|
+
this.$plugWrap.innerHTML = ''
|
|
197
|
+
this.$plugWrap.style.display = 'none'
|
|
200
198
|
this.openedPlugName = null
|
|
201
|
-
this.
|
|
199
|
+
this.$plugSwitcherWrap.innerHTML = ''
|
|
202
200
|
|
|
203
201
|
// 依次实例化 plug
|
|
204
202
|
this.LOADABLE_PLUG_LIST.forEach((PlugObj) => {
|
|
@@ -207,27 +205,27 @@ export default class Editor extends Component {
|
|
|
207
205
|
|
|
208
206
|
// 切换按钮
|
|
209
207
|
const btnElem = Utils.createElement(`<span class="atk-editor-action atk-editor-plug-switcher">${plug.getBtnHtml()}</span>`)
|
|
210
|
-
this.
|
|
208
|
+
this.$plugSwitcherWrap.appendChild(btnElem)
|
|
211
209
|
btnElem.addEventListener('click', () => {
|
|
212
|
-
this.
|
|
210
|
+
this.$plugSwitcherWrap.querySelectorAll('.active').forEach(item => item.classList.remove('active'))
|
|
213
211
|
|
|
214
212
|
// 若点击已打开的,则收起
|
|
215
213
|
if (plug.getName() === this.openedPlugName) {
|
|
216
214
|
plug.onHide()
|
|
217
|
-
this.
|
|
215
|
+
this.$plugWrap.style.display = 'none'
|
|
218
216
|
this.openedPlugName = null
|
|
219
217
|
return
|
|
220
218
|
}
|
|
221
219
|
|
|
222
|
-
if (this.
|
|
220
|
+
if (this.$plugWrap.querySelector(`[data-plug-name="${plug.getName()}"]`) === null) {
|
|
223
221
|
// 需要初始化
|
|
224
222
|
const plugEl = plug.getEl()
|
|
225
223
|
plugEl.setAttribute('data-plug-name', plug.getName())
|
|
226
224
|
plugEl.style.display = 'none'
|
|
227
|
-
this.
|
|
225
|
+
this.$plugWrap.appendChild(plugEl)
|
|
228
226
|
}
|
|
229
227
|
|
|
230
|
-
(Array.from(this.
|
|
228
|
+
(Array.from(this.$plugWrap.children) as HTMLElement[]).forEach((plugItemEl: HTMLElement) => {
|
|
231
229
|
const plugItemName = plugItemEl.getAttribute('data-plug-name')!
|
|
232
230
|
if (plugItemName === plug.getName()) {
|
|
233
231
|
plugItemEl.style.display = ''
|
|
@@ -238,7 +236,7 @@ export default class Editor extends Component {
|
|
|
238
236
|
}
|
|
239
237
|
})
|
|
240
238
|
|
|
241
|
-
this.
|
|
239
|
+
this.$plugWrap.style.display = ''
|
|
242
240
|
this.openedPlugName = plug.getName()
|
|
243
241
|
|
|
244
242
|
btnElem.classList.add('active')
|
|
@@ -248,33 +246,33 @@ export default class Editor extends Component {
|
|
|
248
246
|
|
|
249
247
|
/** 关闭编辑器插件 */
|
|
250
248
|
closePlug () {
|
|
251
|
-
this.
|
|
252
|
-
this.
|
|
249
|
+
this.$plugWrap.innerHTML = ''
|
|
250
|
+
this.$plugWrap.style.display = 'none'
|
|
253
251
|
this.openedPlugName = null
|
|
254
252
|
}
|
|
255
253
|
|
|
256
254
|
insertContent (val: string) {
|
|
257
255
|
if ((document as any).selection) {
|
|
258
|
-
this.
|
|
256
|
+
this.$textarea.focus();
|
|
259
257
|
(document as any).selection.createRange().text = val
|
|
260
|
-
this.
|
|
261
|
-
} else if (this.
|
|
262
|
-
const sStart = this.
|
|
263
|
-
const sEnd = this.
|
|
264
|
-
const sT = this.
|
|
265
|
-
this.setContent(this.
|
|
266
|
-
this.
|
|
267
|
-
this.
|
|
268
|
-
this.
|
|
269
|
-
this.
|
|
258
|
+
this.$textarea.focus()
|
|
259
|
+
} else if (this.$textarea.selectionStart || this.$textarea.selectionStart === 0) {
|
|
260
|
+
const sStart = this.$textarea.selectionStart
|
|
261
|
+
const sEnd = this.$textarea.selectionEnd
|
|
262
|
+
const sT = this.$textarea.scrollTop
|
|
263
|
+
this.setContent(this.$textarea.value.substring(0, sStart) + val + this.$textarea.value.substring(sEnd, this.$textarea.value.length))
|
|
264
|
+
this.$textarea.focus()
|
|
265
|
+
this.$textarea.selectionStart = sStart + val.length
|
|
266
|
+
this.$textarea.selectionEnd = sStart + val.length
|
|
267
|
+
this.$textarea.scrollTop = sT
|
|
270
268
|
} else {
|
|
271
|
-
this.
|
|
272
|
-
this.
|
|
269
|
+
this.$textarea.focus()
|
|
270
|
+
this.$textarea.value += val
|
|
273
271
|
}
|
|
274
272
|
}
|
|
275
273
|
|
|
276
274
|
setContent (val: string) {
|
|
277
|
-
this.
|
|
275
|
+
this.$textarea.value = val
|
|
278
276
|
this.saveContent()
|
|
279
277
|
if (!!this.plugList && !!this.plugList.preview) {
|
|
280
278
|
this.plugList.preview.updateContent()
|
|
@@ -300,7 +298,7 @@ export default class Editor extends Component {
|
|
|
300
298
|
}
|
|
301
299
|
|
|
302
300
|
getContentOriginal () {
|
|
303
|
-
return this.
|
|
301
|
+
return this.$textarea.value || '' // Tip: !!"0" === true
|
|
304
302
|
}
|
|
305
303
|
|
|
306
304
|
getContentMarked () {
|
|
@@ -314,7 +312,7 @@ export default class Editor extends Component {
|
|
|
314
312
|
|
|
315
313
|
initReply () {
|
|
316
314
|
this.replyComment = null
|
|
317
|
-
this
|
|
315
|
+
this.$sendReply = null
|
|
318
316
|
}
|
|
319
317
|
|
|
320
318
|
setReply (commentData: CommentData) {
|
|
@@ -322,31 +320,31 @@ export default class Editor extends Component {
|
|
|
322
320
|
this.cancelReply()
|
|
323
321
|
}
|
|
324
322
|
|
|
325
|
-
if (this
|
|
326
|
-
this
|
|
327
|
-
this.
|
|
328
|
-
this.
|
|
323
|
+
if (this.$sendReply === null) {
|
|
324
|
+
this.$sendReply = Utils.createElement('<div class="atk-send-reply-wrap"><div class="atk-send-reply">回复 <span class="atk-text"></span><span class="atk-cancel" title="取消 AT">×</span></div></div>');
|
|
325
|
+
this.$sendReply.querySelector<HTMLElement>('.atk-text')!.innerText = `@${commentData.nick}`
|
|
326
|
+
this.$sendReply.addEventListener('click', () => {
|
|
329
327
|
this.cancelReply()
|
|
330
328
|
})
|
|
331
|
-
this.
|
|
329
|
+
this.$textareaWrap.prepend(this.$sendReply)
|
|
332
330
|
}
|
|
333
331
|
this.replyComment = commentData
|
|
334
|
-
Ui.scrollIntoView(this
|
|
335
|
-
this.
|
|
332
|
+
Ui.scrollIntoView(this.$el)
|
|
333
|
+
this.$textarea.focus()
|
|
336
334
|
}
|
|
337
335
|
|
|
338
336
|
cancelReply () {
|
|
339
|
-
if (this
|
|
340
|
-
this.
|
|
341
|
-
this
|
|
337
|
+
if (this.$sendReply !== null) {
|
|
338
|
+
this.$sendReply.remove()
|
|
339
|
+
this.$sendReply = null
|
|
342
340
|
}
|
|
343
341
|
this.replyComment = null
|
|
344
342
|
}
|
|
345
343
|
|
|
346
344
|
initSubmit () {
|
|
347
|
-
this
|
|
345
|
+
this.$submitBtn.innerText = this.ctx.conf.sendBtn || 'Send'
|
|
348
346
|
|
|
349
|
-
this
|
|
347
|
+
this.$submitBtn.addEventListener('click', (evt) => {
|
|
350
348
|
const btnEl = evt.currentTarget
|
|
351
349
|
this.submit()
|
|
352
350
|
})
|
|
@@ -354,11 +352,13 @@ export default class Editor extends Component {
|
|
|
354
352
|
|
|
355
353
|
async submit () {
|
|
356
354
|
if (this.getContent().trim() === '') {
|
|
357
|
-
this.
|
|
355
|
+
this.$textarea.focus()
|
|
358
356
|
return
|
|
359
357
|
}
|
|
360
358
|
|
|
361
|
-
|
|
359
|
+
this.ctx.trigger('editor-submit')
|
|
360
|
+
|
|
361
|
+
Ui.showLoading(this.$el)
|
|
362
362
|
|
|
363
363
|
try {
|
|
364
364
|
const nComment = await new Api(this.ctx).add({
|
|
@@ -369,39 +369,41 @@ export default class Editor extends Component {
|
|
|
369
369
|
rid: this.replyComment === null ? 0 : this.replyComment.id
|
|
370
370
|
})
|
|
371
371
|
|
|
372
|
-
this.ctx.
|
|
372
|
+
this.ctx.trigger('list-insert', nComment)
|
|
373
373
|
this.clearEditor() // 清空编辑器
|
|
374
|
+
this.ctx.trigger('editor-submitted')
|
|
374
375
|
} catch (err: any) {
|
|
376
|
+
console.error(err)
|
|
375
377
|
this.showNotify(`评论失败,${err.msg || String(err)}`, 'e')
|
|
376
378
|
} finally {
|
|
377
|
-
Ui.hideLoading(this
|
|
379
|
+
Ui.hideLoading(this.$el)
|
|
378
380
|
}
|
|
379
381
|
}
|
|
380
382
|
|
|
381
383
|
showNotify (msg: string, type) {
|
|
382
|
-
Ui.showNotify(this
|
|
384
|
+
Ui.showNotify(this.$notifyWrap, msg, type)
|
|
383
385
|
}
|
|
384
386
|
|
|
385
387
|
/** 关闭评论 */
|
|
386
|
-
|
|
387
|
-
this.
|
|
388
|
+
close () {
|
|
389
|
+
this.$closeComment.style.display = ''
|
|
388
390
|
|
|
389
391
|
if (!this.user.data.isAdmin) {
|
|
390
|
-
this.
|
|
392
|
+
this.$textarea.style.display = 'none'
|
|
391
393
|
this.closePlug()
|
|
392
|
-
this.
|
|
394
|
+
this.$bottom.style.display = 'none'
|
|
393
395
|
} else {
|
|
394
396
|
// 管理员一直打开评论
|
|
395
|
-
this.
|
|
396
|
-
this.
|
|
397
|
+
this.$textarea.style.display = ''
|
|
398
|
+
this.$bottom.style.display = ''
|
|
397
399
|
}
|
|
398
400
|
}
|
|
399
401
|
|
|
400
402
|
/** 打开评论 */
|
|
401
|
-
|
|
402
|
-
this.
|
|
403
|
-
this.
|
|
404
|
-
this.
|
|
403
|
+
open () {
|
|
404
|
+
this.$closeComment.style.display = 'none'
|
|
405
|
+
this.$textarea.style.display = ''
|
|
406
|
+
this.$bottom.style.display = ''
|
|
405
407
|
}
|
|
406
408
|
}
|
|
407
409
|
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
<div class="atk-comment-wrap" data-comment-id="">
|
|
2
2
|
<div class="atk-comment">
|
|
3
3
|
|
|
4
|
-
<div class="atk-avatar">
|
|
5
|
-
<a target="_blank"><img src=""></a>
|
|
6
|
-
</div>
|
|
4
|
+
<div class="atk-avatar"></div>
|
|
7
5
|
|
|
8
6
|
<div class="atk-comment-main">
|
|
9
7
|
|
|
10
8
|
<div class="atk-header">
|
|
11
|
-
<span class="atk-nick"
|
|
9
|
+
<span class="atk-nick"></span>
|
|
12
10
|
<span class="atk-badge"></span>
|
|
13
11
|
<span class="atk-date"></span>
|
|
14
|
-
<span class="atk-ua ua-browser"></span>
|
|
15
|
-
<span class="atk-ua ua-os"></span>
|
|
16
12
|
</div>
|
|
17
13
|
|
|
18
14
|
<div class="atk-body">
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
</div>
|
|
7
7
|
<div class="atk-right-action">
|
|
8
8
|
<span data-action="admin-close-comment" class="atk-hide" atk-only-admin-show>关闭评论</span>
|
|
9
|
-
<span data-action="open-admin-panel" class="atk-hide atk-on" atk-only-admin-show>控制台</span>
|
|
10
9
|
<span data-action="open-sidebar" class="atk-hide atk-on">
|
|
11
10
|
<span class="atk-unread-badge" style="display: none;"></span>
|
|
12
11
|
通知中心
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
<div class="atk-sidebar">
|
|
2
2
|
<div class="atk-sidebar-inner">
|
|
3
|
-
<div class="atk-sidebar-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
<div class="atk-sidebar-header">
|
|
4
|
+
<span class="atk-avatar">
|
|
5
|
+
<span class="atk-site-logo"></span>
|
|
6
|
+
</span>
|
|
7
|
+
<span class="atk-menu">
|
|
8
|
+
<span class="atk-item atk-active atk-sidebar-title">控制中心</span>
|
|
9
|
+
</span>
|
|
10
|
+
<div class="atk-sidebar-close"><i class="atk-icon atk-icon-close"></i></div>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="atk-sidebar-nav">
|
|
13
|
+
<div class="akt-curt-view-btn">
|
|
14
|
+
<div class="atk-icon"><span></span><span></span><span></span></div>
|
|
15
|
+
<div class="atk-text"></div>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="atk-tabs"></div>
|
|
18
|
+
<div class="atk-tabs atk-views" style="display: none;"></div>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="atk-sidebar-view-wrap"></div>
|
|
7
21
|
</div>
|
|
8
22
|
</div>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import '../style/item-text-editor.less'
|
|
2
|
+
|
|
3
|
+
import * as Utils from '../lib/utils'
|
|
4
|
+
|
|
5
|
+
interface ItemTextEditorConf {
|
|
6
|
+
initValue?: string
|
|
7
|
+
validator?: (value: string) => boolean
|
|
8
|
+
onYes?: (value: string) => boolean|void|Promise<boolean|void>
|
|
9
|
+
onNo?: () => boolean|void|Promise<boolean|void>
|
|
10
|
+
placeholder?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 通用列表项目文本编辑器
|
|
15
|
+
*/
|
|
16
|
+
export default class ItemTextEditor {
|
|
17
|
+
private conf: ItemTextEditorConf
|
|
18
|
+
public $el: HTMLElement
|
|
19
|
+
|
|
20
|
+
public $input: HTMLInputElement
|
|
21
|
+
public $yesBtn: HTMLElement
|
|
22
|
+
public $noBtn: HTMLElement
|
|
23
|
+
|
|
24
|
+
public value: string = ''
|
|
25
|
+
public allowSubmit = true
|
|
26
|
+
|
|
27
|
+
constructor(conf: ItemTextEditorConf) {
|
|
28
|
+
this.conf = conf
|
|
29
|
+
|
|
30
|
+
this.$el = Utils.createElement(
|
|
31
|
+
`<div class="atk-item-text-editor-layer">
|
|
32
|
+
<div class="atk-edit-form">
|
|
33
|
+
<input class="atk-main-input" type="text" placeholder="输入内容..." autocomplete="off" autofocus>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="atk-actions">
|
|
36
|
+
<div class="atk-item atk-yes-btn">
|
|
37
|
+
<i class="atk-icon atk-icon-yes"></i>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="atk-item atk-no-btn">
|
|
40
|
+
<i class="atk-icon atk-icon-no"></i>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>`)
|
|
44
|
+
|
|
45
|
+
this.$input = this.$el.querySelector('.atk-main-input')!
|
|
46
|
+
this.$yesBtn = this.$el.querySelector('.atk-yes-btn')!
|
|
47
|
+
this.$noBtn = this.$el.querySelector('.atk-no-btn')!
|
|
48
|
+
|
|
49
|
+
this.$input.value = conf.initValue || ''
|
|
50
|
+
this.value = conf.initValue || ''
|
|
51
|
+
if (this.conf.placeholder) this.$input.placeholder = this.conf.placeholder
|
|
52
|
+
|
|
53
|
+
this.$input.oninput = () => this.onInput()
|
|
54
|
+
this.$input.onkeyup = (evt) => {
|
|
55
|
+
if (evt.key === 'Enter' || evt.keyCode === 13) { // 按下回车键
|
|
56
|
+
evt.preventDefault()
|
|
57
|
+
this.submit()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
window.setTimeout(() => this.$input.focus(), 80)
|
|
62
|
+
|
|
63
|
+
this.$yesBtn.onclick = () => { this.submit() }
|
|
64
|
+
this.$noBtn.onclick = () => { this.cancel() }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public appendTo(parentDOM: HTMLElement) {
|
|
68
|
+
parentDOM.append(this.$el)
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private onInput() {
|
|
73
|
+
this.value = this.$input.value
|
|
74
|
+
|
|
75
|
+
// 验证器
|
|
76
|
+
if (this.conf.validator) {
|
|
77
|
+
const ok = this.conf.validator(this.value)
|
|
78
|
+
this.setAllowSubmit(ok)
|
|
79
|
+
if (!ok) {
|
|
80
|
+
this.$input.classList.add('atk-invalid')
|
|
81
|
+
} else {
|
|
82
|
+
this.$input.classList.remove('atk-invalid')
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public setAllowSubmit(allow: boolean) {
|
|
88
|
+
if (this.allowSubmit === allow) return
|
|
89
|
+
this.allowSubmit = allow
|
|
90
|
+
if (!allow) {
|
|
91
|
+
this.$yesBtn.classList.add('.atk-disabled')
|
|
92
|
+
} else {
|
|
93
|
+
this.$yesBtn.classList.remove('.atk-disabled')
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public async submit() {
|
|
98
|
+
if (!this.allowSubmit) return
|
|
99
|
+
|
|
100
|
+
if (this.conf.onYes) {
|
|
101
|
+
let isContinue: any
|
|
102
|
+
if (this.conf.onYes instanceof (async () => {}).constructor) {
|
|
103
|
+
isContinue = await this.conf.onYes(this.value)
|
|
104
|
+
} else {
|
|
105
|
+
isContinue = this.conf.onYes(this.value)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isContinue === undefined || isContinue === true) {
|
|
109
|
+
this.closeEditor()
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
this.closeEditor()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public async cancel() {
|
|
117
|
+
if (this.conf.onNo) {
|
|
118
|
+
let isContinue: any
|
|
119
|
+
if (this.conf.onNo instanceof (async () => {}).constructor) {
|
|
120
|
+
isContinue = await this.conf.onNo()
|
|
121
|
+
} else {
|
|
122
|
+
isContinue = this.conf.onNo()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (isContinue === undefined || isContinue === true) {
|
|
126
|
+
this.closeEditor()
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
this.closeEditor()
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public closeEditor() {
|
|
134
|
+
this.$el.remove()
|
|
135
|
+
}
|
|
136
|
+
}
|