Kaynağa Gözat

update dept

smallwei 7 yıl önce
ebeveyn
işleme
57ab08c554
100 değiştirilmiş dosya ile 7634 ekleme ve 2465 silme
  1. 2464 2464
      package-lock.json
  2. 1 1
      package.json
  3. 7 0
      packages/carousel/index.js
  4. 49 0
      packages/carousel/src/main.vue
  5. 7 0
      packages/crud-cascader/index.js
  6. 7 0
      packages/crud-checkbox/index.js
  7. 7 0
      packages/crud-date/index.js
  8. 7 0
      packages/crud-input-number/index.js
  9. 7 0
      packages/crud-input/index.js
  10. 7 0
      packages/crud-radio/index.js
  11. 7 0
      packages/crud-rate/index.js
  12. 7 0
      packages/crud-select/index.js
  13. 7 0
      packages/crud-silder/index.js
  14. 7 0
      packages/crud-switch/index.js
  15. 7 0
      packages/crud-time/index.js
  16. 7 0
      packages/crud-upload/index.js
  17. 7 0
      packages/crud/index.js
  18. 67 0
      packages/crud/src/config.js
  19. 68 0
      packages/crud/src/crud-cascader.vue
  20. 47 0
      packages/crud/src/crud-checkbox.vue
  21. 85 0
      packages/crud/src/crud-components.vue
  22. 72 0
      packages/crud/src/crud-date.vue
  23. 65 0
      packages/crud/src/crud-input-number.vue
  24. 285 0
      packages/crud/src/crud-input.vue
  25. 41 0
      packages/crud/src/crud-radio.vue
  26. 64 0
      packages/crud/src/crud-rate.vue
  27. 58 0
      packages/crud/src/crud-select.vue
  28. 68 0
      packages/crud/src/crud-silder.vue
  29. 49 0
      packages/crud/src/crud-switch.vue
  30. 68 0
      packages/crud/src/crud-time.vue
  31. 230 0
      packages/crud/src/crud-upload.vue
  32. 834 0
      packages/crud/src/main.vue
  33. 7 0
      packages/data-box/index.js
  34. 52 0
      packages/data-box/src/data-box.vue
  35. 7 0
      packages/data-card/index.js
  36. 63 0
      packages/data-card/src/data-card.vue
  37. 7 0
      packages/data-display/index.js
  38. 53 0
      packages/data-display/src/data-display.vue
  39. 7 0
      packages/data-icons/index.js
  40. 52 0
      packages/data-icons/src/data-icons.vue
  41. 7 0
      packages/data-progress/index.js
  42. 53 0
      packages/data-progress/src/data-progress.vue
  43. 7 0
      packages/data-tabs/index.js
  44. 56 0
      packages/data-tabs/src/data-tabs.vue
  45. 7 0
      packages/date-group/index.js
  46. 91 0
      packages/date-group/src/main.vue
  47. 7 0
      packages/form-detail/index.js
  48. 111 0
      packages/form-detail/src/main.vue
  49. 7 0
      packages/form/index.js
  50. 410 0
      packages/form/src/main.vue
  51. 104 0
      packages/index.js
  52. 7 0
      packages/json/index.js
  53. 159 0
      packages/json/src/main.vue
  54. 45 0
      packages/mixins/bem.js
  55. 48 0
      packages/mixins/column.js
  56. 120 0
      packages/mixins/crud-compoents.js
  57. 166 0
      packages/mixins/crud.js
  58. 71 0
      packages/mixins/fun.js
  59. 7 0
      packages/steps/index.js
  60. 282 0
      packages/steps/src/main.vue
  61. 7 0
      packages/table-tree/index.js
  62. 25 0
      packages/table-tree/src/eval.js
  63. 130 0
      packages/table-tree/src/main.vue
  64. 7 0
      packages/tabs/index.js
  65. 231 0
      packages/tabs/src/main.vue
  66. 25 0
      packages/theme-chalk/gulpfile.js
  67. 1 0
      packages/theme-chalk/lib/carousel.css
  68. 1 0
      packages/theme-chalk/lib/common.css
  69. 1 0
      packages/theme-chalk/lib/crud-upload.css
  70. 1 0
      packages/theme-chalk/lib/crud.css
  71. 1 0
      packages/theme-chalk/lib/data-box.css
  72. 1 0
      packages/theme-chalk/lib/data-card.css
  73. 1 0
      packages/theme-chalk/lib/data-display.css
  74. 1 0
      packages/theme-chalk/lib/data-icons.css
  75. 1 0
      packages/theme-chalk/lib/data-progress.css
  76. 1 0
      packages/theme-chalk/lib/data-tabs.css
  77. 1 0
      packages/theme-chalk/lib/date-group.css
  78. 1 0
      packages/theme-chalk/lib/date-select.css
  79. 1 0
      packages/theme-chalk/lib/element-ui.css
  80. 1 0
      packages/theme-chalk/lib/form-detail.css
  81. 1 0
      packages/theme-chalk/lib/form-steps.css
  82. 1 0
      packages/theme-chalk/lib/form.css
  83. 1 0
      packages/theme-chalk/lib/index.css
  84. 1 0
      packages/theme-chalk/lib/json.css
  85. 1 0
      packages/theme-chalk/lib/select-date.css
  86. 1 0
      packages/theme-chalk/lib/steps.css
  87. 1 0
      packages/theme-chalk/lib/table-tree.css
  88. 1 0
      packages/theme-chalk/lib/tree.css
  89. 24 0
      packages/theme-chalk/package.json
  90. 30 0
      packages/theme-chalk/src/carousel.scss
  91. 38 0
      packages/theme-chalk/src/common.scss
  92. 27 0
      packages/theme-chalk/src/crud-upload.scss
  93. 95 0
      packages/theme-chalk/src/crud.scss
  94. 51 0
      packages/theme-chalk/src/data-box.scss
  95. 44 0
      packages/theme-chalk/src/data-card.scss
  96. 25 0
      packages/theme-chalk/src/data-display.scss
  97. 40 0
      packages/theme-chalk/src/data-icons.scss
  98. 20 0
      packages/theme-chalk/src/data-progress.scss
  99. 67 0
      packages/theme-chalk/src/data-tabs.scss
  100. 0 0
      packages/theme-chalk/src/date-group.scss

Dosya farkı çok büyük olduğundan ihmal edildi
+ 2464 - 2464
package-lock.json


+ 1 - 1
package.json

@@ -10,7 +10,7 @@
         "test:e2e": "vue-cli-service test:e2e"
     },
     "dependencies": {
-        "@smallwei/avue": "^1.4.0",
+        "@smallwei/avue": "^1.4.2",
         "avue-plugin-transfer": "^0.0.2",
         "avue-plugin-ueditor": "^0.0.1",
         "axios": "^0.18.0",

+ 7 - 0
packages/carousel/index.js

@@ -0,0 +1,7 @@
+import Carousel from './src/main';
+
+Carousel.install = function(Vue) {
+    Vue.component(Carousel.name, Carousel);
+};
+
+export default Carousel;

+ 49 - 0
packages/carousel/src/main.vue

@@ -0,0 +1,49 @@
+<template>
+  <div :class="b()">
+    <el-carousel :type="option.type"
+                 :height="option.height+'px'"
+                 :autoplay="option.autoplay"
+                 :interval="option.interval"
+                 indicator-position="outside">
+      <el-carousel-item v-for="(item,index) in data"
+                        :key="index">
+        <div :class="b('item')">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <div :class="b('img')"
+                 :style="{backgroundImage:'url('+item.src+')'}"></div>
+            <div :class="b('title')"
+                 v-if="item.title">{{ item.title }}</div>
+          </a>
+        </div>
+      </el-carousel-item>
+    </el-carousel>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'carousel',
+  data () {
+    return {
+
+    };
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  computed: {
+    data () {
+      return this.option.data || [];
+    },
+  },
+  created () { },
+  mounted () { },
+  watch: {},
+  methods: {}
+});
+</script>

+ 7 - 0
packages/crud-cascader/index.js

@@ -0,0 +1,7 @@
+import CrudCascader from '../crud/src/crud-cascader';
+
+CrudCascader.install = function(Vue) {
+  Vue.component(CrudCascader.name, CrudCascader);
+};
+
+export default CrudCascader;

+ 7 - 0
packages/crud-checkbox/index.js

@@ -0,0 +1,7 @@
+import CrudCheckBox from '../crud/src/crud-checkbox';
+
+CrudCheckBox.install = function(Vue) {
+  Vue.component(CrudCheckBox.name, CrudCheckBox);
+};
+
+export default CrudCheckBox;

+ 7 - 0
packages/crud-date/index.js

@@ -0,0 +1,7 @@
+import CrudData from '../crud/src/crud-date';
+
+CrudData.install = function(Vue) {
+  Vue.component(CrudData.name, CrudData);
+};
+
+export default CrudData;

+ 7 - 0
packages/crud-input-number/index.js

@@ -0,0 +1,7 @@
+import CrudInputNumber from '../crud/src/crud-input-number';
+
+CrudInputNumber.install = function(Vue) {
+  Vue.component(CrudInputNumber.name, CrudInputNumber);
+};
+
+export default CrudInputNumber;

+ 7 - 0
packages/crud-input/index.js

@@ -0,0 +1,7 @@
+import CrudInput from '../crud/src/crud-input';
+
+CrudInput.install = function(Vue) {
+  Vue.component(CrudInput.name, CrudInput);
+};
+
+export default CrudInput;

+ 7 - 0
packages/crud-radio/index.js

@@ -0,0 +1,7 @@
+import CrudRadio from '../crud/src/crud-radio';
+
+CrudRadio.install = function(Vue) {
+  Vue.component(CrudRadio.name, CrudRadio);
+};
+
+export default CrudRadio;

+ 7 - 0
packages/crud-rate/index.js

@@ -0,0 +1,7 @@
+import CrudRate from '../crud/src/crud-rate';
+
+CrudRate.install = function(Vue) {
+  Vue.component(CrudRate.name, CrudRate);
+};
+
+export default CrudRate;

+ 7 - 0
packages/crud-select/index.js

@@ -0,0 +1,7 @@
+import CrudSelect from '../crud/src/crud-select';
+
+CrudSelect.install = function(Vue) {
+  Vue.component(CrudSelect.name, CrudSelect);
+};
+
+export default CrudSelect;

+ 7 - 0
packages/crud-silder/index.js

@@ -0,0 +1,7 @@
+import CrudSilder from '../crud/src/crud-silder';
+
+CrudSilder.install = function(Vue) {
+  Vue.component(CrudSilder.name, CrudSilder);
+};
+
+export default CrudSilder;

+ 7 - 0
packages/crud-switch/index.js

@@ -0,0 +1,7 @@
+import CrudSwitch from '../crud/src/crud-switch';
+
+CrudSwitch.install = function(Vue) {
+  Vue.component(CrudSwitch.name, CrudSwitch);
+};
+
+export default CrudSwitch;

+ 7 - 0
packages/crud-time/index.js

@@ -0,0 +1,7 @@
+import CrudTime from '../crud/src/crud-time';
+
+CrudTime.install = function(Vue) {
+  Vue.component(CrudTime.name, CrudTime);
+};
+
+export default CrudTime;

+ 7 - 0
packages/crud-upload/index.js

@@ -0,0 +1,7 @@
+import CrudUpload from '../crud/src/crud-upload.vue';
+
+CrudUpload.install = function(Vue) {
+  Vue.component(CrudUpload.name, CrudUpload);
+};
+
+export default CrudUpload;

+ 7 - 0
packages/crud/index.js

@@ -0,0 +1,7 @@
+import Crud from './src/main';
+
+Crud.install = function(Vue) {
+  Vue.component(Crud.name, Crud);
+};
+
+export default Crud;

+ 67 - 0
packages/crud/src/config.js

@@ -0,0 +1,67 @@
+//crud配置文件
+export default {
+    //标题
+    editTitle: '编 辑',
+    addTitle: '新 增',
+    viewTitle: '查 看',
+    menuTitle: '操作',
+    tipStartTitle: '当前表格已选择',
+    tipEndTitle: '项',
+    //尺寸
+    menuWidth: 240,
+    //文字
+    viewBtnTitle: '查 看',
+    editBtnTitle: '编 辑',
+    addBtnTitle: '新 增',
+    delBtnTitle: '删 除',
+    updateBtnTitle: '修 改',
+    saveBtnTitle: '新 增',
+    cancelBtnTitle: '取 消',
+    columnBtnTitle: '多 选',
+    searchBtnTitle: '搜 索',
+    emptyBtnTitle: '清 空',
+    tipBtnTitle: '清空',
+    menuBtnTitle: '功 能',
+    cellEditBtnTitle: '修改',
+    cellSaveBtnTitle: '保存',
+    //图标
+    viewBtnIcon: 'el-icon-view',
+    editBtnIcon: 'el-icon-edit',
+    addBtnIcon: 'el-icon-plus',
+    delBtnIcon: 'el-icon-delete',
+    searchBtnIcon: 'el-icon-search',
+    emptyBtnIcon: 'el-icon-delete',
+    cellEditBtnIcon: 'el-icon-edit',
+    cellSaveBtnIcon: 'el-icon-check',
+    columnBtnIcon: 'el-icon-menu',
+    refreshBtnIcon: 'el-icon-refresh',
+    searchboxBtnIcon: 'el-icon-search',
+    //显隐
+    viewBtn: false,
+    editBtn: true,
+    addBtn: true,
+    delBtn: true,
+    cellBtn: false,
+    dateBtn: false,
+    refreshBtn: true,
+    columnBtn: true,
+    searchBtn: true,
+    menuBtn: false,
+    selectClearBtn: true,
+    searchShow: true,
+    tip: true,
+    dialogWidth: '50%',
+    formFullscreen: false,
+    customClass: '',
+    pageBackground: true,
+    page: true,
+    menu: true,
+    indexLabel: '#',
+    filterMultiple: true,
+    calcHeight: 300,
+    title: '表格标题',
+    width: '100%',
+    dateDefault: false,
+    //搜索参数
+    searchMultiple: ['checkbox', 'tree', 'select']
+}

+ 68 - 0
packages/crud/src/crud-cascader.vue

