Merge branch 'main' into refactor/setting-config-update

pull/6661/head
Ryan Wang 2024-09-28 17:52:12 +08:00 committed by GitHub
commit 982a45bd32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 466 additions and 357 deletions

View File

@ -26,6 +26,7 @@ import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.web.filter.reactive.ServerWebExchangeContextFilter;
import org.springframework.web.reactive.config.ResourceHandlerRegistration; import org.springframework.web.reactive.config.ResourceHandlerRegistration;
import org.springframework.web.reactive.config.ResourceHandlerRegistry; import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer; import org.springframework.web.reactive.config.WebFluxConfigurer;
@ -252,4 +253,11 @@ public class WebFluxConfig implements WebFluxConfigurer {
return new AdditionalWebFilterChainProxy(extensionGetter); return new AdditionalWebFilterChainProxy(extensionGetter);
} }
@Bean
// We expect this filter to be executed before AdditionalWebFilterChainProxy
@Order(-102)
ServerWebExchangeContextFilter serverWebExchangeContextFilter() {
return new ServerWebExchangeContextFilter();
}
} }

View File

@ -1,6 +1,7 @@
package run.halo.app.config; package run.halo.app.config;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.net.URI; import java.net.URI;
@ -18,10 +19,15 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.filter.reactive.ServerWebExchangeContextFilter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.socket.WebSocketHandler; import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage; import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier; import reactor.test.StepVerifier;
import run.halo.app.core.endpoint.WebSocketEndpoint; import run.halo.app.core.endpoint.WebSocketEndpoint;
import run.halo.app.core.extension.Role; import run.halo.app.core.extension.Role;
@ -31,7 +37,10 @@ import run.halo.app.extension.Metadata;
@SpringBootTest(properties = "halo.console.location=classpath:/console/", webEnvironment = @SpringBootTest(properties = "halo.console.location=classpath:/console/", webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT) SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(WebFluxConfigTest.WebSocketSupportTest.TestWebSocketConfiguration.class) @Import({
WebFluxConfigTest.WebSocketSupportTest.TestWebSocketConfiguration.class,
WebFluxConfigTest.ServerWebExchangeContextFilterTest.TestConfig.class
})
@AutoConfigureWebTestClient @AutoConfigureWebTestClient
class WebFluxConfigTest { class WebFluxConfigTest {
@ -154,4 +163,34 @@ class WebFluxConfigTest {
.expectStatus().isNotFound(); .expectStatus().isNotFound();
} }
} }
@Nested
class ServerWebExchangeContextFilterTest {
@TestConfiguration
static class TestConfig {
@Bean
RouterFunction<ServerResponse> assertServerWebExchangeRoute() {
return RouterFunctions.route()
.GET("/assert-server-web-exchange",
request -> Mono.deferContextual(contextView -> {
var exchange = ServerWebExchangeContextFilter.getExchange(contextView);
assertTrue(exchange.isPresent());
return ServerResponse.ok().build();
}))
.build();
}
}
@Test
void shouldGetExchangeFromContextView() {
webClient.get().uri("/assert-server-web-exchange")
.exchange()
.expectStatus().isOk();
}
}
} }

View File

