feat: add devices mock preview for post and single page (#4846)

#### What type of PR is this?
/kind feature
/area console


#### What this PR does / why we need it:
为文章以及页面预览增加终端切换功能,类似于预览主题的终端切换

#### Which issue(s) this PR fixes:

Fixes #4789

#### Special notes for your reviewer:
测试方式:
本地运行halo,预览文章和页面,切换不同终端,各个界面正常显示且功能正常。


#### Does this PR introduce a user-facing change?

```release-note
文章预览支持模拟不同设备尺寸。
```
pull/4842/head^2
inkslab 2023-11-13 12:06:08 +08:00 committed by GitHub
parent 841aa96e59
commit 4a6ce88b7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 2 deletions

View File

@ -1,5 +1,13 @@
<script lang="ts" setup>
import { VModal, IconLink } from "@halo-dev/components";
import {
VModal,
IconLink,
VTabbar,
IconComputer,
IconTablet,
IconPhone,
} from "@halo-dev/components";
import { computed, markRaw, ref } from "vue";
withDefaults(
defineProps<{
@ -25,6 +33,32 @@ const onVisibleChange = (visible: boolean) => {
emit("close");
}
};
const mockDevices = [
{
id: "desktop",
icon: markRaw(IconComputer),
},
{
id: "tablet",
icon: markRaw(IconTablet),
},
{
id: "phone",
icon: markRaw(IconPhone),
},
];
const deviceActiveId = ref(mockDevices[0].id);
const iframeClasses = computed(() => {
if (deviceActiveId.value === "desktop") {
return "w-full h-full";
}
if (deviceActiveId.value === "tablet") {
return "w-2/3 h-2/3 ring-2 rounded ring-gray-300";
}
return "w-96 h-[50rem] ring-2 rounded ring-gray-300";
});
</script>
<template>
<VModal
@ -35,6 +69,14 @@ const onVisibleChange = (visible: boolean) => {
:layer-closable="true"
@update:visible="onVisibleChange"
>
<template #center>
<!-- TODO: Reactor VTabbar component to support icon prop -->
<VTabbar
v-model:active-id="deviceActiveId"
:items="mockDevices as any"
type="outline"
></VTabbar>
</template>
<template #actions>
<slot name="actions"></slot>
<span>
@ -46,7 +88,8 @@ const onVisibleChange = (visible: boolean) => {
<div class="flex h-full items-center justify-center">
<iframe
v-if="visible"
class="h-full w-full border-none transition-all duration-300"
class="border-none transition-all duration-500"
:class="iframeClasses"
:src="url"
></iframe>
</div>