index.vue 8.9 KB

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