chore(组件): 全部使用easycom来处理组件问题

This commit is contained in:
2026-01-05 17:24:49 +08:00
parent b1ebb38c06
commit 73f9cb8820
152 changed files with 5177 additions and 6364 deletions

View File

@@ -0,0 +1,105 @@
<template>
<text
v-if="text"
:class="inverted ? 'uni-badge-' + type + ' uni-badge--' + size + ' uni-badge-inverted' : 'uni-badge-' + type + ' uni-badge--' + size"
class="uni-badge"
@click="onClick()"
>
{{ text }}
</text>
</template>
<script>
export default {
name: 'UniBadge',
props: {
type: {
type: String,
default: 'default'
},
inverted: {
type: Boolean,
default: false
},
text: {
type: String,
default: ''
},
size: {
// small.normal
type: String,
default: 'normal'
}
},
methods: {
onClick() {
this.$emit('click');
}
}
};
</script>
<style>
.uni-badge {
font-family: 'Helvetica Neue', Helvetica, sans-serif;
box-sizing: border-box;
font-size: 24rpx;
line-height: 1;
display: inline-block;
padding: 6rpx 12rpx;
color: #333;
border-radius: 200rpx;
background-color: #e5e5e5;
}
.uni-badge.uni-badge-inverted {
padding: 0 10rpx 0 0;
color: #999;
background-color: transparent;
}
.uni-badge-primary {
color: #fff;
background-color: #007aff;
}
.uni-badge-primary.uni-badge-inverted {
color: #007aff;
background-color: transparent;
}
.uni-badge-success {
color: #fff;
background-color: #4cd964;
}
.uni-badge-success.uni-badge-inverted {
color: #4cd964;
background-color: transparent;
}
.uni-badge-warning {
color: #fff;
background-color: #f0ad4e;
}
.uni-badge-warning.uni-badge-inverted {
color: #f0ad4e;
background-color: transparent;
}
.uni-badge-error {
color: #fff;
background-color: #dd524d;
}
.uni-badge-error.uni-badge-inverted {
color: #dd524d;
background-color: transparent;
}
.uni-badge--small {
transform: scale(0.8);
transform-origin: center center;
}
</style>

View File

@@ -0,0 +1,105 @@
<template>
<text
v-if="text"
:class="inverted ? 'uni-badge-' + type + ' uni-badge--' + size + ' uni-badge-inverted' : 'uni-badge-' + type + ' uni-badge--' + size"
class="uni-badge"
@click="onClick()"
>
{{ text }}
</text>
</template>
<script>
export default {
name: 'UniBadge',
props: {
type: {
type: String,
default: 'default'
},
inverted: {
type: Boolean,
default: false
},
text: {
type: String,
default: ''
},
size: {
// small.normal
type: String,
default: 'normal'
}
},
methods: {
onClick() {
this.$emit('click');
}
}
};
</script>
<style>
.uni-badge {
font-family: 'Helvetica Neue', Helvetica, sans-serif;
box-sizing: border-box;
font-size: 24rpx;
line-height: 1;
display: inline-block;
padding: 6rpx 12rpx;
color: #333;
border-radius: 200rpx;
background-color: #e5e5e5;
}
.uni-badge.uni-badge-inverted {
padding: 0 10rpx 0 0;
color: #999;
background-color: transparent;
}
.uni-badge-primary {
color: #fff;
background-color: #007aff;
}
.uni-badge-primary.uni-badge-inverted {
color: #007aff;
background-color: transparent;
}
.uni-badge-success {
color: #fff;
background-color: #4cd964;
}
.uni-badge-success.uni-badge-inverted {
color: #4cd964;
background-color: transparent;
}
.uni-badge-warning {
color: #fff;
background-color: #f0ad4e;
}
.uni-badge-warning.uni-badge-inverted {
color: #f0ad4e;
background-color: transparent;
}
.uni-badge-error {
color: #fff;
background-color: #dd524d;
}
.uni-badge-error.uni-badge-inverted {
color: #dd524d;
background-color: transparent;
}
.uni-badge--small {
transform: scale(0.8);
transform-origin: center center;
}
</style>

View File

