Sfoglia il codice sorgente

通用组件更新

CzRger 1 anno fa
parent
commit
fe024f0335

+ 1 - 1
package.json

@@ -12,7 +12,7 @@
     "@types/node": "^20.1.0",
     "animate.css": "^4.1.1",
     "axios": "^1.3.4",
-    "element-plus": "^2.4.3",
+    "element-plus": "^2.5.1",
     "sass": "^1.60.0",
     "uuid": "^9.0.0",
     "vue": "^3.3.9",

+ 2 - 4
src/components/cus/CusDialog.vue

@@ -32,7 +32,7 @@
       <div class="__cus-dialog-content">
         <slot/>
       </div>
-      <div class="__cus-dialog-foot" :style="`justify-content: ${footAlign};padding: ${footPadding};`">
+      <div class="__cus-dialog-foot" :style="`justify-content: ${footAlign};padding: ${footPadding};`" v-if="showSubmit || showClose || $slots.foot">
         <slot name="foot" :close="CDClose" :submit="CDSubmit"/>
         <template v-if="footAlign === 'center'">
           <div v-if="showSubmit" class="__cus-dialog-foot_submit __hover" @click="CDSubmit">{{submitText}}</div>
@@ -76,9 +76,7 @@ export default defineComponent({
     closeText: {default: '取消'},
     showClose: {default: true},
     showSubmit: {default: true},
-    footAlign: {default: 'center', validator(val: string) {
-      return ['center', 'right'].includes(val)
-    }},
+    footAlign: {default: 'center'},
     footPadding: {default: '16px 26px'},
     height: {default: '60%'},
     maxHeight: {default: 'unset'},

+ 20 - 4
src/components/cus/CusFormColumn.vue

@@ -6,8 +6,13 @@
     span4: filterSpan == 4,
     span5: filterSpan == 5,
   }" :span="span" :offset="offset" ref="ref_cusFormColumn">
-    <el-form-item :label="label" :label-width="labelWidth" :class="{ required: required !== false }"
-                  :error="errorMessage" :required="required">
+    <el-form-item :label="label" :label-width="labelWidth" :class="{
+      required: required !== false,
+      'no-label': (labelWidth == 0 || labelWidth === '0px') && !$util.isValue(label)
+    }" :error="errorMessage" :required="required">
+      <template #label>
+        <slot name="label"/>
+      </template>
       <slot name="cus" :handleValidate="handleValidate">
         <template v-if="link === 'input'">
           <InputCom
