Browse Source

完成组件修改

qin_v8_isTrue
herenshan112 9 months ago
parent
commit
aedd578093
  1. 824
      package-lock.json
  2. 8
      package.json
  3. 150
      src/components/lowCode/assistant/quillEditor.vue
  4. 233
      src/components/lowCode/assistant/quillEditorNew.vue
  5. 3
      src/components/lowCode/assistant/tinymce.vue
  6. 4
      src/components/lowCode/formItem.vue
  7. 4739
      yarn.lock

824
package-lock.json

File diff suppressed because it is too large

8
package.json

@ -11,8 +11,13 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@tinymce/tinymce-vue": "^6.1.0",
"@vueup/vue-quill": "^1.2.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"@zxing/browser": "^0.1.5",
"@zxing/library": "^0.21.3",
"appformlowcode": "file:",
"axios": "^1.7.7",
"element-plus": "^2.8.6",
"font-awesome": "^4.7.0",
@ -23,10 +28,11 @@
"pdfjs-dist": "^4.8.69",
"pinia": "^2.2.4",
"pinia-plugin-persistedstate": "^4.1.1",
"quill": "^2.0.3",
"sass": "^1.80.3",
"scss": "^0.2.4",
"spark-md5": "^3.0.2",
"tinymce": "^7.5.1",
"tinymce": "^7.7.1",
"ts-md5": "^1.3.1",
"vue": "^3.5.10",
"vue-pdf-embed": "^1.2.1",

150
src/components/lowCode/assistant/quillEditor.vue

