<template> 
 | 
  <el-form 
 | 
    style="display: inline-block; width: 100%" 
 | 
    :inline="true" 
 | 
    ref="volform" 
 | 
    @submit.prevent 
 | 
    :model="formFields" 
 | 
    :label-width="labelWidth" 
 | 
    :rules="rules" 
 | 
  > 
 | 
    <template v-for="(row, findex) in formRules" :key="findex"> 
 | 
      <div class="vol-form-item"> 
 | 
        <el-form-item 
 | 
          :label="item.title ? item.title + ':' : ''" 
 | 
          v-show="!item.hidden" 
 | 
          v-for="(item, index) in row" 
 | 
          :prop="item.field" 
 | 
          :key="item.field + index" 
 | 
          :style="{ width: getColWidth(item) + '%' }" 
 | 
        > 
 | 
          <!-- render --> 
 | 
          <form-expand 
 | 
            v-if="item.render && typeof item.render == 'function'" 
 | 
            :render="item.render" 
 | 
            :par="12" 
 | 
          ></form-expand> 
 | 
          <!-- 2021.10.17增加表单实时方法计算 --> 
 | 
          <span 
 | 
            v-else-if=" 
 | 
              item.readonly && typeof formFields[item.field] == 'function' 
 | 
            " 
 | 
            >{{ formFields[item.field]() }}</span 
 | 
          > 
 | 
          <!-- 只读图片或文件  --> 
 | 
          <div v-else-if="isReadonlyImgFile(item, formFields)"> 
 | 
            <div v-if="item.type == 'img'" class="form-imgs"> 
 | 
              <div 
 | 
                class="img-item" 
 | 
                v-for="(img, imgIndex) in formFields[item.field]" 
 | 
                :key="imgIndex" 
 | 
              > 
 | 
                <img 
 | 
                  :src="getSrc(img.path)" 
 | 
                  :onerror="errorImg" 
 | 
                  @click="previewImg(img.path)" 
 | 
                /> 
 | 
              </div> 
 | 
            </div> 
 | 
            <div 
 | 
              v-else 
 | 
              class="form-file-list" 
 | 
              v-for="(file, fileIndex) in formFields[item.field]" 
 | 
              :key="fileIndex" 
 | 
            > 
 | 
              <a @click="dowloadFile(formFields[item.field][fileIndex])">{{ 
 | 
                file.name 
 | 
              }}</a> 
 | 
            </div> 
 | 
          </div> 
 | 
  
 | 
          <div v-else :class="{ 'form-item-extra': item.extra }"> 
 | 
            <!-- 只读属性 --> 
 | 
            <label 
 | 
              :style="item.inputStyle" 
 | 
              v-if="item.type == 'label'" 
 | 
              class="readonly-input" 
 | 
              >{{ getText(formFields, item) }}</label 
 | 
            > 
 | 
            <!-- 20223.05.13集成el-tree-select --> 
 | 
            <!-- :filter-method="(value)=>{filterMethod(value,item.data)}" --> 
 | 
            <!-- :filterable="true" --> 
 | 
            <el-tree-select 
 | 
              style="width: 100%" 
 | 
              v-else-if="item.type == 'treeSelect'" 
 | 
              v-model="formFields[item.field]" 
 | 
              :data="item.data" 
 | 
              :multiple="item.multiple" 
 | 
              :render-after-expand="false" 
 | 
              :show-checkbox="false" 
 | 
              :check-strictly="true" 
 | 
              check-on-click-node 
 | 
              node-key="key" 
 | 
              :props="{ label: 'label' }" 
 | 
            > 
 | 
              <template #default="{data,node }"> 
 | 
                <!-- <el-checkbox v-model="node.checked"></el-checkbox> --> 
 | 
               <!-- {{getNode(node, data)}} --> 
 | 
               <!-- {{node.checked}} --> 
 | 
               <!-- 这里还有点问题,后面处理 --> 
 | 
                {{  data.label}}</template 
 | 
              > 
 | 
            </el-tree-select> 
 | 
            <template 
 | 
              v-else-if="['select', 'selectList'].indexOf(item.type) != -1" 
 | 
            > 
 | 
              <el-select-v2 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                v-show="!item.hidden" 
 | 
                style="width: 100%" 
 | 
                :size="size" 
 | 
                v-if="item.data.length > select2Count" 
 | 
                v-model="formFields[item.field]" 
 | 
                filterable 
 | 
                :multiple="item.type == 'select' ? false : true" 
 | 
                :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
                :allow-create="item.autocomplete" 
 | 
                :options="item.data" 
 | 
                @change=" 
 | 
                  (val) => { 
 | 
                    item.onChange(val, item.data); 
 | 
                  } 
 | 
                " 
 | 
                clearable 
 | 
              > 
 | 
                <template #default="{ item }"> 
 | 
                  {{ item.label }} 
 | 
                </template> 
 | 
              </el-select-v2> 
 | 
              <el-select 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                v-show="!item.hidden" 
 | 
                style="width: 100%" 
 | 
                :size="size" 
 | 
                v-else-if="item.remote || item.url" 
 | 
                v-model="formFields[item.field]" 
 | 
                filterable 
 | 
                :multiple="item.type == 'select' ? false : true" 
 | 
                :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
                clearable 
 | 
                :remote-method=" 
 | 
                  (val) => { 
 | 
                    remoteSearch(item, formFields, val); 
 | 
                  } 
 | 
                " 
 | 
              > 
 | 
                <el-option 
 | 
                  v-for="item in item.data" 
 | 
                  :key="item.key" 
 | 
                  :label="item.value" 
 | 
                  :value="item.key" 
 | 
                > 
 | 
                </el-option> 
 | 
              </el-select> 
 | 
              <el-select 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                v-show="!item.hidden" 
 | 
                style="width: 100%" 
 | 
                :size="size" 
 | 
                v-else 
 | 
                v-model="formFields[item.field]" 
 | 
                filterable 
 | 
                :multiple="item.type == 'select' ? false : true" 
 | 
                :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
                :allow-create="item.autocomplete" 
 | 
                @change=" 
 | 
                  (val) => { 
 | 
                    item.onChange(val, item.data); 
 | 
                  } 
 | 
                " 
 | 
                clearable 
 | 
              > 
 | 
                <el-option 
 | 
                  v-show="!item.hidden" 
 | 
                  :disabled="item.disabled" 
 | 
                  v-for="item in item.data" 
 | 
                  :key="item.key" 
 | 
                  :label="item.value" 
 | 
                  :value="item.key" 
 | 
                > 
 | 
                </el-option> 
 | 
              </el-select> 
 | 
            </template> 
 | 
  
 | 
            <el-switch 
 | 
              v-show="!item.hidden" 
 | 
              v-else-if="item.type == 'switch'" 
 | 
              v-model="formFields[item.field]" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              active-color="#0f84ff" 
 | 
              @change="item.onChange" 
 | 
              inactive-color="rgb(194 194 194)" 
 | 
              :active-value=" 
 | 
                typeof formFields[item.field] == 'boolean' 
 | 
                  ? true 
 | 
                  : typeof formFields[item.field] == 'string' 
 | 
                  ? '1' 
 | 
                  : 1 
 | 
              " 
 | 
              :inactive-value=" 
 | 
                typeof formFields[item.field] == 'boolean' 
 | 
                  ? false 
 | 
                  : typeof formFields[item.field] == 'string' 
 | 
                  ? '0' 
 | 
                  : 0 
 | 
              " 
 | 
            > 
 | 
            </el-switch> 
 | 
  
 | 
            <el-radio-group 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-show="!item.hidden" 
 | 
              v-model="formFields[item.field]" 
 | 
              v-else-if="item.type == 'radio'" 
 | 
              @change="item.onChange" 
 | 
            > 
 | 
              <el-radio 
 | 
                v-for="kv in item.data" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                :key="kv.key" 
 | 
                :label="kv.key" 
 | 
                >{{ kv.value }}</el-radio 
 | 
              > 
 | 
            </el-radio-group> 
 | 
  
 | 
            <el-checkbox-group 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-show="!item.hidden" 
 | 
              v-model="formFields[item.field]" 
 | 
              v-else-if="item.type == 'checkbox'" 
 | 
              @change="item.onChange" 
 | 
            > 
 | 
              <el-checkbox 
 | 
                v-for="kv in item.data" 
 | 
                :key="kv.key" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                :label="kv.key" 
 | 
                >{{ kv.value }}</el-checkbox 
 | 
              > 
 | 
            </el-checkbox-group> 
 | 
            <div 
 | 
              class="v-date-range" 
 | 
              style="display: flex" 
 | 
              v-else-if=" 
 | 
                ['date', 'datetime'].indexOf(item.type) != -1 && item.range 
 | 
              " 
 | 
            > 
 | 
              <el-date-picker 
 | 
                :size="size" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                style="flex: 1; width: auto" 
 | 
                v-model="formFields[item.field][0]" 
 | 
                :type="item.type == 'date' ? 'date' : 'datetime'" 
 | 
                :disabledDate="(val) => getDateOptions(val, item)" 
 | 
                placeholder="开始时间" 
 | 
                @change=" 
 | 
                  (val) => { 
 | 
                    dateRangeChange(val, item); 
 | 
                  } 
 | 
                " 
 | 
                :value-format="getDateFormat(item)" 
 | 
              > 
 | 
              </el-date-picker> 
 | 
              <span style="margin: 0px 5px; font-size: 13px; color: #6f6b6b" 
 | 
                >至</span 
 | 
              > 
 | 
              <el-date-picker 
 | 
                :size="size" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                style="flex: 1; width: auto" 
 | 
                v-model="formFields[item.field][1]" 
 | 
                placeholder="结束时间" 
 | 
                :type="item.type == 'date' ? 'date' : 'datetime'" 
 | 
                :disabledDate="(val) => getDateOptions(val, item)" 
 | 
                @change=" 
 | 
                  (val) => { 
 | 
                    dateRangeChange(val, item); 
 | 
                  } 
 | 
                " 
 | 
                :value-format="getDateFormat(item)" 
 | 
              > 
 | 
              </el-date-picker> 
 | 
            </div> 
 | 
            <!-- v-show不添加根节点就会报错没有根点节 --> 
 | 
            <div 
 | 
              v-show="!item.hidden" 
 | 
              style="width: 100%" 
 | 
              v-else-if="['date', 'datetime', 'month'].indexOf(item.type) != -1" 
 | 
            > 
 | 
              <el-date-picker 
 | 
                :size="size" 
 | 
                clearable 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                style="width: 100%" 
 | 
                v-model="formFields[item.field]" 
 | 
                @change="item.onChange" 
 | 
                :type="item.type" 
 | 
                :placeholder=" 
 | 
                  item.placeholder ? item.placeholder : '请选择' + item.title 
 | 
                " 
 | 
                :disabledDate="(val) => getDateOptions(val, item)" 
 | 
                :value-format="getDateFormat(item)" 
 | 
              > 
 | 
              </el-date-picker> 
 | 
            </div> 
 | 
  
 | 
            <el-time-picker 
 | 
              :size="size" 
 | 
              v-else-if="item.type == 'time'" 
 | 
              v-model="formFields[item.field]" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              placeholder="请选择时间" 
 | 
              :value-format="item.format || 'HH:mm:ss'" 
 | 
              :format="item.format" 
 | 
              style="width: 100%" 
 | 
            > 
 | 
            </el-time-picker> 
 | 
  
 | 
            <el-scrollbar 
 | 
              style="border: 1px solid #c7d8db; border-radius: 5px" 
 | 
              :height="item.height || 150" 
 | 
              v-else-if=" 
 | 
                item.type == 'editor' && (item.readonly || item.disabled) 
 | 
              " 
 | 
            > 
 | 
              <div ref="editor" v-html="formFields[item.field]"></div> 
 | 
            </el-scrollbar> 
 | 
  
 | 
            <vol-wang-editor 
 | 
              ref="editor" 
 | 
              v-else-if="item.type == 'editor'" 
 | 
              :url="item.url || editor.uploadImgUrl" 
 | 
              :upload="item.upload || editor.upload" 
 | 
              v-model="formFields[item.field]" 
 | 
              :height="item.height || 350" 
 | 
            ></vol-wang-editor> 
 | 
  
 | 
            <vol-upload 
 | 
              v-show="!item.hidden" 
 | 
              v-else-if="isFile(item, formFields)" 
 | 
              :desc="item.desc" 
 | 
              :multiple="item.multiple" 
 | 
              :max-file="item.maxFile" 
 | 
              :max-size="item.maxSize" 
 | 
              :autoUpload="item.autoUpload" 
 | 
              :fileInfo="formFields[item.field]" 
 | 
              :url="item.url" 
 | 
              :img="item.type == 'img' || item.columnType == 'img'" 
 | 
              :excel="item.type == 'excel'" 
 | 
              :fileTypes="item.fileTypes ? item.fileTypes : []" 
 | 
              :upload-before="item.uploadBefore" 
 | 
              :upload-after="item.uploadAfter" 
 | 
              :append="item.multiple" 
 | 
              :on-change=" 
 | 
                (files) => { 
 | 
                  return fileOnChange(files, item); 
 | 
                } 
 | 
              " 
 | 
              :file-click="item.fileClick" 
 | 
              :remove-before="item.removeBefore" 
 | 
              :downLoad="item.downLoad ? true : false" 
 | 
            ></vol-upload> 
 | 
            <el-cascader 
 | 
              :size="size" 
 | 
              clearable 
 | 
              style="width: 100%; margin-top: -3px" 
 | 
              v-model="formFields[item.field]" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-else-if="item.type == 'cascader'" 
 | 
              :options="item.data" 
 | 
              :props="{ 
 | 
                checkStrictly: item.changeOnSelect || item.checkStrictly 
 | 
              }" 
 | 
              @change="item.onChange" 
 | 
            > 
 | 
            </el-cascader> 
 | 
            <el-rate 
 | 
              v-else-if="item.type == 'rate'" 
 | 
              @change=" 
 | 
                (val) => { 
 | 
                  item.onChange && item.onChange(val); 
 | 
                } 
 | 
              " 
 | 
              :max="item.max" 
 | 
              v-model="formFields[item.field]" 
 | 
            /> 
 | 
            <div 
 | 
              style="display: flex" 
 | 
              v-else-if="item.type == 'range' || item.range" 
 | 
            > 
 | 
              <el-input 
 | 
                :size="size" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                style="flex: 1" 
 | 
                v-model="formFields[item.field][0]" 
 | 
                clearable 
 | 
              /> 
 | 
              <span style="margin: 0 5px">-</span> 
 | 
              <el-input 
 | 
                :size="size" 
 | 
                :disabled="item.readonly || item.disabled" 
 | 
                style="flex: 1" 
 | 
                v-model="formFields[item.field][1]" 
 | 
                clearable 
 | 
              /> 
 | 
            </div> 
 | 
            <el-input 
 | 
              :size="size" 
 | 
              clearable 
 | 
              :ref="item.field" 
 | 
              :input-style="item.inputStyle" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-else-if="item.type == 'textarea'" 
 | 
              v-model="formFields[item.field]" 
 | 
              type="textarea" 
 | 
              :autosize="{ 
 | 
                minRows: item.minRows || 2, 
 | 
                maxRows: item.maxRows || 10 
 | 
              }" 
 | 
              :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
            /> 
 | 
            <el-input-number 
 | 
              :size="size" 
 | 
              style="width: 100%" 
 | 
              :ref="item.field" 
 | 
              :input-style="item.inputStyle" 
 | 
              v-else-if="item.type == 'number'" 
 | 
              v-model="formFields[item.field]" 
 | 
              :min="item.min" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              :max="item.max" 
 | 
              controls-position="right" 
 | 
            /> 
 | 
            <el-input 
 | 
              :size="size" 
 | 
              clearable 
 | 
              :input-style="item.inputStyle" 
 | 
              v-else-if="item.type == 'password'" 
 | 
              type="password" 
 | 
              v-model="formFields[item.field]" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-show="!item.hidden" 
 | 
              :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
            /> 
 | 
            <!-- 2021.11.18修复el-input没有默认enter事件时回车异常 --> 
 | 
            <el-input 
 | 
              :size="size" 
 | 
              clearable 
 | 
              :ref="item.field" 
 | 
              :input-style="item.inputStyle" 
 | 
              v-else-if="item.onKeyPress" 
 | 
              :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-show="!item.hidden" 
 | 
              v-model="formFields[item.field]" 
 | 
              @keypress=" 
 | 
                ($event) => { 
 | 
                  onKeyPress($event, item); 
 | 
                } 
 | 
              " 
 | 
              @change="item.onKeyPress" 
 | 
              @keyup.enter="item.onKeyPress" 
 | 
            ></el-input> 
 | 
            <el-input 
 | 
              :size="size" 
 | 
              clearable 
 | 
              v-else 
 | 
              :ref="item.field" 
 | 
              :input-style="item.inputStyle" 
 | 
              :placeholder="item.placeholder ? item.placeholder : item.title" 
 | 
              :disabled="item.readonly || item.disabled" 
 | 
              v-show="!item.hidden" 
 | 
              v-model="formFields[item.field]" 
 | 
            ></el-input> 
 | 
  
 | 
            <div class="form-extra" v-if="item.extra"> 
 | 
              <form-expand 
 | 
                v-if="item.extra.render" 
 | 
                :render="item.extra.render" 
 | 
              ></form-expand> 
 | 
              <a 
 | 
                v-else-if="item.extra.click" 
 | 
                :style="item.extra.style" 
 | 
                @click="item.extra.click(item, formFields[item.field])" 
 | 
              > 
 | 
                <i v-if="item.extra.icon" :class="item.extra.icon" /> 
 | 
                {{ item.extra.text }} 
 | 
              </a> 
 | 
              <a v-else :style="item.extra.style"> 
 | 
                <i v-if="item.extra.icon" :class="item.extra.icon" /> 
 | 
                {{ item.extra.text }} 
 | 
              </a> 
 | 
            </div> 
 | 
          </div> 
 | 
        </el-form-item> 
 | 
      </div> 
 | 
    </template> 
 | 
    <slot></slot> 
 | 
    <div style="width: 100%"> 
 | 
      <slot name="footer"></slot> 
 | 
    </div> 
 | 
  </el-form> 
 | 
