This commit is contained in:
Viet An
2026-06-20 14:48:35 +07:00
parent 7402e61906
commit b596ea0a0f
31 changed files with 5911 additions and 13522 deletions

View File

@@ -4,8 +4,14 @@
@click="$emit('justclick')"
:style="image ? 'border: none' : ''"
>
<figure class="image" v-if="image">
<img class="is-rounded" :src="`${$path()}download?name=${image}`" />
<figure
class="image"
v-if="image"
>
<img
class="is-rounded"
:src="`${$path()}download?name=${image}`"
/>
</figure>
<div v-else>
<span>{{ text }}</span>
@@ -14,19 +20,18 @@
</template>
<script>
export default {
props: ['text', 'image', 'type', 'size'],
props: ["text", "image", "type", "size"],
};
</script>
<style>
.cbox-findata-two {
font-size: 16px;
font-weight: bold;
font-weight: 500;
width: 34px;
height: 34px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #e4e4e4;
border: 1px solid #d3d3d3;
border-radius: 50%;
}
</style>

View File

@@ -1,393 +1,3 @@
<template>
<ClientOnly>
<div ref="el"></div>
</ClientOnly>
</template>
<template>hey</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import 'ckeditor5/ckeditor5.css';
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
const el = ref(null);
let editor = null;
const props = defineProps({
modelValue: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:modelValue']);
const content = ref(props.modelValue || '');
onMounted(async () => {
if (!process.client) return;
const {
ClassicEditor,
AccessibilityHelp,
Autoformat,
AutoImage,
AutoLink,
Autosave,
BalloonToolbar,
BlockQuote,
BlockToolbar,
Bold,
CKBox,
CKBoxImageEdit,
CloudServices,
Essentials,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
Highlight,
ImageBlock,
ImageCaption,
ImageInline,
ImageInsert,
ImageInsertViaUrl,
ImageResize,
ImageStyle,
ImageTextAlternative,
ImageToolbar,
ImageUpload,
Indent,
IndentBlock,
Italic,
Link,
LinkImage,
List,
ListProperties,
MediaEmbed,
Mention,
PageBreak,
Paragraph,
PasteFromOffice,
PictureEditing,
RemoveFormat,
SelectAll,
SpecialCharacters,
SpecialCharactersArrows,
SpecialCharactersCurrency,
SpecialCharactersEssentials,
SpecialCharactersLatin,
SpecialCharactersMathematical,
SpecialCharactersText,
Subscript,
Superscript,
Table,
TableCaption,
TableCellProperties,
GeneralHtmlSupport,
TableColumnResize,
TableProperties,
TableToolbar,
TextTransformation,
TodoList,
Underline,
Alignment,
Undo,
} = await import('ckeditor5');
const { ExportPdf, ExportWord, ImportWord } = await import('ckeditor5-premium-features');
editor = await ClassicEditor.create(el.value, {
// licenseKey: 'GPL',
plugins: [
AccessibilityHelp,
Autoformat,
AutoImage,
AutoLink,
Autosave,
BalloonToolbar,
BlockQuote,
BlockToolbar,
Bold,
CKBox,
CKBoxImageEdit,
CloudServices,
Essentials,
ExportPdf,
ExportWord,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
Highlight,
ImageBlock,
ImageCaption,
ImageInline,
ImageInsert,
ImageInsertViaUrl,
ImageResize,
ImageStyle,
ImageTextAlternative,
ImageToolbar,
ImageUpload,
ImportWord,
Indent,
IndentBlock,
Italic,
Link,
LinkImage,
List,
ListProperties,
MediaEmbed,
Mention,
PageBreak,
Paragraph,
PasteFromOffice,
PictureEditing,
RemoveFormat,
SelectAll,
SpecialCharacters,
SpecialCharactersArrows,
SpecialCharactersCurrency,
SpecialCharactersEssentials,
SpecialCharactersLatin,
SpecialCharactersMathematical,
SpecialCharactersText,
Subscript,
Superscript,
Table,
TableCaption,
TableCellProperties,
TableColumnResize,
TableProperties,
TableToolbar,
TextTransformation,
TodoList,
Underline,
Alignment,
GeneralHtmlSupport,
Undo,
],
toolbar: [
'undo',
'redo',
'|',
'importWord',
'exportWord',
'exportPdf',
'|',
'heading',
'|',
'fontSize',
'fontFamily',
'fontColor',
'fontBackgroundColor',
'|',
'bold',
'italic',
'underline',
'subscript',
'superscript',
'removeFormat',
'|',
'alignment', // 👈 THÊM
'|',
'specialCharacters',
'pageBreak',
'link',
'insertImage',
'insertImageViaUrl',
'ckbox',
'mediaEmbed',
'insertTable',
'highlight',
'blockQuote',
'|',
'bulletedList',
'numberedList',
'todoList',
'outdent',
'indent',
],
exportPdf: {
stylesheets: [
'https://cdn.ckeditor.com/ckeditor5/43.2.0/ckeditor5.css',
'https://cdn.ckeditor.com/ckeditor5-premium-features/43.2.0/ckeditor5-premium-features.css',
],
fileName: 'export-pdf-demo.pdf',
converterOptions: {
format: 'Tabloid',
margin_top: '20mm',
margin_bottom: '20mm',
margin_right: '24mm',
margin_left: '24mm',
page_orientation: 'portrait',
},
},
exportWord: {
stylesheets: [
'https://cdn.ckeditor.com/ckeditor5/43.2.0/ckeditor5.css',
'https://cdn.ckeditor.com/ckeditor5-premium-features/43.2.0/ckeditor5-premium-features.css',
],
fileName: 'export-word-demo.docx',
converterOptions: {
document: {
orientation: 'portrait',
size: 'Tabloid',
margins: {
top: '20mm',
bottom: '20mm',
right: '24mm',
left: '24mm',
},
},
},
},
balloonToolbar: ['bold', 'italic','fontFamily','fontSize', '|', 'alignment', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'],
blockToolbar: [
'fontSize',
'fontColor',
'fontBackgroundColor',
'|',
'bold',
'italic',
'|',
'link',
'insertImage',
'insertTable',
'|',
'bulletedList',
'numberedList',
'outdent',
'indent',
],
fontFamily: {
supportAllValues: true,
},
fontSize: {
options: [10, 12,13, 14, 'default', 18, 20, 22],
supportAllValues: true,
},
heading: {
options: [
{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph',
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1',
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2',
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3',
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4',
},
{
model: 'heading5',
view: 'h5',
title: 'Heading 5',
class: 'ck-heading_heading5',
},
{
model: 'heading6',
view: 'h6',
title: 'Heading 6',
class: 'ck-heading_heading6',
},
],
},
image: {
toolbar: [
'toggleImageCaption',
'imageTextAlternative',
'|',
'imageStyle:inline',
'imageStyle:wrapText',
'imageStyle:breakText',
'|',
'resizeImage',
'|',
'ckboxImageEdit',
],
},
link: {
addTargetToExternalLinks: true,
defaultProtocol: 'https://',
decorators: {
toggleDownloadable: {
mode: 'manual',
label: 'Downloadable',
attributes: {
download: 'file',
},
},
},
},
list: {
properties: {
styles: true,
startIndex: true,
reversed: true,
},
},
mention: {
feeds: [
{
marker: '@',
feed: [],
},
],
},
menuBar: {
isVisible: true,
},
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'],
},
alignment: {
options: ['left', 'center', 'right', 'justify'],
},
});
// set data ban đầu
editor.setData(props.modelValue || '');
// khi thay đổi → emit ra ngoài
editor.model.document.on('change:data', () => {
const data = editor.getData();
emit('update:modelValue', data);
});
});
watch(
() => props.modelValue,
(val) => {
if (editor && val !== editor.getData()) {
editor.setData(val || '');
}
},
);
onBeforeUnmount(async () => {
if (editor) {
await editor.destroy();
editor = null;
}
});
</script>
<script setup></script>