StandardTable.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <template>
  2. <div class="standard-table">
  3. <div class="alert">
  4. <a-alert type="info" :show-icon="true" v-if="selectedRows">
  5. <div class="message" slot="message">
  6. 已选择&nbsp;<a>{{ selectedRows.length }}</a
  7. >&nbsp;项 <a class="clear" @click="onClear">清空</a>
  8. <template v-for="(item, index) in needTotalList">
  9. <div v-if="item.needTotal" :key="index">
  10. {{ item.title }}总计&nbsp;
  11. <a>{{
  12. item.customRender ? item.customRender(item.total) : item.total
  13. }}</a>
  14. </div>
  15. </template>
  16. </div>
  17. </a-alert>
  18. </div>
  19. <a-table
  20. :bordered="bordered"
  21. :loading="loading"
  22. :columns="columns"
  23. :dataSource="dataSource"
  24. :rowKey="rowKey"
  25. :pagination="pagination"
  26. :expandedRowKeys="expandedRowKeys"
  27. :expandedRowRender="expandedRowRender"
  28. @change="onChange"
  29. :rowSelection="
  30. selectedRows
  31. ? { selectedRowKeys: selectedRowKeys, onChange: updateSelect }
  32. : undefined
  33. "
  34. :rowClassName="rowClassName"
  35. :custom-row="onClickRow"
  36. :scroll="scroll"
  37. >
  38. <template
  39. slot-scope="text, record, index"
  40. :slot="slot"
  41. v-for="slot in Object.keys($scopedSlots).filter(
  42. (key) => key !== 'expandedRowRender'
  43. )"
  44. >
  45. <slot :name="slot" v-bind="{ text, record, index }"></slot>
  46. </template>
  47. <template :slot="slot" v-for="slot in Object.keys($slots)">
  48. <slot :name="slot"></slot>
  49. </template>
  50. <template
  51. slot-scope="record, index, indent, expanded"
  52. :slot="$scopedSlots.expandedRowRender ? 'expandedRowRender' : ''"
  53. >
  54. <slot
  55. v-bind="{ record, index, indent, expanded }"
  56. :name="$scopedSlots.expandedRowRender ? 'expandedRowRender' : ''"
  57. ></slot>
  58. </template>
  59. </a-table>
  60. </div>
  61. </template>
  62. <script>
  63. export default {
  64. name: "StandardTable",
  65. props: {
  66. bordered: Boolean,
  67. loading: [Boolean, Object],
  68. columns: Array,
  69. dataSource: Array,
  70. scroll: Object,
  71. rowKey: {
  72. type: [String, Function],
  73. default: "key",
  74. },
  75. pagination: {
  76. type: [Object, Boolean],
  77. default: () => {
  78. return {
  79. current: 1,
  80. defaultPageSize: 10,
  81. total: 0,
  82. pagesize0ptions: ["10", "20", "30"],
  83. hideOnSinglePage: false,
  84. showQuickJumper: true, //
  85. showsizeChanger: true, //是否可以改变pagesize
  86. };
  87. },
  88. },
  89. selectedRows: Array,
  90. expandedRowKeys: Array,
  91. expandedRowRender: Function,
  92. },
  93. data() {
  94. return {
  95. needTotalList: [],
  96. selectRow: -1,
  97. };
  98. },
  99. methods: {
  100. onClickRow(record, index) {
  101. return {
  102. on: {
  103. click: () => {
  104. this.$emit("onClickRow", record);
  105. this.selectRow = index;
  106. },
  107. },
  108. };
  109. },
  110. rowClassName(record, index) {
  111. // 根据是否是选中行来设置不同的class
  112. // console.log(this.selectRow, index);
  113. return this.selectRow === index ? "highlight-row" : "";
  114. },
  115. updateSelect(selectedRowKeys, selectedRows) {
  116. console.log(selectedRowKeys, selectedRows);
  117. this.$emit("update:selectedRows", selectedRows);
  118. this.$emit("selectedRowChange", selectedRowKeys, selectedRows);
  119. },
  120. initTotalList(columns) {
  121. const totalList = columns
  122. .filter((item) => item.needTotal)
  123. .map((item) => {
  124. return {
  125. ...item,
  126. total: 0,
  127. };
  128. });
  129. return totalList;
  130. },
  131. onClear() {
  132. this.updateSelect([], []);
  133. this.$emit("clear");
  134. },
  135. onChange(pagination, filters, sorter, { currentDataSource }) {
  136. this.$emit("change", pagination, filters, sorter, { currentDataSource });
  137. },
  138. },
  139. created() {
  140. this.needTotalList = this.initTotalList(this.columns);
  141. },
  142. watch: {
  143. selectedRows(selectedRows) {
  144. this.needTotalList = this.needTotalList.map((item) => {
  145. return {
  146. ...item,
  147. total: selectedRows.reduce((sum, val) => {
  148. let v;
  149. try {
  150. v = val[item.dataIndex]
  151. ? val[item.dataIndex]
  152. : eval(`val.${item.dataIndex}`);
  153. } catch (_) {
  154. v = val[item.dataIndex];
  155. }
  156. v = !isNaN(parseFloat(v)) ? parseFloat(v) : 0;
  157. return sum + v;
  158. }, 0),
  159. };
  160. });
  161. },
  162. },
  163. computed: {
  164. selectedRowKeys() {
  165. return this.selectedRows.map((record) => {
  166. return typeof this.rowKey === "function"
  167. ? this.rowKey(record)
  168. : record[this.rowKey];
  169. });
  170. },
  171. },
  172. };
  173. </script>
  174. <style scoped lang="less">
  175. .standard-table {
  176. background: #fff;
  177. padding: 0 15px;
  178. box-sizing: border-box;
  179. width: 100%;
  180. .alert {
  181. margin-bottom: 16px;
  182. .message {
  183. a {
  184. font-weight: 600;
  185. }
  186. }
  187. .clear {
  188. float: right;
  189. }
  190. }
  191. /deep/ .ant-table-thead > tr > th {
  192. background: #fff;
  193. }
  194. /deep/ .ant-table-tbody > tr.highlight-row {
  195. background: linear-gradient(
  196. 90deg,
  197. rgba(52, 93, 230, 0.1) 0%,
  198. rgba(113, 229, 236, 0.1) 100%
  199. );
  200. // opacity: ;
  201. }
  202. }
  203. </style>