@ -1,19 +1,12 @@
<!--
@ 作者: 秦东
@ 时间: 2025-03-07 08:45:16
@ 备注: Quill 富文本
@ 时间: 2025-03-14 19:17:35
@ 备注:
-->
<script lang='ts' setup>
import { ref } from 'vue';
//
import { Quill, QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
//
import BlotFormatter from 'quill-blot-formatter'
Quill.register('modules/blotFormatter', BlotFormatter)
//
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import { newUploadFileApi } from '@/api/common/public'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import '@wangeditor/editor/dist/css/style.css';
const props = withDefaults(
defineProps<{
modelValue: string
@ -52,38 +45,95 @@ const content = computed({
emits('update:modelValue', newVal)
}
})
// shallowRef
const editorRef = shallowRef();
// HTML
const valueHtml = ref('<p>hello <strong>hello world</strong></p>');
const toolbarConfig = {};
const editorConfig = ref({ placeholder: '请输入内容...', MENU_CONF: {} });
const toolbarOptions = [
['bold', 'italic', 'underline'],
[{ 'header': [1, 2, 3, false] }],
['image', 'code-block']
];
//
editorConfig.value.MENU_CONF['uploadImage'] = {
async customUpload(file, insertFn) {
console.log('上传图片', file,insertFn);
// filebase64
const base64 = URL.createObjectURL(file);
const handleEditorReady = (editor) => {
console.log('Editor实例:', editor);
const params = new FormData()
params.append('file', file)
params.append('type',"1")
newUploadFileApi(params)
.then(res =>{
console.log("上传图片--------->",res.data)
// resolve(res.data.url)
insertFn(res.data.url, 'img');
})
.catch(()=>{
ElMessage.error('上传出错,请查看你上传的文件是否符合要求!')
})
// file,insertFn
// insertFn(base64, 'img');
},
};
watch(
() => props.modelValue,
(n: any) => {
if (n && n !== content.value) {
content.value = n
}
}
)
</script>
<template><div class="butBox" @click="openVideo">按钮</div>
<div v-if="type==1 || type == 5" class="edioBox">
<QuillEditor
v-model:content="content"
contentType="html"
:toolbar="toolbarOptions"
@ready="handleEditorReady"
//
editorConfig.value.MENU_CONF['uploadVideo'] = {
async customUpload(file, insertFn) {
console.log('上传视频', file);
const params = new FormData()
params.append('file', file)
params.append('type',"2")
newUploadFileApi(params)
.then(res =>{
console.log("上传图片--------->",res.data)
// resolve(res.data.url)
insertFn(res.data.url, 'video');
/>
})
.catch(()=>{
ElMessage.error('上传出错,请查看你上传的文件是否符合要求!')
})
},
};
//
const handleCreated = editor => {
editorRef.value = editor; // editor
console.log(editorConfig.value.MENU_CONF, 'editorConfig.value');
};
//
const customPaste = (editor, event, callback) => {
//
const text = event.clipboardData.getData('text/plain');
if (text) {
editor.insertText(text);
event.preventDefault();
callback(false);
}
};
// html
const getEditorHTML = () => {
console.log(editorRef.value.getHtml());
};
//
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
</script>
<template><div class="butBox" >按钮</div>
<div style="border: 1px solid #ccc; width: 100%; margin: 20px auto">
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" mode="default" />
<Editor style="height: 600px; overflow-y: hidden" v-model="content" :defaultConfig="editorConfig" mode="default" @onCreated="handleCreated" @customPaste="customPaste" />
</div>
<div v-else class="edioBoxHtml" v-html="content"></div>
</template>
<style lang='scss' scoped>
.butBox{
@ -92,30 +142,4 @@ watch(
background-color: #FB041A;
display:none;
}
.edioBoxHtml{
width: 100%;
}
.edioBox{
width: 100%;
height: 350px;
.ql-toolbar{
.ql-snow{
height: 300px;
}
}
:deep .ql-toolbar.ql-snow + .ql-container.ql-snow{
height: 300px;
}
}
.ql-editor.ql-fullscreen {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
}
.ql-container {
user-select: auto !important;
-webkit-user-select: auto !important;
}
</style>

233
src/components/lowCode/assistant/quillEditorNew.vue

@ -4,13 +4,12 @@
@ 备注:
-->
<script lang='ts' setup>
//
import { Quill, QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import { newUploadFileApi } from '@/api/common/public'
//
import BlotFormatter from 'quill-blot-formatter'
Quill.register('modules/blotFormatter', BlotFormatter)
import { onMounted, ref } from 'vue';
import Quill from 'quill';
import 'quill/dist/quill.snow.css'; //
const editor = ref(null);
const props = withDefaults(
defineProps<{
@ -50,199 +49,19 @@ const content = computed({
emits('update:modelValue', newVal)
}
})
const editorRef = ref(null)
//
const imageHandler = () => {
//
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
//
input.click();
//
input.onchange = async () => {
//
const file = input.files ? input.files[0] : null;
if (file) {
// FormData
const formData = new FormData();
formData.append('file', file);
formData.append('type',"1")
try {
newUploadFileApi(formData)
.then(res =>{
// console.log("",res.data)
// resolve(res.data.url)
const quill = toRaw(editorRef.value).getQuill()
if (quill) {
//
const range = quill.getSelection(true);
//
quill.insertEmbed(range.index, 'image',res.data.url);
}
})
.catch(()=>{
// reject('')
alert('上传出错,请查看你上传的文件是否符合要求!')
})
} catch (error) {
alert('图片上传失败')
}
// try {
// /**
// * @todo file线
// * abc,使 axios POST
// * */
// // todo
// // 使 axios POST ,abc
// // file线
// const res = await abc(formData);
// // Quill
// const quill = toRaw(editorRef.value).getQuill()
// if (quill) {
// //
// const range = quill.getSelection(true);
// //
// quill.insertEmbed(range.index, 'image', res.data);
// }
// } catch (error) {
// alert('')
// }
}
};
}
// toolbar,
const titleConfig = [
{ Choice: '.ql-insertMetric', title: '跳转配置' },
{ Choice: '.ql-bold', title: '加粗' },
{ Choice: '.ql-italic', title: '斜体' },
{ Choice: '.ql-underline', title: '下划线' },
{ Choice: '.ql-header', title: '段落格式' },
{ Choice: '.ql-strike', title: '删除线' },
{ Choice: '.ql-blockquote', title: '块引用' },
{ Choice: '.ql-code', title: '插入代码' },
{ Choice: '.ql-code-block', title: '插入代码段' },
{ Choice: '.ql-font', title: '字体' },
{ Choice: '.ql-size', title: '字体大小' },
{ Choice: '.ql-list[value="ordered"]', title: '编号列表' },
{ Choice: '.ql-list[value="bullet"]', title: '项目列表' },
{ Choice: '.ql-direction', title: '文本方向' },
{ Choice: '.ql-header[value="1"]', title: 'h1' },
{ Choice: '.ql-header[value="2"]', title: 'h2' },
{ Choice: '.ql-align', title: '对齐方式' },
{ Choice: '.ql-color', title: '字体颜色' },
{ Choice: '.ql-background', title: '背景颜色' },
{ Choice: '.ql-image', title: '图像' },
{ Choice: '.ql-video', title: '视频' },
{ Choice: '.ql-link', title: '添加链接' },
{ Choice: '.ql-formula', title: '插入公式' },
{ Choice: '.ql-clean', title: '清除字体格式' },
{ Choice: '.ql-script[value="sub"]', title: '下标' },
{ Choice: '.ql-script[value="super"]', title: '上标' },
{ Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
{ Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
{ Choice: '.ql-header .ql-picker-label', title: '标题大小' },
{ Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
{ Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
{ Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
{ Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
{ Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
{ Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
{ Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
{ Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
{ Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
{ Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
{ Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
{ Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
{ Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]
//
const options = ref({
theme: 'snow', // 使snow
modules: {
//
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'], // 线 线
[{ color: [] }, { background: [] }], //
[{ align: [] }], //
[{ size: ['small', false, 'large', 'huge'] }], //
[{ font: [] }], //
[{ header: [1, 2, 3, 4, 5, 6, false] }], //
[{ direction: 'ltl' }], //
[{ direction: 'rtl' }], //
[{ indent: '-1' }, { indent: '+1' }], //
[{ list: 'ordered' }, { list: 'bullet' }], //
[{ script: 'sub' }, { script: 'super' }], // /
['blockquote', 'code-block'], //
['clean'], //
['link', 'image', 'video'], //
],
handlers: {
image: imageHandler, //
},
},
//
blotFormatter: {
//
// overlay: {
// style: {
// border: '2px solid red',
// }
// },
toolbar: {
mainClassName: 'blot-formatter__toolbar'
}
}
}
})
// imageHandler options
//
const initTitle = () => {
for (let item of titleConfig) {
// .editor
let tip = document.querySelector('.editor ' + item.Choice);
if (tip) {
tip.setAttribute('title', item.title);
}
}
}
//
const customPaste=(e)=>{
//
let newTime = new Date().getTime()
const clipboardData = e.clipboardData //
const types = clipboardData.types //
if (types.includes('Files')) {
e.preventDefault();
e.clipboardData.files.forEach(file=>{
//
//
})
}
}
onMounted(()=>{
nextTick(()=>{
//
initTitle()
quill()
})
//
editorRef.value.getQuill().root.addEventListener('customPaste', customPaste, false)
})
watch(
() => props.modelValue,
@ -252,16 +71,36 @@ watch(
}
}
)
const quill = new Quill(editor.value, {
theme: 'snow',
modules: {
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ list: 'ordered'}, { list: 'bullet' }],
[{ script: 'sub'}, { script: 'super' }], // superscript/subscript
[{ indent: '-1'}, { indent: '+1' }], // outdent/indent
[{ direction: 'rtl' }], // text direction
[{ size: ['small', false, 'large', 'huge'] }], // custom dropdown
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ font: [] }],
[{ align: [] }],
['clean'] // remove formatting button
]
}
});
</script>
<template><div class="butBox" @click="openVideo">按钮</div>
<template><div class="butBox" >按钮</div>
<div class="editor">
<!-- 这两个都是获取值的必要条件 v-model:content contentType="html" -->
<quill-editor
ref="editorRef"
v-model:content="content"
:options="options"
contentType="html"
></quill-editor>
{{ content }} {{ newUploadFileApi }}
<div ref="editor">{{ content }}</div>
</div>
</template>
<style lang='scss' scoped>

3
src/components/lowCode/assistant/tinymce.vue

@ -33,6 +33,7 @@ const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const contentValue = ref(props.modelValue)
const tinymce = ref(null)
//
// eslint-disable-next-line max-len
const buttonPlugins ='preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media code codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave '
@ -184,7 +185,7 @@ watch(
)
</script>
<template>
<textarea id="myTextarea" v-model="contentValue"></textarea>
<textarea ref="tinymce" id="myTextarea" v-model="contentValue"></textarea>
</template>
<style lang='scss' scoped>
.tox-tinymce-aux {

4
src/components/lowCode/formItem.vue

@ -43,8 +43,8 @@ import UrlLink from '@/components/lowCode/assistant/urlLink.vue'
import DepartmentOrg from '@/components/lowCode/assistant/departmentOrg.vue'
import DigitpagePage from '@/components/lowCode/assistant/digitpage.vue'
import OrgCentent from '@/components/lowCode/assistant/org.vue'
import Tinymce from '@/components/lowCode/assistant/tinymce.vue'
import QuillEditor from '@/components/lowCode/assistant/quillEditorNew.vue'
// import Tinymce from '@/components/lowCode/assistant/tinymce.vue'
import QuillEditor from '@/components/lowCode/assistant/quillEditor.vue'
const props = withDefaults(

4739
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save