diff --git a/api/lib/cmdb/attribute.py b/api/lib/cmdb/attribute.py
index f36de13..1d2fe3f 100644
--- a/api/lib/cmdb/attribute.py
+++ b/api/lib/cmdb/attribute.py
@@ -38,17 +38,30 @@ class AttributeManager(object):
             db.session.add(table)
         db.session.flush()
 
-    def get_attributes(self, name=None):
+    @classmethod
+    def search_attributes(cls, name=None, alias=None, page=1, page_size=None):
         """
         :param name: 
+        :param alias: 
+        :param page: 
+        :param page_size: 
         :return: attribute, if name is None, then return all attributes
         """
-        attrs = Attribute.get_by_like(name=name) if name is not None else Attribute.get_by()
+        if name is not None:
+            attrs = Attribute.get_by_like(name=name)
+        elif alias is not None:
+            attrs = Attribute.get_by_like(alias=alias)
+        else:
+            attrs = Attribute.get_by()
+
+        numfound = len(attrs)
+        attrs = attrs[(page - 1) * page_size:][:page_size]
         res = list()
         for attr in attrs:
-            attr["is_choice"] and attr.update(dict(choice_value=self.get_choice_values(attr["id"], attr["value_type"])))
+            attr["is_choice"] and attr.update(dict(choice_value=cls.get_choice_values(attr["id"], attr["value_type"])))
             res.append(attr)
-        return res
+
+        return numfound, res
 
     def get_attribute_by_name(self, name):
         attr = Attribute.get_by(name=name, first=True)
@@ -112,19 +125,19 @@ class AttributeManager(object):
         is_choice = True if choice_value else False
 
         attr.update(flush=True, **kwargs)
-        
+
         if is_choice:
             self._add_choice_values(attr.id, attr.value_type, choice_value)
-            
+
         try:
             db.session.commit()
         except Exception as e:
             db.session.rollback()
             current_app.logger.error("update attribute error, {0}".format(str(e)))
             return abort(400, "update attribute <{0}> failed".format(_id))
-        
+
         AttributeCache.clean(attr)
-        
+
         return attr.id
 
     @staticmethod
diff --git a/api/lib/cmdb/ci.py b/api/lib/cmdb/ci.py
index 74c5619..e62e675 100644
--- a/api/lib/cmdb/ci.py
+++ b/api/lib/cmdb/ci.py
@@ -34,8 +34,6 @@ from api.models.cmdb import CITypeAttribute
 from api.tasks.cmdb import ci_cache
 from api.tasks.cmdb import ci_delete
 
-__author__ = 'pycook'
-
 
 class CIManager(object):
     """ manage CI interface
diff --git a/api/lib/cmdb/search.py b/api/lib/cmdb/search.py
index 95de15d..df46d9f 100644
--- a/api/lib/cmdb/search.py
+++ b/api/lib/cmdb/search.py
@@ -1,6 +1,8 @@
 # -*- coding:utf-8 -*- 
 
 
+from __future__ import unicode_literals
+
 import time
 
 from flask import current_app
@@ -39,7 +41,7 @@ class Search(object):
         self.query_sql = ""
         self.type_id_list = []
         self.only_type_query = False
-    
+
     @staticmethod
     def _operator_proc(key):
         operator = "&"
@@ -127,7 +129,7 @@ class Search(object):
 
         if self.only_type_query:
             return ret_sql.format(query_sql, "ORDER BY B.ci_id {1} LIMIT {0:d}, {2};".format(
-                    (self.page - 1) * self.count, sort_type, self.count))
+                (self.page - 1) * self.count, sort_type, self.count))
 
         elif self.type_id_list:
             self.query_sql = "SELECT B.ci_id FROM ({0}) AS B {1}".format(
@@ -170,13 +172,13 @@ class Search(object):
         elif self.type_id_list:
             self.query_sql = """SELECT C.ci_id
                                 FROM ({0}) AS C
-                                INNER JOIN cis on c_cis.id=C.ci_id
-                                WHERE cis.type_id in ({1})""".format(new_table, ",".join(self.type_id_list))
+                                INNER JOIN c_cis on c_cis.id=C.ci_id
+                                WHERE c_cis.type_id in ({1})""".format(new_table, ",".join(self.type_id_list))
 
             return """SELECT SQL_CALC_FOUND_ROWS DISTINCT C.ci_id, C.value
                       FROM ({0}) AS C
-                      INNER JOIN cis on c_cis.id=C.ci_id
-                      WHERE cis.type_id in ({4})
+                      INNER JOIN c_cis on c_cis.id=C.ci_id
+                      WHERE c_cis.type_id in ({4})
                       ORDER BY C.value {2}
                       LIMIT {1:d}, {3};""".format(new_table,
                                                   (self.page - 1) * self.count,
@@ -299,7 +301,7 @@ class Search(object):
             self.query_sql = query_sql
             current_app.logger.debug(query_sql)
             numfound, res = self._execute_sql(query_sql)
-            current_app.logger.info("query ci ids is: {0}".format(time.time() - s))
+            current_app.logger.debug("query ci ids is: {0}".format(time.time() - s))
             return numfound, [_res[0] for _res in res]
 
         return 0, []
diff --git a/api/lib/cmdb/value.py b/api/lib/cmdb/value.py
index 951b29e..e4ef9b3 100644
--- a/api/lib/cmdb/value.py
+++ b/api/lib/cmdb/value.py
@@ -14,6 +14,7 @@ from api.lib.cmdb.const import TableMap
 from api.lib.cmdb.const import ExistPolicy
 from api.lib.cmdb.const import OperateType
 from api.lib.cmdb.history import AttributeHistoryManger
+from api.models.cmdb import Attribute
 
 
 class AttributeValueManager(object):
@@ -47,6 +48,7 @@ class AttributeValueManager(object):
             attr = self._get_attr(field)
             if not attr:
                 continue
+
             value_table = TableMap(attr_name=attr.name).table
             rs = value_table.get_by(ci_id=ci_id,
                                     attr_id=attr.id,
@@ -130,9 +132,16 @@ class AttributeValueManager(object):
 
         for v in value_list:
             v = self._validate(attr, v, value_table, ci_id)
+            if not v and attr.value_type != Attribute.TEXT:
+                v = None
+
             if operate_type == OperateType.ADD:
-                value_table.create(ci_id=ci_id, attr_id=attr.id, value=v)
-                self._write_change(ci_id, attr.id, operate_type, None, v)
+                if v is not None:
+                    value_table.create(ci_id=ci_id, attr_id=attr.id, value=v)
+                    self._write_change(ci_id, attr.id, operate_type, None, v)
             elif existed_attr.value != v:
-                existed_attr.update(value=v)
+                if v is not None:
+                    existed_attr.update(value=v)
+                else:
+                    existed_attr.delete()
                 self._write_change(ci_id, attr.id, operate_type, existed_value, v)
diff --git a/api/views/cmdb/attribute.py b/api/views/cmdb/attribute.py
index 0ce947b..b09e3df 100644
--- a/api/views/cmdb/attribute.py
+++ b/api/views/cmdb/attribute.py
@@ -11,16 +11,26 @@ from api.lib.cmdb.const import RoleEnum
 from api.lib.cmdb.attribute import AttributeManager
 from api.lib.decorator import args_required
 from api.lib.utils import handle_arg_list
+from api.lib.utils import get_page
+from api.lib.utils import get_page_size
+
 
 
 class AttributeSearchView(APIView):
     url_prefix = ("/attributes/s", "/attributes/search")
 
     def get(self):
-        q = request.values.get("q")
-        attrs = AttributeManager().get_attributes(name=q)
-        count = len(attrs)
-        return self.jsonify(numfound=count, attributes=attrs)
+        name = request.values.get("name")
+        alias = request.values.get("alias")
+        page = get_page(request.values.get("page", 1))
+        page_size = get_page_size(request.values.get("page_size"))
+        numfound, res = AttributeManager.search_attributes(name=name, alias=alias, page=page, page_size=page_size)
+
+        return self.jsonify(page=page,
+                            page_size=page_size,
+                            numfound=numfound,
+                            total=len(res),
+                            attributes=res)
 
 
 class AttributeView(APIView):
diff --git a/ui/src/views/cmdb/attributes/index.vue b/ui/src/views/cmdb/attributes/index.vue
index b3d97fb..9fac323 100644
--- a/ui/src/views/cmdb/attributes/index.vue
+++ b/ui/src/views/cmdb/attributes/index.vue
@@ -12,7 +12,9 @@
       :rowKey="record=>record.id"
       :rowSelection="options.rowSelection"
       :scroll="scroll"
-      :showPagination="showPagination"
+      :pagination="{ showTotal: (total, range) => `${range[0]}-${range[1]} 共 ${total} 条记录`, pageSizeOptions: pageSizeOptions}"
+      showPagination="auto"
+      :pageSize="25"
       ref="table"
       size="middle"
 
@@ -20,7 +22,7 @@
       <div slot="filterDropdown" slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }" class="custom-filter-dropdown">
         <a-input
           v-ant-ref="c => searchInput = c"
-          :placeholder="`Search ${column.dataIndex}`"
+          :placeholder="` ${column.title}`"
           :value="selectedKeys[0]"
           @change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
           @pressEnter="() => handleSearch(selectedKeys, confirm, column)"
@@ -32,12 +34,12 @@
           icon="search"
           size="small"
           style="width: 90px; margin-right: 8px"
-        >Search</a-button>
+        >搜索</a-button>
         <a-button
           @click="() => handleReset(clearFilters, column)"
           size="small"
           style="width: 90px"
-        >Reset</a-button>
+        >重置</a-button>
       </div>
       <a-icon slot="filterIcon" slot-scope="filtered" type="search" :style="{ color: filtered ? '#108ee9' : undefined }" />
 
@@ -69,7 +71,16 @@
         <template>
           <a @click="handleEdit(record)">编辑</a>
           <a-divider type="vertical"/>
-          <a @click="handleDelete(record)">删除</a>
+
+          <a-popconfirm
+            title="确认删除?"
+            @confirm="handleDelete(record)"
+            @cancel="cancel"
+            okText="是"
+            cancelText="否"
+          >
+            <a>删除</a>
+          </a-popconfirm>
         </template>
       </span>
 
@@ -93,7 +104,7 @@ export default {
   },
   data () {
     return {
-      scroll: { x: 1400, y: 500 },
+      scroll: { x: 1000, y: 500 },
       btnName: '新增属性',
 
       CITypeName: this.$route.params.CITypeName,
@@ -107,11 +118,8 @@ export default {
       transferTargetKeys: [],
       transferSelectedKeys: [],
       originTargetKeys: [],
+      pageSizeOptions: ['10', '25', '50', '100'],
 
-      pagination: {
-        defaultPageSize: 20
-      },
-      showPagination: false,
       columnSearchText: {
         alias: '',
         name: ''
@@ -121,7 +129,7 @@ export default {
           title: '名称',
           dataIndex: 'alias',
           sorter: false,
-          width: 200,
+          width: 250,
           scopedSlots: {
             customRender: 'aliasSearchRender',
             filterDropdown: 'filterDropdown',
@@ -140,7 +148,7 @@ export default {
           title: '英文名',
           dataIndex: 'name',
           sorter: false,
-          width: 200,
+          width: 250,
           scopedSlots: {
             customRender: 'nameSearchRender',
             filterDropdown: 'filterDropdown',
@@ -159,7 +167,7 @@ export default {
           title: '类型',
           dataIndex: 'value_type',
           sorter: false,
-          width: 100,
+          width: 80,
           scopedSlots: { customRender: 'value_type' },
           customRender: (text) => valueTypeMap[text]
 
@@ -167,7 +175,7 @@ export default {
         {
           title: '唯一',
           dataIndex: 'is_unique',
-          width: 80,
+          width: 50,
           sorter: false,
           scopedSlots: { customRender: 'is_check' }
 
@@ -176,7 +184,7 @@ export default {
           title: '索引',
           dataIndex: 'is_index',
           sorter: false,
-          width: 80,
+          width: 50,
           scopedSlots: { customRender: 'is_check' }
 
         },
@@ -184,7 +192,7 @@ export default {
           title: '排序',
           dataIndex: 'is_sortable',
           sorter: false,
-          width: 80,
+          width: 50,
           scopedSlots: { customRender: 'is_check' }
 
         },
@@ -192,7 +200,7 @@ export default {
           title: '链接',
           dataIndex: 'is_link',
           sorter: false,
-          width: 80,
+          width: 50,
           scopedSlots: { customRender: 'is_check' }
 
         },
@@ -200,7 +208,7 @@ export default {
           title: '密码',
           dataIndex: 'is_password',
           sorter: false,
-          width: 100,
+          width: 50,
           scopedSlots: { customRender: 'is_check' }
 
         },
@@ -221,15 +229,22 @@ export default {
         }
       ],
       loadData: parameter => {
+        parameter['page_size'] = parameter['pageSize']
+        parameter['page'] = parameter['pageNo']
+        Object.assign(parameter, this.queryParam)
         console.log('loadData.parameter', parameter)
 
-        return searchAttributes()
+        return searchAttributes(parameter)
           .then(res => {
-            this.allAttributes = res.attributes
-            return {
-              data: res.attributes
+            res.pageNo = res.page
+            res.pageSize = res.total
+            res.totalCount = res.numfound
+            res.totalPage = Math.ceil(res.numfound / parameter.pageSize)
+            res.data = res.attributes
 
-            }
+            console.log('loadData.res', res)
+            this.allAttributes = res.attributes
+            return res
           })
       },
 
@@ -285,17 +300,20 @@ export default {
     this.getAttributes()
     this.setScrollY()
   },
+  inject: ['reload'],
+
   methods: {
     handleSearch (selectedKeys, confirm, column) {
       confirm()
       this.columnSearchText[column.dataIndex] = selectedKeys[0]
+      this.queryParam[column.dataIndex] = selectedKeys[0]
     },
 
     handleReset (clearFilters, column) {
       clearFilters()
       this.columnSearchText[column.dataIndex] = ''
+      this.queryParam[column.dataIndex] = ''
     },
-
     getAttributes () {
       searchAttributes().then(res => {
         this.allAttributes = res.attributes
diff --git a/ui/src/views/cmdb/attributes/module/attributeForm.vue b/ui/src/views/cmdb/attributes/module/attributeForm.vue
index 9959925..7c41f40 100644
--- a/ui/src/views/cmdb/attributes/module/attributeForm.vue
+++ b/ui/src/views/cmdb/attributes/module/attributeForm.vue
@@ -255,7 +255,6 @@ export default {
       e.preventDefault()
       this.form.validateFields((err, values) => {
         if (!err) {
-          // eslint-disable-next-line no-console
           console.log('Received values of form: ', values)
           if (values.choice_value) {
             values.choice_value = values.choice_value.split('\n')