mini-ali-UI
日历组件回显修改源码版:calendar
组件没有暴露出日期回显的参数,无法出现打开日历默认选择某一日期阶段,用户在点击打开日历时,默认选择了近30天的日期,用户未选择日期时,上下切换月份不清除选择的日期,用户选择日期后清除默认选择,展示用户选择的日期。经过查询,确定需要修改源码实现,以下为实现代码:axml
文件:几乎没有改动,可以直接使用源码<view class="am-calendar {{className}}" a:if="{{dates.length > 0}}">
<view class="am-calendar-months">
<view class="am-calendar-prev-month {{prevYearDisable?'am-calendar-prev-year_disable':''}}" onTap="onPrevYearTap" a:if="{{haveYear}}">
<view class="am-calendar-arrow am-calendar-arrow_year"></view>
</view>
<view class="am-calendar-prev-month {{prevMonthDisable?'am-calendar-prev-month_disable':''}}" onTap="onPrevMonthTap">
<am-icon type="left" class="am-calendar-arrow" />
</view>
<view class="am-calendar-selected-month">
{{selectedYear}}{{_i18nYear}}{{_i18nMonth.length > 1?'':selectedMonth + 1}}{{_i18nMonth[selectedMonth]?_i18nMonth[selectedMonth]:_i18nMonth}}
</view>
<view class="am-calendar-next-month {{nextvMonthDisable?'am-calendar-next-month_disable':''}}" onTap="onNextMonthTap">
<am-icon type="right" class="am-calendar-arrow" />
</view>
<view class="am-calendar-next-month {{nextYearDisable?'am-calendar-next-year_disable':''}}" onTap="onNextYearTap" a:if="{{haveYear}}">
<view class="am-calendar-arrow am-calendar-arrow_year next"></view>
</view>
</view>
<!-- 星期 -->
<view class="am-calendar-days">
<block a:for="{{[`${_i18nWeekSun}`, `${_i18nWeekMon}`, `${_i18nWeekTue}`, `${_i18nWeekWed}`, `${_i18nWeekThu}`, `${_i18nWeekFri}`, `${_i18nWeekSat}`]}}">
<view class="am-calendar-day">{{item}}</view>
</block>
</view>
<!-- 日历 -->
<view class="am-calendar-dates">
<block a:for="{{dates}}">
<view class="am-calendar-week">
<block a:for="{{item}}">
<view class="am-calendar-date-wrap
{{ item.isSelected ? 'am-calendar-selected': '' }}
{{ item.isStart ? 'am-calendar-start': '' }}
{{ item.isMiddle ? 'am-calendar-middle': '' }}
{{ item.isEnd ? 'am-calendar-end': '' }}
{{ item.disable ? 'am-calendar-disable': '' }}
{{ type === 'range' ? 'is-range' : '' }}" data-year="{{item.year}}" data-month="{{item.month}}" data-date="{{item.date}}" onTap="onDateTap">
<view class="am-calendar-block {{ blockType === 2 ? 'has-tag': '' }}"></view>
<view class="am-calendar-date {{ item.isGray ? 'am-calendar-gray': '' }} {{ item.isToday ? 'am-calendar-today': ''}}">
{{item.date}}
</view>
<view class="am-calendar-tag" style="{{
color: item.isSelected || item.isMiddle || item.isStart || item.isEnd ? '#fff' : (item.disable ? '#ccc' : item.color)
}}">{{item.disable ? '' : item.tag}}</view>
</view>
</block>
</view>
</block>
</view>
</view>
json
文件:
UI
库里的iocn
,不用下载该文件,直接指向原来的node_modules
里就可以{
"component": true,
"usingComponents": {
"am-icon":"../../node_modules/mini-ali-ui/es/am-icon/index"
}
}
js
文件
json
文件一样,指向node_modules
就可以// import getI18n from '../_util/getI18n';
import getI18n from '../../node_modules/mini-ali-ui/es/_util/getI18n';
const i18n = getI18n().calendar;
/* eslint-disable complexity, no-param-reassign */
/* eslint max-depth: [2, 7] */
const leapYear = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const commonYear = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const FIRST_MONTH = 0;
const LAST_MONTH = 11;
const DAYS_PER_ROW = 7;
const COLOR_MAP = {
1: '#ff6010',
2: '#00b578',
3: '#ff8f1f',
4: '#1677ff',
5: '#999',
};
// 获取某月第某天是星期几
function getDay(month, year, index) {
return new Date(year, month, index).getDay();
}
// 获取某月有几天
function getMonthLength(month, year) {
if ((year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0)) {
return leapYear[month];
} else {
return commonYear[month];
}
}
// 数字补位 1 -> 01
function prefixNum(num) {
if (num < 10) {
return `0${num}`;
} else {
return `${num}`;
}
}
Component({
data: {
selectedYear: 0,
selectedMonth: 0,
currentDate: null,
dates: [],
ischeckd: false,
blockType: 1, // 1.没有待办纯数字 2.有待办 用于区分不同类型日期块的样式。
_i18nYear: i18n.year,
_i18nMonth: i18n.month,
_i18nWeekSun: i18n.sunday,
_i18nWeekMon: i18n.monday,
_i18nWeekTue: i18n.tuesday,
_i18nWeekWed: i18n.wednesday,
_i18nWeekThu: i18n.thursday,
_i18nWeekFri: i18n.friday,
_i18nWeekSat: i18n.saturday,
},
props: {
currentDate: '',
className: '',
tagData: [],
type: 'single',
haveYear: false,
prevMonthDisable: false,
prevYearDisable: false,
nextvMonthDisable: false,
nextYearDisable: false,
needbackdate: true, //是否需要回显日期
needbackdateNum: '30',
},
didMount() {
this.tapTimes = 1;
const date = new Date();
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
const year = date.getFullYear();
const month = date.getMonth();
this.setData({
selectedYear: year,
selectedMonth: month,
currentDate: date,
});
this.refreshdates(month, year);
},
/**
* 日历加载切换月份都刷新
* */
didUpdate() {
if (this.data.ischeckd) {
const {
dates
} = this.data;
let blockType = 1;
for (let i = 0; i < dates.length; i++) {
for (let j = 0; j < dates[i].length; j++) {
if (this.hasTag(dates[i][j])) {
blockType = 2;
}
}
}
this.setData({
dates,
blockType,
});
} else {
if (this.props.needbackdate) {
let date1 = new Date();
let date2 = new Date(date1);
date2.setDate(date1.getDate() - this.props.needbackdateNum);
// console.log(this.data.currentDate.getFullYear(), this.data.currentDate.getMonth(), this.data.currentDate.getDate())
// console.log(this.props.needbackdateNum, date2.getFullYear(), date2.getMonth(), date2.getDay());
const {
dates
} = this.data;
let blockType = 1;
for (let i = 0; i < dates.length; i++) {
for (let j = 0; j < dates[i].length; j++) {
if (dates[i][j].year == date2.getFullYear() || dates[i][j].year == this.data.currentDate.getFullYear()) {
if (dates[i][j].month == date2.getMonth() || dates[i][j].month == this.data.currentDate.getMonth()) {
if (dates[i][j].month == this.data.currentDate.getMonth() && dates[i][j].date <= this.data.currentDate.getDate()) {
dates[i][j].isSelected = true
dates[i][j].isMiddle = true
if (dates[i][j].date == this.data.currentDate.getDate()) {
dates[i][j].isSelected = true
dates[i][j].isMiddle = false
}
}
if (dates[i][j].month == date2.getMonth() && dates[i][j].date >= date2.getDay()) {
dates[i][j].isSelected = true
dates[i][j].isMiddle = true
if (dates[i][j].date == date2.getDay()) {
dates[i][j].isSelected = true
dates[i][j].isMiddle = false
}
}
}
}
if (this.hasTag(dates[i][j])) {
blockType = 2;
}
}
}
this.setData({
dates,
blockType,
});
}
}
},
methods: {
/**
* 点击上一年按钮
* */
onPrevYearTap() {
const {
selectedMonth,
selectedYear
} = this.data;
const {
prevYearDisable
} = this.props;
if (!prevYearDisable) {
let year = selectedYear;
const month = selectedMonth;
year = selectedYear - 1;
if (this.props.onYearChange) {
this.props.onYearChange(year, selectedYear);
}
if (this.props.onChange) {
this.props.onChange({
year,
month
}, {
year: selectedYear,
month: selectedMonth
});
}
this.setData({
selectedYear: year,
});
this.refreshdates(month, year);
}
},
/**
* 点击下一年按钮
* */
onNextYearTap() {
const {
selectedMonth,
selectedYear
} = this.data;
const {
nextYearDisable
} = this.props;
if (!nextYearDisable) {
let year = selectedYear;
const month = selectedMonth;
year = selectedYear + 1;
if (this.props.onYearChange) {
this.props.onYearChange(year, selectedYear);
}
if (this.props.onChange) {
this.props.onChange({
year,
month
}, {
year: selectedYear,
month: selectedMonth
});
}
this.setData({
selectedYear: year,
});
this.refreshdates(month, year);
}
},
/**
* 点击上一月按钮
* */
onPrevMonthTap() {
const {
selectedMonth,
selectedYear
} = this.data;
const {
prevMonthDisable
} = this.props;
if (!prevMonthDisable) {
let year = selectedYear;
let month = selectedMonth;
// 如果当前选中是一月份,前一月是去年的12月
if (selectedMonth === FIRST_MONTH) {
year = selectedYear - 1;
month = LAST_MONTH;
} else {
month = selectedMonth - 1;
}
if (this.props.onMonthChange) {
this.props.onMonthChange(month, selectedMonth);
}
if (this.props.onChange) {
this.props.onChange({
year,
month
}, {
year: selectedYear,
month: selectedMonth
});
}
this.setData({
selectedYear: year,
selectedMonth: month,
});
this.refreshdates(month, year);
}
},
/**
* 点击下一月按钮
* */
onNextMonthTap() {
const {
selectedMonth,
selectedYear
} = this.data;
const {
nextvMonthDisable
} = this.props;
if (!nextvMonthDisable) {
let year = selectedYear;
let month = selectedMonth;
// 如果当前选中是十二月份,下一月是去年的12月
if (selectedMonth === LAST_MONTH) {
year = selectedYear + 1;
month = FIRST_MONTH;
} else {
month = selectedMonth + 1;
}
if (this.props.onMonthChange) {
this.props.onMonthChange(month, selectedMonth);
}
if (this.props.onChange) {
this.props.onChange({
year,
month
}, {
year: selectedYear,
month: selectedMonth
});
}
this.setData({
selectedYear: year,
selectedMonth: month,
});
this.refreshdates(month, year);
}
},
/**
* 非点击事件,待逆向测试
* */
refreshdates(month, year) {
this.tapTimes = 1;
const {
selectedYear,
selectedMonth,
currentDate
} = this.data;
const firstDay = getDay(month, year, 1);
const days = getMonthLength(month, year);
const datesArray = [];
const currentDateTimeStamp = +currentDate;
let num = 0;
for (let i = 0; i < firstDay; i++) {
num += 1;
// 如果当前选中的是一月份,前一个月是去年的12月
let _year = selectedYear;
let _month = selectedMonth;
if (selectedMonth === 0) {
_year = selectedYear - 1;
_month = LAST_MONTH;
} else {
_year = selectedYear;
_month = selectedMonth - 1;
}
const date = getMonthLength(_month, _year) - i;
datesArray.unshift({
year: _year,
month: _month,
date,
isToday: false,
isGray: true,
isSelected: false,
tag: '',
});
}
for (let i = 0; i < days; i++) {
num += 1;
const date = i + 1;
const dateTimeStamp = +new Date(selectedYear, selectedMonth, date);
datesArray.push({
year: selectedYear,
month: selectedMonth,
date,
isToday: dateTimeStamp === currentDateTimeStamp,
isGray: false,
isSelected: dateTimeStamp === currentDateTimeStamp,
tag: '',
});
}
let nextDate = 0;
let daysPerPage = 35;
if (num > 35) {
daysPerPage = 42;
}
for (let i = 0; i < daysPerPage - days - firstDay; i++) {
// 如果是12月,下月是第二年的1月份
nextDate += 1;
let _year = selectedYear;
let _month = selectedMonth;
if (selectedMonth === LAST_MONTH) {
_year = selectedYear + 1;
_month = FIRST_MONTH;
} else {
_year = selectedYear;
_month = selectedMonth + 1;
}
datesArray.push({
year: _year,
month: _month,
date: nextDate,
isToday: false,
isGray: true,
isSelected: false,
tag: '',
});
}
let blockType = 1;
for (let i = 0; i < datesArray.length; i++) {
if (this.hasTag(datesArray[i])) {
blockType = 2;
}
}
const dates = [];
let weekDates = [];
for (let i = 0; i < datesArray.length; i++) {
weekDates.push(datesArray[i]);
if ((i + 1) % DAYS_PER_ROW === 0) {
dates.push([...weekDates]);
weekDates = [];
}
}
this.setData({
dates,
blockType,
});
},
/**
* 检查是否有tag并循环
* */
hasTag(dateObj) {
const {
tagData
} = this.props;
// 去重由调用者处理
if (tagData.length === 0) {
dateObj.tag = '';
return false;
}
return tagData.some((item) => {
const dateArr = item.date.split('-');
const dateStr = [];
// 兼容ios下new Date('2018-1-1')格式返回invalid Date的问题
for (let i = 0; i < dateArr.length; i++) {
dateStr.push(dateArr[i].length > 1 ? dateArr[i] : `0${dateArr[i]}`);
}
const date = new Date(dateStr.join('-'));
if (dateObj.year === date.getFullYear() &&
dateObj.month === date.getMonth() &&
dateObj.date === date.getDate()) {
dateObj.tag = item.tag;
dateObj.color = COLOR_MAP[item.tagColor];
dateObj.disable = item.disable;
return true;
} else {
dateObj.tag = '';
return false;
}
});
},
/**
* 选择日期区间
* */
getDateGap(day1, day2) {
const date1 = +new Date(day1.year, prefixNum(day1.month), prefixNum(day1.date));
const date2 = +new Date(day2.year, prefixNum(day2.month), prefixNum(day2.date));
return (date1 - date2) / (24 * 3600 * 1000);
},
/**
* 生成日期格式
* 用户点击后
* */
makeDate(dateObj) {
/**
* 记录用户是否选择了日期,
* 判断展示默认回显还是不显示
* */
this.setData({
ischeckd: true
})
return new Date(`${dateObj.year}-${prefixNum(dateObj.month + 1)}-${prefixNum(dateObj.date)}`);
},
/**
* 日历点击事件
* */
onDateTap(event) {
const {
dates
} = this.data;
const {
year,
month,
date
} = event.currentTarget.dataset;
const {
type
} = this.props;
if (type === 'range') {
if (this.tapTimes % 2 === 0) {
this.tapTimes += 1;
this.endDate = {
year,
month,
date
};
const dateGap = this.getDateGap(this.startDate, this.endDate);
if (dateGap > 0) {
[this.startDate, this.endDate] = [this.endDate, this.startDate];
}
let hasDisable = false;
for (let i = 0; i < dates.length; i++) {
for (let j = 0; j < dates[i].length; j++) {
const dateObj = dates[i][j];
dateObj.isStart = false;
dateObj.isMiddle = false;
dateObj.isEnd = false;
const startDateGap = this.getDateGap(dateObj, this.startDate);
const endDateGap = this.getDateGap(dateObj, this.endDate);
if (dateObj.year === year && dateObj.month === month && dateObj.date === date && dateObj.disable) {
hasDisable = true;
}
if (startDateGap > 0 && endDateGap < 0) {
if (dateObj.disable) {
hasDisable = true;
}
if (dateGap !== 0) {
if (j === 0) {
dateObj.isStart = true;
} else if (j === 6) {
dateObj.isEnd = true;
} else {
dateObj.isMiddle = true;
}
} else {
dateObj.isSelected = true;
}
}
if (this.startDate.year === dateObj.year &&
this.startDate.month === dateObj.month &&
this.startDate.date === dateObj.date && dateGap !== 0) {
if (j === 6) {
dateObj.isSelected = true;
} else {
dateObj.isStart = true;
}
}
if (this.endDate.year === dateObj.year &&
this.endDate.month === dateObj.month &&
this.endDate.date === dateObj.date && dateGap !== 0) {
if (j === 0) {
dateObj.isSelected = true;
} else {
dateObj.isEnd = true;
}
}
}
}
if (hasDisable) {
this.props.onSelectHasDisableDate([this.makeDate(this.startDate), this.makeDate(this.endDate)]);
return;
}
if (this.props.onSelect) {
this.props.onSelect([this.makeDate(this.startDate), this.makeDate(this.endDate)]);
}
} else {
let isDisable = false;
for (let i = 0; i < dates.length; i++) {
for (let j = 0; j < dates[i].length; j++) {
const dateObj = dates[i][j];
if (dateObj.year === year && dateObj.month === month && dateObj.date === date) {
if (dateObj.disable) {
isDisable = true;
dateObj.isSelected = false;
} else {
dateObj.isSelected = true;
}
dateObj.isStart = false;
dateObj.isMiddle = false;
dateObj.isEnd = false;
} else {
dateObj.isSelected = false;
dateObj.isStart = false;
dateObj.isMiddle = false;
dateObj.isEnd = false;
}
}
}
if (!isDisable) {
this.tapTimes += 1;
}
this.startDate = {
year,
month,
date
};
}
this.setData({
dates,
});
} else {
let isDisable = false;
for (let i = 0; i < dates.length; i++) {
for (let j = 0; j < dates[i].length; j++) {
const dateObj = dates[i][j];
if (dateObj.year === year && dateObj.month === month && dateObj.date === date) {
dateObj.isSelected = true;
if (dateObj.disable) {
isDisable = true;
}
} else {
dateObj.isSelected = false;
}
}
}
if (isDisable) {
return;
}
this.setData({
dates,
});
if (this.props.onSelect) {
this.props.onSelect([this.makeDate({
year,
month,
date
}), undefined]);
}
}
},
},
});
使用方法和普通组件一样,唯一一点区别就是我没有修改样式组件,因为源码组件样式是用less写的,有点错综复杂,代价太大,于是在引用这个组件时,需要json
文件中在组件库里引用原组件,就可以自动识别它的样式了。
举例:
{
"defaultTitle": "日历测试页面",
"titleBarColor":"#fff",
"pullRefresh": true,
"usingComponents": {
"calendar": "mini-ali-ui/es/calendar/index", //原组件日历
"calendar-local": "../../Component/calendar/calendar" //修改后的日历组件
}
}
属性 | 类型 | 描述 |
---|---|---|
needbackdate | Boolean | 是否展示回显30日,默认为false |