artalk 2.3.4 → 2.4.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.
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +3171 -3008
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -1
- package/dist/ArtalkLite.es.js +3124 -2980
- package/dist/ArtalkLite.iife.js +1 -1
- package/dist/ArtalkLite.js +1 -1
- package/dist/src/api/admin.d.ts +10 -0
- package/dist/src/api/api-base.d.ts +14 -0
- package/dist/src/api/captcha.d.ts +14 -0
- package/dist/src/api/comment.d.ts +29 -0
- package/dist/src/api/index.d.ts +31 -0
- package/dist/src/api/page.d.ts +22 -0
- package/dist/src/api/request.d.ts +12 -0
- package/dist/src/api/site.d.ts +17 -0
- package/dist/src/api/system.d.ts +13 -0
- package/dist/src/api/upload.d.ts +11 -0
- package/dist/src/api/user.d.ts +28 -0
- package/dist/src/artalk.d.ts +56 -0
- package/dist/src/comment/actions.d.ts +17 -0
- package/dist/src/comment/comment.d.ts +67 -0
- package/dist/src/comment/index.d.ts +2 -0
- package/dist/src/comment/render.d.ts +76 -0
- package/dist/src/components/action-btn.d.ts +52 -0
- package/dist/src/components/dialog.d.ts +18 -0
- package/dist/src/components/pagination.d.ts +30 -0
- package/dist/src/components/read-more-btn.d.ts +33 -0
- package/dist/src/context.d.ts +72 -0
- package/dist/src/defaults.d.ts +3 -0
- package/dist/src/editor/editor.d.ts +84 -0
- package/dist/src/editor/index.d.ts +2 -0
- package/dist/src/editor/plugs/editor-plug.d.ts +26 -0
- package/dist/src/editor/plugs/emoticons-plug.d.ts +36 -0
- package/dist/src/editor/plugs/header-input-plug.d.ts +13 -0
- package/dist/src/editor/plugs/preview-plug.d.ts +10 -0
- package/dist/src/editor/plugs/upload-plug.d.ts +10 -0
- package/dist/src/i18n/en.d.ts +69 -0
- package/dist/src/i18n/index.d.ts +294 -0
- package/dist/src/i18n/zh-CN.d.ts +3 -0
- package/dist/src/layer/index.d.ts +3 -0
- package/dist/src/layer/layer.d.ts +32 -0
- package/dist/src/layer/sidebar-layer.d.ts +20 -0
- package/dist/src/lib/checker/admin-checker.d.ts +3 -0
- package/dist/src/lib/checker/captcha-checker.d.ts +3 -0
- package/dist/src/lib/checker/index.d.ts +42 -0
- package/dist/src/lib/component.d.ts +12 -0
- package/dist/src/lib/detect.d.ts +10 -0
- package/dist/src/lib/stat.d.ts +15 -0
- package/dist/src/lib/ui.d.ts +23 -0
- package/dist/src/lib/user.d.ts +13 -0
- package/dist/src/lib/utils.d.ts +39 -0
- package/dist/src/list/index.d.ts +2 -0
- package/dist/src/list/list-lite.d.ts +63 -0
- package/dist/src/list/list-nest.d.ts +10 -0
- package/dist/src/list/list.d.ts +26 -0
- package/dist/src/main.d.ts +4 -0
- package/dist/types/artalk-config.d.ts +132 -0
- package/dist/types/artalk-data.d.ts +204 -0
- package/dist/types/context.d.ts +146 -0
- package/dist/types/event.d.ts +28 -0
- package/dist/types/global.d.ts +0 -0
- package/dist/types/plug.d.ts +4 -0
- package/index.html +3 -3
- package/package.json +5 -5
- package/src/api/admin.ts +18 -0
- package/src/api/api-base.ts +27 -0
- package/src/api/captcha.ts +24 -0
- package/src/api/comment.ts +84 -0
- package/src/api/index.ts +25 -366
- package/src/api/page.ts +85 -0
- package/src/api/site.ts +51 -0
- package/src/api/system.ts +39 -0
- package/src/api/upload.ts +29 -0
- package/src/api/user.ts +75 -0
- package/src/artalk.ts +50 -46
- package/src/comment/actions.ts +3 -3
- package/src/comment/comment.ts +6 -9
- package/src/comment/render.ts +76 -40
- package/src/components/pagination.ts +0 -1
- package/src/context.ts +31 -31
- package/src/editor/editor.ts +2 -4
- package/src/editor/plugs/header-input-plug.ts +1 -1
- package/src/editor/plugs/upload-plug.ts +1 -1
- package/src/i18n/index.ts +117 -2
- package/src/layer/sidebar-layer.ts +1 -3
- package/src/lib/checker/admin-checker.ts +1 -1
- package/src/lib/checker/captcha-checker.ts +3 -3
- package/src/lib/stat.ts +2 -2
- package/src/lib/ui.ts +6 -0
- package/src/list/list-lite.ts +25 -25
- package/src/list/list.ts +3 -4
- package/src/main.ts +3 -0
- package/src/style/main.less +6 -0
- package/types/context.d.ts +4 -1
- package/types/global.d.ts +0 -2
- package/vite-base.config.ts +9 -5
- package/vite.config.ts +5 -1
- package/types/index.d.ts +0 -3
package/src/api/page.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { PageData, CommentData } from '~/types/artalk-data'
|
|
2
|
+
import ApiBase from './api-base'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 页面 API
|
|
6
|
+
*/
|
|
7
|
+
export default class PageApi extends ApiBase {
|
|
8
|
+
/** 页面 · 获取 */
|
|
9
|
+
public async pageGet(siteName?: string, offset?: number, limit?: number) {
|
|
10
|
+
const params: any = {
|
|
11
|
+
site_name: siteName || '',
|
|
12
|
+
offset: offset || 0,
|
|
13
|
+
limit: limit || 15,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const d = await this.POST<any>('/admin/page-get', params)
|
|
17
|
+
return (d as { pages: PageData[], total: number })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** 页面 · 修改 */
|
|
21
|
+
public async pageEdit(data: PageData) {
|
|
22
|
+
const params: any = {
|
|
23
|
+
id: data.id,
|
|
24
|
+
key: data.key,
|
|
25
|
+
title: data.title,
|
|
26
|
+
admin_only: data.admin_only,
|
|
27
|
+
site_name: data.site_name || this.ctx.conf.site,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const d = await this.POST<any>('/admin/page-edit', params)
|
|
31
|
+
return (d.page as PageData)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 页面 · 删除 */
|
|
35
|
+
public pageDel(pageKey: string, siteName?: string) {
|
|
36
|
+
const params: any = {
|
|
37
|
+
key: String(pageKey),
|
|
38
|
+
site_name: siteName || '',
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return this.POST('/admin/page-del', params)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 页面 · 数据更新 */
|
|
45
|
+
public async pageFetch(id?: number, siteName?: string, getStatus?: boolean) {
|
|
46
|
+
const params: any = {}
|
|
47
|
+
if (id) params.id = id
|
|
48
|
+
if (siteName) params.site_name = siteName
|
|
49
|
+
if (getStatus) params.get_status = getStatus
|
|
50
|
+
|
|
51
|
+
const d = await this.POST<any>('/admin/page-fetch', params)
|
|
52
|
+
return (d as any)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** PV */
|
|
56
|
+
public async pv() {
|
|
57
|
+
const params: any = {
|
|
58
|
+
site_name: this.ctx.conf.site || '',
|
|
59
|
+
page_key: this.ctx.conf.pageKey || '',
|
|
60
|
+
page_title: this.ctx.conf.pageTitle || ''
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const p = await this.POST<any>('/pv', params)
|
|
64
|
+
return p.pv as number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 统计 */
|
|
68
|
+
public async stat(
|
|
69
|
+
type: 'latest_comments'|'latest_pages'|'pv_most_pages'|'comment_most_pages'|
|
|
70
|
+
'page_pv'|'site_pv'|'page_comment'|'site_comment',
|
|
71
|
+
pageKeys?: string|string[],
|
|
72
|
+
limit?: number
|
|
73
|
+
) {
|
|
74
|
+
const params: any = {
|
|
75
|
+
type,
|
|
76
|
+
site_name: this.ctx.conf.site || '',
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (pageKeys) params.page_keys = Array.isArray(pageKeys) ? pageKeys.join(',') : pageKeys
|
|
80
|
+
if (limit) params.limit = limit
|
|
81
|
+
|
|
82
|
+
const data = await this.POST<PageData[]|CommentData[]|object|number>(`/stat`, params)
|
|
83
|
+
return data
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/api/site.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SiteData } from '~/types/artalk-data'
|
|
2
|
+
import ApiBase from './api-base'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 站点 API
|
|
6
|
+
*/
|
|
7
|
+
export default class SiteApi extends ApiBase {
|
|
8
|
+
/** 站点 · 获取 */
|
|
9
|
+
public async siteGet() {
|
|
10
|
+
const params: any = {}
|
|
11
|
+
|
|
12
|
+
const d = await this.POST<any>('/admin/site-get', params)
|
|
13
|
+
return (d.sites as SiteData[])
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** 站点 · 创建 */
|
|
17
|
+
public async siteAdd(name: string, urls: string) {
|
|
18
|
+
const params: any = {
|
|
19
|
+
name, urls,
|
|
20
|
+
site_name: '' // 全局保留字段,当前站点名
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const d = await this.POST<any>('/admin/site-add', params)
|
|
24
|
+
return (d.site as SiteData)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 站点 · 修改 */
|
|
28
|
+
public async siteEdit(data: SiteData) {
|
|
29
|
+
const params: any = {
|
|
30
|
+
id: data.id,
|
|
31
|
+
name: data.name || '',
|
|
32
|
+
urls: data.urls || '',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const d = await this.POST<any>('/admin/site-edit', params)
|
|
36
|
+
return (d.site as SiteData)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 站点 · 删除 */
|
|
40
|
+
public siteDel(id: number, delContent = false) {
|
|
41
|
+
const params: any = { id, del_content: delContent }
|
|
42
|
+
|
|
43
|
+
return this.POST('/admin/site-del', params)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** 导出 */
|
|
47
|
+
public async export() {
|
|
48
|
+
const d = await this.Fetch(`/admin/export`, { method: 'POST' }, 0)
|
|
49
|
+
return (d.data?.data || '' as string)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import ArtalkConfig from '~/types/artalk-config'
|
|
2
|
+
import ApiBase from './api-base'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 系统 API
|
|
6
|
+
*/
|
|
7
|
+
export default class SystemApi extends ApiBase {
|
|
8
|
+
/** 获取配置 */
|
|
9
|
+
public async conf() {
|
|
10
|
+
const data = await this.POST<any>(`/conf`)
|
|
11
|
+
const conf = (data.frontend_conf || {}) as ArtalkConfig
|
|
12
|
+
|
|
13
|
+
// Patch: `emoticons` config string to json
|
|
14
|
+
if (conf.emoticons && typeof conf.emoticons === "string") {
|
|
15
|
+
conf.emoticons = conf.emoticons.trim()
|
|
16
|
+
if (conf.emoticons.startsWith("[") || conf.emoticons.startsWith("{")) {
|
|
17
|
+
conf.emoticons = JSON.parse(conf.emoticons) // pase json
|
|
18
|
+
} else if (conf.emoticons === "false") {
|
|
19
|
+
conf.emoticons = false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return conf
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 获取配置数据 */
|
|
27
|
+
public async getSettings() {
|
|
28
|
+
const data = await this.POST<string>('/admin/setting-get')
|
|
29
|
+
return data
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** 保存配置数据 */
|
|
33
|
+
public async saveSettings(yamlStr: string) {
|
|
34
|
+
const data = await this.POST<boolean>('/admin/setting-save', {
|
|
35
|
+
data: yamlStr,
|
|
36
|
+
})
|
|
37
|
+
return data
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ToFormData } from './request'
|
|
2
|
+
import ApiBase from './api-base'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 上传 API
|
|
6
|
+
*/
|
|
7
|
+
export default class UploadApi extends ApiBase {
|
|
8
|
+
/** 图片上传 */
|
|
9
|
+
public async imgUpload(file: File) {
|
|
10
|
+
const params: any = {
|
|
11
|
+
name: this.ctx.user.data.nick,
|
|
12
|
+
email: this.ctx.user.data.email,
|
|
13
|
+
page_key: this.ctx.conf.pageKey,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (this.ctx.conf.site) params.site_name = this.ctx.conf.site
|
|
17
|
+
|
|
18
|
+
const form = ToFormData(params)
|
|
19
|
+
form.set('file', file)
|
|
20
|
+
|
|
21
|
+
const init: RequestInit = {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
body: form
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const json = await this.Fetch('/img-upload', init)
|
|
27
|
+
return ((json.data || {}) as any) as { img_file: string, img_url: string }
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/api/user.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { UserData, NotifyData } from '~/types/artalk-data'
|
|
2
|
+
import ApiBase from './api-base'
|
|
3
|
+
import { ToFormData } from './request'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 用户 API
|
|
7
|
+
*/
|
|
8
|
+
export default class UserApi extends ApiBase {
|
|
9
|
+
/** 用户 · 登录 */
|
|
10
|
+
public async login(name: string, email: string, password: string) {
|
|
11
|
+
const params: any = {
|
|
12
|
+
name, email, password
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (this.ctx.conf.site) params.site_name = this.ctx.conf.site
|
|
16
|
+
|
|
17
|
+
const data = await this.POST<any>('/login', params)
|
|
18
|
+
return (data.token as string)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 用户 · 获取 */
|
|
22
|
+
public userGet(name: string, email: string) {
|
|
23
|
+
const ctrl = new AbortController()
|
|
24
|
+
const params: any = {
|
|
25
|
+
name, email, site_name: (this.ctx.conf.site || '')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const req = this.Fetch(`/user-get`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
body: ToFormData(params),
|
|
31
|
+
signal: ctrl.signal,
|
|
32
|
+
}).then((json) => ({
|
|
33
|
+
user: json.data.user as UserData|null,
|
|
34
|
+
is_login: json.data.is_login as boolean,
|
|
35
|
+
unread: (json.data.unread || []) as NotifyData[],
|
|
36
|
+
unread_count: json.data.unread_count || 0,
|
|
37
|
+
}))
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
req,
|
|
41
|
+
abort: () => { ctrl.abort() },
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 用户 · 登录状态 */
|
|
46
|
+
public async loginStatus() {
|
|
47
|
+
const data = await this.POST<any>('/login-status', {
|
|
48
|
+
name: this.ctx.user.data.nick,
|
|
49
|
+
email: this.ctx.user.data.email
|
|
50
|
+
})
|
|
51
|
+
return (data || { is_login: false, is_admin: false }) as { is_login: boolean, is_admin: boolean }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 用户 · 注销 */
|
|
55
|
+
public async logout() {
|
|
56
|
+
return this.POST('/logout')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** 已读标记 */
|
|
60
|
+
public markRead(notifyKey: string, readAll = false) {
|
|
61
|
+
const params: any = {
|
|
62
|
+
site_name: this.ctx.conf.site || '',
|
|
63
|
+
notify_key: notifyKey,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (readAll) {
|
|
67
|
+
delete params.notify_key
|
|
68
|
+
params.read_all = true
|
|
69
|
+
params.name = this.ctx.user.data.nick
|
|
70
|
+
params.email = this.ctx.user.data.email
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return this.POST(`/mark-read`, params)
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/artalk.ts
CHANGED
|
@@ -6,7 +6,6 @@ import ArtalkPlug from '~/types/plug'
|
|
|
6
6
|
import Context from '~/types/context'
|
|
7
7
|
import ConcreteContext from './context'
|
|
8
8
|
import defaults from './defaults'
|
|
9
|
-
import { internal as internalLocales } from './i18n'
|
|
10
9
|
|
|
11
10
|
import CheckerLauncher from './lib/checker'
|
|
12
11
|
import Editor from './editor'
|
|
@@ -30,17 +29,15 @@ export default class Artalk {
|
|
|
30
29
|
public ctx!: Context
|
|
31
30
|
public $root!: HTMLElement
|
|
32
31
|
|
|
33
|
-
public checkerLauncher!: CheckerLauncher
|
|
34
|
-
public editor!: Editor
|
|
35
|
-
public list!: List
|
|
36
|
-
public sidebarLayer!: SidebarLayer
|
|
37
|
-
|
|
38
32
|
/** Plugins (in global scope) */
|
|
39
33
|
protected static Plugins: ArtalkPlug[] = [ Stat.PvCountWidget ]
|
|
40
34
|
|
|
41
35
|
/** Plugins (in a instance scope) */
|
|
42
36
|
protected instancePlugins: ArtalkPlug[] = []
|
|
43
37
|
|
|
38
|
+
/** 禁用的组件 */
|
|
39
|
+
public static DisabledComponents: string[] = []
|
|
40
|
+
|
|
44
41
|
constructor(customConf: Partial<ArtalkConfig>) {
|
|
45
42
|
/* 初始化基本配置 */
|
|
46
43
|
this.conf = Artalk.HandelBaseConf(customConf)
|
|
@@ -63,30 +60,50 @@ export default class Artalk {
|
|
|
63
60
|
this.initDarkMode()
|
|
64
61
|
Utils.initMarked(this.ctx)
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
63
|
+
const Components: { [name: string]: () => void } = {
|
|
64
|
+
// CheckerLauncher
|
|
65
|
+
checkerLauncher: () => {
|
|
66
|
+
const checkerLauncher = new CheckerLauncher(this.ctx)
|
|
67
|
+
this.ctx.setCheckerLauncher(checkerLauncher)
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// 编辑器
|
|
71
|
+
editor: () => {
|
|
72
|
+
const editor = new Editor(this.ctx)
|
|
73
|
+
this.ctx.setEditor(editor)
|
|
74
|
+
this.$root.appendChild(editor.$el)
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// 评论列表
|
|
78
|
+
list: () => {
|
|
79
|
+
// 评论列表
|
|
80
|
+
const list = new List(this.ctx)
|
|
81
|
+
this.ctx.setList(list)
|
|
82
|
+
this.$root.appendChild(list.$el)
|
|
83
|
+
|
|
84
|
+
// 评论获取
|
|
85
|
+
list.fetchComments(0)
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// 侧边栏 Layer
|
|
89
|
+
sidebarLayer: () => {
|
|
90
|
+
const sidebarLayer = new SidebarLayer(this.ctx)
|
|
91
|
+
this.ctx.setSidebarLayer(sidebarLayer)
|
|
92
|
+
this.$root.appendChild(sidebarLayer.$el)
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// 默认事件绑定
|
|
96
|
+
eventsDefault: () => {
|
|
97
|
+
this.initEventBind()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
84
100
|
|
|
85
|
-
//
|
|
86
|
-
|
|
101
|
+
// 组件初始化
|
|
102
|
+
Object.entries(Components).forEach(([name, initComponent]) => {
|
|
103
|
+
if (Artalk.DisabledComponents.includes(name)) return
|
|
87
104
|
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
initComponent()
|
|
106
|
+
})
|
|
90
107
|
|
|
91
108
|
// 插件初始化 (global scope)
|
|
92
109
|
Artalk.Plugins.forEach(plugin => {
|
|
@@ -96,7 +113,7 @@ export default class Artalk {
|
|
|
96
113
|
}
|
|
97
114
|
|
|
98
115
|
/** 基本配置初始化 */
|
|
99
|
-
|
|
116
|
+
public static HandelBaseConf(customConf: Partial<ArtalkConfig>): ArtalkConfig {
|
|
100
117
|
// 合并默认配置
|
|
101
118
|
const conf: ArtalkConfig = Utils.mergeDeep(Artalk.defaults, customConf)
|
|
102
119
|
|
|
@@ -141,7 +158,7 @@ export default class Artalk {
|
|
|
141
158
|
Ui.showLoading(this.$root)
|
|
142
159
|
let backendConf = {}
|
|
143
160
|
try {
|
|
144
|
-
backendConf = await this.ctx.getApi().conf()
|
|
161
|
+
backendConf = await this.ctx.getApi().system.conf()
|
|
145
162
|
} catch (err) { console.error("Load config from remote err", err) }
|
|
146
163
|
this.ctx.conf = Utils.mergeDeep(this.ctx.conf, backendConf)
|
|
147
164
|
Ui.hideLoading(this.$root)
|
|
@@ -151,8 +168,7 @@ export default class Artalk {
|
|
|
151
168
|
private initEventBind() {
|
|
152
169
|
// 锚点快速跳转评论
|
|
153
170
|
window.addEventListener('hashchange', () => {
|
|
154
|
-
this.
|
|
155
|
-
this.list.checkGoToCommentByUrlHash()
|
|
171
|
+
this.ctx.listHashGotoCheck()
|
|
156
172
|
})
|
|
157
173
|
|
|
158
174
|
// 本地用户数据变更
|
|
@@ -164,20 +180,8 @@ export default class Artalk {
|
|
|
164
180
|
|
|
165
181
|
/** 语言初始化 */
|
|
166
182
|
private initLocale() {
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
this.conf.locale = ((navigator.languages) ? navigator.languages[0] : navigator.language)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
this.conf.locale = this.conf.locale.replace(
|
|
173
|
-
/^([a-zA-Z]+)(-[a-zA-Z]+)?$/,
|
|
174
|
-
(_, p1: string, p2: string) => (p1.toLowerCase() + (p2 || '').toUpperCase())
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
if (!internalLocales[this.conf.locale]) { // 语言不存在时,使用 en
|
|
178
|
-
console.log(`Locale "${this.conf.locale}" not found.`)
|
|
179
|
-
this.conf.locale = 'en'
|
|
180
|
-
}
|
|
183
|
+
if (this.conf.locale === 'auto') { // 自适应语言
|
|
184
|
+
this.conf.locale = navigator.language
|
|
181
185
|
}
|
|
182
186
|
}
|
|
183
187
|
|
package/src/comment/actions.ts
CHANGED
|
@@ -16,7 +16,7 @@ export default class CommentActions {
|
|
|
16
16
|
public vote(type: 'up'|'down') {
|
|
17
17
|
const actionBtn = (type === 'up') ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown
|
|
18
18
|
|
|
19
|
-
this.ctx.getApi().vote(this.data.id, `comment_${type}`)
|
|
19
|
+
this.ctx.getApi().comment.vote(this.data.id, `comment_${type}`)
|
|
20
20
|
.then((v) => {
|
|
21
21
|
this.data.vote_up = v.up
|
|
22
22
|
this.data.vote_down = v.down
|
|
@@ -45,7 +45,7 @@ export default class CommentActions {
|
|
|
45
45
|
modify.is_pinned = !modify.is_pinned
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
this.ctx.getApi().commentEdit(modify).then((data) => {
|
|
48
|
+
this.ctx.getApi().comment.commentEdit(modify).then((data) => {
|
|
49
49
|
btnElem.setLoading(false)
|
|
50
50
|
|
|
51
51
|
// 刷新当前 Comment UI
|
|
@@ -64,7 +64,7 @@ export default class CommentActions {
|
|
|
64
64
|
if (btnElem.isLoading) return // 若正在删除中
|
|
65
65
|
|
|
66
66
|
btnElem.setLoading(true, `${this.ctx.$t('deleting')}...`)
|
|
67
|
-
this.ctx.getApi().commentDel(this.data.id, this.data.site_name)
|
|
67
|
+
this.ctx.getApi().comment.commentDel(this.data.id, this.data.site_name)
|
|
68
68
|
.then(() => {
|
|
69
69
|
btnElem.setLoading(false)
|
|
70
70
|
if (this.cConf.onDelete) this.cConf.onDelete(this.comment)
|
package/src/comment/comment.ts
CHANGED
|
@@ -172,16 +172,13 @@ export default class Comment extends Component {
|
|
|
172
172
|
return Utils.timeAgo(new Date(this.data.date), this.ctx)
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/** 获取用户 UserAgent
|
|
176
|
-
public
|
|
175
|
+
/** 获取用户 UserAgent 信息 */
|
|
176
|
+
public getUserUA() {
|
|
177
177
|
const info = UADetect(this.data.ua)
|
|
178
|
-
return
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
public getUserUaOS() {
|
|
183
|
-
const info = UADetect(this.data.ua)
|
|
184
|
-
return `${info.os} ${info.osVersion}`
|
|
178
|
+
return {
|
|
179
|
+
browser: `${info.browser} ${info.version}`,
|
|
180
|
+
os: `${info.os} ${info.osVersion}`
|
|
181
|
+
}
|
|
185
182
|
}
|
|
186
183
|
|
|
187
184
|
/** 获取配置 */
|