mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
style: update dialog (#402)
This commit is contained in:
parent
442beb8053
commit
d3a7d08f9d
@ -5,66 +5,63 @@
|
|||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 0 0% 3.9%;
|
||||||
|
|
||||||
--muted: 210 40% 96.1%;
|
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
|
||||||
|
|
||||||
--popover: 0 0% 100%;
|
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
|
||||||
|
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
--card-foreground: 0 0% 3.9%;
|
||||||
|
|
||||||
--border: 214.3 31.8% 91.4%;
|
--popover: 0 0% 100%;
|
||||||
--input: 214.3 31.8% 91.4%;
|
--popover-foreground: 0 0% 3.9%;
|
||||||
|
|
||||||
--primary: 222.2 47.4% 11.2%;
|
--primary: 0 0% 9%;
|
||||||
--primary-foreground: 210 40% 98%;
|
--primary-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--secondary: 210 40% 96.1%;
|
--secondary: 0 0% 96.1%;
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
--secondary-foreground: 0 0% 9%;
|
||||||
|
|
||||||
--accent: 210 40% 96.1%;
|
--muted: 0 0% 96.1%;
|
||||||
--accent-foreground: 222.2 47.4% 11.2%;
|
--muted-foreground: 0 0% 45.1%;
|
||||||
|
|
||||||
|
--accent: 0 0% 96.1%;
|
||||||
|
--accent-foreground: 0 0% 9%;
|
||||||
|
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 84.2% 60.2%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--ring: 222.2 84% 4.9%;
|
|
||||||
|
|
||||||
|
--border:0 0% 89.8%;
|
||||||
|
--input:0 0% 89.8%;
|
||||||
|
--ring:0 0% 3.9%;
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: 222.2 84% 4.9%;
|
--background:0 0% 3.9%;
|
||||||
--foreground: 210 40% 98%;
|
--foreground:0 0% 98%;
|
||||||
|
|
||||||
--muted: 217.2 32.6% 17.5%;
|
--card:0 0% 3.9%;
|
||||||
--muted-foreground: 215 20.2% 65.1%;
|
--card-foreground:0 0% 98%;
|
||||||
|
|
||||||
--popover: 222.2 84% 4.9%;
|
--popover:0 0% 3.9%;
|
||||||
--popover-foreground: 210 40% 98%;
|
--popover-foreground:0 0% 98%;
|
||||||
|
|
||||||
--card: 222.2 84% 4.9%;
|
--primary:0 0% 98%;
|
||||||
--card-foreground: 210 40% 98%;
|
--primary-foreground:0 0% 9%;
|
||||||
|
|
||||||
--border: 217.2 32.6% 17.5%;
|
--secondary:0 0% 14.9%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--secondary-foreground:0 0% 98%;
|
||||||
|
|
||||||
--primary: 210 40% 98%;
|
--muted:0 0% 14.9%;
|
||||||
--primary-foreground: 222.2 47.4% 11.2%;
|
--muted-foreground:0 0% 63.9%;
|
||||||
|
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
--accent:0 0% 14.9%;
|
||||||
--secondary-foreground: 210 40% 98%;
|
--accent-foreground:0 0% 98%;
|
||||||
|
|
||||||
--accent: 217.2 32.6% 17.5%;
|
--destructive:0 62.8% 30.6%;
|
||||||
--accent-foreground: 210 40% 98%;
|
--destructive-foreground:0 0% 98%;
|
||||||
|
|
||||||
--destructive: 0 62.8% 30.6%;
|
--border:0 0% 14.9%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--input:0 0% 14.9%;
|
||||||
|
--ring:0 0% 83.1%;
|
||||||
--ring: 212.7 26.8% 83.9%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,6 @@ section {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
@ -87,8 +86,6 @@ section {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: var(--el-text-color-regular);
|
|
||||||
box-shadow: var(--el-box-shadow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview table {
|
.preview table {
|
||||||
|
@ -1,35 +1,13 @@
|
|||||||
@nightBgColor: #333333;
|
@nightPreviewColor: #191919;
|
||||||
@nightPreviewColor: #1e1e1e;
|
@nightCodeMirrorColor: #191919;
|
||||||
@nightHeaderColor: #3c3c3c;
|
|
||||||
@nightCodeMirrorColor: #1e1e1e;
|
|
||||||
@nightActiveCodeMirrorColor: gray;
|
@nightActiveCodeMirrorColor: gray;
|
||||||
@nightFontColor: gray;
|
@nightFontColor: gray;
|
||||||
@nightLinkColor: #8e9eb9;
|
@nightLinkColor: #8e9eb9;
|
||||||
@nightLinkTextColor: #84868b;
|
@nightLinkTextColor: #84868b;
|
||||||
@nightWhiteColor: #f0f0f0;
|
|
||||||
@nightButtonBg: #1e1e1e;
|
|
||||||
@nightButtonHoverColor: #84868b;
|
|
||||||
@nightLineColor: #84868b;
|
@nightLineColor: #84868b;
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
.container {
|
.container {
|
||||||
background-color: @nightBgColor;
|
|
||||||
|
|
||||||
.CodeMirror {
|
|
||||||
caret-color: @nightFontColor;
|
|
||||||
color: @nightFontColor;
|
|
||||||
background-color: @nightCodeMirrorColor;
|
|
||||||
box-shadow: inset 0 0 0 1px rgba(100, 37, 37, 0.102);
|
|
||||||
|
|
||||||
.CodeMirror-cursor {
|
|
||||||
border-left: 1px solid @nightLineColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-activeline-background {
|
|
||||||
background-color: #3e3e3e!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.output_night {
|
.output_night {
|
||||||
.preview {
|
.preview {
|
||||||
background-color: @nightPreviewColor;
|
background-color: @nightPreviewColor;
|
||||||
@ -46,20 +24,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-s-xq-light span.cm-variable-2,
|
|
||||||
|
|
||||||
.cm-s-xq-light .CodeMirror-activeline-background {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cm-s-xq-light span.cm-string {
|
|
||||||
color: @nightLinkColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cm-s-xq-light span.cm-link {
|
|
||||||
color: @nightLinkTextColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
background-color: @nightCodeMirrorColor;
|
background-color: @nightCodeMirrorColor;
|
||||||
}
|
}
|
||||||
@ -69,7 +33,6 @@
|
|||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue',
|
font-family: 'PingFang SC', BlinkMacSystemFont, Roboto, 'Helvetica Neue',
|
||||||
sans-serif !important;
|
sans-serif !important;
|
||||||
|
@ -67,7 +67,7 @@ function handleTabsEdit(targetName, action) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<transition enter-active-class="bounceInRight">
|
<transition enter-active-class="bounceInRight">
|
||||||
<el-col v-show="store.isShowCssEditor" :span="8" class="cssEditor-wrapper order-1 h-full flex flex-col">
|
<el-col v-show="store.isShowCssEditor" :span="8" class="cssEditor-wrapper order-1 h-full flex flex-col border-l-1">
|
||||||
<el-tabs
|
<el-tabs
|
||||||
v-model="store.cssContentConfig.active"
|
v-model="store.cssContentConfig.active"
|
||||||
type="border-card"
|
type="border-card"
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -8,6 +16,12 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits([`close`])
|
const emit = defineEmits([`close`])
|
||||||
|
|
||||||
|
function onUpdate(val) {
|
||||||
|
if (!val) {
|
||||||
|
emit(`close`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{ label: `GitHub 仓库`, url: `https://github.com/doocs/md` },
|
{ label: `GitHub 仓库`, url: `https://github.com/doocs/md` },
|
||||||
{ label: `Gitee 仓库`, url: `https://gitee.com/doocs/md` },
|
{ label: `Gitee 仓库`, url: `https://gitee.com/doocs/md` },
|
||||||
@ -20,34 +34,30 @@ function onRedirect(url) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<Dialog :open="props.visible" @update:open="onUpdate">
|
||||||
title="关于"
|
<DialogContent>
|
||||||
class="about__dialog"
|
<DialogHeader>
|
||||||
:model-value="props.visible"
|
<DialogTitle>关于</DialogTitle>
|
||||||
width="520"
|
</DialogHeader>
|
||||||
center
|
<div class="text-center">
|
||||||
@close="emit('close')"
|
<h3>一款高度简洁的微信 Markdown 编辑器</h3>
|
||||||
>
|
<p>扫码关注公众号 Doocs,原创技术文章第一时间推送!</p>
|
||||||
<div class="text-center">
|
<img
|
||||||
<h3>一款高度简洁的微信 Markdown 编辑器</h3>
|
class="mx-auto my-5"
|
||||||
<p>扫码关注公众号 Doocs,原创技术文章第一时间推送!</p>
|
src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png"
|
||||||
<img
|
alt="Doocs Markdown 编辑器"
|
||||||
class="mx-auto my-5"
|
style="width: 40%"
|
||||||
src="https://cdn-doocs.oss-cn-shenzhen.aliyuncs.com/gh/doocs/md/images/1648303220922-7e14aefa-816e-44c1-8604-ade709ca1c69.png"
|
>
|
||||||
alt="Doocs Markdown 编辑器"
|
</div>
|
||||||
style="width: 40%"
|
<DialogFooter class="sm:justify-evenly">
|
||||||
>
|
<Button
|
||||||
</div>
|
v-for="link in links"
|
||||||
<template #footer>
|
:key="link.url"
|
||||||
<el-button
|
@click="onRedirect(link.url)"
|
||||||
v-for="link in links"
|
>
|
||||||
:key="link.url"
|
{{ link.label }}
|
||||||
type="primary"
|
</Button>
|
||||||
plain
|
</DialogFooter>
|
||||||
@click="onRedirect(link.url)"
|
</DialogContent>
|
||||||
>
|
</Dialog>
|
||||||
{{ link.label }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,49 +1,27 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/components/ui/dropdown-menu'
|
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
const props = defineProps([`isOpen`, `clickTrigger`, `openDropdown`, `updateOpen`])
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const {
|
const { toggleShowInsertFormDialog, toggleShowUploadImgDialog } = store
|
||||||
toggleShowInsertFormDialog,
|
|
||||||
toggleShowUploadImgDialog,
|
|
||||||
} = store
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu :open="props.isOpen" @update:open="props.updateOpen">
|
<MenubarMenu>
|
||||||
<DropdownMenuTrigger
|
<MenubarTrigger> 编辑 </MenubarTrigger>
|
||||||
class="flex items-center p-2 px-4 hover:bg-gray-2 dark:hover:bg-stone-9"
|
<MenubarContent align="start">
|
||||||
:class="{
|
<MenubarItem @click="toggleShowUploadImgDialog()">
|
||||||
'bg-gray-2': props.isOpen,
|
|
||||||
'dark:bg-stone-9': props.isOpen,
|
|
||||||
}"
|
|
||||||
@click="props.clickTrigger()"
|
|
||||||
@mouseenter="props.openDropdown()"
|
|
||||||
>
|
|
||||||
编辑
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="start">
|
|
||||||
<DropdownMenuItem @click="toggleShowUploadImgDialog()">
|
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<el-icon class="mr-2 h-4 w-4">
|
||||||
<ElIconUpload />
|
<ElIconUpload />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
上传图片
|
上传图片
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuItem @click="toggleShowInsertFormDialog()">
|
<MenubarItem @click="toggleShowInsertFormDialog()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<el-icon class="mr-2 h-4 w-4">
|
||||||
<ElIconGrid />
|
<ElIconGrid />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
插入表格
|
插入表格
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
</DropdownMenuContent>
|
</MenubarContent>
|
||||||
</DropdownMenu>
|
</MenubarMenu>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,18 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/components/ui/dropdown-menu'
|
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
const props = defineProps([`isOpen`, `clickTrigger`, `openDropdown`, `updateOpen`])
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -30,51 +20,43 @@ const {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu :open="props.isOpen" @update:open="props.updateOpen">
|
<MenubarMenu>
|
||||||
<DropdownMenuTrigger
|
<MenubarTrigger>
|
||||||
class="flex items-center p-2 px-4 hover:bg-gray-2 dark:hover:bg-stone-9"
|
|
||||||
:class="{
|
|
||||||
'bg-gray-2': props.isOpen,
|
|
||||||
'dark:bg-stone-9': props.isOpen,
|
|
||||||
}"
|
|
||||||
@click="props.clickTrigger()"
|
|
||||||
@mouseenter="props.openDropdown()"
|
|
||||||
>
|
|
||||||
文件
|
文件
|
||||||
</DropdownMenuTrigger>
|
</MenubarTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<MenubarContent align="start">
|
||||||
<DropdownMenuItem @click="importMarkdownContent()">
|
<MenubarItem @click="importMarkdownContent()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<el-icon class="mr-2 h-4 w-4">
|
||||||
<ElIconUpload />
|
<ElIconUpload />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
导入 .md
|
导入 .md
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuItem @click="exportEditorContent2MD()">
|
<MenubarItem @click="exportEditorContent2MD()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<el-icon class="mr-2 h-4 w-4">
|
||||||
<ElIconDownload />
|
<ElIconDownload />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
导出 .md
|
导出 .md
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuItem @click="exportEditorContent2HTML()">
|
<MenubarItem @click="exportEditorContent2HTML()">
|
||||||
<el-icon class="mr-2 h-4 w-4">
|
<el-icon class="mr-2 h-4 w-4">
|
||||||
<ElIconDocument />
|
<ElIconDocument />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
导出 .html
|
导出 .html
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuSeparator />
|
<MenubarSeparator />
|
||||||
<DropdownMenuItem @click="toggleDark()">
|
<MenubarItem @click="toggleDark()">
|
||||||
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isDark }">
|
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isDark }">
|
||||||
<ElIconCheck />
|
<ElIconCheck />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
深色模式
|
深色模式
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuSeparator />
|
<MenubarSeparator />
|
||||||
<DropdownMenuItem @click="toggleEditOnLeft()">
|
<MenubarItem @click="toggleEditOnLeft()">
|
||||||
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isEditOnLeft }">
|
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isEditOnLeft }">
|
||||||
<ElIconCheck />
|
<ElIconCheck />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
左侧编辑
|
左侧编辑
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
</DropdownMenuContent>
|
</MenubarContent>
|
||||||
</DropdownMenu>
|
</MenubarMenu>
|
||||||
</template>
|
</template>
|
||||||
|
@ -3,41 +3,21 @@ import { ref } from 'vue'
|
|||||||
|
|
||||||
import AboutDialog from './AboutDialog.vue'
|
import AboutDialog from './AboutDialog.vue'
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/components/ui/dropdown-menu'
|
|
||||||
|
|
||||||
const props = defineProps([`isOpen`, `clickTrigger`, `openDropdown`, `updateOpen`])
|
|
||||||
|
|
||||||
const aboutDialogVisible = ref(false)
|
const aboutDialogVisible = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu :open="props.isOpen" @update:open="props.updateOpen">
|
<MenubarMenu>
|
||||||
<DropdownMenuTrigger
|
<MenubarTrigger>
|
||||||
class="flex items-center p-2 px-4 hover:bg-gray-2 dark:hover:bg-stone-9"
|
|
||||||
:class="{
|
|
||||||
'bg-gray-2': props.isOpen,
|
|
||||||
'dark:bg-stone-9': props.isOpen,
|
|
||||||
}"
|
|
||||||
@click="props.clickTrigger()"
|
|
||||||
@mouseenter="props.openDropdown()"
|
|
||||||
>
|
|
||||||
帮助
|
帮助
|
||||||
</DropdownMenuTrigger>
|
</MenubarTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<MenubarContent align="start">
|
||||||
<DropdownMenuItem @click="aboutDialogVisible = true">
|
<MenubarItem @click="aboutDialogVisible = true">
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
<span>关于</span>
|
<span>关于</span>
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
</DropdownMenuContent>
|
</MenubarContent>
|
||||||
</DropdownMenu>
|
</MenubarMenu>
|
||||||
|
|
||||||
<AboutDialog
|
<AboutDialog :visible="aboutDialogVisible" @close="aboutDialogVisible = false" />
|
||||||
:visible="aboutDialogVisible"
|
|
||||||
@close="aboutDialogVisible = false"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog'
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
@ -48,6 +55,12 @@ function post() {
|
|||||||
content: form.value.content || form.value.auto.content,
|
content: form.value.content || form.value.auto.content,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onUpdate(val) {
|
||||||
|
if (!val) {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -55,51 +68,43 @@ function post() {
|
|||||||
发布
|
发布
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<el-dialog
|
<Dialog :open="dialogVisible" @update:open="onUpdate">
|
||||||
title="发布"
|
<DialogContent>
|
||||||
:model-value="dialogVisible"
|
<DialogHeader>
|
||||||
@close="dialogVisible = false"
|
<DialogTitle>发布</DialogTitle>
|
||||||
>
|
</DialogHeader>
|
||||||
<el-alert
|
|
||||||
class="mb-4"
|
|
||||||
title="注:此功能由第三方浏览器插件支持,本平台不保证安全性。"
|
|
||||||
type="info"
|
|
||||||
show-icon
|
|
||||||
/>
|
|
||||||
<el-form
|
|
||||||
class="postInfo"
|
|
||||||
label-width="50"
|
|
||||||
:model="form"
|
|
||||||
>
|
|
||||||
<el-form-item label="封面">
|
|
||||||
<el-input
|
|
||||||
v-model="form.thumb"
|
|
||||||
placeholder="自动提取第一张图"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="标题">
|
|
||||||
<el-input
|
|
||||||
v-model="form.title"
|
|
||||||
placeholder="自动提取第一个标题"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="描述">
|
|
||||||
<el-input
|
|
||||||
v-model="form.desc"
|
|
||||||
type="textarea"
|
|
||||||
:rows="4"
|
|
||||||
placeholder="自动提取第一个段落"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<template #footer>
|
<el-alert
|
||||||
<el-button @click="dialogVisible = false">
|
class="mb-4"
|
||||||
取 消
|
title="注:此功能由第三方浏览器插件支持,本平台不保证安全性。"
|
||||||
</el-button>
|
type="info"
|
||||||
<el-button type="primary" @click="post">
|
show-icon
|
||||||
确 定
|
/>
|
||||||
</el-button>
|
<el-form class="postInfo" label-width="50" :model="form">
|
||||||
</template>
|
<el-form-item label="封面">
|
||||||
</el-dialog>
|
<el-input v-model="form.thumb" placeholder="自动提取第一张图" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="标题">
|
||||||
|
<el-input v-model="form.title" placeholder="自动提取第一个标题" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="描述">
|
||||||
|
<el-input
|
||||||
|
v-model="form.desc"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="自动提取第一个段落"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" @click="dialogVisible = false">
|
||||||
|
取 消
|
||||||
|
</Button>
|
||||||
|
<Button @click="post">
|
||||||
|
确 定
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
@ -4,25 +4,22 @@ import { storeToRefs } from 'pinia'
|
|||||||
|
|
||||||
import StyleOptionMenu from './StyleOptionMenu.vue'
|
import StyleOptionMenu from './StyleOptionMenu.vue'
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/components/ui/dropdown-menu'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HoverCard,
|
HoverCard,
|
||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger,
|
HoverCardTrigger,
|
||||||
} from '@/components/ui/hover-card'
|
} from '@/components/ui/hover-card'
|
||||||
|
|
||||||
import { codeBlockThemeOptions, colorOptions, fontFamilyOptions, fontSizeOptions, legendOptions, themeOptions } from '@/config'
|
import {
|
||||||
|
codeBlockThemeOptions,
|
||||||
|
colorOptions,
|
||||||
|
fontFamilyOptions,
|
||||||
|
fontSizeOptions,
|
||||||
|
legendOptions,
|
||||||
|
themeOptions,
|
||||||
|
} from '@/config'
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
const props = defineProps([`isOpen`, `clickTrigger`, `openDropdown`, `updateOpen`])
|
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -69,23 +66,28 @@ function customStyle() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu :open="props.isOpen" @update:open="props.updateOpen">
|
<MenubarMenu>
|
||||||
<DropdownMenuTrigger
|
<MenubarTrigger> 样式 </MenubarTrigger>
|
||||||
class="flex items-center p-2 px-4 hover:bg-gray-2 dark:hover:bg-stone-9"
|
<MenubarContent class="w-56" align="start">
|
||||||
:class="{
|
<StyleOptionMenu
|
||||||
'bg-gray-2': props.isOpen,
|
title="主题"
|
||||||
'dark:bg-stone-9': props.isOpen,
|
:options="themeOptions"
|
||||||
}"
|
:current="theme"
|
||||||
@click="props.clickTrigger()"
|
:change="themeChanged"
|
||||||
@mouseenter="props.openDropdown()"
|
/>
|
||||||
>
|
<MenubarSeparator />
|
||||||
样式
|
<StyleOptionMenu
|
||||||
</DropdownMenuTrigger>
|
title="字体"
|
||||||
<DropdownMenuContent class="w-56" align="start">
|
:options="fontFamilyOptions"
|
||||||
<StyleOptionMenu title="主题" :options="themeOptions" :current="theme" :change="themeChanged" />
|
:current="fontFamily"
|
||||||
<DropdownMenuSeparator />
|
:change="fontChanged"
|
||||||
<StyleOptionMenu title="字体" :options="fontFamilyOptions" :current="fontFamily" :change="fontChanged" />
|
/>
|
||||||
<StyleOptionMenu title="字号" :options="fontSizeOptions" :current="fontSize" :change="sizeChanged" />
|
<StyleOptionMenu
|
||||||
|
title="字号"
|
||||||
|
:options="fontSizeOptions"
|
||||||
|
:current="fontSize"
|
||||||
|
:change="sizeChanged"
|
||||||
|
/>
|
||||||
<StyleOptionMenu
|
<StyleOptionMenu
|
||||||
title="主题色"
|
title="主题色"
|
||||||
:options="colorOptions"
|
:options="colorOptions"
|
||||||
@ -98,9 +100,14 @@ function customStyle() {
|
|||||||
:current="codeBlockTheme"
|
:current="codeBlockTheme"
|
||||||
:change="codeBlockThemeChanged"
|
:change="codeBlockThemeChanged"
|
||||||
/>
|
/>
|
||||||
<StyleOptionMenu title="图注格式" :options="legendOptions" :current="legend" :change="legendChanged" />
|
<StyleOptionMenu
|
||||||
<DropdownMenuSeparator />
|
title="图注格式"
|
||||||
<DropdownMenuItem @click.self.prevent="showPicker">
|
:options="legendOptions"
|
||||||
|
:current="legend"
|
||||||
|
:change="legendChanged"
|
||||||
|
/>
|
||||||
|
<MenubarSeparator />
|
||||||
|
<MenubarItem @click.self.prevent="showPicker">
|
||||||
<HoverCard :open-delay="100">
|
<HoverCard :open-delay="100">
|
||||||
<HoverCardTrigger class="w-full flex">
|
<HoverCardTrigger class="w-full flex">
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
@ -131,23 +138,23 @@ function customStyle() {
|
|||||||
@change="colorChanged"
|
@change="colorChanged"
|
||||||
@click="showPicker"
|
@click="showPicker"
|
||||||
/> -->
|
/> -->
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuItem @click="customStyle">
|
<MenubarItem @click="customStyle">
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
自定义 CSS
|
自定义 CSS
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuSeparator />
|
<MenubarSeparator />
|
||||||
<DropdownMenuItem @click="macCodeBlockChanged">
|
<MenubarItem @click="macCodeBlockChanged">
|
||||||
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isMacCodeBlock }">
|
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isMacCodeBlock }">
|
||||||
<ElIconCheck />
|
<ElIconCheck />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
Mac 代码块
|
Mac 代码块
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuSeparator />
|
<MenubarSeparator />
|
||||||
<DropdownMenuItem divided @click="resetStyleConfirm">
|
<MenubarItem divided @click="resetStyleConfirm">
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
重置
|
重置
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
</DropdownMenuContent>
|
</MenubarContent>
|
||||||
</DropdownMenu>
|
</MenubarMenu>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
DropdownMenuItem,
|
MenubarItem,
|
||||||
DropdownMenuPortal,
|
MenubarSub,
|
||||||
DropdownMenuShortcut,
|
MenubarSubContent,
|
||||||
DropdownMenuSub,
|
MenubarSubTrigger,
|
||||||
DropdownMenuSubContent,
|
} from '@/components/ui/menubar'
|
||||||
DropdownMenuSubTrigger,
|
|
||||||
} from '@/components/ui/dropdown-menu'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
@ -42,30 +40,28 @@ function setStyle(title, value) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenuSub>
|
<MenubarSub>
|
||||||
<DropdownMenuSubTrigger>
|
<MenubarSubTrigger>
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
<span>{{ props.title }}</span>
|
<span>{{ props.title }}</span>
|
||||||
</DropdownMenuSubTrigger>
|
</MenubarSubTrigger>
|
||||||
<DropdownMenuPortal>
|
<MenubarSubContent class="max-h-56 overflow-auto">
|
||||||
<DropdownMenuSubContent class="max-h-56 overflow-auto">
|
<MenubarItem
|
||||||
<DropdownMenuItem
|
v-for="{ label, value, desc } in options"
|
||||||
v-for="{ label, value, desc } in options"
|
:key="value"
|
||||||
:key="value"
|
:label="label"
|
||||||
:label="label"
|
:model-value="value"
|
||||||
:model-value="value"
|
class="w-50"
|
||||||
class="w-50"
|
@click="change(value)"
|
||||||
@click="change(value)"
|
>
|
||||||
>
|
<el-icon class="mr-2 h-4 w-4" :style="{ opacity: +(current === value) }">
|
||||||
<el-icon class="mr-2 h-4 w-4" :style="{ opacity: +(current === value) }">
|
<ElIconCheck />
|
||||||
<ElIconCheck />
|
</el-icon>
|
||||||
</el-icon>
|
{{ label }}
|
||||||
{{ label }}
|
<DropdownMenuShortcut :style="setStyle(title, value)">
|
||||||
<DropdownMenuShortcut :style="setStyle(title, value)">
|
{{ desc }}
|
||||||
{{ desc }}
|
</DropdownMenuShortcut>
|
||||||
</DropdownMenuShortcut>
|
</MenubarItem>
|
||||||
</DropdownMenuItem>
|
</MenubarSubContent>
|
||||||
</DropdownMenuSubContent>
|
</MenubarSub>
|
||||||
</DropdownMenuPortal>
|
|
||||||
</DropdownMenuSub>
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { nextTick, reactive, ref } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
import { Moon, Paintbrush, Sun } from 'lucide-vue-next'
|
import { Moon, Paintbrush, Sun } from 'lucide-vue-next'
|
||||||
@ -9,7 +9,18 @@ import FileDropdown from './FileDropdown.vue'
|
|||||||
import HelpDropdown from './HelpDropdown.vue'
|
import HelpDropdown from './HelpDropdown.vue'
|
||||||
import StyleDropdown from './StyleDropdown.vue'
|
import StyleDropdown from './StyleDropdown.vue'
|
||||||
import EditDropdown from './EditDropdown.vue'
|
import EditDropdown from './EditDropdown.vue'
|
||||||
import { altSign, codeBlockThemeOptions, colorOptions, ctrlKey, ctrlSign, fontFamilyOptions, fontSizeOptions, legendOptions, shiftSign, themeOptions } from '@/config'
|
import {
|
||||||
|
altSign,
|
||||||
|
codeBlockThemeOptions,
|
||||||
|
colorOptions,
|
||||||
|
ctrlKey,
|
||||||
|
ctrlSign,
|
||||||
|
fontFamilyOptions,
|
||||||
|
fontSizeOptions,
|
||||||
|
legendOptions,
|
||||||
|
shiftSign,
|
||||||
|
themeOptions,
|
||||||
|
} from '@/config'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
@ -19,29 +30,22 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/components/ui/select'
|
} from '@/components/ui/select'
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
Menubar,
|
||||||
DropdownMenuContent,
|
MenubarContent,
|
||||||
DropdownMenuItem,
|
MenubarItem,
|
||||||
DropdownMenuSeparator,
|
MenubarMenu,
|
||||||
DropdownMenuShortcut,
|
MenubarSeparator,
|
||||||
DropdownMenuTrigger,
|
MenubarShortcut,
|
||||||
} from '@/components/ui/dropdown-menu'
|
MenubarTrigger,
|
||||||
import {
|
} from '@/components/ui/menubar'
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/components/ui/popover'
|
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
|
|
||||||
import { mergeCss, solveWeChatImage } from '@/utils'
|
import { mergeCss, solveWeChatImage } from '@/utils'
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([`addFormat`, `formatContent`, `startCopy`, `endCopy`])
|
||||||
`addFormat`,
|
|
||||||
`formatContent`,
|
|
||||||
`startCopy`,
|
|
||||||
`endCopy`,
|
|
||||||
])
|
|
||||||
|
|
||||||
const formatItems = [
|
const formatItems = [
|
||||||
{
|
{
|
||||||
@ -78,18 +82,9 @@ const formatItems = [
|
|||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const {
|
const { isDark, isCiteStatus, output, primaryColor } = storeToRefs(store)
|
||||||
isDark,
|
|
||||||
isCiteStatus,
|
|
||||||
output,
|
|
||||||
primaryColor,
|
|
||||||
} = storeToRefs(store)
|
|
||||||
|
|
||||||
const {
|
const { toggleDark, editorRefresh, citeStatusChanged } = store
|
||||||
toggleDark,
|
|
||||||
editorRefresh,
|
|
||||||
citeStatusChanged,
|
|
||||||
} = store
|
|
||||||
|
|
||||||
// 复制到微信公众号
|
// 复制到微信公众号
|
||||||
function copy() {
|
function copy() {
|
||||||
@ -103,10 +98,7 @@ function copy() {
|
|||||||
const originalItems = tempDiv.querySelectorAll(`li > ul, li > ol`)
|
const originalItems = tempDiv.querySelectorAll(`li > ul, li > ol`)
|
||||||
|
|
||||||
originalItems.forEach((originalItem) => {
|
originalItems.forEach((originalItem) => {
|
||||||
originalItem.parentElement.insertAdjacentElement(
|
originalItem.parentElement.insertAdjacentElement(`afterend`, originalItem)
|
||||||
`afterend`,
|
|
||||||
originalItem,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 返回修改后的 HTML 字符串
|
// 返回修改后的 HTML 字符串
|
||||||
@ -161,76 +153,43 @@ function copy() {
|
|||||||
})
|
})
|
||||||
}, 350)
|
}, 350)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isClickTrigger = ref(false)
|
|
||||||
const isOpenList = reactive(Array.from({ length: 5 }).fill(false))
|
|
||||||
function clickTrigger() {
|
|
||||||
isClickTrigger.value = !isClickTrigger.value
|
|
||||||
}
|
|
||||||
|
|
||||||
function openDropdown(index) {
|
|
||||||
return () => {
|
|
||||||
isOpenList.fill(false)
|
|
||||||
isOpenList[index] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateOpen(isOpen) {
|
|
||||||
if (!isOpen) {
|
|
||||||
isClickTrigger.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="header-container">
|
<header class="header-container h-15 flex items-center px-5">
|
||||||
<div class="dropdowns flex flex-auto">
|
<Menubar class="menubar mr-auto">
|
||||||
<FileDropdown
|
<FileDropdown />
|
||||||
:is-open="isClickTrigger && isOpenList[0]" :click-trigger="clickTrigger"
|
|
||||||
:open-dropdown="openDropdown(0)" :update-open="updateOpen"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DropdownMenu :open="isClickTrigger && isOpenList[1]" @update:open="updateOpen">
|
<MenubarMenu>
|
||||||
<DropdownMenuTrigger
|
<MenubarTrigger> 格式 </MenubarTrigger>
|
||||||
class="flex items-center p-2 px-4 hover:bg-gray-2 dark:hover:bg-stone-9" :class="{
|
<MenubarContent class="w-60" align="start">
|
||||||
'bg-gray-2': isClickTrigger && isOpenList[1],
|
<MenubarItem
|
||||||
'dark:bg-stone-9': isClickTrigger && isOpenList[1],
|
v-for="{ label, kbd, emitArgs } in formatItems"
|
||||||
}" @click="clickTrigger()" @mouseenter="openDropdown(1)()"
|
:key="kbd"
|
||||||
>
|
@click="$emit(...emitArgs)"
|
||||||
格式
|
>
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent class="w-60" align="start">
|
|
||||||
<DropdownMenuItem v-for="{ label, kbd, emitArgs } in formatItems" :key="kbd" @click="$emit(...emitArgs);">
|
|
||||||
<el-icon class="mr-2 h-4 w-4" />
|
<el-icon class="mr-2 h-4 w-4" />
|
||||||
{{ label }}
|
{{ label }}
|
||||||
<DropdownMenuShortcut>
|
<MenubarShortcut>
|
||||||
<kbd v-for="item in kbd" :key="item" class="mx-1 bg-gray-2 dark:bg-stone-9">
|
<kbd v-for="item in kbd" :key="item" class="mx-1 bg-gray-2 dark:bg-stone-9">
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</kbd>
|
</kbd>
|
||||||
</DropdownMenuShortcut>
|
</MenubarShortcut>
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
<DropdownMenuSeparator />
|
<MenubarSeparator />
|
||||||
<DropdownMenuItem @click="citeStatusChanged()">
|
<MenubarItem @click="citeStatusChanged()">
|
||||||
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isCiteStatus }">
|
<el-icon class="mr-2 h-4 w-4" :class="{ 'opacity-0': !isCiteStatus }">
|
||||||
<ElIconCheck />
|
<ElIconCheck />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
微信外链转底部引用
|
微信外链转底部引用
|
||||||
</DropdownMenuItem>
|
</MenubarItem>
|
||||||
</DropdownMenuContent>
|
</MenubarContent>
|
||||||
</DropdownMenu>
|
</MenubarMenu>
|
||||||
<EditDropdown
|
<EditDropdown />
|
||||||
:is-open="isClickTrigger && isOpenList[2]" :click-trigger="clickTrigger"
|
<StyleDropdown />
|
||||||
:open-dropdown="openDropdown(2)" :update-open="updateOpen"
|
<HelpDropdown />
|
||||||
/>
|
</Menubar>
|
||||||
<StyleDropdown
|
|
||||||
:is-open="isClickTrigger && isOpenList[3]" :click-trigger="clickTrigger"
|
|
||||||
:open-dropdown="openDropdown(3)" :update-open="updateOpen"
|
|
||||||
/>
|
|
||||||
<HelpDropdown
|
|
||||||
:is-open="isClickTrigger && isOpenList[4]" :click-trigger="clickTrigger"
|
|
||||||
:open-dropdown="openDropdown(4)" :update-open="updateOpen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Button variant="outline">
|
<Button variant="outline">
|
||||||
@ -240,25 +199,24 @@ function updateOpen(isOpen) {
|
|||||||
<PopoverContent class="h-100 w-100 overflow-auto px-6" align="end">
|
<PopoverContent class="h-100 w-100 overflow-auto px-6" align="end">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>主题</h2>
|
||||||
主题
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-3 justify-items-center gap-2">
|
<div class="grid grid-cols-3 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
v-for="{ label, value } in themeOptions"
|
v-for="{ label, value } in themeOptions"
|
||||||
:key="value"
|
:key="value"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.theme === value }" @click="store.themeChanged(value)"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.theme === value,
|
||||||
|
}"
|
||||||
|
@click="store.themeChanged(value)"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>字体</h2>
|
||||||
字体
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-3 justify-items-center gap-2">
|
<div class="grid grid-cols-3 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
v-for="{ label, value } in fontFamilyOptions"
|
v-for="{ label, value } in fontFamilyOptions"
|
||||||
@ -273,9 +231,7 @@ function updateOpen(isOpen) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>字号</h2>
|
||||||
字号
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
v-for="{ value, desc } in fontSizeOptions"
|
v-for="{ value, desc } in fontSizeOptions"
|
||||||
@ -283,26 +239,30 @@ function updateOpen(isOpen) {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
:class="{
|
:class="{
|
||||||
'border-black dark:border-white': store.fontSize === value }" @click="store.sizeChanged(value)"
|
'border-black dark:border-white': store.fontSize === value,
|
||||||
|
}"
|
||||||
|
@click="store.sizeChanged(value)"
|
||||||
>
|
>
|
||||||
{{ desc }}
|
{{ desc }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>主题色</h2>
|
||||||
主题色
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-3 justify-items-center gap-2">
|
<div class="grid grid-cols-3 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
v-for="{ label, value } in colorOptions"
|
v-for="{ label, value } in colorOptions"
|
||||||
:key="value"
|
:key="value"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.primaryColor === value }" @click="store.colorChanged(value)"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.primaryColor === value,
|
||||||
|
}"
|
||||||
|
@click="store.colorChanged(value)"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="mr-2 inline-block h-4 w-4 rounded-full" :style="{
|
class="mr-2 inline-block h-4 w-4 rounded-full"
|
||||||
|
:style="{
|
||||||
background: value,
|
background: value,
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
@ -311,9 +271,7 @@ function updateOpen(isOpen) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>自定义主题色</h2>
|
||||||
自定义主题色
|
|
||||||
</h2>
|
|
||||||
<div>
|
<div>
|
||||||
<el-color-picker
|
<el-color-picker
|
||||||
v-model="primaryColor"
|
v-model="primaryColor"
|
||||||
@ -324,16 +282,21 @@ function updateOpen(isOpen) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>代码块主题</h2>
|
||||||
代码块主题
|
|
||||||
</h2>
|
|
||||||
<div>
|
<div>
|
||||||
<Select v-model="store.codeBlockTheme" @update:model-value="store.codeBlockThemeChanged">
|
<Select
|
||||||
|
v-model="store.codeBlockTheme"
|
||||||
|
@update:model-value="store.codeBlockThemeChanged"
|
||||||
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select a fruit" />
|
<SelectValue placeholder="Select a fruit" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem v-for="{ label, value } in codeBlockThemeOptions" :key="label" :value="value">
|
<SelectItem
|
||||||
|
v-for="{ label, value } in codeBlockThemeOptions"
|
||||||
|
:key="label"
|
||||||
|
:value="value"
|
||||||
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
@ -341,16 +304,17 @@ function updateOpen(isOpen) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>图注格式</h2>
|
||||||
图注格式
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-3 justify-items-center gap-2">
|
<div class="grid grid-cols-3 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
v-for="{ label, value } in legendOptions"
|
v-for="{ label, value } in legendOptions"
|
||||||
:key="value"
|
:key="value"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.legend === value }" @click="store.legendChanged(value)"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.legend === value,
|
||||||
|
}"
|
||||||
|
@click="store.legendChanged(value)"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</Button>
|
</Button>
|
||||||
@ -358,84 +322,100 @@ function updateOpen(isOpen) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>Mac 代码块</h2>
|
||||||
Mac 代码块
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.isMacCodeBlock }" @click="!store.isMacCodeBlock && store.macCodeBlockChanged()"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.isMacCodeBlock,
|
||||||
|
}"
|
||||||
|
@click="!store.isMacCodeBlock && store.macCodeBlockChanged()"
|
||||||
>
|
>
|
||||||
开启
|
开启
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': !store.isMacCodeBlock }" @click="store.isMacCodeBlock && store.macCodeBlockChanged()"
|
:class="{
|
||||||
|
'border-black dark:border-white': !store.isMacCodeBlock,
|
||||||
|
}"
|
||||||
|
@click="store.isMacCodeBlock && store.macCodeBlockChanged()"
|
||||||
>
|
>
|
||||||
关闭
|
关闭
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>微信外链转底部引用</h2>
|
||||||
微信外链转底部引用
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.isCiteStatus }" @click="!store.isCiteStatus && store.citeStatusChanged()"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.isCiteStatus,
|
||||||
|
}"
|
||||||
|
@click="!store.isCiteStatus && store.citeStatusChanged()"
|
||||||
>
|
>
|
||||||
开启
|
开启
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': !store.isCiteStatus }" @click="store.isCiteStatus && store.citeStatusChanged()"
|
:class="{
|
||||||
|
'border-black dark:border-white': !store.isCiteStatus,
|
||||||
|
}"
|
||||||
|
@click="store.isCiteStatus && store.citeStatusChanged()"
|
||||||
>
|
>
|
||||||
关闭
|
关闭
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>编辑区位置</h2>
|
||||||
编辑区位置
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': store.isEditOnLeft }" @click="!store.isEditOnLeft && store.toggleEditOnLeft()"
|
:class="{
|
||||||
|
'border-black dark:border-white': store.isEditOnLeft,
|
||||||
|
}"
|
||||||
|
@click="!store.isEditOnLeft && store.toggleEditOnLeft()"
|
||||||
>
|
>
|
||||||
左侧
|
左侧
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': !store.isEditOnLeft }" @click="store.isEditOnLeft && store.toggleEditOnLeft()"
|
:class="{
|
||||||
|
'border-black dark:border-white': !store.isEditOnLeft,
|
||||||
|
}"
|
||||||
|
@click="store.isEditOnLeft && store.toggleEditOnLeft()"
|
||||||
>
|
>
|
||||||
右侧
|
右侧
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<h2>
|
<h2>模式</h2>
|
||||||
模式
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-5 justify-items-center gap-2">
|
<div class="grid grid-cols-5 justify-items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': !isDark }" @click="store.toggleDark(false)"
|
:class="{
|
||||||
|
'border-black dark:border-white': !isDark,
|
||||||
|
}"
|
||||||
|
@click="store.toggleDark(false)"
|
||||||
>
|
>
|
||||||
<Sun class="h-4 w-4" />
|
<Sun class="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
class="w-full"
|
class="w-full"
|
||||||
variant="outline" :class="{
|
variant="outline"
|
||||||
'border-black dark:border-white': isDark }" @click="store.toggleDark(true)"
|
:class="{
|
||||||
|
'border-black dark:border-white': isDark,
|
||||||
|
}"
|
||||||
|
@click="store.toggleDark(true)"
|
||||||
>
|
>
|
||||||
<Moon class="h-4 w-4" />
|
<Moon class="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
@ -449,18 +429,11 @@ function updateOpen(isOpen) {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<PostInfo />
|
<PostInfo />
|
||||||
</div>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.header-container {
|
.menubar {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdowns {
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, toRaw } from 'vue'
|
import { ref, toRaw } from 'vue'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from '@/components/ui/dialog'
|
||||||
|
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
import { createTable } from '@/utils'
|
import { createTable } from '@/utils'
|
||||||
|
|
||||||
@ -28,72 +36,67 @@ function insertTable() {
|
|||||||
resetVal()
|
resetVal()
|
||||||
toggleShowInsertFormDialog()
|
toggleShowInsertFormDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onUpdate(val) {
|
||||||
|
if (!val) {
|
||||||
|
toggleShowInsertFormDialog(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<Dialog :open="store.isShowInsertFormDialog" @update:open="onUpdate">
|
||||||
title="插入表格"
|
<DialogContent>
|
||||||
class="insert__dialog"
|
<DialogHeader>
|
||||||
:model-value="store.isShowInsertFormDialog"
|
<DialogTitle>插入表格</DialogTitle>
|
||||||
@close="toggleShowInsertFormDialog(false)"
|
</DialogHeader>
|
||||||
>
|
<el-row class="tb-options" type="flex" align="middle" :gutter="10">
|
||||||
<el-row class="tb-options" type="flex" align="middle" :gutter="10">
|
<el-col :span="12">
|
||||||
<el-col :span="12">
|
行数:
|
||||||
行数:
|
<el-input-number
|
||||||
<el-input-number
|
v-model="rowNum"
|
||||||
v-model="rowNum"
|
controls-position="right"
|
||||||
controls-position="right"
|
:min="1"
|
||||||
:min="1"
|
:max="100"
|
||||||
:max="100"
|
size="small"
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
列数:
|
|
||||||
<el-input-number
|
|
||||||
v-model="colNum"
|
|
||||||
controls-position="right"
|
|
||||||
:min="1"
|
|
||||||
:max="100"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<table style="border-collapse: collapse" class="input-table">
|
|
||||||
<tr
|
|
||||||
v-for="row in rowNum + 1"
|
|
||||||
:key="row"
|
|
||||||
:class="{ 'head-style': row === 1 }"
|
|
||||||
>
|
|
||||||
<td v-for="col in colNum" :key="col">
|
|
||||||
<el-input
|
|
||||||
v-model="tableData[`k_${row - 1}_${col - 1}`]"
|
|
||||||
align="center"
|
|
||||||
:placeholder="row === 1 ? '表头' : ''"
|
|
||||||
/>
|
/>
|
||||||
</td>
|
</el-col>
|
||||||
</tr>
|
<el-col :span="12">
|
||||||
</table>
|
列数:
|
||||||
<template #footer>
|
<el-input-number
|
||||||
<div class="dialog-footer">
|
v-model="colNum"
|
||||||
<el-button plain @click="toggleShowInsertFormDialog(false)">
|
controls-position="right"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<table style="border-collapse: collapse" class="input-table">
|
||||||
|
<tr v-for="row in rowNum + 1" :key="row" :class="{ 'head-style': row === 1 }">
|
||||||
|
<td v-for="col in colNum" :key="col">
|
||||||
|
<el-input
|
||||||
|
v-model="tableData[`k_${row - 1}_${col - 1}`]"
|
||||||
|
align="center"
|
||||||
|
:placeholder="row === 1 ? '表头' : ''"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" @click="toggleShowInsertFormDialog(false)">
|
||||||
取 消
|
取 消
|
||||||
</el-button>
|
</Button>
|
||||||
<el-button type="primary" plain @click="insertTable">
|
<Button @click="insertTable">
|
||||||
确 定
|
确 定
|
||||||
</el-button>
|
</Button>
|
||||||
</div>
|
</DialogFooter>
|
||||||
</template>
|
</DialogContent>
|
||||||
</el-dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
:deep(.el-dialog) {
|
|
||||||
width: 55%;
|
|
||||||
min-height: 375px;
|
|
||||||
min-width: 440px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tb-options {
|
.tb-options {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import CodeMirror from 'codemirror/lib/codemirror'
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { UploadFilled } from '@element-plus/icons-vue'
|
import { UploadFilled } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||||
|
|
||||||
import { checkImage, removeLeft } from '@/utils'
|
import { checkImage, removeLeft } from '@/utils'
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
|
|
||||||
@ -117,22 +119,25 @@ const imgHost = ref(`default`)
|
|||||||
const formCustomElInput = ref(null)
|
const formCustomElInput = ref(null)
|
||||||
const activeName = ref(`upload`)
|
const activeName = ref(`upload`)
|
||||||
|
|
||||||
watch(activeName, async (val) => {
|
watch(
|
||||||
if (val === `formCustom`) {
|
activeName,
|
||||||
nextTick(() => {
|
async (val) => {
|
||||||
const textarea
|
if (val === `formCustom`) {
|
||||||
= formCustomElInput.value.$el.querySelector(`textarea`)
|
nextTick(() => {
|
||||||
formCustom.value.editor
|
const textarea = formCustomElInput.value.$el.querySelector(`textarea`)
|
||||||
= formCustom.value.editor
|
formCustom.value.editor
|
||||||
|| CodeMirror.fromTextArea(textarea, {
|
= formCustom.value.editor
|
||||||
mode: `javascript`,
|
|| CodeMirror.fromTextArea(textarea, {
|
||||||
})
|
mode: `javascript`,
|
||||||
// formCustom.value.editor.setValue(formCustom.value.code)
|
})
|
||||||
})
|
// formCustom.value.editor.setValue(formCustom.value.code)
|
||||||
}
|
})
|
||||||
}, {
|
}
|
||||||
immediate: true,
|
},
|
||||||
})
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
if (localStorage.getItem(`githubConfig`)) {
|
if (localStorage.getItem(`githubConfig`)) {
|
||||||
@ -278,26 +283,48 @@ function uploadImage(params) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog title="本地上传" class="upload__dialog" :model-value="store.isShowUploadImgDialog" @close="store.toggleShowUploadImgDialog(false)">
|
<Dialog v-model:open="store.isShowUploadImgDialog">
|
||||||
<el-tabs v-model="activeName">
|
<DialogContent class="max-w-max">
|
||||||
<el-tab-pane class="upload-panel" label="选择上传" name="upload">
|
<DialogHeader>
|
||||||
<el-select v-model="imgHost" placeholder="请选择" size="small" @change="changeImgHost">
|
<DialogTitle>本地上传</DialogTitle>
|
||||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
</DialogHeader>
|
||||||
</el-select>
|
|
||||||
<el-upload
|
<el-tabs v-model="activeName">
|
||||||
drag multiple action="" :headers="{ 'Content-Type': 'multipart/form-data' }" :show-file-list="false"
|
<el-tab-pane class="upload-panel" label="选择上传" name="upload">
|
||||||
accept=".jpg, .jpeg, .png, .gif" name="file" :before-upload="beforeImageUpload" :http-request="uploadImage"
|
<el-select
|
||||||
>
|
v-model="imgHost"
|
||||||
<el-icon class="el-icon--upload">
|
placeholder="请选择"
|
||||||
<UploadFilled />
|
size="small"
|
||||||
</el-icon>
|
@change="changeImgHost"
|
||||||
<div class="el-upload__text">
|
>
|
||||||
将图片拖到此处,或
|
<el-option
|
||||||
<em>点击上传</em>
|
v-for="item in options"
|
||||||
</div>
|
:key="item.value"
|
||||||
</el-upload>
|
:label="item.label"
|
||||||
</el-tab-pane>
|
:value="item.value"
|
||||||
<!-- <el-tab-pane class="github-panel" label="Gitee 图床" name="gitee">
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-upload
|
||||||
|
drag
|
||||||
|
multiple
|
||||||
|
action=""
|
||||||
|
:headers="{ 'Content-Type': 'multipart/form-data' }"
|
||||||
|
:show-file-list="false"
|
||||||
|
accept=".jpg, .jpeg, .png, .gif"
|
||||||
|
name="file"
|
||||||
|
:before-upload="beforeImageUpload"
|
||||||
|
:http-request="uploadImage"
|
||||||
|
>
|
||||||
|
<el-icon class="el-icon--upload">
|
||||||
|
<UploadFilled />
|
||||||
|
</el-icon>
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将图片拖到此处,或
|
||||||
|
<em>点击上传</em>
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-tab-pane>
|
||||||
|
<!-- <el-tab-pane class="github-panel" label="Gitee 图床" name="gitee">
|
||||||
<el-form
|
<el-form
|
||||||
class="setting-form"
|
class="setting-form"
|
||||||
:model="formGitee"
|
:model="formGitee"
|
||||||
@ -336,203 +363,290 @@ function uploadImage(params) {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane> -->
|
</el-tab-pane> -->
|
||||||
<el-tab-pane class="github-panel" label="GitHub 图床" name="github">
|
<el-tab-pane class="github-panel" label="GitHub 图床" name="github">
|
||||||
<el-form class="setting-form" :model="formGitHub" label-position="right" label-width="150px">
|
<el-form
|
||||||
<el-form-item label="GitHub 仓库" :required="true">
|
class="setting-form"
|
||||||
<el-input v-model.trim="formGitHub.repo" placeholder="如:github.com/yanglbme/resource" />
|
:model="formGitHub"
|
||||||
</el-form-item>
|
label-position="right"
|
||||||
<el-form-item label="分支">
|
label-width="150px"
|
||||||
<el-input v-model.trim="formGitHub.branch" placeholder="如:release,可不填,默认 master" />
|
>
|
||||||
</el-form-item>
|
<el-form-item label="GitHub 仓库" :required="true">
|
||||||
<el-form-item label="Token" :required="true">
|
<el-input
|
||||||
<el-input
|
v-model.trim="formGitHub.repo"
|
||||||
v-model.trim="formGitHub.accessToken" show-password
|
placeholder="如:github.com/yanglbme/resource"
|
||||||
placeholder="如:cc1d0c1426d0fd0902bd2d7184b14da61b8abc46"
|
/>
|
||||||
/>
|
</el-form-item>
|
||||||
<el-link
|
<el-form-item label="分支">
|
||||||
type="primary"
|
<el-input
|
||||||
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
|
v-model.trim="formGitHub.branch"
|
||||||
target="_blank"
|
placeholder="如:release,可不填,默认 master"
|
||||||
>
|
/>
|
||||||
如何获取 GitHub Token?
|
</el-form-item>
|
||||||
</el-link>
|
<el-form-item label="Token" :required="true">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item>
|
v-model.trim="formGitHub.accessToken"
|
||||||
<el-button type="primary" @click="saveGitHubConfiguration">
|
show-password
|
||||||
保存配置
|
placeholder="如:cc1d0c1426d0fd0902bd2d7184b14da61b8abc46"
|
||||||
</el-button>
|
/>
|
||||||
</el-form-item>
|
<el-link
|
||||||
</el-form>
|
type="primary"
|
||||||
</el-tab-pane>
|
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
|
||||||
<el-tab-pane class="github-panel" label="阿里云 OSS" name="aliOSS">
|
target="_blank"
|
||||||
<el-form class="setting-form" :model="formAliOSS" label-position="right" label-width="150px">
|
>
|
||||||
<el-form-item label="AccessKey ID" :required="true">
|
如何获取 GitHub Token?
|
||||||
<el-input v-model.trim="formAliOSS.accessKeyId" placeholder="如:LTAI4GdoocsmdoxUf13ylbaNHk" />
|
</el-link>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="AccessKey Secret" :required="true">
|
<el-form-item>
|
||||||
<el-input
|
<el-button type="primary" @click="saveGitHubConfiguration">
|
||||||
v-model.trim="formAliOSS.accessKeySecret" show-password
|
保存配置
|
||||||
placeholder="如:cc1d0c142doocs0902bd2d7md4b14da6ylbabc46"
|
</el-button>
|
||||||
/>
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-form>
|
||||||
<el-form-item label="Bucket" :required="true">
|
</el-tab-pane>
|
||||||
<el-input v-model.trim="formAliOSS.bucket" placeholder="如:doocs" />
|
<el-tab-pane class="github-panel" label="阿里云 OSS" name="aliOSS">
|
||||||
</el-form-item>
|
<el-form
|
||||||
<el-form-item label="Bucket 所在区域" :required="true">
|
class="setting-form"
|
||||||
<el-input v-model.trim="formAliOSS.region" placeholder="如:oss-cn-shenzhen" />
|
:model="formAliOSS"
|
||||||
</el-form-item>
|
label-position="right"
|
||||||
<el-form-item label="UseSSL" :required="true">
|
label-width="150px"
|
||||||
<el-switch v-model="formAliOSS.useSSL" active-text="是" inactive-text="否" />
|
>
|
||||||
</el-form-item>
|
<el-form-item label="AccessKey ID" :required="true">
|
||||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
<el-input
|
||||||
<el-input v-model.trim="formAliOSS.cdnHost" placeholder="如:https://imagecdn.alidaodao.com,可不填" />
|
v-model.trim="formAliOSS.accessKeyId"
|
||||||
</el-form-item>
|
placeholder="如:LTAI4GdoocsmdoxUf13ylbaNHk"
|
||||||
<el-form-item label="存储路径">
|
/>
|
||||||
<el-input v-model.trim="formAliOSS.path" placeholder="如:img,可不填,默认为根目录" />
|
</el-form-item>
|
||||||
<el-link type="primary" href="https://help.aliyun.com/document_detail/31883.html" target="_blank">
|
<el-form-item label="AccessKey Secret" :required="true">
|
||||||
如何使用阿里云 OSS?
|
<el-input
|
||||||
</el-link>
|
v-model.trim="formAliOSS.accessKeySecret"
|
||||||
</el-form-item>
|
show-password
|
||||||
<el-form-item>
|
placeholder="如:cc1d0c142doocs0902bd2d7md4b14da6ylbabc46"
|
||||||
<el-button type="primary" @click="saveAliOSSConfiguration">
|
/>
|
||||||
保存配置
|
</el-form-item>
|
||||||
</el-button>
|
<el-form-item label="Bucket" :required="true">
|
||||||
</el-form-item>
|
<el-input v-model.trim="formAliOSS.bucket" placeholder="如:doocs" />
|
||||||
</el-form>
|
</el-form-item>
|
||||||
</el-tab-pane>
|
<el-form-item label="Bucket 所在区域" :required="true">
|
||||||
<el-tab-pane class="github-panel" label="腾讯云 COS" name="txCOS">
|
<el-input
|
||||||
<el-form class="setting-form" :model="formTxCOS" label-position="right" label-width="150px">
|
v-model.trim="formAliOSS.region"
|
||||||
<el-form-item label="SecretId" :required="true">
|
placeholder="如:oss-cn-shenzhen"
|
||||||
<el-input v-model.trim="formTxCOS.secretId" placeholder="如:AKIDnQp1w3DOOCSs8F5MDp9tdoocsmdUPonW3" />
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="SecretKey" :required="true">
|
<el-form-item label="UseSSL" :required="true">
|
||||||
<el-input
|
<el-switch
|
||||||
v-model.trim="formTxCOS.secretKey" show-password
|
v-model="formAliOSS.useSSL"
|
||||||
placeholder="如:ukLmdtEJ9271f3DOocsMDsCXdS3YlbW0"
|
active-text="是"
|
||||||
/>
|
inactive-text="否"
|
||||||
</el-form-item>
|
/>
|
||||||
<el-form-item label="Bucket" :required="true">
|
</el-form-item>
|
||||||
<el-input v-model.trim="formTxCOS.bucket" placeholder="如:doocs-3212520134" />
|
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item label="Bucket 所在区域" :required="true">
|
v-model.trim="formAliOSS.cdnHost"
|
||||||
<el-input v-model.trim="formTxCOS.region" placeholder="如:ap-guangzhou" />
|
placeholder="如:https://imagecdn.alidaodao.com,可不填"
|
||||||
</el-form-item>
|
/>
|
||||||
<el-form-item label="自定义 CDN 域名" :required="false">
|
</el-form-item>
|
||||||
<el-input v-model.trim="formTxCOS.cdnHost" placeholder="如:https://imagecdn.alidaodao.com,可不填" />
|
<el-form-item label="存储路径">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item label="存储路径">
|
v-model.trim="formAliOSS.path"
|
||||||
<el-input v-model.trim="formTxCOS.path" placeholder="如:img,可不填,默认根目录" />
|
placeholder="如:img,可不填,默认为根目录"
|
||||||
<el-link type="primary" href="https://cloud.tencent.com/document/product/436/38484" target="_blank">
|
/>
|
||||||
如何使用腾讯云 COS?
|
<el-link
|
||||||
</el-link>
|
type="primary"
|
||||||
</el-form-item>
|
href="https://help.aliyun.com/document_detail/31883.html"
|
||||||
<el-form-item>
|
target="_blank"
|
||||||
<el-button type="primary" @click="saveTxCOSConfiguration">
|
>
|
||||||
保存配置
|
如何使用阿里云 OSS?
|
||||||
</el-button>
|
</el-link>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
<el-form-item>
|
||||||
</el-tab-pane>
|
<el-button type="primary" @click="saveAliOSSConfiguration">
|
||||||
<el-tab-pane class="github-panel" label="七牛云 Kodo" name="qiniu">
|
保存配置
|
||||||
<el-form class="setting-form" :model="formQiniu" label-position="right" label-width="150px">
|
</el-button>
|
||||||
<el-form-item label="AccessKey" :required="true">
|
</el-form-item>
|
||||||
<el-input v-model.trim="formQiniu.accessKey" placeholder="如:6DD3VaLJ_SQgOdoocsyTV_YWaDmdnL2n8EGx7kG" />
|
</el-form>
|
||||||
</el-form-item>
|
</el-tab-pane>
|
||||||
<el-form-item label="SecretKey" :required="true">
|
<el-tab-pane class="github-panel" label="腾讯云 COS" name="txCOS">
|
||||||
<el-input
|
<el-form
|
||||||
v-model.trim="formQiniu.secretKey" show-password
|
class="setting-form"
|
||||||
placeholder="如:qgZa5qrvDOOcsmdKStD1oCjZ9nB7MDvJUs_34SIm"
|
:model="formTxCOS"
|
||||||
/>
|
label-position="right"
|
||||||
</el-form-item>
|
label-width="150px"
|
||||||
<el-form-item label="Bucket" :required="true">
|
>
|
||||||
<el-input v-model.trim="formQiniu.bucket" placeholder="如:md" />
|
<el-form-item label="SecretId" :required="true">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item label="Bucket 对应域名" :required="true">
|
v-model.trim="formTxCOS.secretId"
|
||||||
<el-input v-model.trim="formQiniu.domain" placeholder="如:https://images.123ylb.cn" />
|
placeholder="如:AKIDnQp1w3DOOCSs8F5MDp9tdoocsmdUPonW3"
|
||||||
</el-form-item>
|
/>
|
||||||
<el-form-item label="存储区域" :required="false">
|
</el-form-item>
|
||||||
<el-input v-model.trim="formQiniu.region" placeholder="如:z2,可不填" />
|
<el-form-item label="SecretKey" :required="true">
|
||||||
</el-form-item>
|
<el-input
|
||||||
<el-form-item label="存储路径" :required="false">
|
v-model.trim="formTxCOS.secretKey"
|
||||||
<el-input v-model.trim="formQiniu.path" placeholder="如:img,可不填,默认为根目录" />
|
show-password
|
||||||
<el-link type="primary" href="https://developer.qiniu.com/kodo" target="_blank">
|
placeholder="如:ukLmdtEJ9271f3DOocsMDsCXdS3YlbW0"
|
||||||
如何使用七牛云 Kodo?
|
/>
|
||||||
</el-link>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="Bucket" :required="true">
|
||||||
<el-form-item>
|
<el-input
|
||||||
<el-button type="primary" @click="saveQiniuConfiguration">
|
v-model.trim="formTxCOS.bucket"
|
||||||
保存配置
|
placeholder="如:doocs-3212520134"
|
||||||
</el-button>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
<el-form-item label="Bucket 所在区域" :required="true">
|
||||||
</el-tab-pane>
|
<el-input v-model.trim="formTxCOS.region" placeholder="如:ap-guangzhou" />
|
||||||
<el-tab-pane class="github-panel" label="MinIO" name="minio">
|
</el-form-item>
|
||||||
<el-form class="setting-form" :model="minioOSS" label-position="right" label-width="150px">
|
<el-form-item label="自定义 CDN 域名" :required="false">
|
||||||
<el-form-item label="Endpoint" :required="true">
|
<el-input
|
||||||
<el-input v-model.trim="minioOSS.endpoint" placeholder="如:play.min.io" />
|
v-model.trim="formTxCOS.cdnHost"
|
||||||
</el-form-item>
|
placeholder="如:https://imagecdn.alidaodao.com,可不填"
|
||||||
<el-form-item label="Port" :required="false">
|
/>
|
||||||
<el-input v-model.trim="minioOSS.port" type="number" placeholder="如:9000,可不填,http 默认为 80,https 默认为 443" />
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="存储路径">
|
||||||
<el-form-item label="UseSSL" :required="true">
|
<el-input
|
||||||
<el-switch v-model="minioOSS.useSSL" active-text="是" inactive-text="否" />
|
v-model.trim="formTxCOS.path"
|
||||||
</el-form-item>
|
placeholder="如:img,可不填,默认根目录"
|
||||||
<el-form-item label="Bucket" :required="true">
|
/>
|
||||||
<el-input v-model.trim="minioOSS.bucket" placeholder="如:doocs" />
|
<el-link
|
||||||
</el-form-item>
|
type="primary"
|
||||||
<el-form-item label="AccessKey" :required="true">
|
href="https://cloud.tencent.com/document/product/436/38484"
|
||||||
<el-input v-model.trim="minioOSS.accessKey" placeholder="如:zhangsan" />
|
target="_blank"
|
||||||
</el-form-item>
|
>
|
||||||
<el-form-item label="SecretKey" :required="true">
|
如何使用腾讯云 COS?
|
||||||
<el-input v-model.trim="minioOSS.secretKey" placeholder="如:asdasdasd" />
|
</el-link>
|
||||||
<el-link
|
</el-form-item>
|
||||||
type="primary" href="http://docs.minio.org.cn/docs/master/minio-client-complete-guide"
|
<el-form-item>
|
||||||
target="_blank"
|
<el-button type="primary" @click="saveTxCOSConfiguration">
|
||||||
>
|
保存配置
|
||||||
如何使用 MinIO?
|
</el-button>
|
||||||
</el-link>
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-form>
|
||||||
<el-form-item>
|
</el-tab-pane>
|
||||||
<el-button type="primary" @click="saveMinioOSSConfiguration">
|
<el-tab-pane class="github-panel" label="七牛云 Kodo" name="qiniu">
|
||||||
保存配置
|
<el-form
|
||||||
</el-button>
|
class="setting-form"
|
||||||
</el-form-item>
|
:model="formQiniu"
|
||||||
</el-form>
|
label-position="right"
|
||||||
</el-tab-pane>
|
label-width="150px"
|
||||||
<el-tab-pane class="github-panel formCustom" label="自定义代码" name="formCustom">
|
>
|
||||||
<el-form class="setting-form" :model="formCustom" label-position="right">
|
<el-form-item label="AccessKey" :required="true">
|
||||||
<el-form-item label="" :required="true">
|
<el-input
|
||||||
<el-input
|
v-model.trim="formQiniu.accessKey"
|
||||||
ref="formCustomElInput" v-model="formCustom.code" class="formCustomElInput" type="textarea"
|
placeholder="如:6DD3VaLJ_SQgOdoocsyTV_YWaDmdnL2n8EGx7kG"
|
||||||
resize="none" placeholder="Your custom code here."
|
/>
|
||||||
/>
|
</el-form-item>
|
||||||
<el-link type="primary" href="https://github.com/doocs/md#自定义上传逻辑" target="_blank">
|
<el-form-item label="SecretKey" :required="true">
|
||||||
参数详情?
|
<el-input
|
||||||
</el-link>
|
v-model.trim="formQiniu.secretKey"
|
||||||
</el-form-item>
|
show-password
|
||||||
<el-form-item>
|
placeholder="如:qgZa5qrvDOOcsmdKStD1oCjZ9nB7MDvJUs_34SIm"
|
||||||
<el-button type="primary" @click="formCustomSave">
|
/>
|
||||||
保存配置
|
</el-form-item>
|
||||||
</el-button>
|
<el-form-item label="Bucket" :required="true">
|
||||||
</el-form-item>
|
<el-input v-model.trim="formQiniu.bucket" placeholder="如:md" />
|
||||||
</el-form>
|
</el-form-item>
|
||||||
</el-tab-pane>
|
<el-form-item label="Bucket 对应域名" :required="true">
|
||||||
</el-tabs>
|
<el-input
|
||||||
</el-dialog>
|
v-model.trim="formQiniu.domain"
|
||||||
|
placeholder="如:https://images.123ylb.cn"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="存储区域" :required="false">
|
||||||
|
<el-input v-model.trim="formQiniu.region" placeholder="如:z2,可不填" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="存储路径" :required="false">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="formQiniu.path"
|
||||||
|
placeholder="如:img,可不填,默认为根目录"
|
||||||
|
/>
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
href="https://developer.qiniu.com/kodo"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
如何使用七牛云 Kodo?
|
||||||
|
</el-link>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="saveQiniuConfiguration">
|
||||||
|
保存配置
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane class="github-panel" label="MinIO" name="minio">
|
||||||
|
<el-form
|
||||||
|
class="setting-form"
|
||||||
|
:model="minioOSS"
|
||||||
|
label-position="right"
|
||||||
|
label-width="150px"
|
||||||
|
>
|
||||||
|
<el-form-item label="Endpoint" :required="true">
|
||||||
|
<el-input v-model.trim="minioOSS.endpoint" placeholder="如:play.min.io" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Port" :required="false">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="minioOSS.port"
|
||||||
|
type="number"
|
||||||
|
placeholder="如:9000,可不填,http 默认为 80,https 默认为 443"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="UseSSL" :required="true">
|
||||||
|
<el-switch v-model="minioOSS.useSSL" active-text="是" inactive-text="否" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Bucket" :required="true">
|
||||||
|
<el-input v-model.trim="minioOSS.bucket" placeholder="如:doocs" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="AccessKey" :required="true">
|
||||||
|
<el-input v-model.trim="minioOSS.accessKey" placeholder="如:zhangsan" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SecretKey" :required="true">
|
||||||
|
<el-input v-model.trim="minioOSS.secretKey" placeholder="如:asdasdasd" />
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
href="http://docs.minio.org.cn/docs/master/minio-client-complete-guide"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
如何使用 MinIO?
|
||||||
|
</el-link>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="saveMinioOSSConfiguration">
|
||||||
|
保存配置
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane class="github-panel formCustom" label="自定义代码" name="formCustom">
|
||||||
|
<el-form class="setting-form" :model="formCustom" label-position="right">
|
||||||
|
<el-form-item label="" :required="true">
|
||||||
|
<el-input
|
||||||
|
ref="formCustomElInput"
|
||||||
|
v-model="formCustom.code"
|
||||||
|
class="formCustomElInput"
|
||||||
|
type="textarea"
|
||||||
|
resize="none"
|
||||||
|
placeholder="Your custom code here."
|
||||||
|
/>
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
href="https://github.com/doocs/md#自定义上传逻辑"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
参数详情?
|
||||||
|
</el-link>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="formCustomSave">
|
||||||
|
保存配置
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.upload__dialog {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-dialog) {
|
|
||||||
width: 55%;
|
|
||||||
min-width: 640px;
|
|
||||||
min-height: 615px;
|
|
||||||
margin: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-upload-dragger) {
|
:deep(.el-upload-dragger) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
|
14
src/components/ui/dialog/Dialog.vue
Normal file
14
src/components/ui/dialog/Dialog.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<DialogRootProps>()
|
||||||
|
const emits = defineEmits<DialogRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogRoot v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</DialogRoot>
|
||||||
|
</template>
|
11
src/components/ui/dialog/DialogClose.vue
Normal file
11
src/components/ui/dialog/DialogClose.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DialogClose, type DialogCloseProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<DialogCloseProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogClose v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</DialogClose>
|
||||||
|
</template>
|
50
src/components/ui/dialog/DialogContent.vue
Normal file
50
src/components/ui/dialog/DialogContent.vue
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
type DialogContentEmits,
|
||||||
|
type DialogContentProps,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { X } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
const emits = defineEmits<DialogContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay
|
||||||
|
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80"
|
||||||
|
/>
|
||||||
|
<DialogContent
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
|
||||||
|
<DialogClose
|
||||||
|
class="data-[state=open]:bg-accent ring-offset-background data-[state=open]:text-muted-foreground focus:ring-ring absolute right-4 top-4 rounded-sm opacity-70 transition-opacity disabled:pointer-events-none hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2"
|
||||||
|
>
|
||||||
|
<X class="h-4 w-4" />
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
</DialogClose>
|
||||||
|
</DialogContent>
|
||||||
|
</DialogPortal>
|
||||||
|
</template>
|
24
src/components/ui/dialog/DialogDescription.vue
Normal file
24
src/components/ui/dialog/DialogDescription.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogDescription
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</DialogDescription>
|
||||||
|
</template>
|
19
src/components/ui/dialog/DialogFooter.vue
Normal file
19
src/components/ui/dialog/DialogFooter.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<{ class?: HTMLAttributes[`class`] }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
16
src/components/ui/dialog/DialogHeader.vue
Normal file
16
src/components/ui/dialog/DialogHeader.vue
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
class?: HTMLAttributes[`class`]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="cn('flex flex-col gap-y-1.5 text-center sm:text-left', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
59
src/components/ui/dialog/DialogScrollContent.vue
Normal file
59
src/components/ui/dialog/DialogScrollContent.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
type DialogContentEmits,
|
||||||
|
type DialogContentProps,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { X } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<DialogContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
const emits = defineEmits<DialogContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogPortal>
|
||||||
|
<DialogOverlay
|
||||||
|
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/80"
|
||||||
|
>
|
||||||
|
<DialogContent
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'relative z-50 grid w-full max-w-lg my-8 gap-4 border border-border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-bind="forwarded"
|
||||||
|
@pointer-down-outside="(event) => {
|
||||||
|
const originalEvent = event.detail.originalEvent;
|
||||||
|
const target = originalEvent.target as HTMLElement;
|
||||||
|
if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
|
||||||
|
<DialogClose
|
||||||
|
class="hover:bg-secondary absolute right-3 top-3 rounded-md p-0.5 transition-colors"
|
||||||
|
>
|
||||||
|
<X class="h-4 w-4" />
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
</DialogClose>
|
||||||
|
</DialogContent>
|
||||||
|
</DialogOverlay>
|
||||||
|
</DialogPortal>
|
||||||
|
</template>
|
29
src/components/ui/dialog/DialogTitle.vue
Normal file
29
src/components/ui/dialog/DialogTitle.vue
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogTitle
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'text-lg font-semibold leading-none tracking-tight',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</DialogTitle>
|
||||||
|
</template>
|
11
src/components/ui/dialog/DialogTrigger.vue
Normal file
11
src/components/ui/dialog/DialogTrigger.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DialogTrigger, type DialogTriggerProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<DialogTriggerProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogTrigger v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</DialogTrigger>
|
||||||
|
</template>
|
9
src/components/ui/dialog/index.ts
Normal file
9
src/components/ui/dialog/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export { default as Dialog } from './Dialog.vue'
|
||||||
|
export { default as DialogClose } from './DialogClose.vue'
|
||||||
|
export { default as DialogTrigger } from './DialogTrigger.vue'
|
||||||
|
export { default as DialogHeader } from './DialogHeader.vue'
|
||||||
|
export { default as DialogTitle } from './DialogTitle.vue'
|
||||||
|
export { default as DialogDescription } from './DialogDescription.vue'
|
||||||
|
export { default as DialogContent } from './DialogContent.vue'
|
||||||
|
export { default as DialogScrollContent } from './DialogScrollContent.vue'
|
||||||
|
export { default as DialogFooter } from './DialogFooter.vue'
|
35
src/components/ui/menubar/Menubar.vue
Normal file
35
src/components/ui/menubar/Menubar.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarRoot,
|
||||||
|
type MenubarRootEmits,
|
||||||
|
type MenubarRootProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarRootProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
const emits = defineEmits<MenubarRootEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarRoot
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex h-10 items-center gap-x-1 rounded-md border bg-background p-1',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</MenubarRoot>
|
||||||
|
</template>
|
40
src/components/ui/menubar/MenubarCheckboxItem.vue
Normal file
40
src/components/ui/menubar/MenubarCheckboxItem.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarCheckboxItem,
|
||||||
|
type MenubarCheckboxItemEmits,
|
||||||
|
type MenubarCheckboxItemProps,
|
||||||
|
MenubarItemIndicator,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarCheckboxItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
const emits = defineEmits<MenubarCheckboxItemEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarCheckboxItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn(
|
||||||
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<span class="absolute left-2 h-3.5 w-3.5 flex items-center justify-center">
|
||||||
|
<MenubarItemIndicator>
|
||||||
|
<Check class="h-4 w-4" />
|
||||||
|
</MenubarItemIndicator>
|
||||||
|
</span>
|
||||||
|
<slot />
|
||||||
|
</MenubarCheckboxItem>
|
||||||
|
</template>
|
43
src/components/ui/menubar/MenubarContent.vue
Normal file
43
src/components/ui/menubar/MenubarContent.vue
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarContent,
|
||||||
|
type MenubarContentProps,
|
||||||
|
MenubarPortal,
|
||||||
|
useForwardProps,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<MenubarContentProps & { class?: HTMLAttributes[`class`] }>(),
|
||||||
|
{
|
||||||
|
align: `start`,
|
||||||
|
alignOffset: -4,
|
||||||
|
sideOffset: 8,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarPortal>
|
||||||
|
<MenubarContent
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'z-50 min-w-48 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</MenubarContent>
|
||||||
|
</MenubarPortal>
|
||||||
|
</template>
|
11
src/components/ui/menubar/MenubarGroup.vue
Normal file
11
src/components/ui/menubar/MenubarGroup.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { MenubarGroup, type MenubarGroupProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarGroupProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarGroup v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</MenubarGroup>
|
||||||
|
</template>
|
35
src/components/ui/menubar/MenubarItem.vue
Normal file
35
src/components/ui/menubar/MenubarItem.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarItem,
|
||||||
|
type MenubarItemEmits,
|
||||||
|
type MenubarItemProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
const emits = defineEmits<MenubarItemEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn(
|
||||||
|
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
|
inset && 'pl-8',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</MenubarItem>
|
||||||
|
</template>
|
13
src/components/ui/menubar/MenubarLabel.vue
Normal file
13
src/components/ui/menubar/MenubarLabel.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { MenubarLabel, type MenubarLabelProps } from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarLabel :class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)">
|
||||||
|
<slot />
|
||||||
|
</MenubarLabel>
|
||||||
|
</template>
|
11
src/components/ui/menubar/MenubarMenu.vue
Normal file
11
src/components/ui/menubar/MenubarMenu.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { MenubarMenu, type MenubarMenuProps } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarMenuProps>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarMenu v-bind="props">
|
||||||
|
<slot />
|
||||||
|
</MenubarMenu>
|
||||||
|
</template>
|
20
src/components/ui/menubar/MenubarRadioGroup.vue
Normal file
20
src/components/ui/menubar/MenubarRadioGroup.vue
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
MenubarRadioGroup,
|
||||||
|
type MenubarRadioGroupEmits,
|
||||||
|
type MenubarRadioGroupProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarRadioGroupProps>()
|
||||||
|
|
||||||
|
const emits = defineEmits<MenubarRadioGroupEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarRadioGroup v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</MenubarRadioGroup>
|
||||||
|
</template>
|
40
src/components/ui/menubar/MenubarRadioItem.vue
Normal file
40
src/components/ui/menubar/MenubarRadioItem.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarItemIndicator,
|
||||||
|
MenubarRadioItem,
|
||||||
|
type MenubarRadioItemEmits,
|
||||||
|
type MenubarRadioItemProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { Circle } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarRadioItemProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
const emits = defineEmits<MenubarRadioItemEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarRadioItem
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="cn(
|
||||||
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<span class="absolute left-2 h-3.5 w-3.5 flex items-center justify-center">
|
||||||
|
<MenubarItemIndicator>
|
||||||
|
<Circle class="h-2 w-2 fill-current" />
|
||||||
|
</MenubarItemIndicator>
|
||||||
|
</span>
|
||||||
|
<slot />
|
||||||
|
</MenubarRadioItem>
|
||||||
|
</template>
|
19
src/components/ui/menubar/MenubarSeparator.vue
Normal file
19
src/components/ui/menubar/MenubarSeparator.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import { MenubarSeparator, type MenubarSeparatorProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarSeparatorProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarSeparator :class=" cn('-mx-1 my-1 h-px bg-muted', props.class)" v-bind="forwardedProps" />
|
||||||
|
</template>
|
14
src/components/ui/menubar/MenubarShortcut.vue
Normal file
14
src/components/ui/menubar/MenubarShortcut.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
class?: HTMLAttributes[`class`]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', props.class)">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</template>
|
19
src/components/ui/menubar/MenubarSub.vue
Normal file
19
src/components/ui/menubar/MenubarSub.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { MenubarSub, type MenubarSubEmits, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
|
interface MenubarSubRootProps {
|
||||||
|
defaultOpen?: boolean
|
||||||
|
open?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<MenubarSubRootProps>()
|
||||||
|
const emits = defineEmits<MenubarSubEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarSub v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</MenubarSub>
|
||||||
|
</template>
|
39
src/components/ui/menubar/MenubarSubContent.vue
Normal file
39
src/components/ui/menubar/MenubarSubContent.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import {
|
||||||
|
MenubarPortal,
|
||||||
|
MenubarSubContent,
|
||||||
|
type MenubarSubContentEmits,
|
||||||
|
type MenubarSubContentProps,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarSubContentProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
const emits = defineEmits<MenubarSubContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarPortal>
|
||||||
|
<MenubarSubContent
|
||||||
|
v-bind="forwarded"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</MenubarSubContent>
|
||||||
|
</MenubarPortal>
|
||||||
|
</template>
|
30
src/components/ui/menubar/MenubarSubTrigger.vue
Normal file
30
src/components/ui/menubar/MenubarSubTrigger.vue
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import { MenubarSubTrigger, type MenubarSubTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { ChevronRight } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes[`class`], inset?: boolean }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarSubTrigger
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="cn(
|
||||||
|
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||||
|
inset && 'pl-8',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
<ChevronRight class="ml-auto h-4 w-4" />
|
||||||
|
</MenubarSubTrigger>
|
||||||
|
</template>
|
29
src/components/ui/menubar/MenubarTrigger.vue
Normal file
29
src/components/ui/menubar/MenubarTrigger.vue
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { type HTMLAttributes, computed } from 'vue'
|
||||||
|
import { MenubarTrigger, type MenubarTriggerProps, useForwardProps } from 'radix-vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<MenubarTriggerProps & { class?: HTMLAttributes[`class`] }>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MenubarTrigger
|
||||||
|
v-bind="forwardedProps"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none hover:bg-accent focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</MenubarTrigger>
|
||||||
|
</template>
|
15
src/components/ui/menubar/index.ts
Normal file
15
src/components/ui/menubar/index.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export { default as Menubar } from './Menubar.vue'
|
||||||
|
export { default as MenubarItem } from './MenubarItem.vue'
|
||||||
|
export { default as MenubarContent } from './MenubarContent.vue'
|
||||||
|
export { default as MenubarGroup } from './MenubarGroup.vue'
|
||||||
|
export { default as MenubarMenu } from './MenubarMenu.vue'
|
||||||
|
export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue'
|
||||||
|
export { default as MenubarRadioItem } from './MenubarRadioItem.vue'
|
||||||
|
export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue'
|
||||||
|
export { default as MenubarSeparator } from './MenubarSeparator.vue'
|
||||||
|
export { default as MenubarSub } from './MenubarSub.vue'
|
||||||
|
export { default as MenubarSubContent } from './MenubarSubContent.vue'
|
||||||
|
export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue'
|
||||||
|
export { default as MenubarTrigger } from './MenubarTrigger.vue'
|
||||||
|
export { default as MenubarShortcut } from './MenubarShortcut.vue'
|
||||||
|
export { default as MenubarLabel } from './MenubarLabel.vue'
|
@ -6,6 +6,7 @@ import App from './App.vue'
|
|||||||
import 'virtual:uno.css'
|
import 'virtual:uno.css'
|
||||||
import 'codemirror/lib/codemirror.css'
|
import 'codemirror/lib/codemirror.css'
|
||||||
import 'codemirror/theme/xq-light.css'
|
import 'codemirror/theme/xq-light.css'
|
||||||
|
import 'codemirror/theme/darcula.css'
|
||||||
|
|
||||||
/* 每个页面公共css */
|
/* 每个页面公共css */
|
||||||
import '@/assets/index.css'
|
import '@/assets/index.css'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { computed, markRaw, onMounted, ref } from 'vue'
|
import { computed, markRaw, onMounted, ref, toRaw, watch } from 'vue'
|
||||||
import { createPinia, defineStore } from 'pinia'
|
import { createPinia, defineStore } from 'pinia'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
@ -184,11 +184,11 @@ export const useStore = defineStore(`store`, () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const cssEditorDom = document.querySelector(`#cssEditor`)
|
const cssEditorDom = document.querySelector(`#cssEditor`)
|
||||||
cssEditorDom.value = getCurrentTab().content
|
cssEditorDom.value = getCurrentTab().content
|
||||||
|
const theme = isDark.value ? `darcula` : `xq-light`
|
||||||
cssEditor.value = markRaw(
|
cssEditor.value = markRaw(
|
||||||
CodeMirror.fromTextArea(cssEditorDom, {
|
CodeMirror.fromTextArea(cssEditorDom, {
|
||||||
mode: `css`,
|
mode: `css`,
|
||||||
theme: `xq-light`,
|
theme,
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
@ -219,6 +219,11 @@ export const useStore = defineStore(`store`, () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(isDark, () => {
|
||||||
|
const theme = isDark.value ? `darcula` : `xq-light`
|
||||||
|
toRaw(cssEditor.value)?.setOption?.(`theme`, theme)
|
||||||
|
})
|
||||||
|
|
||||||
// 重置样式
|
// 重置样式
|
||||||
const resetStyle = () => {
|
const resetStyle = () => {
|
||||||
isCiteStatus.value = false
|
isCiteStatus.value = false
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, toRaw } from 'vue'
|
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
@ -31,7 +31,7 @@ import {
|
|||||||
} from '@/utils'
|
} from '@/utils'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const { output, editor, editorContent, isShowCssEditor } = storeToRefs(store)
|
const { isDark, output, editor, editorContent, isShowCssEditor } = storeToRefs(store)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editorRefresh,
|
editorRefresh,
|
||||||
@ -178,6 +178,12 @@ function uploadImage(file, cb) {
|
|||||||
|
|
||||||
const changeTimer = ref(0)
|
const changeTimer = ref(0)
|
||||||
|
|
||||||
|
// 监听暗色模式并更新编辑器
|
||||||
|
watch(isDark, () => {
|
||||||
|
const theme = isDark.value ? `darcula` : `xq-light`
|
||||||
|
toRaw(editor.value)?.setOption?.(`theme`, theme)
|
||||||
|
})
|
||||||
|
|
||||||
// 初始化编辑器
|
// 初始化编辑器
|
||||||
function initEditor() {
|
function initEditor() {
|
||||||
const editorDom = document.querySelector(`#editor`)
|
const editorDom = document.querySelector(`#editor`)
|
||||||
@ -187,7 +193,7 @@ function initEditor() {
|
|||||||
}
|
}
|
||||||
editor.value = CodeMirror.fromTextArea(editorDom, {
|
editor.value = CodeMirror.fromTextArea(editorDom, {
|
||||||
mode: `text/x-markdown`,
|
mode: `text/x-markdown`,
|
||||||
theme: `xq-light`,
|
theme: isDark.value ? `darcula` : `xq-light`,
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
@ -370,88 +376,82 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="container" class="container">
|
<div ref="container" class="container flex flex-col">
|
||||||
<el-container>
|
<EditorHeader
|
||||||
<el-header class="editor__header">
|
@add-format="addFormat"
|
||||||
<EditorHeader
|
@format-content="formatContent"
|
||||||
@add-format="addFormat"
|
@start-copy="startCopy"
|
||||||
@format-content="formatContent"
|
@end-copy="endCopy"
|
||||||
@start-copy="startCopy"
|
/>
|
||||||
@end-copy="endCopy"
|
<main class="container-main flex-1">
|
||||||
/>
|
<el-row class="container-main-section h-full border-1">
|
||||||
</el-header>
|
<el-col
|
||||||
<el-main class="container-main">
|
ref="codeMirrorWrapper"
|
||||||
<el-row class="container-main-section">
|
:span="isShowCssEditor ? 8 : 12"
|
||||||
<el-col
|
class="codeMirror-wrapper border-r-1"
|
||||||
ref="codeMirrorWrapper"
|
:class="{
|
||||||
:span="isShowCssEditor ? 8 : 12"
|
'order-1': !store.isEditOnLeft,
|
||||||
class="codeMirror-wrapper"
|
}"
|
||||||
:class="{
|
>
|
||||||
'order-1': !store.isEditOnLeft,
|
<ContextMenu>
|
||||||
}"
|
<ContextMenuTrigger>
|
||||||
>
|
<textarea
|
||||||
<ContextMenu>
|
id="editor"
|
||||||
<ContextMenuTrigger>
|
type="textarea"
|
||||||
<textarea
|
placeholder="Your markdown text here."
|
||||||
id="editor"
|
/>
|
||||||
type="textarea"
|
</ContextMenuTrigger>
|
||||||
placeholder="Your markdown text here."
|
<ContextMenuContent class="w-64">
|
||||||
/>
|
<ContextMenuItem inset @click="toggleShowUploadImgDialog()">
|
||||||
</ContextMenuTrigger>
|
上传图片
|
||||||
<ContextMenuContent class="w-64">
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="toggleShowUploadImgDialog()">
|
<ContextMenuItem inset @click="toggleShowInsertFormDialog()">
|
||||||
上传图片
|
插入表格
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="toggleShowInsertFormDialog()">
|
<ContextMenuItem inset @click="resetStyleConfirm()">
|
||||||
插入表格
|
恢复默认样式
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="resetStyleConfirm()">
|
<ContextMenuSeparator />
|
||||||
恢复默认样式
|
<ContextMenuItem inset @click="importMarkdownContent()">
|
||||||
</ContextMenuItem>
|
导入 .md 文档
|
||||||
<ContextMenuSeparator />
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="importMarkdownContent()">
|
<ContextMenuItem inset @click="exportEditorContent2MD()">
|
||||||
导入 .md 文档
|
导出 .md 文档
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="exportEditorContent2MD()">
|
<ContextMenuItem inset @click="exportEditorContent2HTML()">
|
||||||
导出 .md 文档
|
导出 .html
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
<ContextMenuItem inset @click="exportEditorContent2HTML()">
|
<ContextMenuItem inset @click="formatContent()">
|
||||||
导出 .html
|
格式化
|
||||||
</ContextMenuItem>
|
<ContextMenuShortcut>{{ altSign }} + {{ shiftSign }} + F</ContextMenuShortcut>
|
||||||
<ContextMenuItem inset @click="formatContent()">
|
</ContextMenuItem>
|
||||||
格式化
|
</ContextMenuContent>
|
||||||
<ContextMenuShortcut>{{ altSign }} + {{ shiftSign }} + F</ContextMenuShortcut>
|
</ContextMenu>
|
||||||
</ContextMenuItem>
|
</el-col>
|
||||||
</ContextMenuContent>
|
<el-col
|
||||||
</ContextMenu>
|
id="preview"
|
||||||
</el-col>
|
ref="preview"
|
||||||
<el-col
|
:span="isShowCssEditor ? 8 : 12"
|
||||||
id="preview"
|
class="preview-wrapper p-5"
|
||||||
ref="preview"
|
>
|
||||||
:span="isShowCssEditor ? 8 : 12"
|
<div id="output-wrapper" :class="{ output_night: !backLight }">
|
||||||
class="preview-wrapper"
|
<div class="preview border shadow-xl">
|
||||||
>
|
<section id="output" v-html="output" />
|
||||||
<div id="output-wrapper" :class="{ output_night: !backLight }">
|
<div v-if="isCoping" class="loading-mask">
|
||||||
<div class="preview">
|
<div class="loading-mask-box">
|
||||||
<section id="output" v-html="output" />
|
<div class="loading__img" />
|
||||||
<div v-if="isCoping" class="loading-mask">
|
<span>正在生成</span>
|
||||||
<div class="loading-mask-box">
|
|
||||||
<div class="loading__img" />
|
|
||||||
<span>正在生成</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</div>
|
||||||
<CssEditor />
|
</el-col>
|
||||||
</el-row>
|
<CssEditor />
|
||||||
</el-main>
|
</el-row>
|
||||||
</el-container>
|
</main>
|
||||||
|
|
||||||
<UploadImgDialog
|
<UploadImgDialog
|
||||||
@before-upload="beforeUpload"
|
|
||||||
@upload-image="uploadImage"
|
@upload-image="uploadImage"
|
||||||
@uploaded="uploaded"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InsertFormDialog />
|
<InsertFormDialog />
|
||||||
@ -466,20 +466,17 @@ onMounted(() => {
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.container {
|
.container {
|
||||||
height: 100%;
|
height: 100vh;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-main {
|
.container-main {
|
||||||
|
overflow: hidden;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-main-section {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#output-wrapper {
|
#output-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
|
Loading…
Reference in New Issue
Block a user