StdTable.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <div class="std-table">
  3. <a-form v-if="!disable_search" layout="inline">
  4. <a-form-item
  5. v-for="c in searchColumns(columns)" :key="c.dataIndex?c.dataIndex:c.name"
  6. :label="c.title">
  7. <a-input v-if="c.search.type==='input'" v-model="params[c.dataIndex]"/>
  8. <a-checkbox
  9. v-if="c.search.type==='checkbox'"
  10. :default-checked="c.search.default"
  11. :name="c.search.condition?c.search.condition:c.dataIndex"
  12. @change="checked"/>
  13. <a-slider
  14. v-else-if="c.search.type==='slider'"
  15. v-model="params[c.dataIndex]"
  16. :marks="c.mask"
  17. :max="c.search.max"
  18. :min="c.search.min"
  19. style="width: 130px"
  20. />
  21. <a-select v-if="c.search.type==='select'" v-model="params[c.dataIndex]"
  22. style="width: 130px">
  23. <a-select-option v-for="(v,k) in c.mask" :key="k" :value="k">{{ v }}</a-select-option>
  24. </a-select>
  25. </a-form-item>
  26. <a-form-item :wrapper-col="{span:8}">
  27. <a-button type="primary" @click="get_list()">查询</a-button>
  28. </a-form-item>
  29. <a-form-item :wrapper-col="{span:8}">
  30. <a-button @click="reset_search">重置</a-button>
  31. </a-form-item>
  32. </a-form>
  33. <div v-if="soft_delete" style="text-align: right">
  34. <a v-if="params['trashed']" href="javascript:;"
  35. @click="params['trashed']=false; get_list()">返回</a>
  36. <a v-else href="javascript:;" @click="params['trashed']=true; get_list()">回收站</a>
  37. </div>
  38. <a-table
  39. :columns="pithyColumns(columns)"
  40. :customRow="row"
  41. :data-source="data_source"
  42. :loading="loading"
  43. :pagination="false"
  44. :row-key="'name'"
  45. :rowSelection="{
  46. selectedRowKeys: selectedRowKeys,
  47. onChange: onSelectChange,
  48. onSelect: onSelect,
  49. type: selectionType,
  50. }"
  51. @change="stdChange"
  52. >
  53. <template
  54. v-for="c in pithyColumns(columns)"
  55. :slot="c.scopedSlots.customRender"
  56. slot-scope="text, record">
  57. <span v-if="c.badge" :key="c.dataIndex">
  58. <a-badge v-if="text === true || text > 0" status="success"/>
  59. <a-badge v-else status="error"/>
  60. {{ c.mask ? c.mask[text] : text }}
  61. </span>
  62. <span v-else-if="c.datetime" :key="c.dataIndex">{{ moment(text).format("yyyy-MM-DD HH:mm:ss") }}</span>
  63. <span v-else-if="c.click" :key="c.dataIndex">
  64. <a href="javascript:;" @click="handleClick(record[c.click.index?c.click.index:c.dataIndex],
  65. c.click.index?c.click.index:c.dataIndex,
  66. c.click.method, c.click.path)">
  67. {{ text != null ? text : c.default }}
  68. </a>
  69. </span>
  70. <span v-else :key="c.dataIndex">
  71. {{ text != null ? (c.mask ? c.mask[text] : text) : c.default }}
  72. </span>
  73. </template>
  74. <span v-if="!pithy" slot="action" slot-scope="text, record">
  75. <slot name="action" :record="record" />
  76. <a href="javascript:;" @click="$emit('clickEdit', record)">
  77. <template v-if="edit_text">{{ edit_text }}</template>
  78. <template v-else>编辑</template>
  79. </a>
  80. <template v-if="deletable">
  81. <a-divider type="vertical"/>
  82. <a-popconfirm
  83. v-if="soft_delete&&params.trashed"
  84. cancelText="再想想"
  85. okText="是的" title="你确定要反删除?"
  86. @confirm="restore(record.name)">
  87. <a href="javascript:;">反删除</a>
  88. </a-popconfirm>
  89. <a-popconfirm
  90. v-else
  91. cancelText="再想想"
  92. okText="是的" title="你确定要删除?"
  93. @confirm="destroy(record.name)"
  94. >
  95. <a href="javascript:;">删除</a>
  96. </a-popconfirm>
  97. </template>
  98. </span>
  99. </a-table>
  100. <std-pagination :pagination="pagination" @changePage="get_list"/>
  101. </div>
  102. </template>
  103. <script>
  104. import StdPagination from './StdPagination'
  105. import moment from "moment"
  106. export default {
  107. name: 'StdTable',
  108. components: {
  109. StdPagination,
  110. },
  111. props: {
  112. columns: Array,
  113. api: Object,
  114. data_key: String,
  115. selectionType: {
  116. type: String,
  117. default: 'checkbox',
  118. validator: function (value) {
  119. return ['checkbox', 'radio'].indexOf(value) !== -1
  120. }
  121. },
  122. pithy: {
  123. type: Boolean,
  124. default: false
  125. },
  126. disable_search: {
  127. type: Boolean,
  128. default: false
  129. },
  130. soft_delete: {
  131. type: Boolean,
  132. default: false
  133. },
  134. edit_text: String,
  135. deletable: {
  136. type: Boolean,
  137. default: true
  138. }
  139. },
  140. data() {
  141. return {
  142. moment,
  143. data_source: [],
  144. loading: true,
  145. pagination: {
  146. total: 1,
  147. per_page: 10,
  148. current_page: 1,
  149. total_pages: 1
  150. },
  151. params: {},
  152. selectedRowKeys: [],
  153. }
  154. },
  155. mounted() {
  156. this.get_list()
  157. },
  158. methods: {
  159. get_list(page_num = null) {
  160. this.loading = true
  161. this.params['page'] = page_num
  162. this.api.get_list(this.params).then(response => {
  163. if (response[this.data_key] === undefined && response.data !== undefined) {
  164. this.data_source = response.data
  165. } else {
  166. this.data_source = response[this.data_key]
  167. }
  168. if (response.pagination !== undefined) {
  169. this.pagination = response.pagination
  170. }
  171. this.loading = false
  172. }).catch(e => {
  173. console.log(e)
  174. this.$message.error('服务器错误')
  175. })
  176. },
  177. stdChange(pagination, filters, sorter) {
  178. if (sorter) {
  179. this.params['order_by'] = sorter.field
  180. this.params['sort'] = sorter.order === 'ascend' ? 'asc' : 'desc'
  181. this.$nextTick(() => {
  182. this.get_list()
  183. })
  184. }
  185. },
  186. destroy(id) {
  187. this.api.destroy(id).then(() => {
  188. this.get_list()
  189. this.$message.success('删除 ID: ' + id + ' 成功')
  190. }).catch(e => {
  191. this.$message.error('服务器错误' + (e.message ? " " + e.message : ""))
  192. })
  193. },
  194. restore(id) {
  195. this.api.restore(id).then(() => {
  196. this.get_list()
  197. this.$message.success('反删除 ID: ' + id + ' 成功')
  198. }).catch(() => {
  199. this.$message.error('服务器错误')
  200. })
  201. },
  202. searchColumns(columns) {
  203. return columns.filter((column) => {
  204. return column.search
  205. })
  206. },
  207. pithyColumns(columns) {
  208. if (this.pithy) {
  209. return columns.filter((c) => {
  210. return c.pithy === true && c.display !== false
  211. })
  212. }
  213. return columns.filter((c) => {
  214. return c.display !== false
  215. })
  216. },
  217. checked(c) {
  218. this.params[c.target.value] = c.target.checked
  219. },
  220. onSelectChange(selectedRowKeys) {
  221. this.selectedRowKeys = selectedRowKeys
  222. this.$emit('selected', selectedRowKeys)
  223. },
  224. onSelect(record) {
  225. console.log(record)
  226. this.$emit('selectedRecord', record)
  227. },
  228. handleClick(data, index, method = '', path = '') {
  229. if (method === 'router') {
  230. this.$router.push(path + '/' + data).then()
  231. } else {
  232. this.params[index] = data
  233. this.get_list()
  234. }
  235. },
  236. row(record) {
  237. return {
  238. on: {
  239. click: () => {
  240. this.$emit('clickRow', record.id)
  241. }
  242. }
  243. }
  244. },
  245. async reset_search() {
  246. this.params = {}
  247. await this.get_list()
  248. }
  249. }
  250. }
  251. </script>
  252. <style lang="less" scoped>
  253. .ant-form {
  254. margin: 10px 0 20px 0;
  255. }
  256. .ant-slider {
  257. min-width: 90px;
  258. }
  259. .std-table {
  260. .ant-table-wrapper {
  261. overflow: scroll;
  262. }
  263. }
  264. </style>