uniapp+ts模仿popup弹出框(下拉框)

[复制链接]
发表于 2025-7-8 14:55:13 | 显示全部楼层 |阅读模式
效果图(未展开的样子):

效果图(展开的样子):

子组件代码
  1. <!--
  2. * @Date: 2024-04-26 14:30:00
  3. * @LastEditTime: 2025-05-29 09:01:06
  4. * @Description: 技术服务
  5. -->
  6. <template>
  7.     <view class="reg-info">
  8.         <view class="item-class">
  9.             <view class="title-region flex-center-start" @click="arrowClick()">
  10.                 <view class="title">{{ currentDate }}</view>
  11.                 <view class="arrow-region">
  12.                     <view class="iconfont icon-arrow-chevron-down1" />
  13.                 </view>
  14.             </view>
  15.             <view class="content-region" :style="{ height: showSelect ? `${dateContBgHeight}vh` : '0' }">
  16.                 <view class="content-region-cont" :style="{ height: showSelect ? `${dateContHeight}rpx` : '0' }">
  17.                     <view class="content-item-box">
  18.                         <view
  19.                             v-for="(item, index) in dateList"
  20.                             :key="index"
  21.                             class="content-item flex-column-center"
  22.                             :class="{ selected: item.date === currentDate }"
  23.                             @click="selectDate(item)"
  24.                         >
  25.                             <view class="server-order-week">
  26.                                 {{ item.week }}
  27.                             </view>
  28.                             <view class="server-order-date">
  29.                                 {{ item.date }}
  30.                             </view>
  31.                             <view class="server-order-num"> (12) </view>
  32.                         </view>
  33.                     </view>
  34.                 </view>
  35.             </view>
  36.         </view>
  37.     </view>
  38. </template>
  39. <script setup lang="ts">
  40. import { ref } from 'vue';
  41. import { formatDateAsMD } from '@/utils/DateUtils';
  42. // 星期映射表
  43. const WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  44. const currentDate = ref(formatDateAsMD(new Date())); // 默认今日日期
  45. const showSelect = ref(true); //下拉框
  46. const dateContBgHeight = ref(100); //遮罩层
  47. const dateContHeight = ref(584); //484白色弹框
  48. // 获取当前日期对象
  49. const today = new Date();
  50. // 用于存储日期的数组 - 修改为对象数组格式
  51. const dateList = ref<{ week: string; date: string }[]>([]);
  52. // 填充前4天的日期
  53. for (let i = 4; i > 0; i--) {
  54.     const tempDate = new Date(today.getTime() - i * 24 * 60 * 60 * 1000);
  55.     const month = (tempDate.getMonth() + 1).toString().padStart(2, '0');
  56.     const day = tempDate.getDate().toString().padStart(2, '0');
  57.     const week = WEEKDAYS[tempDate.getDay()]; // 获取星期几
  58.     dateList.value.push({
  59.         week,
  60.         date: `${month}.${day}`,
  61.     });
  62. }
  63. // 填充今天的日期
  64. const todayMonth = (today.getMonth() + 1).toString().padStart(2, '0');
  65. const todayDay = today.getDate().toString().padStart(2, '0');
  66. const todayWeek = WEEKDAYS[today.getDay()]; // 获取今天星期几
  67. dateList.value.push({
  68.     week: todayWeek,
  69.     date: `${todayMonth}.${todayDay}`,
  70. });
  71. // 填充后11天的日期
  72. for (let i = 1; i <= 11; i++) {
  73.     const tempDate = new Date(today.getTime() + i * 24 * 60 * 60 * 1000);
  74.     const month = (tempDate.getMonth() + 1).toString().padStart(2, '0');
  75.     const day = tempDate.getDate().toString().padStart(2, '0');
  76.     const week = WEEKDAYS[tempDate.getDay()]; // 获取星期几
  77.     dateList.value.push({
  78.         week,
  79.         date: `${month}.${day}`,
  80.     });
  81. }
  82. const arrowClick = () => {
  83.     showSelect.value = !showSelect.value;
  84. };
  85. // 新增日期选择方法
  86. const selectDate = (item: { week: string; date: string }) => {
  87.     currentDate.value = item.date;
  88.     showSelect.value = false;
  89. };
  90. </script>
  91. <style lang="scss">
  92. // @import './index.scss';
  93. .reg-info {
  94.     height: auto;
  95.     background: #fff;
  96.     padding: 40rpx 0 0 0;
  97.     .item-class {
  98.         &:nth-child(n + 2) {
  99.             margin: 40rpx 0 0 0;
  100.         }
  101.         .title-region {
  102.             padding: 0 30rpx;
  103.             position: absolute;//父组件最外层div设置position: relative;
  104.             height: 45rpx;
  105.             font-family: DINAlternate, DINAlternate;
  106.             font-weight: bold;
  107.             font-size: 28rpx;
  108.             color: #13161b;
  109.             line-height: 32rpx;
  110.         }
  111.         .content-region {
  112.             width: 100%;
  113.             background: rgba(0, 0, 0, 0.5);
  114.             margin: 20rpx 0 0 0;
  115.             overflow: hidden;
  116.             position: absolute;
  117.             left: 0;
  118.             top: 61rpx;
  119.             height: 0rpx;
  120.             .content-region-cont {
  121.                 height: 0rpx;
  122.                 padding: 20rpx 40rpx;
  123.                 background: #ffffff;
  124.                 transition: all 0.38s;
  125.             }
  126.         .content-item-box {
  127.             display: grid;
  128.             grid-template-columns: repeat(4, 1fr);//固定显示4个
  129.         }
  130.         .content-item {
  131.             border: 2rpx solid rgba(151, 151, 151, 0.2);
  132.             margin-left: -2rpx; /* 抵消相邻边框 */
  133.             margin-top: -2rpx; /* 抵消相邻边框 */
  134.             padding: 4rpx 0;
  135.             height: 110rpx;
  136.             box-sizing: border-box;
  137.             position: relative;
  138.             z-index: 1;
  139.         }
  140.       /* 处理边缘边框 */
  141.         .content-item:nth-child(4n + 1) {
  142.             margin-left: 0;
  143.         }
  144.         .content-item:nth-child(-n + 4) {
  145.             margin-top: 0;
  146.         }
  147.             .selected {
  148.                 color: rgba(255, 167, 38, 1);
  149.             border-color: rgba(255, 167, 38, 1);
  150.             background: rgba(255, 233, 179, 0.20);
  151.             z-index: 2;
  152.             }
  153.         }
  154.     }
  155. }
  156. </style>
复制代码
 父组件代码
  1. <template>
  2.    <view class="service-order">     
  3.        <view class="service-order-filter flex">
  4.             <timeSelect />
  5.         </view>
  6.    </view>
  7. </template>
  8. <script setup lang="ts">
  9.     import timeSelect from '@/components/time-select/time-select.vue';//引入子组件
  10. </script>
  11. <style lang="scss">
  12. .service-order {
  13.     width: 100vw;
  14.     background: #f1f2f5;
  15.     box-sizing: border-box;
  16.     position: relative;//父组件一定要定义
  17.     .service-order-filter{
  18.         width: 100%;
  19.         background: #fff;
  20.         position: sticky;
  21.         height: 80rpx;
  22.         top: 0;
  23.         left: 0;
  24.     }
  25. </style>
复制代码

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

快速回复 返回顶部 返回列表