mirror of https://github.com/halo-dev/halo
feat: add H2 database usage warning to setup page (#6502)
#### What type of PR is this? /area ui /kind improvement /milestone 2.19.x #### What this PR does / why we need it: 在初始化页面添加使用 H2 数据库的警告。 <img width="773" alt="image" src="https://github.com/user-attachments/assets/3be83064-2075-4d3d-9511-9c67ffb68076"> #### Special notes for your reviewer: 需要测试在首次安装的时候使用 H2 数据库时,初始化页面是否有警告界面。 #### Does this PR introduce a user-facing change? ```release-note 在初始化页面添加使用 H2 数据库的警告。 ```pull/6512/head
parent
2b84b41987
commit
3767a5a239
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import H2WarningAlert from "@/components/alerts/H2WarningAlert.vue";
|
||||||
import type { GlobalInfo, Info, Startup } from "@/types";
|
import type { GlobalInfo, Info, Startup } from "@/types";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
import { usePermission } from "@/utils/permission";
|
import { usePermission } from "@/utils/permission";
|
||||||
|
@ -364,17 +365,7 @@ const handleDownloadLogfile = () => {
|
||||||
<span>
|
<span>
|
||||||
{{ [info.database.name, info.database.version].join(" / ") }}
|
{{ [info.database.name, info.database.version].join(" / ") }}
|
||||||
</span>
|
</span>
|
||||||
<VAlert
|
<H2WarningAlert class="mt-3" />
|
||||||
v-if="info.database.name.startsWith('H2')"
|
|
||||||
class="mt-3"
|
|
||||||
type="warning"
|
|
||||||
:title="$t('core.common.text.warning')"
|
|
||||||
:closable="false"
|
|
||||||
>
|
|
||||||
<template #description>
|
|
||||||
{{ $t("core.overview.alert.h2_warning") }}
|
|
||||||
</template>
|
|
||||||
</VAlert>
|
|
||||||
</VDescriptionItem>
|
</VDescriptionItem>
|
||||||
<VDescriptionItem :label="$t('core.overview.fields.os')">
|
<VDescriptionItem :label="$t('core.overview.fields.os')">
|
||||||
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}
|
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}
|
||||||
|
|
|
@ -57,17 +57,11 @@ export const routes: Array<RouteRecordRaw> = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/setup",
|
path: "/setup",
|
||||||
component: GatewayLayout,
|
component: Setup,
|
||||||
children: [
|
name: "Setup",
|
||||||
{
|
meta: {
|
||||||
path: "",
|
title: "core.setup.title",
|
||||||
name: "Setup",
|
},
|
||||||
component: Setup,
|
|
||||||
meta: {
|
|
||||||
title: "core.setup.title",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/setup-initial-data",
|
path: "/setup-initial-data",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import H2WarningAlert from "@/components/alerts/H2WarningAlert.vue";
|
||||||
import LocaleChange from "@/components/common/LocaleChange.vue";
|
import LocaleChange from "@/components/common/LocaleChange.vue";
|
||||||
import { useGlobalInfoStore } from "@/stores/global-info";
|
import { useGlobalInfoStore } from "@/stores/global-info";
|
||||||
import type { SystemInitializationRequest } from "@halo-dev/api-client";
|
import type { SystemInitializationRequest } from "@halo-dev/api-client";
|
||||||
|
@ -7,6 +8,7 @@ import { Toast, VButton } from "@halo-dev/components";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -43,82 +45,93 @@ const inputClasses = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex w-72 flex-col">
|
<div
|
||||||
<FormKit
|
class="flex h-screen flex-col items-center overflow-auto bg-white/90 pt-[20vh]"
|
||||||
id="setup-form"
|
>
|
||||||
v-model="formState"
|
<IconLogo class="mb-8 flex-none" />
|
||||||
name="setup-form"
|
|
||||||
:actions="false"
|
<div class="flex w-72 flex-col">
|
||||||
:classes="{
|
<H2WarningAlert class="mb-3" />
|
||||||
form: '!divide-none',
|
|
||||||
}"
|
<FormKit
|
||||||
:config="{ validationVisibility: 'submit' }"
|
id="setup-form"
|
||||||
type="form"
|
v-model="formState"
|
||||||
@submit="handleSubmit"
|
name="setup-form"
|
||||||
@keyup.enter="$formkit.submit('setup-form')"
|
:actions="false"
|
||||||
|
:classes="{
|
||||||
|
form: '!divide-none',
|
||||||
|
}"
|
||||||
|
:config="{ validationVisibility: 'submit' }"
|
||||||
|
type="form"
|
||||||
|
@submit="handleSubmit"
|
||||||
|
@keyup.enter="$formkit.submit('setup-form')"
|
||||||
|
>
|
||||||
|
<FormKit
|
||||||
|
name="siteTitle"
|
||||||
|
:classes="inputClasses"
|
||||||
|
:autofocus="true"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.site_title.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.site_title.label')"
|
||||||
|
validation="required:trim|length:0,100"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="email"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.email.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.email.label')"
|
||||||
|
validation="required|email|length:0,100"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="username"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="text"
|
||||||
|
:validation-label="$t('core.setup.fields.username.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.username.label')"
|
||||||
|
:validation="[
|
||||||
|
['required'],
|
||||||
|
['length:0,63'],
|
||||||
|
[
|
||||||
|
'matches',
|
||||||
|
/^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
|
||||||
|
],
|
||||||
|
]"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="password"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="password"
|
||||||
|
:validation-label="$t('core.setup.fields.password.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.password.label')"
|
||||||
|
validation="required:trim|length:5,100|matches:/^\S.*\S$/"
|
||||||
|
autocomplete="current-password"
|
||||||
|
></FormKit>
|
||||||
|
<FormKit
|
||||||
|
name="password_confirm"
|
||||||
|
:classes="inputClasses"
|
||||||
|
type="password"
|
||||||
|
:validation-label="$t('core.setup.fields.confirm_password.label')"
|
||||||
|
:placeholder="$t('core.setup.fields.confirm_password.label')"
|
||||||
|
validation="confirm|required:trim|length:5,100|matches:/^\S.*\S$/"
|
||||||
|
autocomplete="current-password"
|
||||||
|
></FormKit>
|
||||||
|
</FormKit>
|
||||||
|
<VButton
|
||||||
|
block
|
||||||
|
class="mt-8"
|
||||||
|
type="secondary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="$formkit.submit('setup-form')"
|
||||||
|
>
|
||||||
|
{{ $t("core.setup.operations.submit.button") }}
|
||||||
|
</VButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5"
|
||||||
>
|
>
|
||||||
<FormKit
|
<LocaleChange />
|
||||||
name="siteTitle"
|
</div>
|
||||||
:classes="inputClasses"
|
|
||||||
:autofocus="true"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.site_title.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.site_title.label')"
|
|
||||||
validation="required:trim|length:0,100"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="email"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.email.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.email.label')"
|
|
||||||
validation="required|email|length:0,100"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="username"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="text"
|
|
||||||
:validation-label="$t('core.setup.fields.username.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.username.label')"
|
|
||||||
:validation="[
|
|
||||||
['required'],
|
|
||||||
['length:0,63'],
|
|
||||||
[
|
|
||||||
'matches',
|
|
||||||
/^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/,
|
|
||||||
],
|
|
||||||
]"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="password"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="password"
|
|
||||||
:validation-label="$t('core.setup.fields.password.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.password.label')"
|
|
||||||
validation="required:trim|length:5,100|matches:/^\S.*\S$/"
|
|
||||||
autocomplete="current-password"
|
|
||||||
></FormKit>
|
|
||||||
<FormKit
|
|
||||||
name="password_confirm"
|
|
||||||
:classes="inputClasses"
|
|
||||||
type="password"
|
|
||||||
:validation-label="$t('core.setup.fields.confirm_password.label')"
|
|
||||||
:placeholder="$t('core.setup.fields.confirm_password.label')"
|
|
||||||
validation="confirm|required:trim|length:5,100|matches:/^\S.*\S$/"
|
|
||||||
autocomplete="current-password"
|
|
||||||
></FormKit>
|
|
||||||
</FormKit>
|
|
||||||
<VButton
|
|
||||||
block
|
|
||||||
class="mt-8"
|
|
||||||
type="secondary"
|
|
||||||
:loading="loading"
|
|
||||||
@click="$formkit.submit('setup-form')"
|
|
||||||
>
|
|
||||||
{{ $t("core.setup.operations.submit.button") }}
|
|
||||||
</VButton>
|
|
||||||
</div>
|
|
||||||
<div class="bottom-0 mb-10 mt-auto flex items-center justify-center gap-2.5">
|
|
||||||
<LocaleChange />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Info } from "@/types";
|
||||||
|
import { VAlert } from "@halo-dev/components";
|
||||||
|
import { useQuery } from "@tanstack/vue-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const { data: info } = useQuery<Info>({
|
||||||
|
queryKey: ["system-info"],
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await axios.get<Info>(`/actuator/info`, {
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
retry: 0,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<VAlert
|
||||||
|
v-if="!info?.database.name.startsWith('H2')"
|
||||||
|
class="mt-3"
|
||||||
|
type="warning"
|
||||||
|
:title="$t('core.components.h2_warning_alert.title')"
|
||||||
|
:closable="false"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
{{ $t("core.components.h2_warning_alert.description") }}
|
||||||
|
</template>
|
||||||
|
</VAlert>
|
||||||
|
</template>
|
|
@ -1428,11 +1428,6 @@ core:
|
||||||
The external access url detected is inconsistent with the current access
|
The external access url detected is inconsistent with the current access
|
||||||
url, which may cause some links to fail to redirect properly. Please
|
url, which may cause some links to fail to redirect properly. Please
|
||||||
check the external access url settings.
|
check the external access url settings.
|
||||||
h2_warning: >-
|
|
||||||
H2 database is only used in development and testing environments. It is
|
|
||||||
not recommended to use H2 database in production environment.
|
|
||||||
|
|
||||||
If you must use it, please back up your data on time.
|
|
||||||
backup:
|
backup:
|
||||||
title: Backup and Restore
|
title: Backup and Restore
|
||||||
tabs:
|
tabs:
|
||||||
|
@ -1699,6 +1694,13 @@ core:
|
||||||
aspect_ratio_square: Crop square
|
aspect_ratio_square: Crop square
|
||||||
aspect_ratio_landscape: Crop landscape (16:9)
|
aspect_ratio_landscape: Crop landscape (16:9)
|
||||||
aspect_ratio_portrait: Crop portrait (9:16)
|
aspect_ratio_portrait: Crop portrait (9:16)
|
||||||
|
h2_warning_alert:
|
||||||
|
title: "Warning: H2 database in use"
|
||||||
|
description: >-
|
||||||
|
The H2 database is only suitable for development and testing
|
||||||
|
environments and is not recommended for use in production environments.
|
||||||
|
H2 is very easy to cause data file corruption due to improper operation.
|
||||||
|
If you must use it, please back up the data on time.
|
||||||
composables:
|
composables:
|
||||||
content_cache:
|
content_cache:
|
||||||
toast_recovered: Recovered unsaved content from cache
|
toast_recovered: Recovered unsaved content from cache
|
||||||
|
|
|
@ -1335,7 +1335,6 @@ core:
|
||||||
os: 操作系统:{os}
|
os: 操作系统:{os}
|
||||||
alert:
|
alert:
|
||||||
external_url_invalid: 检测到外部访问地址与当前访问地址不一致,可能会导致部分链接无法正常跳转,请检查外部访问地址设置。
|
external_url_invalid: 检测到外部访问地址与当前访问地址不一致,可能会导致部分链接无法正常跳转,请检查外部访问地址设置。
|
||||||
h2_warning: H2 数据库仅用于开发环境和测试环境,不推荐在生产环境中使用 H2 数据库。如果必须要使用,请按时进行数据备份。
|
|
||||||
backup:
|
backup:
|
||||||
title: 备份与恢复
|
title: 备份与恢复
|
||||||
tabs:
|
tabs:
|
||||||
|
@ -1611,6 +1610,9 @@ core:
|
||||||
aspect_ratio_square: 裁剪为正方形
|
aspect_ratio_square: 裁剪为正方形
|
||||||
aspect_ratio_landscape: 裁剪为横向 (16:9)
|
aspect_ratio_landscape: 裁剪为横向 (16:9)
|
||||||
aspect_ratio_portrait: 裁剪为纵向 (9:16)
|
aspect_ratio_portrait: 裁剪为纵向 (9:16)
|
||||||
|
h2_warning_alert:
|
||||||
|
title: 警告:正在使用 H2 数据库
|
||||||
|
description: H2 数据库仅适用于开发环境和测试环境,不推荐在生产环境中使用,H2 非常容易因为操作不当导致数据文件损坏。如果必须要使用,请按时进行数据备份。
|
||||||
composables:
|
composables:
|
||||||
content_cache:
|
content_cache:
|
||||||
toast_recovered: 已从缓存中恢复未保存的内容
|
toast_recovered: 已从缓存中恢复未保存的内容
|
||||||
|
|
|
@ -1314,9 +1314,6 @@ core:
|
||||||
os: 操作系統:{os}
|
os: 操作系統:{os}
|
||||||
alert:
|
alert:
|
||||||
external_url_invalid: 檢測到外部訪問地址與當前訪問地址不一致,可能會導致部分連結無法正常跳轉,請檢查外部訪問地址設置。
|
external_url_invalid: 檢測到外部訪問地址與當前訪問地址不一致,可能會導致部分連結無法正常跳轉,請檢查外部訪問地址設置。
|
||||||
h2_warning: |-
|
|
||||||
H2 資料庫僅用於開發環境和測試環境,不建議在生產環境中使用 H2 資料庫。
|
|
||||||
如果必須要使用,請按時進行資料備份。
|
|
||||||
backup:
|
backup:
|
||||||
title: 備份與還原
|
title: 備份與還原
|
||||||
tabs:
|
tabs:
|
||||||
|
@ -1568,6 +1565,11 @@ core:
|
||||||
aspect_ratio_square: 裁剪為正方形
|
aspect_ratio_square: 裁剪為正方形
|
||||||
aspect_ratio_landscape: 裁剪為橫向 (16:9)
|
aspect_ratio_landscape: 裁剪為橫向 (16:9)
|
||||||
aspect_ratio_portrait: 裁剪為縱向 (9:16)
|
aspect_ratio_portrait: 裁剪為縱向 (9:16)
|
||||||
|
h2_warning_alert:
|
||||||
|
title: 警告:正在使用 H2 資料庫
|
||||||
|
description: >-
|
||||||
|
H2 資料庫僅適用於開發環境和測試環境,不建議在生產環境中使用,H2
|
||||||
|
非常容易因為操作不當而導致資料檔案損壞。如果必須要使用,請按時進行資料備份。
|
||||||
composables:
|
composables:
|
||||||
content_cache:
|
content_cache:
|
||||||
toast_recovered: 已從緩存中恢復未保存的內容
|
toast_recovered: 已從緩存中恢復未保存的內容
|
||||||
|
|
Loading…
Reference in New Issue