Leopoldthecoder 9 年之前
父节点
当前提交
1c3d119caf

+ 3 - 0
components.json

@@ -151,5 +151,8 @@
   ],
   "card": [
     "./packages/card/index.js"
+  ],
+  "rate": [
+    "./packages/rate/index.js"
   ]
 }

+ 91 - 0
examples/docs/rate.md

@@ -0,0 +1,91 @@
+<script>
+  export default {
+    data() {
+      return {
+        value1: null,
+        value2: null,
+        value3: null,
+        value4: null,
+        value5: 3.6
+      };
+    }
+  }
+</script>
+<style>
+  .demo-box.demo-rate {
+    margin: 20px 0;
+  }
+</style>
+## 基础用法
+
+<div class="demo-box demo-rate">
+  <el-rate v-model="value1"></el-rate>
+</div>
+
+``` html
+<el-rate v-model="value1"></el-rate>
+```
+
+## 区分颜色
+
+利用颜色对分数及情感倾向进行分级。分数可以被分为三个等级,对应的两个阈值可分别通过 `low-threshold` 和 `high-threshold` 设定。
+
+<div class="demo-box demo-rate">
+  <el-rate v-model="value2" multi-color></el-rate>
+</div>
+
+``` html
+<el-rate v-model="value2" multi-color></el-rate>
+```
+
+## 辅助文字
+
+为组件设置 `show-text` 属性会在右侧显示辅助文字。通过设置 `texts` 可以为每一个分值指定对应的辅助文字。`texts` 为一个数组,长度应等于最大值 `max`。
+
+<div class="demo-box demo-rate">
+  <el-rate v-model="value3" show-text></el-rate>
+</div>
+
+``` html
+<el-rate v-model="value3" show-text></el-rate>
+```
+
+## 其他 icon
+
+<div class="demo-box demo-rate">
+  <el-rate v-model="value4" smiley></el-rate>
+</div>
+
+``` html
+<el-rate v-model="value4" smiley></el-rate>
+```
+
+## 只读
+为组件设置 `disabled` 属性表示组件为只读,支持小数分值。此时若设置 `show-text`,则会在右侧显示目前的分值。可以提供 `text-template` 作为显示模板,模板为一个包含了 `{value}` 的字符串,`{value}` 会被解析为分值。
+
+<div class="demo-box demo-rate">
+  <el-rate v-model="value5" disabled show-text text-template="{value} 分"></el-rate>
+</div>
+
+``` html
+<el-rate v-model="value5" disabled show-text text-template="{value} 分"></el-rate>
+```
+## Attributes
+| 参数      | 说明    | 类型      | 可选值       | 默认值   |
+|---------- |-------- |---------- |-------------  |-------- |
+| v-model | 绑定值 | Number | | 0 |
+| max | 最大分值 | Number | | 5 |
+| multi-color | 是否根据分数等级区分颜色 | Boolean | | false |
+| lowThreshold | 低分和中等分数的界限值,值本身被划分在低分中 | Number | | 2 |
+| highThreshold | 高分和中等分数的界限值,值本身被划分在高分中 | Number | | 4 |
+| smiley | 是否使用 smiley icon | Boolean | | false |
+| disabled | 是否为只读 | Boolean | | false |
+| show-text | 是否显示辅助文字 | Boolean | | false |
+| texts | 辅助文字数组 | Array | | ['极差', '失望', '一般', '满意', '惊喜'] |
+| text-template | 只读时的辅助文字模板 | String | | '{value}' |
+
+## Events
+| 事件名称      | 说明    | 回调参数      |
+|---------- |-------- |---------- |
+| change | 分值改变时触发 | 改变后的分值 |
+

+ 5 - 0
examples/nav.config.json

@@ -178,6 +178,11 @@
         "name": "滑块 (slider)",
         "title": "slider 滑块",
         "description": "通过拖动滑块在一个固定区间内进行选择"
+      },
+      {
+        "path": "/rate",
+        "name": "评分 (rate)",
+        "title": "评分组件"
       }
     ]
   },