@@ -0,0 +1,623 @@
/**
* @1900-2100区间内的公历、农历互转
* @charset UTF-8
* @github https://github.com/jjonline/calendar.js
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
* @Version 1.0.3
* @公历转农历calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
/* eslint-disable */
var calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0,
0x055d2, // 1900-1909
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
/** Add By JJonline@JJonline.Cn**/
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
0x0d520
], // 2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149',
'\u620c',
'\u4ea5'
],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21',
'\u72d7', '\u732a'
],
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206',
'\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3',
'\u5c0f\u6691',
'\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732',
'\u971c\u964d',
'\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'
],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'
],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d',
'\u5341'
],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341',
'\u51ac',
'\u814a'
],
/**
* 返回农历y年一整年的总天数
* @param lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays: function(y) {
var i;
var sum = 348
for (i = 0x8000; i > 0x8; i >>= 1) {
sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0
}
return (sum + this.leapDays(y))
},
/**
* 返回农历y年闰月是哪个月若y年没有闰月 则返回0
* @param lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth: function(y) { // 闰字编码 \u95f0
return (this.lunarInfo[y - 1900] & 0xf)
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param lunar Year
* @return Number (0、29、30)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays: function(y) {
if (this.leapMonth(y)) {
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
}
return (0)
},
/**
* 返回农历y年m月非闰月的总天数计算m为闰月时的天数请使用leapDays方法
* @param lunar Year
* @return Number (-1、29、30)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays: function(y, m) {
if (m > 12 || m < 1) {
return -1
} // 月份参数从1至12参数错误返回-1
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
},
/**
* 返回公历(!)y年m月的天数
* @param solar Year
* @return Number (-1、28、29、30、31)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays: function(y, m) {
if (m > 12 || m < 1) {
return -1
} // 若参数错误 返回-1
var ms = m - 1
if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
} else {
return (this.solarMonth[ms])
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear: function(lYear) {
var ganKey = (lYear - 3) % 10
var zhiKey = (lYear - 3) % 12
if (ganKey == 0) ganKey = 10 // 如果余数为0则为最后一个天干
if (zhiKey == 0) zhiKey = 12 // 如果余数为0则为最后一个地支
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
},
/**
* 公历月、日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro: function(cMonth, cDay) {
var s =
'\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7' // 座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi: function(offset) {
return this.Gan[offset % 10] + this.Zhi[offset % 12]
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y公历年(1900-2100)n二十四节气中的第几个节气(1~24)从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm: function(y, n) {
if (y < 1900 || y > 2100) {
return -1
}
if (n < 1 || n > 24) {
return -1
}
var _table = this.sTermInfo[y - 1900]
var _info = [
parseInt('0x' + _table.substr(0, 5)).toString(),
parseInt('0x' + _table.substr(5, 5)).toString(),
parseInt('0x' + _table.substr(10, 5)).toString(),
parseInt('0x' + _table.substr(15, 5)).toString(),
parseInt('0x' + _table.substr(20, 5)).toString(),
parseInt('0x' + _table.substr(25, 5)).toString()
]
var _calday = [
_info[0].substr(0, 1),
_info[0].substr(1, 2),
_info[0].substr(3, 1),
_info[0].substr(4, 2),
_info[1].substr(0, 1),
_info[1].substr(1, 2),
_info[1].substr(3, 1),
_info[1].substr(4, 2),
_info[2].substr(0, 1),
_info[2].substr(1, 2),
_info[2].substr(3, 1),
_info[2].substr(4, 2),
_info[3].substr(0, 1),
_info[3].substr(1, 2),
_info[3].substr(3, 1),
_info[3].substr(4, 2),
_info[4].substr(0, 1),
_info[4].substr(1, 2),
_info[4].substr(3, 1),
_info[4].substr(4, 2),
_info[5].substr(0, 1),
_info[5].substr(1, 2),
_info[5].substr(3, 1),
_info[5].substr(4, 2)
]
return parseInt(_calday[n - 1])
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth: function(m) { // 月 => \u6708
if (m > 12 || m < 1) {
return -1
} // 若参数错误 返回-1
var s = this.nStr3[m - 1]
s += '\u6708' // 加上月字
return s
},
/**
* 传入农历日期数字返回汉字表示法
* @param lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay: function(d) { // 日 => \u65e5
var s
switch (d) {
case 10:
s = '\u521d\u5341';
break
case 20:
s = '\u4e8c\u5341';
break
break
case 30:
s = '\u4e09\u5341';
break
break
default:
s = this.nStr2[Math.floor(d / 10)]
s += this.nStr1[d % 10]
}
return (s)
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function(y) {
return this.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
* @param y solar year
* @param m solar month
* @param d solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar: function(y, m, d) { // 参数区间1900.1.31~2100.12.31
// 年份限定、上限
if (y < 1900 || y > 2100) {
return -1 // undefined转换为数字变为NaN
}
// 公历传参最下限
if (y == 1900 && m == 1 && d < 31) {
return -1
}
// 未传参 获得当天
if (!y) {
var objDate = new Date()
} else {
var objDate = new Date(y, parseInt(m) - 1, d)
}
var i;
var leap = 0;
var temp = 0
// 修正ymd参数
var y = objDate.getFullYear()
var m = objDate.getMonth() + 1
var d = objDate.getDate()
var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0,
31)) /
86400000
for (i = 1900; i < 2101 && offset > 0; i++) {
temp = this.lYearDays(i)
offset -= temp
}
if (offset < 0) {
offset += temp;
i--
}
// 是否今天
var isTodayObj = new Date()
var isToday = false
if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
isToday = true
}
// 星期几
var nWeek = objDate.getDay()
var cWeek = this.nStr1[nWeek]
// 数字表示周几顺应天朝周一开始的惯例
if (nWeek == 0) {
nWeek = 7
}
// 农历年
var year = i
var leap = this.leapMonth(i) // 闰哪个月
var isLeap = false
// 效验闰月
for (i = 1; i < 13 && offset > 0; i++) {
// 闰月
if (leap > 0 && i == (leap + 1) && isLeap == false) {
--i
isLeap = true;
temp = this.leapDays(year) // 计算农历闰月天数
} else {
temp = this.monthDays(year, i) // 计算农历普通月天数
}
// 解除闰月
if (isLeap == true && i == (leap + 1)) {
isLeap = false
}
offset -= temp
}
// 闰月导致数组下标重叠取反
if (offset == 0 && leap > 0 && i == leap + 1) {
if (isLeap) {
isLeap = false
} else {
isLeap = true;
--i
}
}
if (offset < 0) {
offset += temp;
--i
}
// 农历月
var month = i
// 农历日
var day = offset + 1
// 天干地支处理
var sm = m - 1
var gzY = this.toGanZhiYear(year)
// 当月的两个节气
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
var firstNode = this.getTerm(y, (m * 2 - 1)) // 返回当月「节」为几日开始
var secondNode = this.getTerm(y, (m * 2)) // 返回当月「节」为几日开始
// 依据12节气修正干支月
var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
if (d >= firstNode) {
gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
}
// 传入的日期的节气与否
var isTerm = false
var Term = null
if (firstNode == d) {
isTerm = true
Term = this.solarTerm[m * 2 - 2]
}
if (secondNode == d) {
isTerm = true
Term = this.solarTerm[m * 2 - 1]
}
// 日柱 当月一日与 1900/1/1 相差天数
var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
var gzD = this.toGanZhi(dayCyclical + d - 1)
// 该日期所属的星座
var astro = this.toAstro(m, d)
return {
'lYear': year,
'lMonth': month,
'lDay': day,
'Animal': this.getAnimal(year),
'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month),
'IDayCn': this.toChinaDay(day),
'cYear': y,
'cMonth': m,
'cDay': d,
'gzYear': gzY,
'gzMonth': gzM,
'gzDay': gzD,
'isToday': isToday,
'isLeap': isLeap,
'nWeek': nWeek,
'ncWeek': '\u661f\u671f' + cWeek,
'isTerm': isTerm,
'Term': Term,
'astro': astro
}
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar: function(y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
var isLeapMonth = !!isLeapMonth
var leapOffset = 0
var leapMonth = this.leapMonth(y)
var leapDay = this.leapDays(y)
if (isLeapMonth && (leapMonth != m)) {
return -1
} // 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) {
return -1
} // 超出了最大极限值
var day = this.monthDays(y, m)
var _day = day
// bugFix 2016-9-25
// if month is leap, _day use leapDays method
if (isLeapMonth) {
_day = this.leapDays(y, m)
}
if (y < 1900 || y > 2100 || d > _day) {
return -1
} // 参数合法性效验
// 计算农历的时间差
var offset = 0
for (var i = 1900; i < y; i++) {
offset += this.lYearDays(i)
}
var leap = 0;
var isAdd = false
for (var i = 1; i < m; i++) {
leap = this.leapMonth(y)
if (!isAdd) { // 处理闰月
if (leap <= i && leap > 0) {
offset += this.leapDays(y);
isAdd = true
}
}
offset += this.monthDays(y, i)
}
// 转换闰月农历 需补充该年闰月的前一个月的时差
if (isLeapMonth) {
offset += day
}
// 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
var calObj = new Date((offset + d - 31) * 86400000 + stmap)
var cY = calObj.getUTCFullYear()
var cM = calObj.getUTCMonth() + 1
var cD = calObj.getUTCDate()
return this.solar2lunar(cY, cM, cD)
}
}
export default calendar

View File

@@ -0,0 +1,186 @@
<template>
<view
class="uni-calendar-item__weeks-box"
:class="{
'uni-calendar-item--disable': weeks.disable,
'uni-calendar-item--isDay': calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked': calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked': weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked': weeks.afterMultiple
}"
@click="choiceDate(weeks)"
>
<view class="uni-calendar-item__weeks-box-item">
<text v-if="selected && weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text"
:class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay': calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked': calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked': weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked': weeks.afterMultiple,
'uni-calendar-item--disable': weeks.disable
}"
>
{{ weeks.date }}
</text>
<text v-if="!lunar && !weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text"
:class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay': calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked': calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked': weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked': weeks.afterMultiple
}"
></text>
<text v-if="lunar && !weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text"
:class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay': calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked': calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked': weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked': weeks.afterMultiple,
'uni-calendar-item--disable': weeks.disable
}"
>
{{ weeks.isDay ? '今天' : weeks.lunar.IDayCn === '初一' ? weeks.lunar.IMonthCn : weeks.lunar.IDayCn }}
</text>
<text v-if="weeks.extraInfo && weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text"
:class="{
'uni-calendar-item--extra': weeks.extraInfo.info,
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay': calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked': calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked': weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked': weeks.afterMultiple,
'uni-calendar-item--disable': weeks.disable
}"
>
{{ weeks.extraInfo.info }}
</text>
</view>
</view>
</template>
<script>
export default {
props: {
weeks: {
type: Object,
default() {
return {};
}
},
calendar: {
type: Object,
default: () => {
return {};
}
},
selected: {
type: Array,
default: () => {
return [];
}
},
lunar: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks);
}
}
};
</script>
<style lang="scss" scoped>
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
}
.uni-calendar-item__weeks-box-text {
font-size: 24rpx;
color: #fff;
}
.uni-calendar-item__weeks-lunar-text {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 10rpx;
right: 10rpx;
width: 16rpx;
height: 16rpx;
border-radius: 16rpx;
background-color: $uni-color-error;
}
.uni-calendar-item--disable {
color: #feaa93;
}
.uni-calendar-item--isDay-text {
color: #fff;
}
.uni-calendar-item--isDay {
color: #000;
background-color: #fff;
border-radius: 50%;
}
.uni-calendar-item--extra {
// color: $uni-color-error;
// opacity: 0.8;
}
.uni-calendar-item--checked {
color: #fff;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
}
.uni-calendar-item--multiple {
background-color: $uni-color-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--before-checked {
background-color: #ff5a5f;
color: #fff;
}
.uni-calendar-item--after-checked {
background-color: #ff5a5f;
color: #fff;
}
</style>

View File

@@ -0,0 +1,476 @@
<template>
<view class="uni-calendar">
<view v-if="!insert && show" class="uni-calendar__mask" :class="{ 'uni-calendar--mask-show': aniMaskShow }" @click="clean"></view>
<view v-if="insert || show" class="uni-calendar__content" :class="{ 'uni-calendar--fixed': !insert, 'uni-calendar--ani-show': aniMaskShow }">
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
<view class="uni-calendar__header-btn-box" @click="close"><text class="uni-calendar__header-text uni-calendar--fixed-width">取消</text></view>
<view class="uni-calendar__header-btn-box" @click="confirm"><text class="uni-calendar__header-text uni-calendar--fixed-width">确定</text></view>
</view>
<view class="uni-calendar__header">
<view class="uni-calendar__header-btn-box" @click.stop="pre">
<!-- <view class="uni-calendar__header-btn uni-calendar--left"></view> -->
<text class="iconfont icon-back_light"></text>
</view>
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
<text class="uni-calendar__header-text">{{ (nowDate.year || '') + '年' + (nowDate.month || '') + '月' }}</text>
</picker>
<view class="uni-calendar__header-btn-box" @click.stop="next">
<!-- <view class="uni-calendar__header-btn uni-calendar--right"></view> -->
<text class="iconfont icon-right"></text>
</view>
</view>
<view class="uni-calendar__box">
<view v-if="showMonth" class="uni-calendar__box-bg">
<text class="uni-calendar__box-bg-text">{{ nowDate.month }}</text>
</view>
<view class="uni-calendar__weeks">
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
<view class="uni-calendar__weeks-day"><text class="uni-calendar__weeks-day-text"></text></view>
</view>
<view class="uni-calendar__weeks" v-for="(item, weekIndex) in weeks" :key="weekIndex">
<view class="uni-calendar__weeks-item" v-for="(weeks, weeksIndex) in item" :key="weeksIndex">
<uni-calendar-item :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></uni-calendar-item>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import Calendar from './util.js';
import uniCalendarItem from './uni-calendar-item.vue';
/**
* Calendar 日历
* @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
* @property {String} date 自定义当前时间,默认为今天
* @property {Boolean} lunar 显示农历
* @property {String} startDate 日期选择范围-开始日期
* @property {String} endDate 日期选择范围-结束日期
* @property {Boolean} range 范围选择
* @property {Boolean} insert = [true|false] 插入模式,默认为false
* @value true 弹窗模式
* @value false 插入模式
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
* @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
* @property {Boolean} showMonth 是否选择月份为背景
* @event {Function} change 日期改变,`insert :ture` 时生效
* @event {Function} confirm 确认选择`insert :false` 时生效
* @event {Function} monthSwitch 切换月份时触发
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
*/
export default {
components: {
uniCalendarItem
},
props: {
date: {
type: String,
default: ''
},
selected: {
type: Array,
default() {
return [];
}
},
lunar: {
type: Boolean,
default: false
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
range: {
type: Boolean,
default: false
},
insert: {
type: Boolean,
default: true
},
showMonth: {
type: Boolean,
default: true
},
clearDate: {
type: Boolean,
default: true
}
},
data() {
return {
show: false,
weeks: [],
calendar: {},
nowDate: '',
aniMaskShow: false
};
},
watch: {
date(newVal) {
this.cale.setDate(newVal);
this.init(this.cale.selectDate.fullDate);
},
startDate(val) {
this.cale.resetSatrtDate(val);
},
endDate(val) {
this.cale.resetEndDate(val);
},
selected(newVal) {
this.cale.setSelectInfo(this.nowDate.fullDate, newVal);
this.weeks = this.cale.weeks;
}
},
created() {
// 获取日历方法实例
this.cale = new Calendar({
// date: new Date(),
selected: this.selected,
startDate: this.startDate,
endDate: this.endDate,
range: this.range
});
// 选中某一天
this.cale.setDate(this.date);
this.init(this.cale.selectDate.fullDate);
// this.setDay
},
methods: {
// 取消穿透
clean() {},
bindDateChange(e) {
const value = e.detail.value + '-1';
this.cale.setDate(value);
this.init(value);
},
/**
* 初始化日期显示
* @param {Object} date
*/
init(date) {
this.weeks = this.cale.weeks;
this.nowDate = this.calendar = this.cale.getInfo(date);
},
/**
* 打开日历弹窗
*/
open() {
// 弹窗模式并且清理数据
if (this.clearDate && !this.insert) {
this.cale.cleanMultipleStatus();
this.cale.setDate(this.date);
this.init(this.cale.selectDate.fullDate);
}
this.show = true;
this.$nextTick(() => {
setTimeout(() => {
this.aniMaskShow = true;
}, 50);
});
},
/**
* 关闭日历弹窗
*/
close() {
this.aniMaskShow = false;
this.$nextTick(() => {
setTimeout(() => {
this.show = false;
this.$emit('close');
}, 300);
});
},
/**
* 确认按钮
*/
confirm() {
this.setEmit('confirm');
this.close();
},
/**
* 变化触发
*/
change() {
if (!this.insert) return;
this.setEmit('change');
},
/**
* 选择月份触发
*/
monthSwitch() {
let { year, month } = this.nowDate;
this.$emit('monthSwitch', {
year,
month: Number(month)
});
},
/**
* 派发事件
* @param {Object} name
*/
setEmit(name) {
let { year, month, date, fullDate, lunar, extraInfo } = this.calendar;
this.$emit(name, {
range: this.cale.multipleStatus,
year,
month,
date,
fulldate: fullDate,
lunar,
extraInfo: extraInfo || {}
});
},
/**
* 选择天触发
* @param {Object} weeks
*/
choiceDate(weeks) {
if (weeks.disable) return;
this.calendar = weeks;
// 设置多选
this.cale.setMultiple(this.calendar.fullDate);
this.weeks = this.cale.weeks;
this.change();
},
/**
* 回到今天
*/
backtoday() {
let date = this.cale.getDate(new Date()).fullDate;
this.cale.setDate(date);
this.init(date);
this.change();
},
/**
* 上个月
*/
pre() {
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate;
this.setDate(preDate);
this.monthSwitch();
},
/**
* 下个月
*/
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate;
this.setDate(nextDate);
this.monthSwitch();
},
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.cale.setDate(date);
this.weeks = this.cale.weeks;
this.nowDate = this.cale.getInfo(date);
}
}
};
</script>
<style lang="scss" scoped>
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--mask-show {
opacity: 1;
}
.uni-calendar--fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--ani-show {
transform: translateY(0);
}
.uni-calendar__content {
background: linear-gradient(180deg, rgba(247, 0, 66, 1), rgba(254, 147, 76, 1));
border-bottom-left-radius: 24rpx;
border-bottom-right-radius: 24rpx;
}
.uni-calendar__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 56rpx;
width: 657rpx;
margin: 0 auto;
background-color: #fa556a;
border-radius: 28px;
}
.uni-calendar--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--fixed-width {
width: 50px;
// padding: 0 15px;
}
.uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 5px;
padding-left: 10px;
height: 25px;
line-height: 25px;
font-size: 12px;
border-top-left-radius: 25px;
border-bottom-left-radius: 25px;
color: $uni-text-color;
background-color: $uni-bg-color-hover;
}
.uni-calendar__header-text {
text-align: center;
width: 100px;
font-size: 26rpx;
color: #fff;
}
.uni-calendar__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
color: #fff !important;
}
.uni-calendar__header-btn {
width: 10px;
height: 10px;
border-left-color: $uni-text-color-placeholder;
border-left-style: solid;
border-left-width: 2px;
border-top-color: $uni-color-subtitle;
border-top-style: solid;
border-top-width: 2px;
}
.uni-calendar--left {
transform: rotate(-45deg);
}
.uni-calendar--right {
transform: rotate(135deg);
}
.uni-calendar__weeks {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-calendar__weeks-item {
flex: 1;
}
.uni-calendar__weeks-day {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
height: 45px;
color: #fff;
font-size: 24rpx;
}
.uni-calendar__weeks-day-text {
font-size: 14px;
}
.uni-calendar__box {
position: relative;
}
.uni-calendar__box-bg {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.uni-calendar__box-bg-text {
font-size: 200px;
font-weight: bold;
color: $uni-text-color-grey;
opacity: 0.1;
text-align: center;
/* #ifndef APP-NVUE */
line-height: 1;
/* #endif */
}
</style>

View File

@@ -0,0 +1,354 @@
import CALENDAR from './calendar.js'
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let isinfo = false
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
let dateCompBefore = this.dateCompare(this.startDate, fullDate)
disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
}
if (this.endDate) {
let dateCompAfter = this.dateCompare(fullDate, this.endDate)
disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
month: full.month,
lunar: this.getlunar(full.year, full.month, i),
disable: !disableBefore || !disableAfter,
isDay
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
disable: true
})
}
return dateArr
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 获取日期范围内所有日期
* @param {Object} begin
* @param {Object} end
*/
geDateAll(begin, end) {
var arr = []
var ab = begin.split('-')
var ae = end.split('-')
var db = new Date()
db.setFullYear(ab[0], ab[1] - 1, ab[2])
var de = new Date()
de.setFullYear(ae[0], ae[1] - 1, ae[2])
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
for (var k = unixDb; k <= unixDe;) {
k = k + 24 * 60 * 60 * 1000
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date)
}
/**
* 设置打点
*/
setSelectInfo(data, value) {
this.selected = value
this._getWeek(data)
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
this.multipleStatus.before = ''
this.multipleStatus.after = ''
this.multipleStatus.data = []
} else {
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
.before);
}
}
}
this._getWeek(fullDate)
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
fullDate,
year,
month,
date,
day
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar

