import React from 'react' import PYAlert from '../../Common/alert/PYAlert' import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {Picker} from '@react-native-picker/picker' import LunarSolarTransform from '../../Common/Solar&Lunar/LunarSolarTransform' import {leap_month_for_year} from '../../Common/Solar&Lunar/Define' import {isFunction, isNumber} from '../../Common/tool/TypeTool' import LunarSolarHelper from '../../Common/Solar&Lunar/LunarSolarHelper' import Lunar from '../../Common/Solar&Lunar/Lunar' import Solar from '../../Common/Solar&Lunar/Solar' type PropsType = { onSelect: (year: number, month: number, day: number, isLunar: boolean, isSecondLeapMonth: boolean) => void } type StateType = { // 年份下标 yearIdx: number // 月份下标 monthIdx: number // 日期下标 dayIdx: number // 是否为农历 isLunar: boolean } export default class BirthdaySelectDateAlert extends React.Component { state: StateType alertRef: PYAlert | null = null constructor(props: PropsType) { super(props) this.state = { yearIdx: 1970, monthIdx: 0, dayIdx: 0, isLunar: false, } } render() { return ( (this.alertRef = e)} closeOnHardwareBackPress={false} closeOnTouchOutside={false} customView={this._renderCustomView()} /> ) } _renderCustomView = () => { return ( {this._renderTitle()} {this._renderSwitchBtn()} {this._renderPickerView()} {this._renderCancelBtn()} {this._renderSureBtn()} ) } _renderTitle = () => { const title = this.state.isLunar ? '农历' : '公历' return {title} } _renderSwitchBtn = () => { return ( {'切换'} ) } _onPressSwitchBtn = () => { const isLunar = this.state.isLunar const dict = this._getDict(isLunar) const year = dict.year const month = dict.month const day = dict.day const isSecondLeapMonth = dict.isSecondLeapMonth if (isLunar) { const lunar = new Lunar(year, month, day, isSecondLeapMonth) const solar = LunarSolarTransform.lunarToSolar(lunar) const idxDict = this._getIdxDict(solar.year, solar.month, solar.day, false, false) this.setState({ yearIdx: idxDict.yearIdx, monthIdx: idxDict.monthIdx, dayIdx: idxDict.dayIdx, isLunar: false, }) } else { const solar = new Solar(year, month, day) const lunar = LunarSolarTransform.solarToLunar(solar) const idxDict = this._getIdxDict(lunar.year, lunar.month, lunar.day, true, lunar.isSecondLeapMonth) this.setState({ yearIdx: idxDict.yearIdx, monthIdx: idxDict.monthIdx, dayIdx: idxDict.dayIdx, isLunar: true, }) } } _renderPickerView = () => { const isLunar = this.state.isLunar const dict = this._getDict(isLunar) const years = this._getYearNames() const yearViews = [] for (let i = 0; i < years.length; i++) { const year = years[i] const view = this._renderItem(year, i) yearViews.push(view) } const months = this._getMonthNames(dict.year) const monthViews = [] for (let i = 0; i < months.length; i++) { const month = months[i] const view = this._renderItem(month, i) monthViews.push(view) } const days = this._getDayNames(dict.year, dict.month) const dayViews = [] for (let i = 0; i < days.length; i++) { const day = days[i] const view = this._renderItem(day, i) dayViews.push(view) } const numberOfLines = this.state.isLunar ? 2 : 1 const idxDict = this._getIdxDict(dict.year, dict.month, dict.day, isLunar, dict.isSecondLeapMonth) return ( style={styles.pickerYear} mode={'dialog'} selectedValue={idxDict.yearIdx} onValueChange={this._onYearChanged.bind(this)} itemStyle={styles.item} numberOfLines={numberOfLines}> {yearViews} style={styles.pickerMonth} mode={'dialog'} selectedValue={idxDict.monthIdx} onValueChange={this._onMonthChanged.bind(this)} itemStyle={styles.item} numberOfLines={numberOfLines}> {monthViews} style={styles.pickerDay} mode={'dialog'} selectedValue={idxDict.dayIdx} onValueChange={this._onDayChanged.bind(this)} itemStyle={styles.item} numberOfLines={numberOfLines}> {dayViews} ) } _onYearChanged = (itemValue: number, itemIndex: number) => { this.setState({ yearIdx: itemIndex, }) } _onMonthChanged = (itemValue: number, itemIndex: number) => { this.setState({ monthIdx: itemIndex, }) } _onDayChanged = (itemValue: number, itemIndex: number) => { this.setState({ dayIdx: itemIndex, }) } _renderItem = (item: string, i: number) => { return } _renderCancelBtn = () => { return ( {'取消'} ) } _onPressCancelBtn = () => { this.alertRef?.hide() } _renderSureBtn = () => { return ( {'确定'} ) } _onPressSureBtn = () => { this.alertRef?.hide() const isLunar = this.state.isLunar const dict = this._getDict(isLunar) const year = dict.year const month = dict.month const day = dict.day const isSecondLeapMonth = dict.isSecondLeapMonth isFunction(this.props.onSelect) && this.props.onSelect(year, month, day, isLunar, isSecondLeapMonth) } _getDict = (isLunar: boolean) => { const year = this.state.yearIdx + 1900 let month = this.state.monthIdx + 1 let isSecondLeapMonth = false const leapMonth = leap_month_for_year[year] if (isLunar && isNumber(leapMonth)) { if (this.state.monthIdx < leapMonth) { month = this.state.monthIdx + 1 } else if (this.state.monthIdx === leapMonth) { month = this.state.monthIdx isSecondLeapMonth = true } else { month = this.state.monthIdx } } const day = this.state.dayIdx + 1 return {year, month, day, isSecondLeapMonth} } _getIdxDict = (year: number, month: number, day: number, isLunar: boolean, isSecondLeapMonth: boolean) => { const yearIdx = year - 1900 let monthIdx = month - 1 const leapMonth = leap_month_for_year[year] if (isLunar && isNumber(leapMonth)) { if (month < leapMonth) { monthIdx = month - 1 } else if (month === leapMonth) { monthIdx = isSecondLeapMonth ? month : month - 1 } else { monthIdx = month } } const dayIdx = day - 1 return {yearIdx, monthIdx, dayIdx} } _getYearNames = (): Array => { const yearNames: Array = [] for (let i = 1900; i < 2100; i++) { if (this.state.isLunar) { const name = LunarSolarHelper.getChineseYearName(i) + '\n' + '(' + i + ')' yearNames.push(name) } else { const name = i + '年' yearNames.push(name) } } return yearNames } _getMonthNames = (year: number): Array => { const leapMonth = leap_month_for_year[year] const monthNames: Array = [] for (let i = 1; i <= 12; i++) { if (this.state.isLunar) { const name = LunarSolarHelper.getChineseMonthName(i, false) monthNames.push(name) if (i === leapMonth) { const leapName = LunarSolarHelper.getChineseMonthName(i, true) monthNames.push(leapName) } } else { const name = i + '月' monthNames.push(name) } } return monthNames } _getDayNames = (year: number, month: number): Array => { const dayNames: Array = [] const days = LunarSolarTransform.getDaysCountForLunarYear(year, month) for (let i = 1; i <= days; i++) { if (this.state.isLunar) { const name = LunarSolarHelper.getChineseDayName(i) dayNames.push(name) } else { const name = i + '日' dayNames.push(name) } } return dayNames } show = (year: number, month: number, day: number, isLunar: boolean, isSecondLeapMonth: boolean) => { const idxDict = this._getIdxDict(year, month, day, isLunar, isSecondLeapMonth) this.setState({ yearIdx: idxDict.yearIdx, monthIdx: idxDict.monthIdx, dayIdx: idxDict.dayIdx, isLunar: isLunar, }) this.alertRef?.show() } } const styles = StyleSheet.create({ container: { width: 320, height: 320, borderRadius: 15, backgroundColor: 'white', alignItems: 'center', }, title: { fontSize: 20, color: '#191919', marginTop: 16, }, switchBtn: { position: 'absolute', width: 80, height: 60, right: 0, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, switchBtnTitle: { fontSize: 15, color: 'rgb(0,115,249)', }, switchBtnImg: { width: 17, height: 17, resizeMode: 'contain', tintColor: 'rgb(0,115,249)', }, cancelBtn: { position: 'absolute', width: 90, height: 40, left: 25, bottom: 15, justifyContent: 'center', alignItems: 'center', borderColor: '#eeeeee', backgroundColor: 'white', borderWidth: 1, borderRadius: 5, }, cancelBtnTitle: { fontSize: 17, color: '#191919', }, sureBtn: { position: 'absolute', width: 90, height: 40, right: 25, bottom: 15, justifyContent: 'center', alignItems: 'center', borderRadius: 5, backgroundColor: '#FFB3DB', }, sureBtnTitle: { fontSize: 17, color: 'white', }, pickerBg: { width: 320, marginTop: 10, flexDirection: 'row', justifyContent: 'center', }, pickerYear: { width: 120, }, pickerMonth: { width: 90, }, pickerDay: { width: 100, }, item: { fontSize: 15, paddingHorizontal: 1, }, })