<template>  
 | 
  <div>  
 | 
    <av-page-header title="高级表单">  
 | 
      <div slot="breadcrumb">  
 | 
        <a-breadcrumb>  
 | 
          <a-breadcrumb-item>  
 | 
            <a >首页</a>  
 | 
          </a-breadcrumb-item>  
 | 
          <a-breadcrumb-item>  
 | 
            <a >表单页</a>  
 | 
          </a-breadcrumb-item>  
 | 
          <a-breadcrumb-item>高级表单</a-breadcrumb-item>  
 | 
        </a-breadcrumb>  
 | 
      </div>  
 | 
      <div slot="content">  
 | 
        高级表单常见于一次性输入和提交大批量数据的场景。  
 | 
      </div>  
 | 
    </av-page-header>  
 | 
    <a-form layout="vertical" hideRequiredMark :autoFormCreate="handlerFormCreate">  
 | 
      <a-card title="仓库管理" class="card" :bordered="false">  
 | 
            <a-row :gutter="16">  
 | 
              <a-col :lg="6" :md="12" :sm="24">  
 | 
                <a-form-item label="仓库名"  
 | 
                  fieldDecoratorId="name"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入仓库名称' }]}"  
 | 
                >  
 | 
                  <a-input placeholder="请输入仓库名称" />  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
              <a-col :xl="{ span: 6, offset: 2 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="24">  
 | 
                <a-form-item label="仓库域名"  
 | 
                  fieldDecoratorId="url"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择' }]}"  
 | 
                >  
 | 
                  <a-input  
 | 
                      :style="{ width: '100%' }"  
 | 
                      addonBefore="http://"  
 | 
                      addonAfter=".com"  
 | 
                      placeholder="请输入"  
 | 
                    />  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
              <a-col :xl="{ span: 8, offset: 2 }" :lg="{ span: 10 }" :md="{ span: 24 }" :sm="24">  
 | 
                <a-form-item label="仓库管理员"  
 | 
                  fieldDecoratorId="owner"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择管理员' }]}"  
 | 
                >  
 | 
                  <a-select placeholder="请选择管理员">  
 | 
                      <a-select-option value="xiao">付晓晓</a-select-option>  
 | 
                      <a-select-option value="mao">周毛毛</a-select-option>  
 | 
                  </a-select>  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
            </a-row>  
 | 
            <a-row :gutter="16">  
 | 
              <a-col :lg="6" :md="12" :sm="24">  
 | 
                <a-form-item label='审批人'  
 | 
                  fieldDecoratorId="approver"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择审批员' }]}"  
 | 
                >  
 | 
                  <a-select placeholder="请选择审批员">  
 | 
                      <a-select-option value="xiao">付晓晓</a-select-option>  
 | 
                      <a-select-option value="mao">周毛毛</a-select-option>  
 | 
                    </a-select>  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
              <a-col :xl="{ span: 6, offset: 2 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="24">  
 | 
                <a-form-item label="生效日期"  
 | 
                  fieldDecoratorId="dateRange"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择生效日期' }]}"  
 | 
                >  
 | 
                  <a-range-picker :placeholder="['开始日期', '结束日期']" :style="{ width: '100%' }" />  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
              <a-col :xl="{ span: 8, offset: 2 }" :lg="{ span: 10 }" :md="{ span: 24 }" :sm="24">  
 | 
                <a-form-item label='仓库类型'  
 | 
                  fieldDecoratorId="type"  
 | 
                  :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择仓库类型' }]}"  
 | 
                >  
 | 
                  <a-select placeholder="请选择仓库类型">  
 | 
                      <a-select-option value="private">私密</a-select-option>  
 | 
                      <a-select-option value="public">公开</a-select-option>  
 | 
                    </a-select>  
 | 
                </a-form-item>  
 | 
              </a-col>  
 | 
            </a-row>  
 | 
        </a-card>  
 | 
    <a-card title="任务管理" class="card" :bordered="false">  
 | 
      <a-row :gutter="16">  
 | 
          <a-col :lg="6" :md="12" :sm="24">  
 | 
            <a-form-item label="任务名"  
 | 
              fieldDecoratorId="name2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入' }]}"  
 | 
            >  
 | 
              <a-input placeholder="请输入" />  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
          <a-col :xl="{ span: 6, offset: 2 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="24">  
 | 
            <a-form-item label="任务描述"  
 | 
              fieldDecoratorId="url2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入' }]}"  
 | 
            >  
 | 
              <a-input placeholder="请输入" />  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
          <a-col :xl="{ span: 8, offset: 2 }" :lg="{ span: 10 }" :md="{ span: 24 }" :sm="24">  
 | 
            <a-form-item label="管理员"  
 | 
              fieldDecoratorId="owner2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择管理员' }]}"  
 | 
            >  
 | 
              <a-select placeholder="请选择管理员">  
 | 
                  <a-select-option value="xiao">付晓晓</a-select-option>  
 | 
                  <a-select-option value="mao">周毛毛</a-select-option>  
 | 
                </a-select>  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
        </a-row>  
 | 
        <a-row :gutter="16">  
 | 
          <a-col :lg="6" :md="12" :sm="24">  
 | 
            <a-form-item label="审批员"  
 | 
              fieldDecoratorId="approver2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择审批员' }]}"  
 | 
            >  
 | 
              <a-select placeholder="请选择审批员">  
 | 
                  <a-select-option value="xiao">付晓晓</a-select-option>  
 | 
                  <a-select-option value="mao">周毛毛</a-select-option>  
 | 
                </a-select>  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
          <a-col :xl="{ span: 6, offset: 2 }" :lg="{ span: 8 }" :md="{ span: 12 }" :sm="24">  
 | 
            <a-form-item label="提醒时间"  
 | 
              fieldDecoratorId="dateRange2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入' }]}"  
 | 
            >  
 | 
              <a-time-picker  
 | 
                  placeholder="提醒时间"  
 | 
                  :style="{ width: '100%' }"  
 | 
                  :getPopupContainer="trigger => trigger.parentNode"  
 | 
                />  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
          <a-col :xl="{ span: 8, offset: 2 }" :lg="{ span: 10 }" :md="{ span: 24 }" :sm="24">  
 | 
            <a-form-item label="仓库类型"  
 | 
              fieldDecoratorId="type2"  
 | 
              :fieldDecoratorOptions="{rules: [{ required: true, message: '请选择仓库类型' }]}"  
 | 
            >  
 | 
              <a-select placeholder="请选择仓库类型">  
 | 
                  <a-select-option value="private">私密</a-select-option>  
 | 
                  <a-select-option value="public">公开</a-select-option>  
 | 
                </a-select>  
 | 
            </a-form-item>  
 | 
          </a-col>  
 | 
        </a-row>  
 | 
    </a-card>  
 | 
  
 | 
    <a-card title="成员管理" :bordered="false">  
 | 
      <table-form :value="tableData"></table-form>  
 | 
    </a-card>  
 | 
    <av-footer-toolbar>  
 | 
      <div slot="children">  
 | 
  
 | 
      <span class="errorIcon" v-if="errorCount>0">  
 | 
        <a-popover title="表单校验信息"  
 | 
          overlayClassName="errorPopover"  
 | 
          trigger="click"  
 | 
        >  
 | 
          <template slot="content">  
 | 
            <li v-for="(item,index) in errors" :key="index" class="errorListItem" @click="scrollToField(item.key)">  
 | 
              <a-icon type="cross-circle-o" class="errorIcon" />  
 | 
              <div class="errorMessage">{{item.msg}}</div>  
 | 
              <div class="errorField">{{item.label}}</div>  
 | 
            </li>  
 | 
          </template>  
 | 
  
 | 
          <a-icon type="exclamation-circle" />  
 | 
          {{errorCount}}  
 | 
        </a-popover>  
 | 
      </span>  
 | 
        <a-button type="primary" slot="children"  
 | 
          @click="validate"  
 | 
          >  
 | 
          提交  
 | 
        </a-button>  
 | 
      </div>  
 | 
    </av-footer-toolbar>  
 | 
    </a-form>  
 | 
  </div>  
 | 
</template>  
 | 
  
 | 
<style lang="less" scoped>  
 | 
.card {  
 | 
  margin-bottom: 24px;  
 | 
}  
 | 
  
 | 
.errorIcon {  
 | 
  cursor: pointer;  
 | 
  color: #f5222d;  
 | 
  margin-right: 24px;  
 | 
  i {  
 | 
    margin-right: 4px;  
 | 
  }  
 | 
}  
 | 
  
 | 
.errorListItem {  
 | 
  list-style: none;  
 | 
  border-bottom: 1px solid #e8e8e8;  
 | 
  padding: 8px 16px;  
 | 
  cursor: pointer;  
 | 
  transition: all 0.3s;  
 | 
  &:hover {  
 | 
    background: rgba(24, 144, 255, 0.1);  
 | 
  }  
 | 
  &:last-child {  
 | 
    border: 0;  
 | 
  }  
 | 
  .errorIcon {  
 | 
    color: #f5222d;  
 | 
    float: left;  
 | 
    margin-top: 4px;  
 | 
    margin-right: 12px;  
 | 
    padding-bottom: 22px;  
 | 
  }  
 | 
  .errorField {  
 | 
    font-size: 12px;  
 | 
    color: rgba(0, 0, 0, 0.45); //@text-color-secondary;  
 | 
    margin-top: 2px;  
 | 
  }  
 | 
}  
 | 
