Browse Source

Merge branch 'dev'

# Conflicts:
#	src/components/Tinymce/src/Editor.vue
Soul 10 months ago
parent
commit
7a39d56467
3 changed files with 245 additions and 178 deletions
  1. 17 15
      src/api/common/api.ts
  2. 224 156
      src/components/Tinymce/src/Editor.vue
  3. 4 7
      src/views/kms/knowledge/article/index.vue

+ 17 - 15
src/api/common/api.ts

@@ -1,8 +1,10 @@
-import { defHttp } from '/@/utils/http/axios';
-import { message } from 'ant-design-vue';
-import { useGlobSetting } from '/@/hooks/setting';
+import {defHttp} from '/@/utils/http/axios';
+import {message} from 'ant-design-vue';
+import {useGlobSetting} from '/@/hooks/setting';
+
 const globSetting = useGlobSetting();
 const baseUploadUrl = globSetting.uploadUrl;
+
 enum Api {
   positionList = '/sys/position/list',
   userList = '/sys/user/list',
@@ -26,7 +28,7 @@ export const uploadUrl = `${baseUploadUrl}/sys/common/upload`;
  * @param params
  */
 export const getPositionList = (params) => {
-  return defHttp.get({ url: Api.positionList, params });
+  return defHttp.get({url: Api.positionList, params});
 };
 
 /**
@@ -34,7 +36,7 @@ export const getPositionList = (params) => {
  * @param params
  */
 export const getUserList = (params) => {
-  return defHttp.get({ url: Api.userList, params });
+  return defHttp.get({url: Api.userList, params});
 };
 
 /**
@@ -42,59 +44,59 @@ export const getUserList = (params) => {
  * @param params
  */
 export const getRoleList = (params) => {
-  return defHttp.get({ url: Api.roleList, params });
+  return defHttp.get({url: Api.roleList, params});
 };
 
 /**
  * 异步获取部门树列表
  */
 export const queryDepartTreeSync = (params?) => {
-  return defHttp.get({ url: Api.queryDepartTreeSync, params });
+  return defHttp.get({url: Api.queryDepartTreeSync, params});
 };
 /**
  * 获取部门树列表
  */
 export const queryTreeList = (params?) => {
-  return defHttp.get({ url: Api.queryTreeList, params });
+  return defHttp.get({url: Api.queryTreeList, params});
 };
 
 /**
  * 分类字典树控件 加载节点
  */
 export const loadTreeData = (params?) => {
-  return defHttp.get({ url: Api.loadTreeData, params });
+  return defHttp.get({url: Api.loadTreeData, params});
 };
 
 /**
  * 根据字典code加载字典text
  */
 export const loadDictItem = (params?) => {
-  return defHttp.get({ url: Api.loadDictItem, params });
+  return defHttp.get({url: Api.loadDictItem, params});
 };
 
 /**
  * 根据字典code加载字典text
  */
 export const getDictItems = (dictCode) => {
-  return defHttp.get({ url: Api.getDictItems + dictCode }, { joinTime: false });
+  return defHttp.get({url: Api.getDictItems + dictCode}, {joinTime: false});
 };
 /**
  * 部门用户modal选择列表加载list
  */
 export const getTableList = (params) => {
-  return defHttp.get({ url: Api.getTableList, params });
+  return defHttp.get({url: Api.getTableList, params});
 };
 /**
  * 加载全部分类字典数据
  */
 export const loadCategoryData = (params) => {
-  return defHttp.get({ url: Api.getCategoryData, params });
+  return defHttp.get({url: Api.getCategoryData, params});
 };
 /**
  * 文件上传
  */
 export const uploadFile = (params, success) => {
-  return defHttp.uploadFile({ url: uploadUrl }, params, { success });
+  return defHttp.uploadFile({url: uploadUrl, timeout: 2 * 60 * 1000}, params, {success});
 };
 /**
  * 下载文件
@@ -138,7 +140,7 @@ export const getFileblob = (url, parameter) => {
       params: parameter,
       responseType: 'blob',
     },
-    { isTransformResponse: false }
+    {isTransformResponse: false}
   );
 };
 

+ 224 - 156
src/components/Tinymce/src/Editor.vue

@@ -1,7 +1,5 @@
 <template>
-
   <div :class="prefixCls" :style="{ width: containerWidth }">
-
     <ImgUpload
       :fullscreen="fullscreen"
       @uploading="handleImageUploading"
@@ -10,128 +8,137 @@
       v-show="editorRef"
       :disabled="disabled"
     />
-    <textarea :id="tinymceId" ref="elRef" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline">
-    </textarea>
-    <div class="tinymce-upload-progress-box" v-if="spinning">
-      <span>正在上传</span>
-    </div>
+    <a-spin class="tinymce-upload-progress-box" tip="正在上传..."
+            :spinning="spinning"
+            :delay="500">
+    </a-spin>
+    <textarea :id="tinymceId" ref="elRef" :style="{ visibility: 'hidden' }"
+              v-if="!initOptions.inline"></textarea>
+    <slot v-else></slot>
 
-    <!--    <slot v-else></slot>-->
 
   </div>
-
 </template>
 
 <script lang="ts">
-import type { Editor, RawEditorSettings } from "tinymce";
-import tinymce from "tinymce/tinymce";
-import "tinymce/themes/silver";
-import "tinymce/icons/default/icons";
-import "tinymce/plugins/advlist";
-import "tinymce/plugins/anchor";
-import "tinymce/plugins/autolink";
-import "tinymce/plugins/autosave";
-import "tinymce/plugins/code";
-import "tinymce/plugins/codesample";
-import "tinymce/plugins/directionality";
-import "tinymce/plugins/fullscreen";
-import "tinymce/plugins/hr";
-import "tinymce/plugins/insertdatetime";
-import "tinymce/plugins/link";
-import "tinymce/plugins/lists";
-import "tinymce/plugins/media";
-import "tinymce/plugins/nonbreaking";
-import "tinymce/plugins/noneditable";
-import "tinymce/plugins/pagebreak";
-import "tinymce/plugins/paste";
-import "tinymce/plugins/preview";
-import "tinymce/plugins/print";
-import "tinymce/plugins/save";
-import "tinymce/plugins/searchreplace";
-import "tinymce/plugins/spellchecker";
-import "tinymce/plugins/tabfocus";
+import type {Editor, RawEditorSettings} from 'tinymce';
+import tinymce from 'tinymce/tinymce';
+import 'tinymce/themes/silver';
+import 'tinymce/icons/default/icons';
+import 'tinymce/plugins/advlist';
+import 'tinymce/plugins/anchor';
+import 'tinymce/plugins/autolink';
+import 'tinymce/plugins/autosave';
+import 'tinymce/plugins/code';
+import 'tinymce/plugins/codesample';
+import 'tinymce/plugins/directionality';
+import 'tinymce/plugins/fullscreen';
+import 'tinymce/plugins/hr';
+import 'tinymce/plugins/insertdatetime';
+import 'tinymce/plugins/link';
+import 'tinymce/plugins/lists';
+import 'tinymce/plugins/media';
+import 'tinymce/plugins/nonbreaking';
+import 'tinymce/plugins/noneditable';
+import 'tinymce/plugins/pagebreak';
+import 'tinymce/plugins/paste';
+import 'tinymce/plugins/preview';
+import 'tinymce/plugins/print';
+import 'tinymce/plugins/save';
+import 'tinymce/plugins/searchreplace';
+import 'tinymce/plugins/spellchecker';
+import 'tinymce/plugins/tabfocus';
 // import 'tinymce/plugins/table';
-import "tinymce/plugins/template";
-import "tinymce/plugins/textpattern";
-import "tinymce/plugins/visualblocks";
-import "tinymce/plugins/visualchars";
-import "tinymce/plugins/wordcount";
-import "tinymce/plugins/image";
-import "tinymce/plugins/table";
-import "tinymce/plugins/textcolor";
-import "tinymce/plugins/contextmenu";
-import { defineComponent, computed, nextTick, ref, unref, watch, onDeactivated, onBeforeUnmount } from "vue";
-import ImgUpload from "./ImgUpload.vue";
-import { toolbar, plugins, simplePlugins, simpleToolbar, menubar } from "./tinymce";
-import { buildShortUUID } from "/@/utils/uuid";
-import { bindHandlers } from "./helper";
-import { onMountedOrActivated } from "/@/hooks/core/onMountedOrActivated";
-import { useDesign } from "/@/hooks/web/useDesign";
-import { isNumber } from "/@/utils/is";
-import { useLocale } from "/@/locales/useLocale";
-import { useAppStore } from "/@/store/modules/app";
-import { uploadFile } from "/@/api/common/api";
-import { getFileAccessHttpUrl } from "/@/utils/common/compUtils";
+import 'tinymce/plugins/template';
+import 'tinymce/plugins/textpattern';
+import 'tinymce/plugins/visualblocks';
+import 'tinymce/plugins/visualchars';
+import 'tinymce/plugins/wordcount';
+import 'tinymce/plugins/image';
+import 'tinymce/plugins/table';
+import 'tinymce/plugins/textcolor';
+import 'tinymce/plugins/contextmenu';
+import {
+  defineComponent,
+  computed,
+  nextTick,
+  ref,
+  unref,
+  watch,
+  onDeactivated,
+  onBeforeUnmount
+} from 'vue';
+import ImgUpload from './ImgUpload.vue';
+import {toolbar, plugins, simplePlugins, simpleToolbar, menubar} from './tinymce';
+import {buildShortUUID} from '/@/utils/uuid';
+import {bindHandlers} from './helper';
+import {onMountedOrActivated} from '/@/hooks/core/onMountedOrActivated';
+import {useDesign} from '/@/hooks/web/useDesign';
+import {isNumber} from '/@/utils/is';
+import {useLocale} from '/@/locales/useLocale';
+import {useAppStore} from '/@/store/modules/app';
+import {uploadFile} from '/@/api/common/api';
+import {getFileAccessHttpUrl} from '/@/utils/common/compUtils';
 import success from "@/views/demo/page/result/success/index.vue";
-
+import {message} from 'ant-design-vue';
 
 const tinymceProps = {
   path: {
-    type: String
+    type: String,
   },
   options: {
     type: Object as PropType<Partial<RawEditorSettings>>,
-    default: {}
+    default: {},
   },
   value: {
-    type: String
+    type: String,
   },
 
   toolbar: {
     type: [Array as PropType<string[]>, String],
-    default: toolbar
+    default: toolbar,
   },
   plugins: {
     type: Array as PropType<string[]>,
-    default: plugins
+    default: plugins,
   },
   menubar: {
     type: [Object, String],
-    default: menubar
+    default: menubar,
   },
   modelValue: {
-    type: String
+    type: String,
   },
   height: {
     type: [Number, String] as PropType<string | number>,
     required: false,
-    default: 400
+    default: 400,
   },
   width: {
     type: [Number, String] as PropType<string | number>,
     required: false,
-    default: "auto"
+    default: 'auto',
   },
   showImageUpload: {
     type: Boolean,
-    default: true
-  }
+    default: true,
+  },
 };
 
 export default defineComponent({
-  name: "Tinymce",
-  components: { ImgUpload },
+  name: 'Tinymce',
+  components: {ImgUpload},
   inheritAttrs: false,
   props: tinymceProps,
-  emits: ["change", "update:modelValue", "inited", "init-error"],
-  setup(props, { emit, attrs }) {
-    const spinning = ref(false);
+  emits: ['change', 'update:modelValue', 'inited', 'init-error'],
+  setup(props, {emit, attrs}) {
+    const spinning = ref<Boolean>(false);
     const editorRef = ref<Nullable<Editor>>(null);
     const fullscreen = ref(false);
-    const tinymceId = ref<string>(buildShortUUID("tiny-vue"));
+    const tinymceId = ref<string>(buildShortUUID('tiny-vue'));
     const elRef = ref<Nullable<HTMLElement>>(null);
 
-    const { prefixCls } = useDesign("tinymce-container");
+    const {prefixCls} = useDesign('tinymce-container');
 
     const appStore = useAppStore();
 
@@ -146,111 +153,171 @@ export default defineComponent({
     });
 
     const skinName = computed(() => {
-      return appStore.getDarkMode === "light" ? "jeecg" : "oxide-dark";
+      return appStore.getDarkMode === 'light' ? 'jeecg' : 'oxide-dark';
     });
 
     const langName = computed(() => {
       const lang = useLocale().getLocale.value;
-      return ["zh_CN", "en"].includes(lang) ? lang : "zh_CN";
+      return ['zh_CN', 'en'].includes(lang) ? lang : 'zh_CN';
     });
 
     const initOptions = computed((): RawEditorSettings => {
-      const { height, options, toolbar, plugins, menubar } = props;
-      const publicPath = import.meta.env.VITE_PUBLIC_PATH || "/";
+      const {height, options, toolbar, plugins, menubar} = props;
+      const publicPath = import.meta.env.VITE_PUBLIC_PATH || '/';
       return {
         selector: `#${unref(tinymceId)}`,
         height,
         toolbar,
         menubar: menubar,
         plugins,
-        language_url: publicPath + "resource/tinymce/langs/" + langName.value + ".js",
+        language_url: publicPath + 'resource/tinymce/langs/' + langName.value + '.js',
         language: langName.value,
         branding: false,
-        default_link_target: "_blank",
+        default_link_target: '_blank',
         link_title: false,
         object_resizing: true,
         relative_urls: false,
         remove_script_host: false,
         convert_urls: false,
-        toolbar_mode: "sliding",
+        toolbar_mode: 'sliding',
         auto_focus: true,
         toolbar_groups: true,
         skin: skinName.value,
-        skin_url: publicPath + "resource/tinymce/skins/ui/" + skinName.value,
+        skin_url: publicPath + 'resource/tinymce/skins/ui/' + skinName.value,
         images_upload_handler: (blobInfo, success) => {
           let params = {
             file: blobInfo.blob(),
             filename: blobInfo.filename(),
-            data: { biz: "jeditor", jeditor: "1" }
+            data: {biz: 'jeditor', jeditor: '1'},
           };
           const uploadSuccess = (res) => {
             if (res.success) {
-              if (res.message == "local") {
-                const img = "data:image/jpeg;base64," + blobInfo.base64();
+              if (res.message == 'local') {
+                const img = 'data:image/jpeg;base64,' + blobInfo.base64();
                 success(img);
               } else {
                 let img = getFileAccessHttpUrl(res.message);
                 success(img);
               }
+            } else {
+              message.error("上传文件超时,请务必在两分钟内上传完毕")
+              return;
             }
           };
           uploadFile(params, uploadSuccess);
         },
         file_picker_callback: (callback, value, meta) => {
+          let fileName = ""
+          spinning.value = true;
+          const tox = document.getElementsByClassName("tox-dialog")[0];
+          tox.style.zIndex = -20;
+          // console.log(meta.filetype)
           const uploadSuccess = (res) => {
             if (res.success) {
-              let fileUrl = "/jeecgboot/sys/common/file/" + res.message;
-              callback(fileUrl);
+              let fileUrl = '/jeecgboot/sys/common/file/' + res.message;
+              callback(fileUrl, {text: fileName})
+            } else {
+              message.error("上传文件超时,请务必在两分钟内上传完毕")
+              return;
             }
           };
-          if (meta.filetype === "file") {
-            const input = document.createElement("input");
-            input.setAttribute("type", "file");
-            input.onchange = async function() {
-              const file = this.files[0]; // 为 HTMLInputElement 构造函数中的 this,指向 input 实例对象
+          if (meta.filetype === 'file') {
+            const input = document.createElement('input')
+            input.setAttribute('type', 'file')
+            input.oncancel = async function () {
+              spinning.value = false;
+              tox.style.zIndex = 2;
+            }
+            input.onchange = async function () {
+              const file = this.files[0] // 为 HTMLInputElement 构造函数中的 this,指向 input 实例对象
+              fileName = file.name
+              if (file.size / 1024 / 1024 > 1024) {
+                message.error("文件大小超过1G,请压缩或降低质量")
+                spinning.value = false;
+                tox.style.zIndex = 2;
+                return
+              }
               //后缀名
-              const extension = file.name.substring(file.name.lastIndexOf(".") + 1);
+              const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
               let params = {
                 file: file,
                 filename: file.name,
-                data: { biz: extension, jeditor: "1" }
+                data: {biz: extension, jeditor: '1'},
               };
-              uploadFile(params, uploadSuccess);
-            };
-            input.click();
+              uploadFile(params, uploadSuccess).finally(() => {
+                spinning.value = false;
+                tox.style.zIndex = 2;
+              });
+            }
+            input.click()
           }
-          if (meta.filetype === "media") {
-            const input = document.createElement("input");
-            input.setAttribute("type", "file");
-            input.onchange = async function() {
-              const file = this.files[0]; // 为 HTMLInputElement 构造函数中的 this,指向 input 实例对象
+          if (meta.filetype === 'media') {
+            const input = document.createElement('input')
+            input.setAttribute('type', 'file')
+            //设置上传视频的类型
+            input.setAttribute('accept', ".mp4");
+            input.oncancel = async function () {
+              spinning.value = false;
+              tox.style.zIndex = 2;
+            }
+            input.onchange = async function () {
+              const file = this.files[0] // 为 HTMLInputElement 构造函数中的 this,指向 input 实例对象
+              fileName = file.name
+              if (file.size / 1024 / 1024 > 1024) {
+                spinning.value = false;
+                tox.style.zIndex = 2;
+                message.error("视频大小超过1G,请压缩或降低质量")
+                return
+              }
               let params = {
                 file: file,
                 filename: file.name,
-                data: { biz: "video", jeditor: "1" }
+                data: {biz: 'video', jeditor: '1'},
               };
-              const tox = document.getElementsByClassName("tox-dialog")[0];
-              const spin = document.getElementById("spinId");
-
-              tox.style.zIndex = -20;
-              spinning.value = true;
-              console.log(tox);
-              uploadFile(params, uploadSuccess).then(res => {
+              uploadFile(params, uploadSuccess).finally(() => {
+                spinning.value = false;
+                tox.style.zIndex = 2;
+              });
+            }
+            input.click()
+          }
+          if (meta.filetype === 'image') {
+            const input = document.createElement('input')
+            input.setAttribute('type', 'file')
+            //设置上传视频的类型
+            input.setAttribute('accept', ".jpg, .jpeg, .png, .gif");
+            input.oncancel = async function () {
+              spinning.value = false;
+              tox.style.zIndex = 2;
+            }
+            input.onchange = async function () {
+              const file = this.files[0] // 为 HTMLInputElement 构造函数中的 this,指向 input 实例对象
+              fileName = file.name
+              if (file.size / 1024 / 1024 > 1024) {
+                message.error("图片大小超过1G,请压缩或降低质量")
                 spinning.value = false;
                 tox.style.zIndex = 2;
-              }).catch(error => {
+                return
+              }
+              let params = {
+                file: file,
+                filename: file.name,
+                data: {biz: 'jeditor', jeditor: '1'},
+              };
+              uploadFile(params, uploadSuccess).finally(() => {
                 spinning.value = false;
                 tox.style.zIndex = 2;
               });
-            };
-            input.click();
+            }
+            input.click()
           }
+
         },
-        file_url_resolver: function(data, resolve) {
+        file_url_resolver: function (data, resolve) {
 
         },
         //自定义逻辑替换 Tinymce 的默认媒体嵌入逻辑
-        media_url_resolver: function(data, resolve) {
+        media_url_resolver: function (data, resolve) {
           try {
             let videoUri = encodeURI(data.url);
             let embedHtml = `<p>
@@ -263,33 +330,33 @@ export default defineComponent({
                 data-mce-p-allowfullscreen="true"
                 data-mce-p-oncontextmenu="return false;"
                 data-mce-p-controlslist="nodownload"
-                data-mce-p-src="${videoUri}" >
-                <video src="${data.url}" width="800" height="600" controls="controls" >
+                data-mce-p-src=${videoUri} >
+                <video src=${data.url} width="800" height="600" controls="controls" >
                 </video>
             </span>
         </p>
         <p style="text-align: left;"></p>`;
-            resolve({ html: embedHtml });
+            resolve({html: embedHtml});
           } catch (e) {
-            resolve({ html: "" });
+            resolve({html: ""});
           }
         },
-        content_css: publicPath + "resource/tinymce/skins/ui/" + skinName.value + "/content.min.css",
+        content_css: publicPath + 'resource/tinymce/skins/ui/' + skinName.value + '/content.min.css',
         ...options,
         setup: (editor: Editor) => {
           editorRef.value = editor;
-          editor.on("init", (e) => initSetup(e));
-        }
+          editor.on('init', (e) => initSetup(e));
+        },
       };
     });
 
     const disabled = computed(() => {
-      const { options } = props;
-      const getdDisabled = options && Reflect.get(options, "readonly");
+      const {options} = props;
+      const getdDisabled = options && Reflect.get(options, 'readonly');
       const editor = unref(editorRef);
       // update-begin-author:taoyan date:20220407 for: 设置disabled,图片上传没有被禁用
       if (editor) {
-        editor.setMode(getdDisabled || attrs.disabled === true ? "readonly" : "design");
+        editor.setMode(getdDisabled || attrs.disabled === true ? 'readonly' : 'design');
       }
       if (attrs.disabled === true) {
         return true;
@@ -305,13 +372,13 @@ export default defineComponent({
         if (!editor) {
           return;
         }
-        editor.setMode(attrs.disabled ? "readonly" : "design");
+        editor.setMode(attrs.disabled ? 'readonly' : 'design');
       }
     );
 
     onMountedOrActivated(() => {
       if (!initOptions.value.inline) {
-        tinymceId.value = buildShortUUID("tiny-vue");
+        tinymceId.value = buildShortUUID('tiny-vue');
       }
       nextTick(() => {
         setTimeout(() => {
@@ -337,15 +404,15 @@ export default defineComponent({
     function initEditor() {
       const el = unref(elRef);
       if (el) {
-        el.style.visibility = "";
+        el.style.visibility = '';
       }
       tinymce
         .init(unref(initOptions))
         .then((editor) => {
-          emit("inited", editor);
+          emit('inited', editor);
         })
         .catch((err) => {
-          emit("init-error", err);
+          emit('init-error', err);
         });
     }
 
@@ -354,7 +421,7 @@ export default defineComponent({
       if (!editor) {
         return;
       }
-      const value = props.modelValue || "";
+      const value = props.modelValue || '';
 
       editor.setContent(value);
       bindModelHandlers(editor);
@@ -362,14 +429,14 @@ export default defineComponent({
     }
 
     function setValue(editor: Recordable, val: string, prevVal?: string) {
-      if (editor && typeof val === "string" && val !== prevVal && val !== editor.getContent({ format: attrs.outputFormat })) {
+      if (editor && typeof val === 'string' && val !== prevVal && val !== editor.getContent({format: attrs.outputFormat})) {
         editor.setContent(val);
       }
     }
 
     function bindModelHandlers(editor: any) {
       const modelEvents = attrs.modelEvents ? attrs.modelEvents : null;
-      const normalizedEvents = Array.isArray(modelEvents) ? modelEvents.join(" ") : modelEvents;
+      const normalizedEvents = Array.isArray(modelEvents) ? modelEvents.join(' ') : modelEvents;
 
       watch(
         () => props.modelValue,
@@ -384,17 +451,17 @@ export default defineComponent({
           setValue(editor, val, prevVal);
         },
         {
-          immediate: true
+          immediate: true,
         }
       );
 
-      editor.on(normalizedEvents ? normalizedEvents : "change keyup undo redo", () => {
-        const content = editor.getContent({ format: attrs.outputFormat });
-        emit("update:modelValue", content);
-        emit("change", content);
+      editor.on(normalizedEvents ? normalizedEvents : 'change keyup undo redo', () => {
+        const content = editor.getContent({format: attrs.outputFormat});
+        emit('update:modelValue', content);
+        emit('change', content);
       });
 
-      editor.on("FullscreenStateChanged", (e) => {
+      editor.on('FullscreenStateChanged', (e) => {
         fullscreen.value = e.state;
       });
     }
@@ -404,8 +471,8 @@ export default defineComponent({
       if (!editor) {
         return;
       }
-      editor.execCommand("mceInsertContent", false, getUploadingImgName(name));
-      const content = editor?.getContent() ?? "";
+      editor.execCommand('mceInsertContent', false, getUploadingImgName(name));
+      const content = editor?.getContent() ?? '';
       setValue(editor, content);
     }
 
@@ -414,8 +481,8 @@ export default defineComponent({
       if (!editor) {
         return;
       }
-      const content = editor?.getContent() ?? "";
-      const val = content?.replace(getUploadingImgName(name), `<img src="${url}"/>`) ?? "";
+      const content = editor?.getContent() ?? '';
+      const val = content?.replace(getUploadingImgName(name), `<img src="${url}"/>`) ?? '';
       setValue(editor, val);
     }
 
@@ -436,9 +503,9 @@ export default defineComponent({
       editorRef,
       fullscreen,
       disabled,
-      spinning
+      spinning,
     };
-  }
+  },
 });
 </script>
 
@@ -451,18 +518,19 @@ export default defineComponent({
   position: relative;
   line-height: normal;
 
-  .tinymce-upload-progress-box {
-    position: absolute !important;
-    text-align: center;
-    top: 50%;
-    left: 50%;
-    margin-top: -62px !important;;
-    margin-left: -60px !important;;
-  }
-
   textarea {
     z-index: -1;
     visibility: hidden;
   }
 }
+
+.tinymce-upload-progress-box {
+  position: absolute !important;
+  text-align: center;
+  top: 50%;
+  left: 50%;
+  z-index: 200;
+  margin-top: -350px !important;;
+  margin-left: -100px !important;;
+}
 </style>

+ 4 - 7
src/views/kms/knowledge/article/index.vue

@@ -101,12 +101,10 @@
 <!--            </div>-->
 
           </div>
-          <a-row style="height: 200px;">
-            <a-col>
-              <div style="text-align: center">
+          <div style="text-align: center">
                 <div class="nr_center">
                   <div class="foot_rgt">
-                    <a href="http://www.lttc.cn/stepin/" target=“_blank>走进鲁泰</a> |
+                    <a href="http://www.lttc.cn/stepin/" target=“_blank>走进鲁泰</a> | 
                     <a href="http://www.lttc.cn/culture/" target=“_blank>企业文化</a> |
                     <a href="http://www.lttc.cn/news/" target=“_blank>新闻中心</a> |
                     <a href="http://www.lttc.cn/investor/" target=“_blank>投资者关系</a> |
@@ -121,8 +119,7 @@
                   </div>
                 </div>
               </div>
-            </a-col>
-          </a-row>
+          
           <!-- <a-divider/> -->
           <!-- <div class="comment">
           </div> -->
@@ -313,8 +310,8 @@ onMounted(() => {
 
 .nr_center {
   width: 1000px;
+  bottom: 0;
   margin: 0 auto;
-  margin-top: 35px;
 }
 
 .foot_rgt {