拆分通知中心的富文本编辑器
This commit is contained in:
Vendored
+1
@@ -54,6 +54,7 @@ declare module 'vue' {
|
|||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
|
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
|
||||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||||
|
NotificationRichTextEditor: typeof import('./components/NotificationRichTextEditor.vue')['default']
|
||||||
PerformanceReportPanel: typeof import('./components/PerformanceReportPanel.vue')['default']
|
PerformanceReportPanel: typeof import('./components/PerformanceReportPanel.vue')['default']
|
||||||
RichMessageContent: typeof import('./components/RichMessageContent.vue')['default']
|
RichMessageContent: typeof import('./components/RichMessageContent.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Ckeditor } from '@ckeditor/ckeditor5-vue'
|
||||||
|
import {
|
||||||
|
AutoLink,
|
||||||
|
BlockQuote,
|
||||||
|
Bold,
|
||||||
|
ClassicEditor,
|
||||||
|
Essentials,
|
||||||
|
Heading,
|
||||||
|
Image,
|
||||||
|
ImageCaption,
|
||||||
|
ImageInsert,
|
||||||
|
ImageInsertViaUrl,
|
||||||
|
ImageResize,
|
||||||
|
ImageStyle,
|
||||||
|
ImageToolbar,
|
||||||
|
Italic,
|
||||||
|
Link,
|
||||||
|
LinkImage,
|
||||||
|
List,
|
||||||
|
Paragraph,
|
||||||
|
Table,
|
||||||
|
TableCaption,
|
||||||
|
TableCellProperties,
|
||||||
|
TableColumnResize,
|
||||||
|
TableProperties,
|
||||||
|
TableToolbar,
|
||||||
|
type EditorConfig,
|
||||||
|
} from 'ckeditor5'
|
||||||
|
import 'ckeditor5/ckeditor5.css'
|
||||||
|
|
||||||
|
const model = defineModel<string>({ required: true })
|
||||||
|
|
||||||
|
const editorConfig: EditorConfig = {
|
||||||
|
licenseKey: import.meta.env.VITE_CKEDITOR_LICENSE_KEY || 'GPL',
|
||||||
|
plugins: [
|
||||||
|
Essentials, Paragraph, Heading, Bold, Italic, Link, AutoLink, List, BlockQuote,
|
||||||
|
Image, ImageCaption, ImageInsert, ImageInsertViaUrl, ImageResize, ImageStyle,
|
||||||
|
ImageToolbar, LinkImage, Table, TableCaption, TableCellProperties,
|
||||||
|
TableColumnResize, TableProperties, TableToolbar,
|
||||||
|
],
|
||||||
|
toolbar: {
|
||||||
|
items: [
|
||||||
|
'heading', '|', 'bold', 'italic', 'link', '|', 'insertTable', 'insertImage',
|
||||||
|
'|', 'bulletedList', 'numberedList', 'blockQuote', '|', 'undo', 'redo',
|
||||||
|
],
|
||||||
|
shouldNotGroupWhenFull: false,
|
||||||
|
},
|
||||||
|
heading: {
|
||||||
|
options: [
|
||||||
|
{ model: 'paragraph', title: '正文', class: 'ck-heading_paragraph' },
|
||||||
|
{ model: 'heading2', view: 'h2', title: '标题', class: 'ck-heading_heading2' },
|
||||||
|
{ model: 'heading3', view: 'h3', title: '小标题', class: 'ck-heading_heading3' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
link: { addTargetToExternalLinks: true, defaultProtocol: 'https://' },
|
||||||
|
image: {
|
||||||
|
insert: { integrations: ['insertImageViaUrl'] },
|
||||||
|
toolbar: [
|
||||||
|
'toggleImageCaption', 'imageTextAlternative', '|', 'imageStyle:inline',
|
||||||
|
'imageStyle:wrapText', 'imageStyle:breakText', '|', 'resizeImage', 'linkImage',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
contentToolbar: [
|
||||||
|
'tableColumn', 'tableRow', 'mergeTableCells', 'toggleTableCaption',
|
||||||
|
'tableProperties', 'tableCellProperties',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Ckeditor
|
||||||
|
v-model="model"
|
||||||
|
:editor="ClassicEditor"
|
||||||
|
:config="editorConfig"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, reactive, ref } from 'vue'
|
import { computed, defineAsyncComponent, onMounted, reactive, ref } from 'vue'
|
||||||
import {
|
import {
|
||||||
Bell,
|
Bell,
|
||||||
Check,
|
Check,
|
||||||
@@ -11,35 +11,6 @@ import {
|
|||||||
Search,
|
Search,
|
||||||
User,
|
User,
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
import { Ckeditor } from '@ckeditor/ckeditor5-vue'
|
|
||||||
import {
|
|
||||||
AutoLink,
|
|
||||||
BlockQuote,
|
|
||||||
Bold,
|
|
||||||
ClassicEditor,
|
|
||||||
Essentials,
|
|
||||||
Heading,
|
|
||||||
Image,
|
|
||||||
ImageCaption,
|
|
||||||
ImageInsert,
|
|
||||||
ImageInsertViaUrl,
|
|
||||||
ImageResize,
|
|
||||||
ImageStyle,
|
|
||||||
ImageToolbar,
|
|
||||||
Italic,
|
|
||||||
Link,
|
|
||||||
LinkImage,
|
|
||||||
List,
|
|
||||||
Paragraph,
|
|
||||||
Table,
|
|
||||||
TableCaption,
|
|
||||||
TableCellProperties,
|
|
||||||
TableColumnResize,
|
|
||||||
TableProperties,
|
|
||||||
TableToolbar,
|
|
||||||
type EditorConfig,
|
|
||||||
} from 'ckeditor5'
|
|
||||||
import 'ckeditor5/ckeditor5.css'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import http, { apiErrorMessage } from '../api/http'
|
import http, { apiErrorMessage } from '../api/http'
|
||||||
import RichMessageContent from '../components/RichMessageContent.vue'
|
import RichMessageContent from '../components/RichMessageContent.vue'
|
||||||
@@ -47,6 +18,8 @@ import { useAuthStore } from '../stores/auth'
|
|||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
|
const NotificationRichTextEditor = defineAsyncComponent(
|
||||||
|
() => import('../components/NotificationRichTextEditor.vue'))
|
||||||
const senderRoles = ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor', 'Teacher']
|
const senderRoles = ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor', 'Teacher']
|
||||||
const canSend = computed(() =>
|
const canSend = computed(() =>
|
||||||
auth.user?.roles.some(role => senderRoles.includes(role)) ?? false)
|
auth.user?.roles.some(role => senderRoles.includes(role)) ?? false)
|
||||||
@@ -91,92 +64,6 @@ const recipientFilters = reactive({
|
|||||||
keyword: '',
|
keyword: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const editorConfig: EditorConfig = {
|
|
||||||
licenseKey: import.meta.env.VITE_CKEDITOR_LICENSE_KEY || 'GPL',
|
|
||||||
plugins: [
|
|
||||||
Essentials,
|
|
||||||
Paragraph,
|
|
||||||
Heading,
|
|
||||||
Bold,
|
|
||||||
Italic,
|
|
||||||
Link,
|
|
||||||
AutoLink,
|
|
||||||
List,
|
|
||||||
BlockQuote,
|
|
||||||
Image,
|
|
||||||
ImageCaption,
|
|
||||||
ImageInsert,
|
|
||||||
ImageInsertViaUrl,
|
|
||||||
ImageResize,
|
|
||||||
ImageStyle,
|
|
||||||
ImageToolbar,
|
|
||||||
LinkImage,
|
|
||||||
Table,
|
|
||||||
TableCaption,
|
|
||||||
TableCellProperties,
|
|
||||||
TableColumnResize,
|
|
||||||
TableProperties,
|
|
||||||
TableToolbar,
|
|
||||||
],
|
|
||||||
toolbar: {
|
|
||||||
items: [
|
|
||||||
'heading',
|
|
||||||
'|',
|
|
||||||
'bold',
|
|
||||||
'italic',
|
|
||||||
'link',
|
|
||||||
'|',
|
|
||||||
'insertTable',
|
|
||||||
'insertImage',
|
|
||||||
'|',
|
|
||||||
'bulletedList',
|
|
||||||
'numberedList',
|
|
||||||
'blockQuote',
|
|
||||||
'|',
|
|
||||||
'undo',
|
|
||||||
'redo',
|
|
||||||
],
|
|
||||||
shouldNotGroupWhenFull: false,
|
|
||||||
},
|
|
||||||
heading: {
|
|
||||||
options: [
|
|
||||||
{ model: 'paragraph', title: '正文', class: 'ck-heading_paragraph' },
|
|
||||||
{ model: 'heading2', view: 'h2', title: '标题', class: 'ck-heading_heading2' },
|
|
||||||
{ model: 'heading3', view: 'h3', title: '小标题', class: 'ck-heading_heading3' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
addTargetToExternalLinks: true,
|
|
||||||
defaultProtocol: 'https://',
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
insert: {
|
|
||||||
integrations: ['insertImageViaUrl'],
|
|
||||||
},
|
|
||||||
toolbar: [
|
|
||||||
'toggleImageCaption',
|
|
||||||
'imageTextAlternative',
|
|
||||||
'|',
|
|
||||||
'imageStyle:inline',
|
|
||||||
'imageStyle:wrapText',
|
|
||||||
'imageStyle:breakText',
|
|
||||||
'|',
|
|
||||||
'resizeImage',
|
|
||||||
'linkImage',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
table: {
|
|
||||||
contentToolbar: [
|
|
||||||
'tableColumn',
|
|
||||||
'tableRow',
|
|
||||||
'mergeTableCells',
|
|
||||||
'toggleTableCaption',
|
|
||||||
'tableProperties',
|
|
||||||
'tableCellProperties',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const categories: Record<string, { label: string; className: string }> = {
|
const categories: Record<string, { label: string; className: string }> = {
|
||||||
General: { label: '一般通知', className: 'general' },
|
General: { label: '一般通知', className: 'general' },
|
||||||
Approval: { label: '审核待办', className: 'approval' },
|
Approval: { label: '审核待办', className: 'approval' },
|
||||||
@@ -872,10 +759,8 @@ onMounted(() => load())
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="消息正文" required class="editor-form-item">
|
<el-form-item label="消息正文" required class="editor-form-item">
|
||||||
<Ckeditor
|
<NotificationRichTextEditor
|
||||||
v-model="messageForm.content"
|
v-model="messageForm.content"
|
||||||
:editor="ClassicEditor"
|
|
||||||
:config="editorConfig"
|
|
||||||
/>
|
/>
|
||||||
<div class="editor-footnote">
|
<div class="editor-footnote">
|
||||||
<span>支持表格、超链接和外链图片;图片请填写 HTTPS 地址,不上传本地文件。</span>
|
<span>支持表格、超链接和外链图片;图片请填写 HTTPS 地址,不上传本地文件。</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user