@@ -0,0 +1,68 @@
+<template>
+  <el-cascader :options="dic"
+               v-model="text"
+               :placeholder="placeholder?placeholder:`请选择${label}`"
+               :props="props"
+               :readonly="readonly"
+               :change-on-select="changeoOnSelect"
+               :clearable="disabled?false:clearable"
+               :expand-trigger="expandTrigger"
+               :show-all-levels="showAllLevels"
+               :filterable="filterable"
+               :separator="separator"
+               :disabled="disabled"
+               @click.native="handleClick"
+               @change="handleChange">
+  </el-cascader>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-cascader',
+  mixins: [crudCompoents()],
+  props: {
+    value: {
+      type: Array,
+      default: () => []
+    },
+    changeoOnSelect: {
+      type: Boolean,
+      default: false
+    },
+    expandTrigger: {
+      type: String,
+      default: 'hover'
+    },
+    showAllLevels: {
+      type: Boolean,
+      default: true
+    },
+    filterable: {
+      type: Boolean,
+      default: false
+    },
+    separator: {
+      type: String,
+      default: '/'
+    }
+  },
+  data () {
+    return {};
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 47 - 0
packages/crud/src/crud-checkbox.vue

@@ -0,0 +1,47 @@
+<template>
+  <el-checkbox-group v-model="text"
+                     @change="handleChange"
+                     :disabled="disabled"
+                     @click.native="handleClick">
+    <el-checkbox v-for="(item,index) in dic"
+                 :label="item[valueKey]"
+                 :border="border"
+                 :min="min"
+                 :readonly="readonly"
+                 :max="max"
+                 :disabled="item[disabledKey]"
+                 :key="index">{{item[labelKey]}}</el-checkbox>
+  </el-checkbox-group>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-checkbox',
+  mixins: [crudCompoents()],
+  data () {
+    return {};
+  },
+  props: {
+    value: {
+      type: Array,
+      default: () => []
+    }
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>
+

+ 85 - 0
packages/crud/src/crud-components.vue

@@ -0,0 +1,85 @@
+<template>
+  <div>
+    <el-table-column v-if="columnIndex.indexOf(column.prop)!=-1"
+                     v-for="(column,index) in columnOption"
+                     :prop="column.prop"
+                     :key="index"
+                     filter-placement="bottom-end"
+                     :filters="column.filters"
+                     :filter-method="column.filterMethod"
+                     :filter-multiple="vaildData(column.filterMultiple,true)"
+                     :show-overflow-tooltip="column.overHidden"
+                     :min-width="column.minWidth"
+                     :sortable="column.sortable"
+                     :align="vaildData(column.align,tableOption.align)"
+                     :header-align="vaildData(column.headerAlign,tableOption.headerAlign)"
+                     :width="column.width"
+                     :label="column.label"
+                     :fixed="column.fixed">
+      <crud-components v-if="column.children"
+                       :columnOption="column.children"
+                       :tableOption="tableOption"
+                       :tableForm="tableForm"
+                       :columnIndex="columnIndex"
+                       :DIC="DIC">
+        <template slot-scope="scope"
+                  v-for="item in column.children"
+                  :slot="item.prop">
+          <slot :row="scope.row"
+                :dic="scope.dic"
+                :label="scope.label"
+                :name="item.prop"
+                v-if="item.solt"></slot>
+        </template>
+      </crud-components>
+      <template slot-scope="scope">
+        <template v-if="cellEditFlag(scope.row,column)">
+          <component size="small"
+                     :is="getSearchType(column.type)"
+                     v-model="tableForm[column.prop]"
+                     :type="getType(column)"
+                     clearable
+                     :placeholder="column.label"
+                     :dic="setDic(column.dicData,DIC[column.dicData])"></component>
+        </template>
+        <slot :row="scope.row"
+              :dic="setDic(column.dicData,DIC[column.dicData])"
+              :label="detail(scope.row,column)"
+              :name="column.prop"
+              v-else-if="column.solt"></slot>
+        <template v-else>
+          <span v-html="detail(scope.row,column)"></span>
+        </template>
+      </template>
+    </el-table-column>
+  </div>
+</template>
+
+<script>
+import column from '../../mixins/column'
+import crudInput from './crud-input';
+import crudSelect from './crud-select';
+export default {
+  name: 'crud-components',
+  mixins: [column()],
+  props: [
+    'columnIndex',
+    'columnOption',
+    'tableOption',
+    'DIC',
+    'tableForm'
+  ],
+  components: {
+    crudInput,
+    crudSelect,
+  },
+  created () {
+    this.initFun();
+  },
+  methods: {
+  }
+}
+</script>
+
+<style>
+</style>

+ 72 - 0
packages/crud/src/crud-date.vue

@@ -0,0 +1,72 @@
+<template>
+  <el-date-picker :type="type"
+                  v-model="text"
+                  :size="size"
+                  :readonly="readonly"
+                  range-separator="至"
+                  :start-placeholder="startPlaceholder"
+                  :end-placeholder="endPlaceholder"
+                  :format="format"
+                  :clearable="disabled?false:clearable"
+                  :picker-options="pickerOptions"
+                  :value-format="valueFormat"
+                  :default-time="defaultTime"
+                  :placeholder="placeholder?placeholder:`请输入${label}`"
+                  @change="handleChange"
+                  @click.native="handleClick"
+                  :disabled="disabled"> </el-date-picker>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-date',
+  mixins: [crudCompoents()],
+  data () {
+    return {
+      text: ''
+    };
+  },
+  props: {
+    value: {
+    },
+    startPlaceholder: {
+      type: String,
+      default: '开始日期'
+    },
+    endPlaceholder: {
+      type: String,
+      default: '结束日期'
+    },
+    defaultTime: {
+      type: String
+    },
+    pickerOptions: {
+      type: Object,
+      default: () => { }
+    },
+    type: {
+      default: 'date'
+    },
+    valueFormat: {
+    },
+    format: {
+    }
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>
+

+ 65 - 0
packages/crud/src/crud-input-number.vue

@@ -0,0 +1,65 @@
+<template>
+  <el-input-number v-model="text"
+                   class="avue-input-number"
+                   @change="handleChange"
+                   @click.native="handleClick"
+                   :precision="precision"
+                   :size="size"
+                   :min="minRows"
+                   :max="maxRows"
+                   :clearable="disabled?false:clearable"
+                   :readonly="readonly"
+                   :controls-position="controlsPosition"
+                   :label="placeholder?placeholder:`请输入${label}`"
+                   :disabled="disabled"></el-input-number>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-input-number',
+  mixins: [crudCompoents()],
+  data () {
+    return {};
+  },
+  props: {
+    value: {
+      type: Number
+    },
+    step: {
+      type: Number,
+      default: 1
+    },
+    controlsPosition: {
+      type: String,
+      default: 'right'
+    },
+    precision: {
+      type: Number,
+      default: 0
+    },
+    minRows: {
+      type: Number,
+      default: -Infinity
+    },
+    maxRows: {
+      type: Number,
+      default: Infinity
+    }
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 285 - 0
packages/crud/src/crud-input.vue

@@ -0,0 +1,285 @@
+<template>
+  <div>
+    <el-input v-if="type==='tree'"
+              :size="size"
+              v-model="labelShow"
+              :type="typeParam"
+              :clearable="disabled?false:clearable"
+              :autosize="{ minRows: minRows, maxRows: maxRows}"
+              :prefix-icon="prefixIcon"
+              :suffix-icon="suffixIcon"
+              :placeholder="placeholder?placeholder:`请选择${label}`"
+              @change="handleChange"
+              :disabled="disabled"
+              :readonly="true"
+              @click.native="disabled?'':open()" />
+    <el-input v-else-if="type==='phone'"
+              :size="size"
+              :clearable="disabled?false:clearable"
+              v-model="text"
+              @click.native="handleClick"
+              :type="typeParam"
+              :maxlength="maxlength"
+              :autosize="{ minRows: minRows, maxRows: maxRows}"
+              :prefix-icon="prefixIcon"
+              :suffix-icon="suffixIcon"
+              :readonly="readonly"
+              :placeholder="placeholder?placeholder:`请输入${label}`"
+              @change="handleChange"
+              :disabled="disabled" />
+    <el-input v-else
+              :size="size"
+              :clearable="disabled?false:clearable"
+              v-model="text"
+              @click.native="handleClick"
+              :type="typeParam"
+              :maxlength="maxlength"
+              :minlength="minlength"
+              :autosize="{ minRows: minRows, maxRows: maxRows}"
+              :prefix-icon="prefixIcon"
+              :suffix-icon="suffixIcon"
+              :readonly="readonly"
+              :placeholder="placeholder?placeholder:`请输入${label}`"
+              @change="handleChange"
+              :disabled="disabled">
+      <template slot="prepend"
+                v-if="prepend">{{prepend}}</template>
+      <template slot="append"
+                v-if="append">{{append}}</template>
+    </el-input>
+    <el-dialog :visible.sync="box"
+               append-to-body
+               :title="`请选择${label}`"
+               width="50%">
+      <el-input style="margin-bottom:15px;"
+                placeholder="输入关键字进行过滤"
+                v-model="filterText"
+                v-if="filter">
+      </el-input>
+      <div class="avue-dialog">
+        <el-tree :data="dic"
+                 :node-key="valueKey"
+                 :show-checkbox="multiple"
+                 :props="props"
+                 ref="tree"
+                 @check="checkChange"
+                 :filter-node-method="filterNode"
+                 :default-expanded-keys="multiple?text:[]"
+                 :default-checked-keys="multiple?text:[]"
+                 :default-expand-all="defaultExpandAll"
+                 @node-click="handleNodeClick"></el-tree>
+      </div>
+
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+import { validatenull } from '../../utils/validate';
+export default create({
+  name: 'crud-input',
+  mixins: [crudCompoents()],
+  data () {
+    return {
+      filterText: '',
+      box: false,
+      labelText: this.multiple ? [] : ''
+    };
+  },
+  props: {
+    nodeClick: Function,
+    checked: Function,
+    value: {
+    },
+    filter: {
+      type: Boolean,
+      default: true
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    parent: {
+      type: Boolean,
+      default: true
+    },
+    defaultExpandAll: {
+      type: Boolean,
+      default: true
+    },
+    prefixIcon: {
+      type: String
+    },
+    suffixIcon: {
+      type: String
+    },
+    prepend: {
+      type: String
+    },
+    append: {
+      type: String
+    },
+    minlength: {
+      type: Number
+    },
+    maxlength: {
+      type: Number,
+      default: function () {
+        if (this.type === 'phone') return 11;
+      }
+    },
+    minRows: {
+      type: Number,
+      default: 3
+    },
+    maxRows: {
+      type: Number,
+      default: 4
+    }
+  },
+  watch: {
+    value () {
+      this.init();
+    },
+    filterText (val) {
+      this.$refs.tree.filter(val);
+    }
+  },
+  computed: {
+    labelShow () {
+      return this.multiple ? this.labelText.join('/').toString() : this.labelText;
+    },
+    textShow () {
+      if (this.textLen === 11) return `${this.text.substr(0, 3)} ${this.text.substr(3, 4)} ${this.text.substr(7, 4)}`
+      return this.text;
+    },
+    textLen () {
+      return this.text.length;
+    },
+    typeParam: function () {
+      if (this.type === 'textarea') {
+        return 'textarea';
+      } else if (this.type === 'password') {
+        return 'password';
+      } else {
+        return 'text';
+      }
+    }
+  },
+  created () { },
+  mounted () {
+    this.init();
+  },
+  methods: {
+    filterNode (value, data) {
+      if (!value) return true;
+      return data[this.labelKey].indexOf(value) !== -1;
+    },
+    checkChange (checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys) {
+      console.log(checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys);
+      this.text = [];
+      this.labelText = [];
+      checkedKeys.checkedNodes.forEach(node => {
+        if (validatenull(node[this.childrenKey])) {
+          this.text.push(node[this.valueKey]);
+          this.labelText.push(node[this.labelKey]);
+        }
+      });
+      if (typeof this.checked === 'function') this.checked(checkedNodes);
+      this.$emit('input', this.text);
+      this.$emit('change', this.text);
+    },
+    open () {
+      this.box = true;
+      this.handleClick();
+    },
+    init () {
+      if (this.type === 'tree') {
+        if (this.multiple) {
+          this.labelText = ['获取字典中...'];
+        } else {
+          this.labelText = '获取字典中...';
+        }
+        const check = setInterval(() => {
+          if (!validatenull(this.dic)) {
+            if (this.multiple) {
+              this.labelText = [];
+              this.text.forEach(ele => {
+                this.findLabelNode(this.dic, ele, this.props);
+              });
+            } else {
+              this.labelText = this.text;
+              this.findLabelNode(this.dic, this.text, this.props);
+            }
+            if (!this.parent) this.disabledParentNode(this.dic);
+            clearInterval(check);
+          } else {
+            this.labelText = '';
+          }
+        }, 500);
+      } else if (this.type === 'phone') {
+        if (!validatenull(this.text) && this.textLen == 11) {
+          this.text = this.textShow;
+        }
+      }
+    },
+    findLabelNode (dic, value, props) {
+      const labelKey = props.label || 'label';
+      const valueKey = props.value || 'value';
+      const childrenKey = props.children || 'children';
+      dic.forEach(ele => {
+        const children = ele[childrenKey];
+        if (ele[valueKey] === value) {
+          const label = ele[labelKey];
+          this.multiple ? this.labelText.push(label) : this.labelText = label;
+        } else if (!validatenull(children)) {
+          this.findLabelNode(children, value, props);
+        }
+      });
+    },
+    disabledParentNode (dic) {
+      dic.forEach(ele => {
+        const children = ele[this.childrenKey];
+        if (!validatenull(children)) {
+          ele.disabled = true;
+          this.disabledParentNode(children);
+        }
+      });
+    },
+    handleNodeClick (data) {
+      const callback = () => {
+        this.box = false;
+      }
+      if (typeof this.nodeClick === 'function') this.nodeClick(data);
+      if (this.multiple) return;
+      if (validatenull(data[this.childrenKey]) && !this.multiple || this.parent) {
+        const value = data[this.valueKey];
+        const label = data[this.labelKey];
+        this.text = value;
+        this.labelText = label;
+        this.$emit('input', value);
+        this.$emit('change', value);
+        callback();
+      }
+
+    },
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      let text = this.text;
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      if (this.type === 'phone') {
+        this.text = text.replace(/[^0-9.]/g, '');
+        this.text = this.textShow;
+        text = this.text.replace(/\s/g, "");
+      }
+      this.$emit('input', text);
+      this.$emit('change', text);
+    }
+  }
+});
+</script>
+

+ 41 - 0
packages/crud/src/crud-radio.vue

@@ -0,0 +1,41 @@
+<template>
+  <el-radio-group v-model="text"
+                  @change="handleChange"
+                  @click.native="handleClick"
+                  :disabled="disabled">
+    <el-radio v-for="(item,index) in dic"
+              :label="item[valueKey]"
+              :border="border"
+              :readonly="readonly"
+              :disabled="item[disabledKey]"
+              :key="index">{{item[labelKey]}}</el-radio>
+  </el-radio-group>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-radio',
+  mixins: [crudCompoents()],
+  data () {
+    return {};
+  },
+  props: {
+    value: {}
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 64 - 0
packages/crud/src/crud-rate.vue

@@ -0,0 +1,64 @@
+<template>
+  <el-rate v-model="text"
+           style="margin-top:10px"
+           @change="handleChange"
+           @click.native="handleClick"
+           :max="max"
+           :readonly="readonly"
+           :show-text="showText"
+           :icon-classes="iconClasses"
+           :void-icon-class="voidIconClass"
+           :disabled="disabled"
+           :colors="colors"></el-rate>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-rate',
+  mixins: [crudCompoents()],
+  props: {
+    value: {
+      type: Number,
+      default: 0
+    },
+    colors: {
+      type: Array
+    },
+    max: {
+      type: Number,
+      default: 5
+    },
+    iconClasses: {
+      type: Array
+    },
+    texts: {
+      type: Array
+    },
+    showText: {
+      type: Boolean,
+      default: false
+    },
+    voidIconClass: {
+      type: String
+    }
+  },
+  data () {
+    return {};
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 58 - 0
packages/crud/src/crud-select.vue

@@ -0,0 +1,58 @@
+<template>
+  <el-select v-model="text"
+             :size="size"
+             :multiple="multiple"
+             :filterable="filterable"
+             :readonly="readonly"
+             :clearable="disabled?false:clearable"
+             :placeholder="placeholder?placeholder:`请选择${label}`"
+             @change="handleChange"
+             @click.native="handleClick"
+             :disabled="disabled">
+    <el-option v-for="(item,index) in dic"
+               :key="index"
+               :disabled="item[disabledKey]"
+               :label="item[labelKey]"
+               :value="item[valueKey]">
+    </el-option>
+  </el-select>
+
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-select',
+  mixins: [crudCompoents()],
+  data () {
+    return {};
+  },
+  props: {
+    value: {
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    filterable: {
+      type: Boolean,
+      default: false
+    },
+  },
+  watch: {
+  },
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 68 - 0
packages/crud/src/crud-silder.vue

@@ -0,0 +1,68 @@
+<template>
+  <el-slider v-model="text"
+             :disabled="disabled"
+             :step="step"
+             :min="min"
+             :max="max"
+             :range="range"
+             :show-stops="showStops"
+             :show-input="showInput"
+             :format-tooltip="formatTooltip"
+             @click.native="handleClick"
+             @change="handleChange"></el-slider>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-silder',
+  mixins: [crudCompoents()],
+  props: {
+    value: {
+
+    },
+    step: {
+      type: Number
+    },
+    min: {
+      type: Number
+    },
+    max: {
+      type: Number
+    },
+    range: {
+      type: Boolean,
+      default: false
+    },
+    showInput: {
+      type: Boolean,
+      default: false
+    },
+    showStops: {
+      type: Boolean,
+      default: false
+    },
+    formatTooltip: Function
+  },
+  data () {
+    return {};
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    },
+    getDic (index) {
+      return this.dic[index] ? this.dic[index] : {};
+    }
+  }
+});
+</script>

+ 49 - 0
packages/crud/src/crud-switch.vue

@@ -0,0 +1,49 @@
+<template>
+  <div>
+    <el-switch v-model="text"
+               @change="handleChange"
+               @click.native="handleClick"
+               :active-text="getDic(0)[labelKey]"
+               :active-value="getDic(0)[valueKey]"
+               :inactive-value="getDic(1)[valueKey]"
+               :inactive-text="getDic(1)[labelKey]"
+               :disabled="disabled"
+               :readonly="readonly"
+               :size="size">
+    </el-switch>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-switch',
+  mixins: [crudCompoents()],
+  props: {
+    value: {
+
+    }
+  },
+  data () {
+    return {};
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    },
+    getDic (index) {
+      return this.dic[index] ? this.dic[index] : {};
+    }
+  }
+});
+</script>
+

+ 68 - 0
packages/crud/src/crud-time.vue

@@ -0,0 +1,68 @@
+<template>
+  <el-time-picker v-model="text"
+                  :is-range="isRange"
+                  :size="size"
+                  range-separator="至"
+                  :start-placeholder="startPlaceholder"
+                  :end-placeholder="endPlaceholder"
+                  :format="format"
+                  :readonly="readonly"
+                  :clearable="disabled?false:clearable"
+                  :value-format="valueFormat"
+                  :placeholder="placeholder?placeholder:`请输入${label}`"
+                  @change="handleChange"
+                  @click.native="handleClick"
+                  :disabled="disabled"> </el-time-picker>
+</template>
+
+<script>
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-time',
+  mixins: [crudCompoents()],
+  data () {
+    return {};
+  },
+  props: {
+    startPlaceholder: {
+      type: String,
+      default: '开始时间'
+    },
+    endPlaceholder: {
+      type: String,
+      default: '结束时间'
+    },
+    value: {
+      required: true
+    },
+    valueFormat: {
+      default: ''
+    },
+    type: {
+      default: ''
+    },
+    format: {
+      default: ''
+    }
+  },
+  watch: {},
+  created () { },
+  mounted () { },
+  computed: {
+    isRange () {
+      return this.type === 'timerange'
+    }
+  },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (value) {
+      if (typeof this.change === 'function') this.change({ value: value, column: this.column });
+      this.$emit('input', value);
+      this.$emit('change', value);
+    }
+  }
+});
+</script>

+ 230 - 0
packages/crud/src/crud-upload.vue

