Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion apps/web/src/components/CodemirrorEditor/CssEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ import { useDisplayStore, useStore } from '@/stores'
const store = useStore()
const displayStore = useDisplayStore()

// 控制是否启用动画
const enableAnimation = ref(false)

// 监听 CssEditor 开关状态变化
watch(() => displayStore.isShowCssEditor, () => {
if (store.isMobile) {
// 在移动端,用户操作时启用动画
enableAnimation.value = true
}
})

// 监听设备类型变化,重置动画状态
watch(() => store.isMobile, () => {
enableAnimation.value = false
})

const isOpenEditDialog = ref(false)
const editInputVal = ref(``)
const tabHistory = ref([``, store.cssContentConfig.active])
Expand Down Expand Up @@ -103,8 +119,37 @@ function tabChanged(tabName: string | number) {
</script>

<template>
<!-- 移动端遮罩层 -->
<div
v-if="store.isMobile && displayStore.isShowCssEditor"
class="fixed inset-0 bg-black/50 z-40"
@click="displayStore.isShowCssEditor = false"
/>

<transition enter-active-class="bounceInRight">
<div v-show="displayStore.isShowCssEditor" class="cssEditor-wrapper h-full flex flex-col border-l-2 border-gray/50">
<div
v-show="displayStore.isShowCssEditor"
class="cssEditor-wrapper h-full flex flex-col mobile-css-editor"
:class="{
// 移动端样式
'fixed top-0 right-0 w-full h-full z-100 bg-background border-l shadow-lg': store.isMobile,
'animate': store.isMobile && enableAnimation,
// 桌面端样式
'border-l-2 flex-1 order-2 border-gray/50': !store.isMobile,
}"
:style="{
transform: store.isMobile ? (displayStore.isShowCssEditor ? 'translateX(0)' : 'translateX(100%)') : undefined,
}"
>
<!-- 移动端标题栏 -->
<div v-if="store.isMobile" class="sticky top-0 z-10 flex items-center justify-between px-4 py-3 border-b mb-2 bg-background">
<h2 class="text-lg font-semibold">
自定义 CSS
</h2>
<Button variant="ghost" size="sm" @click="displayStore.isShowCssEditor = false">
<X class="h-4 w-4" />
</Button>
</div>
<Tabs
v-model="store.cssContentConfig.active"
@update:model-value="tabChanged"
Expand Down Expand Up @@ -200,6 +245,12 @@ function tabChanged(tabName: string | number) {
</template>

<style lang="less" scoped>
/* 移动端CSS编辑器动画 - 只有添加了 animate 类才启用 */
.mobile-css-editor.animate {
transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* 桌面端的bounceInRight动画 */
.bounceInRight {
animation-name: bounceInRight;
animation-duration: 1s;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function onRedirect(url: string) {
style="width: 40%"
>
</div>
<DialogFooter class="sm:justify-evenly">
<DialogFooter class="sm:justify-evenly flex flex-wrap gap-2">
<Button
v-for="link in links"
:key="link.url"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
<script setup lang="ts">
import { ClipboardPasteIcon, Contact2Icon, CopyIcon, Redo2Icon, TableIcon, Undo2Icon, UploadCloudIcon } from 'lucide-vue-next'

const props = withDefaults(defineProps<{
asSub?: boolean
}>(), {
asSub: false,
})

const { asSub } = toRefs(props)

const { toggleShowInsertFormDialog, toggleShowUploadImgDialog, toggleShowInsertMpCardDialog } = useDisplayStore()

const { copyToClipboard, pasteFromClipboard, undo, redo } = useStore()
</script>

<template>
<MenubarMenu>
<!-- 作为 MenubarSub 使用 -->
<MenubarSub v-if="asSub">
<MenubarSubTrigger>
编辑
</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem @click="undo()">
<Undo2Icon class="mr-2 h-4 w-4" />
撤销
</MenubarItem>
<MenubarItem @click="redo()">
<Redo2Icon class="mr-2 h-4 w-4" />
重做
</MenubarItem>
<MenubarSeparator />
<MenubarItem @click="toggleShowUploadImgDialog()">
<UploadCloudIcon class="mr-2 h-4 w-4" />
上传图片
</MenubarItem>
<MenubarItem @click="toggleShowInsertFormDialog()">
<TableIcon class="mr-2 h-4 w-4" />
插入表格
</MenubarItem>
<MenubarItem @click="toggleShowInsertMpCardDialog()">
<Contact2Icon class="mr-2 h-4 w-4" />
插入公众号名片
</MenubarItem>
<MenubarSeparator />
<MenubarItem @click="copyToClipboard()">
<CopyIcon class="mr-2 h-4 w-4" />
复制
</MenubarItem>
<MenubarItem @click="pasteFromClipboard()">
<ClipboardPasteIcon class="mr-2 h-4 w-4" />
粘贴
</MenubarItem>
</MenubarSubContent>
</MenubarSub>

<!-- 作为 MenubarMenu 使用(默认) -->
<MenubarMenu v-else>
<MenubarTrigger>
编辑
</MenubarTrigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
import { Download, FileCode, FileCog, FileText, Upload } from 'lucide-vue-next'
import { useStore } from '@/stores'

const props = withDefaults(defineProps<{
asSub?: boolean
}>(), {
asSub: false,
})

const emit = defineEmits([`openEditorState`])

const { asSub } = toRefs(props)

const store = useStore()

const {
isDark,
isEditOnLeft,
} = storeToRefs(store)
const { isDark, isEditOnLeft, isOpenPostSlider } = storeToRefs(store)

const {
exportEditorContent2HTML,
Expand All @@ -17,13 +24,66 @@ const {
exportEditorContent2PDF,
} = store

const editorStateDialogVisible = ref(false)

const importMarkdownContent = useImportMarkdownContent()

function openEditorStateDialog() {
emit(`openEditorState`)
}
</script>

<template>
<MenubarMenu>
<!-- 作为 MenubarSub 使用 -->
<MenubarSub v-if="asSub">
<MenubarSubTrigger>
文件
</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem @click="importMarkdownContent()">
<Upload class="mr-2 size-4" />
导入 .md
</MenubarItem>
<MenubarItem @click="exportEditorContent2MD()">
<Download class="mr-2 size-4" />
导出 .md
</MenubarItem>
<MenubarItem @click="exportEditorContent2HTML()">
<FileCode class="mr-2 size-4" />
导出 .html
</MenubarItem>
<MenubarItem @click="exportEditorContent2PureHTML()">
<FileCode class="mr-2 size-4" />
导出 .html(无样式)
</MenubarItem>
<MenubarItem @click="exportEditorContent2PDF()">
<FileText class="mr-2 size-4" />
导出 .pdf
</MenubarItem>
<MenubarItem @click="downloadAsCardImage()">
<Download class="mr-2 size-4" />
导出 .png
</MenubarItem>
<MenubarSeparator />
<MenubarItem @click="openEditorStateDialog()">
<FileCog class="mr-2 size-4" />
导入/导出项目配置
</MenubarItem>
<MenubarSeparator />
<MenubarCheckboxItem v-model:checked="isDark">
深色模式
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarCheckboxItem v-model:checked="isEditOnLeft">
左侧编辑
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarCheckboxItem v-model:checked="isOpenPostSlider">
内容管理
</MenubarCheckboxItem>
</MenubarSubContent>
</MenubarSub>

<!-- 作为 MenubarMenu 使用(默认) -->
<MenubarMenu v-else>
<MenubarTrigger>
文件
</MenubarTrigger>
Expand Down Expand Up @@ -53,7 +113,7 @@ const importMarkdownContent = useImportMarkdownContent()
导出 .png
</MenubarItem>
<MenubarSeparator />
<MenubarItem @click="editorStateDialogVisible = true">
<MenubarItem @click="openEditorStateDialog()">
<FileCog class="mr-2 size-4" />
导入/导出项目配置
</MenubarItem>
Expand All @@ -65,9 +125,10 @@ const importMarkdownContent = useImportMarkdownContent()
<MenubarCheckboxItem v-model:checked="isEditOnLeft">
左侧编辑
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarCheckboxItem v-model:checked="isOpenPostSlider">
内容管理
</MenubarCheckboxItem>
</MenubarContent>
</MenubarMenu>

<!-- 各弹窗挂载 -->
<EditorStateDialog :visible="editorStateDialogVisible" @close="editorStateDialogVisible = false" />
</template>
Loading