mirror of
https://github.com/doocs/md.git
synced 2025-02-10 16:55:49 +08:00
chore: update ui
This commit is contained in:
parent
c52593ba50
commit
fd24cb67a2
@ -47,7 +47,8 @@
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tiny-oss": "^0.5.1",
|
||||
"uuid": "^11.0.3",
|
||||
"vue": "^3.5.13"
|
||||
"vue": "^3.5.13",
|
||||
"vue-sonner": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "3.11.0",
|
||||
|
@ -1,4 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Menubar,
|
||||
@ -17,7 +28,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
|
||||
import { Toaster } from '@/components/ui/sonner'
|
||||
import {
|
||||
altSign,
|
||||
codeBlockThemeOptions,
|
||||
@ -32,16 +43,14 @@ import {
|
||||
} from '@/config'
|
||||
import { useDisplayStore, useStore } from '@/stores'
|
||||
import { mergeCss, solveWeChatImage } from '@/utils'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { Moon, Paintbrush, Sun } from 'lucide-vue-next'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import { nextTick } from 'vue'
|
||||
import EditDropdown from './EditDropdown.vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
import EditDropdown from './EditDropdown.vue'
|
||||
import FileDropdown from './FileDropdown.vue'
|
||||
import HelpDropdown from './HelpDropdown.vue'
|
||||
|
||||
import PostInfo from './PostInfo.vue'
|
||||
import StyleDropdown from './StyleDropdown.vue'
|
||||
|
||||
@ -152,13 +161,7 @@ function copy() {
|
||||
}
|
||||
|
||||
// 输出提示
|
||||
ElNotification({
|
||||
showClose: true,
|
||||
message: `已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴`,
|
||||
offset: 80,
|
||||
duration: 1600,
|
||||
type: `success`,
|
||||
})
|
||||
toast.success(`已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴`)
|
||||
|
||||
editorRefresh()
|
||||
emit(`endCopy`)
|
||||
@ -493,12 +496,28 @@ function customStyle() {
|
||||
<div class="space-y-2">
|
||||
<h2>样式配置</h2>
|
||||
<div>
|
||||
<Button
|
||||
class="w-full"
|
||||
@click="store.resetStyleConfirm()"
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger as-child>
|
||||
<!-- <Button variant="outline">-->
|
||||
<Button>
|
||||
重置
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>提示</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
此操作将丢失本地自定义样式,是否继续?
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||
<AlertDialogAction @click="store.resetStyleConfirm()">
|
||||
确认
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -509,6 +528,8 @@ function customStyle() {
|
||||
</Button>
|
||||
|
||||
<PostInfo />
|
||||
|
||||
<Toaster close-button rich-colors position="top-center" />
|
||||
</header>
|
||||
</template>
|
||||
|
||||
|
14
src/components/ui/alert-dialog/AlertDialog.vue
Normal file
14
src/components/ui/alert-dialog/AlertDialog.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { type AlertDialogEmits, type AlertDialogProps, AlertDialogRoot, useForwardPropsEmits } from 'radix-vue'
|
||||
|
||||
const props = defineProps<AlertDialogProps>()
|
||||
const emits = defineEmits<AlertDialogEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogRoot v-bind="forwarded">
|
||||
<slot />
|
||||
</AlertDialogRoot>
|
||||
</template>
|
20
src/components/ui/alert-dialog/AlertDialogAction.vue
Normal file
20
src/components/ui/alert-dialog/AlertDialogAction.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue'
|
||||
import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<AlertDialogActionProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogAction v-bind="delegatedProps" :class="cn(buttonVariants(), props.class)">
|
||||
<slot />
|
||||
</AlertDialogAction>
|
||||
</template>
|
27
src/components/ui/alert-dialog/AlertDialogCancel.vue
Normal file
27
src/components/ui/alert-dialog/AlertDialogCancel.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
import { buttonVariants } from '@/components/ui/button'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue'
|
||||
import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<AlertDialogCancelProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogCancel
|
||||
v-bind="delegatedProps"
|
||||
:class="cn(
|
||||
buttonVariants({ variant: 'outline' }),
|
||||
'mt-2 sm:mt-0',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogCancel>
|
||||
</template>
|
42
src/components/ui/alert-dialog/AlertDialogContent.vue
Normal file
42
src/components/ui/alert-dialog/AlertDialogContent.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
AlertDialogContent,
|
||||
type AlertDialogContentEmits,
|
||||
type AlertDialogContentProps,
|
||||
AlertDialogOverlay,
|
||||
AlertDialogPortal,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<AlertDialogContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<AlertDialogContentEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay
|
||||
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
||||
/>
|
||||
<AlertDialogContent
|
||||
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 />
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</template>
|
25
src/components/ui/alert-dialog/AlertDialogDescription.vue
Normal file
25
src/components/ui/alert-dialog/AlertDialogDescription.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<script setup lang="ts">
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
AlertDialogDescription,
|
||||
type AlertDialogDescriptionProps,
|
||||
} from 'radix-vue'
|
||||
import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<AlertDialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogDescription
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogDescription>
|
||||
</template>
|
21
src/components/ui/alert-dialog/AlertDialogFooter.vue
Normal file
21
src/components/ui/alert-dialog/AlertDialogFooter.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<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/alert-dialog/AlertDialogHeader.vue
Normal file
16
src/components/ui/alert-dialog/AlertDialogHeader.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-2 text-center sm:text-left', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
22
src/components/ui/alert-dialog/AlertDialogTitle.vue
Normal file
22
src/components/ui/alert-dialog/AlertDialogTitle.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { cn } from '@/lib/utils'
|
||||
import { AlertDialogTitle, type AlertDialogTitleProps } from 'radix-vue'
|
||||
import { computed, type HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<AlertDialogTitleProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogTitle
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('text-lg font-semibold', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogTitle>
|
||||
</template>
|
11
src/components/ui/alert-dialog/AlertDialogTrigger.vue
Normal file
11
src/components/ui/alert-dialog/AlertDialogTrigger.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { AlertDialogTrigger, type AlertDialogTriggerProps } from 'radix-vue'
|
||||
|
||||
const props = defineProps<AlertDialogTriggerProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogTrigger v-bind="props">
|
||||
<slot />
|
||||
</AlertDialogTrigger>
|
||||
</template>
|
9
src/components/ui/alert-dialog/index.ts
Normal file
9
src/components/ui/alert-dialog/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export { default as AlertDialog } from './AlertDialog.vue'
|
||||
export { default as AlertDialogAction } from './AlertDialogAction.vue'
|
||||
export { default as AlertDialogCancel } from './AlertDialogCancel.vue'
|
||||
export { default as AlertDialogContent } from './AlertDialogContent.vue'
|
||||
export { default as AlertDialogDescription } from './AlertDialogDescription.vue'
|
||||
export { default as AlertDialogFooter } from './AlertDialogFooter.vue'
|
||||
export { default as AlertDialogHeader } from './AlertDialogHeader.vue'
|
||||
export { default as AlertDialogTitle } from './AlertDialogTitle.vue'
|
||||
export { default as AlertDialogTrigger } from './AlertDialogTrigger.vue'
|
22
src/components/ui/sonner/Sonner.vue
Normal file
22
src/components/ui/sonner/Sonner.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<script lang="ts" setup>
|
||||
import { Toaster as Sonner, type ToasterProps } from 'vue-sonner'
|
||||
|
||||
const props = defineProps<ToasterProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sonner
|
||||
class="toaster group"
|
||||
v-bind="props"
|
||||
:toast-options="{
|
||||
classes: {
|
||||
toast: 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',
|
||||
description: 'group-[.toast]:text-muted-foreground',
|
||||
actionButton:
|
||||
'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',
|
||||
cancelButton:
|
||||
'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground',
|
||||
},
|
||||
}"
|
||||
/>
|
||||
</template>
|
1
src/components/ui/sonner/index.ts
Normal file
1
src/components/ui/sonner/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as Toaster } from './Sonner.vue'
|
@ -6,10 +6,10 @@ import { initRenderer } from '@/utils/renderer'
|
||||
import { useDark, useStorage, useToggle } from '@vueuse/core'
|
||||
|
||||
import CodeMirror from 'codemirror'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { marked } from 'marked'
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, markRaw, onMounted, ref, toRaw, watch } from 'vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
export const useStore = defineStore(`store`, () => {
|
||||
// 是否开启深色模式
|
||||
@ -361,7 +361,7 @@ export const useStore = defineStore(`store`, () => {
|
||||
reader.readAsText(file)
|
||||
reader.onload = (event) => {
|
||||
(editor.value!).setValue((event.target!).result as string)
|
||||
ElMessage.success(`文档导入成功`)
|
||||
toast.success(`文档导入成功`)
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,26 +372,23 @@ export const useStore = defineStore(`store`, () => {
|
||||
|
||||
// 重置样式
|
||||
const resetStyleConfirm = () => {
|
||||
ElMessageBox.confirm(
|
||||
`此操作将丢失本地自定义样式,是否继续?`,
|
||||
`提示`,
|
||||
{
|
||||
confirmButtonText: `确定`,
|
||||
cancelButtonText: `取消`,
|
||||
type: `warning`,
|
||||
center: true,
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
// ElMessageBox.confirm(
|
||||
// `此操作将丢失本地自定义样式,是否继续?`,
|
||||
// `提示`,
|
||||
// {
|
||||
// confirmButtonText: `确定`,
|
||||
// cancelButtonText: `取消`,
|
||||
// type: `warning`,
|
||||
// center: true,
|
||||
// },
|
||||
// )
|
||||
// .then(() => {
|
||||
resetStyle()
|
||||
ElMessage({
|
||||
type: `success`,
|
||||
message: `样式重置成功~`,
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
(editor.value!).focus()
|
||||
})
|
||||
toast.success(`样式重置成功~`)
|
||||
// })
|
||||
// .catch(() => {
|
||||
// (editor.value!).focus()
|
||||
// })
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -4,7 +4,6 @@ import CssEditor from '@/components/CodemirrorEditor/CssEditor.vue'
|
||||
import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index.vue'
|
||||
import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog.vue'
|
||||
import UploadImgDialog from '@/components/CodemirrorEditor/UploadImgDialog.vue'
|
||||
|
||||
import RunLoading from '@/components/RunLoading.vue'
|
||||
import {
|
||||
ContextMenu,
|
||||
@ -24,12 +23,10 @@ import {
|
||||
} from '@/utils'
|
||||
import fileApi from '@/utils/file'
|
||||
import CodeMirror from 'codemirror'
|
||||
|
||||
import { ElCol, ElMessage } from 'element-plus'
|
||||
|
||||
import { ElCol } from 'element-plus'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import { onMounted, ref, toRaw, watch } from 'vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
const store = useStore()
|
||||
const displayStore = useDisplayStore()
|
||||
@ -131,7 +128,7 @@ function beforeUpload(file: File) {
|
||||
// validate image
|
||||
const checkResult = checkImage(file)
|
||||
if (!checkResult.ok) {
|
||||
ElMessage.error(checkResult.msg)
|
||||
toast.error(checkResult.msg)
|
||||
return false
|
||||
}
|
||||
|
||||
@ -142,7 +139,7 @@ function beforeUpload(file: File) {
|
||||
const config = localStorage.getItem(`${imgHost}Config`)
|
||||
const isValidHost = imgHost === `default` || config
|
||||
if (!isValidHost) {
|
||||
ElMessage.error(`请先配置 ${imgHost} 图床参数`)
|
||||
toast.error(`请先配置 ${imgHost} 图床参数`)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -151,7 +148,7 @@ function beforeUpload(file: File) {
|
||||
// 图片上传结束
|
||||
function uploaded(imageUrl: string) {
|
||||
if (!imageUrl) {
|
||||
ElMessage.error(`上传图片未知异常`)
|
||||
toast.error(`上传图片未知异常`)
|
||||
return
|
||||
}
|
||||
toggleShowUploadImgDialog(false)
|
||||
@ -160,7 +157,7 @@ function uploaded(imageUrl: string) {
|
||||
const markdownImage = `![](${imageUrl})`
|
||||
// 将 Markdown 形式的 URL 插入编辑框光标所在位置
|
||||
toRaw(store.editor!).replaceSelection(`\n${markdownImage}\n`, cursor as any)
|
||||
ElMessage.success(`图片上传成功`)
|
||||
toast.success(`图片上传成功`)
|
||||
}
|
||||
function uploadImage(file: File, cb?: { (url: any): void, (arg0: unknown): void } | undefined) {
|
||||
isImgLoading.value = true
|
||||
@ -176,7 +173,7 @@ function uploadImage(file: File, cb?: { (url: any): void, (arg0: unknown): void
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage.error(err.message)
|
||||
toast.error(err.message)
|
||||
})
|
||||
.finally(() => {
|
||||
isImgLoading.value = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user