@@ -0,0 +1,230 @@
+<template>
+  <div :class="b()">
+    <el-upload :class="b({'list':listType=='picture-img'})"
+               @click.native="handleClick"
+               :action="action"
+               :on-remove="handleRemove"
+               :before-remove="beforeRemove"
+               :multiple="multiple"
+               :on-preview="handlePictureCardPreview"
+               :limit="status?99:limit"
+               :http-request="httpRequest"
+               :drag="drag"
+               :readonly="readonly"
+               :show-file-list="showFileList"
+               :list-type="listType"
+               :on-change="handleChange"
+               :on-exceed="handleExceed"
+               :disabled="disabled"
+               :file-list="fileList">
+      <template v-if="listType=='picture-card'">
+        <i class="el-icon-plus"></i>
+      </template>
+      <template v-else-if="listType=='picture-img'">
+        <img v-if="imageUrl"
+             :src="imageUrl"
+             :class="b('avatar')">
+        <i v-else
+           class="el-icon-plus"
+           :class="b('icon')"></i>
+      </template>
+      <template v-else-if="drag">
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">将文件拖到此处,或
+          <em>点击上传</em>
+        </div>
+      </template>
+      <template v-else>
+        <el-button size="small"
+                   type="primary">点击上传</el-button>
+      </template>
+      <div slot="tip"
+           class="el-upload__tip">{{tip}}</div>
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <div class="avue-dialog">
+        <img width="100%"
+             :src="dialogImageUrl"
+             alt="">
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+
+import create from '../../utils/create';
+import crudCompoents from '../../mixins/crud-compoents.js';
+export default create({
+  name: 'crud-upload',
+  mixins: [crudCompoents()],
+  data () {
+    return {
+      loading: false,
+      dialogImageUrl: '',
+      dialogVisible: false,
+      text: this.status ? '' : [],
+      file: {}
+    };
+  },
+  props: {
+    value: {
+
+    },
+    showFileList: {
+      type: Boolean,
+      default: true
+    },
+    limit: {
+      type: Number,
+      default: 3
+    },
+    listType: {
+      type: String
+    },
+    drag: {
+      type: Boolean,
+      default: false
+    },
+    multiple: {
+      type: Boolean,
+      default: true
+    },
+    loadText: {
+      type: String,
+      default: '文件上传中,请稍等'
+    },
+    action: {
+      type: String,
+      default: ''
+    },
+    uploadBefore: Function,
+    uploadAfter: Function
+  },
+  computed: {
+    status () {
+      return this.listType === 'picture-img';
+    },
+    isArray () {
+      return this.dataType === 'array';
+    },
+    imageUrl () {
+      return this.status ? this.text : '';
+    },
+    fileList () {
+      let list = [];
+      if (!Array.isArray(this.text) && !this.status) this.text = (this.text || '').split(',');
+      if (!this.status) {
+        this.text.forEach((ele, index) => {
+          let obj;
+          if (this.isArray) {
+            obj = {
+              name: index,
+              url: ele,
+            }
+          } else {
+            obj = {
+              name: ele[this.labelKey],
+              url: ele[this.valueKey],
+            }
+          }
+          list.push(obj)
+        })
+      }
+      return list;
+    }
+  },
+  created () {
+
+  },
+  watch: {
+  },
+  mounted () { },
+  methods: {
+    handleClick () {
+      if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
+    },
+    handleChange (file, fileList) {
+      if (typeof this.change === 'function') this.change({ value: this.text, column: this.column });
+    },
+    handleSuccess (file) {
+      if (!this.status) {
+        if (this.isArray) {
+          this.text.push(file[this.nameKey]);
+        } else {
+          let obj = {};
+          obj[this.labelKey] = file[this.nameKey];
+          obj[this.valueKey] = file[this.urlKey];
+          this.text.push(obj);
+        }
+      } else {
+        this.text = file[this.urlKey];
+      }
+      this.$message.success('上传成功');
+      this.setVal();
+
+    },
+    handleRemove (file, fileList) {
+      this.delete(file);
+      this.$message.success('删除成功');
+      this.setVal();
+    },
+    handleError () {
+      this.$message.error('上传失败');
+    },
+    delete (file) {
+      this.text.forEach((ele, index) => {
+        if (ele[this.valueKey] === file.url) this.text.splice(index, 1);
+      })
+    },
+    show (res) {
+      this.loading.close();
+      this.handleSuccess(res.data);
+    },
+    hide () {
+      this.loading.close();
+      this.handleError();
+    },
+    httpRequest (config) {
+      this.loading = this.$loading({
+        lock: true,
+        text: this.loadText,
+        spinner: 'el-icon-loading',
+      });
+      const file = config.file;
+      this.file = config.file;
+      const headers = { 'Content-Type': 'multipart/form-data' }
+      let param = new FormData()
+      param.append('file', file, file.name)
+
+      const callack = () => {
+        this.$http.post(this.action, param, { headers }).then(res => {
+          if (typeof this.uploadAfter === 'function') this.uploadAfter(res, () => {
+            this.show(res)
+          })
+          else this.show(res);
+        }).catch((error) => {
+          if (typeof this.uploadAfter === 'function') this.uploadAfter(error, this.hide);
+          else this.hide(error);
+        });
+      };
+      if (typeof this.uploadBefore === 'function') this.uploadBefore(this.file, callack);
+      else callack();
+    },
+    setVal () {
+      this.$emit('input', this.text);
+      this.$emit('change', this.text);
+    },
+    handleExceed (files, fileList) {
+      this.$message.warning(`当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共上传了 ${files.length + fileList.length} 个文件`);
+    },
+    handlePictureCardPreview (file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    beforeRemove (file) {
+      return this.$confirm(`确定移除 ${file.name}?`);
+    }
+  }
+});
+</script>

+ 834 - 0
packages/crud/src/main.vue

@@ -0,0 +1,834 @@
+<template>
+  <div :class="b()">
+    <el-card :class="b('box')">
+      <div slot="header"
+           :class="b('title')"
+           v-if="vaildData(tableOption.title,false) || vaildData(tableOption.dateBtn,config.dateBtn)">
+        <span>{{tableOption.title}}</span>
+        <date-group @change="dateChange"
+                    v-if="vaildData(tableOption.dateBtn,config.dateBtn)"
+                    :default="vaildData(tableOption.dateDefault,config.dateDefault)"
+                    :size="isMediumSize">
+        </date-group>
+      </div>
+      <div :class="b('header')"
+           v-if="vaildData(tableOption.header,true)">
+        <el-collapse-transition>
+          <el-form :model="searchForm"
+                   :inline="true"
+                   ref="searchForm"
+                   v-if="searchShow && searchFlag">
+            <!-- 循环列搜索框 -->
+            <el-form-item :prop="column.prop"
+                          :label="column.label"
+                          v-for="(column,index) in columnOption"
+                          :key="index"
+                          v-if="column.search">
+              <component :is="getSearchType(column.type)"
+                         :size="isMediumSize"
+                         v-model="searchForm[column.prop]"
+                         :type="getType(column)"
+                         :props="column.props || tableOption.props"
+                         :format="column.format"
+                         :parent="column.parent"
+                         :defaultExpandAll="column.defaultExpandAll"
+                         :filterable="column.searchFilterable"
+                         :filter-method="column.searchFilterMethod"
+                         :value-format="column.valueFormat"
+                         :multiple="config.searchMultiple.includes(column.type) && vaildData(column.searchMmultiple,false)"
+                         :clearable="column.searchClearable"
+                         :placeholder="column.searchPlaceholder || column.label"
+                         :dic="setDic(column.dicData,DIC[column.dicData])"></component>
+            </el-form-item>
+            <slot name="search"></slot>
+            <el-form-item>
+              <el-button type="primary"
+                         @click="searchChange"
+                         :icon="config.searchBtnIcon"
+                         :size="isMediumSize">{{config.searchBtnTitle}}</el-button>
+              <el-button @click="searchReset"
+                         :icon="config.emptyBtnIcon"
+                         :size="isMediumSize">{{config.emptyBtnTitle}}</el-button>
+              <slot name="searchMenu"></slot>
+            </el-form-item>
+          </el-form>
+        </el-collapse-transition>
+      </div>
+      <!-- 表格功能列 -->
+      <div :class="b('menu')"
+           v-if="vaildData(tableOption.header,true)">
+        <div :class="b('left')">
+          <el-button type="primary"
+                     @click="rowAdd"
+                     :icon="config.addBtnIcon"
+                     :size="isMediumSize"
+                     v-if="vaildData(tableOption.addBtn,config.addBtn)">{{config.addBtnTitle}}</el-button>
+          <slot name="menuLeft"></slot>
+        </div>
+        <div :class="b('right')">
+          <slot name="menuRight"></slot>
+          <el-button :icon="config.refreshBtnIcon"
+                     circle
+                     :size="isMediumSize"
+                     @click="refreshChange"
+                     v-if="vaildData(tableOption.refreshBtn,config.refreshBtn)"></el-button>
+          <el-button :icon="config.columnBtnIcon"
+                     circle
+                     :size="isMediumSize"
+                     @click="columnBox=true"
+                     v-if="vaildData(tableOption.columnBtn,config.columnBtn)"></el-button>
+          <el-button :icon="config.searchboxBtnIcon"
+                     circle
+                     :size="isMediumSize"
+                     @click="searchShow=!searchShow"
+                     v-if="searchFlag && vaildData(tableOption.searchBtn,config.searchBtn)"></el-button>
+        </div>
+      </div>
+      <el-tag class="avue-tip"
+              v-if="vaildData(tableOption.tip,config.tip) && tableOption.selection">
+        <i class="el-icon-info avue-tip__icon">&nbsp;</i>
+        <span class="avue-tip__name">
+          {{config.tipStartTitle}}
+          <span class="avue-tip__name--bold">{{selectLen}}</span> {{config.tipEndTitle}}
+        </span>
+        <span class="avue-tip__btn"
+              @click="selectClear"
+              v-if="vaildData(tableOption.selectClearBtn,config.selectClearBtn) && tableOption.selection">
+          {{config.tipBtnTitle}}
+        </span>
+      </el-tag>
+      <el-table :data="list"
+                :size="controlSize"
+                :highlight-current-row="tableOption.highlightCurrentRow"
+                @current-change="currentRowChange"
+                :show-summary="tableOption.showSummary"
+                :summary-method="tableSummaryMethod"
+                :sum-text="tableOption.sumText"
+                :empty-text="tableOption.emptyText"
+                :span-method="tableSpanMethod"
+                :stripe="tableOption.stripe"
+                :show-header="tableOption.showHeader"
+                :default-sort="tableOption.defaultSort"
+                @row-click="rowClick"
+                @row-dblclick="rowDblclick"
+                :row-class-name="rowClassName"
+                :max-height="tableOption.maxHeight"
+                :height="tableOption.height=='auto'?(clientHeight - vaildData(tableOption.calcHeight,config.calcHeight)):tableOption.height"
+                ref="table"
+                :width="setPx(tableOption.width,config.width)"
+                :border="tableOption.border"
+                v-loading="tableLoading"
+                @selection-change="selectionChange"
+                @sort-change="sortChange">
+        <!-- 暂无数据提醒 -->
+        <template slot="empty">
+          <slot name="empty"
+                v-if="$slots.empty"></slot>
+          <span @click="refreshChange"
+                v-else
+                style="cursor:pointer">暂无数据,点击刷新</span>
+        </template>
+
+        <!-- 折叠面板  -->
+        <el-table-column type="expand"
+                         width="50"
+                         fixed="left"
+                         align="center"
+                         v-if="tableOption.expand">
+          <template slot-scope="props">
+            <slot :row="props.row"
+                  name="expand"></slot>
+          </template>
+        </el-table-column>
+        <!-- 选择框 -->
+        <el-table-column v-if="tableOption.selection"
+                         type="selection"
+                         width="50"
+                         fixed="left"
+                         align="center">
+        </el-table-column>
+        <!-- 序号 -->
+        <el-table-column v-if="tableOption.index"
+                         :label="vaildData(tableOption.indexLabel,config.indexLabel)"
+                         type="index"
+                         width="50"
+                         :index="indexMethod"
+                         fixed="left"
+                         align="center">
+        </el-table-column>
+        <!-- 循环列 -->
+        <el-table-column v-if="columnIndex.indexOf(column.prop)!=-1"
+                         v-for="(column,index) in columnOption"
+                         :prop="column.prop"
+                         :key="index"
+                         filter-placement="bottom-end"
+                         :filters="column.filters"
+                         :filter-method="column.filterMethod"
+                         :filter-multiple="vaildData(column.filterMultiple,config.filterMultiple)"
+                         :show-overflow-tooltip="column.overHidden"
+                         :min-width="column.minWidth"
+                         :sortable="column.sortable"
+                         :align="vaildData(column.align,tableOption.align)"
+                         :header-align="vaildData(column.headerAlign,tableOption.headerAlign)"
+                         :width="column.width"
+                         :label="column.label"
+                         :fixed="column.fixed">
+          <crud-components v-if="column.children"
+                           :columnOption="column.children"
+                           :tableOption="tableOption"
+                           :tableForm="tableForm"
+                           :columnIndex="columnIndex"
+                           :DIC="DIC">
+            <template slot-scope="scope"
+                      v-for="item in column.children"
+                      :slot="item.prop">
+              <slot :row="scope.row"
+                    :dic="scope.dic"
+                    :label="scope.label"
+                    :name="item.prop"
+                    v-if="item.solt"></slot>
+            </template>
+          </crud-components>
+          <template slot-scope="scope">
+            <template v-if="cellEditFlag(scope.row,column)">
+              <component :is="getSearchType(column.type)"
+                         v-model="tableForm[column.prop]"
+                         :type="getType(column)"
+                         :clearable="column.clearable"
+                         :size="isMediumSize"
+                         :placeholder="column.label"
+                         :dic="setDic(column.dicData,DIC[column.dicData])"></component>
+            </template>
+            <slot :row="scope.row"
+                  :dic="setDic(column.dicData,DIC[column.dicData])"
+                  :label="detail(scope.row,column)"
+                  :name="column.prop"
+                  v-else-if="column.solt"></slot>
+            <template v-else>
+              <span v-html="detail(scope.row,column)"></span>
+            </template>
+          </template>
+        </el-table-column>
+        <el-table-column fixed="right"
+                         v-if="vaildData(tableOption.menu,config.menu)"
+                         :label="config.menuTitle"
+                         :align="tableOption.menuAlign"
+                         :header-align="tableOption.menuHeaderAlign"
+                         :width="vaildData(tableOption.menuWidth,config.menuWidth)">
+          <template slot-scope="scope">
+            <el-dropdown v-if="menuType==='menu'"
+                         style="margin-right:9px;">
+
+              <el-button type="primary"
+                         :size="isMediumSize">
+                {{config.menuBtnTitle}}<i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item v-if="vaildData(tableOption.viewBtn,true)"
+                                  @click.native="rowView(scope.row,scope.$index)">{{config.viewBtnTitle}}</el-dropdown-item>
+                <el-dropdown-item divided
+                                  v-if="vaildData(tableOption.editBtn,true)"
+                                  @click.native="rowEdit(scope.row,scope.$index)">{{config.editBtnTitle}}</el-dropdown-item>
+                <el-dropdown-item divided
+                                  v-if="vaildData(tableOption.delBtn,true)"
+                                  @click.native="rowDel(scope.row,scope.$index)">{{config.delBtnTitle}}</el-dropdown-item>
+                <slot name="menuBtn"
+                      :row="scope.row"
+                      :dic="scope.dic"
+                      :label="scope.label"
+                      :index="scope.$index"></slot>
+              </el-dropdown-menu>
+            </el-dropdown>
+            <template v-else-if="['button','text','icon'].includes(menuType)">
+              <el-button :type="menuText('primary')"
+                         :icon="scope.row.$cellEdit?config.cellSaveBtnIcon:config.cellEditBtnIcon"
+                         :size="isMediumSize"
+                         @click.stop="rowCell(scope.row,scope.$index)"
+                         v-if="vaildData(tableOption.cellBtn ,config.cellBtn)">{{menuIcon(scope.row.$cellEdit?config.cellSaveBtnTitle:config.cellEditBtnTitle)}}</el-button>
+              <el-button :type="menuText('success')"
+                         :icon="config.viewBtnIcon"
+                         :size="isMediumSize"
+                         @click.stop="rowView(scope.row,scope.$index)"
+                         v-if="vaildData(tableOption.viewBtn,config.viewBtn)">{{menuIcon(config.viewBtnTitle)}}</el-button>
+              <el-button :type="menuText('primary')"
+                         :icon="config.editBtnIcon"
+                         :size="isMediumSize"
+                         @click.stop="rowEdit(scope.row,scope.$index)"
+                         v-if="vaildData(tableOption.editBtn,config.editBtn)">{{menuIcon(config.editBtnTitle)}}</el-button>
+              <el-button :type="menuText('danger')"
+                         :icon="config.delBtnIcon"
+                         :size="isMediumSize"
+                         @click.stop="rowDel(scope.row,scope.$index)"
+                         v-if="vaildData(tableOption.delBtn,config.delBtn)">{{menuIcon(config.delBtnTitle)}}</el-button>
+            </template>
+            <slot name="menu"
+                  :row="scope.row"
+                  :dic="scope.dic"
+                  :label="scope.label"
+                  :index="scope.$index"></slot>
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 分页 -->
+      <div :class="b('pagination')"
+           v-if="vaildData(tableOption.page,config.page) && listLen">
+        <el-pagination :current-page.sync="defaultPage.currentPage"
+                       :background="vaildData(defaultPage.pageBackground,config.pageBackground)"
+                       :page-size="defaultPage.pageSize"
+                       :page-sizes="defaultPage.pageSizes"
+                       @size-change="sizeChange"
+                       @current-change="currentChange"
+                       layout="total, sizes, prev, pager, next, jumper"
+                       :total="defaultPage.total"></el-pagination>
+      </div>
+    </el-card>
+    <!-- 表单 -->
+    <el-dialog lock-scroll
+               :custom-class="vaildData(tableOption.customClass,config.customClass)"
+               :fullscreen="tableOption.dialogFullscreen"
+               :modal-append-to-body="false"
+               :append-to-body="true"
+               :title="dialogTitle"
+               :close-on-press-escape="tableOption.dialogEscape"
+               :close-on-click-modal="tableOption.dialogClickModal"
+               :modal="tableOption.dialogModal"
+               :show-close="tableOption.dialogCloseBtn"
+               :visible.sync="boxVisible"
+               :width="vaildData(tableOption.dialogWidth,config.dialogWidth)"
+               @close="closeDialog">
+      <div :class="b('dialog', ['overflow'])">
+        <avue-form v-model="tableForm"
+                   ref="tableForm"
+                   :disabled="keyBtn"
+                   :uploadBefore="uploadBefore"
+                   :uploadAfter="uploadAfter"
+                   :option="formOption">
+          <template slot-scope="scope"
+                    v-for="item in columnOption"
+                    :slot="item.prop">
+            <slot :value="scope.value"
+                  :column="scope.column"
+                  :dic="scope.dic"
+                  :row="tableForm"
+                  :index="tableIndex"
+                  :name="item.prop+'Form'"
+                  v-if="item.formsolt"></slot>
+          </template>
+        </avue-form>
+      </div>
+      <span slot="footer"
+            class="dialog-footer">
+        <!-- 弹出框按钮组 -->
+        <slot name="menuForm"
+              :row="tableForm"
+              :type="boxType"></slot>
+        <el-button type="primary"
+                   @click="rowUpdate"
+                   :size="controlSize"
+                   v-if="boxType=='edit'"
+                   :loading="keyBtn">{{vaildData(tableOption.updateBtnTitle,config.updateBtnTitle)}}</el-button>
+        <el-button type="primary"
+                   @click="rowSave"
+                   :size="controlSize"
+                   :loading="keyBtn"
+                   v-else-if="boxType=='add'">{{vaildData(tableOption.saveBtnTitle,config.saveBtnTitle)}}</el-button>
+        <el-button :size="controlSize"
+                   @click="closeDialog">{{vaildData(tableOption.cancelBtnTitle,config.cancelBtnTitle)}}</el-button>
+      </span>
+    </el-dialog>
+    <!-- 动态列 -->
+    <el-dialog lock-scroll
+               :modal-append-to-body="false"
+               :append-to-body="true"
+               :title="config.columnBtnTitle"
+               :visible.sync="columnBox">
+      <el-checkbox-group v-model="columnIndex">
+        <el-row :span="24">
+          <el-col :span="6"
+                  v-for="(item,index) in columnList"
+                  :key="index">
+            <el-checkbox :label="item.prop">{{item.label}}</el-checkbox>
+          </el-col>
+        </el-row>
+      </el-checkbox-group>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import dateGroup from '../../date-group'
+import create from '../../utils/create';
+import crud from '../../mixins/crud.js';
+import column from '../../mixins/column.js';
+import crudComponents from './crud-components';
+import config from './config.js';
+import {
+  validatenull
+} from '../../utils/validate.js';
+import {
+  setTimeout
+} from 'timers';
+export default create({
+  name: 'crud',
+  mixins: [crud(), column()],
+  components: {
+    crudComponents,
+    dateGroup
+  },
+  data () {
+    return {
+      clientHeight: document.documentElement.clientHeight,
+      defaultForm: {
+        tableForm: {},
+        searchForm: {}
+      },
+      defaultPage: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 10, // 每页显示多少条
+        pageSizes: [10, 20, 30, 40, 50, 100],
+        background: true // 背景颜色
+      },
+      defaultParam: ['$index'],
+      keyBtn: false,
+      config: config,
+      list: [],
+      searchShow: true,
+      searchForm: {},
+      boxVisible: false,
+      boxType: 'add',
+      columnIndex: [],
+      columnBox: false,
+      columnList: [],
+      tableForm: {},
+      tableOption: {},
+      tableFormRules: {},
+      tableIndex: -1,
+      tableSelect: [],
+    };
+  },
+  created () {
+    // 初始化数据
+    this.dataInit();
+    // 初始化列
+    this.columnInit();
+    //初始化分页
+    this.$emit('on-load', this.defaultPage);
+    this.pageInit();
+  },
+  computed: {
+    dialogTitle () {
+      const key = `${this.boxType}Title`;
+      return this.tableOption[key] || this.config[key];
+    },
+    menuType () {
+      return this.tableOption.menuType || 'button'
+    },
+    listLen () {
+      return this.list.length !== 0
+    },
+    columnOption () {
+      return this.tableOption.column || [];
+    },
+    sumColumnList () {
+      return this.tableOption.sumColumnList || [];
+    },
+    selectLen () {
+      return this.tableSelect ? this.tableSelect.length : 0;
+    },
+    searchSolt () {
+      return this.vaildData(this.tableOption.searchsolt, false);
+    },
+    searchFlag () {
+      if (this.searchSolt) return true;
+      else return !validatenull(this.searchForm);
+    },
+    formOption () {
+      let option = this.deepClone(this.tableOption);
+      option.submitBtn = false;
+      option.submitPostion = 'right';
+      option.boxType = this.boxType;
+      option.dicFlag = false;
+      option.dicData = this.DIC;
+      option.emptyBtn = false;
+      return option;
+    }
+  },
+  watch: {
+    value: {
+      handler () {
+        this.formVal();
+      },
+      deep: true
+    },
+    page: {
+      handler () {
+        this.pageInit();
+      },
+      deep: true
+    },
+    columnOption () {
+      this.columnInit();
+    },
+    data () {
+      this.dataInit();
+    }
+  },
+  mounted () { },
+  props: {
+    value: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    },
+    spanMethod: Function,
+    summaryMethod: Function,
+    beforeClose: Function,
+    beforeOpen: Function,
+    rowClassName: Function,
+    uploadBefore: Function,
+    uploadAfter: Function,
+    page: {
+      type: Object,
+      default () {
+        return {};
+      }
+    },
+    tableLoading: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Array,
+      required: true,
+      default: () => {
+        return [];
+      }
+    }
+  },
+  methods: {
+    menuIcon (value) {
+      return this.menuType === 'icon' ? '' : value
+    },
+    menuText (value) {
+      return this.menuType === 'text' ? 'text' : value
+    },
+    closeDialog () {
+      this.tableIndex = -1;
+      this.tableForm = {};
+      this.boxVisible = false;
+      this.keyBtn = false;
+      this.hide();
+    },
+    selectClear () {
+      this.$refs.table.clearSelection();
+    },
+    indexMethod (index) {
+      return (index + 1) + (((this.defaultPage.currentPage || 1) - 1) * (this.defaultPage.pageSize || 10));
+    },
+    refreshChange () {
+      this.$emit('refresh-change', {
+        page: this.defaultPage,
+        searchForm: this.searchForm
+      });
+    },
+    pageInit (onload) {
+      this.page.total ? this.defaultPage.total = this.page.total : '';
+      this.page.currentPage ? this.defaultPage.currentPage = this.page.currentPage : ''
+      this.page.pageSize ? this.defaultPage.pageSize = this.page.pageSize : ''
+      this.page.pageSizes ? this.defaultPage.pageSizes = this.page.pageSizes : ''
+      this.page.background ? this.defaultPage.background = this.page.background : ''
+    },
+    rulesInit () {
+      this.tableFormRules = {};
+      this.columnOption.forEach(ele => {
+        if (ele.rules) this.tableFormRules[ele.prop] = ele.rules;
+      });
+    },
+    columnInit: function () {
+      const safe = this;
+      this.columnIndex = [];
+      this.columnList = [];
+
+      function addChild (list) {
+        list.forEach((ele, index) => {
+          const children = ele.children;
+          if (!validatenull(children)) {
+            safe.tableOption.columnBtn = false;
+            addChild(children);
+          }
+          if (validatenull(ele.hide)) safe.columnIndex.push(ele.prop);
+          if (ele.showClomnu !== false) {
+            let obj = {
+              label: ele.label,
+              prop: ele.prop,
+              index: index
+            };
+            safe.columnList.push(safe.deepClone(obj));
+          }
+        });
+      }
+      addChild(this.columnOption)
+    },
+    formVal () {
+      Object.keys(this.value).forEach(ele => {
+        this.tableForm[ele] = this.value[ele];
+      })
+      this.$emit('input', this.tableForm);
+    },
+    dataInit () {
+      this.list = [].concat(this.data);
+      //初始化序号
+      this.list.forEach((ele, index) => {
+        ele.$index = index;
+      })
+    },
+    formInit () {
+      this.defaultForm = this.formInitVal(this.columnOption);
+      this.tableForm = this.deepClone(this.defaultForm.tableForm);
+      this.searchForm = this.deepClone(this.defaultForm.searchForm);
+      this.searchShow = this.vaildData(this.tableOption.searchShow, this.config.searchShow);
+      this.formVal();
+    },
+    // 搜索清空
+    searchReset () {
+      this.$refs['searchForm'].resetFields();
+      this.$emit('search-reset');
+    },
+    // 页大小回调
+    sizeChange (val) {
+      this.defaultPage.currentPage = 1;
+      this.defaultPage.pageSize = val
+      this.$emit('on-load', this.defaultPage);
+      this.$emit('size-change', val);
+    },
+    //日期组件回调
+    dateChange (val) {
+      this.$emit('date-change', val);
+    },
+    // 页码回调
+    currentChange (val) {
+      this.$emit('on-load', this.defaultPage);
+      this.$emit('current-change', val);
+    },
+    //设置单选
+    currentRowChange (currentRow, oldCurrentRow) {
+      this.$emit('current-row-change', currentRow, oldCurrentRow);
+    },
+    //设置多选选中
+    setCurrentRow (row) {
+      this.$refs.table.setCurrentRow(row);
+    },
+    // 选中实例
+    toggleSelection (rows) {
+      if (rows) {
+        rows.forEach(row => {
+          this.$refs.table.toggleRowSelection(row);
+        });
+      } else {
+        this.$refs.table.clearSelection();
+      }
+    },
+    // 选择回调
+    selectionChange (val) {
+      this.tableSelect = val;
+      this.$emit('selection-change', this.tableSelect);
+    },
+    // 排序回调
+    sortChange (val) {
+      this.$emit('sort-change', val);
+    },
+    // 搜索回调
+    searchChange () {
+      this.$emit('search-change', this.searchForm);
+    },
+    // 行双击
+    rowDblclick (row, event) {
+      this.$emit('row-dblclick', row, event);
+    },
+    // 行单机
+    rowClick (row, event, column) {
+      this.$emit('row-click', row, event, column);
+    },
+    // 新增
+    rowAdd () {
+      this.boxType = 'add';
+      this.tableForm = this.deepClone(this.defaultForm.tableForm);
+      this.clearDefaultParam();
+      this.$emit('input', this.tableForm);
+      this.show();
+    },
+    rowCell (row, index) {
+      if (row.$cellEdit) this.rowCellUpdate(row, index)
+      else this.rowCellEdit(row, index)
+    },
+    // 单元格编辑
+    rowCellEdit (row, index) {
+      if (this.tableIndex != -1) {
+        this.$message.error('先保存当前编辑的数据');
+        return;
+      }
+      this.tableIndex = index;
+      this.tableForm = this.deepClone(row);
+      this.$emit('input', this.tableForm);
+      row.$cellEdit = !row.$cellEdit;
+      this.$set(this.list, index, row);
+    },
+    // 编辑
+    rowEdit (row, index) {
+      this.tableForm = this.deepClone(row);
+      this.clearDefaultParam();
+      this.$emit('input', this.tableForm);
+      this.tableIndex = index;
+      this.boxType = 'edit';
+      this.show();
+    },
+
+    //查看
+    rowView (row, index) {
+      this.tableForm = this.deepClone(row);
+      this.clearDefaultParam();
+      this.$emit('input', this.tableForm);
+      this.tableIndex = index;
+      this.boxType = 'view';
+      this.keyBtn = true;
+      this.show();
+    },
+    rowCellUpdate (row, index) {
+      const form = this.deepClone(this.tableForm);
+      this.$emit('input', form);
+      this.$emit(
+        'row-update',
+        form,
+        index,
+        () => {
+          row.$cellEdit = !row.$cellEdit;
+          this.tableForm = {};
+          this.tableIndex = -1;
+          this.$set(this.list, index, form);
+        }
+      );
+    },
+    // 删除
+    rowDel (row, index) {
+      this.$emit('row-del', row, index);
+    },
+    // 保存
+    rowSave () {
+      this.$refs['tableForm'].validate().then(() => {
+        this.keyBtn = true;
+        this.$emit('row-save', this.deepClone(this.tableForm), this.closeDialog,
+          () => {
+            this.keyBtn = false;
+          });
+      });
+    },
+    // 更新
+    rowUpdate () {
+      this.$refs['tableForm'].validate().then(() => {
+        this.keyBtn = true;
+        const index = this.tableIndex;
+        this.$emit(
+          'row-update',
+          this.deepClone(this.tableForm),
+          index,
+          this.closeDialog,
+          () => {
+            this.keyBtn = false;
+          }
+        );
+      });
+    },
+    // 显示表单
+    show (cancel) {
+      const callack = () => {
+        if (cancel !== true) {
+          this.boxVisible = true;
+          this.$nextTick(() => {
+            this.$refs['tableForm'].clearValidate();
+            this.$refs['tableForm'].cascadeInit();
+          });
+        }
+      };
+      if (typeof this.beforeOpen === 'function') this.beforeOpen(callack, this.boxType);
+      else callack();
+    },
+    // 隐藏表单
+    hide (cancel) {
+      const callack = () => {
+        if (cancel !== false) {
+          this.$refs['tableForm'].resetForm();
+          this.$refs['tableForm'].clearValidate();
+        }
+      };
+      if (typeof this.beforeClose === 'function') this.beforeClose(callack, this.boxType);
+      else callack();
+    },
+    //清空多余字段
+    clearDefaultParam () {
+      this.defaultParam.forEach(ele => {
+        delete this.tableForm[ele];
+      })
+    },
+    //清空表单
+    resetForm () {
+      this.$refs['tableForm'].resetForm();
+      this.$emit('input', this.tableForm);
+    },
+    //合并行
+    tableSpanMethod (param) {
+      if (typeof this.spanMethod === 'function') return this.spanMethod(param);
+    },
+    //合集统计逻辑
+    tableSummaryMethod (param) {
+      //如果自己写逻辑则调用summaryMethod方法
+      if (typeof this.summaryMethod === 'function') return this.summaryMethod(param);
+      const {
+        columns,
+        data
+      } = param;
+      const sums = [];
+      if (columns.length > 0) {
+        columns.forEach((column, index) => {
+          let currItem = this.sumColumnList.find((item => item.name === column.property));
+          if (currItem) {
+            switch (currItem.type) {
+              case "count":
+                sums[index] = '计数:' + data.length;
+                break;
+              case "avg":
+                let avgValues = data.map(item => Number(item[column.property]));
+                let nowindex = 1;
+                sums[index] = avgValues.reduce((perv, curr) => {
+                  let value = Number(curr);
+                  if (!isNaN(value)) {
+                    return (perv + curr) / nowindex++;
+                  } else {
+                    return perv;
+                  }
+                }, 0);
+                sums[index] = '平均:' + sums[index];
+                break;
+              case "sum":
+                let values = data.map(item => Number(item[column.property]));
+                sums[index] = values.reduce((perv, curr) => {
+                  let value = Number(curr);
+                  if (!isNaN(value)) {
+                    return perv + curr;
+                  } else {
+                    return perv;
+                  }
+                }, 0);
+                sums[index] = '合计:' + sums[index];
+                break;
+            }
+          }
+
+        })
+      }
+      return sums;
+    }
+
+  }
+});
+</script>

