filter-page-table.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <div id="data-table">
  3. <el-form :model="searchInfo" :inline="true" style="padding:0.9rem 1.875rem ;" size="mini" v-if="useFilter">
  4. <el-form-item v-for="(item, index) in filterList" :key="index">
  5. <template v-if="item.filter === 'select'">
  6. <el-select
  7. v-model="searchInfo[item.prop]"
  8. size="mini"
  9. clearable
  10. filterable
  11. :placeholder="`请选择${item.label}`"
  12. @clear="toClear(item.prop)"
  13. @change="data => filterReturn(data, item)"
  14. >
  15. <slot name="options" v-bind="{ item }"></slot>
  16. </el-select>
  17. </template>
  18. <template v-else-if="item.filter === 'date'">
  19. <el-date-picker
  20. v-model="searchInfo[item.prop]"
  21. value-format="yyyy-MM-dd"
  22. format="yyyy-MM-dd"
  23. type="daterange"
  24. range-separator="-"
  25. start-placeholder="开始日期"
  26. end-placeholder="结束日期"
  27. clearable
  28. >
  29. </el-date-picker>
  30. </template>
  31. <template v-else>
  32. <el-input v-model="searchInfo[item.prop]" clearable size="mini" :placeholder="`请输入${item.label}`" @clear="toClear(item.prop)"></el-input>
  33. </template>
  34. </el-form-item>
  35. <el-form-item>
  36. <el-button type="primary" size="mini" @click="filterSearch">查询</el-button>
  37. </el-form-item>
  38. </el-form>
  39. <el-table
  40. ref="table"
  41. row-key="id"
  42. :data="data"
  43. border
  44. stripe
  45. size="mini"
  46. :max-height="height !== null ? height : ''"
  47. @select="handleSelectionChange"
  48. @select-all="handleSelectAll"
  49. v-bind="options"
  50. :show-summary="useSum"
  51. @row-click="rowClick"
  52. >
  53. <el-table-column type="selection" width="55" v-if="select" prop="id" :reserve-selection="true"> </el-table-column>
  54. <template v-for="(item, index) in fields">
  55. <template v-if="!item.notable">
  56. <template v-if="item.custom">
  57. <el-table-column :key="index" align="center" :label="item.label" v-bind="item.options">
  58. <template v-slot="{ row }">
  59. <slot name="custom" v-bind="{ item, row }"></slot>
  60. </template>
  61. </el-table-column>
  62. </template>
  63. <template v-else>
  64. <el-table-column
  65. :key="index"
  66. align="center"
  67. :label="item.label"
  68. :prop="item.prop"
  69. :formatter="toFormatter"
  70. sortable
  71. v-bind="item.options"
  72. :show-overflow-tooltip="item.showTip"
  73. >
  74. </el-table-column>
  75. </template>
  76. </template>
  77. </template>
  78. <template v-if="opera.length > 0">
  79. <el-table-column label="操作" align="center" :width="operaWidth">
  80. <template v-slot="{ row, $index }">
  81. <template v-for="(item, index) in opera">
  82. <template v-if="display(item, row)">
  83. <el-tooltip v-if="item.icon" :key="index" effect="dark" :content="item.label" placement="bottom">
  84. <!-- <el-button
  85. :key="index"
  86. type="text"
  87. :icon="item.icon || ''"
  88. size="mini"
  89. @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
  90. ></el-button> -->
  91. <el-link
  92. :key="index"
  93. :type="item.type || 'primary'"
  94. :icon="item.icon || ''"
  95. size="mini"
  96. style="padding-right:10px"
  97. :underline="false"
  98. @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
  99. >
  100. </el-link>
  101. </el-tooltip>
  102. <el-link
  103. v-else
  104. :key="index"
  105. :type="item.type || 'primary'"
  106. :icon="item.icon || ''"
  107. size="mini"
  108. style="padding-right:10px"
  109. :underline="false"
  110. @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
  111. >
  112. {{ item.label }}
  113. </el-link>
  114. <!-- <el-button v-else :key="index" type="text" size="mini" @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)">
  115. {{ item.label }}
  116. </el-button> -->
  117. </template>
  118. </template>
  119. </template>
  120. </el-table-column>
  121. </template>
  122. </el-table>
  123. <el-row type="flex" align="middle" justify="end" style="padding-top:1rem" v-if="usePage">
  124. <el-col :span="24" style="text-align:right;">
  125. <el-pagination
  126. background
  127. layout="total, prev, pager, next"
  128. :page-sizes="[10, 15, 20, 50, 100]"
  129. :total="total"
  130. :page-size="limit"
  131. :current-page.sync="currentPage"
  132. @current-change="changePage"
  133. @size-change="sizeChange"
  134. >
  135. </el-pagination>
  136. <!-- sizes -->
  137. </el-col>
  138. </el-row>
  139. </div>
  140. </template>
  141. <script>
  142. import _ from 'lodash';
  143. export default {
  144. name: 'data-table',
  145. props: {
  146. fields: { type: Array, required: true },
  147. data: { type: Array, required: true },
  148. opera: { type: Array, default: () => [] },
  149. toFormat: null,
  150. height: null,
  151. select: { type: Boolean, default: false },
  152. selected: { type: Array, default: () => [] },
  153. usePage: { type: Boolean, default: true },
  154. total: { type: Number, default: 0 },
  155. options: null,
  156. useSum: { type: Boolean, default: false },
  157. filter: { type: Array, default: () => [] },
  158. operaWidth: { type: Number, default: 200 },
  159. },
  160. components: {},
  161. data: () => ({
  162. pageSelected: [],
  163. currentPage: 1,
  164. limit: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10,
  165. searchInfo: {},
  166. useFilter: true,
  167. filterList: [],
  168. }),
  169. created() {},
  170. computed: {},
  171. methods: {
  172. toFormatter(row, column, cellValue, index) {
  173. let this_fields = this.fields.filter(fil => fil.prop === column.property);
  174. if (this_fields.length > 0) {
  175. let format = _.get(this_fields[0], `format`, false);
  176. if (format) {
  177. let res;
  178. if (_.isFunction(format)) {
  179. res = format(cellValue);
  180. } else {
  181. res = this.toFormat({
  182. model: this_fields[0].prop,
  183. value: cellValue,
  184. });
  185. }
  186. return res;
  187. } else return cellValue;
  188. }
  189. },
  190. handleOpera(data, method, confirm = false, methodZh, label, index) {
  191. let self = true;
  192. if (_.isFunction(methodZh)) {
  193. methodZh = methodZh(data);
  194. } else if (!_.isString(methodZh)) {
  195. methodZh = label;
  196. self = false;
  197. }
  198. if (confirm) {
  199. this.$confirm(self ? methodZh : `您确认${methodZh}该数据?`, '提示', {
  200. confirmButtonText: '确定',
  201. cancelButtonText: '取消',
  202. type: 'warning',
  203. })
  204. .then(() => {
  205. this.$emit(method, { data, index });
  206. })
  207. .catch(() => {});
  208. } else {
  209. this.$emit(method, { data, index });
  210. }
  211. },
  212. handleSelectionChange(selection, row) {
  213. // console.log(selection);
  214. // console.log(row);
  215. //根据row是否再pageSelected中,判断是添加还是删除
  216. let res = [];
  217. if (this.pageSelected.find(i => i.id === row.id)) {
  218. res = this.pageSelected.filter(f => f.id !== row.id);
  219. } else {
  220. this.pageSelected.push(row);
  221. res = this.pageSelected;
  222. }
  223. this.$set(this, `pageSelected`, res);
  224. this.$emit(`handleSelect`, _.uniqBy(res, 'id'));
  225. },
  226. handleSelectAll(selection) {
  227. //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
  228. // console.log(selection);
  229. let res = [];
  230. if (selection.length > 0) {
  231. //全选
  232. res = _.uniqBy(this.pageSelected.concat(selection), 'id');
  233. } else {
  234. //全取消
  235. res = _.differenceBy(this.pageSelected, this.data, 'id');
  236. }
  237. this.$set(this, `pageSelected`, res);
  238. this.$emit(`handleSelect`, res);
  239. },
  240. initSelection() {
  241. this.$nextTick(() => {
  242. this.$refs.table.clearSelection();
  243. this.selected.forEach(info => {
  244. let d = this.data.filter(p => p.id === info.id);
  245. if (d.length > 0) this.$refs.table.toggleRowSelection(d[0]);
  246. });
  247. });
  248. },
  249. selectReset() {
  250. this.$refs.table.clearSelection();
  251. },
  252. display(item, row) {
  253. let display = _.get(item, `display`, true);
  254. if (display === true) return true;
  255. else {
  256. let res = display(row);
  257. return res;
  258. }
  259. },
  260. //
  261. changePage(page = this.currentPage) {
  262. this.$emit('query', { skip: (page - 1) * this.limit, limit: this.limit, ...this.searchInfo });
  263. },
  264. sizeChange(limit) {
  265. this.limit = limit;
  266. this.currentPage = 1;
  267. this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
  268. },
  269. getFilterList() {
  270. let res = this.fields.filter(f => _.get(f, 'filter', false));
  271. this.$set(this, `useFilter`, res.length > 0);
  272. res.map(i => {
  273. if (i.filter === 'date' && this.searchInfo[i.porp] === undefined) this.$set(this.searchInfo, i.prop, []);
  274. });
  275. res = [...res, ...this.filter];
  276. this.$set(this, `filterList`, res);
  277. },
  278. filterSearch() {
  279. this.currentPage = 1;
  280. this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
  281. },
  282. rowClick(row, column, event) {
  283. this.$emit(`rowClick`, row);
  284. },
  285. toClear(prop) {
  286. delete this.searchInfo[prop];
  287. },
  288. filterReturn(data, item) {
  289. let { prop, filterReturn } = item;
  290. if (filterReturn) this.$emit('filterReturn', { data, prop });
  291. },
  292. },
  293. watch: {
  294. selected: {
  295. handler(val) {
  296. if (val.length > 0) {
  297. this.pageSelected = val;
  298. this.initSelection();
  299. }
  300. },
  301. immediate: true,
  302. },
  303. data: {
  304. handler(val, oval) {
  305. if (this.select) {
  306. this.initSelection();
  307. }
  308. },
  309. },
  310. fields: {
  311. handler(val, oval) {
  312. if (val) this.getFilterList();
  313. },
  314. immediate: true,
  315. },
  316. },
  317. };
  318. </script>
  319. <style lang="less" scoped></style>