diff --git a/src/views/haomo/components/forms/HmComplexForm.vue b/src/views/haomo/components/forms/HmComplexForm.vue
index 696b7fa4739eee525a35e26619afc5ecec95f45e..0f51a3f3d8147d910be1a41136b8a78f5a3225af 100644
--- a/src/views/haomo/components/forms/HmComplexForm.vue
+++ b/src/views/haomo/components/forms/HmComplexForm.vue
@@ -9,61 +9,65 @@
         <div>
           <!--表单部分-->
           <el-form ref="form"
+                   :label-position="formStyle && formStyle.formOptions && formStyle.formOptions.labelPosition || 'right'"
                    element-loading-text="加载中"
+                   :label-width="formStyle && formStyle.formOptions && formStyle.formOptions.labelWidth || '170px'"
                    :model="formModel"
                    :rules="rules"
-                   label-width="200px"
-                   style="width:80%;margin:0 auto">
+                   :style=" formStyle && formStyle.formOptions && formStyle.formOptions.style || {width:'80%',margin:'0 auto'}">
             <el-form-item v-for="column in showUserColumns"
+                          v-show="!column.hide"
                           :key="column.id"
                           :label="column.name"
+                          :rules="column.rule?column.rule:null"
                           :prop="column.codeCamel">
               <!--el-input<el-input v-if="column.codeCamel==='password'" type="password"
                         v-model="formModel[column.codeCamel]"></el-input>-->
-
-              <!-- 1 普通input -->
-              <el-input v-if="column.widgetType === 1"
-                        v-model="formModel[column.codeCamel]"
-                        :disabled="column.disabled"
-                        @change="useralidate(formModel[column.codeCamel])"></el-input>
               <!-- 2 日期选择 -->
-              <el-date-picker v-else-if="column.widgetType === 6 || column.type === 'datetime' || column.type === 'date'"
+              <!-- -->
+              <el-date-picker v-if="column.widgetType === 6 || column.type === 'datetime' || column.type === 'date'"
                               v-model="formModel[column.codeCamel]"
+                              :style="formStyle && formStyle.datePicker && formStyle.datePicker.style || {width: '65%'}"
                               :type="column.dateType || 'date'"
                               align="right" :disabled="column.disabled"
-                              @change="logTimeChange"
+                              @change="column.change && column.change($event)"
                               :value-format="column.dateFormate || 'yyyy-MM-dd'"
                               :picker-options="pickerOptions">
               </el-date-picker>
               <!-- 3 下拉框 -->
               <el-select v-else-if="column.widgetType === 2"
                          v-model="formModel[column.codeCamel]"
-                         @change="selectChange"
+                         @change="column.change && column.change($event)"
+                         :style="formStyle && formStyle.select && formStyle.select.style || {width: '65%'}"
                          :multiple="column.multiple"
                          :disabled="column.disabled"
+                         style="width: 50%"
                          clearable>
-                <el-option v-for="item in column.options"
-                           :key="item.value"
+                <el-option v-for="(item,key) in column.options"
+                           :key="key"
                            :label="item.label"
                            :value="item.value">
                 </el-option>
               </el-select>
               <!-- 4 文本域 -->
               <el-input v-else-if="column.widgetType === 4"
+                        :style="formStyle && formStyle.textarea && formStyle.textarea.style || {width: '65%'}"
                         v-model="formModel[column.codeCamel]"
                         type="textarea" :disabled="column.disabled"
-                        :autosize="{ minRows: 2, maxRows: 5}"
-                        :rows="2">
+                        :resize="formStyle && formStyle.textarea && formStyle.textarea.resize || 'vertical'"
+                        :autosize="formStyle && formStyle.textarea && formStyle.textarea.autosize || { minRows: 4, maxRows: 6}"
+                        :rows="formStyle && formStyle.textarea && formStyle.textarea.rows || 4" @change="column.change && column.change($event)">
               </el-input>
               <!-- 5 复选框 -->
               <el-checkbox v-else-if="column.widgetType === 3 && !column.options"
                            v-model="formModel[column.codeCamel]"
                            :disabled="column.disabled"
+                           @change="column.change && column.change($event)"
                            true-label="1" false-label="0"></el-checkbox>
               <el-checkbox-group v-else-if="column.widgetType === 3 && column.options"
                                  v-model="formModel[column.codeCamel]"
                                  :disabled="column.disabled"
-                                  @change="checkboxsChange">
+                                 @change="column.change && column.change($event)">
                 <el-checkbox v-for="option in column.options"
                              :label="option" :key="option">{{option}}</el-checkbox>
               </el-checkbox-group>
@@ -71,28 +75,39 @@
               <quill-editor v-else-if="column.widgetType === 5"
                             ref="textEditor" :disabled="column.disabled"
                             v-model="formModel[column.codeCamel]"
+                            :style="formStyle && formStyle.quillEdito && formStyle.quillEdito.style || {width:'65%'}"
                             :options="editorOption"
                             @blur="onEditorBlur($event)"
                             @focus="onEditorFocus($event)"
+                            @change="column.change && column.change($event)"
                             @ready="onEditorReady($event)">
               </quill-editor>
               <!-- 7 单选框 -->
               <el-radio-group v-else-if="column.widgetType === 7"
                               :disabled="column.disabled"
+                              @change="column.change && column.change($event)"
                               v-model="formModel[column.codeCamel]">
-                <el-radio v-for="(option,key) in column.options"
-                          :key="key" :label="key">{{option}}</el-radio>
+                <el-radio v-for="option in column.options"
+                          :key="option.label" :label="option.label">{{option.value}}</el-radio>
               </el-radio-group>
               <!-- 8 文件 -->
               <el-upload v-else-if="column.widgetType === 8"
-                class="upload-demo"
-                action="/api/upload"
-                :on-remove="handleRemove"
-                multiple
-                :on-exceed="handleExceed">
+                         name="picture"
+                         :action=" column.url || '/api/upload'"
+                         :on-remove="handleRemove"
+                         :file-list="fileList"
+                         :multiple="column.multiple"
+                         ref="upload"
+                         :on-success="uploadSuccess">
                 <el-button slot="trigger" size="small" type="primary"
                            :disabled="column.disabled">选取文件</el-button>
               </el-upload>
+              <!-- 1 普通input -->
+              <el-input v-else
+                        :style="formStyle && formStyle.input && formStyle.input.style || {width:'65%'}"
+                        v-model="formModel[column.codeCamel]"
+                        :disabled="column.disabled"
+                        @change="column.change && column.change($event)"></el-input>
             </el-form-item>
             <!--按钮-->
             <el-form-item v-if="buttons && buttons.length > 0">
@@ -105,7 +120,10 @@
                            @click="resetForm(btn.method)">{{btn.text}}</el-button>
                 <el-button v-if="btn.type === 3"
                            type="primary"
-                           @click="btn.method">{{btn.text}}</el-button>
+                           @click="cancel(btn.method)">{{btn.text}}</el-button>
+                <el-button v-if="!btn.type"
+                           type="primary"
+                           @click="cancel(btn.method)">{{btn.text}}</el-button>
               </el-col>
             </el-form-item>
           </el-form>