View File

@@ -0,0 +1,252 @@
<template>
<view class="uni-countdown">
<view
v-if="showDay && d > 0"
:style="{ borderColor: borderColor, color: color, background: backgroundColor }"
class="uni-countdown__number "
:class="[backgroundColorClass, colorClass, borderColorClass]"
>
{{ d }}
</view>
<view v-if="showDay && d > 0" :style="{ color: splitorColor }" class="uni-countdown__splitor day" :class="splitorColorClass">{{ showColon ? '' : '' }}</view>
<view
:style="{ borderColor: borderColor, color: color, background: backgroundColor }"
class="uni-countdown__number "
:class="[backgroundColorClass, colorClass, borderColorClass]"
>
{{ h }}
</view>
<view :style="{ color: splitorColor }" class="uni-countdown__splitor" :class="splitorColorClass">{{ showColon ? ':' : '时' }}</view>
<view
:style="{ borderColor: borderColor, color: color, background: backgroundColor }"
class="uni-countdown__number "
:class="[backgroundColorClass, colorClass, borderColorClass]"
>
{{ i }}
</view>
<view :style="{ color: splitorColor }" class="uni-countdown__splitor" :class="splitorColorClass">{{ showColon ? ':' : '分' }}</view>
<view
:style="{ borderColor: borderColor, color: color, background: backgroundColor }"
class="uni-countdown__number "
:class="[backgroundColorClass, colorClass, borderColorClass]"
>
{{ s }}
</view>
<view v-if="!showColon" :style="{ color: splitorColor }" class="uni-countdown__splitor" :class="splitorColorClass"></view>
</view>
</template>
<script>
export default {
name: 'UniCountDown',
props: {
showDay: {
type: Boolean,
default: true
},
showColon: {
type: Boolean,
default: true
},
backgroundColor: {
type: String,
default: '#FFFFFF'
},
backgroundColorClass: {
type: String,
default: ''
},
borderColor: {
type: String,
default: '#000000'
},
borderColorClass: {
type: String,
default: ''
},
color: {
type: String,
default: '#000000'
},
colorClass: {
type: String,
default: ''
},
splitorColor: {
type: String,
default: '#000000'
},
splitorColorClass: {
type: String,
default: ''
},
day: {
type: [Number, String],
default: 0
},
hour: {
type: [Number, String],
default: 0
},
minute: {
type: [Number, String],
default: 0
},
second: {
type: [Number, String],
default: 0
}
},
data() {
return {
timer: null,
d: '00',
h: '00',
i: '00',
s: '00',
leftTime: 0,
seconds: 0
};
},
mounted: function(e) {
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second);
this.countDown();
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds < 0) {
this.timeUp();
return;
}
this.countDown();
}, 1000);
},
watch: {
day: function(newVal) {
this.timeUp();
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second);
this.countDown();
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds < 0) {
this.timeUp();
return;
}
this.countDown();
}, 1000);
},
hour: function(newVal) {
this.timeUp();
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second);
this.countDown();
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds < 0) {
this.timeUp();
return;
}
this.countDown();
}, 1000);
},
minute: function(newVal) {
this.timeUp();
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second);
this.countDown();
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds < 0) {
this.timeUp();
return;
}
this.countDown();
}, 1000);
},
second: function(newVal) {
this.timeUp();
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second);
this.countDown();
this.timer = setInterval(() => {
this.seconds--;
if (this.seconds < 0) {
this.timeUp();
return;
}
this.countDown();
}, 1000);
}
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
toSeconds(day, hours, minutes, seconds) {
day = Number(day);
hours = Number(hours);
minutes = Number(minutes);
seconds = Number(seconds);
return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds;
},
timeUp() {
clearInterval(this.timer);
this.$emit('timeup');
},
countDown() {
let seconds = this.seconds;
let [day, hour, minute, second] = [0, 0, 0, 0];
if (seconds > 0) {
day = Math.floor(seconds / (60 * 60 * 24));
hour = Math.floor(seconds / (60 * 60)) - day * 24;
minute = Math.floor(seconds / 60) - day * 24 * 60 - hour * 60;
second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
} else {
this.timeUp();
}
if (day < 10) {
day = '0' + day;
}
if (hour < 10) {
hour = '0' + hour;
}
if (minute < 10) {
minute = '0' + minute;
}
if (second < 10) {
second = '0' + second;
}
this.d = day;
this.h = hour;
this.i = minute;
this.s = second;
}
}
};
</script>
<style lang="scss">
.uni-countdown {
padding: 2rpx 0;
display: inline-flex;
flex-wrap: nowrap;
justify-content: center;
}
.uni-countdown__splitor {
justify-content: center;
line-height: 44rpx;
padding: 0 5rpx;
font-size: 24rpx;
}
.uni-countdown__splitor.day {
line-height: 50rpx;
}
.uni-countdown__number {
line-height: 44rpx;
justify-content: center;
height: 44rpx;
border-radius: 6rpx;
margin: 0 5rpx;
border: 2rpx solid #000;
font-size: 24rpx;
padding: 0 10rpx;
}
</style>

