mirror of
https://github.com/doocs/md.git
synced 2025-01-22 20:04:39 +08:00
Compare commits
2 Commits
741322d69e
...
5094d90b43
Author | SHA1 | Date | |
---|---|---|---|
|
5094d90b43 | ||
|
1dc3693826 |
@ -1,12 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
import { Info } from 'lucide-vue-next'
|
import { Info } from 'lucide-vue-next'
|
||||||
|
import { Primitive } from 'radix-vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const { output } = storeToRefs(store)
|
const { output } = storeToRefs(store)
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
|
const extensionInstalled = ref(false)
|
||||||
const form = ref<any>({
|
const form = ref<any>({
|
||||||
title: ``,
|
title: ``,
|
||||||
desc: ``,
|
desc: ``,
|
||||||
@ -40,12 +41,12 @@ function prePost() {
|
|||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
syncPost: (data: { thumb: string, title: string, desc: string, content: string }) => void
|
syncPost: (data: { thumb: string, title: string, desc: string, content: string }) => void
|
||||||
|
$syncer: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function post() {
|
function post() {
|
||||||
dialogVisible.value = false;
|
dialogVisible.value = false;
|
||||||
// 使用 window.$syncer 可以检测是否安装插件
|
|
||||||
(window.syncPost)({
|
(window.syncPost)({
|
||||||
thumb: form.value.thumb || form.value.auto.thumb,
|
thumb: form.value.thumb || form.value.auto.thumb,
|
||||||
title: form.value.title || form.value.auto.title,
|
title: form.value.title || form.value.auto.title,
|
||||||
@ -59,6 +60,10 @@ function onUpdate(val: boolean) {
|
|||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
extensionInstalled.value = window.$syncer !== undefined
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -80,6 +85,23 @@ function onUpdate(val: boolean) {
|
|||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
|
<Alert v-if="!extensionInstalled">
|
||||||
|
<Info class="h-4 w-4" />
|
||||||
|
<AlertTitle>未检测到插件</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
请安装
|
||||||
|
<Primitive
|
||||||
|
as="a"
|
||||||
|
class="text-blue-500"
|
||||||
|
href="https://www.wechatsync.com/?utm_source=syncicon#install"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
文章同步助手
|
||||||
|
</Primitive>
|
||||||
|
插件
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
|
||||||
<div class="w-full flex items-center gap-4">
|
<div class="w-full flex items-center gap-4">
|
||||||
<Label for="thumb" class="w-10 text-end">
|
<Label for="thumb" class="w-10 text-end">
|
||||||
封面
|
封面
|
||||||
@ -103,7 +125,7 @@ function onUpdate(val: boolean) {
|
|||||||
<Button variant="outline" @click="dialogVisible = false">
|
<Button variant="outline" @click="dialogVisible = false">
|
||||||
取 消
|
取 消
|
||||||
</Button>
|
</Button>
|
||||||
<Button @click="post">
|
<Button :disabled="!extensionInstalled" @click="post">
|
||||||
确 定
|
确 定
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
} from '@/config'
|
} from '@/config'
|
||||||
import { useStore } from '@/stores'
|
import { useStore } from '@/stores'
|
||||||
import { addPrefix, processClipboardContent } from '@/utils'
|
import { addPrefix, processClipboardContent } from '@/utils'
|
||||||
import { ChevronDownIcon, PanelLeftClose, PanelLeftOpen, Settings } from 'lucide-vue-next'
|
import { ChevronDownIcon, Moon, PanelLeftClose, PanelLeftOpen, Settings, Sun } from 'lucide-vue-next'
|
||||||
|
|
||||||
const emit = defineEmits([`addFormat`, `formatContent`, `startCopy`, `endCopy`])
|
const emit = defineEmits([`addFormat`, `formatContent`, `startCopy`, `endCopy`])
|
||||||
|
|
||||||
@ -155,6 +155,11 @@ function copy() {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
|
||||||
|
<Button variant="outline" @click="toggleDark()">
|
||||||
|
<Moon v-show="isDark" class="size-4" />
|
||||||
|
<Sun v-show="!isDark" class="size-4" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
<div class="space-x-1 bg-background text-background-foreground mx-2 flex items-center border rounded-md">
|
<div class="space-x-1 bg-background text-background-foreground mx-2 flex items-center border rounded-md">
|
||||||
<Button variant="ghost" class="shadow-none" @click="copy">
|
<Button variant="ghost" class="shadow-none" @click="copy">
|
||||||
复制
|
复制
|
||||||
|
61
src/components/ui/back-top/BackTop.vue
Normal file
61
src/components/ui/back-top/BackTop.vue
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { throttle } from 'es-toolkit'
|
||||||
|
import { ArrowUpFromLine } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
type Target = HTMLElement | Window | null
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
left?: number
|
||||||
|
top?: number
|
||||||
|
right?: number
|
||||||
|
bottom?: number
|
||||||
|
visibilityHeight?: number
|
||||||
|
target?: string
|
||||||
|
onClick?: (e: MouseEvent) => void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const visibilityHeight = ref(props.visibilityHeight ?? 400)
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
const target = ref<Target>(null)
|
||||||
|
|
||||||
|
function scrollToTop(e: MouseEvent) {
|
||||||
|
console.log(`scrollToTop`)
|
||||||
|
target.value?.scrollTo({ top: 0, left: 0, behavior: `smooth` })
|
||||||
|
props.onClick?.(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const throttledScroll = throttle((el: Target) => {
|
||||||
|
if (el instanceof HTMLElement) {
|
||||||
|
visible.value = el.scrollTop > visibilityHeight.value
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
visible.value = window.scrollY > visibilityHeight.value
|
||||||
|
}
|
||||||
|
}, 200, { edges: [`leading`, `trailing`] })
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.target) {
|
||||||
|
target.value = document.getElementById(props.target)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target.value = window
|
||||||
|
}
|
||||||
|
|
||||||
|
target.value!.addEventListener(`scroll`, () => {
|
||||||
|
throttledScroll(target.value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
target.value!.removeEventListener(`scroll`, () => {
|
||||||
|
throttledScroll(target.value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Button v-if="visible" variant="outline" size="icon" class="fixed z-50 rounded-full" :style="{ left: `${left}px`, top: `${top}px`, right: `${right}px`, bottom: `${bottom}px` }" @click="scrollToTop">
|
||||||
|
<ArrowUpFromLine />
|
||||||
|
</Button>
|
||||||
|
</template>
|
1
src/components/ui/back-top/index.ts
Normal file
1
src/components/ui/back-top/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as BackTop } from './BackTop.vue'
|
@ -430,6 +430,8 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<BackTop target="preview" :right="40" :bottom="40" />
|
||||||
</div>
|
</div>
|
||||||
<CssEditor class="order-2 flex-1" />
|
<CssEditor class="order-2 flex-1" />
|
||||||
<RightSlider class="order-2" />
|
<RightSlider class="order-2" />
|
||||||
|
Loading…
Reference in New Issue
Block a user