visualTable.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <div class="sys-databaseVisual-container">
  3. <div style="height: calc(100vh - 60px)">
  4. <RelationGraph ref="graphRef" :options="graphOptions" :on-node-click="onNodeClick" :on-line-click="onLineClick">
  5. <template #graph-plug>
  6. <!-- To facilitate understanding, the CSS style code is directly embedded here. -->
  7. <div
  8. style="
  9. z-index: 300;
  10. position: absolute;
  11. left: 10px;
  12. top: calc(100% - 50px);
  13. font-size: 12px;
  14. background-color: #ffffff;
  15. border: #efefef solid 1px;
  16. border-radius: 10px;
  17. width: 260px;
  18. height: 40px;
  19. display: flex;
  20. align-items: center;
  21. justify-content: center;
  22. "
  23. >
  24. 图例:
  25. <div>
  26. 一对多
  27. <div style="height: 5px; width: 80px; background-color: rgba(159, 23, 227, 0.65)"></div>
  28. </div>
  29. <div style="margin-left: 10px">
  30. 一对一
  31. <div style="height: 5px; width: 80px; background-color: rgba(29, 169, 245, 0.76)"></div>
  32. </div>
  33. </div>
  34. </template>
  35. <template #canvas-plug>
  36. <!--- You can put some elements that are not allowed to be dragged here --->
  37. </template>
  38. <template #node="{ node }">
  39. <div style="width: 350px; background-color: #f39930">
  40. <!---------------- if node a ---------------->
  41. <div style="height: 30px; display: flex; align-items: center; justify-content: center">{{ node.text }} - 【{{ node.data.columns.length }}列】</div>
  42. <table class="c-data-table">
  43. <tr>
  44. <th>列名</th>
  45. <th>类型</th>
  46. </tr>
  47. <template v-for="column of node.data.columns" :key="column.columnName">
  48. <tr>
  49. <td>
  50. <div :id="`${node.id}-${column.columnName}`" style="background-color: var(--el-color-primary-light-3)">{{ column.columnName }}</div>
  51. </td>
  52. <td>{{ column.dataType }}</td>
  53. </tr>
  54. </template>
  55. </table>
  56. </div>
  57. </template>
  58. </RelationGraph>
  59. </div>
  60. </div>
  61. </template>
  62. <script lang="ts" setup name="databaseVisual">
  63. import { onMounted, reactive, ref } from 'vue';
  64. import { useRoute } from 'vue-router';
  65. import RelationGraph from 'relation-graph/vue3';
  66. import type { RGOptions, RGNode, RGLine, RGLink, RGUserEvent, RGJsonData, RelationGraphComponent } from 'relation-graph/vue3';
  67. import { getAPI } from '/@/utils/axios-utils';
  68. import { SysDatabaseApi } from '/@/api-services/api';
  69. import { DbColumnOutput, DbTableInfo } from '/@/api-services/models';
  70. const route = useRoute();
  71. const state = reactive({
  72. loading: false,
  73. loading1: false,
  74. dbData: [] as any,
  75. configId: '' as any,
  76. tableData: [] as Array<DbTableInfo>,
  77. visualTable: [],
  78. visualRTable: [],
  79. tableName: '',
  80. columnData: [] as Array<DbColumnOutput>,
  81. queryParams: {
  82. name: undefined,
  83. code: undefined,
  84. },
  85. editPosTitle: '',
  86. appNamespaces: [] as Array<String>, // 存储位置
  87. //graphOptions: {
  88. // defaultNodeBorderWidth: 0,
  89. // defaultNodeColor: "rgba(238, 178, 94, 1)",
  90. // allowSwitchLineShape: true,
  91. // allowSwitchJunctionPoint: true,
  92. // defaultLineShape: 1,
  93. // layouts: [
  94. // {
  95. // label: "自动布局",
  96. // layoutName: "force",
  97. // layoutClassName: "seeks-layout-force",
  98. // distance_coefficient: 3
  99. // },
  100. // ],
  101. // defaultJunctionPoint: "border",
  102. // },
  103. });
  104. onMounted(async () => {
  105. state.configId = route.query.configId;
  106. console.log(state.configId);
  107. showGraph();
  108. });
  109. const graphRef = ref<RelationGraphComponent | null>(null);
  110. const graphOptions: RGOptions = {
  111. debug: false,
  112. allowSwitchLineShape: true,
  113. allowSwitchJunctionPoint: true,
  114. allowShowDownloadButton: true,
  115. defaultJunctionPoint: 'border',
  116. // placeOtherNodes: false,
  117. placeSingleNode: false,
  118. graphOffset_x: -200,
  119. graphOffset_y: 100,
  120. defaultLineMarker: {
  121. markerWidth: 20,
  122. markerHeight: 20,
  123. refX: 3,
  124. refY: 3,
  125. data: 'M 0 0, V 6, L 4 3, Z',
  126. },
  127. layout: {
  128. layoutName: 'fixed',
  129. },
  130. // You can refer to the parameters in "Graph" for setting here
  131. };
  132. // 获取可视化表和字段
  133. const showGraph = async () => {
  134. var res = await getAPI(SysDatabaseApi).apiSysDatabaseVisualDbTableGet();
  135. const visualTableList: any = res.data.result?.visualTableList;
  136. const visualColumnList: any = res.data.result?.visualColumnList;
  137. const columnRelationList: any = res.data.result?.columnRelationList;
  138. const graphNodes = visualTableList.map((table: any) => {
  139. const { tableName, tableComents, x, y } = table;
  140. return {
  141. id: tableName,
  142. text: tableComents,
  143. x,
  144. y,
  145. nodeShape: 1,
  146. data: {
  147. // Costomer key have to in data
  148. columns: visualColumnList.filter((col: any) => col.tableName === table.tableName),
  149. },
  150. };
  151. });
  152. const graphLines = columnRelationList.map((relation: any) => {
  153. return {
  154. from: relation.sourceTableName + '-' + relation.sourceColumnName, // HtmlElement id
  155. to: relation.targetTableName + '-' + relation.targetColumnName, // HtmlElement id
  156. color: relation.type === 'ONE_TO_ONE' ? 'rgba(29,169,245,0.76)' : 'rgba(159,23,227,0.65)',
  157. text: '',
  158. fromJunctionPoint: 'left',
  159. toJunctionPoint: 'lr',
  160. lineShape: 6,
  161. lineWidth: 3,
  162. };
  163. });
  164. const graphJsonData: RGJsonData = {
  165. nodes: graphNodes,
  166. lines: [],
  167. elementLines: graphLines,
  168. };
  169. const graphInstance = graphRef.value?.getInstance();
  170. if (graphInstance) {
  171. await graphInstance.setJsonData(graphJsonData);
  172. await graphInstance.moveToCenter();
  173. await graphInstance.zoomToFit();
  174. }
  175. };
  176. const onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {
  177. console.log('onNodeClick:', nodeObject);
  178. };
  179. const onLineClick = (lineObject: RGLine, linkObject: RGLink, $event: RGUserEvent) => {
  180. console.log('onLineClick:', lineObject);
  181. };
  182. </script>
  183. <style lang="scss" scoped>
  184. ::v-deep(.relation-graph) {
  185. .rel-node-shape-1 {
  186. overflow: hidden;
  187. }
  188. }
  189. .c-data-table {
  190. background-color: #ffffff;
  191. border-collapse: collapse;
  192. width: 100%;
  193. }
  194. .c-data-table td,
  195. .c-data-table th {
  196. border: 1px solid #f39930;
  197. color: #333333;
  198. padding: 5px;
  199. padding-left: 20px;
  200. padding-right: 20px;
  201. }
  202. .c-data-table td div,
  203. .c-data-table th div {
  204. background-color: #1da9f5;
  205. color: #ffffff;
  206. border-radius: 5px;
  207. }
  208. </style>