Преглед на файлове

扩展ss-editor支持play模式,改校验BUG

Ben преди 14 часа
родител
ревизия
4760489f12
променени са 2 файла, в които са добавени 160 реда и са изтрити 21 реда
  1. 9 6
      js/validate/validation-manager.js
  2. 151 15
      js/vue/ss-components.js

+ 9 - 6
js/validate/validation-manager.js

@@ -81,9 +81,11 @@ class ValidationManager {
         for (const f of tdFields) {
             const element = document.querySelector(`[name="${f}"]`);
             const value = element.value;
-            
-            // 检查是否为空
-            if (!value || value.trim() === '') {
+
+            // 功能说明:只有存在 notNull 规则且值为空时,才认为是空的必填字段 by xu 20260402
+            const fieldValidations = this.validations.get(f);
+            const hasNotNullRule = fieldValidations && fieldValidations.some(v => v.ruleName && v.ruleName.includes('notNull'));
+            if (hasNotNullRule && (!value || value.trim() === '')) {
                 hasEmptyRequired = true;
             }
 
@@ -112,13 +114,14 @@ class ValidationManager {
                 }
             }
         }
-        // 管理必填标记
+        // 管理必填标记:有错误时显示红线(包括非空错误和其他校验错误)by xu 20260402
         let requiredMark = td.querySelector('.required');
-        if ((hasEmptyRequired || errors.length > 0) && !requiredMark) {
+        const hasErrors = errors.length > 0;
+        if ((hasEmptyRequired || hasErrors) && !requiredMark) {
             requiredMark = document.createElement('div');
             requiredMark.className = 'required';
             td.appendChild(requiredMark);
-        } else if (!hasEmptyRequired && errors.length === 0 && requiredMark) {
+        } else if (!hasEmptyRequired && !hasErrors && requiredMark) {
             requiredMark.remove();
         }
 

+ 151 - 15
js/vue/ss-components.js

@@ -206,13 +206,24 @@ import { EVEN_VAR } from "./EventBus.js";
         mode = props.param.mode;
       }
 
+      // 功能说明:只有存在非空校验(notNull)且值为空时,才显示红线 by xu 20260402
+      const hasNotNullRule = () => {
+        const validations = window.ssVm?.validations?.get(props.name);
+        if (!validations || validations.length === 0) return false;
+        return validations.some(v => v.ruleName && v.ruleName.includes('notNull'));
+      };
+
       const showRequired = computed(() => {
-        // 检查是否有验证规则(通过 window.ssVm 判断)
-        const hasValidationRule = window.ssVm?.validations?.has(props.name);
+        const validations = window.ssVm?.validations?.get(props.name);
+        if (!validations || validations.length === 0) return false;
+
+        // 检查是否存在 notNull 规则
+        const hasNotNull = validations.some(v => v.ruleName && v.ruleName.includes('notNull'));
 
-        if (!hasValidationRule) return false;
-        if (errMsg.value) return true;
-        if (!inputValue.value) return true;
+        // 有非空规则且值为空时显示红线
+        if (hasNotNull && !inputValue.value) {
+          return true;
+        }
         return false;
       });
 
@@ -259,8 +270,6 @@ import { EVEN_VAR } from "./EventBus.js";
       const validate = () => {
         if (window.ssVm) {
           const result = window.ssVm.validateField(props.name);
-          console.log(result);
-
           errMsg.value = result.valid ? "" : result.message;
         }
       };
@@ -573,7 +582,6 @@ import { EVEN_VAR } from "./EventBus.js";
                   ]
                 )
               : null,
-            // this.showRequired ? h("div", { class: "required" }) : null,
           ]),
           this.contentFloatingDiv || ""
             ? h(
@@ -728,7 +736,6 @@ import { EVEN_VAR } from "./EventBus.js";
               ...this.$attrs,
               autocomplete: "off",
             }),
-            this.required ? h("div", { class: "required" }) : null,
           ]),
         ]),
       ]);
@@ -3474,6 +3481,10 @@ import { EVEN_VAR } from "./EventBus.js";
         type: Boolean,
         default: false,
       },
