From cb0791d5df11b51b6d15c3daab30e99e0e317afc Mon Sep 17 00:00:00 2001
From: houzhongjian <houzhongyi@126.com>
Date: 星期一, 20 一月 2025 14:59:30 +0800
Subject: [PATCH] 指标管理数据集和计划数据➡计划数据集增加查询语句敏感词校验与限制表单提交

---
 src/views/data/ind/data/DataSetForm.vue  |   44 +++++++++++++++++----
 src/views/data/plan/data/DataSetForm.vue |   39 ++++++++++++++++---
 2 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/src/views/data/ind/data/DataSetForm.vue b/src/views/data/ind/data/DataSetForm.vue
index 4b03f66..464ede2 100644
--- a/src/views/data/ind/data/DataSetForm.vue
+++ b/src/views/data/ind/data/DataSetForm.vue
@@ -23,7 +23,11 @@
       <el-form-item label="查询语句" prop="querySql">
         <el-input v-model="formData.querySql" placeholder="请输入内容" type="textarea" maxlength="500"
                   :rows="6"
+                  @input="checkSensitiveWords"
                   show-word-limit spellcheck="false"/>
+      </el-form-item>
+      <el-form-item v-if="showError">
+        <p>输入中包含以下敏感词:<span style="color: red">{{sensitiveMessage}}</span></p>
       </el-form-item>
       <el-form-item label="备注" prop="remark">
         <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" maxlength="100"
@@ -31,25 +35,29 @@
       </el-form-item>
     </el-form>
     <template #footer>
-      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button :disabled="disableSubmit" type="primary" @click="submitForm">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
 <script lang="ts" setup>
-  import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
-  import * as DataSetApi from '@/api/data/ind/data/data.set'
-  import { CommonStatusEnum } from '@/utils/constants'
-  import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig";
+import * as DataSetApi from '@/api/data/ind/data/data.set'
+import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig";
 
-  defineOptions({ name: 'IndDataSetForm' })
+defineOptions({ name: 'IndDataSetForm' })
 
   const { t } = useI18n() // 国际化
   const message = useMessage() // 消息弹窗
 
+  const showError = ref(false)
+  const foundSensitiveWords = ref()
+  const sensitiveMessage = ref('')
+  const sensitiveWords = [';', 'master', 'truncate', 'insert', 'select', 'delete', 'update', 'declare', 'alter', 'drop']
+
   const dialogVisible = ref(false) // 弹窗的是否展示
   const dialogTitle = ref('') // 弹窗的标题
-  const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+  const formLoading = ref(false) // 表单的加载中:修改时的数据加载
+  const disableSubmit = ref(false) // 禁止提交
   const formType = ref('') // 表单的类型:create - 新增;update - 修改
   const formData = ref({
     id: undefined,
@@ -85,10 +93,26 @@
         formLoading.value = false
       }
     }
-
-
   }
   defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+  /**
+   * 验证敏感词
+   */
+  const checkSensitiveWords = () => {
+    showError.value = false;
+    const regex = new RegExp(sensitiveWords.map(word => `${word}`).join('|'), 'gi');
+    let matches = formData.value.querySql.match(regex);
+    if (matches) {
+      showError.value = true;
+      foundSensitiveWords.value = Array.from(new Set(matches));
+      disableSubmit.value = true
+      sensitiveMessage.value = foundSensitiveWords.value.join('、')
+    } else {
+      foundSensitiveWords.value = undefined
+      disableSubmit.value = false
+    }
+  }
 
   /** 提交表单 */
   const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
@@ -99,6 +123,7 @@
     if (!valid) return
     // 提交请求
     formLoading.value = true
+    disableSubmit.value = true
     try {
       const data = formData.value as DataSetApi.DataSetVO
       if (formType.value === 'create') {
@@ -113,6 +138,7 @@
       emit('success')
     } finally {
       formLoading.value = false
+      disableSubmit.value = false
     }
   }
 
diff --git a/src/views/data/plan/data/DataSetForm.vue b/src/views/data/plan/data/DataSetForm.vue
index 5c02606..56aa7da 100644
--- a/src/views/data/plan/data/DataSetForm.vue
+++ b/src/views/data/plan/data/DataSetForm.vue
@@ -22,7 +22,10 @@
       </el-form-item>
       <el-form-item label="查询语句" prop="querySql">
         <el-input v-model="formData.querySql" placeholder="请输入内容" type="textarea" maxlength="300"
-                  show-word-limit :rows="6" spellcheck="false"/>
+                  show-word-limit :rows="6" @input="checkSensitiveWords" spellcheck="false"/>
+      </el-form-item>
+      <el-form-item v-if="showError">
+        <p>输入中包含以下敏感词:<span style="color: red">{{sensitiveMessage}}</span></p>
       </el-form-item>
       <el-form-item label="备注" prop="remark">
         <el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" maxlength="100"
@@ -30,15 +33,13 @@
       </el-form-item>
     </el-form>
     <template #footer>
-      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button :disabled="disableSubmit" type="primary" @click="submitForm">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
 <script lang="ts" setup>
-import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import * as DataSetApi from '@/api/data/plan/data'
-import { CommonStatusEnum } from '@/utils/constants'
 import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig";
 
 defineOptions({ name: 'PlanDataSetForm' })
@@ -46,9 +47,15 @@
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
+const showError = ref(false)
+const foundSensitiveWords = ref()
+const sensitiveMessage = ref('')
+const sensitiveWords = [';', 'master', 'truncate', 'insert', 'select', 'delete', 'update', 'declare', 'alter', 'drop']
+
 const dialogVisible = ref(false) // 弹窗的是否展示
 const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formLoading = ref(false) // 表单的加载中:修改时的数据加载;
+const disableSubmit = ref(false) // 禁止提交
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
   id: undefined,
@@ -84,10 +91,26 @@
       formLoading.value = false
     }
   }
-
-
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/**
+ * 验证敏感词
+ */
+const checkSensitiveWords = () => {
+  showError.value = false;
+  const regex = new RegExp(sensitiveWords.map(word => `${word}`).join('|'), 'gi');
+  let matches = formData.value.querySql.match(regex);
+  if (matches) {
+    showError.value = true;
+    foundSensitiveWords.value = Array.from(new Set(matches));
+    disableSubmit.value = true
+    sensitiveMessage.value = foundSensitiveWords.value.join('、')
+  } else {
+    foundSensitiveWords.value = undefined
+    disableSubmit.value = false
+  }
+}
 
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
@@ -98,6 +121,7 @@
   if (!valid) return
   // 提交请求
   formLoading.value = true
+  disableSubmit.value = true
   try {
     const data = formData.value as DataSetApi.DataSetVO
     if (formType.value === 'create') {
@@ -112,6 +136,7 @@
     emit('success')
   } finally {
     formLoading.value = false
+    disableSubmit.value = false
   }
 }
 

--
Gitblit v1.9.3