Browse Source

feat: notify

shenqistart 5 years ago
parent
commit
73acdfe02d

+ 10 - 0
src/config.json

@@ -632,6 +632,16 @@
       "sort": "6",
       "sort": "6",
       "showDemo": true,
       "showDemo": true,
       "author": "yangxiaolu"
       "author": "yangxiaolu"
+    },
+    {
+      "version": "1.0.0",
+      "name": "Notify",
+      "type": "method",
+      "chnName": "展示消息提示",
+      "desc": "在页面顶部展示消息提示,支持函数调用和组件调用两种方式",
+      "sort": "2",
+      "showDemo": true,
+      "author": "wangyue217"
     }
     }
   ]
   ]
 }
 }

+ 8 - 6
src/nutui.js

@@ -119,11 +119,13 @@ import './packages/subsidenavbar/subsidenavbar.scss';
 import SideNavBarItem from './packages/sidenavbaritem/index.js';
 import SideNavBarItem from './packages/sidenavbaritem/index.js';
 import './packages/sidenavbaritem/sidenavbaritem.scss';
 import './packages/sidenavbaritem/sidenavbaritem.scss';
 import Drag from './packages/drag/index.js';
 import Drag from './packages/drag/index.js';
-import './packages/drag/drag.scss';
-// import VueQr from "./packages/qart/index.js";
+import './packages/drag/drag.scss'; // import VueQr from "./packages/qart/index.js";
 // import "./packages/qart/qart.scss";
 // import "./packages/qart/qart.scss";
+
 import Address from './packages/address/index.js';
 import Address from './packages/address/index.js';
 import './packages/address/address.scss';
 import './packages/address/address.scss';
+import Notify from "./packages/notify/index.js";
+import "./packages/notify/notify.scss";
 
 
 const packages = {
 const packages = {
   Cell,
   Cell,
@@ -185,7 +187,8 @@ const packages = {
   SubSideNavBar: SubSideNavBar,
   SubSideNavBar: SubSideNavBar,
   SideNavBarItem: SideNavBarItem,
   SideNavBarItem: SideNavBarItem,
   Drag: Drag,
   Drag: Drag,
-  Address: Address
+  Address: Address,
+  Notify: Notify
 };
 };
 
 
 const components = {};
 const components = {};
@@ -213,7 +216,7 @@ pkgList.map(item => {
   }
   }
 });
 });
 
 
