Pārlūkot izejas kodu

feat:增加API定义保存时必填项弹出提示

microrain 5 mēneši atpakaļ
vecāks
revīzija
97fc83c841
1 mainītis faili ar 220 papildinājumiem un 19 dzēšanām
  1. 220 19
      src/views/apihub/component/edit.vue

+ 220 - 19
src/views/apihub/component/edit.vue

@@ -293,6 +293,133 @@ const editorDidMount = (editor) => {
   }
 };
 
+// 检查哪个标签页有验证错误并切换到该标签页
+const checkTabWithErrors = () => {
+  // 获取所有验证失败的字段
+  const fields = formRef.value.fields;
+  const errorFields = [];
+  
+  // 收集所有错误字段
+  for (const field in fields) {
+    if (fields[field].validateState === 'error') {
+      errorFields.push(field);
+    }
+  }
+  
+  if (errorFields.length === 0) return;
+  
+  // 基本信息标签页的字段
+  const basicTabFields = ['name', 'path', 'version', 'description', 'groupKey'];
+  // 执行器标签页的字段
+  const executorTabFields = ['dataSourceKey', 'sqlType', 'sqlContent', 'returnFormat', 'status'];
+  // 全局插件标签页的字段
+  const pluginsTabFields = [];
+  // 检查插件相关字段
+  errorFields.forEach(field => {
+    if (field.startsWith('plugins[')) {
+      pluginsTabFields.push(field);
+    }
+  });
+  
+  // 检查每个标签页并切换到有错误的标签页
+  const errorTabs = [];
+  
+  if (errorFields.some(field => basicTabFields.includes(field))) {
+    errorTabs.push({ tab: 'basic', name: '基本信息' });
+  }
+  if (errorFields.some(field => executorTabFields.includes(field))) {
+    errorTabs.push({ tab: 'executor', name: '执行器' });
+  }
+  if (pluginsTabFields.length > 0) {
+    errorTabs.push({ tab: 'plugins', name: '全局插件' });
+  }
+  
+  if (errorTabs.length > 0) {
+    // 如果当前标签页不在错误标签页列表中,切换到第一个错误标签页
+    const currentTabHasError = errorTabs.some(tab => tab.tab === activeTab.value);
+    if (!currentTabHasError) {
+      activeTab.value = errorTabs[0].tab;
+    }
+    
+    // 显示错误提示
+    showErrorTooltip(errorTabs);
+    
+    // 等待DOM更新后滚动到错误字段
+    nextTick(() => {
+      const errorElement = document.querySelector('.is-error');
+      if (errorElement) {
+        errorElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
+      }
+    });
+  }
+};
+
+// 显示错误提示
+const showErrorTooltip = (errorTabs) => {
+  // 创建错误标签页列表的HTML
+  let errorMessage = '<div class="error-tabs-list">';
+  errorMessage += '<div class="error-title">以下标签页有必填项未填写:</div>';
+  errorMessage += '<ul>';
+  errorTabs.forEach(tab => {
+    errorMessage += `<li class="error-tab-item" data-tab="${tab.tab}">${tab.name}</li>`;
+  });
+  errorMessage += '</ul>';
+  errorMessage += '</div>';
+  
+  // 显示消息提示
+  ElMessage({
+    dangerouslyUseHTMLString: true,
+    message: errorMessage,
+    type: 'error',
+    duration: 5000,
+    showClose: true,
+    onClose: () => {
+      // 消息关闭后移除事件监听
+      removeErrorTabClickListeners();
+    }
+  });
+  
+  // 等待DOM更新后添加点击事件
+  nextTick(() => {
+    addErrorTabClickListeners();
+  });
+};
+
+// 添加错误标签页点击事件
+const addErrorTabClickListeners = () => {
+  const tabItems = document.querySelectorAll('.error-tab-item');
+  tabItems.forEach(item => {
+    item.addEventListener('click', handleErrorTabClick);
+    // 添加手型光标和下划线样式
+    item.style.cursor = 'pointer';
+    item.style.textDecoration = 'underline';
+    item.style.color = '#409EFF';
+  });
+};
+
+// 移除错误标签页点击事件
+const removeErrorTabClickListeners = () => {
+  const tabItems = document.querySelectorAll('.error-tab-item');
+  tabItems.forEach(item => {
+    item.removeEventListener('click', handleErrorTabClick);
+  });
+};
+
+// 错误标签页点击处理函数
+const handleErrorTabClick = (event) => {
+  const tabName = event.target.getAttribute('data-tab');
+  if (tabName) {
+    activeTab.value = tabName;
+    // 等待DOM更新后滚动到错误字段
+    nextTick(() => {
+      const errorElement = document.querySelector('.is-error');
+      if (errorElement) {
+        errorElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
+      }
+    });
+  }
+};
+
 api.dataSource.list().then((res: any) => {
   dataSources.value = res.list;
 });
