修改发布增加拖动
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Popup, Button } from '@nutui/nutui-react-taro'
|
||||
import styles from './index.module.scss'
|
||||
@@ -19,6 +19,7 @@ export interface CommonPopupProps {
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
style?: React.CSSProperties
|
||||
enableDragToClose?: boolean
|
||||
}
|
||||
|
||||
const CommonPopup: React.FC<CommonPopupProps> = ({
|
||||
@@ -36,8 +37,14 @@ const CommonPopup: React.FC<CommonPopupProps> = ({
|
||||
round = true,
|
||||
zIndex,
|
||||
style,
|
||||
children
|
||||
children,
|
||||
enableDragToClose = true
|
||||
}) => {
|
||||
const [dragOffset, setDragOffset] = useState(0)
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const touchStartY = useRef(0)
|
||||
const popupRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const handleCancel = () => {
|
||||
if (onCancel) {
|
||||
onCancel()
|
||||
@@ -46,6 +53,39 @@ const CommonPopup: React.FC<CommonPopupProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
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, 200))
|
||||
}
|
||||
}
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
if (!enableDragToClose || !isDragging) return
|
||||
|
||||
setIsDragging(false)
|
||||
|
||||
// 如果拖动距离超过阈值,关闭弹窗
|
||||
if (dragOffset > 100) {
|
||||
onClose()
|
||||
}
|
||||
|
||||
// 重置拖动偏移
|
||||
setDragOffset(0)
|
||||
}
|
||||
|
||||
return (
|
||||
<Popup
|
||||
visible={visible}
|
||||
@@ -54,8 +94,27 @@ const CommonPopup: React.FC<CommonPopupProps> = ({
|
||||
closeable={false}
|
||||
onClose={onClose}
|
||||
className={`${styles['common-popup']} ${className ? className : ''}`}
|
||||
style={{ zIndex: zIndex ? zIndex : undefined, ...style }}
|
||||
style={{
|
||||
zIndex: zIndex ? zIndex : undefined,
|
||||
...style
|
||||
}}
|
||||
>
|
||||
{enableDragToClose && (
|
||||
<View className={styles['common-popup__drag-handle-container']}>
|
||||
<View
|
||||
className={styles['common-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'
|
||||
}}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchMove={handleTouchMove}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showHeader && (
|
||||
<View className={styles['common-popup__header']}>
|
||||
{typeof title === 'string' ? <Text className={styles['common-popup__title']}>{title}</Text> : title}
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
@use '~@/scss/themeColor.scss' as theme;
|
||||
|
||||
.common-popup {
|
||||
.common-popup__drag-handle-container {
|
||||
position: position;
|
||||
}
|
||||
.common-popup__drag-handle {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 50%;
|
||||
width: 32px;
|
||||
height: 4px;
|
||||
background-color: rgba(22, 24, 35, 0.20);
|
||||
border-radius: 2px;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:active {
|
||||
background-color: #9ca3af;
|
||||
}
|
||||
}
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
max-height: calc(100vh - 10px);
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
.info-popover {
|
||||
position: absolute;
|
||||
bottom: 22px;
|
||||
left: -65px;
|
||||
width: 130px;
|
||||
left: -92px;
|
||||
width: 184px;
|
||||
padding:12px;
|
||||
background: rgba(57, 59, 68, 0.90);
|
||||
color: #fff;
|
||||
@@ -51,7 +51,7 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
left: 68px; /* 对齐图标(宽12px),可按需微调 */
|
||||
left: 94px; /* 对齐图标(宽12px),可按需微调 */
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 6px solid transparent;
|
||||
|
||||
@@ -61,9 +61,7 @@ const HourMinutePicker: React.FC<HourMinutePickerProps> = ({
|
||||
|
||||
return (
|
||||
<View className={styles['hour-minute-picker-popup']}>
|
||||
{/* 拖拽手柄 */}
|
||||
<View className={styles['drag-handle']} />
|
||||
|
||||
{/* 拖拽手柄 */}
|
||||
{/* 时间选择器 */}
|
||||
<View className={styles['picker-container']}>
|
||||
{/* 多列选择器 */}
|
||||
|
||||
@@ -8,14 +8,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
width: 40px;
|
||||
height: 4px;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 2px;
|
||||
margin: 0 auto 20px;
|
||||
}
|
||||
|
||||
.picker-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -6,16 +6,30 @@ import { InputNumber } from '@nutui/nutui-react-taro'
|
||||
interface NumberIntervalProps {
|
||||
value: [number, number]
|
||||
onChange: (value: [number, number]) => void
|
||||
min: number
|
||||
max: number
|
||||
}
|
||||
|
||||
const NumberInterval: React.FC<NumberIntervalProps> = ({
|
||||
value,
|
||||
onChange
|
||||
onChange,
|
||||
min,
|
||||
max
|
||||
}) => {
|
||||
const [minParticipants, maxParticipants] = value || [1, 4]
|
||||
const [minParticipants, maxParticipants] = value || [1, 1]
|
||||
|
||||
const handleChange = (value: [number | string, number | string]) => {
|
||||
onChange([Number(value[0]), Number(value[1])])
|
||||
const newMin = Number(value[0])
|
||||
const newMax = Number(value[1])
|
||||
|
||||
// 确保最少人数不能大于最多人数
|
||||
if (newMin > newMax) {
|
||||
return
|
||||
}
|
||||
|
||||
onChange([newMin, newMax])
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='participants-control-section'>
|
||||
<View className='participant-control'>
|
||||
@@ -24,7 +38,7 @@ const NumberInterval: React.FC<NumberIntervalProps> = ({
|
||||
<InputNumber
|
||||
className="format-width"
|
||||
defaultValue={minParticipants}
|
||||
min={minParticipants}
|
||||
min={min}
|
||||
max={maxParticipants}
|
||||
onChange={(value) => handleChange([value, maxParticipants])}
|
||||
formatter={(value) => `${value}人`}
|
||||
@@ -37,9 +51,9 @@ const NumberInterval: React.FC<NumberIntervalProps> = ({
|
||||
<InputNumber
|
||||
className="format-width"
|
||||
defaultValue={maxParticipants}
|
||||
onChange={(value) => handleChange([value, maxParticipants])}
|
||||
onChange={(value) => handleChange([minParticipants, value])}
|
||||
min={minParticipants}
|
||||
max={maxParticipants}
|
||||
max={max}
|
||||
formatter={(value) => `${value}人`}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
&.rotated {
|
||||
transform: rotate(45deg);
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const TextareaTag: React.FC<TextareaTagProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = '请输入',
|
||||
maxLength = 500,
|
||||
maxLength = 1000,
|
||||
options = []
|
||||
}) => {
|
||||
// 处理文本输入变化
|
||||
|
||||
Reference in New Issue
Block a user