-const install = function(Vue, opts = {}) {
+const install = function (Vue, opts = {}) {
   if (install.installed) return;
   if (install.installed) return;
 
 
   if (opts.locale) {
   if (opts.locale) {
@@ -265,9 +268,8 @@ export default {
   install,
   install,
   Lazyload,
   Lazyload,
   // VueQr,
   // VueQr,
-
   ...components,
   ...components,
   ...filters,
   ...filters,
   ...directives,
   ...directives,
   ...methods
   ...methods
-};
+};

+ 110 - 0
src/packages/notify/_notify.js

@@ -0,0 +1,110 @@
+import Vue from 'vue';
+import settings from './notify.vue';
+// 扩展为类
+let NotifyConstructor = Vue.extend(settings);
+let timer, instance, instanceArr = [];
+let defaultOptionsMap = {};
+const id = '0';
+// 默认传入值
+const defaultOptions = {
+  type: 'danger',
+  showPopup: false,
+  msg: '',
+  color: undefined,
+  background: undefined,
+  duration: 3000,
+  className: '',
+  onClosed: null,
+  onClick: null,
+  onOpened: null,
+  textTimer: null,
+};
+// 当前传入值
+let currentOptions = {
+  ...defaultOptions
+};
+// 展示,挂载
+function _showNotify() {
+  instance.vm = instance.$mount();
+  document.body.appendChild(instance.$el);
+  Vue.nextTick(() => {
+    instance.showPopup = true;
+  });
+}
+function _getInstance(obj) {
+  // 默认传递的值
+  let opt = {
+    id
+  };
+  Object.assign(opt, currentOptions, defaultOptionsMap[obj.type], obj);
+  console.log(opt, obj, 'obj');
+  //有相同id者共用一个实例,否则新增实例
+  if (opt['id'] && instanceArr[opt['id']]) {
+    instance = instanceArr[opt['id']];
+    instance.hide(true);
+    instance = Object.assign(instance, opt);
+  } else {
+    instance = new NotifyConstructor({
+      propsData: opt
+    });
+
+    instance = Object.assign(instance, obj);
+    opt['id'] && (instanceArr[opt['id']] = instance);
+  }
+
+  _showNotify();
+  return instance;
+}
+
+function errorMsg(msg) {
+  if (!msg) {
+    console.warn('[NutUI Toast]: msg不能为空');
+    return;
+  }
+}
+
+let Notify = {
+  text(msg, obj = {}) {
+    errorMsg(msg);
+    return _getInstance({ ...obj, msg });
+  },
+  primary(msg, obj = {}) {
+    errorMsg(msg);
+    return _getInstance({ ...obj, msg, type: 'primary' });
+  },
+  success(msg, obj = {}) {
+    errorMsg(msg);
+    return _getInstance({ ...obj, msg, type: 'success' });
+  },
+  danger(msg, obj = {}) {
+    errorMsg(msg);
+    return _getInstance({ ...obj, msg, type: 'danger' });
+  },
+  warn(msg, obj = {}) {
+    errorMsg(msg);
+    return _getInstance({ ...obj, msg, type: 'warning' });
+  },
+
+  // 全局设置默认内容
+  setDefaultOptions(type, options) {
+    if (typeof type === 'string') {
+      defaultOptionsMap[type] = options;
+    } else {
+      Object.assign(currentOptions, type);
+    }
+  },
+  // 重置默认内容
+  resetDefaultOptions(type) {
+    if (typeof type === 'string') {
+      defaultOptionsMap[type] = null;
+    } else {
+      currentOptions = { ...defaultOptions };
+      defaultOptionsMap = {};
+    }
+  }
+};
+
+
+
+
+export default Notify;

+ 120 - 0
src/packages/notify/demo.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="demo-list">
+    <h4>基本用法</h4>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="notify1('通知内容')">
+        <span slot="title">
+          <label>基础用法</label>
+        </span>
+      </nut-cell>
+    </div>
+    <h4>通知类型</h4>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="notify2('通知内容')">
+        <span slot="title">
+          <label>主要通知</label>
+        </span>
+      </nut-cell>
+    </div>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="notify3('成功通知')">
+        <span slot="title">
+          <label>成功通知</label>
+        </span>
+      </nut-cell>
+    </div>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="notify4('危险通知')">
+        <span slot="title">
+          <label>危险通知</label>
+        </span>
+      </nut-cell>
+    </div>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="notify5('警告通知')">
+        <span slot="title">
+          <label>警告通知</label>
+        </span>
+      </nut-cell>
+    </div>
+    <h4>自定义样式</h4>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="cusBgNotify('自定义背景色和字体颜色')">
+        <span slot="title">
+          <label>自定义背景色和字体颜色</label>
+        </span>
+      </nut-cell>
+    </div>
+    <h4>自定义时长</h4>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="timeNotify('自定义时间')">
+        <span slot="title">
+          <label>自定义时长</label>
+        </span>
+      </nut-cell>
+    </div>
+    <h4>组件调用</h4>
+    <div>
+      <nut-cell :showIcon="true" :isLink="true" @click.native="showNotify">
+        <span slot="title">
+          <label>组件调用</label>
+        </span>
+      </nut-cell>
+      <nut-notify :showPopup="show" type="success" msg="通知内容"></nut-notify>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      show: false
+    };
+  },
+  methods: {
+    notify1(val) {
+      this.$notify.text(val, {
+        onClosed() {
+          console.log('close');
+        },
+        onClick: () => {
+          console.log('click');
+        },
+        onOpened: () => {
+          console.log('opened');
+        }
+      });
+    },
+    notify2(val) {
+      this.$notify.primary(val);
+    },
+    notify3(val) {
+      this.$notify.success(val);
+    },
+    notify4(val) {
+      this.$notify.danger(val);
+    },
+    notify5(val) {
+      this.$notify.warn(val);
+    },
+    cusBgNotify(val) {
+      this.$notify.text(val, {
+        color: '#ad0000',
+        background: '#ffe1e1'
+      });
+    },
+    timeNotify(val) {
+      this.$notify.text(val, {
+        duration: 10000
+      });
+    },
+    showNotify() {
+      // debugger;
+      this.show = true;
+      setTimeout(() => {
+        this.show = false;
+      }, 2000);
+    }
+  }
+};
+</script>

