zhuhao před 2 roky
rodič
revize
e2a444fa61

+ 9 - 0
src/utils/model/index.js

@@ -5,13 +5,22 @@ import myTree from './tree/index.vue';
 import myRichText from './RichText/index.vue';
 import mySearch from './retrieval/search.vue';
 import myMenu from './menu/index.vue';
+import myView from './myView/index.vue';
+import mySelectButton from './selectButton/index.vue';
+import myFormSearch from './search/searchIndex.vue';
+import myTimeChoose from './time/timeIndex.vue';
 
 var models = {
   myCustomSvg,
   myTree,
   myRichText,
   mySearch,
+  
   myMenu,
+  myView,
+  mySelectButton,
+  myFormSearch,
+  myTimeChoose,
 }
 export default {
   install(Vue) {

+ 1 - 1
src/utils/model/menu/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <!-- 下载/预览/删除 -->
+  <!-- 菜单下载/预览/删除 -->
   <div class="menuPopover" :class="menuStyle" @mouseover="mouseover" @mouseout="mouseout">
 
     <el-popover placement="top-start" title="" trigger="hover" popper-class="popperClass"

+ 227 - 0
src/utils/model/myView/index.vue

@@ -0,0 +1,227 @@
+<template>
+  <!-- 双视图 -->
+  <div class="myView" v-listenDom="getShow" :style="{ 'flex-direction': direction }">
+    <slot name="left" class="myView_Left"></slot>
+    <div :class="className" data-type="mouse" @mousedown="mousedown" v-show="show"></div>
+    <slot name="right" class="myView_Right"></slot>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    position: {
+      default: 'row'
+    }
+  },
+  data() {
+    return {
+      show: true,
+      direction: null,
+      className: 'myView_Middle',
+    }
+  },
+  // 自定义指令
+  directives: {
+    listenDom: {
+      // 只调用一次
+      bind: function (el, binding, vnode) {
+        vnode.context.EventListener(el)
+        if (el.childNodes.length < 3) {
+          binding.value(false, el)
+        } else if (el.childNodes.length == 3) {
+          if (el.childNodes[2].style.display == 'none' || el.childNodes[0].style.display == 'none') {
+            binding.value(false, el)
+          } else {
+            binding.value(true, el)
+          }
+        }
+      },
+      // 插入中
+      inserted: function (el, binding) {
+        if (el.childNodes[2].style.display == 'none' || el.childNodes[0].style.display == 'none') {
+          binding.value(false, el)
+        } else {
+          binding.value(true, el)
+        }
+      },
+      // 更新前
+      update: function (el, binding) {
+      },
+      // 更新后
+      componentUpdated: function (el, binding) {
+        if (el.childNodes.length < 3) {
+          binding.value(false, el)
+        } else if (el.childNodes.length == 3) {
+          if (el.childNodes[2].style.display == 'none' || el.childNodes[0].style.display == 'none') {
+            binding.value(false, el)
+          } else {
+            binding.value(true, el)
+          }
+        }
+      }
+    }
+  },
+  watch: {
+    position() {
+      this.directionRule()
+    }
+  },
+  mounted() {
+    this.directionRule()
+
+  },
+  methods: {
+    // 窗口缩放,内容等比例缩放
+    EventListener(dom) {
+      window.addEventListener('resize', (e) => {
+        let len = dom.childNodes.length
+        for (var i = 0; i < len; i++) {
+          if (dom.childNodes[i].getAttribute('data-type') && dom.childNodes[i].getAttribute('data-type') == 'mouse') {
+            if (this.direction == 'row' || this.direction == 'row-reverse') {
+              dom.childNodes[i].style.width = '10px'
+            } else {
+              dom.childNodes[i].style.width = '100%'
+            }
+          } else {
+            if (this.direction == 'row' || this.direction == 'row-reverse') {
+              dom.childNodes[i].style.width = (dom.childNodes[i].clientWidth / (dom.clientWidth - 10)) * 100 + '%'
+            } else {
+              dom.childNodes[i].style.height = (dom.childNodes[i].clientHeight / (dom.clientHeight - 10)) * 100 + '%'
+            }
+
+          }
+        }
+      })
+    },
+    // 排列方向
+    directionRule() {
+      var a = ['row', "row-reverse", "column", "column-reverse"]
+      if (a.indexOf(this.position) == -1) {
+        this.direction = 'row'
+      } else {
+        this.direction = this.position
+      }
+
+      if (this.direction == 'row' || this.direction == 'row-reverse') {
+        this.className = 'myView_Middle'
+      } else {
+        this.className = 'myView_Middle2'
+      }
+    },
+
+    //获取show的值
+    getShow(val, dom) {
+      this.$set(this, 'show', val)
+      if (!val) {
+        var len = dom.childNodes.length
+        for (var i = 0; i < len; i++) {
+          if (dom.childNodes[i].getAttribute('data-type') && dom.childNodes[i].getAttribute('data-type') == 'mouse') {
+            if (this.direction == 'row' || this.direction == 'row-reverse') {
+              dom.childNodes[i].style.width = '10px'
+            } else {
+              dom.childNodes[i].style.width = '100%'
+            }
+          } else {
+            if (this.direction == 'row' || this.direction == 'row-reverse') {
+              dom.childNodes[i].style.width = '100%'
+            } else {
+              dom.childNodes[i].style.height = '100%'
+            }
+
+          }
+
+        }
+      }
+    },
+    // 鼠标按下
+    mousedown(e) {
+      // 上一个兄弟
+      var prev = e.currentTarget.previousElementSibling
+      // 下一个兄弟
+      var next = e.currentTarget.nextElementSibling
+      // 绑定事件的目标元素
+      var now = e.currentTarget
+      // 绑定事件目标元素的父级
+      var box = e.currentTarget.parentNode
+      // 当事件被触发时鼠标相对于窗口左侧的距离
+      var startX = e.clientX;
+      // 目标元素距离左侧的距离
+      now.left = now.offsetLeft;
+      // 当事件被触发时鼠标相对于窗口顶部的距离
+      var startY = e.clientY;
+      // 目标元素距离顶部的距离
+      now.Top = now.offsetTop;
+      // 鼠标拖动
+      document.onmousemove = (e) => {
+        if (this.direction == 'row' || this.direction == 'row-reverse') {
+          var endX = e.clientX;
+          // (endx-startx)=移动的距离。
+          // now.left + 移动的距离 - 整个盒子距离左侧的距离 = 左边区域最后的宽度
+          var moveLen = now.left + (endX - startX) - box.offsetLeft;
+          // 容器宽度 - 左边区域的宽度 = 右边区域的宽度
+          var maxT = box.clientWidth - now.offsetWidth;
+          // 左边区域的最小宽度为150px
+          if (moveLen < 150) moveLen = 150;
+          //右边区域最小宽度为150px
+          if (moveLen > maxT - 150) moveLen = maxT - 150;
+          // 设置目标元素距离左侧区域的距离
+          now.style.left = moveLen;
+          // 左侧(上一个)的兄弟元素
+          prev.style.width = moveLen + 'px';
+          now.style.width = '10px'
+          if (next) {
+            next.style.width = (box.clientWidth - moveLen - 10) + 'px';
+          }
+        } else {
+          var endY = e.clientY;
+          // (endx-startx)=移动的距离。 
+          // now.Top + 移动的距离 - 整个盒子距离上边的距离= 上边区域最后的宽度
+          var moveLen = now.Top + (endY - startY) - box.offsetTop;
+          // 容器宽度 - 上边区域的宽度 = 下边区域的宽度
+          var maxT = box.clientHeight - now.offsetHeight;
+          // 上边区域的最小宽度为150px
+          if (moveLen < 150) moveLen = 150;
+          //下边区域最小宽度为150px
+          if (moveLen > maxT - 150) moveLen = maxT - 150;
+          // 设置目标元素距离顶部的距离
+          now.style.left = moveLen;
+          // 左侧(上一个)的兄弟元素
+          prev.style.height = moveLen + 'px';
+          now.style.height = '10px'
+          if (next) {
+            next.style.height = (box.clientHeight - moveLen) + 'px';
+          }
+        }
+      }
+      // 鼠标抬起清空按下及拖动事件
+      document.onmouseup = (e) => {
+        document.onmouseup = null;
+        document.onmousemove = null;
+      }
+    },
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.myView {
+  width: 100%;
+  height: 100%;
+  display: flex;
+
+  .myView_Middle {
+    width: 20px;
+    height: 100%;
+    background: #ABABAB;
+    cursor: col-resize;
+  }
+
+  .myView_Middle2 {
+    height: 20px;
+    width: 100%;
+    background: #ABABAB;
+    cursor: row-resize;
+  }
+}
+</style>

+ 475 - 0
src/utils/model/search/search.vue

@@ -0,0 +1,475 @@
+<template>
+    <div style="padding:10px">
+        <!-- 表单检索 -->
+        <div>
+            <div class="content_border">
+                <div v-for="(items,i) in list" :key="i" class="content"> 
+                    <!-- <el-row :gutter="24"> -->
+                        <!-- 逻辑符 -->
+                        <!-- <el-col :span="5"> -->
+                            <span style="width:150px" v-if="!searchResult">
+                                <span v-if="i==0" style="opacity: 0;"> 内容 </span>
+                                <el-select v-else v-model="list[i].logical" size='small' width='100%' >
+                                    <el-option
+                                        v-for="item in logical"
+                                        :key="item[logicalProps.value]"
+                                        :label="item[logicalProps.value]"
+                                        :value="item[logicalProps.value]">
+                                    </el-option>
+                                </el-select>
+                            </span>
+                        <!-- </el-col> -->
+                        <!-- 搜索条件 -->
+                        <!-- <el-col :span="7"> -->
+                            <!-- <el-select v-model="list[i].field" @change="change(list[i])" filterable size='small' style="width:250px" :title="getTitle(list[i].field)">
+                                <el-option
+                                    v-for="item in field"
+                                    :key="item[fieldProps.value]"
+                                    :label="item[fieldProps.label]+'('+item[fieldProps.value]+')'"
+                                    :value="item[fieldProps.value]">
+                                </el-option>
+                            </el-select> -->
+                            <el-cascader :options="field" v-model="list[i].field" :props="deftProps" filterable size='small' @change="change(list[i])" style="width:250px" :title="getTitle(list[i].field)" :show-all-levels="false"></el-cascader>
+                        <!-- </el-col> -->
+                        <!-- 运算符 -->
+                        <!-- <el-col :span="3" style="padding:0"> -->
+                            <el-select v-model="list[i].operator" size='small' style="width:150px" v-if="!searchResult">
+                                <el-option
+                                    v-for="item in operator"
+                                    :key="item[operatorProps.value]"
+                                    :label="item[operatorProps.label]"
+                                    :value="item[operatorProps.value]">
+                                </el-option>
+                            </el-select>
+                        <!-- </el-col> -->
+                        <!-- 搜索值 -->
+                        <!-- <el-col :span="9"> -->
+                            <div style="width:100%;display: flex;justify-content: center;align-items: center;" >
+                            <!-- <div style="" > -->
+                                <div v-if="list[i].dataType==2" style="display:flex;width:100%">
+                                    <el-date-picker
+                                        v-model="list[i].value[0]"
+                                        style="width:50%"
+                                        type="date"
+                                        size='small'
+                                        value-format="yyyyMMdd"
+                                        placeholder="开始,例:20000101">
+                                    </el-date-picker>
+                                    <el-date-picker
+                                        style="width:50%"
+                                        v-model="list[i].value[1]"
+                                        type="date"
+                                        size='small'
+                                        value-format="yyyyMMdd"
+                                        placeholder="结束,例:20001231">
+                                    </el-date-picker>
+                                </div>
+                                <div v-else-if="list[i].dataType==3" style="width:100%">
+                                    <el-select v-model="list[i].value" size="small" multiple filterable collapse-tags placeholder="请选择,可多选" style="width:100%">
+                                        <el-option
+                                            v-for="item in constants[list[i].field]"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value">
+                                        </el-option>
+                                    </el-select>
+                                </div>
+                                <div v-else style="width:100%"><el-input size='small' style="width:100%" v-model="list[i].value" :placeholder="list[i].placeholder"></el-input> </div>
+                              
+                                <template v-if="searchResult">
+                                    <div style="display: flex;margin-left: 10px;">
+                                      <el-button size="small" type="primary" @click="searchTwo('repeat')">二次检索</el-button>
+                                      <el-button size="small" type="primary" @click="searchTwo('new')">重新检索</el-button>
+                                    </div>
+                                </template>
+                              </div>
+                        <!-- </el-col> -->
+                    <!-- </el-row> -->
+                    <div style="width:50px">
+                        <span v-if="list.length==1" style="opacity: 0;"> 内容 </span>
+                        <el-button v-else size="small" @click="deleteList(i)"><i class="el-icon-delete"></i></el-button>
+                    </div>
+                </div>
+
+            </div>
+            <div class="button_group" v-if="searchValue">
+                <el-button size="small" type="primary" @click="add">增加</el-button>
+                <el-button size="small" type="primary" @click="search2">检索</el-button>
+                <el-button size="small" @click="reset">重置</el-button>
+                <!-- <el-button size="small" @click="createSearch" v-if="searchValue">生成检索式</el-button> -->
+            </div>
+           
+        </div>
+        <!-- 检索式检索 -->
+        <div v-if="searchValue">
+            <p><b>检索式检索</b><span style="margin-left:10px">[例: TI=计算机 ]</span></p>
+            <div>
+                <el-input type="textarea" :rows="4" readonly v-model="searchStr"></el-input>
+            </div>
+            <!-- <div class="button_group">
+                <el-button size="small" type="primary" @click="search2">检索</el-button>
+            </div> -->
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    props:{
+        //逻辑符
+        logical:{
+            type:Array,
+            default: ()=>{ return [
+                {
+                    label:'并且',
+                    value:'&&'
+                },
+                {
+                    label:'或者',
+                    value:'||'
+                },
+            ] }
+        },
+        //逻辑符配置
+        logicalProps:{
+            type:Object,
+            default:()=>{
+                return {
+                    label:'label',
+                    value:'value',
+                }
+            }
+        },
+        //运算符
+        operator:{
+            type:Array,
+            default: ()=>{ return [
+                {
+                    label:'=',
+                    value:'='
+                },
+                {
+                    label:'>',
+                    value:'>'
+                },
+                {
+                    label:'<',
+                    value:'<'
+                },
+            ] }
+        },
+        //运算符配置
+        operatorProps:{
+            type:Object,
+            default:()=>{
+                return {
+                    label:'label',
+                    value:'value',
+                }
+            }
+        },
+        //搜索值
+        field:{
+            type:Array,
+            default: ()=>{ return [] }
+        },
+        //搜索值配置
+        fieldProps:{
+            type:Object,
+            default:()=>{
+                return {
+                    label:'label',
+                    value:'value',
+                }
+            }
+        },
+        //是否展示检索式
+        searchValue:{
+            type:Boolean,
+            default:()=>{
+                return true
+            }
+        },
+        //默认值
+        list:{
+            type:Array,
+            default:()=>{
+                return []
+            }
+        },
+        // 是否是从检索结果页面进入,true是从检索结果页面进入
+        searchResult: {
+          type:Boolean,
+          default: () => {
+            return false
+          }
+        },
+        // 国家及地区
+        countryList: {
+          type: Array,
+          default: () => {
+            return []
+          }
+        }
+    },
+    data() {
+        return {
+            // list:[],
+            searchStr:'',
+            constants:this.$constants,
+            deftProps:{
+                emitPath:false
+            },
+            filedList:[]
+        }
+    },
+    watch:{
+        field(){
+            this.list.length = 0
+            this.rule()
+        },
+        list: {
+            handler(val) {
+                this.createSearch()
+            },
+            deep: true,// 深度监听
+        }
+    },
+    mounted() {
+        this.filedList =[].concat(...this.field.map(item=>{return item.children}))
+        this.rule()
+        if (this.countryList) {
+          let a = JSON.parse(JSON.stringify(this.countryList))
+          this.constants.GJ=a.filter(item => {
+            return item.value != 'CN'
+          })
+          // this.constants.GJ=this.countryList
+        }
+    },
+    methods: {
+        change(list){
+            var a = this.filedList.find(item=>{
+                return item.value == list.field
+            })
+            list.dataType = a.dataType
+            list.placeholder = a.placeholder
+            if(list.dataType==2 || list.dataType==3){
+                this.$set(list,'value', [])
+            }else{
+                this.$set(list,'value', '')
+            }
+        },
+        //校验
+        rule(){
+            if(this.list.length>=1){
+                return false
+            }else{
+                this.list.push({
+                    logical:this.logical.length>0?this.logical[0][this.logicalProps.value]:'',
+                    // field:this.field.length>0?this.field[0][this.fieldProps.value]:'',
+                    field:'PN',
+                    placeholder:'请输入公开号,例:CN102860161 OR CN1526554846',
+                    operator:this.operator.length>0?this.operator[0][this.operatorProps.value]:'',
+                })
+                // this.rule()
+            }
+        },
+        //增加
+        add(){
+            this.list.push({
+                logical:this.logical.length>0?this.logical[0][this.logicalProps.value]:'',
+                // field:this.field.length>0?this.field[0][this.fieldProps.value]:'',
+                field:'PN',
+                placeholder:'请输入公开号,例:CN102860161 OR CN1526554846',
+                operator:this.operator.length>0?this.operator[0][this.operatorProps.value]:'',
+            },
+            // {
+            //     logical:this.logical.length>0?this.logical[0][this.logicalProps.value]:'',
+            //     field:this.field.length>0?this.field[0][this.fieldProps.value]:'',
+            //     operator:this.operator.length>0?this.operator[0][this.operatorProps.value]:''
+            // }
+            )
+        },
+        //鼠标悬浮文字提示
+        getTitle(val){
+            if(val){
+                return this.filedList.filter(item=>{
+                    return item.value == val
+                })[0].label + '('+ val + ')'
+            }
+        },
+        //删除
+        deleteList(index){
+            this.list.splice(index,1)
+        },
+        //重置
+        reset(){
+            this.list = [
+                {
+                    logical:this.logical.length>0?this.logical[0][this.logicalProps.value]:'',
+                    // field:this.field.length>0?this.field[0][this.fieldProps.value]:'',
+                    field:'PN',
+                    placeholder:'请输入公开号,例:CN102860161 OR CN1526554846',
+                    operator:this.operator.length>0?this.operator[0][this.operatorProps.value]:''
+                },
+                // {
+                //     logical:this.logical.length>0?this.logical[0][this.logicalProps.value]:'',
+                //     field:this.field.length>0?this.field[0][this.fieldProps.value]:'',
+                //     operator:this.operator.length>0?this.operator[0][this.operatorProps.value]:''
+                // }
+            ]
+        },
+        //生成检索式
+        createSearch(){
+            if(this.list.length == 0){
+                this.searchStr = ''
+                return 
+            }
+            var str = ''
+            if(!this.list[0].field || !this.list[0].operator){
+                return false
+            }
+            var a = false
+            this.list.forEach((item,index) => {
+                if(item.dataType == 3){
+                    if(item.value.length>0){
+                        a = true
+                        if(index == 0){
+                            if(item.value.length == 1){
+                                str = str +''+ item.field + item.operator  + item.value[0]
+                            }else{
+                                str = str +''+ item.field + item.operator +'(' + item.value.join(' OR ')+')'
+                            }
+                           
+                        }else{
+                            if(item.value.length == 1){
+                                str = str + " "+ item.logical + ' '+ item.field + item.operator + item.value[0]
+                            }else{
+                                str = str + " "+ item.logical + ' '+ item.field + item.operator + '(' + item.value.join(" OR ")+')'
+                            }
+                            
+                        }
+                    }
+                }else if(item.dataType == 2){
+                    if(item.value.length>0){
+                        if(!item.value[0] && !item.value[1]){
+
+                        }else{
+                            if(index == 0){
+                                if( item.value[0] && item.value[1] ){
+                                    str = str  + ''+ item.field + item.operator + '(' + item.value[0] +'~'+item.value[1]+')'
+                                }else if(!item.value[0] || !item.value[1]){
+                                    str = str  + ''+ item.field + item.operator + (item.value[0] || item.value[1])
+                                }
+                            }else{
+                                if( item.value[0] && item.value[1] ){
+                                    str = str + " "+ item.logical + ' '+ item.field + item.operator + '(' + item.value[0] +'~'+item.value[1]+')'
+                                }else if(!item.value[0] || !item.value[1]){
+                                    str = str + " "+ item.logical + ' '+ item.field + item.operator + (item.value[0] || item.value[1])
+                                }
+                            }
+                            
+                        }    
+                    }
+                }else{
+                    if(item.value){
+                        a = true
+                        var a = item.value.replace(/("[^"]*"|'[^']*')/g,'')
+                        var arr = a.match(/\s{1}and|AND|OR|or|NOT|not\s{1}/g)
+                        if(arr&&arr.length>0){
+                            if(index == 0){
+                                str = str +''+ item.field + item.operator +'(' + item.value+')'
+                            }else{
+                                str = str + " "+ item.logical + ' '+ item.field + item.operator +'(' + item.value+')'
+                            }
+                        }else{
+                            if(index == 0){
+                                str = str +''+ item.field + item.operator  + item.value
+                            }else{
+                                str = str + " "+ item.logical + ' '+ item.field + item.operator  + item.value
+                            }
+                        }
+                    }
+                        
+                }
+                
+            });
+            // if(!a){
+            //     this.$message.info('请输入要检索的内容')
+            //     return false
+            // }
+            this.searchStr = str
+        },
+        //表单检索
+        search1(){
+            var str = ''
+            if(!this.list[0].field || !this.list[0].operator){
+                return false
+            }
+            var a = false
+            this.list.forEach((item,index) => {
+                if(item.value){
+                    a = true
+                    if(index == 0){
+                        str = str +'('+ item.field + item.operator + item.value+')'
+                    }else{
+                        str = str + item.logical + '('+ item.field + item.operator + item.value+')'
+                    }
+                }
+            });
+            if(!a){
+                this.$message.info('请输入要检索的内容')
+                return false
+            }
+            this.$emit('search',str)
+        },
+    //检索式检索
+    search2() {
+      this.$emit('search', this.searchStr.trim())
+    },
+    // 二次检索和重新检索
+    searchTwo(val) {
+      var a = {
+        searchStr: this.searchStr.trim(),
+      }
+      if (val == 'repeat') {//二次检索
+        a.isRepeat = true
+      } else {//重新检索
+        a.isRepeat = false
+      }
+      this.$emit('search', a)
+    },
+    },
+}
+</script>
+<style lang="scss" scoped>
+    .content_border{
+        width:100%;
+        // min-width: 1500px;
+      //  display: flex;
+       align-items: center; 
+       justify-content: flex-start;
+       flex-wrap:wrap;
+    }
+    .content_border .content{
+        display: flex;
+        align-items: center;
+        position: relative;
+        width: 100%;
+        // margin-bottom: 10px;
+        padding-right:20px;
+        
+    }
+    .content_border .content>*{
+        padding:10px
+    }
+    .button_group{
+        margin-top:20px;
+        margin-right:20px;
+        display: flex;
+        justify-content: flex-end;
+    }
+    .button_group .el-button{
+        width:92px
+    }
+    
+</style>

+ 74 - 0
src/utils/model/search/searchIndex.vue

@@ -0,0 +1,74 @@
+<template>
+    <div>
+        <search :logical="logical" :logicalProps="logicalProps" :operator="operator" :field="field" :searchValue="true" :list="list"></search>
+    </div>
+</template>
+<script>
+import search from './search.vue'
+export default {
+    components:{
+        search
+    },
+    data() {
+        return {
+        //逻辑符
+        logical:[
+            {
+                name:'并且',
+                value:'&&'
+            },
+            {
+                name:'或者',
+                value:'||'
+            },
+        ],
+        logicalProps:{
+            label:'name',
+            value:'value'
+        },
+        //运算符
+        operator:[
+            {
+                label:'=',
+                value:'='
+            },
+            {
+                label:'>',
+                value:'>'
+            },
+            {
+                label:'<',
+                value:'<'
+            },
+            {
+                label:'<=',
+                value:'<='
+            },
+        ],
+        //搜索值
+        field:[
+            {
+                label:'专利号',
+                value:'patentNo'
+            },
+            {
+                label:'标题',
+                value:'title'
+            },
+            {
+                label:'公开日',
+                value:'publicDate'
+            },
+        ],
+        list:[
+            {
+                logical:'and',
+                field:'patentNo',
+                operator:'=',
+                value:'123'
+            }
+        ],
+        }
+    },
+}
+</script>

+ 142 - 0
src/utils/model/selectButton/index.vue

@@ -0,0 +1,142 @@
+<template>
+  <div class="selectButton">
+    <div class="selectButton-div" style="padding: 20px;">
+      <el-select v-model="selectValue" :placeholder="placeholder" :size="size"
+        :clearable="clearable" :disabled="disabled" :multiple="multiple" :filterable="filterable" @change="change">
+        <el-option v-for="(item,index) in optionArr" :key="'myButton'+ index" :label="item[prop.label]" :value="item[prop.value]">
+        </el-option>
+      </el-select>
+      <el-button  @click="handleClick" :disabled="disabled" :size="size" class="selectButton-button">
+        <slot name="button">
+         <i class="el-icon-search"></i> 
+        </slot>
+        
+      </el-button>
+    </div>
+   
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    // 数据源(选择)
+    optionArr: {
+      type: Array,
+      default: ()=>[],
+    },
+    prop: {
+      default: () => {
+        return {
+          label: 'label',
+          value:'value'
+        }
+      }
+      
+    },
+    //v-model传过来的值(双向绑定的值)
+    value: {
+      default:''
+    },
+    // 尺寸
+    size: {
+      type: String,
+      default: 'small'
+    },
+    // 提示内容
+    placeholder: {
+      type: String,
+      default: ''
+    },
+    // 单选清空或不清空
+    clearable: {
+      type: Boolean,
+      default: false
+    },
+    // 是否禁用
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    // 多选
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    // 是否可搜索
+    filterable: {
+      type: Boolean,
+      default: false
+    }
+
+  },
+  data() {
+    return {
+      selectValue: this.value
+    }
+  },
+  watch: {
+  },
+  mounted() {
+    this.init()
+  },
+  methods: {
+    //初始化
+    init() {
+      // if (this.multiple) {
+      //   if (typeof this.value == 'object') {
+          
+      //   } else {
+      //     this.selectValue = []
+      //     this.selectValue.push(this.value)
+      //     console.log('不是Array');
+      //   }
+      // } else {
+      //   if (typeof this.value == 'string') {
+          
+      //   } else {
+      //     this.selectValue = ''
+      //     this.selectValue = this.value
+      //     console.log('不是String');
+      //   }
+      // }
+    },
+    //切换下拉框的值
+    change(val) {
+      this.$emit('input', val)
+    },
+    // 按钮点击事件
+    handleClick(e) {
+      this.$emit('click', e)
+    },
+  },
+}
+</script>
+
+<style lang="scss">
+.selectButton {
+
+  .el-select {
+    display: inline-block;
+    position: relative;
+    width: 100%;
+  }
+  .el-input__inner {
+    color: #606266 !important;
+    border-radius: 5px 0px 0px 5px;
+  }
+}
+</style>
+<style lang="scss" scoped>
+.selectButton {
+  .selectButton-div {
+    width: calc(100% - 40px);
+    display: flex;
+    align-items: center;
+  }
+
+  .selectButton-button {
+    border-radius: 0px 5px 5px 0px;
+  }
+}
+</style>

