memi-board 0.44.0 → 0.45.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/README.md +54 -3
- package/dist/ar-BCQdRw_S.js +622 -0
- package/dist/ar-BCQdRw_S.js.map +1 -0
- package/dist/composables/fetchPublicSeo.d.ts +4 -1
- package/dist/composables/useMemiBoardAutoTranslate.d.ts +33 -0
- package/dist/composables/useMemiBoardModeration.d.ts +5 -1
- package/dist/composables/useMemiBoardReports.d.ts +6 -1
- package/dist/composables/useMemiBoardSections.d.ts +2 -1
- package/dist/composables/useMemiBoardUsers.d.ts +4 -0
- package/dist/composables/useMemiBoardWritingAssistant.d.ts +9 -1
- package/dist/config.d.ts +5 -0
- package/dist/de-ddWQNaqs.js +622 -0
- package/dist/de-ddWQNaqs.js.map +1 -0
- package/dist/en-BVUBLkxc.js +648 -0
- package/dist/en-BVUBLkxc.js.map +1 -0
- package/dist/es-7JHjGVlM.js +622 -0
- package/dist/es-7JHjGVlM.js.map +1 -0
- package/dist/fr-C3NCMNoy.js +622 -0
- package/dist/fr-C3NCMNoy.js.map +1 -0
- package/dist/id-C8hCAMPJ.js +622 -0
- package/dist/id-C8hCAMPJ.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1218 -1487
- package/dist/index.js.map +1 -1
- package/dist/ja-oTWri4hY.js +622 -0
- package/dist/ja-oTWri4hY.js.map +1 -0
- package/dist/module.mjs +55 -31
- package/dist/module.mjs.map +1 -1
- package/dist/pt-B9EH4scA.js +622 -0
- package/dist/pt-B9EH4scA.js.map +1 -0
- package/dist/runtime/components/Attachments.vue +4 -2
- package/dist/runtime/components/AuthorMenu.vue +14 -12
- package/dist/runtime/components/AvatarCropModal.vue +8 -5
- package/dist/runtime/components/CategorySettings.vue +65 -43
- package/dist/runtime/components/CommentFeed.vue +9 -7
- package/dist/runtime/components/CommentForm.vue +16 -10
- package/dist/runtime/components/CommentItem.vue +25 -26
- package/dist/runtime/components/CommentList.vue +7 -4
- package/dist/runtime/components/CommentThread.vue +7 -5
- package/dist/runtime/components/Detail.vue +20 -15
- package/dist/runtime/components/Editor.vue +145 -135
- package/dist/runtime/components/Footer.vue +14 -13
- package/dist/runtime/components/List.vue +31 -29
- package/dist/runtime/components/ListDefault.vue +4 -3
- package/dist/runtime/components/ListDense.vue +6 -5
- package/dist/runtime/components/ListImage.vue +4 -2
- package/dist/runtime/components/ListVideo.vue +3 -2
- package/dist/runtime/components/ListViewSwitch.vue +10 -6
- package/dist/runtime/components/MiniCard.vue +3 -2
- package/dist/runtime/components/MiniComments.vue +5 -4
- package/dist/runtime/components/MiniList.vue +3 -2
- package/dist/runtime/components/MiniPicker.vue +10 -9
- package/dist/runtime/components/MiniPost.vue +3 -2
- package/dist/runtime/components/MiniPosts.vue +5 -4
- package/dist/runtime/components/Profile.vue +12 -7
- package/dist/runtime/components/ProfileEditModal.vue +14 -13
- package/dist/runtime/components/ReportButton.vue +20 -10
- package/dist/runtime/components/ReportList.vue +11 -10
- package/dist/runtime/components/Section.vue +3 -2
- package/dist/runtime/components/Settings.vue +84 -62
- package/dist/runtime/components/ShareButton.vue +3 -1
- package/dist/runtime/components/SignIn.vue +14 -8
- package/dist/runtime/components/SwipeHint.vue +5 -3
- package/dist/runtime/components/UserCommentList.vue +8 -6
- package/dist/runtime/components/UserPostList.vue +6 -4
- package/dist/runtime/components/Users.vue +16 -10
- package/dist/runtime/composables/useMemiBoardSeo.ts +16 -10
- package/dist/slugify-6bG6GSO_.js +942 -0
- package/dist/slugify-6bG6GSO_.js.map +1 -0
- package/dist/storage.js +72 -71
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/utils/boardSeo.d.ts +5 -5
- package/dist/utils/compressImage.d.ts +2 -1
- package/dist/utils/formatDate.d.ts +6 -4
- package/dist/utils/imeSafeSubmit.d.ts +2 -0
- package/dist/utils/moderation-prompt.d.ts +18 -1
- package/dist/utils/moderation-strike.d.ts +2 -1
- package/dist/utils/section.d.ts +15 -2
- package/dist/zh-D5rDYV6E.js +622 -0
- package/dist/zh-D5rDYV6E.js.map +1 -0
- package/package.json +2 -3
- package/dist/slugify-Cm_pi2al.js +0 -124
- package/dist/slugify-Cm_pi2al.js.map +0 -1
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref } from 'vue'
|
|
3
|
-
import { BOARD_USER_ROLES, useMemiBoardAuth, useMemiBoardUsers } from 'memi-board/runtime'
|
|
3
|
+
import { BOARD_USER_ROLES, useMemiBoardAuth, useMemiBoardI18n, useMemiBoardUsers } from 'memi-board/runtime'
|
|
4
4
|
import type { BoardUserRole } from 'memi-board/runtime'
|
|
5
5
|
|
|
6
6
|
const props = withDefaults(defineProps<{ authorized?: boolean }>(), { authorized: false })
|
|
7
7
|
const { isAdmin, rolePending } = useMemiBoardAuth()
|
|
8
8
|
const canManage = computed(() => isAdmin.value || props.authorized)
|
|
9
9
|
const { users, usersPending, updateUserRole } = useMemiBoardUsers({ enabled: canManage })
|
|
10
|
+
const { t, formatNumber } = useMemiBoardI18n()
|
|
11
|
+
const roleItems = computed(() => BOARD_USER_ROLES.map(item => ({
|
|
12
|
+
...item,
|
|
13
|
+
label: t(`common.role.${item.value}`),
|
|
14
|
+
description: t(`boardUsers.roleDescription.${item.value}`),
|
|
15
|
+
})))
|
|
10
16
|
const savingUid = ref<string | null>(null)
|
|
11
17
|
const savedUid = ref<string | null>(null)
|
|
12
18
|
const error = ref('')
|
|
@@ -21,7 +27,7 @@ async function changeRole(uid: string, role: BoardUserRole) {
|
|
|
21
27
|
savedUid.value = uid
|
|
22
28
|
}
|
|
23
29
|
catch (cause) {
|
|
24
|
-
error.value = cause instanceof Error ? cause.message : '
|
|
30
|
+
error.value = cause instanceof Error ? cause.message : t('users.changeRoleFailed')
|
|
25
31
|
}
|
|
26
32
|
finally {
|
|
27
33
|
savingUid.value = null
|
|
@@ -32,25 +38,25 @@ async function changeRole(uid: string, role: BoardUserRole) {
|
|
|
32
38
|
<template>
|
|
33
39
|
<div class="flex flex-col gap-6">
|
|
34
40
|
<div class="grid gap-3 md:grid-cols-3">
|
|
35
|
-
<UAlert v-for="item in
|
|
41
|
+
<UAlert v-for="item in roleItems" :key="item.value" color="neutral" variant="subtle" :title="item.label" :description="item.description" />
|
|
36
42
|
</div>
|
|
37
43
|
<UAlert v-if="error" color="error" variant="subtle" icon="i-lucide-circle-alert" :description="error" />
|
|
38
|
-
<div v-if="rolePending || usersPending" class="py-12 text-center text-sm text-muted"
|
|
39
|
-
<UAlert v-else-if="!canManage" color="error" variant="subtle" icon="i-lucide-shield-alert" title="
|
|
40
|
-
<div v-else-if="users.length === 0" class="py-12 text-center text-sm text-muted"
|
|
44
|
+
<div v-if="rolePending || usersPending" class="py-12 text-center text-sm text-muted">{{ t('users.loading') }}</div>
|
|
45
|
+
<UAlert v-else-if="!canManage" color="error" variant="subtle" icon="i-lucide-shield-alert" :title="t('users.noPermission.title')" :description="t('users.noPermission.description')" />
|
|
46
|
+
<div v-else-if="users.length === 0" class="py-12 text-center text-sm text-muted">{{ t('users.empty') }}</div>
|
|
41
47
|
<div v-else class="divide-y divide-default rounded-lg border border-default">
|
|
42
48
|
<div v-for="boardUser in users" :key="boardUser.id" class="grid gap-4 p-4 md:grid-cols-[minmax(0,1fr)_12rem] md:items-center">
|
|
43
49
|
<div class="min-w-0">
|
|
44
50
|
<div class="flex items-center gap-2">
|
|
45
|
-
<p class="truncate font-medium text-highlighted">{{ boardUser.displayName || '
|
|
46
|
-
<UBadge v-if="savedUid === boardUser.id" color="success" variant="subtle" label="
|
|
51
|
+
<p class="truncate font-medium text-highlighted">{{ boardUser.displayName || t('users.noName') }}</p>
|
|
52
|
+
<UBadge v-if="savedUid === boardUser.id" color="success" variant="subtle" :label="t('common.action.saved')" />
|
|
47
53
|
</div>
|
|
48
54
|
<p class="truncate text-sm text-muted">{{ boardUser.id }}</p>
|
|
49
|
-
<p v-if="boardUser.moderationBlockCount" class="mt-1 text-xs text-warning"
|
|
55
|
+
<p v-if="boardUser.moderationBlockCount" class="mt-1 text-xs text-warning">{{ t('users.moderationWarnings', { count: formatNumber(boardUser.moderationBlockCount) }) }}</p>
|
|
50
56
|
</div>
|
|
51
57
|
<USelect
|
|
52
58
|
:model-value="boardUser.role || 'user'"
|
|
53
|
-
:items="
|
|
59
|
+
:items="roleItems"
|
|
54
60
|
value-key="value"
|
|
55
61
|
label-key="label"
|
|
56
62
|
:loading="savingUid === boardUser.id"
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
resolvePublicSeoDb,
|
|
23
23
|
toAbsoluteUrl,
|
|
24
24
|
useMemiBoardConfig,
|
|
25
|
+
useMemiBoardI18n,
|
|
25
26
|
type BoardListSeoPayload,
|
|
26
27
|
type BoardPostSeoPayload,
|
|
27
28
|
} from 'memi-board/runtime'
|
|
@@ -68,6 +69,8 @@ export async function useMemiBoardPostSeo(opts?: {
|
|
|
68
69
|
const siteName = seo.siteName?.trim() || 'Board'
|
|
69
70
|
const origin = resolveOrigin(seo.siteUrl)
|
|
70
71
|
const basePath = normalizeBasePath(seo.basePath)
|
|
72
|
+
const { locale, intlLocale, t } = useMemiBoardI18n()
|
|
73
|
+
const ogLocale = computed(() => intlLocale.value.replace('-', '_'))
|
|
71
74
|
|
|
72
75
|
if (seo.enabled === false) {
|
|
73
76
|
return { post: computed(() => null as BoardPostSeoPayload | null) }
|
|
@@ -100,8 +103,9 @@ export async function useMemiBoardPostSeo(opts?: {
|
|
|
100
103
|
post.value.categoryLabel,
|
|
101
104
|
siteName,
|
|
102
105
|
post.value.summary,
|
|
106
|
+
locale.value,
|
|
103
107
|
)
|
|
104
|
-
:
|
|
108
|
+
: t('seo.postFallbackTitle', { site: siteName }),
|
|
105
109
|
)
|
|
106
110
|
const description = computed(() =>
|
|
107
111
|
post.value
|
|
@@ -109,8 +113,8 @@ export async function useMemiBoardPostSeo(opts?: {
|
|
|
109
113
|
summary: post.value.summary,
|
|
110
114
|
categoryLabel: post.value.categoryLabel,
|
|
111
115
|
authorName: post.value.authorName,
|
|
112
|
-
})
|
|
113
|
-
: '
|
|
116
|
+
}, locale.value)
|
|
117
|
+
: t('seo.postFallbackDescription'),
|
|
114
118
|
)
|
|
115
119
|
const ogImage = computed(() => {
|
|
116
120
|
const img = post.value?.previewImage || seo.defaultOgImage || ''
|
|
@@ -133,7 +137,7 @@ export async function useMemiBoardPostSeo(opts?: {
|
|
|
133
137
|
ogUrl: canonical,
|
|
134
138
|
ogType: 'article',
|
|
135
139
|
ogSiteName: siteName,
|
|
136
|
-
ogLocale
|
|
140
|
+
ogLocale,
|
|
137
141
|
twitterCard: 'summary_large_image',
|
|
138
142
|
twitterTitle: title,
|
|
139
143
|
twitterDescription: description,
|
|
@@ -174,6 +178,8 @@ export async function useMemiBoardListSeo(opts?: {
|
|
|
174
178
|
const siteName = seo.siteName?.trim() || 'Board'
|
|
175
179
|
const origin = resolveOrigin(seo.siteUrl)
|
|
176
180
|
const basePath = normalizeBasePath(seo.basePath)
|
|
181
|
+
const { locale, intlLocale, t } = useMemiBoardI18n()
|
|
182
|
+
const ogLocale = computed(() => intlLocale.value.replace('-', '_'))
|
|
177
183
|
|
|
178
184
|
if (seo.enabled === false) {
|
|
179
185
|
return { list: computed(() => null as BoardListSeoPayload | null) }
|
|
@@ -189,20 +195,20 @@ export async function useMemiBoardListSeo(opts?: {
|
|
|
189
195
|
const seoDb = resolvePublicSeoDb()
|
|
190
196
|
|
|
191
197
|
const listAsync = useAsyncData(
|
|
192
|
-
() => `memi-board-seo-list-${category.value || 'all'}`,
|
|
193
|
-
() => fetchPublicListForSeo(category.value, seoDb),
|
|
194
|
-
{ watch: [category], server: true, lazy: false },
|
|
198
|
+
() => `memi-board-seo-list-${category.value || 'all'}-${locale.value}`,
|
|
199
|
+
() => fetchPublicListForSeo(category.value, seoDb, locale.value),
|
|
200
|
+
{ watch: [category, locale], server: true, lazy: false },
|
|
195
201
|
)
|
|
196
202
|
const list = computed(() => listAsync.data.value ?? null)
|
|
197
203
|
|
|
198
204
|
const title = computed(() =>
|
|
199
|
-
boardListOgTitle(list.value?.categoryLabel || category.value, siteName),
|
|
205
|
+
boardListOgTitle(list.value?.categoryLabel || category.value, siteName, locale.value),
|
|
200
206
|
)
|
|
201
207
|
const description = computed(() => boardListOgDescription({
|
|
202
208
|
categoryLabel: list.value?.categoryLabel,
|
|
203
209
|
description: list.value?.description,
|
|
204
210
|
recentTitles: list.value?.recentTitles,
|
|
205
|
-
}))
|
|
211
|
+
}, locale.value))
|
|
206
212
|
const ogImage = computed(() => {
|
|
207
213
|
const img = list.value?.ogImage || seo.defaultOgImage || ''
|
|
208
214
|
return origin ? toAbsoluteUrl(img, origin, seo.defaultOgImage || '') : img
|
|
@@ -235,7 +241,7 @@ export async function useMemiBoardListSeo(opts?: {
|
|
|
235
241
|
ogUrl: canonical,
|
|
236
242
|
ogType: 'website',
|
|
237
243
|
ogSiteName: siteName,
|
|
238
|
-
ogLocale
|
|
244
|
+
ogLocale,
|
|
239
245
|
twitterCard: 'summary_large_image',
|
|
240
246
|
twitterTitle: title,
|
|
241
247
|
twitterDescription: description,
|