|
@@ -269,63 +269,63 @@
|
|
|
'请选择' + (chargeTime.isPowerSaving ? '省电模式' : '') + '充电时间'
|
|
'请选择' + (chargeTime.isPowerSaving ? '省电模式' : '') + '充电时间'
|
|
|
"
|
|
"
|
|
|
>
|
|
>
|
|
|
- <view class="flex" style="border-top: 1rpx solid var(--divider)">
|
|
|
|
|
- <view
|
|
|
|
|
- class="flex-shrink"
|
|
|
|
|
- style="height: 840rpx; width: 256rpx; background-color: var(--color-sec)"
|
|
|
|
|
- >
|
|
|
|
|
- <view
|
|
|
|
|
- class="flex-align-center pl-32 height-90"
|
|
|
|
|
- v-for="(day, index) in timesInfo.day"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- :style="{
|
|
|
|
|
- backgroundColor:
|
|
|
|
|
- day.format === chargeTime.day ? '#fff' : 'transparent',
|
|
|
|
|
- }"
|
|
|
|
|
- @click="changeDay(index)"
|
|
|
|
|
- >
|
|
|
|
|
- <view
|
|
|
|
|
- :class="[
|
|
|
|
|
- 'fs-32',
|
|
|
|
|
- 'fw-500',
|
|
|
|
|
- day.format === chargeTime.day ? 'color-primary' : 'color-000',
|
|
|
|
|
- ]"
|
|
|
|
|
- >{{ day.format }}
|
|
|
|
|
- </view
|
|
|
|
|
- >
|
|
|
|
|
- <view
|
|
|
|
|
- class="fs-24 color-666 ml-12 br-8 width-60 height-40 flex-center"
|
|
|
|
|
- style="background-color: rgba(28, 43, 41, 0.06)"
|
|
|
|
|
- v-if="day.year && day.format !== chargeTime.day"
|
|
|
|
|
- >{{ day.year }}年
|
|
|
|
|
- </view
|
|
|
|
|
- >
|
|
|
|
|
- </view>
|
|
|
|
|
|
|
+ <view class="time-picker">
|
|
|
|
|
+ <!-- 智能推荐快捷项 -->
|
|
|
|
|
+ <view class="tp-quick">
|
|
|
|
|
+ <view class="fs-24 color-999 mb-16">智能推荐(24小时内)</view>
|
|
|
|
|
+ <scroll-view scroll-x class="tp-quick_scroll">
|
|
|
|
|
+ <view class="tp-quick_list">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(q, i) in quickOptions"
|
|
|
|
|
+ :key="i"
|
|
|
|
|
+ class="tp-chip pressable"
|
|
|
|
|
+ hover-class="pressed"
|
|
|
|
|
+ hover-stay-time="80"
|
|
|
|
|
+ :class="{ 'tp-chip_active': selectedTs === q.ts }"
|
|
|
|
|
+ @click="pickOption(q)"
|
|
|
|
|
+ >{{ q.label }}</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </scroll-view>
|
|
|
</view>
|
|
</view>
|
|
|
- <scroll-view
|
|
|
|
|
- scroll-y
|
|
|
|
|
- class="flex-grow"
|
|
|
|
|
- style="height: 840rpx"
|
|
|
|
|
- :scroll-into-view="chargeTime.scrollId"
|
|
|
|
|
- >
|
|
|
|
|
- <view
|
|
|
|
|
- :id="`hour-${hour.format}`"
|
|
|
|
|
- class="flex-align-center pl-40 height-90 fs-32"
|
|
|
|
|
- v-for="(hour, index) in timesInfo.hour"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- :style="{
|
|
|
|
|
- color: hour.disabled
|
|
|
|
|
- ? '#999'
|
|
|
|
|
- : hour.format === chargeTime.hour
|
|
|
|
|
- ? 'var(--color-primary)'
|
|
|
|
|
- : '#000',
|
|
|
|
|
- }"
|
|
|
|
|
- @click="changeHour(index)"
|
|
|
|
|
- >
|
|
|
|
|
- {{ hour.format }}
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="hour-placeholder"></view>
|
|
|
|
|
|
|
+ <!-- 时段网格(30分钟粒度) -->
|
|
|
|
|
+ <scroll-view scroll-y class="tp-grid_scroll">
|
|
|
|
|
+ <block v-for="(group, gi) in timeGroups" :key="gi">
|
|
|
|
|
+ <view class="tp-group_title fs-26 color-999">{{ group.title }}</view>
|
|
|
|
|
+ <view class="tp-grid">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="opt in group.options"
|
|
|
|
|
+ :key="opt.ts"
|
|
|
|
|
+ class="tp-cell pressable"
|
|
|
|
|
+ hover-class="pressed"
|
|
|
|
|
+ hover-stay-time="80"
|
|
|
|
|
+ :class="{
|
|
|
|
|
+ 'tp-cell_active': selectedTs === opt.ts,
|
|
|
|
|
+ 'tp-cell_disabled': opt.disabled,
|
|
|
|
|
+ }"
|
|
|
|
|
+ @click="pickOption(opt)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="fs-28">{{ opt.timeLabel }}</view>
|
|
|
|
|
+ <view class="fs-20 tp-cell_price" v-if="opt.price">{{ opt.price }}元/度</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </block>
|
|
|
|
|
+ <view style="height: 24rpx"></view>
|
|
|
</scroll-view>
|
|
</scroll-view>
|
|
|
|
|
+ <!-- 底部确认 -->
|
|
|
|
|
+ <view class="tp-footer">
|
|
|
|
|
+ <view class="flex-column flex-grow" v-if="selected">
|
|
|
|
|
+ <view class="fs-30 fw-600 color-000">{{ selected.fullLabel }}</view>
|
|
|
|
|
+ <view class="fs-22 color-999 mt-4" v-if="selected.price"
|
|
|
|
|
+ >该时段电价 {{ selected.price }}元/度
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="fs-26 color-999 flex-grow" v-else>请选择充电开始时间</view>
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="tp-confirm flex-center fs-28 fw-500"
|
|
|
|
|
+ :class="{ 'tp-confirm_disabled': !selected }"
|
|
|
|
|
+ @click="confirmTime"
|
|
|
|
|
+ >确定</view>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
</style-dialog>
|
|
</style-dialog>
|
|
|
<PriceDesc
|
|
<PriceDesc
|
|
@@ -369,10 +369,6 @@ const station = ref<any>();
|
|
|
const stationId = ref<any>();
|
|
const stationId = ref<any>();
|
|
|
const priceInfo = ref();
|
|
const priceInfo = ref();
|
|
|
const priceDescVisible = ref(false);
|
|
const priceDescVisible = ref(false);
|
|
|
-const timesInfo = ref<any>({
|
|
|
|
|
- day: [],
|
|
|
|
|
- time: [],
|
|
|
|
|
-});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const checkedUserRightsOrCoupon = ref<any>({
|
|
const checkedUserRightsOrCoupon = ref<any>({
|
|
@@ -405,7 +401,6 @@ const chargeTime = ref({
|
|
|
hour: "",
|
|
hour: "",
|
|
|
format: "",
|
|
format: "",
|
|
|
formatPrice: "",
|
|
formatPrice: "",
|
|
|
- scrollId: "",
|
|
|
|
|
isPowerSaving: false, // 省电模式
|
|
isPowerSaving: false, // 省电模式
|
|
|
});
|
|
});
|
|
|
const appointmentData = ref();
|
|
const appointmentData = ref();
|
|
@@ -446,12 +441,6 @@ const changeType = (index: number) => {
|
|
|
chargeType.value = index;
|
|
chargeType.value = index;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const isPassTime = (hour: string, day: number) => {
|
|
|
|
|
- const now = new Date();
|
|
|
|
|
- const time = new Date(format("y/M/d", day) + " " + hour + ":00");
|
|
|
|
|
- return now > time;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
const getHourPrice = (hour: string) => {
|
|
const getHourPrice = (hour: string) => {
|
|
|
let price = "";
|
|
let price = "";
|
|
|
priceInfo.value.policyInfos.forEach((item: any) => {
|
|
priceInfo.value.policyInfos.forEach((item: any) => {
|
|
@@ -462,37 +451,114 @@ const getHourPrice = (hour: string) => {
|
|
|
return price;
|
|
return price;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const rebuildHours = (day: Date) => {
|
|
|
|
|
- timesInfo.value.hour = [];
|
|
|
|
|
- const nowHour = format("h");
|
|
|
|
|
- const isToday = format("d") === format("d", day.getTime());
|
|
|
|
|
- // 当前时间的24小时内
|
|
|
|
|
- let startHour = isToday ? Number(nowHour) : 0;
|
|
|
|
|
- let endHour = isToday ? 24 : Number(nowHour) + 1;
|
|
|
|
|
- if (chargeTime.value.isPowerSaving) {
|
|
|
|
|
- startHour = 0;
|
|
|
|
|
- endHour = 8;
|
|
|
|
|
- }
|
|
|
|
|
- for (let index = startHour; index < endHour; index++) {
|
|
|
|
|
- timesInfo.value.hour = [...timesInfo.value.hour, ...buildHours(index, day)];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/* ============ 时间选择(智能推荐 + 24小时内,30分钟粒度) ============ */
|
|
|
|
|
+const STEP = 30 * 60 * 1000; // 30分钟粒度
|
|
|
|
|
+const WINDOW = 24 * 60 * 60 * 1000; // 只能选择从此时开始24小时内
|
|
|
|
|
+const QUICK_OFFSETS = [30 * 60 * 1000, 60 * 60 * 1000, 2 * 60 * 60 * 1000]; // 尽快/1小时/2小时
|
|
|
|
|
+
|
|
|
|
|
+const timesInfo = ref<any>({
|
|
|
|
|
+ groups: [] as any[],
|
|
|
|
|
+ flat: {} as Record<number, any>,
|
|
|
|
|
+});
|
|
|
|
|
+const selectedTs = ref(0);
|
|
|
|
|
+
|
|
|
|
|
+const pad2 = (n: number) => (n < 10 ? `0${n}` : `${n}`);
|
|
|
|
|
+
|
|
|
|
|
+/** 把时间对齐到下一个5分钟(智能推荐用) */
|
|
|
|
|
+const ceil5 = (ts: number) => Math.ceil(ts / (5 * 60 * 1000)) * 5 * 60 * 1000;
|
|
|
|
|
+
|
|
|
|
|
+const buildOption = (ts: number, now: number): any => {
|
|
|
|
|
+ const d = new Date(ts);
|
|
|
|
|
+ const hourStr = `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
|
|
|
|
|
+ return {
|
|
|
|
|
+ ts,
|
|
|
|
|
+ timeLabel: hourStr,
|
|
|
|
|
+ price: getHourPrice(`${pad2(d.getHours())}`),
|
|
|
|
|
+ disabled: ts <= now,
|
|
|
|
|
+ get fullLabel() {
|
|
|
|
|
+ const dayDiff = Math.floor(
|
|
|
|
|
+ (new Date(ts).setHours(0, 0, 0, 0) - new Date(now).setHours(0, 0, 0, 0)) / DAY
|
|
|
|
|
+ );
|
|
|
|
|
+ const dayText = dayDiff <= 0 ? "今天" : dayDiff === 1 ? "明天" : "";
|
|
|
|
|
+ return `${dayText} ${format("M月d日", ts)} ${hourStr}`;
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const buildHours = (hour: number, day: Date) => {
|
|
|
|
|
- let res: any[] = [];
|
|
|
|
|
- let hourTemp = hour >= 10 ? `${hour}` : `0${hour}`;
|
|
|
|
|
- let priceTemp = getHourPrice(hourTemp);
|
|
|
|
|
- for (let index = 0; index < 12; index++) {
|
|
|
|
|
- res.push({
|
|
|
|
|
- format: `${hourTemp}:${index * 5 >= 10 ? index * 5 : `0${index * 5}`}`,
|
|
|
|
|
- formatPrice: priceTemp,
|
|
|
|
|
- disabled: isPassTime(
|
|
|
|
|
- `${hourTemp}:${index * 5 >= 10 ? index * 5 : `0${index * 5}`}`,
|
|
|
|
|
- chargeTime.value.time ? chargeTime.value.time : day.getTime()
|
|
|
|
|
- ),
|
|
|
|
|
|
|
+/** 生成24小时内的可选项:今天/明天两组,30分钟粒度 */
|
|
|
|
|
+const buildTimeOptions = () => {
|
|
|
|
|
+ const now = Date.now();
|
|
|
|
|
+ // 网格首个时间:10分钟后取整到下一个半点
|
|
|
|
|
+ let first = Math.ceil((now + 10 * 60 * 1000) / STEP) * STEP;
|
|
|
|
|
+ const last = now + WINDOW; // 窗口上限
|
|
|
|
|
+ const groups: any[] = [];
|
|
|
|
|
+ const flat: Record<number, any> = {};
|
|
|
|
|
+
|
|
|
|
|
+ // 按天分组
|
|
|
|
|
+ const firstDay = new Date(first).setHours(0, 0, 0, 0);
|
|
|
|
|
+ for (let dayStart = firstDay; dayStart <= last; dayStart += DAY) {
|
|
|
|
|
+ const dayEnd = dayStart + DAY;
|
|
|
|
|
+ const dayFirst = Math.max(first, dayStart);
|
|
|
|
|
+ const dayLast = Math.min(last, dayEnd - 1);
|
|
|
|
|
+ const options: any[] = [];
|
|
|
|
|
+ for (let ts = dayFirst; ts <= dayLast; ts += STEP) {
|
|
|
|
|
+ // 对齐到半点(dayFirst 来自 first 已对齐,跨天起点为 00:00 天然对齐)
|
|
|
|
|
+ const d = new Date(ts);
|
|
|
|
|
+ if (d.getMinutes() !== 0 && d.getMinutes() !== 30) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ const opt = buildOption(ts, now);
|
|
|
|
|
+ options.push(opt);
|
|
|
|
|
+ flat[opt.ts] = opt;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!options.length) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ const dayDiff = Math.round((dayStart - new Date(now).setHours(0, 0, 0, 0)) / DAY);
|
|
|
|
|
+ groups.push({
|
|
|
|
|
+ title: dayDiff <= 0 ? `今天 ${format("M月d日", dayStart)}` : `明天 ${format("M月d日", dayStart)}`,
|
|
|
|
|
+ options,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
+ timesInfo.value = { groups, flat };
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 智能推荐:尽快开始 / 1小时后 / 2小时后 / 00:00 低谷(5分钟粒度,独立于网格) */
|
|
|
|
|
+const quickOptions = computed(() => {
|
|
|
|
|
+ const res: any[] = [];
|
|
|
|
|
+ const now = Date.now();
|
|
|
|
|
+ const labels = ["尽快", "1小时后", "2小时后"];
|
|
|
|
|
+ QUICK_OFFSETS.forEach((offset, i) => {
|
|
|
|
|
+ const ts = ceil5(now + offset);
|
|
|
|
|
+ if (ts <= now + WINDOW) {
|
|
|
|
|
+ const opt = buildOption(ts, now);
|
|
|
|
|
+ res.push({ ...opt, label: `${labels[i]} ${opt.timeLabel}` });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // 下一低谷 00:00
|
|
|
|
|
+ const tomorrowZero = new Date().setHours(24, 0, 0, 0);
|
|
|
|
|
+ if (tomorrowZero <= now + WINDOW) {
|
|
|
|
|
+ const opt = buildOption(tomorrowZero, now);
|
|
|
|
|
+ res.push({ ...opt, label: "00:00 低谷充电" });
|
|
|
|
|
+ }
|
|
|
return res;
|
|
return res;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const selected = computed(
|
|
|
|
|
+ () =>
|
|
|
|
|
+ timesInfo.value.flat[selectedTs.value] ||
|
|
|
|
|
+ quickOptions.value.find((q: any) => q.ts === selectedTs.value)
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+const pickOption = (opt: any) => {
|
|
|
|
|
+ if (opt.disabled) {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: "无法选择过去的时间",
|
|
|
|
|
+ icon: "none",
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ selectedTs.value = opt.ts;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const selectTime = () => {
|
|
const selectTime = () => {
|
|
@@ -510,84 +576,36 @@ const selectTime = () => {
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- const now = appointmentData.value
|
|
|
|
|
- ? new Date(appointmentData.value.startTime.replace(/-/g, "/"))
|
|
|
|
|
- : new Date();
|
|
|
|
|
- const year = format("y", now.getTime());
|
|
|
|
|
- const nextyear = format("y", now.getTime() + DAY);
|
|
|
|
|
-
|
|
|
|
|
- // 天
|
|
|
|
|
- timesInfo.value.day = [
|
|
|
|
|
- {
|
|
|
|
|
- time: now.getTime(),
|
|
|
|
|
- format: format("M月d日", now.getTime()),
|
|
|
|
|
- year: "",
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- time: now.getTime() + DAY,
|
|
|
|
|
- format: format("M月d日", now.getTime() + DAY),
|
|
|
|
|
- year: year === nextyear ? "" : nextyear.slice(2),
|
|
|
|
|
- },
|
|
|
|
|
- ];
|
|
|
|
|
- rebuildHours(now);
|
|
|
|
|
-
|
|
|
|
|
- // 预约时间
|
|
|
|
|
- if (!appointmentData.value) {
|
|
|
|
|
- if (!chargeTime.value.day) {
|
|
|
|
|
- chargeTime.value.time = timesInfo.value.day[0].time;
|
|
|
|
|
- chargeTime.value.day = timesInfo.value.day[0].format;
|
|
|
|
|
- }
|
|
|
|
|
- // 滚动到特定位置
|
|
|
|
|
- if (chargeTime.value.hour) {
|
|
|
|
|
- chargeTime.value.scrollId = `hour-${chargeTime.value.hour}`;
|
|
|
|
|
- } else {
|
|
|
|
|
- let hourNow = now.getHours();
|
|
|
|
|
- chargeTime.value.scrollId = `hour-${hourNow}:00`;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // 修改时间
|
|
|
|
|
|
|
+ buildTimeOptions();
|
|
|
|
|
+ // 智能默认:已预约则定位当前预约时间,否则默认选中"尽快开始"
|
|
|
if (appointmentData.value) {
|
|
if (appointmentData.value) {
|
|
|
- chargeTime.value.time = timesInfo.value.day[0].time;
|
|
|
|
|
- chargeTime.value.day = timesInfo.value.day[0].format;
|
|
|
|
|
- const findIndex = timesInfo.value.hour.findIndex(
|
|
|
|
|
- (item: any) => item.format === format("h:m:s", now.getTime())
|
|
|
|
|
- );
|
|
|
|
|
- if (findIndex >= 0) {
|
|
|
|
|
- chargeTime.value.hour = timesInfo.value.hour[findIndex].format;
|
|
|
|
|
- chargeTime.value.formatPrice =
|
|
|
|
|
- timesInfo.value.hour[findIndex].formatPrice;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const start = new Date(
|
|
|
|
|
+ appointmentData.value.startTime.replace(/-/g, "/")
|
|
|
|
|
+ ).getTime();
|
|
|
|
|
+ const aligned = Math.ceil(start / STEP) * STEP;
|
|
|
|
|
+ selectedTs.value = timesInfo.value.flat[aligned]
|
|
|
|
|
+ ? aligned
|
|
|
|
|
+ : quickOptions.value[0]?.ts || 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ selectedTs.value = quickOptions.value[0]?.ts || 0;
|
|
|
}
|
|
}
|
|
|
chargeTimeDialog.value = true;
|
|
chargeTimeDialog.value = true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const changeDay = (index: number) => {
|
|
|
|
|
- chargeTime.value.time = timesInfo.value.day[index].time;
|
|
|
|
|
- chargeTime.value.day = timesInfo.value.day[index].format;
|
|
|
|
|
- if (chargeTime.value.hour) {
|
|
|
|
|
- chargeTime.value.hour = "";
|
|
|
|
|
- chargeTime.value.formatPrice = "";
|
|
|
|
|
- }
|
|
|
|
|
- const now = new Date(chargeTime.value.time);
|
|
|
|
|
- rebuildHours(now);
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- chargeTime.value.scrollId = `hour-${timesInfo.value.hour[0].format}`;
|
|
|
|
|
- }, 0);
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const changeHour = (index: number) => {
|
|
|
|
|
- if (timesInfo.value.hour[index].disabled) {
|
|
|
|
|
|
|
+const confirmTime = () => {
|
|
|
|
|
+ const opt = selected.value;
|
|
|
|
|
+ if (!opt) {
|
|
|
uni.showToast({
|
|
uni.showToast({
|
|
|
- title: "无法选择过去的时间",
|
|
|
|
|
|
|
+ title: "请选择充电时间",
|
|
|
icon: "none",
|
|
icon: "none",
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (appointmentData.value) {
|
|
if (appointmentData.value) {
|
|
|
- // 修改时间
|
|
|
|
|
|
|
+ // 修改已预约时间
|
|
|
uni.showModal({
|
|
uni.showModal({
|
|
|
title: "温馨提示",
|
|
title: "温馨提示",
|
|
|
- content: `确认修改为${timesInfo.value.hour[index].format}吗?`,
|
|
|
|
|
|
|
+ content: `确认修改为${opt.fullLabel}吗?`,
|
|
|
confirmText: "确定",
|
|
confirmText: "确定",
|
|
|
confirmColor: "#2d9e95",
|
|
confirmColor: "#2d9e95",
|
|
|
success(modal) {
|
|
success(modal) {
|
|
@@ -598,9 +616,7 @@ const changeHour = (index: number) => {
|
|
|
});
|
|
});
|
|
|
changeAppointmentTime(
|
|
changeAppointmentTime(
|
|
|
appointmentData.value.startChargeSeq,
|
|
appointmentData.value.startChargeSeq,
|
|
|
- `${format("y-M-d", chargeTime.value.time)} ${
|
|
|
|
|
- timesInfo.value.hour[index].format
|
|
|
|
|
- }:00`
|
|
|
|
|
|
|
+ `${format("y-M-d", opt.ts)} ${opt.timeLabel}:00`
|
|
|
)
|
|
)
|
|
|
.then(() => {
|
|
.then(() => {
|
|
|
return fetchChargeStatus();
|
|
return fetchChargeStatus();
|
|
@@ -622,11 +638,11 @@ const changeHour = (index: number) => {
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- chargeTime.value.hour = timesInfo.value.hour[index].format;
|
|
|
|
|
- chargeTime.value.format = `${format("y年M月d日", chargeTime.value.time)} ${
|
|
|
|
|
- chargeTime.value.hour
|
|
|
|
|
- }`;
|
|
|
|
|
- chargeTime.value.formatPrice = timesInfo.value.hour[index].formatPrice;
|
|
|
|
|
|
|
+ chargeTime.value.time = opt.ts;
|
|
|
|
|
+ chargeTime.value.day = format("M月d日", opt.ts);
|
|
|
|
|
+ chargeTime.value.hour = opt.timeLabel;
|
|
|
|
|
+ chargeTime.value.format = `${format("y年M月d日", opt.ts)} ${opt.timeLabel}`;
|
|
|
|
|
+ chargeTime.value.formatPrice = opt.price;
|
|
|
closeTime();
|
|
closeTime();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -638,7 +654,6 @@ const changePowerSaving = (e: any) => {
|
|
|
isPowerSaving: e.detail.value,
|
|
isPowerSaving: e.detail.value,
|
|
|
format: "",
|
|
format: "",
|
|
|
formatPrice: "",
|
|
formatPrice: "",
|
|
|
- scrollId: "",
|
|
|
|
|
};
|
|
};
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -655,7 +670,6 @@ const closeTime = () => {
|
|
|
isPowerSaving: chargeTime.value.isPowerSaving, // 省电模式
|
|
isPowerSaving: chargeTime.value.isPowerSaving, // 省电模式
|
|
|
format: "",
|
|
format: "",
|
|
|
formatPrice: "",
|
|
formatPrice: "",
|
|
|
- scrollId: "",
|
|
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
@@ -1018,9 +1032,128 @@ onShow(() => {
|
|
|
border-bottom: 1rpx solid var(--divider);
|
|
border-bottom: 1rpx solid var(--divider);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.hour-placeholder {
|
|
|
|
|
- box-sizing: content-box;
|
|
|
|
|
- padding-bottom: constant(safe-area-inset-bottom);
|
|
|
|
|
- padding-bottom: env(safe-area-inset-bottom);
|
|
|
|
|
|
|
+/* ============ 时间选择器 ============ */
|
|
|
|
|
+.time-picker {
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-quick {
|
|
|
|
|
+ padding: 24rpx 30rpx 8rpx;
|
|
|
|
|
+ border-bottom: 1rpx solid var(--divider);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-quick_scroll {
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-quick_list {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ padding-bottom: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-chip {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 64rpx;
|
|
|
|
|
+ padding: 0 28rpx;
|
|
|
|
|
+ margin-right: 16rpx;
|
|
|
|
|
+ background: var(--color-sec);
|
|
|
|
|
+ border-radius: 32rpx;
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #5c6b69;
|
|
|
|
|
+ transition: background-color 0.15s cubic-bezier(0.22, 1, 0.36, 1),
|
|
|
|
|
+ color 0.15s cubic-bezier(0.22, 1, 0.36, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-chip_active {
|
|
|
|
|
+ background: var(--color-primary);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-grid_scroll {
|
|
|
|
|
+ height: 560rpx;
|
|
|
|
|
+ padding: 8rpx 30rpx 0;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-group_title {
|
|
|
|
|
+ padding: 24rpx 0 16rpx;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(4, 1fr);
|
|
|
|
|
+ gap: 12rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-cell {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 96rpx;
|
|
|
|
|
+ background: var(--color-sec);
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ color: #1c2b29;
|
|
|
|
|
+ transition: background-color 0.15s cubic-bezier(0.22, 1, 0.36, 1),
|
|
|
|
|
+ color 0.15s cubic-bezier(0.22, 1, 0.36, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-cell_price {
|
|
|
|
|
+ margin-top: 2rpx;
|
|
|
|
|
+ color: #8c9997;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-cell_active {
|
|
|
|
|
+ background: var(--color-primary-tint-strong);
|
|
|
|
|
+ color: var(--color-primary);
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+
|
|
|
|
|
+ .tp-cell_price {
|
|
|
|
|
+ color: var(--color-primary);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-cell_disabled {
|
|
|
|
|
+ color: #c4cfcd;
|
|
|
|
|
+ background: rgba(28, 43, 41, 0.03);
|
|
|
|
|
+
|
|
|
|
|
+ .tp-cell_price {
|
|
|
|
|
+ color: #d5dedc;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-footer {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
|
|
+ padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|
|
|
|
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
|
|
|
+ border-top: 1rpx solid var(--divider);
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-confirm {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ width: 200rpx;
|
|
|
|
|
+ height: 80rpx;
|
|
|
|
|
+ margin-left: 24rpx;
|
|
|
|
|
+ background: var(--color-primary);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ border-radius: 40rpx;
|
|
|
|
|
+ transition: background-color 0.15s cubic-bezier(0.22, 1, 0.36, 1),
|
|
|
|
|
+ opacity 0.15s cubic-bezier(0.22, 1, 0.36, 1);
|
|
|
|
|
+
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ background: var(--color-primary-deep);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tp-confirm_disabled {
|
|
|
|
|
+ opacity: 0.45;
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|