index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <route lang="yaml">
  2. meta:
  3. enabled: false
  4. </route>
  5. <script lang="ts" setup>
  6. import { getModelTreeData } from '@/api/model/modelApi'
  7. import { getTableDataByList, getTableFieldsByList } from '@/api/database/dbApi'
  8. interface TreeNode {
  9. label: string
  10. isLeaf: boolean
  11. value: number
  12. objectCode: string
  13. children?: TreeNode[]
  14. }
  15. const state = reactive({
  16. loading: false,
  17. keywords: '',
  18. treeData: [] as TreeNode[],
  19. curModelId: 0,
  20. curObjectId: 0,
  21. curObjectCode: '',
  22. dialogState: 1,
  23. tableFields: [],
  24. tableDataList: [],
  25. search: {
  26. keywords: '',
  27. },
  28. })
  29. const leftTreeRef = ref()
  30. const getTreeData = async () => {
  31. state.loading = true
  32. const { data } = await getModelTreeData()
  33. state.treeData = data
  34. state.loading = false
  35. if (data && data.length > 0) {
  36. const firstModel = data[0]
  37. state.curModelId = firstModel.value
  38. if (firstModel.children && firstModel.children.size > 0) {
  39. const firstObject = firstModel.children[0]
  40. nextTick(() => {
  41. leftTreeRef.value.setCurrentKey(firstObject.value)
  42. })
  43. }
  44. }
  45. }
  46. const getTableFields = async () => {
  47. const tableName = state.curObjectCode
  48. const res = await getTableFieldsByList(tableName)
  49. state.tableFields = res.data
  50. }
  51. const getTableData = async () => {
  52. const tableName = state.curObjectCode
  53. const res = await getTableDataByList(tableName)
  54. state.tableDataList = res.data
  55. }
  56. const getData = () => {
  57. if (state.curObjectCode !== '') {
  58. state.loading = true
  59. getTableFields()
  60. getTableData()
  61. state.loading = false
  62. }
  63. }
  64. onMounted(() => {
  65. getTreeData()
  66. })
  67. // 对象选择
  68. const onTreeNodeClick = (node: TreeNode) => {
  69. if (node.isLeaf) {
  70. state.curObjectId = node.value
  71. state.curObjectCode = node.objectCode
  72. getTableFields()
  73. getTableData()
  74. }
  75. else {
  76. state.curModelId = node.value
  77. }
  78. }
  79. const tableDataRef = ref()
  80. // 检索对象
  81. const onSearch = () => {
  82. getData()
  83. }
  84. </script>
  85. <template>
  86. <div class="absolute-container">
  87. <tool-header title="数据仓库">
  88. <template #right />
  89. </tool-header>
  90. <div class="page-main">
  91. <LayoutContainer left-side-width="250px" hide-left-side-toggle>
  92. <template #leftSide>
  93. <el-scrollbar class="tree">
  94. <ElTree ref="leftTreeRef" :data="state.treeData" default-expand-all node-key="modelId" @node-click="onTreeNodeClick">
  95. <template #default="{ node, data }">
  96. <div class="custom-tree-node">
  97. <div class="label" :title="node.label">
  98. <el-icon v-if="data.isLeaf" size="16px" style="margin-right: 5px;">
  99. <svg-icon name="uim:box" />
  100. </el-icon>
  101. <el-icon v-else size="16px" style="margin-right: 5px;">
  102. <svg-icon name="bx:bxs-component" />
  103. </el-icon>
  104. <div class="text">
  105. {{ data.label }}
  106. </div>
  107. </div>
  108. </div>
  109. </template>
  110. </ElTree>
  111. </el-scrollbar>
  112. </template>
  113. <div class="container">
  114. <tool-bar>
  115. <template #right>
  116. <el-input v-model="state.search.keywords" placeholder="请输入名称,支持模糊查询" style="padding-right: 10px;" clearable />
  117. <el-button type="primary" @click="onSearch">
  118. <template #icon>
  119. <el-icon>
  120. <svg-icon name="i-ep:search" />
  121. </el-icon>
  122. </template>
  123. </el-button>
  124. </template>
  125. </tool-bar>
  126. <el-table ref="tableDataRef" v-loading="state.loading" class="list-table" :data="state.tableDataList" size="small" border stripe highlight-current-row height="100%">
  127. <el-table-column type="index" label="序号" header-align="center" align="center" width="70" />
  128. <template v-for="(field, index) in state.tableFields" :key="index">
  129. <el-table-column :prop="field.attrCode" :label="field.attrCode" header-align="center" align="center" />
  130. </template>
  131. </el-table>
  132. </div>
  133. </LayoutContainer>
  134. </div>
  135. </div>
  136. </template>
  137. <style lang="scss" scoped>
  138. .container {
  139. height: 100%;
  140. display: flex;
  141. flex-direction: column;
  142. }
  143. .absolute-container {
  144. :deep(.left-side) {
  145. display: flex;
  146. flex-direction: column;
  147. height: 100%;
  148. .btns {
  149. display: inline-flex;
  150. width: 100%;
  151. margin-bottom: var(--container-padding);
  152. .add {
  153. width: 100%;
  154. }
  155. }
  156. .tree {
  157. flex: 1;
  158. overflow-y: auto;
  159. .el-tree {
  160. .el-tree-node__content {
  161. height: 40px;
  162. }
  163. .is-current > .el-tree-node__content {
  164. background-color: var(--el-color-primary-light-9);
  165. }
  166. .custom-tree-node {
  167. flex: 1;
  168. position: relative;
  169. width: 0;
  170. height: 100%;
  171. display: flex;
  172. flex-direction: column;
  173. justify-content: center;
  174. .label {
  175. display: inline-flex;
  176. align-items: center;
  177. width: calc(100% - 10px);
  178. color: var(--el-text-color-primary);
  179. .text {
  180. @include text-overflow;
  181. }
  182. }
  183. &:hover {
  184. .actions {
  185. display: block;
  186. }
  187. }
  188. .actions {
  189. display: none;
  190. position: absolute;
  191. right: 10px;
  192. top: 50%;
  193. transform: translateY(-50%);
  194. .el-button {
  195. padding: 5px 8px;
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. }
  203. </style>