修改发布
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
@use '~@/scss/images.scss' as img;
|
||||
@use '~@/scss/themeColor.scss' as theme;
|
||||
// FormBasicInfo 组件样式
|
||||
.form-basic-info{
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 100%;
|
||||
|
||||
|
||||
// 费用项目
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
padding-left: 12px;
|
||||
&:last-child{
|
||||
.form-wrapper{
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
padding-right: 14px;
|
||||
.lable-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
text {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.form-wrapper{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||
align-items: center;
|
||||
.form-item-label{
|
||||
display: flex;
|
||||
}
|
||||
.form-right-wrapper{
|
||||
display: flex;
|
||||
padding-right: 12px;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
align-items: center;
|
||||
.title-placeholder{
|
||||
font-size: 14px;
|
||||
color: theme.$textarea-placeholder-color;
|
||||
font-weight: 400;
|
||||
}
|
||||
.h5-input{
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.unit{
|
||||
font-size: 14px;
|
||||
color: theme.$primary-color;
|
||||
}
|
||||
.right-text{
|
||||
color: theme.$textarea-placeholder-color;
|
||||
font-size: 14px;
|
||||
padding-right: 8px;
|
||||
width: 200px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
.arrow{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 4px;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import React from 'react'
|
||||
import { View, Text, Input, Image, Picker } from '@tarojs/components'
|
||||
import { Stadium } from '../SelectStadium'
|
||||
import img from '@/config/images';
|
||||
import './FormBasicInfo.scss'
|
||||
import { FormFieldConfig } from '@/config/formSchema/publishBallFormSchema';
|
||||
|
||||
interface FormBasicInfoProps {
|
||||
fee: string
|
||||
location: string
|
||||
gameplay: string
|
||||
selectedStadium: Stadium | null
|
||||
onFeeChange: (value: string) => void
|
||||
onLocationChange: (value: string) => void
|
||||
onGameplayChange: (value: string) => void
|
||||
onStadiumSelect: () => void
|
||||
children: FormFieldConfig[]
|
||||
}
|
||||
|
||||
const FormBasicInfo: React.FC<FormBasicInfoProps> = ({
|
||||
fee,
|
||||
location,
|
||||
gameplay,
|
||||
selectedStadium,
|
||||
onFeeChange,
|
||||
onLocationChange,
|
||||
onGameplayChange,
|
||||
onStadiumSelect,
|
||||
children
|
||||
}) => {
|
||||
const renderChildren = () => {
|
||||
return children.map((child: any, index: number) => {
|
||||
return <View className='form-item'>
|
||||
<View className='form-label'>
|
||||
<Image className='lable-icon' src={img[child.iconType]} />
|
||||
</View>
|
||||
{
|
||||
index === 0 && (<View className='form-wrapper'>
|
||||
<Text className='form-item-label'>{child.label}</Text>
|
||||
<View className='form-right-wrapper'>
|
||||
<Input
|
||||
className='fee-input'
|
||||
placeholder='请输入'
|
||||
placeholderClass='title-placeholder'
|
||||
type='digit'
|
||||
value={fee}
|
||||
onInput={(e) => onFeeChange(e.detail.value)}
|
||||
/>
|
||||
<Text className='unit'>元/每人</Text>
|
||||
</View>
|
||||
</View>)
|
||||
}
|
||||
{
|
||||
index === 1 && (<View className='form-wrapper'>
|
||||
<Text className='form-item-label'>{child.label}</Text>
|
||||
<View className='form-right-wrapper' onClick={onStadiumSelect}>
|
||||
<Text className={`right-text ${selectedStadium ? 'selected' : ''}`}>
|
||||
{selectedStadium ? selectedStadium.name : '请选择'}
|
||||
</Text>
|
||||
<Image src={img.ICON_ARROW_RIGHT} className='arrow'/>
|
||||
</View>
|
||||
</View>)
|
||||
}
|
||||
{
|
||||
index === 2 && ( <View className='form-wrapper'>
|
||||
<Text className='form-item-label'>{child.label}</Text>
|
||||
<View className='form-right-wrapper'>
|
||||
<Text className={`right-text ${gameplay ? 'selected' : ''}`}>
|
||||
{gameplay ? gameplay : '请选择'}
|
||||
</Text>
|
||||
<Image src={img.ICON_ARROW_RIGHT} className='arrow'/>
|
||||
</View>
|
||||
</View>)
|
||||
}
|
||||
</View>
|
||||
})
|
||||
}
|
||||
return (
|
||||
<View className='form-basic-info'>
|
||||
{/* 费用 */}
|
||||
{renderChildren()}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormBasicInfo
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default } from './FormBasicInfo'
|
||||
export type { FormBasicInfoProps } from './FormBasicInfo'
|
||||
@@ -1,94 +0,0 @@
|
||||
# 球馆选择流程说明
|
||||
|
||||
## 🎯 完整流程
|
||||
|
||||
### 1. 初始状态 - 球馆列表
|
||||
用户看到球馆选择弹窗,显示:
|
||||
- 搜索框(可点击)
|
||||
- 热门球场标题
|
||||
- 球馆列表
|
||||
- 底部取消/完成按钮
|
||||
|
||||
### 2. 点击搜索框
|
||||
- 搜索框变为可点击状态
|
||||
- 点击后跳转到地图选择页面
|
||||
|
||||
### 3. 地图选择页面
|
||||
用户在地图页面可以:
|
||||
- 查看地图,选择位置
|
||||
- 在搜索框输入关键词搜索地点
|
||||
- 从搜索结果中选择地点
|
||||
- 点击"确定"按钮确认选择
|
||||
|
||||
### 4. 返回球馆详情
|
||||
选择地点后:
|
||||
- 自动跳转回球馆选择页面
|
||||
- 显示球馆详情配置页面
|
||||
- 新选择的球馆名称会显示在"已选球场"部分
|
||||
|
||||
### 5. 配置球馆详情
|
||||
用户可以配置:
|
||||
- 场地类型(室内/室外/室外雨棚)
|
||||
- 地面材质(硬地/红土/草地)
|
||||
- 场地信息补充(文本输入)
|
||||
|
||||
### 6. 完成选择
|
||||
- 点击"完成"按钮
|
||||
- 关闭弹窗,返回主页面
|
||||
- 选中的球馆信息传递给父组件
|
||||
|
||||
## 🔄 状态管理
|
||||
|
||||
```typescript
|
||||
// 主要状态
|
||||
const [showDetail, setShowDetail] = useState(false) // 是否显示详情页
|
||||
const [showMapSelector, setShowMapSelector] = useState(false) // 是否显示地图选择器
|
||||
const [selectedStadium, setSelectedStadium] = useState<Stadium | null>(null) // 选中的球馆
|
||||
```
|
||||
|
||||
## 📱 组件切换逻辑
|
||||
|
||||
```typescript
|
||||
// 组件渲染优先级
|
||||
if (showMapSelector) {
|
||||
return <MapSelector /> // 1. 地图选择器
|
||||
} else if (showDetail && selectedStadium) {
|
||||
return <StadiumDetail /> // 2. 球馆详情
|
||||
} else {
|
||||
return <SelectStadium /> // 3. 球馆列表
|
||||
}
|
||||
```
|
||||
|
||||
## 🗺️ 地图集成
|
||||
|
||||
- 使用 Taro 的 `Map` 组件
|
||||
- 支持地图标记和位置选择
|
||||
- 集成搜索功能,支持关键词搜索
|
||||
- 搜索结果包含地点名称、地址和距离信息
|
||||
|
||||
## 📋 数据传递
|
||||
|
||||
```typescript
|
||||
// 从地图选择器传递到球馆详情
|
||||
const handleMapLocationSelect = (location: Location) => {
|
||||
const newStadium: Stadium = {
|
||||
id: `map_${location.id}`,
|
||||
name: location.name, // 地图选择的球场名称
|
||||
address: location.address // 地图选择的球场地址
|
||||
}
|
||||
|
||||
// 添加到球馆列表并选择
|
||||
stadiumList.unshift(newStadium)
|
||||
setSelectedStadium(newStadium)
|
||||
setShowMapSelector(false)
|
||||
setShowDetail(true)
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 用户体验
|
||||
|
||||
1. **无缝切换**:三个页面共享同一个弹窗容器
|
||||
2. **状态保持**:选择的地点信息会正确传递
|
||||
3. **视觉反馈**:选中状态有明确的视觉指示
|
||||
4. **操作简单**:点击搜索即可进入地图选择
|
||||
5. **数据同步**:地图选择的球场会自动添加到球馆列表
|
||||
@@ -1,118 +0,0 @@
|
||||
# SelectStadium 球馆选择组件
|
||||
|
||||
这是一个球馆选择和详情的复合组件,包含两个主要功能:
|
||||
1. 球馆列表选择
|
||||
2. 球馆详情配置
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 🏟️ 球馆搜索和选择
|
||||
- 📱 响应式设计,适配移动端
|
||||
- 🔄 无缝切换球馆列表和详情页面
|
||||
- 🎯 支持场地类型、地面材质等配置
|
||||
- 📝 场地信息补充
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 基础用法
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react'
|
||||
import { SelectStadium, Stadium } from './components/SelectStadium'
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [showSelector, setShowSelector] = useState(false)
|
||||
const [selectedStadium, setSelectedStadium] = useState<Stadium | null>(null)
|
||||
|
||||
const handleStadiumSelect = (stadium: Stadium | null) => {
|
||||
setSelectedStadium(stadium)
|
||||
setShowSelector(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => setShowSelector(true)}>
|
||||
选择球馆
|
||||
</button>
|
||||
|
||||
<SelectStadium
|
||||
visible={showSelector}
|
||||
onClose={() => setShowSelector(false)}
|
||||
onConfirm={handleStadiumSelect}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 组件结构
|
||||
|
||||
```
|
||||
SelectStadium/
|
||||
├── SelectStadium.tsx # 主组件,管理状态和切换逻辑
|
||||
├── StadiumDetail.tsx # 球馆详情组件
|
||||
├── SelectStadium.scss # 球馆列表样式
|
||||
├── StadiumDetail.scss # 球馆详情样式
|
||||
├── index.ts # 导出文件
|
||||
└── README.md # 说明文档
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
### SelectStadium
|
||||
|
||||
| 属性 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| visible | boolean | 是 | 控制弹窗显示/隐藏 |
|
||||
| onClose | () => void | 是 | 关闭弹窗回调 |
|
||||
| onConfirm | (stadium: Stadium \| null) => void | 是 | 确认选择回调 |
|
||||
|
||||
### StadiumDetail
|
||||
|
||||
| 属性 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| stadium | Stadium | 是 | 选中的球馆信息 |
|
||||
| onBack | () => void | 是 | 返回球馆列表回调 |
|
||||
| onConfirm | (stadium, venueType, groundMaterial, additionalInfo) => void | 是 | 确认配置回调 |
|
||||
|
||||
## 数据接口
|
||||
|
||||
### Stadium
|
||||
|
||||
```typescript
|
||||
interface Stadium {
|
||||
id: string
|
||||
name: string
|
||||
address?: string
|
||||
}
|
||||
```
|
||||
|
||||
## 配置选项
|
||||
|
||||
### 场地类型
|
||||
- 室内
|
||||
- 室外
|
||||
- 室外雨棚
|
||||
|
||||
### 地面材质
|
||||
- 硬地
|
||||
- 红土
|
||||
- 草地
|
||||
|
||||
### 场地信息补充
|
||||
- 文本输入框,支持用户自定义备注信息
|
||||
|
||||
## 样式定制
|
||||
|
||||
组件使用 SCSS 编写,可以通过修改以下文件来自定义样式:
|
||||
|
||||
- `SelectStadium.scss` - 球馆列表样式
|
||||
- `StadiumDetail.scss` - 球馆详情样式
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 组件依赖 `@nutui/nutui-react-taro` 的 `Popup` 组件
|
||||
2. 确保在 Taro 环境中使用
|
||||
3. 组件内部管理状态,外部只需要控制 `visible` 属性
|
||||
4. 球馆列表数据在组件内部硬编码,实际使用时可以通过 props 传入
|
||||
5. StadiumDetail 组件现在只包含场地配置选项,去掉了头部、提醒和活动封面部分
|
||||
@@ -1,240 +0,0 @@
|
||||
|
||||
|
||||
.select-stadium {
|
||||
width: 100%;
|
||||
height: calc(100vh - 10px);
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
// 搜索区域
|
||||
.search-section {
|
||||
background: #f5f5f5;
|
||||
padding: 26px 15px 0px 15px;
|
||||
|
||||
.search-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.search-bar {
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
height: 44px;
|
||||
padding: 0 12px;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||
background: #FFF;
|
||||
box-shadow: 0 4px 48px 0 rgba(0, 0, 0, 0.08);
|
||||
.search-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
&:active {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.clear-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
.search-placeholder{
|
||||
color: rgba(60, 60, 67, 0.60);
|
||||
}
|
||||
}
|
||||
|
||||
.map-btn {
|
||||
display: flex;
|
||||
height: 44px;
|
||||
padding: 0 12px;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||
background: #FFF;
|
||||
box-shadow: 0 4px 48px 0 rgba(0, 0, 0, 0.08);
|
||||
box-sizing: border-box;
|
||||
&:active {
|
||||
background: #e0f0ff;
|
||||
}
|
||||
.map-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.map-text {
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 热门球场区域
|
||||
.hot-section {
|
||||
padding: 23px 20px 10px 20px;
|
||||
|
||||
.hot-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.hot-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
.hot-stadium-line{
|
||||
height: 6px;
|
||||
width: 1px;
|
||||
background: rgba(22, 24, 35, 0.12);
|
||||
margin: 0 12px;;
|
||||
}
|
||||
|
||||
.booking-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(0, 0, 0, 0.50);
|
||||
gap: 4px;
|
||||
|
||||
.booking-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.booking-status {
|
||||
display: flex;
|
||||
padding: 2px 5px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.16);
|
||||
background: #FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 场馆列表
|
||||
.stadium-list {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.stadium-item {
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
gap: 12px;
|
||||
.stadium-item-left{
|
||||
display: flex;
|
||||
padding: 14px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.08);
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
.stadium-icon{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
.stadium-item-right{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
.stadium-name{
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
display: flex;
|
||||
}
|
||||
.stadium-address{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: rgba(0, 0, 0, 0.80);
|
||||
font-size: 12px;
|
||||
}
|
||||
.stadium-map-icon{
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部按钮区域
|
||||
.bottom-actions {
|
||||
background: white;
|
||||
padding: 16px;
|
||||
padding-bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #e5e5e5;
|
||||
flex-shrink: 0;
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
||||
.cancel-btn,
|
||||
.confirm-btn {
|
||||
flex: 1;
|
||||
height: 48px;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #e0e0e0;
|
||||
|
||||
.cancel-text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background: #333;
|
||||
|
||||
.confirm-text {
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索框占位符样式
|
||||
.search-input::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Text, Input, ScrollView, Image } from '@tarojs/components'
|
||||
import { Popup } from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import StadiumDetail from './StadiumDetail'
|
||||
import CommonPopup from '../CommonPopup'
|
||||
import './SelectStadium.scss'
|
||||
import images from '@/config/images'
|
||||
|
||||
export interface Stadium {
|
||||
id?: string
|
||||
name: string
|
||||
address?: string
|
||||
istance?: string
|
||||
longitude?: number
|
||||
latitude?: number
|
||||
}
|
||||
|
||||
interface SelectStadiumProps {
|
||||
visible: boolean
|
||||
onClose: () => void
|
||||
onConfirm: (stadium: Stadium | null) => void
|
||||
}
|
||||
|
||||
const stadiumList: Stadium[] = [
|
||||
{ id: '1', name: '静安网球馆', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304},
|
||||
{ id: '2', name: '芦湾体育馆', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '3', name: '静安网球馆', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '4', name: '徐汇游泳中心', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '5', name: '汇龙新城小区', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '6', name: '翠湖御苑小区', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '7', name: '仁恒河滨花园网球场', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '8', name: 'Our Tennis 东江球场', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 },
|
||||
{ id: '9', name: '上海琦梦网球俱乐部', address: '浦东新区东园路18号', istance: '100米' , longitude: 121.4367, latitude: 31.2304 }
|
||||
]
|
||||
|
||||
const SelectStadium: React.FC<SelectStadiumProps> = ({
|
||||
visible,
|
||||
onClose,
|
||||
onConfirm
|
||||
}) => {
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
const [selectedStadium, setSelectedStadium] = useState<Stadium | null>(null)
|
||||
const [showDetail, setShowDetail] = useState(false)
|
||||
|
||||
if (!visible) return null
|
||||
|
||||
// 过滤场馆列表
|
||||
const filteredStadiums = stadiumList.filter(stadium =>
|
||||
stadium.name.toLowerCase().includes(searchValue.toLowerCase())
|
||||
)
|
||||
|
||||
// 处理场馆选择
|
||||
const handleStadiumSelect = (stadium: Stadium) => {
|
||||
setSelectedStadium(stadium)
|
||||
setShowDetail(true)
|
||||
}
|
||||
|
||||
// 处理返回球馆列表
|
||||
const handleBackToList = () => {
|
||||
setShowDetail(false)
|
||||
setSelectedStadium(null)
|
||||
}
|
||||
|
||||
// 处理搜索框输入
|
||||
const handleSearchInput = (e: any) => {
|
||||
setSearchValue(e.detail.value)
|
||||
}
|
||||
|
||||
// 处理地图选择位置
|
||||
const handleMapLocation = () => {
|
||||
Taro.chooseLocation({
|
||||
success: (res) => {
|
||||
console.log('选择位置成功:', res)
|
||||
setSelectedStadium({
|
||||
name: res.name,
|
||||
address: res.address,
|
||||
longitude: res.longitude,
|
||||
latitude: res.latitude
|
||||
})
|
||||
setShowDetail(true)
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择位置失败:', err)
|
||||
Taro.showToast({
|
||||
title: '位置选择失败',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 处理确认
|
||||
const handleConfirm = (stadium: Stadium, venueType: string, groundMaterial: string, additionalInfo: string) => {
|
||||
// 这里可以处理球馆详情的信息
|
||||
console.log('球馆详情:', { stadium, venueType, groundMaterial, additionalInfo })
|
||||
onConfirm(stadium)
|
||||
setShowDetail(false)
|
||||
setSelectedStadium(null)
|
||||
setSearchValue('')
|
||||
}
|
||||
|
||||
// 处理球馆列表确认
|
||||
const handleListConfirm = () => {
|
||||
if (selectedStadium) {
|
||||
onConfirm(selectedStadium)
|
||||
setSelectedStadium(null)
|
||||
setSearchValue('')
|
||||
}
|
||||
}
|
||||
|
||||
// 处理取消
|
||||
const handleCancel = () => {
|
||||
onClose()
|
||||
setShowDetail(false)
|
||||
setSelectedStadium(null)
|
||||
setSearchValue('')
|
||||
}
|
||||
|
||||
const handleItemLocation = (stadium: Stadium) => {
|
||||
console.log(stadium,'stadiumstadium');
|
||||
if(stadium.latitude && stadium.longitude){
|
||||
Taro.openLocation({
|
||||
latitude: stadium.latitude,
|
||||
longitude: stadium.longitude,
|
||||
name: stadium.name,
|
||||
address: stadium.address,
|
||||
success: (res) => {
|
||||
console.log(res,'resres');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const markSearchText = (text: string) => {
|
||||
return text.replace(searchValue, `<span style="color: #007AFF;">${searchValue}</span>`)
|
||||
}
|
||||
|
||||
// 如果显示详情页面
|
||||
if (showDetail && selectedStadium) {
|
||||
return (
|
||||
<CommonPopup
|
||||
visible={visible}
|
||||
onClose={handleCancel}
|
||||
cancelText="返回"
|
||||
confirmText="确认"
|
||||
className="select-stadium-popup"
|
||||
onCancel={handleCancel}
|
||||
onConfirm={handleListConfirm}
|
||||
position="bottom"
|
||||
round
|
||||
>
|
||||
<StadiumDetail
|
||||
stadium={selectedStadium}
|
||||
onBack={handleBackToList}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
</CommonPopup>
|
||||
)
|
||||
}
|
||||
|
||||
// 显示球馆列表
|
||||
return (
|
||||
<CommonPopup
|
||||
visible={visible}
|
||||
hideFooter
|
||||
onClose={handleCancel}
|
||||
cancelText="返回"
|
||||
confirmText="完成"
|
||||
className="select-stadium-popup"
|
||||
onCancel={handleCancel}
|
||||
onConfirm={handleListConfirm}
|
||||
position="bottom"
|
||||
round
|
||||
>
|
||||
|
||||
<View className='select-stadium'>
|
||||
{/* 搜索框 */}
|
||||
<View className='search-section'>
|
||||
<View className='search-wrapper'>
|
||||
<View className='search-bar'>
|
||||
<Image src={images.ICON_SEARCH} className='search-icon' />
|
||||
<Input
|
||||
className='search-input'
|
||||
placeholder='搜索'
|
||||
placeholderClass='search-placeholder'
|
||||
value={searchValue}
|
||||
onInput={handleSearchInput}
|
||||
/>
|
||||
{searchValue && (
|
||||
<View className='clear-btn' onClick={() => setSearchValue('')}>
|
||||
<Image src={images.ICON_REMOVE} className='clear-icon' />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
{
|
||||
!searchValue && (
|
||||
<View className='map-btn' onClick={handleMapLocation}>
|
||||
<Image src={images.ICON_MAP} className='map-icon' />
|
||||
<Text className='map-text'>地图</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 热门球场标题 */}
|
||||
<View className='hot-section'>
|
||||
<View className='hot-header'>
|
||||
<Text className='hot-title'>热门球场</Text>
|
||||
<View className='hot-stadium-line'></View>
|
||||
<View className='booking-section'>
|
||||
<Text className='booking-title'>预定球场</Text>
|
||||
<Text className='booking-status'>敬请期待</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 场馆列表 */}
|
||||
<ScrollView className='stadium-list' scrollY>
|
||||
{filteredStadiums.map((stadium) => (
|
||||
<View
|
||||
key={stadium.id}
|
||||
className={`stadium-item ${selectedStadium?.id === stadium.id ? 'selected' : ''}`}
|
||||
onClick={() => handleStadiumSelect(stadium)}
|
||||
>
|
||||
<View className='stadium-item-left'>
|
||||
<Image src={images.ICON_STADIUM} className='stadium-icon' />
|
||||
</View>
|
||||
<View className='stadium-item-right'>
|
||||
<View className='stadium-name' dangerouslySetInnerHTML={{ __html: markSearchText(stadium.name) }}></View>
|
||||
<View className='stadium-address' >
|
||||
<Text onClick={(e) => { e.stopPropagation(); handleItemLocation(stadium); }}>{stadium.istance} · </Text>
|
||||
<Text onClick={(e) => { e.stopPropagation(); handleItemLocation(stadium); }}>{stadium.address}</Text>
|
||||
<Image src={images.ICON_ARRORW_SMALL} className='stadium-map-icon' />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
))}
|
||||
{
|
||||
searchValue && (<View
|
||||
className={`stadium-item`}
|
||||
onClick={() => handleMapLocation()}
|
||||
>
|
||||
<View className='stadium-item-left'>
|
||||
<Image src={images.ICON_MAP_SEARCH} className='stadium-icon' />
|
||||
</View>
|
||||
<View className='stadium-item-right'>
|
||||
<View className='stadium-name'>没有找到球场?去地图定位</View>
|
||||
<View className='stadium-address'>
|
||||
<Text>腾讯地图</Text>
|
||||
<Image src={images.ICON_ARRORW_SMALL} className='stadium-map-icon' />
|
||||
</View>
|
||||
</View>
|
||||
</View>)
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</CommonPopup>
|
||||
)
|
||||
}
|
||||
|
||||
export default SelectStadium
|
||||
@@ -1,193 +0,0 @@
|
||||
.stadium-detail {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: 60vh;
|
||||
background: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
// 已选球场
|
||||
// 场馆列表
|
||||
.stadium-item {
|
||||
padding: 32px 20px 16px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
gap: 12px;
|
||||
.stadium-item-left{
|
||||
display: flex;
|
||||
padding: 14px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.08);
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
.stadium-icon{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
.stadium-item-right{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
.stadium-name{
|
||||
font-size: 16px;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
display: flex;
|
||||
}
|
||||
.stadium-address{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: rgba(0, 0, 0, 0.80);
|
||||
font-size: 12px;
|
||||
}
|
||||
.stadium-map-icon{
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 场地类型
|
||||
.venue-type-section {
|
||||
flex-shrink: 0;
|
||||
|
||||
.section-title {
|
||||
padding: 18px 20px 10px 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
.heart-wrapper{
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.heart-icon{
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
z-index: 1;
|
||||
}
|
||||
.icon-bg{
|
||||
border-radius: 1.6px;
|
||||
width: 165px;
|
||||
height: 17px;
|
||||
flex-shrink: 0;
|
||||
border: 0.5px solid rgba(238, 255, 135, 0.00);
|
||||
opacity: 0.4;
|
||||
background: linear-gradient(258deg, rgba(220, 250, 97, 0.00) 6.85%, rgba(228, 255, 59, 0.82) 91.69%);
|
||||
backdrop-filter: blur(1.25px);
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 4px;
|
||||
}
|
||||
.heart-text{
|
||||
font-size: 12px;
|
||||
color: rgba(0, 0, 0, 0.90);
|
||||
z-index: 2;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.option-buttons {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 0 15px;
|
||||
.textarea-tag-container{
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
background: #FFF;
|
||||
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.option-btn {
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e0e0e0;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||
background: #FFF;
|
||||
font-weight: 500;
|
||||
&.selected {
|
||||
background: #000;
|
||||
border-color: #fff;
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.06);
|
||||
.option-text {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.option-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 底部按钮
|
||||
.bottom-actions {
|
||||
background: white;
|
||||
padding: 16px;
|
||||
padding-bottom: calc(16px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #e5e5e5;
|
||||
flex-shrink: 0;
|
||||
margin-top: auto;
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
||||
.cancel-btn,
|
||||
.confirm-btn {
|
||||
flex: 1;
|
||||
height: 48px;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: white;
|
||||
border: 1px solid #e0e0e0;
|
||||
|
||||
.cancel-text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background: #333;
|
||||
|
||||
.confirm-text {
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { View, Text, Image } from '@tarojs/components'
|
||||
import images from '@/config/images'
|
||||
import './StadiumDetail.scss'
|
||||
import TextareaTag from '@/components/TextareaTag'
|
||||
import CoverImageUpload, { type CoverImage } from '@/components/ImageUpload'
|
||||
|
||||
export interface Stadium {
|
||||
id?: string
|
||||
name: string
|
||||
address?: string
|
||||
longitude?: number
|
||||
latitude?: number
|
||||
istance?: string
|
||||
}
|
||||
|
||||
interface StadiumDetailProps {
|
||||
stadium: Stadium
|
||||
onBack: () => void
|
||||
onConfirm: (stadium: Stadium, venueType: string, groundMaterial: string, additionalInfo: string) => void
|
||||
}
|
||||
|
||||
const stadiumInfo = [
|
||||
{
|
||||
label: '场地类型',
|
||||
options: ['室内', '室外', '室外雨棚'],
|
||||
prop: 'venueType',
|
||||
type: 'tags'
|
||||
},
|
||||
{
|
||||
label: '地面材质',
|
||||
options: ['硬地', '红土', '草地'],
|
||||
prop: 'groundMaterial',
|
||||
type: 'tags'
|
||||
},
|
||||
{
|
||||
label: '场地信息补充',
|
||||
options: ['1号场', '2号场', '3号场', '4号场', '有空调', '6号场','6号场'],
|
||||
prop: 'additionalInfo',
|
||||
type: 'textareaTag'
|
||||
},
|
||||
{
|
||||
label: '场地预定截图',
|
||||
options: ['有其他场地信息可备注'],
|
||||
prop: 'imagesList',
|
||||
type: 'image'
|
||||
}
|
||||
]
|
||||
|
||||
// 公共的标题组件
|
||||
const SectionTitle: React.FC<{ title: string,prop: string }> = ({ title, prop }) => {
|
||||
console.log(prop,'propprop');
|
||||
if (prop === 'imagesList') {
|
||||
return (
|
||||
<View className='section-title'>
|
||||
<Text>{title}</Text>
|
||||
<View className='heart-wrapper'>
|
||||
<Image src={images.ICON_HEART_CIRCLE} className='heart-icon' />
|
||||
<View className='icon-bg'></View>
|
||||
<Text className='heart-text'>添加截图,平台会优先推荐</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Text className='section-title'>{title}</Text>
|
||||
)
|
||||
}
|
||||
|
||||
// 公共的容器组件
|
||||
const SectionContainer: React.FC<{ title: string; children: React.ReactNode, prop: string }> = ({ title, children, prop }) => (
|
||||
<View className='venue-type-section'>
|
||||
<SectionTitle title={title} prop={prop}/>
|
||||
<View className='option-buttons'>
|
||||
{children}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
||||
const StadiumDetail: React.FC<StadiumDetailProps> = ({
|
||||
stadium,
|
||||
}) => {
|
||||
const [formData, setFormData] = useState({
|
||||
stadiumName: stadium.name,
|
||||
stadiumAddress: stadium.address,
|
||||
stadiumLongitude: stadium.longitude,
|
||||
stadiumLatitude: stadium.latitude,
|
||||
istance: stadium.istance,
|
||||
venueType: '室内',
|
||||
groundMaterial: '硬地',
|
||||
additionalInfo: '',
|
||||
imagesList: [] as CoverImage[]
|
||||
})
|
||||
|
||||
|
||||
|
||||
const handleMapLocation = () => {
|
||||
Taro.chooseLocation({
|
||||
success: (res) => {
|
||||
console.log(res,'resres');
|
||||
setFormData({
|
||||
...formData,
|
||||
stadiumName: res.name,
|
||||
stadiumAddress: res.address,
|
||||
stadiumLongitude: res.longitude,
|
||||
stadiumLatitude: res.latitude
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择位置失败:', err)
|
||||
Taro.showToast({
|
||||
title: '位置选择失败',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const updateFormData = useCallback((prop: string, value: any) => {
|
||||
setFormData(prev => ({ ...prev, [prop]: value }))
|
||||
}, [])
|
||||
|
||||
const getSelectedByLabel = useCallback((label: string) => {
|
||||
if (label === '场地类型') return formData.venueType
|
||||
if (label === '地面材质') return formData.groundMaterial
|
||||
return ''
|
||||
}, [formData.venueType, formData.groundMaterial])
|
||||
|
||||
|
||||
console.log(stadium,'stadiumstadium');
|
||||
return (
|
||||
<View className='stadium-detail'>
|
||||
{/* 已选球场 */}
|
||||
<View
|
||||
className={`stadium-item`}
|
||||
onClick={() => handleMapLocation()}
|
||||
>
|
||||
<View className='stadium-item-left'>
|
||||
<Image src={images.ICON_STADIUM} className='stadium-icon' />
|
||||
</View>
|
||||
<View className='stadium-item-right'>
|
||||
<View className='stadium-name'>{formData.stadiumName}</View>
|
||||
<View className='stadium-address'>
|
||||
<Text>{formData.istance} · </Text>
|
||||
<Text>{formData.stadiumAddress}</Text>
|
||||
<Image src={images.ICON_ARRORW_SMALL} className='stadium-map-icon' />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{stadiumInfo.map((item) => {
|
||||
if (item.type === 'tags') {
|
||||
const selected = getSelectedByLabel(item.label)
|
||||
return (
|
||||
<SectionContainer key={item.label} title={item.label} prop={item.prop}>
|
||||
{item.options.map((opt) => (
|
||||
<View
|
||||
key={opt}
|
||||
className={`option-btn ${selected === opt ? 'selected' : ''}`}
|
||||
onClick={() => updateFormData(item.prop, opt)}
|
||||
>
|
||||
<Text className='option-text'>{opt}</Text>
|
||||
</View>
|
||||
))}
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
||||
if (item.type === 'textareaTag') {
|
||||
return (
|
||||
<SectionContainer key={item.label} title={item.label} prop={item.prop}>
|
||||
<View className='textarea-tag-container'>
|
||||
<TextareaTag
|
||||
value={formData.additionalInfo}
|
||||
onChange={(value) => updateFormData(item.prop, value)}
|
||||
placeholder='有其他场地信息可备注'
|
||||
options={(item.options || []).map((o) => ({ label: o, value: o }))}
|
||||
/>
|
||||
</View>
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
||||
if (item.type === 'image') {
|
||||
return (
|
||||
<SectionContainer key={item.label} title={item.label} prop={item.prop}>
|
||||
<CoverImageUpload
|
||||
images={formData.imagesList}
|
||||
onChange={(images) => updateFormData(item.prop, images)}
|
||||
/>
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
})}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default StadiumDetail
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as SelectStadium } from './SelectStadium'
|
||||
export { default as StadiumDetail } from './StadiumDetail'
|
||||
export type { Stadium } from './SelectStadium'
|
||||
@@ -24,6 +24,7 @@ const TextareaTag: React.FC<TextareaTagProps> = ({
|
||||
}) => {
|
||||
// 处理输入框变化
|
||||
const [tags, setTags] = useState<string[]>([])
|
||||
console.log(value, 'options')
|
||||
const handleInputChange = useCallback((e: any) => {
|
||||
onChange(e.detail.value)
|
||||
}, [onChange])
|
||||
@@ -43,6 +44,7 @@ const TextareaTag: React.FC<TextareaTagProps> = ({
|
||||
onChange(newValue)
|
||||
}, [value, onChange])
|
||||
|
||||
console.log(options, 'options')
|
||||
return (
|
||||
<View className='textarea-tag'>
|
||||
{/* 选择选项 */}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react'
|
||||
import { View, Text, Picker } from '@tarojs/components'
|
||||
import { getDate, getTime } from '@/utils/timeUtils'
|
||||
import './TimeSelector.scss'
|
||||
|
||||
export interface TimeRange {
|
||||
startDate: string
|
||||
startTime: string
|
||||
endTime: string
|
||||
start_time: string
|
||||
end_time: string
|
||||
}
|
||||
|
||||
interface TimeSelectorProps {
|
||||
@@ -15,40 +15,13 @@ interface TimeSelectorProps {
|
||||
|
||||
const TimeSelector: React.FC<TimeSelectorProps> = ({
|
||||
value = {
|
||||
startDate: '',
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
start_time: '',
|
||||
end_time: ''
|
||||
},
|
||||
onChange
|
||||
}) => {
|
||||
// 格式化日期显示
|
||||
const formatDate = (dateStr: string) => {
|
||||
return dateStr.replace(/-/g, '年').replace(/-/g, '月') + '日'
|
||||
}
|
||||
|
||||
// 处理开始日期变化
|
||||
const handleStartDateChange = (e: any) => {
|
||||
onChange({
|
||||
...value,
|
||||
startDate: e.detail.value
|
||||
})
|
||||
}
|
||||
|
||||
// 处理开始时间变化
|
||||
const handleStartTimeChange = (e: any) => {
|
||||
onChange({
|
||||
...value,
|
||||
startTime: e.detail.value
|
||||
})
|
||||
}
|
||||
|
||||
// 处理结束时间变化
|
||||
const handleEndTimeChange = (e: any) => {
|
||||
onChange({
|
||||
...value,
|
||||
endTime: e.detail.value
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<View className='time-selector'>
|
||||
@@ -61,8 +34,8 @@ const TimeSelector: React.FC<TimeSelectorProps> = ({
|
||||
<View className='time-content'>
|
||||
<Text className='time-label'>开始时间</Text>
|
||||
<view className='time-text-wrapper'>
|
||||
<Text className='time-text'>2025年11月23日</Text>
|
||||
<Text className='time-text time-am'>8:00 AM</Text>
|
||||
<Text className='time-text'>{getDate(value.start_time)}</Text>
|
||||
<Text className='time-text time-am'>{getTime(value.start_time)}</Text>
|
||||
</view>
|
||||
</View>
|
||||
</View>
|
||||
@@ -75,8 +48,7 @@ const TimeSelector: React.FC<TimeSelectorProps> = ({
|
||||
<View className='time-content'>
|
||||
<Text className='time-label'>结束时间</Text>
|
||||
<view className='time-text-wrapper'>
|
||||
<Text className='time-text'>2025年11月23日</Text>
|
||||
<Text className='time-text time-am'>8:00 AM</Text>
|
||||
<Text className='time-text time-am'>{getTime(value.end_time)}</Text>
|
||||
</view>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './TitleInput'
|
||||
@@ -3,14 +3,14 @@ import { View } from '@tarojs/components'
|
||||
import { TextArea } from '@nutui/nutui-react-taro'
|
||||
import './index.scss'
|
||||
|
||||
interface TitleInputProps {
|
||||
interface TitleTextareaProps {
|
||||
value: string
|
||||
onChange: (value: string) => void
|
||||
maxLength?: number
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
const TitleInput: React.FC<TitleInputProps> = ({
|
||||
const TitleTextarea: React.FC<TitleTextareaProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
maxLength = 20,
|
||||
@@ -32,4 +32,4 @@ const TitleInput: React.FC<TitleInputProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default TitleInput
|
||||
export default TitleTextarea
|
||||
1
src/components/TitleTextarea/index.ts
Normal file
1
src/components/TitleTextarea/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './TitleTextarea'
|
||||
@@ -2,12 +2,11 @@ import ActivityTypeSwitch from './ActivityTypeSwitch'
|
||||
import TextareaTag from './TextareaTag'
|
||||
import FormSwitch from './FormSwitch'
|
||||
import ImageUpload from './ImageUpload'
|
||||
import FormBasicInfo from './FormBasicInfo'
|
||||
import Range from './Range'
|
||||
import NumberInterval from './NumberInterval'
|
||||
import { SelectStadium, StadiumDetail } from './SelectStadium'
|
||||
|
||||
import TimeSelector from './TimeSelector'
|
||||
import TitleInput from './TitleInput'
|
||||
import TitleTextarea from './TitleTextarea'
|
||||
import CommonPopup from './CommonPopup'
|
||||
|
||||
export {
|
||||
@@ -15,13 +14,10 @@ export {
|
||||
TextareaTag,
|
||||
FormSwitch,
|
||||
ImageUpload,
|
||||
FormBasicInfo,
|
||||
Range,
|
||||
NumberInterval,
|
||||
SelectStadium,
|
||||
TimeSelector,
|
||||
TitleInput,
|
||||
StadiumDetail,
|
||||
TitleTextarea,
|
||||
CommonPopup
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { type TimeRange } from './TimeSelector'
|
||||
import { type Stadium } from './SelectStadium'
|
||||
import { type ActivityType } from './ActivityTypeSwitch'
|
||||
import { type CoverImage } from './ImageUpload'
|
||||
export type { TimeRange, Stadium, ActivityType, CoverImage }
|
||||
export type { TimeRange, ActivityType, CoverImage }
|
||||
Reference in New Issue
Block a user