+ 31 - 0
packages/rate/cooking.conf.js

@@ -0,0 +1,31 @@
+var cooking = require('cooking');
+var path = require('path');
+
+cooking.set({
+  entry: {
+    index: path.join(__dirname, 'index.js')
+  },
+  dist: path.join(__dirname, 'lib'),
+  template: false,
+  format: 'umd',
+  moduleName: 'ElRate',
+  extractCSS: 'style.css',
+
+  extends: ['vue', 'saladcss']
+});
+
+cooking.add('resolve.alias', {
+  'main': path.join(__dirname, '../../src'),
+  'packages': path.join(__dirname, '../../packages')
+});
+
+cooking.add('externals', {
+  vue: {
+    root: 'Vue',
+    commonjs: 'vue',
+    commonjs2: 'vue',
+    amd: 'vue'
+  }
+});
+
+module.exports = cooking.resolve();

二进制
packages/rate/fonts/icomoon.eot


+ 19 - 0
packages/rate/fonts/icomoon.svg

@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Generated by IcoMoon</metadata>
+<defs>
+<font id="icomoon" horiz-adv-x="1024">
+<font-face units-per-em="1024" ascent="960" descent="-64" />
+<missing-glyph horiz-adv-x="1024" />
+<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
+<glyph unicode="&#xe900;" glyph-name="rate-face-void" d="M0 448c0 282.766 229.234 512 512 512s512-229.234 512-512c0-282.766-229.234-512-512-512s-512 229.234-512 512zM947.2 448c0 240.351-194.849 435.2-435.2 435.2s-435.2-194.849-435.2-435.2c0-240.351 194.849-435.2 435.2-435.2s435.2 194.849 435.2 435.2zM294.4 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM627.2 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM361.143 281.6c-22.711 0-41.143-18.637-41.143-41.6s18.432-41.6 41.143-41.6h301.714c22.711 0 41.143 18.637 41.143 41.6s-18.432 41.6-41.143 41.6h-301.714z" />
+<glyph unicode="&#xe901;" d="M512.001 960c-282.771 0-512.001-229.23-512.001-512.002 0-282.77 229.23-511.998 512.001-511.998 282.769 0 511.999 229.227 511.999 511.998s-229.23 512.002-511.999 512.002v0z" />
+<glyph unicode="&#xe902;" d="M294.4 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM627.2 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM694.529 181.197l-3.422 1.216c-56.15 27.872-116.388 42.047-178.882 42.047-64.556 0-125.611-14.316-181.515-42.45l-3.382-1.132c-2.102-0.628-4.945-1.529-8.489-1.529-20.554 0-37.239 18.29-37.239 40.734 0 10.655 4.571 21.361 12.114 29.399l-0.456 2.483 9.516 4.698c66.74 33.104 139.336 50.537 209.907 50.537 71.889 0 142.336-16.984 210.314-50.948 11.943-7.181 19.405-20.953 19.405-35.903 0-26.328-21.71-47.958-47.871-39.153z" />
+<glyph unicode="&#xe903;" d="M512-64c-282.766 0-512 229.234-512 512s229.234 512 512 512c282.766 0 512-229.234 512-512s-229.234-512-512-512v0z" />
+<glyph unicode="&#xe904;" d="M294.4 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM627.2 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM361.143 281.6c-22.711 0-41.143-18.637-41.143-41.6s18.432-41.6 41.143-41.6h301.714c22.711 0 41.143 18.637 41.143 41.6s-18.432 41.6-41.143 41.6h-301.714z" />
+<glyph unicode="&#xe905;" d="M512.001 960c-282.77 0-512.001-229.23-512.001-511.999s229.23-512.001 512.001-512.001c282.77 0 511.999 229.23 511.999 511.999s-229.229 512.001-511.999 512.001v0z" />
+<glyph unicode="&#xe906;" d="M817.495 305.565c-0.445-1.485-0.963-2.939-1.569-4.35-0.676-1.572-1.455-3.089-2.317-4.556-55.631-107.613-169.518-181.459-301.323-181.459-0.096 0-0.19 0.002-0.286 0.002s-0.19-0.002-0.286-0.002c-131.804 0-245.693 73.845-301.323 181.459-0.862 1.467-1.641 2.984-2.317 4.556-0.606 1.41-1.124 2.865-1.569 4.35-1.103 3.68-1.705 7.569-1.705 11.597 0 6.566 1.579 12.771 4.372 18.282 6.897 13.601 21.239 22.955 37.822 22.955s30.927-9.355 37.823-22.955h0.676c41.411-81.453 127.131-137.544 226.507-137.652 99.375 0.108 185.095 56.2 226.507 137.652h0.676c6.897 13.601 21.239 22.955 37.823 22.955s30.927-9.355 37.822-22.955c2.794-5.511 4.372-11.715 4.372-18.282 0-4.029-0.602-7.918-1.705-11.597zM627.2 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307zM294.4 588.853c0 28.247 22.726 51.147 51.2 51.147 28.277 0 51.2-22.664 51.2-51.147v-51.307c0-28.247-22.726-51.147-51.2-51.147-28.277 0-51.2 22.664-51.2 51.147v51.307z" />
+<glyph unicode="&#xe907;" glyph-name="rate-star-void" d="M779.518 29.414c10.587-6.217 18.901-9.345 23.926-9.961-0.519 0.064-4.025-0.689-8.174-3.745-4.111-3.028-5.83-6.069-5.909-6.499 0.928 5.022 0.452 13.902-2.267 25.831l-48.871 214.449c-11.327 49.703 8.583 109.981 46.99 143.349l167.879 145.854c9.047 7.86 14.515 14.575 16.618 18.988-0.298-0.625-0.709-4.339 0.932-9.381 1.625-4.994 4.071-7.682 4.562-7.95-4.432 2.418-12.992 4.717-25.18 5.835l-223.357 20.487c-50.107 4.596-101.469 41.879-121.596 88.102l-87.917 201.902c-4.865 11.172-9.736 18.558-13.464 22.030 0.263-0.245 3.332-1.609 8.231-1.609s7.966 1.364 8.228 1.608c-3.729-3.473-8.599-10.858-13.464-22.029l-87.917-201.902c-20.245-46.493-71.405-83.498-121.596-88.102l-223.357-20.487c-12.361-1.134-21.058-3.451-25.573-5.895 0.491 0.266 2.985 2.987 4.647 8.087 1.682 5.159 1.254 8.952 0.946 9.593 2.149-4.476 7.719-11.291 16.911-19.277l167.879-145.854c38.555-33.497 58.274-93.837 46.99-143.349l-48.871-214.449c-2.708-11.883-3.172-20.709-2.242-25.684-0.086 0.458-1.816 3.501-5.91 6.501-4.101 3.005-7.542 3.743-8.025 3.684 5.004 0.611 13.26 3.712 23.753 9.874l192.138 112.831c43.815 25.73 107.277 25.631 150.924 0l192.138-112.831zM465.263 93.189l-192.138-112.831c-68.347-40.136-109.472-10.003-91.85 67.322l48.871 214.449c6.589 28.911-6.009 67.933-28.834 87.764l-167.879 145.854c-59.718 51.883-44.364 99.791 35.183 107.088l223.357 20.487c29.367 2.694 62.617 26.566 74.634 54.163l87.917 201.902c31.697 72.793 83.086 72.801 114.787 0l87.917-201.902c11.853-27.22 45.236-51.466 74.634-54.163l223.357-20.487c79.149-7.26 94.51-55.544 35.183-107.088l-167.879-145.854c-22.513-19.56-35.514-58.452-28.834-87.764l48.871-214.449c17.62-77.317-23.159-107.66-91.85-67.322l-192.138 112.831c-25.767 15.131-67.185 15.341-93.309 0z" />
+<glyph unicode="&#xe908;" glyph-name="rate-star" d="M558.572 93.189c-25.767 15.131-67.185 15.341-93.309 0l-192.138-112.831c-68.347-40.136-109.472-10.003-91.85 67.322l48.871 214.449c6.589 28.911-6.009 67.933-28.834 87.764l-167.879 145.854c-59.718 51.883-44.364 99.791 35.183 107.088l223.357 20.487c29.367 2.694 62.617 26.566 74.634 54.163l87.917 201.902c31.697 72.793 83.086 72.801 114.787 0l87.917-201.902c11.853-27.22 45.236-51.466 74.634-54.163l223.357-20.487c79.149-7.26 94.51-55.544 35.183-107.088l-167.879-145.854c-22.513-19.56-35.514-58.452-28.834-87.764l48.871-214.449c17.62-77.317-23.159-107.66-91.85-67.322l-192.138 112.831z" />
+</font></defs></svg>