+ 50 - 0
src/packages/notify/doc.md

@@ -0,0 +1,50 @@
+# Notify 消息提示
+
+## 基本用法
+
+```html
+    <nut-noticebar
+      text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
+    ></nut-noticebar>
+```
+## 通知类型
+文字内容多于一行时,可通过scrollable参数控制是否开启滚动
+```html
+    <nut-noticebar
+      text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
+      :scrollable="false"
+    ></nut-noticebar>
+```
+## 自定义样式
+
+
+
+
+## Prop
+
+| 字段       | 说明                                     | 类型          | 默认值 |
+| ---------- | ---------------------------------------- | ------------- | ------ |
+| type       | 提示的信息                               | String        | 空     |
+| message    | 展示文案,支持通过\n换行                 | Boolean       | false  |
+| duration   | 展示时长(ms),值为 0 时,notify 不会消失 | String        | 空     |
+| color      | 字体颜色                                 | String        | 空     |
+| background | 背景颜色                                 | String        | 空     |
+| className  | 自定义类名                               | String/Number | 1      |
+
+## Event
+
+| 字段     | 说明               | 回调参数 |
+| -------- | ------------------ | -------- |
+| onClick  | 点击事件回调       | 无       |
+| onOpened | 完全展示后事件回调 | 无       |
+| onClose  | 关闭事件回调       | 无       |
+
+
+## Function
+
+| 方法名                     | 说明                             | 参数    | 返回值  |
+| -------------------------- | -------------------------------- | ------- | ------- |
+| Notify                     | 提示的信息                       | options | message | notify 实例 |
+| Notify.clear               | 关闭提示                         | -       | void    |
+| Notify.setDefaultOptions   | 修改默认配置,对所有 Notify 生效 | options | void    |
+| Notify.resetDefaultOptions | 重置默认配置,对所有 Notify 生效 | String  | void    |

+ 12 - 0
src/packages/notify/index.js

@@ -0,0 +1,12 @@
+import Notify from './_notify';
+import NotifyVue from './notify.vue';
+import './notify.scss';
+
+const NotifyArr = [Notify, NotifyVue];
+// console.log(NotifyArr, Notify.text('Notify'));
+NotifyArr.install = function (Vue) {
+  Vue.prototype['$notify'] = Notify;
+  Vue.component(NotifyVue.name, NotifyVue);
+};
+
+export default NotifyArr

+ 28 - 0
src/packages/notify/notify.scss

@@ -0,0 +1,28 @@
+@import '../../styles/variable.scss';
+.nut-notify {
+    box-sizing: border-box;
+    padding: $notify-padding;
+    color: $notify-text-color;
+    font-size: $notify-font-size;
+    line-height: $notify-line-height;
+  
+    white-space: pre-wrap;
+    text-align: center;
+    word-wrap: break-word;
+  
+    &--primary {
+      background-color: $notify-primary-background-color;
+    }
+  
+    &--success {
+      background-color: $notify-success-background-color;
+    }
+  
+    &--danger {
+      background-color: $notify-danger-background-color;
+    }
+  
+    &--warning {
+      background-color: $notify-warning-background-color;
+    }
+  }