</style>  
 | 
  
 | 
<style lang="less">  
 | 
.errorPopover {  
 | 
  .ant-popover-inner-content {  
 | 
    padding: 0;  
 | 
    max-height: 290px;  
 | 
    overflow: auto;  
 | 
    min-width: 256px;  
 | 
  }  
 | 
}  
 | 
</style>  
 | 
  
 | 
<script  lang="ts">  
 | 
import { Component, Prop, Vue } from 'vue-property-decorator';  
 | 
import { State, Mutation, namespace } from 'vuex-class';  
 | 
  
 | 
import * as _ from 'lodash';  
 | 
  
 | 
import TableForm from './components/TableForm.vue';  
 | 
  
 | 
const fieldLabels: any = {  
 | 
  name: '仓库名',  
 | 
  url: '仓库域名',  
 | 
  owner: '仓库管理员',  
 | 
  approver: '审批人',  
 | 
  dateRange: '生效日期',  
 | 
  type: '仓库类型',  
 | 
  name2: '任务名',  
 | 
  url2: '任务描述',  
 | 
  owner2: '执行人',  
 | 
  approver2: '责任人',  
 | 
  dateRange2: '生效日期',  
 | 
  type2: '任务类型',  
 | 
};  
 | 
  
 | 
@Component({  
 | 
  components: {  
 | 
    TableForm,  
 | 
  },  
 | 
})  
 | 
export default class AdvancedForm extends Vue {  
 | 
  private tableData: any[] = [  
 | 
    {  
 | 
      key: '1',  
 | 
      workId: '00001',  
 | 
      name: 'John Brown',  
 | 
      department: 'New York No. 1 Lake Park',  
 | 
    },  
 | 
    {  
 | 
      key: '2',  
 | 
      workId: '00002',  
 | 
      name: 'Jim Green',  
 | 
      department: 'London No. 1 Lake Park',  
 | 
    },  
 | 
    {  
 | 
      key: '3',  
 | 
      workId: '00003',  
 | 
      name: 'Joe Black',  
 | 
      department: 'Sidney No. 1 Lake Park',  
 | 
    },  
 | 
  ];  
 | 
  
 | 
  private form: any = null;  
 | 
  
 | 
  private errorCount: number = 0;  
 | 
  private errors: any[] = [];  
 | 
  
 | 
  constructor() {  
 | 
    super();  
 | 
  }  
 | 
  
 | 
  private handlerFormCreate(form: any) {  
 | 
    this.form = form;  
 | 
  }  
 | 
  
 | 
  private validate(e: any) {  
 | 
    e.preventDefault();  
 | 
  
 | 
    this.form.validateFieldsAndScroll((err: any, values: any) => {  
 | 
      if (err) {  
 | 
        this.formError();  
 | 
      }  
 | 
    });  
 | 
  }  
 | 
  
 | 
  private formError() {  
 | 
    if (this.form == null) {  
 | 
      return;  
 | 
    }  
 | 
    const errors = this.form.getFieldsError();  
 | 
    this.errors = Object.keys(errors)  
 | 
      .map((key: any) => {  
 | 
        if (!errors[key]) {  
 | 
          return;  
 | 
        }  
 | 
        const message = errors[key][0];  
 | 
        const label = fieldLabels[key];  
 | 
        return {  
 | 
          [key]: key,  
 | 
          msg: message,  
 | 
          [label]: label,  
 | 
        };  
 | 
      })  
 | 
      .filter((item: any) => item != null);  
 | 
  
 | 
    const errorCount = Object.keys(errors).filter((key: any) => errors[key])  
 | 
      .length;  
 | 
    this.errorCount = errorCount;  
 | 
  }  
 | 
  
 | 
  private scrollToField(fieldKey: any) {  
 | 
    const labelNode = document.querySelector(`label[for='${fieldKey}']`);  
 | 
    if (labelNode) {  
 | 
      labelNode.scrollIntoView(true);  
 | 
    }  
 | 
  }  
 | 
}  
 | 
</script> 
 |