Pārlūkot izejas kodu

fixed: 修改数据聚合模块数据处理逻辑

liuyang 2 gadi atpakaļ
vecāks
revīzija
c3515a0fa1

+ 1 - 0
.eslintrc

@ -34,6 +34,7 @@
34 34
        "endOfLine": "auto",
35 35
        "singleQuote": true,
36 36
        "trailingComma": "none",
37
        "no-nested-ternary": "ignore",
37 38
        "bracketSpacing": true,
38 39
        "jsxBracketSameLine": false,
39 40
        "vueIndentScriptAndStyle": false,

+ 5 - 1
src/views/_components/_flow/Index.vue

@ -77,6 +77,7 @@ function initGraph() {
77 77
  graph.value = new Graph({
78 78
    container,
79 79
    autoResize: true,
80
    rendering: 'canvas',
80 81
    background: {
81 82
      color: '#F8F8F8'
82 83
    },
@ -349,7 +350,10 @@ function registerRouter() {
349 350
    const points = [];
350 351
    points.push(new Point(start.x + 48, start.y));
351 352
    points.push(
352
      new Point(view.targetBBox.leftMiddle.x - 20, view.targetBBox.leftMiddle.y)
353
      new Point(
354
        view.targetBBox.leftMiddle.x - 120,
355
        view.targetBBox.leftMiddle.y
356
      )
353 357
    );
354 358
    return points;
355 359
  });

+ 0 - 157
src/views/_components/panel/PanelBranch.vue

@ -1,157 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <!-- 功能区域 -->
13
        <add-item
14
          :item-list="panelData.function.branchList"
15
          @update:item-list="panelData.function.branchList = $event"
16
        ></add-item>
17
      </template>
18
    </common-panel>
19
  </div>
20
</template>
21
22
<script setup>
23
import { ref, watch, onMounted } from 'vue';
24
import CommonPanel from './common/CommonPanel.vue';
25
import InputOutputTab from './sql-components/InputOutputTab.vue';
26
import AddItem from './common/AddItem.vue';
27
28
const props = defineProps({
29
  targetNode: {
30
    type: Object,
31
    default: () => {}
32
  }
33
});
34
35
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
36
37
const panelData = ref(
38
  nodePanelData.value || {
39
    basicData: {
40
      name: props.targetNode.cell.getData().label,
41
      desc: ''
42
    },
43
    inputOutput: {
44
      input: {
45
        header: [
46
          {
47
            label: 'ID',
48
            name: 'id',
49
            'min-width': '150'
50
          },
51
          {
52
            label: '名称',
53
            name: 'name',
54
            'min-width': '150'
55
          },
56
          {
57
            label: '类型',
58
            name: 'type',
59
            'min-width': '150'
60
          },
61
          {
62
            label: '别名',
63
            name: 'alias',
64
            type: 'input',
65
            'min-width': '150'
66
          },
67
          {
68
            label: '操作',
69
            name: 'custom',
70
            type: 'custom',
71
            fixed: 'right',
72
            width: '100'
73
          }
74
        ],
75
        data: []
76
      },
77
      output: {
78
        header: [
79
          {
80
            label: 'ID',
81
            name: 'id',
82
            'min-width': '150'
83
          },
84
          {
85
            label: '别名',
86
            name: 'alias',
87
            type: 'input',
88
            'min-width': '150'
89
          },
90
          {
91
            label: '操作',
92
            name: 'custom',
93
            type: 'custom',
94
            fixed: 'right',
95
            width: '100'
96
          }
97
        ],
98
        data: []
99
      }
100
    },
101
    function: {
102
      branchList: [],
103
      defaultId: ''
104
    }
105
  }
106
);
107
108
function setNodeAttrData() {
109
  // 使用overwrite + silent 进行数据的重置覆盖,防止节点中的数据不准确
110
  const data = props.targetNode.cell.getData();
111
  console.log(data);
112
  props.targetNode.cell.setData(
113
    {
114
      ...data,
115
      attrsData: JSON.parse(JSON.stringify(panelData.value))
116
    },
117
    {
118
      overwrite: true,
119
      silent: false
120
    }
121
  );
122
}
123
124
// 给default port 绑定节点
125
function formatDefaultPort() {
126
  const nodeInfo = props.targetNode.node;
127
  const { ports } = nodeInfo.port;
128
  if (ports?.length) {
129
    ports.forEach((port) => {
130
      if (port.group === 'output' && !port?.type) {
131
        panelData.value.function.defaultId = port.id;
132
      }
133
    });
134
  }
135
}
136
formatDefaultPort();
137
138
watch(
139
  panelData.value,
140
  () => {
141
    setNodeAttrData();
142
  },
143
  { deep: true }
144
);
145
146
onMounted(() => {
147
  setNodeAttrData();
148
});
149
</script>
150
151
<script>
152
export default {
153
  name: 'PanelBranch'
154
};
155
</script>
156
157
<style scoped lang="scss"></style>

+ 0 - 135
src/views/_components/panel/PanelDataAggregation.vue

@ -1,135 +0,0 @@
1
<template>
2
  <div class="panel-data-aggregation">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <div class="content">
13
          <!-- <JsonEditorVue
14
            v-model="panelData.function.aggregate"
15
            class="editor"
16
            @blur="validate"
17
          ></JsonEditorVue> -->
18
        </div>
19
      </template>
20
    </common-panel>
21
  </div>
22
</template>
23
24
<script setup>
25
import { ref, watch } from 'vue';
26
// import JsonEditorVue from 'json-editor-vue3';
27
import CommonPanel from './common/CommonPanel.vue';
28
import InputOutputTab from './sql-components/InputOutputTab.vue';
29
30
const props = defineProps({
31
  targetNode: {
32
    type: Object,
33
    default: () => {}
34
  }
35
});
36
37
// const
38
39
const panelData = ref(
40
  props.targetNode.cell.getData()?.attrsData || {
41
    basicData: {
42
      name: props.targetNode.cell.getData().label,
43
      desc: ''
44
    },
45
    inputOutput: {
46
      input: {
47
        header: [
48
          {
49
            label: 'ID',
50
            name: 'id',
51
            'min-width': '150'
52
          },
53
          {
54
            label: '名称',
55
            name: 'name',
56
            'min-width': '150'
57
          },
58
          {
59
            label: '类型',
60
            name: 'type',
61
            'min-width': '150'
62
          },
63
          {
64
            label: '别名',
65
            name: 'alias',
66
            type: 'input',
67
            'min-width': '150'
68
          },
69
          {
70
            label: '操作',
71
            name: 'custom',
72
            type: 'custom',
73
            fixed: 'right',
74
            width: '100'
75
          }
76
        ],
77
        data: []
78
      },
79
      output: {
80
        header: [
81
          {
82
            label: 'ID',
83
            name: 'id',
84
            'min-width': '150'
85
          },
86
          {
87
            label: '别名',
88
            name: 'alias',
89
            type: 'input',
90
            'min-width': '150'
91
          },
92
          {
93
            label: '操作',
94
            name: 'custom',
95
            type: 'custom',
96
            fixed: 'right',
97
            width: '100'
98
          }
99
        ],
100
        data: []
101
      }
102
    },
103
    function: {
104
      aggregate: {}
105
    }
106
  }
107
);
108
109
// function validate() {}
110
111
function setNodeAttrData() {
112
  props.targetNode.cell.setData({
113
    attrsData: panelData.value
114
  });
115
}
116
watch(
117
  panelData.value,
118
  () => {
119
    setNodeAttrData();
120
  },
121
  { deep: true }
122
);
123
</script>
124
125
<script>
126
export default {
127
  name: 'PanelDataAggregation'
128
};
129
</script>
130
131
<style scoped lang="scss">
132
.editor {
133
  height: 300px;
134
}
135
</style>

+ 0 - 169
src/views/_components/panel/PanelEnd.vue

@ -1,169 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <el-tabs v-model="activeName" @tab-click="handleClick">
4
      <el-tab-pane label="功能" name="function">
5
        <el-button type="success" @click.stop="setting">设置</el-button>
6
        <common-table
7
          :table-header="tableHeader"
8
          :table-data="panelData.function.tableData"
9
        >
10
          <template #custom="scope">
11
            <el-icon class="icon" @click.stop="deleteAttr(scope.row)">
12
              <Delete></Delete>
13
            </el-icon>
14
          </template>
15
        </common-table>
16
      </el-tab-pane>
17
    </el-tabs>
18
  </div>
19
20
  <dialog-panel
21
    v-if="showSetting"
22
    :dialog-data="dialogData"
23
    @confirm-dialog="confirmSettingDialog"
24
    @clos-dialog="closeSettingDialog"
25
  >
26
    <!-- 数据展示 -->
27
    <attr-info
28
      :table="inputOutputDialog"
29
      @checked-attrs="checkedAttrs"
30
    ></attr-info>
31
  </dialog-panel>
32
</template>
33
34
<script setup>
35
import { ref, computed, watch } from 'vue';
36
import { useRoute } from 'vue-router';
37
import AttrInfo from './common/AttrInfo.vue';
38
39
const route = useRoute();
40
const props = defineProps({
41
  targetNode: {
42
    type: Object,
43
    default: () => {}
44
  }
45
});
46
47
// 设置结束节点信息
48
function setEndNodeInfo() {
49
  const activeName = ref('function');
50
  const showSetting = ref(false);
51
  const dialogData = ref({
52
    title: '变量声明'
53
  });
54
  const formData = ref({
55
    id: ''
56
  });
57
  const tableHeader = ref([
58
    { label: '返回键', name: 'id', 'min-width': '150' },
59
    { label: '返回名', name: 'name', 'min-width': '150' },
60
    { label: '别名', name: 'alias', type: 'input', 'min-width': '150' },
61
    {
62
      label: '操作',
63
      name: 'custom',
64
      type: 'custom',
65
      fixed: 'right',
66
      width: '100'
67
    }
68
  ]);
69
70
  const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
71
  const panelData = ref(
72
    nodePanelData.value || {
73
      basicData: {},
74
      inputOutput: {},
75
      function: {
76
        tableData: []
77
      }
78
    }
79
  );
80
  const dataBus = JSON.parse(localStorage.getItem('panelGlobal')) || {};
81
  const flowId = computed(() => route.query.id);
82
83
  const inputOutputDialog = ref({
84
    modelAttrs: {
85
      header: [{ label: '模型属性', name: 'modelAttrs', 'min-width': '150' }],
86
      data: dataBus[flowId.value]?.modelAttrs?.data || []
87
    },
88
    customAttrs: {
89
      header: [
90
        { label: 'ID', name: 'id', 'min-width': '150' },
91
        { label: '名称', name: 'name', 'min-width': '150' }
92
      ],
93
      data: dataBus[flowId.value]?.customAttrs?.data || []
94
    },
95
    models: {
96
      header: [{ label: '模型', name: 'model', 'min-width': '150' }],
97
      data: dataBus[flowId.value]?.models?.data || []
98
    }
99
  });
100
  const setting = () => {
101
    showSetting.value = true;
102
  };
103
  const closeSettingDialog = () => {
104
    showSetting.value = false;
105
  };
106
  const confirmSettingDialog = () => {
107
    closeSettingDialog();
108
  };
109
  function checkedAttrs(data) {
110
    panelData.value.function.tableData = data.customAttrs;
111
  }
112
  return {
113
    tableHeader,
114
    panelData,
115
    checkedAttrs,
116
    inputOutputDialog,
117
    showSetting,
118
    activeName,
119
    dialogData,
120
    formData,
121
    setting,
122
    closeSettingDialog,
123
    confirmSettingDialog
124
  };
125
}
126
127
const {
128
  tableHeader,
129
  checkedAttrs,
130
  inputOutputDialog,
131
  activeName,
132
  showSetting,
133
  dialogData,
134
  panelData,
135
  setting,
136
  closeSettingDialog,
137
  confirmSettingDialog
138
} = setEndNodeInfo();
139
140
function setNodeAttrData() {
141
  props.targetNode.cell.setData({
142
    attrsData: panelData.value
143
  });
144
}
145
146
function deleteAttr(row) {
147
  panelData.value.function.tableData.forEach((item, index) => {
148
    if (item.id === row.id) {
149
      panelData.value.function.tableData.splice(index, 1);
150
    }
151
  });
152
}
153
154
watch(
155
  panelData.value,
156
  () => {
157
    setNodeAttrData();
158
  },
159
  { deep: true }
160
);
161
</script>
162
163
<script>
164
export default {
165
  name: 'PanelEnd'
166
};
167
</script>
168
169
<style scoped lang="scss"></style>

+ 0 - 273
src/views/_components/panel/PanelExpression.vue

@ -1,273 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <!-- 输入输出 -->
5
      <template #input-output>
6
        <div class="content">
7
          <input-output-tab
8
            :input-output="panelData.inputOutput"
9
          ></input-output-tab>
10
        </div>
11
      </template>
12
13
      <!-- 函数 -->
14
      <template #function>
15
        <div class="form-item">
16
          <div class="form-title">
17
            <h5>名称</h5>
18
          </div>
19
          <el-input
20
            v-bind="attributes"
21
            v-model="panelData.function.name"
22
          ></el-input>
23
        </div>
24
        <div class="form-item">
25
          <div class="form-title">
26
            <h5>表达式</h5>
27
          </div>
28
          <my-code-hint
29
            :editor-value="panelData.function.expression"
30
            @update:editor-value="panelData.function.expression = $event"
31
            @change-textarea="changeTextarea"
32
            @code-editor-get-cursor="codeEditorGetCursor"
33
          ></my-code-hint>
34
        </div>
35
      </template>
36
    </common-panel>
37
  </div>
38
  <dialog-panel
39
    v-if="showSetting"
40
    :dialog-data="dialogData"
41
    @confirm-dialog="confirmSettingDialog"
42
    @close-dialog="closeSettingDialog"
43
  >
44
    <!-- 数据展示 -->
45
    <attr-info
46
      :table="inputOutputDialog"
47
      @checked-attrs="checkedAttrs"
48
    ></attr-info>
49
  </dialog-panel>
50
</template>
51
52
<script setup>
53
import { computed, ref, watch } from 'vue';
54
import { useRoute } from 'vue-router';
55
import CommonPanel from './common/CommonPanel.vue';
56
import InputOutputTab from './sql-components/InputOutputTab.vue';
57
58
import MyCodeHint from '../_codemirror/MyCodeHint.vue';
59
60
const route = useRoute();
61
const props = defineProps({
62
  targetNode: {
63
    type: Object,
64
    default: () => {}
65
  }
66
});
67
68
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
69
70
const panelData = ref(
71
  nodePanelData.value || {
72
    basicData: {
73
      name: props.targetNode.cell.getData().label,
74
      desc: ''
75
    },
76
    inputOutput: {
77
      input: {
78
        header: [
79
          {
80
            label: 'ID',
81
            name: 'id',
82
            'min-width': '150'
83
          },
84
          {
85
            label: '名称',
86
            name: 'name',
87
            'min-width': '150'
88
          },
89
          {
90
            label: '类型',
91
            name: 'type',
92
            'min-width': '150'
93
          },
94
          {
95
            label: '别名',
96
            name: 'alias',
97
            type: 'input',
98
            'min-width': '150'
99
          },
100
          {
101
            label: '操作',
102
            name: 'custom',
103
            type: 'custom',
104
            fixed: 'right',
105
            width: '100'
106
          }
107
        ],
108
        data: []
109
      },
110
      output: {
111
        header: [
112
          {
113
            label: 'ID',
114
            name: 'id',
115
            'min-width': '150'
116
          },
117
          {
118
            label: '别名',
119
            name: 'alias',
120
            type: 'input',
121
            'min-width': '150'
122
          },
123
          {
124
            label: '操作',
125
            name: 'custom',
126
            type: 'custom',
127
            fixed: 'right',
128
            width: '100'
129
          }
130
        ],
131
        data: []
132
      }
133
    },
134
    function: {
135
      name: '',
136
      cdatafForeach: ''
137
    }
138
  }
139
);
140
function changeTextarea(val) {
141
  panelData.value.function.expression = val;
142
}
143
144
function codeEditorGetCursor(codeData) {
145
  const pos1 = codeData.getCursor;
146
  const pos2 = {};
147
  if (pos1) {
148
    pos2.line = pos1.line;
149
    pos2.ch = pos1.ch;
150
    codeData.codeE.setCursor(pos2); // 设置光标位置
151
    codeData.codeE.replaceRange('', pos2); // 替换光标位置的内容
152
  }
153
}
154
155
// const activeName = ref('action');
156
157
// const baseInit = () => {
158
//   const basicData = ref(
159
//     nodePanelData.value || {
160
//       name: props.targetNode.cell.getData().label,
161
//       desc: ''
162
//     }
163
//   );
164
//   // 高级设置
165
//   const seniorData = ref({
166
//     nodeId: '',
167
//     nextNode: ''
168
//   });
169
//   const formRules = reactive({
170
//     name: [
171
//       {
172
//         required: true,
173
//         message: '请输入服务名称',
174
//         trigger: 'blur'
175
//       },
176
//       { min: 3, max: 100, message: '名称在3-100之间', trigger: 'blur' }
177
//     ]
178
//   });
179
//   const showMoreSettings = ref(false);
180
//   return {
181
//     basicData,
182
//     seniorData,
183
//     formRules,
184
//     showMoreSettings
185
//   };
186
// };
187
188
const dataBus = JSON.parse(localStorage.getItem('panelGlobal')) || {};
189
const flowId = computed(() => route.query.id);
190
const dialogData = ref({
191
  title: '输入模型/属性引入'
192
});
193
const inputOutputDialog = ref({
194
  modelAttrs: {
195
    header: [{ label: '模型属性', name: 'modelAttrs', 'min-width': '150' }],
196
    data: dataBus[flowId.value]?.modelAttrs?.data || []
197
  },
198
  customAttrs: {
199
    header: [
200
      { label: 'ID', name: 'id', 'min-width': '150' },
201
      { label: '名称', name: 'name', 'min-width': '150' }
202
    ],
203
    data: dataBus[flowId.value]?.customAttrs?.data || []
204
  },
205
  models: {
206
    header: [{ label: '模型', name: 'model', 'min-width': '150' }],
207
    data: dataBus[flowId.value]?.models?.data || []
208
  }
209
});
210
function closeSettingDialog() {
211
  showSetting.value = false;
212
}
213
function confirmSettingDialog() {
214
  closeSettingDialog();
215
}
216
const showSetting = ref(false);
217
218
// const { basicData, seniorData, formRules, showMoreSettings } = baseInit();
219
220
const attributes = ref({
221
  type: 'textarea',
222
  autosize: { minRows: 2, maxRows: 5 }
223
});
224
function setNodeAttrData() {
225
  props.targetNode.cell.setData({
226
    attrsData: panelData.value
227
  });
228
}
229
230
watch(
231
  panelData.value,
232
  () => {
233
    setNodeAttrData();
234
  },
235
  { deep: true }
236
);
237
</script>
238
239
<script>
240
export default {
241
  name: 'PanelExpression'
242
};
243
</script>
244
245
<style scoped lang="scss">
246
.form-item {
247
  .form-title {
248
    display: flex;
249
    justify-content: space-between;
250
    align-items: center;
251
    margin: 20px 0 10px 0;
252
    h5 {
253
      font-size: 14px;
254
      color: rgba(0, 0, 0, 0.65);
255
    }
256
  }
257
}
258
.collapse {
259
  display: flex;
260
  justify-content: flex-start;
261
  align-items: center;
262
  margin: 30px 0;
263
  .icon {
264
    margin: 0 10px;
265
    font-size: 16px;
266
  }
267
  .line {
268
    flex: 1;
269
    height: 1px;
270
    background: rgba(0, 0, 0, 0.09);
271
  }
272
}
273
</style>

+ 0 - 209
src/views/_components/panel/PanelForeach.vue

@ -1,209 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <div class="form-item">
13
          <div class="form-title">
14
            <h5>迭代器</h5>
15
          </div>
16
          <common-select
17
            v-model="panelData.function.iterator"
18
            :props-map="propsMap"
19
            :options="iteratorDataList"
20
          ></common-select>
21
        </div>
22
        <div class="form-item">
23
          <div class="form-title">
24
            <h5>数据类型</h5>
25
          </div>
26
          <common-select
27
            v-model="panelData.function.resultType"
28
            :options="resultTypes"
29
          ></common-select>
30
        </div>
31
        <div class="form-item">
32
          <div class="form-title">
33
            <h5>表达式</h5>
34
          </div>
35
          <my-code-hint
36
            class="form-content"
37
            :editor-value="panelData.function.expression"
38
            @update:editor-value="panelData.function.expression = $event"
39
            @change-textarea="changeTextarea"
40
            @code-editor-get-cursor="codeEditorGetCursor"
41
          ></my-code-hint>
42
        </div>
43
      </template>
44
    </common-panel>
45
  </div>
46
</template>
47
48
<script setup>
49
import { ref, watch } from 'vue';
50
import { useRoute } from 'vue-router';
51
import MyCodeHint from '../_codemirror/MyCodeHint.vue';
52
53
import CommonPanel from './common/CommonPanel.vue';
54
import InputOutputTab from './sql-components/InputOutputTab.vue';
55
56
const route = useRoute();
57
const props = defineProps({
58
  targetNode: {
59
    type: Object,
60
    default: () => {}
61
  }
62
});
63
64
// 数据总线
65
const logicId = route.query.id;
66
const databusData = JSON.parse(localStorage.getItem('panelGlobal')) || {};
67
68
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
69
70
const panelData = ref(
71
  nodePanelData.value || {
72
    basicData: {
73
      name: props.targetNode.cell.getData().label,
74
      desc: ''
75
    },
76
    inputOutput: {
77
      input: {
78
        header: [
79
          {
80
            label: 'ID',
81
            name: 'id',
82
            'min-width': '150'
83
          },
84
          {
85
            label: '名称',
86
            name: 'name',
87
            'min-width': '150'
88
          },
89
          {
90
            label: '类型',
91
            name: 'type',
92
            'min-width': '150'
93
          },
94
          {
95
            label: '别名',
96
            name: 'alias',
97
            type: 'input',
98
            'min-width': '150'
99
          },
100
          {
101
            label: '操作',
102
            name: 'custom',
103
            type: 'custom',
104
            fixed: 'right',
105
            width: '100'
106
          }
107
        ],
108
        data: []
109
      },
110
      output: {
111
        header: [
112
          {
113
            label: 'ID',
114
            name: 'id',
115
            'min-width': '150'
116
          },
117
          {
118
            label: '别名',
119
            name: 'alias',
120
            type: 'input',
121
            'min-width': '150'
122
          },
123
          {
124
            label: '操作',
125
            name: 'custom',
126
            type: 'custom',
127
            fixed: 'right',
128
            width: '100'
129
          }
130
        ],
131
        data: []
132
      }
133
    },
134
    function: {
135
      cdatafForeach: '',
136
      iterator: '',
137
      resultType: ''
138
    }
139
  }
140
);
141
142
const propsMap = ref({
143
  value: 'id',
144
  label: 'name'
145
});
146
const iteratorDataList = ref(databusData?.[logicId]?.customAttrs?.data || []);
147
console.log(iteratorDataList.value);
148
149
const resultTypes = ref([
150
  { value: 'int', label: 'int' },
151
  { value: 'string', label: 'string' },
152
  { value: 'map', label: 'map' },
153
  { value: 'list', label: 'list' }
154
]);
155
156
function changeTextarea(val) {
157
  console.log(val);
158
  panelData.value.function.expression = val;
159
}
160
161
function codeEditorGetCursor(codeData) {
162
  const pos1 = codeData.getCursor;
163
  const pos2 = {};
164
  // console.log('setCode pos1 === ', pos1);
165
  if (pos1) {
166
    pos2.line = pos1.line;
167
    pos2.ch = pos1.ch;
168
    codeData.codeE.setCursor(pos2); // 设置光标位置
169
    codeData.codeE.replaceRange('', pos2); // 替换光标位置的内容
170
  }
171
}
172
173
function setNodeAttrData() {
174
  props.targetNode.cell.setData({
175
    attrsData: panelData.value
176
  });
177
}
178
179
watch(
180
  panelData.value,
181
  () => {
182
    setNodeAttrData();
183
  },
184
  { deep: true }
185
);
186
</script>
187
188
<script>
189
export default {
190
  name: 'PanelForeach'
191
};
192
</script>
193
<style scoped lang="scss">
194
.form-item {
195
  .form-title {
196
    display: flex;
197
    justify-content: space-between;
198
    align-items: center;
199
    margin: 20px 0 10px 0;
200
    h5 {
201
      font-size: 14px;
202
      color: rgba(0, 0, 0, 0.65);
203
    }
204
  }
205
  .form-content {
206
    flex: 1;
207
  }
208
}
209
</style>

+ 0 - 213
src/views/_components/panel/PanelFunction.vue

@ -1,213 +0,0 @@
1
<template>
2
  <div class="http-function">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <div class="content">
13
          <div class="form-item">
14
            <span class="form-item-title">DOMAIN</span>
15
            <common-select
16
              v-model="panelData.function.domain"
17
              :options="domainList"
18
              :props-map="domainMap"
19
              @change="changeDomain(panelData.function.domain)"
20
            ></common-select>
21
          </div>
22
          <div class="form-item">
23
            <span class="form-item-title">NAME</span>
24
            <common-select
25
              v-model="panelData.function.name"
26
              class="select"
27
              :props-map="domainMap"
28
              :options="nameList"
29
              @change="changeName(panelData.function.name)"
30
            ></common-select>
31
          </div>
32
          <h4 class="form-title">函数参数</h4>
33
          <param-item :item-list="panelData.function?.params"></param-item>
34
        </div>
35
      </template>
36
    </common-panel>
37
  </div>
38
</template>
39
40
<script setup>
41
import { ref, watch } from 'vue';
42
import CommonPanel from './common/CommonPanel.vue';
43
import InputOutputTab from './sql-components/InputOutputTab.vue';
44
import ParamItem from './common/ParamItem.vue';
45
import { getFunctionList } from '../../../api/flow';
46
47
const props = defineProps({
48
  targetNode: {
49
    type: Object,
50
    default: () => {}
51
  }
52
});
53
54
const domainList = ref([]);
55
const domainMap = ref({
56
  value: 'code',
57
  label: 'code'
58
});
59
const nameList = ref([]);
60
const paramsResult = ref([]);
61
62
const panelData = ref(
63
  props.targetNode.cell.getData()?.attrsData || {
64
    basicData: {
65
      name: props.targetNode.cell.getData().label,
66
      desc: ''
67
    },
68
    inputOutput: {
69
      input: {
70
        header: [
71
          // {
72
          //   label: '模型名称',
73
          //   name: 'modelName',
74
          //   'min-width': '150'
75
          // },
76
          // {
77
          //   label: '输入',
78
          //   name: 'input',
79
          //   'min-width': '150'
80
          // },
81
          {
82
            label: 'ID',
83
            name: 'id',
84
            'min-width': '150'
85
          },
86
          {
87
            label: '名称',
88
            name: 'name',
89
            'min-width': '150'
90
          },
91
          {
92
            label: '类型',
93
            name: 'type',
94
            'min-width': '150'
95
          },
96
          {
97
            label: '别名',
98
            name: 'alias',
99
            type: 'input',
100
            'min-width': '150'
101
          },
102
          {
103
            label: '操作',
104
            name: 'custom',
105
            type: 'custom',
106
            fixed: 'right',
107
            width: '100'
108
          }
109
        ],
110
        data: []
111
      },
112
      output: {
113
        header: [
114
          {
115
            label: 'ID',
116
            name: 'id',
117
            'min-width': '150'
118
          },
119
          {
120
            label: '别名',
121
            name: 'alias',
122
            type: 'input',
123
            'min-width': '150'
124
          },
125
          {
126
            label: '操作',
127
            name: 'custom',
128
            type: 'custom',
129
            fixed: 'right',
130
            width: '100'
131
          }
132
        ],
133
        data: []
134
      }
135
    },
136
    function: {
137
      domain: '',
138
      name: '',
139
      params: []
140
    }
141
  }
142
);
143
144
function setNodeAttrData() {
145
  props.targetNode.cell.setData({
146
    attrsData: panelData.value
147
  });
148
}
149
150
// 初始化数据
151
// function initData() {
152
//   if (panelData.value.function.domain) {
153
//     changeDomain(panelData.value.function.domain);
154
//   }
155
//   if (panelData.value.function.name) {
156
//     changeName(panelData.value.function.name);
157
//   }
158
// }
159
160
async function getList() {
161
  await getFunctionList()
162
    .then((res) => {
163
      domainList.value = res.data.result;
164
    })
165
    .catch((err) => {
166
      console.log(err);
167
    });
168
}
169
getList();
170
// 选择domain
171
function changeDomain(data) {
172
  nameList.value =
173
    domainList.value.filter((el) => el.code === data)[0].children || [];
174
}
175
// 选择name
176
function changeName(data) {
177
  paramsResult.value =
178
    nameList.value.filter((el) => el.code === data)[0].params || [];
179
  panelData.value.function.params = paramsResult.value;
180
}
181
182
watch(
183
  panelData.value,
184
  () => {
185
    setNodeAttrData();
186
  },
187
  { deep: true }
188
);
189
</script>
190
191
<script>
192
export default {
193
  name: 'PanelFunction'
194
};
195
</script>
196
<style scoped lang="scss">
197
.form-title {
198
  color: rgba(0, 0, 0, 0.65);
199
  font-size: 16px;
200
  line-height: 32px;
201
  font-weight: 500;
202
  margin: 15px 0 8px;
203
}
204
.form-item {
205
  display: flex;
206
  justify-content: flex-start;
207
  align-items: center;
208
  line-height: 42px;
209
  .form-item-title {
210
    width: 100px;
211
  }
212
}
213
</style>

+ 14 - 8
src/views/_components/panel/PanelGlobal.vue

@ -431,15 +431,21 @@ function customAttrFn() {
431 431
  //     return item;
432 432
  //   });
433 433
434
  // const newData = [...data, ...table.value.customAttrs.data];
435
  // newData.filter(
436
  //   (item, index) => newData.findIndex((t) => t.id === item.id) === index
437
  // );
438
  // table.value.customAttrs.data = newData;
439
  // table.value.customAttrs.data.map((item) => {
440
  //   item.actions = btns;
441
  //   return item;
442
  // });
434 443
  const data = customDetail.value.attrList;
435
  const newData = [...data, ...table.value.customAttrs.data];
436
  newData.filter(
437
    (item, index) => newData.findIndex((t) => t.id === item.id) === index
438
  );
439
  table.value.customAttrs.data = newData;
440
  table.value.customAttrs.data.map((item) => {
441
    item.actions = btns;
442
    return item;
444
  data.forEach((item) => {
445
    if (!table.value.customAttrs.data.some((el) => el.id === item.id)) {
446
      item.actions = btns;
447
      table.value.customAttrs.data.push(item);
448
    }
443 449
  });
444 450
445 451
  closeDialog();

+ 0 - 308
src/views/_components/panel/PanelHttp.vue

@ -1,308 +0,0 @@
1
<template>
2
  <div class="http-pannel">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <div class="content">
13
          <div class="panel-content">
14
            <!-- 请求参数 -->
15
            <h4 class="form-title">接口参数</h4>
16
            <common-form
17
              :forms="panelData?.function?.forms"
18
              :form-values="panelData?.function?.formValues"
19
            ></common-form>
20
21
            <!-- 请求头 -->
22
            <h4 class="form-title">请求头</h4>
23
            <add-form-item
24
              :datas="panelData?.function?.headers"
25
            ></add-form-item>
26
          </div>
27
        </div>
28
      </template>
29
    </common-panel>
30
  </div>
31
  <dialog-panel
32
    v-if="showSetting"
33
    :dialog-data="dialogData"
34
    @confirm-dialog="confirmSettingDialog"
35
    @close-dialog="closeSettingDialog"
36
  >
37
    <!-- 数据展示 -->
38
    <attr-info
39
      :table="inputOutputDialog"
40
      @checked-attrs="checkedAttrs"
41
    ></attr-info>
42
  </dialog-panel>
43
</template>
44
45
<script setup>
46
import { ref, watch, computed } from 'vue';
47
import { useRoute } from 'vue-router';
48
import CommonPanel from './common/CommonPanel.vue';
49
import AddFormItem from './common/AddFormItem.vue';
50
// import AttrInfo from './common/AttrInfo.vue'
51
import InputOutputTab from './sql-components/InputOutputTab.vue';
52
53
const route = useRoute();
54
55
const props = defineProps({
56
  targetNode: {
57
    type: Object,
58
    default: () => {}
59
  }
60
});
61
const dataBus = JSON.parse(localStorage.getItem('panelGlobal')) || {};
62
const flowId = computed(() => route.query.id);
63
64
const forms = ref([
65
  {
66
    name: 'protocol',
67
    type: 'select',
68
    label: '协议类型',
69
    value: 'HTTP',
70
    attrs: {
71
      col: 1,
72
      options: [
73
        { label: 'HTTP', value: 'HTTP' },
74
        { label: 'HTTPS', value: 'HTTPS' }
75
      ],
76
      clearable: true,
77
      placeholder: '请选择协议类型'
78
    }
79
  },
80
  {
81
    name: 'url',
82
    type: 'input',
83
    label: 'URL',
84
    value: '',
85
    attrs: {
86
      col: 1,
87
      clearable: true,
88
      placeholder: '请输入URL'
89
    }
90
  },
91
  {
92
    name: 'requestType',
93
    type: 'select',
94
    label: '请求方法',
95
    value: 'GET',
96
    attrs: {
97
      col: 1,
98
      options: [
99
        { label: 'GET', value: 'GET' },
100
        { label: 'POST', value: 'POST' },
101
        { label: 'PUT', value: 'PUT' },
102
        { label: 'DELETE', value: 'DELETE' },
103
        { label: 'PATCH', value: 'PATCH' }
104
      ],
105
      clearable: true,
106
      placeholder: '请选择请求方法'
107
    }
108
  },
109
  {
110
    name: 'connTimeout',
111
    type: 'input-num',
112
    label: '连接超时',
113
    value: 30000,
114
    attrs: {
115
      col: 1,
116
      clearable: true,
117
      placeholder: '请输入URL',
118
      step: 1000,
119
      min: 10000
120
    }
121
  },
122
  {
123
    name: 'readTimeout',
124
    type: 'input-num',
125
    label: '读取超时',
126
    value: 70000,
127
    attrs: {
128
      col: 1,
129
      clearable: true,
130
      placeholder: '请输入URL',
131
      min: 10000,
132
      step: 1000
133
    }
134
  }
135
]);
136
137
watch(
138
  forms.value,
139
  (list) => {
140
    list.forEach((item) => {
141
      panelData.value.function.formValues[item.name] = item.value;
142
    });
143
    panelData.value.function.forms = forms.value;
144
  },
145
  { deep: true }
146
);
147
const panelData = ref(
148
  props.targetNode.cell.getData()?.attrsData || {
149
    basicData: {
150
      name: props.targetNode.cell.getData().label,
151
      desc: ''
152
    },
153
    inputOutput: {
154
      input: {
155
        header: [
156
          // {
157
          //   label: '模型名称',
158
          //   name: 'modelName',
159
          //   'min-width': '150'
160
          // },
161
          // {
162
          //   label: '输入',
163
          //   name: 'input',
164
          //   'min-width': '150'
165
          // },
166
          {
167
            label: 'ID',
168
            name: 'id',
169
            'min-width': '150'
170
          },
171
          {
172
            label: '名称',
173
            name: 'name',
174
            'min-width': '150'
175
          },
176
          {
177
            label: '类型',
178
            name: 'type',
179
            'min-width': '150'
180
          },
181
          {
182
            label: '别名',
183
            name: 'alias',
184
            type: 'input',
185
            'min-width': '150'
186
          },
187
          {
188
            label: '操作',
189
            name: 'custom',
190
            type: 'custom',
191
            fixed: 'right',
192
            width: '100'
193
          }
194
        ],
195
        data: []
196
      },
197
      output: {
198
        header: [
199
          {
200
            label: 'ID',
201
            name: 'id',
202
            'min-width': '150'
203
          },
204
          {
205
            label: '别名',
206
            name: 'alias',
207
            type: 'input',
208
            'min-width': '150'
209
          },
210
          {
211
            label: '操作',
212
            name: 'custom',
213
            type: 'custom',
214
            fixed: 'right',
215
            width: '100'
216
          }
217
        ],
218
        data: []
219
      }
220
    },
221
    function: {
222
      formValues: {
223
        protocol: 'HTTP',
224
        url: '',
225
        requestType: 'GET',
226
        connTimeout: 30000,
227
        readTimeout: 70000
228
      },
229
      forms: forms.value,
230
      headers: [
231
        {
232
          key: '',
233
          value: ''
234
        }
235
      ]
236
    }
237
  }
238
);
239
240
function setNodeAttrData() {
241
  props.targetNode.cell.setData({
242
    attrsData: panelData.value
243
  });
244
}
245
246
watch(
247
  panelData.value,
248
  () => {
249
    setNodeAttrData();
250
  },
251
  { deep: true }
252
);
253
254
const dialogData = ref({
255
  title: '输入模型/属性引入'
256
});
257
const inputOutputDialog = ref({
258
  modelAttrs: {
259
    header: [{ label: '模型属性', name: 'modelAttrs', 'min-width': '150' }],
260
    data: dataBus[flowId.value]?.modelAttrs?.data || []
261
  },
262
  customAttrs: {
263
    header: [
264
      { label: 'ID', name: 'id', 'min-width': '150' },
265
      { label: '名称', name: 'name', 'min-width': '150' }
266
    ],
267
    data: dataBus[flowId.value]?.customAttrs?.data || []
268
  },
269
  models: {
270
    header: [{ label: '模型', name: 'model', 'min-width': '150' }],
271
    data: dataBus[flowId.value]?.models?.data || []
272
  }
273
});
274
275
function checkedAttrs(data) {
276
  console.log(data);
277
  panelData.value.inputOutput.output.table.data = data.customAttrs;
278
}
279
function closeSettingDialog() {
280
  showSetting.value = false;
281
}
282
function confirmSettingDialog() {
283
  closeSettingDialog();
284
}
285
const showSetting = ref(false);
286
</script>
287
288
<script>
289
export default {
290
  name: 'PanelHttp'
291
};
292
</script>
293
294
<style scoped lang="scss">
295
.form-title {
296
  color: rgba(0, 0, 0, 0.65);
297
  font-size: 16px;
298
  line-height: 32px;
299
  font-weight: 500;
300
  margin: 15px 0 8px;
301
}
302
.btns {
303
  display: flex;
304
  justify-content: space-between;
305
  align-items: center;
306
  margin: 10px 0 20px 0;
307
}
308
</style>

+ 0 - 364
src/views/_components/panel/PanelSql.vue

@ -1,364 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <el-tabs v-model="activeName" @tab-click="handleClick">
4
      <el-tab-pane label="基础" name="action">
5
        <!--  普通设置 -->
6
        <el-form
7
          :model="panelData.basicData"
8
          :rules="formRules"
9
          label-position="top"
10
        >
11
          <el-form-item label="服务名称" prop="name">
12
            <el-input
13
              v-model="panelData.basicData.name"
14
              placeholder="请输入场景名"
15
              @change="changeName"
16
            ></el-input>
17
          </el-form-item>
18
          <el-form-item label="服务描述">
19
            <el-input
20
              v-model="panelData.basicData.desc"
21
              type="textarea"
22
              clearable
23
              :autosize="{ minRows: 10, maxRows: 20 }"
24
              maxlength="200"
25
              show-word-limit
26
              placeholder="请输入服务描述"
27
            ></el-input>
28
          </el-form-item>
29
        </el-form>
30
        <!-- 高级设置 -->
31
      </el-tab-pane>
32
      <el-tab-pane label="输入输出" name="input-output">
33
        <input-output-tab
34
          :input-output="panelData.inputOutput"
35
        ></input-output-tab>
36
      </el-tab-pane>
37
38
      <el-tab-pane label="功能" name="function">
39
        <div class="form-item">
40
          <div class="form-title">
41
            <h5>数据源</h5>
42
          </div>
43
          <common-select
44
            v-model="panelData.function.datasource"
45
            class="int-select"
46
            :props-map="propsMap"
47
            :options="datasources"
48
          ></common-select>
49
        </div>
50
        <div class="form-item">
51
          <div class="form-title">
52
            <h5>SQL脚本</h5>
53
            <el-button type="success" @click.stop="sqlEditor">
54
              脚本编辑器
55
            </el-button>
56
          </div>
57
          <el-input
58
            v-model="panelData.function.sql"
59
            v-bind="attributes"
60
            disabled
61
          ></el-input>
62
          <!-- <div class="editor">
63
            <my-code
64
              :editorValue="panelData.function.sql"
65
              @changeTextarea="changeTextarea"
66
            ></my-code>
67
          </div> -->
68
        </div>
69
      </el-tab-pane>
70
    </el-tabs>
71
  </div>
72
73
  <dialog-panel
74
    v-if="showSqlEditor"
75
    :dialog-data="dialogData"
76
    @confirm-dialog="confirmSqlDialog"
77
    @close-dialog="closeSqlEditor"
78
  >
79
    <!-- <el-input
80
      v-model="panelData.function.sql"
81
      v-bind="attributes"
82
    >
83
    </el-input> -->
84
    <div class="editor">
85
      <my-code
86
        :editor-value="panelData.function.sql"
87
        @update:editor-value="panelData.function.sql = $event"
88
        @change-textarea="changeTextarea"
89
        @code-editor-get-cursor="codeEditorGetCursor"
90
      ></my-code>
91
    </div>
92
  </dialog-panel>
93
</template>
94
95
<script setup>
96
// import DialogSqlEditor from '../dialog/DialogSqlEditor.vue'
97
import { getCurrentInstance, reactive, ref, watch } from 'vue';
98
import MyCode from '../_codemirror/MyCode.vue';
99
import InputOutputTab from './sql-components/InputOutputTab.vue';
100
import { getSqlList } from '../../../api/flow';
101
102
const { proxy } = getCurrentInstance();
103
const props = defineProps({
104
  targetNode: {
105
    type: Object,
106
    default: () => {}
107
  }
108
});
109
110
function changeName() {
111
  props.targetNode.cell.setData({
112
    label: panelData.value.basicData.name
113
  });
114
}
115
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
116
117
const panelData = ref(
118
  nodePanelData.value || {
119
    basicData: {
120
      name: props.targetNode.cell.getData().label,
121
      desc: ''
122
    },
123
    inputOutput: {
124
      input: {
125
        header: [
126
          {
127
            label: 'ID',
128
            name: 'id',
129
            'min-width': '150'
130
          },
131
          {
132
            label: '名称',
133
            name: 'name',
134
            'min-width': '150'
135
          },
136
          {
137
            label: '类型',
138
            name: 'type',
139
            'min-width': '150'
140
          },
141
          {
142
            label: '别名',
143
            name: 'alias',
144
            type: 'input',
145
            'min-width': '150'
146
          },
147
          {
148
            label: '操作',
149
            name: 'custom',
150
            type: 'custom',
151
            fixed: 'right',
152
            width: '100'
153
          }
154
        ],
155
        data: []
156
      },
157
      output: {
158
        header: [
159
          {
160
            label: 'ID',
161
            name: 'id',
162
            'min-width': '150'
163
          },
164
          {
165
            label: '别名',
166
            name: 'alias',
167
            type: 'input',
168
            'min-width': '150'
169
          },
170
          {
171
            label: '操作',
172
            name: 'custom',
173
            type: 'custom',
174
            fixed: 'right',
175
            width: '100'
176
          }
177
        ],
178
        data: []
179
      }
180
    },
181
    function: {
182
      datasource: '',
183
      sql: ''
184
    }
185
  }
186
);
187
188
function changeTextarea(val) {
189
  console.log(val);
190
  panelData.value.function.sql = val;
191
}
192
193
function codeEditorGetCursor(codeData) {
194
  const pos1 = codeData.getCursor;
195
  const pos2 = {};
196
  // console.log('setCode pos1 === ', pos1);
197
  if (pos1) {
198
    pos2.line = pos1.line;
199
    pos2.ch = pos1.ch;
200
    codeData.codeE.setCursor(pos2); // 设置光标位置
201
    codeData.codeE.replaceRange('', pos2); // 替换光标位置的内容
202
  }
203
}
204
205
const activeName = ref('action');
206
207
const baseInit = () => {
208
  const basicData = ref(
209
    nodePanelData.value || {
210
      name: props.targetNode.cell.getData().label,
211
      desc: ''
212
    }
213
  );
214
  // 高级设置
215
  const seniorData = ref({
216
    nodeId: '',
217
    nextNode: ''
218
  });
219
  const formRules = reactive({
220
    name: [
221
      {
222
        required: true,
223
        message: '请输入服务名称',
224
        trigger: 'blur'
225
      },
226
      { min: 3, max: 100, message: '名称在3-100之间', trigger: 'blur' }
227
    ]
228
  });
229
  const showMoreSettings = ref(false);
230
  return {
231
    basicData,
232
    seniorData,
233
    formRules,
234
    showMoreSettings
235
  };
236
};
237
238
const { formRules } = baseInit();
239
240
// const sql = ref('')
241
242
// const datasource = ref('')
243
const datasources = ref([]);
244
const attributes = ref({
245
  type: 'textarea',
246
  autosize: { minRows: 20, maxRows: 50 }
247
});
248
249
// 脚本编辑器
250
const showSqlEditor = ref(false);
251
function sqlEditor() {
252
  showSqlEditor.value = true;
253
}
254
const dialogData = ref({
255
  title: 'SQL编辑器'
256
});
257
258
function closeSqlEditor() {
259
  showSqlEditor.value = false;
260
}
261
262
function confirmSqlDialog(data) {
263
  closeSqlEditor();
264
}
265
266
function setNodeAttrData() {
267
  props.targetNode.cell.setData({
268
    attrsData: panelData.value
269
  });
270
}
271
272
const propsMap = ref({
273
  value: 'sqlConn',
274
  label: 'showName'
275
});
276
// 获取数据库列表
277
function getList() {
278
  getSqlList()
279
    .then((res) => {
280
      if (res.data.resultCode === '0') {
281
        datasources.value = res.data.result.map((item) => {
282
          item.sqlConn = `business_${item?.id || ''}`;
283
          item.showName = `${item.code}-${item.name}-${item.ip || ''}${
284
            item.port || ''
285
          }${item.path || ''}`;
286
          return item;
287
        });
288
      } else {
289
        datasources.value = [];
290
        proxy.$message.error(res.data.resultMsg);
291
      }
292
    })
293
    .catch((err) => {
294
      console.log(err);
295
      datasources.value = [];
296
    });
297
}
298
getList();
299
watch(
300
  panelData.value,
301
  () => {
302
    setNodeAttrData();
303
  },
304
  { deep: true }
305
);
306
</script>
307
308
<script>
309
export default {
310
  name: 'PanelSql'
311
};
312
</script>
313
<style scoped lang="scss">
314
.form-item {
315
  .form-title {
316
    display: flex;
317
    justify-content: space-between;
318
    align-items: center;
319
    margin: 20px 0 10px 0;
320
    h5 {
321
      font-size: 14px;
322
      color: rgba(0, 0, 0, 0.65);
323
    }
324
  }
325
}
326
.collapse {
327
  display: flex;
328
  justify-content: flex-start;
329
  align-items: center;
330
  margin: 30px 0;
331
  .icon {
332
    margin: 0 10px;
333
    font-size: 16px;
334
  }
335
  .line {
336
    flex: 1;
337
    height: 1px;
338
    background: rgba(0, 0, 0, 0.09);
339
  }
340
}
341
342
// .editor{
343
//   width: 98%;
344
//   border: 1px solid rgba(0,0,0,0.1);
345
//   :deep(.CodeMirror-gutter){
346
//     width: 30px!important;
347
//   }
348
349
//   :deep(.CodeMirror-gutter-wrapper){
350
//     left: -30px!important;
351
//   }
352
353
//   :deep(.CodeMirror-code){
354
//     padding-left: 30px!important;
355
//   }
356
//   :deep(.CodeMirror-cursors){
357
//     left: 30px;
358
//   }
359
360
// }
361
.int-select {
362
  width: 100%;
363
}
364
</style>

+ 0 - 220
src/views/_components/panel/PanelStart.vue

@ -1,220 +0,0 @@
1
<template>
2
  <div class="panel-start">
3
    <el-tabs v-model="activeName">
4
      <el-tab-pane label="功能" name="action">
5
        <el-button type="success" @click="importData">引入</el-button>
6
        <common-table
7
          class="table"
8
          :table-header="tableHeader"
9
          :table-data="panelData.function.tableData"
10
        >
11
          <template #custom="scope">
12
            <!-- 删除 -->
13
            <el-popconfirm
14
              title="确定要移除该属性吗?"
15
              @confirm="confirmEvent(scope.row)"
16
              @cancel="cancelEvent"
17
            >
18
              <template #reference>
19
                <el-icon class="icon"><Delete></Delete></el-icon>
20
              </template>
21
            </el-popconfirm>
22
          </template>
23
        </common-table>
24
      </el-tab-pane>
25
    </el-tabs>
26
  </div>
27
  <!-- 引入弹窗 -->
28
  <dialog-panel
29
    v-if="showImport"
30
    :dialog-data="dialogData"
31
    @confirm-dialog="confirmModelDialog"
32
    @close-dialog="closeModelDialog"
33
  >
34
    <!-- 选择 -->
35
    <el-radio-group v-model="selectTab">
36
      <el-radio-button label="attributes">自定义属性</el-radio-button>
37
      <el-radio-button label="models">模型</el-radio-button>
38
    </el-radio-group>
39
40
    <!-- 数据展示 -->
41
    <common-table
42
      class="table"
43
      :table-header="table[selectTab].header"
44
      :table-data="table[selectTab].data"
45
      :is-check="true"
46
      @selection-change="handleSelectChange"
47
    ></common-table>
48
  </dialog-panel>
49
</template>
50
51
<script setup>
52
import { computed, ref, watch } from 'vue';
53
import { useRoute } from 'vue-router';
54
55
const route = useRoute();
56
const dataBus = JSON.parse(localStorage.getItem('panelGlobal')) || {};
57
const flowId = computed(() => route.query.id);
58
59
const props = defineProps({
60
  targetNode: {
61
    type: Object,
62
    default: () => {}
63
  }
64
});
65
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
66
const panelData = ref(
67
  nodePanelData.value || {
68
    basicData: {},
69
    inputOutput: {},
70
    function: {
71
      tableData: []
72
    }
73
  }
74
);
75
const tableHeader = ref([
76
  {
77
    label: 'ID',
78
    name: 'id',
79
    'min-width': '150'
80
  },
81
  {
82
    label: '名称',
83
    name: 'name',
84
    'min-width': '150'
85
  },
86
  {
87
    label: '类型',
88
    name: 'type',
89
    'min-width': '150'
90
  },
91
  {
92
    label: '描述',
93
    name: 'desc',
94
    'min-width': '150'
95
  },
96
  {
97
    label: '操作',
98
    name: 'custom',
99
    type: 'custom',
100
    fixed: 'right',
101
    width: '100'
102
  }
103
]);
104
105
watch(
106
  panelData,
107
  () => {
108
    setNodeAttrData();
109
  },
110
  { deep: true }
111
);
112
113
// 存储到节点中
114
function setNodeAttrData() {
115
  props.targetNode.cell.setData({
116
    attrsData: panelData.value
117
  });
118
}
119
// 开始节点
120
function initStartNode() {
121
  const activeName = ref('action');
122
  // 引入
123
  const dialogData = ref({
124
    title: '引入'
125
  });
126
  const showImport = ref(false);
127
  function importData() {
128
    showImport.value = true;
129
  }
130
  function closeModelDialog() {
131
    showImport.value = false;
132
  }
133
  function confirmModelDialog() {
134
    panelData.value.function.tableData = checkedAttrs.value;
135
    closeModelDialog();
136
  }
137
  function confirmEvent(row) {
138
    panelData.value.function.tableData.forEach((item, index) => {
139
      if (item.id === row.id) {
140
        panelData.value.function.tableData.splice(index, 1);
141
      }
142
    });
143
  }
144
  function cancelEvent() {}
145
  return {
146
    activeName,
147
    dialogData,
148
    showImport,
149
    importData,
150
    confirmEvent,
151
    closeModelDialog,
152
    confirmModelDialog
153
  };
154
}
155
156
const {
157
  activeName,
158
  dialogData,
159
  showImport,
160
  importData,
161
  confirmEvent,
162
  closeModelDialog,
163
  confirmModelDialog
164
} = initStartNode();
165
166
// 设置弹窗信息
167
function setDialogInfo() {
168
  const selectTab = ref('attributes');
169
  const checkedAttrs = ref([]);
170
  const table = ref({
171
    models: {
172
      header: [
173
        {
174
          label: '模型',
175
          name: 'model',
176
          'min-width': '150'
177
        },
178
        {
179
          label: '已选属性',
180
          name: 'attributes',
181
          'min-width': '150'
182
        }
183
      ],
184
      data: []
185
    },
186
    attributes: {
187
      header: [
188
        {
189
          label: '属性',
190
          name: 'id',
191
          'min-width': '150'
192
        },
193
        {
194
          label: '名称',
195
          name: 'name',
196
          'min-width': '150'
197
        }
198
      ],
199
      data: dataBus?.[flowId.value]?.customAttrs?.data || []
200
    }
201
  });
202
  const handleSelectChange = (checkeds) => {
203
    checkedAttrs.value = checkeds;
204
  };
205
  return { selectTab, table, checkedAttrs, handleSelectChange };
206
}
207
208
const { selectTab, table, checkedAttrs, handleSelectChange } = setDialogInfo();
209
</script>
210
211
<script>
212
export default {
213
  name: 'PanelStart'
214
};
215
</script>
216
<style scoped lang="scss">
217
.table {
218
  margin-top: 10px;
219
}
220
</style>

+ 0 - 169
src/views/_components/panel/PanelSubFlow.vue

@ -1,169 +0,0 @@
1
<template>
2
  <div class="panel-end">
3
    <common-panel :panel-data="panelData" :target-node="targetNode">
4
      <template #input-output>
5
        <div class="content">
6
          <input-output-tab
7
            :input-output="panelData.inputOutput"
8
          ></input-output-tab>
9
        </div>
10
      </template>
11
      <template #function>
12
        <!-- 功能区域 -->
13
        <div class="form-item">
14
          <div class="form-title">
15
            <h5>子流程</h5>
16
          </div>
17
          <common-select
18
            v-model="panelData.function.datasource"
19
            class="int-select"
20
            :props-map="propsMap"
21
            :options="subflowList"
22
          ></common-select>
23
        </div>
24
        <div class="form-item">
25
          <div class="form-title">
26
            <h5>入参映射</h5>
27
          </div>
28
        </div>
29
        <div class="form-item">
30
          <div class="form-title">
31
            <h5>出参映射</h5>
32
          </div>
33
        </div>
34
      </template>
35
    </common-panel>
36
  </div>
37
</template>
38
39
<script setup>
40
import { ref, watchEffect, onMounted } from 'vue';
41
import CommonPanel from './common/CommonPanel.vue';
42
import InputOutputTab from './sql-components/InputOutputTab.vue';
43
import { getSubFlowList } from '../../../api/subflow';
44
45
const subflowList = ref([]);
46
const propsMap = ref({
47
  label: 'name',
48
  value: 'id'
49
});
50
const props = defineProps({
51
  targetNode: {
52
    type: Object,
53
    default: () => {}
54
  }
55
});
56
57
const nodePanelData = ref(props.targetNode.cell.getData()?.attrsData || null);
58
59
// 弹窗数据
60
const panelData = ref(
61
  nodePanelData.value || {
62
    basicData: {
63
      name: props.targetNode.cell.getData().label,
64
      desc: ''
65
    },
66
    inputOutput: {
67
      input: {
68
        header: [
69
          {
70
            label: 'ID',
71
            name: 'id',
72
            'min-width': '150'
73
          },
74
          {
75
            label: '名称',
76
            name: 'name',
77
            'min-width': '150'
78
          },
79
          {
80
            label: '类型',
81
            name: 'type',
82
            'min-width': '150'
83
          },
84
          {
85
            label: '别名',
86
            name: 'alias',
87
            type: 'input',
88
            'min-width': '150'
89
          },
90
          {
91
            label: '操作',
92
            name: 'custom',
93
            type: 'custom',
94
            fixed: 'right',
95
            width: '100'
96
          }
97
        ],
98
        data: []
99
      },
100
      output: {
101
        header: [
102
          {
103
            label: 'ID',
104
            name: 'id',
105
            'min-width': '150'
106
          },
107
          {
108
            label: '别名',
109
            name: 'alias',
110
            type: 'input',
111
            'min-width': '150'
112
          },
113
          {
114
            label: '操作',
115
            name: 'custom',
116
            type: 'custom',
117
            fixed: 'right',
118
            width: '100'
119
          }
120
        ],
121
        data: []
122
      }
123
    },
124
    // 功能区域
125
    function: {
126
      subflowId: '',
127
      input: [],
128
      output: []
129
    }
130
  }
131
);
132
133
// 获取子流程列表
134
function getFlowList() {
135
  getSubFlowList().then((res) => {
136
    subflowList.value = res.result;
137
  });
138
}
139
140
watchEffect(() => {
141
  props.targetNode.cell.setData({
142
    attrsData: JSON.parse(JSON.stringify(panelData.value))
143
  });
144
});
145
146
onMounted(() => {
147
  getFlowList();
148
});
149
</script>
150
151
<script>
152
export default {
153
  name: 'PanelSubFlow'
154
};
155
</script>
156
<style scoped lang="scss">
157
.form-item {
158
  .form-title {
159
    display: flex;
160
    justify-content: space-between;
161
    align-items: center;
162
    margin: 20px 0 10px 0;
163
    h5 {
164
      font-size: 14px;
165
      color: rgba(0, 0, 0, 0.65);
166
    }
167
  }
168
}
169
</style>

+ 2 - 2
src/views/_components/panel/global/CustomDetail copy.vue

@ -49,8 +49,8 @@ const typeList = reactive([
49 49
  { label: '日期', value: 'date' },
50 50
  { label: '时间', value: 'datetime' },
51 51
  { label: '长整数', value: 'long' },
52
  { label: 'object', value: 'object' },
53
  { label: 'array', value: 'array' }
52
  { label: '对象', value: 'object' },
53
  { label: '数组', value: 'array' }
54 54
]);
55 55
// 表达式列表
56 56

+ 2 - 2
src/views/_components/panel/global/CustomDetail.vue

@ -96,8 +96,8 @@ const typeList = reactive<any>([
96 96
  { label: '日期', value: 'date' },
97 97
  { label: '时间', value: 'datetime' },
98 98
  { label: '长整数', value: 'long' },
99
  { label: 'object', value: 'object' },
100
  { label: 'array', value: 'array' }
99
  { label: '对象', value: 'object' },
100
  { label: '数组', value: 'array' }
101 101
]);
102 102
103 103
const verificationList = reactive<any>([

+ 7 - 2
src/views/_components/right-panel/PanelDataAggregation.vue

@ -33,6 +33,7 @@
33 33
    <panel-data-assembly
34 34
      ref="dataAssembly"
35 35
      :data-source="inputData"
36
      :is-json-path="true"
36 37
    ></panel-data-assembly>
37 38
  </common-dialog>
38 39
</template>
@ -94,7 +95,7 @@ function closeDialog() {
94 95
}
95 96
// 数据确认
96 97
function confirmDialog() {
97
  functionData.value.aggregate = dataAssembly.value.jsonData;
98
  functionData.value.aggregate = dataAssembly.value.jsonpathData;
98 99
  inputData.value = dataAssembly.value.treeData;
99 100
  showDataAssembly.value = false;
100 101
}
@ -114,4 +115,8 @@ export default {
114 115
};
115 116
</script>
116 117
117
<style scoped lang="scss"></style>
118
<style scoped lang="scss">
119
.editor {
120
  height: 420px;
121
}
122
</style>

+ 224 - 29
src/views/_components/right-panel/_components/PanelDataAssembly.vue

@ -6,16 +6,24 @@
6 6
    <!--左树-->
7 7
    <div class="__left">
8 8
      <div class="__up">
9
        <h5 class="title">属性树形结构</h5>
9
        <h5 class="title">
10
          <span>属性树形结构</span>
11
          <div>
12
            <el-button size="small" @click.stop="expandAll">全部展开</el-button>
13
            <el-button size="small" @click.stop="clearAll">全部清除</el-button>
14
          </div>
15
        </h5>
10 16
        <div class="tree-content">
11 17
          <el-tree
12 18
            ref="myTree"
13 19
            :allow-drop="allowDrop"
14 20
            :allow-drag="allowDrag"
15 21
            :data="treeData"
22
            :expand-on-click-node="false"
16 23
            highlight-current
17 24
            draggable
18 25
            :default-expanded-keys="currentNodes"
26
            :default-expand-all="defaultExpandAll"
19 27
            node-key="uuid"
20 28
            @node-click="getCurrentNode"
21 29
            @node-contextmenu="cancelCurrent"
@ -39,6 +47,7 @@
39 47
                  v-model="data.alias"
40 48
                  class="tree-int"
41 49
                  size="small"
50
                  @click.stop
42 51
                ></el-input>
43 52
                <common-icon
44 53
                  name="common-shanchu"
@ -51,6 +60,16 @@
51 60
      </div>
52 61
53 62
      <div class="__down">
63
        <h5>后台jsonpath</h5>
64
        <div class="attr-content">
65
          <JsonEditor
66
            v-model="jsonpathData"
67
            class="editor"
68
            current-mode="code"
69
            :mode-list="['code']"
70
            @blur="validate"
71
          ></JsonEditor>
72
        </div>
54 73
        <h5 class="title">属性内容</h5>
55 74
        <div class="attr-content">
56 75
          <JsonEditor
@ -65,7 +84,12 @@
65 84
    </div>
66 85
    <!--右列表-->
67 86
    <div class="__right">
68
      <h5 class="title">属性</h5>
87
      <h5 class="title">
88
        <span>数据总线</span>
89
        <el-button size="small" type="primary" @click.stop="quickCreate">
90
          快速创建
91
        </el-button>
92
      </h5>
69 93
      <ul class="tag-list">
70 94
        <li v-for="(item, index) in tagList" :key="index">
71 95
          <h5 class="tag-title">
@ -82,12 +106,21 @@
82 106
                {{ tag.name }}
83 107
              </span>
84 108
            </template>
85
            <!-- <el-button size="small" @click.stop="">快速创建</el-button> -->
86 109
          </div>
87 110
        </li>
88 111
      </ul>
89 112
    </div>
90 113
  </div>
114
115
  <common-dialog
116
    v-if="showAttrDialog"
117
    title="新增自定义属性"
118
    @close-dialog="closeDialog"
119
    @confirm-dialog="confirmDialog"
120
  >
121
    <!-- 自定义属性 -->
122
    <CustomDetail ref="customDetail" :attr-info="attrInfo"></CustomDetail>
123
  </common-dialog>
91 124
</template>
92 125
93 126
<script setup lang="ts">
@ -103,21 +136,24 @@ import JsonEditor from 'json-editor-vue3';
103 136
import { v4 as uuidv4 } from 'uuid';
104 137
import { useRoute } from 'vue-router';
105 138
139
import CustomDetail from '../../panel/global/CustomDetail.vue';
140
106 141
const { proxy } = getCurrentInstance();
107 142
const route = useRoute();
108 143
109 144
const systemId = route.query.id;
110
111
const dataBus = JSON.parse(localStorage.getItem('panelGlobal'))?.[
112
  `${systemId}`
113
];
114
const customAttrs = dataBus?.customAttrs?.data || [];
115
console.log(customAttrs);
145
const panelGlobal = JSON.parse(localStorage.getItem('panelGlobal'));
146
const dataBus = panelGlobal?.[`${systemId}`];
147
const customAttrs = ref<any>(dataBus?.customAttrs?.data || []);
116 148
117 149
const props = defineProps({
118 150
  dataSource: {
119 151
    type: Array,
120 152
    default: () => []
153
  },
154
  isJsonPath: {
155
    type: Boolean,
156
    default: () => false
121 157
  }
122 158
});
123 159
// 源数据
@ -134,6 +170,7 @@ const tagList = ref<any>([
134 170
]);
135 171
const treeData = ref<any>([...props.dataSource] || []);
136 172
const jsonData = ref<any>({});
173
const jsonpathData = ref<any>({});
137 174
138 175
const currentNode = ref<any>({});
139 176
const myTree = ref<any>(null);
@ -144,14 +181,16 @@ function formateSourceData(data: any) {
144 181
    data.forEach((tag: any) => {
145 182
      if (tag.type === item.type) {
146 183
        tag.alias = '';
147
        item.tags.push(tag);
184
        if (!item.tags.some((el: any) => el.id === tag.id)) {
185
          item.tags.push(tag);
186
        }
148 187
      }
149 188
    });
150 189
    return item;
151 190
  });
152 191
}
153 192
154
formateSourceData(customAttrs);
193
formateSourceData(customAttrs.value);
155 194
/**
156 195
 * el-tree拖拽start
157 196
 */
@ -175,7 +214,7 @@ const allowDrag = (draggingNode: any) => {
175 214
  console.log(draggingNode);
176 215
  return true;
177 216
};
178
217
const defaultExpandAll = ref(false);
179 218
function handleDragStart() {}
180 219
function handleDragEnter() {}
181 220
function handleDragLeave() {}
@ -183,6 +222,15 @@ function handleDragOver() {}
183 222
function handleDragEnd() {}
184 223
function handleDrop() {}
185 224
225
// 展开全部
226
function expandAll() {
227
  defaultExpandAll.value = true;
228
}
229
// 清除树组件数据
230
function clearAll() {
231
  treeData.value = [];
232
}
233
186 234
// 获取当前节点
187 235
function getCurrentNode(node: any) {
188 236
  if (currentNode.value === node) {
@ -207,10 +255,25 @@ function handleClickTag(tag: any) {
207 255
    type: tag.type,
208 256
    children: []
209 257
  };
258
  if (tag.type === 'array') {
259
    proxy
260
      .$confirm('需要创建有迭代器的数组吗?', '提示', {
261
        confirmButtonText: '是的',
262
        cancelButtonText: '不是',
263
        type: 'warning'
264
      })
265
      .then(() => {
266
        newChild.type = 'array-interator';
267
      })
268
      .catch(() => {
269
        newChild.type = 'array-null';
270
      });
271
  }
272
210 273
  if (currentNode.value?.type) {
211 274
    if (
212 275
      currentNode.value?.type === 'object' ||
213
      currentNode.value?.type === 'array'
276
      currentNode.value?.type.indexOf('array') > -1
214 277
    ) {
215 278
      if (
216 279
        !currentNode.value.children.some((el: any) => el.name === newChild.name)
@ -228,11 +291,12 @@ function handleClickTag(tag: any) {
228 291
  } else {
229 292
    treeData.value.push(newChild);
230 293
  }
294
295
  console.log(JSON.stringify(treeData.value));
296
231 297
  nextTick(() => {
232 298
    myTree.value.setCurrentKey(currentNode.value.uuid);
233 299
  });
234
  // myTree.value.updateKeyChildren(treeData.value[0]);
235
  // console.log(myTree.value.getCurrentKey());
236 300
}
237 301
238 302
function cancelCurrent() {
@ -266,6 +330,8 @@ const defaultvalueMap = <any>{
266 330
  int: 0,
267 331
  boolean: false,
268 332
  array: [],
333
  'array-interator': [],
334
  'array-null': [],
269 335
  long: 0,
270 336
  date: '',
271 337
  datetime: '',
@ -273,19 +339,103 @@ const defaultvalueMap = <any>{
273 339
};
274 340
275 341
// 数据处理
276
function tree2json(data: any[], type: 'array' | 'object'): any {
342
function tree2json(
343
  data: any[],
344
  type: 'array-interator' | 'array-null' | 'object'
345
): any {
277 346
  const obj: any = {};
278
  data.forEach((item) => {
279
    const { children } = item;
280
    if (children && children.length) {
281
      const childType = item.type;
282
      obj[item.id] = tree2json(children, childType as 'array' | 'object');
283
    } else {
284
      // obj[item.name] = assignment(item.type);
285
      obj[item.id] = defaultvalueMap[item.type];
347
  data.map(({ children = [], type, alias, id }) => {
348
    const key = alias || id;
349
    obj[key] = children.length
350
      ? tree2json(children, type)
351
      : defaultvalueMap[type];
352
    return null;
353
  });
354
  return type.indexOf('array') > -1 ? [obj] : obj;
355
}
356
357
/**
358
 *
359
 * @param data 数据源
360
 * @param type 数据类型
361
 * 方法说明:
362
 * 1. 正常取值转换,通过对databus中的基础数据进行直接赋值的操作;
363
 * 2. 对象型数据转换,从模型中取数进行数据的赋值;
364
 * 3. 数组数据转换;1)需要迭代器的数据格式;2)不需要迭代器的数据格式;
365
 */
366
367
// tree to jsonpath
368
function arrayNullFunc(item: any) {
369
  const { children, id } = item;
370
  let values;
371
  if (children.length) {
372
    values = children.map((child: any) => {
373
      if (child.type === 'array-null' && child.children.length) {
374
        const childKey = child.alias || child.id;
375
        return {
376
          [childKey]: {
377
            _$$_isInterator: false,
378
            _$$_interator: '',
379
            values: arrayNullFunc(child)
380
          }
381
        };
382
      }
383
      if (
384
        (child.type === 'object' || child.type === 'array-interator') &&
385
        child.children.length
386
      ) {
387
        // eslint-disable-next-line no-use-before-define
388
        return tree2Jsonpath(child.children);
389
      }
390
      return `$.${child.id}`;
391
    });
392
  } else {
393
    values = `$.${id}`;
394
  }
395
  return values;
396
}
397
function tree2Jsonpath(data: any) {
398
  const result = {};
399
  const typeMap = {
400
    'array-null': (item: any) => {
401
      const { id, alias } = item;
402
      const key = alias || id;
403
404
      const values = arrayNullFunc(item);
405
      result[key] = {
406
        _$$_isInterator: false,
407
        _$$_interator: '',
408
        values
409
      };
410
    },
411
    'array-interator': (item: any) => {
412
      const { children, id, alias } = item;
413
      const key = alias || id;
414
      result[key] = {
415
        _$$_isInterator: true,
416
        _$$_interator: `$.${id}`,
417
        values: [tree2Jsonpath(children)]
418
      };
419
    },
420
    object: (item: any) => {
421
      const { children, id, alias } = item;
422
      const key = alias || id;
423
      result[key] = tree2Jsonpath(children);
424
    },
425
    default: (item: any) => {
426
      const { id, alias } = item;
427
      const key = alias || id;
428
      result[key] = `$.${id}`;
286 429
    }
430
  };
431
432
  data.forEach((item: any) => {
433
    const { type } = item;
434
    const fn = typeMap[type] || typeMap.default;
435
    fn(item);
287 436
  });
288
  return type === 'array' ? [obj] : obj;
437
438
  return result;
289 439
}
290 440
291 441
function validate() {}
@ -294,14 +444,48 @@ watch(
294 444
  () => {
295 445
    if (treeData.value?.length) {
296 446
      jsonData.value = tree2json(treeData.value, 'object');
297
      // myTree.value.setCurrentKey(currentNode.value.uuid);
447
      jsonpathData.value = tree2Jsonpath(treeData.value);
298 448
    } else {
299 449
      currentNode.value = {};
450
      jsonData.value = {};
451
      jsonpathData.value = {};
300 452
    }
301 453
  },
302 454
  { deep: true }
303 455
);
304 456
457
// 快速创建databus数据
458
const attrInfo = ref<any>([]);
459
const showAttrDialog = ref<any>(false);
460
const customDetail = ref<any>(null);
461
function quickCreate() {
462
  showAttrDialog.value = true;
463
}
464
// 关闭弹窗
465
function closeDialog() {
466
  showAttrDialog.value = false;
467
}
468
function confirmEvent() {}
469
const btns = [
470
  // { label: '编辑', name: 'edit', onClick: editFn },
471
  { label: '删除', name: 'delete', onClick: confirmEvent }
472
];
473
// 确认弹窗
474
function confirmDialog() {
475
  const data = customDetail.value.attrList;
476
  data.forEach((item: any) => {
477
    if (!customAttrs.value.some((el: any) => el.id === item.id)) {
478
      item.actions = btns;
479
      customAttrs.value.push(item);
480
    }
481
  });
482
483
  formateSourceData(customAttrs.value);
484
  dataBus.customAttrs.data = customAttrs.value;
485
  panelGlobal[`${systemId}`] = dataBus;
486
  localStorage.setItem('panelGlobal', JSON.stringify(panelGlobal));
487
  closeDialog();
488
}
305 489
const currentNodes = ref<any>([]);
306 490
307 491
watch(
@ -314,12 +498,14 @@ watch(
314 498
315 499
defineExpose({
316 500
  treeData,
317
  jsonData
501
  jsonData,
502
  jsonpathData
318 503
});
319 504
320 505
onMounted(() => {
321 506
  if (treeData.value?.length) {
322 507
    jsonData.value = tree2json(treeData.value, 'object');
508
    jsonpathData.value = tree2Jsonpath(treeData.value);
323 509
  } else {
324 510
    currentNode.value = {};
325 511
  }
@ -337,7 +523,11 @@ onMounted(() => {
337 523
    width: calc(60% - 7px);
338 524
    .__up {
339 525
      height: calc(50% - 20px);
340
526
      .title {
527
        display: flex;
528
        justify-content: space-between;
529
        margin-bottom: 5px;
530
      }
341 531
      .tree-content {
342 532
        background: #ffffff;
343 533
        border: 1px solid rgba(0, 0, 0, 0.15);
@ -371,7 +561,12 @@ onMounted(() => {
371 561
  .__right {
372 562
    width: calc(40% - 8px);
373 563
    height: 100%;
374
564
    .title {
565
      display: flex;
566
      justify-content: space-between;
567
      align-items: center;
568
      margin-bottom: 5px;
569
    }
375 570
    .tag-list {
376 571
      background-color: #ffffff;
377 572
      border: 1px solid rgba(0, 0, 0, 0.15);

+ 7 - 1
src/views/_components/right-panel/_components/PanelNodeIO.vue

@ -25,12 +25,13 @@
25 25
    <panel-data-assembly
26 26
      ref="dataAssembly"
27 27
      :data-source="inputData.data"
28
      :is-json-path="isJsonPath"
28 29
    ></panel-data-assembly>
29 30
  </common-dialog>
30 31
</template>
31 32
32 33
<script setup lang="ts">
33
import { ref, watch } from 'vue';
34
import { ref, watch, computed } from 'vue';
34 35
import PanelDataAssembly from './PanelDataAssembly.vue';
35 36
36 37
const showDataAssembly = ref<any>(false);
@ -69,6 +70,11 @@ const props = defineProps({
69 70
    default: () => 'input'
70 71
  }
71 72
});
73
const isJsonPath = computed(
74
  () =>
75
    ['polymerization'].includes(props.targetNode.cell.getData().id) &&
76
    props.inputType === 'function'
77
);
72 78
73 79
const nodePanelData = ref<any>(
74 80
  props.targetNode.cell.getData()?.attrsData || null