+ 101 - 0
src/packages/notify/notify.vue

@@ -0,0 +1,101 @@
+<template>
+  <nut-popup
+    v-model="showPopup"
+    position="top"
+    :style="{'color':color,
+    'background': background}"
+    :overlay="false"
+    :lockScroll="false"
+    :class="['nut-notify',`nut-notify--${type}`,{className}]"
+    @click="handleClick"
+    @opened="handleOpened"
+    @closed="handleClosed"
+  >{{msg}}</nut-popup>
+</template>
+<script>
+import { overlayProps, getProps } from '../popup/index';
+import Popup from './../popup/popup.vue';
+console.log(overlayProps, 'overlayProps');
+
+export default {
+  name: 'nut-notify',
+  props: {
+    ...overlayProps,
+    color: { type: String, default: '' },
+    msg: { type: [Number, String], default: '' },
+    // duration: { type: [Number, String], default: 3000 },
+    className: {
+      type: String,
+      default: ''
+    },
+    background: { type: String, default: '' },
+    type: {
+      type: String,
+      default: 'danger'
+    },
+    showPopup: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    showPopup(val) {
+      if (val) {
+        this.show();
+      }
+    }
+  },
+  data() {
+    return { timer: null };
+  },
+  components: {
+    'nut-popup': Popup
+  },
+  methods: {
+    handleClick() {
+      typeof this.onClick === 'function' && this.onClick();
+    },
+    handleOpened() {
+      typeof this.onOpened === 'function' && this.onOpened();
+    },
+    handleClosed() {
+      typeof this.onClosed === 'function' && this.onClosed();
+    },
+    show(force) {
+      this.clearTimer();
+      clearTimeout(this.textTimer);
+
+      if (this.duration) {
+        this.timer = setTimeout(() => {
+          this.hide(force);
+        }, this.duration);
+      }
+    },
+    hide(force) {
+      this.clearTimer();
+      this.showPopup = false;
+      if (force) {
+        clearTimeout(this.textTimer);
+      } else {
+        this.textTimer = setTimeout(() => {
+          clearTimeout(this.textTimer);
+          this.msg = '';
+        }, 300);
+      }
+    },
+    clearTimer() {
+      if (this.timer) {
+        clearTimeout(this.timer);
+        this.timer = null;
+      }
+    }
+  },
+  mounted() {
+    console.log(this, this.onClick, this.onOpened, this.onClosed, 'mounted');
+  },
+  destroyed() {
+    this.textTimer = null;
+    this.timer = null;
+  }
+};
+</script>

+ 10 - 0
src/styles/variable.scss

@@ -83,3 +83,13 @@ $assetsPath: '../../assets' !default;
 $stepper-color: #333 !default;
 $stepper-color: #333 !default;
 $stepperbar-width: 11px !default;
 $stepperbar-width: 11px !default;
 $stepperbar-color: #333 !default;
 $stepperbar-color: #333 !default;
+
+// Notify
+$notify-text-color: #fff;
+$notify-padding: 8px 16px;
+$notify-font-size: $font-size-base;
+$notify-line-height: 20px;
+$notify-primary-background-color: #1989fa;
+$notify-success-background-color: #07c160;
+$notify-danger-background-color: #ee0a24;
+$notify-warning-background-color: #ff976a;

+ 1 - 0
types/nutui.d.ts

@@ -81,3 +81,4 @@ export declare class SideNavBarItem extends UIComponent {}
 export declare class Qart extends UIComponent {}
 export declare class Qart extends UIComponent {}
 export declare class Drag extends UIComponent {}
 export declare class Drag extends UIComponent {}
 export declare class Address extends UIComponent {}
 export declare class Address extends UIComponent {}
+export declare class Notify extends UIComponent {}