|
|
@@ -0,0 +1,176 @@
|
|
|
+<template>
|
|
|
+ <ElForm inline ref="sql-form" :model="form" label-width="80px">
|
|
|
+ <ElFormItem label="实例">
|
|
|
+ <ElSelect class="input" v-model="form.deploymentId" placeholder="请选择数据库实例">
|
|
|
+ <ElOption v-for="db in dbs" :key="db.id" :label="db.name" :value="db.id"></ElOption>
|
|
|
+ </ElSelect>
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem label="用户名">
|
|
|
+ <ElInput class="input" v-model="form.username" placeholder="请输入用户名"></ElInput>
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem label="密码">
|
|
|
+ <ElInput class="input" v-model="form.password" type="password" placeholder="请输入密码"></ElInput>
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem label="数据库">
|
|
|
+ <ElInput class="input" v-model="form.db" placeholder="请输入数据库名"></ElInput>
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem label="SQL">
|
|
|
+ <ElInput class="sql" v-model="form.sql" :rows="5" type="textarea" clearable></ElInput>
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem>
|
|
|
+ <ElButton type="primary" @click="exec">执行</ElButton>
|
|
|
+ </ElFormItem>
|
|
|
+ </ElForm>
|
|
|
+ <ElDivider content-position="left">当前执行记录</ElDivider>
|
|
|
+ <ElRow type="flex" justify="space-between" v-if="execHistory.size > 0">
|
|
|
+ <ElCol :span="4" height="600px">
|
|
|
+ <div
|
|
|
+ :class="['list-item', active === key?'active':'']"
|
|
|
+ v-for="key in [...execHistory.keys()].reverse()"
|
|
|
+ :key="key"
|
|
|
+ @click="switchRecord(key)"
|
|
|
+ >{{key}}</div>
|
|
|
+ </ElCol>
|
|
|
+ <ElDivider direction="vertical"></ElDivider>
|
|
|
+ <ElCol :span="18" v-show="active > 0">
|
|
|
+ <ElDivider content-position="left">SQL</ElDivider>
|
|
|
+ <pre>{{activeRecord.sql}}</pre>
|
|
|
+ <ElDivider content-position="left">结果</ElDivider>
|
|
|
+ <template v-if="showTable">
|
|
|
+ <pre>{{b}}</pre>
|
|
|
+ <table>
|
|
|
+ <tr v-for="(row, i) in content" :key="i">
|
|
|
+ <td v-for="(cell,j) in row" :key="j">{{cell}}</td>
|
|
|
+ </tr>
|
|
|
+ </table>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <pre>{{activeRecord.result}}</pre>
|
|
|
+ </template>
|
|
|
+ </ElCol>
|
|
|
+ </ElRow>
|
|
|
+ <ElEmpty v-else description="暂无记录"></ElEmpty>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { SQLExecAPI, PipelineAPI } from '@/api';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'Database',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ dbs: [],
|
|
|
+ execHistory: new Map(),
|
|
|
+ active: -1,
|
|
|
+ showTable: true,
|
|
|
+ form: {
|
|
|
+ db: '',
|
|
|
+ deploymentId: null,
|
|
|
+ password: '',
|
|
|
+ sql: '',
|
|
|
+ username: 'root',
|
|
|
+ },
|
|
|
+ b: '',
|
|
|
+ content: '',
|
|
|
+ };
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ this.dbs = await PipelineAPI.getDeploymentsByProjectId(this.$store.state.workspace.currentProjectId);
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ activeRecord() {
|
|
|
+ if (this.active < 0) return {};
|
|
|
+ return this.execHistory.get(this.active);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async exec() {
|
|
|
+ const result = await SQLExecAPI.SQLExec(this.form);
|
|
|
+ this.execHistory.set(this.execHistory.size + 1, {
|
|
|
+ sql: this.form.sql,
|
|
|
+ result,
|
|
|
+ });
|
|
|
+ this.switchRecord(this.execHistory.size);
|
|
|
+ },
|
|
|
+ switchRecord(key) {
|
|
|
+ this.active = key;
|
|
|
+ const { b, content } = this.process(this.activeRecord.result);
|
|
|
+ if (typeof content === 'string') {
|
|
|
+ this.showTable = false;
|
|
|
+ } else {
|
|
|
+ this.showTable = true;
|
|
|
+ }
|
|
|
+ this.b = b;
|
|
|
+ this.content = content;
|
|
|
+ },
|
|
|
+ process(result) {
|
|
|
+ const i = result.indexOf('\n');
|
|
|
+ const b = result.substr(0, i);
|
|
|
+ let content = result.substr(i + 1);
|
|
|
+ if (!content.startsWith('[[')) {
|
|
|
+ return {
|
|
|
+ b,
|
|
|
+ content,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ content = content.substring(1, content.length - 1);
|
|
|
+ const recordList = content.match(/\[.*?\]/g);
|
|
|
+ content = [];
|
|
|
+ recordList.forEach((_record) => content.push(_record.substring(1, _record.length - 1).split(',').map((val) => val.trim())));
|
|
|
+ return {
|
|
|
+ b,
|
|
|
+ content,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.input {
|
|
|
+ width: 240px;
|
|
|
+}
|
|
|
+.sql {
|
|
|
+ width: 1000px;
|
|
|
+ input {
|
|
|
+ font: 1em monospace;
|
|
|
+ }
|
|
|
+}
|
|
|
+.list-item {
|
|
|
+ height: 32px;
|
|
|
+ line-height: 32px;
|
|
|
+ padding: 4px 4px 4px 32px;
|
|
|
+ width: 80%;
|
|
|
+ &.active {
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+ &:hover {
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+pre {
|
|
|
+ font-size: 1.2em;
|
|
|
+ word-break: break-word;
|
|
|
+ white-space: pre-wrap;
|
|
|
+}
|
|
|
+
|
|
|
+table {
|
|
|
+ margin-top: 24px;
|
|
|
+ color: #333333;
|
|
|
+ border-width: 1px;
|
|
|
+ border-color: #666666;
|
|
|
+ border-collapse: collapse;
|
|
|
+ td {
|
|
|
+ border-width: 1px;
|
|
|
+ padding: 8px 12px;
|
|
|
+ border-style: solid;
|
|
|
+ border-color: #666666;
|
|
|
+ background-color: #ffffff;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|