View File

@@ -0,0 +1,85 @@
## 2.2.22021-12-10
- 修复 clear-icon 属性在小程序平台不生效的 bug
## 2.2.12021-12-10
- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug
## 2.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
## 2.1.52021-11-09
- 新增 提供组件设计资源,组件样式调整
## 2.1.42021-09-10
- 修复 hide-second 在移动端的 bug
- 修复 单选赋默认值时,赋值日期未高亮的 bug
- 修复 赋默认值时,移动端未正确显示时间的 bug
## 2.1.32021-09-09
- 新增 hide-second 属性,支持只使用时分,隐藏秒
## 2.1.22021-09-03
- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
- 优化 调整字号大小,美化日历界面
- 修复 因国际化导致的 placeholder 失效的 bug
## 2.1.12021-08-24
- 新增 支持国际化
- 优化 范围选择器在 pc 端过宽的问题
## 2.1.02021-08-09
- 新增 适配 vue3
## 2.0.192021-08-09
- 新增 支持作为 uni-forms 子组件相关功能
- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
## 2.0.182021-08-05
- 修复 type 属性动态赋值无效的 bug
- 修复 ‘确认’按钮被 tabbar 遮盖 bug
- 修复 组件未赋值时范围选左、右日历相同的 bug
## 2.0.172021-08-04
- 修复 范围选未正确显示当前值的 bug
- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
## 2.0.162021-07-21
- 新增 return-type 属性支持返回 date 日期对象
## 2.0.152021-07-14
- 修复 单选日期类型,初始赋值后不在当前日历的 bug
- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
- 优化 移动端移除显示框的清空按钮,无实际用途
## 2.0.142021-07-14
- 修复 组件赋值为空,界面未更新的 bug
- 修复 start 和 end 不能动态赋值的 bug
- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug
## 2.0.132021-07-08
- 修复 范围选择不能动态赋值的 bug
## 2.0.122021-07-08
- 修复 范围选择的初始时间在一个月内时造成无法选择的bug
## 2.0.112021-07-08
- 优化 弹出层在超出视窗边缘定位不准确的问题
## 2.0.102021-07-08
- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug
- 优化 弹出层在超出视窗边缘被遮盖的问题
## 2.0.92021-07-07
- 新增 maskClick 事件
- 修复 特殊情况日历 rpx 布局错误的 bugrpx -> px
- 修复 范围选择时清空返回值不合理的bug['', ''] -> []
## 2.0.82021-07-07
- 新增 日期时间显示框支持插槽
## 2.0.72021-07-01
- 优化 添加 uni-icons 依赖
## 2.0.62021-05-22
- 修复 图标在小程序上不显示的 bug
- 优化 重命名引用组件,避免潜在组件命名冲突
## 2.0.52021-05-20
- 优化 代码目录扁平化
## 2.0.42021-05-12
- 新增 组件示例地址
## 2.0.32021-05-10
- 修复 ios 下不识别 '-' 日期格式的 bug
- 优化 pc 下弹出层添加边框和阴影
## 2.0.22021-05-08
- 修复 在 admin 中获取弹出层定位错误的bug
## 2.0.12021-05-08
- 修复 type 属性向下兼容,默认值从 date 变更为 datetime
## 2.0.02021-04-30
- 支持日历形式的日期+时间的范围选择
> 注意此版本不向后兼容不再支持单独时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker
## 1.0.62021-03-18
- 新增 hide-second 属性,时间支持仅选择时、分
- 修复 选择跟显示的日期不一样的 bug
- 修复 chang事件触发2次的 bug
- 修复 分、秒 end 范围错误的 bug
- 优化 更好的 nvue 适配

View File