</template> 
 | 
<script> 
 | 
const rule = { 
 | 
  change: [ 
 | 
    'checkbox', 
 | 
    'select', 
 | 
    'date', 
 | 
    'datetime', 
 | 
    'drop', 
 | 
    'radio', 
 | 
    'cascader' 
 | 
  ], // 2020.05.31增加级联类型 
 | 
  phone: /^[1][3,4,5,6,7,8,9][0-9]{9}$/, 
 | 
  decimal: /(^[\-0-9][0-9]*(.[0-9]+)?)$/, 
 | 
  number: /(^[\-0-9][0-9]*([0-9]+)?)$/ 
 | 
}; 
 | 
const inputTypeArr = ['text', 'string', 'mail', 'textarea', 'password']; 
 | 
const types = { 
 | 
  int: 'number', 
 | 
  byte: 'number', 
 | 
  decimal: 'number', // "float", 
 | 
  string: 'string', 
 | 
  bool: 'boolean', 
 | 
  date: 'datetime', 
 | 
  date: 'date', 
 | 
  mail: 'email' 
 | 
}; 
 | 
//表单验证注意:每次验证都必须执行callback,否则验证不执行回调方法 
 | 
const colPow = Math.pow(10, 3); 
 | 
import FormExpand from './VolForm/VolFormRender'; 
 | 
import { 
 | 
  defineAsyncComponent, 
 | 
  defineComponent, 
 | 
  ref, 
 | 
  reactive, 
 | 
  toRefs, 
 | 
  getCurrentInstance, 
 | 
  onMounted, 
 | 
  watch 
 | 
} from 'vue'; 
 | 
export default defineComponent({ 
 | 
  components: { 
 | 
    FormExpand, 
 | 
    'vol-upload': defineAsyncComponent(() => 
 | 
      import('@/components/basic/VolUpload.vue') 
 | 
    ), 
 | 
    'vol-wang-editor': defineAsyncComponent(() => 
 | 
      import('@/components/editor/VolWangEditor.vue') 
 | 
    ) 
 | 
  }, 
 | 
  props: { 
 | 
    loadKey: { 
 | 
      // 是否加载formRules字段配置的数据源 
 | 
      type: Boolean, 
 | 
      default: true 
 | 
    }, 
 | 
    width: { 
 | 
      // 表单宽度 
 | 
      type: Number, 
 | 
      default: 0 
 | 
    }, 
 | 
    labelWidth: { 
 | 
      // 表单左边label文字标签的宽度 
 | 
      type: Number, 
 | 
      default: 100 
 | 
    }, 
 | 
    formRules: { 
 | 
      // 表单配置规则,如字段类型,是否必填 
 | 
      type: Array, 
 | 
      default: [] 
 | 
    }, 
 | 
    formFields: { 
 | 
      type: Object, 
 | 
      default: () => { 
 | 
        return {}; 
 | 
      } 
 | 
    }, 
 | 
    editor: { 
 | 
      // 2021.01.16编辑器信息 {uploadImgUrl:"",upload:null//上传方法} 
 | 
      type: Object, 
 | 
      default: () => { 
 | 
        return {}; 
 | 
      } 
 | 
    }, 
 | 
    size: { 
 | 
      type: String, //large / default / small 
 | 
      default: 'large' 
 | 
    }, 
 | 
    select2Count: { 
 | 
      //超出数量显示select2组件 
 | 
      type: Number, 
 | 
      default: 500 
 | 
    } 
 | 
  }, 
 | 
  computed: { 
 | 
    rules() { 
 | 
      let ruleResult = {}; 
 | 
      this.formRules.forEach((option, xIndex) => { 
 | 
        option.forEach((item) => { 
 | 
          ruleResult[item.field] = [this.getRule(item, this.formFields)]; 
 | 
        }); 
 | 
      }); 
 | 
      if (this.$refs.volform) { 
 | 
        setTimeout(() => { 
 | 
          this.$refs.volform.clearValidate(); 
 | 
        }, 100); 
 | 
      } 
 | 
      return ruleResult; 
 | 
    } 
 | 
  }, 
 | 
  setup(props, context) { 
 | 
    const { appContext, proxy } = getCurrentInstance(); 
 | 
    const remoteCall = ref(true); 
 | 
    const span = ref(1); 
 | 
    const rangeFields = toRefs([]); 
 | 
    const volform = ref(null); 
 | 
    const numberFields = toRefs([]); 
 | 
    onMounted(() => {}); 
 | 
    const initFormRules = (init) => { 
 | 
      if (props.loadKey) { 
 | 
        initSource(); 
 | 
      } 
 | 
      props.formRules.forEach((row, xIndex) => { 
 | 
        if (row.length > span.value) span.value = row.length; 
 | 
        let _count = 0, 
 | 
          _size = 0; 
 | 
        row.forEach((x) => { 
 | 
          if (x.colSize > 0) { 
 | 
            _size = _size + x.colSize; 
 | 
            _count++; 
 | 
          } 
 | 
        }); 
 | 
        if (_count > 0 && row.length - _count > 0) { 
 | 
          let _cellSize = (12 - _size) / (row.length - _count); 
 | 
          row.forEach((x) => { 
 | 
            if (!x.colSize) { 
 | 
              x.colSize = _cellSize; 
 | 
            } 
 | 
          }); 
 | 
        } 
 | 
        row.forEach((item, yIndex) => { 
 | 
          if (item.type == 'number') { 
 | 
            numberFields.push(item.field); 
 | 
          } 
 | 
          // 目前只支持select单选远程搜索,remote远程从后台字典数据源进行搜索,url从指定的url搜索 
 | 
          if (item.remote || item.url) { 
 | 
            // item.remoteData = []; 
 | 
            item.loading = false; 
 | 
            item.point = { x: xIndex, y: yIndex }; 
 | 
          } 
 | 
          // 初始化上传文件信息 
 | 
          initUpload(item, init); 
 | 
          // 初始化数据源空对象 
 | 
          if (item.dataKey) { 
 | 
            // 下拉框都强制设置为字符串类型 
 | 
            item.columnType = 'string'; 
 | 
            if (!item.data) { 
 | 
              item.data = []; 
 | 
            } 
 | 
          } 
 | 
  
 | 
          if (item.range || item.type == 'range') { 
 | 
            if ( 
 | 
              !(props.formFields[item.field] instanceof Array) || 
 | 
              props.formFields[item.field].length != 2 
 | 
            ) { 
 | 
              props.formFields[item.field] = ['', '']; 
 | 
            } 
 | 
            rangeFields.push(item.field); 
 | 
          } 
 | 
        }); 
 | 
      }); 
 | 
    }; 
 | 
  
 | 
    const initSource = () => { 
 | 
      let keys = [], 
 | 
        binds = []; 
 | 
      // 初始化字典数据源 
 | 
      props.formRules.forEach((item) => { 
 | 
        item.forEach((x) => { 
 | 
          if (x.dataKey && (!x.data || x.data.length == 0) && !x.remote) { 
 | 
            x.data = []; 
 | 
            binds.push({ key: x.dataKey, data: x.data, type: x.type }); 
 | 
            if (keys.indexOf(x.dataKey) == -1) { 
 | 
              keys.push(x.dataKey); 
 | 
            } 
 | 
          } 
 | 
        }); 
 | 
      }); 
 | 
  
 | 
      if (keys.length == 0) return; 
 | 
      appContext.config.globalProperties.http 
 | 
        .post('/api/Sys_Dictionary/GetVueDictionary', keys) 
 | 
        .then((dic) => { 
 | 
          bindOptions(dic, binds); 
 | 
          proxy.$emit('dicInited', dic); 
 | 
        }); 
 | 
    }; 
 | 
    const bindOptions = (dic, binds) => { 
 | 
      dic.forEach((d) => { 
 | 
        if (d.data.length > props.select2Count) { 
 | 
          if ( 
 | 
            !binds.some((x) => { 
 | 
              return x.key == d.dicNo && x.type == 'cascader'; 
 | 
            }) 
 | 
          ) { 
 | 
            d.data.forEach((item) => { 
 | 
              item.label = item.value; 
 | 
              item.value = item.key; 
 | 
            }); 
 | 
          } 
 | 
        } 
 | 
        binds.forEach((x) => { 
 | 
          if (x.key != d.dicNo) return true; 
 | 
          // 如果有数据的则不查询 
 | 
          if (x.data.length > 0) return true; 
 | 
          //2022.03.13增加级联数据源自动转换 
 | 
          if (x.type == 'cascader' || x.type == 'treeSelect') { 
 | 
            let _data = JSON.parse(JSON.stringify(d.data)); 
 | 
            let cascaderArr = appContext.config.globalProperties.base.convertTree( 
 | 
              _data, 
 | 
              (node, data, isRoot) => { 
 | 
                if (!node.inited) { 
 | 
                  node.inited = true; 
 | 
                  node.label = node.value; 
 | 
                  node.value = node.key; 
 | 
                } 
 | 
              } 
 | 
            ); 
 | 
            props.formRules.forEach((option) => { 
 | 
              option.forEach((item) => { 
 | 
                if (item.dataKey == x.key) { 
 | 
                  item.orginData = x.data; 
 | 
                  item.data = cascaderArr; 
 | 
                } 
 | 
              }); 
 | 
            }); 
 | 
          } else if (d.data.length > 0 && !d.data[0].hasOwnProperty('key')) { 
 | 
            let source = d.data, 
 | 
              newSource = new Array(source.length); 
 | 
            for (let index = 0; index < source.length; index++) { 
 | 
              newSource[index] = { 
 | 
                key: source['key'] + '', 
 | 
                value: source['value'] 
 | 
              }; 
 | 
            } 
 | 
            x.data.push(...newSource); 
 | 
          } else { 
 | 
            x.data.push(...d.data); 
 | 
          } 
 | 
        }); 
 | 
      }); 
 | 
    }; 
 | 
  
 | 
    const initUpload = (item, init) => { 
 | 
      if (!init) return; 
 | 
      if ( 
 | 
        ['img', 'excel', 'file'].indexOf(item.type != -1) || 
 | 
        item.columnType == 'img' 
 | 
      ) { 
 | 
        // 只是没设置是否自动上传的,默认都是选择文件后自动上传 
 | 
        if (!item.hasOwnProperty('autoUpload')) { 
 | 
          item.autoUpload = true; 
 | 
        } 
 | 
        if (!item.hasOwnProperty('fileList')) { 
 | 
          item.fileList = true; 
 | 
        } 
 | 
        if (!item.hasOwnProperty('downLoad')) { 
 | 
          item.downLoad = true; 
 | 
        } 
 | 
        if (!item.removeBefore) { 
 | 
          item.removeBefore = (index, file, files) => { 
 | 
            return true; 
 | 
          }; 
 | 
        } 
 | 
        if (!item.fileClick) { 
 | 
          item.fileClick = (index, file, files) => { 
 | 
            return true; 
 | 
          }; 
 | 
        } 
 | 
        if (!item.onChange) { 
 | 
          item.onChange = (files) => { 
 | 
            return true; 
 | 
          }; 
 | 
        } 
 | 
        if (!item.uploadAfter) { 
 | 
          item.uploadAfter = (result, files) => { 
 | 
            return true; 
 | 
          }; 
 | 
        } 
 | 
        if (!item.uploadBefore) { 
 | 
          item.uploadBefore = (files) => { 
 | 
            return true; 
 | 
          }; 
 | 
        } 
 | 
      } 
 | 
    }; 
 | 
    const validate = (callback) => { 
 | 
      let result = true; 
 | 
      volform.value.validate((valid) => { 
 | 
        if (!valid) { 
 | 
          appContext.config.globalProperties.$message.error('数据验证未通过!'); 
 | 
          result = false; 
 | 
        } else if (typeof callback === 'function') { 
 | 
          try { 
 | 
            callback(valid); 
 | 
          } catch (error) { 
 | 
            let msg = `表单验证回调方法异常:${error.message}`; 
 | 
            appContext.config.globalProperties.$message.error(msg); 
 | 
            console.log(msg); 
 | 
          } 
 | 
        } 
 | 
      }); 
 | 
      return result; 
 | 
    }; 
 | 
  
 | 
    initFormRules(true); 
 | 
    return { 
 | 
      remoteCall, 
 | 
      span, 
 | 
      rangeFields, 
 | 
      numberFields, 
 | 
      validate, 
 | 
      volform 
 | 
      //  initFormRules, 
 | 
      // initSource 
 | 
    }; 
 | 
  }, 
 | 
  created() { 
 | 
    this.formRules.forEach((rules) => { 
 | 
      rules.forEach((option) => { 
 | 
        if (option.type == 'treeSelect' && option.multiple === undefined) { 
 | 
          option.multiple = true; 
 | 
        } 
 | 
      }); 
 | 
    }); 
 | 
  }, 
 | 
  
 | 
  data() { 
 | 
    return { 
 | 
      // remoteCall: true, 
 | 
      errorImg: 'this.src="' + require('@/assets/imgs/error-img.png') + '"' 
 | 
      // span: 1, 
 | 
      // rangeFields: [], 
 | 
    }; 
 | 
  }, 
 | 
  methods: { 
 | 
    getColWidth(item) { 
 | 
      //2021.08.30 增加动态计算表单宽度 
 | 
      let _span = 0; 
 | 
      this.formRules.forEach((row, xIndex) => { 
 | 
        //2022.05.06 追加表单中隐藏的元素不参与动态计算表单宽度 
 | 
        let rowLength = row.filter((item) => { 
 | 
          return !item.hidden; 
 | 
        }).length; 
 | 
        if (rowLength > _span) _span = rowLength; 
 | 
      }); 
 | 
      let rete = 
 | 
        Math.round(((item.colSize || 12 / _span) / 0.12) * colPow, 10.0) / 
 | 
        colPow; 
 | 
      if (item.colSize) return rete.toFixed(3); 
 | 
      return rete.toFixed(3); 
 | 
      // return (100 - rete).toFixed(3); 
 | 
    }, 
 | 
    previewImg(url) { 
 | 
      this.base.previewImg(url, this.http.ipAddress); 
 | 
    }, 
 | 
    getSrc(path) { 
 | 
      if (!path) return; 
 | 
      if (!this.base.isUrl(path) && path.indexOf('.') != -1) { 
 | 
        return this.http.ipAddress + path; 
 | 
      } 
 | 
      return path; 
 | 
    }, 
 | 
    // 是否为图片文件等格式并对字段的转换成数组:[{name:'1.jpg',path:'127.0.0.1/ff/1.jpg'}] 
 | 
    isFile(item, formFields) { 
 | 
      if ( 
 | 
        item.type == 'img' || 
 | 
        item.columnType == 'img' || 
 | 
        item.type == 'excel' || 
 | 
        item.type == 'file' 
 | 
      ) { 
 | 
        this.convertFileToArray(item, formFields); 
 | 
        return true; 
 | 
      } 
 | 
      return false; 
 | 
    }, 
 | 
    isReadonlyImgFile(item, formFields) { 
 | 
      if ((item.disabled || item.readonly) && this.isFile(item, formFields)) { 
 | 
        return true; 
 | 
      } 
 | 
      return false; 
 | 
    }, 
 | 
    convertFileToArray(item, formFields) { 
 | 
      if (!item.maxFile) { 
 | 
        item.maxFile = 1; // 默认只能上传一个文件,可以在onInit中设置 
 | 
      } 
 | 
  
 | 
      let fileInfo = formFields[item.field]; 
 | 
      if (fileInfo instanceof Array) { 
 | 
        return; 
 | 
      } 
 | 
      if (fileInfo === null || fileInfo === undefined) { 
 | 
        formFields[item.field] = []; 
 | 
        return; 
 | 
      } 
 | 
      // 将以逗号隔开的文件分割成数组127.0.0.1/aa/1.jpg,将127.0.0.1/aa/2.jpg 
 | 
      if (typeof fileInfo === 'string') { 
 | 
        if (fileInfo.trim() === '') { 
 | 
          formFields[item.field] = []; 
 | 
          return; 
 | 
        } 
 | 
        // 如果文件路径是字符串,则使用,拆分 
 | 
        fileInfo = fileInfo.replace(/\\/g, '/'); 
 | 
        let files = fileInfo.split(','); 
 | 
        formFields[item.field] = []; 
 | 
        for (let index = 0; index < files.length; index++) { 
 | 
          let file = files[index]; 
 | 
          let splitFile = file.split('/'); 
 | 
          formFields[item.field].push({ 
 | 
            name: splitFile.length > 0 ? splitFile[splitFile.length - 1] : file, 
 | 
            path: file // this.base.isUrl(file) ? file : this.http.ipAddress + file, 
 | 
          }); 
 | 
        } 
 | 
      } 
 | 
    }, 
 | 
    dowloadFile(file) { 
 | 
      this.base.dowloadFile( 
 | 
        file.path, 
 | 
        file.name, 
 | 
        { 
 | 
          Authorization: this.$store.getters.getToken() 
 | 
        }, 
 | 
        this.http.ipAddress 
 | 
      ); 
 | 
    }, 
 | 
    validatorPhone(ruleOption, value, callback) { 
 | 
      if (!ruleOption.required && !value && value != '0') { 
 | 
        return callback(); 
 | 
      } 
 | 
      if (!rule.phone.test((value || '').trim())) { 
 | 
        return callback(new Error('请输入正确的手机号')); 
 | 
      } 
 | 
      callback(); 
 | 
    }, 
 | 
    validatorPwd(ruleOption, value, callback) { 
 | 
      if (!ruleOption.required && !value && value != '0') { 
 | 
        return callback(); 
 | 
      } 
 | 
      if ((value + '').trim().length < 6) { 
 | 
        return callback(new Error('密码长度不能小于6位')); 
 | 
      } 
 | 
      callback(); 
 | 
    }, 
 | 
    convertArrayValue(data, val) { 
 | 
      // 2020.12.13增加表单多选只转换字典 
 | 
      // 编辑多选table显示 
 | 
      //2023.04.20修复只读为label时原数据被字典替换了的问题 
 | 
      let valArr = Array.isArray(val) 
 | 
        ? val.map((x) => { 
 | 
            return x; 
 | 
          }) 
 | 
        : val.split(','); 
 | 
      for (let index = 0; index < valArr.length; index++) { 
 | 
        var _item = data.find((x) => { 
 | 
          return x.key && x.key != '0' && x.key + '' == valArr[index] + ''; 
 | 
        }); 
 | 
        if (_item) { 
 | 
          valArr[index] = _item.value; 
 | 
        } 
 | 
      } 
 | 
      return valArr.join(','); 
 | 
    }, 
 | 
    getText(formFields, item) { 
 | 
      // 2019.10.24修复表单select组件为只读的属性时没有绑定数据源 
 | 
      let text = formFields[item.field]; 
 | 
      if (typeof text === 'function') return text(formFields); 
 | 
      if (text === 'null' || text === '' || text === null || text === undefined) 
 | 
        return '--'; 
 | 
      //2021.03.02增加只读时日期处理 
 | 
      if (item.type == 'date') { 
 | 
        return text.replace('T', ' ').split(' ')[0]; 
 | 
      } 
 | 
      //2021.03.31修复表单switch只读时没有转换值的问题 
 | 
      if (item.type == 'switch') { 
 | 
        return text ? '是' : '否'; 
 | 
      } 
 | 
      if (!item.data) return text; 
 | 
      if (item.type == 'selectList' || item.type == 'checkbox') { 
 | 
        return this.convertArrayValue(item.data, text); 
 | 
      } 
 | 
      var _item = item.data.find((x) => { 
 | 
        return x.key == text; 
 | 
      }); 
 | 
      return _item ? _item.value : text; 
 | 
    }, 
 | 
    onClear(item, formFields) { 
 | 
      // 远程select标签清空选项 
 | 
      item.data.splice(0); 
 | 
      // console.log(2); 
 | 
    }, 
 | 
    onChange(item, value) { 
 | 
      if (item.onChange && typeof item.onChange === 'function') { 
 | 
        item.onChange(value, item); 
 | 
      } 
 | 
    }, 
 | 
    onRemoteChange(item, value) { 
 | 
      // 第二次打开时,默认值成了undefined,待查viewgrid中重置代码 
 | 
      if (value == undefined && item.data.length > 0) { 
 | 
        this.formFields[item.field] = item.data[0].key; 
 | 
        //  console.log('undefined'); 
 | 
      } 
 | 
      this.remoteCall = false; 
 | 
      if (item.onChange && typeof item.onChange === 'function') { 
 | 
        item.onChange(value, item); 
 | 
      } 
 | 
    }, 
 | 
    getData(item) { 
 | 
      return item.data; 
 | 
    }, 
 | 
  
 | 
    // 远程搜索(打开弹出框时应该禁止搜索) 
 | 
    remoteSearch(item, formFields, val) { 
 | 
      if (!item.remote && !item.url) { 
 | 
        return; 
 | 
      } 
 | 
      if ( 
 | 
        val == '' || 
 | 
        (item.data.length == 1 && 
 | 
          (val == item.data[0].key || val == item.data[0].value)) 
 | 
      ) { 
 | 
        return; 
 | 
      } 
 | 
      // 弹出框或初始化表单时给data设置数组默认值2 
 | 
      // 2020.09.26修复远程搜索自定义url不起作用的问题 
 | 
      let url; 
 | 
      if (typeof item.url === 'function') { 
 | 
        url = item.url(val, item.dataKey, item); 
 | 
      } else { 
 | 
        url = 
 | 
          (item.url || '/api/Sys_Dictionary/GetSearchDictionary') + 
 | 
          '?dicNo=' + 
 | 
          item.dataKey + 
 | 
          '&value=' + 
 | 
          val; 
 | 
      } 
 | 
      this.http.post(url).then((dicData) => { 
 | 
        //this.$set(item, "loading", false); 
 | 
        item.loading = false; 
 | 
        item.data = dicData; 
 | 
        this.formRules[item.point.x].splice(item.point.y, 1, item); 
 | 
      }); 
 | 
    }, 
 | 
    getObject(date) { 
 | 
      if (typeof date === 'object') { 
 | 
        return date; 
 | 
      } 
 | 
      return new Date(date); 
 | 
    }, 
 | 
    reset(sourceObj) { 
 | 
      // 重置表单时,禁用远程查询 
 | 
      this.$refs['volform'].resetFields(); 
 | 
      if (this.rangeFields.length) { 
 | 
        this.rangeFields.forEach((key) => { 
 | 
          this.formFields[key].splice(0); 
 | 
          this.formFields[key] = [null, null]; 
 | 
        }); 
 | 
      } 
 | 
      if (!sourceObj) return; 
 | 
      for (const key in this.formFields) { 
 | 
        if (sourceObj.hasOwnProperty(key)) { 
 | 
          this.formFields[key] = sourceObj[key]; 
 | 
          if (this.numberFields.indexOf(key) != -1) { 
 | 
            this.formFields[key] = sourceObj[key] * 1 || 0; 
 | 
          } 
 | 
        } 
 | 
      } 
 | 
      //  this.remoteCall = true; 
 | 
    }, 
 | 
  
 | 
    fileOnChange(files, item) { 
 | 
      this.$refs.volform.clearValidate(item.field); 
 | 
      if (item.onChange) { 
 | 
        return item.onChange(files); 
 | 
      } 
 | 
      return true; 
 | 
    }, 
 | 
    isReadonly(item) { 
 | 
      return item.readonly || item.disabled; 
 | 
    }, 
 | 
    getRule(item, formFields) { 
 | 
      //2021.07.17增加只读表单不验证 
 | 
      //range与swtich暂时不做校验 
 | 
      if ( 
 | 
        // item.readonly || 
 | 
        // item.disabled || 
 | 
        item.type == 'switch' || 
 | 
        item.type == 'range' 
 | 
      ) 
 | 
        return { required: false }; 
 | 
      // 用户设置的自定义方法 
 | 
      if (item.validator && typeof item.validator === 'function') { 
 | 
        return { 
 | 
          validator: (rule, val, callback) => { 
 | 
            // 用户自定义的方法,如果返回了值,直接显示返回的值,验证不通过 
 | 
            let message = item.validator(rule, val); 
 | 
            if (message) return callback(new Error(message + '')); 
 | 
            return callback(); 
 | 
          }, 
 | 
          required: item.required, 
 | 
          trigger: rule.change.indexOf(item.type) != -1 ? 'change' : 'blur' 
 | 
        }; 
 | 
      } 
 | 
      if (['img', 'excel', 'file'].indexOf(item.type) != -1) { 
 | 
        return { 
 | 
          validator: (rule, val, callback) => { 
 | 
            //2021.09.05移除文件上传默认必填 
 | 
            if ( 
 | 
              item.required && 
 | 
              !this.isReadonly(item) && 
 | 
              (!val || !val.length) 
 | 
            ) { 
 | 
              return callback( 
 | 
                new Error(item.type == 'img' ? '请上传照片' : '请上传文件') 
 | 
              ); 
 | 
            } 
 | 
            return callback(); 
 | 
          }, 
 | 
          required: item.required, 
 | 
          trigger: 'change' 
 | 
        }; 
 | 
      } 
 | 
      // 设置数字的最大值民最小值 
 | 
      if ( 
 | 
        item.type == 'number' || 
 | 
        item.columnType == 'number' || 
 | 
        item.columnType == 'int' || 
 | 
        item.type == 'decimal' 
 | 
      ) { 
 | 
        // 如果是必填项的数字,设置一个默认最大与最值小 
 | 
        if (item.required && typeof item.min !== 'number') { 
 | 
          item.min = 0; //item.type == "decimal" ? 0.1 : 1; 
 | 
        } 
 | 
  
 | 
        return { 
 | 
          required: item.required, 
 | 
          message: item.title + '只能是数字', 
 | 
          title: item.title, 
 | 
          trigger: 'blur', 
 | 
          min: item.min, 
 | 
          max: item.max, 
 | 
          type: item.columnType || item.type, 
 | 
          validator: (ruleObj, value, callback) => { 
 | 
            if (!ruleObj.min && !ruleObj.max) { 
 | 
              if (ruleObj.required) { 
 | 
                if ((!value && value != '0') || !rule.decimal.test(value)) { 
 | 
                  return callback(new Error('只能是数字')); 
 | 
                } 
 | 
              } 
 | 
              return callback(); 
 | 
            } 
 | 
            if (this.isReadonly(item)) return callback(); 
 | 
            if (ruleObj.type == 'number') { 
 | 
              if (!rule.number.test(value)) { 
 | 
                ruleObj.message = ruleObj.title + '只能是整数'; 
 | 
                return callback(new Error(ruleObj.message)); 
 | 
              } 
 | 
            } else { 
 | 
              if (!rule.decimal.test(value)) { 
 | 
                ruleObj.message = ruleObj.title + '只能是数字'; 
 | 
                return callback(new Error(ruleObj.message)); 
 | 
              } 
 | 
            } 
 | 
            if ( 
 | 
              ruleObj.min !== undefined && 
 | 
              typeof ruleObj.min === 'number' && 
 | 
              value < ruleObj.min 
 | 
            ) { 
 | 
              ruleObj.message = ruleObj.title + '不能小于' + ruleObj.min; 
 | 
              return callback(new Error(ruleObj.message)); 
 | 
            } 
 | 
            if ( 
 | 
              ruleObj.max !== undefined && 
 | 
              typeof ruleObj.max === 'number' && 
 | 
              value > ruleObj.max 
 | 
            ) { 
 | 
              ruleObj.message = ruleObj.title + '不能大于' + ruleObj.max; 
 | 
              return callback(new Error(ruleObj.message)); 
 | 
            } 
 | 
            return callback(); 
 | 
          } 
 | 
        }; 
 | 
      } 
 | 
  
 | 
      // 手机、密码验证 
 | 
      if (item.type == 'password' || item.type == 'phone') { 
 | 
        return { 
 | 
          validator: 
 | 
            item.type == 'phone' ? this.validatorPhone : this.validatorPwd, 
 | 
          required: item.required, 
 | 
          trigger: 'blur' 
 | 
        }; 
 | 
      } 
 | 
  
 | 
      if (!item.required && item.type != 'mail') return { required: false }; 
 | 
  
 | 
      if (!item.hasOwnProperty('type')) item.type = 'text'; 
 | 
  
 | 
      if (inputTypeArr.indexOf(item.type) != -1) { 
 | 
        let message = 
 | 
          item.title + 
 | 
          (item.type == 'mail' ? '必须是一个邮箱地址' : '不能为空'); 
 | 
        let type = item.type == 'mail' ? 'email' : types[item.columnType]; 
 | 
        let _rule = { 
 | 
          required: true, 
 | 
          message: message, 
 | 
          trigger: 'blur', 
 | 
          type: type, 
 | 
          validator: (ruleObj, value, callback) => { 
 | 
            if ( 
 | 
              !this.isReadonly(item) && 
 | 
              (value === '' || value === undefined || value === null) 
 | 
            ) { 
 | 
              return callback(new Error(ruleObj.message)); 
 | 
            } 
 | 
            return callback(); 
 | 
          } 
 | 
        }; 
 | 
        if (item.type == 'mail') { 
 | 
          _rule.validator = undefined; 
 | 
          return _rule; 
 | 
        } 
 | 
        if (item.min) { 
 | 
          _rule.min = item.min; 
 | 
          _rule.message = item.title + '至少' + item.min + '个字符!'; 
 | 
        } 
 | 
        if (item.max) { 
 | 
          return [ 
 | 
            _rule, 
 | 
            { 
 | 
              max: item.max, 
 | 
              required: true, 
 | 
              message: item.title + '最多' + item.max + '个字符!', 
 | 
              trigger: 'blur' 
 | 
            } 
 | 
          ]; 
 | 
        } 
 | 
        return _rule; 
 | 
      } 
 | 
  
 | 
      if (item.type == 'radio') { 
 | 
        return { 
 | 
          required: item.required, 
 | 
          message: '请选择' + item.title, 
 | 
          trigger: 'change', 
 | 
          type: 'string' 
 | 
        }; 
 | 
      } 
 | 
      if ( 
 | 
        item.type == 'date' || 
 | 
        item.type == 'datetime' || 
 | 
        item.type == 'month' || 
 | 
        item.type == 'time' 
 | 
      ) { 
 | 
        return { 
 | 
          required: true, 
 | 
          message: '请选择' + item.title, 
 | 
          trigger: 'change', 
 | 
          type: item.range ? 'array' : 'string', 
 | 
          validator: (rule, val, callback) => { 
 | 
            if (this.isReadonly(item)) return callback(); 
 | 
            // 用户自定义的方法,如果返回了值,直接显示返回的值,验证不通过 
 | 
            if (!val || (item.range && !val.length)) { 
 | 
              return callback(new Error('请选择日期')); 
 | 
            } 
 | 
            return callback(); 
 | 
          } 
 | 
        }; 
 | 
      } 
 | 
  
 | 
      if (item.type == 'cascader') { 
 | 
        return { 
 | 
          type: 'array', 
 | 
          required: true, 
 | 
          min: item.min || 1, 
 | 
          // message: "请选择" + item.title, 
 | 
          trigger: 'change', 
 | 
          validator: (rule, val, callback) => { 
 | 
            if (this.isReadonly(item)) return callback(); 
 | 
            // 用户自定义的方法,如果返回了值,直接显示返回的值,验证不通过 
 | 
            let _arr = this.formFields[item.field]; 
 | 
            if (!_arr || !_arr.length) { 
 | 
              return callback(new Error('请选择' + item.title)); 
 | 
            } 
 | 
            return callback(); 
 | 
          } 
 | 
        }; 
 | 
      } 
 | 
  
 | 
      if ( 
 | 
        ['select', 'selectList', 'checkbox', 'cascader', 'treeSelect'].indexOf( 
 | 
          item.type 
 | 
        ) != -1 
 | 
      ) { 
 | 
        let _rule = { 
 | 
          type: item.type == 'select' ? 'string' : 'array', 
 | 
          required: true, 
 | 
          min: item.min || 1, 
 | 
          message: '请选择' + item.title, 
 | 
          trigger: 'change', 
 | 
          validator: (rule, value, callback) => { 
 | 
            if (this.isReadonly(item)) return callback(); 
 | 
            //2021.11.27修复多选没有提示的问题 
 | 
            if (value == undefined || value === '') { 
 | 
              return callback(new Error(rule.message)); 
 | 
            } else if ( 
 | 
              (item.type == 'checkbox' || 
 | 
                item.type == 'selectList' || 
 | 
                item.type == 'treeSelect') && 
 | 
              (!(value instanceof Array) || !value.length) 
 | 
            ) { 
 | 
              return callback(new Error(rule.message)); 
 | 
            } 
 | 
            return callback(); 
 | 
          } 
 | 
        }; 
 | 
  
 | 
        if (_rule.max) { 
 | 
          _rule.nax = item.max; 
 | 
          _rule.message = '最多只能选择' + item.max + '项'; 
 | 
        } 
 | 
        return _rule; 
 | 
      } 
 | 
      return {}; 
 | 
    }, 
 | 
    compareDate(date1, date2) { 
 | 
      if (!date2) { 
 | 
        return true; 
 | 
      } 
 | 
      return ( 
 | 
        date1.valueOf() < 
 | 
        (typeof date2 == 'number' ? date2 : new Date(date2).valueOf()) 
 | 
      ); 
 | 
    }, 
 | 
    getDateOptions(date, item) { 
 | 
      //2021.07.17设置时间可选范围 
 | 
      if ((!item.min && !item.max) || !date) { 
 | 
        return false; 
 | 
      } 
 | 
      if (item.min && item.min.indexOf(' ') == -1) { 
 | 
        //不设置时分秒,后面会自动加上 08:00 
 | 
        item.min = item.min + ' 00:00:000'; 
 | 
      } 
 | 
      return ( 
 | 
        this.compareDate(date, item.min) || !this.compareDate(date, item.max) 
 | 
      ); 
 | 
    }, 
 | 
    getDateFormat(item) { 
 | 
      if (item.type == 'month') { 
 | 
        return 'YYYY-MM'; 
 | 
      } 
 | 
      // if (item.type=='time') { 
 | 
      //     return 'HH:mm:ss' 
 | 
      // } 
 | 
      //见https://day.js.org/docs/zh-CN/display/format 
 | 
      return item.type == 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'; 
 | 
    }, 
 | 
    dateRangeChange(val, item) { 
 | 
      if (!val) { 
 | 
        this.$emit('update:formFields'); 
 | 
        return; 
 | 
      } 
 | 
      item.onChange && item.onChange(val); 
 | 
    }, 
 | 
    onKeyPress($event, item) { 
 | 
      if ($event.keyCode == 13) { 
 | 
        return; 
 | 
      } 
 | 
      item.onKeyPress($event); 
 | 
    }, 
 | 
    filterMethod(value, data) { 
 | 
      return data.label.includes(value); 
 | 
    }, 
 | 
    getNode( label,node, data){ 
 | 
      console.log(label) 
 | 
    } 
 | 
  } 
 | 
}); 
 | 
