You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

662 lines
23 KiB
Vue

<template>
<div>
<el-card style="margin: 8px">
<el-form :inline="true" :model="selectForm" class="demo-form-inline" label-width="120px">
<el-form-item label="数据源名称">
<el-input v-model="selectForm.dataSourceName" clearable />
</el-form-item>
<el-form-item label="请求地址">
<el-input v-model="selectForm.requestUrl" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="queryList">查询</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="margin: 8px">
<el-button plain type="primary" icon="Plus" @click="constructionData">新增接口</el-button>
<el-button plain type="primary" icon="Plus" @click="addSQL">新增SQL</el-button>
<!-- <el-button plain type="success" icon="Edit" @click="editData">修改</el-button>-->
<!-- <el-button plain type="danger" icon="Delete" @click="delData">删除</el-button>-->
</el-card>
<el-card style="margin: 8px">
<el-table :data="tableData" style="width: 100%" v-loading="loading">
<el-table-column prop="dataSourceName" label="数据源名称" align="center" />
<el-table-column prop="requestMethod" label="请求方式" align="center" />
<el-table-column prop="requestUrl" label="请求地址" align="center" />
<el-table-column label="操作" width="300" align="center">
<template #default="scope">
<el-button text type="primary" size="small" @click="editDataSource(scope.row)">修改
</el-button>
<el-button size="small" type="danger" text @click="delDataSource(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination class="pagination" v-model:current-page="selectForm.pageNum"
v-model:page-size="selectForm.pageSize" :page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper" v-if="total > 0" :total="total"
@size-change="pageChange"
@current-change="pageChange" />
</el-card>
<el-dialog v-model="constructionDataFormVisible" draggable width="800">
<template #header>
<div style="width: 100%">
<span>{{ constructionDataForm.dataSourceId ? '修改' : '构造' }}数据源</span>
<div style="text-align:right;display: inline-block;width: calc(100% - 100px)">
<span>简易模式</span>
<el-switch v-model="isEasy" />
</div>
</div>
</template>
<el-form :model="constructionDataForm">
<el-form-item label="数据名称" prop="dataSourceName">
<el-input v-model="constructionDataForm.dataSourceName" />
</el-form-item>
<el-form-item label="请求地址" prop="requestUrl">
<el-input v-model="constructionDataForm.requestUrl">
<template #prepend>
<el-select v-model="constructionDataForm.requestMethod" style="width: 100px">
<el-option label="get" value="get" />
<el-option label="post" value="post" />
<el-option label="socket" value="socket" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item label="请求数据" v-if="isEasy">
<el-table :data="paramsTableData" style="width: 100%">
<el-table-column label="字段名称" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.name" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="备注" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.remark" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="测试数据" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.test" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="操作" min-width="120">
<template #default="scope">
<el-button link size="small" type="primary" @click="paramsTableData.splice(scope.$index, 1)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-button style="width: 100%" @click="paramsTableData.push({})">
添加字段
</el-button>
</el-form-item>
<el-form-item label="输出数据">
<el-table :data="constructionDataForm.designDataFieldList" style="width: 100%">
<el-table-column label="字段名称" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldOne" style="width: 100%" />
</template>
</el-table-column>
<el-table-column v-if="!isEasy" label="字段层级" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldTwo" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="备注" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.remark" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="操作" min-width="120">
<template #default="scope">
<el-button link size="small" type="primary"
@click="constructionDataForm.designDataFieldList.splice(scope.$index, 1)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-button style="width: 100%" @click="constructionDataForm.designDataFieldList.push({})">
添加字段
</el-button>
<el-button v-if="isEasy" style="width: 100%;margin: 12px 0 0 0" @click="findTier">
查找
</el-button>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="constructionDataFormVisible = false">关闭</el-button>
<el-button type="primary" @click="createData">
{{ constructionDataForm.dataSourceId ? '确定' : '创建' }}
</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="addSQLFormVisible" draggable width="800">
<template #header>
<div style="width: 100%">
<span>{{ addSQLForm.dataSourceId ? '修改' : '构造' }}数据源</span>
</div>
</template>
<el-form :model="addSQLForm" label-width="auto">
<el-form-item label="数据名称" prop="dataSourceName">
<el-input v-model="addSQLForm.dataSourceName" />
</el-form-item>
<el-form-item label="数据库" prop="db">
<el-select @change="selectDb" v-model="addSQLForm.db" placeholder="选择数据库" style="width: 240px">
<el-option v-for="item in dbList" :key="item.value" :label="`${item.linkName}(${item.host}:${item.port})`"
:value="item.linkId" />
</el-select>
</el-form-item>
<el-form-item label="是否分页" prop="dataSourceName">
<el-switch v-model="addSQLForm.isPage" />
</el-form-item>
<el-form-item label="输入数据">
<el-table :data="addSQLForm.testList" style="width: 100%">
<el-table-column label="字段名称" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldOne" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="测试数据" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldTwo" style="width: 100%" />
</template>
</el-table-column>
</el-table>
<el-button style="width: 100%" @click="addSQLForm.testList.push({})">
添加字段
</el-button>
</el-form-item>
<el-form-item label="SQL" prop="SQL">
<el-input v-model="addSQLForm.SQL" style="width: 100%" :rows="2" type="textarea" placeholder="" />
</el-form-item>
<!-- <el-form-item label="关键字">-->
<!-- <el-tag type="success" style="margin-right: 8px;margin-bottom: 8px;" v-for="i in keyword"-->
<!-- @click="addSQLInput(i)">{{ i }}-->
<!-- </el-tag>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="表">-->
<!-- <el-select @change="selectTable" v-model="addSQLForm.table" placeholder="选择表" style="width: 240px">-->
<!-- <el-option-->
<!-- v-for="item in tableList"-->
<!-- :key="item.value"-->
<!-- :label="item.tableName"-->
<!-- :value="item.tableName"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="字段">-->
<!-- <el-tag type="primary" style="margin-right: 8px;margin-bottom: 8px;" @click="addSQLInput(addSQLForm.table)">-->
<!-- {{ addSQLForm.table }}-->
<!-- </el-tag>-->
<!-- <el-tag type="success" style="margin-right: 8px;margin-bottom: 8px;" v-for="i in fieldList"-->
<!-- @click="addSQLInput(i.columnName)">{{ i.columnName-->
<!-- }}-->
<!-- </el-tag>-->
<!-- </el-form-item>-->
<el-form-item label="输出数据">
<el-table :data="addSQLForm.designDataFieldList" style="width: 100%">
<el-table-column label="字段名称" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldOne" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="字段层级" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.fieldTwo" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="备注" min-width="120">
<template #default="scope">
<el-input v-model="scope.row.remark" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="操作" min-width="120">
<template #default="scope">
<el-button link size="small" type="primary"
@click="addSQLForm.designDataFieldList.splice(scope.$index, 1)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-button style="width: 100%" @click="addSQLForm.designDataFieldList.push({})">
添加字段
</el-button>
<el-button style="width: 100%;margin: 12px 0 0 0" @click="sqlFindTier">
查找
</el-button>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="addSQLFormVisible = false">关闭</el-button>
<el-button type="primary" @click="createSQL">
{{ addSQLForm.dataSourceId ? '' : '' }}
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import axios from 'axios';
import request from '@/utils/request';
import { options } from './tool.js';
import {
addDataSourceApi,
delDataSourceApi,
editDataSourceApi,
getDataSourceList,
querySql,
querySql1
} from './api/dataSource';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getDatabaseLink, getFieldList, listDatabaseLink } from '@/views/boardGenerate/api/db';
const comparisonTable = {
starttime: '开始时间',
time: '时间',
value: '值'
};
const isEasy = ref(true);
const loading = ref(false);
const paramsTableData = ref([]);
const selectForm = ref({
pageNum: 1,
pageSize: 10
});
const total = ref(0);
const tableData = ref([]);
const constructionDataForm = ref({ designDataFieldList: [] });
const constructionDataFormVisible = ref(false);
const addSQLFormVisible = ref(false);
const addSQLForm = ref({});
const dbList = ref([]);
const tableList = ref([]);
const fieldList = ref([]);
const keyword = ref(['SELECT', 'FROM', 'WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT', 'TOP', 'DISTINCT', 'AS',
'INSERT INTO', 'VALUES', 'UPDATE', 'SET', 'DELETE',
'CREATE', 'DROP', 'ALTER', 'TRUNCATE', 'RENAME',
'PRIMARY KEY', 'FOREIGN KEY', 'UNIQUE', 'NOT NULL', 'DEFAULT', 'AUTO_INCREMENT', 'CHECK',
'GRANT', 'REVOKE',
'BEGIN', 'START TRANSACTION', 'COMMIT', 'ROLLBACK', 'SAVEPOINT',
'JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL JOIN', 'ON', 'IN', 'EXISTS', 'ANY', 'ALL',
'CASE', 'WHEN', 'THEN', 'ELSE', 'IS NULL', 'IS NOT NULL', 'LIKE', 'BETWEEN',
'UNION', 'UNION ALL', 'WITH']);
const getList = async () => {
loading.value = true;
getDataSourceList(selectForm.value)
.then((res) => {
console.log(res);
tableData.value = res.rows;
total.value = res.total;
})
.finally(() => {
loading.value = false;
});
};
const queryList = async () => {
selectForm.value.pageNum = 1;
await getList();
};
const pageChange = () => {
getList();
};
const constructionData = () => {
paramsTableData.value = [];
constructionDataForm.value = { designDataFieldList: [] };
constructionDataFormVisible.value = true;
};
const addSQL = () => {
addSQLFormVisible.value = true;
addSQLForm.value = {
designDataFieldList: [],
testList: []
};
getDbList();
};
const getDbList = () => {
listDatabaseLink().then(e => {
dbList.value = e.rows;
});
};
const selectDb = (e) => {
getDatabaseLink(e).then((res) => {
tableList.value = res.data;
});
};
const selectTable = () => {
getFieldList(addSQLForm.value.db, addSQLForm.value.table).then((res) => {
fieldList.value = res.data;
});
};
const addSQLInput = (data) => {
addSQLForm.value.SQL = (addSQLForm.value.SQL || '') + `${data} `;
};
const testSql = () => {
querySql(addSQLForm.value.SQL, addSQLForm.value.db).then((res) => {
console.log(res);
});
};
const createSQL = () => {
let params = {
...addSQLForm.value,
dataSourceName: addSQLForm.value.dataSourceName,
activeFlag: '1',
responseType: '2',
designDataFieldList: addSQLForm.value.designDataFieldList.map(e => {
return {
fieldType: '2',
activeFlag: '1',
dataSourceId: addSQLForm.value.dataSourceId,
fieldOne: e.fieldOne,
fieldTwo: e.fieldTwo
};
}),
requestUrl: 'system/databaseLink/querySql',
requestMethod: 'querySql',
fieldOne: addSQLForm.value.db,
fieldTwo: addSQLForm.value.SQL,
fieldThree: addSQLForm.value.isPage
};
delete params.SQL;
if (addSQLForm.value.dataSourceId) {
editDataSourceApi(params).then(() => {
addSQLFormVisible.value = false;
ElMessage({
type: 'success',
message: '修改成功'
});
getList();
});
} else {
addDataSourceApi(params).then(() => {
addSQLFormVisible.value = false;
ElMessage({
type: 'success',
message: '创建成功'
});
getList();
});
}
// let nowData = JSON.parse(localStorage.getItem('DATANODE') || '[]');
// nowData.push(constructionDataForm.value);
// localStorage.setItem('DATANODE', JSON.stringify(nowData));
};
const editData = () => {
paramsTableData.value = [];
constructionDataForm.value = { designDataFieldList: [] };
constructionDataFormVisible.value = true;
};
const delData = () => {
paramsTableData.value = [];
constructionDataForm.value = { designDataFieldList: [] };
constructionDataFormVisible.value = true;
};
const editDataSource = (e) => {
if (e.responseType === '1' || !e.responseType) {
constructionDataFormVisible.value = true;
constructionDataForm.value = e;
}
if (e.responseType === '2') {
addSQLFormVisible.value = true;
addSQLForm.value = {
...e,
db: parseFloat(e.fieldOne),
SQL: e.fieldTwo,
isPage: e.fieldThree === 'true'
};
getDbList();
}
};
const delDataSource = (e) => {
ElMessageBox.confirm(
'要删除这条数据源吗?',
'Warning',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
.then(() => {
delDataSourceApi(e.dataSourceId).then(() => {
ElMessage({
type: 'success',
message: '删除成功'
});
getList();
});
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消'
});
});
};
const createData = () => {
if (!constructionDataForm.value.designDataFieldList) {
constructionDataForm.value.designDataFieldList = [];
}
let params = JSON.parse(JSON.stringify(constructionDataForm.value));
params.activeFlag = '1';
params.responseType = '1';
params.designDataFieldList = params.designDataFieldList.map(e => {
return {
fieldType: '2',
activeFlag: '1',
dataSourceId: params.dataSourceId,
fieldOne: e.fieldOne,
fieldTwo: e.fieldTwo
};
});
if (constructionDataForm.value.dataSourceId) {
editDataSourceApi(params).then(() => {
constructionDataFormVisible.value = false;
ElMessage({
type: 'success',
message: '修改成功'
});
getList();
});
} else {
addDataSourceApi(params).then(() => {
constructionDataFormVisible.value = false;
ElMessage({
type: 'success',
message: '创建成功'
});
getList();
});
}
// let nowData = JSON.parse(localStorage.getItem('DATANODE') || '[]');
// nowData.push(constructionDataForm.value);
// localStorage.setItem('DATANODE', JSON.stringify(nowData));
};
const findTier = () => {
constructionDataForm.value.designDataFieldList = [];
let params = {};
(paramsTableData.value || []).forEach((item) => {
params[item.name] = item.test;
});
(options.isD ? request : axios.request)({
method: constructionDataForm.value.requestMethod,
url: constructionDataForm.value.requestUrl,
params: constructionDataForm.value.requestMethod === 'get' ? params : '',
data: constructionDataForm.value.requestMethod === 'post' ? params : ''
}).then(res => {
let data = (options.isD ? res : res.data);
if (data?.data) {
Object.keys(data.data?.[0]).forEach(key => {
constructionDataForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `data,map%${key}`
});
});
constructionDataForm.value.designDataFieldList.push({
fieldOne: 'data',
remark: '',
fieldTwo: `data`
});
} else if (data?.rows) {
console.log(data?.rows);
Object.keys(data.rows?.[0]).forEach(key => {
constructionDataForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `rows,map%${key}`
});
});
constructionDataForm.value.designDataFieldList.push({
fieldOne: 'rows',
remark: '',
fieldTwo: `rows`
});
} else {
let exclude = ['code'];
Object.keys(data).forEach(key => {
if (!exclude.includes(key.toLowerCase())) {
if (typeof data[key] === 'string' || typeof data[key] === 'string') {
constructionDataForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `${key}`
});
}
}
});
}
});
};
const formulaFun = (formula) => {
let data = formula.replace(/\$\{\s*([^}]+?)\s*\}/g, (_, key) => {
let infos = key.split(',');
if (infos.length === 1) {
if (addSQLForm.value.testList.find(e => e.fieldOne === infos[0])) {
return addSQLForm.value.testList.find(e => e.fieldOne === infos[0])?.fieldTwo || '';
} else {
addSQLForm.value.testList.push({
fieldOne: infos[0],
fieldTwo: ''
});
return '';
}
}
if (infos.length === 2) {
if (addSQLForm.value.testList.find(e => e.fieldOne === infos[1])) {
return `AND ${infos[0]} = ${addSQLForm.value.testList.find(e => e.fieldOne === infos[1])?.fieldTwo || ''}`;
} else {
addSQLForm.value.testList.push({
fieldOne: infos[1],
fieldTwo: ''
});
return '';
}
}
});
return data;
};
const sqlFindTier = () => {
addSQLForm.value.designDataFieldList = [];
if (addSQLForm.value.isPage) {
querySql1({
sql: formulaFun(addSQLForm.value.SQL.replace(/\n/g, ' ')),
linkId: addSQLForm.value.db,
pageSize: 10,
pageNum: 1
}).then((res) => {
let data = res.data || {};
Object.keys(data.rows?.[0]).forEach(key => {
addSQLForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `data,rows,map%${key}`
});
});
addSQLForm.value.designDataFieldList.push({
fieldOne: 'data',
remark: '',
fieldTwo: `data,rows`
});
addSQLForm.value.designDataFieldList.push({
fieldOne: 'total',
remark: '',
fieldTwo: `data,total`
});
});
} else {
querySql(formulaFun(addSQLForm.value.SQL.replace(/\n/g, ' ')), addSQLForm.value.db).then((res) => {
let data = res;
if (data?.data) {
Object.keys(data.data?.[0]).forEach(key => {
addSQLForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `data,map%${key}`
});
});
addSQLForm.value.designDataFieldList.push({
fieldOne: 'data',
remark: '',
fieldTwo: `data`
});
} else if (data?.rows) {
Object.keys(data.rows?.[0]).forEach(key => {
addSQLForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `rows,map%${key}`
});
});
addSQLForm.value.designDataFieldList.push({
fieldOne: 'rows',
remark: '',
fieldTwo: `rows`
});
} else {
let exclude = ['code'];
Object.keys(data).forEach(key => {
if (!exclude.includes(key.toLowerCase())) {
if (typeof data[key] === 'string' || typeof data[key] === 'string') {
addSQLForm.value.designDataFieldList.push({
fieldOne: key,
remark: comparisonTable[key],
fieldTwo: `${key}`
});
}
}
});
}
});
}
};
onMounted(async () => {
await queryList();
});
</script>
<style lang="less" scoped>
.pagination {
float: right;
margin: 12px 0;
}
</style>