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
Ryan Wang 2024-08-26 10:29:12 +08:00 committed by GitHub
parent 2b84b41987
commit 3767a5a239
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 141 additions and 107 deletions

View File

@ -1,4 +1,5 @@
<script lang="ts" setup>
import H2WarningAlert from "@/components/alerts/H2WarningAlert.vue";
import type { GlobalInfo, Info, Startup } from "@/types";
import { formatDatetime } from "@/utils/date";
import { usePermission } from "@/utils/permission";
@ -364,17 +365,7 @@ const handleDownloadLogfile = () => {
<span>
{{ [info.database.name, info.database.version].join(" / ") }}
</span>
<VAlert
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>
<H2WarningAlert class="mt-3" />
</VDescriptionItem>
<VDescriptionItem :label="$t('core.overview.fields.os')">
{{ info.os.name }} {{ info.os.version }} / {{ info.os.arch }}

View File

@ -57,17 +57,11 @@ export const routes: Array<RouteRecordRaw> = [
},
{
path: "/setup",
component: GatewayLayout,
children: [
{
path: "",
name: "Setup",
component: Setup,
meta: {
title: "core.setup.title",
},
},
],
component: Setup,
name: "Setup",
meta: {
title: "core.setup.title",
},
},
{
path: "/setup-initial-data",

View File

@ -1,4 +1,5 @@
<script lang="ts" setup>
import H2WarningAlert from "@/components/alerts/H2WarningAlert.vue";
import LocaleChange from "@/components/common/LocaleChange.vue";
import { useGlobalInfoStore } from "@/stores/global-info";
import type { SystemInitializationRequest } from "@halo-dev/api-client";
@ -7,6 +8,7 @@ import { Toast, VButton } from "@halo-dev/components";
import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import IconLogo from "~icons/core/logo?width=5rem&height=2rem";
const router = useRouter();
const { t } = useI18n();
@ -43,82 +45,93 @@ const inputClasses = {
</script>
<template>
<div class="flex w-72 flex-col">
<FormKit
id="setup-form"
v-model="formState"
name="setup-form"
:actions="false"
:classes="{
form: '!divide-none',
}"
:config="{ validationVisibility: 'submit' }"
type="form"
@submit="handleSubmit"
@keyup.enter="$formkit.submit('setup-form')"
<div
class="flex h-screen flex-col items-center overflow-auto bg-white/90 pt-[20vh]"
>
<IconLogo class="mb-8 flex-none" />
<div class="flex w-72 flex-col">
<H2WarningAlert class="mb-3" />
<FormKit
id="setup-form"
v-model="formState"
name="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
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">
<LocaleChange />
<LocaleChange />
</div>
</div>
</template>

View File

@ -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>

View File

@ -1428,11 +1428,6 @@ core:
The external access url detected is inconsistent with the current access
url, which may cause some links to fail to redirect properly. Please
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:
title: Backup and Restore
tabs:
@ -1699,6 +1694,13 @@ core:
aspect_ratio_square: Crop square
aspect_ratio_landscape: Crop landscape (16:9)
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:
content_cache:
toast_recovered: Recovered unsaved content from cache

View File

@ -1335,7 +1335,6 @@ core:
os: 操作系统:{os}
alert:
external_url_invalid: 检测到外部访问地址与当前访问地址不一致,可能会导致部分链接无法正常跳转,请检查外部访问地址设置。
h2_warning: H2 数据库仅用于开发环境和测试环境,不推荐在生产环境中使用 H2 数据库。如果必须要使用,请按时进行数据备份。
backup:
title: 备份与恢复
tabs:
@ -1611,6 +1610,9 @@ core:
aspect_ratio_square: 裁剪为正方形
aspect_ratio_landscape: 裁剪为横向 (16:9)
aspect_ratio_portrait: 裁剪为纵向 (9:16)
h2_warning_alert:
title: 警告:正在使用 H2 数据库
description: H2 数据库仅适用于开发环境和测试环境不推荐在生产环境中使用H2 非常容易因为操作不当导致数据文件损坏。如果必须要使用,请按时进行数据备份。
composables:
content_cache:
toast_recovered: 已从缓存中恢复未保存的内容

View File

@ -1314,9 +1314,6 @@ core:
os: 操作系統:{os}
alert:
external_url_invalid: 檢測到外部訪問地址與當前訪問地址不一致,可能會導致部分連結無法正常跳轉,請檢查外部訪問地址設置。
h2_warning: |-
H2 資料庫僅用於開發環境和測試環境,不建議在生產環境中使用 H2 資料庫。
如果必須要使用,請按時進行資料備份。
backup:
title: 備份與還原
tabs:
@ -1568,6 +1565,11 @@ core:
aspect_ratio_square: 裁剪為正方形
aspect_ratio_landscape: 裁剪為橫向 (16:9)
aspect_ratio_portrait: 裁剪為縱向 (9:16)
h2_warning_alert:
title: 警告:正在使用 H2 資料庫
description: >-
H2 資料庫僅適用於開發環境和測試環境不建議在生產環境中使用H2
非常容易因為操作不當而導致資料檔案損壞。如果必須要使用,請按時進行資料備份。
composables:
content_cache:
toast_recovered: 已從緩存中恢復未保存的內容