|
@@ -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;
|