+ 7 - 0
packages/data-box/index.js

@@ -0,0 +1,7 @@
+import DataBox from './src/data-box.vue';
+
+DataBox.install = function(Vue) {
+  Vue.component(DataBox.name, DataBox);
+};
+
+export default DataBox;

+ 52 - 0
packages/data-box/src/data-box.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="data-box">
+    <el-row :span="24">
+      <el-col :md="span"
+              :xs="24"
+              :sm="12"
+              v-for="(item,index) in data"
+              :key="index">
+        <div class="item">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <div class="item-icon"
+                 :style="{backgroundColor:item.color}">
+              <i :class="item.icon"></i>
+            </div>
+            <div class="item-info">
+              <div :style="{color:item.color}"
+                   class="title">{{item.count}}</div>
+              <div class="info">{{item.title}}</div>
+            </div>
+          </a>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-box',
+  data () {
+    return {
+
+    };
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  computed: {
+    span () { return this.option.span || 8; },
+    data () { return this.option.data || []; }
+  },
+  created () { },
+  mounted () { },
+  watch: {},
+  methods: {}
+});
+</script>

+ 7 - 0
packages/data-card/index.js

@@ -0,0 +1,7 @@
+import DataCard from './src/data-card.vue';
+
+DataCard.install = function(Vue) {
+  Vue.component(DataCard.name, DataCard);
+};
+
+export default DataCard;

+ 63 - 0
packages/data-card/src/data-card.vue

@@ -0,0 +1,63 @@
+<template>
+  <div class="data-card">
+    <el-row :span="24">
+      <el-col :md="span"
+              :xs="24"
+              :sm="12"
+              v-for="(item,index) in data"
+              :key="index">
+        <div class="item">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <img :src="item.src"
+                 class="item-img" />
+            <div class="item-text"
+                 :style="{backgroundColor:bgText}">
+              <h3 :style="{color:colorText}">{{item.name}}</h3>
+              <p :style="{color:colorText}">{{item.text}}</p>
+            </div>
+          </a>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-card',
+  data () {
+    return {
+
+    };
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  computed: {
+    span () {
+      return this.option.span || 6;
+    },
+    data () {
+      return this.option.data || [];
+    },
+    colorText () {
+      return this.option.colorText || '#fff';
+    },
+    bgText () {
+      return this.option.bgText || '#2e323f';
+    },
+    borderColor () {
+      return this.option.borderColor || '#2e323f';
+    }
+  },
+  created () { },
+  mounted () { },
+  watch: {},
+  methods: {}
+});
+</script>

+ 7 - 0
packages/data-display/index.js

@@ -0,0 +1,7 @@
+import DataDisplay from './src/data-display.vue';
+
+DataDisplay.install = function(Vue) {
+  Vue.component(DataDisplay.name, DataDisplay);
+};
+
+export default DataDisplay;

+ 53 - 0
packages/data-display/src/data-display.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="avue-data-display">
+    <el-row :span="24">
+      <el-col v-for="(item,index) in data"
+              :key="index"
+              :md="span"
+              :xs="12"
+              :sm="12">
+        <div class="item"
+             :style="{color:color}">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <h5 class="count">{{item.count}}</h5>
+            <span class="splitLine" />
+            <p class="title">{{item.title}}</p>
+          </a>
+        </div>
+      </el-col>
+    </el-row>
+
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-display',
+  data () {
+    return {
+
+    };
+  },
+  computed: {
+    span () {
+      return this.option.span || 6;
+    },
+    data () {
+      return this.option.data || [];
+    },
+    color () {
+      return this.option.color || 'rgb(63, 161, 255)';
+    }
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  created () { },
+  methods: {}
+});
+</script>

+ 7 - 0
packages/data-icons/index.js

@@ -0,0 +1,7 @@
+import DataIcons from './src/data-icons.vue';
+
+DataIcons.install = function(Vue) {
+  Vue.component(DataIcons.name, DataIcons);
+};
+
+export default DataIcons;

+ 52 - 0
packages/data-icons/src/data-icons.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="data-icons">
+    <el-row :span="24">
+      <template v-for="(item,index) in data">
+        <el-col :xs="12"
+                :sm="6"
+                :md="span"
+                :key="index">
+          <div class="item"
+               :class="[{'item--easy':discount}]">
+            <a :href="item.href?item.href:'javascript:void(0);'"
+               :target="item.target">
+              <div class="item-icon"
+                   :style="{color:color}">
+                <i :class="item.icon"></i>
+              </div>
+              <div class="item-info">
+                <span>{{item.title}}</span>
+                <div class="count"
+                     :style="{color:color}">{{item.count}}</div>
+              </div>
+            </a>
+          </div>
+        </el-col>
+      </template>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-icons',
+  data () {
+    return {
+
+    };
+  },
+  computed: {
+    span () { return this.option.span || 4; },
+    data () { return this.option.data; },
+    color () { return this.option.color || 'rgb(63, 161, 255)'; },
+    discount () { return this.option.discount || false; }
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  }
+});
+</script>

+ 7 - 0
packages/data-progress/index.js

@@ -0,0 +1,7 @@
+import DataProgress from './src/data-progress.vue';
+
+DataProgress.install = function(Vue) {
+    Vue.component(DataProgress.name, DataProgress);
+};
+
+export default DataProgress;

+ 53 - 0
packages/data-progress/src/data-progress.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="data-progress">
+    <el-row :span="24">
+      <el-col :md="span"
+              :xs="24"
+              :sm="12"
+              v-for="(item,index) in data"
+              :key="index">
+        <div class="item">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <div class="item-header">
+              <div class="item-count"
+                   v-text="item.count+'%'"></div>
+              <div class="item-title"
+                   v-text="item.title"></div>
+            </div>
+            <el-progress :stroke-width="15"
+                         :percentage="item.count"
+                         :color="item.color"
+                         :show-text="false"></el-progress>
+          </a>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-progress',
+  data () {
+    return {
+
+    };
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  computed: {
+    span () { return this.option.span || 8; },
+    data () { return this.option.data || []; }
+  },
+  created () { },
+  mounted () { },
+  watch: {},
+  methods: {}
+});
+</script>

+ 7 - 0
packages/data-tabs/index.js

@@ -0,0 +1,7 @@
+import DataTabs from './src/data-tabs.vue';
+
+DataTabs.install = function(Vue) {
+  Vue.component(DataTabs.name, DataTabs);
+};
+
+export default DataTabs;

