zhaoxiaoqiang
2023-09-06 57b7e93baf35afbb9e1c569477052daa01de4699
编辑器,项目新增,管理员订单管理
5 files added
8 files modified
517 ■■■■■ changed files
package.json 1 ●●●● patch | view | raw | blame | history
src/components/Tinymce/components/EditorImage.vue 111 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/dynamicLoadScript.js 59 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/index.vue 247 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/plugins.js 7 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/toolbar.js 14 ●●●●● patch | view | raw | blame | history
src/views/qyp-project-management/index.vue 23 ●●●● patch | view | raw | blame | history
src/views/qyp-project-management/promotion.vue 9 ●●●●● patch | view | raw | blame | history
src/views/qyp-project-order/admin.vue 17 ●●●● patch | view | raw | blame | history
src/views/qyp-project-order/draw.vue 7 ●●●●● patch | view | raw | blame | history
src/views/qyp-project-order/history.vue 10 ●●●●● patch | view | raw | blame | history
src/views/qyp-project-order/index.vue 2 ●●● patch | view | raw | blame | history
src/views/qyp-project-order/plan.vue 10 ●●●●● patch | view | raw | blame | history
package.json
@@ -14,6 +14,7 @@
    "test:ci": "npm run lint && npm run test:unit"
  },
  "dependencies": {
    "@wangeditor/editor": "^5.1.23",
    "axios": "0.18.1",
    "blueimp-md5": "^2.19.0",
    "core-js": "3.6.5",
src/components/Tinymce/components/EditorImage.vue
New file
@@ -0,0 +1,111 @@
<template>
  <div class="upload-container">
    <!-- <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
      upload
    </el-button> -->
    <el-dialog :visible.sync="dialogVisible">
      <el-upload
        :multiple="true"
        :file-list="fileList"
        :show-file-list="true"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
        :before-upload="beforeUpload"
        class="editor-slide-upload"
        action="https://httpbin.org/post"
        list-type="picture-card"
      >
        <el-button size="small" type="primary">
          Click upload
        </el-button>
      </el-upload>
      <el-button @click="dialogVisible = false">
        Cancel
      </el-button>
      <el-button type="primary" @click="handleSubmit">
        Confirm
      </el-button>
    </el-dialog>
  </div>
</template>
<script>
// import { getToken } from 'api/qiniu'
export default {
  name: 'EditorSlideUpload',
  props: {
    color: {
      type: String,
      default: '#1890ff'
    }
  },
  data() {
    return {
      dialogVisible: false,
      listObj: {},
      fileList: []
    }
  },
  methods: {
    checkAllSuccess() {
      return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
    },
    handleSubmit() {
      const arr = Object.keys(this.listObj).map(v => this.listObj[v])
      if (!this.checkAllSuccess()) {
        this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
        return
      }
      this.$emit('successCBK', arr)
      this.listObj = {}
      this.fileList = []
      this.dialogVisible = false
    },
    handleSuccess(response, file) {
      const uid = file.uid
      const objKeyArr = Object.keys(this.listObj)
      for (let i = 0, len = objKeyArr.length; i < len; i++) {
        if (this.listObj[objKeyArr[i]].uid === uid) {
          this.listObj[objKeyArr[i]].url = response.files.file
          this.listObj[objKeyArr[i]].hasSuccess = true
          return
        }
      }
    },
    handleRemove(file) {
      const uid = file.uid
      const objKeyArr = Object.keys(this.listObj)
      for (let i = 0, len = objKeyArr.length; i < len; i++) {
        if (this.listObj[objKeyArr[i]].uid === uid) {
          delete this.listObj[objKeyArr[i]]
          return
        }
      }
    },
    beforeUpload(file) {
      const _self = this
      const _URL = window.URL || window.webkitURL
      const fileName = file.uid
      this.listObj[fileName] = {}
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = _URL.createObjectURL(file)
        img.onload = function() {
          _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
        }
        resolve(true)
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.editor-slide-upload {
  margin-bottom: 20px;
  ::v-deep .el-upload--picture-card {
    width: 100%;
  }
}
</style>
src/components/Tinymce/dynamicLoadScript.js
New file
@@ -0,0 +1,59 @@
let callbacks = []
function loadedTinymce() {
  // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
  // check is successfully downloaded script
  return window.tinymce
}
const dynamicLoadScript = (src, callback) => {
  const existingScript = document.getElementById(src)
  const cb = callback || function() {}
  if (!existingScript) {
    const script = document.createElement('script')
    script.src = src // src url for the third-party library being loaded.
    script.id = src
    document.body.appendChild(script)
    callbacks.push(cb)
    const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
    onEnd(script)
  }
  if (existingScript && cb) {
    if (loadedTinymce()) {
      cb(null, existingScript)
    } else {
      callbacks.push(cb)
    }
  }
  function stdOnEnd(script) {
    script.onload = function() {
      // this.onload = null here is necessary
      // because even IE9 works not like others
      this.onerror = this.onload = null
      for (const cb of callbacks) {
        cb(null, script)
      }
      callbacks = null
    }
    script.onerror = function() {
      this.onerror = this.onload = null
      cb(new Error('Failed to load ' + src), script)
    }
  }
  function ieOnEnd(script) {
    script.onreadystatechange = function() {
      if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
      this.onreadystatechange = null
      for (const cb of callbacks) {
        cb(null, script) // there is no way to catch loading errors in IE8
      }
      callbacks = null
    }
  }
}
export default dynamicLoadScript
src/components/Tinymce/index.vue
New file
@@ -0,0 +1,247 @@
<template>
  <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
    <textarea :id="tinymceId" class="tinymce-textarea" />
    <div class="editor-custom-btn-container">
      <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
    </div>
  </div>
</template>
<script>
/**
 * docs:
 * https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
 */
import editorImage from './components/EditorImage'
import plugins from './plugins'
import toolbar from './toolbar'
import load from './dynamicLoadScript'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
export default {
  name: 'Tinymce',
  components: { editorImage },
  props: {
    id: {
      type: String,
      default: function() {
        return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
      }
    },
    value: {
      type: String,
      default: ''
    },
    toolbar: {
      type: Array,
      required: false,
      default() {
        return []
      }
    },
    menubar: {
      type: String,
      default: 'file edit insert view format table'
    },
    height: {
      type: [Number, String],
      required: false,
      default: 360
    },
    width: {
      type: [Number, String],
      required: false,
      default: 'auto'
    }
  },
  data() {
    return {
      hasChange: false,
      hasInit: false,
      tinymceId: this.id,
      fullscreen: false,
      languageTypeList: {
        'en': 'en',
        'zh': 'zh_CN',
        'es': 'es_MX',
        'ja': 'ja'
      }
    }
  },
  computed: {
    containerWidth() {
      const width = this.width
      if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
        return `${width}px`
      }
      return width
    }
  },
  watch: {
    value(val) {
      if (!this.hasChange && this.hasInit) {
        this.$nextTick(() =>
          window.tinymce.get(this.tinymceId).setContent(val || ''))
      }
    }
  },
  mounted() {
    this.init()
  },
  activated() {
    if (window.tinymce) {
      this.initTinymce()
    }
  },
  deactivated() {
    this.destroyTinymce()
  },
  destroyed() {
    this.destroyTinymce()
  },
  methods: {
    init() {
      // dynamic load tinymce from cdn
      load(tinymceCDN, (err) => {
        if (err) {
          this.$message.error(err.message)
          return
        }
        this.initTinymce()
      })
    },
    initTinymce() {
      const _this = this
      window.tinymce.init({
        selector: `#${this.tinymceId}`,
        language: this.languageTypeList['zh'],
        height: this.height,
        body_class: 'panel-body ',
        object_resizing: false,
        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
        menubar: this.menubar,
        plugins: plugins,
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        advlist_bullet_styles: 'square',
        advlist_number_styles: 'default',
        imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
        default_link_target: '_blank',
        link_title: false,
        nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
        init_instance_callback: editor => {
          if (_this.value) {
            editor.setContent(_this.value)
          }
          _this.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
            this.hasChange = true
            this.$emit('input', editor.getContent())
          })
        },
        setup(editor) {
          editor.on('FullscreenStateChanged', (e) => {
            _this.fullscreen = e.state
          })
        },
        // it will try to keep these URLs intact
        // https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
        // https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
        convert_urls: false
        // 整合七牛上传
        // images_dataimg_filter(img) {
        //   setTimeout(() => {
        //     const $image = $(img);
        //     $image.removeAttr('width');
        //     $image.removeAttr('height');
        //     if ($image[0].height && $image[0].width) {
        //       $image.attr('data-wscntype', 'image');
        //       $image.attr('data-wscnh', $image[0].height);
        //       $image.attr('data-wscnw', $image[0].width);
        //       $image.addClass('wscnph');
        //     }
        //   }, 0);
        //   return img
        // },
        // images_upload_handler(blobInfo, success, failure, progress) {
        //   progress(0);
        //   const token = _this.$store.getters.token;
        //   getToken(token).then(response => {
        //     const url = response.data.qiniu_url;
        //     const formData = new FormData();
        //     formData.append('token', response.data.qiniu_token);
        //     formData.append('key', response.data.qiniu_key);
        //     formData.append('file', blobInfo.blob(), url);
        //     upload(formData).then(() => {
        //       success(url);
        //       progress(100);
        //     })
        //   }).catch(err => {
        //     failure('出现未知问题,刷新页面,或者联系程序员')
        //     console.log(err);
        //   });
        // },
      })
    },
    destroyTinymce() {
      const tinymce = window.tinymce.get(this.tinymceId)
      if (this.fullscreen) {
        tinymce.execCommand('mceFullScreen')
      }
      if (tinymce) {
        tinymce.destroy()
      }
    },
    setContent(value) {
      window.tinymce.get(this.tinymceId).setContent(value)
    },
    getContent() {
      window.tinymce.get(this.tinymceId).getContent()
    },
    imageSuccessCBK(arr) {
      arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
    }
  }
}
</script>
<style lang="scss" scoped>
.tinymce-container {
  position: relative;
  line-height: normal;
}
.tinymce-container {
  ::v-deep {
    .mce-fullscreen {
      z-index: 10000;
    }
  }
}
.tinymce-textarea {
  visibility: hidden;
  z-index: -1;
}
.editor-custom-btn-container {
  position: absolute;
  right: 4px;
  top: 4px;
  /*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
  z-index: 10000;
  position: fixed;
}
.editor-upload-btn {
  display: inline-block;
}
</style>
src/components/Tinymce/plugins.js
New file
@@ -0,0 +1,7 @@
// Any plugins you want to use has to be imported
// Detail plugins list see https://www.tinymce.com/docs/plugins/
// Custom builds see https://www.tinymce.com/download/custom-builds/
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
export default plugins
src/components/Tinymce/toolbar.js
New file
@@ -0,0 +1,14 @@
/*
 * @Author: zhaoxiaoqiang 287285524@qq.com
 * @Date: 2023-09-06 16:27:01
 * @LastEditors: zhaoxiaoqiang 287285524@qq.com
 * @LastEditTime: 2023-09-06 16:52:22
 * @FilePath: \qyp_plat\src\components\Tinymce\toolbar.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// Here is a list of the toolbar
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link charmap preview anchor pagebreak insertdatetime forecolor backcolor fullscreen']
export default toolbar
src/views/qyp-project-management/index.vue
@@ -13,7 +13,6 @@
              <el-input
                v-model.trim="formInline.projName"
                style="width: 240px"
                @keyup.native="keyupEvent($event)"
                type="tel"
                clearable
                placeholder="请输入"
@@ -71,7 +70,7 @@
          }"
        ></Etable>
      </div>
      <el-dialog top="2vh"  :title="title" :visible.sync="addProd" width="60%">
      <el-dialog top="2vh"  :title="title" :visible.sync="addProd" width="1000px">
          <!-- 新增商品名称 -->
          <el-form :model="ruleForm" :rules="rules" ref="ruleForm" size="small" label-width="120px" class="demo-ruleForm">
            <el-form-item label="项目名称" prop="projName">
@@ -100,23 +99,19 @@
            <el-form-item label="项目优惠券图片" ref="titleFilePath" prop="titleFilePath">
              <uploadImg v-if="addProd"  @sendList="imgSet($event,'titleFilePath')" :disabled="disabled" :defaultList="ruleForm.titleFilePath"></uploadImg>
            </el-form-item>
            <el-form-item label="会员权益" ref="qyFilePath"  prop="qyFilePath">
            <el-form-item label="会员权益" ref="qyFilePath">
              <uploadImg v-if="addProd" @sendList="imgSet($event,'qyFilePath')"     :disabled="disabled" :defaultList="ruleForm.qyFilePath"></uploadImg>
            </el-form-item>
            <!-- <el-form-item label="活动规则" ref="ruleFilePath" prop="ruleFilePath">
              <uploadImg v-if="addProd"  @sendList="imgSet($event,'ruleFilePath')" :disabled="disabled" :defaultList="ruleForm.ruleFilePath"></uploadImg>
            </el-form-item> -->
            <el-form-item label="活动规则" prop="ruleContent">
              <el-input type="textarea" v-model="ruleForm.ruleContent" :disabled="disabled"></el-input>
              <!-- <uploadImg v-if="addProd"  @sendList="imgSet($event,'ruleFilePath')" :disabled="disabled" :defaultList="ruleForm.ruleFilePath"></uploadImg> -->
              <tinymce v-model="ruleForm.ruleContent" :disabled="disabled" :height="300" />
            </el-form-item>
            <el-form-item style="text-align:right;" v-if="!disabled">
              <el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
              <!-- <el-button @click="resetForm('ruleForm')">重置</el-button> -->
            </el-form-item>
          </el-form>
      </el-dialog>
    </div>
  </template>
  
@@ -124,9 +119,10 @@
  import Etable from "../../components/table.vue";
  import {projectInit,projectAdd,projectDtl,projectUpdata} from "@/api/credit";
  import uploadImg from "@/components/upload.vue";
  import Tinymce from '@/components/Tinymce'
  export default {
    name: "order",
    components: { Etable,uploadImg },
    components: { Etable,uploadImg,Tinymce },
    data() {
      let backFilePathImage = (rule, value, callback) => { //验证器
        if (!this.ruleForm.backFilePath.length) {     //为true代表图片在  false报错
@@ -301,6 +297,9 @@
              ],
              ruleFilePath: [
                { required: true,  trigger: 'change',validator: ruleFilePathImage  }
              ],
              ruleContent:[
                { required: true, message: '请输入活动规则',  trigger: 'blur', }
              ]
          },
          title:"新增项目"
@@ -368,7 +367,7 @@
        }
        let objForm = JSON.parse(JSON.stringify(this.formInline));
        for (let key in objForm) {
          if (objForm[key] === "all") {
          if (objForm[key] === "all"||objForm[key] === "") {
            delete objForm[key];
          }
        }
@@ -431,7 +430,7 @@
          body.backFilePath = this.setDefaultImg(backFilePath,'backFilePath');
          body.logoFilePath = this.setDefaultImg(logoFilePath,'logoFilePath');
          body.titleFilePath = this.setDefaultImg(titleFilePath,"titleFilePath");
          body.qyFilePath = this.setDefaultImg(qyFilePath,"qyFilePath");
          body.qyFilePath =qyFilePath? this.setDefaultImg(qyFilePath,"qyFilePath"):[];
          body.ruleFilePath = this.setDefaultImg(ruleFilePath,"ruleFilePath");
          this.ruleForm = body;
          this.$nextTick(()=>{ 
src/views/qyp-project-management/promotion.vue
@@ -11,7 +11,7 @@
          <div style="width: 90%">
            <el-form-item label="项目名称:">
                <el-select
                    v-model="formInline.status"
                    v-model="formInline.projId"
                    style="width:200px"
                    clearable
                    placeholder="请选择"
@@ -270,6 +270,7 @@
            status:[{ required: true, message: "请选择上架状态", trigger: "change" }]
          },
          formInline: {
            projId:"all",
            status:"all",
          },
          searchData: {},
@@ -336,15 +337,15 @@
          this.formInline.projCreEndTime = null;
        }
        if (this.promotionCreatedTime && this.promotionCreatedTime.length) {
          this.formInline.promCreEndTime = this.createdTime[0];
          this.formInline.promCreStartTime = this.createdTime[1];
          this.formInline.promCreEndTime = this.promotionCreatedTime[0];
          this.formInline.promCreStartTime = this.promotionCreatedTime[1];
        } else {
          this.formInline.promCreEndTime = null;
          this.formInline.promCreStartTime = null;
        }
        let objForm = JSON.parse(JSON.stringify(this.formInline));
        for (let key in objForm) {
          if (objForm[key] === "all") {
          if (objForm[key] === "all"||objForm[key] === ""||objForm[key] === null) {
            delete objForm[key];
          }
        }
src/views/qyp-project-order/admin.vue
@@ -132,9 +132,9 @@
        </el-descriptions>
      </el-dialog>
      <el-dialog top="2vh"  :title="subTitle" fullscreen :visible.sync="productShow" width="60%">
          <history v-if="isWhith==1"></history>
          <plan  v-else-if="isWhith==2"></plan>
          <draw  v-else-if="isWhith==3"></draw>
          <history :orderId="orderId" v-if="isWhith==1"></history>
          <plan :orderId="orderId" v-else-if="isWhith==2"></plan>
          <draw :orderId="orderId" v-else-if="isWhith==3"></draw>
      </el-dialog>
    </div>
  </template>
@@ -251,6 +251,8 @@
                      },
                      on: {
                        click: () => {
                          let {orderId} = scope.row;
                          this.orderId = orderId;
                          this.isWhith = 1;
                          this.productShow  = true;
                        },
@@ -271,6 +273,8 @@
                      },
                      on: {
                        click: () => {
                          let {orderId} = scope.row;
                          this.orderId = orderId;
                          this.isWhith = 2;
                          this.productShow  = true;
                        },
@@ -291,6 +295,8 @@
                      },
                      on: {
                        click: () => {
                          let {orderId} = scope.row;
                          this.orderId = orderId;
                          this.isWhith = 3;
                          this.productShow  = true;
                        },
@@ -309,7 +315,8 @@
          title:"新增项目",
          orderDetail:{},
          exportExcelList:[],
          isWhith:''
          isWhith:'',
          orderId:''
      }
    },
    computed:{
@@ -367,7 +374,7 @@
        }
        let objForm = JSON.parse(JSON.stringify(this.formInline));
        for (let key in objForm) {
          if (objForm[key] === "all") {
          if (objForm[key] === "all"||objForm[key] === ""||objForm[key] === null) {
            delete objForm[key];
          }
        }
src/views/qyp-project-order/draw.vue
@@ -64,6 +64,13 @@
import Etable from "@/components/table.vue";
export default {
    components: { Etable },
    props:{
     orderId:""
    },
    created(){
        this.searchData.orderId = this.orderId;
        this.formInline.orderId = this.orderId;
    },
    data() {
        return {
            columns:[
src/views/qyp-project-order/history.vue
@@ -3,7 +3,7 @@
 * @Author: zhaoxiaoqiang 287285524@qq.com
 * @Date: 2023-08-24 15:16:23
 * @LastEditors: zhaoxiaoqiang 287285524@qq.com
 * @LastEditTime: 2023-09-05 17:14:35
 * @LastEditTime: 2023-09-06 17:44:03
 * @FilePath: \qyp_plat\src\views\qyp-project-order\history.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@@ -97,6 +97,9 @@
import Etable from "@/components/table.vue";
export default {
    components: { Etable },
    props:{
     orderId:""
    },
    data() {
        return {
            productShow:false,
@@ -224,9 +227,14 @@
                }
            },
            deep: true
        },
        orderId(value){
           console.log(value)
        }
    },
    created() {
     this.searchData.orderId = this.orderId;
     this.formInline.orderId = this.orderId;
     this.initSerch();
    },
    methods: {
src/views/qyp-project-order/index.vue
@@ -244,7 +244,7 @@
        }
        let objForm = JSON.parse(JSON.stringify(this.formInline));
        for (let key in objForm) {
          if (objForm[key] === "all") {
          if (objForm[key] === "all"||objForm[key] === ""||objForm[key] === null) {
            delete objForm[key];
          }
        }
src/views/qyp-project-order/plan.vue
@@ -3,7 +3,7 @@
 * @Author: zhaoxiaoqiang 287285524@qq.com
 * @Date: 2023-08-24 15:16:23
 * @LastEditors: zhaoxiaoqiang 287285524@qq.com
 * @LastEditTime: 2023-09-01 10:31:52
 * @LastEditTime: 2023-09-06 17:49:37
 * @FilePath: \qyp_plat\src\views\qyp-project-order\history.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@@ -13,6 +13,7 @@
            hasIndex
            httpUrl="payPlanList"
            :columns="columns"
            :searchData="searchData"
            :exportUrl="{
                url: '/qyp/order/payPlanExport',
                powerId: '',
@@ -27,8 +28,15 @@
import Etable from "@/components/table.vue";
export default {
    components: { Etable },
    props:{
     orderId:""
    },
    created(){
        this.searchData.orderId = this.orderId;
    },
    data() {
        return {
            searchData:{},
            columns:[
                {
                    lable: "扣款次数",