dymic_table.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <div class="dymic-table scrollbar">
  3. <el-table
  4. :height="height"
  5. class="no-scrollbar"
  6. :summary-method="getSummaries"
  7. style="width: 100%"
  8. :data="data"
  9. :show-header="settings.showHeader"
  10. size="small"
  11. lazy
  12. v-loading="loading"
  13. :row-class-name="setRowClassName"
  14. :show-summary="!!(settings.summaryCol && settings.summaryCol.length)"
  15. @selection-change="selectionChange"
  16. :empty-text="emptyText"
  17. >
  18. <el-table-column
  19. type="selection"
  20. width="50"
  21. align="center"
  22. v-if="settings.showCheckbox"
  23. :selectable="selectable"
  24. ></el-table-column>
  25. <el-table-column
  26. label="No."
  27. type="index"
  28. align="center"
  29. v-if="settings.showIndex"
  30. ></el-table-column>
  31. <el-table-column
  32. v-for="(item, index) in cols"
  33. :key="index"
  34. :width="item.width"
  35. :min-width="item.minWidth"
  36. :label="item.label"
  37. :prop="item.prop"
  38. align="center"
  39. >
  40. <template v-if="item.children" :label="item.label">
  41. <el-table-column
  42. v-for="(item1, index1) in item.children"
  43. :prop="item1.prop"
  44. :key="index1"
  45. :width="item.width"
  46. :min-width="item.minWidth"
  47. :label="item1.label"
  48. align="center"
  49. >
  50. <template slot-scope="scope">
  51. <!-- 插槽 -->
  52. <slotItem v-if="item1.slot" :row="scope.row" :index="scope.$index" :slots="$scopedSlots[item1.slot]"></slotItem>
  53. <!-- 过滤方法 -->
  54. <p v-else-if="item1.format" v-tip
  55. :data-txt="item1.format(scope.row[item1.prop],scope.row)"
  56. @click="item1.click?item1.click():null">
  57. {{
  58. item1.format(scope.row[item1.prop],scope.row)||
  59. (item1.format(scope.row[item1.prop],scope.row)===0?0:item1.empty?'':'-')
  60. }}
  61. </p>
  62. <!-- 默认显示 -->
  63. <p v-else-if="item1.fixToolTip" v-tip.same :data-txt="scope.row[item1.prop]" @click="item1.click?item1.click():null">
  64. {{scope.row[item1.prop]||(scope.row[item1.prop]===0?0:item1.empty?'':'-')}}
  65. </p>
  66. <p v-else v-tip :data-txt="scope.row[item1.prop]" @click="item1.click?item1.click():null">
  67. {{scope.row[item1.prop]||(scope.row[item1.prop]===0?0:item1.empty?'':'-')}}
  68. </p>
  69. </template>
  70. <template v-if="item1.children" :label="item1.label">
  71. <el-table-column
  72. v-for="(item2,index2) in item1.children" :prop="item2.prop"
  73. :key="index2"
  74. :width="item1.width"
  75. :min-width="item1.minWidth"
  76. :label="item2.label"
  77. align="center">
  78. <template slot-scope="scope">
  79. <p v-if="item2.format" v-tip
  80. :data-txt="item2.format(scope.row[item2.prop],scope.row)"
  81. @click="item2.click?item2.click():null">
  82. {{
  83. item2.format(scope.row[item2.prop],scope.row)||
  84. (item2.format(scope.row[item2.prop],scope.row)===0?0:item2.empty?'':'-')
  85. }}
  86. </p>
  87. </template>
  88. </el-table-column>
  89. </template>
  90. </el-table-column>
  91. </template>
  92. <template slot-scope="scope">
  93. <!-- 插槽 -->
  94. <slotItem v-if="item.slot" :row="scope.row" :index="scope.$index" :slots="$scopedSlots[item.slot]"></slotItem>
  95. <!-- 过滤方法 -->
  96. <p v-else-if="item.format" v-tip
  97. :data-txt="item.format(scope.row[item.prop],scope.row)"
  98. @click="item.click?item.click():null">
  99. {{
  100. item.format(scope.row[item.prop],scope.row)||
  101. (item.format(scope.row[item.prop],scope.row)===0?0:item.empty?'':'-')
  102. }}
  103. </p>
  104. <!-- 默认显示 -->
  105. <p v-else-if="item.fixToolTip" v-tip.same :data-txt="scope.row[item.prop]" @click="item.click?item.click():null">
  106. {{scope.row[item.prop]||(scope.row[item.prop]===0?0:item.empty?'':'-')}}
  107. </p>
  108. <p v-tip v-else :data-txt="scope.row[item.prop]" @click="item.click?item.click():null">
  109. {{scope.row[item.prop]||(scope.row[item.prop]===0?0:item.empty?'':'-')}}
  110. </p>
  111. </template>
  112. </el-table-column>
  113. </el-table>
  114. <div class="foot">
  115. <!-- 手动全选及操作 -->
  116. <el-pagination
  117. class="pagination"
  118. background
  119. @size-change="sizeChange"
  120. @current-change="currentChange"
  121. :current-page="currentPage"
  122. :page-sizes="pageset.pageSizes || [15, 30, 60, 120]"
  123. :page-size="pageset.pageSize || 15"
  124. :total="pageset.total || 0"
  125. layout="total, sizes, prev, pager, next, jumper"
  126. >
  127. </el-pagination>
  128. </div>
  129. </div>
  130. </template>
  131. <script>
  132. export default {
  133. name: "dymic-table",
  134. props: {
  135. /** 列数据*/
  136. cols: {
  137. type: Array,
  138. default() {
  139. return [];
  140. },
  141. },
  142. /**table数据*/
  143. data: {
  144. type: Array,
  145. default() {
  146. return [];
  147. },
  148. },
  149. /**table表格设置 */
  150. settings: {
  151. type: Object,
  152. default() {
  153. return {
  154. // 是否显示表头
  155. showHeader: false,
  156. // 是否显示序号
  157. showIndex: false,
  158. // 是否显示多选框
  159. showCheckbox: false,
  160. hideAllCheckbox: false,
  161. // 是否显示单选框
  162. showRadio: false,
  163. // 需要统计列的prop集合,从0开始
  164. summaryCol: [],
  165. };
  166. },
  167. },
  168. /**分页设置*/
  169. pageset: {
  170. type: Object,
  171. default() {
  172. return {
  173. total: 0,
  174. pageSize: 10,
  175. pageNum: 1,
  176. pageSizes: [15, 30, 60, 120],
  177. };
  178. },
  179. },
  180. loading: {
  181. type: Boolean,
  182. default() {
  183. return false;
  184. }
  185. },
  186. height: 0,
  187. /**数据为空的显示 */
  188. emptyText: {
  189. type: String,
  190. default() {
  191. return "暂无相关结果";
  192. },
  193. },
  194. /**判断多选框是否可以勾选*/
  195. selectable: {
  196. type: Function,
  197. default() {
  198. return (row, index) => {
  199. return true;
  200. };
  201. },
  202. },
  203. },
  204. watch: {
  205. radioSelect(n) {
  206. this.$emit("radio-change", this.data[n]);
  207. },
  208. pageset: {
  209. deep: true,
  210. handler(n) {
  211. this.currentPage = n.pageNum;
  212. },
  213. },
  214. },
  215. components:{
  216. slotItem:{
  217. props:['slots','row','index'],
  218. render(h){
  219. let vnode = this.slots({
  220. row:this.row,
  221. index:this.index
  222. })
  223. return h('div',vnode)
  224. }
  225. }
  226. },
  227. data() {
  228. return {
  229. currentPage: 1,
  230. };
  231. },
  232. methods: {
  233. // 多选派发事件selection-change
  234. selectionChange(val) {
  235. this.isSelectAll = val.length == this.data.length;
  236. this.$emit("selection-change", val);
  237. },
  238. currentChange(page) {
  239. this.currentPage = page;
  240. this.$emit("page-change", {
  241. page: page,
  242. });
  243. },
  244. sizeChange(pageSize) {
  245. this.$emit("page-change", {
  246. pageSize: pageSize,
  247. });
  248. },
  249. currentChange(page) {
  250. this.currentPage = page;
  251. this.$emit("page-change", {
  252. page: page,
  253. });
  254. },
  255. // 合计
  256. getSummaries(params) {
  257. let { data } = params;
  258. if ("{}" != JSON.stringify(this.summaryData)) {
  259. data = [this.summaryData];
  260. }
  261. let sums = [];
  262. sums[0] = "合计";
  263. let cols = JSON.parse(JSON.stringify(this.settings.summaryCol));
  264. let i = cols.length;
  265. while (i--) {
  266. // 计算当前列的prop字段
  267. let index = cols[i];
  268. if (this.settings.showIndex) {
  269. index -= 1;
  270. }
  271. if (this.settings.showCheckbox) {
  272. index -= 1;
  273. }
  274. if (this.settings.showRadio) {
  275. index -= 1;
  276. }
  277. let prop = this.cols[index].prop;
  278. const values = data.map((item) => Number(item[prop]));
  279. if (!values.every((value) => isNaN(value))) {
  280. sums[cols[i]] = values.reduce((prev, curr) => {
  281. const value = Number(curr);
  282. if (!isNaN(value)) {
  283. return prev + curr;
  284. } else {
  285. return prev;
  286. }
  287. }, 0);
  288. sums[cols[i]];
  289. }
  290. }
  291. return sums;
  292. },
  293. checkAllChange(val) {
  294. if (val) {
  295. this.$refs.table.toggleAllSelection();
  296. } else {
  297. this.$refs.table.clearSelection();
  298. }
  299. },
  300. //自定义表头斑马线
  301. setRowClassName({ row, rowIndex }) {
  302. let index = rowIndex;
  303. if (index % 2 == 0) {
  304. return "warning-row";
  305. }
  306. },
  307. },
  308. created() {
  309. },
  310. };
  311. </script>
  312. <style lang="scss" scoped>
  313. /deep/.dymic-table .el-table .el-table__body td p{
  314. overflow: hidden;
  315. text-overflow: ellipsis;
  316. white-space: nowrap;
  317. }
  318. /deep/.dymic-table .el-table--enable-row-transition .el-table__body td{
  319. border:none;
  320. }
  321. .dymic-table .el-table {
  322. border-radius: 6px;
  323. }
  324. /deep/ .el-table{
  325. .el-table__header-wrapper thead tr th:nth-child(-n+2){
  326. .cell{
  327. width: max-content;
  328. }
  329. }
  330. }
  331. </style>