pref: split editor module
This commit is contained in:
parent
29b02adbf0
commit
3006f9e9e8
|
@ -3,15 +3,8 @@ import { defineAsyncComponent, computed, ref, onBeforeMount } from 'vue'
|
||||||
|
|
||||||
// 引入编辑器
|
// 引入编辑器
|
||||||
import { QuillEditor } from '@vueup/vue-quill'
|
import { QuillEditor } from '@vueup/vue-quill'
|
||||||
// 引入 quill module: for resizing and realigning images and iframe video
|
// 导入编辑器 Modules
|
||||||
import BlotFormatter from 'quill-blot-formatter'
|
import { modules } from './modules'
|
||||||
// 引入 module: 上传图片
|
|
||||||
import ImageUploader from 'quill-image-uploader'
|
|
||||||
// 引入 module: URL、邮箱 自动识别
|
|
||||||
import MagicUrl from 'quill-magic-url'
|
|
||||||
// 引入 module: mention
|
|
||||||
import Mention from 'quill-mention'
|
|
||||||
import '@/styles/editor/editor.snow.scss'
|
|
||||||
|
|
||||||
// 自定义 quill 的两个主题,第二个主题暂时懒得动
|
// 自定义 quill 的两个主题,第二个主题暂时懒得动
|
||||||
import '@/styles/editor/editor.snow.scss'
|
import '@/styles/editor/editor.snow.scss'
|
||||||
|
@ -58,127 +51,6 @@ const props = defineProps<{
|
||||||
// 编辑器实例
|
// 编辑器实例
|
||||||
const editorRef = ref<typeof QuillEditor>()
|
const editorRef = ref<typeof QuillEditor>()
|
||||||
|
|
||||||
// 定义提及源数据的接口
|
|
||||||
interface MentionItem {
|
|
||||||
id: number
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑器 modules
|
|
||||||
const modules = [
|
|
||||||
// BlotFormatter
|
|
||||||
{
|
|
||||||
name: 'blotFormatter',
|
|
||||||
module: BlotFormatter,
|
|
||||||
// see: https://github.com/Fandom-OSS/quill-blot-formatter/blob/master/src/Options.js
|
|
||||||
options: {
|
|
||||||
overlay: {
|
|
||||||
style: {
|
|
||||||
border: '2px solid var(--kungalgame-blue-3)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// ImageUploader
|
|
||||||
{
|
|
||||||
name: 'imageUploader',
|
|
||||||
module: ImageUploader,
|
|
||||||
options: {
|
|
||||||
upload: (file: File) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('image', file)
|
|
||||||
// 在这里发送请求
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// MagicUrl
|
|
||||||
{
|
|
||||||
name: 'magicUrl',
|
|
||||||
module: MagicUrl,
|
|
||||||
options: {
|
|
||||||
// Regex used to check URLs during typing
|
|
||||||
urlRegularExpression:
|
|
||||||
/(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}(?:\/[^\s]*)?/,
|
|
||||||
// Regex used to check URLs on paste
|
|
||||||
globalRegularExpression: /(https?:\/\/|www\.|tel:)[\S]+/g,
|
|
||||||
mailRegularExpression: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
||||||
globalMailRegularExpression:
|
|
||||||
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Mention
|
|
||||||
{
|
|
||||||
name: 'mention',
|
|
||||||
module: Mention,
|
|
||||||
options: {
|
|
||||||
// 允许的输入搜索字符
|
|
||||||
// allowedChars: /^[A-Za-z\s]*$/,
|
|
||||||
// 触发 mention 操作的关键词
|
|
||||||
mentionDenotationChars: ['@', '#'],
|
|
||||||
/**
|
|
||||||
* @param {string} searchTerm - 用户输入的搜索关键词
|
|
||||||
* @param {(items: MentionItem[]) => void} renderList - 渲染列表回调函数,需传入从后端获取的搜索结果数组
|
|
||||||
* @param {string} mentionChar - 触发 mention 操作的关键词
|
|
||||||
*/
|
|
||||||
source: async function (
|
|
||||||
searchTerm: string,
|
|
||||||
renderList: (items: MentionItem[]) => void,
|
|
||||||
mentionChar: string
|
|
||||||
) {
|
|
||||||
// 根据 mentionChar 的不同值执行不同的搜索逻辑
|
|
||||||
if (mentionChar === '@') {
|
|
||||||
// 执行对用户的搜索
|
|
||||||
const matchedUsers: MentionItem[] = await searchUsers(searchTerm)
|
|
||||||
renderList(matchedUsers)
|
|
||||||
} else if (mentionChar === '#') {
|
|
||||||
// 执行对话题的搜索
|
|
||||||
const matchedTopics: MentionItem[] = await searchTopics(searchTerm)
|
|
||||||
renderList(matchedTopics)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// 模拟搜索用户的函数
|
|
||||||
async function searchUsers(searchTerm: string): Promise<MentionItem[]> {
|
|
||||||
// 实际搜索逻辑
|
|
||||||
// 返回匹配的用户列表
|
|
||||||
return [
|
|
||||||
{ id: 1, value: 'kun' },
|
|
||||||
{ id: 2, value: 'yuyu' },
|
|
||||||
{ id: 3, value: 'kun' },
|
|
||||||
{ id: 4, value: 'yuyu' },
|
|
||||||
{ id: 5, value: 'kun' },
|
|
||||||
{ id: 6, value: 'yuyu' },
|
|
||||||
{ id: 7, value: 'kun' },
|
|
||||||
{ id: 8, value: 'yuyu' },
|
|
||||||
{ id: 9, value: 'kun' },
|
|
||||||
{ id: 10, value: 'yuyu' },
|
|
||||||
{ id: 11, value: 'kun' },
|
|
||||||
{ id: 12, value: 'yuyu' },
|
|
||||||
{ id: 13, value: 'kun' },
|
|
||||||
{ id: 14, value: 'yuyu' },
|
|
||||||
{ id: 15, value: 'kun' },
|
|
||||||
{ id: 16, value: 'yuyu' },
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟搜索话题的函数
|
|
||||||
async function searchTopics(searchTerm: string): Promise<MentionItem[]> {
|
|
||||||
// 实际搜索逻辑
|
|
||||||
// 返回匹配的话题列表
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
value: '啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星',
|
|
||||||
},
|
|
||||||
{ id: 2, value: '鲲最可爱' },
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑器的高度
|
// 编辑器的高度
|
||||||
const editorHeightStyle = computed(
|
const editorHeightStyle = computed(
|
||||||
() => `height: ${props.height ? props.height : editorHeight.value}px`
|
() => `height: ${props.height ? props.height : editorHeight.value}px`
|
||||||
|
@ -206,8 +78,6 @@ onBeforeMount(() => {
|
||||||
if (isSave.value) {
|
if (isSave.value) {
|
||||||
valueHtml.value = content.value
|
valueHtml.value = content.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不显示高级选项则隐藏工具栏
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 编辑器文本改变时自动保存数据
|
// 编辑器文本改变时自动保存数据
|
||||||
|
|
130
src/components/quill-editor/modules.ts
Normal file
130
src/components/quill-editor/modules.ts
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// 引入 quill module: for resizing and realigning images and iframe video
|
||||||
|
import BlotFormatter from 'quill-blot-formatter'
|
||||||
|
// 引入 module: 上传图片
|
||||||
|
import ImageUploader from 'quill-image-uploader'
|
||||||
|
// 引入 module: URL、邮箱 自动识别
|
||||||
|
import MagicUrl from 'quill-magic-url'
|
||||||
|
// 引入 module: mention
|
||||||
|
import Mention from 'quill-mention'
|
||||||
|
import '@/styles/editor/editor.snow.scss'
|
||||||
|
|
||||||
|
// 定义提及源数据的接口
|
||||||
|
interface MentionItem {
|
||||||
|
id: number
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑器 modules
|
||||||
|
export const modules = [
|
||||||
|
// BlotFormatter
|
||||||
|
{
|
||||||
|
name: 'blotFormatter',
|
||||||
|
module: BlotFormatter,
|
||||||
|
// see: https://github.com/Fandom-OSS/quill-blot-formatter/blob/master/src/Options.js
|
||||||
|
options: {
|
||||||
|
overlay: {
|
||||||
|
style: {
|
||||||
|
border: '2px solid var(--kungalgame-blue-3)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ImageUploader
|
||||||
|
{
|
||||||
|
name: 'imageUploader',
|
||||||
|
module: ImageUploader,
|
||||||
|
options: {
|
||||||
|
upload: (file: File) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('image', file)
|
||||||
|
// 在这里发送请求
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// MagicUrl
|
||||||
|
{
|
||||||
|
name: 'magicUrl',
|
||||||
|
module: MagicUrl,
|
||||||
|
options: {
|
||||||
|
// Regex used to check URLs during typing
|
||||||
|
urlRegularExpression:
|
||||||
|
/(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}(?:\/[^\s]*)?/,
|
||||||
|
// Regex used to check URLs on paste
|
||||||
|
globalRegularExpression: /(https?:\/\/|www\.|tel:)[\S]+/g,
|
||||||
|
mailRegularExpression: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
||||||
|
globalMailRegularExpression:
|
||||||
|
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Mention,TODO: 实现点击 mention 就跳转到对应的用户或话题主页
|
||||||
|
{
|
||||||
|
name: 'mention',
|
||||||
|
module: Mention,
|
||||||
|
options: {
|
||||||
|
// 允许的输入搜索字符
|
||||||
|
// allowedChars: /^[A-Za-z\s]*$/,
|
||||||
|
// 触发 mention 操作的关键词
|
||||||
|
mentionDenotationChars: ['@', '#'],
|
||||||
|
/**
|
||||||
|
* @param {string} searchTerm - 用户输入的搜索关键词
|
||||||
|
* @param {(items: MentionItem[]) => void} renderList - 渲染列表回调函数,需传入从后端获取的搜索结果数组
|
||||||
|
* @param {string} mentionChar - 触发 mention 操作的关键词
|
||||||
|
*/
|
||||||
|
source: async function (
|
||||||
|
searchTerm: string,
|
||||||
|
renderList: (items: MentionItem[]) => void,
|
||||||
|
mentionChar: string
|
||||||
|
) {
|
||||||
|
// 根据 mentionChar 的不同值执行不同的搜索逻辑
|
||||||
|
if (mentionChar === '@') {
|
||||||
|
// 执行对用户的搜索
|
||||||
|
const matchedUsers: MentionItem[] = await searchUsers(searchTerm)
|
||||||
|
renderList(matchedUsers)
|
||||||
|
} else if (mentionChar === '#') {
|
||||||
|
// 执行对话题的搜索
|
||||||
|
const matchedTopics: MentionItem[] = await searchTopics(searchTerm)
|
||||||
|
renderList(matchedTopics)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 模拟搜索用户的函数 TODO:
|
||||||
|
async function searchUsers(searchTerm: string): Promise<MentionItem[]> {
|
||||||
|
// 实际搜索逻辑
|
||||||
|
// 返回匹配的用户列表
|
||||||
|
return [
|
||||||
|
{ id: 1, value: 'kun' },
|
||||||
|
{ id: 2, value: 'yuyu' },
|
||||||
|
{ id: 3, value: 'kun' },
|
||||||
|
{ id: 4, value: 'yuyu' },
|
||||||
|
{ id: 5, value: 'kun' },
|
||||||
|
{ id: 6, value: 'yuyu' },
|
||||||
|
{ id: 7, value: 'kun' },
|
||||||
|
{ id: 8, value: 'yuyu' },
|
||||||
|
{ id: 9, value: 'kun' },
|
||||||
|
{ id: 10, value: 'yuyu' },
|
||||||
|
{ id: 11, value: 'kun' },
|
||||||
|
{ id: 12, value: 'yuyu' },
|
||||||
|
{ id: 13, value: 'kun' },
|
||||||
|
{ id: 14, value: 'yuyu' },
|
||||||
|
{ id: 15, value: 'kun' },
|
||||||
|
{ id: 16, value: 'yuyu' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟搜索话题的函数 TODO:
|
||||||
|
async function searchTopics(searchTerm: string): Promise<MentionItem[]> {
|
||||||
|
// 实际搜索逻辑
|
||||||
|
// 返回匹配的话题列表
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
value: '啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星',
|
||||||
|
},
|
||||||
|
{ id: 2, value: '鲲最可爱' },
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue