Sfoglia il codice sorgente

修改自定义时间

付晓文。 3 settimane fa
parent
commit
794822d715
1 ha cambiato i file con 90 aggiunte e 36 eliminazioni
  1. 90 36
      pages/merchantDish/dish/sale-time.vue

+ 90 - 36
pages/merchantDish/dish/sale-time.vue

@@ -72,12 +72,17 @@
 		<view class="pick-mask" v-if="monthPickerShow" @click="monthPickerShow = false">
 			<view class="pick-sheet" @click.stop>
 				<view class="pick-title">选择月份</view>
-				<picker-view class="pick-view" :value="monthPickerValue" @change="onMonthPickerChange">
+				<picker-view
+					class="pick-view"
+					:indicator-style="pickerIndicatorStyle"
+					:value="monthPickerValue"
+					@change="onMonthPickerChange"
+				>
 					<picker-view-column>
-						<view class="pick-item" v-for="y in yearList" :key="y">{{ y }}年</view>
+						<view class="pick-item" :style="pickerItemStyle" v-for="y in yearList" :key="y">{{ y }}年</view>
 					</picker-view-column>
 					<picker-view-column>
-						<view class="pick-item" v-for="m in 12" :key="m">{{ m }}月</view>
+						<view class="pick-item" :style="pickerItemStyle" v-for="m in 12" :key="m">{{ m }}月</view>
 					</picker-view-column>
 				</picker-view>
 				<view class="pick-confirm" @click="confirmMonthPicker">确定</view>
@@ -95,6 +100,7 @@
 					>
 						{{ formatCnDate(tempStart) || '开始日期' }}
 					</view>
+					<text class="range-sep">-</text>
 					<view
 						:class="['preview-box', rangeField === 'end' ? 'on' : '']"
 						@click="switchRangeField('end')"
@@ -102,15 +108,21 @@
 						{{ formatCnDate(tempEnd) || '结束日期' }}
 					</view>
 				</view>
-				<picker-view class="pick-view" :value="datePickerValue" @change="onDatePickerChange">
+				<picker-view
+					:key="rangePickerKey"
+					class="pick-view"
+					:indicator-style="pickerIndicatorStyle"
+					:value="datePickerValue"
+					@change="onDatePickerChange"
+				>
 					<picker-view-column>
-						<view class="pick-item" v-for="y in yearList" :key="'dy' + y">{{ y }}年</view>
+						<view class="pick-item" :style="pickerItemStyle" v-for="y in yearList" :key="'dy' + y">{{ y }}年</view>
 					</picker-view-column>
 					<picker-view-column>
-						<view class="pick-item" v-for="m in 12" :key="'dm' + m">{{ m }}月</view>
+						<view class="pick-item" :style="pickerItemStyle" v-for="m in 12" :key="'dm' + m">{{ m }}月</view>
 					</picker-view-column>
 					<picker-view-column>
-						<view class="pick-item" v-for="d in dayList" :key="'dd' + d">{{ d }}日</view>
+						<view class="pick-item" :style="pickerItemStyle" v-for="d in dayList" :key="'dd' + d">{{ d }}日</view>
 					</picker-view-column>
 				</picker-view>
 				<view class="pick-confirm" @click="confirmRangePicker">确定</view>
