|
@@ -7,55 +7,44 @@
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<div class="editor-wrap">
|
|
<div class="editor-wrap">
|
|
- <n-form
|
|
|
|
- ref="modalFormRef" class="form wh-full" label-placement="left" label-align="left" :label-width="80"
|
|
|
|
- :model="modalForm"
|
|
|
|
- >
|
|
|
|
- <n-form-item
|
|
|
|
- label="文章名称" path="title" :rule="{
|
|
|
|
- required: true,
|
|
|
|
- message: '请输入文章名称',
|
|
|
|
- trigger: ['input', 'blur'],
|
|
|
|
- }"
|
|
|
|
- >
|
|
|
|
|
|
+ <n-form ref="modalFormRef" class="form wh-full" label-placement="left" label-align="left" :label-width="80"
|
|
|
|
+ :model="modalForm">
|
|
|
|
+ <n-form-item label="文章名称" path="title" :rule="{
|
|
|
|
+ required: true,
|
|
|
|
+ message: '请输入文章名称',
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
+ }">
|
|
<n-input v-model:value="modalForm.title" />
|
|
<n-input v-model:value="modalForm.title" />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
|
|
|
|
- <n-form-item
|
|
|
|
- label="文章分类" path="categoryId" :rule="{
|
|
|
|
- required: true,
|
|
|
|
- type: 'number',
|
|
|
|
- trigger: ['change', 'blur'],
|
|
|
|
- message: '请输入文章分类',
|
|
|
|
- }"
|
|
|
|
- >
|
|
|
|
- <n-tree-select
|
|
|
|
- v-model:value="modalForm.categoryId"
|
|
|
|
- :options="allCategory"
|
|
|
|
- label-field="title"
|
|
|
|
- key-field="id"
|
|
|
|
- placeholder="根分类"
|
|
|
|
- clearable
|
|
|
|
- style="max-width: 300px;"
|
|
|
|
- />
|
|
|
|
|
|
+ <n-form-item label="文章分类" path="categoryId" :rule="{
|
|
|
|
+ required: true,
|
|
|
|
+ type: 'number',
|
|
|
|
+ trigger: ['change', 'blur'],
|
|
|
|
+ message: '请输入文章分类',
|
|
|
|
+ }">
|
|
|
|
+ <n-tree-select v-model:value="modalForm.categoryId" :options="allCategory" label-field="title" key-field="id"
|
|
|
|
+ placeholder="根分类" clearable style="max-width: 300px;" />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
|
|
|
|
<n-tabs type="line" animated>
|
|
<n-tabs type="line" animated>
|
|
<template v-for="(lang, index) in langs" :key="lang">
|
|
<template v-for="(lang, index) in langs" :key="lang">
|
|
<n-tab-pane :name="lang" :tab="langLabel[lang]" :index="index">
|
|
<n-tab-pane :name="lang" :tab="langLabel[lang]" :index="index">
|
|
- <n-form-item
|
|
|
|
- label="文章名称" path="title" :rule="{
|
|
|
|
- required: true,
|
|
|
|
- message: '请输入文章名称',
|
|
|
|
- trigger: ['input', 'blur'],
|
|
|
|
- }"
|
|
|
|
- >
|
|
|
|
|
|
+ <n-form-item label="文章名称" path="title" :rule="{
|
|
|
|
+ required: true,
|
|
|
|
+ message: '请输入文章名称',
|
|
|
|
+ trigger: ['input', 'blur'],
|
|
|
|
+ }">
|
|
<n-input v-model:value="modalForm.translations[index].title" />
|
|
<n-input v-model:value="modalForm.translations[index].title" />
|
|
</n-form-item>
|
|
</n-form-item>
|
|
<div class="h-450">
|
|
<div class="h-450">
|
|
- <VividEditor v-model="modalForm.translations[index].content" :dark="isDark">
|
|
|
|
|
|
+ <VividEditor v-model="modalForm.translations[index].content" :dark="isDark"
|
|
|
|
+ :handle-image-upload="handleUpload" :handle-video-upload="handleVideoUpload" >
|
|
<SlashCommand />
|
|
<SlashCommand />
|
|
<DragHandle />
|
|
<DragHandle />
|
|
|
|
+ <!-- <template #menu>
|
|
|
|
+ <ImageExt />
|
|
|
|
+ </template> -->
|
|
</VividEditor>
|
|
</VividEditor>
|
|
</div>
|
|
</div>
|
|
</n-tab-pane>
|
|
</n-tab-pane>
|
|
@@ -67,7 +56,7 @@
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
-import { DragHandle, SlashCommand, VividEditor } from '@4dkankan/vivid'
|
|
|
|
|
|
+import { DragHandle, ImageExt, SlashCommand, VividEditor } from '@4dkankan/vivid'
|
|
import { useUserStore } from '@/store/index.js'
|
|
import { useUserStore } from '@/store/index.js'
|
|
import { initTranslations, langLabel, langs } from '@/utils/translations'
|
|
import { initTranslations, langLabel, langs } from '@/utils/translations'
|
|
import { useDark } from '@vueuse/core'
|
|
import { useDark } from '@vueuse/core'
|
|
@@ -120,6 +109,28 @@ function handleAdd() {
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
+function handleUpload(file) {
|
|
|
|
+ // eslint-disable-next-line no-async-promise-executor
|
|
|
|
+ return new Promise(async (resolve) => {
|
|
|
|
+ // console.log('handleUpload', file)
|
|
|
|
+ const data = new FormData()
|
|
|
|
+ // data.append('file', file)
|
|
|
|
+ const res = await articleApi.uploadImage(data)
|
|
|
|
+ // console.log('res', res)
|
|
|
|
+ resolve(res.data)
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+function handleVideoUpload(file) {
|
|
|
|
+ // eslint-disable-next-line no-async-promise-executor
|
|
|
|
+ return new Promise(async (resolve) => {
|
|
|
|
+ // console.log('handleUpload', file)
|
|
|
|
+ const data = new FormData()
|
|
|
|
+ data.append('file', file)
|
|
|
|
+ const res = await articleApi.uploadImage(data)
|
|
|
|
+ // console.log('res', res)
|
|
|
|
+ resolve(res.data)
|
|
|
|
+ })
|
|
|
|
+}
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style>
|
|
<style>
|