@ -364,11 +364,9 @@ const handleApproveInBatch = async () => {
:title="$t('core.comment.empty.title')" :title="$t('core.comment.empty.title')"
> >
<template #actions> <template #actions>
<VSpace>
<VButton @click="refetch"> <VButton @click="refetch">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
</VSpace>
</template> </template>
</VEmpty> </VEmpty>
</Transition> </Transition>

View File

@ -281,7 +281,7 @@ watch(
<VButton <VButton
v-permission="['system:singlepages:view']" v-permission="['system:singlepages:view']"
:route="{ name: 'SinglePages' }" :route="{ name: 'SinglePages' }"
type="primary" type="secondary"
> >
{{ $t("core.common.buttons.back") }} {{ $t("core.common.buttons.back") }}
</VButton> </VButton>

View File

@ -432,7 +432,7 @@ watch(selectedPageNames, (newValue) => {
<VButton <VButton
v-permission="['system:singlepages:manage']" v-permission="['system:singlepages:manage']"
:route="{ name: 'SinglePageEditor' }" :route="{ name: 'SinglePageEditor' }"
type="primary" type="secondary"
> >
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />

View File

@ -280,7 +280,7 @@ watch(
<VButton @click="refetch"> <VButton @click="refetch">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
<VButton :route="{ name: 'Posts' }" type="primary"> <VButton :route="{ name: 'Posts' }" type="secondary">
{{ $t("core.common.buttons.back") }} {{ $t("core.common.buttons.back") }}
</VButton> </VButton>
</VSpace> </VSpace>

View File

@ -563,7 +563,7 @@ watch(
<VButton <VButton
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
:route="{ name: 'PostEditor' }" :route="{ name: 'PostEditor' }"
type="primary" type="secondary"
> >
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />

View File

@ -117,7 +117,7 @@ const handleUpdateInBatch = useDebounceFn(async () => {
</VButton> </VButton>
<VButton <VButton
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
type="primary" type="secondary"
@click="creationModal = true" @click="creationModal = true"
> >
<template #icon> <template #icon>

View File

@ -27,7 +27,7 @@ const props = withDefaults(
defineProps<{ defineProps<{
category?: Category; category?: Category;
parentCategory?: Category; parentCategory?: Category;
isChildLevelCategory: boolean; isChildLevelCategory?: boolean;
}>(), }>(),
{ {
category: undefined, category: undefined,

View File

@ -267,7 +267,7 @@ watch(selectedTagNames, (newVal) => {
<VButton @click="() => handleFetchTags"> <VButton @click="() => handleFetchTags">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
<VButton type="primary" @click="editingModal = true"> <VButton type="secondary" @click="editingModal = true">
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />
</template> </template>

View File

@ -259,7 +259,7 @@ const handleDelete = async (menuItem: MenuTreeItem) => {
</VButton> </VButton>
<VButton <VButton
v-permission="['system:menus:manage']" v-permission="['system:menus:manage']"
type="primary" type="secondary"
@click="menuItemEditingModal = true" @click="menuItemEditingModal = true"
> >
<template #icon> <template #icon>

View File

@ -12,7 +12,6 @@ import {
VEntity, VEntity,
VEntityField, VEntityField,
VLoading, VLoading,
VSpace,
VStatusDot, VStatusDot,
VTag, VTag,
} from "@halo-dev/components"; } from "@halo-dev/components";
@ -187,11 +186,9 @@ const handleSetPrimaryMenu = async (menu: Menu) => {
:title="$t('core.menu.empty.title')" :title="$t('core.menu.empty.title')"
> >
<template #actions> <template #actions>
<VSpace>
<VButton size="sm" @click="refetch()"> <VButton size="sm" @click="refetch()">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
</VSpace>
</template> </template>
</VEmpty> </VEmpty>
</Transition> </Transition>

View File

@ -81,7 +81,7 @@ const handleOpenPreview = (theme: Theme) => {
</VButton> </VButton>
<VButton <VButton
v-permission="['system:themes:manage']" v-permission="['system:themes:manage']"
type="primary" type="secondary"
@click="activeTabId = 'local-upload'" @click="activeTabId = 'local-upload'"
> >
<template #icon> <template #icon>

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Theme } from "@halo-dev/api-client"; import type { Theme } from "@halo-dev/api-client";
import { consoleApiClient } from "@halo-dev/api-client"; import { consoleApiClient } from "@halo-dev/api-client";
import { VButton, VEmpty, VLoading, VSpace } from "@halo-dev/components"; import { VButton, VEmpty, VLoading } from "@halo-dev/components";
import { useQuery } from "@tanstack/vue-query"; import { useQuery } from "@tanstack/vue-query";
import ThemeListItem from "../ThemeListItem.vue"; import ThemeListItem from "../ThemeListItem.vue";
@ -29,11 +29,9 @@ const {
<Transition v-else-if="!themes?.length" appear name="fade"> <Transition v-else-if="!themes?.length" appear name="fade">
<VEmpty :title="$t('core.theme.list_modal.not_installed_empty.title')"> <VEmpty :title="$t('core.theme.list_modal.not_installed_empty.title')">
<template #actions> <template #actions>
<VSpace>
<VButton :loading="isFetching" @click="refetch"> <VButton :loading="isFetching" @click="refetch">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
</VSpace>
</template> </template>
</VEmpty> </VEmpty>
</Transition> </Transition>

View File

@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import StickyBlock from "@/components/sticky-block/StickyBlock.vue";
import { useSettingFormConvert } from "@console/composables/use-setting-form"; import { useSettingFormConvert } from "@console/composables/use-setting-form";
import { useThemeStore } from "@console/stores/theme"; import { useThemeStore } from "@console/stores/theme";
import type { import type {
@ -28,7 +29,6 @@ import { storeToRefs } from "pinia";
import { computed, markRaw, onMounted, ref, toRaw } from "vue"; import { computed, markRaw, onMounted, ref, toRaw } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import ThemePreviewListItem from "./ThemePreviewListItem.vue"; import ThemePreviewListItem from "./ThemePreviewListItem.vue";
import StickyBlock from "@/components/sticky-block/StickyBlock.vue";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -304,6 +304,7 @@ const iframeClasses = computed(() => {
@after-leave="switching = false" @after-leave="switching = false"
> >
<div v-show="settingsVisible" class="mb-20"> <div v-show="settingsVisible" class="mb-20">
<!-- @vue-skip -->
<VTabbar <VTabbar
v-model:active-id="activeSettingTab" v-model:active-id="activeSettingTab"
:items="settingTabs" :items="settingTabs"

View File

@ -235,7 +235,7 @@ onMounted(() => {
<VButton @click="themesModal = true"> <VButton @click="themesModal = true">
{{ $t("core.theme.common.buttons.install") }} {{ $t("core.theme.common.buttons.install") }}
</VButton> </VButton>
<VButton type="primary" @click="themesModal = true"> <VButton type="secondary" @click="themesModal = true">
<template #icon> <template #icon>
<IconExchange class="h-full w-full" /> <IconExchange class="h-full w-full" />
</template> </template>

View File

@ -66,6 +66,7 @@ const handleChangePassword = async () => {
:title="$t('core.user.change_password_modal.title')" :title="$t('core.user.change_password_modal.title')"
@close="emit('close')" @close="emit('close')"
> >
<!-- @vue-ignore -->
<FormKit <FormKit
id="password-form" id="password-form"
v-model="formState" v-model="formState"

View File

@ -50,6 +50,7 @@ const inputClasses = {
<IconLogo class="mb-8 flex-none" /> <IconLogo class="mb-8 flex-none" />
<div class="flex w-72 flex-col"> <div class="flex w-72 flex-col">
<!-- @vue-ignore -->
<FormKit <FormKit
id="setup-form" id="setup-form"
v-model="formState" v-model="formState"

View File

@ -100,7 +100,7 @@
"short-unique-id": "^5.0.2", "short-unique-id": "^5.0.2",
"transliteration": "^2.3.5", "transliteration": "^2.3.5",
"ua-parser-js": "^1.0.38", "ua-parser-js": "^1.0.38",
"vue": "^3.4.27", "vue": "^3.5.8",
"vue-demi": "^0.14.7", "vue-demi": "^0.14.7",
"vue-draggable-plus": "^0.4.1", "vue-draggable-plus": "^0.4.1",
"vue-grid-layout": "3.0.0-beta1", "vue-grid-layout": "3.0.0-beta1",
@ -122,7 +122,7 @@
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@types/randomstring": "^1.1.8", "@types/randomstring": "^1.1.8",
"@types/ua-parser-js": "^0.7.39", "@types/ua-parser-js": "^0.7.39",
"@vitejs/plugin-vue": "^5.1.2", "@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1", "@vitejs/plugin-vue-jsx": "^4.0.1",
"@vitest/ui": "^0.34.1", "@vitest/ui": "^0.34.1",
"@vue/compiler-sfc": "^3.4.27", "@vue/compiler-sfc": "^3.4.27",
@ -151,7 +151,7 @@
"tailwindcss": "^3.2.7", "tailwindcss": "^3.2.7",
"tailwindcss-safe-area": "^0.2.2", "tailwindcss-safe-area": "^0.2.2",
"tailwindcss-themer": "^2.0.3", "tailwindcss-themer": "^2.0.3",
"typescript": "~5.5.4", "typescript": "~5.6.2",
"unplugin-icons": "^0.19.2", "unplugin-icons": "^0.19.2",
"vite": "^5.4.1", "vite": "^5.4.1",
"vite-plugin-externals": "^0.6.2", "vite-plugin-externals": "^0.6.2",
@ -160,6 +160,6 @@
"vite-plugin-static-copy": "^1.0.6", "vite-plugin-static-copy": "^1.0.6",
"vite-plugin-vue-devtools": "^7.3.8", "vite-plugin-vue-devtools": "^7.3.8",
"vitest": "^0.34.1", "vitest": "^0.34.1",
"vue-tsc": "^2.0.29" "vue-tsc": "^2.1.6"
} }
} }

View File

@ -50,7 +50,7 @@
"rimraf": "^5.0.7", "rimraf": "^5.0.7",
"typescript": "~5.5.4", "typescript": "~5.5.4",
"unbuild": "^0.7.6", "unbuild": "^0.7.6",
"vite-plugin-dts": "^4.0.3" "vite-plugin-dts": "^4.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"axios": "^1.7.x" "axios": "^1.7.x"

View File

@ -58,10 +58,10 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"storybook": "^7.6.3", "storybook": "^7.6.3",
"unplugin-icons": "^0.14.15", "unplugin-icons": "^0.14.15",
"vite-plugin-dts": "^4.0.3" "vite-plugin-dts": "^4.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.4.27", "vue": "^3.5.8",
"vue-router": "^4.3.2" "vue-router": "^4.3.2"
}, },
"exports": { "exports": {

View File

@ -12,6 +12,7 @@ const meta: Meta<typeof VDialog> = {
height: 400, height: 400,
setup() { setup() {
const showDialog = () => { const showDialog = () => {
// @ts-ignore
args.visible = true; args.visible = true;
}; };

View File

@ -18,9 +18,12 @@ const meta: Meta<typeof VDropdown> = {
template: ` template: `
<div style="height: 300px"> <div style="height: 300px">
<VDropdown> <VDropdown>
${args.default} <VButton>Hello</VButton>
<template #popper> <template #popper>
${args.popper} <VDropdownItem></VDropdownItem>
<VDropdownDivider></VDropdownDivider>
<VDropdownItem></VDropdownItem>
<VDropdownItem></VDropdownItem>
</template> </template>
</VDropdown> </VDropdown>
</div> </div>
@ -34,13 +37,5 @@ export default meta;
type Story = StoryObj<typeof VDropdown>; type Story = StoryObj<typeof VDropdown>;
export const Default: Story = { export const Default: Story = {
args: { args: {},
default: `<VButton>Hello</VButton>`,
popper: `
<VDropdownItem></VDropdownItem>
<VDropdownDivider></VDropdownDivider>
<VDropdownItem></VDropdownItem>
<VDropdownItem></VDropdownItem>
`,
},
}; };

View File

@ -41,7 +41,7 @@ defineExpose({
</script> </script>
<template> <template>
<!-- @vue-ignore --> <!-- @vue-skip -->
<FloatingDropdown <FloatingDropdown
ref="dropdownRef" ref="dropdownRef"
:placement="placement" :placement="placement"

View File

@ -6,7 +6,7 @@ const props = withDefaults(
defineProps<{ defineProps<{
selected?: boolean; selected?: boolean;
disabled?: boolean; disabled?: boolean;
type: "default" | "danger"; type?: "default" | "danger";
}>(), }>(),
{ {
selected: false, selected: false,

View File

@ -1,7 +1,7 @@
{ {
"extends": "@vue/tsconfig/tsconfig.dom.json", "extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"], "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"], "exclude": ["src/**/__tests__/*", "node_modules"],
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"baseUrl": ".", "baseUrl": ".",

View File

@ -87,9 +87,9 @@
"@iconify/json": "^2.2.117", "@iconify/json": "^2.2.117",
"@types/linkifyjs": "^2.1.7", "@types/linkifyjs": "^2.1.7",
"release-it": "^16.1.5", "release-it": "^16.1.5",
"vite-plugin-dts": "^4.0.3" "vite-plugin-dts": "^4.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.4.27" "vue": "^3.5.8"
} }
} }

View File

@ -38,10 +38,10 @@
"homepage": "https://github.com/halo-dev/halo/tree/main/ui/packages/shared#readme", "homepage": "https://github.com/halo-dev/halo/tree/main/ui/packages/shared#readme",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"vite-plugin-dts": "^4.0.3" "vite-plugin-dts": "^4.2.2"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.4.27", "vue": "^3.5.8",
"vue-router": "^4.3.2" "vue-router": "^4.3.2"
}, },
"dependencies": { "dependencies": {

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,6 @@ export interface FileProps {
editor: CoreEditor; editor: CoreEditor;
} }
const { currentUserHasPermission } = usePermission();
/** /**
* Handles file events, determining if the file is an image and triggering the appropriate upload process. * Handles file events, determining if the file is an image and triggering the appropriate upload process.
* *
@ -21,6 +19,8 @@ const { currentUserHasPermission } = usePermission();
* @returns {boolean} - True if a file is handled, otherwise false * @returns {boolean} - True if a file is handled, otherwise false
*/ */
export const handleFileEvent = ({ file, editor }: FileProps) => { export const handleFileEvent = ({ file, editor }: FileProps) => {
const { currentUserHasPermission } = usePermission();
if (!file) { if (!file) {
return false; return false;
} }

View File

@ -3,12 +3,12 @@ import { onMounted, ref } from "vue";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
src: string; src?: string;
alt?: string; alt?: string;
classes?: string | string[]; classes?: string | string[];
}>(), }>(),
{ {
src: "", src: undefined,
alt: "", alt: "",
classes: "", classes: "",
} }
@ -18,8 +18,12 @@ const isLoading = ref(false);
const error = ref(false); const error = ref(false);
const loadImage = async () => { const loadImage = async () => {
if (!props.src) {
throw new Error("src is required");
}
const image = new Image(); const image = new Image();
image.src = props.src; image.src = props.src || "";
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
image.onload = () => resolve(image); image.onload = () => resolve(image);
image.onerror = (err) => reject(err); image.onerror = (err) => reject(err);

View File

@ -3,11 +3,11 @@ import { onMounted, ref } from "vue";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
src: string; src?: string;
classes?: string | string[]; classes?: string | string[];
}>(), }>(),
{ {
src: "", src: undefined,
classes: "", classes: "",
} }
); );
@ -16,6 +16,10 @@ const isLoading = ref(false);
const error = ref(false); const error = ref(false);
const loadVideo = async () => { const loadVideo = async () => {
if (!props.src) {
throw new Error("src is required");
}
const video = document.createElement("video"); const video = document.createElement("video");
video.src = props.src; video.src = props.src;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -1,8 +1,8 @@
import Logo from "@/assets/logo.png"; import Logo from "@/assets/logo.png";
import DefaultEditor from "@/components/editor/DefaultEditor.vue";
import { usePluginModuleStore } from "@/stores/plugin"; import { usePluginModuleStore } from "@/stores/plugin";
import { VLoading } from "@halo-dev/components";
import type { EditorProvider } from "@halo-dev/console-shared"; import type { EditorProvider } from "@halo-dev/console-shared";
import { defineAsyncComponent, markRaw, ref, type Ref } from "vue"; import { markRaw, ref, type Ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
interface useEditorExtensionPointsReturn { interface useEditorExtensionPointsReturn {
@ -19,13 +19,7 @@ export function useEditorExtensionPoints(): useEditorExtensionPointsReturn {
{ {
name: "default", name: "default",
displayName: t("core.plugin.extension_points.editor.providers.default"), displayName: t("core.plugin.extension_points.editor.providers.default"),
component: markRaw( component: markRaw(DefaultEditor),
defineAsyncComponent({
loader: () => import("@/components/editor/DefaultEditor.vue"),
loadingComponent: VLoading,
delay: 200,
})
),
rawType: "HTML", rawType: "HTML",
logo: Logo, logo: Logo,
}, },

View File

@ -485,7 +485,7 @@ core:
cover: cover:
label: 封面图 label: 封面图
deleted_page: deleted_page:
title: 自定义页面回收站 title: 页面回收站
empty: empty:
title: 没有自定义页面被放入回收站 title: 没有自定义页面被放入回收站
message: 你可以尝试刷新或者返回自定义页面管理 message: 你可以尝试刷新或者返回自定义页面管理

View File

@ -465,7 +465,7 @@ core:
cover: cover:
label: 封面圖 label: 封面圖
deleted_page: deleted_page:
title: 自定義頁面回收站 title: 頁面回收站
empty: empty:
title: 沒有自定義頁面被放入回收站 title: 沒有自定義頁面被放入回收站
message: 你可以嘗試刷新或者返回自定義頁面管理 message: 你可以嘗試刷新或者返回自定義頁面管理

View File

@ -17,7 +17,6 @@
"@uc/*": ["./uc-src/*"], "@uc/*": ["./uc-src/*"],
"@console/*": ["./console-src/*"] "@console/*": ["./console-src/*"]
}, },
"noStrictGenericChecks": true,
"ignoreDeprecations": "5.0", "ignoreDeprecations": "5.0",
"types": ["unplugin-icons/types/vue"] "types": ["unplugin-icons/types/vue"]
} }

View File

@ -175,7 +175,7 @@ const {
<VButton <VButton
v-permission="['system:posts:manage']" v-permission="['system:posts:manage']"
:route="{ name: 'PostEditor' }" :route="{ name: 'PostEditor' }"
type="primary" type="secondary"
> >
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />

View File

@ -78,6 +78,7 @@ const publishTimeHelp = computed(() => {
</script> </script>
<template> <template>
<!-- @vue-ignore -->
<FormKit <FormKit
id="post-setting-form" id="post-setting-form"
v-model="internalFormState" v-model="internalFormState"

View File

@ -56,6 +56,7 @@ const handleChangePassword = async () => {
:title="$t('core.uc_profile.change_password_modal.title')" :title="$t('core.uc_profile.change_password_modal.title')"
@close="emit('close')" @close="emit('close')"
> >
<!-- @vue-ignore -->
<FormKit <FormKit
id="password-form" id="password-form"
v-model="formState" v-model="formState"

View File

@ -120,6 +120,7 @@ const { mutate, isLoading } = useMutation({
</div> </div>
</div> </div>
<div class="mt-5 divide-y divide-gray-100 md:col-span-3 md:mt-0"> <div class="mt-5 divide-y divide-gray-100 md:col-span-3 md:mt-0">
<!-- @vue-ignore -->
<FormKit <FormKit
id="pat-creation-form" id="pat-creation-form"
v-model="formState.spec" v-model="formState.spec"

View File

@ -56,7 +56,7 @@ const creationModal = ref(false);
<VButton @click="refetch"> <VButton @click="refetch">
{{ $t("core.common.buttons.refresh") }} {{ $t("core.common.buttons.refresh") }}
</VButton> </VButton>
<VButton type="primary" @click="creationModal = true"> <VButton type="secondary" @click="creationModal = true">
<template #icon> <template #icon>
<IconAddCircle class="h-full w-full" /> <IconAddCircle class="h-full w-full" />
</template> </template>