@@ -134,6 +146,8 @@ export default {
 		const year = now.getFullYear();
 		const yearList = [];
 		for (let y = year - 2; y <= year + 10; y++) yearList.push(y);
+		// picker-view 的 indicator-style 只认 px;与选项行高必须一致,否则会视觉错位选错
+		const itemPx = uni.upx2px(80);
 		return {
 			fromMulti: false,
 			mode: 'fixed',
@@ -149,10 +163,13 @@ export default {
 			monthPickerValue: [2, now.getMonth()],
 			rangePickerShow: false,
 			rangeField: 'start',
+			rangePickerKey: 0,
 			tempStart: '',
 			tempEnd: '',
 			datePickerValue: [2, now.getMonth(), now.getDate() - 1],
-			pickerDay: now.getDate()
+			pickerDay: now.getDate(),
+			pickerIndicatorStyle: `height: ${itemPx}px;`,
+			pickerItemStyle: `height: ${itemPx}px; line-height: ${itemPx}px;`
 		};
 	},
 	computed: {
@@ -293,19 +310,33 @@ export default {
 			const base = this.normalizeDate(
 				field === 'end' ? this.endDate || this.startDate : this.startDate || this.endDate
 			);
-			this.applyDateToPicker(base);
-			// 首次打开且对应字段为空时,用当前滚轮日期预填
 			const now = new Date();
 			const fallback = this.toYmd(now.getFullYear(), now.getMonth() + 1, now.getDate());
 			const seed = base || fallback;
 			if (field === 'start' && !this.tempStart) this.tempStart = seed;
 			if (field === 'end' && !this.tempEnd) this.tempEnd = seed;
+			this.remountRangePicker(
+				this.normalizeDate(field === 'end' ? this.tempEnd : this.tempStart) || seed
+			);
 			this.rangePickerShow = true;
 		},
 		switchRangeField(field) {
+			if (this.rangeField === field) return;
+			// 切换前先把当前滚轮值写回当前字段,避免开始/结束串值
+			this.syncPickerToField();
 			this.rangeField = field;
 			const base = this.normalizeDate(field === 'start' ? this.tempStart : this.tempEnd);
-			this.applyDateToPicker(base);
+			const now = new Date();
+			const fallback = this.toYmd(now.getFullYear(), now.getMonth() + 1, now.getDate());
+			const seed = base || fallback;
+			if (field === 'start' && !this.tempStart) this.tempStart = seed;
+			if (field === 'end' && !this.tempEnd) this.tempEnd = seed;
+			this.remountRangePicker(seed);
+		},
+		/** 强制重建 picker-view,避免日列天数变化后索引错位 */
+		remountRangePicker(ymd) {
+			this.rangePickerKey += 1;
+			this.applyDateToPicker(ymd);
 		},
 		applyDateToPicker(ymd) {
 			const now = new Date();
@@ -322,39 +353,56 @@ export default {
 			if (yi < 0) yi = 0;
 			const total = new Date(y, m, 0).getDate();
 			if (d > total) d = total;
+			if (d < 1) d = 1;
 			this.pickerDay = d;
-			this.datePickerValue = [yi, m - 1, d - 1];
+			const next = [yi, m - 1, d - 1];
+			this.datePickerValue = next;
 			this.$nextTick(() => {
-				this.datePickerValue = [yi, m - 1, d - 1];
+				this.datePickerValue = next.slice();
 			});
 		},
-		onDatePickerChange(e) {
-			const val = e.detail.value || [0, 0, 0];
-			const y = this.yearList[val[0]] || this.year;
-			const m = (val[1] || 0) + 1;
+		parsePickerValue(val) {
+			const raw = Array.isArray(val) ? val : [0, 0, 0];
+			const yi = Math.max(0, Number(raw[0]) || 0);
+			const mi = Math.max(0, Number(raw[1]) || 0);
+			const y = this.yearList[yi] || this.year;
+			const m = mi + 1;
 			const total = new Date(y, m, 0).getDate();
-			let d = (val[2] || 0) + 1;
+			let d = Math.max(0, Number(raw[2]) || 0) + 1;
 			if (d > total) d = total;
-			this.pickerDay = d;
-			this.datePickerValue = [val[0], val[1], d - 1];
+			if (d < 1) d = 1;
+			return { yi, mi, y, m, d, total };
+		},
+		syncPickerToField() {
+			const { y, m, d } = this.parsePickerValue(this.datePickerValue);
 			const ymd = this.toYmd(y, m, d);
 			if (this.rangeField === 'start') this.tempStart = ymd;
 			else this.tempEnd = ymd;
+			return ymd;
 		},
-		confirmRangePicker() {
-			// 滚轮停住后若未触发 change,用当前索引兜底写入当前字段
-			const [yi, mi, di] = this.datePickerValue;
-			const y = this.yearList[yi] || this.year;
-			const m = (mi || 0) + 1;
-			const total = new Date(y, m, 0).getDate();
-			let d = (di || 0) + 1;
-			if (d > total) d = total;
-			const ymd = this.toYmd(y, m, d);
-			if (this.rangeField === 'start') {
-				if (!this.tempStart) this.tempStart = ymd;
-			} else if (!this.tempEnd) {
-				this.tempEnd = ymd;
+		onDatePickerChange(e) {
+			const prev = this.datePickerValue || [0, 0, 0];
+			const { yi, mi, y, m, d, total } = this.parsePickerValue(e.detail.value);
+			const dayIdx = Math.min(d - 1, total - 1);
+			const next = [yi, mi, dayIdx];
+			this.pickerDay = dayIdx + 1;
+			this.datePickerValue = next;
+
+			const ymd = this.toYmd(y, m, dayIdx + 1);
+			if (this.rangeField === 'start') this.tempStart = ymd;
+			else this.tempEnd = ymd;
+
+			// 年/月变化会导致日列长度变化,需重建,否则日列视觉与索引错位
+			if (prev[0] !== yi || prev[1] !== mi) {
+				this.rangePickerKey += 1;
+				this.$nextTick(() => {
+					this.datePickerValue = next.slice();
+				});
 			}
+		},
+		confirmRangePicker() {
+			// 始终以当前滚轮为准写回当前字段,避免未触发 change 时显示与提交不一致
+			this.syncPickerToField();
 
 			if (!this.tempStart || !this.tempEnd) {
 				uni.showToast({ title: '请选择开始和结束日期', icon: 'none' });
@@ -707,11 +755,13 @@ export default {
 }
 .range-preview {
 	display: flex;
-	gap: 20rpx;
+	align-items: center;
+	gap: 16rpx;
 	margin-bottom: 12rpx;
 }
 .preview-box {
 	flex: 1;
+	min-width: 0;
 	height: 72rpx;
 	line-height: 70rpx;
 	text-align: center;
@@ -721,6 +771,10 @@ export default {
 	border: 2rpx solid #e5e5e5;
 	border-radius: 12rpx;
 	box-sizing: border-box;
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	padding: 0 8rpx;
 	&.on {
 		color: #449aff;
 		border-color: #449aff;
@@ -732,11 +786,11 @@ export default {
 	width: 100%;
 }
 .pick-item {
-	height: 80rpx;
-	line-height: 80rpx;
+	/* 具体 height/line-height 由 pickerItemStyle(px)控制,与 indicator 对齐 */
 	text-align: center;
 	font-size: 30rpx;
 	color: #333;
+	box-sizing: border-box;
 }
 .pick-confirm {
 	margin-top: 12rpx;