LoongPanel-Asp/web/components/MarkdownEdit.vue

195 lines
4.4 KiB
Vue
Raw Normal View History

2024-06-29 18:16:29 +08:00
<script lang="ts" setup>
import {MdEditor,MdPreview} from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import {v4 as uuidv4} from 'uuid';
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
import {useToast} from "vue-toastification";
import dayjs from "dayjs";
const props=defineProps({
wordId:{
type:String,
default:null
},
preview:{
type:Boolean,
default:false
},
template:{
type:String,
default: `# ${dayjs().format()}`
2024-07-02 14:28:15 +08:00
},
closeCallBack:{
type:Function,
default:()=>{}
2024-06-29 18:16:29 +08:00
}
})
const text = ref<string>(props.template);
const mainLayoutStore=useMainLayoutStore()
const toast=useToast()
const filenameVisible=ref(false)
let id = uuidv4();
const fileName = ref<string|null>(null);
const saveFileName=()=>{
if(fileName.value===null||fileName.value===''){
toast.error('文件名不能为空')
if(fileName.value!==null&&fileName.value.length<=6){
toast.error('文件名不能小于6位')
}
return
}
filenameVisible.value=false
uploadFile()
}
const onUploadImg = async (files: any[], callback: Function) => {
const res = await Promise.all(
files.map((file) => {
return new Promise((rev, rej) => {
const form = new FormData();
form.append('file', file);
$fetch('/Api/PublicFile/UploadImage', {
method: 'POST',
body: form,
headers: {
'Authorization': "Bearer " + useCookie('token').value
},
baseURL: useRuntimeConfig().public.baseUrl,
}).then(
(res:any) => {
toast.success('上传成功')
rev(`${useRuntimeConfig().public.baseUrl}${res.fileUrl}`)
},
).catch((err) => {
toast.error('上传失败'+err)
rej(err)
})
})
})
);
callback(res.map((item) => item));
};
const onSave = (v:string, _:string) => {
if(fileName.value===null||fileName.value===''&&fileName.value.length<=6){
filenameVisible.value=true
return
}
uploadFile()
};
const uploadFile=()=>{
$fetch('/Api/Server/UpLoadWord', {
method: 'POST',
params:{
serverId: mainLayoutStore.SelectServer.id,
userName:mainLayoutStore.UserInfo.userName,
wordId: id,
},
body: {
name: fileName.value,
content: text.value
},
headers: {
'Authorization': "Bearer " + useCookie('token').value
},
baseURL: useRuntimeConfig().public.baseUrl,
}).then(
(res:any) => {
toast.success(res,{
timeout:1000
})
},
)
}
onBeforeMount(()=>{
if(props.wordId){
id=props.wordId
$fetch('/Api/Server/GetWordContent', {
method: 'GET',
params:{
serverId: mainLayoutStore.SelectServer.id,
wordId: props.wordId,
},
headers: {
"content-type": "application/json",
'Authorization': "Bearer " + useCookie('token').value
},
baseURL: useRuntimeConfig().public.baseUrl,
}).then(
(res:any) =>{
text.value=res.content
fileName.value=res.wordName
}
)
}
})
</script>
<template>
<div class="editor-layout">
<Dialog
v-model:visible="filenameVisible"
modal
header="输入文件名"
>
<div class="fileName">
<input v-model="fileName">
<Button label="保存" @click="saveFileName" />
</div>
</Dialog>
2024-07-02 14:28:15 +08:00
<div class="actions">
<Icon name="X" @click="closeCallBack" ></Icon>
</div>
2024-06-29 18:16:29 +08:00
<MdEditor v-model="text" v-if="!preview" :theme="$colorMode.value as 'light'| 'dark'" class="editor" codeTheme="kimbie"
@onSave="onSave" @onUploadImg="onUploadImg" />
<MdPreview :modelValue="text" v-else class="editor-preview"/>
</div>
</template>
<style lang="scss" scoped>
@import "base";
.editor-layout {
height: 80vh;
display: flex;
justify-content: center;
}
.editor {
width: 80vw;
height: 100%;
border-radius: $radius;
border: $border;
}
.editor-preview{
border-radius: $radius;
width: 40vw;
min-width: 1000px;
}
.fileName{
display: flex;
justify-content: space-between;
input{
width: 70%;
border: $border;
background: rgba(51, 51, 51, 0.1);
border-radius: $radius;
padding: $padding;
}
}
2024-07-02 14:28:15 +08:00
.actions{
position: absolute;
z-index: 20;
top: 10px;
right: 10px;
svg{
cursor: pointer;
stroke: $light-text-color;
color: $light-text-color;
&:hover{
stroke: red;
}
}
}
2024-06-29 18:16:29 +08:00
</style>