@@ -260,9 +265,10 @@ export default defineComponent({
     maxLength: {type: Number, default: null},
     minLength: {type: Number, default: null},
     defaultErrorMsg: {default: null},
-    unit: {default: '', type: String}
+    unit: {default: '', type: String},
+    otherInfo: {}
   },
-  setup(props) {
+  setup(props, {attrs}) {
     const store = useStore();
     const router = useRouter();
     const route = useRoute();
@@ -294,6 +300,11 @@ export default defineComponent({
           handle: (val: any) => !isValue(val) || (isValue(val) && String(val).length <= props.maxLength),
           message: `内容过长,字数需小于等于${props.maxLength}`
         })
+      } else if (props.link === 'input' && attrs.type === 'textarea' && isValue(attrs.maxlength)) {
+        r.unshift({
+          handle: (val: any) => !isValue(val) || (isValue(val) && String(val).length <= Number(attrs.maxlength)),
+          message: `内容过长,字数需小于等于${attrs.maxlength}`
+        })
       }
       const doStr = ['input', 'number', 'input-number', 'rich'].includes(props.link) ? '输入' : '选择'
       if (props.required !== false && !props.rules.some((v: any) => v.type === 'default')) {
@@ -410,6 +421,11 @@ export default defineComponent({
     flex: unset;
   }
   :deep(.el-form-item) {
+    &.no-label {
+      .el-form-item__label {
+        display: none;
+      }
+    }
     .el-form-item__label {
       line-height: 1;
       text-align: right;

+ 1 - 1
src/components/cus/CusPopover.vue

@@ -3,7 +3,7 @@
       placement="top-start"
       trigger="hover"
       :content="value"
-      popper-class="cus-popover"
+      popper-class="__cus-popover"
   >
     <template #reference>
       <slot/>

+ 1 - 1
src/components/cus/CusTab.vue

@@ -108,7 +108,7 @@ export default defineComponent({
             width: 100%;
             height: 5px;
             bottom: -3px;
-            //background-image: url("@/assets/images/cus/cus-tab_type2-active.png");
+            background-image: url("@/assets/images/cus/cus-tab_type2-active.png");
             background-repeat: no-repeat;
             background-size: 100% 100%;
           }

+ 53 - 12
src/components/cus/CusTable.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="cus-table" :class="{'cus-table-normal': !otherStyle, 'cus-table-full': full !== false}">
-    <div class="cus-table-main" ref="ref_tableMain">
+    <div class="cus-table-main" ref="ref_tableMain" :class="{'cus-table-main-no-foot': noFoot !== false}">
       <el-table
           v-bind="$attrs"
           class="ct-table"
@@ -11,8 +11,8 @@
           @filter-change="handleFilter"
           @selection-change="v => $emit('update:selected', v)"
       >
-        <el-table-column v-if="selected" type="selection" :width="selectWidth" align="center" width="52" :selectable="selectable"/>
-        <el-table-column v-if="singled" :width="singledWidth" align="center" width="52" class-name="single-column">
+        <el-table-column v-if="selected" type="selection" :width="selectWidth" align="center" :selectable="selectable"/>
+        <el-table-column v-if="singled" :width="singledWidth" align="center" class-name="single-column">
           <template #default="scope">
             <div class="single-circle" :class="{active: scope.row[singledKey] === singled[singledKey]}" @click.stop="$emit('update:singled', scope.row)">
               <div class="single-circle-in"></div>
@@ -70,9 +70,12 @@
         </template>
       </el-table>
     </div>
-    <div class="ct-page">
+    <div class="ct-foot" v-if="noFoot === false">
       <div class="total">
-        <template v-if="$util.isValue(selected?.length)">
+        <template v-if="$util.isValue(selectedNum)">
+          已选中 {{ selectedNum }} 条 /
+        </template>
+        <template v-else-if="$util.isValue(selected?.length)">
           已选中 {{ selected.length }} 条 /
         </template>
         共 {{ total }} 条
@@ -130,6 +133,9 @@ import {
       selected: {
         default: null
       },
+      selectedNum: {
+        default: null
+      },
       selectWidth: {
         default: 50
       },
@@ -157,7 +163,10 @@ import {
       full: {
         default: false
       },
-      selectable: {}
+      selectable: {},
+      noFoot: {
+        default: false
+      }
     },
     setup(props, { emit }) {
       const store = useStore();
@@ -217,12 +226,35 @@ import {
       }
       const handleFilter = (val: any) => {
         const key = Object.keys(val)[0]
-        let value = val[key].length > 0 ? val[key][0] : null
+        const head = props.tableHead.filter(v => v.value === key)[0]
+        let value = null
+        if (val[key].length > 0) {
+          if (head.filterMultiple) {
+            value = val[key]
+          } else {
+            value = val[key][0]
+          }
+        }
         emit('handleFilter', {key, value})
       }
-      const resetFilter = (key: any) => {
+      const resetFilter = (key: any = null) => {
         key ? ref_table.value.clearFilter([key]) : ref_table.value.clearFilter()
       }
+      const reset = (key: any = null) => {
+        resetFilter(key)
+        ref_table.value.clearSort()
+      }
+      watch(() => props.selected, (n: any) => {
+        if (n.length === 0) {
+          ref_table.value.clearSelection()
+        } else {
+          setTimeout(() => {
+            n.forEach(v => {
+              ref_table.value.toggleRowSelection(v, true)
+            })
+          }, 100)
+        }
+      })
       onMounted(() => {
         formatTableHead(props.tableHead)
       })
@@ -236,7 +268,8 @@ import {
         ref_tableMain,
         ref_tablePage,
         ...toRefs(state),
-        pageLayoutCpt
+        pageLayoutCpt,
+        reset
       }
     },
   })
@@ -259,11 +292,14 @@ import {
     width: 100%;
     height: calc(100% - #{$cus-page-height} - #{$cus-page-mt}) !important;
     position: absolute;
+    &.cus-table-main-no-foot {
+      height: 100% !important;
+    }
     :deep(.ct-table) {
       height: 100%;
     }
   }
-  :deep(.ct-page) {
+  :deep(.ct-foot) {
     height: $cus-page-height;
     font-size: 14px;
     font-family: Microsoft YaHei;
@@ -318,6 +354,10 @@ import {
                   font-family: 微软雅黑;
                   font-weight: 400;
                   color: #666666;
+                  padding: 0 4px;
+                  &.highlight {
+                    color: #409eff;
+                  }
                 }
               }
               &:first-child {
@@ -346,6 +386,7 @@ import {
                   overflow: hidden;
                   text-overflow: ellipsis;
                   word-break: break-all;
+                  padding: 0 6px;
                   .el-link +.el-link {
                     margin-left: 10px;
                   }
@@ -356,7 +397,7 @@ import {
         }
       }
     }
-    :deep(.ct-page) {
+    :deep(.ct-foot) {
       margin-top: auto;
     }
   }
@@ -365,7 +406,7 @@ import {
       position: unset;
       height: 100% !important;
     }
-    :deep(.ct-page) {
+    :deep(.ct-foot) {
       margin-top: $cus-page-mt;
     }
   }

+ 1 - 1
src/components/cus/CusTableColumn.vue

@@ -12,7 +12,7 @@
         :header-align="item?.headerAlign ? item?.headerAlign : 'center'"
         :fixed="item?.fixed ? item?.fixed : false"
         :filters="item?.filters ? item?.filters : null"
-        :filter-multiple="false"
+        :filter-multiple="!!item?.filterMultiple"
       >
         <template #default="scope">
           <template v-if="item.html">

+ 8 - 1
src/components/cus/CusTree.vue

@@ -75,7 +75,14 @@
         const deep = (arr) => {
           arr.forEach(v => {
             v._count = 0
-            if (props.filterMethod(v)) {
+            if (props.filterMethod) {
+              if (props.filterMethod(v)) {
+                if (isExpend !== null) {
+                  v._expend = isExpend
+                }
+                v._count++
+              }
+            } else {
               if (isExpend !== null) {
                 v._expend = isExpend
               }

+ 3 - 3
src/components/cus/cus-form-link/cascader.vue

@@ -4,12 +4,12 @@
        style="width: 100%;"
        v-bind="$attrs"
        v-model="paramVal"
-       :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+       :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
        :options="options"
        :clearable="$util.isValue($attrs.clearable) ? $attrs.clearable : true"
        :filterable="$util.isValue($attrs.filterable) ? $attrs.filterable : true"
        :props="propsCpt"
-       :teleported="false"
+       :teleported="$util.isValue($attrs.teleported) ? $attrs.teleported : false"
        :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"
     >
       <template #default="{ node, data }">
@@ -93,7 +93,7 @@ export default defineComponent({
       state.loading = false
     })
     const propsCpt = computed(() => {
-      return props.props ? props.props : state.defaultProps
+      return props.props ? Object.assign(state.defaultProps, props.props) : state.defaultProps
     })
     onMounted(() => {
       if (props.static !== false || props.options?.length > 0) {

+ 6 - 6
src/components/cus/cus-form-link/date.vue

@@ -5,7 +5,7 @@
       v-bind="$attrs"
       v-model="paramVal"
       clearable
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
       :valueFormat="valueFormatCpt"
       :format="formatCpt"
       unlink-panels
@@ -47,7 +47,7 @@ export default defineComponent({
         return ['date', 'year', 'week', 'month', 'dates', 'monthrange', 'daterange'].includes(val)
       }
     },
-    valueFormat: { type: String, default: ''},
+    valueFormat: { type: [String, Boolean], default: false},
     format: { type: String, default: ''},
   },
   setup(props, { emit }) {
@@ -67,13 +67,13 @@ export default defineComponent({
     })
     const formatCpt = computed(() => {
       let val = props.format
-      if (!val) {
+      if (!val && val !== undefined) {
         switch (props.type) {
           case 'year':
             val = 'YYYY'
             break;
           case 'month':
-            val = 'YYYY-DD'
+            val = 'YYYY-MM'
             break;
           case 'week':
             val = '[第]ww[周]'
@@ -86,13 +86,13 @@ export default defineComponent({
     })
     const valueFormatCpt = computed(() => {
       let val = props.valueFormat
-      if (!val) {
+      if (val === false) {
         switch (props.type) {
           case 'year':
             val = 'YYYY'
             break;
           case 'month':
-            val = 'YYYY-DD'
+            val = 'YYYY-MM'
             break;
           case 'week':
             val = ''

+ 1 - 1
src/components/cus/cus-form-link/datetime.vue

@@ -5,7 +5,7 @@
       v-bind="$attrs"
       v-model="paramVal"
       clearable
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
       :valueFormat="valueFormat"
       :format="format"
       unlink-panels

+ 2 - 2
src/components/cus/cus-form-link/dept.vue

@@ -4,9 +4,9 @@
         style="width: 100%;"
         v-bind="$attrs"
         v-model="paramVal"
-        :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+        :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
         :data="optionsCpt"
-        :clearable="$util.isValue($attrs.clearable) ? $attrs.clearable : true"
+        :clearable="$util.isValue($attrs.clearable) ? $attrs.clearable : false"
         :filterable="$util.isValue($attrs.filterable) ? $attrs.filterable : true"
         :check-strictly="checkStrictly"
         node-key="deptId"

+ 2 - 2
src/components/cus/cus-form-link/input-number.vue

@@ -2,7 +2,7 @@
   <el-input-number
       v-bind="$attrs"
       v-model="paramVal"
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请输入${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请输入${label}`)"
       @keyup.enter.native="$emit('emitEnter')"
       :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"
   >
@@ -39,7 +39,7 @@ export default defineComponent({
     const route = useRoute();
     const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
     const state = reactive({
-      paramVal: props.param,
+      paramVal: <any>Number(props.param),
       formView: inject('form-view', false),
     })
     watch(() => state.paramVal, (n) => {

+ 1 - 1
src/components/cus/cus-form-link/input.vue

@@ -4,7 +4,7 @@
       v-model="paramVal"
       :type="type"
       clearable
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请输入${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请输入${label}`)"
       @keyup.enter.native="$emit('emitEnter')"
       :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"
   >

+ 1 - 1
src/components/cus/cus-form-link/number.vue

@@ -4,7 +4,7 @@
       v-model="paramVal"
       :type="type"
       clearable
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请输入${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请输入${label}`)"
       @keyup.enter.native="$emit('emitEnter')"
       :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"
       @input="handleInput"

+ 2 - 2
src/components/cus/cus-form-link/select.vue

@@ -4,13 +4,13 @@
         style="width: 100%;"
         v-bind="$attrs"
         v-model="paramVal"
-        :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+        :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
         :clearable="$util.isValue($attrs.clearable) ? $attrs.clearable : true"
         :filterable="$util.isValue($attrs.filterable) ? $attrs.filterable : true"
         @change="handleChange"
-        :popper-append-to-body="false"
         :title="optionsMapCpt.get(paramVal)?.[labelKey]"
         :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"
+        :teleported="$util.isValue($attrs.teleported) ? $attrs.teleported : false"
     >
       <slot v-if="$slots.default">
         <el-option

+ 1 - 1
src/components/cus/cus-form-link/time.vue

@@ -4,7 +4,7 @@
       v-bind="$attrs"
       v-model="paramVal"
       clearable
-      :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+      :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
       :valueFormat="valueFormat"
       :format="format"
       :disabled="$util.isValue($attrs.disabled) ? $attrs.disabled : formView"

+ 1 - 1
src/components/cus/cus-form-link/tree-select.vue

@@ -4,7 +4,7 @@
         style="width: 100%;"
         v-bind="$attrs"
         v-model="paramVal"
-        :placeholder="$attrs.placeholder ? $attrs.placeholder : `请选择${label}`"
+        :placeholder="((typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) || formView) ? '' : ($attrs.placeholder ? $attrs.placeholder : `请选择${label}`)"
         :data="options"
         :clearable="$util.isValue($attrs.clearable) ? $attrs.clearable : true"
         :filterable="$util.isValue($attrs.filterable) ? $attrs.filterable : true"

+ 44 - 11
src/styles/cus.scss

@@ -10,6 +10,16 @@
   overflow: hidden;
   text-overflow: ellipsis;
   word-break: break-all;
+  &.el-link {
+    max-width: 100%;
+    .el-link__inner {
+      display: unset;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      word-break: break-all;
+    }
+  }
 }
 
 .__normal-page {
@@ -17,7 +27,28 @@
   flex: 1;
   display: flex;
   overflow: hidden;
+  background-color: #F5FBFF;
   .__normal-tree {
+    width: 250px;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    margin-right: 10px;
+    background-color: #FFFFFF;
+    .__normal-tree_filter {
+      width: 100%;
+      height: 60px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      padding: 0 10px;
+      border-bottom: 1px solid #d9dcea;
+    }
+    .__normal-tree_content {
+      flex: 1;
+      overflow: auto;
+      padding: 10px;
+    }
   }
   .__normal-content {
     flex: 1;
@@ -25,7 +56,9 @@
     overflow: hidden;
   }
 }
-
+.__normal-form {
+  padding: 16px 24px 0 24px;
+}
 .__cus-pagination {
   display: flex;
   justify-content: flex-end;
@@ -39,16 +72,11 @@
     color: #999999;
   }
   .el-pagination__sizes {
-    .el-input {
-      max-width: 100px !important;
-      .el-input__wrapper {
-        padding-left: 8px !important;
-        padding-right: 8px !important;
-        .el-input__inner {
-          font-size: 14px;
-          font-family: Microsoft YaHei;
-          font-weight: 400;
-          color: #999999;
+    .el-select {
+      .el-select__wrapper {
+        .el-select__selection {
+          .el-select__selected-item {
+          }
         }
       }
     }
@@ -259,3 +287,8 @@
     background-size: 100% 100%;
   }
 }
+
+.__cus-popover {
+  max-width: 60% !important;
+  width: auto !important;
+}

+ 4 - 4
yarn.lock

@@ -2224,10 +2224,10 @@ echarts@^5.4.3:
     tslib "2.3.0"
     zrender "5.4.4"
 
-element-plus@^2.4.3:
-  version "2.4.4"
-  resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.4.tgz#962be40b4843381af04b8f799bfc142072184b8b"
-  integrity sha512-TlKubXJgxwhER0dw+8ULn9hr9kZjraV4R6Q/eidwWUwCKxwXYPBGmMKsZ/85tlxlhMYbcLZd/YZh6G3QkHX4fg==
+element-plus@^2.5.1:
+  version "2.5.3"
+  resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.5.3.tgz#d4f8988ea199ad28ef15a6b0b8f94b7639d262fb"
+  integrity sha512-wmtstxaMkD6UinIgD+45CjrhbRh4u0vt+/GgxfPeMLt5pDpIVwZFjkUaVcWqqxcxd5a80HP3XlDF74fW7wim9A==
   dependencies:
     "@ctrl/tinycolor" "^3.4.1"
     "@element-plus/icons-vue" "^2.3.1"