tables.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <template>
  2. <div class="table-main">
  3. <div v-if="controllable" class="table-tools">
  4. <div class=" clearfix">
  5. <div class="tools-left fl">
  6. <div class="tools-search-item" v-for="(tools, index) in tools" :key="index">
  7. <label>{{ tools.label }}</label>
  8. <Select clearable v-model="pageParam[`tools_${index}`]" style="width:240px" size="large" :placeholder="tools.placeholder" filterable @on-change="handleTableData">
  9. <Option v-for="item in tools.options" :value="item.value" :key="item.value">{{ item.label }}</Option>
  10. </Select>
  11. </div>
  12. <div class="tools-search-item">
  13. <Input :placeholder="placeholder" v-model="pageParam.searchKey" style="width: 240px" size="large" @on-enter="handleTableData" @on-click="handleTableData">
  14. <Icon type="ios-search" slot="suffix" />
  15. </Input>
  16. </div>
  17. </div>
  18. <!-- 顶部按钮组,由父组件:buttonList 传递 -->
  19. <div v-if="buttonList.length > 0" class="button-group fr">
  20. <Button
  21. v-for="(btn, index) in buttonList"
  22. :key="index"
  23. size="large"
  24. :type="btn.type ? btn.type : 'primary'"
  25. @click="btnHandle(btn.handle, btn.param)"
  26. >{{ btn.text }}</Button>
  27. </div>
  28. </div>
  29. </div>
  30. <Table :data="tableData" :columns="tableColumns" @on-selection-change="handleSelect">
  31. <template slot="action" slot-scope="{ row, index }">
  32. <handleBtns
  33. :tools-btn-group="toolsBtnGroup"
  34. :row="row"
  35. @handleClickBtn="handleRowBtn"
  36. />
  37. </template>
  38. </Table>
  39. <div style="margin-top: 20px; overflow: hidden;">
  40. <div style="float: right;">
  41. <Page
  42. v-if="pageParam.total > 0"
  43. :current.sync="pageParam.current"
  44. :total="pageParam.total"
  45. :page-size="pageParam.page_size"
  46. class-name="tatle-page"
  47. size="small"
  48. show-total
  49. show-elevator
  50. @on-change="changePage"
  51. />
  52. </div>
  53. </div>
  54. </div>
  55. </template>
  56. <script>
  57. import handleBtns from './handle-btns.vue'
  58. export default {
  59. name: 'Tables',
  60. components: {
  61. handleBtns
  62. },
  63. props: {
  64. // 从父组件得到的数据接口
  65. dataApi: Function,
  66. deleteApi: Function,
  67. deleteIdKey: String,
  68. // 从父组件得到的表格列数据
  69. columns: {
  70. type: Array,
  71. default() {
  72. return []
  73. }
  74. },
  75. tools: {
  76. type: Array,
  77. default () {
  78. return []
  79. }
  80. },
  81. // 是否显示工具控件
  82. controllable: {
  83. type: Boolean,
  84. default: true
  85. },
  86. // 是否显示按钮组
  87. buttonList: {
  88. type: Array,
  89. default() {
  90. return []
  91. }
  92. },
  93. long: {
  94. type: Boolean,
  95. default: false
  96. },
  97. placeholder: {
  98. type: String,
  99. default: '房源ID/名称/经纪人'
  100. }
  101. },
  102. data() {
  103. return {
  104. // 通过dataApi获取,处理后的单元格数据
  105. tableData: [],
  106. // 通过props获取后,处理后的表格列数据
  107. tableColumns: [],
  108. // 工具按钮组
  109. toolsBtnGroup: [],
  110. time: null,
  111. pageParam: { page_num: 1, page_size: 10, searchKey: '', total: 0, current: 1, tools_0: '', tools_1: '' }
  112. }
  113. },
  114. computed: {
  115. access() {
  116. return this.$store.state.user.access
  117. }
  118. },
  119. watch: {
  120. // 监听搜索框,并在用户在时间间隔内只发送一次请求
  121. 'pageParam.searchKey'() {
  122. this.$bebounce(this.handleTableData, { page_num: 1, current: 1 })
  123. },
  124. columns() {
  125. this.handleTableData()
  126. }
  127. },
  128. created() {
  129. },
  130. mounted() {
  131. this.handleColumns(this.columns)
  132. if (this.long) {
  133. this.time = window.setInterval(() => {
  134. setTimeout(this.handleTableData, 0)
  135. }, 3000)
  136. }
  137. this.handleTableData()
  138. },
  139. beforeDestroy() {
  140. clearInterval(this.time)
  141. },
  142. methods: {
  143. // 处理表格列数据
  144. handleColumns(columns) {
  145. this.tableColumns = columns.map(item => {
  146. const res = item
  147. // 当表格列数据存在 slot 时,特殊处理
  148. if (item.slot === 'action') this.slotAction(res)
  149. return res
  150. })
  151. },
  152. // 处理表格列中 含有 slot 的项
  153. slotAction(item) {
  154. const arr = ['admin', 'edit']
  155. const access = this.access.some(i => arr.includes(i))
  156. const { tools = [] } = item
  157. // this.toolsBtnGroup = access ? tools : tools.filter(item => item == 'view' || item == 'del')
  158. this.toolsBtnGroup = tools
  159. },
  160. // 处理单元格数据
  161. handleTableData(param) {
  162. const fetchParam = Object.assign(this.pageParam, param)
  163. this.dataApi(fetchParam).then(
  164. res => {
  165. const { data } = res
  166. const list = data.list || data
  167. // list.forEach(item => {
  168. // if (item.roleKey === 'admin') item._disabled = true
  169. // item.orientation = this.oriAction(item.orientation)
  170. // })
  171. this.tableData = list
  172. this.pageParam.total = data.totalNum || data.total
  173. }
  174. )
  175. },
  176. // 处理表格列中 朝向 的项
  177. oriAction(ori) {
  178. const aspectList = [
  179. {
  180. value: 'E',
  181. label: '东'
  182. },
  183. {
  184. value: 'W',
  185. label: '西'
  186. },
  187. {
  188. value: 'S',
  189. label: '南'
  190. },
  191. {
  192. value: 'N',
  193. label: '北'
  194. },
  195. {
  196. value: 'ES',
  197. label: '东南'
  198. },
  199. {
  200. value: 'EN',
  201. label: '东北'
  202. },
  203. {
  204. value: 'WS',
  205. label: '西南'
  206. },
  207. {
  208. value: 'WN',
  209. label: '西北'
  210. }
  211. ]
  212. for (let i = 0; i < aspectList.length; i++) {
  213. if (aspectList[i].value === ori) {
  214. return aspectList[i].label
  215. }
  216. }
  217. },
  218. // 选中某列 返回选中的数据
  219. handleSelect(selection) {
  220. this.$emit('chooseSelection', selection)
  221. },
  222. // 按钮事件
  223. btnHandle(handleName, param) {
  224. this.$emit(handleName, param)
  225. },
  226. async handleRowBtn(param) {
  227. if (param.action === 'toDel') {
  228. // 获取对应的id字段得值
  229. await this.deleteApi([param.row[this.deleteIdKey] || param.row[Object.keys(param.row).find(item => item.indexOf('_id') > -1)]])
  230. this.handleTableData()
  231. return
  232. }
  233. this.$emit(param.action, param.row)
  234. },
  235. // 分页
  236. changePage(page) {
  237. this.handleTableData({ page_num: page })
  238. }
  239. }
  240. }
  241. </script>
  242. <style scoped lang="less">
  243. .search-box {
  244. display: inline-block;
  245. }
  246. .button-group {
  247. float: right;
  248. }
  249. .table-tools {
  250. margin-bottom: 20px;
  251. }
  252. .tools-search-item {
  253. margin-right: 20px;
  254. display: inline-block;
  255. label {
  256. margin-right: 10px;
  257. }
  258. }
  259. </style>