| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- <template>
- <div>
- <u-popup :show="modelshow" @close="close" :closeable="closeable" round="20rpx" mode="bottom">
- <view>
- <view class="popup-title">
- <view class="" style="width: 500rpx;margin: auto;">
- <u-tabs :list="contentTabslist" @click="click"
- :activeStyle="{ color: '#333', fontWeight: 'bold', fontSize: '36rpx' }"
- :itemStyle="{ height: '100rpx' }" :inactiveStyle="{ color: '#999', fontSize: '32rpx' }"
- :current="currentIndex" :scrollable="false" lineColor="#FDE935" lineWidth="60rpx"
- lineHeight="10rpx"></u-tabs>
- </view>
- </view>
- <template v-if="currentName == '选择月份'">
- <picker-view :indicator-style="indicatorStyle" :value="monthvalue" @change="monthbindChange"
- class="picker-view">
- <picker-view-column>
- <view class="item dis a-c j-c " v-for="(item, index) in years" :key="index">{{ item }}年
- </view>
- </picker-view-column>
- <picker-view-column>
- <view class="item dis a-c j-c " v-for="(item, index) in months" :key="index">{{ item }}月
- </view>
- </picker-view-column>
- </picker-view>
- </template>
- <template v-if="currentName == '自定义时间'">
- <view class="quickOptions dis f-c" v-if="quickOptionsShow">
- <view class=" dis a-c j-start">
- <view class="tab" :class="{ tabactive: OptionsTabIndex == index }"
- v-for="(item, index) in quickOptions" :key="index"
- @click="OptionsTabSelect(item, index)">
- <text>{{ item }}</text>
- </view>
- </view>
- </view>
- <view style="padding:20rpx 42rpx">
- <view class="popup-data dis j-s a-c">
- <text :class="startShow ? 'active' : ''" @click="startClick()">{{ interviewStartTime || '开始时间'
- }}</text>至
- <text :class="endShow ? 'active' : ''" @click="endClick()">{{ interviewEndTime || '结束时间'
- }}</text>
- </view>
- <picker-view :indicator-style="indicatorStyle" :value="value" @change="bindChange"
- class="picker-view">
- <picker-view-column>
- <view class="item dis a-c j-c " v-for="(item, index) in years" :key="index">{{ item }}年
- </view>
- </picker-view-column>
- <picker-view-column>
- <view class="item dis a-c j-c " v-for="(item, index) in months" :key="index">{{ item }}月
- </view>
- </picker-view-column>
- <picker-view-column>
- <view class="item dis a-c j-c " v-for="(item, index) in days" :key="index">{{ item }}日
- </view>
- </picker-view-column>
- </picker-view>
- </view>
- </template>
- </view>
- <view class="popup-footer dis j-s a-c">
- <view class="dis a-c j-c" @tap="reset">重置</view>
- <view class="dis a-c j-c" @tap="confirm">确定</view>
- </view>
- </u-popup>
- </div>
- </template>
- <script>
- export default {
- data() {
- return {
- modelshow: this.show,
- currentIndex: this.current,
- currentName: "自定义时间",
- quickOptions: ["本周", "本月", "本年"], //快捷选项
- OptionsTabIndex: null, //下标
- startShow: true,
- endShow: false,
- interviewStartTime: '', //开始时间
- interviewEndTime: '', //结束时间
- monthTime: '', //月份
- years: [],
- year: null,
- year1: null,
- months: [],
- month: null,
- month1: null,
- days: [],
- day: null,
- hours: [],
- hour: null,
- minutes: [],
- minute: null,
- value: [],
- monthvalue: [],
- indicatorStyle: `height: 50px`,
- visible: true //控制日期显示
- }
- },
- props: {
- contentTabslist: {
- type: Array,
- default: () => [{ //选项卡
- name: '选择月份'
- }, {
- name: '自定义时间'
- }]
- },
- //关闭图标
- closeable: {
- type: Boolean,
- default: true,
- },
- show: {
- type: Boolean,
- default: false
- },
- // 快捷选项显示
- quickOptionsShow: {
- type: Boolean,
- default: true
- },
- current: {
- type: Number,
- default: 1,
- }
- },
- mounted() {
- this.init();
- },
- watch: {
- show(newVal) {
- this.modelshow = newVal
- // 弹窗打开时,自动定位到已选日期
- if (newVal) {
- this.$nextTick(() => {
- const targetDate = this.startShow ? this.interviewStartTime : this.interviewEndTime;
- if (targetDate) {
- this.updatePickerPosition(targetDate);
- }
- });
- }
- },
- current(newVal) {
- this.currentIndex = newVal
- }
- },
- methods: {
- //选项卡切换
- click(item) {
- this.currentName = item.name;
- this.currentIndex = item.index;
- this.$emit('tabClick', item.name);
- },
- //快捷选择
- OptionsTabSelect(item, index) {
- switch (item) {
- case "本周":
- const WeekRange = this.getWeekRange();
- this.interviewStartTime = WeekRange.start;
- this.interviewEndTime = WeekRange.end;
- break;
- case "本月":
- const currentMonthRange = this.getCurrentMonthRange();
- this.interviewStartTime = currentMonthRange.start;
- this.interviewEndTime = currentMonthRange.end;
- break;
- case "本年":
- const currentYear = new Date().getFullYear();
- this.interviewStartTime = `${currentYear}-01-01`;
- this.interviewEndTime = `${currentYear}-12-31`;
- break;
- default:
- break;
- }
- this.OptionsTabIndex = index;
- },
- //获取本月
- getCurrentMonthRange() {
- const today = new Date();
- const firstDay = new Date(today.getFullYear(), today.getMonth(), 1); // 本月第一天
- const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0); // 本月最后一天
- // 格式化为 YYYY-MM-DD
- const formatDate = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, '0');
- const day = String(date.getDate()).padStart(2, '0');
- return `${year}-${month}-${day}`;
- };
- return {
- start: formatDate(firstDay),
- end: formatDate(lastDay)
- };
- },
- //获取本周
- getWeekRange(date = new Date()) {
- // 获取当前日期是星期几(0-6,0 是周日)
- const dayOfWeek = date.getDay();
- // 计算本周的第一天(周一)
- const startOfWeek = new Date(date);
- startOfWeek.setDate(date.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1)); // 如果周日,则减去6天
- // 计算本周的最后一天(周日)
- const endOfWeek = new Date(startOfWeek);
- endOfWeek.setDate(startOfWeek.getDate() + 6);
- // 格式化为 YYYY-MM-DD
- const formatDate = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, '0');
- const day = String(date.getDate()).padStart(2, '0');
- return `${year}-${month}-${day}`;
- };
- return {
- start: formatDate(startOfWeek),
- end: formatDate(endOfWeek)
- };
- },
- open() {
- this.$refs.popup.open()
- },
- bindChange: function(e) {
- const val = e.detail.value; //年月日当前选中下标数组
- let year = this.years[val[0]] //获取对应年份下标
- let isDay = 30,
- days = [];
- const currentMonth = parseInt(this.months[val[1]]);
- if (currentMonth == 2) {
- if ((val[0] % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
- isDay = 29;
- } else {
- isDay = 28;
- }
- } else if ([1, 3, 5, 7, 8, 10, 12].includes(currentMonth)) {
- isDay = 31;
- } else {
- isDay = 30;
- }
- for (let i = 1; i <= isDay; i++) {
- days.push(String(i).padStart(2, '0'))
- }
- this.days = days;
- this.year = this.years[val[0]]
- this.month = this.months[val[1]]
- this.day = this.days[val[2]];
- // this.monthTime = this.year + '-' + this.month;
- if (this.startShow) {
- this.interviewStartTime = this.year + '-' + this.month + '-' + this.day
- }
- if (this.endShow) {
- this.interviewEndTime = this.year + '-' + this.month + '-' + this.day
- }
- // 同步更新 value,保持 picker 位置一致
- this.value = val;
- },
- //月份滚动事件
- monthbindChange: function(e) {
- const val = e.detail.value; //年月日当前选中下标数组
- this.year1 = this.years[val[0]] //获取对应年份下标
- this.month1 = this.months[val[1]]
- this.monthTime = this.year1 + '-' + this.month1;
- },
- init() {
- const date = new Date();
- const years = []
- const year = date.getFullYear()
- const months = []
- const month = date.getMonth() + 1
- const days = []
- const day = date.getDate()
- let isDay = 30;
- if (month == 2) {
- if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
- isDay = 29;
- } else {
- isDay = 28;
- }
- } else if ([1, 3, 5, 7, 8, 10, 12].includes(month)) {
- isDay = 31;
- } else {
- isDay = 30;
- }
- for (let i = date.getFullYear(); i >= 1900; i--) {
- years.push(i)
- }
- for (let i = 1; i <= 12; i++) {
- months.push(String(i).padStart(2, '0'))
- }
- for (let i = 1; i <= isDay; i++) {
- days.push(String(i).padStart(2, '0'))
- }
- this.years = years
- this.year = year
- this.year1 = year
- this.months = months
- this.month = String(month).padStart(2, '0')
- this.month1 = String(month).padStart(2, '0')
- this.days = days
- this.day = String(day).padStart(2, '0')
- this.value = [0, month - 1, day - 1]
- this.monthvalue = [0, month - 1]
- this.interviewStartTime = this.year + '-' + this.month + '-' + this.day
- this.interviewEndTime = this.year + '-' + this.month + '-' + this.day
- this.monthTime = this.year1 + '-' + this.month1;
- },
- close() {
- this.$emit('close');
- },
- reset() {
- this.interviewStartTime = ''
- this.interviewEndTime = ''
- this.startShow = false
- this.endShow = false
- },
- startClick() {
- this.startShow = true
- this.endShow = false
- // 已有已选日期时,滚动到该日期;否则用当前 picker 位置
- if (this.interviewStartTime) {
- this.updatePickerPosition(this.interviewStartTime);
- } else {
- this.interviewStartTime = this.year + '-' + this.month + '-' + this.day;
- }
- },
- endClick() {
- this.startShow = false
- this.endShow = true
- // 已有已选日期时,滚动到该日期;否则用当前 picker 位置
- if (this.interviewEndTime) {
- this.updatePickerPosition(this.interviewEndTime);
- } else {
- this.interviewEndTime = this.year + '-' + this.month + '-' + this.day;
- }
- },
- // 根据日期字符串更新 picker 滚动位置
- updatePickerPosition(dateStr) {
- if (!dateStr) return;
- const [yearStr, monthStr, dayStr] = dateStr.split('-');
- const targetYear = parseInt(yearStr);
- const targetMonth = parseInt(monthStr);
- const targetDay = parseInt(dayStr);
- // 查找年份和月份对应的下标 (this.years 是倒序,所以需要计算下标)
- const yearIndex = this.years.findIndex(y => y === targetYear);
- const monthIndex = targetMonth - 1; // months 数组是 1-12,下标 0-11
- // 根据年月重新生成天数数组
- let isDay = 30;
- if (targetMonth === 2) {
- if ((targetYear % 4 === 0 && targetYear % 100 !== 0) || (targetYear % 400 === 0)) {
- isDay = 29;
- } else {
- isDay = 28;
- }
- } else if ([1, 3, 5, 7, 8, 10, 12].includes(targetMonth)) {
- isDay = 31;
- } else {
- isDay = 30;
- }
- const days = [];
- for (let i = 1; i <= isDay; i++) {
- days.push(String(i).padStart(2, '0'));
- }
- this.days = days;
- const dayIndex = targetDay - 1;
- // 更新 picker 位置
- this.value = [yearIndex, monthIndex, dayIndex];
- this.year = targetYear;
- this.month = String(targetMonth).padStart(2, '0');
- this.day = String(targetDay).padStart(2, '0');
- },
- confirm() {
- if (this.currentName == "自定义时间") {
- this.$emit('customTime', this.interviewStartTime, this.interviewEndTime);
- } else {
- this.$emit('customMonth', this.monthTime);
- }
- },
- },
- }
- </script>
- <style lang="scss" scoped>
- .popup {
- border-radius: 10px 10px 0 0 !important;
- }
- .popup-title {
- border-bottom: 1rpx solid #EEEEEE;
- margin-bottom: 40rpx;
- text:first-child {
- font-weight: 600;
- }
- text:last-child {
- position: absolute;
- right: 10px;
- font-size: 21px;
- color: #999999;
- line-height: 23px;
- }
- }
- .quickOptions {
- padding: 0 42rpx;
- box-sizing: border-box;
- margin-bottom: 20rpx;
- .tab {
- padding: 9rpx 24rpx;
- box-sizing: border-box;
- font-size: 30rpx;
- color: #666;
- border-radius: 4rpx 4rpx 4rpx 4rpx;
- border: 1rpx solid #EEEEEE;
- margin-right: 30rpx;
- }
- .tabactive {
- background: #FDE935;
- color: #333;
- border: 1rpx solid #FDE935;
- }
- }
- .popup-footer {
- padding: 20rpx 45rpx;
- box-sizing: border-box;
- view {
- font-size: 30rpx;
- padding: 20rpx;
- flex: 1;
- }
- view:first-child {
- color: #333;
- background: transparent;
- border-radius: 50rpx;
- border: 1rpx solid #FDE935;
- margin-right: 28rpx;
- }
- view:last-child {
- background: #FDE935;
- border-radius: 50rpx;
- color: #1F1F1F;
- }
- }
- .popup-data {
- text {
- font-size: 14px;
- color: #999999;
- display: inline-block;
- width: 44%;
- text-align: center;
- border: 1px solid #DDDDDD;
- border-radius: 4rpx;
- font-size: 30rpx;
- padding: 7rpx;
- box-sizing: border-box;
- }
- .active {
- border: 1px solid #FDE935;
- color: #333;
- }
- }
- .picker-view {
- width: 100%;
- height: 400rpx;
- .item {
- font-size: 28rpx;
- color: #333;
- }
- }
- </style>
|