</script> 
 | 
<style lang="less" scoped> 
 | 
.el-form-item { 
 | 
  margin-right: 0; 
 | 
} 
 | 
.el-form-item { 
 | 
  .form-imgs { 
 | 
    img { 
 | 
      float: left; 
 | 
      cursor: pointer; 
 | 
      object-fit: cover; 
 | 
      margin: 0 10px 10px 0; 
 | 
      width: 65px; 
 | 
      height: 65px; 
 | 
      border: 1px solid #c7c7c7; 
 | 
      overflow: hidden; 
 | 
      border-radius: 5px; 
 | 
      box-sizing: content-box; 
 | 
    } 
 | 
  } 
 | 
} 
 | 
.el-form-item ::v-deep(.el-form-item__label) { 
 | 
  padding: 0 0px 0 4px; 
 | 
  overflow: hidden; 
 | 
  text-overflow: ellipsis; 
 | 
  white-space: nowrap; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-range-separator) { 
 | 
  text-align: center; 
 | 
  width: 13px; 
 | 
  padding: 0px 1px; 
 | 
  font-size: 12px; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-range__close-icon) { 
 | 
  margin-right: -10px; 
 | 
} 
 | 
.form-item-extra { 
 | 
  > *:first-child { 
 | 
    flex: 1; 
 | 
  } 
 | 
  display: flex; 
 | 
  .form-extra { 
 | 
    padding-left: 7px; 
 | 
    line-height: 36px; 
 | 
  } 
 | 
} 
 | 
