From 7f9d13ccc6d8ecf264e6d33c1bd4c79ec62c7546 Mon Sep 17 00:00:00 2001
From: yupi <592789970@qq.com>
Date: Sat, 14 May 2022 13:34:24 +0800
Subject: [PATCH] =?UTF-8?q?add=20=E6=94=AF=E6=8C=81=E6=9F=A5=E7=9C=8B?=
=?UTF-8?q?=E8=B0=83=E7=94=A8=E6=A0=91=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=94=AF?=
=?UTF-8?q?=E6=8C=81=E6=90=9C=E7=B4=A2=E8=8A=82=E7=82=B9=20update=20?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9=20ESLINT=20=E8=AF=AD=E6=B3=95=E4=B8=BA=20Vue?=
=?UTF-8?q?3=20update=20=E4=BC=98=E5=8C=96=E8=A7=A3=E6=9E=90=E5=99=A8?=
=?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BE=BF=E4=BA=8E=E7=90=86=E8=A7=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.eslintrc.js | 2 +-
src/App.vue | 67 ++++---
src/components/SearchableTree.vue | 91 ++++++++++
src/examples/index.ts | 3 +
src/generator/index.ts | 285 +++++++++++++++++++-----------
src/generator/type.d.ts | 3 +-
6 files changed, 322 insertions(+), 129 deletions(-)
create mode 100644 src/components/SearchableTree.vue
create mode 100644 src/examples/index.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index 35ed473..98b6948 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -4,7 +4,7 @@ module.exports = {
es2021: true,
node: true,
},
- extends: ["plugin:vue/essential", "plugin:prettier/recommended"],
+ extends: ["plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
diff --git a/src/App.vue b/src/App.vue
index 57b7bc9..64c88fc 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,5 +1,6 @@
diff --git a/src/examples/index.ts b/src/examples/index.ts
new file mode 100644
index 0000000..4aadbd1
--- /dev/null
+++ b/src/examples/index.ts
@@ -0,0 +1,3 @@
+export const importExample = () => {
+ alert(1);
+};
diff --git a/src/generator/index.ts b/src/generator/index.ts
index 28e1b72..08ff8ec 100644
--- a/src/generator/index.ts
+++ b/src/generator/index.ts
@@ -1,14 +1,53 @@
/**
- * 生成 SQL
+ * 生成 SQL 入口函数
* @param json
*/
-export function doGenerateSQL(json: InputJSON): string {
- if (!json?.main) {
- return "";
- }
- const context = json;
- const result = replaceParams(context.main, context);
- return replaceSubSql(result, context);
+export function doGenerateSQL(json: InputJSON) {
+ // 缺失入口
+ if (!json?.main) {
+ return null;
+ }
+ const sql = json.main.sql ?? json.main;
+ if (!sql) {
+ return null;
+ }
+ const initTreeNode = {
+ title: "main",
+ sql,
+ children: [],
+ };
+ const rootInvokeTreeNode = { ...initTreeNode };
+ const context = json;
+ const resultSQL = generateSQL(
+ context.main,
+ context,
+ context.main?.params,
+ rootInvokeTreeNode
+ );
+ return {
+ resultSQL,
+ invokeTree: rootInvokeTreeNode,
+ };
+}
+
+/**
+ * 递归生成 SQL
+ * @param currentNode
+ * @param context
+ * @param params
+ * @param invokeTreeNode
+ */
+function generateSQL(
+ currentNode: InputJSONValue,
+ context: InputJSON,
+ params?: Record,
+ invokeTreeNode?: InvokeTreeNode
+): string {
+ if (!currentNode) {
+ return "";
+ }
+ const result = replaceParams(currentNode, context, params, invokeTreeNode);
+ return replaceSubSql(result, context, invokeTreeNode);
}
/**
@@ -16,78 +55,112 @@ export function doGenerateSQL(json: InputJSON): string {
* @param currentNode
* @param context
* @param params 动态参数
+ * @param invokeTreeNode
*/
-function replaceParams(currentNode: InputJSONValue, context: InputJSON, params?: Record): string {
- if (currentNode == null) {
- return "";
- }
- const sql = currentNode.sql ?? currentNode;
- if (!sql) {
- return "";
- }
- // 动态、静态参数结合,且优先用静态参数
- params = {...(params ?? {}), ...currentNode.params};
- // 无需替换
- if (!params || Object.keys(params).length < 1) {
- return sql;
- }
- let result = sql;
- for (const paramsKey in params) {
- const replacedKey = `#{${paramsKey}}`;
- // 递归解析
- const replacement = replaceSubSql(params[paramsKey], context);
- // find and replace
- result = result.replaceAll(replacedKey, replacement);
- }
- return result;
+function replaceParams(
+ currentNode: InputJSONValue,
+ context: InputJSON,
+ params?: Record,
+ invokeTreeNode?: InvokeTreeNode
+): string {
+ if (currentNode == null) {
+ return "";
+ }
+ const sql = currentNode.sql ?? currentNode;
+ if (!sql) {
+ return "";
+ }
+ // 动态、静态参数结合,且优先用静态参数
+ params = { ...(params ?? {}), ...currentNode.params };
+ // 无需替换
+ if (!params || Object.keys(params).length < 1) {
+ return sql;
+ }
+ let result = sql;
+ for (const paramsKey in params) {
+ const replacedKey = `#{${paramsKey}}`;
+ // 递归解析
+ // const replacement = replaceSubSql(
+ // params[paramsKey],
+ // context,
+ // invokeTreeNode
+ // );
+ const replacement = params[paramsKey];
+ // find and replace
+ result = result.replaceAll(replacedKey, replacement);
+ }
+ return result;
}
/**
* 替换子 SQL(@xxx)
* @param sql
* @param context
+ * @param invokeTreeNode
*/
-function replaceSubSql(sql: string, context: InputJSON): string {
- if (!sql) {
- return "";
+function replaceSubSql(
+ sql: string,
+ context: InputJSON,
+ invokeTreeNode?: InvokeTreeNode
+): string {
+ if (!sql) {
+ return "";
+ }
+ let result = sql;
+ result = String(result);
+ let regExpMatchArray = matchSubQuery(result);
+ // 依次替换
+ while (regExpMatchArray && regExpMatchArray.length > 2) {
+ // 找到结果
+ const subKey = regExpMatchArray[1];
+ // 可用来替换的节点
+ const replacementNode = context[subKey];
+ // 没有可替换的节点
+ if (!replacementNode) {
+ const errorMsg = `${subKey} 不存在`;
+ alert(errorMsg);
+ throw new Error(errorMsg);
+ }
+ // 获取要传递的动态参数
+ // e.g. "a = b, c = d"
+ let paramsStr = regExpMatchArray[2];
+ if (paramsStr) {
+ paramsStr = paramsStr.trim();
}
- let result = sql;
- result = String(result);
- let regExpMatchArray = matchSubQuery(result);
- // 依次替换
- while (regExpMatchArray && regExpMatchArray.length > 2) {
- // 找到结果
- const subKey = regExpMatchArray[1];
- // 可用来替换的节点
- const replacementNode = context[subKey];
- // 没有可替换的节点
- if (!replacementNode) {
- throw new Error(`${subKey} 不存在`);
- }
- // 获取要传递的动态参数
- // e.g. "a = b, c = d"
- let paramsStr = regExpMatchArray[2];
- if (paramsStr) {
- paramsStr = paramsStr.trim();
- }
- // e.g. ["a = b", "c = d"]
- const singleParamsStrArray = paramsStr.split('|||');
- // string => object
- const params: Record = {};
- for (const singleParamsStr of singleParamsStrArray) {
- // 必须分成 2 段
- const keyValueArray = singleParamsStr.split('=', 2);
- if (keyValueArray.length < 2) {
- continue;
- }
- const key = keyValueArray[0].trim();
- params[key] = keyValueArray[1].trim();
- }
- const replacement = replaceParams(replacementNode, context, params);
- result = result.replaceAll(regExpMatchArray[0], replacement);
- regExpMatchArray = matchSubQuery(result);
+ // e.g. ["a = b", "c = d"]
+ const singleParamsStrArray = paramsStr.split("|||");
+ // string => object
+ const params: Record = {};
+ for (const singleParamsStr of singleParamsStrArray) {
+ // 必须分成 2 段
+ const keyValueArray = singleParamsStr.split("=", 2);
+ if (keyValueArray.length < 2) {
+ continue;
+ }
+ const key = keyValueArray[0].trim();
+ params[key] = keyValueArray[1].trim();
}
- return result;
+ let childInvokeTreeNode;
+ if (invokeTreeNode) {
+ childInvokeTreeNode = {
+ title: subKey,
+ sql,
+ params,
+ children: [],
+ };
+ invokeTreeNode.children?.push(childInvokeTreeNode);
+ }
+ // 递归解析被替换节点
+ const replacement = generateSQL(
+ replacementNode,
+ context,
+ params,
+ childInvokeTreeNode
+ );
+ result = result.replace(regExpMatchArray[0], replacement);
+ regExpMatchArray = matchSubQuery(result);
+ }
+ return result;
}
/**
@@ -95,41 +168,41 @@ function replaceSubSql(sql: string, context: InputJSON): string {
* @param str
*/
function matchSubQuery(str: string) {
- if (!str) {
- return null;
- }
- const regExp = /@([\u4e00-\u9fa5_a-zA-Z0-9]+)\((.*?)\)/;
- let regExpMatchArray = str.match(regExp);
- if (!regExpMatchArray || regExpMatchArray.index === undefined) {
- return null;
+ if (!str) {
+ return null;
+ }
+ const regExp = /@([\u4e00-\u9fa5_a-zA-Z0-9]+)\((.*?)\)/;
+ let regExpMatchArray = str.match(regExp);
+ if (!regExpMatchArray || regExpMatchArray.index === undefined) {
+ return null;
+ }
+ // @ 开始位置
+ let startPos = regExpMatchArray.index;
+ // 左括号右侧
+ let leftParenthesisPos = startPos + regExpMatchArray[1].length + 2;
+ // 遍历游标
+ let currPos = leftParenthesisPos;
+ // 默认匹配结束位置,需要对此结果进行修正
+ let endPos = startPos + regExpMatchArray[0].length;
+ // 剩余待匹配左括号数量
+ let leftCount = 1;
+ while (currPos < str.length) {
+ const currentChar = str.charAt(currPos);
+ if (currentChar === "(") {
+ leftCount++;
+ } else if (currentChar === ")") {
+ leftCount--;
}
- // @ 开始位置
- let startPos = regExpMatchArray.index;
- // 左括号右侧
- let leftParenthesisPos = startPos + regExpMatchArray[1].length + 2;
- // 遍历游标
- let currPos = leftParenthesisPos;
- // 默认匹配结束位置,需要对此结果进行修正
- let endPos = startPos + regExpMatchArray[0].length;
- // 剩余待匹配左括号数量
- let leftCount = 1;
- while (currPos < str.length) {
- const currentChar = str.charAt(currPos);
- if (currentChar === '(') {
- leftCount++;
- } else if (currentChar === ')') {
- leftCount--;
- }
- // 匹配结束
- if (leftCount == 0) {
- endPos = currPos + 1;
- break;
- }
- currPos++;
+ // 匹配结束
+ if (leftCount == 0) {
+ endPos = currPos + 1;
+ break;
}
- return [
- str.slice(startPos, endPos),
- regExpMatchArray[1],
- str.slice(leftParenthesisPos, endPos - 1)
- ]
-}
\ No newline at end of file
+ currPos++;
+ }
+ return [
+ str.slice(startPos, endPos),
+ regExpMatchArray[1],
+ str.slice(leftParenthesisPos, endPos - 1),
+ ];
+}
diff --git a/src/generator/type.d.ts b/src/generator/type.d.ts
index 1cbd594..6fd20bb 100644
--- a/src/generator/type.d.ts
+++ b/src/generator/type.d.ts
@@ -12,8 +12,9 @@ interface InputJSONValue {
* 调用树节点
*/
interface InvokeTreeNode {
- label: string;
+ title: string;
sql: string;
+ key?: string;
params?: Record;
children?: InvokeTreeNode[];
}