Browse Source

feat: 消息通知组件

ChenYangfan 6 years ago
parent
commit
c345288162
6 changed files with 100 additions and 25 deletions
  1. 7 2
      src/App.vue
  2. 75 13
      src/components/GlobalMessage.vue
  3. 6 9
      src/store/modules/message.js
  4. 2 0
      src/style/theme.scss
  5. 1 0
      src/utils/icon-map.js
  6. 9 1
      src/views/Home.vue

+ 7 - 2
src/App.vue

@@ -1,10 +1,15 @@
 <template>
-  <router-view/>
+  <div>
+    <router-view/>
+    <global-message></global-message>
+  </div>
 </template>
 
 <script>
+import GlobalMessage from '@/components/GlobalMessage'
+
 export default {
-  components: {},
+  components: { GlobalMessage },
   mounted () {}
 }
 </script>

+ 75 - 13
src/components/GlobalMessage.vue

@@ -1,30 +1,62 @@
 <template>
-  <div class="message-wrapper">
+  <div class="message-wrapper" :class="type" v-if="show">
     <div class="message">
-      <div class="icon warning">{{iconfontMap['error']}}</div>
-      自动保存成功!
+      <span class="icon warning">{{iconMap[type] ? iconMap[type] : iconMap['info']}}</span>
+      <span class="message-content">{{ message }}</span>
     </div>
   </div>
 
 </template>
 
 <script>
-import iconfontMap from '@/utils/iconfont-map'
+import iconMap from '@/utils/icon-map'
+import { mapState } from 'vuex'
+import { USE_MESSAGE } from '@/store/types/message-types'
 
 export default {
   data () {
     return {
-      iconfontMap: iconfontMap
+      iconMap: iconMap,
+      show: false
     }
   },
-  computed: {}
+  computed: {
+    ...mapState({
+      message: state => state.message.message,
+      type: state => state.message.type,
+      duration: state => state.message.duration
+    })
+  },
+  watch: {
+    message (newMessage) {
+      if (newMessage) {
+        this.show = false
+        this.$nextTick(() => {
+          this.show = true
+          setTimeout(() => {
+            this.show = false
+            this.$store.commit(USE_MESSAGE)
+          }, 5000)
+        })
+      }
+    }
+  }
 }
 </script>
 
 <style lang="scss" scoped>
+@import "~@/style/theme.scss";
+
 .message-wrapper {
+  width: 100%;
+  opacity: 0;
   display: flex;
   justify-content: center;
+  position: fixed;
+  top: 20px;
+  margin: 0 auto;
+  z-index: 2;
+  animation: show 5s ease-out;
 }
 
 .icon {
@@ -35,24 +67,54 @@ export default {
   user-select: none;
 }
 
-.warning {
-  color: darkorange;
+.message-content {
+  padding: 0 12px 0 4px
 }
 
 .message {
-  color: #2a3a4a;
+  color: #6a7a8a;
   display: flex;
   align-items: center;
   justify-content: center;
-  position: fixed;
-  top: 20px;
-  z-index: 2;
   font-size: 16px;
   font-weight: bold;
   margin: 0 auto;
   padding: 8px 10px;
   border-radius: 100px;
   backdrop-filter: saturate(180%) blur(20px);
-  background: rgba(230, 230, 230, 0.6);
+  background: $theme-blue-transparent;
+}
+
+.error {
+  .message {
+    color: $theme-red;
+    background: $theme-red-transparent;
+  }
+}
+
+.success {
+  .message {
+    color: $theme-green;
+    background: $theme-green-transparent;
+  }
+}
+
+@keyframes show {
+  0% {
+    opacity: 0;
+    transform: translateY(-100px);
+  }
+  12% {
+    opacity: 1;
+    transform: translateY(0);
+  }
+  95% {
+    opacity: 1;
+    transform: translateY(0);
+  }
+  100% {
+    opacity: 0;
+    transform: translateY(-100px);
+  }
 }
 </style>

+ 6 - 9
src/store/modules/message.js

@@ -3,20 +3,17 @@ import { SET_MESSAGE, USE_MESSAGE } from '@/store/types/message-types'
 export default {
   state: {
     message: null,
-    type: null,
-    duration: 0
+    type: null
   },
 
   mutations: {
     [SET_MESSAGE] (state, payload) {
-      this.message = payload.message ? payload.message : '未知消息信息'
-      this.type = payload.type ? payload.type : 'info'
-      this.duration = payload.duration ? payload.duration : 3000
+      state.message = payload.message ? payload.message : '未知消息信息'
+      state.type = payload.type ? payload.type : 'info'
     },
-    [USE_MESSAGE] (state, payload) {
-      this.message = 0
-      this.type = null
-      this.duration = 0
+    [USE_MESSAGE] (state) {
+      state.message = 0
+      state.type = null
     }
   }
 }

+ 2 - 0
src/style/theme.scss

@@ -1,10 +1,12 @@
 $theme-blue: #5485e5;
 $theme-orange: #ffaa44;
 $theme-red: #f44336;
+$theme-green: #4caf50;
 
 $theme-blue-transparent: rgba(84, 133, 229, .1);
 $theme-orange-transparent: rgba(255, 170, 68, .1);
 $theme-red-transparent: rgba(244, 67, 54, .1);
+$theme-green-transparent: rgba(76, 175, 80, .1);
 
 
 $icon-normal-color: #7a8a9a;

+ 1 - 0
src/utils/icon-map.js

@@ -7,6 +7,7 @@ const iconMap = {
   'discussion': '\ue610',
   'error': '\ue686',
   'info': '\ue68e',
+  'success': '\ue67b',
   'explore': '\ue684',
   'courses': '\ue67d',
   'add': '\ue71b',

+ 9 - 1
src/views/Home.vue

@@ -5,7 +5,7 @@
         SEEC 课堂助手
       </h1>
       <c-button @click.native="handleLoginButtonClick" class="full-width mb-12">去登录</c-button>
-      <c-button class="secondary full-width">去注册</c-button>
+      <c-button class="secondary full-width" @click.native="showMessage">去注册</c-button>
     </div>
     <background></background>
   </div>
@@ -14,12 +14,20 @@
 <script>
 import CButton from '@/components/CButton'
 import Background from '@/components/Background'
+import { SET_MESSAGE } from '@/store/types/message-types'
 
 export default {
   components: { CButton, Background },
   methods: {
     handleLoginButtonClick () {
       this.$router.push('/login')
+    },
+    showMessage () {
+      // todo
+      this.$store.commit(SET_MESSAGE, {
+        message: '消息提醒测试',
+        type: 'success'
+      })
     }
   }
 }