This commit is contained in:
筱野
2025-09-25 21:42:40 +08:00
parent 19a51fc679
commit 76d26831ca
4 changed files with 45 additions and 44 deletions

View File

@@ -6,27 +6,13 @@
width: 100%; width: 100%;
padding: 9px 12px; padding: 9px 12px;
display: flex; display: flex;
justify-content: space-between; flex-direction: column;
height: 48px;
box-sizing: border-box; box-sizing: border-box;
.participant-control { .participant-control {
display: flex; display: flex;
align-items: center; align-items: center;
position: relative; position: relative;
&:first-child{ justify-content: space-between;
width: 50%;
&::after{
content: '';
display: block;
width: 1px;
height: 16px;
background: #E5E5E5;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
}
.control-label { .control-label {
font-size: 13px; font-size: 13px;
color: theme.$primary-color; color: theme.$primary-color;

View File

@@ -1,11 +1,12 @@
import React from 'react' import React from 'react'
import { View, Text, Button } from '@tarojs/components' import { View, Text } from '@tarojs/components'
import './NumberInterval.scss'
import { InputNumber } from '@nutui/nutui-react-taro' import { InputNumber } from '@nutui/nutui-react-taro'
import { Checkbox } from '@nutui/nutui-react-taro'
import './NumberInterval.scss'
interface NumberIntervalProps { interface NumberIntervalProps {
value: [number, number] value: { min: number, max: number, is_participate: boolean }
onChange: (value: [number, number]) => void onChange: (value: { min: number, max: number, is_participate: boolean }) => void
min: number min: number
max: number max: number
} }
@@ -16,48 +17,50 @@ const NumberInterval: React.FC<NumberIntervalProps> = ({
min, min,
max max
}) => { }) => {
const [minParticipants, maxParticipants] = value || [1, 1] const { min:minParticipants, max:maxParticipants, is_participate } = value || { min: 1, max: 1, is_participate: true }
const handleChange = (value: { min: number | string, max: number | string, is_participate: boolean }) => {
const handleChange = (value: [number | string, number | string]) => { const toNumber = (v: number | string): number => typeof v === 'string' ? Number(v) : v
const newMin = Number(value[0]) const { min, max, is_participate } = value;
const newMax = Number(value[1]) onChange({ min: toNumber(min), max: toNumber(max), is_participate })
// 确保最少人数不能大于最多人数
if (newMin > newMax) {
return
}
onChange([newMin, newMax])
} }
return ( return (
<View className='participants-control-section'> <View className='participants-control-section'>
<View className='participant-control'> <View className='participant-control'>
<Text className='control-label'></Text> <Text className='control-label'></Text>
<View className='control-buttons'> <View className='control-buttons'>
<InputNumber <InputNumber
className="format-width" className="format-width"
defaultValue={minParticipants} defaultValue={minParticipants}
min={min} min={min}
max={maxParticipants} max={maxParticipants}
onChange={(value) => handleChange([value, maxParticipants])} onChange={(value) => handleChange({ min: value, max: maxParticipants, is_participate: is_participate })}
formatter={(value) => `${value}`} formatter={(value) => `${value}`}
/> />
</View> </View>
</View> </View>
<View className='participant-control'> <View className='participant-control'>
<Text className='control-label'></Text> <Text className='control-label'></Text>
<View className='control-buttons'> <View className='control-buttons'>
<InputNumber <InputNumber
className="format-width" className="format-width"
defaultValue={maxParticipants} defaultValue={maxParticipants}
onChange={(value) => handleChange([minParticipants, value])} onChange={(value) => handleChange({ min: minParticipants, max: value, is_participate: is_participate })}
min={minParticipants} min={minParticipants}
max={max} max={max}
formatter={(value) => `${value}`} formatter={(value) => `${value}`}
/> />
</View> </View>
</View> </View>
<View className='participant-control'>
<Checkbox
className=''
checked={is_participate}
onChange={(checked) => handleChange({ min: minParticipants, max: maxParticipants, is_participate: checked })}
/>
</View>
</View> </View>
) )
} }

View File

@@ -39,7 +39,11 @@ const defaultFormData: PublishBallFormData = {
venue_description: '', venue_description: '',
venue_image_list: [], venue_image_list: [],
}, },
players: [1, 1], players: {
min: 1,
max: 1,
is_participate: true
},
skill_level: [1.0, 5.0], skill_level: [1.0, 5.0],
descriptionInfo: { descriptionInfo: {
description: '', description: '',
@@ -257,14 +261,16 @@ const PublishBall: React.FC = () => {
if (!isValid) { if (!isValid) {
return return
} }
const { activityInfo, descriptionInfo, timeRange, players, skill_level,image_list,wechat, ...rest } = formData[0]; const { activityInfo, descriptionInfo, timeRange, players, skill_level, image_list, wechat, ...rest } = formData[0];
const { min, max, is_participate } = players;
const options = { const options = {
...rest, ...rest,
...activityInfo, ...activityInfo,
...descriptionInfo, ...descriptionInfo,
...timeRange, ...timeRange,
max_players: players[1], max_players: max,
min_players: players[0], min_players: min,
is_participate: is_participate,
skill_level_min: skill_level[0], skill_level_min: skill_level[0],
skill_level_max: skill_level[1], skill_level_max: skill_level[1],
image_list: image_list.map(item => item.url), image_list: image_list.map(item => item.url),
@@ -305,13 +311,15 @@ const PublishBall: React.FC = () => {
} }
const options = formData.map((item) => { const options = formData.map((item) => {
const { activityInfo, descriptionInfo, timeRange, players, skill_level, ...rest } = item; const { activityInfo, descriptionInfo, timeRange, players, skill_level, ...rest } = item;
const { min, max, is_participate } = players;
return { return {
...rest, ...rest,
...activityInfo, ...activityInfo,
...descriptionInfo, ...descriptionInfo,
...timeRange, ...timeRange,
max_players: players[1], max_players: max,
min_players: players[0], min_players: min,
is_participate: is_participate,
skill_level_min: skill_level[0], skill_level_min: skill_level[0],
skill_level_max: skill_level[1], skill_level_max: skill_level[1],
image_list: item.image_list.map(img => img.url) image_list: item.image_list.map(img => img.url)
@@ -382,7 +390,7 @@ const PublishBall: React.FC = () => {
...(description_tag ? { description_tag } : {}), ...(description_tag ? { description_tag } : {}),
}, },
...(skill_level_max && skill_level_min ? { skill_level: [skill_level_min, skill_level_max] } : {}), ...(skill_level_max && skill_level_min ? { skill_level: [skill_level_min, skill_level_max] } : {}),
...(max_players && min_players ? { players: [min_players, max_players] } : {}), ...(max_players && min_players ? { players: { min: min_players, max: max_players, is_participate: true } } : {}),
wechat: { ...defaultFormData.wechat, default_wechat_contact: userPhone } wechat: { ...defaultFormData.wechat, default_wechat_contact: userPhone }
} }
} }

View File

@@ -20,7 +20,11 @@ export interface PublishBallFormData {
venue_description?: string // 场地描述 venue_description?: string // 场地描述
venue_image_list?: string[] // 场地图片 venue_image_list?: string[] // 场地图片
} }
players: [number, number] // 人数要求 players: {
min: number,
max: number,
is_participate: boolean
} // 人数要求
skill_level: [number, number] // 水平要求(NTRP) skill_level: [number, number] // 水平要求(NTRP)
descriptionInfo: { descriptionInfo: {
description: string // 备注 description: string // 备注