@@ -0,0 +1,90 @@
{
"id": "uni-datetime-picker",
"displayName": "uni-datetime-picker 日期选择器",
"version": "2.2.2",
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
"keywords": [
"uni-datetime-picker",
"uni-ui",
"uniui",
"日期时间选择器",
"日期时间"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,21 @@
> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容不再支持单独的时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker。若仍需使用旧版本可在插件市场下载*非uni_modules版本*,旧版本将不再维护`
## DatetimePicker 时间选择器
> **组件名uni-datetime-picker**
> 代码块: `uDatetimePicker`
该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。
若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
**_点击 picker 默认值规则_**
- 若设置初始值 value, 会显示在 picker 显示框中
- 若无初始值 value则初始值 value 为当前本地时间 Date.now() 但不会显示在 picker 显示框中
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,146 @@
<template>
<view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer, 'uni-drawer--right': rightMode }" class="uni-drawer" @touchmove.stop.prevent="moveHandle">
<view class="uni-drawer__mask" @tap="close" ></view>
<view class="uni-drawer__content" :class="{ 'safe-area': isIphoneX }"><slot /></view>
</view>
</template>
<script>
export default {
name: 'UniDrawer',
props: {
/**
* 显示状态
*/
visible: {
type: Boolean,
default: false
},
/**
* 显示模式(左、右),只在初始化生效
*/
mode: {
type: String,
default: ''
},
/**
* 蒙层显示状态
*/
mask: {
type: Boolean,
default: true
}
},
data() {
return {
visibleSync: false,
showDrawer: false,
rightMode: false,
closeTimer: null,
watchTimer: null,
isIphoneX: false
};
},
watch: {
visible(val) {
clearTimeout(this.watchTimer);
setTimeout(() => {
this.showDrawer = val;
}, 100);
if (this.visibleSync) {
clearTimeout(this.closeTimer);
}
if (val) {
this.visibleSync = val;
} else {
this.watchTimer = setTimeout(() => {
this.visibleSync = val;
}, 300);
}
}
},
created() {
this.isIphoneX = this.$util.uniappIsIPhoneX();
this.visibleSync = this.visible;
setTimeout(() => {
this.showDrawer = this.visible;
}, 100);
this.rightMode = this.mode === 'right';
},
methods: {
close() {
this.showDrawer = false;
this.closeTimer = setTimeout(() => {
this.visibleSync = false;
this.$emit('close');
}, 200);
},
moveHandle() {}
}
};
</script>
<style>
.uni-drawer {
display: block;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
visibility: hidden;
z-index: 999;
height: 100%;
}
.uni-drawer.uni-drawer--right .uni-drawer__content {
left: auto;
right: 0;
transform: translatex(100%);
}
.uni-drawer.uni-drawer--visible {
visibility: visible;
}
.uni-drawer.uni-drawer--visible .uni-drawer__content {
transform: translatex(0);
}
.uni-drawer.uni-drawer--visible .uni-drawer__mask {
display: block;
opacity: 1;
}
.uni-drawer__mask {
display: block;
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
transition: opacity 0.3s;
}
.uni-drawer__content {
display: block;
position: absolute;
top: 0;
left: 0;
width: 61.8%;
height: 100%;
background: #fff;
transition: all 0.3s ease-out;
transform: translatex(-100%);
}
.safe-area {
padding-bottom: 68rpx;
padding-top: 44rpx;
box-sizing: border-box;
}
</style>

View File

@@ -0,0 +1,219 @@
<template>
<view v-if="width" :style="{ width: width }" class="uni-grid-item">
<view
:class="{ border: showBorder, 'uni-grid-item__box-square': square, 'border-top': showBorder && index < column, 'uni-highlight': highlight }"
:style="{ 'border-color': borderColor }"
class="uni-grid-item__box"
@click="_onClick"
>
<view v-if="marker === 'dot'" :style="{ left: top * 2 + 'rpx', top: left * 2 + 'rpx' }" class="uni-grid-item__box-dot" />
<view v-if="marker === 'badge'" :style="{ left: top * 2 + 'rpx', top: left * 2 + 'rpx' }" class="uni-grid-item__box-badge">
<uni-badge :text="text" :type="type" :size="size" :inverted="inverted" />
</view>
<view v-if="marker === 'image'" :style="{ left: top * 2 + 'rpx', top: left * 2 + 'rpx' }" class="uni-grid-item__box-image">
<image :style="{ width: imgWidth * 2 + 'rpx' }" :src="src" class="box-image" mode="widthFix" />
</view>
<view class="uni-grid-item__box-item"><slot /></view>
</view>
</view>
</template>
<script>
export default {
name: 'UniGridItem',
props: {
// 类型可选值dot圆点badge角标image图片
marker: {
type: String,
default: ''
},
// 水平方向
hor: {
type: Number,
default: 0
},
// 垂直方向
ver: {
type: Number,
default: 0
},
// badge 下颜色类型可选值default灰色、primary蓝色、success绿色、warning(黄色)、error(红色)
type: {
type: String,
default: ''
},
// badge 下显示内容汉字最多为1个
text: {
type: String,
default: ''
},
// badge 下 Badge 大小
size: {
type: String,
default: 'normal'
},
// badge 下 是否无需背景颜色
inverted: {
type: Boolean,
default: false
},
// image 下图片路径
src: {
type: String,
default: ''
},
// image 下图片宽度 ,最大 为 100 。 默认为 30
imgWidth: {
type: Number,
default: 30
}
},
inject: ['grid'],
data() {
return {
column: 0,
showBorder: true,
square: true,
highlight: true,
left: 0,
top: 0,
index: 0,
openNum: 2,
width: 0,
borderColor: '#e5e5e5'
};
},
created() {
this.column = this.grid.column;
this.showBorder = this.grid.showBorder;
this.square = this.grid.square;
this.highlight = this.grid.highlight;
this.top = this.hor === 0 ? this.grid.hor : this.hor;
this.left = this.ver === 0 ? this.grid.ver : this.ver;
this.borderColor = this.grid.borderColor;
this.index = this.grid.index++;
},
// #ifdef H5
mounted() {
this.grid._getSize(width => {
this.width = width;
});
},
// #endif
// #ifndef H5
onReady() {
this.grid._getSize(width => {
this.width = width;
});
},
// #endif
methods: {
_onClick() {
this.grid.change({
detail: {
index: this.index
}
});
}
}
};
</script>
<style>
.uni-grid-item {
box-sizing: border-box;
}
.uni-grid-item__box {
position: relative;
width: 100%;
}
.uni-grid-item__box-item {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
font-size: 32rpx;
color: #666;
padding: 20rpx 0;
box-sizing: border-box;
}
.uni-grid-item__box-item .image {
width: 50rpx;
height: 50rpx;
}
.uni-grid-item__box-item .text {
font-size: 26rpx;
margin-top: 10rpx;
}
.uni-grid-item__box.uni-grid-item__box-square {
height: 0;
padding-top: 100%;
}
.uni-grid-item__box.uni-grid-item__box-square .uni-grid-item__box-item {
position: absolute;
top: 0;
}
.uni-grid-item__box.border {
position: relative;
box-sizing: border-box;
border-bottom: 2rpx #e5e5e5 solid;
border-right: 2rpx #e5e5e5 solid;
}
.uni-grid-item__box.border-top {
border-top: 2rpx #e5e5e5 solid;
}
.uni-grid-item__box.uni-highlight:active {
background-color: #eee;
}
.uni-grid-item__box-badge,
.uni-grid-item__box-dot,
.uni-grid-item__box-image {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
margin: auto;
z-index: 10;
}
.uni-grid-item__box-dot {
width: 20rpx;
height: 20rpx;
background: #ff5a5f;
border-radius: 50%;
}
.uni-grid-item__box-badge {
display: flex;
justify-content: center;
align-items: center;
width: 0;
height: 0;
}
.uni-grid-item__box-image {
display: flex;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
overflow: hidden;
}
.uni-grid-item__box-image .box-image {
width: 90rpx;
}
</style>

View File

@@ -0,0 +1,95 @@
<template>
<view>
<view :id="elId" :class="{ border: showBorder }" :style="{ 'border-left': showBorder ? '1px ' + borderColor + ' solid' : 'none' }" class="uni-grid">
<slot />
</view>
</view>
</template>
<script>
export default {
name: 'UniGrid',
props: {
// 每列显示个数
column: {
type: Number,
default: 3
},
// 是否显示边框
showBorder: {
type: Boolean,
default: true
},
// 是否显示边框
borderColor: {
type: String,
default: '#e5e5e5'
},
// 全局标记水平方向移动距离 ,起点为中心,负数为左移动,正数为右移动
hor: {
type: Number,
default: 0
},
// 全局标记垂直方向移动距离 ,起点为中心,负数为上移动,正数为下移动
ver: {
type: Number,
default: 0
},
// 是否正方形显示,默认为 true
square: {
type: Boolean,
default: true
},
highlight: {
type: Boolean,
default: true
}
},
provide() {
return {
grid: this
};
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`;
return {
index: 0,
elId
};
},
created() {
this.index = 0;
this.childrens = [];
this.pIndex = this.pIndex ? this.pIndex++ : 0;
},
methods: {
change(e) {
this.$emit('change', e);
},
_getSize(fn) {
uni.createSelectorQuery()
.in(this)
.select(`#${this.elId}`)
.boundingClientRect()
.exec(ret => {
if (!ret[0]) {
setTimeout(this._getSize(fn));
return;
}
let width = (parseInt(ret[0].width / this.column) - 1) * 2 + 'rpx';
typeof fn === 'function' && fn(width);
});
}
}
};
</script>
<style>
.uni-grid {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
border-left: 2rpx #e5e5e5 solid;
}
</style>

View File

