index.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <template>
  2. <el-table
  3. ref="table"
  4. v-el-table-infinite-scroll="load"
  5. :row-key="tableProps.rowKey"
  6. :row-style="rowStyle"
  7. :data="tableData"
  8. :height="tableProps.height"
  9. :max-height="tableProps.maxHeight"
  10. :stripe="tableProps.stripe"
  11. :border="tableProps.border"
  12. :highlight-current-row="tableProps.highlightCurrentRow"
  13. :header-cell-class-name="tableProps.headerRowClassName"
  14. :tooltip-effect="tableProps.tooltipEffect"
  15. :show-summary="tableProps.showSummary"
  16. :row-class-name="tableRowClassName"
  17. :cell-class-name="cellClassName"
  18. @row-click="rowClickHandler"
  19. @cell-click="cellClickHandler"
  20. >
  21. <el-table-column v-if="isStatus" width="55">
  22. <template #default="scope">
  23. <div class="tableStatus">
  24. <div
  25. v-if="tableData[scope.$index].nodeState === '运行'"
  26. class="status0"
  27. >
  28. <span class="icon"></span>
  29. </div>
  30. <div
  31. v-else-if="tableData[scope.$index].nodeState === '停止'"
  32. class="status1"
  33. >
  34. <span class="icon"></span>
  35. </div>
  36. <div v-else class="status2"><span class="icon"></span></div>
  37. </div>
  38. </template>
  39. </el-table-column>
  40. <!-- label-class-name 可通过 tableHeader中传入class来修改某一个或某一类表头的样式-->
  41. <el-table-column
  42. class="infinite-list-item"
  43. v-for="(items, index) in tableHeaderList"
  44. :key="index"
  45. :label="items.columnLabel"
  46. :prop="items.columnName"
  47. :width="items.width ? items.width : tableColumnProperty.width"
  48. :sortable="items.needSort ? items.needSort : tableColumnProperty.sortable"
  49. :show-overflow-tooltip="tableColumnProperty.showOverflowTooltip"
  50. :align="items.align ? items.align : tableColumnProperty.align"
  51. :header-align="
  52. items.headerAlign ? items.headerAlign : tableColumnProperty.headerAlign
  53. "
  54. :label-class-name="items.lableClass ? items.lableClass : ''"
  55. :class-name="items.columnClassName"
  56. >
  57. <template #default="scope">
  58. <!-- 枚举值则为 items.key+'-enum' -->
  59. <template v-if="isChild(scope.row[items.columnName])">
  60. <div
  61. class="child-list"
  62. v-for="(newItem, i) in childDatas(scope.row[items.columnName])"
  63. :key="i"
  64. >
  65. {{ newItem }}
  66. </div>
  67. </template>
  68. <template v-else>
  69. {{
  70. scope.row[items.columnName + '-enum']
  71. ? scope.row[items.columnName + '-enum']
  72. : scope.row[items.columnName]
  73. }}
  74. </template>
  75. </template>
  76. </el-table-column>
  77. <el-table-column
  78. v-if="tableBtnGroup.length"
  79. label="操作"
  80. :align="tableColumnProperty.align"
  81. :width="btnGroupWidth"
  82. >
  83. <template #default="scope">
  84. <el-button
  85. v-for="(btn, index) in tableBtnGroup"
  86. :key="index"
  87. size="small"
  88. @click="handleClick(scope.$index, scope.row, btn.param)"
  89. :class="btn.className"
  90. >{{ btn.name }}</el-button
  91. >
  92. </template>
  93. </el-table-column>
  94. </el-table>
  95. <!-- <ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto">
  96. <li v-for="i in count" :key="i" class="infinite-list-item">{{ i }}</li>
  97. </ul> -->
  98. </template>
  99. <script setup lang="ts">
  100. import { PropType, computed, watchEffect } from 'vue'
  101. import { ElTable } from 'element-plus'
  102. import { CommonTableColumn } from '~/common'
  103. export interface TableButton {
  104. name: string
  105. className: string
  106. param: number
  107. }
  108. const props = defineProps({
  109. // 表头参数数组
  110. tableHeader: {
  111. type: Array as PropType<CommonTableColumn[]>,
  112. default: [] as CommonTableColumn[],
  113. },
  114. // 表格参数
  115. tableProperty: {
  116. type: Object,
  117. default: {},
  118. },
  119. // 公共表头参数
  120. tableColumnProperty: {
  121. type: Object,
  122. default: {
  123. width: '',
  124. fixed: '',
  125. sortable: false,
  126. showOverflowTooltip: true,
  127. align: 'center',
  128. headerAlign: '',
  129. },
  130. },
  131. // 操作栏按钮组
  132. tableBtnGroup: {
  133. type: Array as PropType<TableButton[]>,
  134. default: [] as TableButton[],
  135. },
  136. // 表格数据
  137. tableData: {
  138. type: Array as PropType<any[]>,
  139. default: [] as any[],
  140. },
  141. // 操作栏宽度
  142. btnGroupWidth: {
  143. type: String,
  144. default: '',
  145. },
  146. // 自定义表头
  147. isStatus: {
  148. type: Boolean,
  149. default: false,
  150. },
  151. })
  152. //表格参数
  153. const tableProps = reactive({
  154. height: '100%',
  155. maxHeight: '100%',
  156. stripe: true,
  157. border: true,
  158. highlightCurrentRow: false,
  159. rowClassName: 'rowClass',
  160. headerRowClassName: 'headerRowClass',
  161. tooltipEffect: 'light',
  162. showSummary: false,
  163. rowKey: '',
  164. })
  165. watchEffect(() => {
  166. Object.assign(tableProps, props.tableProperty)
  167. })
  168. const tableHeaderList = ref<CommonTableColumn[]>([])
  169. watchEffect(() => {
  170. tableHeaderList.value = props.tableHeader.filter(column => column.needShow)
  171. })
  172. const isChild = computed(() => (item: any) => {
  173. const msg = typeof item === 'string' ? item : `${item}`
  174. return msg.includes('-')
  175. })
  176. const childDatas = computed(() => (item: any) => {
  177. const msg = typeof item === 'string' ? item : `${item}`
  178. return msg.split('-')
  179. })
  180. //向父组件传参 btnClick:点击按钮后 load 触发下拉加载 cellClass 修改某一行class的触发条件
  181. const emit = defineEmits([
  182. 'btnClick',
  183. 'load',
  184. 'cellClass',
  185. 'rowClick',
  186. 'cellClick',
  187. ])
  188. //按钮点击index为当前行序号 row 为当前行 param按钮类型判断参数由父组件传过来
  189. const handleClick = (rowIndex: number, row: any, param: number) => {
  190. emit('btnClick', rowIndex, row, param)
  191. }
  192. //行公共样式
  193. const rowStyle = ({ row, rowIndex }: { row: any; rowIndex: number }) => {
  194. let styleJson = {
  195. height: '50px',
  196. fontSize: '14px',
  197. color: '#101116',
  198. }
  199. return styleJson
  200. }
  201. //表格行class样式 可通过父组件直接传class名称修改当前行样式
  202. const tableRowClassName = ({
  203. row,
  204. rowIndex,
  205. }: {
  206. row: any
  207. rowIndex: number
  208. }) => {
  209. if (row.rowClass) {
  210. return row.rowClass
  211. }
  212. return ''
  213. }
  214. //给某一格加class
  215. const cellClass = ref('')
  216. const cellClassName = (row: Object) => {
  217. emit('cellClass', row)
  218. return cellClass.value
  219. }
  220. //滚动分页加载
  221. const load = () => {
  222. emit('load', true)
  223. }
  224. const rowClickHandler = (row, column, event) => {
  225. emit('rowClick', row, column, event)
  226. }
  227. const cellClickHandler = (row, column, cell, event) => {
  228. emit('cellClick', row, column, cell, event)
  229. }
  230. const table = ref<InstanceType<typeof ElTable> | null>(null)
  231. defineExpose({
  232. cellClass,
  233. table,
  234. })
  235. </script>
  236. <style scoped lang="scss">
  237. .infinite-list {
  238. height: 300px;
  239. padding: 0;
  240. margin: 0;
  241. list-style: none;
  242. }
  243. .infinite-list .infinite-list-item {
  244. display: flex;
  245. align-items: center;
  246. justify-content: center;
  247. height: 50px;
  248. background: var(--el-color-primary-light-9);
  249. margin: 10px;
  250. color: var(--el-color-primary);
  251. }
  252. .infinite-list .infinite-list-item + .list-item {
  253. margin-top: 10px;
  254. }
  255. :deep.el-table {
  256. .rowClass {
  257. height: 40px;
  258. font-size: 14px;
  259. color: #101116;
  260. }
  261. .headerRowClass {
  262. height: 40px;
  263. background: #ffffff;
  264. font-size: 14px;
  265. font-weight: bold;
  266. color: #101116;
  267. }
  268. .editBtn {
  269. background: #ffffff;
  270. border: 1px solid #f79ec6;
  271. box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.06);
  272. border-radius: 4px;
  273. font-size: 12px;
  274. font-weight: 400;
  275. color: #ac014d;
  276. }
  277. .delBtn {
  278. background: #eb2f3b;
  279. box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.06);
  280. border-radius: 4px;
  281. font-size: 12px;
  282. font-weight: 400;
  283. color: #ffffff;
  284. border: none;
  285. }
  286. .child-list {
  287. font-size: 14px;
  288. font-family: Helvetica;
  289. font-weight: 400;
  290. color: #101116;
  291. }
  292. .el-table__body .el-table__cell.cell-click {
  293. color: #2d67e3;
  294. cursor: pointer;
  295. }
  296. }
  297. :deep.el-table--striped
  298. .el-table__body
  299. tr.el-table__row--striped
  300. td.el-table__cell {
  301. background-color: #f0f3f7;
  302. }
  303. .tableStatus {
  304. font-size: 14px;
  305. .icon {
  306. width: 14px;
  307. height: 14px;
  308. background: #2d67e3;
  309. border-radius: 2px;
  310. display: inline-block;
  311. vertical-align: middle;
  312. position: relative;
  313. top: -2px;
  314. }
  315. .status0 {
  316. position: relative;
  317. top: 5px;
  318. }
  319. .status1 {
  320. position: relative;
  321. top: 5px;
  322. .icon {
  323. background-color: #afb4bf;
  324. }
  325. }
  326. .status2 {
  327. position: relative;
  328. top: 5px;
  329. .icon {
  330. background-color: #eb2f3b;
  331. }
  332. }
  333. }
  334. </style>