Database.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <ElForm inline ref="sql-form" :model="form" label-width="80px">
  3. <ElFormItem label="实例">
  4. <ElSelect class="input" v-model="form.deploymentId" placeholder="请选择数据库实例">
  5. <ElOption v-for="db in dbs" :key="db.id" :label="db.name" :value="db.id"></ElOption>
  6. </ElSelect>
  7. </ElFormItem>
  8. <ElFormItem label="用户名">
  9. <ElInput class="input" v-model="form.username" placeholder="请输入用户名"></ElInput>
  10. </ElFormItem>
  11. <ElFormItem label="密码">
  12. <ElInput class="input" v-model="form.password" type="password" placeholder="请输入密码"></ElInput>
  13. </ElFormItem>
  14. <ElFormItem label="数据库">
  15. <ElInput class="input" v-model="form.db" placeholder="请输入数据库名"></ElInput>
  16. </ElFormItem>
  17. <ElFormItem label="SQL">
  18. <ElInput class="sql" v-model="form.sql" :rows="5" type="textarea" clearable></ElInput>
  19. </ElFormItem>
  20. <ElFormItem>
  21. <ElButton type="primary" @click="exec">执行</ElButton>
  22. </ElFormItem>
  23. </ElForm>
  24. <ElDivider content-position="left">当前执行记录</ElDivider>
  25. <ElRow type="flex" justify="space-between" v-if="execHistory.size > 0">
  26. <ElCol :span="4" height="600px">
  27. <div
  28. :class="['list-item', active === key?'active':'']"
  29. v-for="key in [...execHistory.keys()].reverse()"
  30. :key="key"
  31. @click="switchRecord(key)"
  32. >{{key}}</div>
  33. </ElCol>
  34. <ElDivider direction="vertical"></ElDivider>
  35. <ElCol :span="18" v-show="active > 0">
  36. <ElDivider content-position="left">SQL</ElDivider>
  37. <pre>{{activeRecord.sql}}</pre>
  38. <ElDivider content-position="left">结果</ElDivider>
  39. <template v-if="showTable">
  40. <pre>{{b}}</pre>
  41. <table>
  42. <tr v-for="(row, i) in content" :key="i">
  43. <td v-for="(cell,j) in row" :key="j">{{cell}}</td>
  44. </tr>
  45. </table>
  46. </template>
  47. <template v-else>
  48. <pre>{{activeRecord.result}}</pre>
  49. </template>
  50. </ElCol>
  51. </ElRow>
  52. <ElEmpty v-else description="暂无记录"></ElEmpty>
  53. </template>
  54. <script>
  55. import { SQLExecAPI } from '@/api';
  56. export default {
  57. name: 'Database',
  58. data() {
  59. return {
  60. dbs: [],
  61. execHistory: new Map(),
  62. active: -1,
  63. showTable: true,
  64. form: {
  65. db: '',
  66. deploymentId: null,
  67. password: '',
  68. sql: '',
  69. username: 'root',
  70. },
  71. b: '',
  72. content: '',
  73. };
  74. },
  75. async mounted() {
  76. this.dbs = await SQLExecAPI.getDatabaseInstances(this.$store.state.workspace.currentProjectId);
  77. },
  78. computed: {
  79. activeRecord() {
  80. if (this.active < 0) return {};
  81. return this.execHistory.get(this.active);
  82. },
  83. },
  84. methods: {
  85. async exec() {
  86. const result = await SQLExecAPI.SQLExec(this.form);
  87. this.execHistory.set(this.execHistory.size + 1, {
  88. sql: this.form.sql,
  89. result,
  90. });
  91. this.switchRecord(this.execHistory.size);
  92. },
  93. switchRecord(key) {
  94. this.active = key;
  95. const { b, content } = this.process(this.activeRecord.result);
  96. if (typeof content === 'string') {
  97. this.showTable = false;
  98. } else {
  99. this.showTable = true;
  100. }
  101. this.b = b;
  102. this.content = content;
  103. },
  104. process(result) {
  105. const i = result.indexOf('\n');
  106. const b = result.substr(0, i);
  107. let content = result.substr(i + 1);
  108. if (!content.startsWith('[[')) {
  109. return {
  110. b,
  111. content,
  112. };
  113. }
  114. content = content.substring(1, content.length - 1);
  115. const recordList = content.match(/\[.*?\]/g);
  116. content = [];
  117. recordList.forEach((_record) => content.push(_record.substring(1, _record.length - 1).split(',').map((val) => val.trim())));
  118. return {
  119. b,
  120. content,
  121. };
  122. },
  123. },
  124. };
  125. </script>
  126. <style lang="scss" scoped>
  127. .input {
  128. width: 240px;
  129. }
  130. .sql {
  131. width: 1000px;
  132. input {
  133. font: 1em monospace;
  134. }
  135. }
  136. .list-item {
  137. height: 32px;
  138. line-height: 32px;
  139. padding: 4px 4px 4px 32px;
  140. width: 80%;
  141. &.active {
  142. background-color: #ecf5ff;
  143. color: #409eff;
  144. }
  145. &:hover {
  146. background-color: #ecf5ff;
  147. color: #409eff;
  148. }
  149. }
  150. pre {
  151. font-size: 1.2em;
  152. word-break: break-word;
  153. white-space: pre-wrap;
  154. }
  155. table {
  156. margin-top: 24px;
  157. color: #333333;
  158. border-width: 1px;
  159. border-color: #666666;
  160. border-collapse: collapse;
  161. td {
  162. border-width: 1px;
  163. padding: 8px 12px;
  164. border-style: solid;
  165. border-color: #666666;
  166. background-color: #ffffff;
  167. white-space: nowrap;
  168. }
  169. }
  170. </style>