feat(src): 新增文章、经销商申请、用户地址和礼物添加功能
- 新增文章添加页面,支持文章基本信息、设置、高级设置和图片上传 - 新增经销商申请页面,支持申请信息填写和审核状态显示 - 新增用户地址添加页面,支持地址信息填写和地址识别功能 - 新增礼物添加页面,功能与文章添加类似 - 统一使用 .tsx 文件格式 - 添加 .editorconfig、.eslintrc 和 .gitignore 文件,规范代码风格和项目结构
This commit is contained in:
210
src/components/CouponFilter.tsx
Normal file
210
src/components/CouponFilter.tsx
Normal file
@@ -0,0 +1,210 @@
|
||||
import React, {useState} from 'react'
|
||||
import {View, Text} from '@tarojs/components'
|
||||
import {Button, Popup, Radio, RadioGroup, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Filter, Close} from '@nutui/icons-react-taro'
|
||||
|
||||
export interface CouponFilterProps {
|
||||
/** 是否显示筛选器 */
|
||||
visible: boolean
|
||||
/** 当前筛选条件 */
|
||||
filters: {
|
||||
type?: number[]
|
||||
minAmount?: number
|
||||
sortBy?: 'createTime' | 'amount' | 'expireTime'
|
||||
sortOrder?: 'asc' | 'desc'
|
||||
}
|
||||
/** 筛选条件变更回调 */
|
||||
onFiltersChange: (filters: any) => void
|
||||
/** 关闭回调 */
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const CouponFilter: React.FC<CouponFilterProps> = ({
|
||||
visible,
|
||||
filters,
|
||||
onFiltersChange,
|
||||
onClose
|
||||
}) => {
|
||||
const [tempFilters, setTempFilters] = useState(filters)
|
||||
|
||||
// 优惠券类型选项
|
||||
const typeOptions = [
|
||||
{label: '全部类型', value: ''},
|
||||
{label: '满减券', value: '10'},
|
||||
{label: '折扣券', value: '20'},
|
||||
{label: '免费券', value: '30'}
|
||||
]
|
||||
|
||||
// 最低金额选项
|
||||
const minAmountOptions = [
|
||||
{label: '不限', value: ''},
|
||||
{label: '10元以上', value: '10'},
|
||||
{label: '50元以上', value: '50'},
|
||||
{label: '100元以上', value: '100'},
|
||||
{label: '200元以上', value: '200'}
|
||||
]
|
||||
|
||||
// 排序选项
|
||||
const sortOptions = [
|
||||
{label: '创建时间', value: 'createTime'},
|
||||
{label: '优惠金额', value: 'amount'},
|
||||
{label: '到期时间', value: 'expireTime'}
|
||||
]
|
||||
|
||||
// 排序方向选项
|
||||
const sortOrderOptions = [
|
||||
{label: '升序', value: 'asc'},
|
||||
{label: '降序', value: 'desc'}
|
||||
]
|
||||
|
||||
// 重置筛选条件
|
||||
const handleReset = () => {
|
||||
const resetFilters = {
|
||||
type: [],
|
||||
minAmount: undefined,
|
||||
sortBy: 'createTime' as const,
|
||||
sortOrder: 'desc' as const
|
||||
}
|
||||
setTempFilters(resetFilters)
|
||||
}
|
||||
|
||||
// 应用筛选条件
|
||||
const handleApply = () => {
|
||||
onFiltersChange(tempFilters)
|
||||
onClose()
|
||||
}
|
||||
|
||||
// 更新临时筛选条件
|
||||
const updateTempFilters = (key: string, value: any) => {
|
||||
setTempFilters(prev => ({
|
||||
...prev,
|
||||
[key]: value
|
||||
}))
|
||||
}
|
||||
|
||||
return (
|
||||
<Popup
|
||||
visible={visible}
|
||||
position="right"
|
||||
style={{width: '80%', height: '100%'}}
|
||||
>
|
||||
<View className="h-full flex flex-col">
|
||||
{/* 头部 */}
|
||||
<View className="flex items-center justify-between p-4 border-b border-gray-100">
|
||||
<View className="flex items-center">
|
||||
<Filter size="20" className="text-gray-600 mr-2"/>
|
||||
<Text className="text-lg font-semibold">筛选条件</Text>
|
||||
</View>
|
||||
<View onClick={onClose}>
|
||||
<Close size="20" className="text-gray-600"/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 筛选内容 */}
|
||||
<View className="flex-1 overflow-y-auto p-4">
|
||||
{/* 优惠券类型 */}
|
||||
<View className="mb-6">
|
||||
<Text className="text-base font-semibold mb-3 text-gray-900">
|
||||
优惠券类型
|
||||
</Text>
|
||||
<RadioGroup
|
||||
value={tempFilters.type?.[0]?.toString() || ''}
|
||||
onChange={(value: any) => {
|
||||
updateTempFilters('type', value ? [parseInt(value)] : [])
|
||||
}}
|
||||
>
|
||||
{typeOptions.map(option => (
|
||||
<Radio key={option.value} value={option.value} className="mb-2">
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</View>
|
||||
|
||||
<Divider/>
|
||||
|
||||
{/* 最低消费金额 */}
|
||||
<View className="mb-6">
|
||||
<Text className="text-base font-semibold mb-3 text-gray-900">
|
||||
最低消费金额
|
||||
</Text>
|
||||
<RadioGroup
|
||||
value={tempFilters.minAmount?.toString() || ''}
|
||||
onChange={(value: any) => {
|
||||
updateTempFilters('minAmount', value ? parseInt(value) : undefined)
|
||||
}}
|
||||
>
|
||||
{minAmountOptions.map(option => (
|
||||
<Radio key={option.value} value={option.value} className="mb-2">
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</View>
|
||||
|
||||
<Divider/>
|
||||
|
||||
{/* 排序方式 */}
|
||||
<View className="mb-6">
|
||||
<Text className="text-base font-semibold mb-3 text-gray-900">
|
||||
排序方式
|
||||
</Text>
|
||||
<RadioGroup
|
||||
value={tempFilters.sortBy || 'createTime'}
|
||||
onChange={(value) => updateTempFilters('sortBy', value)}
|
||||
>
|
||||
{sortOptions.map(option => (
|
||||
<Radio key={option.value} value={option.value} className="mb-2">
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</View>
|
||||
|
||||
<Divider/>
|
||||
|
||||
{/* 排序方向 */}
|
||||
<View className="mb-6">
|
||||
<Text className="text-base font-semibold mb-3 text-gray-900">
|
||||
排序方向
|
||||
</Text>
|
||||
<RadioGroup
|
||||
value={tempFilters.sortOrder || 'desc'}
|
||||
onChange={(value) => updateTempFilters('sortOrder', value)}
|
||||
>
|
||||
{sortOrderOptions.map(option => (
|
||||
<Radio key={option.value} value={option.value} className="mb-2">
|
||||
{option.label}
|
||||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 底部按钮 */}
|
||||
<View className="p-4 border-t border-gray-100">
|
||||
<View className="flex gap-3">
|
||||
<Button
|
||||
fill="outline"
|
||||
size="large"
|
||||
className="flex-1"
|
||||
onClick={handleReset}
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
className="flex-1"
|
||||
onClick={handleApply}
|
||||
>
|
||||
应用
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
|
||||
export default CouponFilter
|
||||
Reference in New Issue
Block a user