feat(web/miniapp): 批次/蚕匾管理与蚕房详情展示(#7)
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { get } from './request';
|
||||
|
||||
export interface Tray {
|
||||
id: string;
|
||||
name: string;
|
||||
code?: string;
|
||||
position?: string;
|
||||
roomId: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface Batch {
|
||||
id: string;
|
||||
roomId: string;
|
||||
name: string;
|
||||
variety?: string;
|
||||
source?: string;
|
||||
instar?: number;
|
||||
status: string;
|
||||
enteredAt?: string;
|
||||
}
|
||||
|
||||
export const getTrays = (roomId: string) => get<Tray[]>('/trays', { roomId });
|
||||
export const getBatches = (roomId: string) => get<Batch[]>('/batches', { roomId });
|
||||
|
||||
export const batchStatusLabel = (status: string) => {
|
||||
const labels: Record<string, string> = { rearing: '饲养中', mounted: '已上蔟', finished: '已结束' };
|
||||
return labels[status] || status;
|
||||
};
|
||||
@@ -5,6 +5,7 @@ import styles from './index.module.scss';
|
||||
import { getRoomById } from '@/api/rooms';
|
||||
import { getDevices } from '@/api/devices';
|
||||
import { getLatestTelemetry, fetchTrend } from '@/api/telemetry';
|
||||
import { getTrays, getBatches, batchStatusLabel, type Tray, type Batch } from '@/api/trayBatch';
|
||||
import MiniChart from '@/components/MiniChart';
|
||||
import {
|
||||
roomStatusLabel,
|
||||
@@ -24,6 +25,8 @@ const RoomDetailPage: React.FC = () => {
|
||||
const [devices, setDevices] = useState<Device[]>([]);
|
||||
const [telemetryMap, setTelemetryMap] = useState<Record<string, TelemetryRecord[]>>({});
|
||||
const [trend, setTrend] = useState<TrendPoint[]>([]);
|
||||
const [trays, setTrays] = useState<Tray[]>([]);
|
||||
const [batches, setBatches] = useState<Batch[]>([]);
|
||||
const [trendLoading, setTrendLoading] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
@@ -37,12 +40,14 @@ const RoomDetailPage: React.FC = () => {
|
||||
}
|
||||
try {
|
||||
setError('');
|
||||
const [roomRes, devicesRes] = await Promise.all([
|
||||
const [roomRes, devicesRes, traysRes, batchesRes] = await Promise.all([
|
||||
getRoomById(roomId).catch((e) => {
|
||||
console.error('[RoomDetail] 获取蚕房失败:', e);
|
||||
return null;
|
||||
}),
|
||||
getDevices().catch(() => [] as Device[]),
|
||||
getTrays(roomId).catch(() => [] as Tray[]),
|
||||
getBatches(roomId).catch(() => [] as Batch[]),
|
||||
]);
|
||||
|
||||
if (roomRes) {
|
||||
@@ -51,6 +56,8 @@ const RoomDetailPage: React.FC = () => {
|
||||
|
||||
const roomDevices = devicesRes.filter((d) => d.roomId === roomId);
|
||||
setDevices(roomDevices);
|
||||
setTrays(traysRes);
|
||||
setBatches(batchesRes);
|
||||
|
||||
// 获取每个设备的最新遥测
|
||||
const telemetryEntries = await Promise.all(
|
||||
@@ -271,6 +278,61 @@ const RoomDetailPage: React.FC = () => {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 蚕匾 */}
|
||||
<View className={styles.section}>
|
||||
<Text className={styles.sectionTitle}>蚕匾</Text>
|
||||
{trays.length > 0 ? (
|
||||
<View className={styles.deviceList}>
|
||||
{trays.map((t) => (
|
||||
<View key={t.id} className={styles.deviceItem}>
|
||||
<View className={styles.deviceLeft}>
|
||||
<Text className={styles.deviceIcon}>🪵</Text>
|
||||
<View className={styles.deviceInfo}>
|
||||
<Text className={styles.deviceName}>{t.name}</Text>
|
||||
<Text className={styles.deviceMeta}>
|
||||
{[t.code, t.position].filter(Boolean).join(' · ') || '无位置信息'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
) : (
|
||||
<View className={styles.emptyWrap}>
|
||||
<Text className={styles.emptyIcon}>📭</Text>
|
||||
<Text className={styles.emptyText}>该蚕房暂无蚕匾</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 当前批次 */}
|
||||
<View className={styles.section}>
|
||||
<Text className={styles.sectionTitle}>当前批次</Text>
|
||||
{batches.length > 0 ? (
|
||||
<View className={styles.deviceList}>
|
||||
{batches.map((b) => (
|
||||
<View key={b.id} className={styles.deviceItem}>
|
||||
<View className={styles.deviceLeft}>
|
||||
<Text className={styles.deviceIcon}>🐛</Text>
|
||||
<View className={styles.deviceInfo}>
|
||||
<Text className={styles.deviceName}>{b.name}</Text>
|
||||
<Text className={styles.deviceMeta}>
|
||||
{batchStatusLabel(b.status)} · {b.instar ? `${b.instar}龄` : '龄期未设置'}
|
||||
{b.variety ? ` · ${b.variety}` : ''}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
) : (
|
||||
<View className={styles.emptyWrap}>
|
||||
<Text className={styles.emptyIcon}>📭</Text>
|
||||
<Text className={styles.emptyText}>该蚕房暂无批次</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user