单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
zhangchen
2025-09-09 5f67438ad9e315ca94114c7f4b6c85369c621855
src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue
@@ -1,6 +1,6 @@
<template>
  <div class="time-picker">
    <div class="picker-column" ref="hourRef" @scroll="onScroll('hour')">
    <div class="picker-column" ref="hourRef" @scroll="onScroll('hour')" :class="disabled ? 'disabled' : ''">
      <div
        v-for="(h, index) in loopHours"
        :key="index"
@@ -12,7 +12,7 @@
      </div>
    </div>
    <span class="colon">:</span>
    <div class="picker-column" ref="minuteRef" @scroll="onScroll('minute')">
    <div class="picker-column" ref="minuteRef" @scroll="onScroll('minute')" :class="disabled ? 'disabled' : ''">
      <div
        v-for="(m, index) in loopMinutes"
        :key="index"
@@ -29,7 +29,7 @@
<script setup lang="ts">
import { ref, watch, onMounted, nextTick } from "vue";
const props = defineProps<{ modelValue: string }>();
const props = defineProps<{ modelValue: string, disabled: boolean }>();
const emit = defineEmits(["update:modelValue"]);
const hours = Array.from({ length: 24 }, (_, i) => i);
@@ -46,7 +46,7 @@
const hourRef = ref<HTMLElement | null>(null);
const minuteRef = ref<HTMLElement | null>(null);
const ITEM_REM = 0.4;
const ITEM_REM = 0.26;
const itemHeight = remToPx(ITEM_REM);
const selectedIndexHour = ref(2);
@@ -89,7 +89,29 @@
  }
);
watch(
  () => props.modelValue,
  (newVal) => {
    const [h, m] = newVal.split(":").map(Number);
    const hourIdx = hours.indexOf(h);
    const minuteIdx = minutes.indexOf(m);
    if (hourIdx !== -1) {
      selectedIndexHour.value = hourIdx + 2;
      selectedHour.value = h;
      scrollToSelected("hour", selectedIndexHour.value);
    }
    if (minuteIdx !== -1) {
      selectedIndexMinute.value = minuteIdx + 2;
      selectedMinute.value = m;
      scrollToSelected("minute", selectedIndexMinute.value);
    }
  }
);
function onScroll(type: "hour" | "minute") {
  if (props.disabled) return;
  if (isProgrammaticScroll[type]) {
    // 程序滚动,忽略,避免死循环
    isProgrammaticScroll[type] = false;
@@ -162,12 +184,12 @@
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2rem; // 5 * 0.4rem 每个item高度0.4rem
  height: 1.3rem; // 5 * 0.4rem 每个item高度0.4rem
  overflow: hidden;
  .picker-column {
    height: 2rem;
    width: 0.9rem;
    height: 1.3rem;
    width: 0.7rem;
    overflow-y: scroll;
    scroll-snap-type: y mandatory;
    -webkit-overflow-scrolling: touch;
@@ -176,20 +198,22 @@
    &::-webkit-scrollbar {
      display: none; /* Chrome Safari */
    }
    &.disabled{
      overflow: hidden;
    }
    .picker-item {
      height: 0.4rem;
      line-height: 0.4rem;
      height: 0.26rem;
      line-height: 0.26rem;
      text-align: center;
      font-size: 0.24rem;
      font-size: 0.2rem;
      scroll-snap-align: center;
      user-select: none;
      cursor: pointer;
      transition: color 0.3s ease, font-size 0.3s ease;
      &.active {
        font-size: 0.5rem;
        font-size: 0.28rem;
        font-weight: 700;
        color: #111;
        &.hours {
@@ -200,26 +224,26 @@
        }
      }
      &.medium {
        font-size: 0.3rem;
        font-size: 0.22rem;
        color: #666;
        &.hours {
          text-align: left;
          padding-left: 0.2rem;
          padding-left: 0.16rem;
        }
        &.minutes {
          text-align: right;
          padding-right: 0.2rem;
          padding-right: 0.16rem;
        }
      }
      &.small {
        font-size: 0.24rem;
        font-size: 0.18rem;
        color: #aaa;
      }
    }
  }
  .colon {
    font-size: 0.5rem;
    font-size: 0.28rem;
    font-weight: 600;
    color: #444;
    user-select: none;