+ 357 - 0
src/utils/model/time/mixins.js

@@ -0,0 +1,357 @@
+export const cron = {
+    methods: {
+        //生成cron表达式
+    getCron(type) {
+      if(type){
+        var cron = ''
+        if(type == "day"){
+            let m = "";
+            let s = "";
+            let h = "";
+            let date = new Date();
+            if (date) {
+              h = date.getHours();
+              m = date.getMinutes();
+              s = date.getSeconds();
+          }
+          this.$set(this,'value',h+':'+m+':'+s)
+            cron = s + " " + m + " " + h + " * * ? *";
+        }else if (type == "week") { //星期
+          let m = "";
+          let s = "";
+          let h = "";
+          var value1 = ''
+          var week = new Date().getDay()
+          // 编辑回显后再次转义
+          switch (week) {
+            case 0:
+              value1 = "1";
+              break;
+            case 1:
+              value1 = "2";
+              break;
+            case 2:
+              value1 = "3";
+              break;
+            case 3:
+              value1 = "4";
+              break;
+            case 4:
+              value1 = "5";
+              break;
+            case 5:
+              value1 = "6";
+              break;
+            case 6:
+              value1 = "7";
+              break;
+          }
+          var en2cnMap = {
+            1: "周日",
+            2: "周一",
+            3: "周二",
+            4: "周三",
+            5: "周四",
+            6: "周五",
+            7: "周六",
+          };
+          this.$set(this,'day',en2cnMap[value1])
+          let date = new Date();
+          if (date) {
+            h = date.getHours();
+            m = date.getMinutes();
+            s = date.getSeconds();
+          }
+          this.$set(this, 'time', (h < 10 ? ("0" + h) : h )+ ':' + (m < 10 ? ("0" + m) : m) + ':' + (s < 10 ? ("0" + s) : s))
+          this.$set(this, 'value', this.day + " " + this.time)
+          cron = s + " " + m + " " + h + " ? * " + value1 + " *";
+          //周cron表达式
+        } else if (type == "month") {//每月的几号
+          let m = "";
+          let s = "";
+          let h = "";
+          let mo =  "";
+          var date = new Date();
+          if (date) {
+            mo = date.getDate() 
+            h = date.getHours();
+            m = date.getMinutes();
+            s = date.getSeconds();
+          }
+          this.$set(this,'day',mo+'日')
+          this.$set(this, 'time', (h < 10 ? ("0" + h) : h )+ ':' + (m < 10 ? ("0" + m) : m) + ':' + (s < 10 ? ("0" + s) : s))
+          this.$set(this,'value',this.day+" "+this.time)
+          cron = s + " " + m + " " + h + " " + mo + " * ? *"
+        } else if (type == "year") {//指定年月日
+          let m = "";
+          let s = "";
+          let h = "";
+          let year = "";
+          let month = "";
+          let day = "";
+          //指定时间
+
+          var date = new Date();
+          if (date) {
+            h = date.getHours();
+            m = date.getMinutes();
+            s = date.getSeconds();
+            year = date.getFullYear();
+            month =date.getMonth() + 1 
+            day = date.getDate() 
+          }
+          this.$set(this,'value',date)
+          cron =
+            s +
+            " " +
+            m +
+            " " +
+            h +
+            " " +
+            day +
+            " " +
+            month +
+            " " +
+            "?" +
+            " " +
+            "*";
+        }
+        return cron
+      }
+            var cron = ''
+            if(this.type == "day"){//天
+                let m = "";
+                let s = "";
+                let h = "";
+                let date = this.value;
+                date= date.split(':')
+                if (date) {
+                  h = date[0];
+                  m = date[1];
+                  s = date[2];
+                }
+                cron = s + " " + m + " " + h + " * * ? *";
+            }else if (this.type == "week") { //星期
+                let m = "";
+                let s = "";
+                let h = "";
+                var day = this.day || "";
+                switch (day) {
+                  case "周日":
+                    day = "1";
+                    break;
+                  case "周一":
+                    day = "2";
+                    break;
+                  case "周二":
+                    day = "3";
+                    break;
+                  case "周三":
+                    day = "4";
+                    break;
+                  case "周四":
+                    day = "5";
+                    break;
+                  case "周五":
+                    day = "6";
+                    break;
+                  case "周六":
+                    day = "7";
+                    break;
+                }
+                let date = this.time;
+                date= date.split(':')
+                if (date) {
+                  h = date[0];
+                  m = date[1];
+                  s = date[2];
+                }
+                
+                cron = s + " " + m + " " + h + " ? * " + day + " *";
+                //周cron表达式
+              } else if (this.type == "month") {//每月的几号
+                let m = "";
+                let s = "";
+                let h = "";
+                let mo = this.day.match(/\d+/) || "";
+                let date = this.time;
+                date= date.split(':')
+                if (date) {
+                  h = date[0];
+                  m = date[1];
+                  s = date[2];
+                }
+                cron = s + " " + m + " " + h + " " + mo + " * ? *";
+              } else if (this.type == "year") {//指定年月日
+                let m = "";
+                let s = "";
+                let h = "";
+                let year = "";
+                let month = "";
+                let day = "";
+                //指定时间
+                var date = this.value;
+                date = new Date(date);
+                if (date) {
+                  h = date.getHours();
+                  m = date.getMinutes();
+                  s = date.getSeconds();
+                  year = date.getFullYear();
+                  month = date.getMonth() + 1 
+                  day = date.getDate()
+                }
+                cron =
+                  s +
+                  " " +
+                  m +
+                  " " +
+                  h +
+                  " " +
+                  day +
+                  " " +
+                  month +
+                  " " +
+                  "?" +
+                  " " +
+                  "*";
+              }
+              return cron
+        },
+        //反编译cron
+    cronChangeDate(str) {
+        var toDate = {};
+        if (!str) {
+          return;
+        } else {
+          var result = str.split(" ").join("");
+          var nArr = str.split(" ");
+          var countData = this.getPlaceholderCount(result);
+          var str1 = "";
+          str1 = result.split("").reverse().join("").substring(3, 4);
+          if (countData.count1 && str1 == "?") {
+            toDate.loopType = "周循环";
+            var keys = nArr[5];
+            var en2cnMap = {
+              1: "周日",
+              2: "周一",
+              3: "周二",
+              4: "周三",
+              5: "周四",
+              6: "周五",
+              7: "周六",
+            };
+            var cnKeys = keys.split(",").map(function (key, idx) {
+              return en2cnMap[key];
+            });
+            toDate.loopValue = cnKeys.join(",");
+          } else if (countData.count1 + countData.count2 === 3) {
+            toDate.loopType = "月循环";
+            var mot = [];
+            var mkeys = nArr[3].split(",");
+            for (var i = 0; i < mkeys.length; i++) {
+              let mo = mkeys[i];
+              mot.push(mo);
+            }
+            toDate.loopValue = mot.join(",");
+          } else {
+          }
+          if (this.type == "year") {
+            toDate.loopTime =
+              nArr[6] +
+              "-" +
+              nArr[4] +
+              "-" +
+              nArr[3] +
+              " " +
+              nArr[2] +
+              ":" +
+              nArr[1] +
+              ":" +
+              nArr[0];
+          } else {
+            toDate.loopTime =
+              2020 +
+              "-" +
+              10 +
+              "-" +
+              10 +
+              " " +
+              nArr[2] +
+              ":" +
+              nArr[1] +
+              ":" +
+              nArr[0];
+          }
+  
+          var date = toDate.loopTime;
+          date = date.substring(0, 19);
+          date = date.replace(/-/g, "/");
+          var timestamp = new Date(date);
+          if (toDate.loopType == "周循环") {
+            // this.time = date;
+            // this.day = toDate.loopValue;
+            date = date.split(' ')[1].split(":")
+            var h = date[0];
+             var m = date[1];
+             var s = date[2];
+            this.$set(this, 'time', (h < 10 ? ("0" + h) : h )+ ':' + (m < 10 ? ("0" + m) : m) + ':' + (s < 10 ? ("0" + s) : s))
+            this.$set(this, 'day', toDate.loopValue)
+            this.$set(this,'value',this.day+" "+this.time)
+          } else if (toDate.loopType == "月循环") {
+            date = date.split(' ')[1].split(":")
+              var h = date[0];
+             var m = date[1];
+             var s = date[2];
+            this.$set(this, 'time', (h < 10 ? ("0" + h) : h )+ ':' + (m < 10 ? ("0" + m) : m) + ':' + (s < 10 ? ("0" + s) : s))
+            // this.time = date;
+            // this.day = toDate.loopValue + '日';
+            // this.$set(this,'time',date)
+            this.$set(this, 'day', toDate.loopValue + '日')
+            this.$set(this,'value',this.day+" "+this.time)
+          } else {
+            // this.value = date;
+            this.$set(this,'value',date)
+          }
+        }
+        return toDate;
+    },
+    // 根据cron表达式获取更新周期
+    getType(str){
+      if(!str){
+        return "";
+      }
+      var type = ''
+      var result = str.split(" ").join("");
+      var countData = this.getPlaceholderCount(result);
+      var str1 = "";
+      str1 = result.split("").reverse().join("").substring(3, 4);
+      if (countData.count1 && str1 == "?") {
+        type = 'week'
+      } else if (countData.count1 + countData.count2 === 3) {
+        type = 'month'
+      } else if(countData.count1 && str1 == "*") {
+        type = 'day'
+      }else{
+        type = 'year'
+      }
+      return type
+    },
+      // 统计字符串中包含某个字符的个数
+      getPlaceholderCount(strSource) {
+        var count1 = 0; 
+        var count2 = 0; 
+        strSource.replace(/\*|\?/g, function (m, i) {
+          if (m === "?") {
+            count1++;
+          } else if (m === "*") {
+            count2++;
+          }
+        });
+  
+        var obj = {};
+        obj.count1 = count1;
+        obj.count2 = count2;
+        return obj; 
+      },
+    },
+}

