Parcourir la source

封装moduleView组件

ymy il y a 2 ans
Parent
commit
4391ac8783

+ 20 - 4
package-lock.json

@@ -22,6 +22,7 @@
         "register-service-worker": "^1.7.2",
         "screenfull": "^5.0.2",
         "svg-sprite-loader": "^6.0.11",
+        "uuid": "^9.0.0",
         "vue": "^2.6.14",
         "vue-class-component": "^7.2.3",
         "vue-property-decorator": "^9.1.2",
@@ -35,6 +36,7 @@
         "@types/js-cookie": "^3.0.3",
         "@types/lodash": "^4.14.192",
         "@types/nprogress": "^0.2.0",
+        "@types/uuid": "^9.0.1",
         "@vue/cli-plugin-babel": "~5.0.0",
         "@vue/cli-plugin-pwa": "~5.0.0",
         "@vue/cli-plugin-router": "~5.0.0",
@@ -2324,6 +2326,12 @@
       "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
       "dev": true
     },
+    "node_modules/@types/uuid": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
+      "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==",
+      "dev": true
+    },
     "node_modules/@types/webpack-env": {
       "version": "1.18.0",
       "resolved": "https://registry.npmmirror.com/@types/webpack-env/-/webpack-env-1.18.0.tgz",
@@ -11401,6 +11409,15 @@
         "websocket-driver": "^0.7.4"
       }
     },
+    "node_modules/sockjs/node_modules/uuid": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+      "dev": true,
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
     "node_modules/source-list-map": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/source-list-map/-/source-list-map-2.0.1.tgz",
