flat: 暂存
This commit is contained in:
290
packageA/pages/selectDate/selectDate.vue
Normal file
290
packageA/pages/selectDate/selectDate.vue
Normal file
@@ -0,0 +1,290 @@
|
||||
<template>
|
||||
<AppLayout title="选择日期" :use-scroll-view="false" back-gorund-color="#FAFAFA">
|
||||
<template #headerleft>
|
||||
<view class="btn">
|
||||
<image src="@/static/icon/back.png" @click="navBack"></image>
|
||||
</view>
|
||||
</template>
|
||||
<template #headerright>
|
||||
<view class="btn mar_ri10 button-click" @click="backParams">确认</view>
|
||||
</template>
|
||||
<view class="content">
|
||||
<view class="top-date">
|
||||
<view
|
||||
class="weekText"
|
||||
:class="{ color_256BFA: item === '日' || item === '六' }"
|
||||
v-for="(item, index) in weekMap"
|
||||
:key="index"
|
||||
>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y class="main-scroll" @scrolltolower="onScrollBottom">
|
||||
<view class="date-list" v-for="(vItem, vIndex) in calendarData" :key="vIndex">
|
||||
<view class="list-title">{{ vItem.title }}</view>
|
||||
<view class="list-item">
|
||||
<view
|
||||
class="item button-click"
|
||||
:class="{
|
||||
noOptional: !item.isThisMonth,
|
||||
active: current.date === item.date && item.isThisMonth,
|
||||
}"
|
||||
v-for="(item, index) in vItem.list"
|
||||
:key="index"
|
||||
@click="selectDay(item)"
|
||||
>
|
||||
<view class="item-top">{{ item.day }}</view>
|
||||
<view class="item-nong">{{ item.nl }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
const { $api, navTo, navBack } = inject('globalFunction');
|
||||
const weekMap = ['日', '一', '二', '三', '四', '五', '六'];
|
||||
const calendarData = ref([]);
|
||||
const current = ref({});
|
||||
import { Solar, Lunar } from '@/lib/lunar-javascript@1.7.2.js';
|
||||
|
||||
const pages = reactive({
|
||||
year: 0,
|
||||
month: 0,
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.date) {
|
||||
current.value = {
|
||||
date: options?.date || null,
|
||||
};
|
||||
}
|
||||
console.log(options);
|
||||
initPagesDate();
|
||||
addMonth();
|
||||
addMonth();
|
||||
addMonth();
|
||||
});
|
||||
|
||||
function backParams() {
|
||||
console.log(isValidDateString(current.value.date));
|
||||
if (isValidDateString(current.value.date)) {
|
||||
navBack({
|
||||
data: current.value,
|
||||
});
|
||||
} else {
|
||||
$api.msg('请选择日期');
|
||||
}
|
||||
}
|
||||
|
||||
function isValidDateString(dateStr) {
|
||||
const regex = /^\d{4}-\d{2}-\d{2}$/;
|
||||
if (!regex.test(dateStr)) return false;
|
||||
|
||||
const date = new Date(dateStr);
|
||||
if (isNaN(date.getTime())) return false;
|
||||
|
||||
// 检查日期部分是否一致(防止 "2020-02-31" 这种被 Date 自动修正)
|
||||
const [year, month, day] = dateStr.split('-').map(Number);
|
||||
return date.getFullYear() === year && date.getMonth() + 1 === month && date.getDate() === day;
|
||||
}
|
||||
|
||||
function onScrollBottom() {
|
||||
addMonth();
|
||||
}
|
||||
|
||||
function selectDay(item) {
|
||||
current.value = item;
|
||||
}
|
||||
|
||||
function initPagesDate() {
|
||||
const d = new Date();
|
||||
pages.year = d.getFullYear();
|
||||
pages.month = d.getMonth();
|
||||
}
|
||||
|
||||
function addMonth() {
|
||||
if (pages.month >= 12) {
|
||||
pages.year += 1;
|
||||
pages.month = 1;
|
||||
} else {
|
||||
pages.month += 1;
|
||||
}
|
||||
const month = getMonthCalendarData(pages);
|
||||
calendarData.value.push(month);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {Array<string>} selectedDates - 选中的日期数组 ['2025-04-21', ...]
|
||||
* @returns {Array<Object>} 六个月日历数据
|
||||
*/
|
||||
function getMonthCalendarData({ year, month, selectableDates = [] }) {
|
||||
const todayStr = new Date().toISOString().split('T')[0];
|
||||
const isSelected = (y, m, d) =>
|
||||
selectableDates.includes(`${y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`);
|
||||
|
||||
const list = [];
|
||||
|
||||
const firstDay = new Date(year, month - 1, 1);
|
||||
const firstWeekday = firstDay.getDay(); // 0 是周日
|
||||
const lastDate = new Date(year, month, 0).getDate();
|
||||
|
||||
// 补全前一月天数(上月最后几天)
|
||||
if (firstWeekday !== 0) {
|
||||
const prevLastDate = new Date(year, month - 1, 0).getDate();
|
||||
for (let i = firstWeekday - 1; i >= 0; i--) {
|
||||
const d = prevLastDate - i;
|
||||
const prevMonth = month - 1 <= 0 ? 12 : month - 1;
|
||||
const prevYear = month - 1 <= 0 ? year - 1 : year;
|
||||
const solar = Solar.fromYmd(prevYear, prevMonth, d);
|
||||
const lunar = Lunar.fromSolar(solar);
|
||||
const dateStr = `${prevYear}-${String(prevMonth).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
|
||||
list.push({
|
||||
day: d,
|
||||
nl: lunar.getDayInChinese(),
|
||||
isThisMonth: false,
|
||||
isToday: dateStr === todayStr,
|
||||
isSelectable: isSelected(prevYear, prevMonth, d),
|
||||
week: weekMap[new Date(prevYear, prevMonth - 1, d).getDay()],
|
||||
date: dateStr,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 当前月天数
|
||||
for (let d = 1; d <= lastDate; d++) {
|
||||
const solar = Solar.fromYmd(year, month, d);
|
||||
const lunar = Lunar.fromSolar(solar);
|
||||
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
|
||||
list.push({
|
||||
day: d,
|
||||
nl: lunar.getDayInChinese(),
|
||||
isThisMonth: true,
|
||||
isToday: dateStr === todayStr,
|
||||
isSelectable: isSelected(year, month, d),
|
||||
week: weekMap[new Date(year, month - 1, d).getDay()],
|
||||
date: dateStr,
|
||||
});
|
||||
}
|
||||
|
||||
// 补全下个月天数(让最后一行完整 7 个)
|
||||
const remaining = 7 - (list.length % 7);
|
||||
if (remaining < 7) {
|
||||
for (let d = 1; d <= remaining; d++) {
|
||||
const nextMonth = month + 1 > 12 ? 1 : month + 1;
|
||||
const nextYear = month + 1 > 12 ? year + 1 : year;
|
||||
const solar = Solar.fromYmd(nextYear, nextMonth, d);
|
||||
const lunar = Lunar.fromSolar(solar);
|
||||
const dateStr = `${nextYear}-${String(nextMonth).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
|
||||
list.push({
|
||||
day: d,
|
||||
nl: lunar.getDayInChinese(),
|
||||
isThisMonth: false,
|
||||
isToday: dateStr === todayStr,
|
||||
isSelectable: isSelected(nextYear, nextMonth, d),
|
||||
week: weekMap[new Date(nextYear, nextMonth - 1, d).getDay()],
|
||||
date: dateStr,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: `${year}年${month}月`,
|
||||
list,
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.btn {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
white-space: nowrap
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
image {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
height: 100%
|
||||
display: flex
|
||||
flex-direction: column
|
||||
border-radius: 40rpx 40rpx 0 0
|
||||
background: #FFFFFF;
|
||||
overflow: hidden
|
||||
margin-top: 20rpx
|
||||
.top-date{
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
padding: 28rpx
|
||||
.weekText{
|
||||
text-align: center
|
||||
width: 99rpx;
|
||||
}
|
||||
|
||||
}
|
||||
.main-scroll{
|
||||
flex: 1
|
||||
overflow: hidden
|
||||
}
|
||||
.date-list{
|
||||
.list-title{
|
||||
height: 84rpx;
|
||||
line-height: 84rpx
|
||||
background: #FAFAFA;
|
||||
font-weight: 600;
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
padding: 0 28rpx;
|
||||
box-sizing: border-box
|
||||
}
|
||||
.list-item{
|
||||
padding: 16rpx 28rpx 20rpx 28rpx;
|
||||
display: grid
|
||||
grid-template-columns: repeat(7, 1fr)
|
||||
grid-gap: 0rpx
|
||||
.item{
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
justify-content: center
|
||||
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||
padding: 16rpx 0
|
||||
margin-bottom: 20rpx
|
||||
.item-top{
|
||||
font-weight: 600;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.item-nong{
|
||||
font-size: 16rpx;
|
||||
color: #666666
|
||||
margin-top: 2rpx
|
||||
}
|
||||
}
|
||||
.optional{
|
||||
// height: 96rpx;
|
||||
border: 2rpx solid #92B5FC;
|
||||
}
|
||||
.noOptional{
|
||||
color: #B8B8B8;
|
||||
}
|
||||
.active{
|
||||
background: linear-gradient( 225deg, #9E74FD 0%, #256BFA 100%);
|
||||
color: #FFFFFF
|
||||
.item-nong{
|
||||
font-size: 16rpx;
|
||||
color: #FFFFFF
|
||||
margin-top: 2rpx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user