Browse Source

update: 更新sql节点功能 + 加全局配置 + 全局databus实现导入导出

liuyang 2 years ago
parent
commit
3e2fa15aef

+ 13 - 0
src/App.vue

@ -29,6 +29,7 @@ import { ref, computed, watch } from 'vue';
29 29
import { useStore } from 'vuex';
30 30
import { useRoute } from 'vue-router';
31 31
import logoImg from './assets/images/logo.svg';
32
import { getSystemConfig } from './api/flow';
32 33
33 34
const store = useStore();
34 35
const route = useRoute();
@ -88,6 +89,18 @@ function handleChangeCollapse(collapse: any) {
88 89
89 90
const exposePath = <any>['/flow-module', '/flow-detail'];
90 91
92
// 查询全局配置
93
function getGlobalConfig() {
94
  getSystemConfig().then((res) => {
95
    if (res.resultCode === '0') {
96
      localStorage.setItem('GLOBAL_CONFIG', JSON.stringify(res.result));
97
    } else {
98
      localStorage.setItem('GLOBAL_CONFIG', '{}');
99
    }
100
  });
101
}
102
103
getGlobalConfig();
91 104
watch(
92 105
  route,
93 106
  () => {

+ 25 - 0
src/api/flow.ts

@ -225,3 +225,28 @@ export function getServiceDetail(data: any) {
225 225
    data
226 226
  });
227 227
}
228
229
export const otherApi = {
230
  getSqlList: '/df/ipu/sql/getSqlWithPage',
231
  downloadTemplate: 'ipu/file/databusTemplate/download',
232
  getSystemConfig: 'ipu/config/value'
233
};
234
235
// 获取接口详情
236
export function getSqlServiceList(data: any): Promise<any> {
237
  return AIotRequest.post({
238
    url: otherApi.getSqlList,
239
    data
240
  });
241
}
242
// 模板下载
243
export function downloadTemplaye() {
244
  return otherApi.downloadTemplate;
245
}
246
247
// 查询全局配置
248
export function getSystemConfig() {
249
  return AIotRequest.get({
250
    url: otherApi.getSystemConfig
251
  });
252
}

+ 16 - 123
src/views/_components/panel/PanelGlobal.vue

@ -54,15 +54,10 @@
54 54
            <el-button @click.stop="viewCustomDetail">查看列表详情</el-button>
55 55
            <!-- <el-button @click.stop="downloadModule">模板下载</el-button> -->
56 56
          </span>
57
          <el-upload
58
            action
59
            accept=".xlsx, .xls"
60
            :auto-upload="false"
61
            :show-file-list="false"
62
            :on-change="useExcelHooks"
63
          >
64
            <el-button type="success">快速创建</el-button>
65
          </el-upload>
57
58
          <el-button type="success" @click.stop="handleClickImport">
59
            导入导出
60
          </el-button>
66 61
        </div>
67 62
      </el-tab-pane>
68 63
@ -82,13 +77,6 @@
82 77
      :table-data="table[activeName]?.data"
83 78
    >
84 79
      <template #custom="scope">
85
        <!-- <el-icon
86
          v-if="activeName === 'customAttrs'"
87
          class="icon"
88
          @click="editFn(scope.row)"
89
        >
90
          <Edit></Edit>
91
        </el-icon> -->
92 80
        <common-icon
93 81
          v-if="activeName === 'customAttrs'"
94 82
          name="common-bianji"
@ -131,13 +119,16 @@
131 119
      v-if="dialogType === 'viewCustomDetail'"
132 120
      :attr-datas="table.customAttrs.data"
133 121
    ></custom-detail-list>
122
123
    <!-- 上传下载 -->
124
    <custom-import v-if="dialogType === 'fileImport'"></custom-import>
134 125
  </dialog-panel>
135 126
</template>
136 127
137 128
<script setup>
138 129
import { computed, reactive, ref, watch } from 'vue';
139 130
140
import XLSX from 'xlsx';
131
// import XLSX from 'xlsx';
141 132
// 模型属性引入
142 133
import { useRoute } from 'vue-router';
143 134
import { useStore } from 'vuex';
@ -145,6 +136,7 @@ import { useStore } from 'vuex';
145 136
import ImportModel from './global/ImportModel.vue';
146 137
import CustomDetailList from './global/CustomDetailList.vue';
147 138
import CustomDetail from './global/CustomDetail.vue';
139
import CustomImport from './global/CustomImport.vue';
148 140
149 141
const activeName = ref('customAttrs');
150 142
const route = useRoute();
@ -256,6 +248,10 @@ const dialog = ref({
256 248
  modelAttrImport: {
257 249
    title: '模型属性声明',
258 250
    name: 'modelAttrs'
251
  },
252
  fileImport: {
253
    title: '属性导入',
254
    name: 'fileImport'
259 255
  }
260 256
});
261 257
@ -416,113 +412,10 @@ function customAttrFn() {
416 412
417 413
  closeDialog();
418 414
}
419
420
// excel表数据处理
421
const tableData = ref([]);
422
function useExcelHooks(e) {
423
  const result = ref([]);
424
425
  // 文件读取
426
  function readFile(file) {
427
    return new Promise((resolve) => {
428
      const reader = new FileReader();
429
      reader.readAsBinaryString(file);
430
      reader.onload = (e) => {
431
        resolve(e.target.result);
432
      };
433
    });
434
  }
435
  function parseTableData(data) {
436
    tableData.value = [];
437
    if (Array.isArray(data) && data.length) {
438
      let el = {};
439
      data.forEach((item) => {
440
        el = {
441
          id: item.id,
442
          isValidate: item.isValidate || '',
443
          name: item.name || '',
444
          type: item.type || '',
445
          validateRules: {
446
            equal: item.equal || '',
447
            less: item.less || '',
448
            max: item.max || '',
449
            min: item.min || '',
450
            more: item.more || '',
451
            nullable: item.nullable || false,
452
            precision: item.precision || '',
453
            scale: item.scale || '',
454
            unequal: item.unequal || ''
455
          }
456
        };
457
        tableData.value.push(el);
458
      });
459
    }
460
  }
461
  function duplication(data) {
462
    const set = new Set();
463
    data.forEach((item) => set.add(item));
464
    return Array.from(set);
465
  }
466
  function unique(arr) {
467
    const res = new Map();
468
    return arr.filter(
469
      (a) =>
470
        !res.has(a.id) &&
471
        res.set(a.id, 1) &&
472
        !res.has(a.name) &&
473
        res.set(a.name, 1)
474
    );
475
  }
476
  // excel转json
477
  function excelToJson() {
478
    const file = e.raw;
479
    readFile(file)
480
      .then((data) => {
481
        const workbook = XLSX.read(data, { type: 'binary' }); // 解析二进制格式数据
482
        console.log(workbook);
483
        const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个Sheet
484
        console.log(worksheet);
485
        result.value = XLSX.utils.sheet_to_json(worksheet); // json数据格式
486
        parseTableData(result.value);
487
        console.log(result.value);
488
      })
489
      .finally(() => {
490
        table.value[activeName.value].data = unique([
491
          ...table.value[activeName.value].data,
492
          ...tableData.value
493
        ]);
494
      });
495
  }
496
  excelToJson();
415
function handleClickImport() {
416
  isShowPanel.value = true;
417
  dialogType.value = 'fileImport';
497 418
}
498
499
// 模板下载
500
// function downloadModule() {
501
//   const title = '自定义属性模板.xlsx';
502
//   const headers = [
503
//     [
504
//       'id',
505
//       'name',
506
//       'type',
507
//       'isValidate',
508
//       'equal',
509
//       'less',
510
//       'max',
511
//       'min',
512
//       'more',
513
//       'nullable',
514
//       'precision',
515
//       'scale',
516
//       'unequal'
517
//     ],
518
//     ['', '', '', '', '', '', '', '', '', '', '', '', '']
519
//   ];
520
//   const worksheet = XLSX.utils.aoa_to_sheet(headers);
521
//   const workbook = XLSX.utils.book_new();
522
//   XLSX.utils.book_append_sheet(workbook, worksheet, '自定义属性模板');
523
524
//   XLSX.writeFile(workbook, title, { type: 'file' });
525
// }
526 419
</script>
527 420
528 421
<script>

+ 135 - 0
src/views/_components/panel/global/CustomImport.vue

@ -0,0 +1,135 @@
1
<template>
2
  <div class="demo">
3
    <div class="form-item">
4
      <div class="form-title">
5
        <h5>模板下载:</h5>
6
      </div>
7
      <span class="download" @click.stop="downTemplate">global_template</span>
8
    </div>
9
    <div class="form-item">
10
      <div class="form-title">
11
        <h5>文件导入:</h5>
12
      </div>
13
      <el-upload
14
        size="small"
15
        action
16
        accept=".xlsx, .xls"
17
        :auto-upload="false"
18
        :show-file-list="false"
19
        :on-change="useExcelHooks"
20
      >
21
        <el-button type="success">文件导入</el-button>
22
      </el-upload>
23
    </div>
24
  </div>
25
</template>
26
27
<script setup lang="ts">
28
import { ref } from 'vue';
29
import XLSX from 'xlsx';
30
import { downloadTemplaye } from '../../../../api/flow';
31
32
function downTemplate() {
33
  window.open(downloadTemplaye());
34
}
35
36
// excel表数据处理
37
const tableData = ref([]);
38
function useExcelHooks(e: any) {
39
  const result = ref([]);
40
41
  // 文件读取
42
  function readFile(file: any) {
43
    return new Promise((resolve) => {
44
      const reader = new FileReader();
45
      reader.readAsBinaryString(file);
46
      reader.onload = (e) => {
47
        resolve(e.target.result);
48
      };
49
    });
50
  }
51
  function parseTableData(data: any) {
52
    tableData.value = [];
53
    if (Array.isArray(data) && data.length) {
54
      let el = {};
55
      data.forEach((item) => {
56
        el = {
57
          id: item.id,
58
          isValidate: item.isValidate || '',
59
          name: item.name || '',
60
          type: item.type || '',
61
          validateRules: {
62
            equal: item.equal || '',
63
            less: item.less || '',
64
            max: item.max || '',
65
            min: item.min || '',
66
            more: item.more || '',
67
            nullable: item.nullable || false,
68
            precision: item.precision || '',
69
            scale: item.scale || '',
70
            unequal: item.unequal || ''
71
          }
72
        };
73
        tableData.value.push(el);
74
      });
75
    }
76
  }
77
78
  // function unique(arr: any) {
79
  //   const res = new Map();
80
  //   return arr.filter(
81
  //     (a: any) =>
82
  //       !res.has(a.id) &&
83
  //       res.set(a.id, 1) &&
84
  //       !res.has(a.name) &&
85
  //       res.set(a.name, 1)
86
  //   );
87
  // }
88
  // excel转json
89
  function excelToJson() {
90
    const file = e.raw;
91
    readFile(file)
92
      .then((data) => {
93
        const workbook = XLSX.read(data, { type: 'binary' }); // 解析二进制格式数据
94
        console.log(workbook);
95
        const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个Sheet
96
        console.log(worksheet);
97
        result.value = XLSX.utils.sheet_to_json(worksheet); // json数据格式
98
        parseTableData(result.value);
99
        console.log(result.value);
100
      })
101
      .finally(() => {
102
        // props.table[props.activeName].data = unique([
103
        //   ...props.table[props.activeName].data,
104
        //   ...tableData.value
105
        // ]);
106
        return tableData.value;
107
      });
108
  }
109
  excelToJson();
110
}
111
112
defineExpose({
113
  tableData
114
});
115
</script>
116
117
<style scoped lang="scss">
118
.form-item {
119
  display: flex;
120
  align-items: center;
121
  .form-title {
122
    display: flex;
123
    justify-content: space-between;
124
    align-items: center;
125
    margin: 10px 20px;
126
    h5 {
127
      font-size: 14px;
128
      color: rgba(0, 0, 0, 0.65);
129
    }
130
  }
131
  .download {
132
    text-decoration: underline;
133
  }
134
}
135
</style>

+ 79 - 7
src/views/_components/right-panel/PanelSql.vue

@ -5,12 +5,34 @@
5 5
        <!-- 功能 -->
6 6
        <panel-node-function>
7 7
          <template #function-basic>
8
            <div v-if="isSelectSql" class="form-item">
9
              <div class="form-title">
10
                <h5>SQL方法</h5>
11
              </div>
12
              <el-radio-group v-model="inputMethod" class="ml-4">
13
                <el-radio label="input" size="large">手动输入</el-radio>
14
                <el-radio label="select" size="large">对接SQL服务</el-radio>
15
              </el-radio-group>
16
            </div>
17
            <div v-if="inputMethod === 'select'" class="form-item">
18
              <div class="form-title">
19
                <h5>SQL选择</h5>
20
              </div>
21
              <common-select
22
                v-model="functionData.checkedId"
23
                :options="sqlList"
24
                :props-map="sqlPropsMap"
25
                @change="handleChange"
26
              ></common-select>
27
            </div>
28
8 29
            <div class="form-item">
9 30
              <div class="form-title">
10 31
                <h5>数据源</h5>
11 32
              </div>
12 33
              <common-select
13 34
                v-model="functionData.datasource"
35
                :disabled="inputMethod === 'select'"
14 36
                class="int-select"
15 37
                :props-map="propsMap"
16 38
                :options="datasources"
@ -19,7 +41,11 @@
19 41
            <div class="form-item">
20 42
              <div class="form-title">
21 43
                <h5>SQL脚本</h5>
22
                <el-button type="success" @click.stop="sqlEditor">
44
                <el-button
45
                  type="success"
46
                  :disabled="inputMethod === 'select'"
47
                  @click.stop="sqlEditor"
48
                >
23 49
                  脚本编辑器
24 50
                </el-button>
25 51
              </div>
@ -30,6 +56,8 @@
30 56
              ></el-input>
31 57
            </div>
32 58
          </template>
59
60
          <template #function-senior></template>
33 61
        </panel-node-function>
34 62
      </template>
35 63
    </panel-node-layout>
@ -54,11 +82,14 @@
54 82
55 83
<script setup lang="ts">
56 84
import { ref, getCurrentInstance, onMounted, watch } from 'vue';
57
import { getSqlList } from '../../../api/flow';
85
import { getSqlList, getSqlServiceList } from '../../../api/flow';
58 86
import PanelNodeLayout from './_components/PanelNodeLayout.vue';
59 87
import PanelNodeFunction from './_components/PanelNodeFunction.vue';
60 88
import MyCode from '../_codemirror/MyCode.vue';
61 89
90
const globalConfig = JSON.parse(localStorage.getItem('GLOBAL_CONFIG'));
91
console.log(globalConfig);
92
62 93
const { proxy } = getCurrentInstance();
63 94
const props = defineProps({
64 95
  targetNode: {
@ -69,6 +100,8 @@ const props = defineProps({
69 100
70 101
const datasources = ref<any>([]);
71 102
103
const inputMethod = ref<any>('input');
104
72 105
const attributes = ref({
73 106
  type: 'textarea',
74 107
  autosize: { minRows: 20, maxRows: 50 }
@ -79,7 +112,8 @@ const nodePanelData = <any>props.targetNode.cell.getData()?.attrsData || null;
79 112
const functionData = ref<any>(
80 113
  nodePanelData?.function || {
81 114
    datasource: '',
82
    sql: ''
115
    sql: '',
116
    checkedId: ''
83 117
  }
84 118
);
85 119
@ -87,8 +121,8 @@ const functionData = ref<any>(
87 121
function getList() {
88 122
  getSqlList()
89 123
    .then((res) => {
90
      if (res.data.resultCode === '0') {
91
        datasources.value = res.data.result.map((item: any) => {
124
      if (res.resultCode === '0') {
125
        datasources.value = res.result.map((item: any) => {
92 126
          item.sqlConn = `business_${item?.id || ''}`;
93 127
          item.showName = `${item.code}-${item.name}-${item.ip || ''}${
94 128
            item.port || ''
@ -97,7 +131,7 @@ function getList() {
97 131
        });
98 132
      } else {
99 133
        datasources.value = [];
100
        proxy.$message.error(res.data.resultMsg);
134
        proxy.$message.error(res.resultMsg);
101 135
      }
102 136
    })
103 137
    .catch((err) => {
@ -113,7 +147,7 @@ const tabList = ref<any>([
113 147
  { name: 'output', label: '输出' }
114 148
]);
115 149
116
const propsMap = ref({
150
const propsMap = ref<any>({
117 151
  value: 'sqlConn',
118 152
  label: 'showName'
119 153
});
@ -162,6 +196,44 @@ function setNodeAttrData() {
162 196
  );
163 197
}
164 198
199
// 对接sql服务
200
const sqlList = ref<any>([]);
201
const isSelectSql = ref<any>(
202
  globalConfig?.dependenceSqlmgmtUsed === 'true' ||
203
    globalConfig?.dependenceSqlmgmtUsed === true
204
);
205
const sqlPropsMap = ref<any>({
206
  label: 'name',
207
  value: 'id'
208
});
209
function getSQLList() {
210
  const params = <any>{
211
    name: '',
212
    pageNumber: 1,
213
    pageSize: 1000
214
  };
215
  getSqlServiceList(params).then((res) => {
216
    console.log(res);
217
    if (res.resultCode === '0') {
218
      sqlList.value = res.result;
219
    } else {
220
      sqlList.value = [];
221
    }
222
  });
223
}
224
225
if (isSelectSql.value) {
226
  getSQLList();
227
} else {
228
  inputMethod.value = 'input';
229
}
230
231
// sql选择
232
function handleChange(val: any) {
233
  const selectedItem = sqlList.value.filter((item: any) => item.id === val)[0];
234
  functionData.value.datasource = selectedItem?.databaseCode || '';
235
  functionData.value.sql = selectedItem?.sql || '';
236
}
165 237
watch(
166 238
  functionData,
167 239
  () => {

+ 25 - 2
src/views/_components/right-panel/_components/PanelNodeLayout.vue

@ -23,7 +23,30 @@
23 23
        </el-collapse-item>
24 24
      </el-collapse>
25 25
    </template>
26
    <template v-if="layType === 'tabs'"></template>
26
    <template v-if="layType === 'tabs'">
27
      <el-tabs v-model="activeTab">
28
        <el-tab-pane label="基础" name="basic">
29
          <panel-node-basic :target-node="targetNode"></panel-node-basic>
30
        </el-tab-pane>
31
32
        <el-tab-pane
33
          v-for="tab in tabList"
34
          :key="tab.name"
35
          :label="tab.label"
36
          :name="tab.name"
37
        >
38
          <template v-if="tab.name === 'input' || tab.name === 'output'">
39
            <PanelNodeIO
40
              :target-node="targetNode"
41
              :input-type="tab.name"
42
            ></PanelNodeIO>
43
          </template>
44
          <template v-else>
45
            <slot :name="tab.name"></slot>
46
          </template>
47
        </el-tab-pane>
48
      </el-tabs>
49
    </template>
27 50
  </div>
28 51
</template>
29 52
@ -39,7 +62,7 @@ defineProps({
39 62
  },
40 63
  layType: {
41 64
    type: String,
42
    default: () => 'collapse'
65
    default: () => 'tabs'
43 66
  },
44 67
  tabList: {
45 68
    type: Array<any>,

+ 5 - 0
vite.config.ts

@ -119,6 +119,11 @@ export default defineConfig(({ mode }) => {
119 119
          target: 'http://8.130.24.19:8106',
120 120
          changOrigin: true,
121 121
          rewrite: path => path.replace(/^\/logic/, '/')
122
        },
123
        '^/df': {
124
          target: 'http://8.130.24.19:8082',
125
          changOrigin: true,
126
          rewrite: path => path.replace(/^\/df/, '/df')
122 127
        }
123 128
      }
124 129
    }