@@ -0,0 +1,96 @@
export default {
'contact': '\ue100',
'person': '\ue101',
'personadd': '\ue102',
'contact-filled': '\ue130',
'person-filled': '\ue131',
'personadd-filled': '\ue132',
'phone': '\ue200',
'email': '\ue201',
'chatbubble': '\ue202',
'chatboxes': '\ue203',
'phone-filled': '\ue230',
'email-filled': '\ue231',
'chatbubble-filled': '\ue232',
'chatboxes-filled': '\ue233',
'weibo': '\ue260',
'weixin': '\ue261',
'pengyouquan': '\ue262',
'chat': '\ue263',
'qq': '\ue264',
'videocam': '\ue300',
'camera': '\ue301',
'mic': '\ue302',
'location': '\ue303',
'mic-filled': '\ue332',
'speech': '\ue332',
'location-filled': '\ue333',
'micoff': '\ue360',
'image': '\ue363',
'map': '\ue364',
'compose': '\ue400',
'trash': '\ue401',
'upload': '\ue402',
'download': '\ue403',
'close': '\ue404',
'redo': '\ue405',
'undo': '\ue406',
'refresh': '\ue407',
'star': '\ue408',
'plus': '\ue409',
'minus': '\ue410',
'circle': '\ue411',
'checkbox': '\ue411',
'close-filled': '\ue434',
'clear': '\ue434',
'refresh-filled': '\ue437',
'star-filled': '\ue438',
'plus-filled': '\ue439',
'minus-filled': '\ue440',
'circle-filled': '\ue441',
'checkbox-filled': '\ue442',
'closeempty': '\ue460',
'refreshempty': '\ue461',
'reload': '\ue462',
'starhalf': '\ue463',
'spinner': '\ue464',
'spinner-cycle': '\ue465',
'search': '\ue466',
'plusempty': '\ue468',
'forward': '\ue470',
'back': '\ue471',
'left-nav': '\ue471',
'checkmarkempty': '\ue472',
'home': '\ue500',
'navigate': '\ue501',
'gear': '\ue502',
'paperplane': '\ue503',
'info': '\ue504',
'help': '\ue505',
'locked': '\ue506',
'more': '\ue507',
'flag': '\ue508',
'home-filled': '\ue530',
'gear-filled': '\ue532',
'info-filled': '\ue534',
'help-filled': '\ue535',
'more-filled': '\ue537',
'settings': '\ue560',
'list': '\ue562',
'bars': '\ue563',
'loop': '\ue565',
'paperclip': '\ue567',
'eye': '\ue568',
'arrowup': '\ue580',
'arrowdown': '\ue581',
'arrowleft': '\ue582',
'arrowright': '\ue583',
'arrowthinup': '\ue584',
'arrowthindown': '\ue585',
'arrowthinleft': '\ue586',
'arrowthinright': '\ue587',
'pulldown': '\ue588',
'closefill': '\ue589',
'sound': '\ue590',
'scan': '\ue612'
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,214 @@
<template>
<view class="uni-navbar">
<view
:class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
:style="{ 'background-color': backgroundColor }"
class="uni-navbar__content">
<uni-status-bar v-if="statusBar" />
<view :style="{ color: color, backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="leftIcon.length"><uni-icons :color="color" :type="leftIcon" size="24" /></view>
<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view" v-if="leftText.length">
<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
</view>
<slot name="left" />
</view>
<view class="uni-navbar__header-container uni-navbar__content_view">
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
<text class="uni-nav-bar-text" :style="{ color: color }">{{ title }}</text>
</view>
<!-- 标题插槽 -->
<slot />
</view>
<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="rightIcon.length"><uni-icons :color="color" :type="rightIcon" size="24" /></view>
<!-- 优先显示图标 -->
<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
<text class="uni-nav-bar-right-text">{{ rightText }}</text>
</view>
<slot name="right" />
</view>
</view>
</view>
<view class="uni-navbar__placeholder" v-if="fixed">
<uni-status-bar v-if="statusBar" />
<view class="uni-navbar__placeholder-view" />
</view>
</view>
</template>
<script>
export default {
name: 'UniNavBar',
props: {
title: {
type: String,
default: ''
},
leftText: {
type: String,
default: ''
},
rightText: {
type: String,
default: ''
},
leftIcon: {
type: String,
default: ''
},
rightIcon: {
type: String,
default: ''
},
fixed: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: '#000000'
},
backgroundColor: {
type: String,
default: '#FFFFFF'
},
statusBar: {
type: [Boolean, String],
default: false
},
shadow: {
type: [String, Boolean],
default: false
},
border: {
type: [String, Boolean],
default: true
}
},
mounted() {
if (uni.report && this.title !== '') {
uni.report('title', this.title);
}
},
methods: {
onClickLeft() {
this.$emit('clickLeft');
},
onClickRight() {
this.$emit('clickRight');
}
}
};
</script>
<style lang="scss" scoped>
$nav-height: 44px;
.uni-nav-bar-text {
/* #ifdef APP-PLUS */
font-size: 34rpx;
/* #endif */
/* #ifndef APP-PLUS */
font-size: $uni-font-size-lg;
/* #endif */
}
.uni-nav-bar-right-text {
font-size: $uni-font-size-base;
}
.uni-navbar {
width: 750rpx;
}
.uni-navbar__content {
position: relative;
width: 750rpx;
background-color: $uni-bg-color;
overflow: hidden;
}
.uni-navbar__content_view {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
flex-direction: row;
// background-color: #FFFFFF;
}
.uni-navbar__header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
width: 750rpx;
height: $nav-height;
line-height: $nav-height;
font-size: 16px;
// background-color: #ffffff;
}
.uni-navbar__header-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-wrap: nowrap;
width: 120rpx;
padding: 0 6px;
justify-content: center;
align-items: center;
}
.uni-navbar__header-btns-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
justify-content: flex-start;
}
.uni-navbar__header-btns-right {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
padding-right: 30rpx;
justify-content: flex-end;
}
.uni-navbar__header-container {
flex: 1;
}
.uni-navbar__header-container-inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
align-items: center;
justify-content: center;
font-size: $uni-font-size-base;
}
.uni-navbar__placeholder-view {
height: $nav-height;
}
.uni-navbar--fixed {
position: fixed;
z-index: 998;
}
.uni-navbar--shadow {
/* #ifndef APP-NVUE */
box-shadow: 0 1px 6px #ccc;
/* #endif */
}
.uni-navbar--border {
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: $uni-border-color;
}
</style>

View File