@@ -149,34 +167,46 @@
       /**
        * 必传,指定要显示的表单字段及类型。数组的元素为对象类型,对象的属性有name、codeCamel、widgetType、disabled、
        * options、multiple、dateType等,不同的表单类型需配置的属性不同,
-       * codeCamel必须有,表示要显示的表单字段,
-       * name表示自定义的字段名,如果不传,默认为数据库中的字段名,
-       * widgetType表示该字段要显示的表单类型(普通输入框、文本域、富文本、下拉框...),不传默认为普通input
-       * 取值1-7(1表示普通输入框,2表示下拉框,3表示复选框,4表示文本域,5表示富文本,6表示日期,7表示单选框),
+       * codeCamel属性,表示要显示的表单字段, 如果其他字段都不需要传,可以只写codeCamel的值,比如['username','departmentId']
+       * name属性可选,表示自定义的字段名,如果不传,默认为数据库中的字段名,
+       * change属性可选,值为函数类型,表示input的change事件的执行方法,参数即为input输入内容
+       * default属性可选(复选框不支持),设置默认值,取值规范参考form/index.vue
+       * hide属性可选,设置该表单字段是否显示,值为boolean
+       * widgetType属性可选,表示该字段要显示的表单类型(普通输入框、文本域、富文本、下拉框...),不传默认为普通input
+       * 取值1-8(1表示普通输入框,2表示下拉框,3表示复选框,4表示文本域,5表示富文本,6表示日期,7表示单选框,8表示文件上传),
        * 若表单类型为下拉框/复选框/单选框,还需传入options字段,值为数组(数组元素是下拉框/复选框/单选框的选项),
        * 对于复选框,如果只有一个备选项则不必传options,
-       * 若表单类型为下拉框,还可传入multiple字段,取值true/false,表示是否多选,默认false
-       * 若表单类型为时间日期,可传入dateType字段,值为date(只显示日期)或datetime(显示日期和时间),如果不传,
+       * 若表单类型为下拉框,还可传入multiple字段,取值boolean类型,true/false,表示是否多选,默认false
+       * 若表单类型为时间日期,可传入dateType字段,值为'date'(只显示日期)或'datetime'(显示日期和时间),如果不传,
        * 默认只显示日期; 可传入dateFormate字段,为日期格式,取值遵循elementUI DatePicker组件中的日期格式,
-       * 比如 只显示日期取值'yyyy-MM-dd',显示日期和时间取值'yyyy-MM-dd HH:mm:ss',如果不传默认为只显示日期取值'yyyy-MM-dd',date字段和dateFormate字段取值须对应
-       * 所有的表单类型都可传入disabled字段,取值true/false,表示是否禁用,默认不禁用
+       * 比如 只显示日期取值'yyyy-MM-dd',显示日期和时间取值'yyyy-MM-ddHH:mm:ss',
+       * 如果不传默认为只显示日期取值'yyyy-MM-dd',date字段和dateFormate字段取值须对应
+       * disabled属性可选,取值boolean类型,true/false,表示是否禁用,默认不禁用
+       * rule属性可选,进行自定义验证规则,rule取值规范参照elementUI,下面有简单示例
        * 示例:[
-                { name: '用户名称', codeCamel: 'username', widgetType: 1, disabled: true },
-                { name: '电子邮件', codeCamel: 'email', widgetType: 5, disabled: false },
-                { name: '选择类型', codeCamel: 'type', widgetType: 2, multiple: false,
-                  options: [
-                              { value: 0, label: '选项1' },
-                              { value: 1, label: '选项2' },
-                              { value: 2, label: '选项3' },
-                              { value: 3, label: '选项4' },
-                              { value: 4, label: '选项5' }
-                            ]
-                },
-                { name: '部门ID', codeCamel: 'departmentId', widgetType: 3, options: ['美女', '帅哥'] },
-                { codeCamel: 'password', widgetType: 4 },
-                { name: '新建时间', codeCamel: 'createTime', widgetType: 6, dateType: 'datetime', dateFormate: 'yyyy-MM-dd HH:mm:ss' },
-                { name: '登陆id', codeCamel: 'loginid', widgetType: 7, options: ['会员', '访客'] },
-                { name: '选择头像', codeCamel: 'avatar', widgetType: 8 }
+       { name: '用户名称', codeCamel: 'username', widgetType: 1, disabled: true,
+         rule: { required: true, message: '用户名不能为空', trigger: 'blur' }
+       },
+       { name: '电子邮件', codeCamel: 'email', widgetType: 5, disabled: false,
+         rule: [
+           { required: true, message: '请输入邮箱地址', trigger: 'blur' },
+           { type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur,change' }
+         ]
+       },
+       { name: '选择类型', codeCamel: 'type', widgetType: 2, multiple: false,
+         options: [
+                     { value: 0, label: '选项1' },
+                     { value: 1, label: '选项2' },
+                     { value: 2, label: '选项3' },
+                     { value: 3, label: '选项4' },
+                     { value: 4, label: '选项5' }
+                   ]
+       },
+       { name: '部门ID', codeCamel: 'departmentId', widgetType: 3, options: ['美女', '帅哥'] },
+       { codeCamel: 'password', widgetType: 4 },
+       { name: '新建时间', codeCamel: 'createTime', widgetType: 6, dateType: 'datetime', dateFormate: 'yyyy-MM-dd HH:mm:ss' },
+       { name: '登陆id', codeCamel: 'loginid', widgetType: 7, options: ['会员', '访客'] },
+       { name: '选择头像', codeCamel: 'avatar', widgetType: 8 }
        ]
        */
       columns: {
@@ -193,16 +223,18 @@
       /**
        * 非必传,指定要显示的按钮及类型,默认不显示。
        * 类型(type)关系到按钮要执行的方法,type=1,执行组件的提交方法,还可以传入了method字段,值为函数,
-       * 该函数会作为提交方法的回调函数执行,同时还可以传入beforeSubmit字段,值为函数,函数接受一个包含表单数据的Object
-       * 类型参数,该函数可以在提交之前对表单数据进行处理,参数类似{username: 'name', loginid: 'id'},其中键为
-       * 调用者传入的codeCamel
+       * 该函数会作为提交方法的回调函数执行,函数接受一个参数为新建或修改的数据,
+       * 同时还可以传入beforeSubmit字段,值为函数,函数接受两个参数(value,isCancel)
+       * value为包含表单数据的对象,{username: 'name', loginid: 'id'},其中键为调用者传入的codeCamel
+       * 该函数可以在提交之前对表单数据进行处理,并返回数据;对象isCancel包含一个值为false的属性cancelSubmit
+       * 如果需要取消提交,将cancelSubmit值改为true
        * type=2,执行组件的重置方法,如果用户传入了method,会作为重置方法的回调函数执行
        * type=3,直接执行用户传入的方法
        * 如果要传入了确定/取消的回调函数,请先传入对应的按钮
        * 示例:[
-       *        {text: '确定', type: '1', method: method1},
-       *        {text: '重置', type: '2', method: method2},
-       *        {text: '取消', type: '3', method: method3}
+       *        {text: '确定', type: 1, method: method1, beforeSubmit: this.processData},
+       *        {text: '重置', type: 2, method: method2},
+       *        {text: '取消', type: 3, method: method3}
        *      ]
        */
       buttons: {
@@ -224,33 +256,93 @@
       layout: {
         type: Object,
         required: false
+      },
+      /**
+       * 用来将本表的外链字段(table_id类似的字段)指向的外链表相关联, 格式为:
+       *  {
+       *    "hm_user": {    //外链表 表名 本表所对应的主键表)
+       *      includes:['user_id'] // 与主表所对应的外键
+       *    }
+       *  }
+       *
+       */
+      includes: {
+        type: Object,
+        required: false
+      },
+      /**
+       * 用来将其他表的外链字段指向本表关联,同时返回数据, 格式为:
+       *  {
+       *    'auth_token': {          //主键id所对应的外键表 表名1 (本表所对应的外键表)
+       *      includes: ['user_id']   //外键表的外键字段
+       *    }
+       *  }
+       */
+      refers: {
+        type: Object,
+        required: false
+      },
+      /**
+       * 请求成功或失败时的提示信息,格式为:
+       *  tips: {
+       *     hidde: false, // 是否显示提示,默认false显示
+       *     newSuccess: { text: '发布成功' }, // 新建成功的提示
+       *     newError: { text: '发布失败' }, // 新建失败的提示
+       *     editSuccess: { text: '编辑成功' }, // 编辑成功的提示
+       *     editError: { text: '编辑失败' } // 编辑失败的提示
+       *     otherError: { text: '没有传ID,不可以提交' }
+       *  }
+       */
+      tips: {
+        type: Object,
+        required: false
+      },
+      /**
+       * 表单样式设置,格式为:
+       *  formStyle: {
+       *   formOptions: { labelWidth: '170px', labelPosition: 'right' },
+       *   datePicker: { style: { width: '60%' }},
+       *   input: { style: { width: '60%' }},
+       *   select: { style: { width: '60%' }},
+       *   textarea: {
+       *      style: { width: '60%' },
+       *      resize: 'none',
+       *      autosize: { minRows: 3, maxRows: 5 },
+       *      rows: 3
+       *   },
+       *  quillEdito: { style: { width: '65%' }}
+       * },
+       */
+      formStyle: {
+        type: Object,
+        required: false
       }
     },
     data() {
-      var validateUsername = (rule, value, callback) => {
-        // console.log(value.length)
-        if (!value) {
-          callback(new Error('请输入用户名'))
-        } else if ((value.length < 2 || value.length > 10)) {
-          callback(new Error('用户名长度在 2 到 10 个字符'))
-        } else {
-          callback()
-        }
-      }
-      var validatePassword = (rule, value, callback) => {
-        if (value.length > 0 && !(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(value))) {
-          callback(new Error('密码必须同时包含数字和字母 6-20位'))
-        } else {
-          callback()
-        }
-      }
-      var validateMobile = (rule, value, callback) => {
-        if (value.length > 0 && !(/^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/.test(value))) {
-          callback(new Error('请输入正确的电话号码或手机号'))
-        } else {
-          callback()
-        }
-      }
+      // var validateUsername = (rule, value, callback) => {
+      //   // console.log(value.length)
+      //   if (!value) {
+      //     callback(new Error('请输入用户名'))
+      //   } else if ((value.length < 2 || value.length > 10)) {
+      //     callback(new Error('用户名长度在 2 到 10 个字符'))
+      //   } else {
+      //     callback()
+      //   }
+      // }
+      // var validatePassword = (rule, value, callback) => {
+      //   if (value.length > 0 && !(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(value))) {
+      //     callback(new Error('密码必须同时包含数字和字母 6-20位'))
+      //   } else {
+      //     callback()
+      //   }
+      // }
+      // var validateMobile = (rule, value, callback) => {
+      //   if (value.length > 0 && !(/^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/.test(value))) {
+      //     callback(new Error('请输入正确的电话号码或手机号'))
+      //   } else {
+      //     callback()
+      //   }
+      // }
       // var validateEmail = (rule, value, callback) => {
       //   if (value.length > 0) {
       //     if (!(/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value))) {
@@ -266,26 +358,26 @@
         formModel: {}, // 双向绑定的数据变量
         showUserColumns: [], // 要显示的字段
         rules: {
-          username: [
-            { validator: validateUsername, trigger: 'change' }
+          // username: [
+          //   { validator: validateUsername, trigger: 'change' }
           // { required: true, message: '请输入用户名', trigger: 'blur' },
           // { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }
-          ],
-          loginid: [
-            // { required: true, message: '请输入登陆ID', trigger: 'blur' }
-          ],
-          password: [
-            { validator: validatePassword, trigger: 'change' }
-            // { pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/, message: '密码必须同时包含数字和字母 6-20位', trigger: 'change' }
-          ],
-          mobile: [
-            { validator: validateMobile, trigger: 'change' }
-            // { pattern: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/, message: '请输入正确的电话号码', trigger: 'change' }
-          ],
-          email: [
-            // { validator: validateEmail, trigger: 'change' }
-            { type: 'email', message: '请输入正确的邮箱', trigger: 'change' }
-          ]
+          // ],
+          // loginid: [
+          // { required: true, message: '请输入登陆ID', trigger: 'blur' }
+          // ],
+          // password: [
+          //   { validator: validatePassword, trigger: 'change' }
+          // { pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/, message: '密码必须同时包含数字和字母 6-20位', trigger: 'change' }
+          // ],
+          // mobile: [
+          //   { validator: validateMobile, trigger: 'change' }
+          // { pattern: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/, message: '请输入正确的电话号码', trigger: 'change' }
+          // ]
+          // email: [
+          // { validator: validateEmail, trigger: 'change' }
+          // { type: 'email', message: '请输入正确的邮箱', trigger: 'change' }
+          // ]
         },
         editorOption: { // 富文本选项配置
           placeholder: '',
@@ -299,9 +391,9 @@
           }
         },
         pickerOptions: { // 日期选项配置
-          disabledDate(time) {
-            return time.getTime() > Date.now()
-          },
+          // disabledDate(time) {
+          //   return time.getTime() > Date.now()
+          // },
           shortcuts: [{
             text: '今天',
             onClick(picker) {
@@ -322,45 +414,88 @@
               picker.$emit('pick', date)
             }
           }]
-        }
+        },
+        fileList: [], // 上传文件列表
+        fileCode: '', // 上传组件对应的数据库字段
+        isCancel: { cancelSubmit: false }
       }
     },
     created() {
       // this.validate()
       this.init()
       this.getList()
-      console.log(this.buttons)
+      // console.log(this.buttons)
     },
     methods: {
-      createRule() {
-        _.each()
+      handleRemove(file, fileList) {
+        // console.log(self.formModel)
       },
-      useralidate(value) {
-        // console.log(event)
-        console.log(value)
+      handlePreview(file) {
+        console.log(file)
       },
-      handleRemove(file, fileList) {
-        console.log(file, fileList)
+      uploadSuccess(response, file, fileList) {
+        const self = this
+        console.log('上传成功')
+        // console.log(response)
+        // console.log('fileList', fileList)
+        // console.log(self.fileList)
+        _.each(self.columns, function(item, index) {
+          if (item.widgetType === 8) {
+            _.forEach(self.formModel, function(value, key) {
+              if (item.codeCamel === key) {
+                self.formModel[key] = response.message || response.visitName
+              }
+            })
+          }
+        })
+        // console.log(404, self.formModel)
       },
-      handleExceed(files, fileList) {
-        this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
+      // inputChange(val) {
+      //   // console.log(event)
+      //   // console.log(val)
+      // },
+      // checkboxChange(val) {
+      //   console.log(val)
+      // },
+      // checkboxsChange(val) {
+      //   console.log(val)
+      // },
+      // selectChange(val) {
+      //   console.log(val)
+      // },
+      // radioChange(val) {
+      //   console.log(val)
+      // },
+      // logTimeChange(val) {
+      //   console.log(val)
+      // },
+      // textareaChange(val) {
+      //   console.log(val)
+      // },
+      // onEditorChange({ quill, html, text }) {
+      //   console.log(quill)
+      //   console.log(html)
+      //   console.log(text)
+      //   // this.content = html
+      // },
+      onEditorBlur(val) {
+        // console.log(val)
       },
-      checkboxsChange(val) {
-        console.log(val)
+      onEditorFocus(val) {
+        // console.log('editor focus!')
       },
-      selectChange(val) {
-        console.log(val)
+      onEditorReady(val) {
+        // console.log('editor ready!')
       },
       // 判断是否一个对象的所有属性都为空
       isEmpty(obj) {
-        _.forEach(obj, function(val) {
-          if (val) return false
-        })
+        for (var key in obj) {
+          if (obj[key] && _.trim(obj[key])) {
+            return false
+          }
+        }
         return true
       },
-      logTimeChange(value) {
-        console.log(value)
-      },
       validate() {
         const self = this
         // this.columns数组元素本身必须是string或者object. 且必须是schema中定义的列
@@ -381,15 +516,6 @@
           }
         })
       },
-      onEditorBlur(editor) {
-        // console.log('editor blur!')
-      },
-      onEditorFocus(editor) {
-        // console.log('editor focus!')
-      },
-      onEditorReady(editor) {
-        // console.log('editor ready!')
-      },
       // 存在tableId,修改数据前先获取数据
       getList() {
         const self = this
@@ -402,49 +528,63 @@
           } */
           self.Loading = false
           // console.log(self.formModel)
-          var formArray = _.keys(self.formModel)
+          var formArray = _.keys(self.formModel) // 提取formModel的属性到数组
           // console.log(formArray)
-          self.formModel = _.pick(resp.data, formArray)
-          // console.log(self.formModel)
+          self.formModel = _.pick(resp.data, formArray) // 根据数组中的属性提取出data中对应的数据
+
+          // 下拉框多选时将字符串转为数组
+          _.each(self.columns, function(item, index) {
+            if (item.widgetType === 2 && item.multiple === true) {
+              _.forEach(self.formModel, function(value, key) {
+                if (item.codeCamel === key) {
+                  // console.log(11111, self.formModel[key])
+                  self.formModel[key] = self.formModel[key].split(',')
+                }
+              })
+            }
+          })
+          // console.log(2222, self.formModel)
         })
       },
+      // 初始化
       init() {
         const self = this
         if (self.columns && self.columns.length) {
-          self.showUserColumns = JSON.parse(JSON.stringify(self.columns))
-          // console.log(self.showUserColumns)
-          // 将字符串对象进行替换处理
+          self.showUserColumns = _.cloneDeep(self.columns)
+          // console.log(504, self.showUserColumns)
+          // console.log(514, self.formModel)
+          // 处理传来的表单字段
           _.each(self.showUserColumns, function(column, index) {
-            if (typeof column === 'object') {
+            if (typeof column === 'string') {
               // 生成一个新对象
-              const tmp = _.keyBy(self.schema['columns'], 'codeCamel')[column.codeCamel]
-              // console.log(tmp)
-              // self.$set(tmp, 'code', tmp.code.toLowerCase())
+              const tmp = _.keyBy(self.schema['columns'], 'codeCamel')[column]
+              /* self.$set(tmp, 'code', tmp.code.toLowerCase())
               column.name && self.$set(tmp, 'name', column.name) // 自定义字段名
-              self.$set(tmp, 'widgetType', column.widgetType || 1)
-              // column.validate && self.$set(tmp, 'validate', column.validate)
+              column.rule && self.$set(tmp, 'rule', column.rule) // 设置表单校验规则
               column.disabled && self.$set(tmp, 'disabled', column.disabled) // 设置是否禁用
               column.options && self.$set(tmp, 'options', column.options) // 设置下拉框或者多选的选项
               column.multiple && self.$set(tmp, 'multiple', column.multiple) // 设置下拉框是否多选
               column.dateType && self.$set(tmp, 'dateType', column.dateType) // 设置日期表单显示类型
               column.dateFormate && self.$set(tmp, 'dateFormate', column.dateFormate) // 设置日期格式
+              column.change && self.$set(tmp, 'change', column.change) // 设置change函数
+              column.url && self.$set(tmp, 'url', column.url) // 设置文件上传地址 */
+              self.$set(tmp, 'widgetType', 1) // 设置表单类型
               self.$set(self.showUserColumns, index, tmp) // 顺序
             }
           })
           console.log(self.showUserColumns)
           // 提取v-model绑定的变量
           _.each(self.showUserColumns, function(item) {
-            if (item.widgetType === 3 && item.options && item.options.length > 0) {
+            if (item.widgetType === 8 || (item.widgetType === 3 && item.options && item.options.length > 0)) {
               self.$set(self.formModel, item.codeCamel, [])
             } else {
-              self.$set(self.formModel, item.codeCamel, '')
+              item.default ? self.$set(self.formModel, item.codeCamel, item.default) : self.$set(self.formModel, item.codeCamel, '')
             }
           })
           if (!request.defaults.baseURL) {
             request.defaults.baseURL = '/org/api'
-            console.log('没有')
           }
-          console.log(request.defaults.baseURL)
+          // console.log(request.defaults.baseURL)
           // 加载等待
           if (self.tableId) {
             self.Loading = true
@@ -465,13 +605,36 @@
       onSubmit(callback, processData) {
         const self = this
         console.log('点击了提交函数')
-        // console.log(self.formModel)
-        self.formModel = processData ? processData(self.formModel) : self.formModel // 对表单数据进行处理
         console.log(self.formModel)
-        // if (self.isEmpty(self.formModel)) return
+        // 对表单数据进行处理
+        self.formModel = processData ? processData(self.formModel, self.isCancel) : self.formModel
+        // 如果在processData中禁止提交了,显示提示信息
+        if (self.isCancel.cancelSubmit) {
+          console.log('取消提交')
+          if (self.tips && !self.tips.hidde) {
+            self.$message({
+              message: self.tips.otherError.text,
+              type: 'error'
+            })
+          }
+          return
+        }
+        // self.formModel = JSON.stringify(self.formModel)
+        // var params = _.cloneDeep(self.formModel)
+        // params = JSON.stringify(params)
+        // console.log(self.formModel)
+        // 如果所有值都为空 禁止提交
+        if (self.isEmpty(self.formModel)) {
+          self.$message({
+            message: '不能都为空',
+            type: 'error'
+          })
+          return
+        }
+        // 验证、提交
         self.$refs.form.validate((valid) => {
           if (valid) {
-            console.log('valid通过!')
+            // console.log('valid通过!')
             // 存在tableId 则修改信息
             if (self.tableId) {
               request(self.schema.modelUnderscorePlural + '/' + self.tableId + '/edit', {
@@ -483,7 +646,7 @@
                     var str = []
                     // 删除空值的属性
                     obj = _.omitBy(obj, function(value) {
-                      return !value
+                      return value === null // 删除value=null的属性,剩下的返回给新对象
                     })
                     for (var p in obj) {
                       str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]))
@@ -492,12 +655,35 @@
                   }
               }).then(resp => {
                 console.log('修改成功')
-                self.resetForm()
+                // self.resetForm()
+                if (self.tips && !self.tips.hidde) {
+                  self.$message({
+                    message: self.tips.editSuccess.text,
+                    type: 'success'
+                  })
+                }
+                // self.formModel = {} // 新建完成清空数据
                 if (typeof (callback) === 'function') {
-                  callback()
+                  callback(resp.data)
+                }
+              }).catch(err => {
+                console.log(err)
+                if (self.tips && !self.tips.hidde) {
+                  self.$message({
+                    message: self.tips.editError.text,
+                    type: 'error'
+                  })
                 }
               })
             } else { // 不存在tableId 则创建一条数据
+              console.log(self.formModel)
+              // if (self.isEmpty(self.formModel)) {
+              //   self.$message({
+              //     message: '不能都为空',
+              //     type: 'error'
+              //   })
+              //   return
+              // }
               request(self.schema.modelUnderscorePlural + '/new', {
                 method: 'post',
                 headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
@@ -512,14 +698,33 @@
                   }
               }).then(resp => {
                 console.log('创建成功')
+                if (self.tips && !self.tips.hidde) {
+                  self.$message({
+                    message: self.tips.newSuccess.text,
+                    type: 'success'
+                  })
+                }
+                // self.formModel = {} // 新建完成清空数据
                 // self.resetForm()
                 if (typeof (callback) === 'function') {
-                  callback()
+                  callback(resp.data)
+                }
+              }).catch(err => {
+                console.log(err)
+                if (self.tips && !self.tips.hidde) {
+                  self.$message({
+                    message: self.tips.newError.text,
+                    type: 'error'
+                  })
                 }
               })
             }
           } else {
             console.log('提交失败!!')
+            self.$message({
+              message: '验证未通过',
+              type: 'error'
+            })
             return false
           }
         })
@@ -535,8 +740,20 @@
        * 清空所有输入及提示信息。
        */
       resetForm(callback) {
+        // const self = this
         console.log('重置')
         this.$refs.form.resetFields()
+        // console.log(self.formModel)
+        // // 清空
+        // _.each(self.formModel, function(value, index) {
+        //   self.formModel[index] = ''
+        // })
+        // 执行回调
+        if (typeof (callback) === 'function') {
+          callback()
+        }
+      },
+      cancel(callback) {
         if (typeof (callback) === 'function') {
           callback()
         }
diff --git a/src/views/haomo/components/forms/index.vue b/src/views/haomo/components/forms/index.vue
index 8c6313002f25cd86bf24e90c6abfa25006e8cc47..bde8ee940a93542b3ec69c4d8ff5d519feba47e8 100644
--- a/src/views/haomo/components/forms/index.vue
+++ b/src/views/haomo/components/forms/index.vue
@@ -1,12 +1,12 @@
 <template>
-  <!--:tableId="tableId"-->
+  <!--:refers="judgeRefers"-->
   <div>
     <hm-complex-form :schema="schema['HmUser']"
                      :columns="showUserColumns"
                      :buttons="showUserButtons"
-                     :tableId="tableId"
                      :layout="layout"
-                     >
+                     :tips="tips"
+                     :refers="userRefers">
     </hm-complex-form>
   </div>
 </template>
@@ -25,34 +25,119 @@
     },
     data() {
       return {
-        // widgetType值 1:普通input 2:下拉框 (如果是下拉框 再传一个options表示下拉框选项)3:复选框 4:文本域 5:富文本 6:日期 7:单选框
+        // widgetType值 1:普通input 2:下拉框 (如果是下拉框 再传一个options表示下拉框选项)3:复选框 4:文本域 5:富文本 6:日期 7:单选框 8: 文件上传
         showUserColumns: [
-          { name: '用户名称', codeCamel: 'username', widgetType: 1, disabled: true },
-          { name: '电子邮件', codeCamel: 'email', widgetType: 5, disabled: false },
-          { name: '选择类型', codeCamel: 'type', widgetType: 2, multiple: false,
+          // 1普通input
+          { name: '选择类型', codeCamel: 'type', widgetType: 1, disabled: false,
+            change: this.inputChange
+            // rule: { required: true, message: '用户名不能为空', trigger: 'blur' }
+            //  hide: true
+          //  default: '默认值',
+          },
+          // 5富文本
+          { name: '电子邮件', codeCamel: 'email', widgetType: 5, disabled: false,
+            change: this.inputChange, hide: false
+            // rule: [
+            //   { required: true, message: '请输入邮箱地址', trigger: 'blur' },
+            //   { type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur,change' }
+            // ]
+          },
+          // 2下拉框
+          { name: '用户名称', codeCamel: 'username', widgetType: 2, multiple: false,
+            change: this.inputChange, // default: [1], 如果开启多选,默认选中项用数组[1]、[1,2,3]
             options: [
-              { value: 0, label: '选项1' },
-              { value: 1, label: '选项2' },
-              { value: 2, label: '选项3' },
-              { value: 3, label: '选项4' },
-              { value: 4, label: '选项5' }
+              { value: '1', label: '企业' }, // 下拉框的label是选项文字,value是选中值
+              { value: '2', label: '代理商' },
+              { value: '3', label: '会员' },
+              { value: '4', label: '访客' }
             ]
           },
-          { name: '部门ID', codeCamel: 'departmentId', widgetType: 3, options: ['美女', '帅哥'] },
-          { codeCamel: 'password', widgetType: 4 },
-          { name: '新建时间', codeCamel: 'createTime', widgetType: 6, dateType: 'datetime', dateFormate: 'yyyy-MM-dd HH:mm:ss' },
-          { name: '登陆id', codeCamel: 'loginid', widgetType: 7, options: ['会员', '访客'] },
-          { name: '选择头像', codeCamel: 'avatar', widgetType: 8 }
+          // 3多选 不支持默认值
+          { name: '部门ID', codeCamel: 'departmentId', widgetType: 3, options: ['美女', '帅哥'], change: this.inputChange },
+          // 4密码
+          { name: '密码', codeCamel: 'password', widgetType: 4, change: this.inputChange },
+          // 'password',
+          // 6日期
+          { name: '新建时间', codeCamel: 'createTime', widgetType: 6, dateType: 'datetime',
+            dateFormate: 'yyyy-MM-dd HH:mm:ss', change: this.inputChange
+          // default: '2018-01-01 00:07:08'
+          },
+          // 7单选
+          { name: '登陆id', codeCamel: 'loginid', widgetType: 7,
+            options: [
+              { label: 1, value: '会员' }, // 单选的value是选项文字,label是选中值
+              { label: 2, value: '访客' }
+            ], // default: 1
+            change: this.inputChange },
+          // 8文件
+          { name: '选择头像', codeCamel: 'avatar', widgetType: 8, url: '/api/upload' } // url是后台接口地址
+        ],
+        showUserColumns2: [
+          // 1普通input
+          { name: '用户名称', codeCamel: 'username', widgetType: 1 },
+          { name: '部门ID', codeCamel: 'departmentId', widgetType: 1 },
+          { name: '部门名称', codeCamel: 'departmentName', widgetType: 1 },
+          { name: '密码', codeCamel: 'password', widgetType: 1 },
+          { name: '电话', codeCamel: 'mobile', widgetType: 1 },
+          { name: '电子邮件', codeCamel: 'email', widgetType: 1 },
+          { name: '新建时间', codeCamel: 'createTime', widgetType: 1 },
+          { name: '登陆id', codeCamel: 'loginid', widgetType: 1 }
         ],
+        userIncludes: {
+          'hm_user': {
+            includes: ['user_id']
+          }
+        },
+        // 主查外
+        userRefers: {
+          'cc_shift': {
+            includes: ['applicant_id']
+          }
+        },
         // 要显示按钮
         showUserButtons: [
           { text: '确定', type: 1, method: this.method1, beforeSubmit: this.processData },
           { text: '重置', type: 2, method: this.method2 },
+          { text: '生成', method: this.method4 },
           { text: '取消', type: 3, method: this.method3 }
         ],
         // showUserButtons: []
         // 布局方式
-        layout: { left: 6, middle: 12, right: 6 }
+        layout: { left: 4, middle: 16, right: 4 },
+        // 自定义提示消息
+        tips: {
+          hidde: false, // 是否显示提示,默认false显示
+          newSuccess: { text: '发布成功' }, // 新建成功的提示
+          newError: { text: '发布失败' }, // 新建失败的提示
+          editSuccess: { text: '编辑成功' }, // 编辑成功的提示
+          editError: { text: '编辑失败' }, // 编辑失败的提示
+          otherError: { text: '填写有误,不可以提交' } // processData中取消提交的提示
+        },
+        // 各类型表单样式设置
+        formStyle: {
+          formOptions: {
+            labelWidth: '170px',
+            labelPosition: 'right'
+          },
+          datePicker: { style: { width: '60%' }},
+          input: { style: { width: '60%' }},
+          select: { style: { width: '60%' }},
+          textarea: {
+            style: { width: '60%' },
+            resize: 'none',
+            autosize: { minRows: 3, maxRows: 5 },
+            rows: 3
+          },
+          quillEdito: { style: { width: '65%' }}
+        },
+        // 'cc_option': {
+        //   includes: ['ccSubjectId']
+        // }
+        judgeRefers: { // 主查外
+          'cc_hm_user': {
+            includes: ['applicantId']
+          }
+        }
       }
     },
     computed: {
@@ -62,12 +147,18 @@
     created() {
       this.schema = schema
       // console.log(this.schema)
-      this.tableId = '0e26566e953449a7a7500c34be39fd26'
+      // this.tableId = '1efff63125954583b0ac5a9c252b9041'
+      this.tableId = 'b08d2220d2574bf2ac09ec4f470ed999'
     },
     methods: {
-      processData(object) {
-        console.log(object)
-        return object
+      inputChange(val) {
+        // console.log(event)
+        console.log(val)
+      },
+      processData(object, isCancel) {
+        isCancel.cancelSubmit = false // 如果要取消提交,设为true
+        console.log(125, object)
+        return object // 将数据返回
       },
       method1() {
         console.log('method1')
@@ -78,15 +169,8 @@
       method3() {
         console.log('method3')
       },
-      usernameValidate() {
-        console.log(1)
-        // if (!value) {
-        //   callback(new Error('请输入用户名'))
-        // } else if ((value.length < 2 || value.length > 10)) {
-        //   callback(new Error('用户名长度在 2 到 10 个字符'))
-        // } else {
-        //   callback()
-        // }
+      method4() {
+        console.log('method4')
       }
     }
   }
diff --git a/src/views/haomo/components/tables/HmComplexTable.vue b/src/views/haomo/components/tables/HmComplexTable.vue
index e2c5b5d5901f8b1f2dd3c232a2c227d1c9388345..cc4175cf6f8ee678c64c73d7190d1c77a8685288 100644
--- a/src/views/haomo/components/tables/HmComplexTable.vue
+++ b/src/views/haomo/components/tables/HmComplexTable.vue
@@ -3,104 +3,98 @@
     <!-- 过滤 -->
     <div class="filter-container">
       <el-form :inline="true">
-      <!-- 过滤条件 -->
-      <span v-for="filter in filters" class="hm-complex-table__filter-span">
-        <el-input @keyup.enter.native="handleFilter"
-                  style="width: 200px;"
-                  class="filter-item"
-                  :placeholder="filter.placeholder"
-                  v-if="filter.isShow && isShowFilter(filter)"
-                  v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
-        </el-input>
-
-        <el-input @keyup.enter.native="handleFilter"
-                  style="width: 200px;"
-                  class="filter-item"
-                  :placeholder="filter.placeholder[0]"
-                  v-if="filter.isShow && !isShowFilter(filter) && !isDatetimeFilter(filter)"
-                  v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
-        </el-input>
-        <el-input @keyup.enter.native="handleFilter"
-                  style="width: 200px;"
-                  class="filter-item"
-                  :placeholder="filter.placeholder[1]"
-                  v-if="filter.isShow && !isShowFilter(filter) && !isDatetimeFilter(filter)"
-                  v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOperTwin(filter)]">
-        </el-input>
-
-        <el-date-picker type="datetime"
-                        align="right"
-                        class="filter-item hm-complex-table__filter-span"
-                        @keyup.enter.native="handleFilter"
-                        value-format="yyyy-MM-dd HH:mm:ss"
-                        :picker-options="pickerOptions"
-                        :placeholder="filter.placeholder[0]"
-                        v-if="filter.isShow && !isShowFilter(filter) && isDatetimeFilter(filter)"
-                        v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
-        </el-date-picker>
-        <el-date-picker type="datetime"
-                        align="right"
-                        class="filter-item"
-                        @keyup.enter.native="handleFilter"
-                        value-format="yyyy-MM-dd HH:mm:ss"
-                        :picker-options="pickerOptions"
-                        :placeholder="filter.placeholder[1]"
-                        v-if="filter.isShow && !isShowFilter(filter) && isDatetimeFilter(filter)"
-                        v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOperTwin(filter)]">
-        </el-date-picker>
-      </span>
-      <!-- end 过滤条件 -->
-
-      <!--预定义按钮-->
-      <el-button-group v-if="buttonGroup">
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
-        <el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" v-if="isShowExport" @click="handleDownload">导出</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-plus" v-if="isShowNewButton" @click="openDialog('newData')">新建</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-refresh" v-if="isShowRefresh" @click="refreshList">刷新</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-close" v-if="multipleSelection.length" @click="BatchRemove">批量删除</el-button>
-      </el-button-group>
-      <span v-if="!buttonGroup">
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
-        <el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" v-if="isShowExport" @click="handleDownload">导出</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-plus" v-if="isShowNewButton" @click="openDialog('newData')">新建</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-refresh" v-if="isShowRefresh" @click="refreshList">刷新</el-button>
-        <el-button class="filter-item" type="primary" v-waves icon="el-icon-close" v-if="multipleSelection.length" @click="BatchRemove">批量删除</el-button>
-      </span>
-
-      <!--自定义-->
-      <span v-if="definedOperate.length" v-for="operate in definedOperate">
-        <!--自定义按钮-->
-        <el-button v-if="operate.type == 'button'" class="filter-item" type="primary" v-waves :icon="operate.icon" @click="operate.func">{{operate.label}}</el-button>
-        <!--自定义下拉选择-->
-        <el-form-item v-if="operate.type == 'select'" :label="operate.label">
-          <el-select v-model="operate.value" :placeholder="operate.placeholder">
-            <el-option v-for="o in operate.options" :label="o.label" :value="o.code"></el-option>
-          </el-select>
-        </el-form-item>
-        <!--自定义输入框-->
-        <el-form-item v-if="operate.type == 'input'" :label="operate.label">
+        <!-- 过滤条件 -->
+        <span v-for="filter in filters" class="hm-complex-table__filter-span">
           <el-input @keyup.enter.native="handleFilter"
                     style="width: 200px;"
                     class="filter-item"
-                    :placeholder="operate.placeholder"
-                    v-model="operate.value">
+                    :placeholder="filter.placeholder"
+                    v-if="filter.isShow && isShowFilter(filter)"
+                    v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
           </el-input>
-        </el-form-item>
-        <!--自定义时间选择-->
-        <el-form-item v-if="operate.type == 'datetime'" :label="operate.label">
+
+          <el-input @keyup.enter.native="handleFilter"
+                    style="width: 200px;"
+                    class="filter-item"
+                    :placeholder="filter.placeholder[0]"
+                    v-if="filter.isShow && !isShowFilter(filter) && !isDatetimeFilter(filter)"
+                    v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
+          </el-input>
+          <el-input @keyup.enter.native="handleFilter"
+                    style="width: 200px;"
+                    class="filter-item"
+                    :placeholder="filter.placeholder[1]"
+                    v-if="filter.isShow && !isShowFilter(filter) && !isDatetimeFilter(filter)"
+                    v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOperTwin(filter)]">
+          </el-input>
+
+          <el-date-picker type="datetime"
+                          align="right"
+                          class="filter-item hm-complex-table__filter-span"
+                          @keyup.enter.native="handleFilter"
+                          value-format="yyyy-MM-dd HH:mm:ss"
+                          :placeholder="filter.placeholder[0]"
+                          v-if="filter.isShow && !isShowFilter(filter) && isDatetimeFilter(filter)"
+                          v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOper(filter)]">
+          </el-date-picker>
           <el-date-picker type="datetime"
                           align="right"
                           class="filter-item"
                           @keyup.enter.native="handleFilter"
                           value-format="yyyy-MM-dd HH:mm:ss"
-                          :picker-options="pickerOptions"
-                          :placeholder="operate.placeholder"
-                          v-model="operate.value">
+                          :placeholder="filter.placeholder[1]"
+                          v-if="filter.isShow && !isShowFilter(filter) && isDatetimeFilter(filter)"
+                          v-model="listQuery.filters[schema['modelUnderscore']][getFilterColumn(filter)][getFilterOperTwin(filter)]">
           </el-date-picker>
-        </el-form-item>
-      </span>
-
-
+        </span>
+        <!-- end 过滤条件 -->
+        <!--自定义-->
+        <span v-if="definedOperate.length" v-for="operate in definedOperate">
+          <!--自定义按钮-->
+          <el-button v-if="operate.type == 'button'" class="filter-item" type="primary" v-waves :icon="operate.icon" @click="operate.func">{{operate.label}}</el-button>
+          <!--自定义下拉选择-->
+          <el-form-item v-if="operate.type == 'select'" :label="operate.label">
+            <el-select v-model="operate.value" :placeholder="operate.placeholder" clearable>
+              <el-option v-for="o in operate.options" :label="o.label" :value="o.code"></el-option>
+            </el-select>
+          </el-form-item>
+          <!--自定义输入框-->
+          <el-form-item v-if="operate.type == 'input'" :label="operate.label">
+            <el-input @keyup.enter.native="handleFilter"
+                      style="width: 200px;"
+                      class="filter-item"
+                      :placeholder="operate.placeholder"
+                      v-model="operate.value">
+            </el-input>
+          </el-form-item>
+          <!--自定义时间选择-->
+          <el-form-item v-if="operate.type == 'datetime'" :label="operate.label">
+            <el-date-picker type="datetime"
+                            class="filter-item"
+                            @keyup.enter.native="handleFilter"
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            :placeholder="operate.placeholder"
+                            v-model="operate.value">
+            </el-date-picker>
+          </el-form-item>
+        </span>
+
+        <!--预定义按钮-->
+        <el-button-group v-if="buttonGroup">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
+          <el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" v-if="isShowExport" @click="handleDownload">导出</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-plus" v-if="isShowNewButton" @click="openDialog('newData')">新建</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-refresh" v-if="isShowRefresh" @click="refreshList">刷新</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-close" v-if="multipleSelection.length" @click="BatchRemove">批量删除</el-button>
+        </el-button-group>
+
+        <span v-if="!buttonGroup">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">搜索</el-button>
+          <el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" v-if="isShowExport" @click="handleDownload">导出</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-plus" v-if="isShowNewButton" @click="openDialog('newData')">新建</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-refresh" v-if="isShowRefresh" @click="refreshList">刷新</el-button>
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-close" v-if="multipleSelection.length" @click="BatchRemove">批量删除</el-button>
+        </span>
 
       </el-form>
     </div>
@@ -108,20 +102,23 @@
 
     <!-- 表格 -->
     <el-table :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row
-              style="width: 100%" @selection-change="handleSelectionChange">
+              style="width: 100%" @selection-change="handleSelectionChange" @sort-change="sortChange" @current-change="tableCurrentChange">
       <el-table-column type="index" :index="indexMethod" label="序号" width="50px"></el-table-column>
-      <el-table-column type="selection" width="55">
+      <el-table-column type="selection" width="55" v-if="isShowSelection"></el-table-column>
+      <el-table-column v-for="(column,index) in showColumns" :key="index" align="center" :label="column.name"
+                       :prop="column.codeCamel" :sortable="column.isSort" :width="column.width" :show-overflow-tooltip="showOverflowTooltip">
+      <template slot-scope="scope">
+          <span v-if="(scope.row[column.codeCamel] !== false && scope.row[column.codeCamel] !== true )&& !column.render">{{ scope.row[column.codeCamel] }}</span>
+          <el-checkbox v-if="(scope.row[column.codeCamel] === false || scope.row[column.codeCamel] === true) && !column.render" v-model="scope.row[column.codeCamel]"></el-checkbox>
+          <span v-if='column.render' v-html="column.render(scope)"></span>
+      </template>
       </el-table-column>
-      <el-table-column v-for="(column,index) in showColumns" :key="index" align="center" :label="column.name">
-        <template slot-scope="scope">
-          <span>{{ scope.row[column.codeCamel] }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column fixed="right" label="操作" :width="operationWidth" v-if="isShowEditDataButton || isShowDeleteButton">
+      <el-table-column fixed="right" label="操作" :width="operationWidth" v-if="isShowEditDataButton || isShowDeleteButton || definedOperation.length">
         <template slot-scope="scope">
           <el-button @click="openDialog('editData',scope.row)" v-if="isShowEditDataButton" type="text" size="small">编辑</el-button>
           <el-button @click="deleteData(scope.row)" type="text" v-if="isShowDeleteButton" size="small">删除</el-button>
           <el-button @click="openDialog('detail',scope.row)" type="text" v-if="isShowDetail" size="small">详情</el-button>
+          <el-button @click="operation.func(scope.row)" type="text" v-if="definedOperation.length" size="small" v-for="operation in definedOperation">{{operation.label}}</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -138,17 +135,15 @@
     <!-- 弹窗 -->
     <!-- @TODO 补充详情弹窗 -->
 
-    <el-dialog :title="dialogName" :visible.sync="dialogFormVisible" :close-on-click-modal="closeOnClickModal" width="dialogWidth">
-      <el-form v-if="dialogName == '详情'">
-        <el-form-item :label="dialog.name" :label-width="formLabelWidth" v-for="dialog in dialogForm">
-          <el-input v-model="dialog.value" disabled auto-complete="off"></el-input>
-        </el-form-item>
-      </el-form>
+    <el-dialog :title="dialogName" :visible.sync="dialogFormVisible" :close-on-click-modal="closeOnClickModal" width="dialogWidth" v-if="dialogFormVisible">
       <hm-complex-form :schema="formSchema"
                        :columns="showUserColumns"
                        :buttons="showUserButtons"
                        :layout="layout"
-                       :tableId="tableId" v-if="dialogName != '详情'">
+                       :tableId="tableId"
+                       :tips="formTips"
+                       :formStyle="formStyle"
+                       ref="selectfood">
       </hm-complex-form>
     </el-dialog>
 
@@ -253,6 +248,7 @@
        *    {
        *      "name": "姓名",
        *      "codeCamel": "username",
+       *      "isSort": false, //是否排序,默认false
        *      "render": function(value){
        *        return "<a href='value'></a>"
        *      }
@@ -282,7 +278,7 @@
       },
       /**
        * 表格的选项,包括:pageSize、showExport、sortItem、sortOrder、showRefresh、showDeleteButton、
-       * buttonGroup、showDetail、dataProcessing、changeValue、newData、editData完整的示例为:
+       * buttonGroup、showDetail、dataProcessing、promiseProcessing、changeValue、newData、editData完整的示例为:
        *  {
        *    "pageSize": 10, // 默认为10条数据/页
        *    "showExport": false,  // 默认为不显示导出按钮
@@ -291,13 +287,12 @@
        *    "showRefresh": false, //默认不显示刷新按钮
        *    "showDeleteButton": false,  //默认不显示删除按钮
        *    "buttonGroup": false  //默认不以按钮组的方式呈现button
-       *    showDetail: {
-       *      isShow: false,      // 默认不显示详情
-       *      showColumns: ['mobile', 'loginid', 'username', 'email']
-       *    },
-       *    dataProcessing(value){}  // 对接口返回数据进行处理
+       *    tableCurrentChange(value){} // 设置点击某行所执行方法
+       *    dataProcessing(value, params, definedOperate){}  // 对接口返回数据进行处理(必须有返回值,返回值需为 [{}] 的形式,支持放回Promise对象)
+       *    promiseProcessing(value, params, definedOperate){}  // 对接口返回数据进行处理(必须有返回值,返回Promise对象)
        *    "changeValue": {      // 数据库字段转化显示,例如(0=否,1=是)
-       *      username: {1: '是', 0: '否'}
+       *      username: {1: '是', 0: '否'},
+       *      type: { 1: 'Hm-isChecked', 0: 'Hm-noChecked' } // 以多选框的形式展示Hm-isChecked(选择状态)、Hm-noChecked(未选择状态)
        *    },
        *    "newData": {  // 新建按钮的配置
        *      isShow: false,  // 默认不显示新建按钮
@@ -310,7 +305,10 @@
        *      showUserColumns: [], // 编辑表单的Columns配置,详情参考Form组件
        *      formSchema: {}, // 编辑表单的schema配置
        *      layout: {} // 布局方式
-       *    }
+       *    },
+       *    showDetail: { // 同编辑的的配置
+       *      isShow: false,      // 默认不显示详情
+       *    },
        *  }
        */
       options: {
@@ -321,7 +319,7 @@
        * 自定义表格选项,包括:definedParams、definedOperate、完整的示例为:
        *  {
        *    definedParams(params, operate){return params} // 自定义查询数据时的Params
-       *    definedOperate: [         // 自定义table顶部的操作,如果要根据多选框、输入框、时间选择器的值查询,需在自定义definedParams()方法中添加
+       *    definedOperate: [         // 自定义table顶部的操作,如果要根据下拉选择、输入框、时间选择器的值查询,需在自定义definedParams()方法中添加
        *      { type: 'select', label:'', placeholder: '', options:[{label: '', code: ''}], value:''}, // 自定义多选框
        *      { type: 'input', label:'', placeholder: '', code:'', value:''}, // 自定义输入框
        *      { type: 'datetime', label:'', placeholder: '', code:'', value:''},  // 自定义时间选择器
@@ -358,18 +356,19 @@
         multipleSelection: [], // 选择的数组
         dialogName: '',
 
+        isShowSelection: false, // 是否显示多选
         isShowNewButton: false, // 是否显示新建
         isShowEditDataButton: false, // 是否显示编辑
         isShowDeleteButton: false, // 是否显示删除
         isShowExport: false, // 是否显示导出按钮
         formSchema: {}, // form弹窗的Schema定义
         showUserColumns: [], // form弹窗的Columns定义
-        showUserButtons: [ // from弹窗显示按钮
-          { text: '确定', type: 1, method: this.formConfirm },
-          { text: '取消', type: 2, method: this.formCancel }
-        ],
+        showUserButtons: [], // from弹窗显示按钮,
         layout: { left: 0, middle: 24, right: 0 }, // form弹窗的布局方式
         tableId: '',
+        formTips: '',
+        formStyle: '',
+        showOverflowTooltip: false,
 
         isShowRefresh: false,
         buttonGroup: false,
@@ -377,32 +376,7 @@
         isShowDetail: false, // 是否显示详情按钮
 
         definedOperate: [], // 自定义操作
-
-        pickerOptions: { // 日期选项配置
-          disabledDate(time) {
-            return time.getTime() > Date.now()
-          },
-          shortcuts: [{
-            text: '今天',
-            onClick(picker) {
-              picker.$emit('pick', new Date())
-            }
-          }, {
-            text: '昨天',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() - 3600 * 1000 * 24)
-              picker.$emit('pick', date)
-            }
-          }, {
-            text: '一周前',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-              picker.$emit('pick', date)
-            }
-          }]
-        }
+        definedOperation: []
       }
     },
     computed: {
@@ -429,10 +403,16 @@
     },
     created() {
       // this.validate()
-
-      this.init()
-
-      this.getList()
+      const self = this
+      if (this.userDefined && this.userDefined.pretreatment) {
+        self.userDefined.pretreatment().then(function() {})
+        self.init()
+        self.getList()
+        console.log('IS-[object Promise]')
+      } else {
+        self.init()
+        self.getList()
+      }
     },
     methods: {
       indexMethod(index) {
@@ -469,7 +449,7 @@
             self.showColumns.push(tmp)
           })
         } else {
-          self.showColumns = JSON.parse(JSON.stringify(self.columns))
+          self.showColumns = _.cloneDeep(self.columns)
           // 将字符串对象进行替换处理
           _.each(self.showColumns, function(column, index) {
             if (typeof column === 'string') {
@@ -481,6 +461,11 @@
             }
           })
         }
+        if (self.showColumns) {
+          _.map(self.showColumns, function(item, index) {
+            item.isSort = item.isSort === undefined ? false : item.isSort === true ? 'custom' : false
+          })
+        }
 
         // 处理过滤条件
         if (self.filters) {
@@ -511,11 +496,22 @@
         console.log(request.defaults)
         console.log(`request.defaults.baseURL: ${request.defaults.baseURL}`)
       },
+      // 设置自定义组件
       setDefinedOperate() {
         const self = this
         if (self.userDefined.definedOperate) {
           self.definedOperate = self.userDefined.definedOperate
         }
+        if (self.userDefined.definedOperation) {
+          self.operationWidth += 50 * self.userDefined.definedOperation.length
+          self.definedOperation = self.userDefined.definedOperation
+        }
+      },
+      // 排序
+      sortChange(row) {
+        this.listQuery.sortItem = row.prop.replace(/([A-Z])/g, '_$1').toLowerCase()
+        this.listQuery.sortOrder = row.order === 'descending' ? 'desc' : 'asc'
+        this.getList()
       },
       getList() {
         const self = this
@@ -540,10 +536,6 @@
         request(self.schema.modelUnderscorePlural, {
           params: params
         }).then(resp => {
-          // 数据库字段转化显示
-          if (self.options && self.options.changeValue) {
-            resp.data = self.changeValue(resp.data)
-          }
           if (resp.data.length !== 0 && resp.data[0].superior !== undefined && resp.data[0].includes !== undefined &&
             resp.data[0].refers !== undefined && resp.data[0].relates !== undefined) {
             self.list = []
@@ -553,22 +545,39 @@
           } else {
             self.list = resp.data
           }
+          // 数据库字段转化显示
+          if (self.options && self.options.changeValue) {
+            self.list = self.changeValue(self.list)
+          }
 
           // 数据处理
           if (self.options && self.options.dataProcessing) {
-            self.list = self.options.dataProcessing(resp.data)
+            console.log('NO-[object Promise]')
+            self.list = self.options.dataProcessing(resp.data, params, self.definedOperate)
+          }
+          if (self.options && self.options.promiseProcessing) {
+            self.options.promiseProcessing(resp.data, params, self.definedOperate).then(function(dataList) {
+              self.list = dataList
+            })
           }
           self.total = parseInt(resp.headers.total)
           self.listLoading = false
         })
       },
+      tableCurrentChange(value) {
+        const self = this
+        if (self.options && self.options.tableCurrentChange) {
+          console.log('value', value)
+          self.options.tableCurrentChange(value)
+        }
+      },
       // 数据库字段转化显示,例如(0=否,1=是)
       changeValue(data) {
         const self = this
         _.map(data, function(item, index) {
           _.forEach(item, function(listValue, listKey) {
             if (self.options.changeValue[listKey] && self.options.changeValue[listKey][listValue]) {
-              item[listKey] = self.options.changeValue[listKey][listValue]
+              item[listKey] = self.options.changeValue[listKey][listValue] === 'Hm-isChecked' ? true : self.options.changeValue[listKey][listValue] === 'Hm-noChecked' ? false : self.options.changeValue[listKey][listValue]
             }
           })
         })
@@ -590,36 +599,57 @@
       // 添加一条数据
       openDialog(type, data) {
         const self = this
-        self.dialogFormVisible = true
+        if (type === 'editData' && self.userDefined && self.userDefined.definedEdit) {
+          self.userDefined.definedEdit(true, data)
+          return false
+        }
+        if (type === 'newData' && self.userDefined && self.userDefined.definedNew) {
+          self.userDefined.definedNew(true)
+          return false
+        }
+        if (type === 'detail' && self.userDefined && self.userDefined.definedDetail) {
+          self.userDefined.definedDetail(true, data)
+          return false
+        }
+        self.tableId = ''
         if (type === 'editData') {
           self.dialogName = '编辑'
+          if (self.options.editData.showUserButtons) {
+            self.showUserButtons = self.options.editData.showUserButtons
+          }
+          self.tableId = data.id
           self.showUserColumns = self.options.editData.showUserColumns
           self.formSchema = self.options.editData.formSchema
           self.layout = self.options.editData.layout
-          self.tableId = data.id
+          self.formTips = self.options.editData.tips
+          self.formStyle = self.options.editData.formStyle
         }
         if (type === 'newData') {
           self.dialogName = '新建'
+          if (self.options.newData.showUserButtons) {
+            self.showUserButtons = self.options.newData.showUserButtons
+          }
           self.showUserColumns = self.options.newData.showUserColumns
           self.formSchema = self.options.newData.formSchema
           self.layout = self.options.newData.layout
+          self.formTips = self.options.newData.tips
+          self.formStyle = self.options.newData.formStyle
         }
         if (type === 'detail') {
           self.dialogName = '详情'
-          self.dialogForm = []
-          _.each(self.options.showDetail.showColumns, function(columns) {
-            _.each(self.schema.columns, function(item, index) {
-              if (columns === item.codeCamel) {
-                self.dialogForm.push(item)
-              }
-            })
-          })
 
-          _.map(self.dialogForm, function(item, index) {
-            item.value = data[item.code]
-            item.id = data.id
-          })
+          if (self.options.detailData.showUserButtons) {
+            self.showUserButtons = self.options.detailData.showUserButtons
+          }
+          self.showUserColumns = self.options.showDetail.showUserColumns
+          self.formSchema = self.options.showDetail.formSchema
+          self.layout = self.options.showDetail.layout
+          self.formTips = self.options.showDetail.tips
+          self.formStyle = self.options.showDetail.formStyle
+          self.tableId = data.id
         }
+
+        self.dialogFormVisible = true
       },
       // 表单的提交
       formConfirm() {
@@ -748,6 +778,12 @@
           self.isShowDetail = self.options.showDetail.isShow
           self.operationWidth += 50
         }
+        if (self.options.showSelection) { // 设置是否显示多选
+          self.isShowSelection = self.options.showSelection
+        }
+        if (self.options.showOverflowTooltip) { // 当内容过长被隐藏时显示 tooltip
+          self.showOverflowTooltip = self.options.showOverflowTooltip
+        }
       },
       handleSelectionChange(val) {
         this.multipleSelection = val
diff --git a/src/views/haomo/components/tables/index.vue b/src/views/haomo/components/tables/index.vue
index 9f45ac742d1dfb095219b25c1fecc14ebacc936d..16480b596dbf79aa28bb91713ffb0da72dad4d3b 100644
--- a/src/views/haomo/components/tables/index.vue
+++ b/src/views/haomo/components/tables/index.vue
@@ -24,7 +24,11 @@
     },
     data() {
       return {
-        showUserColumns: ['mobile', 'loginid', 'username', 'email', 'createTime'],
+        showUserColumns: [
+          { name: '手机号', codeCamel: 'mobile', isSort: true },
+          { name: '登录ID', codeCamel: 'loginid', isSort: true },
+          'username', 'email', { name: '创建时间', codeCamel: 'createTime', isSort: true, width: '130px' }
+        ],
         userFilters: [
           { placeholder: '过滤手机号', 'mobile': { 'like': '' }, isShow: true },
           { placeholder: '过滤用户名', 'username': { 'equalTo': '' }, isShow: true },
@@ -51,7 +55,7 @@
         sortItem: 'create_time',
         sortOrder: 'desc',
         changeValue: {
-          username: { 1: '是', 0: '否' }
+          username: { 1: 'Hm-isChecked', 0: 'Hm-noChecked' }
         },
         newData: {
           isShow: true,
@@ -60,24 +64,33 @@
             { name: '登录ID', codeCamel: 'loginid', widgetType: 1 },
             { name: '类型', codeCamel: 'type', widgetType: 1 }
           ],
+          showUserButtons: [],
           formSchema: schema['HmUser'],
-          layout: { left: 0, middle: 24, right: 0 }
+          layout: { left: 0, middle: 24, right: 0 },
+          tips: {},
+          formStyle: {}
         },
         editData: {
           isShow: true,
           showUserColumns: [{ name: '姓名', codeCamel: 'username', widgetType: 1 }],
+          showUserButtons: [],
           formSchema: schema['HmUser'],
-          layout: { left: 0, middle: 24, right: 0 }
+          layout: { left: 0, middle: 24, right: 0 },
+          tips: {},
+          formStyle: {}
+        },
+        showDetail: {
+          isShow: true
         },
         showRefresh: true,
         showExport: true,
         showDeleteButton: true,
         buttonGroup: false,
-        showDetail: {
-          isShow: true,
-          showColumns: ['mobile', 'loginid', 'username', 'email']
-        }
-        // dataProcessing(value) {} // 处理返回后的数据,必须return 处理后的数据
+        showSelection: false,
+        showOverflowTooltip: true,
+        tableCurrentChange(value) {}
+        // dataProcessing(value, params, definedOperate) {}, // 处理返回后的数据,必须return 处理后的数据
+        // promiseProcessing(value, params, definedOperate) {} // 处理返回后的数据,必须return Promise对象
       }
       this.userDefined = {
         definedParams(params, operate) {
@@ -86,8 +99,19 @@
         definedOperate: [
           { type: 'select', label: '', placeholder: '类型', options: [{ label: '姓名', code: 'username' }, { label: '登录ID', code: 'loginid' }], value: '' },
           { type: 'input', label: '', placeholder: '邮箱', code: 'email', value: '' },
-          { type: 'datetime', label: '', placeholder: '创建时间', code: 'createTime', value: '' },
-          { type: 'button', label: '搜索', icon: 'el-icon-search', func: this.dropDown }]
+          { type: 'datetime', label: '', placeholder: '创建时间', code: 'createTime', value: '' }
+        ],
+        definedOperation: [{ label: '测试', func: this.dropDown }],
+        definedEdit() {
+
+        },
+        definedNew() {
+
+        },
+        definedDetail() {
+
+        }
+        // pretreatment() {}
       }
     },
     methods: {
@@ -95,8 +119,8 @@
         this.dialogFormVisible = false
         console.log('method1')
       },
-      dropDown() {
-        console.log('输出一些东西')
+      dropDown(value) {
+        console.log('输出一些东西', value)
       }
     }
   }