StandardTable.vue 5.1 KB

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