@waline/client 2.11.3 → 2.13.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/api.cjs +1 -1
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +205 -0
- package/dist/api.d.mts +205 -0
- package/dist/api.d.ts +205 -0
- 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.js +1 -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.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.js +1 -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 +65 -1
- package/dist/shim.d.mts +65 -1
- 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 +65 -1
- package/dist/waline.d.mts +65 -1
- package/dist/waline.d.ts +65 -1
- package/dist/waline.js +1 -1
- package/dist/waline.js.map +1 -1
- package/dist/waline.mjs +1 -1
- package/dist/waline.mjs.map +1 -1
- package/package.json +23 -21
- package/src/api/index.ts +1 -0
- package/src/api/user.ts +35 -0
- package/src/components/CommentBox.vue +6 -5
- package/src/components/ImageWall.vue +6 -1
- package/src/composables/userInfo.ts +1 -2
- package/src/composables/vote.ts +1 -1
- package/src/config/default.ts +45 -83
- package/src/entrys/api.ts +1 -1
- package/src/styles/index.scss +1 -0
- package/src/styles/userlist.scss +116 -0
- package/src/utils/config.ts +2 -2
- package/src/widgets/index.ts +1 -0
- package/src/widgets/userList.ts +138 -0
- package/LICENSE +0 -339
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waline/client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "client for waline comment system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"valine",
|
|
@@ -93,6 +93,17 @@
|
|
|
93
93
|
"dist",
|
|
94
94
|
"src"
|
|
95
95
|
],
|
|
96
|
+
"scripts": {
|
|
97
|
+
"build": "pnpm rollup && pnpm style",
|
|
98
|
+
"clean": "rimraf ./dist",
|
|
99
|
+
"dev": "vite -c config/vite.config.js",
|
|
100
|
+
"lint": "eslint --ext .ts,.vue .",
|
|
101
|
+
"prepublishOnly": "pnpm clean && pnpm build",
|
|
102
|
+
"rollup": "rollup -c ./config/rollup.config.js",
|
|
103
|
+
"style": "pnpm style:main && pnpm style:meta",
|
|
104
|
+
"style:main": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed",
|
|
105
|
+
"style:meta": "sass ./src/styles/meta.scss ./dist/waline-meta.css --style=compressed"
|
|
106
|
+
},
|
|
96
107
|
"browserslist": {
|
|
97
108
|
"production": [
|
|
98
109
|
">0.5%",
|
|
@@ -108,42 +119,33 @@
|
|
|
108
119
|
]
|
|
109
120
|
},
|
|
110
121
|
"dependencies": {
|
|
111
|
-
"@vueuse/core": "^9.
|
|
122
|
+
"@vueuse/core": "^9.3.0",
|
|
112
123
|
"autosize": "^5.0.1",
|
|
113
|
-
"marked": "^4.1.
|
|
114
|
-
"vue": "^3.2.
|
|
124
|
+
"marked": "^4.1.1",
|
|
125
|
+
"vue": "^3.2.40"
|
|
115
126
|
},
|
|
116
127
|
"devDependencies": {
|
|
117
|
-
"@babel/core": "7.19.
|
|
118
|
-
"@babel/preset-env": "7.19.
|
|
128
|
+
"@babel/core": "7.19.3",
|
|
129
|
+
"@babel/preset-env": "7.19.3",
|
|
130
|
+
"@giphy/js-types": "4.2.1",
|
|
119
131
|
"@rollup/plugin-babel": "5.3.1",
|
|
120
132
|
"@rollup/plugin-commonjs": "22.0.2",
|
|
121
133
|
"@rollup/plugin-node-resolve": "14.1.0",
|
|
122
134
|
"@rollup/plugin-replace": "4.0.0",
|
|
123
135
|
"@types/autosize": "4.0.1",
|
|
124
136
|
"@types/marked": "4.0.7",
|
|
125
|
-
"@types/node": "18.
|
|
126
|
-
"@vitejs/plugin-vue": "3.1.
|
|
137
|
+
"@types/node": "18.8.2",
|
|
138
|
+
"@vitejs/plugin-vue": "3.1.2",
|
|
127
139
|
"recaptcha-v3": "1.10.0",
|
|
128
140
|
"rimraf": "3.0.2",
|
|
129
141
|
"rollup": "2.79.1",
|
|
130
142
|
"rollup-plugin-dts": "4.2.2",
|
|
131
143
|
"rollup-plugin-terser": "7.0.2",
|
|
132
144
|
"rollup-plugin-ts": "3.0.2",
|
|
133
|
-
"typescript": "4.8.
|
|
134
|
-
"vite": "3.1.
|
|
145
|
+
"typescript": "4.8.4",
|
|
146
|
+
"vite": "3.1.4"
|
|
135
147
|
},
|
|
136
148
|
"engines": {
|
|
137
149
|
"node": ">=14"
|
|
138
|
-
},
|
|
139
|
-
"scripts": {
|
|
140
|
-
"build": "pnpm rollup && pnpm style",
|
|
141
|
-
"clean": "rimraf ./dist",
|
|
142
|
-
"dev": "vite -c config/vite.config.js",
|
|
143
|
-
"lint": "eslint --ext .ts,.vue .",
|
|
144
|
-
"rollup": "rollup -c ./config/rollup.config.js",
|
|
145
|
-
"style": "pnpm style:main && pnpm style:meta",
|
|
146
|
-
"style:main": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed",
|
|
147
|
-
"style:meta": "sass ./src/styles/meta.scss ./dist/waline-meta.css --style=compressed"
|
|
148
150
|
}
|
|
149
|
-
}
|
|
151
|
+
}
|
package/src/api/index.ts
CHANGED
package/src/api/user.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { WalineComment } from '../typings';
|
|
2
|
+
import { errorCheck } from './utils';
|
|
3
|
+
|
|
4
|
+
export interface FetchUserListOptions {
|
|
5
|
+
serverURL: string;
|
|
6
|
+
pageSize: number;
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
lang: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface WalineUser
|
|
12
|
+
extends Pick<WalineComment, 'nick' | 'link' | 'avatar' | 'label' | 'level'> {
|
|
13
|
+
count: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const fetchUserList = ({
|
|
17
|
+
serverURL,
|
|
18
|
+
signal,
|
|
19
|
+
pageSize,
|
|
20
|
+
lang,
|
|
21
|
+
}: FetchUserListOptions): Promise<WalineUser[]> => {
|
|
22
|
+
return fetch(`${serverURL}/user?pageSize=${pageSize}&lang=${lang}`, {
|
|
23
|
+
signal,
|
|
24
|
+
})
|
|
25
|
+
.then(
|
|
26
|
+
(resp) =>
|
|
27
|
+
resp.json() as Promise<{
|
|
28
|
+
errno: number;
|
|
29
|
+
message: string;
|
|
30
|
+
data: WalineUser[];
|
|
31
|
+
}>
|
|
32
|
+
)
|
|
33
|
+
.then((resp) => errorCheck(resp, 'user list'))
|
|
34
|
+
.then((resp) => resp.data);
|
|
35
|
+
};
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
>
|
|
37
37
|
<div v-for="kind in config.meta" :key="kind" class="wl-header-item">
|
|
38
38
|
<label
|
|
39
|
-
:for="kind"
|
|
39
|
+
:for="`wl-${kind}`"
|
|
40
40
|
v-text="
|
|
41
41
|
locale[kind] +
|
|
42
42
|
(config.requiredMeta.includes(kind) || !config.requiredMeta.length
|
|
@@ -624,11 +624,12 @@ export default defineComponent({
|
|
|
624
624
|
|
|
625
625
|
searchResults.loading = true;
|
|
626
626
|
|
|
627
|
-
searchResults.list
|
|
628
|
-
...
|
|
627
|
+
searchResults.list = [
|
|
628
|
+
...searchResults.list,
|
|
629
|
+
...(searchOptions.more && searchResults.list.length
|
|
629
630
|
? await searchOptions.more(keyword, searchResults.list.length)
|
|
630
|
-
: await searchOptions.search(keyword))
|
|
631
|
-
|
|
631
|
+
: await searchOptions.search(keyword)),
|
|
632
|
+
];
|
|
632
633
|
|
|
633
634
|
searchResults.loading = false;
|
|
634
635
|
|
|
@@ -42,7 +42,7 @@ SOFTWARE. -->
|
|
|
42
42
|
:src="items[itemIndex].src"
|
|
43
43
|
:title="items[itemIndex].title"
|
|
44
44
|
loading="lazy"
|
|
45
|
-
@load="
|
|
45
|
+
@load="imageLoad"
|
|
46
46
|
@click="$emit('insert', ``)"
|
|
47
47
|
/>
|
|
48
48
|
</template>
|
|
@@ -133,6 +133,10 @@ export default defineComponent({
|
|
|
133
133
|
window.scrollTo({ top: scrollY });
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
+
const imageLoad = (e: Event) => {
|
|
137
|
+
state.value[(e.target as HTMLImageElement).src] = true;
|
|
138
|
+
};
|
|
139
|
+
|
|
136
140
|
watch(
|
|
137
141
|
() => [props.items],
|
|
138
142
|
() => {
|
|
@@ -158,6 +162,7 @@ export default defineComponent({
|
|
|
158
162
|
columns,
|
|
159
163
|
state,
|
|
160
164
|
wall,
|
|
165
|
+
imageLoad,
|
|
161
166
|
};
|
|
162
167
|
},
|
|
163
168
|
});
|
|
@@ -10,8 +10,7 @@ export type UserInfoRef = Ref<UserInfo | Record<string, never>>;
|
|
|
10
10
|
let userInfoStorage: UserInfoRef | null = null;
|
|
11
11
|
|
|
12
12
|
export const useUserInfo = (): UserInfoRef =>
|
|
13
|
-
userInfoStorage
|
|
14
|
-
(userInfoStorage = useStorage<UserInfo | Record<string, never>>(
|
|
13
|
+
(userInfoStorage ??= useStorage<UserInfo | Record<string, never>>(
|
|
15
14
|
USER_KEY,
|
|
16
15
|
{}
|
|
17
16
|
));
|
package/src/composables/vote.ts
CHANGED
|
@@ -17,4 +17,4 @@ export type VoteRef = Ref<VoteLogItem[]>;
|
|
|
17
17
|
let voteStorage: VoteRef | null = null;
|
|
18
18
|
|
|
19
19
|
export const useVoteStorage = (): VoteRef =>
|
|
20
|
-
|
|
20
|
+
(voteStorage ??= useStorage<VoteLogItem[]>(VOTE_KEY, []));
|
package/src/config/default.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IGif } from '@giphy/js-types';
|
|
2
|
+
import type {
|
|
3
|
+
WalineMeta,
|
|
4
|
+
WalineSearchOptions,
|
|
5
|
+
WalineSearchResult,
|
|
6
|
+
} from '../typings';
|
|
2
7
|
|
|
3
8
|
const availableMeta: WalineMeta[] = ['nick', 'mail', 'link'];
|
|
4
9
|
|
|
@@ -25,94 +30,51 @@ export const defaultTexRenderer = (blockMode: boolean): string =>
|
|
|
25
30
|
? '<p class="wl-tex">Tex is not available in preview</p>'
|
|
26
31
|
: '<span class="wl-tex">Tex is not available in preview</span>';
|
|
27
32
|
|
|
28
|
-
export const getDefaultSearchOptions = (): WalineSearchOptions => {
|
|
29
|
-
interface
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
export const getDefaultSearchOptions = (lang: string): WalineSearchOptions => {
|
|
34
|
+
interface Result {
|
|
35
|
+
meta: {
|
|
36
|
+
msg: string;
|
|
37
|
+
response_id: string;
|
|
38
|
+
status: number;
|
|
39
|
+
};
|
|
40
|
+
pagination: {
|
|
41
|
+
count: number;
|
|
42
|
+
total_count: number;
|
|
43
|
+
offset: number;
|
|
44
|
+
};
|
|
32
45
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
| 'gif'
|
|
36
|
-
| 'mediumgif'
|
|
37
|
-
| 'tinygif'
|
|
38
|
-
| 'nanogif'
|
|
39
|
-
| 'mp4'
|
|
40
|
-
| 'loopedmp4'
|
|
41
|
-
| 'tinymp4'
|
|
42
|
-
| 'nanomp4'
|
|
43
|
-
| 'webm'
|
|
44
|
-
| 'tinywebm'
|
|
45
|
-
| 'nanowebm';
|
|
46
|
-
|
|
47
|
-
interface MediaObject {
|
|
48
|
-
preview: string;
|
|
49
|
-
url: string;
|
|
50
|
-
dims: number[];
|
|
51
|
-
size: number;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface GifObject {
|
|
55
|
-
created: number;
|
|
56
|
-
hasaudio: boolean;
|
|
57
|
-
id: string;
|
|
58
|
-
media: Record<GifFormat, MediaObject>[];
|
|
59
|
-
tags: string[];
|
|
60
|
-
title: string;
|
|
61
|
-
itemurl: string;
|
|
62
|
-
hascaption: boolean;
|
|
63
|
-
url: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface FetchGifResponse {
|
|
67
|
-
next: string;
|
|
68
|
-
results: GifObject[];
|
|
46
|
+
interface GifsResult extends Result {
|
|
47
|
+
data: IGif[];
|
|
69
48
|
}
|
|
70
49
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
})
|
|
93
|
-
.then((resp) => resp.json() as Promise<FetchGifResponse>)
|
|
94
|
-
.catch(() => ({ next: pos || '', results: [] }));
|
|
50
|
+
const fetchGiphy = async (
|
|
51
|
+
url: string,
|
|
52
|
+
params: Record<string, string> = {}
|
|
53
|
+
): Promise<WalineSearchResult> => {
|
|
54
|
+
const querystring = new URLSearchParams({
|
|
55
|
+
lang,
|
|
56
|
+
limit: '20',
|
|
57
|
+
rating: 'g',
|
|
58
|
+
api_key: '6CIMLkNMMOhRcXPoMCPkFy4Ybk2XUiMp',
|
|
59
|
+
...params,
|
|
60
|
+
}).toString();
|
|
61
|
+
|
|
62
|
+
const resp = await fetch(
|
|
63
|
+
`https://api.giphy.com/v1/gifs/${url}?${querystring}`
|
|
64
|
+
).then((resp) => resp.json() as Promise<GifsResult>);
|
|
65
|
+
|
|
66
|
+
return resp.data.map((gif) => ({
|
|
67
|
+
title: gif.title,
|
|
68
|
+
src: gif.images.downsized_medium.url,
|
|
69
|
+
}));
|
|
95
70
|
};
|
|
96
71
|
|
|
97
72
|
return {
|
|
98
|
-
search: (word
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
title: item.title,
|
|
104
|
-
src: item.media[0].tinygif.url,
|
|
105
|
-
}));
|
|
106
|
-
}),
|
|
107
|
-
more: (word) =>
|
|
108
|
-
fetchGif({ keyword: word, pos: state.next }).then((resp) => {
|
|
109
|
-
state.next = resp.next;
|
|
110
|
-
|
|
111
|
-
return resp.results.map((item) => ({
|
|
112
|
-
title: item.title,
|
|
113
|
-
src: item.media[0].tinygif.url,
|
|
114
|
-
}));
|
|
115
|
-
}),
|
|
73
|
+
search: (word: string): Promise<WalineSearchResult> =>
|
|
74
|
+
fetchGiphy('search', { q: word, offset: '0' }),
|
|
75
|
+
default: (): Promise<WalineSearchResult> => fetchGiphy('trending', {}),
|
|
76
|
+
more: (word: string, offset = 0): Promise<WalineSearchResult> =>
|
|
77
|
+
fetchGiphy('search', { q: word, offset: offset.toString() }),
|
|
116
78
|
};
|
|
117
79
|
};
|
|
118
80
|
|
package/src/entrys/api.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from '
|
|
1
|
+
export * from '../api';
|
package/src/styles/index.scss
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--waline-rank-gold-bgcolor: #FA3939;
|
|
3
|
+
--waline-rank-silver-bgcolor: #FB811C;
|
|
4
|
+
--waline-rank-copper-bgcolor: #FEB207;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.wl-user-list {
|
|
8
|
+
list-style: none;
|
|
9
|
+
padding: 0;
|
|
10
|
+
|
|
11
|
+
> li + li {
|
|
12
|
+
margin-top: 10px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
> li, > li > a {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: row;
|
|
18
|
+
gap: 10px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
a,
|
|
22
|
+
a:hover,
|
|
23
|
+
a:visited {
|
|
24
|
+
text-decoration: none;
|
|
25
|
+
color: var(--waline-color);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.wl-user-avatar {
|
|
29
|
+
position: relative;
|
|
30
|
+
line-height: 0;
|
|
31
|
+
|
|
32
|
+
> i {
|
|
33
|
+
position: absolute;
|
|
34
|
+
bottom: 0;
|
|
35
|
+
right: 0;
|
|
36
|
+
min-width: 1.5em;
|
|
37
|
+
height: 1.5em;
|
|
38
|
+
line-height: 1.5em;
|
|
39
|
+
background: var(--waline-info-bgcolor);
|
|
40
|
+
text-align: center;
|
|
41
|
+
font-size: 10px;
|
|
42
|
+
border-radius: 2px;
|
|
43
|
+
font-style: normal;
|
|
44
|
+
color: var(--waline-info-color);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
img {
|
|
49
|
+
width: 48px;
|
|
50
|
+
height: 48px;
|
|
51
|
+
border-radius: 2px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.wl-user-name {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: row;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 10px;
|
|
59
|
+
}
|
|
60
|
+
.wl-user-tag {
|
|
61
|
+
padding-bottom: 0;
|
|
62
|
+
border-bottom: none;
|
|
63
|
+
width: auto;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
> li:nth-child(1) i {
|
|
68
|
+
background: var(--waline-rank-gold-bgcolor);
|
|
69
|
+
color: var(--waline-white);
|
|
70
|
+
font-weight: bold;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
> li:nth-child(2) i {
|
|
74
|
+
background: var(--waline-rank-silver-bgcolor);
|
|
75
|
+
color: var(--waline-white);
|
|
76
|
+
font-weight: bold;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
> li:nth-child(3) i {
|
|
80
|
+
background: var(--waline-rank-copper-bgcolor);
|
|
81
|
+
color: var(--waline-white);
|
|
82
|
+
font-weight: bold;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.wl-user-wall {
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: row;
|
|
89
|
+
list-style: none;
|
|
90
|
+
padding: 0;
|
|
91
|
+
|
|
92
|
+
> li {
|
|
93
|
+
width: 48px;
|
|
94
|
+
height: 48px;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
> li:hover img {
|
|
99
|
+
transform: scale(1.25);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
img {
|
|
103
|
+
width: 48px;
|
|
104
|
+
height: 48px;
|
|
105
|
+
border-radius: 0;
|
|
106
|
+
transition: transform ease-in-out 400ms;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.wl-user-avatar > i,
|
|
110
|
+
.wl-user-meta {
|
|
111
|
+
display: none;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
package/src/utils/config.ts
CHANGED
|
@@ -64,7 +64,7 @@ export const getConfig = ({
|
|
|
64
64
|
texRenderer,
|
|
65
65
|
copyright = true,
|
|
66
66
|
login = 'enable',
|
|
67
|
-
search
|
|
67
|
+
search,
|
|
68
68
|
reaction,
|
|
69
69
|
recaptchaV3Key = '',
|
|
70
70
|
...more
|
|
@@ -87,7 +87,7 @@ export const getConfig = ({
|
|
|
87
87
|
pageSize,
|
|
88
88
|
login,
|
|
89
89
|
copyright,
|
|
90
|
-
search,
|
|
90
|
+
search: search || getDefaultSearchOptions(lang),
|
|
91
91
|
recaptchaV3Key,
|
|
92
92
|
reaction: Array.isArray(reaction)
|
|
93
93
|
? reaction
|
package/src/widgets/index.ts
CHANGED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { fetchUserList, WalineUser } from '../api';
|
|
2
|
+
import { defaultLang, defaultLocales } from '../config';
|
|
3
|
+
import { WalineLocale } from '../typings';
|
|
4
|
+
import { getRoot } from '../utils';
|
|
5
|
+
|
|
6
|
+
export interface WalineUserListOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Waline 服务端地址
|
|
9
|
+
*
|
|
10
|
+
* Waline serverURL
|
|
11
|
+
*/
|
|
12
|
+
serverURL: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 获取用户列表的数量
|
|
16
|
+
*
|
|
17
|
+
* fetch number of user list
|
|
18
|
+
*/
|
|
19
|
+
count: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 需要挂载的元素
|
|
23
|
+
*
|
|
24
|
+
* Element to be mounted
|
|
25
|
+
*/
|
|
26
|
+
el?: string | HTMLElement;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 错误提示消息所使用的语言
|
|
30
|
+
*
|
|
31
|
+
* Language of error message
|
|
32
|
+
*
|
|
33
|
+
* @default 'zh-CN'
|
|
34
|
+
*/
|
|
35
|
+
lang?: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 自定义 waline 语言显示
|
|
39
|
+
*
|
|
40
|
+
* @see [自定义语言](https://waline.js.org/client/i18n.html)
|
|
41
|
+
*
|
|
42
|
+
* Custom display language in waline
|
|
43
|
+
*
|
|
44
|
+
* @see [I18n](https://waline.js.org/en/client/i18n.html)
|
|
45
|
+
*/
|
|
46
|
+
locale?: WalineLocale;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 列表模式还是头像墙模式
|
|
50
|
+
*
|
|
51
|
+
* list mode or avatar wall mode
|
|
52
|
+
*/
|
|
53
|
+
mode: 'list' | 'wall';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface WalineUserListResult {
|
|
57
|
+
/**
|
|
58
|
+
* 用户数据
|
|
59
|
+
*
|
|
60
|
+
* User Data
|
|
61
|
+
*/
|
|
62
|
+
users: WalineUser[];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 取消挂载挂件
|
|
66
|
+
*
|
|
67
|
+
* Umount widget
|
|
68
|
+
*/
|
|
69
|
+
destroy: () => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const UserList = ({
|
|
73
|
+
el,
|
|
74
|
+
serverURL,
|
|
75
|
+
count,
|
|
76
|
+
locale,
|
|
77
|
+
lang = defaultLang,
|
|
78
|
+
mode = 'list',
|
|
79
|
+
}: WalineUserListOptions): Promise<WalineUserListResult> => {
|
|
80
|
+
const root = getRoot(el);
|
|
81
|
+
const controller = new AbortController();
|
|
82
|
+
|
|
83
|
+
return fetchUserList({
|
|
84
|
+
serverURL,
|
|
85
|
+
pageSize: count,
|
|
86
|
+
lang,
|
|
87
|
+
signal: controller.signal,
|
|
88
|
+
}).then((users) => {
|
|
89
|
+
if (!root || !users.length) {
|
|
90
|
+
return {
|
|
91
|
+
users,
|
|
92
|
+
destroy: (): void => controller.abort(),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
locale = {
|
|
97
|
+
...(defaultLocales[lang] || defaultLocales[defaultLang]),
|
|
98
|
+
...(typeof locale === 'object' ? locale : {}),
|
|
99
|
+
} as WalineLocale;
|
|
100
|
+
|
|
101
|
+
root.innerHTML = `<ul class="wl-user-${mode}">${users
|
|
102
|
+
.map((user, index) =>
|
|
103
|
+
[
|
|
104
|
+
'<li class="wl-user-item">',
|
|
105
|
+
user.link && `<a href="${user.link}" target="_blank">`,
|
|
106
|
+
'<div class="wl-user-avatar">',
|
|
107
|
+
`<img src="${user.avatar}" alt="${user.nick}">`,
|
|
108
|
+
`<i>${index + 1}</i>`,
|
|
109
|
+
'</div>',
|
|
110
|
+
'<div class="wl-user-meta">',
|
|
111
|
+
`<div class="wl-user-name"><div>${user.nick}</div>`,
|
|
112
|
+
'<div class="wl-user-tag wl-card">',
|
|
113
|
+
user.level &&
|
|
114
|
+
`<span class="wl-badge">${
|
|
115
|
+
locale ? locale[`level${user.level}`] : `Level ${user.level}`
|
|
116
|
+
}</span>`,
|
|
117
|
+
user.label && `<span class="wl-badge">${user.label}</span>`,
|
|
118
|
+
'</div>',
|
|
119
|
+
'</div>',
|
|
120
|
+
user.link && `<span class="wl-user-meta">${user.link}</span>`,
|
|
121
|
+
'</div>',
|
|
122
|
+
user.link && '</a>',
|
|
123
|
+
'</li>',
|
|
124
|
+
]
|
|
125
|
+
.filter((v) => v)
|
|
126
|
+
.join('')
|
|
127
|
+
)
|
|
128
|
+
.join('')}</ul>`;
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
users,
|
|
132
|
+
destroy: (): void => {
|
|
133
|
+
controller.abort();
|
|
134
|
+
root.innerHTML = '';
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
};
|