SEC_Warehouse/src/pages/scene/select.tsx

106 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState, useEffect } from 'react'
import Taro from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import { useAppDispatch, useAppSelector } from '@/store/hooks'
import { setScene, type Scene } from '@/store/sceneSlice'
import { Navbar } from '@/components/navbar'
import { Loading } from '@/components/loading'
import { Empty } from '@/components/empty'
import { StateView } from '@/components/state-view'
import { getSceneList, addScene } from '@/api/scene'
import { showToast } from '@/utils/toast'
import { navigateBack } from '@/utils/navigation'
import styles from './select.module.scss'
// Taro 类型未跟进 wx.showModal 的 editable 扩展(微信 2.17.1+),运行时真实存在
interface EditableModalOption extends Taro.showModal.Option {
editable?: boolean
placeholderText?: string
}
interface EditableModalResult extends Taro.showModal.SuccessCallbackResult {
content?: string
}
const showEditableModal = (option: EditableModalOption) =>
Taro.showModal(option as Taro.showModal.Option) as Promise<EditableModalResult>
export default function SceneSelect() {
const dispatch = useAppDispatch()
const current = useAppSelector((s) => s.scene.current)
const [loading, setLoading] = useState(true)
const [loadError, setLoadError] = useState(false)
const [list, setList] = useState<Scene[]>([])
const load = async () => {
setLoading(true)
setLoadError(false)
try {
const data = await getSceneList()
setList(data ?? [])
} catch {
setLoadError(true)
} finally {
setLoading(false)
}
}
useEffect(() => { load() }, [])
const selectScene = (scene: Scene) => {
dispatch(setScene(scene))
navigateBack()
}
// 添加房间:可编辑弹窗输入名称,成功后刷新列表
const addRoom = () => {
showEditableModal({
title: '添加房间',
editable: true,
placeholderText: '请输入房间名称(如:阳台)'
}).then(async ({ confirm, content }) => {
if (!confirm) return
try {
await addScene(content ?? '')
showToast('添加成功')
await load()
} catch (error) {
showToast(error instanceof Error ? error.message : '添加失败')
}
})
}
return (
<View className={styles.page}>
<Navbar title="房间管理" variant="hero" />
{loading ? (
<View className={styles.stateWrap}><Loading /></View>
) : loadError ? (
<StateView status="error" onRetry={load} />
) : (
<View className={styles.list}>
{list.map((scene) => (
<View
key={scene.id}
className={`${styles.item} ${scene.id === current?.id ? styles.itemActive : ''}`}
onClick={() => selectScene(scene)}
>
<Text className={styles.name}>{scene.name}</Text>
<Text className={styles.check}>{scene.id === current?.id ? '✓' : '›'}</Text>
</View>
))}
{/* 空列表时也保留添加入口 */}
{list.length === 0 && (
<View className={styles.stateWrap}><Empty text="暂无房间,点击下方添加" /></View>
)}
<View className={styles.addBtn} hoverClass={styles.addBtnPressed} onClick={addRoom}>
<Text className={styles.addIcon}>+</Text>
<Text className={styles.addText}>添加房间</Text>
</View>
</View>
)}
</View>
)
}