227 lines
8.2 KiB
TypeScript
227 lines
8.2 KiB
TypeScript
import { View, Text, ScrollView, Image } from '@tarojs/components'
|
|
import Taro from '@tarojs/taro'
|
|
import { useState, useEffect, useCallback } from 'react'
|
|
import './index.scss'
|
|
import { getDesignList, removeDesigns, type DesignItem } from '../../utils/store'
|
|
import { PRODUCT_ICON_MAP } from '../../utils/productConfig'
|
|
import { assetUrl } from '../../utils/asset'
|
|
import { useThemeContext } from '../../context/ThemeContext'
|
|
import { useSafeArea } from '../../hooks/useSafeArea'
|
|
import { useStatusBar } from '../../hooks/useStatusBar'
|
|
import LoginGuard from '../../components/LoginGuard'
|
|
import ThemedPageMeta from '../../components/ThemedPageMeta'
|
|
|
|
const STATUS_TABS = [
|
|
{ code: 'all', label: '全部' },
|
|
{ code: 'toDesign', label: '待设计' },
|
|
{ code: 'undesigned', label: '未设计' },
|
|
{ code: 'designing', label: '设计中' },
|
|
{ code: 'ordered', label: '已下单' }
|
|
]
|
|
|
|
const VISIBLE_STATUS_TABS = STATUS_TABS.filter(tab => tab.code !== 'undesigned')
|
|
|
|
const STATUS_STYLE: Record<string, { label: string; cls: string }> = {
|
|
undesigned: { label: '未设计', cls: 'badge-pink' },
|
|
designing: { label: '设计中', cls: 'badge-blue' },
|
|
ordered: { label: '已下单', cls: 'badge-green' }
|
|
}
|
|
|
|
export default function DesignListPage() {
|
|
const { resolvedTheme } = useThemeContext()
|
|
const safe = useSafeArea()
|
|
useStatusBar(resolvedTheme)
|
|
const [activeTab, setActiveTab] = useState('all')
|
|
const [list, setList] = useState<DesignItem[]>([])
|
|
const [managing, setManaging] = useState(false)
|
|
const [selected, setSelected] = useState<Set<string>>(new Set())
|
|
|
|
const load = useCallback(() => {
|
|
setList(getDesignList())
|
|
}, [])
|
|
|
|
const init = useCallback(() => {
|
|
const filter = Taro.getStorageSync('designList:filter')
|
|
if (filter && STATUS_TABS.some(t => t.code === filter)) {
|
|
setActiveTab(filter)
|
|
Taro.removeStorageSync('designList:filter')
|
|
}
|
|
load()
|
|
}, [load])
|
|
|
|
useEffect(() => {
|
|
const page = Taro.getCurrentInstance().page
|
|
if (page) {
|
|
const orig = page.onShow
|
|
page.onShow = function () {
|
|
init()
|
|
if (orig) orig.apply(this)
|
|
}
|
|
}
|
|
init()
|
|
}, [init])
|
|
|
|
const filtered = activeTab === 'all'
|
|
? list
|
|
: activeTab === 'toDesign'
|
|
? list.filter(d => d.status === 'undesigned' || d.status === 'designing')
|
|
: list.filter(d => d.status === activeTab)
|
|
|
|
const goDesign = (item: DesignItem) => {
|
|
if (item.status === 'ordered') {
|
|
Taro.showToast({ title: '该商品已下单,请查看订单', icon: 'none' })
|
|
return
|
|
}
|
|
Taro.navigateTo({
|
|
url: `/pages/diy/index?source=designList&designId=${item.id}`
|
|
})
|
|
}
|
|
|
|
const toggleSelect = (id: string) => {
|
|
const next = new Set(selected)
|
|
if (next.has(id)) next.delete(id)
|
|
else next.add(id)
|
|
setSelected(next)
|
|
}
|
|
|
|
const toggleSelectAll = () => {
|
|
if (selected.size === filtered.length) {
|
|
setSelected(new Set())
|
|
} else {
|
|
setSelected(new Set(filtered.map(i => i.id)))
|
|
}
|
|
}
|
|
|
|
const handleDelete = () => {
|
|
if (selected.size === 0) return
|
|
Taro.showModal({
|
|
title: '确认删除',
|
|
content: `确定删除选中的 ${selected.size} 个条目吗?`,
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
removeDesigns(Array.from(selected))
|
|
setSelected(new Set())
|
|
setManaging(false)
|
|
load()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleManage = () => {
|
|
if (managing) {
|
|
setManaging(false)
|
|
setSelected(new Set())
|
|
} else {
|
|
setManaging(true)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<View className={`theme-${resolvedTheme}`}>
|
|
<ThemedPageMeta />
|
|
<LoginGuard>
|
|
<View className='design-page'>
|
|
<View className='page-header design-header' style={{ paddingTop: `${safe.headerPaddingTop}px` }}>
|
|
<View className='header-spacer' />
|
|
<Text className='header-title'>我的设计清单</Text>
|
|
<View className='header-manage' onTap={handleManage}>
|
|
<Text>{managing ? '完成' : '管理'}</Text>
|
|
</View>
|
|
</View>
|
|
|
|
{/* 状态筛选 */}
|
|
<View className='status-tabs'>
|
|
<ScrollView className='tabs-scroll' scrollX>
|
|
{VISIBLE_STATUS_TABS.map(tab => (
|
|
<View
|
|
key={tab.code}
|
|
className={`chip ${activeTab === tab.code ? 'active' : ''}`}
|
|
onTap={() => setActiveTab(tab.code)}
|
|
>
|
|
<Text className='tab-label'>{tab.label}</Text>
|
|
</View>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
|
|
{/* 批量管理工具栏 */}
|
|
{managing && (
|
|
<View className='batch-bar'>
|
|
<View className='flex-between' style={{ width: '100%' }}>
|
|
<View className='batch-select-all' onTap={toggleSelectAll}>
|
|
<View className={`batch-checkbox ${selected.size === filtered.length && filtered.length > 0 ? 'checked' : ''}`} />
|
|
<Text className='batch-text'>全选 ({selected.size}/{filtered.length})</Text>
|
|
</View>
|
|
<View className={`batch-delete ${selected.size > 0 ? 'active' : ''}`} onTap={handleDelete}>
|
|
<Text>删除</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
)}
|
|
|
|
{/* 列表 */}
|
|
<ScrollView className='design-list' scrollY>
|
|
{filtered.map(item => {
|
|
const style = STATUS_STYLE[item.status]
|
|
const rawIcon = (item.productIcon || '').startsWith('/icon/') || /^https?:/i.test(item.productIcon || '')
|
|
? item.productIcon
|
|
: PRODUCT_ICON_MAP[item.productId] || '/icon/四角星.svg'
|
|
const iconSrc = assetUrl(rawIcon)
|
|
const isSelected = selected.has(item.id)
|
|
return (
|
|
<View
|
|
key={item.id}
|
|
className={`design-card ${isSelected ? 'selected' : ''}`}
|
|
onTap={() => managing ? toggleSelect(item.id) : undefined}
|
|
>
|
|
<View className='design-body'>
|
|
{managing && (
|
|
<View className={`batch-checkbox ${isSelected ? 'checked' : ''}`} />
|
|
)}
|
|
<Image className='design-icon-img' src={iconSrc} mode='aspectFit' />
|
|
<View className='design-info'>
|
|
<View className='design-title-row'>
|
|
<Text className='design-name'>{item.productName}</Text>
|
|
<Text className={`badge ${style.cls}`}>{style.label}</Text>
|
|
</View>
|
|
<Text className='design-meta'>数量: {item.count} 件 | 单价: ¥{item.unitPrice}</Text>
|
|
<Text className='design-total'>小计: ¥{(item.unitPrice * item.count).toFixed(2)}</Text>
|
|
</View>
|
|
</View>
|
|
{!managing && (
|
|
<View className='design-actions'>
|
|
{item.status !== 'ordered' && (
|
|
<View className='btn-primary design-btn' onTap={() => goDesign(item)}>
|
|
<Text>{item.status === 'undesigned' ? '开始设计' : '继续设计'}</Text>
|
|
</View>
|
|
)}
|
|
{item.status === 'ordered' && (
|
|
<View className='btn-secondary design-btn' onTap={() => Taro.switchTab({ url: '/pages/orders/index' })}>
|
|
<Text>查看订单</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
)}
|
|
</View>
|
|
)
|
|
})}
|
|
|
|
{filtered.length === 0 && (
|
|
<View className='empty-state'>
|
|
<Image className='empty-icon-img' src={assetUrl('/icon/调色盘.png')} mode='aspectFit' />
|
|
<Text className='empty-text'>还没有设计清单</Text>
|
|
<Text className='empty-sub'>去首页逛逛,找到喜欢的定制品</Text>
|
|
<View className='btn-primary' onTap={() => Taro.switchTab({ url: '/pages/index/index' })}>
|
|
<Text>去逛逛</Text>
|
|
</View>
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
|
|
</View>
|
|
</LoginGuard>
|
|
</View>
|
|
)
|
|
}
|