+ 56 - 0
packages/data-tabs/src/data-tabs.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="data-tabs">
+    <el-row :span="24">
+      <el-col :md="span"
+              :xs="24"
+              :sm="12"
+              v-for="(item,index) in data"
+              :key="index">
+        <div class="item"
+             :style="{background:item.color}">
+          <a :href="item.href?item.href:'javascript:void(0);'"
+             :target="item.target">
+            <div class="item-header">
+              <p>{{item.title}}</p>
+              <span>{{item.subtitle}}</span>
+            </div>
+            <div class="item-body">
+              <h2>{{item.count}}</h2>
+            </div>
+            <div class="item-footer">
+              <span>{{item.allcount}}</span>
+              <p>{{item.text}}</p>
+            </div>
+            <p class="item-tip">{{item.key}}</p>
+          </a>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+export default create({
+  name: 'data-tabs',
+  data () {
+    return {
+
+    };
+  },
+  computed: {
+    span () {
+      return this.option.span || 8;
+    },
+    data () {
+      return this.option.data || [];
+    }
+  },
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    }
+  }
+});
+</script>

+ 7 - 0
packages/date-group/index.js

@@ -0,0 +1,7 @@
+import DateGroup from './src/main';
+
+DateGroup.install = function(Vue) {
+    Vue.component(DateGroup.name, DateGroup);
+};
+
+export default DateGroup;

+ 91 - 0
packages/date-group/src/main.vue

@@ -0,0 +1,91 @@
+<template>
+  <div :class="b()">
+    <div :class="b('radio')">
+      <el-radio-group :size="size"
+                      @change="handleChange"
+                      v-model="text">
+        <el-radio-button :label="item.value"
+                         v-for="(item,index) in menu"
+                         :key="index">{{item.label}}</el-radio-button>
+      </el-radio-group>
+    </div>
+    <div :class="b('date')">
+      <el-date-picker v-model="datetime"
+                      type="daterange"
+                      :size="size"
+                      format="yyyy-MM-dd"
+                      value-format="yyyy-MM-dd"
+                      range-separator="至"
+                      start-placeholder="开始日期"
+                      end-placeholder="结束日期">
+      </el-date-picker>
+    </div>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+import { GetDateStr } from '../../utils/dateUtil.js';
+export default create({
+  name: 'date-group',
+  data () {
+    return {
+      menu: [],
+      text: '',
+      datetime: [GetDateStr(0), GetDateStr(30)]
+    };
+  },
+  watch: {
+    datetime () {
+      this.text = '';
+      this.setCurrent(this.datetime.join(','));
+    },
+  },
+  computed: {
+
+  },
+  props: {
+    default: {
+      type: Boolean,
+      default: false
+    },
+    size: {
+      type: String,
+      default: 'medium'
+    }
+  },
+  created () {
+    this.init();
+  },
+  methods: {
+    handleChange (val) {
+      this.setCurrent(val);
+    },
+    setCurrent (val) {
+      this.$emit('input', val);
+      this.$emit('change', val);
+    },
+    init () {
+      this.menu = [
+        {
+          label: '今天',
+          value: GetDateStr(0)
+        }, {
+          label: '昨天',
+          value: GetDateStr(-1)
+        }, {
+          label: '近7天',
+          value: GetDateStr(-7)
+        }, {
+          label: '全部',
+          value: '-1'
+        }
+      ];
+      if (this.default) {
+        this.text = GetDateStr(0);
+        this.setCurrent(this.text);
+      }
+    }
+  }
+});
+</script>

+ 7 - 0
packages/form-detail/index.js

@@ -0,0 +1,7 @@
+import FormDetail from './src/main';
+
+FormDetail.install = function(Vue) {
+  Vue.component(FormDetail.name, FormDetail);
+};
+
+export default FormDetail;

+ 111 - 0
packages/form-detail/src/main.vue

@@ -0,0 +1,111 @@
+<template>
+  <div :class="b()">
+    <el-row span="24"
+            :class="b('item')"
+            v-for="(item,index) in columnOption"
+            :key="index">
+      <div :class="b('header')">
+        <i :class="[item.icon,b('icon')]"></i>
+        <h1 :class="b('title')">{{item.label}}</h1>
+      </div>
+      <slot :name="item.prop"
+            :form="form"
+            :column="item"
+            v-if="item.slot"></slot>
+      <el-col :md="column.span||8"
+              :xs="24"
+              v-else
+              v-for="(column,cindex) in item.column"
+              :key="cindex">
+        <div :class="b('box')">
+          <span :class="b('label',[labelPostion])"
+                :style="{width:`${item.labelWidth}px`}">{{column.label}}:</span>
+          <slot :name="column.prop+'Form'"
+                :column="column"
+                :form="form"
+                v-if="column.slot"></slot>
+          <span v-else
+                :class="b('content')">{{detail(form,column)}}</span>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+
+import create from '../../utils/create';
+import crud from '../../mixins/crud.js';
+import column from '../../mixins/column.js';
+import { validatenull } from '../../utils/validate.js';
+export default create({
+  name: 'form-detail',
+  mixins: [crud(), column()],
+  props: {
+    option: {
+      type: Object,
+      default: () => { }
+    },
+    value: {}
+  },
+  computed: {
+    labelPostion: function () {
+      if (this.option.labelPostion) {
+        return this.option.labelPostion;
+      }
+      return 'left';
+    },
+    columnOption () {
+      return this.option.option || [];
+    }
+  },
+  watch: {
+    value: {
+      handler (n) {
+        this.form = n;
+      },
+      deep: true
+    }
+  },
+  data () {
+    return {
+      tableOption: {},
+      form: {}
+    };
+  },
+  created () {
+    this.formInit();
+  },
+  methods: {
+    dicInit () {
+      let locaDic = this.tableOption.dicData || {};
+      this.columnOption.forEach(child => {
+        child.column.forEach(ele => {
+          if (this.vaildData(ele.dicFlag, true)) {
+            if (!validatenull(ele.dicUrl)) {
+              this.dicCascaderList.push({
+                dicUrl: ele.dicUrl,
+                dicData: ele.dicData
+              });
+            } else if (!validatenull(this.tableOption.dicUrl) && typeof ele.dicData === 'string') {
+              this.dicCascaderList.push({
+                dicUrl: this.tableOption.dicUrl,
+                dicData: ele.dicData
+              });
+            }
+          }
+        })
+      });
+      this.GetDic().then(data => {
+        this.DIC = Object.assign({}, locaDic, data);
+      });
+    },
+    rulesInit () {
+
+    },
+    formInit () {
+      this.form = this.value;
+    }
+  }
+});
+</script>

+ 7 - 0
packages/form/index.js

@@ -0,0 +1,7 @@
+import Form from './src/main';
+
+Form.install = function(Vue) {
+  Vue.component(Form.name, Form);
+};
+
+export default Form;

+ 410 - 0
packages/form/src/main.vue

@@ -0,0 +1,410 @@
+<template>
+  <div :class="b()"
+       :style="{width:setPx(tableOption.formWidth,'100%')}">
+    <el-form ref="form"
+             :model="form"
+             :label-position="tableOption.labelPosition"
+             :size="controlSize"
+             :label-width="setPx(tableOption.labelWidth,80)"
+             :rules="formRules">
+      <el-row :gutter="20"
+              :span="24">
+        <draggable :list="columnOption"
+                   :options="dragOptions"
+                   :class="b('group')">
+          <template v-if="vaildVisdiplay(column)"
+                    v-for="(column,index) in columnOption">
+            <el-col :key="index"
+                    :md="column.span||12"
+                    :xs="24"
+                    :class="b('row',{'cursor':draggableStart})"
+                    @mouseover.native="draggableMenu?mouseover(index):''"
+                    @mouseout.native="draggableMenu?mouseout(index):''">
+              <div :class="b('option')"
+                   v-if="optionIndex[index]">
+                <i class="el-icon-menu"
+                   @click="optionMenu(column,index)"></i>
+                <i class="el-icon-delete"
+                   @click="optionDelete(column,index)"></i>
+              </div>
+              <el-form-item :label="column.label"
+                            :prop="column.prop"
+                            :label-width="setPx(column.labelWidth,tableOption.labelWidth || 80)">
+                <slot :value="form[column.prop]"
+                      :column="column"
+                      :dic="setDic(column.dicData,DIC[column.dicData])"
+                      :name="column.prop"
+                      v-if="column.formsolt"></slot>
+
+                <component :is="getComponent({type:column.type,component:column.component})"
+                           v-else
+                           :props="column.props || tableOption.props"
+                           :propsHttp="column.propsHttp || tableOption.propsHttp"
+                           v-model="form[column.prop]"
+                           :change="column.change"
+                           :click="column.click"
+                           :nodeClick="column.nodeClick"
+                           :checked="column.checked"
+                           :prepend="column.prepend"
+                           :append="column.append"
+                           :column="column"
+                           :filter="column.filter"
+                           :precision="column.precision"
+                           :multiple="column.multiple"
+                           :readonly="vaildData(draggableStart,column.readonly)"
+                           :placeholder="column.placeholder"
+                           :step="column.step"
+                           :range="column.range"
+                           :showStops="column.showStops"
+                           :showInput="column.showInput"
+                           :controls-position="column.controlsPosition"
+                           :expand-trigger="column.expandTrigger"
+                           :size="column.size || controlSize"
+                           :parent="column.parent"
+                           :colors="column.colors"
+                           :action="column.action"
+                           :limit="column.limit"
+                           :tip="column.tip"
+                           :loadText="column.loadText"
+                           :listType="column.listType"
+                           :drag="column.drag"
+                           :showFileList="column.showFileList"
+                           :iconClasses="column.iconClasses"
+                           :voidIconClass="column.voidIconClass"
+                           :showText="column.showText"
+                           :texts="column.texts"
+                           :filterable="column.filterable"
+                           :separator="column.separator"
+                           :border="column.border"
+                           :minlength="column.minlength"
+                           :maxlength="column.maxlength"
+                           :prefixIcon="column.prefixIcon"
+                           :suffixIcon="column.suffixIcon"
+                           :defaultExpandAll="column.defaultExpandAll"
+                           :options="column.options"
+                           :pickerOptions="column.pickerOptions"
+                           :defaultTime="column.defaultTime"
+                           :min="column.min"
+                           :max="column.max"
+                           :changeoOnSelect="column.changeoOnSelect"
+                           :label="column.label"
+                           :clearable="column.clearable"
+                           :startPlaceholder="column.startPlaceholder"
+                           :dataType="column.dataType"
+                           :endPlaceholder="column.endPlaceholder"
+                           :type="column.type"
+                           :minRows="column.minRows"
+                           :maxRows="column.maxRows"
+                           :format="column.format"
+                           :formatTooltip="column.formatTooltip"
+                           :value-format="column.valueFormat"
+                           :dic="setDic(column.dicData,DIC[column.dicData])"
+                           :disabled="vaildDisabled(column)"
+                           :upload-before="uploadBefore"
+                           :upload-after="uploadAfter"
+                           @change="column.cascader?change(index):''"></component>
+                <!-- <p class="avue-tip">{{column.tip}}</p> -->
+              </el-form-item>
+            </el-col>
+            <div :class="b('line')"
+                 :key="index"
+                 :style="{width:(column.count/24*100)+'%'}"
+                 v-if="column.row && column.span!==24">
+            </div>
+          </template>
+        </draggable>
+        <el-col :span="24"
+                v-if="vaildData(tableOption.menuBtn,true)">
+          <el-form-item :label-width="menuWidth">
+            <!-- 菜单按钮组 -->
+            <div :class="b('menu',[menuPostion])">
+              <el-button type="primary"
+                         @click="handleMock"
+                         :size="controlSize"
+                         icon="el-icon-edit-outline"
+                         v-if="vaildData(tableOption.mock,false)">一键填充数据</el-button>
+              <el-button type="primary"
+                         @click="submit"
+                         :size="controlSize"
+                         icon="el-icon-check"
+                         v-if="vaildData(tableOption.submitBtn,true)">{{vaildData(tableOption.submitText,'提 交')}}</el-button>
+              <el-button icon="el-icon-delete"
+                         :size="controlSize"
+                         v-if="vaildData(tableOption.emptyBtn,true)"
+                         @click="resetForm">{{vaildData(tableOption.emptyText,'清 空')}}</el-button>
+              <slot name="menuForm"></slot>
+            </div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+  </div>
+</template>
+
+<script>
+
+import create from '../../utils/create';
+import draggable from "vuedraggable";
+import crud from '../../mixins/crud';
+import { deepClone } from '../../utils/util';
+import mock from '../../utils/mock';
+import { validatenull } from '../../utils/validate.js';
+export default create({
+  name: 'form',
+  mixins: [crud()],
+  components: {
+    draggable
+  },
+  data () {
+    return {
+      first: true,
+      optionIndex: [],
+      optionBox: false,
+      tableOption: {},
+      form: {},
+      formDefault: {},
+      formRules: {}
+    };
+  },
+  created () {
+  },
+  watch: {
+    value: {
+      handler () {
+        this.formVal();
+      },
+      deep: true
+    }
+  },
+  mounted () { },
+  computed: {
+    columnOption () {
+      let list = this.tableOption.column || [];
+      let count = 0;
+      list.forEach(ele => {
+        count = count + (ele.span || 12);
+        if (count >= 24) {
+          count = 0 + (ele.span || 12);
+        } else if (ele.row && count !== 24) {
+          ele.count = 24 - count;
+          count = 0
+        }
+      })
+      return list;
+    },
+    draggable () {
+      return this.tableOption.draggable || {};
+    },
+    draggableMenu () {
+      return this.draggable.menu || false;
+    },
+    draggableStart () {
+      return this.draggable.start;
+    },
+    draggableFlag () {
+      return this.vaildData(this.draggable.clone, true)
+    },
+    dragOptions () {
+      if (!this.draggableStart) {
+        return {
+          disabled: true,
+        }
+      }
+      let pull = (() => {
+        if (this.draggableFlag) {
+          return {
+            pull: 'clone',
+            revertClone: false
+          }
+        }
+        return {
+
+        }
+      })();
+      return {
+        animation: 0,
+        ghostClass: "avue-ghost",
+        group: (function () {
+          return Object.assign({ name: "avue" }, pull);
+        })(),
+        sort: this.vaildData(this.draggable.sort, false),
+      };
+    },
+    menuWidth: function () {
+      if (this.tableOption.menuPostion === 'left') {
+        return '';
+      } else {
+        return '0';
+      }
+    },
+    menuPostion: function () {
+      if (this.tableOption.menuPostion) {
+        return this.tableOption.menuPostion;
+      } else {
+        return 'center';
+      }
+    },
+    boxType: function () {
+      return this.tableOption.boxType;
+    }
+  },
+  props: {
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    uploadBefore: Function,
+    uploadAfter: Function,
+    value: {
+      type: Object,
+      required: true,
+      default: () => {
+        return {};
+      }
+    }
+  },
+  methods: {
+    handleMock () {
+      const form = mock(this.columnOption, this.DIC);
+      Object.keys(form).forEach(ele => {
+        this.form[ele] = form[ele];
+      })
+      this.clearValidate();
+      this.$message.success('模拟数据填充成功');
+    },
+    optionDelete (column, index) {
+      this.$emit('option-delete', { column, index })
+    },
+    optionMenu (column, index) {
+      this.$emit('option-menu', { column, index })
+    },
+    mouseover (index) {
+      this.optionIndex[index] = true;
+      this.optionIndex.splice(0, 0);
+    },
+    mouseout (index) {
+      this.optionIndex[index] = false;
+      this.optionIndex.splice(0, 0);
+    },
+    // 验证表单是否禁止
+    vaildDisabled (column) {
+      if (this.disabled) return true;
+      if (!validatenull(column.disabled)) {
+        return this.vaildData(column.disabled, false);
+      } else if (this.boxType === 'add') {
+        return this.vaildData(column.addDisabled, false);
+      } else if (this.boxType === 'edit') {
+        return this.vaildData(column.editDisabled, false);
+      } else if (this.boxType === 'view') {
+        return true;
+      } else {
+        return false;
+      }
+    },
+    // 验证表单是否显隐
+    vaildVisdiplay (column) {
+      if (!validatenull(column.visdiplay)) {
+        return this.vaildData(column.visdiplay, true);
+      } else if (this.boxType === 'add') {
+        return this.vaildData(column.addVisdiplay, true);
+      } else if (this.boxType === 'edit') {
+        return this.vaildData(column.editVisdiplay, true);
+      } else if (this.boxType === 'view') {
+        return this.vaildData(column.viewVisdiplay, true);
+      } else {
+        return true;
+      }
+
+    },
+    rulesInit () {
+      this.formRules = {};
+      this.columnOption.forEach(ele => {
+        if (ele.rules) this.formRules[ele.prop] = ele.rules;
+      });
+    },
+    change (index) {
+      const column = this.columnOption;
+      const list = column[index].cascader;
+      const prop = column[index].prop;
+      const url = column[index + 1].dicUrl;
+      const type = column[index + 1].dicData;
+      if (!this.first) {
+        list.forEach((ele) => {
+          this.form[ele] = '';
+          this.DIC[ele] = [];
+          this.DIC = Object.assign({}, this.DIC);
+        });
+      }
+      this.GetDicByType(url.replace('{{key}}', this.form[prop])).then(res => {
+        let data = res;
+        this.DIC[type] = data;
+        this.DIC = Object.assign({}, this.DIC);
+      });
+    },
+    formInit () {
+      this.formDefault = this.formInitVal(this.columnOption);
+      this.form = this.deepClone(this.formDefault.tableForm);
+      this.formVal();
+      const dicFlag = this.vaildData(this.tableOption.dicFlag, true);
+      //初始化联动
+      if (dicFlag) this.cascadeInit();
+    },
+    cascadeInit () {
+      this.first = true;
+      for (let i = 0; i < this.columnOption.length; i++) {
+        const ele = this.columnOption[i];
+        if (ele.cascaderFirst) {
+          const cascader = [].concat(ele.cascader);
+          const cascaderLen = ele.cascader.length - 1;
+          cascader.forEach((ele) => {
+            this.DIC[ele] = [];
+            this.DIC = Object.assign({}, this.DIC);
+          });
+          if (!validatenull(this.form[ele.prop])) this.change(i);
+          for (let j = 0; j < cascaderLen; j++) {
+            const cindex = i + (j + 1);
+            const cele = this.columnOption[cindex];
+            cele.cascader = cascader.slice(cindex);
+            if (!validatenull(this.form[cele.prop])) this.change(cindex);
+          }
+        }
+      }
+      this.first = false;
+    },
+    formVal () {
+      Object.keys(this.value).forEach(ele => {
+        this.form[ele] = this.value[ele];
+      })
+      this.$emit('input', this.form);
+    },
+    clearValidate () {
+      this.$refs['form'].clearValidate();
+    },
+    validate () {
+      return new Promise((resolve, reject) => {
+        this.$refs.form.validate(valid => {
+          if (valid) {
+            resolve();
+          } else {
+            reject();
+          }
+        });
+      });
+    },
+    resetForm () {
+      this.form = this.deepClone(this.formDefault.tableForm);
+      this.clearValidate();
+      this.$emit('input', this.form);
+      this.$emit('reset-change');
+    },
+    submit () {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          this.$emit('submit', this.form);
+        }
+      });
+    }
+  }
+});
+</script>
+

