From 810fb4b698f5450d04e5769f32ced55a9115f6fa Mon Sep 17 00:00:00 2001 From: 田源 <lastanimals@163.com> Date: 星期三, 10 四月 2024 11:57:50 +0800 Subject: [PATCH] 富文本以及路由改造 --- Source/ProjectWeb/package.json | 2 Source/ProjectWeb/src/router/avue-router.js | 39 +++++-- Source/ProjectWeb/src/components/dynamic-components/dynamic-form.vue | 143 +++++++++++++++++++-------- Source/ProjectWeb/src/main.js | 7 + Source/ProjectWeb/src/views/custom-ui/test.vue | 88 ++++++++++++++++- 5 files changed, 219 insertions(+), 60 deletions(-) diff --git a/Source/ProjectWeb/package.json b/Source/ProjectWeb/package.json index dfd881d..a8b7304 100644 --- a/Source/ProjectWeb/package.json +++ b/Source/ProjectWeb/package.json @@ -24,10 +24,12 @@ "node-gyp": "^5.0.6", "nprogress": "^0.2.0", "portfinder": "^1.0.23", + "quill": "^1.3.7", "script-loader": "^0.7.2", "vue": "^2.6.10", "vue-axios": "^2.1.2", "vue-i18n": "^8.7.0", + "vue-quill-editor": "^3.0.6", "vue-router": "^3.0.1", "vuex": "^3.1.1" }, diff --git a/Source/ProjectWeb/src/components/dynamic-components/dynamic-form.vue b/Source/ProjectWeb/src/components/dynamic-components/dynamic-form.vue index 9641b5f..3104d06 100644 --- a/Source/ProjectWeb/src/components/dynamic-components/dynamic-form.vue +++ b/Source/ProjectWeb/src/components/dynamic-components/dynamic-form.vue @@ -1,5 +1,5 @@ <template> - <div class="UI-dynamic" :id="'UI-dynamic-'+areasName+componentVO.oid"> + <div :id="'UI-dynamic-'+areasName+componentVO.oid" class="UI-dynamic"> <avue-form v-model="form" :option="option"> <template v-for="item in slotData" :slot="item.prop + 'Label'"> <span> @@ -16,13 +16,13 @@ </span> </template> <template slot="menuForm"> - <dynamic-button type="form" :butttonList="componentVO.buttons" @buttonClick="buttonClick"></dynamic-button> + <dynamic-button :butttonList="componentVO.buttons" type="form" @buttonClick="buttonClick"></dynamic-button> </template> <template v-for="item in slotData" :slot="item.prop + ''"> <vciWebRefer v-if="item.type == 'refer'" :key="item.prop" - referType="master" + :ref="'referFormRef'+item.prop" :data-key="item.prop" :disabled="item.disabled || false" :display="item.display || true" @@ -30,10 +30,12 @@ :reloadFormKey="(item.referConfig.useFormKey && item.referConfig.formValues && item.referConfig.formValues[item.referConfig.useFormKey]) || ''" :text="item.referConfig.showProp" :value="item.prop || item.value" - @setReferValue="setReferValue" - :ref="'referFormRef'+item.prop"> + referType="master" + @setReferValue="setReferValue"> </vciWebRefer> + <quill-editor ref="customQuillEditor" v-model="content" :options="editorOption" class="editor"> + </quill-editor> </template> </avue-form> </div> @@ -43,6 +45,26 @@ import vciWebRefer from '@/components/refer/vciWebRefer' import VciWebRefer from "@/components/refer/vciWebRefer"; import {verifyNull, verifySlash} from "@/util/validate"; + +const toolbarOptions = [ + ['bold', 'italic', 'underline', 'strike'], // toggled buttons + ['blockquote', 'code-block'], + + [{'header': 1}, {'header': 2}], // custom button values + [{'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': []}], + ['link', 'image', 'video'], + ['clean'] // remove formatting button +]; export default { name: "dynamic-form", components: {VciWebRefer}, @@ -59,14 +81,14 @@ type: String, default: '' }, - sourceData:{ + sourceData: { //鎵�灞炲尯鍩熺殑涓婁竴鍖哄煙閫変腑鏁版嵁 - type:Object, + type: Object, default: {} }, - dataStore:{ + dataStore: { //寮圭獥鏃舵寜閽墍灞炲尯鍩熼�変腑鏁版嵁 - type:Array, + type: Array, default: [] }, paramVOS: { @@ -81,7 +103,40 @@ }, data() { return { - form: {} + form: {}, + content: '', + editorOption: { + placeholder: '浣犳兂璇翠粈涔堬紵', + modules: { + imageResize: { + displayStyles: { + backgroundColor: 'black', + border: 'none', + color: 'white' + }, + modules: ['Resize', 'DisplaySize', 'Toolbar'] + }, + toolbar: { + container: toolbarOptions, // 宸ュ叿鏍� + handlers: { + 'image': function (value) { + if (value) { + document.querySelector('#quillEditorQiniu .avatar-uploader input').click() + } else { + this.quill.format('image', false); + } + }, + 'video': function (value) { + if (value) { + document.querySelector('#quillEditorQiniu .avatar-uploader input').click() + } else { + this.quill.format('video', false); + } + }, + } + } + } + } } }, mounted() { @@ -99,10 +154,10 @@ return this.getColumnData() } }, - watch:{ - slotData:{ - handler(newV){ - this.getDictList(newV) + watch: { + slotData: { + handler(newV) { + this.getDictList(newV) }, immediate: true, }, @@ -129,7 +184,7 @@ deep: true, immediate: true, }, - sourceData:{ + sourceData: { handler(newval) { //婧愭暟鎹湁鍙樺寲鏃跺彉鏇村綋鍓嶅尯鍩熸暟鎹� console.log(this.areasName); @@ -140,39 +195,39 @@ methods: { //杞寲鏁版嵁 formColumn(formList) { - return formList.map(item => { - const typeValue = item.type === 'text' ? 'input' : item.type === 'combox' ? 'select' : item.type; + return formList.map(item => { + const typeValue = item.type === 'text' ? 'input' : item.type === 'combox' ? 'select' : item.type; - const focusFunc = item.type === 'refer' ? (i) => { + const focusFunc = item.type === 'refer' ? (i) => { - } : undefined; + } : undefined; - return { - label: item.text, - prop: item.field, - type: typeValue, - labelWidth:item.text.length >= 6 ? 115 : 90, - value: item.defaultValue, - dicData: item.type === 'combox' ? item.dicData : item.dicUrl, - readonly: item.readOnly, - disabled: item.disabled, - display: !item.hidden, - labelSuffix: item.suffix, - suffixIcon: item.prefix, - placeholder: item.placeholder, - clearable: item.clearable, - tip: item.tooltips, - keyAttr: item.keyAttr, - focus:focusFunc, - referConfig:item.referConfig, - rules: [{ - required: item.required, - message: `璇疯緭鍏�${item.text}!`, - trigger: "blur" - }] - }; - }); + return { + label: item.text, + prop: item.field, + type: typeValue, + labelWidth: item.text.length >= 6 ? 115 : 90, + value: item.defaultValue, + dicData: item.type === 'combox' ? item.dicData : item.dicUrl, + readonly: item.readOnly, + disabled: item.disabled, + display: !item.hidden, + labelSuffix: item.suffix, + suffixIcon: item.prefix, + placeholder: item.placeholder, + clearable: item.clearable, + tip: item.tooltips, + keyAttr: item.keyAttr, + focus: focusFunc, + referConfig: item.referConfig, + rules: [{ + required: item.required, + message: `璇疯緭鍏�${item.text}!`, + trigger: "blur" + }] + }; + }); }, //鏁版嵁鍒ょ┖ diff --git a/Source/ProjectWeb/src/main.js b/Source/ProjectWeb/src/main.js index 1d74b80..acf22d9 100644 --- a/Source/ProjectWeb/src/main.js +++ b/Source/ProjectWeb/src/main.js @@ -31,6 +31,13 @@ import dynamicTableForm from '@/components/dynamic-components/dynamic-table-form' //鍥哄畾琛ㄥ崟缁勪欢 import dynamicForm from '@/components/dynamic-components/dynamic-form' + +import 'quill/dist/quill.core.css' +import 'quill/dist/quill.snow.css' +import 'quill/dist/quill.bubble.css' +import VueQuillEditor from 'vue-quill-editor' + +Vue.use(VueQuillEditor) // 娉ㄥ唽鍏ㄥ眬crud椹卞姩 window.$crudCommon = crudCommon; // 鍔犺浇Vue鎷撳睍 diff --git a/Source/ProjectWeb/src/router/avue-router.js b/Source/ProjectWeb/src/router/avue-router.js index e8f5e4b..fb9f9e2 100644 --- a/Source/ProjectWeb/src/router/avue-router.js +++ b/Source/ProjectWeb/src/router/avue-router.js @@ -96,9 +96,9 @@ // 璁剧疆 props榛樿鍊� 浣滅敤灏辨槸灏嗗瓧娈佃缃垚閰嶇疆鐨� const propsDefault = { label: propsConfig.label || 'name', - path:'code', + path: 'code', code: 'code', - pathValue:'pathValue', + pathValue: 'pathValue', icon: propsConfig.icon || 'icon', children: propsConfig.children || 'children', meta: propsConfig.meta || 'meta', @@ -121,16 +121,33 @@ let code = (() => { return oMenu[propsDefault.code] })(); - // 灏嗗瓧绗︿覆鍒嗗壊鎴愭暟缁勶紝浠�'?'浣滀负鍒嗛殧绗� - let parts = path.split("?"); - // 濡傛灉鏁扮粍鐨勯暱搴﹀ぇ浜�1锛岃〃绀烘湁'?'锛屽垯鍙栫涓�涓厓绱犵殑绗竴涓儴鍒嗭紝鍚﹀垯鐩存帴鍙栨暣涓瓧绗︿覆 - let bsValue = parts.length > 1 ? parts[0].split("=")[1] : path.split("=")[1]; - if (bsValue === '' || bsValue === undefined || bsValue === null) { - bsValue = "UI"; + + let component = ''; + let parts = ''; + + // 濡傛灉璺緞涓瓨鍦� '?'锛屽垯鍙栭棶鍙峰墠闈㈤儴鍒嗙粰 parts + if (path.includes('?')) { + parts = path.split("?")[0]; + } else { + parts = path; // 涓嶅瓨鍦� '?' 鏁存潯璺緞灏辨槸 parts } - //鐗规畩澶勭悊缁勪欢 鎵ц瀹岃繖涓� component 涔熷氨鏄簿纭埌鍏蜂綋鐨勬枃浠朵簡 views鏂囦欢澶逛笅闈㈠氨鏄叿浣撶殑椤甸潰浠g爜 - let component = bsValue === 'UI' ? 'views/base/UIContentViewer' : `views/custom-ui/${bsValue}`, - name = oMenu[propsDefault.label], + + // 濡傛灉闂彿鍓嶉潰閮ㄥ垎涓嶅湪 ['ui', 'UI', 'base'] 涓紝鍒欐槸鑷畾涔夌粍浠� + if (!['ui', 'UI', 'base'].includes(parts)) { + component = `views/custom-ui/${parts}`; + } + + // 濡傛灉闂彿鍓嶉潰绛変簬绌猴紝鍒欓粯璁や负UI寮曟搸 + if (!parts) { + component = 'views/base/UIContentViewer'; + } + + // 濡傛灉闂彿鍓嶉潰绛変簬 UI銆乽i 鍒欎负UI寮曟搸 + if (['UI', 'ui'].includes(parts)) { + component = 'views/base/UIContentViewer'; + } + + let name = oMenu[propsDefault.label], icon = oMenu[propsDefault.icon], children = oMenu[propsDefault.children], meta = oMenu[propsDefault.meta] || {}; diff --git a/Source/ProjectWeb/src/views/custom-ui/test.vue b/Source/ProjectWeb/src/views/custom-ui/test.vue index 6b3584e..c4ac63c 100644 --- a/Source/ProjectWeb/src/views/custom-ui/test.vue +++ b/Source/ProjectWeb/src/views/custom-ui/test.vue @@ -1,15 +1,93 @@ <template> <div> - 娴嬭瘯鑷畾涔夌粍浠跺睍绀篸dddd + <quill-editor + class="editor" + v-model="content" + ref="quillEditor" + :options="editorOptions" + ></quill-editor> </div> </template> <script> +const toolbarOptions = [ + ['bold', 'italic', 'underline', 'strike'], // 鍔犵矖 鏂滀綋 涓嬪垝绾� 鍒犻櫎绾� + ['blockquote', 'code-block'], // 寮曠敤 浠g爜鍧� + [{ header: 1 }, { header: 2 }], // 1銆�2 绾ф爣棰� + [{ list: 'ordered' }, { list: 'bullet' }], // 鏈夊簭銆佹棤搴忓垪琛� + [{ script: 'sub' }, { script: 'super' }], // 涓婃爣/涓嬫爣 + [{ indent: '-1' }, { indent: '+1' }], // 缂╄繘 + // [{'direction': 'rtl'}], // 鏂囨湰鏂瑰悜 + [{ size: ['small', false, 'large', 'huge'] }], // 瀛椾綋澶у皬 + [{ header: [1, 2, 3, 4, 5, 6, false] }], // 鏍囬 + [{ color: [] }, { background: [] }], // 瀛椾綋棰滆壊銆佸瓧浣撹儗鏅鑹� + [{ font: [] }], // 瀛椾綋绉嶇被 + [{ align: [] }], // 瀵归綈鏂瑰紡 + ['clean'], // 娓呴櫎鏂囨湰鏍煎紡 + // ['link', 'image', 'video'] // 閾炬帴銆佸浘鐗� + ['link', 'image'] // 閾炬帴銆佸浘鐗� +] export default { - name: "test" -} -</script> + name:'test', + data() { + return { + content: '', + editorOptions: { + // Quill缂栬緫鍣ㄧ殑閫夐」 + placeholder: '璇疯緭鍏ュ唴瀹癸紒', + modules:{ + toolbar:{ + container:toolbarOptions + } + } -<style scoped> + } + }; + }, + mounted() { + let self = this; + const editor = this.$refs.quillEditor.quill; + const toolbar = editor.getModule('toolbar'); + toolbar.addHandler('image', () => { + self.selectLocalImage(); + }); + }, + methods: { + selectLocalImage() { + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.click(); + input.onchange = () => { + const file = input.files[0]; + if (file) { + // 鍦ㄨ繖閲岃皟鐢ㄤ綘鐨勫浘鐗囦笂浼犻�昏緫锛屽苟鑾峰彇鍥剧墖鐨刄RL + // 鍋囪浣犱笂浼犲悗寰楀埌浜嗗浘鐗嘦RL + const url = '浣犵殑鍥剧墖URL'; + // 鎻掑叆鍥剧墖鍒扮紪杈戝櫒 + this.insertToEditor(url); + } + }; + }, + insertToEditor(url) { + const range = this.$refs.quillEditor.quill.getSelection(); + this.$refs.quillEditor.quill.insertEmbed(range.index, 'image', url); + } + } +}; +</script> +<style lang="scss" scoped> +.editor { + line-height: normal !important; + height: 400px; + margin-bottom: 50px; +} +//.ql-snow .ql-tooltip[data-mode="link"]::before { +// content: "璇疯緭鍏ラ摼鎺ュ湴鍧�:"; +//} +//.ql-snow .ql-tooltip.ql-editing a.ql-action::after { +// border-right: 0px; +// content: "淇濆瓨"; +// padding-right: 0px; +//} </style> -- Gitblit v1.9.3