+ 149 - 0
src/utils/model/time/timeChoose.vue

@@ -0,0 +1,149 @@
+<template>
+    <div>
+        <div style="width:100%">
+            <el-popover
+                v-if="!showTime && !showDate"
+                ref="popover"
+                placement="bottom"
+                width="400"
+                trigger="click">
+            <div style="display:flex;width:100%" >
+                <el-input  v-model="day" placeholder="选择时间" style="margin-right:10px;width:100%"></el-input>
+                <el-time-picker
+                    @change="changeTime"
+                    @blur="changeTime"
+                    v-model="time"
+                    value-format="HH:mm:ss"
+                    placeholder="选择时间">
+                </el-time-picker>
+            </div>
+            <div style="display:flex;flex-wrap:wrap;width:100% " >
+                <p style="min-width:50px;width:calc(100% / 7);text-align:center;cursor:pointer" v-for="(item,index) in list[type]" :key="index" @click="check(item)">{{ item }}</p>
+            </div>
+            <el-input slot="reference" v-model="value" placeholder="选择时间"  style="width:100%"></el-input>
+            </el-popover>
+            <el-time-picker
+                v-if="showTime"
+                @change="changeTime"
+                v-model="value"
+                style="width:100%"
+                value-format="HH:mm:ss"
+                placeholder="选择时间">
+            </el-time-picker>
+            <el-date-picker
+                popper-class="picker-date"
+                format="MM-dd HH:mm:ss"
+                v-if="showDate"
+                @change="changeTime"
+                v-model="value"
+                type="datetime"
+                placeholder="选择日期时间">
+            </el-date-picker>
+        </div>
+       
+    </div>
+</template>
+<script>
+import { cron } from "./mixins";
+export default {
+  mixins:[cron],
+    props:{
+        type:{
+            default:'day'
+      },
+        cron:{}
+        
+    },
+    data() {
+        return {
+            value:'',
+            day:'',
+            time:'',
+            list:{
+                week:['周一','周二','周三','周四','周五','周六','周日'],
+                month:[]
+            },
+            showDate:false,
+            showTime:false,
+            
+        }
+  },
+  watch: {
+    type(val) {
+      this.init()
+     }, 
+    },
+  mounted() {
+        this.init()
+    },
+  methods: {
+    init() {
+      this.value = ''
+      this.day = ''
+      this.time = ''
+      this.showTime =this.type=='day'? true:false
+      this.showDate = this.type == 'year' ? true : false
+      
+      switch (this.type) {
+            case 'day':
+                break;
+            case 'week':
+                break;
+            case 'month':
+                for(let i = 1;i < 32;i++){
+                    this.list.month.push(i+'日')
+                }
+                break;
+        case 'year':
+                break;
+      }
+      if (!this.cron && this.type) {
+        let cron = this.getCron(this.type)
+        this.$emit('value', cron)
+      } else if(this.cron && this.type){
+         this.cronChangeDate(this.cron)
+      }
+      },
+        check(item){
+            this.$set(this,'day',item)
+            if(!this.time){
+               this.$set(this,'time','18:30:00') 
+            }
+            
+            this.changeTime()
+        },
+        changeTime(){
+            if(!this.showDate && !this.showTime){
+                this.$set(this,'value',this.day+" "+this.time)
+            }
+          // console.log(this.value)
+            let cron=this.getCron()
+          this.$emit('value', cron)
+        }
+    },
+}
+</script>
+
+<style lang="scss">
+.el-time-panel{
+    margin-top:20px;
+    z-index: 9999 !important;
+}
+.el-picker-panel{
+    z-index: 9999 !important;
+}
+
+.picker-date {
+  .el-date-picker__header {
+    span:nth-child(3) {      
+      display: none;
+    }
+    button:nth-child(1) {
+      display: none;
+    }
+    button:nth-child(5) {
+      display: none;
+    }
+  }
+}
+</style>

+ 19 - 0
src/utils/model/time/timeIndex.vue

@@ -0,0 +1,19 @@
+<template>
+    <div>
+        <timeChoose :type="type" style="width:200px"></timeChoose>
+    </div>
+</template>
+<script>
+import timeChoose from './timeChoose.vue'
+export default {
+    components:{
+        timeChoose
+    },
+    data() {
+        return {
+            width:'300px',
+            type:'week'
+        }
+    },
+}
+</script>