+ 104 - 0
packages/index.js

@@ -0,0 +1,104 @@
+import Carousel from './carousel/';
+import Json from './json/'
+import Crud from './crud/';
+import CrudCheckbox from './crud-checkbox/';
+import CrudDate from './crud-date/';
+import CrudTime from './crud-time/';
+import CrudInput from './crud-input/';
+import CrudRadio from './crud-radio/';
+import CrudSelect from './crud-select/';
+import CrudCascader from './crud-cascader/';
+import CrudNumberInput from './crud-input-number/';
+import CrudSwitch from './crud-switch/';
+import CrudRate from './crud-rate/';
+import CrudUpload from './crud-upload/';
+import CrudSilder from './crud-silder/';
+import DataDisplay from './data-display/';
+import DataCard from './data-card/';
+import DataTabs from './data-tabs/';
+import DataProgress from './data-progress/';
+import DataIcons from './data-icons/';
+import DataBox from './data-box/';
+import Form from './form/';
+import Tabs from './tabs/';
+import Steps from './steps/';
+import Tree from './tree/';
+import FormDetail from './form-detail/';
+import TableTree from './table-tree/';
+import DateGroup from './date-group/';
+import axios from 'axios';
+const components = [
+    Json,
+    Crud,
+    Form,
+    Tabs,
+    Tree,
+    Carousel,
+    Steps,
+    FormDetail,
+    CrudCheckbox,
+    CrudDate,
+    CrudTime,
+    CrudInput,
+    CrudRadio,
+    CrudSelect,
+    CrudCascader,
+    CrudNumberInput,
+    CrudSwitch,
+    CrudRate,
+    CrudUpload,
+    CrudSilder,
+    DataProgress,
+    DataDisplay,
+    DataCard,
+    DataIcons,
+    DataTabs,
+    DataBox,
+    TableTree,
+    DateGroup
+];
+
+function install(Vue, opts = {}) {
+    if (axios || window.axios) Vue.prototype.$http = axios || window.axios;
+    components.map(component => {
+        Vue.component(component.name, component);
+    });
+    Vue.prototype.$AVUE = {
+        size: opts.size || 'medium',
+    };
+}
+
+if (window.Vue) {
+    install(window.Vue, window.axios);
+}
+export default {
+    install,
+    Json,
+    Crud,
+    Form,
+    Tabs,
+    Tree,
+    Carousel,
+    Steps,
+    FormDetail,
+    CrudCheckbox,
+    CrudDate,
+    CrudTime,
+    CrudInput,
+    CrudRadio,
+    CrudSelect,
+    CrudCascader,
+    CrudNumberInput,
+    CrudSwitch,
+    CrudRate,
+    CrudUpload,
+    CrudSilder,
+    DataProgress,
+    DataDisplay,
+    DataCard,
+    DataIcons,
+    DataTabs,
+    DataBox,
+    TableTree,
+    DateGroup
+};

+ 7 - 0
packages/json/index.js

@@ -0,0 +1,7 @@
+import Json from './src/main';
+
+Json.install = function(Vue) {
+    Vue.component(Json.name, Json);
+};
+
+export default Json;

+ 159 - 0
packages/json/src/main.vue

@@ -0,0 +1,159 @@
+<template>
+  <span class="json-tree"
+        :class="{'json-tree-root': parsed.depth === 0}">
+    <span class="json-tree-row"
+          v-if="parsed.primitive"
+          @mouseover="hovered = true"
+          @mouseout="hovered = false">
+      <span class="json-tree-indent"
+            v-for="n in (parsed.depth * 2 + 3)"
+            :key="n">&nbsp;</span>
+      <span class="json-tree-key"
+            v-if="parsed.key">{{ parsed.key }}</span>
+      <span class="json-tree-colon"
+            v-if="parsed.key">:&nbsp;</span>
+      <span class="json-tree-value"
+            :class="'json-tree-value-' + parsed.type"
+            :title="`${parsed.value}`">{{ `${parsed.value}` }}</span>
+      <span class="json-tree-comma"
+            v-if="!parsed.last">,</span>
+      <span class="json-tree-indent">&nbsp;</span>
+    </span>
+    <span class="json-tree-deep"
+          v-if="!parsed.primitive">
+      <span class="json-tree-row json-tree-expando"
+            @mouseover="hovered = true"
+            @mouseout="hovered = false">
+        <span class="json-tree-indent">&nbsp;</span>
+        <span class="json-tree-sign"
+              @click="expanded = !expanded">{{ expanded ? '-' : '+' }}</span>
+        <span class="json-tree-indent"
+              v-for="n in (parsed.depth * 2 + 1)"
+              :key="n">&nbsp;</span>
+        <span class="json-tree-key"
+              v-if="parsed.key">{{ parsed.key }}</span>
+        <span class="json-tree-colon"
+              v-if="parsed.key">:&nbsp;</span>
+
+        <span class="json-tree-open">{{ parsed.type === 'array' ? '[' : '{' }}</span>
+        <span class="json-tree-collapsed"
+              v-show="!expanded">&nbsp;/*&nbsp;{{ format(parsed.value.length) }}&nbsp;*/&nbsp;</span>
+        <span class="json-tree-close"
+              v-show="!expanded">{{ parsed.type === 'array' ? ']' : '}' }}</span>
+        <span class="json-tree-comma"
+              v-show="!expanded && !parsed.last">,</span>
+        <span class="json-tree-indent">&nbsp;</span>
+      </span>
+      <span class="json-tree-deeper"
+            v-show="expanded">
+        <avue-json-tree v-for="(item, index) in parsed.value"
+                        :key="index"
+                        :data="data"
+                        :kv="item"
+                        :level="level"></avue-json-tree>
+      </span>
+      <span class="json-tree-row"
+            v-show="expanded">
+        <span class="json-tree-ending"
+              :class="{'json-tree-paired': hovered}">
+          <span class="json-tree-indent"
+                v-for="n in (parsed.depth * 2 + 3)"
+                :key="n">&nbsp;</span>
+          <span class="json-tree-close">{{ parsed.type === 'array' ? ']' : '}' }}</span>
+          <span class="json-tree-comma"
+                v-if="!parsed.last">,</span>
+          <span class="json-tree-indent">&nbsp;</span>
+        </span>
+      </span>
+    </span>
+  </span>
+</template>
+
+<script>
+function parse (data, depth = 0, last = true, key = undefined, parent = [], isArray = false, index = -1) {
+  let kv = { depth, last, primitive: true, key: JSON.stringify(key), parent, isArray, index }
+  if (typeof data !== 'object') {
+    return Object.assign(kv, { type: typeof data, value: JSON.stringify(data) })
+  } else if (data === null) {
+    return Object.assign(kv, { type: 'null', value: 'null' })
+  } else if (Array.isArray(data)) {
+    let value = data.map((item, index) => {
+      key ? parent.push(key) : ''
+      parent.push(index);
+      return parse(item, depth + 1, index === data.length - 1, undefined, [...parent], true, index)
+    })
+    return Object.assign(kv, { primitive: false, type: 'array', value })
+  } else {
+    let keys = Object.keys(data)
+    key ? parent.push(key) : ''
+    let value = keys.map((item, index) => {
+      return parse(data[item], depth + 1, index === keys.length - 1, item, [...parent], isArray, index)
+    })
+    return Object.assign(kv, { primitive: false, type: 'object', value })
+  }
+}
+
+import create from '../../utils/create';
+export default create({
+  name: 'json-tree',
+
+  props: {
+    level: {
+      type: Number,
+      default: Infinity
+    },
+    kv: {
+      type: Object
+    },
+    raw: {
+      type: Object
+    },
+    data: {}
+  },
+
+  data () {
+    return {
+      expanded: true,
+      hovered: false,
+      list: {},
+    }
+  },
+
+  computed: {
+    parsed () {
+      if (this.kv) {
+        return this.kv
+      }
+      let result
+      try {
+        if (this.raw) {
+          result = JSON.parse(this.raw);
+        } else if (typeof this.data !== 'undefined') {
+          result = this.data
+        } else {
+          result = '[Vue JSON Tree] No data passed.'
+          console.warn(result)
+        }
+
+      } catch (e) {
+        result = '[Vue JSON Tree] Invalid raw JSON.'
+        console.warn(result)
+      } finally {
+        return parse(result)
+      }
+    }
+  },
+
+  methods: {
+    format (n) {
+      if (n > 1) return `${n} items`
+      return n ? '1 item' : 'no items'
+    }
+  },
+
+  created () {
+    this.list = this.data;
+    this.expanded = this.parsed.depth < this.level
+  }
+})
+</script>

+ 45 - 0
packages/mixins/bem.js

@@ -0,0 +1,45 @@
+/**
+ * bem helper
+ * b() // 'button'
+ * b('text') // 'button__text'
+ * b({ disabled }) // 'button button--disabled'
+ * b('text', { disabled }) // 'button__text button__text--disabled'
+ * b(['disabled', 'primary']) // 'button button--disabled button--primary'
+ */
+
+const ELEMENT = '__';
+const MODS = '--';
+
+const join = (name, el, symbol) => el ? name + symbol + el : name;
+
+const prefix = (name, mods) => {
+    if (typeof mods === 'string') {
+        return join(name, mods, MODS);
+    }
+
+    if (Array.isArray(mods)) {
+        return mods.map(item => prefix(name, item));
+    }
+
+    const ret = {};
+    Object.keys(mods).forEach(key => {
+        ret[name + MODS + key] = mods[key];
+    });
+    return ret;
+};
+
+export default {
+    methods: {
+        b(el, mods) {
+            const { name } = this.$options;
+
+            if (el && typeof el !== 'string') {
+                mods = el;
+                el = '';
+            }
+            el = join(name, el, ELEMENT);
+
+            return mods ? [el, prefix(el, mods)] : el;
+        }
+    }
+};

+ 48 - 0
packages/mixins/column.js

@@ -0,0 +1,48 @@
+import * as utils from '../utils/util.js';
+import { validatenull } from '../utils/validate.js';
+import dayjs from 'dayjs';
+export default function() {
+    return {
+        methods: {
+            initFun() {
+                Object.keys(utils).forEach(key => {
+                    this[key] = utils[key];
+                });
+            },
+            cellEditFlag(row, column) {
+                return row.$cellEdit && [undefined, 'select', 'input'].includes(column.type) && column.solt !== true && column.cell;
+            },
+            // 处理数据
+            detail(row, column) {
+                let result = row[column.prop || column.value],
+                    type = column.type;
+                if (validatenull(result)) result = '';
+                if (type) {
+                    //日期处理
+                    if (['date', 'time', 'datetime'].includes(type) && column.format && !validatenull(result)) {
+                        const format = column.format
+                            .replace('dd', 'DD')
+                            .replace('yyyy', 'YYYY');
+                        result = dayjs(result).format(format);
+                    }
+                    // 密码处理
+                    if (['password'].includes(type)) {
+                        return this.getPasswordChar(result.toString().length, '*');
+                    }
+                    //字典处理
+                    if (column.dicData) {
+                        result = this.findByvalue(
+                            (typeof column.dicData === 'string' ? this.DIC[column.dicData] : column.dicData) || [],
+                            result,
+                            (column.props || this.tableOption.props)
+                        );
+                    }
+                }
+                if (column.formatter && typeof column.formatter === 'function') {
+                    result = column.formatter(row, row[column.prop], result, column);
+                }
+                return result;
+            },
+        }
+    }
+}

+ 120 - 0
packages/mixins/crud-compoents.js

@@ -0,0 +1,120 @@
+export default function() {
+    //props配置
+    const propsDefault = {
+            id: 'id',
+            label: 'label',
+            value: 'value',
+            children: 'children',
+            disabled: 'disabled'
+        }
+        //httpProps配置
+    const propsHttpDefault = {
+        name: 'name',
+        url: 'url',
+    }
+    return {
+        data() {
+            return {
+                text: undefined,
+                propsHttpDefault: propsHttpDefault,
+                propsDefault: propsDefault
+            }
+        },
+        props: {
+            change: Function,
+            click: Function,
+            column: {
+                type: Object,
+                default: () => {}
+            },
+            label: {
+                type: String,
+                default: ''
+            },
+            readonly: {
+                type: Boolean,
+                default: false
+            },
+            size: {
+                type: String,
+                default: ''
+            },
+            tip: {
+                type: String,
+                default: ''
+            },
+            disabled: {
+                type: Boolean,
+                default: false
+            },
+            dataType: {
+                type: String
+            },
+            clearable: {
+                type: Boolean,
+                default: true
+            },
+            type: {
+                type: String,
+                default: ''
+            },
+            dic: {
+                type: Array,
+                default: () => []
+            },
+            placeholder: {
+                type: String,
+                default: ''
+            },
+            min: {
+                type: Number
+            },
+            max: {
+                type: Number
+            },
+            border: {
+                type: Boolean,
+                default: false
+            },
+            propsHttp: {
+                type: Object,
+                default: () => propsHttpDefault
+            },
+            props: {
+                type: Object,
+                default: () => propsDefault
+            }
+        },
+        watch: {
+            value() {
+                this.text = this.value;
+            }
+        },
+        computed: {
+            nameKey: function() {
+                return this.propsHttp.name || this.propsHttpDefault.name;
+            },
+            urlKey: function() {
+                return this.propsHttp.url || this.propsHttpDefault.url;
+            },
+            valueKey: function() {
+                return this.props.value || this.propsDefault.value;
+            },
+            labelKey: function() {
+                return this.props.label || this.propsDefault.label;
+            },
+            childrenKey: function() {
+                return this.props.children || this.propsDefault.children;
+            },
+            disabledKey: function() {
+                return this.props.disabled || this.propsDefault.disabled;
+            },
+            idKey: function() {
+                return this.props.id || this.propsDefault.id;
+            }
+        },
+        created() {
+            this.text = this.value;
+        }
+    };
+}

+ 166 - 0
packages/mixins/crud.js

@@ -0,0 +1,166 @@
+import * as utils from '../utils/util.js';
+import { validatenull } from '../utils/validate.js';
+import crudInput from '../crud/src/crud-input';
+import crudSelect from '../crud/src/crud-select';
+import crudRadio from '../crud/src/crud-radio';
+import crudCheckbox from '../crud/src/crud-checkbox';
+import crudCascader from '../crud/src/crud-cascader';
+import crudDate from '../crud/src/crud-date';
+import crudTime from '../crud/src/crud-time';
+import crudInputNumber from '../crud/src/crud-input-number';
+import crudSwitch from '../crud/src/crud-switch';
+import crudRate from '../crud/src/crud-rate';
+import crudUpload from '../crud/src/crud-upload';
+import crudSilder from '../crud/src/crud-silder';
+export default function() {
+    return {
+        props: {
+            option: {
+                type: Object,
+                required: true,
+                default: () => {
+                    return {};
+                }
+            }
+        },
+        components: {
+            crudInput,
+            crudSelect,
+            crudRadio,
+            crudCheckbox,
+            crudDate,
+            crudTime,
+            crudCascader,
+            crudInputNumber,
+            crudSwitch,
+            crudRate,
+            crudUpload,
+            crudSilder
+        },
+        watch: {
+            tableForm: {
+                handler() {
+                    this.$emit('input', this.tableForm);
+                },
+                deep: true
+            },
+            form: {
+                handler() {
+                    this.$emit('input', this.form);
+                },
+                deep: true
+            },
+            option: {
+                handler() {
+                    this.init();
+                },
+                deep: true
+            }
+        },
+        data() {
+            return {
+                DIC: {},
+                dicCascaderList: []
+            };
+        },
+        created() {
+            this.init();
+        },
+        computed: {
+            isMediumSize() {
+                return this.controlSize === 'medium' ? 'small' : this.controlSize;
+            },
+            controlSize() {
+                return this.tableOption.size || (this.$AVUE || {}).size || 'medium';
+            }
+        },
+        methods: {
+            init() {
+                // 初始化工具
+                this.initFun();
+                this.tableOption = this.option;
+                const dicFlag = this.vaildData(this.tableOption.dicFlag, true);
+                // 规则初始化
+                this.rulesInit();
+
+                // 初始化字典
+                if (dicFlag) this.dicInit();
+                else this.DIC = this.tableOption.dicData;
+
+                // 初始化表单formInitVal
+                this.formInit();
+
+
+            },
+            dicInit() {
+                let locaDic = this.tableOption.dicData || {};
+                this.columnOption.forEach(ele => {
+                    if (this.vaildData(ele.dicFlag, true)) {
+                        if (!validatenull(ele.dicUrl)) {
+                            this.dicCascaderList.push({
+                                dicUrl: ele.dicUrl,
+                                dicData: ele.dicData
+                            });
+                        } else if (!validatenull(this.tableOption.dicUrl) && typeof ele.dicData === 'string') {
+                            this.dicCascaderList.push({
+                                dicUrl: this.tableOption.dicUrl,
+                                dicData: ele.dicData
+                            });
+                        }
+                    }
+                });
+                this.GetDic().then(data => {
+                    this.DIC = Object.assign({}, locaDic, data);
+                });
+            },
+            vaildData(val, dafult) {
+                if (typeof val === 'boolean') {
+                    return val;
+                }
+                return !validatenull(val) ? val : dafult;
+            },
+            GetDicByType(href) {
+                return new Promise((resolve) => {
+                    this.$http.get(href).then(function(res) {
+                        // 降级处理
+                        const list = res.data;
+                        if (!validatenull(list.data)) {
+                            resolve(list.data instanceof Array ? list.data : []);
+                        } else if (!validatenull(list)) {
+                            resolve(list instanceof Array ? list : []);
+                        } else {
+                            resolve([]);
+                        }
+                    });
+                });
+            },
+            GetDic() {
+                return new Promise((resolve) => {
+                    let result = [];
+                    let dicData = {};
+                    let cascaderList = Object.assign([], this.dicCascaderList);
+                    if (validatenull(cascaderList)) resolve({});
+                    cascaderList.forEach(ele => {
+                        result.push(new Promise((resolve) => {
+                            this.GetDicByType(`${ele.dicUrl.replace('{{key}}', ele.dicData)}`).then(function(res) {
+                                resolve(res);
+                            });
+                        }));
+                    });
+                    Promise.all(result).then(data => {
+                        cascaderList.forEach((ele, index) => {
+                            dicData[ele.dicData] = data[index];
+                        });
+                        resolve(dicData);
+                    });
+                });
+
+            },
+            initFun() {
+                Object.keys(utils).forEach(key => {
+                    this[key] = utils[key];
+                });
+            }
+        }
+    };
+}

