修改日期问题弹出问题
This commit is contained in:
181
src/components/CustomPopup/CustomPopup.tsx
Normal file
181
src/components/CustomPopup/CustomPopup.tsx
Normal file
@@ -0,0 +1,181 @@
|
||||
import React, { useRef, useState } from 'react'
|
||||
import type { CSSProperties, ReactNode } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Button } from '@nutui/nutui-react-taro'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
export interface CustomPopupProps {
|
||||
visible: boolean
|
||||
onClose: () => void
|
||||
title?: ReactNode
|
||||
showHeader?: boolean
|
||||
hideFooter?: boolean
|
||||
cancelText?: string
|
||||
confirmText?: string
|
||||
onCancel?: () => void
|
||||
onConfirm?: () => void
|
||||
children?: ReactNode
|
||||
className?: string
|
||||
style?: CSSProperties
|
||||
// 与 CommonPopup 保持入参一致
|
||||
position?: 'center' | 'bottom' | 'top' | 'left' | 'right'
|
||||
round?: boolean
|
||||
zIndex?: number
|
||||
enableDragToClose?: boolean
|
||||
}
|
||||
|
||||
const CustomPopup: React.FC<CustomPopupProps> = ({
|
||||
visible,
|
||||
onClose,
|
||||
title,
|
||||
showHeader = false,
|
||||
hideFooter = false,
|
||||
cancelText = '返回',
|
||||
confirmText = '完成',
|
||||
onCancel,
|
||||
onConfirm,
|
||||
children,
|
||||
className,
|
||||
style,
|
||||
position = 'bottom',
|
||||
round = true,
|
||||
zIndex,
|
||||
enableDragToClose = true,
|
||||
}) => {
|
||||
const [dragOffset, setDragOffset] = useState(0)
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const touchStartY = useRef(0)
|
||||
|
||||
if (!visible) {
|
||||
return null
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
if (onCancel) {
|
||||
onCancel()
|
||||
} else {
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
|
||||
const handleTouchStart = (e: any) => {
|
||||
if (!enableDragToClose) return
|
||||
|
||||
touchStartY.current = e.touches[0].clientY
|
||||
setIsDragging(true)
|
||||
}
|
||||
|
||||
const handleTouchMove = (e: any) => {
|
||||
if (!enableDragToClose || !isDragging) return
|
||||
|
||||
const currentY = e.touches[0].clientY
|
||||
const deltaY = currentY - touchStartY.current
|
||||
|
||||
if (deltaY > 0) {
|
||||
setDragOffset(Math.min(deltaY, 100))
|
||||
}
|
||||
}
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
if (!enableDragToClose || !isDragging) return
|
||||
|
||||
setIsDragging(false)
|
||||
|
||||
if (dragOffset > 50) {
|
||||
onClose()
|
||||
}
|
||||
|
||||
setDragOffset(0)
|
||||
}
|
||||
|
||||
const overlayAlignItems =
|
||||
position === 'center'
|
||||
? 'center'
|
||||
: position === 'top'
|
||||
? 'flex-start'
|
||||
: 'flex-end'
|
||||
|
||||
const handleOverlayClick = () => {
|
||||
onClose()
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<View
|
||||
className={styles['custom-popup-overlay']}
|
||||
style={{ zIndex: zIndex ?? undefined, alignItems: overlayAlignItems }}
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<View className={styles['custom-popup-move']} catchMove></View>
|
||||
<View
|
||||
className={`${styles['custom-popup']} ${className ? className : ''}`}
|
||||
style={{
|
||||
...style,
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
}}
|
||||
>
|
||||
{enableDragToClose && (
|
||||
<View
|
||||
className={styles['custom-popup__drag-handle-container']}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchMove={handleTouchMove}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
>
|
||||
<View
|
||||
className={styles['custom-popup__drag-handle']}
|
||||
style={{
|
||||
transform: `translateX(-50%) translateY(${dragOffset * 0.3}px)`,
|
||||
opacity: isDragging ? 0.8 : 1,
|
||||
transition: isDragging ? 'none' : 'all 0.3s ease-out',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showHeader && (
|
||||
<View className={styles['custom-popup__header']}>
|
||||
{typeof title === 'string' ? (
|
||||
<Text className={styles['custom-popup__title']}>{title}</Text>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
<View className={styles['close_button']} onClick={onClose}>
|
||||
<View className={styles['close_icon']}>
|
||||
<View className={styles['close_line']} />
|
||||
<View className={styles['close_line']} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className={styles['custom-popup__body']}>{children}</View>
|
||||
|
||||
{!hideFooter && (
|
||||
<View className={styles['custom-popup__footer']}>
|
||||
<Button
|
||||
className={`${styles['custom-popup__btn']} ${styles['custom-popup__btn-cancel']}`}
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={handleCancel}
|
||||
>
|
||||
{cancelText}
|
||||
</Button>
|
||||
<Button
|
||||
className={`${styles['custom-popup__btn']} ${styles['custom-popup__btn-confirm']}`}
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{confirmText}
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomPopup
|
||||
|
||||
153
src/components/CustomPopup/index.module.scss
Normal file
153
src/components/CustomPopup/index.module.scss
Normal file
@@ -0,0 +1,153 @@
|
||||
@use "~@/scss/themeColor.scss" as theme;
|
||||
|
||||
.custom-popup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
}
|
||||
.custom-popup-move{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9998;
|
||||
}
|
||||
.custom-popup {
|
||||
position: relative;
|
||||
z-index: 9999;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: theme.$page-background-color;
|
||||
border-radius: 20px 20px 0 0;
|
||||
overflow: hidden;
|
||||
.custom-popup__drag-handle-container {
|
||||
position: relative;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.custom-popup__drag-handle {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 50%;
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 32px;
|
||||
height: 4px;
|
||||
background-color: rgba(22, 24, 35, 0.2);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-popup__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px;
|
||||
|
||||
.custom-popup__title {
|
||||
font-family: "PingFang SC";
|
||||
font-weight: 600;
|
||||
font-size: 22px;
|
||||
line-height: 1.27em;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.close_button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 4px 36px 0px rgba(0, 0, 0, 0.06);
|
||||
|
||||
.close_icon {
|
||||
position: relative;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
.close_line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 17px;
|
||||
height: 3px;
|
||||
border-radius: 3px;
|
||||
background: #000000;
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
|
||||
&:nth-child(2) {
|
||||
transform: translate(-50%, -50%) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-popup__body {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.custom-popup__footer {
|
||||
padding: 8px 10px 0 10px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
background: #fafafa;
|
||||
padding-bottom: max(10px, env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.custom-popup__btn {
|
||||
flex: 1;
|
||||
font-feature-settings: "liga" off, "clig" off;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.custom-popup__btn-cancel {
|
||||
background: #f5f6f7;
|
||||
color: #1f2329;
|
||||
border: none;
|
||||
width: 154px;
|
||||
height: 44px;
|
||||
border-radius: 12px !important;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||
background: #fff;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.custom-popup__btn-confirm {
|
||||
width: 154px;
|
||||
height: 44px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||
background: #000;
|
||||
border-radius: 12px !important;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
4
src/components/CustomPopup/index.ts
Normal file
4
src/components/CustomPopup/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import CustomPopup from './CustomPopup'
|
||||
export default CustomPopup
|
||||
export * from './CustomPopup'
|
||||
|
||||
Reference in New Issue
Block a user