删除多余文件
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
# TimePicker 时间选择器组件
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 使用自定义样式重写PickerViewColumn功能
|
||||
- 完全还原原生PickerView的样式和动画效果
|
||||
- 支持年份和月份选择
|
||||
- 平滑的滚动动画和切换效果
|
||||
- 响应式设计,支持触摸滚动
|
||||
- 渐变遮罩效果增强视觉层次
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 核心特性
|
||||
- 使用ScrollView替代PickerViewColumn
|
||||
- 自定义滚动逻辑实现选项对齐
|
||||
- CSS动画和过渡效果还原原生体验
|
||||
- 智能滚动位置计算和自动对齐
|
||||
|
||||
### 样式还原
|
||||
- 选中项指示器(高亮背景)
|
||||
- 渐变遮罩效果(顶部和底部)
|
||||
- 平滑的过渡动画
|
||||
- 精确的尺寸和间距
|
||||
|
||||
## 使用方法
|
||||
|
||||
```tsx
|
||||
import { TimePicker } from '@/components/TimePicker'
|
||||
|
||||
const [visible, setVisible] = useState(false)
|
||||
|
||||
<TimePicker
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
onConfirm={(year, month) => {
|
||||
console.log('选择的时间:', year, month)
|
||||
setVisible(false)
|
||||
}}
|
||||
defaultYear={2024}
|
||||
defaultMonth={6}
|
||||
minYear={2020}
|
||||
maxYear={2030}
|
||||
/>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| visible | boolean | - | 是否显示选择器 |
|
||||
| visible | boolean | - | 是否显示选择器 |
|
||||
| onClose | () => void | - | 关闭回调 |
|
||||
| onConfirm | (year: number, month: number) => void | - | 确认选择回调 |
|
||||
| defaultYear | number | 当前年份 | 默认选中的年份 |
|
||||
| defaultMonth | number | 当前月份 | 默认选中的月份 |
|
||||
| minYear | number | 2020 | 最小年份 |
|
||||
| maxYear | number | 2030 | 最大年份 |
|
||||
|
||||
## 样式定制
|
||||
|
||||
组件使用CSS Modules,可以通过修改`index.module.scss`文件来自定义样式:
|
||||
|
||||
- `.time-picker-popup`: 弹出层容器
|
||||
- `.picker-container`: 选择器容器
|
||||
- `.custom-picker`: 自定义选择器
|
||||
- `.picker-indicator`: 选中项指示器
|
||||
- `.picker-column`: 选择列
|
||||
- `.picker-item`: 选择项
|
||||
- `.picker-item-active`: 激活状态的选择项
|
||||
|
||||
## 测试
|
||||
|
||||
运行测试页面:
|
||||
```tsx
|
||||
import TimePickerTest from '@/components/TimePicker/test'
|
||||
```
|
||||
@@ -1,233 +0,0 @@
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { View, Text, ScrollView } from '@tarojs/components'
|
||||
import { CommonPopup } from '../index'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
export interface TimePickerProps {
|
||||
visible: boolean
|
||||
onClose: () => void
|
||||
onConfirm: (year: number, month: number) => void
|
||||
defaultYear?: number
|
||||
defaultMonth?: number
|
||||
minYear?: number
|
||||
maxYear?: number
|
||||
}
|
||||
|
||||
const TimePicker: React.FC<TimePickerProps> = ({
|
||||
visible,
|
||||
onClose,
|
||||
onConfirm,
|
||||
defaultYear = new Date().getFullYear(),
|
||||
defaultMonth = new Date().getMonth() + 1,
|
||||
minYear = 2020,
|
||||
maxYear = 2030
|
||||
}) => {
|
||||
const [selectedYear, setSelectedYear] = useState(defaultYear)
|
||||
const [selectedMonth, setSelectedMonth] = useState(defaultMonth)
|
||||
const [yearScrollTop, setYearScrollTop] = useState(0)
|
||||
const [monthScrollTop, setMonthScrollTop] = useState(0)
|
||||
|
||||
const yearScrollRef = useRef<any>(null)
|
||||
const monthScrollRef = useRef<any>(null)
|
||||
|
||||
// 计算当前选项在数组中的索引
|
||||
const getYearIndex = (year: number) => year - minYear
|
||||
const getMonthIndex = (month: number) => month - 1
|
||||
|
||||
// 生成选择器的选项数据
|
||||
const yearOptions = Array.from({ length: maxYear - minYear + 1 }, (_, index) => ({
|
||||
text: `${minYear + index}年`,
|
||||
value: minYear + index
|
||||
}))
|
||||
|
||||
const monthOptions = Array.from({ length: 12 }, (_, index) => ({
|
||||
text: `${index + 1}月`,
|
||||
value: index + 1
|
||||
}))
|
||||
|
||||
// 计算滚动位置 - 确保每次只显示一个选项
|
||||
const calculateScrollTop = (index: number) => {
|
||||
const itemHeight = 48 // 每个选项的高度
|
||||
const containerHeight = 216 // 容器高度
|
||||
const centerOffset = (containerHeight - itemHeight) / 2
|
||||
return index * itemHeight - centerOffset
|
||||
}
|
||||
|
||||
// 获取当前可见的选项数量
|
||||
const getVisibleItemCount = () => {
|
||||
const containerHeight = 216
|
||||
const itemHeight = 48
|
||||
return Math.floor(containerHeight / itemHeight)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setSelectedYear(defaultYear)
|
||||
setSelectedMonth(defaultMonth)
|
||||
|
||||
// 设置初始滚动位置
|
||||
const yearScrollTop = calculateScrollTop(getYearIndex(defaultYear))
|
||||
const monthScrollTop = calculateScrollTop(getMonthIndex(defaultMonth))
|
||||
setYearScrollTop(yearScrollTop)
|
||||
setMonthScrollTop(monthScrollTop)
|
||||
}
|
||||
}, [visible, defaultYear, defaultMonth])
|
||||
|
||||
// 处理年份滚动
|
||||
const handleYearScroll = (event: any) => {
|
||||
const scrollTop = event.detail.scrollTop
|
||||
const itemHeight = 48
|
||||
const containerHeight = 216
|
||||
const centerOffset = (containerHeight - itemHeight) / 2
|
||||
|
||||
// 计算当前选中的年份索引
|
||||
const currentIndex = Math.round((scrollTop + centerOffset) / itemHeight)
|
||||
const clampedIndex = Math.max(0, Math.min(currentIndex, yearOptions.length - 1))
|
||||
const newYear = minYear + clampedIndex
|
||||
|
||||
if (newYear !== selectedYear) {
|
||||
setSelectedYear(newYear)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理年份滚动结束,自动对齐
|
||||
const handleYearScrollEnd = () => {
|
||||
const yearIndex = getYearIndex(selectedYear)
|
||||
const alignedScrollTop = calculateScrollTop(yearIndex)
|
||||
// 使用setTimeout确保滚动动画完成后再对齐
|
||||
setTimeout(() => {
|
||||
setYearScrollTop(alignedScrollTop)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
// 处理月份滚动
|
||||
const handleMonthScroll = (event: any) => {
|
||||
const scrollTop = event.detail.scrollTop
|
||||
const itemHeight = 48
|
||||
const containerHeight = 216
|
||||
const centerOffset = (containerHeight - itemHeight) / 2
|
||||
|
||||
// 计算当前选中的月份索引
|
||||
const currentIndex = Math.round((scrollTop + centerOffset) / itemHeight)
|
||||
const clampedIndex = Math.max(0, Math.min(currentIndex, monthOptions.length - 1))
|
||||
const newMonth = clampedIndex + 1
|
||||
|
||||
if (newMonth !== selectedMonth) {
|
||||
setSelectedMonth(newMonth)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理月份滚动结束,自动对齐
|
||||
const handleMonthScrollEnd = () => {
|
||||
const monthIndex = getMonthIndex(selectedMonth)
|
||||
const alignedScrollTop = calculateScrollTop(monthIndex)
|
||||
// 使用setTimeout确保滚动动画完成后再对齐
|
||||
setTimeout(() => {
|
||||
setMonthScrollTop(alignedScrollTop)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
onConfirm(selectedYear, selectedMonth)
|
||||
onClose()
|
||||
}
|
||||
|
||||
if (!visible) return null
|
||||
|
||||
return (
|
||||
<CommonPopup
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
onConfirm={handleConfirm}
|
||||
showHeader={false}
|
||||
hideFooter={false}
|
||||
cancelText="返回"
|
||||
confirmText="完成"
|
||||
position="bottom"
|
||||
round={true}
|
||||
className={styles['time-picker-popup']}
|
||||
>
|
||||
{/* 拖拽手柄 */}
|
||||
<View className={styles['popup-handle']} />
|
||||
|
||||
{/* 时间选择器 */}
|
||||
<View className={styles['picker-container']}>
|
||||
{/* 自定义多列选择器 */}
|
||||
<View className={styles['picker-wrapper']}>
|
||||
<View className={styles['custom-picker']}>
|
||||
{/* 选中项指示器 */}
|
||||
<View className={styles['picker-indicator']} />
|
||||
|
||||
{/* 年份列 */}
|
||||
<View className={styles['picker-column']}>
|
||||
<ScrollView
|
||||
ref={yearScrollRef}
|
||||
scrollY
|
||||
scrollTop={yearScrollTop}
|
||||
onScroll={handleYearScroll}
|
||||
onTouchEnd={handleYearScrollEnd}
|
||||
onScrollToLower={handleYearScrollEnd}
|
||||
onScrollToUpper={handleYearScrollEnd}
|
||||
className={styles['picker-scroll']}
|
||||
scrollWithAnimation={true}
|
||||
enhanced={true}
|
||||
showScrollbar={false}
|
||||
bounces={false}
|
||||
fastDeceleration={true}
|
||||
>
|
||||
<View className={styles['picker-padding']} />
|
||||
{yearOptions.map((option, index) => (
|
||||
<View
|
||||
key={option.value}
|
||||
className={`${styles['picker-item']} ${
|
||||
option.value === selectedYear ? styles['picker-item-active'] : ''
|
||||
}`}
|
||||
data-value={option.value}
|
||||
>
|
||||
<Text className={styles['picker-item-text']}>{option.text}</Text>
|
||||
</View>
|
||||
))}
|
||||
<View className={styles['picker-padding']} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
{/* 月份列 */}
|
||||
<View className={styles['picker-column']}>
|
||||
<ScrollView
|
||||
ref={monthScrollRef}
|
||||
scrollY
|
||||
scrollTop={monthScrollTop}
|
||||
onScroll={handleMonthScroll}
|
||||
onTouchEnd={handleMonthScrollEnd}
|
||||
onScrollToLower={handleMonthScrollEnd}
|
||||
onScrollToUpper={handleMonthScrollEnd}
|
||||
className={styles['picker-scroll']}
|
||||
scrollWithAnimation={true}
|
||||
enhanced={true}
|
||||
showScrollbar={false}
|
||||
bounces={false}
|
||||
fastDeceleration={true}
|
||||
>
|
||||
<View className={styles['picker-padding']} />
|
||||
{monthOptions.map((option, index) => (
|
||||
<View
|
||||
key={option.value}
|
||||
className={`${styles['picker-item']} ${
|
||||
option.value === selectedMonth ? styles['picker-item-active'] : ''
|
||||
}`}
|
||||
data-value={option.value}
|
||||
>
|
||||
<Text className={styles['picker-item-text']}>{option.text}</Text>
|
||||
</View>
|
||||
))}
|
||||
<View className={styles['picker-padding']} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</CommonPopup>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimePicker
|
||||
@@ -1,81 +0,0 @@
|
||||
.demoContainer {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 16px;
|
||||
margin-bottom: 30px;
|
||||
display: block;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.demoButton {
|
||||
margin: 20px 0;
|
||||
width: 250px;
|
||||
height: 50px;
|
||||
border-radius: 25px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
color: white;
|
||||
|
||||
&:active {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.demoResult {
|
||||
margin: 30px 0;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 16px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
|
||||
text {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.demoFeatures {
|
||||
margin-top: 40px;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
opacity: 0.9;
|
||||
border-radius: 16px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.featureItem {
|
||||
font-size: 14px;
|
||||
margin: 8px 0;
|
||||
display: block;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
line-height: 1.5;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Button, Text } from '@tarojs/components'
|
||||
import TimePicker from './TimePicker'
|
||||
import styles from './demo.module.scss'
|
||||
|
||||
const TimePickerDemo: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [selectedTime, setSelectedTime] = useState('')
|
||||
|
||||
const handleConfirm = (year: number, month: number) => {
|
||||
setSelectedTime(`${year}年${month}月`)
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.demoContainer}>
|
||||
<Text className={styles.title}>TimePicker 演示</Text>
|
||||
<Text className={styles.subtitle}>体验"一个一个往下翻"的效果</Text>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => setVisible(true)}
|
||||
className={styles.demoButton}
|
||||
>
|
||||
打开时间选择器
|
||||
</Button>
|
||||
|
||||
{selectedTime && (
|
||||
<View className={styles.demoResult}>
|
||||
<Text>已选择: {selectedTime}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className={styles.demoFeatures}>
|
||||
<Text className={styles.featureTitle}>特性说明:</Text>
|
||||
<Text className={styles.featureItem}>• 每次只显示一个选项</Text>
|
||||
<Text className={styles.featureItem}>• 完美居中对齐</Text>
|
||||
<Text className={styles.featureItem}>• 平滑滚动动画</Text>
|
||||
<Text className={styles.featureItem}>• 触摸结束后自动对齐</Text>
|
||||
</View>
|
||||
|
||||
<TimePicker
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
defaultYear={2024}
|
||||
defaultMonth={6}
|
||||
minYear={2020}
|
||||
maxYear={2030}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimePickerDemo
|
||||
@@ -1,187 +0,0 @@
|
||||
/* 时间选择器弹出层样式 */
|
||||
.time-picker-popup {
|
||||
.common-popup-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-handle {
|
||||
width: 32px;
|
||||
height: 4px;
|
||||
background: #e0e0e0;
|
||||
border-radius: 2px;
|
||||
margin: 12px auto;
|
||||
}
|
||||
|
||||
.picker-container {
|
||||
padding: 26px 16px 0 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.picker-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.custom-picker {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 216px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* 确保只显示一个选项 */
|
||||
perspective: 1000px;
|
||||
/* 水平布局 */
|
||||
flex-direction: row;
|
||||
/* 确保列之间有适当间距 */
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* 选中项指示器 */
|
||||
.picker-indicator {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 48px;
|
||||
background: rgba(22, 24, 35, 0.05);
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 0 0 1px rgba(22, 24, 35, 0.1);
|
||||
/* 确保指示器完美覆盖选中项 */
|
||||
margin: 0 20px;
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.picker-column {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* 水平居中布局 */
|
||||
min-width: 0;
|
||||
/* 确保列之间有适当间距 */
|
||||
padding: 0 8px;
|
||||
|
||||
&:first-child {
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 确保滚动容器正确显示 */
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 84px;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.picker-scroll {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
will-change: scroll-position;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
/* 确保滚动行为 */
|
||||
scroll-snap-type: y mandatory;
|
||||
/* 优化滚动性能 */
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.picker-padding {
|
||||
height: 84px; /* (216 - 48) / 2 = 84px,用于居中对齐 */
|
||||
/* 确保padding区域不可见 */
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.picker-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
color: #161823;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
position: relative;
|
||||
will-change: transform, color;
|
||||
/* 确保每个选项都能正确对齐 */
|
||||
scroll-snap-align: center;
|
||||
/* 水平居中 */
|
||||
text-align: center;
|
||||
|
||||
&.picker-item-active {
|
||||
color: #161823;
|
||||
font-weight: 600;
|
||||
transform: scale(1.02);
|
||||
|
||||
.picker-item-text {
|
||||
color: #161823;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.picker-item-active) {
|
||||
color: rgba(22, 24, 35, 0.6);
|
||||
|
||||
.picker-item-text {
|
||||
color: rgba(22, 24, 35, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.picker-item-text {
|
||||
font-size: 16px;
|
||||
color: inherit;
|
||||
text-align: center;
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
line-height: 48px;
|
||||
white-space: nowrap;
|
||||
/* 确保文字完美居中 */
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
/* 强制居中对齐 */
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* 滚动条隐藏 */
|
||||
.picker-scroll {
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/* 移除重复的渐变遮罩代码,已在.picker-column中定义 */
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default } from './TimePicker'
|
||||
export type { TimePickerProps } from './TimePicker'
|
||||
@@ -1,59 +0,0 @@
|
||||
.testContainer {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background: #f8f9fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.testTitle {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.testSubtitle {
|
||||
font-size: 16px;
|
||||
margin-bottom: 30px;
|
||||
display: block;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.testInfo {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
text-align: left;
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
margin: 8px 0;
|
||||
display: block;
|
||||
color: #555;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.testButton {
|
||||
margin: 20px 0;
|
||||
width: 200px;
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
background: #007bff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.testResult {
|
||||
margin: 20px 0;
|
||||
color: white;
|
||||
border-radius: 8px;
|
||||
|
||||
text {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Text, Button } from '@tarojs/components'
|
||||
import TimePicker from './TimePicker'
|
||||
import styles from './layout-test.module.scss'
|
||||
|
||||
const LayoutTest: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [selectedTime, setSelectedTime] = useState('')
|
||||
|
||||
const handleConfirm = (year: number, month: number) => {
|
||||
setSelectedTime(`${year}年${month}月`)
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.testContainer}>
|
||||
<Text className={styles.testTitle}>布局测试</Text>
|
||||
<Text className={styles.testSubtitle}>验证年份和月份的水平居中对齐</Text>
|
||||
|
||||
<View className={styles.testInfo}>
|
||||
<Text>• 年份和月份应该在同一行显示</Text>
|
||||
<Text>• 两个列应该水平居中对齐</Text>
|
||||
<Text>• 选中项指示器应该完美覆盖两个列</Text>
|
||||
</View>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => setVisible(true)}
|
||||
className={styles.testButton}
|
||||
>
|
||||
测试布局
|
||||
</Button>
|
||||
|
||||
{selectedTime && (
|
||||
<View className={styles.testResult}>
|
||||
<Text>选择结果: {selectedTime}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TimePicker
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
defaultYear={2024}
|
||||
defaultMonth={6}
|
||||
minYear={2020}
|
||||
maxYear={2030}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
.container {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 30px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin: 20px 0;
|
||||
width: 200px;
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin-top: 30px;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
|
||||
text {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Button, Text } from '@tarojs/components'
|
||||
import TimePicker from './TimePicker'
|
||||
import styles from './test.module.scss'
|
||||
|
||||
const TimePickerTest: React.FC = () => {
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [selectedTime, setSelectedTime] = useState('')
|
||||
|
||||
const handleConfirm = (year: number, month: number) => {
|
||||
setSelectedTime(`${year}年${month}月`)
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.container}>
|
||||
<Text className={styles.title}>TimePicker 组件测试</Text>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => setVisible(true)}
|
||||
className={styles.button}
|
||||
>
|
||||
打开时间选择器
|
||||
</Button>
|
||||
|
||||
{selectedTime && (
|
||||
<View className={styles.result}>
|
||||
<Text>已选择: {selectedTime}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TimePicker
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
defaultYear={2024}
|
||||
defaultMonth={6}
|
||||
minYear={2020}
|
||||
maxYear={2030}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimePickerTest
|
||||
@@ -8,7 +8,6 @@ import NumberInterval from "./NumberInterval";
|
||||
import TimeSelector from "./TimeSelector";
|
||||
import TitleTextarea from "./TitleTextarea";
|
||||
import CommonPopup from "./CommonPopup";
|
||||
import TimePicker from "./TimePicker/TimePicker";
|
||||
import { CalendarUI, DialogCalendarCard } from "./Picker";
|
||||
import CommonDialog from "./CommonDialog";
|
||||
import PublishMenu from "./PublishMenu/PublishMenu";
|
||||
@@ -28,7 +27,6 @@ export {
|
||||
TimeSelector,
|
||||
TitleTextarea,
|
||||
CommonPopup,
|
||||
TimePicker,
|
||||
DialogCalendarCard,
|
||||
CalendarUI,
|
||||
CommonDialog,
|
||||
|
||||
Reference in New Issue
Block a user