byTable.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <template>
  2. <div class="by-table">
  3. <vxe-table
  4. ref="table"
  5. :data="value"
  6. :size="attrs.size?attrs.size:'small'"
  7. sync-resize
  8. auto-resize
  9. :height="attrs.height"
  10. :max-height="attrs.maxHeight"
  11. :stripe="attrs.stripe"
  12. :border="attrs.border"
  13. :align="attrs.align"
  14. :tree-config="{transform: attrs.transform, rowField: attrs.rowField, parentField: attrs.parentField}"
  15. :row-config="{isHover: true}"
  16. :tooltip-config="{showAll: true}"
  17. :radio-config="{trigger: attrs.triggerRowCheck}"
  18. :checkbox-config="{ checkMethod: attrs.checkMethod, visibleMethod: attrs.visibleMethod,trigger: attrs.triggerRowCheck}">
  19. style="width: 100%">
  20. <vxe-column v-if="attrs.checkbox" type="checkbox" width="50" fixed="left" />
  21. <vxe-column v-if="attrs.radio" type="radio" width="50" fixed="left" />
  22. <vxe-column v-if="attrs.seq" type="seq" title="序号" :width="attrs.seqWidth?attrs.seqWidth:50" fixed="left" :tree-node="attrs.treeNodeSeq" />
  23. <template v-for="(item,index) in columns">
  24. <vxe-column
  25. v-if="item.action"
  26. :key="'action_'+index"
  27. :title="item.title"
  28. :width="item.width"
  29. resizable
  30. fixed="right"
  31. >
  32. <template #default="{ row }">
  33. <template v-if="item.plugins">
  34. <template v-for="(pluginsItem,_index) of item.plugins" >
  35. <span class="col-action"
  36. :key="'plu'+_index"
  37. v-hasPermi="[pluginsItem.audit]"
  38. v-if="showPlugin(pluginsItem,row)"
  39. @click="pluginClick(pluginsItem,row)">
  40. <i v-if="pluginsItem.icon" :class="pluginsItem.icon" ></i>
  41. {{ pluginsItem.name }}
  42. </span>
  43. </template>
  44. </template>
  45. </template>
  46. </vxe-column>
  47. <vxe-column
  48. v-if="!item.action"
  49. :key="item.field?item.field:index"
  50. :field="item.field"
  51. :title="item.title"
  52. :width="item.width"
  53. :fixed="item.fixed"
  54. resizable
  55. :align="item.align"
  56. :tree-node="item.treeNode"
  57. >
  58. <template #default="{ row }">
  59. <slot v-if="item.slot" :name='item.field' :row='row'></slot>
  60. <component v-else-if="item.component" :is="item.component" :ref="item.prop+'Comp'" :propConfig="item.compConfig" :parentValue="row"
  61. :propValue="row[item.field]" @onChange="onChange($event, row,item.field)" />
  62. <template v-else>
  63. <div v-if="item.isDetail" :class="{'ellipsis':item.ellipsis}" :title="row[item.field]" :style="{ 'text-align': item.align }" class="tdCol detail" @click="detail(row)">{{ row[item.field] }}</div>
  64. <div class="tdCol" :class="{'ellipsis':item.ellipsis}" :title="row[item.field]" :style="{ 'text-align': item.align }" v-else>{{ row[item.field] }}</div>
  65. </template>
  66. </template>
  67. </vxe-column>
  68. </template>
  69. </vxe-table>
  70. <div class="page" v-if="page.total > 0">
  71. <el-pagination
  72. @size-change="handleSizeChange"
  73. @current-change="handleCurrentChange"
  74. :current-page="page.pageNo"
  75. :page-sizes="attrs.pageSizes"
  76. :page-size="page.pageSize?page.pageSize:20"
  77. :layout="attrs.layoutPage?attrs.layoutPage:'total, sizes, prev, pager, next, jumper'"
  78. :total="page.total">
  79. </el-pagination>
  80. </div>
  81. </div>
  82. </template>
  83. <script lang="ts">
  84. /**
  85. config:{
  86. attr:{
  87. triggerRowCheck:'row' //点击行选中
  88. size: medium / small / mini //尺寸
  89. height: '' //高度
  90. maxHeight:'' //最大高度
  91. stripe: true/false //是否为斑马纹
  92. border: true/false //是否带有纵向边框
  93. seq:true/false //显示序号
  94. seqWidth:'' //序号宽度
  95. checkbox: true/false //显示复选框
  96. radio:true/false //显示单选框
  97. align: left/center/right //对齐方式
  98. transform: true/false //开启自动将列表转成树结构
  99. rowField:'' row对应id
  100. parentField:'' row父id
  101. pageSize:'' //分页条数
  102. pageSizes:[] //每页显示个数选择器的选项设置
  103. layoutPage:'' //分页组件布局
  104. checkMethod:()=>{} //禁用复选框方法
  105. visibleMethod:()=>{} //显示复选框方法
  106. },
  107. columns:[{
  108. ellipsis:true/false //超出省略号表示
  109. title:'' //标题
  110. field:'' //字段名
  111. align: left/center/right //对齐方式
  112. width:'' //列宽
  113. fixed: true, left, right // 固定列
  114. action: true/false 是否操作列
  115. plugins:操作列执行
  116. component:'' //组件
  117. compConfig:{} //组件配置
  118. slot: true/false //是否插槽
  119. isDetail:true/false //点击详情
  120. tree-node: true/false //展开节点
  121. }],
  122. request:{}
  123. }
  124. */
  125. import { Component, Prop, Vue, Watch } from "vue-property-decorator";
  126. import VueViews from '@/benyun/compVue/VueViews'
  127. interface Page{
  128. pageNo?:number,
  129. pageSize?:number,
  130. total?:number
  131. }
  132. @Component
  133. export default class ByTable extends VueViews {
  134. value:Array<any>=[];
  135. key_id="_X_ROW_KEY"
  136. page = {
  137. pageNo: 1, //当前页
  138. pageSize: 20, //每页条数
  139. total: 0 //总条数
  140. }
  141. get columns(){
  142. return this.config?.columns ? this.config.columns : [];
  143. }
  144. created(){
  145. this.initConfig()
  146. }
  147. initConfig(){
  148. if(this.propConfig){
  149. this.setConfig(this.propConfig)
  150. }
  151. }
  152. mounted(){
  153. this.$nextTick(()=>{
  154. if(this.requestConfig){
  155. this.request();
  156. }
  157. })
  158. }
  159. recalculate(){
  160. if(this.$refs.table){
  161. (this.$refs.table as any).recalculate(true);
  162. this.$forceUpdate();
  163. }
  164. }
  165. loadTableData(data:Array<any>){
  166. if(this.$refs.table){
  167. (this.$refs.table as any).loadData(data);
  168. }
  169. }
  170. //点击详情
  171. detail(row:any){
  172. let data = (this as any).$lodash.cloneDeep(row);
  173. delete data[this.key_id];
  174. this.$emit('detail',data)
  175. }
  176. setConfigAfter(){
  177. if(this.attrs.pageSize){
  178. this.page.pageSize = this.attrs.pageSize;
  179. }
  180. this.recalculate();
  181. }
  182. //设置分页
  183. setPage(page:Page){
  184. if(page.pageNo){
  185. this.page.pageNo = page.pageNo;
  186. }
  187. if(page.pageSize){
  188. this.page.pageSize = page.pageSize;
  189. }
  190. this.page.total = page.total?page.total:0;
  191. }
  192. getPage(){
  193. return this.page
  194. }
  195. //每页条数发生变化
  196. handleSizeChange(val:number) {
  197. this.page.pageSize = val;
  198. if (this.page.pageSize * val > this.page.total) {
  199. this.page.pageNo = 1
  200. }
  201. this.$emit('pagination',{pageNum:this.page.pageNo,pageSize:this.page.pageSize})
  202. }
  203. //当前页发生变化
  204. handleCurrentChange(val:number) {
  205. this.page.pageNo = val;
  206. this.$emit('pagination',{pageNum:this.page.pageNo,pageSize:this.page.pageSize})
  207. }
  208. //操作列点击操作
  209. pluginClick(config:any,row:any){
  210. if(config?.event?.click){
  211. // let data = (this as any).$lodash.cloneDeep(row)
  212. // delete data[this.key_id];
  213. config.event.click(row)
  214. }
  215. }
  216. //操作按钮是否显示
  217. showPlugin(config:any,row:any){
  218. if(config?.event?.show){
  219. let data = (this as any).$lodash.cloneDeep(row)
  220. delete data[this.key_id];
  221. return config.event.show(data)
  222. }
  223. return true
  224. }
  225. //组件值的变化
  226. onChange(val:any,row:any,code:string){
  227. if(val && (val as any).constructor == Object){
  228. for (const key in val) {
  229. if (!row[key]) {
  230. Vue.set(row, key, val[key])
  231. } else {
  232. row[key] = val[key]
  233. }
  234. }
  235. }else{
  236. if(!row[code]){
  237. Vue.set(row, code, val)
  238. }else{
  239. row[code] = val
  240. }
  241. }
  242. this.$emit('onChangeRow',row);
  243. }
  244. //获取表格选中的数据
  245. getSelectData() {
  246. let data: Array<any> = []
  247. if (this.$refs.table) {
  248. if (this.attrs.radio && (this.$refs.table as any).getRadioRecord()) {
  249. data = (this as any).$lodash.cloneDeep([(this.$refs.table as any).getRadioRecord()]);
  250. }
  251. if(this.attrs.checkbox && (this.$refs.table as any).getCheckboxRecords()){
  252. data = (this as any).$lodash.cloneDeep((this.$refs.table as any).getCheckboxRecords());
  253. }
  254. }
  255. for(let item of data){
  256. delete item[this.key_id];
  257. }
  258. return data
  259. }
  260. //清楚选中
  261. clearCheckboxRow(){
  262. if(this.attrs.checkbox){
  263. (this.$refs.table as any).clearCheckboxRow();
  264. }
  265. if(this.attrs.radio){
  266. (this.$refs.table as any).clearRadioRow();
  267. }
  268. }
  269. setValue(data:Array<any>){
  270. // setTimeout(()=>{
  271. this.value = data ? data : [];
  272. // },100)
  273. this.$forceUpdate()
  274. }
  275. getValue(){
  276. let d = (this as any).$lodash.cloneDeep(this.value);
  277. for(let item of d){
  278. delete item[this.key_id];
  279. }
  280. return d;
  281. }
  282. request(){
  283. if(!this.requestConfig || !this.requestConfig.url){
  284. return
  285. }
  286. let parame = (this as any).$lodash.cloneDeep(this.requestConfig);
  287. parame.success = (res:any) => {
  288. if(res.data){
  289. this.setValue(res.data);
  290. }
  291. }
  292. parame.fail = (err:any) => {}
  293. this.requestHandle(parame);
  294. }
  295. }
  296. </script>
  297. <style lang="scss" scoped>
  298. .by-table{
  299. width: 100%;
  300. .page{
  301. width: 100%;
  302. display: flex;
  303. padding-top: 16px;
  304. justify-content: flex-end;
  305. }
  306. .tdCol{
  307. width: 100%;
  308. }
  309. .ellipsis{
  310. width: 100%;
  311. overflow: hidden;
  312. white-space: nowrap;
  313. text-overflow: ellipsis;
  314. }
  315. }
  316. .col-action{
  317. color: #0089ff;
  318. cursor: pointer;
  319. padding: 0 4px;
  320. }
  321. .detail{
  322. color: #0089ff;
  323. cursor: pointer;
  324. }
  325. </style>