+ 71 - 0
packages/mixins/fun.js

@@ -0,0 +1,71 @@
+export default function() {
+    return {
+        props: {
+            tableLoading: {
+                type: Boolean,
+                default: false,
+            },
+            beforeOpen: Function,
+            beforeClose: Function,
+            uploadBefore: Function,
+            uploadAfter: Function,
+            rowClassName: Function,
+            spanMethod: Function,
+            summaryMethod: Function,
+            data: {
+                type: Array,
+                default: () => []
+            },
+        },
+        methods: {
+            refreshChange(params) {
+                this.$emit('refresh-change', params);
+            },
+            searchReset() {
+                this.$emit('search-reset');
+            },
+            sizeChange(val) {
+                this.$emit('size-change', val);
+            },
+            dateChange(val) {
+                this.$emit('date-change', val);
+            },
+            currentChange(val) {
+                this.$emit('current-change', val);
+            },
+            currentRowChange(currentRow, oldCurrentRow) {
+                this.$emit('current-row-change', currentRow, oldCurrentRow);
+            },
+            selectionChange(val) {
+                this.$emit('selection-change', val);
+            },
+            sortChange(val) {
+                this.$emit('sort-change', val);
+            },
+            searchChange(val) {
+                this.$emit('search-change', val);
+            },
+            rowDblclick(row, event) {
+                this.$emit('row-dblclick', row, event);
+            },
+            rowClick(row, event, column) {
+                this.$emit('row-click', row, event, column);
+            },
+            rowDel(row, index) {
+                this.$emit('row-del', row, index);
+            },
+            rowSave(row, done, loading) {
+                this.$emit('row-save', row, done, loading);
+            },
+            rowUpdate(row, index, done, loading) {
+                this.$emit('row-update', row, index, done, loading);
+            },
+            rowAdd() {
+                this.$refs.crud.rowAdd();
+            },
+            rowEdit(row, index) {
+                this.$refs.crud.rowEdit(row, index);
+            }
+        }
+    }
+}

+ 7 - 0
packages/steps/index.js

@@ -0,0 +1,7 @@
+import Steps from './src/main';
+
+Steps.install = function(Vue) {
+    Vue.component(Steps.name, Steps);
+};
+
+export default Steps;

+ 282 - 0
packages/steps/src/main.vue

@@ -0,0 +1,282 @@
+<template>
+  <div :class="b()">
+    <el-steps :active="formIndex"
+              :space="option.space"
+              :simple="option.simple"
+              finish-status="process"
+              process-status="wait"
+              :align-center='vaildData(option.simple?false:option.alignCenter,true)'
+              :direction="option.direction"
+              :class="b('tabs',{'steps':option.direction})">
+      <el-step :title="item.label"
+               :icon="item.icon"
+               :status="vaildData(item.status,status[index])"
+               :description="item.description"
+               v-for="(item,index) in columnOption"
+               :key="index"
+               @click.native="option.switchBtn?switchs(index):''"></el-step>
+    </el-steps>
+    <div :class="b('contail')">
+      <slot name="before"></slot>
+      <div v-if="crudFlag">
+        <avue-crud ref="crud"
+                   :option="formOption"
+                   :data="data"
+                   :table-loading="tableLoading"
+                   :before-open="beforeOpen"
+                   :before-close="beforeClose"
+                   :upload-before="uploadBefore"
+                   :upload-after="uploadAfter"
+                   :row-class-name="rowClassName"
+                   :span-method="spanMethod"
+                   :summary-method="summaryMethod"
+                   @refresh-change="refreshChange"
+                   @search-reset="searchReset"
+                   @size-change="size-change"
+                   @date-change="date-change"
+                   @current-change="currentChange"
+                   @current-row-change="currentRowChange"
+                   @selection-change="selectionChange"
+                   @sort-change="sortChange"
+                   @search-change="searchChange"
+                   @row-dblclick="rowDblclick"
+                   @row-click="rowClick"
+                   @row-del="rowDel"
+                   @row-save="rowSave"
+                   @row-update="rowUpdate"
+                   v-model="text">
+          <!-- 自定义搜索 -->
+          <template slot="search">
+            <slot name="search"></slot>
+          </template>
+          <!-- 自定义搜索按钮 -->
+          <template slot="searchMenu">
+            <slot name="searchMenu"></slot>
+          </template>
+          <!-- 自定义表单列 -->
+          <template slot-scope="scope"
+                    v-for="item in formColumnOption"
+                    :slot="item.prop">
+            <slot :value="scope.value"
+                  :column="scope.column"
+                  :dic="scope.dic"
+                  :name="item.prop+'Form'"
+                  v-if="item.formsolt"></slot>
+          </template>
+          <!-- 自定义表格列 -->
+          <template slot-scope="scope"
+                    v-for="item in formColumnOption"
+                    :slot="item.prop">
+            <slot :value="scope.value"
+                  :column="scope.column"
+                  :dic="scope.dic"
+                  :name="item.prop"
+                  v-if="item.solt"></slot>
+          </template>
+          <!-- 表格左侧卡槽 -->
+          <template slot="menuLeft">
+            <slot name="menuLeft"></slot>
+          </template>
+          <!-- 表格右测卡槽 -->
+          <template slot="menuRight">
+            <slot name="menuRight"></slot>
+          </template>
+          <!-- 清空卡槽 -->
+          <template slot="empty">
+            <slot name="empty"
+                  v-if="$slots.empty"></slot>
+          </template>
+          <!-- 折叠面板卡槽 -->
+          <template slot-scope="props"
+                    slot="expand">
+            <slot :row="props.row"
+                  name="expand"></slot>
+          </template>
+          <!-- 菜单栏按钮卡槽 -->
+          <template slot-scope="scope"
+                    slot="menuBtn">
+            <slot name="menuBtn"
+                  :row="scope.row"
+                  :dic="scope.dic"
+                  :label="scope.label"
+                  :index="scope.$index"></slot>
+          </template>
+          <!-- 菜单栏 -->
+          <template slot-scope="scope"
+                    slot="menu">
+            <slot name="menu"
+                  :value="scope.value"
+                  :column="scope.column"
+                  :dic="scope.dic"></slot>
+          </template>
+          <!-- 弹出框按钮 -->
+          <template slot="menuForm">
+            <slot name="menuForm"></slot>
+          </template>
+        </avue-crud>
+        <div :class="b('menu')">
+          <el-button @click="submit"
+                     icon="el-icon-back"
+                     type="primary">{{lastFlag?'提交':'下一步'}}</el-button>
+          <el-button @click="breaks"
+                     icon="el-icon-back"
+                     v-if="formIndex!=1&&vaildData(option.breakBtn,true)">返 回</el-button>
+        </div>
+      </div>
+
+      <avue-form v-else
+                 :option="formOption"
+                 :class="b('form')"
+                 @submit="submit"
+                 v-model="text">
+        <template slot-scope="scope"
+                  v-for="item in formColumnOption"
+                  :slot="item.prop">
+          <slot :value="scope.value"
+                :column="scope.column"
+                :dic="scope.dic"
+                :name="item.prop"
+                v-if="item.formsolt"></slot>
+        </template>
+        <template slot="menuForm">
+          <el-button @click="breaks"
+                     icon="el-icon-back"
+                     v-if="formIndex!=1&&vaildData(option.breakBtn,true)">返 回</el-button>
+          <slot name="menuForm"></slot>
+        </template>
+      </avue-form>
+      <slot name="after"></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+import { deepClone } from '../../utils/util';
+import fun from '../../mixins/fun'
+import { formInitVal, vaildData } from '../../utils/util';
+export default create({
+  name: 'steps',
+  mixins: [fun()],
+  props: {
+    value: {
+      type: Object,
+      default: () => { }
+    },
+    option: {
+      type: Object,
+      required: true
+    }
+  },
+  computed: {
+    lastFlag () {
+      return this.formIndex === this.columnLen;
+    },
+    crudFlag () {
+      return this.objectOption.type === 'crud'
+    },
+    columnOption () {
+      return this.option.column || [];
+    },
+    columnLen () {
+      return this.columnOption.length;
+    },
+    formOption () {
+      return this.objectOption.option;
+    },
+
+    formColumnOption () {
+      return this.formOption.column || [];
+    },
+    objectOption () {
+      let formobj = deepClone(this.columnOption[this.formIndex - 1]);
+      let submitText = formobj.option.submitText;
+      if (!submitText && this.formIndex !== this.columnLen) formobj.option.submitText = '下一步';
+      return formobj;
+    },
+    status () {
+      let status = [];
+      const leng = this.step - 1;
+      for (let i = 0; i < leng; i++) {
+        status.push('success');
+      }
+      return status;
+    }
+
+  },
+  watch: {
+    formOption () {
+      this.formInit();
+      this.$emit('change', this.objectOption);
+    },
+    text: {
+      handler () {
+        for (let o in this.tableForm) {
+          this.tableForm[o] = this.text[o];
+        }
+      },
+      deep: true
+    },
+    value: {
+      handler () {
+        this.formVal();
+      },
+      deep: true
+    }
+  },
+  data () {
+    return {
+      step: 1,
+      tableForm: {},
+      text: {},
+      formIndex: 1
+    };
+  },
+  created () {
+    this.formInit();
+    this.$emit('change', this.columnOption[this.formIndex - 1]);
+  },
+  methods: {
+    reset () {
+      this.formIndex = 1;
+      this.step = 1;
+    },
+    switchs (index) {
+      if (index < this.step) { this.formIndex = index + 1; }
+    },
+    next () {
+      if (this.step <= this.formIndex) {
+        this.step++;
+      }
+      if (!this.lastFlag) {
+        this.formIndex++;
+      }
+
+    },
+    breaks () {
+      this.formIndex--;
+    },
+    vaildData (val, dafult) {
+      return vaildData(val, dafult)
+    },
+    formInit () {
+      const column = this.formOption.column;
+      this.tableForm = formInitVal(column).tableForm;
+      this.formVal();
+    },
+    formVal () {
+      for (let o in this.value) {
+        this.text[o] = this.value[o];
+      }
+      for (let o in this.tableForm) {
+        this.tableForm[o] = this.text[o];
+      }
+      this.$emit('input', this.tableForm);
+    },
+    submit () {
+      this.$emit('submit', this.tableForm, this.next);
+    }
+  }
+});
+</script>
+

+ 7 - 0
packages/table-tree/index.js

@@ -0,0 +1,7 @@
+import TableTree from './src/main';
+
+TableTree.install = function(Vue) {
+  Vue.component(TableTree.name, TableTree);
+};
+
+export default TableTree;

+ 25 - 0
packages/table-tree/src/eval.js

@@ -0,0 +1,25 @@
+'use strict';
+import Vue from 'vue';
+export default function treeToArray(data, expandAll, parent = null, level = null) {
+  let tmp = [];
+  Array.from(data).forEach(function(record) {
+    if (record._expanded === undefined) {
+      Vue.set(record, '_expanded', expandAll);
+    }
+    let _level = 1;
+    if (level !== undefined && level !== null) {
+      _level = level + 1;
+    }
+    Vue.set(record, '_level', _level);
+    // 如果有父元素
+    if (parent) {
+      Vue.set(record, 'parent', parent);
+    }
+    tmp.push(record);
+    if (record.children && record.children.length > 0) {
+      const children = treeToArray(record.children, expandAll, record, _level);
+      tmp = tmp.concat(children);
+    }
+  });
+  return tmp;
+}

+ 130 - 0
packages/table-tree/src/main.vue

@@ -0,0 +1,130 @@
+<template>
+  <el-table :data="formatData"
+            :class="b()"
+            :stripe="option.stripe"
+            :row-style="showRow"
+            :row-class-name="rowClassName"
+            v-bind="$attrs"
+            :border="border">
+    <el-table-column v-if="columns.length===0"
+                     width="150">
+      <template slot-scope="scope">
+        <span v-for="space in scope.row._level"
+              class="ms-tree-space"
+              :key="space"></span>
+        <span class="tree-ctrl"
+              v-if="iconShow(0,scope.row)"
+              @click="toggleExpanded(scope.$index)">
+          <i v-if="!scope.row._expanded"
+             class="el-icon-plus"></i>
+          <i v-else
+             class="el-icon-minus"></i>
+        </span>
+        {{scope.$index}}
+      </template>
+    </el-table-column>
+    <el-table-column v-else
+                     v-for="(column, index) in columns"
+                     :key="column.value"
+                     :label="column.text"
+                     :width="column.width">
+      <template slot-scope="scope">
+        <span v-if="index === 0"
+              v-for="space in scope.row._level"
+              class="ms-tree-space"
+              :key="space"></span>
+        <span class="tree-ctrl"
+              v-if="iconShow(index,scope.row)"
+              @click="toggleExpanded(scope.$index)">
+          <i v-if="!scope.row._expanded"
+             class="el-icon-plus"></i>
+          <i v-else
+             class="el-icon-minus"></i>
+        </span>
+        {{detail(scope.row,column)}}
+      </template>
+    </el-table-column>
+    <slot></slot>
+  </el-table>
+</template>
+
+<script>
+import create from '../../utils/create';
+import treeToArray from './eval';
+import crud from '../../mixins/crud.js';
+import column from '../../mixins/column.js';
+export default create({
+  name: 'tree-table',
+  mixins: [crud(), column()],
+  props: {
+    option: {
+      type: Object,
+      required: true
+    },
+    rowClassName: Function,
+    evalFunc: Function,
+    evalArgs: Array
+  },
+  data () {
+    return {};
+  },
+  created () { },
+  computed: {
+    columnOption () {
+      return this.option.columns || [];
+    },
+    data: function () {
+      return this.option.data || [];
+    },
+    columns: function () {
+      return this.option.columns || [];
+    },
+    expandAll: function () {
+      return this.option.expandAll;
+    },
+    border: function () {
+      return this.option.border || true;
+    },
+    // 格式化数据源
+    formatData: function () {
+      let tmp;
+      if (!Array.isArray(this.data)) {
+        tmp = [this.data];
+      } else {
+        tmp = this.data;
+      }
+      const func = this.evalFunc || treeToArray;
+      const args = this.evalArgs
+        ? Array.concat([tmp, this.expandAll], this.evalArgs)
+        : [tmp, this.expandAll];
+      return func.apply(null, args);
+    }
+  },
+  methods: {
+    rulesInit () {
+
+    },
+    formInit () {
+
+    },
+    showRow: function (row) {
+      const show = row.row.parent
+        ? row.row.parent._expanded && row.row.parent._show
+        : true;
+      row.row._show = show;
+      return show
+        ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;'
+        : 'display:none;';
+    },
+    // 切换下级是否展开
+    toggleExpanded: function (trIndex) {
+      const record = this.formatData[trIndex];
+      record._expanded = !record._expanded;
+    },
+    // 图标显示
+    iconShow (index, record) {
+      return index === 0 && record.children && record.children.length > 0;
+    }
+  }
+});
+</script>

+ 7 - 0
packages/tabs/index.js

@@ -0,0 +1,7 @@
+import Tabs from './src/main';
+
+Tabs.install = function(Vue) {
+    Vue.component(Tabs.name, Tabs);
+};
+
+export default Tabs;

+ 231 - 0
packages/tabs/src/main.vue

