提交 b90f66b3 编写于 作者: Z zhangyufei1

Merge branch 'next' of https://github.com/jdf2e/nutui into next

registry=https://registry.npmjs.org
engine-strict=true
......@@ -155,6 +155,16 @@ module.exports = {
show: true,
desc: '轻提示',
author: 'undo'
},
{
version: '3.0.0',
name: 'Notify',
type: 'component',
cName: '消息提示',
desc: '在页面顶部展示消息提示,支持函数调用和组件调用两种方式',
sort: 4,
show: true,
author: 'wangyue217'
}
]
},
......@@ -334,6 +344,16 @@ module.exports = {
show: true,
desc: '标签栏组件',
author: 'Drjingfubo'
},
{
version: '3.0.0',
name: 'NoticeBar',
type: 'component',
cName: '公告栏',
desc: '用于循环播放展示一组消息通知',
sort: 5,
show: false,
author: 'wangyue92'
}
]
},
......
......@@ -39,13 +39,34 @@
>
</nut-calendar>
</div>
<h2>自定义日历</h2>
<h2>自定义日历-自动回填</h2>
<div>
<nut-cell
:showIcon="true"
title="选择日期"
:desc="date3 ? date3 : '请选择'"
@click="openSwitch('isVisible3')"
>
</nut-cell>
<nut-calendar
:is-visible="isVisible3"
@close="closeSwitch('isVisible3')"
@choose="setChooseValue3"
:default-value="date3"
:start-date="null"
:end-date="null"
:is-auto-back-fill="true"
>
</nut-calendar>
</div>
<h2>平铺展示</h2>
<div class="test-calendar-wrapper">
<nut-calendar
:poppable="false"
:is-visible="isVisible2"
:default-value="date2"
:is-auto-back-fill="true"
@choose="setChooseValue2"
>
</nut-calendar>
......@@ -64,12 +85,11 @@ interface TestCalendarState {
isVisible: boolean;
date: string;
dateWeek: string;
date2: string;
isVisible2: boolean;
isVisible1: boolean;
date1: string[];
date2: string;
isVisible3: boolean;
date3: string;
}
export default createDemo({
props: {},
......@@ -79,11 +99,13 @@ export default createDemo({
date: '',
dateWeek: '',
isVisible1: false,
date1: ['2019-12-23', '2019-12-26'],
date2: '2020-07-08',
isVisible2: true,
isVisible1: false,
date1: ['2019-12-23', '2019-12-26']
isVisible3: false,
date3: ''
});
const openSwitch = param => {
state[`${param}`] = true;
......@@ -98,13 +120,17 @@ export default createDemo({
state.dateWeek = param[4];
};
const setChooseValue1 = param => {
state.date1 = [...[param[0][3], param[1][3]]];
};
const setChooseValue2 = param => {
state.date2 = param[3];
console.log(state.date2);
};
const setChooseValue1 = param => {
state.date1 = [...[param[0][3], param[1][3]]];
const setChooseValue3 = param => {
state.date3 = param[3];
};
return {
......@@ -112,8 +138,9 @@ export default createDemo({
openSwitch,
closeSwitch,
setChooseValue,
setChooseValue1,
setChooseValue2,
setChooseValue1
setChooseValue3
};
}
});
......
# calendar组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
\ No newline at end of file
# calendar 组件
### 介绍
日历,可平铺/弹窗展示
### 安装
```javascript
import { createApp } from 'vue';
import { Calendar } from '@nutui/nutui';
const app = createApp();
app.use(Calendar);
```
## 代码演示
### 基础用法
```html
<nut-cell
:showIcon="true"
title="选择单个日期"
:desc="date ? `${date} ${dateWeek}` : '请选择'"
@click="openSwitch('isVisible')"
>
</nut-cell>
<nut-calendar
:is-visible="isVisible"
:default-value="date"
@close="closeSwitch('isVisible')"
@choose="setChooseValue"
:start-date="`2019-10-11`"
:end-date="`2022-11-11`"
>
</nut-calendar>
```
```javascript
setup() {
const state: TestCalendarState = reactive({
isVisible: false,
date: '',
dateWeek: ''
});
const openSwitch = param => {
state[`${param}`] = true;
};
const closeSwitch = param => {
state[`${param}`] = false;
};
const setChooseValue = param => {
state.date = param[3];
state.dateWeek = param[4];
};
return {
...toRefs(state),
openSwitch,
closeSwitch,
setChooseValue
};
}
```
### 区间选择
```html
<nut-cell
:showIcon="true"
title="选择日期区间"
:desc="date ? `${date[0]}至${date[1]}` : '请选择'"
@click="openSwitch('isVisible')"
>
</nut-cell>
<nut-calendar
:is-visible="isVisible"
:default-value="date"
type="range"
:start-date="`2019-12-22`"
:end-date="`2021-01-08`"
@close="closeSwitch('isVisible')"
@choose="setChooseValue"
>
</nut-calendar>
```
```javascript
setup() {
const state: TestCalendarState = reactive({
date: ['2019-12-23', '2019-12-26'],
isVisible2: true
});
const openSwitch = param => {
state[`${param}`] = true;
};
const closeSwitch = param => {
state[`${param}`] = false;
};
const setChooseValue= param => {
state.date = [...[param[0][3], param[1][3]]];
};
return {
...toRefs(state),
openSwitch,
closeSwitch,
setChooseValue,
};
}
```
### 自定义日历-自动回填
```html
<nut-cell
:showIcon="true"
title="选择日期"
:desc="date ? date : '请选择'"
@click="openSwitch('isVisible')"
>
</nut-cell>
<nut-calendar
:is-visible="isVisible"
@close="closeSwitch('isVisible')"
@choose="setChooseValue"
:start-date="null"
:end-date="null"
:is-auto-back-fill="true"
>
</nut-calendar>
```
```javascript
setup() {
const state: TestCalendarState = reactive({
date: '',
isVisible: false
});
const openSwitch = param => {
state[`${param}`] = true;
};
const closeSwitch = param => {
state[`${param}`] = false;
};
const setChooseValue = param => {
state.date= param[3];
};
return {
...toRefs(state),
setChooseValue
};
}
```
### 平铺展示
```html
<div class="test-calendar-wrapper">
<nut-calendar
:poppable="false"
:is-auto-back-fill="true"
:default-value="date"
@choose="setChooseValue"
>
</nut-calendar
></div>
```
```javascript
setup() {
const state: TestCalendarState = reactive({
date: '2020-07-08'
});
const setChooseValue = param => {
state.date = param[3];
};
return {
...toRefs(state),
setChooseValue
};
}
```
### 基础用法
```html
```
```javascript
```
## API
### Props
| 字段 | 说明 | 类型 | 默认值 |
| ----------------- | ------------------------------------------------- | -------------- | --------------- |
| type | 类型,日期选择'one',区间选择'range' | String | 'one' |
| is-visible | 是否可见 | Boolean | false |
| poppable | 是否弹窗状态展示 | Boolean | true |
| is-auto-back-fill | 自动回填 | Boolean | false |
| title | 显示标题 | String | ‘日期选择’ |
| default-value | 默认值,日期选择 String 格式,区间选择 Array 格式 | String / Array | null |
| start-date | 开始日期, 如果不限制开始日期传 null | String | 今天 |
| end-date | 结束日期,如果不限制结束日期传 null | String | 距离今天 365 天 |
### Events
| 事件名 | 说明 | 回调参数 |
| choose | 选择之后或是点击确认按钮触发 | 日期数组(包含年月日和星期)
| close | 关闭时触发 | -
<template>
<nut-popup
v-if="poppable"
v-model:show="state.childIsVisible"
position="bottom"
round
@click="closeActionSheet"
v-if="poppable"
:closeable="true"
@click-overlay="closePopup"
@click-close-icon="closePopup"
>
<nut-calendar-item
props
ref="mychild"
ref="calendarRef"
:type="type"
:is-auto-back-fill="isAutoBackFill"
:poppable="poppable"
......@@ -83,7 +85,7 @@ export default create({
setup(props, { emit }) {
// element refs
const mychild = ref<null | HTMLElement>(null);
const calendarRef = ref<null | HTMLElement>(null);
// state
const state = reactive({
......@@ -91,10 +93,6 @@ export default create({
});
// methods
const closeActionSheet = () => {
//mychild.value && mychild.value.closeActionSheet();
};
const update = () => {
state.childIsVisible = false;
};
......@@ -108,6 +106,10 @@ export default create({
emit('choose', param);
};
const closePopup = () => {
close();
};
watch(
() => props.isVisible,
val => {
......@@ -118,11 +120,11 @@ export default create({
);
return {
closeActionSheet,
closePopup,
update,
close,
choose,
mychild,
calendarRef,
state,
...toRefs(props)
};
......
......@@ -2,7 +2,7 @@
position: relative;
display: flex;
flex: 1;
height: 100%;
height: 518px;
padding-top: 132px;
padding-bottom: 78px;
color: $calendar-base-color;
......@@ -11,6 +11,7 @@
overflow: hidden;
&.nut-calendar-tile {
height: 100%;
padding-top: 46px;
padding-bottom: 0;
......@@ -21,6 +22,10 @@
}
}
&.nut-calendar-nofooter {
padding-bottom: 0;
}
// 头部导航
.nut-calendar-header {
position: absolute;
......@@ -51,7 +56,6 @@
align-items: center;
justify-content: space-around;
height: 46px;
border-radius: 0px 0px 12px 12px;
box-shadow: 0px 4px 10px 0px rgba($color: #000000, $alpha: 0.06);
.calendar-week-item {
......@@ -123,7 +127,7 @@
flex-direction: column;
position: relative;
.curr-tips,
.calendar-curr-tips,
.calendar-day-tip {
position: absolute;
top: 10px;
......@@ -137,7 +141,7 @@
background-color: $calendar-primary-color;
color: $white !important;
.curr-tips {
.calendar-curr-tips {
visibility: hidden;
}
......
<template>
<view class="nut-calendar" :class="{ 'nut-calendar-tile': !poppable }">
<view
class="nut-calendar"
:class="{
'nut-calendar-tile': !poppable,
'nut-calendar-nofooter': isAutoBackFill
}"
>
<!-- header -->
<view
class="nut-calendar-header"
......@@ -7,9 +13,9 @@
>
<template v-if="poppable">
<view class="calendar-title">{{ title }}</view>
<view class="calendar-curr-month">2020年11月</view>
<view class="calendar-curr-month">{{ yearMonthTitle }}</view>
</template>
<view class="calendar-weeks">
<view class="calendar-weeks" ref="weeksPanel">
<view
class="calendar-week-item"
v-for="(item, index) of weeks"
......@@ -50,7 +56,9 @@
<view class="calendar-day">{{
day.type == 'curr' ? day.day : ''
}}</view>
<view class="curr-tips" v-if="isCurrDay(month, day.day)"
<view
class="calendar-curr-tips"
v-if="isCurrDay(month, day.day)"
>今天</view
>
<view
......@@ -71,28 +79,20 @@
</view>
</view>
<!-- footer-->
<view class="nut-calendar-footer" v-if="poppable">
<view class="nut-calendar-footer" v-if="poppable && !isAutoBackFill">
<view class="calendar-confirm-btn" @click="confirm">确定</view>
</view>
</view>
</template>
<script lang="ts">
// import {
// PropType,
// computed,
// watch,
// reactive,
// ref,
// toRefs,
// readonly
// } from 'vue';
import { PropType, reactive, ref, watch, toRefs } from 'vue';
import { createComponent } from '@/utils/create';
import { createComponent } from '../../utils/create';
const { create } = createComponent('calendar-item');
import Utils from '@/utils/date';
import Utils from '../../utils/date';
import requestAniFrame from '../../utils/raf';
type InputDate = string | string[];
interface CalendarState {
childIsVisible: boolean;
yearMonthTitle: string;
currDate: InputDate;
unLoadPrev: boolean;
touchParams: any;
......@@ -106,6 +106,7 @@ interface CalendarState {
startData: InputDate;
endData: InputDate;
isRange: boolean;
timer: number;
}
export default create({
......@@ -147,10 +148,11 @@ export default create({
// element refs
const months = ref<null | HTMLElement>(null);
const monthsPanel = ref<null | HTMLElement>(null);
const weeksPanel = ref<null | HTMLElement>(null);
// state
const state: CalendarState = reactive({
childIsVisible: false,
yearMonthTitle: '',
currDate: '',
unLoadPrev: false,
touchParams: {
......@@ -170,7 +172,8 @@ export default create({
dayPrefix: 'calendar-month-day',
startData: '',
endData: '',
isRange: props.type === 'range'
isRange: props.type === 'range',
timer: 0
});
// 日期转化成数组
......@@ -206,7 +209,8 @@ export default create({
const currDate = getCurrDate(day, month, isRange);
if (day.type == 'curr') {
if (
(!state.isRange && Utils.isEqual(state.currDate, currDate)) ||
(!state.isRange &&
Utils.isEqual(state.currDate as string, currDate)) ||
(state.isRange && (isStart(currDate) || isEnd(currDate)))
) {
return `${state.dayPrefix}-active`;
......@@ -235,7 +239,6 @@ export default create({
if ((state.isRange && state.chooseData.length == 2) || !state.isRange) {
emit('choose', state.chooseData);
if (props.poppable) {
state.childIsVisible = false;
emit('update');
}
}
......@@ -397,12 +400,12 @@ export default create({
} else {
if (
props.startDate &&
Utils.compareDate(state.currDate, props.startDate)
Utils.compareDate(state.currDate as string, props.startDate)
) {
state.currDate = props.startDate;
} else if (
props.endDate &&
!Utils.compareDate(state.currDate, props.endDate)
!Utils.compareDate(state.currDate as string, props.endDate)
) {
state.currDate = props.endDate;
}
......@@ -411,6 +414,7 @@ export default create({
}
getMonth(state.defaultData, 'next');
state.yearMonthTitle = state.monthsData[0].title;
let i = 1;
do {
......@@ -436,7 +440,6 @@ export default create({
true
);
}
console.log(state.currDate, 'state.currDate');
};
// 区间选择&&当前月&&选中态
......@@ -448,6 +451,7 @@ export default create({
);
};
// 是否有开始提示
const isStartTip = (day, month) => {
if (isActive(day, month)) {
return isStart(getCurrDate(day, month));
......@@ -456,34 +460,65 @@ export default create({
}
};
// 是否有结束提示
const isEndTip = (day, month) => {
return isActive(day, month);
};
// 是否有是当前日期
const isCurrDay = (month, day) => {
const date = `${month.curData[0]}-${month.curData[1]}-${day}`;
return Utils.isEqual(date, Utils.date2Str(new Date()));
};
const setTransform = (translateY = 0, type?, time = 1000) => {
if (type === 'end') {
monthsPanel?.value &&
(monthsPanel.value.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`);
} else {
monthsPanel?.value && (monthsPanel.value.style.webkitTransition = '');
// 监听月份滚动,改变月份标题
const loadScroll = () => {
if (!props.poppable) {
return false;
}
requestAniFrame(() => {
if (weeksPanel?.value && monthsPanel?.value) {
const top = weeksPanel?.value.getBoundingClientRect().bottom;
const monthsDoms = monthsPanel.value.querySelectorAll(
'.calendar-month'
);
for (let i = 0; i < monthsDoms.length; i++) {
if (
monthsDoms[i].getBoundingClientRect().top <= top &&
monthsDoms[i].getBoundingClientRect().bottom >= top
) {
state.yearMonthTitle = state.monthsData[i].title;
} else if (state.scrollDistance === 0) {
state.yearMonthTitle = state.monthsData[0].title;
}
}
}
});
};
monthsPanel?.value &&
(monthsPanel.value.style.webkitTransform = `translateY(${translateY}px)`);
state.scrollDistance = translateY;
// 设置月份滚动距离和速度
const setTransform = (translateY = 0, type?, time = 1000) => {
if (monthsPanel?.value) {
if (type === 'end') {
monthsPanel.value.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`;
clearTimeout(state.timer);
state.timer = setTimeout(() => {
loadScroll();
}, time);
} else {
monthsPanel.value.style.webkitTransition = '';
loadScroll();
}
monthsPanel.value.style.webkitTransform = `translateY(${translateY}px)`;
state.scrollDistance = translateY;
}
};
// 计算滚动方向和距离
const setMove = (move, type?, time?) => {
let updateMove = move + state.transformY;
const h = months.value?.offsetHeight || 0;
const offsetHeight = monthsPanel.value?.offsetHeight || 0;
if (type === 'end') {
// 限定滚动距离
if (updateMove > 0) {
......@@ -495,8 +530,7 @@ export default create({
if (offsetHeight <= h && state.monthsData.length == 1) {
updateMove = 0;
}
const endMove = updateMove;
setTransform(endMove, type, time);
setTransform(updateMove, type, time);
} else {
if (updateMove > 0 && updateMove > 100) {
updateMove = 100;
......@@ -518,6 +552,7 @@ export default create({
}
};
// 监听touch开始
const touchStart = event => {
const changedTouches = event.changedTouches[0];
state.touchParams.startY = changedTouches.pageY;
......@@ -525,6 +560,7 @@ export default create({
state.transformY = state.scrollDistance;
};
// 监听touchmove
const touchMove = event => {
//event.preventDefault();
const changedTouches = event.changedTouches[0];
......@@ -537,6 +573,7 @@ export default create({
setMove(move);
};
// 监听touchend
const touchEnd = event => {
const changedTouches = event.changedTouches[0];
state.touchParams.lastY = changedTouches.pageY;
......@@ -568,6 +605,7 @@ export default create({
}
};
// 重新渲染
const resetRender = () => {
state.chooseData.splice(0);
state.monthsData.splice(0);
......@@ -577,16 +615,7 @@ export default create({
initData();
};
const closeActionSheet = () => {
if (props.poppable) {
state.childIsVisible = false;
emit('update');
emit('close');
}
resetRender();
};
// 初始化
// 初始化数据
initData();
//监听 默认值更改
......@@ -594,7 +623,6 @@ export default create({
() => props.defaultValue,
val => {
if (val) {
console.log(val, 'init');
resetRender();
}
}
......@@ -613,7 +641,7 @@ export default create({
confirm,
monthsPanel,
months,
closeActionSheet,
weeksPanel,
...toRefs(state),
...toRefs(props)
};
......
<template>
<div class="demo full">
<div class="demo full menu-demo">
<h2>基础用法</h2>
<nut-menu>
<nut-menu-item :menuList="menuList" title="最新商品"></nut-menu-item>
......@@ -46,6 +46,13 @@
></nut-menu-item>
</nut-menu>
<h2>禁止蒙层展示</h2>
<p class="tips">属性`hasMask`控制是否有蒙层,默认为 `true`展示蒙层 </p>
<nut-menu :hasMask="false">
<nut-menu-item :menuList="menuList" title="最新商品"></nut-menu-item>
<nut-menu-item :menuList="menuList" :title="title"></nut-menu-item>
</nut-menu>
<h2>点击事件</h2>
<p class="tips"
>标题点击事件`menu-click`,菜单列表选择点击事件`on-change`</p
......@@ -136,8 +143,7 @@ export default createDemo({
color: #909ca4;
margin-top: -10px;
margin-bottom: 10px;
}
.nut-menu {
padding: 0 22px;
}
.base-style.nut-menu-item {
.nut-menu-panel {
......@@ -148,4 +154,7 @@ export default createDemo({
.user-style {
padding: 20px;
}
#app .demo.menu-demo {
padding-bottom: 200px;
}
</style>
......@@ -67,6 +67,19 @@ app.use(Menu);
<nut-menu-item :menuList="menuList2" title="筛选" disabled ></nut-menu-item>
</nut-menu>
```
### 禁止蒙层展示
属性`hasMask`控制是否有蒙层,默认为 `true`展示蒙层
```html
<nut-menu :hasMask="false">
<nut-menu-item :menuList="menuList" title="最新商品">
</nut-menu-item>
<nut-menu-item :menuList="menuList" :title="title">
</nut-menu-item>
</nut-menu>
```
### 点击事件
`Menu``@menu-click` 事件返回点击的菜单标题,`@on-change`事件返回菜单列表选中的数据。
......@@ -133,6 +146,7 @@ const alertText = (info, type) => {
| disabled | 是否开启禁用设置,默认不开启 | Boolean | false |
| maxHeight | 菜单列表最大高度,单位px | String, Number | - |
| autoClose | 选择后下拉菜单列表是否自动收起,默认自动收起 | Boolean | true |
|hasMask| 是否有蒙层 | Boolean | true|
### Events
......
<template>
<view class="nut-menu">
<view class="nut-menu" :style="showMask && `z-index:9999`">
<slot></slot>
</view>
</template>
<script lang="ts">
import { toRefs } from 'vue';
import { toRefs, reactive } from 'vue';
import { createComponent } from '@/utils/create';
import { useChildren } from '@/utils/useRelation/useChildren';
export const MENU_KEY = 'nutMenu';
......@@ -16,16 +16,27 @@ export default create({
//单选 simple 多选 multiple,暂留
type: String,
default: 'simple'
},
hasMask: {
type: Boolean,
default: true
}
},
components: {},
setup(props, { emit }) {
// const { autoClose } = toRefs(props);
// const handleClick = (event: Event) => {
// emit('click', event);
// };
// return { autoClose };
const state = reactive({
showMask: false
});
const handleMaskShow = status => {
state.showMask = status;
};
const { linkChildren } = useChildren(MENU_KEY);
linkChildren({
handleMaskShow,
hasMask: props.hasMask
});
return { ...toRefs(state) };
}
});
</script>
......
<template>
<view
id="menuId"
class="nut-menu-item"
:class="[{ disabled: disabled }, { 'nut-menu-active': showPanel }]"
>
<nut-popup v-model:show="showMask"></nut-popup>
<view class="nut-menu-title" @click="handleMenuPanel">
<view class="title-name" v-html="menuTitle"></view>
<i class="icon"></i>
</view>
<view
class="nut-menu-panel"
ref="menuPanel"
......@@ -90,9 +93,11 @@ export default create({
const { menuList, multiStyle } = toRefs(props);
const menuTitle = ref(props.title);
const menu = useParent(MENU_KEY);
const parent: any = reactive(menu.parent as any);
const state = reactive({
showPanel: false,
currMenu: 0
currMenu: 0,
showMask: false
});
const handleMenuPanel = () => {
......@@ -101,7 +106,12 @@ export default create({
if (props.disabled) {
return;
}
state.showPanel = !state.showPanel;
if (parent.hasMask) {
state.showMask = !state.showMask;
parent.handleMaskShow(state.showPanel);
}
};
//menu列表浮层展示和隐藏
const handleShowAndHide = (event: any) => {
......@@ -109,6 +119,8 @@ export default create({
if (menuBox && state.showPanel) {
if (!menuBox.contains(event.target)) {
state.showPanel = false;
state.showMask = false;
parent.handleMaskShow(false);
}
}
};
......@@ -117,6 +129,8 @@ export default create({
state.currMenu = index;
if (props.autoClose) {
state.showPanel = false;
state.showMask = false;
parent.handleMaskShow(false);
}
emit('on-change', item, menuTitle.value);
};
......@@ -138,6 +152,7 @@ export default create({
});
return {
...toRefs(state),
...toRefs(parent),
handleMenuPanel,
checkMenus,
menuTitle,
......
<template>
<div class="demo">
<h2>基础用法</h2>
<nut-cell>
<nut-noticebar
text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
></nut-noticebar>
</nut-cell>
</div>
</template>
<script lang="ts">
import { createComponent } from '@/utils/create';
const { createDemo } = createComponent('noticebar');
export default createDemo({
props: {},
setup() {
return {};
}
});
</script>
<style lang="scss" scoped></style>
# noticebar组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
\ No newline at end of file
<template>
<view :class="classes">
<view>{{ name }}</view>
<view>{{ txt }}</view>
</view>
</template>
<script lang="ts">
import { toRefs } from 'vue';
import { createComponent } from '@/utils/create';
const { componentName, create } = createComponent('noticebar');
export default create({
props: {
name: {
type: String,
default: ''
},
txt: {
type: String,
default: ''
}
},
components: {},
emits: ['click'],
setup(props, { emit }) {
console.log('componentName', componentName);
const { name, txt } = toRefs(props);
const handleClick = (event: Event) => {
emit('click', event);
};
return { name, txt, handleClick };
}
});
</script>
<style lang="scss">
@import 'index.scss';
</style>
<template>
<div class="demo">
<h2>基础用法</h2>
<nut-cell :showIcon="true" :isLink="true" @click="notify1('通知内容')">
<span>
<label>基础用法</label>
</span>
</nut-cell>
</div>
</template>
<script lang="ts">
import { createApp } from 'vue';
import { createComponent } from '@/utils/create';
import notify from './index';
const { createDemo } = createComponent('notify');
const app = createApp({});
app.use(notify);
export default createDemo({
props: {},
setup() {
const notify1 = () => {
notify('content');
};
return {
notify1
};
}
});
</script>
<style lang="scss" scoped>
.nut-temp {
}
</style>
# notify组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
\ No newline at end of file
import VanNotify from './index.vue';
import {
createApp,
reactive,
Component,
nextTick,
getCurrentInstance,
h
} from 'vue';
let timer;
let instance;
const inBrowser = typeof window !== 'undefined';
function isObject(val: unknown): val is Record<any, any> {
return val !== null && typeof val === 'object';
}
function parseOptions(message) {
return isObject(message) ? message : { message };
}
function useExpose(apis: Record<string, any>) {
const instance = getCurrentInstance();
if (instance) {
Object.assign(instance.proxy, apis);
}
}
function usePopupState() {
const state = reactive({
show: false
});
const toggle = (show: boolean) => {
state.show = show;
};
const open = (props: Record<string, any>) => {
Object.assign(state, props);
nextTick(() => {
toggle(true);
});
};
const close = () => {
toggle(false);
};
useExpose({ open, close, toggle });
return {
open,
close,
state,
toggle
};
}
function mountComponent(RootComponent: Component) {
const app = createApp(RootComponent);
const root = document.createElement('div');
document.body.appendChild(root);
return {
instance: app.mount(root),
unmount() {
app.unmount(root);
document.body.removeChild(root);
}
};
}
function initInstance() {
({ instance } = mountComponent({
setup() {
const { state, toggle } = usePopupState();
return h('img', {});
}
}));
}
function Notify(options) {
if (!inBrowser) {
return;
}
if (!instance) {
initInstance();
}
options = {
...Notify.currentOptions,
...parseOptions(options)
};
instance.open(options);
clearTimeout(timer);
if (options.duration > 0) {
timer = setTimeout(Notify.clear, options.duration);
}
return instance;
}
function defaultOptions() {
return {
type: 'danger',
color: undefined,
message: '',
onClose: null,
onClick: null,
onOpened: null,
duration: 3000,
className: '',
background: undefined
};
}
Notify.clear = () => {
if (instance) {
instance.toggle(false);
}
};
Notify.currentOptions = defaultOptions();
Notify.setDefaultOptions = options => {
Object.assign(Notify.currentOptions, options);
};
Notify.resetDefaultOptions = () => {
Notify.currentOptions = defaultOptions();
};
Notify.install = app => {
app.use(VanNotify);
app.config.globalProperties.$notify = Notify;
};
Notify.Component = VanNotify;
export default Notify;
<template>
<view class="nut-notify">
<nut-popup
v-model="curVisible"
position="top"
:style="{ color: color, background: background }"
:overlay="false"
:lockScroll="false"
:class="['nut-notify', `nut-notify--${type}`, { className }]"
@click="handleClick"
@opened="handleOpened"
@closed="handleClosed"
>
<template v-if="$slots.default">
<slot></slot>
</template>
<template v-else>{{ msg }}</template>
</nut-popup>
</view>
</template>
<script lang="ts">
import { toRefs } from 'vue';
import { createComponent } from '@/utils/create';
import Popup from '@/packages/popup/index.vue';
const { componentName, create } = createComponent('notify');
export default create({
props: {
color: String,
message: [Number, String],
className: null,
background: String,
type: {
type: String,
default: 'danger'
}
},
setup(props, { slots }) {
return {};
}
});
</script>
<style lang="scss">
@import 'index.scss';
</style>
......@@ -18,6 +18,6 @@ export class ArticleApiService {
* @returns
*/
saveUserInfo(parmas) {
return this.httpClient.request('/user/saveVisitInfo', 'post', parmas);
return this.httpClient.request('/visit/saveVisitInfo', 'post', parmas);
}
}
......@@ -3,15 +3,15 @@ const Utils = {
* 是否为闫年
* @return {Boolse} true|false
*/
isLeapYear: function(y: number) {
isLeapYear: function(y: number): boolean {
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
},
/**
* 返回星期数
* @return {Number}
* @return {String}
*/
getWhatDay: function(year, month, day) {
getWhatDay: function(year: number, month: number, day: number): string {
const date = new Date(year + '/' + month + '/' + day);
const index = date.getDay();
const dayNames = [
......@@ -30,7 +30,7 @@ const Utils = {
* 返回星期数
* @return {Number}
*/
getMonthPreDay: function(year, month) {
getMonthPreDay: function(year: number, month: number): number {
const date = new Date(year + '/' + month + '/01');
let day = date.getDay();
if (day == 0) {
......@@ -43,14 +43,14 @@ const Utils = {
* 返回月份天数
* @return {Number}
*/
getMonthDays: function(year, month) {
getMonthDays: function(year: string, month: string): number {
if (/^0/.test(month)) {
month = month.split('')[1];
}
return [
0,
31,
this.isLeapYear(year) ? 29 : 28,
this.isLeapYear(Number(year)) ? 29 : 28,
31,
30,
31,
......@@ -68,7 +68,7 @@ const Utils = {
* 补齐数字位数
* @return {string}
*/
getNumTwoBit: function(n) {
getNumTwoBit: function(n: number): string {
n = Number(n);
return (n > 9 ? '' : '0') + n;
},
......@@ -77,8 +77,7 @@ const Utils = {
* 日期对象转成字符串
* @return {string}
*/
date2Str: function(date, split?: string) {
if (typeof date == 'string') return date;
date2Str: function(date: Date, split?: string): string {
split = split || '-';
const y = date.getFullYear();
const m = this.getNumTwoBit(date.getMonth() + 1);
......@@ -91,7 +90,7 @@ const Utils = {
* @param {Number} 0返回今天的日期、1返回明天的日期,2返回后天得日期,依次类推
* @return {string} '2014-12-31'
*/
getDay: function(i) {
getDay: function(i: number): string {
i = i || 0;
let date = new Date();
const diff = i * (1000 * 60 * 60 * 24);
......@@ -99,26 +98,11 @@ const Utils = {
return this.date2Str(date);
},
/**
* 时间戳转换为日期格式
* @return {String}
*/
timestampToDate: function(timestamp) {
const date = new Date(timestamp);
return (
date.getFullYear() +
'-' +
this.getNumTwoBit(date.getMonth() + 1) +
'-' +
this.getNumTwoBit(date.getDate())
);
},
/**
* 时间比较
* @return {Boolean}
*/
compareDate: function(date1, date2) {
compareDate: function(date1: string, date2: string): boolean {
const startTime = new Date(date1.replace('-', '/').replace('-', '/'));
const endTime = new Date(date2.replace('-', '/').replace('-', '/'));
if (startTime >= endTime) {
......@@ -126,27 +110,12 @@ const Utils = {
}
return true;
},
/**
* 时间比较
* @return {Boolean}
*/
compareDateArr: function(date1, date2) {
const startTime = new Date();
startTime.setFullYear(date1[0], date1[1], date1[2]);
startTime.setHours(date1[3], date1[4]);
const endTime = new Date();
endTime.setFullYear(date2[0], date2[1], date2[2]);
endTime.setHours(date2[3], date2[4]);
if (startTime >= endTime) {
return false;
}
return true;
},
/**
* 时间是否相等
* @return {Boolean}
*/
isEqual: function(date1, date2) {
isEqual: function(date1: string, date2: string): boolean {
const startTime = new Date(date1).getTime();
const endTime = new Date(date2).getTime();
if (startTime == endTime) {
......
function requestAniFrame() {
if (typeof window !== 'undefined') {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
}
);
} else {
return function(callback) {
setTimeout(callback, 1000 / 60);
};
}
}
export default requestAniFrame();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册