二进制
packages/rate/fonts/icomoon.ttf


二进制
packages/rate/fonts/icomoon.woff


+ 7 - 0
packages/rate/index.js

@@ -0,0 +1,7 @@
+const Rate = require('./src/main');
+
+Rate.install = function(Vue) {
+  Vue.component(Rate.name, Rate);
+};
+
+module.exports = Rate;

+ 15 - 0
packages/rate/package.json

@@ -0,0 +1,15 @@
+{
+  "name": "el-rate",
+  "version": "0.0.0",
+  "description": "A rate component for Vue.js.",
+  "keywords": [
+    "element",
+    "vue",
+    "component"
+  ],
+  "main": "./lib/index.js",
+  "repository": "https://github.com/element-component/element/tree/master/packages/rate",
+  "author": "elemefe",
+  "license": "MIT",
+  "dependencies": {}
+}

+ 241 - 0
packages/rate/src/main.vue

@@ -0,0 +1,241 @@
+<template>
+  <div class="el-rate">
+    <span
+      v-for="item in max"
+      class="el-rate__item"
+      @mouseenter="setCurrentValue(item)"
+      @mouseleave="resetCurrentValue"
+      @click="selectValue(item)"
+      :style="{ cursor: disabled ? 'auto' : 'pointer' }">
+      <i
+        :class="[classes[item - 1], {'hover': hoverIndex === item}]"
+        class="el-rate__icon"
+        :style="getIconStyle(item)">
+        <span class="path1" v-if="smiley && item <= currentValue"></span>
+        <span class="path2" v-if="smiley && item <= currentValue"></span>
+        <i
+          v-if="showDecimalIcon(item)"
+          :class="decimalIconClass"
+          :style="decimalStyle"
+          class="el-rate__decimal">
+          <span class="path1" v-if="smiley"></span>
+          <span class="path2" v-if="smiley"></span>
+        </i>
+      </i>
+    </span>
+    <span v-if="showText" class="el-rate__text" :style="textStyle">{{ text }}</span>
+  </div>
+</template>
+
+<script type="text/babel">
+  const CLASS_MAP = {
+    noSmiley: 'icon-rate-star',
+    noSmileyVoid: 'icon-rate-star-void',
+    smileyLow: 'icon-rate-face-gray',
+    smileyMedium: 'icon-rate-face-yellow',
+    smileyHigh: 'icon-rate-face-orange',
+    smileyVoid: 'icon-rate-face-void'
+  };
+  const COLOR_MAP = {
+    lowColor: '#99A9BF',
+    mediumColor: '#F7BA2A',
+    highColor: '#FF9900',
+    voidColor: '#C6D1DE',
+    disbaledVoidColor: '#EFF2F7'
+  };
+  import '../style.css';
+  export default {
+    name: 'el-rate',
+
+    data() {
+      return {
+        classes: null,
+        currentValue: 0,
+        colors: null,
+        hoverIndex: -1
+      };
+    },
+
+    props: {
+      value: {
+        type: Number,
+        default: 0
+      },
+      lowThreshold: {
+        type: Number,
+        default: 2
+      },
+      highThreshold: {
+        type: Number,
+        default: 4
+      },
+      max: {
+        type: Number,
+        default: 5
+      },
+      multiColor: {
+        type: Boolean,
+        default: false
+      },
+      smiley: {
+        type: Boolean,
+        default: false
+      },
+      disabled: {
+        type: Boolean,
+        default: false
+      },
+      showText: {
+        type: Boolean,
+        default: false
+      },
+      texts: {
+        type: Array,
+        default() {
+          return ['极差', '失望', '一般', '满意', '惊喜'];
+        }
+      },
+      textTemplate: {
+        type: String,
+        default: '{value}'
+      }
+    },
+
+    computed: {
+      text() {
+        let result = '';
+        if (this.disabled) {
+          result = this.textTemplate.replace('{value}', this.value);
+        } else {
+          result = this.texts[this.currentValue - 1];
+        }
+        return result;
+      },
+
+      textStyle() {
+        let color = '';
+        if (this.multiColor || this.smiley) {
+          color = this.getValueFromMap(this.currentValue, COLOR_MAP);
+        } else {
+          color = COLOR_MAP.mediumColor;
+        }
+        return { color };
+      },
+
+      decimalStyle() {
+        return {
+          color: this.smiley ? '' : this.activeColor,
+          width: this.valueDecimal + '%'
+        };
+      },
+
+      valueDecimal() {
+        return this.value * 100 - Math.floor(this.value) * 100;
+      },
+
+      decimalIconClass() {
+        let className = '';
+        if (!this.smiley) {
+          className = CLASS_MAP.noSmiley;
+        } else {
+          className = this.getValueFromMap(this.value, CLASS_MAP);
+        }
+        return className;
+      },
+
+      voidClass() {
+        const noSmileyVoidClass = this.disabled ? CLASS_MAP.noSmiley : CLASS_MAP.noSmileyVoid;
+        return this.smiley ? CLASS_MAP.smileyVoid : noSmileyVoidClass;
+      },
+
+      activeClass() {
+        let className = '';
+        if (this.smiley) {
+          className = this.getValueFromMap(this.currentValue, CLASS_MAP);
+        } else {
+          className = CLASS_MAP.noSmiley;
+        }
+        return className;
+      },
+
+      activeColor() {
+        let color = '';
+        if (!this.smiley) {
+          if (this.multiColor) {
+            color = this.getValueFromMap(this.currentValue, COLOR_MAP);
+          } else {
+            color = COLOR_MAP.mediumColor;
+          }
+        }
+        return color;
+      },
+
+      classes() {
+        let result = new Array(this.max);
+        result.fill(this.activeClass, 0, this.currentValue).fill(this.voidClass, this.currentValue, this.max);
+        return result;
+      }
+    },
+
+    watch: {
+      value(val) {
+        this.$emit('change', val);
+        this.currentValue = val;
+      }
+    },
+
+    methods: {
+      getValueFromMap(value, map) {
+        let result = '';
+        if (value <= this.lowThreshold) {
+          result = map.lowColor || map.smileyLow;
+        } else if (value >= this.highThreshold) {
+          result = map.highColor || map.smileyHigh;
+        } else {
+          result = map.mediumColor || map.smileyMedium;
+        }
+        return result;
+      },
+
+      showDecimalIcon(item) {
+        return this.disabled && this.valueDecimal > 0 && item - 1 < this.value && item > this.value;
+      },
+
+      getIconStyle(item) {
+        const voidColor = this.disabled ? COLOR_MAP.disbaledVoidColor : COLOR_MAP.voidColor;
+        const noSmileyColor = item <= this.currentValue ? this.activeColor : voidColor;
+        return {
+          color: this.smiley ? '' : noSmileyColor
+        };
+      },
+
+      selectValue(value) {
+        if (this.disabled) {
+          return;
+        }
+        this.currentValue = value;
+        this.$emit('input', value);
+      },
+
+      setCurrentValue(value) {
+        if (this.disabled) {
+          return;
+        }
+        this.currentValue = value;
+        this.hoverIndex = value;
+      },
+
+      resetCurrentValue() {
+        if (this.disabled) {
+          return;
+        }
+        this.currentValue = this.value;
+        this.hoverIndex = -1;
+      }
+    },
+
+    created() {
+      this.currentValue = this.value;
+    }
+  };
+</script>

+ 60 - 0
packages/rate/style.css

@@ -0,0 +1,60 @@
+@font-face {
+  font-family: 'icomoon';
+  src:  url('fonts/icomoon.eot?q2cz0t');
+  src:  url('fonts/icomoon.eot?q2cz0t#iefix') format('embedded-opentype'),
+    url('fonts/icomoon.ttf?q2cz0t') format('truetype'),
+    url('fonts/icomoon.woff?q2cz0t') format('woff'),
+    url('fonts/icomoon.svg?q2cz0t#icomoon') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+
+[class^="icon-"], [class*=" icon-"] {
+  /* use !important to prevent issues with browser extensions that change fonts */
+  font-family: 'icomoon' !important;
+  speak: none;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-transform: none;
+  line-height: 1;
+
+  /* Better Font Rendering =========== */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-rate-face-void:before {
+  content: "\e900";
+}
+.icon-rate-face-gray .path1:before {
+  content: "\e901";
+  color: rgb(192, 204, 218);
+}
+.icon-rate-face-gray .path2:before {
+  content: "\e902";
+  color: rgb(132, 146, 166);
+}
+.icon-rate-face-yellow .path1:before {
+  content: "\e903";
+  color: rgb(247, 186, 42);
+}
+.icon-rate-face-yellow .path2:before {
+  content: "\e904";
+  color: rgb(172, 110, 2);
+}
+.icon-rate-face-orange .path1:before {
+  content: "\e905";
+  color: rgb(255, 153, 0);
+}
+.icon-rate-face-orange .path2:before {
+  content: "\e906";
+  color: rgb(173, 101, 0);
+}
+.icon-rate-star-void:before {
+  content: "\e907";
+}
+.icon-rate-star:before {
+  content: "\e908";
+}
+

+ 1 - 0
packages/theme-default/src/index.css

@@ -33,3 +33,4 @@
 @import "./col.css";
 @import "./spinner.css";
 @import "./card.css";
+@import "./rate.css";

+ 45 - 0
packages/theme-default/src/rate.css

@@ -0,0 +1,45 @@
+@charset "UTF-8";
+@import "./common/var.css";
+
+@component-namespace el {
+
+  @b rate {
+    height: 20px;
+    @e item {
+      display: inline-block;
+      position: relative;
+      font-size: 0;
+      vertical-align: middle;
+    }
+
+    @e icon {
+      position: relative;
+      display: inline-block;
+      font-size: 18px;
+      margin-right: 6px;
+      color: #C6D1DE;
+      &.hover {
+        transform: scale(1.1);
+      }
+
+      .path2 {
+        position: absolute;
+        left: 0;
+        top: 0;
+      }
+    }
+
+    @e decimal {
+      position: absolute;
+      top: 0;
+      left: 0;
+      display: inline-block;
+      overflow: hidden;
+    }
+
+    @e text {
+      font-size: 14px;
+      vertical-align: middle;
+    }
+  }
+}

+ 7 - 1
src/index.js

@@ -48,6 +48,8 @@ import Upload from '../packages/upload/index.js';
 import Progress from '../packages/progress/index.js';
 import Spinner from '../packages/spinner/index.js';
 import Message from '../packages/message/index.js';
+import Card from '../packages/card/index.js';
+import Rate from '../packages/rate/index.js';
 
 const install = function(Vue) {
   if (install.installed) return;
@@ -99,6 +101,8 @@ const install = function(Vue) {
   Vue.component(Progress.name, Progress);
   Vue.component(Spinner.name, Spinner);
   Vue.component(Message.name, Message);
+  Vue.component(Card.name, Card);
+  Vue.component(Rate.name, Rate);
 
   Vue.use(Loading);
 
@@ -166,5 +170,7 @@ module.exports = {
   Upload,
   Progress,
   Spinner,
-  Message
+  Message,
+  Card,
+  Rate
 };