@@ -0,0 +1,261 @@
<template>
<view class="uni-numbox" :class="{ small: size == 'small' }">
<button type="default" class="decrease" :class="{ disabled: inputValue <= min || disabled, small: size == 'small' }" @click="_calcValue('minus')">-</button>
<!-- <view
class="uni-numbox__minus"
> -->
<!-- :style="'background-image:url(' + $util.img('public/uniapp/jian.png') + ')'" -->
<!-- </view> -->
<!-- <input :disabled="disabled || inputDisabled" class="uni-input uni-numbox__value" type="number" @input="_onInput" @blur="_onInput" :class="{ small: size == 'small' }" v-model="inputValue"/> -->
<input :disabled="disabled || inputDisabled" class="uni-input uni-numbox__value" type="number" @blur="_onInput" :class="{ small: size == 'small' }" v-model="inputValue" />
<button type="default" class="increase" :class="{ disabled: inputValue >= max || disabled, small: size == 'small' }" @click="_calcValue('plus')">+</button>
<!-- <view
class="uni-numbox__plus" @click="_calcValue('plus')"
:style="'background-image:url(' + $util.img('public/uniapp/jia.png') + ')'"
>
</view> -->
</view>
</template>
<script>
export default {
name: 'UniNumberBox',
props: {
value: {
type: [Number, String],
default: 1
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
disabled: {
type: Boolean,
default: false
},
inputDisabled: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'default'
},
index: {
type: [Number, String],
default: -1
}
},
data() {
return {
inputValue: 0,
initialValue: 0, // 初始值,防止第一次触发变化
initialIndex: 0, // 初始索引,防止第一次触发变化
};
},
watch: {
value(val) {
this.inputValue = +val;
},
inputValue(newVal, oldVal, params) {
// 与初始值相同,不允许操作
if (+newVal != 0 && +newVal == this.initialValue) return;
// 索引不同,不允许操作
if (this.initialIndex != this.index) return;
if (+newVal !== +oldVal) {
this.$emit('change', newVal, params);
}
}
},
created() {
this.initialValue = +this.value;
this.inputValue = +this.value;
this.initialIndex = this.index;
},
methods: {
_calcValue(type) {
if (this.disabled) {
return;
}
const scale = this._getDecimalScale();
let value = this.inputValue * scale;
let step = this.step * scale;
if (type === 'minus') {
value -= step;
} else if (type === 'plus') {
value += step;
}
if (value < this.min && type === 'minus') {
this.$emit('limit', {
value: this.inputValue,
type
}, this.index);
return;
}
if (value > this.max && type === 'plus') {
this.$emit('limit', {
value: this.inputValue,
type
}, this.index);
return;
}
this.inputValue = value / scale;
},
_getDecimalScale() {
let scale = 1;
// 浮点型
if (~~this.step !== this.step) {
scale = Math.pow(10, (this.step + '').split('.')[1].length);
}
return scale;
},
_onInput(event) {
setTimeout(() => {
let value = event.detail.value;
// if (!/(^[1-9]\d*$)/.test(value)) value = this.min;
// if (!value) {
// this.inputValue = 0;
// return;
// }
value = +value;
if (value > this.max) {
value = this.max;
this.$util.showToast({
title: '商品库存不足'
});
} else if (value < this.min) {
this.$util.showToast({
title: '商品最少购买' + this.min + '件'
});
value = this.min;
}
// 如果没有最小购买同时也删除了输入框的内容默认赋值为1
if (!value) value = 1;
this.inputValue = value;
this.$forceUpdate();
}, 0);
}
}
};
</script>
<style lang="scss">
.uni-numbox {
display: inline-flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 70rpx;
position: relative;
}
.uni-numbox.small {
height: 44rpx;
}
.uni-numbox:after {
content: '';
position: absolute;
transform-origin: center;
box-sizing: border-box;
pointer-events: none;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
border-radius: 12rpx;
transform: scale(0.5);
}
.uni-numbox__minus,
.uni-numbox__plus {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background-size: 100% 100%;
background-position: center;
}
.uni-numbox__value {
position: relative;
background-color: $color-bg;
width: 80rpx;
height: 40rpx;
text-align: center;
border: 1px solid $color-line;
display: inline-block;
line-height: 36rpx;
font-weight: bold;
margin: 0;
padding: 0;
vertical-align: top;
min-height: initial;
border-left: none;
border-right: none;
}
.uni-numbox__value.small {
width: 60rpx;
font-size: $font-size-tag;
}
.uni-numbox__value:after {
content: '';
position: absolute;
transform-origin: center;
box-sizing: border-box;
pointer-events: none;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
border-top-width: 0;
border-bottom-width: 0;
transform: scale(0.5);
}
.uni-numbox--disabled {
color: silver;
}
.uni-numbox button {
width: 40rpx;
height: 40rpx;
display: inline-block;
box-sizing: content-box;
border: 1px solid $color-line;
padding: 0;
margin: 0;
border-radius: 0;
background-color: #fff;
font-weight: bold;
&.disabled {
color: $color-line;
background-color: #f8f8f8 !important;
}
&.decrease {
font-size: 44rpx;
line-height: 32rpx;
}
&.increase {
font-size: $font-size-toolbar;
line-height: 36rpx;
}
}
</style>

View File

