add 添加 eslint 和 prettier

update UI 库由 tDesign 改为 Ant Design Vue(主要是因为前者和 Vite 热更新不兼容)
pull/3/head
yupi 2 years ago
parent 45d17f1e1a
commit b41bea585a

@ -0,0 +1,17 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: ["plugin:vue/essential", "plugin:prettier/recommended"],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint", "prettier"],
rules: {
"prettier/prettier": "error",
},
};

1
.gitignore vendored

@ -1,6 +1,7 @@
# Logs # Logs
logs logs
*.log *.log
package-lock.json
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*

@ -1,20 +1,32 @@
{ {
"name": "sql-generator", "name": "sql-generator",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.1",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vue-tsc --noEmit && vite build", "build": "vue-tsc --noEmit && vite build",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@ant-design/icons-vue": "^6.1.0",
"ant-design-vue": "^3.2.3",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
"sql-formatter": "^4.0.2", "sql-formatter": "^4.0.2",
"tdesign-vue-next": "^0.14.1",
"vue": "^3.2.25" "vue": "^3.2.25"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.23.0",
"@typescript-eslint/parser": "^5.23.0",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.1",
"eslint": "^8.15.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.2.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^8.7.1",
"prettier": "2.6.2",
"typescript": "^4.5.4", "typescript": "^4.5.4",
"vite": "^2.9.7", "vite": "^2.9.7",
"vue-tsc": "^0.34.7" "vue-tsc": "^0.34.7"

@ -1,73 +1,83 @@
<script setup lang="ts"> <script setup lang="ts">
import {doGenerateSQL} from "./generator"; import { doGenerateSQL } from "./generator";
import {onMounted, ref, toRaw} from "vue"; import { onMounted, ref, toRaw } from "vue";
import * as monaco from "monaco-editor"; import * as monaco from "monaco-editor";
import IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor; import { format } from "sql-formatter";
import {format} from "sql-formatter"; import { GithubOutlined } from "@ant-design/icons-vue";
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' import JsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker' import CssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker' import HtmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker' import TsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
// eslint-disable-next-line no-undef
import IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
// @ts-ignore
(self as any).MonacoEnvironment = { (self as any).MonacoEnvironment = {
getWorker(_: any, label: any) { getWorker(_: any, label: any) {
if (label === 'json') { if (label === "json") {
return new jsonWorker() return new JsonWorker();
} }
if (label === 'css' || label === 'scss' || label === 'less') { if (label === "css" || label === "scss" || label === "less") {
return new cssWorker() return new CssWorker();
} }
if (label === 'html' || label === 'handlebars' || label === 'razor') { if (label === "html" || label === "handlebars" || label === "razor") {
return new htmlWorker() return new HtmlWorker();
} }
if (label === 'typescript' || label === 'javascript') { if (label === "typescript" || label === "javascript") {
return new tsWorker() return new TsWorker();
} }
return new editorWorker() return new EditorWorker();
} },
} };
const initTreeNode = {
label: "main",
sql: "",
children: [],
};
const inputEditor = ref<IStandaloneCodeEditor>(); const inputEditor = ref<IStandaloneCodeEditor>();
const outputEditor = ref<IStandaloneCodeEditor>(); const outputEditor = ref<IStandaloneCodeEditor>();
const inputContainer = ref<HTMLElement>(); const inputContainer = ref<HTMLElement>();
const outputContainer = ref<HTMLElement>(); const outputContainer = ref<HTMLElement>();
const treeNode = ref<InvokeTreeNode>({ ...initTreeNode });
const getSQL = () => { const getSQL = () => {
if (inputEditor.value && outputEditor.value) { if (inputEditor.value && outputEditor.value) {
const inputJSON = JSON.parse(toRaw(inputEditor.value).getValue()); const inputJSON = JSON.parse(toRaw(inputEditor.value).getValue());
let result = format(doGenerateSQL(inputJSON)); treeNode.value = { ...initTreeNode };
const sqlResult = doGenerateSQL(inputJSON, treeNode.value);
let result = format(sqlResult);
// //
result = result.replaceAll("{ {", "{{") result = result.replaceAll("{ {", "{{");
result = result.replaceAll("} }", "}}") result = result.replaceAll("} }", "}}");
toRaw(outputEditor.value).setValue(result); toRaw(outputEditor.value).setValue(result);
console.log(treeNode.value);
} }
} };
const getInvokeTree = () => {
} const getInvokeTree = () => {};
const initJSONValue = "{\n" + const initJSONValue =
" \"main\": {\n" + "{\n" +
" \"sql\": \"select * from @union_all_layer(分区 = 2021) where 分区 = #{分区}\",\n" + ' "main": {\n' +
" \"params\": {\n" + ' "sql": "select * from @union_all_layer(分区 = 2021) where 分区 = #{分区}",\n' +
" \"分区\": 2022\n" + ' "params": {\n' +
" }\n" + ' "分区": 2022\n' +
" },\n" + " }\n" +
" \"union_all_layer\": {\n" + " },\n" +
" \"sql\": \"select * from xx where 分区 = #{分区}\"\n" + ' "union_all_layer": {\n' +
" }\n" + ' "sql": "select * from xx where 分区 = #{分区}"\n' +
"}"; " }\n" +
"}";
onMounted(() => { onMounted(() => {
if (inputContainer.value) { if (inputContainer.value) {
inputEditor.value = monaco.editor.create(inputContainer.value, { inputEditor.value = monaco.editor.create(inputContainer.value, {
value: localStorage.getItem('draft') ?? initJSONValue, value: localStorage.getItem("draft") ?? initJSONValue,
language: 'json', language: "json",
theme: 'vs-dark', theme: "vs-dark",
formatOnPaste: true, formatOnPaste: true,
fontSize: 16, fontSize: 16,
minimap: { minimap: {
@ -76,54 +86,73 @@ onMounted(() => {
}); });
setInterval(() => { setInterval(() => {
if (inputEditor.value) { if (inputEditor.value) {
localStorage.setItem('draft', toRaw(inputEditor.value).getValue()); localStorage.setItem("draft", toRaw(inputEditor.value).getValue());
} }
}, 3000) }, 3000);
} }
if (outputContainer.value) { if (outputContainer.value) {
outputEditor.value = monaco.editor.create(outputContainer.value, { outputEditor.value = monaco.editor.create(outputContainer.value, {
value: "", value: "",
language: 'sql', language: "sql",
theme: 'vs-dark', theme: "vs-dark",
formatOnPaste: true, formatOnPaste: true,
fontSize: 16, fontSize: 16,
minimap: { minimap: {
enabled: false, enabled: false,
}, },
}); });
getSQL();
} }
}); });
</script> </script>
<template> <template>
<h1>
SQL 生成器 - JSON 来写 SQL
<div style="float: right">
<t-button size="large" theme="primary" @click="getSQL" > 生成 SQL</t-button>
<t-divider theme="vertical" />
<t-button size="large" theme="default" @click="getInvokeTree"> </t-button>
</div>
<t-tree :data="[]" activable hover />
</h1>
<t-row :gutter="24">
<t-col :xs="12" :sm="6">
<div id="inputContainer" ref="inputContainer" style="height: 80vh; max-width: 100%"/>
</t-col>
<t-col :xs="12" :sm="6">
<div id="outputContainer" ref="outputContainer" style="height: 80vh; max-width: 100%"/>
</t-col>
</t-row>
<br/>
<div> <div>
yupi你能体会手写 1500 SQL牵一发而动全身的恐惧么 <a-row justify="space-between" align="middle" :gutter="[0, 16]">
<h1 style="margin-bottom: 0">🔨 结构化 SQL 生成器</h1>
<div>使用 JSON 来编写 SQL告别重复代码点击查看文档</div>
<a-space size="large">
<a-button size="large" type="primary" @click="getSQL">
生成 SQL
</a-button>
<a-button size="large" type="default" @click="getInvokeTree">
查看调用树
</a-button>
</a-space>
</a-row>
<div style="margin-top: 16px" />
<a-row :gutter="[16, 16]">
<a-col :sm="24" :md="12">
<div
id="inputContainer"
ref="inputContainer"
style="height: 80vh; max-width: 100%"
/>
</a-col>
<a-col :sm="24" :md="12">
<div
id="outputContainer"
ref="outputContainer"
style="height: 80vh; max-width: 100%"
/>
</a-col>
</a-row>
<br />
<div>yupi你能体会手写一句 3000 行的 SQL牵一发而动全身的恐惧么</div>
<a-row justify="center">
<a-space>
作者<a href="https://github.com/liyupi" target="_blank">鱼皮</a>
<a-divider type="vertical" />
<a href="https://github.com/liyupi/sql-generator" target="_blank">
<github-outlined />
项目已开源欢迎 star
</a>
</a-space>
</a-row>
</div> </div>
</template> </template>
<style> <style>
#app { #app {
padding: 0 25px; padding: 20px;
} }
</style>
</style>

@ -1,10 +1,7 @@
import { createApp } from 'vue'; import { createApp } from "vue";
import TDesign from 'tdesign-vue-next'; import App from "./App.vue";
import App from './app.vue'; import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";
// 引入组件库全局样式资源
import 'tdesign-vue-next/es/style/index.css';
const app = createApp(App); const app = createApp(App);
app.use(TDesign); app.use(Antd).mount("#app");
app.mount('#app');

@ -10,9 +10,21 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["esnext", "dom"], "lib": [
"esnext",
"dom"
],
"skipLibCheck": true "skipLibCheck": true
}, },
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "include": [
"references": [{ "path": "./tsconfig.node.json" }] "src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
} }

@ -4,5 +4,7 @@
"module": "esnext", "module": "esnext",
"moduleResolution": "node" "moduleResolution": "node"
}, },
"include": ["vite.config.ts"] "include": [
"vite.config.ts"
]
} }

@ -1,7 +1,11 @@
import { defineConfig } from 'vite' import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue' import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()] server: {
}) open: true,
hmr: true,
},
plugins: [vue()],
});

Loading…
Cancel
Save