From 3c91ee0e8876ddde2447bc3db8318afbf3204ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Mon, 18 Aug 2025 23:34:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=80=E5=90=AF=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=80=99=E8=A1=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/index.ts | 2 +- project.config.json | 51 +++++++--- src/components/FormSwitch/FormSwitch.tsx | 28 ++++-- src/components/FormSwitch/index.scss | 22 ++--- src/components/Range/README.md | 93 +++++++++++++++++++ src/components/Range/example.tsx | 85 +++++++++++++++++ src/components/Range/index.module.scss | 84 +++++++++++++++++ src/components/Range/index.tsx | 93 +++++++++++++++++++ src/components/Range/simple-test.tsx | 22 +++++ src/components/Range/style-test.tsx | 68 ++++++++++++++ src/components/Range/test.tsx | 35 +++++++ src/components/Title/index.module.scss | 11 +++ src/components/Title/index.tsx | 19 ++++ src/components/index.ts | 4 +- .../formSchema/publishBallFormSchema.ts | 17 +++- src/pages/publishBall/index.scss | 51 ++-------- src/pages/publishBall/index.tsx | 65 +------------ src/pages/publishBall/publishForm.tsx | 53 ++--------- types/publishBall.ts | 16 ++++ 19 files changed, 629 insertions(+), 190 deletions(-) create mode 100644 src/components/Range/README.md create mode 100644 src/components/Range/example.tsx create mode 100644 src/components/Range/index.module.scss create mode 100644 src/components/Range/index.tsx create mode 100644 src/components/Range/simple-test.tsx create mode 100644 src/components/Range/style-test.tsx create mode 100644 src/components/Range/test.tsx create mode 100644 src/components/Title/index.module.scss create mode 100644 src/components/Title/index.tsx create mode 100644 types/publishBall.ts diff --git a/config/index.ts b/config/index.ts index 1e0d4ef..7c4734e 100644 --- a/config/index.ts +++ b/config/index.ts @@ -58,7 +58,7 @@ export default defineConfig<'webpack5'>(async (merge, { command, mode }) => { } }, cssModules: { - enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true + enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true config: { namingPattern: 'module', // 转换模式,取值为 global/module generateScopedName: '[name]__[local]___[hash:base64:5]' diff --git a/project.config.json b/project.config.json index 46dc372..3d3f556 100644 --- a/project.config.json +++ b/project.config.json @@ -2,24 +2,45 @@ "miniprogramRoot": "dist/", "projectname": "playBallTogether", "description": "playBallTogether", - "appid": "touristappid", + "appid": "wx815b533167eb7b53", "setting": { - "urlCheck": true, - "es6": false, - "enhance": false, - "compileHotReLoad": false, - "postcss": false, - "preloadBackgroundData": false, - "minified": false, - "newFeature": true, - "autoAudits": false, - "coverView": true, - "showShadowRootInWxmlPanel": false, - "scopeDataCheck": false, - "useCompilerModule": false + "urlCheck": true, + "es6": true, + "enhance": true, + "postcss": false, + "preloadBackgroundData": false, + "minified": false, + "newFeature": true, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": false, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": false, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "enableEngineNative": false, + "useIsolateContext": true, + "useCompilerModule": false, + "userConfirmedUseCompilerModuleSwitch": false, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "minifyWXML": true }, "compileType": "miniprogram", "simulatorType": "wechat", "simulatorPluginLibVersion": {}, "condition": {} -} + } \ No newline at end of file diff --git a/src/components/FormSwitch/FormSwitch.tsx b/src/components/FormSwitch/FormSwitch.tsx index b549a05..d08470e 100644 --- a/src/components/FormSwitch/FormSwitch.tsx +++ b/src/components/FormSwitch/FormSwitch.tsx @@ -1,6 +1,6 @@ -import React from 'react' +import React, { useState } from 'react' import { View, Text } from '@tarojs/components' -import { Checkbox } from '@nutui/nutui-react-taro' +import { Checkbox, Popover } from '@nutui/nutui-react-taro' import { Image } from '@tarojs/components' import images from '@/config/images' import './index.scss' @@ -8,19 +8,35 @@ import './index.scss' interface FormSwitchProps { value: boolean onChange: (checked: boolean) => void - title: string + subTitle: string infoIcon?: string showToast?: boolean + description?: string } -const FormSwitch: React.FC = ({ value, onChange, title, infoIcon, showToast = false}) => { +const FormSwitch: React.FC = ({ value, onChange, subTitle, infoIcon, showToast = false, description}) => { + const [dark, setDark] = useState(false) return ( - {title} + {subTitle} { - showToast && + showToast && { + dark ? setDark(false) : setDark(true) + }} + > + + } { + const [value, setValue] = useState<[number, number]>([2.0, 4.0]); + + return ( + + ); +}; +``` + +## 属性说明 + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `min` | `number` | `2.0` | 最小值 | +| `max` | `number` | `4.0` | 最大值 | +| `step` | `number` | `0.5` | 步长 | +| `value` | `[number, number]` | `[min, max]` | 当前选择的范围值 | +| `onChange` | `(value: [number, number]) => void` | - | 值变化时的回调函数 | +| `disabled` | `boolean` | `false` | 是否禁用 | + +## 技术实现 + +- 基于NutUI Range组件,确保拖拽功能的可靠性 +- 通过CSS样式覆盖,完全匹配设计稿视觉效果 +- TypeScript + React Hooks +- 响应式设计,支持移动端 + +## 设计规范 + +组件严格按照设计稿实现,包含以下视觉元素: + +- **网球图标**: 黑色轮廓的网球图标 +- **标题**: "NTRP水平区间" 文字 +- **标签**: 左右两端的范围标签(如"2.0及以下"、"4.0及以上") +- **滑块轨道**: 圆角矩形容器,带有浅灰色边框和阴影 +- **滑块手柄**: 两个白色圆形手柄,带有黑色边框和阴影 +- **轨道填充**: 黑色填充条,显示当前选择的范围 +- **标记点**: 四个浅灰色圆点,均匀分布在轨道上 + +## 样式定制 + +组件使用 BEM 命名规范,可以通过 CSS 变量或覆盖样式来自定义外观: + +```scss +.ntrp-range { + // 自定义样式 + &__track { + background: #f5f5f5; + border-color: #d0d0d0; + } + + &__handle { + background: #007bff; + border-color: #0056b3; + } +} +``` + +## 注意事项 + +1. 确保 `min < max`,否则组件可能无法正常工作 +2. `step` 值应该能够整除 `max - min` 的差值 +3. 组件内部会确保左右滑块不会重叠,最小间距为 `step` 值 +4. 拖拽时会自动吸附到最近的步长值 + +## 示例 + +查看 `example.tsx` 文件获取更多使用示例。 diff --git a/src/components/Range/example.tsx b/src/components/Range/example.tsx new file mode 100644 index 0000000..a9b65df --- /dev/null +++ b/src/components/Range/example.tsx @@ -0,0 +1,85 @@ +/* + * @Author: juguohong juguohong@flashhold.com + * @Date: 2025-08-16 17:59:28 + * @LastEditors: juguohong juguohong@flashhold.com + * @LastEditTime: 2025-08-16 23:48:25 + * @FilePath: /mini-programs/src/components/Range/example.tsx + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import React, { useState } from 'react'; +import NtrpRange from './index'; + +const RangeExample: React.FC = () => { + const [ntrpRange, setNtrpRange] = useState<[number, number]>([2.0, 4.0]); + const [customRange, setCustomRange] = useState<[number, number]>([0, 100]); + + const handleNtrpChange = (value: [number, number]) => { + console.log('NTRP range changed:', value); + setNtrpRange(value); + }; + + const handleCustomChange = (value: [number, number]) => { + console.log('Custom range changed:', value); + setCustomRange(value); + }; + + return ( +
+

Range 组件示例

+ +
+

NTRP 水平区间选择器

+ +
+ 当前选择范围: {ntrpRange[0]} - {ntrpRange[1]} +
+
+ +
+

自定义范围选择器

+ +
+ 当前选择范围: {customRange[0]} - {customRange[1]} +
+
+ +
+

禁用状态

+ +
+ 此选择器已被禁用 +
+
+ +
+

测试说明

+
+

1. 点击并拖拽左右滑块手柄

+

2. 查看控制台日志确认拖拽事件

+

3. 观察滑块位置和值的实时变化

+

4. 检查调试信息显示

+
+
+
+ ); +}; + +export default RangeExample; diff --git a/src/components/Range/index.module.scss b/src/components/Range/index.module.scss new file mode 100644 index 0000000..8ec582d --- /dev/null +++ b/src/components/Range/index.module.scss @@ -0,0 +1,84 @@ + + +// 全局NutUI样式覆盖 +.nutRange { + width: 100% !important; + height: 100% !important; + + // .nut-range__bar-box { + // margin: 0 !important; + // padding: 0 !important; + // } + + // .nut-range__bar { + // margin: 0 !important; + // } +} + +.nutRangeHeader { + line-height: 20px; + display: flex; + align-items: center; + justify-content: space-between; + .nutRangeHeaderLeft { + display: flex; + align-items: center; + gap: 8px; + } + .nutRangeHeaderTitle { + font-weight: 600; + font-size: 14px; + color: #000000; + } + + .nutRangeHeaderContent { + font-weight: 400; + font-size: 14px; + color: #3c3c34; + } +} + +.rangeWrapper { + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + height: 44px; + border-radius: 12px; + border: 1px solid #e0e0e0; + padding: 0 10px; + .rangeHandle { + :global(.nut-range-mark) { + padding-top: 28px; + left: 8px; + } + :global(.nut-range-bar) { + background: #000000; + height: 6px; + } + :global(.nut-range-button) { + border: none; + box-shadow: 0 6px 13px 0 rgba(0, 0, 0, 0.12); + } + + :global(.nut-range-tick) { + background: rgba(60, 60, 67, 0.18); + height: 4px !important; + width: 4px !important; + } + :global(.nut-range) { + background-color: rgba(120, 120, 120, 0.20) !important; + } + } + + span { + font-size: 12px; + color: #999; + } + .rangeWrapperMin, + .rangeWrapperMax { + flex-shrink: 0; + font-size: 12px; + color: #000000; + } +} diff --git a/src/components/Range/index.tsx b/src/components/Range/index.tsx new file mode 100644 index 0000000..9347f96 --- /dev/null +++ b/src/components/Range/index.tsx @@ -0,0 +1,93 @@ +import React, { useState, useEffect, useMemo } from "react"; +import { Range } from "@nutui/nutui-react-taro"; +import styles from "./index.module.scss"; +import TitleComponent from "../Title"; + +interface RangeProps { + min?: number; + max?: number; + step?: number; + value?: [number, number]; + onChange?: (value: [number, number]) => void; + disabled?: boolean; + className?: string; + showTitle?: boolean; +} + +const NtrpRange: React.FC = ({ + min = 1.0, + max = 5.0, + step = 0.5, + value = [min, max], + onChange, + disabled = false, + className, + showTitle = true, +}) => { + const [currentValue, setCurrentValue] = useState<[number, number]>(value); + + useEffect(() => { + value && setCurrentValue(value); + }, [JSON.stringify(value || [])]); + + const handleChange = (val: [number, number]) => { + setCurrentValue(val); + onChange?.(val); + }; + + const marks = useMemo(() => { + let marksMap = {}; + for (let i = min + step; i < max; i += step) { + marksMap[i] = ""; + } + return marksMap; + }, [min, max, step]); + + const rangContent = useMemo(() => { + const [start, end] = currentValue || []; + if (Number(start) === Number(min) && Number(end) === Number(max)) { + return "不限"; + } + return `${start.toFixed(1)} - ${end.toFixed(1)}之间`; + }, [JSON.stringify(currentValue || []), min, max]); + + return ( +
+ { showTitle && ( +
+ {/*
+
icon
+

NTRP水平区间

+
*/} + +

{rangContent}

+
+ )} + + +
+
+ {min.toFixed(1)} + + {max.toFixed(1)} +
+
+
+ ); +}; + +export default NtrpRange; diff --git a/src/components/Range/simple-test.tsx b/src/components/Range/simple-test.tsx new file mode 100644 index 0000000..f874642 --- /dev/null +++ b/src/components/Range/simple-test.tsx @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import NtrpRange from './index'; + +const SimpleTest: React.FC = () => { + const [value, setValue] = useState<[number, number]>([2.0, 4.0]); + + return ( +
+

简单测试

+ +

当前值: {value[0]} - {value[1]}

+
+ ); +}; + +export default SimpleTest; diff --git a/src/components/Range/style-test.tsx b/src/components/Range/style-test.tsx new file mode 100644 index 0000000..60134d0 --- /dev/null +++ b/src/components/Range/style-test.tsx @@ -0,0 +1,68 @@ +import React, { useState } from 'react'; +import NtrpRange from './index'; + +const StyleTest: React.FC = () => { + const [value, setValue] = useState<[number, number]>([2.0, 4.0]); + + return ( +
+

NtrpRange 样式测试

+ +
+

NTRP 水平区间选择器

+ +
+ 当前选择范围: {value[0]} - {value[1]} +
+
+ +
+

自定义范围选择器

+ console.log('Custom range:', val)} + /> +
+ 固定范围: 20 - 80 +
+
+ +
+

禁用状态

+ +
+ 此选择器已被禁用 +
+
+ +
+

样式说明

+
+

✅ 网球图标 + "NTRP水平区间"标题

+

✅ 左右范围标签("2.0及以下"、"4.0及以上")

+

✅ 圆角矩形轨道容器,带有边框和阴影

+

✅ 白色圆形滑块手柄,黑色边框和阴影

+

✅ 黑色轨道填充条

+

✅ 五个浅灰色标记点

+
+
+
+ ); +}; + +export default StyleTest; diff --git a/src/components/Range/test.tsx b/src/components/Range/test.tsx new file mode 100644 index 0000000..624772c --- /dev/null +++ b/src/components/Range/test.tsx @@ -0,0 +1,35 @@ +import React, { useState } from 'react'; +import NtrpRange from './index'; + +const TestPage: React.FC = () => { + const [value, setValue] = useState<[number, number]>([2.0, 4.0]); + + return ( +
+

NtrpRange 组件测试

+ +
+ +
+ +
+ 当前值: {value[0].toFixed(1)} - {value[1].toFixed(1)} +
+ +
+

测试说明:

+

1. 拖拽左右滑块手柄

+

2. 观察值的变化

+

3. 检查样式是否正确

+
+
+ ); +}; + +export default TestPage; diff --git a/src/components/Title/index.module.scss b/src/components/Title/index.module.scss new file mode 100644 index 0000000..a731606 --- /dev/null +++ b/src/components/Title/index.module.scss @@ -0,0 +1,11 @@ +.titleContainer { + display: flex; + align-items: center; + margin-bottom: 10px; + gap: 6px; +} +.title { + font-weight: 600; + font-size: 16px; + line-height: 20px; +} diff --git a/src/components/Title/index.tsx b/src/components/Title/index.tsx new file mode 100644 index 0000000..2eca985 --- /dev/null +++ b/src/components/Title/index.tsx @@ -0,0 +1,19 @@ +import styles from "./index.module.scss"; +interface IProps { + title: string; + className?: string; +} +const TitleComponent = (props: IProps) => { + const { title, className } = props; + return ( + <> +
+
+

{title}

+
+ + ); +}; +export default TitleComponent; diff --git a/src/components/index.ts b/src/components/index.ts index 80ab7e6..f3493b1 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -3,7 +3,7 @@ import TextareaTag from './TextareaTag' import FormSwitch from './FormSwitch' import CoverImageUpload from './CoverImageUpload' import FormBasicInfo from './FormBasicInfo' -import NTRPSlider from './NTRPSlider' +import Range from './Range' import ParticipantsControl from './ParticipantsControl' import { SelectStadium, StadiumDetail } from './SelectStadium' import TimeSelector from './TimeSelector' @@ -15,7 +15,7 @@ export { FormSwitch, CoverImageUpload, FormBasicInfo, - NTRPSlider, + Range, ParticipantsControl, SelectStadium, TimeSelector, diff --git a/src/config/formSchema/publishBallFormSchema.ts b/src/config/formSchema/publishBallFormSchema.ts index 67fb540..8eaf89d 100644 --- a/src/config/formSchema/publishBallFormSchema.ts +++ b/src/config/formSchema/publishBallFormSchema.ts @@ -143,8 +143,11 @@ export const publishBallFormSchema: FormFieldConfig[] = [ placeholder: '请选择开始时间', required: true, props: { - min: 2.0, - max: 4.0, + showTitle: false, + className: 'ntrp-range', + step: 0.5, + min: 1.0, + max: 5.0, } }, { @@ -165,11 +168,15 @@ export const publishBallFormSchema: FormFieldConfig[] = [ }, { key: 'autoDegrade', - label: '开启自动候补逻辑', + label: '', type: FieldType.CHECKBOX, placeholder: '开启自动候补逻辑', - required: true, - description: '开启后,当活动人数不足时,系统会自动将活动状态改为“候补”,并通知用户。', + required: true, + props:{ + subTitle: '开启自动候补逻辑', + showToast: true, + description: '开启后,当活动人数不足时,系统会自动将活动状态改为“候补”,并通知用户。', + }, rules: [ { required: true, message: '请选择开启自动候补逻辑' } ] diff --git a/src/pages/publishBall/index.scss b/src/pages/publishBall/index.scss index 9d73241..ef6d988 100644 --- a/src/pages/publishBall/index.scss +++ b/src/pages/publishBall/index.scss @@ -10,7 +10,7 @@ } &__content { - padding-bottom: 40px; + padding-bottom: 94px; } @@ -24,7 +24,11 @@ border: 1px solid rgba(0, 0, 0, 0.06); box-shadow: 0px 4px 36px 0px rgba(0, 0, 0, 0.06); display: flex; - + .ntrp-range{ + .rangeWrapper{ + border: none!important; + } + } } @@ -81,49 +85,6 @@ - // 自动降分选择 - 白色块 - .auto-degrade-section { - background: white; - border-radius: 16px; - padding: 20px 16px; - margin-bottom: 16px; - - .auto-degrade-item { - display: flex; - align-items: center; - justify-content: space-between; - - .auto-degrade-content { - display: flex; - align-items: center; - flex: 1; - - .auto-degrade-text { - font-size: 16px; - color: #333; - font-weight: 500; - user-select: none; - } - - .info-icon { - width: 16px; - height: 16px; - border: 1px solid #999; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - color: #999; - margin-left: 8px; - } - } - - .auto-degrade-checkbox { - margin-left: 16px; - } - } - } // 提交区域 .submit-section { diff --git a/src/pages/publishBall/index.tsx b/src/pages/publishBall/index.tsx index 8afce48..f979c1d 100644 --- a/src/pages/publishBall/index.tsx +++ b/src/pages/publishBall/index.tsx @@ -4,27 +4,12 @@ import Taro from '@tarojs/taro' import ActivityTypeSwitch, { type ActivityType } from '../../components/ActivityTypeSwitch' import PublishForm from './publishForm' import { publishBallFormSchema } from '../../config/formSchema/publishBallFormSchema'; +import { PublishBallFormData } from '../../../types/publishBall'; import './index.scss' -interface FormData { - activityType: ActivityType - title: string - timeRange: TimeRange - fee: string - location: string - gameplay: string - minParticipants: number - maxParticipants: number - ntpLevel: NTRPRange - additionalRequirements: string - autoDegrade: boolean -} const PublishBall: React.FC = () => { - const [coverImages, setCoverImages] = useState([]) - const [showStadiumSelector, setShowStadiumSelector] = useState(false) - const [selectedStadium, setSelectedStadium] = useState(null) - const [formData, setFormData] = useState({ + const [formData, setFormData] = useState({ activityType: 'individual', // 默认值 title: '', timeRange: { @@ -37,15 +22,12 @@ const PublishBall: React.FC = () => { gameplay: '', minParticipants: 1, maxParticipants: 4, - ntpLevel: { min: 2.0, max: 4.0 }, + ntpLevel: [2.0, 4.0], additionalRequirements: '', autoDegrade: false }) - // 处理封面图片变化 - const handleCoverImagesChange = (images: CoverImage[]) => { - setCoverImages(images) - } + // 更新表单数据 const updateFormData = (key: keyof FormData, value: any) => { @@ -57,35 +39,6 @@ const PublishBall: React.FC = () => { - // 获取人数要求显示文本 - const getParticipantsText = () => { - return `最少${formData.minParticipants}人,最多${formData.maxParticipants}人` - } - - // 处理NTRP范围变化 - const handleNTRPChange = (range: NTRPRange) => { - updateFormData('ntpLevel', range) - } - - // 处理时间范围变化 - const handleTimeRangeChange = (timeRange: TimeRange) => { - updateFormData('timeRange', timeRange) - } - - // 处理补充要求变化 - const handleAdditionalRequirementsChange = (value: string) => { - updateFormData('additionalRequirements', value) - } - - // 处理场馆选择 - const handleStadiumSelect = (stadium: Stadium | null) => { - setSelectedStadium(stadium) - if (stadium) { - updateFormData('location', stadium.name) - } - setShowStadiumSelector(false) - } - // 处理活动类型变化 const handleActivityTypeChange = (type: ActivityType) => { updateFormData('activityType', type) @@ -104,17 +57,7 @@ const PublishBall: React.FC = () => { }) return } - - if (coverImages.length === 0) { - Taro.showToast({ - title: '请至少上传一张活动封面', - icon: 'none' - }) - return - } - // TODO: 实现提交逻辑 - console.log('提交数据:', { coverImages, formData }) Taro.showToast({ title: '发布成功', diff --git a/src/pages/publishBall/publishForm.tsx b/src/pages/publishBall/publishForm.tsx index 4cdd023..c3ed9c1 100644 --- a/src/pages/publishBall/publishForm.tsx +++ b/src/pages/publishBall/publishForm.tsx @@ -2,30 +2,18 @@ import React, { useState } from 'react' import { View, Text } from '@tarojs/components' import Taro from '@tarojs/taro' -import { CoverImageUpload, NTRPSlider, TimeSelector, TextareaTag, SelectStadium, ParticipantsControl, TitleInput, FormBasicInfo, FormSwitch } from '../../components' -import { type NTRPRange, type TimeRange, type Stadium, type ActivityType, type CoverImage } from '../../components/index.types' +import { CoverImageUpload, Range, TimeSelector, TextareaTag, SelectStadium, ParticipantsControl, TitleInput, FormBasicInfo, FormSwitch } from '../../components' +import { type Stadium, type CoverImage } from '../../components/index.types' import { FormFieldConfig, FieldType } from '../../config/formSchema/publishBallFormSchema' -import './index.scss' +import { PublishBallFormData } from '../../../types/publishBall'; -interface FormData { - activityType: ActivityType - title: string - timeRange: TimeRange - fee: string - location: string - gameplay: string - minParticipants: number - maxParticipants: number - ntpLevel: NTRPRange - TextareaTag: string - autoDegrade: boolean -} +import './index.scss' // 组件映射器 const componentMap = { [FieldType.TEXT]: TitleInput, [FieldType.TIMEINTERVAL]: TimeSelector, - [FieldType.RANGE]: NTRPSlider, + [FieldType.RANGE]: Range, [FieldType.TEXTAREATAG]: TextareaTag, [FieldType.NUMBERINTERVAL]: ParticipantsControl, [FieldType.UPLOADIMAGE]: CoverImageUpload, @@ -34,8 +22,8 @@ const componentMap = { } const PublishForm: React.FC<{ - formData: FormData, - onChange: (key: keyof FormData, value: any) => void, + formData: PublishBallFormData, + onChange: (key: keyof PublishBallFormData, value: any) => void, optionsConfig: FormFieldConfig[] }> = ({ formData, onChange, optionsConfig }) => { const [coverImages, setCoverImages] = useState([]) const [showStadiumSelector, setShowStadiumSelector] = useState(false) @@ -53,26 +41,6 @@ const PublishForm: React.FC<{ - // 获取人数要求显示文本 - const getParticipantsText = () => { - return `最少${formData.minParticipants}人,最多${formData.maxParticipants}人` - } - - // 处理NTRP范围变化 - const handleNTRPChange = (range: NTRPRange) => { - updateFormData('ntpLevel', range) - } - - // 处理时间范围变化 - const handleTimeRangeChange = (timeRange: TimeRange) => { - updateFormData('timeRange', timeRange) - } - - // 处理补充要求变化 - const handleAdditionalRequirementsChange = (value: string) => { - updateFormData('additionalRequirements', value) - } - // 处理场馆选择 const handleStadiumSelect = (stadium: Stadium | null) => { setSelectedStadium(stadium) @@ -82,10 +50,6 @@ const PublishForm: React.FC<{ setShowStadiumSelector(false) } - // 处理活动类型变化 - const handleActivityTypeChange = (type: ActivityType) => { - updateFormData('activityType', type) - } @@ -128,7 +92,7 @@ const PublishForm: React.FC<{ ...item.props, ...(item.key === 'additionalRequirements' ? { options: item.options } : {}) } - console.log(optionProps, item.label); + console.log(optionProps, item.label, formData[item.key]); if (item.type === FieldType.UPLOADIMAGE) { /* 活动封面 */ return updateFormData(item.key as keyof FormData, value)} {...optionProps} diff --git a/types/publishBall.ts b/types/publishBall.ts new file mode 100644 index 0000000..4cc011b --- /dev/null +++ b/types/publishBall.ts @@ -0,0 +1,16 @@ +import { ActivityType, TimeRange } from "@/components/index.types" + + +export interface PublishBallFormData { + activityType: ActivityType + title: string + timeRange: TimeRange + fee: string + location: string + gameplay: string + minParticipants: number + maxParticipants: number + ntpLevel: number[] + additionalRequirements: string + autoDegrade: boolean +} \ No newline at end of file