uni-data-table.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <view class="table-container">
  3. <view class="thead">
  4. <view class="th" v-for="(th, thIndex) in cols" :key="thIndex" :style="{ flex: th.width, maxWidth: th.width + '%', textAlign: th.align ? th.align : 'center' }">
  5. <view class="content">
  6. <view
  7. v-if="th.checkbox"
  8. class="iconfont"
  9. @click="all"
  10. :class="{
  11. iconfuxuankuang2: selected.length == 0,
  12. iconcheckbox_weiquanxuan: selected.length != list.length,
  13. iconfuxuankuang1: selected.length > 0 && selected.length == list.length
  14. }"
  15. ></view>
  16. <text v-else>{{ th.title }}</text>
  17. </view>
  18. </view>
  19. </view>
  20. <view class="tbody">
  21. <view class="tr" v-for="(d, index) in list" :key="index" v-if="list.length">
  22. <view class="td" v-for="(th, thIndex) in cols" :key="thIndex" :style="{ flex: th.width, maxWidth: th.width + '%', textAlign: th.align ? th.align : 'center' }">
  23. <view class="content" :class="{ action: th.action }">
  24. <view v-if="th.checkbox" @click="single(d, index)">
  25. <view
  26. v-if="th.checkbox"
  27. class="iconfont"
  28. :class="{
  29. iconfuxuankuang2: selectedIndex.indexOf(index) == -1,
  30. iconfuxuankuang1: selectedIndex.indexOf(index) != -1
  31. }"
  32. ></view>
  33. </view>
  34. <slot v-else-if="th.action" name="action" :value="d" :index="index"></slot>
  35. <text v-else-if="th.templet" v-html="th.templet(d)"></text>
  36. <text v-else-if="th.return">{{ th.return(d) }}</text>
  37. <text v-else>{{ d[th.field] }}</text>
  38. </view>
  39. </view>
  40. </view>
  41. <view class="tr empty" v-if="!list.length">
  42. <view class="td">
  43. <view class="iconfont iconwushuju"></view>
  44. <view>暂无数据</view>
  45. </view>
  46. </view>
  47. </view>
  48. <view class="tpage" v-if="list.length">
  49. <view class="batch-action"><slot name="batchaction" :value="selected"></slot></view>
  50. <uni-pagination :total="total" :showIcon="true" @change="pageChange" :pageSize="pagesize" :value="page" />
  51. </view>
  52. </view>
  53. </template>
  54. <script>
  55. export default {
  56. name: 'uniDataTable',
  57. props: {
  58. cols: {
  59. type: Array
  60. },
  61. url: {
  62. type: String
  63. },
  64. pagesize: {
  65. type: Number,
  66. default: 10
  67. },
  68. option: {
  69. type: Object,
  70. default: function() {
  71. return {};
  72. }
  73. }
  74. },
  75. created() {
  76. this.load();
  77. },
  78. data() {
  79. return {
  80. list: [],
  81. selected: [],
  82. selectedIndex: [],
  83. page: 1,
  84. total: 0
  85. };
  86. },
  87. methods: {
  88. /**
  89. * 全选
  90. */
  91. all() {
  92. if (this.list.length) {
  93. if (this.selected.length == this.list.length) {
  94. this.selected = [];
  95. this.selectedIndex = [];
  96. } else {
  97. let selectedIndex = [],
  98. selected = [];
  99. this.list.forEach((item, index) => {
  100. selectedIndex.push(index);
  101. selected.push(item);
  102. });
  103. this.selectedIndex = selectedIndex;
  104. this.selected = selected;
  105. }
  106. this.$emit('checkBox', this.selected);
  107. }
  108. },
  109. /**
  110. * 单选
  111. * @param {Object} item
  112. * @param {Object} index
  113. */
  114. single(item, index) {
  115. let _index = this.selectedIndex.indexOf(index);
  116. if (_index == -1) {
  117. this.selectedIndex.push(index);
  118. this.selected.push(item);
  119. } else {
  120. this.selectedIndex.splice(_index, 1);
  121. this.selected.splice(_index, 1);
  122. }
  123. this.$emit('checkBox', this.selected);
  124. },
  125. /**
  126. * 设置默认选中数据
  127. */
  128. defaultSelectData(selected, selectedIndex) {
  129. this.selected = selected;
  130. this.selectedIndex = selectedIndex;
  131. },
  132. pageChange(e) {
  133. this.page = e.current;
  134. this.load();
  135. },
  136. load(option = {}) {
  137. let data = {
  138. page: option.page || this.page,
  139. page_size: this.pagesize
  140. };
  141. if (this.option) Object.assign(data, this.option);
  142. if (option) Object.assign(data, option);
  143. this.$api.sendRequest({
  144. url: this.url,
  145. data: data,
  146. success: res => {
  147. if (res.code >= 0) {
  148. this.list = res.data.list;
  149. this.total = res.data.count;
  150. this.selected = [];
  151. this.selectedIndex = [];
  152. this.$emit('tableData', this.list);
  153. if(option.page){
  154. this.page = option.page;
  155. delete option.page;
  156. }
  157. } else {
  158. this.$util.showToast({ title: res.message });
  159. }
  160. },
  161. fail: () => {
  162. this.$util.showToast({ title: '请求失败' });
  163. }
  164. });
  165. }
  166. }
  167. };
  168. </script>
  169. <style lang="scss">
  170. .table-container {
  171. width: 100%;
  172. .iconcheckbox_weiquanxuan,
  173. .iconfuxuankuang1,
  174. .iconfuxuankuang2 {
  175. color: $primary-color;
  176. cursor: pointer;
  177. font-size: 0.16rem;
  178. transition: all 0.3s;
  179. }
  180. .iconfuxuankuang2 {
  181. color: #e6e6e6;
  182. &:hover {
  183. color: $primary-color;
  184. }
  185. }
  186. }
  187. .thead {
  188. display: flex;
  189. width: 100%;
  190. height: 0.5rem;
  191. background: #f7f8fa;
  192. align-items: center;
  193. .th {
  194. padding: 0 0.1rem;
  195. box-sizing: border-box;
  196. .content {
  197. white-space: nowrap;
  198. width: 100%;
  199. overflow: hidden;
  200. text-overflow: ellipsis;
  201. }
  202. }
  203. }
  204. .tr {
  205. display: flex;
  206. border-bottom: 0.01rem solid #e6e6e6;
  207. min-height: 0.5rem;
  208. align-items: center;
  209. transition: background-color 0.3s;
  210. padding: 0.1rem 0;
  211. box-sizing: border-box;
  212. &:hover {
  213. background: #f5f5f5;
  214. }
  215. .td {
  216. padding: 0 0.1rem;
  217. box-sizing: border-box;
  218. .content {
  219. white-space: nowrap;
  220. width: 100%;
  221. overflow: hidden;
  222. text-overflow: ellipsis;
  223. }
  224. }
  225. &.empty {
  226. justify-content: center;
  227. .td {
  228. text-align: center;
  229. color: #909399;
  230. .iconfont {
  231. font-size: 0.25rem;
  232. margin: 0.05rem;
  233. }
  234. }
  235. }
  236. }
  237. .tpage {
  238. display: flex;
  239. align-items: center;
  240. padding: 0.1rem 0;
  241. margin-bottom: 0.1rem;
  242. .uni-pagination {
  243. justify-content: flex-end;
  244. flex: 1;
  245. }
  246. }
  247. </style>