.vol-form-item { 
 | 
  width: 100%; 
 | 
} 
 | 
.vol-form-item ::v-deep(.el-form-item__content) { 
 | 
  display: unset !important; 
 | 
} 
 | 
.vol-form-item ::v-deep(.el-input--large .el-input__inner) { 
 | 
  height: 34px !important; 
 | 
} 
 | 
.vol-form-item ::v-deep(.el-input-number--large .el-input-number__increase) { 
 | 
  border-top: 1px solid #d4d4d4; 
 | 
} 
 | 
.vol-form-item ::v-deep(.el-input-number--large .el-input-number__decrease) { 
 | 
  border-bottom: 1px solid #d4d4d4; 
 | 
} 
 | 
.vol-form-item ::v-deep(.el-input--large.el-date-editor) { 
 | 
  height: 36px; 
 | 
} 
 | 
.v-date-range ::v-deep(.el-input__prefix) { 
 | 
  display: none; 
 | 
} 
 | 
.v-date-range ::v-deep(.el-input__inner) { 
 | 
  padding: 0; 
 | 
} 
 | 
  
 | 
.el-form-item ::v-deep(.el-checkbox) { 
 | 
  margin-right: 8px; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-checkbox .el-checkbox__label) { 
 | 
  padding-left: 5px; 
 | 
} 
 | 
.el-form-item ::v-deep(textarea) { 
 | 
  font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 
 | 
    'Microsoft YaHei', '微软雅黑', Arial, sans-serif !important; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-select .el-select__tags > span) { 
 | 
  display: flex; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-select-v2__combobox-input) { 
 | 
  height: 30px; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-select__tags) { 
 | 
  overflow: hidden; 
 | 
  height: 30px; 
 | 
} 
 | 
.el-form-item ::v-deep(.el-select-tags-wrapper) { 
 | 
  position: absolute; 
 | 
} 
 | 
  
 | 
.el-form-item { 
 | 
  vertical-align: top !important; 
 | 
} 
 | 
.form-file-list { 
 | 
  a { 
 | 
    color: #3ea9ff; 
 | 
  } 
 | 
  a:hover { 
 | 
    cursor: pointer; 
 | 
    color: #0281e7; 
 | 
  } 
 | 
} 
 | 
</style> 
 |