@@ -12985,10 +13002,9 @@
       }
     },
     "node_modules/uuid": {
-      "version": "8.3.2",
-      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-      "dev": true,
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+      "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
       "bin": {
         "uuid": "dist/bin/uuid"
       }

+ 2 - 0
package.json

@@ -22,6 +22,7 @@
     "register-service-worker": "^1.7.2",
     "screenfull": "^5.0.2",
     "svg-sprite-loader": "^6.0.11",
+    "uuid": "^9.0.0",
     "vue": "^2.6.14",
     "vue-class-component": "^7.2.3",
     "vue-property-decorator": "^9.1.2",
@@ -35,6 +36,7 @@
     "@types/js-cookie": "^3.0.3",
     "@types/lodash": "^4.14.192",
     "@types/nprogress": "^0.2.0",
+    "@types/uuid": "^9.0.1",
     "@vue/cli-plugin-babel": "~5.0.0",
     "@vue/cli-plugin-pwa": "~5.0.0",
     "@vue/cli-plugin-router": "~5.0.0",

+ 149 - 0
src/benyun/compVue/ModuleViewHandle.ts

@@ -0,0 +1,149 @@
+import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
+import VueViews from '@/benyun/compVue/VueViews'
+import lodash from 'lodash' //导入深度拷贝
+export default class ModuleViewHandle extends VueViews{
+  searchID=this.getUuid(); //搜索id
+  toolID=this.getUuid(); // 工具栏id
+  tableID=this.getUuid(); //表格id
+  hideSearch=false  // 隐藏/显示搜索
+  load=false
+  time:any;
+  timeNum = 0;
+
+  value:any=null;
+  config:any={}
+
+  constructor() {
+    super()
+  }
+
+  //显示/隐藏搜索
+  toggleSearch(){
+    this.hideSearch = !this.hideSearch
+  }
+
+  getUuid(){
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  }
+
+  //获取查询值
+  getQuery(){
+    let query:any = (this.$refs[this.searchID] as any).getValue();
+    const page:any = (this.$refs[this.tableID] as any).getPage();
+    query.pageNum = page.pageNo;
+    query.pageSize = page.pageSize;
+    return query;
+  }
+
+  //获取数据列表
+  getList(){
+    if(!this.$refs[this.tableID]){
+      if(this.timeNum > 4){
+        clearInterval(this.time)
+      }
+      this.time =setInterval(()=>{
+        this.getList()
+      },500) 
+      this.timeNum ++;
+      return
+    }
+    clearInterval(this.time)
+    let query = this.getQuery();
+    this.$emit("listAfter",query);
+    this.load = true;
+    this.requestHandle({
+      url: this.requestConfig.url+'/list',
+      method: 'get',
+      params:query,
+      success:(res:any) => {
+        this.load = false;
+        const data:Array<any>=res.rows?res.rows:res.data?res.data:[];
+        if(this.$refs[this.tableID]){
+          (this.$refs[this.tableID] as any).setValue(data);
+          (this.$refs[this.tableID] as any).setPage({total:res.total})
+        }
+      },
+      fail:(err:any) => {
+        this.load = false;
+        this.failHandle(err);
+      }
+    })
+  }
+
+  //删除
+  onDelete(){
+    let data = (this.$refs[this.tableID] as any).getSelectData();
+    if(!data || data.length == 0){
+      this.$message('请选择数据!')
+      return
+    }
+    let id = '';
+    data.forEach((item:any) => {
+      if(item.id){
+        id = id ? id + ',' + item.id : item.id
+      }
+    });
+    this.requestHandle({
+      url: this.requestConfig.url+'/'+id,
+      method: 'delete',
+      success:(res:any) => {
+        this.load = false;
+        this.getList();
+      },
+      fail:(err:any) => {
+        this.load = false;
+        this.failHandle(err);
+      }
+    })
+  }
+
+  //刷新
+  onRefresh(){
+    (this.$refs[this.tableID] as any).setPage({pageNo:1,total:0})
+    this.getList();
+  }
+
+  //搜索
+  searchHandle(){
+    (this.$refs[this.tableID] as any).setPage({pageNo:1,total:0})
+    this.getList();
+  }
+  //重置
+  resertHandle(){
+    (this.$refs[this.searchID] as any).setValue({})
+    (this.$refs[this.tableID] as any).setPage({pageNo:1,total:0})
+    this.getList();
+  }
+
+  //导出
+  onExport(){
+    if(this.requestConfig?.url){
+      let urlArr = this.requestConfig.url.split('/');
+      let query = this.getQuery();
+      (this as any).$download(this.requestConfig?.url + '/export',{
+        ...query
+      },urlArr[urlArr.length - 1] + `_${new Date().getTime()}.xlsx`)
+    }
+    
+  }
+
+  failHandle(err:any){
+    let msg = err.msg ? err.msg :'运行错误!';
+    this.$message.error(msg)
+  }
+
+  //请求
+  requestHandle(requestParames:any){
+    if(requestParames && requestParames.url){
+      (this as any).$request(requestParames).then((res:any) => {
+        if(requestParames.success){
+          requestParames.success(res)
+        }
+      }).catch((err:any) => {
+        if(requestParames.fail){
+          requestParames.fail(err);
+        }
+      })
+    }
+  }
+}

+ 11 - 1
src/benyun/utils/VueViews.ts → src/benyun/compVue/VueViews.ts

@@ -20,6 +20,16 @@ export default class VueViews extends Vue{
   @Prop()
   propValue:any
 
+  constructor() {
+    super()
+  }
+
+
+  // 初始化
+  ini(option?: any): any {
+    return this
+  }
+
   //设置配置
   setConfig(c:any){
     if(c){
@@ -30,7 +40,7 @@ export default class VueViews extends Vue{
 
   //获取配置
   getConfig(){
-    return (this as any).$lodash.cloneDeep(this.config)
+    return lodash.cloneDeep(this.config)
   }
 
   setConfigAfter(){}

+ 1 - 1
src/benyun/components/byDatePicker/byDatePicker.vue

@@ -33,7 +33,7 @@
  */
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
 import Format from '@/benyun/utils/dateFormat'
-import VueViews from '@/benyun/utils/VueViews'
+import VueViews from '@/benyun/compVue/VueViews'
 
 @Component
 export default class ByDatePicker extends VueViews {

+ 3 - 2
src/benyun/components/byForm/byForm.vue

@@ -20,7 +20,7 @@
             :required="item.required"
             :error="item.error"
             :size="item.size"
-            :label-width="item.labelWidth?item.labelWidth:'100px'">
+            :label-width="item.labelWidth?item.labelWidth:'80px'">
             <component v-bind:is="item.component" 
               class="form-comp"
               :propConfig="item.compConfig" 
@@ -69,7 +69,7 @@
   }
  */
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import VueViews from '@/benyun/utils/VueViews'
+import VueViews from '@/benyun/compVue/VueViews'
 @Component
 export default class ByForm extends VueViews {
   value:any={}
@@ -153,6 +153,7 @@ export default class ByForm extends VueViews {
     }else{
       Vue.set(this.value, code, v);
     }
+    this.$emit('formChange',{value:v,code:code})
   }
 
   //表单验证

+ 1 - 1
src/benyun/components/byInput/byInput.vue

@@ -20,7 +20,7 @@
 
 <script lang="ts">
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import VueViews from '@/benyun/utils/VueViews'
+import VueViews from '@/benyun/compVue/VueViews'
 @Component
 export default class ByInput extends VueViews {
   value:any='';

+ 1 - 1
src/benyun/components/bySelect/bySelect.vue

@@ -34,7 +34,7 @@
   }
 */
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import VueViews from '@/benyun/utils/VueViews'
+import VueViews from '@/benyun/compVue/VueViews'
 @Component
 export default class BySelect extends VueViews {
   value:any='';

+ 32 - 15
src/benyun/components/byTable/byTable.vue

@@ -49,11 +49,11 @@
           :align="item.align"
           :tree-node="item.treeNode"
         >
-        <template #default="{ row }">
-          <slot v-if="item.slot" :name='item.field' :row='row'></slot>
-          <span v-else>{{ row[item.field] }}</span>
-        </template>
-        
+          <template #default="{ row }">
+            <slot v-if="item.slot" :name='item.field' :row='row'></slot>
+            <component v-else-if="item.component" :is="item.component" :propConfig="item.compConfig" />
+            <span v-else>{{ row[item.field] }}</span>
+          </template>
         </vxe-column>
     </template>
     </vxe-table>
@@ -100,6 +100,9 @@
       fixed: true, left, right  // 固定列
       action: true/false 是否操作列
       plugins:操作列执行
+      component:''  //组件
+      compConfig:{} //组件配置
+      slot: true/false  //是否插槽
       tree-node: true/false  //展开节点
     }],
     request:{}
@@ -107,21 +110,21 @@
 
  */
 import { Component, Prop, Vue, Watch } from "vue-property-decorator";
-import VueViews from '@/benyun/utils/VueViews'
+import VueViews from '@/benyun/compVue/VueViews'
 
 interface Page{
-  pageNo:number,
-  pageSize:number,
-  total:number
+  pageNo?:number,
+  pageSize?:number,
+  total?:number
 }
 
 @Component
 export default class ByTable extends VueViews {
   value:Array<any>=[];
   page = {
-    pageNo: 1,
-    pageSize: 20,
-    total: 0
+    pageNo: 1, //当前页
+    pageSize: 20, //每页条数
+    total: 0 //总条数
   }
 
   get columns(){
@@ -141,13 +144,27 @@ export default class ByTable extends VueViews {
     })
   }
 
+  setConfigAfter(){
+    if(this.attrs.pageSize){
+      this.page.pageSize = this.attrs.pageSize;
+    }
+  }
+
   //设置分页
   setPage(page:Page){
-    this.page.pageNo = page.pageNo;
-    this.page.pageSize = page.pageSize;
-    this.page.total = page.total;
+    if(page.pageNo){
+      this.page.pageNo = page.pageNo;
+    }
+    if(page.pageSize){
+      this.page.pageSize = page.pageSize;
+    }
+    this.page.total = page.total?page.total:0;
+    
   }
 
+  getPage(){
+    return this.page
+  }
   //每页条数发生变化
   handleSizeChange(val:number) {
     if (this.page.pageSize * val > this.page.total) {

+ 3 - 4
src/benyun/components/byTool/byTool.vue

@@ -84,19 +84,19 @@ export default class GmTools extends Vue {
   }
   //点击刷新按钮
   refresh(){
-    this.$emit('onRefresh')
+    this.$emit('clickHandle','onRefresh')
   }
   //点击搜索
   toggleSearch(){
     this.openSearch = !this.openSearch;
-    this.$emit('searchHandle')
+    this.$emit('clickHandle','toggleSearch')
   }
 
   clickHandle(item:any){
     if(item?.event?.click){
       item.event.click()
     }else{
-      this.$emit(item.clickName)
+      this.$emit('clickHandle',item.clickName)
     }
   }
 }
@@ -105,7 +105,6 @@ export default class GmTools extends Vue {
 <style lang="scss" scoped>
 .tool{
   width: 100%;
-  height: 40px;
   display: flex;
   justify-content: space-between;
   align-items: center;

+ 101 - 0
src/benyun/components/moduleView/moduleView.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="module-view">
+    <div class="search" v-if="searchConfig" v-show="!hideSearch">
+      <by-form :propConfig="searchConfig" :ref="searchID" />
+      <div class="search-btn">
+        <el-button type="primary" size="mini" icon="el-icon-search" @click="search">搜索</el-button>
+        <el-button size="mini" icon="el-icon-refresh" @click="resert">重置</el-button>
+      </div>
+    </div>
+    <div class="tool-box" v-if="toolConfig">
+      <by-tool :propConfig="toolConfig" :ref="toolID" @clickHandle="clickHandle" />
+    </div>
+    <div class="module-main" v-if="tableConfig">
+      <slot name="left"></slot>
+      <div class="table">
+        <by-table :propConfig="tableConfig" :ref="tableID" @pagination="paginationChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch,Mixins } from "vue-property-decorator";
+import ModuleViewHandle from '@/benyun/compVue/ModuleViewHandle'
+
+@Component
+export default class ModuleView extends ModuleViewHandle {
+
+  //搜索配置
+  get searchConfig(){
+    return this.config?.search ? this.config.search : null;
+  }
+
+  //工具栏配置
+  get toolConfig(){
+    return this.config?.tool ? this.config.tool : null
+  }
+
+  //表格配置
+  get tableConfig(){
+    return this.config?.table ? this.config.table : null
+  }
+
+  constructor() {
+    super()
+  }
+
+  created(){
+    if(this.propConfig){
+      this.setConfig(this.propConfig)
+    }
+    
+  }
+  mounted(){
+    this.getList() 
+  }
+  search(){
+    this.searchHandle()
+  }
+  resert(){
+    this.resertHandle()
+  }
+  clickHandle(e:string){
+    if((this as any)[e]){
+      (this as any)[e]()
+    }else{
+      this.$emit('clickHandle',e)
+    }
+  }
+  paginationChange(){
+    this.getList();
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.module-view{
+  width: 100%;
+  box-sizing: border-box;
+  padding:  16px;
+  .search{
+    width: 100%;
+    .search-btn{
+      width: 100%;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+  .tool-box{
+    width: 100%;
+    padding: 8px 0 16px;
+  }
+  .module-main{
+    width: 100%;
+    display: flex;
+    .table{
+      width: 100%;
+    }
+  }
+}
+</style>

+ 5 - 1
src/benyun/plugins/componentRegister.ts

@@ -26,7 +26,11 @@ const comps: Array<ComBase> = [
   {
     name: "byTool",
     component: () => import("@/benyun/components/byTool/byTool.vue"),
-  }
+  },
+  {
+    name: "moduleView",
+    component: () => import("@/benyun/components/moduleView/moduleView.vue"),
+  },
 ];
 
 const install = function (Vue: any) {

+ 8 - 0
src/router/index.ts

@@ -66,6 +66,14 @@ export const constantRoutes: Array<any> = [
           title: '表格',
           activeMenu: '/system/user'
         }
+      },
+      {
+        path:'moduleView',
+        component:()=> import('@/views/demo/moduleView.vue'),
+        name:'ModuleView',
+        meta: {
+          title: 'view封装'
+        }
       }
     ]
   }

+ 1 - 1
src/views/demo/form.vue

@@ -110,7 +110,7 @@ export default class DemoForm extends Vue {
     tools:{
       add:true,
       edit:true,
-      delete:true,
+      del:true,
       export:true,
       search:true,
       refresh:true

+ 5 - 0
src/views/demo/index.vue

@@ -25,6 +25,11 @@ export default class DemoIndex extends Vue {
     click:()=>{
       (this as any).$router.push('/demo/table')
     }
+  },{
+    name:'moduleView',
+    click:()=>{
+      (this as any).$router.push('/demo/moduleView')
+    }
   }]
 }
 </script>

+ 111 - 0
src/views/demo/moduleView.vue

@@ -0,0 +1,111 @@
+<template>
+  <moduleView :propConfig="config" @clickHandle="clickHandle" />
+</template>
+
+<script lang="ts">
+import { Component, Prop, Vue, Watch } from "vue-property-decorator";
+@Component
+export default class ModuleViewDemo extends Vue {
+  config:any={
+    search:{
+      attr:{
+        size:'mini',
+        rules:{
+          name:[{
+            required: true, message: '请输入名称', trigger: 'blur'
+          }]
+        }
+      },
+      columns:[
+        [{
+          span:6,
+          label:'创建时间',
+          prop:'created',
+          // rules:[
+          //   { required: true, message: '请选择时间', trigger: 'change' }
+          // ],
+          component:'by-date-picker',
+          compConfig:{
+            format:'yyyy-MM-dd',
+            type:'datetime'
+          }
+        }]
+      ]
+    },
+    tool:{
+      tools:{
+        add:true,
+        edit:true,
+        delete:true,
+        export:true,
+        search:true,
+        refresh:true
+      },
+      audit:{
+        add:'audit:collaborationLog:add',
+        edit:'audit:collaborationLog:edit',
+        delete:'audit:collaborationLog:remove',
+        export:'audit:collaborationLog:export'
+      }
+    },
+    table:{
+      attr:{
+        size:'mini',
+        seq:true,
+        align:'center',
+        checkbox:true
+      },
+      columns:[{
+        title:'创建时间',
+        field:'created',
+        width:150
+      },
+      {
+        title:'订单号',
+        field:'order_no',
+        width:100
+      },
+      {
+        title:'订单类型',
+        field:'order_type'
+      },
+      {
+        title:'操作',
+        action:true,
+        plugins:[{
+          icon:'el-icon-edit',
+          name:'编辑',
+          audit:'',
+          event:{
+            click:(item:any) => {
+              console.log('该行数据:',item)
+            }
+          }
+        },{
+          name:'查看',
+          event:{
+            click:(item:any) => {
+              console.log('该行数据:',item);
+              this.fun();
+              console.log('this:',this)
+            }
+          }
+        }]
+      }]
+    },
+    request:{
+      url:'/system/audit/collaborationLog'
+    }
+  }
+  fun(){
+    console.log(this)
+  }
+  clickHandle(e:string){
+    console.log(e+'操作')
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 1 - 1
src/views/demo/table.vue

@@ -93,7 +93,7 @@ export default class DemoTable extends Vue {
       parentField:'parentId'
     },
     columns:[{
-      treeNode:true,
+      // treeNode:true,
       title:'menuId',
       field:'menuId',
       width:150