chore: update ui

This commit is contained in:
YangFong 2024-12-04 14:17:33 +08:00
parent c52593ba50
commit fd24cb67a2
16 changed files with 296 additions and 50 deletions

View File

@ -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",

View File

@ -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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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'

View 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>

View File

@ -0,0 +1 @@
export { default as Toaster } from './Sonner.vue'

View File

@ -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 {

View File

@ -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