文章目录
- 效果图
- 1、组件
- 1.1、html部分
- 1.2、JavaScript部分
- 1.3、style部分
- 2、使用组件
- 3、总结
效果图
1、组件
1.1、html部分
<template>
<view v-if="isCalendar" class="calendar_box">
<view v-show="!isTime" class="btn_calendar_box">
<view class="btn_box">
<view class="cancel" @click="cancel">取消</view>
<view class="tab_bar_box">
<view class="tab_bar_item" :class="[calendarType === 'solar' ? 'activation_tab_bar' : '']"
@click="tabBar('solar')">公历</view>
<view class="tab_bar_item" :class="[calendarType === 'lunar' ? 'activation_tab_bar' : '']"
@click="tabBar('lunar')">农历</view>
</view>
<view class="confirm" @click="confirm">确认</view>
</view>
<picker-view :indicator-style="indicatorStyle" :value="value" @change="bindChange"
style="width:750upx; height: 400upx;">
<picker-view-column>
<view class="picker_item" v-for="item in years" :key="item.id">{{ calendarType === 'solar' ?
item.lYear
: item.l_gz_Year }}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker_item" v-for="item in months" :key="item.id">{{ calendarType === 'solar' ?
item.cMonth
: item.IMonthCn }}</view>
</picker-view-column>
<picker-view-column>
<view class="picker_item" v-for="item in days" :key="item.id">{{ calendarType === 'solar' ?
item.cDay
: item.IDayCn }}</view>
</picker-view-column>
<picker-view-column>
<view class="picker_item" v-for="item in hours" :key="item.id">{{ item.title }}</view>
</picker-view-column>
<picker-view-column>
<view class="picker_item" v-for="item in mins" :key="item.id">{{ item.title }}</view>
</picker-view-column>
</picker-view>
</view>
<view v-show="isTime" class="confirm_time_box">
<view class="confirm_time_title">确认时间</view>
<view class="input_time">请确认输入的时间是否正确</view>
<view>
<view class="value_box">
公(阳)历:{{ year.lYear }}{{ month.cMonth }}{{ day.cDay }}{{ hour.title }}{{ min.title }}
</view>
<view class="value_box">
农(阴)历:{{ year.gzYear }}{{ month.IMonthCn }}{{ day.IDayCn }}{{ hour.title }}{{ min.title }}
</view>
</view>
<view class="back_correct_btn_box">
<view class="back_edit" @click="backEdit">返回修改</view>
<view class="correct" @click="alreadyCorrect">确认正确</view>
</view>
</view>
</view>
</template>
1.2、JavaScript部分
需要在当前组件文件夹中下载安装
js-calendar-converter
模块,在uniApp
中不支持使用全局node_modules
。这也是uniApp
不受欢迎的原因之一,但是项目开发需要也是没办法,总之就是能不用uniApp
就不要用。
通过ref
打开组件时,组件的生命周期不会被触发。无论是打开时或页面加载时,都不会触发生命周期,这也是uniApp
的一个诟病。
alreadyCorrect
此方法会返回最终的数据,数据分别有年、月、日、时和分,这些数据是对象类型,对象中包含公历和农历的值。birthdayVal
字段返回拼接后的显示数据值,根据公历和农历返回对应值。
// solar2lunar 阳转阴
// lunar2solar 阴转阳
const res = require('js-calendar-converter');
let calendar = res.default;
export default {
name: 'mjCalendar',
data() {
return {
// lunar 阴历
// solar 阳历
calendarType: 'solar',
value: [23, 4, 0, 16, 16],
years: [],
year: {},
months: [],
month: {},
days: [],
day: {},
hours: [],
hour: {},
mins: [],
min: {},
indicatorStyle: undefined,
dayIndex: 0,
isTime: false,
isCalendar: false,
birthdayVal: ''
}
},
// 页面加载或打开组件时
// 此生命周期都不会被触发
onLoad() {
// this.indicatorStyle = `height: ${Math.round(uni.getSystemInfoSync().screenWidth / (750 / 80))}px;`;
// this.init();
},
methods: {
// 确认正确
alreadyCorrect() {
let year = this.year,
month = this.month,
day = this.day,
hour = this.hour,
min = this.min,
birthdayVal = '';
if (this.calendarType === 'solar') {
birthdayVal += year.lYear;
birthdayVal += month.cMonth;
birthdayVal += day.cDay;
} else {
birthdayVal += year.gzYear;
birthdayVal += month.IMonthCn;
birthdayVal += day.IDayCn;
}
birthdayVal += hour.title;
birthdayVal += min.title;
this.birthdayVal = birthdayVal;
this.isCalendar = false;
this.isTime = false;
this.$emit('backData', { year, month, day, hour, min, birthdayVal });
},
// 打开日期选择器
openCalendar() {
this.indicatorStyle = `height: ${Math.round(uni.getSystemInfoSync().screenWidth / (750 / 80))}px;`;
this.init();
this.isCalendar = true;
},
// 取消
cancel() {
this.isCalendar = false;
this.birthdayVal = '';
},
// 返回修改
backEdit() {
this.isTime = false;
},
// 确认
confirm() {
this.isTime = true;
},
// 阴阳历转换
tabBar(type) {
this.calendarType = type;
},
// 滑动触发
bindChange(event) {
let valArr = event.detail.value;
this.year = this.years[valArr[0]];
if (this.calendarType === 'lunar') {
let dayI = valArr[2],
isTB = dayI - this.dayIndex,
monI = valArr[1];
if (isTB === 1 && this.days[dayI].IDayCn === '初一') valArr[1] = monI + 1;
if (isTB === -1 && (['廿八', '廿九', '三十'].includes(this.days[dayI].IDayCn))) valArr[1] = monI - 1;
this.value = valArr;
this.dayIndex = dayI;
}
this.hour = this.hours[valArr[3]];
this.min = this.mins[valArr[4]];
// 根据年份生成月份数据
this.getMonth(this.year.lYear, valArr[1], valArr[2]);
},
// 初始化
init() {
let years = [],
hoursArr = ["未知时辰", "子", "丑", "丑", "寅", "寅", "卯", "卯", "辰", "辰", "巳", "巳", "午", "午", "未", "未", "申", "申", "酉", "酉", "戌", "戌", "亥", "亥", "子"],
hours = [],
mins = [],
valArr = this.value;
// 生成年份
for (let i = 2000; i < 2025; i++) {
let { lYear, gzYear } = calendar.solar2lunar(i, 5, 1);
years.push({
id: `id${i}`,
lYear: lYear + '年',
gzYear: gzYear + '年',
l_gz_Year: lYear + gzYear + '年'
});
}
this.years = years;
this.year = this.years[valArr[0]];
// 根据年份生成月份数据
this.getMonth(this.year.lYear, valArr[1], valArr[2]);
// 时辰数据
for (let i = 0; i < 25; i++) {
hours.push({
id: `id_${i + 1}`,
title: i !== 0 ? (i - 1) + hoursArr[i] : hoursArr[i],
value: i
});
}
// 分钟数据
for (let i = 0; i < 60; i++) {
mins.push({
id: `id_${i + 1}`,
title: i + '分',
value: i
});
}
this.hours = hours;
this.mins = mins;
this.hour = this.hours[valArr[3]];
this.min = this.mins[valArr[4]];
},
// 日期
getDay(year, month, i) {
month = month.replace(/[^\d]/g, "");
month = Number(month);
let isZero = year % 4 === 0,
len = [1, 3, 5, 7, 8, 10, 12].includes(month) ? 31 : [4, 6, 9, 11].includes(month) ? 30 : isZero ? 29 : 28,
days = [];
for (let i = 0; i < len; i++) {
let { IDayCn, cDay } = calendar.solar2lunar(year, month, i + 1);
days.push({
id: `id${i + 1}`,
IDayCn: IDayCn,
cDay: cDay + '日'
});
}
this.days = days;
this.day = this.days[i];
},
// 月份数据
getMonth(year, i, j) {
let months = [];
for (let i = 0; i < 12; i++) {
let { IMonthCn, cMonth } = calendar.solar2lunar(year, i + 1, 1);
months.push({
id: `id${i + 1}`,
IMonthCn,
cMonth: cMonth + '月'
});
}
this.months = months;
this.month = this.months[i];
// 根据年份和月份生成日期数据
this.getDay(this.year.lYear, this.month.cMonth, j);
}
}
}
1.3、style部分
.calendar_box {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: calc(100vh - 58px);
display: flex;
flex-direction: column-reverse;
background-color: rgba(200, 200, 200, .8);
z-index: 6;
}
.btn_calendar_box {
background-color: #ffffff;
padding-top: 12upx;
padding-bottom: 12upx;
z-index: 7;
}
.btn_box {
padding: 8upx 16upx;
display: flex;
justify-content: space-between;
align-items: center;
}
.tab_bar_box {
display: flex;
justify-content: space-between;
align-items: center;
border: 1upx solid rgb(201, 23, 35);
border-radius: 10upx;
}
.tab_bar_item {
height: 40upx;
line-height: 40upx;
padding: 10upx 30upx;
color: rgb(201, 23, 35);
cursor: pointer;
}
.activation_tab_bar {
background: rgb(201, 23, 35);
color: #FFFFFF;
}
.cancel {
color: rgb(153, 153, 153);
cursor: pointer;
font-size: 32upx;
}
.confirm {
color: rgb(201, 23, 35);
cursor: pointer;
font-size: 32upx;
}
.picker_item {
height: 80upx;
line-height: 80upx;
text-align: center;
font-size: 28upx;
}
/* ------------------------------- */
.confirm_time_box {
background-color: #ffffff;
padding-top: 12upx;
padding-bottom: 12upx;
z-index: 7;
}
.confirm_time_title {
text-align: center;
color: rgb(201, 23, 35);
font-size: 32upx;
border-bottom: 1upx solid #E8E8E8;
height: 88upx;
line-height: 88upx;
}
.input_time {
text-align: center;
font-size: 34upx;
color: #000000;
height: 48upx;
line-height: 48upx;
margin-top: 48upx;
padding-bottom: 20upx;
}
.value_box {
text-align: center;
font-size: 34upx;
color: rgb(163, 30, 26);
height: 34upx;
line-height: 34upx;
padding: 10upx 0px;
}
.back_correct_btn_box {
display: flex;
justify-content: center;
align-items: center;
padding: 40upx 0;
color: #ffffff;
}
.back_edit {
padding: 20upx 40upx;
border-radius: 10upx;
background-color: #DDDDDD;
}
.correct {
padding: 20upx 40upx;
margin-left: 40upx;
border-radius: 10upx;
background-color: rgb(163, 30, 26);
}
2、使用组件
html部分
<view class="open_calendar">
<text>生辰</text>
<input class="input" :value="birthdayVal" placeholder="请选择生辰" disabled @click="openCalendar" />
</view>
<mj-calendar ref="refMjCalendar" @backData="backData"></mj-calendar>
style部分
.open_calendar {
display: flex;
justify-content: center;
align-items: center;
height: 90upx;
line-height: 90upx;
}
.input {
width: 390upx;
margin-left: 12upx;
}
JavaScript部分
import mjCalendar from '@/components/mj-calendar/index';
export default {
components: { mjCalendar },
data() {
return {
birthdayVal: ''
}
},
onLoad() { },
methods: {
// 接收返回数据
backData(val) {
this.birthdayVal = val.birthdayVal;
},
// 打开日期选择器
openCalendar() {
this.$refs.refMjCalendar.openCalendar();
}
}
}
3、总结
1、此组件的功能逻辑基本没啥大的毛病。
2、组件初始值未通过动态设置,目前写死。
3、组件处于农历选项时根据阳历创建数据,可能滑动时有些跳动,但不影响最终的结果,也不会报错。
后续会持续完善,敬请期待!