@@ -0,0 +1,231 @@
+<template>
+  <div class="b()">
+    <el-tabs v-model="formIndex"
+             :type="option.type"
+             :tab-position="option.tabPosition">
+      <el-tab-pane v-for="(item,index) in columnOption"
+                   :key="index"
+                   :disabled="item.disabled"
+                   :name="index+''">
+        <span slot="label">
+          <i :class="item.icon"></i> {{item.label}}</span>
+      </el-tab-pane>
+    </el-tabs>
+    <div>
+      <slot name="before"></slot>
+      <avue-crud v-if="crudFlag"
+                 ref="crud"
+                 :option="formOption"
+                 :data="data"
+                 :table-loading="tableLoading"
+                 :before-open="beforeOpen"
+                 :before-close="beforeClose"
+                 :upload-before="uploadBefore"
+                 :upload-after="uploadAfter"
+                 :row-class-name="rowClassName"
+                 :span-method="spanMethod"
+                 :summary-method="summaryMethod"
+                 @refresh-change="refreshChange"
+                 @search-reset="searchReset"
+                 @size-change="size-change"
+                 @date-change="date-change"
+                 @current-change="currentChange"
+                 @current-row-change="currentRowChange"
+                 @selection-change="selectionChange"
+                 @sort-change="sortChange"
+                 @search-change="searchChange"
+                 @row-dblclick="rowDblclick"
+                 @row-click="rowClick"
+                 @row-del="rowDel"
+                 @row-save="rowSave"
+                 @row-update="rowUpdate"
+                 v-model="text">
+        <!-- 自定义搜索 -->
+        <template slot="search">
+          <slot name="search"></slot>
+        </template>
+        <!-- 自定义搜索按钮 -->
+        <template slot="searchMenu">
+          <slot name="searchMenu"></slot>
+        </template>
+        <!-- 自定义表单列 -->
+        <template slot-scope="scope"
+                  v-for="item in formColumnOption"
+                  :slot="item.prop">
+          <slot :value="scope.value"
+                :column="scope.column"
+                :dic="scope.dic"
+                :name="item.prop+'Form'"
+                v-if="item.formsolt"></slot>
+        </template>
+        <!-- 自定义表格列 -->
+        <template slot-scope="scope"
+                  v-for="item in formColumnOption"
+                  :slot="item.prop">
+          <slot :value="scope.value"
+                :column="scope.column"
+                :dic="scope.dic"
+                :name="item.prop"
+                v-if="item.solt"></slot>
+        </template>
+        <!-- 表格左侧卡槽 -->
+        <template slot="menuLeft">
+          <slot name="menuLeft"></slot>
+        </template>
+        <!-- 表格右测卡槽 -->
+        <template slot="menuRight">
+          <slot name="menuRight"></slot>
+        </template>
+        <!-- 清空卡槽 -->
+        <template slot="empty">
+          <slot name="empty"
+                v-if="$slots.empty"></slot>
+        </template>
+        <!-- 折叠面板卡槽 -->
+        <template slot-scope="props"
+                  slot="expand">
+          <slot :row="props.row"
+                name="expand"></slot>
+        </template>
+        <!-- 菜单栏按钮卡槽 -->
+        <template slot-scope="scope"
+                  slot="menuBtn">
+          <slot name="menuBtn"
+                :row="scope.row"
+                :dic="scope.dic"
+                :label="scope.label"
+                :index="scope.$index"></slot>
+        </template>
+        <!-- 菜单栏 -->
+        <template slot-scope="scope"
+                  slot="menu">
+          <slot name="menu"
+                :value="scope.value"
+                :column="scope.column"
+                :dic="scope.dic"></slot>
+        </template>
+        <!-- 弹出框按钮 -->
+        <template slot="menuForm">
+          <slot name="menuForm"></slot>
+        </template>
+      </avue-crud>
+      <avue-form v-else
+                 :option="formOption"
+                 :upload-before="uploadBefore"
+                 :upload-after="uploadAfter"
+                 @submit="submit"
+                 ref="form"
+                 v-model="text">
+        <template slot-scope="scope"
+                  v-for="item in formColumnOption"
+                  :slot="item.prop">
+          <slot :value="scope.value"
+                :column="scope.column"
+                :dic="scope.dic"
+                :name="item.prop"
+                v-if="item.formsolt"></slot>
+        </template>
+        <template slot="menuForm">
+          <slot name="menuForm"></slot>
+        </template>
+      </avue-form>
+      <slot name="after"></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import create from '../../utils/create';
+import { formInitVal } from '../../utils/util';
+import fun from '../../mixins/fun'
+import { setTimeout } from 'timers';
+export default create({
+  name: 'tabs',
+  mixins: [fun()],
+  props: {
+    value: {
+      type: Object,
+      default: () => { }
+    },
+    option: {
+      type: Object,
+      required: true
+    }
+  },
+  computed: {
+    crudFlag () {
+      return this.objectOption.type === 'crud'
+    },
+    columnOption () {
+      return this.option.column || [];
+    },
+    columnLen () {
+      return this.columnOption.length;
+    },
+    formOption () {
+      return this.objectOption.option;
+    },
+    formColumnOption () {
+      return this.formOption.column || [];
+    },
+    objectOption () {
+      return this.columnOption[this.formIndex];
+    }
+  },
+  watch: {
+    formIndex () {
+      if (!this.crudFlag) {
+        setTimeout(() => {
+          this.$refs.form.clearValidate();
+        }, 0)
+      }
+      this.formInit();
+      this.$emit('change', this.columnOption[this.formIndex]);
+    },
+    text: {
+      handler () {
+        for (let o in this.tableForm) {
+          this.tableForm[o] = this.text[o];
+        }
+      },
+      deep: true
+    },
+    value: {
+      handler () {
+        this.formVal();
+      },
+      deep: true
+    }
+  },
+  data () {
+    return {
+      tableForm: {},
+      text: {},
+      formIndex: '0'
+    };
+  },
+  created () {
+    this.formInit();
+    this.$emit('change', this.columnOption[this.formIndex]);
+  },
+  methods: {
+    formInit () {
+      const column = this.formOption.column;
+      this.tableForm = formInitVal(column).tableForm;
+      this.formVal();
+    },
+    formVal () {
+      for (let o in this.value) {
+        this.text[o] = this.value[o];
+      }
+      for (let o in this.tableForm) {
+        this.tableForm[o] = this.text[o];
+      }
+      this.$emit('input', this.tableForm);
+    },
+    submit () {
+      this.$emit('submit', this.tableForm);
+    },
+  }
+});
+</script>

+ 25 - 0
packages/theme-chalk/gulpfile.js

@@ -0,0 +1,25 @@
+'use strict';
+
+var gulp = require('gulp');
+var sass = require('gulp-sass');
+var autoprefixer = require('gulp-autoprefixer');
+var cssmin = require('gulp-cssmin');
+
+gulp.task('compile', function() {
+  return gulp.src('./src/**')
+    .pipe(sass.sync())
+    .pipe(autoprefixer({
+      browsers: ['ie > 9', 'last 2 versions'],
+      cascade: false
+    }))
+    .pipe(cssmin())
+    .pipe(gulp.dest('./lib'));
+});
+
+gulp.task('copyfont', function() {
+  return gulp.src('./src/fonts/**')
+    .pipe(cssmin())
+    .pipe(gulp.dest('./lib/fonts'));
+});
+
+gulp.task('build', ['compile', 'copyfont']);

+ 1 - 0
packages/theme-chalk/lib/carousel.css

@@ -0,0 +1 @@
+.avue-carousel__item{position:relative;width:100%;height:100%}.avue-carousel__item a{width:100%;height:100%;display:block}.avue-carousel__img{height:100%;background-size:cover;background-position:center center}.avue-carousel__title{z-index:1024;position:absolute;left:0;bottom:0;width:100%;height:50px;line-height:50px;font-size:16px;text-align:center;color:#fff;background-color:rgba(0,0,0,.6)}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/common.css


+ 1 - 0
packages/theme-chalk/lib/crud-upload.css

@@ -0,0 +1 @@
+.avue-crud-upload--list .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avue-crud-upload--list .el-upload:hover{border-color:#409eff}.avue-crud-upload__icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avue-crud-upload__avatar{width:178px;height:178px;display:block}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/crud.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/data-box.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/data-card.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/data-display.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/data-icons.css


+ 1 - 0
packages/theme-chalk/lib/data-progress.css

@@ -0,0 +1 @@
+.data-progress .item{margin:10px}.data-progress .item-header{margin-bottom:10px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.data-progress .item-count{line-height:26px;font-size:26px;color:#666}.data-progress .item-title{color:#999;font-size:14px}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/data-tabs.css


+ 1 - 0
packages/theme-chalk/lib/date-group.css

@@ -0,0 +1 @@
+.avue-date-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-date-group__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-date-group__date{width:300px}.avue-date-group__date .el-date-editor{border-top-left-radius:0;border-bottom-left-radius:0}

+ 1 - 0
packages/theme-chalk/lib/date-select.css

@@ -0,0 +1 @@
+.avue-date-select{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-date-select__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-date-select__date{width:300px}.avue-date-select__date .el-date-editor{border-top-left-radius:0;border-bottom-left-radius:0}

+ 1 - 0
packages/theme-chalk/lib/element-ui.css

@@ -0,0 +1 @@
+.avue-input-number,.el-cascader,.el-date-editor.el-input,.el-date-editor.el-input__inner,.el-select{width:100%!important}.el-input__inner{height:38px;line-height:38px}.el-input--small input{height:32px!important;line-height:32px!important}.el-input--mini input{height:28px!important;line-height:28px!important}.el-table--medium td{padding:7px 0!important}.el-tooltip__popper{max-width:60%}.el-dropdown-menu__item{line-height:25px}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/form-detail.css


+ 1 - 0
packages/theme-chalk/lib/form-steps.css

@@ -0,0 +1 @@
+.avue-form-steps--vertical{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.avue-form-steps__steps{width:230px}.avue-form-steps__contail{-webkit-box-flex:1;-ms-flex:1;flex:1}.avue-form-steps__form{margin:0 auto}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/form.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/index.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/json.css


+ 1 - 0
packages/theme-chalk/lib/select-date.css

@@ -0,0 +1 @@
+.avue-select-date{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-select-date__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-select-date__date{width:300px}.avue-select-date__date .el-date-editor{padding:0 10px;height:36px;border-top-left-radius:0;border-bottom-left-radius:0}

+ 1 - 0
packages/theme-chalk/lib/steps.css

@@ -0,0 +1 @@
+.avue-steps__menu{text-align:center}.avue-steps--vertical{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.avue-steps__tabs{cursor:pointer}.avue-steps__steps{width:230px}.avue-steps__contail{padding:20px 0;-webkit-box-flex:1;-ms-flex:1;flex:1}.avue-steps__form{margin:0 auto}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1 - 0
packages/theme-chalk/lib/table-tree.css


+ 1 - 0
packages/theme-chalk/lib/tree.css

@@ -0,0 +1 @@
+.avue-tree__item{position:relative;width:100%}.avue-tree__title{font-size:14px}.avue-tree__icon{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.avue-tree__menu{position:absolute;top:2px;right:2px;z-index:1024}.avue-tree__filter{margin-bottom:15px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}

+ 24 - 0
packages/theme-chalk/package.json

@@ -0,0 +1,24 @@
+{
+    "name": "avue-theme-chalk",
+    "version": "2.0.0",
+    "main": "lib/index.css",
+    "style": "lib/index.css",
+    "files": [
+        "lib",
+        "src"
+    ],
+    "scripts": {
+        "build": "gulp build"
+    },
+    "keywords": [],
+    "license": "MIT",
+    "bugs": {
+        "devDependencies": {
+            "gulp": "^3.9.1",
+            "gulp-cssmin": "^0.1.7",
+            "gulp-sass": "^3.1.0",
+            "gulp-autoprefixer": "^4.0.0"
+        },
+        "dependencies": {}
+    }
+}

+ 30 - 0
packages/theme-chalk/src/carousel.scss

@@ -0,0 +1,30 @@
+.avue-carousel {
+    &__item {
+        position: relative;
+        width: 100%;
+        height: 100%;
+        a {
+            width: 100%;
+            height: 100%;
+            display: block;
+        }
+    }
+    &__img {
+        height: 100%;
+        background-size: cover;
+        background-position: center center;
+    }
+    &__title {
+        z-index: 1024;
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        width: 100%;
+        height: 50px;
+        line-height: 50px;
+        font-size: 16px;
+        text-align: center;
+        color: #fff;
+        background-color: rgba(0, 0, 0, .6);
+    }
+}

+ 38 - 0
packages/theme-chalk/src/common.scss

@@ -0,0 +1,38 @@
+.avue-ghost {
+    opacity: 0.5;
+    background: #c8ebfb;
+}
+
+.avue-dialog {
+    max-height: 500px;
+    overflow: hidden;
+    overflow-y: auto;
+}
+
+.avue-tip {
+    position: relative;
+    margin-bottom: 12px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    &__icon {
+        margin-top: 3px;
+        margin-right: 5px;
+        font-size: 14px;
+    }
+    &__name {
+        font-size: 12px;
+        margin-right: 15px;
+        color: #515a6e;
+        &--bold {
+            padding: 0 6px;
+            color: #409eff;
+            font-weight: bold;
+            font-size: 18px;
+        }
+    }
+    &__btn {
+        margin-top: 3px;
+        cursor: pointer;
+    }
+}

+ 27 - 0
packages/theme-chalk/src/crud-upload.scss

@@ -0,0 +1,27 @@
+.avue-crud-upload {
+    &--list {
+        .el-upload {
+            border: 1px dashed #d9d9d9;
+            border-radius: 6px;
+            cursor: pointer;
+            position: relative;
+            overflow: hidden;
+        }
+        .el-upload:hover {
+            border-color: #409eff;
+        }
+    }
+    &__icon {
+        font-size: 28px;
+        color: #8c939d;
+        width: 178px;
+        height: 178px;
+        line-height: 178px;
+        text-align: center;
+    }
+    &__avatar {
+        width: 178px;
+        height: 178px;
+        display: block;
+    }
+}

+ 95 - 0
packages/theme-chalk/src/crud.scss

@@ -0,0 +1,95 @@
+.avue-crud {
+    margin: 0 auto;
+    width: 99%;
+    .el-table th {
+        word-break: break-word;
+        color: rgba(0, 0, 0, 0.85);
+        background-color: #fafafa;
+    }
+    &__pagination {
+        position: relative;
+        height: 25px;
+        margin-top: 15px;
+        margin-bottom: 10px;
+        padding: 10px 20px;
+        .el-pagination {
+            position: absolute;
+            right: 0;
+        }
+    }
+    &__form {
+        padding: 0 8px;
+    }
+    &__header {
+        margin-bottom: 10px;
+        &>.el-button {
+            padding: 12px 25px;
+        }
+    }
+    &__box {
+        box-shadow: none !important;
+        border: none;
+        .el-card__body,
+        .el-card__header {
+            padding: 18px 0;
+        }
+    }
+    &__title {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+    }
+    &__menu {
+        position: relative;
+        width: 100%;
+        min-height: 40px;
+        height: auto;
+        overflow: hidden;
+        margin-bottom: 12px;
+    }
+    &__left,
+    &__right {
+        position: absolute;
+        height: auto;
+        overflow: hidden;
+    }
+    &__left {
+        left: 0;
+        .el-button {
+            margin-right: 5px;
+        }
+    }
+    &__right {
+        right: 0;
+        .el-button {
+            margin-left: 5px;
+        }
+    }
+    &__dialog {
+        .el-dialog__header {
+            border-top-left-radius: 5px;
+            border-top-right-radius: 5px;
+            padding: 12px 20px;
+            background-color: #409eff;
+        }
+        .el-dialog__close {
+            color: #fff;
+            font-size: 18px;
+            &:hover {
+                color: #ffddff;
+            }
+        }
+        .el-dialog__title {
+            color: #fff;
+            font-size: 18px;
+        }
+        .el-dialog__headerbtn {
+            top: 18px;
+        }
+        &--overflow {
+            max-height: 400px;
+            overflow: hidden;
+            overflow-y: auto;
+        }
+    }
+}

+ 51 - 0
packages/theme-chalk/src/data-box.scss

@@ -0,0 +1,51 @@
+.data-box {
+    $height: 100px;
+    $radius: 5px;
+    .item {
+        position: relative;
+        margin: 0 auto 10px auto;
+        width: 96%;
+        height: $height;
+        overflow: hidden;
+        border-radius: $radius;
+        box-sizing: border-box;
+        &:hover .item-text {
+            top: 0;
+        }
+        a {
+            display: flex;
+        }
+    }
+    .item-icon {
+        width: 100px;
+        height: $height;
+        color: #fff;
+        text-align: center;
+        line-height: $height;
+        align-items: center;
+        justify-content: center;
+        display: flex;
+        i {
+            font-size: 48px !important;
+        }
+    }
+    .item-info {
+        border: 1px solid #eee;
+        border-left: none;
+        background-color: #fff;
+        flex: 1;
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+        .title {
+            font-size: 30px;
+            line-height: 40px;
+            text-align: center;
+        }
+        .info {
+            color: #999;
+            font-size: 14px;
+            text-align: center;
+        }
+    }
+}

+ 44 - 0
packages/theme-chalk/src/data-card.scss

@@ -0,0 +1,44 @@
+.data-card {
+    $height: 340px;
+    .item {
+        position: relative;
+        margin: 0 auto;
+        margin-bottom: 50px;
+        width: 230px;
+        height: $height;
+        overflow: hidden;
+        border-radius: 5px;
+        border-color: #fff;
+        border-width: 1px;
+        border-style: solid;
+        &:hover .item-text {
+            top: 0;
+        }
+    }
+    .item-img {
+        width: 100%;
+        background: red;
+        border-radius: 5px;
+        border-bottom-left-radius: 0;
+        border-bottom-right-radius: 0;
+    }
+    .item-text {
+        position: absolute;
+        top: 150px;
+        padding: 20px 15px;
+        width: 100%;
+        height: $height;
+        overflow: auto;
+        box-sizing: border-box;
+        border-radius: 5px;
+        border-top-left-radius: 0;
+        border-top-right-radius: 0;
+        opacity: 0.9;
+        transition: top 0.4s;
+        &>p {
+            font-size: 12px;
+            line-height: 25px;
+            text-indent: 2em;
+        }
+    }
+}

+ 25 - 0
packages/theme-chalk/src/data-display.scss

@@ -0,0 +1,25 @@
+.avue-data-display {
+    .item {
+        display: flex;
+        align-items: center;
+        flex-direction: column;
+        margin: 5px 0;
+        text-align: center;
+    }
+    .count {
+        margin: 8px 0;
+        font-weight: bold;
+        font-size: 32px;
+        color: #15A0FF;
+    }
+    .title {
+        color: #999;
+    }
+    .splitLine {
+        display: block;
+        margin: 0 auto;
+        width: 24px;
+        height: 1px;
+        background: #9B9B9B;
+    }
+}

+ 40 - 0
packages/theme-chalk/src/data-icons.scss

@@ -0,0 +1,40 @@
+.data-icons {
+    .item {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 90%;
+        margin: 0 auto;
+    }
+    .item-icon {
+        margin-top: 3px;
+        margin-right: 8px;
+        &>i {
+            font-size: 46px !important;
+        }
+    }
+    .item-info {
+        text-align: center;
+        &>span {
+            display: block;
+            color: #999;
+            font-size: 12px;
+        }
+        .count {
+            font-size: 20px;
+            line-height: 25px;
+        }
+    }
+    .item--easy {
+        flex-direction: column;
+        &>.item-icon {
+            margin: 0;
+        }
+        &>.item-info {
+            margin-top: -15px;
+            &>span {
+                font-size: 14px;
+            }
+        }
+    }
+}

+ 20 - 0
packages/theme-chalk/src/data-progress.scss

@@ -0,0 +1,20 @@
+.data-progress {
+    .item {
+        margin: 10px;
+        &-header {
+            margin-bottom: 10px;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+        }
+        &-count {
+            line-height: 26px;
+            font-size: 26px;
+            color: #666;
+        }
+        &-title {
+            color: #999;
+            font-size: 14px;
+        }
+    }
+}

+ 67 - 0
packages/theme-chalk/src/data-tabs.scss

@@ -0,0 +1,67 @@
+.data-tabs {
+    .item {
+        position: relative;
+        margin: 15px;
+        padding: 12px;
+        height: 160px;
+        border-radius: 4px;
+        box-sizing: border-box;
+        overflow: hidden;
+        color: #fff;
+        a {
+            color: #fff;
+        }
+    }
+    .item-header {
+        position: relative;
+        &>p {
+            color: #fff;
+            margin: 0px;
+            font-size: 14px;
+        }
+        &>span {
+            position: absolute;
+            right: 0px;
+            top: 0px;
+            padding: 2px 8px;
+            border-radius: 4px;
+            font-size: 12px;
+            background: rgba(255, 255, 255, 0.3);
+        }
+    }
+    .item-body {
+        &>h2 {
+            color: #fff;
+            margin: 0;
+            font-size: 32px;
+            line-height: 60px;
+        }
+    }
+    .item-footer {
+        padding-top: 8px;
+        line-height: 20px;
+        &>span {
+            font-size: 10px;
+        }
+        &>p {
+            color: #fff;
+            margin: 0px;
+            font-size: 12px;
+        }
+    }
+    .item-tip {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        position: absolute;
+        width: 80px;
+        height: 80px;
+        bottom: 10px;
+        right: 10px;
+        border: 2px solid #fff;
+        border-radius: 100%;
+        font-size: 48px;
+        transform: rotate(-40deg);
+        opacity: 0.1;
+    }
+}

+ 0 - 0
packages/theme-chalk/src/date-group.scss


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor