diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100755
index 00000000..1a114bc0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,33 @@
+---
+name: Bug report(报告问题)
+about: Create a report to help us improve
+---
+<!--
+    注意:为更好的解决你的问题,请参考模板提供完整信息,准确描述问题,信息不全的 issue 将被关闭。
+
+    Note: In order to better solve your problem, please refer to the template to provide complete information, accurately describe the problem, and the incomplete information issue will be closed.
+-->
+
+
+## Bug report(问题描述)
+
+#### Steps to reproduce(问题复现步骤)
+<!--
+1. [xxx]
+2. [xxx]
+3. [xxxx]
+-->
+
+#### Screenshot or Gif(截图或动态图)
+
+
+#### Link to minimal reproduction(最小可在线还原demo)
+
+<!--
+Please only use Codepen, JSFiddle, CodeSandbox or a github repo
+-->
+
+#### Other relevant information(格外信息)
+- Your OS:
+- Node.js version:
+- vue-element-admin version:
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100755
index 00000000..c33d10d4
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,7 @@
+---
+name: Feature Request(新功能建议)
+about: Suggest an idea for this project
+---
+
+## Feature request(新功能建议)
+
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100755
index 00000000..96be4532
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,14 @@
+---
+name: Question(提问)
+about: Asking questions about use
+---
+
+## Question(提问)
+
+<!--
+    提问之前,请确定你已经过自己的努力,尝试解决过这个问题。
+    若是代码相关问题,请不要只截图,请提供在线 demo,以便节约彼此的时间。
+
+    Before asking a question, please make sure that you have tried your best to solve this problem.
+    If it's a code-related issue, please don't just take screenshots. Please provide an online demo to save each other's time.
+-->
diff --git a/mock/role/routes.js b/mock/role/routes.js
index d8eaf42a..14413d48 100644
--- a/mock/role/routes.js
+++ b/mock/role/routes.js
@@ -19,7 +19,7 @@ export const constantRoutes = [
   },
   {
     path: '/auth-redirect',
-    component: 'views/login/authredirect',
+    component: 'views/login/authRedirect',
     hidden: true
   },
   {
diff --git a/src/components/DndList/index.vue b/src/components/DndList/index.vue
index a4643c0a..23ca006e 100644
--- a/src/components/DndList/index.vue
+++ b/src/components/DndList/index.vue
@@ -2,7 +2,7 @@
   <div class="dndList">
     <div :style="{width:width1}" class="dndList-list">
       <h3>{{ list1Title }}</h3>
-      <draggable :list="list1" group="article" class="dragArea">
+      <draggable :set-data="setData" :list="list1" group="article" class="dragArea">
         <div v-for="element in list1" :key="element.id" class="list-complete-item">
           <div class="list-complete-item-handle">
             {{ element.id }}[{{ element.author }}] {{ element.title }}
@@ -94,6 +94,11 @@ export default {
       if (this.isNotInList1(ele)) {
         this.list1.push(ele)
       }
+    },
+    setData(dataTransfer) {
+      // to avoid Firefox bug
+      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
+      dataTransfer.setData('Text', '')
     }
   }
 }
diff --git a/src/components/Kanban/index.vue b/src/components/Kanban/index.vue
index 1171b5b8..c2cb4691 100644
--- a/src/components/Kanban/index.vue
+++ b/src/components/Kanban/index.vue
@@ -7,6 +7,7 @@
       :list="list"
       v-bind="$attrs"
       class="board-column-content"
+      :set-data="setData"
     >
       <div v-for="element in list" :key="element.id" class="board-item">
         {{ element.name }} {{ element.id }}
@@ -39,6 +40,13 @@ export default {
         return []
       }
     }
+  },
+  methods: {
+    setData(dataTransfer) {
+      // to avoid Firefox bug
+      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
+      dataTransfer.setData('Text', '')
+    }
   }
 }
 </script>
diff --git a/src/lang/index.js b/src/lang/index.js
index 7c9c8af6..c443f41b 100644
--- a/src/lang/index.js
+++ b/src/lang/index.js
@@ -24,11 +24,24 @@ const messages = {
     ...elementEsLocale
   }
 }
+export function getLanguage() {
+  const chooseLanguage = Cookies.get('language')
+  if (chooseLanguage) return chooseLanguage
 
+  // if has not choose language
+  const language = (navigator.language || navigator.browserLanguage).toLowerCase()
+  const locales = Object.keys(messages)
+  for (const locale of locales) {
+    if (language.indexOf(locale) > -1) {
+      return locale
+    }
+  }
+  return 'en'
+}
 const i18n = new VueI18n({
   // set locale
   // options: en | zh | es
-  locale: Cookies.get('language') || 'en',
+  locale: getLanguage(),
   // set locale messages
   messages
 })
diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue
index b0ee54c1..d544f079 100644
--- a/src/layout/components/Navbar.vue
+++ b/src/layout/components/Navbar.vue
@@ -1,19 +1,19 @@
 <template>
   <div class="navbar">
-    <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
+    <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
 
-    <breadcrumb class="breadcrumb-container" />
+    <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
 
     <div class="right-menu">
       <template v-if="device!=='mobile'">
-        <search class="right-menu-item" />
+        <search id="header-search" class="right-menu-item" />
 
         <error-log class="errLog-container right-menu-item hover-effect" />
 
-        <screenfull class="right-menu-item hover-effect" />
+        <screenfull id="screenfull" class="right-menu-item hover-effect" />
 
         <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
-          <size-select class="right-menu-item hover-effect" />
+          <size-select id="size-select" class="right-menu-item hover-effect" />
         </el-tooltip>
 
         <lang-select class="right-menu-item hover-effect" />
diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
index bdddaba6..f06f5156 100644
--- a/src/layout/components/TagsView/index.vue
+++ b/src/layout/components/TagsView/index.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="tags-view-container">
+  <div id="tags-view-container" class="tags-view-container">
     <scroll-pane ref="scrollPane" class="tags-view-wrapper">
       <router-link
         v-for="tag in visitedViews"
@@ -243,7 +243,7 @@ export default {
   .contextmenu {
     margin: 0;
     background: #fff;
-    z-index: 100;
+    z-index: 3000;
     position: absolute;
     list-style-type: none;
     padding: 5px 0;
diff --git a/src/router/index.js b/src/router/index.js
index a883d398..22dad190 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -57,7 +57,7 @@ export const constantRoutes = [
   },
   {
     path: '/auth-redirect',
-    component: () => import('@/views/login/authredirect'),
+    component: () => import('@/views/login/authRedirect'),
     hidden: true
   },
   {
diff --git a/src/store/index.js b/src/store/index.js
index 4842ea7e..70736d3a 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,24 +1,24 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
-import app from './modules/app'
-import errorLog from './modules/errorLog'
-import permission from './modules/permission'
-import tagsView from './modules/tagsView'
-import settings from './modules/settings'
-import user from './modules/user'
 import getters from './getters'
 
 Vue.use(Vuex)
 
+// https://webpack.js.org/guides/dependency-management/#requirecontext
+const modulesFiles = require.context('./modules', false, /\.js$/)
+
+// you do not need `import app from './modules/app'`
+// it will auto require all vuex module from modules file
+const modules = modulesFiles.keys().reduce((modules, modulePath) => {
+  // set './app.js' => 'app'
+  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
+  const value = modulesFiles(modulePath)
+  modules[moduleName] = value.default
+  return modules
+}, {})
+
 const store = new Vuex.Store({
-  modules: {
-    app,
-    errorLog,
-    permission,
-    tagsView,
-    settings,
-    user
-  },
+  modules,
   getters
 })
 
diff --git a/src/store/modules/app.js b/src/store/modules/app.js
index 84875dd6..73616469 100644
--- a/src/store/modules/app.js
+++ b/src/store/modules/app.js
@@ -1,4 +1,5 @@
 import Cookies from 'js-cookie'
+import { getLanguage } from '@/lang/index'
 
 const state = {
   sidebar: {
@@ -6,7 +7,7 @@ const state = {
     withoutAnimation: false
   },
   device: 'desktop',
-  language: Cookies.get('language') || 'en',
+  language: getLanguage(),
   size: Cookies.get('size') || 'medium'
 }
 
diff --git a/src/store/modules/errorLog.js b/src/store/modules/errorLog.js
index c97d452a..8e3db060 100644
--- a/src/store/modules/errorLog.js
+++ b/src/store/modules/errorLog.js
@@ -1,4 +1,3 @@
-
 const state = {
   logs: []
 }
diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js
index 5cbe32f3..3e2c1703 100644
--- a/src/store/modules/tagsView.js
+++ b/src/store/modules/tagsView.js
@@ -1,4 +1,3 @@
-
 const state = {
   visitedViews: [],
   cachedViews: []
diff --git a/src/views/guide/defineSteps.js b/src/views/guide/defineSteps.js
index 405a3f72..283c672e 100644
--- a/src/views/guide/defineSteps.js
+++ b/src/views/guide/defineSteps.js
@@ -1,6 +1,6 @@
 const steps = [
   {
-    element: '.hamburger-container',
+    element: '#hamburger-container',
     popover: {
       title: 'Hamburger',
       description: 'Open && Close sidebar',
@@ -8,7 +8,7 @@ const steps = [
     }
   },
   {
-    element: '.breadcrumb-container',
+    element: '#breadcrumb-container',
     popover: {
       title: 'Breadcrumb',
       description: 'Indicate the current page location',
@@ -16,31 +16,31 @@ const steps = [
     }
   },
   {
-    element: '.screenfull',
+    element: '#header-search',
+    popover: {
+      title: 'Page Search',
+      description: 'Page search, quick navigation',
+      position: 'left'
+    }
+  },
+  {
+    element: '#screenfull',
     popover: {
       title: 'Screenfull',
-      description: 'Bring the page into fullscreen',
+      description: 'Set the page into fullscreen',
       position: 'left'
     }
   },
   {
-    element: '.international-icon',
+    element: '#size-select',
     popover: {
-      title: 'Switch language',
-      description: 'Switch the system language',
+      title: 'Switch Size',
+      description: 'Switch the system size',
       position: 'left'
     }
   },
   {
-    element: '.theme-switch',
-    popover: {
-      title: 'Theme Switch',
-      description: 'Custom switch system theme',
-      position: 'left'
-    }
-  },
-  {
-    element: '.tags-view-container',
+    element: '#tags-view-container',
     popover: {
       title: 'Tags view',
       description: 'The history of the page you visited',
diff --git a/src/views/login/authredirect.vue b/src/views/login/authRedirect.vue
similarity index 92%
rename from src/views/login/authredirect.vue
rename to src/views/login/authRedirect.vue
index 69e15397..7df89342 100644
--- a/src/views/login/authredirect.vue
+++ b/src/views/login/authRedirect.vue
@@ -1,6 +1,6 @@
 <script>
 export default {
-  name: 'Authredirect',
+  name: 'AuthRedirect',
   created() {
     const hash = window.location.search.slice(1)
     if (window.localStorage) {
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index ac467584..979cfcb4 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -77,7 +77,7 @@
 <script>
 import { validUsername } from '@/utils/validate'
 import LangSelect from '@/components/LangSelect'
-import SocialSign from './socialsignin'
+import SocialSign from './socialSignin'
 
 export default {
   name: 'Login',
diff --git a/src/views/login/socialsignin.vue b/src/views/login/socialSignin.vue
similarity index 100%
rename from src/views/login/socialsignin.vue
rename to src/views/login/socialSignin.vue
diff --git a/src/views/table/dragTable.vue b/src/views/table/dragTable.vue
index 50077c6c..7abbd932 100644
--- a/src/views/table/dragTable.vue
+++ b/src/views/table/dragTable.vue
@@ -113,9 +113,9 @@ export default {
       this.sortable = Sortable.create(el, {
         ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
         setData: function(dataTransfer) {
-          dataTransfer.setData('Text', '')
           // to avoid Firefox bug
           // Detail see : https://github.com/RubaXa/Sortable/issues/1012
+          dataTransfer.setData('Text', '')
         },
         onEnd: evt => {
           const targetRow = this.list.splice(evt.oldIndex, 1)[0]