@@ -0,0 +1,221 @@
<template>
<view v-if="showPopup" class="uni-popup">
<view :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__mask" @click="close(true)" ></view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper goodslist-uni-popup safe-area" @click="close(true)" v-if="isIphoneX">
<view class="uni-popup__wrapper-box goodslist-uni-popup-box" @click.stop="clear"><slot /></view>
</view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper goodslist-uni-popup" @click="close(true)" v-else>
<view class="uni-popup__wrapper-box goodslist-uni-popup-box" @click.stop="clear"><slot /></view>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopup',
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
type: {
type: String,
default: 'center'
},
// 是否开启自定义
custom: {
type: Boolean,
default: false
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: true
}
},
data() {
return {
ani: '',
showPopup: false,
callback: null,
isIphoneX: false
};
},
watch: {
show(newValue) {
if (newValue) {
this.open();
} else {
this.close();
}
}
},
created() {
this.isIphoneX = this.$util.uniappIsIPhoneX();
},
methods: {
clear() {},
open(callback) {
if (callback) this.callback = callback;
this.$emit('change', {
show: true
});
this.showPopup = true;
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'uni-' + this.type;
}, 30);
});
},
close(type, callback) {
if (!this.maskClick && type) return;
this.$emit('change', {
show: false
});
this.ani = '';
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false;
}, 300);
});
if (callback) callback();
if (this.callback) this.callback.call(this);
}
}
};
</script>
<style>
.uni-popup {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
overflow: hidden;
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 998;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
}
.uni-popup__mask.ani {
transition: all 0.3s;
}
.uni-popup__mask.uni-bottom,
.uni-popup__mask.uni-center,
.uni-popup__mask.uni-right,
.uni-popup__mask.uni-left,
.uni-popup__mask.uni-top {
opacity: 1;
}
.uni-popup__wrapper {
position: absolute;
z-index: 999;
box-sizing: border-box;
//background: #ffffff;
}
.uni-popup__wrapper.ani {
transition: all 0.3s;
}
.uni-popup__wrapper.top {
top: 0;
left: 0;
width: 100%;
transform: translateY(-100%);
}
.uni-popup__wrapper.bottom {
bottom: 0;
left: 0;
width: 100%;
transform: translateY(100%);
}
.uni-popup__wrapper.right {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(100%);
}
.uni-popup__wrapper.left {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(-100%);
}
.uni-popup__wrapper.center {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0;
}
.uni-popup__wrapper-box {
position: relative;
box-sizing: border-box;
}
.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
//background: #fff;
}
.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
position: relative;
max-width: 80%;
max-height: 80%;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box,
.uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
width: 100%;
max-height: 500px;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-bottom,
.uni-popup__wrapper.uni-top {
transform: translateY(0);
}
.uni-popup__wrapper.uni-left,
.uni-popup__wrapper.uni-right {
transform: translateX(0);
}
.uni-popup__wrapper.uni-center {
transform: scale(1);
opacity: 1;
}
/* isIphoneX系列手机底部安全距离 */
.bottom.safe-area {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>

View File

@@ -0,0 +1,222 @@
<template>
<view v-if="showPopup" class="uni-popup">
<view :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__mask" @click="close(true)" ></view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper safe-area" @click="close(true)" v-if="isIphoneX">
<view class="uni-popup__wrapper-box" @click.stop="clear"><slot /></view>
</view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper" @click="close(true)" v-else>
<view class="uni-popup__wrapper-box" @click.stop="clear"><slot /></view>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopup',
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
type: {
type: String,
default: 'center'
},
// 是否开启自定义
custom: {
type: Boolean,
default: false
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: true
}
},
data() {
return {
ani: '',
showPopup: false,
callback: null,
isIphoneX: false
};
},
watch: {
show(newValue) {
if (newValue) {
this.open();
} else {
this.close();
}
}
},
created() {
this.isIphoneX = this.$util.uniappIsIPhoneX();
},
methods: {
clear() {},
open(callback) {
if (callback) this.callback = callback;
this.$emit('change', {
show: true
});
this.showPopup = true;
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'uni-' + this.type;
}, 30);
});
},
close(type, callback) {
if (!this.maskClick && type) return;
this.$emit('change', {
show: false
});
this.ani = '';
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false;
}, 300);
});
if (callback) callback();
if (this.callback) this.callback.call(this);
}
}
};
</script>
<style>
.uni-popup {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
overflow: hidden;
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 998;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
}
.uni-popup__mask.ani {
transition: all 0.3s;
}
.uni-popup__mask.uni-bottom,
.uni-popup__mask.uni-center,
.uni-popup__mask.uni-right,
.uni-popup__mask.uni-left,
.uni-popup__mask.uni-top {
opacity: 1;
}
.uni-popup__wrapper {
position: absolute;
z-index: 999;
box-sizing: border-box;
background: #ffffff;
}
.uni-popup__wrapper.ani {
transition: all 0.3s;
}
.uni-popup__wrapper.top {
top: 0;
left: 0;
width: 100%;
transform: translateY(-100%);
}
.uni-popup__wrapper.bottom {
bottom: 0;
left: 0;
width: 100%;
transform: translateY(100%);
}
.uni-popup__wrapper.right {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(100%);
}
.uni-popup__wrapper.left {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(-100%);
}
.uni-popup__wrapper.center {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0;
}
.uni-popup__wrapper-box {
position: relative;
box-sizing: border-box;
}
.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
background: #fff;
}
.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
position: relative;
max-width: 80%;
max-height: 80%;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box,
.uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
width: 100%;
max-height: 500px;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-bottom,
.uni-popup__wrapper.uni-top {
transform: translateY(0);
}
.uni-popup__wrapper.uni-left,
.uni-popup__wrapper.uni-right {
transform: translateX(0);
}
.uni-popup__wrapper.uni-center {
transform: scale(1);
opacity: 1;
}
/* isIphoneX系列手机底部安全距离 */
.bottom.safe-area {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>

View File

@@ -0,0 +1,244 @@
<template>
<view v-if="showPopup" class="uni-popup" :class="customClass" :style="{'top': top}">
<view :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__mask" @click="close(true)" ></view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper goodslist-uni-popup safe-area" @click="close(true)" v-if="isIphoneX">
<view class="uni-popup__wrapper-box goodslist-uni-popup-box" @click.stop="clear">
<slot />
</view>
</view>
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper goodslist-uni-popup" @click="close(true)" v-else>
<view class="uni-popup__wrapper-box goodslist-uni-popup-box" @click.stop="clear">
<slot />
</view>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopup',
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
type: {
type: String,
default: 'center'
},
// 是否开启自定义
custom: {
type: Boolean,
default: false
},
// maskClick
maskClick: {
type: Boolean,
default: true
},
show: {
type: Boolean,
default: true
},
top: {
type: String,
default: '0'
},
customClass: {
type: String,
default: ''
}
},
data() {
return {
ani: '',
showPopup: false,
callback: null,
isIphoneX: false
};
},
watch: {
show(newValue) {
if (newValue) {
this.open();
} else {
this.close();
}
}
},
created() {
this.isIphoneX = this.$util.uniappIsIPhoneX();
},
methods: {
clear() {},
open(callback) {
if (callback) this.callback = callback;
this.$emit('change', {
show: true
});
this.showPopup = true;
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'uni-' + this.type;
}, 30);
});
},
close(type, callback) {
if (!this.maskClick && type) return;
this.$emit('change', {
show: false
});
this.ani = '';
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false;
}, 300);
});
if (callback) callback();
if (this.callback) this.callback.call(this);
}
}
};
</script>
<style>
.uni-popup {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
overflow: hidden;
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 998;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
}
.uni-popup__mask.ani {
transition: all 0.3s;
}
.uni-popup__mask.uni-bottom,
.uni-popup__mask.uni-center,
.uni-popup__mask.uni-right,
.uni-popup__mask.uni-left,
.uni-popup__mask.uni-top {
opacity: 1;
}
.uni-popup__wrapper {
position: absolute;
z-index: 999;
box-sizing: border-box;
//background: #ffffff;
}
.uni-popup__wrapper.ani {
transition: all 0.3s;
}
.uni-popup__wrapper.top {
top: 0;
left: 0;
width: 100%;
transform: translateY(-100%);
}
.uni-popup__wrapper.bottom {
bottom: 0;
left: 0;
width: 100%;
transform: translateY(100%);
background: #ffffff;
}
.uni-popup__wrapper.right {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(100%);
}
.uni-popup__wrapper.left {
bottom: 0;
left: 0;
width: 100%;
transform: translateX(-100%);
}
.uni-popup__wrapper.center {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0;
}
.uni-popup__wrapper-box {
position: relative;
box-sizing: border-box;
border-radius: 10rpx;
}
.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
background: #fff;
}
.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
position: relative;
max-width: 80%;
max-height: 80%;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box,
.uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
width: 100%;
max-height: 500px;
overflow-y: scroll;
}
.uni-popup__wrapper.uni-bottom,
.uni-popup__wrapper.uni-top {
transform: translateY(0);
}
.uni-popup__wrapper.uni-left,
.uni-popup__wrapper.uni-right {
transform: translateX(0);
}
.uni-popup__wrapper.uni-center {
transform: scale(1);
opacity: 1;
}
/* isIphoneX系列手机底部安全距离 */
.bottom.safe-area {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.left.safe-area {
padding-bottom: 68rpx;
}
.right.safe-area {
padding-bottom: 68rpx;
}
</style>

View File

@@ -0,0 +1,8 @@
## 1.0.32022-01-21
- 优化 组件示例
## 1.0.22021-11-22
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.12021-11-22
- 修复 vue3中scss语法兼容问题
## 1.0.02021-11-18
- init

View File

@@ -0,0 +1 @@
@import './styles/index.scss';

View File

@@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 通过一些简单的类名和sass变量实现简单的页面布局操作比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,31 @@
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
// 辅助色
$uni-success: #4cd964;
// 警告色
$uni-warning: #f0ad4e;
// 错误色
$uni-error: #dd524d;
// 描述色
$uni-info: #909399;
// 中性色
$uni-main-color: #303133;
$uni-base-color: #606266;
$uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC;
// 背景色
$uni-bg-color: #f5f5f5;
// 边框颜色
$uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED;
$uni-border-3: #EBEEF5;
$uni-border-4: #F2F6FC;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);

View File

@@ -0,0 +1,62 @@
@import './styles/setting/_variables.scss';
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
$uni-primary-disable:mix(#fff,$uni-primary,50%);
$uni-primary-light: mix(#fff,$uni-primary,80%);
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37;
$uni-success-disable:mix(#fff,$uni-success,50%);
$uni-success-light: mix(#fff,$uni-success,80%);
$uni-warning: #f3a73f;
$uni-warning-disable:mix(#fff,$uni-warning,50%);
$uni-warning-light: mix(#fff,$uni-warning,80%);
$uni-error: #e43d33;
$uni-error-disable:mix(#fff,$uni-error,50%);
$uni-error-light: mix(#fff,$uni-error,80%);
$uni-info: #8f939c;
$uni-info-disable:mix(#fff,$uni-info,50%);
$uni-info-light: mix(#fff,$uni-info,80%);
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a; // 主要文字
$uni-base-color: #6a6a6a; // 常规文字
$uni-secondary-color: #909399; // 次要文字
$uni-extra-color: #c7c7c7; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
// 背景色
$uni-bg-color: #f7f7f7;
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4);

View File

@@ -0,0 +1,23 @@
<template>
<view :style="{ height: statusBarHeight }" class="uni-status-bar"><slot /></view>
</template>
<script>
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight * 2 + 'rpx';
export default {
name: 'UniStatusBar',
data() {
return {
statusBarHeight: statusBarHeight
};
}
};
</script>
<style lang="scss" scoped>
.uni-status-bar {
width: 750rpx;
height: 20px;
// height: var(--status-bar-height);
}
</style>

View File

@@ -0,0 +1,158 @@
<template>
<view
v-if="text"
:class="[
disabled === true || disabled === 'true' ? 'uni-tag--disabled' : '',
inverted === true || inverted === 'true' ? 'uni-tag--inverted' : '',
circle === true || circle === 'true' ? 'uni-tag--circle' : '',
mark === true || mark === 'true' ? 'uni-tag--mark' : '',
'uni-tag--' + size,
'uni-tag--' + type
]"
class="uni-tag"
@click="onClick()"
>
{{ text }}
</view>
</template>
<script>
export default {
name: 'UniTag',
props: {
type: {
// 标签类型default、primary、success、warning、danger、royal
type: String,
default: 'default'
},
size: {
// 标签大小 normal, small
type: String,
default: 'normal'
},
// 标签内容
text: {
type: String,
default: ''
},
disabled: {
// 是否为禁用状态
type: [String, Boolean],
defalut: false
},
inverted: {
// 是否为空心
type: [String, Boolean],
defalut: false
},
circle: {
// 是否为圆角样式
type: [String, Boolean],
defalut: false
},
mark: {
// 是否为标记样式
type: [String, Boolean],
defalut: false
}
},
methods: {
onClick() {
if (this.disabled === true || this.disabled === 'true') {
return;
}
this.$emit('click');
}
}
};
</script>
<style>
.uni-tag {
box-sizing: border-box;
padding: 0 32rpx;
height: 60rpx;
line-height: calc(60rpx - 2px);
font-size: 28rpx;
display: inline-flex;
align-items: center;
color: #333;
border-radius: 6rpx;
background-color: #f8f8f8;
border: 1px solid #f8f8f8;
}
.uni-tag--circle {
border-radius: 30rpx;
}
.uni-tag--mark {
border-radius: 0 30rpx 30rpx 0;
}
.uni-tag--disabled {
opacity: 0.5;
}
.uni-tag--small {
height: 40rpx;
padding: 0 16rpx;
line-height: calc(40rpx - 2px);
font-size: 24rpx;
}
.uni-tag--primary {
color: #fff;
background-color: #007aff;
border: 1px solid #007aff;
}
.uni-tag--primary.uni-tag--inverted {
color: #007aff;
background-color: #fff;
border: 1px solid #007aff;
}
.uni-tag--success {
color: #fff;
background-color: #4cd964;
border: 1px solid #4cd964;
}
.uni-tag--success.uni-tag--inverted {
color: #4cd964;
background-color: #fff;
border: 1px solid #4cd964;
}
.uni-tag--warning {
color: #fff;
background-color: #f0ad4e;
border: 1px solid #f0ad4e;
}
.uni-tag--warning.uni-tag--inverted {
color: #f0ad4e;
background-color: #fff;
border: 1px solid #f0ad4e;
}
.uni-tag--error {
color: #fff;
background-color: #dd524d;
border: 1px solid #dd524d;
}
.uni-tag--error.uni-tag--inverted {
color: #dd524d;
background-color: #fff;
border: 1px solid #dd524d;
}
.uni-tag--inverted {
color: #333;
background-color: #fff;
border: 1px solid #f8f8f8;
}
</style>