+      mode: {
+        type: String,
+        default: "edit", // 'edit' | 'view'
+      },
       uploadUrl: {
         type: String,
         default: "/ulByHttp", //原值为“upload” Ben(20251205)
@@ -3497,6 +3508,9 @@ import { EVEN_VAR } from "./EventBus.js";
       const uniqueId = "editor-" + Date.now();
       const errMsg = Vue.ref("");
 
+      // 计算是否只读:mode='play' 表示只读 by xu 20250402
+      const isReadonly = computed(() => props.mode === "play");
+
       // button 支持对象(旧格式,单个附件按钮)或数组(新格式,多个按钮)by xu 20250331
       const buttonConfigRaw = props.param && props.param.button ? props.param.button : null;
       const buttonArray = Array.isArray(buttonConfigRaw)
@@ -3680,6 +3694,44 @@ import { EVEN_VAR } from "./EventBus.js";
       onMounted(() => {
         validate();
 
+        // 只读模式下不初始化 Jodit,直接设置内容 by xu 20250402
+        if (isReadonly) {
+          if (props.html) {
+            setEditorHtml(props.html);
+          } else if (props.url) {
+            const params = new URLSearchParams();
+            if (mode) params.append("mode", mode);
+            if (props.modelValue) params.append("path", props.modelValue);
+
+            axios
+              .post(props.url, params, {
+                headers: {
+                  "Content-Type": "application/x-www-form-urlencoded",
+                },
+              })
+              .then((response) => {
+                if ("timeout" == response.data.statusText) {
+                  alert("网络超时!");
+                  return;
+                }
+
+                const content = response.data.content;
+                if (content != null) {
+                  setEditorHtml(content);
+                }
+
+                const filePath = response.data.path;
+                if (filePath) {
+                  currentModelValue.value = filePath;
+                  emit("update:modelValue", filePath);
+                }
+              });
+          } else {
+            setEditorHtml(props.html);
+          }
+          return;
+        }
+
         // 如果 prop 为空,尝试从各种来源读取按钮配置
         let buttonsToUse = props.customButtons;
         if (!buttonsToUse || buttonsToUse.length === 0) {
@@ -3742,7 +3794,7 @@ import { EVEN_VAR } from "./EventBus.js";
         const editor = Jodit.make(`#${uniqueId}`, {
           height: props.height,
           placeholder: props.placeholder,
-          readonly: props.readonly,
+          readonly: isReadonly,
           language: "zh_cn",
           i18n: {
             zh_cn: {
@@ -4056,10 +4108,10 @@ import { EVEN_VAR } from "./EventBus.js";
       );
 
       watch(
-        () => props.readonly,
-        (newValue) => {
+        () => props.mode,
+        (newMode) => {
           if (editorRef.value) {
-            editorRef.value.setReadOnly(newValue);
+            editorRef.value.setReadOnly(newMode === "play");
           }
         }
       );
@@ -4110,8 +4162,91 @@ import { EVEN_VAR } from "./EventBus.js";
         }
       });
 
-      return () =>
-        h("div", { class: "ss-editor-container" }, [
+      // 只读模式:打开附件弹窗 by xu 20250402
+      const openAttachmentDialog = () => {
+        if (!fjButton.cmsAddUrl || !fjButton.cmsUpdUrl) {
+          console.warn("ss-editor 未配置附件按钮地址,忽略附件操作");
+          return;
+        }
+        if (fjid.value == null || fjid.value === "") {
+          $.ajax({
+            type: "post",
+            url: fjButton.cmsAddUrl,
+            async: false,
+            data: {
+              name: "fjid",
+              ssNrObjName: "sh",
+              ssNrObjId: "",
+            },
+            success: function (_fjid) {
+              console.log("cmsAddUrl success", _fjid);
+              fjid.value = _fjid;
+            },
+          });
+        }
+        var str =
+          "&nrid=T-" +
+          fjid.value +
+          "&objectId=" +
+          fjid.value +
+          "&objectName=" +
+          fjName +
+          "&callback=" +
+          (window["fjidCallbackName"] || "");
+        console.log("str", str);
+        SS.openDialog({
+          src: fjButton.cmsUpdUrl + str,
+          headerTitle: "编辑",
+          width: 900,
+          high: 664,
+          zIndex: 51,
+        });
+      };
+
+      return () => {
+        // 只读模式:不初始化 Jodit,直接渲染 HTML + 附件按钮 by xu 20250402
+        if (isReadonly) {
+          return h("div", { class: "ss-editor-container ss-editor-readonly" }, [
+            fjid.value &&
+              h("input", {
+                type: "hidden",
+                name: "fjid",
+                value: fjid.value,
+              }),
+            h("input", {
+              type: "hidden",
+              name: props.name.replace(/wj$/, "") + "Edit",
+              value: editorContent.value,
+            }),
+            h("input", {
+              type: "hidden",
+              name: props.name.replace(/wj$/, "") + "wj",
+              value: currentModelValue.value,
+            }),
+            h("input", {
+              type: "hidden",
+              name: "ueditorpath",
+              value: "mswj",
+            }),
+            // 附件按钮(只读模式下仍显示)
+            fjButton.cmsAddUrl && fjButton.cmsUpdUrl &&
+              h("div", {
+                class: "ss-editor-attach-btn",
+                onClick: openAttachmentDialog,
+              }, [
+                h("span", { class: "editor-icon editor-icon-file" }),
+                h("span", { class: "ss-editor-attach-text" }, "附件")
+              ]),
+            // HTML 内容展示
+            h("div", {
+              class: "ss-editor-readonly-content",
+              innerHTML: editorContent.value,
+            }),
+          ]);
+        }
+
+        // 正常编辑模式:渲染 textarea 供 Jodit 初始化
+        return h("div", { class: "ss-editor-container" }, [
           fjid.value &&
             h("input", {
               type: "hidden",
@@ -4135,6 +4270,7 @@ import { EVEN_VAR } from "./EventBus.js";
           }),
           h("textarea", { id: uniqueId }),
         ]);
+      };
     },
   };
   // 弹窗右边图标