This commit is contained in:
吴先生 2023-07-07 16:48:16 +08:00
parent 4a4ff0df10
commit 4b3e8e4dbe
30 changed files with 1915 additions and 548 deletions

View File

@ -14,7 +14,7 @@
"@codemirror/theme-one-dark": "^6.1.2", "@codemirror/theme-one-dark": "^6.1.2",
"@element-plus/icons": "^0.0.11", "@element-plus/icons": "^0.0.11",
"axios": "^1.4.0", "axios": "^1.4.0",
"codemirror": "^6.0.1", "codemirror-editor-vue3": "^2.3.0",
"element-plus": "^2.3.5", "element-plus": "^2.3.5",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"jsplumb": "^2.15.6", "jsplumb": "^2.15.6",
@ -23,9 +23,8 @@
"sass": "^1.62.1", "sass": "^1.62.1",
"vform3-builds": "^3.0.10", "vform3-builds": "^3.0.10",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-codemirror": "^6.1.1",
"vue-router": "4", "vue-router": "4",
"vuedraggable": "^2.24.3" "vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^4.1.0", "@vitejs/plugin-vue": "^4.1.0",

Binary file not shown.

View File

@ -1,5 +1,20 @@
<template> <template>
<router-view></router-view> <router-view></router-view>
</template> </template>
<style>
::-webkit-scrollbar {
width: 4px;
height: 4px;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background: #8f8f8f;
height: 20px;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,193 @@
<template>
<div class="codemirror">
<codemirror
ref="codemirror"
v-model:value="code"
:options="cmOption"
:autofocus="true"
@cursorActivity="onCmCursorActivity"
@ready="onCmReady"
@focus="onCmFocus"
@blur="onCmBlur"
/>
</div>
</template>
<script>
import Codemirror from "codemirror-editor-vue3";
// base style
import "codemirror/lib/codemirror.css";
// language
import "codemirror/mode/vue/vue.js";
// active-line.js
import "codemirror/addon/selection/active-line.js";
// styleSelectedText
import "codemirror/addon/selection/mark-selection.js";
import "codemirror/addon/search/searchcursor.js";
// highlightSelectionMatches
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/match-highlighter.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/sublime.js";
// foldGutter
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/xml-fold.js";
// import axios from 'axios';
export default {
props: ["initCode", "mode"],
name: "code-editor",
title: "Mode: text/x-vue & Theme: monokai",
components: {
Codemirror,
},
created() {
// self.axios = axios.create({
// baseURL: '',
// timeout: 1000,
// });
},
mounted() {
this.refreshScript();
},
computed: {
code: {
get() {
return this.codeStore;
},
set(newVal) {
this.codeStore = newVal;
},
},
},
watch: {
initCode() {
this.codeStore = this.initCode;
},
},
data() {
return {
codeStore: this.initCode,
cmOption: {
smartIndent: true, //
indentUnit: 4, // 4
matchBrackets: true, //使
autofocus: true,
showCursorWhenSelecting: true,
autoRefresh: true,
tabSize: 4,
foldGutter: true,
styleActiveLine: true,
lineNumbers: true,
line: true,
keyMap: "sublime",
mode: this.mode,
theme: "monokai",
extraKeys: {
F11(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
Esc(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
},
},
},
};
},
methods: {
refreshScript() {
let codemirror = this.$refs["codemirror"].cminstance;
setTimeout(() => {
codemirror.refresh();
}, 100);
},
onCmCursorActivity(codemirror) {
//
console.log("onCmCursorActivity", codemirror);
},
onCmReady(codemirror) {
//
console.log("onCmReady", codemirror);
},
onCmFocus(codemirror) {
//
console.log("onCmFocus", codemirror);
},
onCmBlur(codemirror) {
//
console.log("onCmBlur", codemirror);
},
getEditorCode() {
//
console.log("getEditorCode", getEditorCode);
return this.codeStore;
},
insert() {
let codemirror = this.$refs["codemirror"].cminstance;
// const editor = this.$refs["codemirror"].getCodeMirror();
// editor.setValue('1212');
// this.CodeMirrorEditor.setValue(Hello Kitty)
// this.CodeMirrorEditor.getValue()
// this.CodeMirrorEditor.getLine(n):n
// this.CodeMirrorEditor.lineCount()
// this.CodeMirrorEditor.lastLine()
// this.CodeMirrorEditor.isClean():booleanclean
// this.CodeMirrorEditor.getSelection()
// this.CodeMirrorEditor.getSelections():array
// this.CodeMirrorEditor.replaceSelection():
// this.CodeMirrorEditor.getCursor():,{line,char}
// this.CodeMirrorEditor.setOption("",""):
// this.CodeMirrorEditor.getOption(""):
// this.CodeMirrorEditor.addKeyMap("",""):key-map
// this.CodeMirrorEditor.removeKeyMap"":key-map
// this.CodeMirrorEditor.addOverlay(""):Enable a highlighting overlay
// this.CodeMirrorEditor.removeOverlay"":Overlay
// this.CodeMirrorEditor.setSize(width,height):
// this.CodeMirrorEditor.scrollTo(x,y):scrollposition
// this.CodeMirrorEditor.refresh():
// this.CodeMirrorEditor.execCommand():
console.log(codemirror.replaceSelection("1212"));
},
replaceSelection(val){
this.$refs["codemirror"].cminstance.replaceSelection(val)
}
},
};
</script>
<style>
.CodeMirror-scroll {
min-height: 200px;
}
</style>

View File

@ -0,0 +1,52 @@
<template>
<div
class="context-menu"
:style="{
top: contextMenuData.axis.y + 'px',
left: contextMenuData.axis.x + 'px',
}"
>
<div @click="clickDel">删除</div>
</div>
<a-modal v-model:visible="visible" @ok="handleOk" @cancel="handleCancel">
<template #title> 提示 </template>
<div>确定要删除节点 线索新增 ,删除后后面的节点数据将清空 ?</div>
</a-modal>
</template>
<script setup>
import { toRefs, ref } from "vue";
const emit = defineEmits(["deletedata",'cancel']);
const visible = ref(false);
const props = defineProps({
contextMenuData: {
type: Object,
default: () => {},
},
});
//使
const { contextMenuData } = toRefs(props);
const clickDel = () => {
visible.value = true;
};
const handleOk = () => {
emit("deletedata");
};
const handleCancel = () => {
emit("cancel");
};
</script>
<style lang="scss">
.context-menu {
position: fixed;
z-index: 999;
left: 0;
top: 0;
background-color: #ffffff;
padding: 8px 16px;
box-shadow: 0 0 5px 2px #efefef;
cursor: pointer;
}
</style>

View File

@ -5,7 +5,8 @@ import router from "./router";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import ElementPlus from "element-plus"; //引入element-plus库 import ElementPlus from "element-plus"; //引入element-plus库
import * as ElementPlusIconsVue from '@element-plus/icons-vue' import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import VForm3 from "vform3-builds"; //引入VForm3库 import VForm3 from "vform3-builds"; //引入VForm3库
import "element-plus/dist/index.css"; //引入element-plus样式 import "element-plus/dist/index.css"; //引入element-plus样式
@ -78,12 +79,10 @@ export const loadView = (view) => {
}; };
app.config.globalProperties.$http = http; app.config.globalProperties.$http = http;
app.config.globalProperties.$message = ElMessage;
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component) app.component(key, component);
} }
app.use(ElementPlus).use(VForm3).use(createPinia()).use(router).mount("#app"); app.use(ElementPlus).use(VForm3).use(createPinia()).use(router).mount("#app");

View File

