index.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <template>
  2. <div>
  3. <el-table
  4. ref="multipleTable"
  5. v-loading="dataLoading"
  6. stripe
  7. border
  8. :header-cell-style="{background:'#F5F7FA'}"
  9. :data="tableData"
  10. :selection-data="selectionData"
  11. :height="tableMaxHeight"
  12. @selection-change="selectionChange"
  13. @row-click="rowdata"
  14. @cell-mouse-enter="cellMouseEnter"
  15. >
  16. <el-table-column fixed :type="selectType" align="center" width="50" />
  17. <el-table-column v-if="showCover" label="Cover" :align="columns[0].align">
  18. <template slot-scope="scope">
  19. <img :src="src+scope.row.cover" width="40" height="40">
  20. </template>
  21. </el-table-column>
  22. <el-table-column v-if="showFace" label="Cover" :align="columns[0].align">
  23. <template slot-scope="scope">
  24. <img :src="src+scope.row.face" width="40" height="40">
  25. </template>
  26. </el-table-column>
  27. <template v-for="(column, index) in columns">
  28. <el-table-column :key="column.label" :prop="column.prop" :label="column.label" :align="column.align" :min-width="column.minWidth" :max-width="column.maxWidth">
  29. <template slot-scope="scope">
  30. <template v-if="!column.render">
  31. <template v-if="typeof column.formatter == 'string'">
  32. <span v-html="formatter(scope.row, column)" />
  33. </template>
  34. <template v-else-if="typeof column.formatter == 'function'">
  35. <span v-html="column.formatter(scope.row, column)" />
  36. </template>
  37. <template v-else>
  38. <span>{{ scope.row[column.prop] }}</span>
  39. </template>
  40. </template>
  41. <template v-else>
  42. <expand-dom :column="column" :row="scope.row" :render="column.render" :index="index" />
  43. </template>
  44. </template>
  45. </el-table-column>
  46. </template>
  47. <el-table-column
  48. v-if="operates.list.length > 0 && (operates.list.filter(_x=>_x.show === true).length > 0 || operates.dropdown.filter(_x=>_x.show === true).length > 0) "
  49. ref="fixedColumn"
  50. label="Operate"
  51. align="center"
  52. :width="operates.width"
  53. :fixed="operates.fixed"
  54. >
  55. <template slot-scope="scope">
  56. <div class="operate-group">
  57. <template v-for="btn in operates.list">
  58. <el-button
  59. v-if="btn.show"
  60. :key="btn.id"
  61. :type="btn.type"
  62. size="mini"
  63. :icon="btn.icon"
  64. :disabled="btn.disabled"
  65. :plain="btn.plain"
  66. @click.native.prevent="btn.method(scope.row)"
  67. >{{ btn.label }}</el-button>
  68. </template>
  69. <div
  70. v-if="operates.dropdown != undefined && operates.dropdown.filter(_x=>_x.show === true).length > 0"
  71. style="display: inline-block;"
  72. >
  73. <el-dropdown style="font-size: 12px" size="mini">
  74. <el-button type="primary" size="mini">More</el-button>
  75. <el-dropdown-menu slot="dropdown">
  76. <el-dropdown-item
  77. v-for="dropbtn in operates.dropdown"
  78. :key="dropbtn.id"
  79. @click.native.prevent="dropbtn.method(scope.row)"
  80. >{{ dropbtn.label }}</el-dropdown-item>
  81. </el-dropdown-menu>
  82. </el-dropdown>
  83. </div>
  84. </div>
  85. </template>
  86. </el-table-column>
  87. </el-table>
  88. <div class="clearfix" style="height: 32px;margin: 10px 24px 0 10px;">
  89. <el-pagination
  90. class="pagination-site"
  91. background
  92. :class="floatType"
  93. :current-page="dataQuery.page"
  94. :page-sizes="page.pageSizes"
  95. :page-size="dataQuery.size"
  96. layout="total, sizes, prev, pager, next, jumper"
  97. :total="page.dataTotal"
  98. @size-change="sizeChange"
  99. @current-change="currentChange"
  100. />
  101. </div>
  102. </div>
  103. </template>
  104. <script>
  105. import { scrollTo } from '@/utils/scroll-to'
  106. import download from '@/utils/download'
  107. import { deepClone } from '@/utils/index'
  108. export default {
  109. name: 'Sheet',
  110. props: {
  111. showFace: {
  112. type: Boolean,
  113. default: false
  114. },
  115. showCover: {
  116. type: Boolean,
  117. default: false
  118. },
  119. headerName: {
  120. type: String,
  121. default: () => 'searchForm'
  122. },
  123. callBack: {
  124. type: Function,
  125. default: () => {}
  126. },
  127. api: {
  128. type: Function,
  129. default: () => {}
  130. },
  131. columns: {
  132. type: Array,
  133. default: () => []
  134. },
  135. floatType: {
  136. type: String,
  137. default: () => ''
  138. },
  139. clearSelection: {
  140. type: String,
  141. default: () => ''
  142. },
  143. selectType: {
  144. type: String,
  145. default: () => ''
  146. },
  147. dataQuery: {
  148. type: Object,
  149. default: () => {
  150. return { page: 1, size: 10 }
  151. }
  152. },
  153. page: {
  154. type: Object,
  155. default: () => {
  156. return {
  157. pageSizes: [5, 10, 20, 50, 100],
  158. dataTotal: 0
  159. }
  160. }
  161. },
  162. operates: {
  163. type: Object,
  164. default: () => {
  165. return {
  166. list: [],
  167. width: 150
  168. }
  169. }
  170. }
  171. },
  172. data: function() {
  173. return {
  174. src: window.Domain.static_url,
  175. tableData: [],
  176. dataLoading: false,
  177. optionsets: {},
  178. selectionData: []
  179. }
  180. },
  181. computed: {
  182. tableMaxHeight() {
  183. if (
  184. this.$store === undefined ||
  185. this.$store.getters.pageTableHeaderHeight === 0
  186. ) { return null }
  187. const height = 240 + 20 + this.$store.getters.pageTableHeaderHeight
  188. return 'calc(100vh - ' + height + 'px)'
  189. }
  190. },
  191. watch: {
  192. clearSelection(newdata, olddata) {
  193. this.$refs.multipleTable.clearSelection()
  194. }
  195. },
  196. created() {
  197. this.getData()
  198. },
  199. methods: {
  200. cellMouseEnter(row, column) {
  201. this.$emit('cell-mouse-enter', row, column)
  202. },
  203. formatter(row, column) {
  204. if (this.optionsets[column.formatter] !== undefined) {
  205. const colValue = row[column.prop]
  206. for (var i = 0; i < this.optionsets[column.formatter].length; i++) {
  207. if (this.optionsets[column.formatter][i].value === colValue) {
  208. return this.optionsets[column.formatter][i].text
  209. }
  210. }
  211. }
  212. return ''
  213. },
  214. rowdata(row, column, event) {
  215. if (column.label !== '操作') {
  216. this.$refs.multipleTable.toggleRowSelection(row)
  217. this.$emit('getRow', row)
  218. }
  219. },
  220. toggleRowSelection(row) {
  221. this.$refs.multipleTable.toggleRowSelection(row)
  222. },
  223. selectionChange(selection) {
  224. this.selectionData = selection
  225. this.$emit('update:selectionData', selection)
  226. },
  227. checkFunc(data) {
  228. return typeof data === 'function' ? data() : data
  229. },
  230. deepCopy(data) {
  231. if (typeof data !== 'object') {
  232. return data
  233. }
  234. if (Array.isArray(data)) {
  235. return data.map(this.deepCopy)
  236. }
  237. const copyData = {}
  238. for (const [key, value] of Object.entries(data)) {
  239. copyData[key] = this.deepCopy(value)
  240. }
  241. return copyData
  242. },
  243. getExportColumns() {
  244. const columns = this.deepCopy(this.checkFunc(this.columns))
  245. return columns
  246. .filter(column => typeof column.show === 'undefined' || column.show)
  247. .map(column => {
  248. if (column.width) {
  249. column.width = column.width * 0.125 || 0
  250. }
  251. return column
  252. })
  253. },
  254. async getData(obj = {}) {
  255. const dataQuery = Object.assign(deepClone(this.dataQuery), obj)
  256. const codes = []
  257. this.columns.forEach(item => {
  258. if (item.formatter !== undefined && typeof item.formatter === 'string') {
  259. codes.push(item.formatter)
  260. }
  261. })
  262. for (var i = 0; i < codes.length; i++) {
  263. this.optionsets[codes[i]] = await this.$store.dispatch('optionset/formatterData', codes[i])
  264. }
  265. if (dataQuery.__export__) {
  266. this.isExporting = true
  267. dataQuery.__columns__ = JSON.stringify(this.getExportColumns())
  268. this.api(dataQuery).then(({ data }) => {
  269. download(data).then(() => {
  270. this.isExporting = false
  271. })
  272. })
  273. } else {
  274. this.dataLoading = true
  275. this.api(dataQuery).then(res => {
  276. if (res.code === 200) {
  277. this.page.dataTotal = res.data.totalrecords
  278. this.tableData = res.data.data
  279. this.$emit('callBack', res.data.content)
  280. } else {
  281. this.page.dataTotal = 0
  282. this.tableData = []
  283. }
  284. this.dataLoading = false
  285. return res
  286. })
  287. }
  288. },
  289. sizeChange(val) {
  290. scrollTo(0, 600)
  291. this.dataQuery.size = val
  292. this.dataQuery.page = 1
  293. this.getData()
  294. },
  295. currentChange(val) {
  296. scrollTo(0, 600)
  297. this.dataQuery.page = val
  298. this.getData()
  299. }
  300. }
  301. }
  302. </script>
  303. <style>
  304. .right {
  305. float: right;
  306. }
  307. .left {
  308. float: left;
  309. }
  310. .el-table--border th.gutter:last-of-type {
  311. display: block !important;
  312. width: 17px !important;
  313. }
  314. </style>