@@ -391,27 +518,79 @@ const toggleFullscreen = () => {
 };
 
 // 提交表单
-const onSubmit = async () => {
-  // 表单验证
-  await formRef.value.validate();
-
-  // 准备提交数据
-  const submitData = JSON.parse(JSON.stringify(formData));
+const onSubmit = () => {
+  // 使用回调形式的验证,而不是异步验证
+  formRef.value.validate((valid, fields) => {
+    if (valid) {
+      // 验证通过
+      // 准备提交数据
+      const submitData = JSON.parse(JSON.stringify(formData));
+
+      // 调用API
+      if (submitData.id) {
+        // 编辑模式
+        api.edit(submitData).then(() => {
+          ElMessage.success("操作成功");
+          resetForm();
+          showDialog.value = false;
+          emit("getList");
+        });
+      } else {
+        // 新增模式
+        delete submitData.id;
+        api.add(submitData).then(() => {
+          ElMessage.success("操作成功");
+          resetForm();
+          showDialog.value = false;
+          emit("getList");
+        });
+      }
+    } else {
+      // 验证失败
+      // 直接显示错误提示
+      showValidationErrorMessage(fields);
+      
+      // 验证失败时检查是哪个标签页的必填项出错
+      checkTabWithErrors();
+      
+      return false;
+    }
+  });
+};
 
-  // 调用API
-  if (submitData.id) {
-    // 编辑模式
-    await api.edit(submitData);
-  } else {
-    // 新增模式
-    delete submitData.id;
-    await api.add(submitData);
+// 显示验证错误消息
+const showValidationErrorMessage = (fields) => {
+  // 获取所有错误字段
+  const errorFields = Object.keys(fields);
+  if (errorFields.length === 0) return;
+  
+  // 基本信息标签页的字段
+  const basicTabFields = ['name', 'path', 'version', 'description', 'groupKey'];
+  // 执行器标签页的字段
+  const executorTabFields = ['dataSourceKey', 'sqlType', 'sqlContent', 'returnFormat', 'status'];
+  
+  // 检查每个标签页的错误
+  const errorTabs = [];
+  
+  if (errorFields.some(field => basicTabFields.includes(field))) {
+    errorTabs.push('基本信息');
+  }
+  if (errorFields.some(field => executorTabFields.includes(field))) {
+    errorTabs.push('执行器');
+  }
+  if (errorFields.some(field => field.startsWith('plugins['))) {
+    errorTabs.push('全局插件');
+  }
+  
+  if (errorTabs.length > 0) {
+    // 显示错误消息
+    ElMessage({
+      message: `请检查以下标签页的必填项:${errorTabs.join('、')}`,
+      type: 'error',
+      duration: 5000,
+      showClose: true
+    });
   }
-
-  ElMessage.success("操作成功");
-  resetForm();
-  showDialog.value = false;
-  emit("getList");
 };
 
 // 重置表单
@@ -481,6 +660,28 @@ defineExpose({ open });
 </script>
 
 <style scoped>
+/* 错误提示样式 */
+:deep(.error-tabs-list) {
+  text-align: left;
+  padding: 5px 0;
+}
+
+:deep(.error-title) {
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+
+:deep(.error-tabs-list ul) {
+  list-style: disc;
+  padding-left: 20px;
+  margin: 5px 0;
+}
+
+:deep(.error-tab-item) {
+  margin: 3px 0;
+  padding: 2px 0;
+}
+
 .dialog-header {
   display: flex;
   justify-content: space-between;