@ -48,14 +48,14 @@ const routes = [
}, },
component: () => import("../views/codemirror/index.vue"), component: () => import("../views/codemirror/index.vue"),
}, },
// { {
// path: "/data-flow-editor", path: "/data-flow-editor",
// name: "data-flow-editor", name: "data-flow-editor",
// mete: { mete: {
// title: "数据中台", title: "数据中台",
// }, },
// component: () => import("../views/data-flow-editor/index.vue"), component: () => import("../views/data-flow-editor/index.vue"),
// }, },
]; ];
const router = createRouter({ const router = createRouter({

View File

@ -1,9 +1,11 @@
import axios from "axios"; import axios from "axios";
import tools from "@/utils/tools"; import tools from "@/utils/tools";
import { ElMessage } from "element-plus";
// axios.defaults.baseURL = '/api' // axios.defaults.baseURL = '/api'
axios.defaults.timeout = 10000; axios.defaults.timeout = 10000;
// HTTP request 拦截器 // HTTP request 拦截器
axios.interceptors.request.use( axios.interceptors.request.use(
(config) => { (config) => {
@ -26,22 +28,22 @@ axios.interceptors.response.use(
(error) => { (error) => {
if (error.response) { if (error.response) {
if (error.response.status == 401) { if (error.response.status == 401) {
this.$message.error("请重新登录!"); ElMessage.error("请重新登录!");
// router.replace({ // router.replace({
// path: '/login' // path: '/login'
// }); // });
} else if (error.response.status == 404) { } else if (error.response.status == 404) {
this.$message.error("Status:404正在请求不存在的服务器记录"); ElMessage.error("Status:404正在请求不存在的服务器记录");
} else if (error.response.status == 500) { } else if (error.response.status == 500) {
this.$message.error({ ElMessage.error({
title: "请求错误", title: "请求错误",
message: "Status:500服务器发生错误", message: "Status:500服务器发生错误",
}); });
} else { } else {
this.$message.error(`Status:${error.response.status},未知错误!`); ElMessage.error(`Status:${error.response.status},未知错误!`);
} }
} else { } else {
this.$message.error("请求服务器无响应!"); ElMessage.error("请求服务器无响应!");
} }
return Promise.reject(error.response); return Promise.reject(error.response);
} }

View File

@ -0,0 +1,105 @@
<template>
<div>
<codemirror
v-model="welcomeCode"
placeholder="Code goes here..."
:style="{ height: '400px' }"
:autofocus="true"
:indent-with-tab="true"
:tab-size="2"
:extensions="extensions"
@blur="change()"
/>
<component v-bind:is="currentTabComponent"></component>
</div>
</template>
<script setup>
import { ref } from "vue";
import { Codemirror } from "vue-codemirror";
import { javascript } from "@codemirror/lang-javascript";
import { oneDark } from "@codemirror/theme-one-dark";
import { compileFile } from "@/compiler/sfc-compiler.js";
import { babelParse } from "@vue/compiler-sfc";
import { ElMessage } from "element-plus";
import { table } from "@/compiler/testCode";
// id scopeId css scope
const id = Date.now().toString();
const scopeId = `data-v-${id}`;
const welcomeCode = ref(table);
const extensions = [javascript(), oneDark];
const change = (e) => {
console.log("change", e);
generateComponent(e);
};
const currentTabComponent = ref(eval(""));
const generateComponent = () => {
let compiled = {};
compileFile("TestCode.vue", welcomeCode.value, compiled);
if (compiled.errors.length > 0) {
ElMessage({
type: "error",
duration: 0,
showClose: true,
message: `
发生错误
${compiled.errors[0]}
`,
});
console.error(`发生错误`);
console.error(compiled.errors[0]);
throw compiled.errors[0];
} else {
var code = compiled.js;
var ast = babelParse(code, {
sourceType: "module",
});
var replaceCode = (node, subCode) =>
code.substring(0, node.start) + subCode + code.substring(node.end);
for (var i = ast.program.body.length - 1; i >= 0; i--) {
var node = ast.program.body[i];
if (node.type === "ImportDeclaration") {
code = replaceCode(
node,
node.specifiers
.map(
(it) =>
`const ${
it.local?.name || it.imported?.name || "*"
} = ___grape__import__('${node.source.value}', '${
it.imported?.name || "*"
}');`
)
.join("\r\n")
);
} else if (node.type === "ExportDefaultDeclaration") {
code = replaceCode(node, `return ${node.declaration.name}`);
}
}
code = `(function(){
${code}
})()`;
var componentStyle = document.createElement("style");
componentStyle.innerHTML = compiled.css;
document.head.appendChild(componentStyle);
currentTabComponent.value = eval(code);
// app.component(item.name, eval(code));
// console.log(code);
}
};
generateComponent()
</script>
<style>
* {
padding: 0;
margin: 0;
}
</style>

View File

@ -1,105 +1,196 @@
<template> <template>
<div> <div class="codemirror">
<codemirror <codemirror
v-model="welcomeCode" ref="codemirror"
placeholder="Code goes here..." v-model:value="code"
:style="{ height: '400px' }" :options="cmOption"
:autofocus="true" :autofocus="true"
:indent-with-tab="true" @cursorActivity="onCmCursorActivity"
:tab-size="2" @ready="onCmReady"
:extensions="extensions" @focus="onCmFocus"
@blur="change()" @blur="onCmBlur"
/> />
<component v-bind:is="currentTabComponent"></component> <component v-bind:is="currentTabComponent"></component>
</div> </div>
</template> </template>
<script setup>
import { ref } from "vue";
import { Codemirror } from "vue-codemirror";
import { javascript } from "@codemirror/lang-javascript";
import { oneDark } from "@codemirror/theme-one-dark";
import { compileFile } from "@/compiler/sfc-compiler.js";
import { babelParse } from "@vue/compiler-sfc";
import { ElMessage } from "element-plus";
import { table } from "@/compiler/testCode";
// id scopeId css scope <script>
const id = Date.now().toString(); import Codemirror from "codemirror-editor-vue3";
const scopeId = `data-v-${id}`;
const welcomeCode = ref(table); // base style
import "codemirror/lib/codemirror.css";
const extensions = [javascript(), oneDark]; // language
import "codemirror/mode/vue/vue.js";
const change = (e) => { // active-line.js
console.log("change", e); import "codemirror/addon/selection/active-line.js";
generateComponent(e);
// styleSelectedText
import "codemirror/addon/selection/mark-selection.js";
import "codemirror/addon/search/searchcursor.js";
// highlightSelectionMatches
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/match-highlighter.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/sublime.js";
// foldGutter
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/xml-fold.js";
// import axios from 'axios';
export default {
props: ["initCode", "mode"],
name: "code-editor",
title: "Mode: text/x-vue & Theme: monokai",
components: {
Codemirror,
},
created() {
// self.axios = axios.create({
// baseURL: '',
// timeout: 1000,
// });
},
mounted() {
this.refreshScript();
},
computed: {
code: {
get() {
return this.codeStore;
},
set(newVal) {
this.codeStore = newVal;
},
},
},
watch: {
initCode() {
this.codeStore = this.initCode;
},
},
data() {
return {
codeStore: this.initCode,
cmOption: {
smartIndent: true, //
indentUnit: 4, // 4
matchBrackets: true, //使
autofocus: true,
showCursorWhenSelecting: true,
autoRefresh: true,
tabSize: 4,
foldGutter: true,
styleActiveLine: true,
lineNumbers: true,
line: true,
keyMap: "sublime",
mode: this.mode,
theme: "monokai",
extraKeys: {
F11(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
Esc(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
},
},
currentTabComponent:''
},
};
},
methods: {
refreshScript() {
let codemirror = this.$refs["codemirror"].cminstance;
setTimeout(() => {
codemirror.refresh();
}, 100);
},
onCmCursorActivity(codemirror) {
//
console.log("onCmCursorActivity", codemirror);
},
onCmReady(codemirror) {
//
console.log("onCmReady", codemirror);
},
onCmFocus(codemirror) {
//
console.log("onCmFocus", codemirror);
},
onCmBlur(codemirror) {
//
console.log("onCmBlur", codemirror);
},
getEditorCode() {
//
console.log("getEditorCode", getEditorCode);
return this.codeStore;
},
insert() {
let codemirror = this.$refs["codemirror"].cminstance;
// const editor = this.$refs["codemirror"].getCodeMirror();
// editor.setValue('1212');
// this.CodeMirrorEditor.setValue(Hello Kitty)
// this.CodeMirrorEditor.getValue()
// this.CodeMirrorEditor.getLine(n):n
// this.CodeMirrorEditor.lineCount()
// this.CodeMirrorEditor.lastLine()
// this.CodeMirrorEditor.isClean():booleanclean
// this.CodeMirrorEditor.getSelection()
// this.CodeMirrorEditor.getSelections():array
// this.CodeMirrorEditor.replaceSelection():
// this.CodeMirrorEditor.getCursor():,{line,char}
// this.CodeMirrorEditor.setOption("",""):
// this.CodeMirrorEditor.getOption(""):
// this.CodeMirrorEditor.addKeyMap("",""):key-map
// this.CodeMirrorEditor.removeKeyMap"":key-map
// this.CodeMirrorEditor.addOverlay(""):Enable a highlighting overlay
// this.CodeMirrorEditor.removeOverlay"":Overlay
// this.CodeMirrorEditor.setSize(width,height):
// this.CodeMirrorEditor.scrollTo(x,y):scrollposition
// this.CodeMirrorEditor.refresh():
// this.CodeMirrorEditor.execCommand():
console.log(codemirror.replaceSelection("1212"));
},
replaceSelection(val) {
this.$refs["codemirror"].cminstance.replaceSelection(val);
},
},
}; };
const currentTabComponent = ref(eval(""));
const generateComponent = () => {
let compiled = {};
compileFile("TestCode.vue", welcomeCode.value, compiled);
if (compiled.errors.length > 0) {
ElMessage({
type: "error",
duration: 0,
showClose: true,
message: `
发生错误
${compiled.errors[0]}
`,
});
console.error(`发生错误`);
console.error(compiled.errors[0]);
throw compiled.errors[0];
} else {
var code = compiled.js;
var ast = babelParse(code, {
sourceType: "module",
});
var replaceCode = (node, subCode) =>
code.substring(0, node.start) + subCode + code.substring(node.end);
for (var i = ast.program.body.length - 1; i >= 0; i--) {
var node = ast.program.body[i];
if (node.type === "ImportDeclaration") {
code = replaceCode(
node,
node.specifiers
.map(
(it) =>
`const ${
it.local?.name || it.imported?.name || "*"
} = ___grape__import__('${node.source.value}', '${
it.imported?.name || "*"
}');`
)
.join("\r\n")
);
} else if (node.type === "ExportDefaultDeclaration") {
code = replaceCode(node, `return ${node.declaration.name}`);
}
}
code = `(function(){
${code}
})()`;
var componentStyle = document.createElement("style");
componentStyle.innerHTML = compiled.css;
document.head.appendChild(componentStyle);
currentTabComponent.value = eval(code);
// app.component(item.name, eval(code));
// console.log(code);
}
};
generateComponent()
</script> </script>
<style> <style>
* { .CodeMirror-scroll {
padding: 0; min-height: 200px;
margin: 0;
} }
</style> </style>

View File

@ -1,12 +1,12 @@
<!-- 算法公式 --> <!-- 算法公式 -->
<template> <template>
<a-tabs <el-tabs
default-active-key="1" v-model="activeName"
@change="tabsChange" @tab-click="tabsChange"
v-if="conArrData.length > 0" v-if="conArrData.length > 0"
> >
<a-tab-pane key="1" title="节点配置"> <el-tab-pane name="1" label="节点配置">
<div class="dataExtend_content"> <div class="dataExtend_content">
<div class="left"> <div class="left">
<div> <div>
@ -17,7 +17,7 @@
v-for="(item, index) in fieldList" v-for="(item, index) in fieldList"
:key="index" :key="index"
> >
<a-input <el-input
v-model="item.value" v-model="item.value"
size="small" size="small"
class="fieldList_item_input" class="fieldList_item_input"
@ -34,25 +34,23 @@
</div> </div>
</div> </div>
</div> </div>
</a-tab-pane> </el-tab-pane>
</a-tabs> </el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" /> <img src="@/assets/images/oneNode.f1997e1e.png" alt="" />
<p>请将1个节点连接至本节点</p> <p>请将1个节点连接至本节点</p>
</div> </div>
</div> </div>
<!-- 配置 --> <!-- 配置 -->
<a-modal <el-dialog
width="auto" width="800"
v-model:visible="visible" v-model="visible"
@ok="handleOk"
@cancel="handleCancel"
class="a-modal" class="a-modal"
title="函数配置"
> >
<template #title> 函数配置 </template>
<div class="deploy_content"> <div class="deploy_content">
<div style="width: 1000px"> <div style="width: 100%">
<codemirror <codemirror
v-if="codemirrorIf" v-if="codemirrorIf"
:initCode="code" :initCode="code"
@ -75,11 +73,11 @@
</div> </div>
<div class="right deploy_deploy_box"> <div class="right deploy_deploy_box">
<p class="title">函数列表</p> <p class="title">函数列表</p>
<div> <el-scrollbar height="200px">
<a-collapse :default-active-key="[0]" accordion> <el-collapse v-model="activeNames" accordion>
<a-collapse-item <el-collapse-item
:header="item.title" :title="item.title"
:key="index" :name="index"
v-for="(item, index) in mainList" v-for="(item, index) in mainList"
> >
<ul> <ul>
@ -90,13 +88,21 @@
{{ item2.label }} {{ item2.label }}
</li> </li>
</ul> </ul>
</a-collapse-item> </el-collapse-item>
</a-collapse> </el-collapse>
</div> </el-scrollbar>
</div> </div>
</div> </div>
</div> </div>
</a-modal> <template #footer>
<span class="dialog-footer">
<el-button @click="handleCancel()">取消</el-button>
<el-button type="primary" @click="handleOk()">
确定
</el-button>
</span>
</template>
</el-dialog>
</template> </template>
<script setup> <script setup>
@ -119,6 +125,9 @@ const props = defineProps({
}, },
}); });
const activeName = ref("1");
const activeNames = ref(["1"]);
const mainList = [ const mainList = [
{ {
title: "基础函数 - 数学函数", title: "基础函数 - 数学函数",
@ -284,8 +293,11 @@ const deploy = () => {
codemirrorIf.value = true; codemirrorIf.value = true;
}); });
}; };
const handleOk = () => {}; const handleOk = () => {
const handleCancel = () => {}; visible.value = false
};
const handleCancel = () => {
visible.value = false};
const code = ref(""); const code = ref("");
@ -317,7 +329,7 @@ disposeLineList();
const codemirrorRef = ref(null); const codemirrorRef = ref(null);
const clickDeploy = (value) => { const clickDeploy = (value) => {
codemirrorRef.value.replaceSelection(value) codemirrorRef.value.replaceSelection(value);
}; };
</script> </script>
@ -336,10 +348,12 @@ const clickDeploy = (value) => {
margin: 0px 6px 8px; margin: 0px 6px 8px;
} }
.fieldList { .fieldList {
padding-left: 5px;
.fieldList_item { .fieldList_item {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 10px; margin-bottom: 10px;
font-size: 0;
.fieldList_item_input { .fieldList_item_input {
width: 165px; width: 165px;
background-color: #fff; background-color: #fff;
@ -348,6 +362,7 @@ const clickDeploy = (value) => {
} }
span { span {
margin-left: 5px; margin-left: 5px;
font-size: 12px;
cursor: pointer; cursor: pointer;
} }
} }
@ -385,7 +400,7 @@ const clickDeploy = (value) => {
ul { ul {
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
padding: 0; padding: 0 15px;
li { li {
padding: 3px 0; padding: 3px 0;
cursor: pointer; cursor: pointer;
@ -407,11 +422,17 @@ const clickDeploy = (value) => {
} }
} }
} }
.a-modal .arco-modal-body {
box-sizing: border-box;
}
.cm-component { .cm-component {
box-sizing: border-box; box-sizing: border-box;
} }
</style> </style>
<style lang="scss">
.deploy_deploy_box {
.el-collapse-item__header {
padding: 0 15px;
}
}
</style>

View File

@ -1,12 +1,12 @@
<!-- 字段设置 --> <!-- 字段设置 -->
<template> <template>
<a-tabs <el-tabs
default-active-key="1" v-model="activeName"
@change="tabsChange" @tab-chang="tabsChange"
v-if="conArrData.length > 0" v-if="conArrData.length > 0"
> >
<a-tab-pane key="1" title="字段配置"> <el-tab-pane name="1" label="字段配置">
<draggable <draggable
v-model="data.fieldSettingList" v-model="data.fieldSettingList"
class="fun-classify" class="fun-classify"
@ -19,7 +19,7 @@
<div class="field-item-head"> <div class="field-item-head">
<span>{{ element.name }}</span> <span>{{ element.name }}</span>
<div class="head-action" @click="clickSet(element)"> <div class="head-action" @click="clickSet(element)">
<icon-settings /> <el-icon><Setting /></el-icon>
</div> </div>
</div> </div>
<div class="field-item-cell"> <div class="field-item-cell">
@ -33,8 +33,8 @@
</div> </div>
</template> </template>
</draggable> </draggable>
</a-tab-pane> </el-tab-pane>
</a-tabs> </el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" /> <img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" />
@ -42,78 +42,93 @@
</div> </div>
</div> </div>
<a-modal <el-dialog
width="auto" width="800"
v-model:visible="visible" v-model="visible"
@ok="handleOk" @ok="handleOk"
@cancel="handleCancel" @cancel="handleCancel"
> >
<template #title> 字段设置 </template> <template #title> 字段设置 </template>
<a-form :model="form" :style="{ width: '500px' }" label-align="left"> <el-form
<a-form-item field="name" label="字段名:">
<a-input v-model="form.name" placeholder="请输入字段名" />
</a-form-item>
<a-form-item field="type" label="类型:">
<a-select placeholder="请选择数据类型">
<a-option>字符串</a-option>
</a-select>
</a-form-item>
<a-form-item field="type" label="值替换:">
<a-button type="outline" @click="addList">新增替换</a-button>
</a-form-item>
</a-form>
<a-form
:model="form" :model="form"
:style="{ width: '500px' }" :style="{ width: '500px' }"
label-align="left" label-align="left"
label-width="100"
>
<el-form-item field="name" label="字段名:">
<el-input v-model="form.name" placeholder="请输入字段名" />
</el-form-item>
<el-form-item field="type" label="类型:">
<el-select placeholder="请选择数据类型">
<el-option value="string" label="字符串" />
</el-select>
</el-form-item>
<el-form-item field="type" label="值替换:">
<el-button type="outline" @click="addList">新增替换</el-button>
</el-form-item>
</el-form>
<el-form
:model="form"
:style="{ width: '100%' }"
label-align="left"
label-width="80"
layout="vertical" layout="vertical"
> >
<a-row <el-row
class="replace-item" class="replace-item"
:gutter="12" :gutter="12"
v-for="(item, index) in form.list" v-for="(item, index) in form.list"
:key="index" :key="index"
> >
<a-col :span="7"> <el-col :span="6">
<a-form-item label="替换类型:"> <el-form-item label="替换类型:">
<a-select placeholder="未选择" v-model="item.type"> <el-select placeholder="未选择" v-model="item.type">
<a-option value="null">空值</a-option> <el-option value="null" label="空值" :key="item.value" />
<a-option value="custom">自定义值</a-option> <el-option value="custom" label="自定义值" />
</a-select> </el-select>
</a-form-item> </el-form-item>
</a-col> </el-col>
<a-col :span="7" v-if="item.type == 'custom'"> <el-col :span="6" v-if="item.type == 'custom'">
<a-form-item field="name" label="原来值:"> <el-form-item field="name" label="原来值:">
<a-input <el-input
placeholder="请输入原来的值" placeholder="请输入原来的值"
allow-clear allow-clear
v-model="item.oldVal" v-model="item.oldVal"
/> />
</a-form-item> </el-form-item>
</a-col> </el-col>
<a-col :span="7" v-if="item.type == 'custom' || item.type == 'null'"> <el-col :span="6" v-if="item.type == 'custom' || item.type == 'null'">
<a-form-item field="name" label="替换值:"> <el-form-item field="name" label="替换值:">
<a-input <el-input
placeholder="请输入替换值" placeholder="请输入替换值"
allow-clear allow-clear
v-model="item.newVal" v-model="item.newVal"
/> />
</a-form-item> </el-form-item>
</a-col> </el-col>
<a-col :span="3"> <el-col :span="3">
<a-form-item> <div class="del" @click="clickDel(index)">
<div class="del" @click="clickDel(index)"><icon-delete /></div> <el-icon>
</a-form-item> <Delete />
</a-col> </el-icon>
</a-row> </div>
</a-form> </el-col>
</a-modal> </el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleOk"> 确定 </el-button>
</span>
</template>
</el-dialog>
</template> </template>
<script setup> <script setup>
import { ref, reactive, nextTick, toRefs } from "vue"; import { ref, reactive, nextTick, toRefs } from "vue";
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import { IconSettings, IconDelete } from "@arco-design/web-vue/es/icon"; import http from "@/utils/request";
import http from "@/scripts/request";
const activeName = ref("1");
const data = reactive({ const data = reactive({
fieldSettingList: [], fieldSettingList: [],
@ -232,8 +247,13 @@ const handleOk = () => {
}); });
console.log("dataList", dataList); console.log("dataList", dataList);
nodeValue.value.data = JSON.stringify(dataList); nodeValue.value.data = JSON.stringify(dataList);
visible.value = false;
};
const handleCancel = () => {
visible.value = false;
}; };
const handleCancel = () => {};
// //
const addList = () => { const addList = () => {
@ -340,9 +360,10 @@ const clickDel = (index) => {
} }
.replace-item { .replace-item {
position: relative; position: relative;
.del { }
cursor: pointer; .del {
margin-top: 26px; cursor: pointer;
} margin-top: 8px;
margin-left: 15px;
} }
</style> </style>

View File

@ -1,43 +1,40 @@
<!-- 数据筛选 --> <!-- 数据筛选 -->
<template> <template>
<a-tabs <el-tabs @tab-chang="tabsChange" v-if="conArrData.length > 0">
default-active-key="1" <el-tab-pane label="节点配置">
@change="tabsChange"
v-if="conArrData.length > 0"
>
<a-tab-pane key="1" title="节点配置">
<div class="data-filter-box"> <div class="data-filter-box">
<div> <div>
<span>筛选出符合以下</span> <span>筛选出符合以下</span>
<a-select <el-select
:style="{ width: '80px', margin: '0 10px' }" :style="{ width: '80px', margin: '0 10px' }"
placeholder="Select" placeholder="Select"
:trigger-props="{ autoFitPopupMinWidth: true }" :trigger-props="{ autoFitPopupMinWidth: true }"
v-model="data.type" v-model="data.type"
> >
<a-option value="and">所有</a-option> <el-option value="and" label="所有" />
<a-option value="or">任一</a-option> <el-option value="or" label="任一" />
</a-select> </el-select>
<span>条件的数据</span> <span>条件的数据</span>
</div> </div>
<div class="data-filter-add"> <div class="data-filter-add">
<a-dropdown @select="handleSelect" position="bl"> <el-dropdown @command="handleSelect">
<a-button type="primary" size="small"> <el-button type="primary">
<template #icon> 添加过滤条件<el-icon class="el-icon--right"
<icon-plus /> ><arrow-down
</template> /></el-icon>
<template #default>添加过滤条件</template> </el-button>
</a-button> <template #dropdown>
<template #content> <el-dropdown-menu>
<a-doption <el-dropdown-item
v-for="item in columnList" v-for="item in columnList"
:key="item.id" :key="item.id"
:value="item.keyword" :command="item.keyword"
>{{ item.name }}</a-doption >{{ item.name }}</el-dropdown-item
> >
</el-dropdown-menu>
</template> </template>
</a-dropdown> </el-dropdown>
</div> </div>
<div class="filter-add-list"> <div class="filter-add-list">
<div <div
@ -45,14 +42,14 @@
v-for="(item, index) in data.conditionList" v-for="(item, index) in data.conditionList"
:key="index" :key="index"
> >
<a-input <el-input
class="item" class="item"
:style="{ width: '200px' }" :style="{ width: '200px' }"
v-model="item.columnText" v-model="item.columnText"
placeholder="Please enter something" placeholder="Please enter something"
readonly readonly
/> />
<a-select <el-select
class="item" class="item"
v-model="item.condition" v-model="item.condition"
:style="{ width: '150px', marginRight: '15px' }" :style="{ width: '150px', marginRight: '15px' }"
@ -60,11 +57,11 @@
:trigger-props="{ autoFitPopupMinWidth: true }" :trigger-props="{ autoFitPopupMinWidth: true }"
@change="update" @change="update"
> >
<a-option value="eq">等于</a-option> <el-option value="eq" label="等于" />
<a-option value="ne">不等于</a-option> <el-option value="ne" label="不等于" />
</a-select> </el-select>
<div> <div>
<a-input <el-input
class="item" class="item"
:style="{ width: '200px' }" :style="{ width: '200px' }"
v-model="item.val" v-model="item.val"
@ -72,46 +69,15 @@
allow-clear allow-clear
@blur="update" @blur="update"
/> />
<!-- <a-tag
v-for="(tag, index) of tags"
:key="tag"
:closable="index !== 0"
@close="handleRemove(tag)"
>
{{ tag }}
</a-tag>
<a-input
v-if="showInput"
ref="inputRef"
:style="{ width: '90px' }"
size="mini"
v-model.trim="inputVal"
@keyup.enter="handleAdd"
@blur="handleAdd"
/>
<a-tag
v-else
:style="{
width: '90px',
backgroundColor: 'var(--color-fill-2)',
border: '1px dashed var(--color-fill-3)',
cursor: 'pointer',
}"
@click="handleEdit"
>
<template #icon>
<icon-plus />
</template>
添加
</a-tag> -->
</div> </div>
<div class="del" @click="clickDel(index)"><icon-delete /></div> <div class="del" @click="clickDel(index)">
<el-icon><Delete /></el-icon>
</div>
</div> </div>
</div> </div>
</div> </div>
</a-tab-pane> </el-tab-pane>
</a-tabs> </el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" /> <img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" />
@ -121,7 +87,6 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, nextTick, toRefs } from "vue"; import { ref, reactive, nextTick, toRefs } from "vue";
import { IconPlus, IconDelete } from "@arco-design/web-vue/es/icon";
const data = reactive({ const data = reactive({
type: "and", type: "and",
@ -168,9 +133,9 @@ const disposeLineList = () => {
columnList.value = JSON.parse(JSON.stringify(conArrItem.columnList)); columnList.value = JSON.parse(JSON.stringify(conArrItem.columnList));
columnList.value.map(item=>{ columnList.value.map((item) => {
item.nodeId = nodeValue.value.id item.nodeId = nodeValue.value.id;
}) });
nodeValue.value.columnList = JSON.parse( nodeValue.value.columnList = JSON.parse(
JSON.stringify(columnList.value) JSON.stringify(columnList.value)
@ -227,6 +192,7 @@ const handleRemove = (key) => {
// end tab // end tab
const handleSelect = (val) => { const handleSelect = (val) => {
console.log(val);
columnList.value.map((item) => { columnList.value.map((item) => {
if (item.keyword == val) { if (item.keyword == val) {
data.conditionList.push({ data.conditionList.push({
@ -249,16 +215,15 @@ const update = () => {
nodeValue.value.data = JSON.stringify(nodeValueDate); nodeValue.value.data = JSON.stringify(nodeValueDate);
}; };
const clickDel = (index) => {
const clickDel = (index)=>{ data.conditionList.splice(index, 1);
data.conditionList.splice(index,1) };
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.data-filter-box { .data-filter-box {
padding: 0 16px; padding: 0 16px;
font-size: 14px;
.data-filter-add { .data-filter-add {
margin: 6px 0; margin: 6px 0;
} }

View File

@ -1,35 +1,38 @@
<template> <template>
<a-tabs <el-tabs
default-active-key="1" v-model="activeName"
@change="tabsChange" @tab-change="tabsChange"
v-if="conArrData.length > 0" v-if="conArrData.length > 0"
> >
<a-tab-pane key="1" title="节点配置"> <el-tab-pane name="1" label="节点配置">
<div class="grouping-content"> <div class="grouping-content">
<div class="grouping-content-left"> <div class="grouping-content-left">
<div class="group-title"><span class="label">分组字段</span></div> <div class="group-title"><span class="label">分组字段</span></div>
<a-dropdown @select="handleSelect" position="bl"> <el-dropdown @command="handleSelect" position="bl">
<a-button type="primary" size="small"> <el-button type="primary">
<template #icon> 添加分组字段<el-icon class="el-icon--right"
<icon-plus /> ><arrow-down
</template> /></el-icon>
<template #default>添加分组字段</template> </el-button>
</a-button> <template #dropdown>
<template #content> <el-dropdown-menu>
<a-doption <el-dropdown-item
v-for="item in columnList" v-for="item in columnList"
:key="item.id" :key="item.id"
:value="item.keyword" :command="item.keyword"
>{{ item.name }}</a-doption >{{ item.name }}</el-dropdown-item
> >
</el-dropdown-menu>
</template> </template>
</a-dropdown> </el-dropdown>
<div class="grouping-list"> <div class="grouping-list">
<div class="grouping-list-item" v-for="item in leftGroupingList"> <div class="grouping-list-item" v-for="item in leftGroupingList">
<span class="name">{{ item.name }}</span> <span class="name">{{ item.name }}</span>
<div class="del" @click="clickLeftDel(index)"> <div class="del" @click="clickLeftDel(index)">
<icon-delete /> <el-icon>
<Delete />
</el-icon>
</div> </div>
</div> </div>
</div> </div>
@ -39,57 +42,67 @@
<span class="label">汇总字段</span> <span class="label">汇总字段</span>
<div> <div>
<span>是否保留原字段</span> <span>是否保留原字段</span>
<a-switch v-model="nodeValueData.isRetain" @change="initData"> <el-switch
<template #checked> </template> v-model="nodeValueData.isRetain"
<template #unchecked> </template> @change="initData"
</a-switch> active-text="是"
inactive-text="否"
/>
</div> </div>
</div> </div>
<a-dropdown @select="addSummary" position="bl">
<a-button type="primary" size="small">
<template #icon> <el-dropdown @command="addSummary" position="bl">
<icon-plus /> <el-button type="primary">
</template> 添加汇总字段<el-icon class="el-icon--right"
<template #default>添加汇总字段</template> ><arrow-down
</a-button> /></el-icon>
<template #content> </el-button>
<a-doption <template #dropdown>
v-for="item in columnList" <el-dropdown-menu>
:key="item.id" <el-dropdown-item
:value="item.keyword" v-for="item in columnList"
>{{ item.name }}</a-doption :key="item.id"
> :command="item.keyword"
>{{ item.name }}</el-dropdown-item
>
</el-dropdown-menu>
</template> </template>
</a-dropdown> </el-dropdown>
<div class="grouping-list"> <div class="grouping-list">
<div class="grouping-list-item" v-for="item in rightGroupingList"> <div class="grouping-list-item" v-for="item in rightGroupingList">
<span class="name">{{ item.name }}</span> <span class="name">{{ item.name }}</span>
<a-select <el-select
:style="{ width: '160px' }" :style="{ width: '160px' }"
v-model="item.type" v-model="item.type"
placeholder="请选择汇总方式" placeholder="请选择汇总方式"
@change="initData()" @change="initData()"
> >
<a-option value="count">总数</a-option> <el-option value="count" label="总数" />
</a-select> </el-select>
<div class="del" @click="clickRightDel(index)"> <div class="del" @click="clickRightDel(index)">
<icon-delete /> <el-icon><Delete /></el-icon>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</a-tab-pane> </el-tab-pane>
<a-tab-pane key="2" title="查看数据"> <el-tab-pane name="2" label="查看数据">
<a-table
:columns="dataColumnList"
:data="columnListData" <el-table :data="columnListData" stripe style="width: 100%" height="345" empty-text="暂无数据">
:pagination="false" <el-table-column
size="small" :prop="item.dataIndex"
/> :label="item.title"
</a-tab-pane> v-for="(item, index) in dataColumnList"
</a-tabs> :key="index"
/>
</el-table>
</el-tab-pane>
</el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" /> <img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" />
@ -98,11 +111,10 @@
</div> </div>
</template> </template>
<script setup > <script setup>
import http from "@/scripts/request"; import http from "@/utils/request";
import { ref, reactive, nextTick, toRefs } from "vue"; import { ref, reactive, nextTick, toRefs } from "vue";
import { IconPlus, IconDelete } from "@arco-design/web-vue/es/icon"; const activeName = ref("1");
const columnList = ref([]); const columnList = ref([]);
const leftGroupingList = ref([]); //left const leftGroupingList = ref([]); //left
@ -218,6 +230,7 @@ const tabsChange = (key) => {
// left // left
const handleSelect = (keyword) => { const handleSelect = (keyword) => {
console.log(keyword);
columnList.value.map((item) => { columnList.value.map((item) => {
if (item.keyword == keyword) { if (item.keyword == keyword) {
leftGroupingList.value.push(item); leftGroupingList.value.push(item);
@ -262,13 +275,12 @@ const initData = () => {
}); });
}); });
nodeValue.value.data = JSON.stringify(nodeValueData.value); nodeValue.value.data = JSON.stringify(nodeValueData.value);
}; };
// //
const dataColumnList = ref([]) const dataColumnList = ref([]);
const columnListData = ref([]) const columnListData = ref([]);
const getDataStream = () => { const getDataStream = () => {
http http
.post("/api/metadata/data_stream/exec", { .post("/api/metadata/data_stream/exec", {

View File

@ -1,58 +1,62 @@
<!-- 数据连接 --> <!-- 数据连接 -->
<template> <template>
<a-tabs default-active-key="1" @change="tabsChange" v-if="passIf"> <el-tabs v-model="activeName" @tab-chang="tabsChange" v-if="passIf">
<a-tab-pane key="1" :title="nodeValue.name"> <el-tab-pane name="1" :label="nodeValue.name">
<div id="join_content"> <div id="join_content">
<div class="left"> <div class="left">
<h4>1.设置连接方式</h4> <h4>1.设置连接方式</h4>
<a-radio-group v-model="data.joinType" :options="options" /> <el-radio-group v-model="data.joinType">
<el-radio :label="item.value" v-for="(item,index) in options" :key="index">{{item.label}}</el-radio>
</el-radio-group>
</div> </div>
<div class="right"> <div class="right">
<h4>2.添加连接方式</h4> <h4>2.添加连接方式</h4>
<div class="content"> <div class="content">
<div> <div>
<h5>左侧表单</h5> <h5>左侧表单</h5>
<a-select <el-select
v-model="data.leftColumnName" v-model="data.leftColumnName"
:style="{ width: '220px' }" :style="{ width: '220px' }"
placeholder="请选择左侧表单字段" placeholder="请选择左侧表单字段"
@change="setData" @change="setData"
> >
<a-option <el-option
v-for="item in conArrData[0].columnList" v-for="item in conArrData[0].columnList"
:label="item.name"
:value="item.keyword" :value="item.keyword"
>{{ item.name }}</a-option />
> </el-select>
</a-select>
</div> </div>
<div> <div>
<h5>右侧表单</h5> <h5>右侧表单</h5>
<a-select <el-select
v-model="data.rightColumnName" v-model="data.rightColumnName"
:style="{ width: '220px' }" :style="{ width: '220px' }"
placeholder="请选择右侧表单字段" placeholder="请选择右侧表单字段"
@change="setData" @change="setData"
> >
<a-option <el-option
v-for="item in conArrData[1].columnList" v-for="item in conArrData[1].columnList"
:label="item.name"
:value="item.keyword" :value="item.keyword"
>{{ item.name }}</a-option />
> </el-select>
</a-select>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</a-tab-pane> </el-tab-pane>
<a-tab-pane key="2" title="查看数据"> <el-tab-pane name="2" label="查看数据">
<a-table <el-table :data="columnListData" stripe style="width: 100%" height="345" empty-text="暂无数据">
:columns="columnList" <el-table-column
:data="columnListData" :prop="item.dataIndex"
:pagination="false" :label="item.title"
size="small" v-for="(item, index) in columnList"
/> :key="index"
</a-tab-pane> />
</a-tabs> </el-table>
</el-tab-pane>
</el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img <img
@ -64,8 +68,9 @@
</template> </template>
<script setup> <script setup>
import http from "@/scripts/request"; import http from "@/utils/request";
import { reactive, toRefs, watch, ref } from "vue"; import { reactive, toRefs, watch, ref } from "vue";
const activeName = ref("1");
const data = ref({ const data = ref({
joinType: "inner", joinType: "inner",
rightNodeId: "", rightNodeId: "",
@ -208,6 +213,15 @@ const tabsChange = (key) => {
flex: 1; flex: 1;
display: flex; display: flex;
padding: 0px 16px; padding: 0px 16px;
font-size: 14px;
h4 {
font-size: 14px;
margin-bottom: 20px;
}
h5 {
font-size: 14px;
margin-bottom: 15px;
}
.left { .left {
flex: 0 0 300px; flex: 0 0 300px;
} }
@ -215,6 +229,7 @@ const tabsChange = (key) => {
flex: auto; flex: auto;
.content { .content {
display: flex; display: flex;
& > div { & > div {
flex: 1; flex: 1;
margin-left: 16px; margin-left: 16px;

View File

@ -1,11 +1,14 @@
<template> <template>
<div id="output" v-if="LinkedDataIf"> <div id="output" v-if="LinkedDataIf">
<a-table
:columns="columnList" <el-table :data="columnListData" stripe style="width: 100%" height="400" empty-text="暂无数据">
:data="columnListData" <el-table-column
:pagination="false" :prop="item.dataIndex"
size="small" :label="item.title"
/> v-for="(item, index) in columnList"
:key="index"
/>
</el-table>
</div> </div>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
@ -17,7 +20,7 @@
<script setup> <script setup>
import { ref, toRefs } from "vue"; import { ref, toRefs } from "vue";
import http from "@/scripts/request"; import http from "@/utils/request";
const props = defineProps({ const props = defineProps({
nodeValue: { nodeValue: {
type: Object, type: Object,

View File

@ -22,12 +22,14 @@
</ul> </ul>
</div> </div>
<div class="disposition_right"> <div class="disposition_right">
<a-table <el-table :data="columnListData" stripe style="width: 100%" height="360" empty-text="暂无数据">
:columns="columnList" <el-table-column
:data="columnListData" :prop="item.dataIndex"
:pagination="false" :label="item.title"
size="small" v-for="(item, index) in columnList"
/> :key="index"
/>
</el-table>
</div> </div>
</div> </div>
</template> </template>
@ -64,6 +66,7 @@ const clickChange = () => {
flex: 0 0 300px; flex: 0 0 300px;
padding: 16px; padding: 16px;
box-sizing: border-box; box-sizing: border-box;
border-right: 1px solid #e9e9e9;
.title { .title {
margin-bottom: 10px; margin-bottom: 10px;
display: flex; display: flex;
@ -77,6 +80,7 @@ const clickChange = () => {
span { span {
color: #0db3a6; color: #0db3a6;
cursor: pointer; cursor: pointer;
font-size: 14px;
} }
} }
ul { ul {

View File

@ -1,50 +1,64 @@
<template> <template>
<a-tabs <el-tabs
default-active-key="1" v-model="activeName"
@change="tabsChange" @tab-change="tabsChange"
v-if="conArrData.length == 0" v-if="conArrData.length == 0"
> >
<a-tab-pane key="1" title="节点配置"> <el-tab-pane name="1" label="节点配置">
<div class="grouping-content"> <div class="grouping-content">
<div class="grouping-content-left"> <div class="grouping-content-left">
<div class="group-title"><span class="label">结构解析字段</span></div> <div class="group-title"><span class="label">结构解析字段</span></div>
<a-dropdown @select="handleSelect" position="bl">
<a-button type="primary" size="small">
<template #icon> <el-dropdown @command="handleSelect" position="bl">
<icon-plus /> <el-button type="primary">
</template> 添加结构解析字段<el-icon class="el-icon--right"
<template #default>添加结构解析字段</template> ><arrow-down
</a-button> /></el-icon>
<template #content> </el-button>
<a-doption <template #dropdown>
v-for="item in columnList" <el-dropdown-menu>
:key="item.id" <el-dropdown-item
:value="item.keyword" v-for="item in columnList"
>{{ item.name }}</a-doption :key="item.id"
> :command="item.keyword"
>{{ item.name }}</el-dropdown-item
>
</el-dropdown-menu>
</template> </template>
</a-dropdown> </el-dropdown>
<div class="grouping-list"> <div class="grouping-list">
<div class="grouping-list-item" v-for="item in leftGroupingList"> <div class="grouping-list-item" v-for="item in leftGroupingList">
<span class="name">{{ item.name }}</span> <span class="name">{{ item.name }}</span>
<div class="del" @click="clickLeftDel(index)"> <div class="del" @click="clickLeftDel(index)">
<icon-delete /> <el-icon>
<Delete />
</el-icon>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</a-tab-pane> </el-tab-pane>
<a-tab-pane key="2" title="查看数据"> <el-tab-pane name="2" label="查看数据">
<a-table <el-table
:columns="dataColumnList"
:data="columnListData" :data="columnListData"
:pagination="false" stripe
size="small" style="width: 100%"
/> height="360"
</a-tab-pane> empty-text="暂无数据"
</a-tabs> >
<el-table-column
:prop="item.dataIndex"
:label="item.title"
v-for="(item, index) in dataColumnList"
:key="index"
/>
</el-table>
</el-tab-pane>
</el-tabs>
<div v-else class="dissatisfy"> <div v-else class="dissatisfy">
<div class="dissatisfy_box"> <div class="dissatisfy_box">
<img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" /> <img src="@/assets/imgs/oneNode.f1997e1e.png" alt="" />
@ -54,10 +68,10 @@
</template> </template>
<script setup> <script setup>
import http from "@/scripts/request"; import http from "@/utils/request";
import { ref, reactive, nextTick, toRefs } from "vue"; import { ref, reactive, nextTick, toRefs } from "vue";
import { IconPlus, IconDelete } from "@arco-design/web-vue/es/icon";
const activeName = ref("1");
const columnList = ref([]); const columnList = ref([]);
const leftGroupingList = ref([]); //left const leftGroupingList = ref([]); //left
@ -123,7 +137,6 @@ const disposeLineList = () => {
} }
}); });
}); });
} else { } else {
console.log("不存在"); console.log("不存在");
nodeValueData.value = { nodeValueData.value = {
@ -179,14 +192,13 @@ const initData = () => {
nodeValueData.value.groupColumnNameList.push(item.keyword); nodeValueData.value.groupColumnNameList.push(item.keyword);
}); });
nodeValue.value.data = JSON.stringify(nodeValueData.value); nodeValue.value.data = JSON.stringify(nodeValueData.value);
console.log(nodeValue.value); console.log(nodeValue.value);
}; };
// //
const dataColumnList = ref([]) const dataColumnList = ref([]);
const columnListData = ref([]) const columnListData = ref([]);
const getDataStream = () => { const getDataStream = () => {
http http
.post("/api/metadata/data_stream/exec", { .post("/api/metadata/data_stream/exec", {

View File

@ -71,15 +71,26 @@
</div> </div>
</div> </div>
<a-modal
width="auto"
v-model:visible="data.visible" <el-dialog
@ok="handleOk" v-model="data.visible"
@cancel="handleCancel" title="选择数据库"
width="60%"
:before-close="handleCancel"
> >
<template #title> 选择数据库 </template>
<usedatabase ref="usedatabaseRef"></usedatabase> <usedatabase ref="usedatabaseRef"></usedatabase>
</a-modal>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleCancel">确定</el-button>
<el-button type="primary" @click="handleCancel">
取消
</el-button>
</span>
</template>
</el-dialog>
<div id="disposition" v-if="dispositionIf"> <div id="disposition" v-if="dispositionIf">
<configureSource <configureSource
@ -109,23 +120,17 @@
</template> </template>
<script setup> <script setup>
// import configureSource from "./components/source.vue"; import configureSource from "./components/source.vue";
// import output from "./components/output.vue"; import output from "./components/output.vue";
// import join from "./components/join.vue"; import join from "./components/join.vue";
// import dataExtend from "./components/dataExtend.vue"; import dataExtend from "./components/dataExtend.vue"; //
// import fieldSetting from "./components/fieldSetting.vue"; import fieldSetting from "./components/fieldSetting.vue"; //
// import filter from "./components/filter.vue"; import filter from "./components/filter.vue";
// import group from "./components/group.vue"; import group from "./components/group.vue";
// import structure from "./components/structure.vue"; import structure from "./components/structure.vue";
// import usedatabase from "./usedatabase.vue"; import usedatabase from "./usedatabase.vue";
import http from '@/utils/request.js' import http from "@/utils/request.js";
import { import { reactive, nextTick, ref, getCurrentInstance, markRaw } from "vue";
reactive,
nextTick,
ref,
getCurrentInstance,
markRaw,
} from "vue";
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import { jsPlumb } from "jsplumb"; import { jsPlumb } from "jsplumb";
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@ -218,7 +223,7 @@ const data = reactive({
], ],
nodeValue: {}, // nodeValue: {}, //
lineList: [], //线 lineList: [], //线
visible: false, visible: true,
}); });
const conArr = ref([]); const conArr = ref([]);
const plumbIns = ref(null); const plumbIns = ref(null);
@ -960,11 +965,13 @@ const cancel = () => {
.data-design-right { .data-design-right {
width: calc(100vw - 150px); width: calc(100vw - 150px);
height: calc(100vh - 45px); height: calc(100vh - 45px);
background: #f0f3fa;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACFJREFUeNpiZGBg4GegAsBlCD8TqSYNQg2Mo6FEBAAIMACdPABtrSW/IQAAAABJRU5ErkJggg=="); background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACFJREFUeNpiZGBg4GegAsBlCD8TqSYNQg2Mo6FEBAAIMACdPABtrSW/IQAAAABJRU5ErkJggg==");
background-repeat: repeat; background-repeat: repeat;
background-attachment: fixed; background-attachment: fixed;
background-color: #f0f3fa;
overflow: auto; overflow: auto;
position: relative;
z-index: 1;
&.on { &.on {
height: calc(100vh - 445px); height: calc(100vh - 445px);
} }
@ -984,6 +991,7 @@ const cancel = () => {
border: 1px solid #acafb3; border: 1px solid #acafb3;
border-radius: 4px; border-radius: 4px;
background-color: #fff; background-color: #fff;
font-size: 14px;
cursor: pointer; cursor: pointer;
&.on, &.on,
&:hover { &:hover {
@ -1038,5 +1046,11 @@ const cancel = () => {
bottom: 0; bottom: 0;
left: 150px; left: 150px;
right: 0; right: 0;
z-index: 100;
}
</style>
<style>
.el-tabs__nav-scroll {
padding: 0 15px;
} }
</style> </style>

View File

@ -1,30 +1,36 @@
<template> <template>
<div class="usedatabase"> <div class="usedatabase">
<div class="usedatabase_left"> <div class="usedatabase_left">
<a-tree :data="treeData" :load-more="loadMore" @select="select" /> <el-tree
:data="treeData"
:props="props"
:load="loadMore"
lazy
@node-click="select"
/>
</div> </div>
<div class="usedatabase_right"> <div class="usedatabase_right" v-loading="loading">
<div v-if="fieldList.length != 0"> <div v-if="fieldList.length != 0">
<div> <div>
<a-checkbox <el-checkbox
:model-value="checkedAll" v-model="checkedAll"
:indeterminate="indeterminate" :indeterminate="indeterminate"
@change="handleChangeAll" @change="handleChangeAll"
>全选 >全选</el-checkbox
</a-checkbox> >
</div> </div>
<a-checkbox-group <el-checkbox-group v-model="data" @change="handleChange" style="display: flex;
v-model="data" flex-direction: column;">
@change="handleChange" <el-checkbox
direction="vertical" v-for="city in fieldList"
> :key="city.id"
<a-checkbox :value="item.id" v-for="item in fieldList">{{ :label="city.id"
item.name >{{ city.name }}</el-checkbox
}}</a-checkbox> >
</a-checkbox-group> </el-checkbox-group>
</div> </div>
<div v-else class="empty"> <div v-else class="empty">
<a-empty /> <el-empty description="暂无数据" />
</div> </div>
</div> </div>
</div> </div>
@ -32,34 +38,43 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import http from "@/scripts/request"; import http from "@/utils/request";
import { del } from "vue-demi"; import { del } from "vue-demi";
const fieldList = ref([]); const fieldList = ref([]);
const treeData = ref([]); const treeData = ref([]);
const loading = ref(false);
const props = {
label: "label",
children: "children",
isLeaf: "leaf",
};
const metadataId = ref(""); //id const metadataId = ref(""); //id
const metadataName = ref(""); //id const metadataName = ref(""); //id
// //
const getProject = () => { const getProject = (resolve) => {
http.get("/api/metadata/project").then((resp) => { http.get("/api/metadata/project").then((resp) => {
let arr = []; let arr = [];
resp.data.records.map((item) => { resp.data.records.map((item) => {
arr.push({ arr.push({
title: item.name, label: item.name,
key: item.id,
children: [], children: [],
isLeaf: false, key: item.id,
leaf: false,
}); });
}); });
// treeData.value = arr;
treeData.value = arr; resolve(arr);
}); });
}; };
// //
const getMetadata = (id) => { const getMetadata = (id) => {
loading.value = true;
http http
.get("/api/metadata/metadataColumn", { .get("/api/metadata/metadataColumn", {
metadataId: id, metadataId: id,
@ -73,42 +88,50 @@ const getMetadata = (id) => {
resp.data.records.map((item) => { resp.data.records.map((item) => {
data.value.push(item.id); data.value.push(item.id);
}); });
loading.value = false;
}); });
}; };
onMounted(() => { onMounted(() => {
getProject(); // getProject();
}); });
const select = (arr, nodeData) => { const select = (arr, nodeData) => {
if (nodeData.node.isLeaf) { console.log(nodeData.isLeaf);
console.log(nodeData.node);
metadataName.value = nodeData.node.title; if (nodeData.isLeaf) {
metadataId.value = nodeData.node.key; console.log(nodeData);
getMetadata(nodeData.node.key); metadataName.value = nodeData.data.label;
metadataId.value = nodeData.data.key;
getMetadata(nodeData.data.key);
} }
}; };
const loadMore = (nodeData) => { const loadMore = (nodeData, resolve) => {
console.log(nodeData); console.log("nodeData", nodeData);
return new Promise((resolve) => { if (nodeData.level === 0) {
http getProject(resolve);
.get("api/metadata/metadata", { return;
projectId: nodeData.key, }
})
.then((resp) => { http
let arr = []; .get("api/metadata/metadata", {
resp.data.records.map((item) => { projectId: nodeData.data.key,
arr.push({ })
title: item.name, .then((resp) => {
key: item.id, let arr = [];
isLeaf: true, resp.data.records.map((item) => {
}); arr.push({
label: item.name,
key: item.id,
children: [],
leaf: true,
}); });
nodeData.children = arr;
resolve();
}); });
}); console.log("arr", arr);
return resolve(arr);
});
}; };
const indeterminate = ref(false); const indeterminate = ref(false);
@ -158,7 +181,7 @@ const getColumnList = (clickEfNodeId) => {
sortNo: item.sortNo, sortNo: item.sortNo,
type: item.type, type: item.type,
typeStr: item.typeStr, typeStr: item.typeStr,
typeColor:item.typeColor typeColor: item.typeColor,
}); });
} }
}); });
@ -172,7 +195,7 @@ const getColumnList = (clickEfNodeId) => {
const assignInit = (nodeValue) => { const assignInit = (nodeValue) => {
let metadataId = JSON.parse(nodeValue.data).metadataId; let metadataId = JSON.parse(nodeValue.data).metadataId;
console.log(metadataId); console.log("metadataId", metadataId);
getMetadata(metadataId); getMetadata(metadataId);
}; };
@ -183,7 +206,7 @@ defineExpose({
</script> </script>
<style lang="scss"> <style lang="scss">
.usedatabase { .usedatabase {
width: 800px; width: 100%;
height: 400px; height: 400px;
display: flex; display: flex;
.usedatabase_left { .usedatabase_left {
@ -191,6 +214,7 @@ defineExpose({
padding-right: 20px; padding-right: 20px;
margin-right: 20px; margin-right: 20px;
border-right: 1px solid rgba(229, 230, 235, 1); border-right: 1px solid rgba(229, 230, 235, 1);
overflow-y: auto;
} }
.usedatabase_right { .usedatabase_right {
flex: 1; flex: 1;

View File

@ -0,0 +1,148 @@
<template>
<a-spin :loading="loading" style="width: 100vw; height: 100vh">
<a-affix :offsetTop="0">
<UIHeader
@changeTabName="handleChangeTabName"
@submit="handleSubmit"
></UIHeader>
</a-affix>
<div class="wk-content">
<div class="wk-page-basic" v-show="tabName == 'basic'">
<a-card title="基本设置" :bordered="false">
<a-form :model="pageStore.page" layout="vertical">
<a-form-item
field="name"
label="列表名称"
:rules="[{ required: true, message: '请输入列表名称' }]"
:validate-trigger="['blur', 'input']"
>
<a-input v-model="pageStore.page.name" placeholder="列表名称" />
</a-form-item>
<a-form-item field="remarks" label="描述">
<a-textarea
v-model="pageStore.page.remarks"
placeholder="描述"
:max-length="255"
allow-clear
show-word-limit
/>
</a-form-item>
</a-form>
</a-card>
<a-card title="预览设置" style="margin-top: 20px" :bordered="false">
<template #extra>可以复制地址直接访问</template>
<a-input v-model="url" readonly disabled />
</a-card>
</div>
<div class="wk-page-list" v-show="tabName == 'list'">
<a-card title="数据管理设计" :bordered="false">
<a-tabs type="capsule">
<a-tab-pane key="tab-datamodel" title="数据模型">
<UITableDataModel />
</a-tab-pane>
<a-tab-pane key="tab-listpage" title="列表页面">
<UITableColumn />
</a-tab-pane>
<a-tab-pane key="tab-button" title="按钮配置">
<UITableButton />
</a-tab-pane>
<a-tab-pane key="tab-filter" title="列表过滤">
<UITableFilter />
</a-tab-pane>
</a-tabs>
</a-card>
</div>
</div>
<a-modal
title="提示"
v-model:visible="visible"
@ok="handleModalOk"
@cancel="handleModalCancel"
:ok-loading="loading"
title-align="start"
>
保存使用新的设计此操作无法恢复是否确认保存
</a-modal>
</a-spin>
</template>
<script setup>
import { nextTick, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { Message } from "@arco-design/web-vue";
import UIHeader from "./ui/ui-header.vue";
import UITableDataModel from "./ui/ui-table-datamodel.vue";
import UITableColumn from "./ui/ui-table-column.vue";
import UITableButton from "./ui/ui-table-button.vue";
import UITableFilter from "./ui/ui-table-filter.vue";
import useAppPageStore from "./store";
import http from "@/scripts/request";
const route = useRoute();
const tabName = ref("basic");
let pageStore = useAppPageStore();
const datamodel = ref(pageStore.datamodel);
const loading = ref(false);
const visible = ref(false);
const id = route.params.id;
if (id) {
loading.value = true;
nextTick(() => {
initData();
});
}
const initData = () => {
http.get(`/api/app_page/${id}`).then((resp) => {
if (resp.code == 200) {
pageStore.page = resp.data;
loading.value = false;
}
});
};
const handleChangeTabName = (name) => {
tabName.value = name;
};
const handleSubmit = () => {
visible.value = true;
};
const handleModalOk = () => {
loading.value = true;
var url = pageStore.page.id
? "/api/app_page/" + pageStore.page.id
: "/api/app_page";
http.post(url, pageStore.page).then((resp) => {
loading.value = false;
if (resp.code == 200) {
Message.success("保存页面成功");
}
});
};
const handleModalCancel = () => {
visible.value = false;
};
const url =
"http://frame.bctools.cn/page-design-ui/#/list/use?id=796051017488568320&dataModelId=796051014330257408&jvsAppId=dc2d6befc3efaf034ea7a65460d49dc7";
</script>
<style scope>
.wk-page-basic {
width: 800px;
margin: 20px auto;
}
.wk-page-list {
width: 1000px;
margin: 20px auto;
}
</style>

View File

@ -0,0 +1,49 @@
import { defineStore } from "pinia";
const useAppPageStore = defineStore("appPageData", {
state: () => ({
page: {
id: "",
name: "",
remarks: "",
type: "crud",
models: [],
columns: [],
buttons: [
{
label: "新增",
place: "top",
type: "new",
},
{
label: "修改",
place: "row",
type: "edit",
},
{
label: "详情",
place: "row",
type: "detail",
},
{
label: "删除",
place: "row",
type: "del",
},
{
label: "导入",
place: "top",
type: "import",
},
{
label: "导出",
place: "top",
type: "export",
},
],
filters: [],
},
}),
});
export default useAppPageStore;

View File

@ -0,0 +1,45 @@
<template>
<div class="wk-header">
<div class="wk-header-left">页面编辑器</div>
<div class="wk-header-center">
<el-tabs :hide-content="true" @tab-click="handleChangeTab">
<el-tab-pane key="basic" title="页面设置"></el-tab-pane>
<a-tab-pane key="list" title="列表设计"></a-tab-pane>
<a-tab-pane key="role" title="页面权限"></a-tab-pane>
<a-tab-pane key="data" title="数据设置"></a-tab-pane>
</el-tabs>
</div>
<div class="wk-header-right">
<el-button size="small" type="primary" @click="handlerSubmit"
>保存</el-button
>
</div>
</div>
</template>
<script setup>
const emit = defineEmits(["changeTabName", "submit"]);
const handleChangeTab = (tabName) => {
emit("changeTabName", tabName);
};
const handlerSubmit = () => {
emit("submit");
};
</script>
<style scoped>
.wk-header {
display: flex;
justify-content: space-between;
align-items: center;
-webkit-box-align: center;
padding: 0 20px;
height: 45px;
border-bottom: 2px solid #f0f2f5;
background-color: #fff;
color: #333;
font-size: 14px;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="toolbar">
<a-button size="mini" @click="handleAddClick">新增一行</a-button>
</div>
<a-table
:columns="columns"
:data="pageStore.page.buttons"
:pagination="false"
:draggable="{ type: 'handle', width: 40 }"
@change="handleDraggable"
>
<template #label="{ rowIndex }">
<a-input
size="mini"
placeholder="请输入按钮名称"
v-model="pageStore.page.buttons[rowIndex].label"
/>
</template>
<template #place="{ rowIndex, record }">
<a-select
size="mini"
placeholder="请选择按钮位置"
v-model="pageStore.page.buttons[rowIndex].place"
:disabled="!record.is_edit"
>
<a-option
v-for="item of placeOptions"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</a-select>
</template>
<template #type="{ rowIndex, record }">
<a-select
size="mini"
placeholder="请选择按钮类型"
v-model="pageStore.page.buttons[rowIndex].type"
:disabled="!hasShowOtherButton(record)"
>
<a-option
v-for="item of hasShowOtherButton(record)
? buttonTypeOptions
: defaultButtonTypeOptions"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</a-select>
</template>
<template #isShow="{ rowIndex }">
<a-switch
size="mini"
v-model="pageStore.page.buttons[rowIndex].is_show"
/>
</template>
<template #actions="{ rowIndex, record }">
<a-link
@click="handleDelClick(rowIndex)"
v-if="hasShowDesignButton(record)"
>设计</a-link
>
<a-link
@click="handleDelClick(rowIndex)"
v-if="hasShowOtherButton(record)"
>删除</a-link
>
</template>
</a-table>
</template>
<script setup>
import { ref } from "vue";
import useAppPageStore from "../store";
const pageStore = useAppPageStore();
const placeOptions = ref([
{
label: "顶部",
value: "top",
},
{
label: "行内",
value: "row",
},
]);
const defaultButtonTypeOptions = ref([
{
label: "新增",
value: "new",
},
{
label: "修改",
value: "edit",
},
{
label: "详情",
value: "detail",
},
{
label: "删除",
value: "del",
},
{
label: "导入",
value: "import",
},
{
label: "导出",
value: "export",
},
]);
const buttonTypeOptions = ref([
{
label: "表单",
value: "form",
},
{
label: "逻辑引擎",
value: "logic-engine",
},
{
label: "内部地址",
value: "link-in",
},
{
label: "外部地址",
value: "link-out",
},
]);
const handleAddClick = () => {
pageStore.page.buttons.push({});
};
const handleDelClick = (index) => {
pageStore.page.buttons.splice(index, 1);
};
const handleDraggable = (_data) => {
pageStore.page.buttons = _data;
};
const hasShowDesignButton = (btn) => {
return btn.type != "del";
};
const hasShowOtherButton = (btn) => {
return (
btn.type == "form" ||
btn.type == "logic-engine" ||
btn.type == "link-in" ||
btn.type == "link-out"
);
};
const columns = [
{
title: "按钮名称",
slotName: "label",
width: 200,
},
{
title: "按钮位置",
slotName: "place",
width: 200,
align: "center",
},
{
title: "按钮类型",
slotName: "type",
width: 200,
align: "center",
},
{
title: "是否显示",
slotName: "isShow",
align: "center",
},
{
title: "操作",
slotName: "actions",
align: "left",
width: 120,
},
];
</script>
<style scoped>
.toolbar {
margin-bottom: 8px;
}
</style>

View File

@ -0,0 +1,116 @@
<template>
<div class="toolbar">
<a-button size="mini" @click="handleAddClick">新增一行</a-button>
</div>
<a-table
:columns="columns"
:data="pageStore.page.columns"
:pagination="false"
:draggable="{ type: 'handle', width: 40 }"
@change="handleDraggable"
>
<template #name="{ rowIndex }">
<a-select
size="mini"
placeholder="请选择字段"
v-model="pageStore.page.columns[rowIndex].name"
@change="(e) => handleChangeName(rowIndex, e)"
>
<a-option
v-for="item of pageStore.page.models"
:value="item.name"
:label="item.label"
:key="item.name"
/>
</a-select>
</template>
<template #label="{ rowIndex }">
<a-input
size="mini"
placeholder="请输入显示名称"
v-model="pageStore.page.columns[rowIndex].label"
/>
</template>
<template #isShow="{ rowIndex }">
<a-switch
size="mini"
v-model="pageStore.page.columns[rowIndex].is_show"
/>
</template>
<template #config>
<a-button size="mini" type="text">配置</a-button>
</template>
<template #isQuery="{ rowIndex }">
<a-switch
size="mini"
v-model="pageStore.page.columns[rowIndex].is_query"
/>
</template>
<template #actions="{ rowIndex }">
<a-button size="mini" type="text" @click="handleDelClick(rowIndex)"
>删除</a-button
>
</template>
</a-table>
</template>
<script setup>
import { ref } from "vue";
import useAppPageStore from "../store";
const pageStore = useAppPageStore();
const handleAddClick = () => {
pageStore.page.columns.push({
is_show: true,
is_query: true,
});
};
const handleDelClick = (index) => {
pageStore.page.columns.splice(index, 1);
};
const handleChangeName = (index, name) => {
const opt = pageStore.page.models.find((item) => item.name == name);
pageStore.page.columns[index].label = opt ? opt.label : "";
};
const handleDraggable = (_data) => {
pageStore.page.columns = _data;
};
const columns = [
{
title: "字段名",
slotName: "name",
width: 200,
},
{
title: "显示中文名",
slotName: "label",
},
{
title: "是否显示",
slotName: "isShow",
},
{
title: "显示配置",
slotName: "config",
},
{
title: "是否查询",
slotName: "isQuery",
},
{
title: "操作",
slotName: "actions",
},
];
</script>
<style scoped>
.toolbar {
margin-bottom: 8px;
}
</style>

View File

@ -0,0 +1,140 @@
<template>
<div class="toolbar">
<a-space>
<a-button size="mini" @click="handleAddClick">新增一行</a-button>
<a-button size="mini">批量增加</a-button>
</a-space>
</div>
<a-table
:columns="columns"
:data="pageStore.page.models"
:pagination="false"
:draggable="{ type: 'handle', width: 40 }"
@change="handleDraggable"
>
<template #label="{ rowIndex }">
<a-input
size="mini"
placeholder="请输入显示中文名"
v-model="pageStore.page.models[rowIndex].label"
/>
</template>
<template #name="{ rowIndex }">
<a-input
size="mini"
placeholder="请输入显示字段名"
v-model="pageStore.page.models[rowIndex].name"
/>
</template>
<template #type="{ rowIndex }">
<a-select
size="mini"
placeholder="请选择字段类型"
v-model="pageStore.page.models[rowIndex].type"
>
<a-option value="string">字符</a-option>
<a-option value="integer">数字</a-option>
<a-option value="date">日期</a-option>
<a-option value="price">货币</a-option>
</a-select>
</template>
<template #length="{ rowIndex }">
<a-input-number
size="mini"
placeholder="字符长度"
v-model="pageStore.page.models[rowIndex].length"
/>
</template>
<template #digit="{ rowIndex }">
<a-input-number
size="mini"
placeholder="位数"
v-model="pageStore.page.models[rowIndex].digit"
/>
</template>
<template #scale="{ rowIndex }">
<a-input-number
size="mini"
placeholder="小数点"
v-model="pageStore.page.models[rowIndex].scale"
/>
</template>
<template #actions="{ rowIndex }">
<a-button size="mini" type="text" @click="handleDelClick(rowIndex)"
>删除</a-button
>
</template>
</a-table>
</template>
<script setup>
import { ref, reactive } from "vue";
import useAppPageStore from "../store";
const pageStore = useAppPageStore();
const handleAddClick = () => {
pageStore.page.models.push({
is_show: true,
is_query: true,
key: pageStore.page.models.lenth,
});
};
const handleDelClick = (index) => {
pageStore.page.models.splice(index, 1);
};
const handleDraggable = (_data) => {
pageStore.page.models = _data;
};
const columns = [
{
title: "显示中文名",
slotName: "label",
width: 200,
},
{
title: "字段名",
slotName: "name",
width: 200,
},
{
title: "字段类型",
slotName: "type",
width: 180,
align: "center",
},
{
title: "字段长度",
slotName: "length",
width: 150,
align: "center",
},
{
title: "位数",
slotName: "digit",
width: 150,
align: "center",
},
{
title: "小数点位数",
slotName: "scale",
width: 150,
align: "center",
},
{
title: "操作",
slotName: "actions",
width: 100,
align: "center",
},
];
</script>
<style scoped>
.toolbar {
margin-bottom: 8px;
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div class="toolbar">
<a-button size="mini" @click="handleAddClick">新增一行</a-button>
</div>
<a-table
:columns="columns"
:data="pageStore.page.filters"
:pagination="false"
>
<template #name="{ rowIndex }">
<a-select
size="mini"
placeholder="请选择字段"
v-model="pageStore.page.filters[rowIndex].name"
>
<a-option
v-for="item of pageStore.page.models"
:value="item.name"
:label="item.label"
:key="item.name"
/>
</a-select>
</template>
<template #rule="{ rowIndex }">
<a-select
size="mini"
placeholder="请选择规则"
v-model="pageStore.page.filters[rowIndex].rule"
>
<a-option
v-for="item of ruleOptions"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</a-select>
</template>
<template #value="{ rowIndex }">
<a-select
size="mini"
placeholder="请选择或者输入"
v-model="pageStore.page.filters[rowIndex].value"
allow-create
>
<a-option
v-for="item of valueOptions"
:value="item.value"
:label="item.label"
:key="item.value"
/>
</a-select>
</template>
<template #isShow="{ rowIndex }">
<a-switch
size="mini"
v-model="pageStore.page.filters[rowIndex].is_show"
/>
</template>
<template #actions="{ rowIndex }">
<a-button size="mini" type="text" @click="handleDelClick(rowIndex)"
>删除</a-button
>
</template>
</a-table>
</template>
<script setup>
import { ref } from "vue";
import useAppPageStore from "../store";
const pageStore = useAppPageStore();
const ruleOptions = ref([
{
label: "等于",
value: "eq",
},
{
label: "包含",
value: "like",
},
{
label: "不包含",
value: "not like",
},
]);
const valueOptions = ref([
{
label: "当前登录用户ID",
value: "user_id",
},
{
label: "当前登录用户名",
value: "username",
},
{
label: "当前登录用户所在部门",
value: "dept",
},
]);
const handleAddClick = () => {
pageStore.page.filters.push({
is_show: true,
is_edit: true,
});
};
const handleDelClick = (index) => {
pageStore.page.filters.splice(index, 1);
console.log(pageStore.page.filters);
};
const columns = [
{
title: "字段名",
slotName: "name",
width: 200,
},
{
title: "规则",
slotName: "rule",
width: 160,
},
{
title: "值",
slotName: "value",
width: 200,
},
{
title: "操作",
slotName: "actions",
width: 100,
align: "center",
},
];
</script>
<style scoped>
.toolbar {
margin-bottom: 8px;
}
</style>

View File

@ -27,8 +27,10 @@ export default defineConfig({
host: '0.0.0.0', // 解决“vite use `--host` to expose”-- 0.0.0.0 将监听所有地址 host: '0.0.0.0', // 解决“vite use `--host` to expose”-- 0.0.0.0 将监听所有地址
proxy: { proxy: {
'/api': { '/api': {
target: 'https://fywz.btdit.cn/', target: 'http://10.0.0.29:9999',
// target: 'https://fywz.btdit.cn/',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
// ws: true,// 开启webSocket // ws: true,// 开启webSocket
} }
} }

View File

@ -22,16 +22,6 @@
"@codemirror/view" "^6.6.0" "@codemirror/view" "^6.6.0"
"@lezer/common" "^1.0.0" "@lezer/common" "^1.0.0"
"@codemirror/commands@6.x", "@codemirror/commands@^6.0.0":
version "6.2.4"
resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec"
integrity sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==
dependencies:
"@codemirror/language" "^6.0.0"
"@codemirror/state" "^6.2.0"
"@codemirror/view" "^6.0.0"
"@lezer/common" "^1.0.0"
"@codemirror/lang-javascript@^6.1.9": "@codemirror/lang-javascript@^6.1.9":
version "6.1.9" version "6.1.9"
resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz#19065ad32db7b3797829eca01b8d9c69da5fd0d6" resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz#19065ad32db7b3797829eca01b8d9c69da5fd0d6"
@ -45,7 +35,7 @@
"@lezer/common" "^1.0.0" "@lezer/common" "^1.0.0"
"@lezer/javascript" "^1.0.0" "@lezer/javascript" "^1.0.0"
"@codemirror/language@6.x", "@codemirror/language@^6.0.0", "@codemirror/language@^6.6.0": "@codemirror/language@^6.0.0", "@codemirror/language@^6.6.0":
version "6.7.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.7.0.tgz#9f1c8923e3234376a40f3392e4a0451e9b4adb8f" resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.7.0.tgz#9f1c8923e3234376a40f3392e4a0451e9b4adb8f"
integrity sha512-4SMwe6Fwn57klCUsVN0y4/h/iWT+XIXFEmop2lIHHuWO0ubjCrF3suqSZLyOQlznxkNnNbOOfKe5HQbQGCAmTg== integrity sha512-4SMwe6Fwn57klCUsVN0y4/h/iWT+XIXFEmop2lIHHuWO0ubjCrF3suqSZLyOQlznxkNnNbOOfKe5HQbQGCAmTg==
@ -66,16 +56,7 @@
"@codemirror/view" "^6.0.0" "@codemirror/view" "^6.0.0"
crelt "^1.0.5" crelt "^1.0.5"
"@codemirror/search@^6.0.0": "@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.0.tgz#308f9968434e0e6ed59c9ec36a0239eb1dfc5d92"
integrity sha512-64/M40YeJPToKvGO6p3fijo2vwUEj4nACEAXElCaYQ50HrXSvRaK+NHEhSh73WFBGdvIdhrV+lL9PdJy2RfCYA==
dependencies:
"@codemirror/state" "^6.0.0"
"@codemirror/view" "^6.0.0"
crelt "^1.0.5"
"@codemirror/state@6.x", "@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4", "@codemirror/state@^6.2.0":
version "6.2.1" version "6.2.1"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.1.tgz#6dc8d8e5abb26b875e3164191872d69a5e85bd73" resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.1.tgz#6dc8d8e5abb26b875e3164191872d69a5e85bd73"
integrity sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw== integrity sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==
@ -90,7 +71,7 @@
"@codemirror/view" "^6.0.0" "@codemirror/view" "^6.0.0"
"@lezer/highlight" "^1.0.0" "@lezer/highlight" "^1.0.0"
"@codemirror/view@6.x", "@codemirror/view@^6.0.0", "@codemirror/view@^6.6.0": "@codemirror/view@^6.0.0", "@codemirror/view@^6.6.0":
version "6.13.0" version "6.13.0"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.13.0.tgz#a86c3c5e588a7e2fc0e8043c8ae9fdcc608f5eb7" resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.13.0.tgz#a86c3c5e588a7e2fc0e8043c8ae9fdcc608f5eb7"
integrity sha512-oXTfJzHJ5Tl7f6T8ZO0HKf981zubxgKohjddLobbntbNZHlOZGMRL+pPZGtclDWFaFJWtGBYRGyNdjQ6Xsx5yA== integrity sha512-oXTfJzHJ5Tl7f6T8ZO0HKf981zubxgKohjddLobbntbNZHlOZGMRL+pPZGtclDWFaFJWtGBYRGyNdjQ6Xsx5yA==
@ -518,18 +499,18 @@ braces@^3.0.2, braces@~3.0.2:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
codemirror@^6.0.1: codemirror-editor-vue3@^2.3.0:
version "6.0.1" version "2.3.0"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" resolved "https://registry.yarnpkg.com/codemirror-editor-vue3/-/codemirror-editor-vue3-2.3.0.tgz#e6c97aba62eee8bc1d980ea78e112179777d5a32"
integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== integrity sha512-e6y/2wBL4Xb4SD10e/jq/lcoIeiWPMw2XnF6KePLlbmOphZ830XGU3kSz52qkoa9RUjaY6zHuSlwd09o13O/oQ==
dependencies: dependencies:
"@codemirror/autocomplete" "^6.0.0" codemirror "^5.64.0"
"@codemirror/commands" "^6.0.0" diff-match-patch "^1.0.5"
"@codemirror/language" "^6.0.0"
"@codemirror/lint" "^6.0.0" codemirror@^5.64.0:
"@codemirror/search" "^6.0.0" version "5.65.13"
"@codemirror/state" "^6.0.0" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.13.tgz#c098a6f409db8b5a7c5722788bd9fa3bb2367f2e"
"@codemirror/view" "^6.0.0" integrity sha512-SVWEzKXmbHmTQQWaz03Shrh4nybG0wXx2MEu3FO4ezbPW8IbnZEd5iGHGEffSUaitKYa3i+pHpBsSvw8sPHtzg==
combined-stream@^1.0.8: combined-stream@^1.0.8:
version "1.0.8" version "1.0.8"
@ -565,6 +546,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==
element-plus@^2.3.5: element-plus@^2.3.5:
version "2.3.5" version "2.3.5"
resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-2.3.5.tgz#5b04de44fd0ee1bd29ad6ed971d9155982cc1295" resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-2.3.5.tgz#5b04de44fd0ee1bd29ad6ed971d9155982cc1295"
@ -954,10 +940,10 @@ scule@^1.0.0:
resolved "https://registry.yarnpkg.com/scule/-/scule-1.0.0.tgz#895e6f4ba887e78d8b9b4111e23ae84fef82376d" resolved "https://registry.yarnpkg.com/scule/-/scule-1.0.0.tgz#895e6f4ba887e78d8b9b4111e23ae84fef82376d"
integrity sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ== integrity sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==
sortablejs@1.10.2: sortablejs@1.14.0:
version "1.10.2" version "1.14.0"
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.10.2.tgz#6e40364d913f98b85a14f6678f92b5c1221f5290" resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
integrity sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A== integrity sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
version "1.0.2" version "1.0.2"
@ -1065,16 +1051,6 @@ vite@^4.3.9:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
vue-codemirror@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/vue-codemirror/-/vue-codemirror-6.1.1.tgz#246697ef4cfa6b2448dd592ade214bb7ff86611f"
integrity sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==
dependencies:
"@codemirror/commands" "6.x"
"@codemirror/language" "6.x"
"@codemirror/state" "6.x"
"@codemirror/view" "6.x"
vue-demi@*, vue-demi@>=0.14.5: vue-demi@*, vue-demi@>=0.14.5:
version "0.14.5" version "0.14.5"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.5.tgz#676d0463d1a1266d5ab5cba932e043d8f5f2fbd9" resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.5.tgz#676d0463d1a1266d5ab5cba932e043d8f5f2fbd9"
@ -1098,12 +1074,12 @@ vue@^3.2.47:
"@vue/server-renderer" "3.3.4" "@vue/server-renderer" "3.3.4"
"@vue/shared" "3.3.4" "@vue/shared" "3.3.4"
vuedraggable@^2.24.3: vuedraggable@^4.1.0:
version "2.24.3" version "4.1.0"
resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.24.3.tgz#43c93849b746a24ce503e123d5b259c701ba0d19" resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-4.1.0.tgz#edece68adb8a4d9e06accff9dfc9040e66852270"
integrity sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g== integrity sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==
dependencies: dependencies:
sortablejs "1.10.2" sortablejs "1.14.0"
w3c-keyname@^2.2.4: w3c-keyname@^2.2.4:
version "2.2.7" version "2.2.7"