@waline/client 2.13.0 → 2.14.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/LICENSE +339 -0
- package/dist/api.cjs +1 -1
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +302 -69
- package/dist/api.d.mts +302 -69
- package/dist/api.d.ts +302 -69
- package/dist/api.mjs +1 -1
- package/dist/api.mjs.map +1 -1
- package/dist/comment.cjs +1 -1
- package/dist/comment.cjs.map +1 -1
- package/dist/comment.d.cts +2 -2
- package/dist/comment.d.mts +2 -2
- package/dist/comment.d.ts +2 -2
- package/dist/comment.js +68 -1
- package/dist/comment.js.map +1 -1
- package/dist/comment.mjs +1 -1
- package/dist/comment.mjs.map +1 -1
- package/dist/component.mjs +1 -1
- package/dist/component.mjs.map +1 -1
- package/dist/legacy.umd.d.ts +21 -11
- package/dist/legacy.umd.js +1 -1
- package/dist/legacy.umd.js.map +1 -1
- package/dist/pageview.cjs +1 -1
- package/dist/pageview.cjs.map +1 -1
- package/dist/pageview.d.cts +1 -1
- package/dist/pageview.d.mts +1 -1
- package/dist/pageview.d.ts +1 -1
- package/dist/pageview.js +121 -1
- package/dist/pageview.js.map +1 -1
- package/dist/pageview.mjs +1 -1
- package/dist/pageview.mjs.map +1 -1
- package/dist/shim.cjs +1 -1
- package/dist/shim.cjs.map +1 -1
- package/dist/shim.d.cts +25 -19
- package/dist/shim.d.mts +25 -19
- package/dist/shim.mjs +1 -1
- package/dist/shim.mjs.map +1 -1
- package/dist/waline.cjs +1 -1
- package/dist/waline.cjs.map +1 -1
- package/dist/waline.css +1 -1
- package/dist/waline.css.map +1 -1
- package/dist/waline.d.cts +25 -19
- package/dist/waline.d.mts +25 -19
- package/dist/waline.d.ts +25 -19
- package/dist/waline.js +6787 -1
- package/dist/waline.js.map +1 -1
- package/dist/waline.mjs +1 -1
- package/dist/waline.mjs.map +1 -1
- package/package.json +28 -29
- package/src/api/articleCounter.ts +52 -22
- package/src/api/comment.ts +158 -55
- package/src/api/commentCount.ts +24 -21
- package/src/api/login.ts +49 -6
- package/src/api/pageview.ts +26 -13
- package/src/api/recentComment.ts +23 -10
- package/src/api/user.ts +24 -18
- package/src/api/utils.ts +33 -10
- package/src/comment.ts +1 -1
- package/src/compact/convert.ts +1 -1
- package/src/components/ArticleReaction.vue +12 -3
- package/src/components/CommentBox.vue +37 -29
- package/src/components/ImageWall.vue +14 -14
- package/src/components/Waline.vue +59 -49
- package/src/config/default.ts +23 -24
- package/src/pageview.ts +3 -3
- package/src/styles/index.scss +3 -3
- package/src/styles/{nomalize.scss → normalize.scss} +0 -0
- package/src/styles/panel.scss +1 -1
- package/src/styles/user-list.scss +158 -0
- package/src/typings/base.ts +5 -1
- package/src/typings/comment.ts +1 -5
- package/src/typings/waline.ts +13 -2
- package/src/utils/config.ts +2 -0
- package/src/utils/date.ts +3 -3
- package/src/utils/emoji.ts +1 -1
- package/src/widgets/recentComments.ts +2 -2
- package/src/widgets/userList.ts +8 -10
- package/src/styles/userlist.scss +0 -116
package/src/api/recentComment.ts
CHANGED
|
@@ -1,21 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BaseAPIOptions } from './utils';
|
|
2
2
|
import type { WalineComment } from '../typings';
|
|
3
3
|
|
|
4
|
-
export interface
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export interface GetRecentCommentOptions extends BaseAPIOptions {
|
|
5
|
+
/**
|
|
6
|
+
* 获取评论的数量
|
|
7
|
+
*
|
|
8
|
+
* Comment number to be fetched
|
|
9
|
+
*/
|
|
7
10
|
count: number;
|
|
8
|
-
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 取消请求的信号
|
|
14
|
+
*
|
|
15
|
+
* AbortSignal to cancel request
|
|
16
|
+
*/
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 用户令牌
|
|
21
|
+
*
|
|
22
|
+
* User token
|
|
23
|
+
*/
|
|
9
24
|
token?: string;
|
|
10
25
|
}
|
|
11
26
|
|
|
12
|
-
export const
|
|
27
|
+
export const getRecentComment = ({
|
|
13
28
|
serverURL,
|
|
14
29
|
lang,
|
|
15
30
|
count,
|
|
16
31
|
signal,
|
|
17
32
|
token,
|
|
18
|
-
}:
|
|
33
|
+
}: GetRecentCommentOptions): Promise<WalineComment[]> => {
|
|
19
34
|
const headers: Record<string, string> = {};
|
|
20
35
|
|
|
21
36
|
if (token) headers.Authorization = `Bearer ${token}`;
|
|
@@ -23,7 +38,5 @@ export const fetchRecentComment = ({
|
|
|
23
38
|
return fetch(`${serverURL}/comment?type=recent&count=${count}&lang=${lang}`, {
|
|
24
39
|
signal,
|
|
25
40
|
headers,
|
|
26
|
-
})
|
|
27
|
-
.then((resp) => resp.json() as Promise<WalineComment[]>)
|
|
28
|
-
.then((data) => errorCheck(data, 'recent comment'));
|
|
41
|
+
}).then((resp) => <Promise<WalineComment[]>>resp.json());
|
|
29
42
|
};
|
package/src/api/user.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { errorCheck, ErrorStatusResponse } from './utils';
|
|
2
|
+
import type { BaseAPIOptions } from './utils';
|
|
3
|
+
import type { WalineComment } from '../typings';
|
|
3
4
|
|
|
4
|
-
export interface
|
|
5
|
-
|
|
5
|
+
export interface GetUserListOptions extends BaseAPIOptions {
|
|
6
|
+
/**
|
|
7
|
+
* 每页个数
|
|
8
|
+
*
|
|
9
|
+
* Number per page
|
|
10
|
+
*/
|
|
6
11
|
pageSize: number;
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 取消请求的信号
|
|
15
|
+
*
|
|
16
|
+
* AbortSignal to cancel request
|
|
17
|
+
*/
|
|
18
|
+
signal?: AbortSignal;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
export interface WalineUser
|
|
@@ -13,23 +23,19 @@ export interface WalineUser
|
|
|
13
23
|
count: number;
|
|
14
24
|
}
|
|
15
25
|
|
|
16
|
-
export
|
|
26
|
+
export interface GetUserListResponse extends ErrorStatusResponse {
|
|
27
|
+
data: WalineUser[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const getUserList = ({
|
|
17
31
|
serverURL,
|
|
18
32
|
signal,
|
|
19
33
|
pageSize,
|
|
20
34
|
lang,
|
|
21
|
-
}:
|
|
22
|
-
|
|
35
|
+
}: GetUserListOptions): Promise<WalineUser[]> =>
|
|
36
|
+
fetch(`${serverURL}/user?pageSize=${pageSize}&lang=${lang}`, {
|
|
23
37
|
signal,
|
|
24
38
|
})
|
|
25
|
-
.then(
|
|
26
|
-
(resp) =>
|
|
27
|
-
resp.json() as Promise<{
|
|
28
|
-
errno: number;
|
|
29
|
-
message: string;
|
|
30
|
-
data: WalineUser[];
|
|
31
|
-
}>
|
|
32
|
-
)
|
|
39
|
+
.then((resp) => <Promise<GetUserListResponse>>resp.json())
|
|
33
40
|
.then((resp) => errorCheck(resp, 'user list'))
|
|
34
41
|
.then((resp) => resp.data);
|
|
35
|
-
};
|
package/src/api/utils.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface BaseAPIOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Waline 服务端地址
|
|
4
|
+
*
|
|
5
|
+
* Waline serverURL
|
|
6
|
+
*/
|
|
7
|
+
serverURL: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 错误信息所使用的语言
|
|
11
|
+
*
|
|
12
|
+
* Language used in error text
|
|
13
|
+
*/
|
|
14
|
+
lang: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ErrorStatusResponse {
|
|
18
|
+
/**
|
|
19
|
+
* 错误代码
|
|
20
|
+
*
|
|
21
|
+
* Error number
|
|
22
|
+
*/
|
|
2
23
|
errno: number;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 错误消息
|
|
27
|
+
*
|
|
28
|
+
* Error msg
|
|
29
|
+
*/
|
|
3
30
|
errmsg: string;
|
|
4
31
|
}
|
|
5
32
|
|
|
@@ -8,16 +35,12 @@ export const JSON_HEADERS: Record<string, string> = {
|
|
|
8
35
|
'Content-Type': 'application/json',
|
|
9
36
|
};
|
|
10
37
|
|
|
11
|
-
export const errorCheck = <T
|
|
12
|
-
data: T
|
|
38
|
+
export const errorCheck = <T extends ErrorStatusResponse>(
|
|
39
|
+
data: T,
|
|
13
40
|
name = ''
|
|
14
41
|
): T => {
|
|
15
|
-
if (typeof data === 'object' &&
|
|
16
|
-
throw new TypeError(
|
|
17
|
-
`Fetch ${name} failed with ${(data as FetchErrorData).errno}: ${
|
|
18
|
-
(data as FetchErrorData).errmsg
|
|
19
|
-
}`
|
|
20
|
-
);
|
|
42
|
+
if (typeof data === 'object' && data.errno)
|
|
43
|
+
throw new TypeError(`${name} failed with ${data.errno}: ${data.errmsg}`);
|
|
21
44
|
|
|
22
|
-
return data
|
|
45
|
+
return data;
|
|
23
46
|
};
|
package/src/comment.ts
CHANGED
package/src/compact/convert.ts
CHANGED
|
@@ -44,7 +44,7 @@ export const covertOptions = (
|
|
|
44
44
|
...more
|
|
45
45
|
} = options;
|
|
46
46
|
|
|
47
|
-
// error with those which can no
|
|
47
|
+
// error with those which can no longer be handled
|
|
48
48
|
DROPPED_OPTIONS_WHICH_CAN_NOT_BE_POLYFILLED.filter((item) =>
|
|
49
49
|
Object.keys(options).includes(item)
|
|
50
50
|
).forEach((item) =>
|
|
@@ -27,8 +27,9 @@ import {
|
|
|
27
27
|
onMounted,
|
|
28
28
|
onUnmounted,
|
|
29
29
|
ref,
|
|
30
|
+
watch,
|
|
30
31
|
} from 'vue';
|
|
31
|
-
import {
|
|
32
|
+
import { getArticleCounter, updateArticleCounter } from '../api';
|
|
32
33
|
import { VOTE_IDENTIFIER, VOTE_INDEX, useVoteStorage } from '../composables';
|
|
33
34
|
import type { WalineConfig } from '../utils';
|
|
34
35
|
import type { WalineLocale } from '../typings';
|
|
@@ -70,7 +71,7 @@ export default defineComponent({
|
|
|
70
71
|
if (reaction.length) {
|
|
71
72
|
const controller = new AbortController();
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
getArticleCounter({
|
|
74
75
|
serverURL,
|
|
75
76
|
lang,
|
|
76
77
|
paths: [path],
|
|
@@ -128,7 +129,15 @@ export default defineComponent({
|
|
|
128
129
|
voteStorage.value = voteStorage.value.slice(-50);
|
|
129
130
|
};
|
|
130
131
|
|
|
131
|
-
onMounted(() =>
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
watch(
|
|
134
|
+
() => [config.value.serverURL, config.value.path],
|
|
135
|
+
() => {
|
|
136
|
+
fetchCounter();
|
|
137
|
+
},
|
|
138
|
+
{ immediate: true }
|
|
139
|
+
);
|
|
140
|
+
});
|
|
132
141
|
onUnmounted(() => abort?.());
|
|
133
142
|
|
|
134
143
|
return {
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
v-show="emoji.tabs.length"
|
|
95
95
|
ref="emojiButtonRef"
|
|
96
96
|
class="wl-action"
|
|
97
|
-
:class="{
|
|
97
|
+
:class="{ active: showEmoji }"
|
|
98
98
|
:title="locale.emoji"
|
|
99
99
|
@click="showEmoji = !showEmoji"
|
|
100
100
|
>
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
v-if="config.search"
|
|
106
106
|
ref="gifButtonRef"
|
|
107
107
|
class="wl-action"
|
|
108
|
-
:class="{
|
|
108
|
+
:class="{ active: showGif }"
|
|
109
109
|
:title="locale.gif"
|
|
110
110
|
@click="showGif = !showGif"
|
|
111
111
|
>
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
|
|
133
133
|
<button
|
|
134
134
|
class="wl-action"
|
|
135
|
-
:class="{
|
|
135
|
+
:class="{ active: showPreview }"
|
|
136
136
|
:title="locale.preview"
|
|
137
137
|
@click="showPreview = !showPreview"
|
|
138
138
|
>
|
|
@@ -287,7 +287,7 @@ import {
|
|
|
287
287
|
GifIcon,
|
|
288
288
|
} from './Icons';
|
|
289
289
|
import ImageWall from './ImageWall.vue';
|
|
290
|
-
import { login,
|
|
290
|
+
import { addComment, login, updateComment } from '../api';
|
|
291
291
|
import { useEditor, useUserMeta, useUserInfo } from '../composables';
|
|
292
292
|
import {
|
|
293
293
|
getEmojis,
|
|
@@ -526,18 +526,21 @@ export default defineComponent({
|
|
|
526
526
|
comment.pid = props.replyId;
|
|
527
527
|
comment.rid = props.rootId;
|
|
528
528
|
comment.at = props.replyUser;
|
|
529
|
-
} else if (props.edit) {
|
|
530
|
-
comment.eid = props.edit.objectId;
|
|
531
529
|
}
|
|
532
530
|
|
|
533
531
|
isSubmitting.value = true;
|
|
534
532
|
|
|
535
|
-
|
|
533
|
+
const options = {
|
|
536
534
|
serverURL,
|
|
537
535
|
lang,
|
|
538
536
|
token: userInfo.value?.token,
|
|
539
537
|
comment,
|
|
540
|
-
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
(props.edit
|
|
541
|
+
? updateComment({ objectId: props.edit.objectId, ...options })
|
|
542
|
+
: addComment(options)
|
|
543
|
+
)
|
|
541
544
|
.then((resp) => {
|
|
542
545
|
isSubmitting.value = false;
|
|
543
546
|
|
|
@@ -590,8 +593,12 @@ export default defineComponent({
|
|
|
590
593
|
const height = 800;
|
|
591
594
|
const left = (window.innerWidth - width) / 2;
|
|
592
595
|
const top = (window.innerHeight - height) / 2;
|
|
596
|
+
const query = new URLSearchParams({
|
|
597
|
+
lng: lang,
|
|
598
|
+
token: userInfo.value!.token,
|
|
599
|
+
});
|
|
593
600
|
const handler = window.open(
|
|
594
|
-
`${serverURL}/ui/profile
|
|
601
|
+
`${serverURL}/ui/profile?${query.toString()}`,
|
|
595
602
|
'_blank',
|
|
596
603
|
`width=${width},height=${height},left=${left},top=${top},scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no`
|
|
597
604
|
);
|
|
@@ -668,25 +675,8 @@ export default defineComponent({
|
|
|
668
675
|
{ immediate: true }
|
|
669
676
|
);
|
|
670
677
|
|
|
671
|
-
watch(showGif, async (showGif) => {
|
|
672
|
-
if (!showGif) return;
|
|
673
|
-
|
|
674
|
-
const searchOptions = config.value.search as WalineSearchOptions;
|
|
675
|
-
|
|
676
|
-
// clear input
|
|
677
|
-
if (gifSearchInputRef.value) gifSearchInputRef.value.value = '';
|
|
678
|
-
|
|
679
|
-
searchResults.loading = true;
|
|
680
|
-
|
|
681
|
-
searchResults.list = searchOptions.default
|
|
682
|
-
? await searchOptions.default()
|
|
683
|
-
: await searchOptions.search('');
|
|
684
|
-
|
|
685
|
-
searchResults.loading = false;
|
|
686
|
-
});
|
|
687
|
-
|
|
688
678
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
689
|
-
const
|
|
679
|
+
const onMessageReceive = ({ data }: any): void => {
|
|
690
680
|
if (!data || data.type !== 'profile') return;
|
|
691
681
|
|
|
692
682
|
userInfo.value = { ...userInfo.value, ...data.data };
|
|
@@ -700,11 +690,29 @@ export default defineComponent({
|
|
|
700
690
|
|
|
701
691
|
onMounted(() => {
|
|
702
692
|
document.body.addEventListener('click', popupHandler);
|
|
703
|
-
window.addEventListener('message',
|
|
693
|
+
window.addEventListener('message', onMessageReceive);
|
|
704
694
|
if (props.edit?.objectId) {
|
|
705
695
|
editor.value = props.edit.orig;
|
|
706
696
|
}
|
|
707
697
|
|
|
698
|
+
// watch gif
|
|
699
|
+
watch(showGif, async (showGif) => {
|
|
700
|
+
if (!showGif) return;
|
|
701
|
+
|
|
702
|
+
const searchOptions = config.value.search as WalineSearchOptions;
|
|
703
|
+
|
|
704
|
+
// clear input
|
|
705
|
+
if (gifSearchInputRef.value) gifSearchInputRef.value.value = '';
|
|
706
|
+
|
|
707
|
+
searchResults.loading = true;
|
|
708
|
+
|
|
709
|
+
searchResults.list = searchOptions.default
|
|
710
|
+
? await searchOptions.default()
|
|
711
|
+
: await searchOptions.search('');
|
|
712
|
+
|
|
713
|
+
searchResults.loading = false;
|
|
714
|
+
});
|
|
715
|
+
|
|
708
716
|
// watch editor
|
|
709
717
|
watch(
|
|
710
718
|
() => editor.value,
|
|
@@ -740,7 +748,7 @@ export default defineComponent({
|
|
|
740
748
|
|
|
741
749
|
onUnmounted(() => {
|
|
742
750
|
document.body.removeEventListener('click', popupHandler);
|
|
743
|
-
window.removeEventListener('message',
|
|
751
|
+
window.removeEventListener('message', onMessageReceive);
|
|
744
752
|
});
|
|
745
753
|
|
|
746
754
|
return {
|
|
@@ -133,27 +133,27 @@ export default defineComponent({
|
|
|
133
133
|
window.scrollTo({ top: scrollY });
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
-
const imageLoad = (e: Event) => {
|
|
136
|
+
const imageLoad = (e: Event): void => {
|
|
137
137
|
state.value[(e.target as HTMLImageElement).src] = true;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
watch(
|
|
141
|
-
() => [props.items],
|
|
142
|
-
() => {
|
|
143
|
-
state.value = {};
|
|
144
|
-
redraw(true);
|
|
145
|
-
}
|
|
146
|
-
);
|
|
147
|
-
watch(
|
|
148
|
-
() => [props.columnWidth, props.gap],
|
|
149
|
-
() => redraw()
|
|
150
|
-
);
|
|
151
|
-
|
|
152
140
|
onMounted(() => {
|
|
153
141
|
redraw(true);
|
|
154
|
-
resizeObserver = new ResizeObserver(() => redraw());
|
|
155
142
|
|
|
143
|
+
resizeObserver = new ResizeObserver(() => redraw());
|
|
156
144
|
resizeObserver.observe(wall.value!);
|
|
145
|
+
|
|
146
|
+
watch(
|
|
147
|
+
() => [props.items],
|
|
148
|
+
() => {
|
|
149
|
+
state.value = {};
|
|
150
|
+
redraw(true);
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
watch(
|
|
154
|
+
() => [props.columnWidth, props.gap],
|
|
155
|
+
() => redraw()
|
|
156
|
+
);
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
onBeforeUnmount(() => resizeObserver!.unobserve(wall.value!));
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
<ul class="wl-sort">
|
|
11
11
|
<li
|
|
12
|
-
v-for="item in
|
|
13
|
-
:key="item
|
|
14
|
-
:class="[item
|
|
15
|
-
@click="onSortByChange(item
|
|
12
|
+
v-for="item in sortingMethods"
|
|
13
|
+
:key="item"
|
|
14
|
+
:class="[item === commentSorting ? 'active' : '']"
|
|
15
|
+
@click="onSortByChange(item)"
|
|
16
16
|
>
|
|
17
|
-
{{ i18n[item
|
|
17
|
+
{{ i18n[item] }}
|
|
18
18
|
</li>
|
|
19
19
|
</ul>
|
|
20
20
|
</div>
|
|
@@ -81,26 +81,31 @@
|
|
|
81
81
|
|
|
82
82
|
<script lang="ts">
|
|
83
83
|
import { useStyleTag } from '@vueuse/core';
|
|
84
|
-
import {
|
|
84
|
+
import {
|
|
85
|
+
computed,
|
|
86
|
+
defineComponent,
|
|
87
|
+
onMounted,
|
|
88
|
+
onUnmounted,
|
|
89
|
+
provide,
|
|
90
|
+
ref,
|
|
91
|
+
watch,
|
|
92
|
+
} from 'vue';
|
|
85
93
|
import Reaction from './ArticleReaction.vue';
|
|
86
94
|
import CommentBox from './CommentBox.vue';
|
|
87
95
|
import CommentCard from './CommentCard.vue';
|
|
88
96
|
import { LoadingIcon } from './Icons';
|
|
89
97
|
import { useUserInfo, useLikeStorage } from '../composables';
|
|
90
98
|
import { defaultLocales } from '../config';
|
|
91
|
-
import {
|
|
92
|
-
deleteComment,
|
|
93
|
-
fetchComment,
|
|
94
|
-
likeComment,
|
|
95
|
-
updateComment,
|
|
96
|
-
} from '../api';
|
|
99
|
+
import { deleteComment, getComment, updateComment } from '../api';
|
|
97
100
|
import { getConfig, getDarkStyle } from '../utils';
|
|
98
101
|
|
|
99
102
|
import type { PropType } from 'vue';
|
|
100
103
|
import type {
|
|
101
104
|
WalineComment,
|
|
105
|
+
WalineCommentSorting,
|
|
102
106
|
WalineCommentStatus,
|
|
103
107
|
WalineEmojiInfo,
|
|
108
|
+
WalineLoginStatus,
|
|
104
109
|
WalineHighlighter,
|
|
105
110
|
WalineTexRenderer,
|
|
106
111
|
WalineImageUploader,
|
|
@@ -119,6 +124,7 @@ const props = [
|
|
|
119
124
|
'meta',
|
|
120
125
|
'requiredMeta',
|
|
121
126
|
'dark',
|
|
127
|
+
'commentSorting',
|
|
122
128
|
'lang',
|
|
123
129
|
'locale',
|
|
124
130
|
'pageSize',
|
|
@@ -134,23 +140,13 @@ const props = [
|
|
|
134
140
|
'reaction',
|
|
135
141
|
];
|
|
136
142
|
|
|
137
|
-
type
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
key: 'insertedAt_asc',
|
|
147
|
-
name: 'oldest',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
key: 'like_desc',
|
|
151
|
-
name: 'hottest',
|
|
152
|
-
},
|
|
153
|
-
];
|
|
143
|
+
type SortKey = 'insertedAt_desc' | 'insertedAt_asc' | 'like_desc';
|
|
144
|
+
const sortKeyMap: Record<WalineCommentSorting, SortKey> = {
|
|
145
|
+
latest: 'insertedAt_desc',
|
|
146
|
+
oldest: 'insertedAt_asc',
|
|
147
|
+
hottest: 'like_desc',
|
|
148
|
+
};
|
|
149
|
+
const sortingMethods = Object.keys(sortKeyMap) as WalineCommentSorting[];
|
|
154
150
|
|
|
155
151
|
const propsWithValidate = {
|
|
156
152
|
serverURL: {
|
|
@@ -181,6 +177,14 @@ const propsWithValidate = {
|
|
|
181
177
|
|
|
182
178
|
dark: [String, Boolean],
|
|
183
179
|
|
|
180
|
+
commentSorting: {
|
|
181
|
+
type: String,
|
|
182
|
+
default: 'latest',
|
|
183
|
+
validator: (value: unknown): boolean =>
|
|
184
|
+
typeof value === 'string' &&
|
|
185
|
+
['latest', 'oldest', 'hottest'].includes(value),
|
|
186
|
+
},
|
|
187
|
+
|
|
184
188
|
lang: {
|
|
185
189
|
type: String,
|
|
186
190
|
default: 'zh-CN',
|
|
@@ -220,7 +224,7 @@ const propsWithValidate = {
|
|
|
220
224
|
)),
|
|
221
225
|
},
|
|
222
226
|
|
|
223
|
-
login: String as PropType<
|
|
227
|
+
login: String as PropType<WalineLoginStatus>,
|
|
224
228
|
|
|
225
229
|
highlighter: Function as PropType<WalineHighlighter>,
|
|
226
230
|
|
|
@@ -263,8 +267,9 @@ export default defineComponent({
|
|
|
263
267
|
|
|
264
268
|
props: SHOULD_VALIDATE ? propsWithValidate : props,
|
|
265
269
|
|
|
266
|
-
setup(
|
|
267
|
-
const
|
|
270
|
+
setup(_props) {
|
|
271
|
+
const props = _props as unknown as WalineProps;
|
|
272
|
+
const config = computed(() => getConfig(props));
|
|
268
273
|
|
|
269
274
|
const userInfo = useUserInfo();
|
|
270
275
|
const likeStorage = useLikeStorage();
|
|
@@ -274,7 +279,7 @@ export default defineComponent({
|
|
|
274
279
|
const count = ref(0);
|
|
275
280
|
const page = ref(1);
|
|
276
281
|
const totalPages = ref(0);
|
|
277
|
-
const
|
|
282
|
+
const commentSorting = ref(config.value.commentSorting);
|
|
278
283
|
|
|
279
284
|
const data = ref<WalineComment[]>([]);
|
|
280
285
|
const reply = ref<WalineComment | null>(null);
|
|
@@ -287,7 +292,7 @@ export default defineComponent({
|
|
|
287
292
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
|
288
293
|
let abort: () => void;
|
|
289
294
|
|
|
290
|
-
const
|
|
295
|
+
const getCommentData = (pageNumber: number): void => {
|
|
291
296
|
const { serverURL, path, pageSize } = config.value;
|
|
292
297
|
const controller = new AbortController();
|
|
293
298
|
|
|
@@ -295,12 +300,12 @@ export default defineComponent({
|
|
|
295
300
|
|
|
296
301
|
abort?.();
|
|
297
302
|
|
|
298
|
-
|
|
303
|
+
getComment({
|
|
299
304
|
serverURL,
|
|
300
305
|
lang: config.value.lang,
|
|
301
306
|
path,
|
|
302
307
|
pageSize,
|
|
303
|
-
sortBy:
|
|
308
|
+
sortBy: sortKeyMap[commentSorting.value],
|
|
304
309
|
page: pageNumber,
|
|
305
310
|
signal: controller.signal,
|
|
306
311
|
token: userInfo.value?.token,
|
|
@@ -322,20 +327,19 @@ export default defineComponent({
|
|
|
322
327
|
abort = controller.abort.bind(controller);
|
|
323
328
|
};
|
|
324
329
|
|
|
325
|
-
const loadMore = (): void =>
|
|
330
|
+
const loadMore = (): void => getCommentData(page.value + 1);
|
|
326
331
|
|
|
327
332
|
const refresh = (): void => {
|
|
328
333
|
count.value = 0;
|
|
329
334
|
data.value = [];
|
|
330
|
-
|
|
335
|
+
getCommentData(1);
|
|
331
336
|
};
|
|
332
337
|
|
|
333
|
-
const onSortByChange = (item:
|
|
334
|
-
if (
|
|
335
|
-
|
|
338
|
+
const onSortByChange = (item: WalineCommentSorting): void => {
|
|
339
|
+
if (commentSorting.value !== item) {
|
|
340
|
+
commentSorting.value = item;
|
|
341
|
+
refresh();
|
|
336
342
|
}
|
|
337
|
-
sortBy.value = item;
|
|
338
|
-
refresh();
|
|
339
343
|
};
|
|
340
344
|
|
|
341
345
|
const onReply = (comment: WalineComment | null): void => {
|
|
@@ -441,10 +445,11 @@ export default defineComponent({
|
|
|
441
445
|
const { objectId } = comment;
|
|
442
446
|
const hasLiked = likeStorage.value.includes(objectId);
|
|
443
447
|
|
|
444
|
-
await
|
|
448
|
+
await updateComment({
|
|
445
449
|
serverURL,
|
|
446
450
|
lang,
|
|
447
451
|
objectId,
|
|
452
|
+
token: userInfo.value?.token,
|
|
448
453
|
like: !hasLiked,
|
|
449
454
|
});
|
|
450
455
|
|
|
@@ -462,9 +467,14 @@ export default defineComponent({
|
|
|
462
467
|
|
|
463
468
|
provide('config', config);
|
|
464
469
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
470
|
+
onMounted(() => {
|
|
471
|
+
watch(
|
|
472
|
+
() => [props.serverURL, props.path],
|
|
473
|
+
() => refresh(),
|
|
474
|
+
{ immediate: true }
|
|
475
|
+
);
|
|
476
|
+
});
|
|
477
|
+
onUnmounted(() => abort?.());
|
|
468
478
|
|
|
469
479
|
return {
|
|
470
480
|
config,
|
|
@@ -475,8 +485,8 @@ export default defineComponent({
|
|
|
475
485
|
count,
|
|
476
486
|
page,
|
|
477
487
|
totalPages,
|
|
478
|
-
|
|
479
|
-
|
|
488
|
+
commentSorting,
|
|
489
|
+
sortingMethods,
|
|
480
490
|
data,
|
|
481
491
|
reply,
|
|
482
492
|
edit,
|