import { useState } from "react"; import { useAsyncData } from "../../lib/useAsyncData"; import { adminListIoT, adminIoTControl, adminIoTScenario, adminIoTRule } from "../../lib/api"; import type { AdminIoTDevice } from "../../lib/types"; import { useAutoReload } from "../hooks"; import { useAuditStore } from "../audit"; import { AdminTable, Notice, PageHeader, type AdminColumn } from "../components"; import { Button, Surface, Tag } from "../../components/primitives"; const columns: AdminColumn[] = [ { key: "name", title: "设备", render: (d) => {d.name} }, { key: "type", title: "类型", render: (d) => {d.type} }, { key: "id", title: "ID", render: (d) => {d.id} }, { key: "online", title: "状态", render: (d) => ( {d.online ? "在线" : "离线"} ), }, { key: "state", title: "实时状态", render: (d) => ( {Object.entries(d.state) .map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`) .join(" · ") || "—"} ), }, { key: "control", title: "控制", render: (d) => ( ), }, ]; function DeviceControl({ device, disabled }: { device: AdminIoTDevice; disabled: boolean }): React.ReactNode { const [action, setAction] = useState("on"); const [params, setParams] = useState(""); const [res, setRes] = useState(null); const [err, setErr] = useState(null); const [busy, setBusy] = useState(false); const log = useAuditStore((s) => s.log); const send = () => { setBusy(true); setErr(null); let parsed: Record | undefined; if (params.trim()) { try { parsed = JSON.parse(params) as Record; } catch { setErr("参数需为合法 JSON"); setBusy(false); return; } } adminIoTControl(device.id, action.trim() || "on", parsed) .then((d) => { log("iot.control", "ok"); setRes(`${d.name} → ${action}:${JSON.stringify(d.state)}`); }) .catch((e: unknown) => { log("iot.control", "error"); setErr(e instanceof Error ? e.message : "控制失败"); }) .finally(() => setBusy(false)); }; return (
setAction(e.target.value)} placeholder="on / off / set_temperature" className="w-28 rounded-[var(--mu-radius-sm)] bg-[var(--mu-surface-2)] px-2 py-1 text-xs outline-none focus:ring-1 focus:ring-[var(--mu-accent)]" /> setParams(e.target.value)} placeholder='{"temp":24}' className="w-28 rounded-[var(--mu-radius-sm)] bg-[var(--mu-surface-2)] px-2 py-1 text-xs outline-none focus:ring-1 focus:ring-[var(--mu-accent)]" /> {res ? {res} : null} {err ? {err} : null}
); } export function IoTModule(): React.ReactNode { const { data, loading, error, reload } = useAsyncData(adminListIoT, []); useAutoReload(reload, 8000); const log = useAuditStore((s) => s.log); const [msg, setMsg] = useState(null); const scenario = () => adminIoTScenario({ name: "场景-夜灯" }) .then(() => { log("iot.scene", "ok"); setMsg("场景保存成功"); }) .catch((e: unknown) => { log("iot.scene", "error"); setMsg(e instanceof Error ? e.message : "场景保存失败"); }); const rule = () => adminIoTRule({ name: "规则-定时", expression: "0 22 * * *" }) .then(() => { log("iot.rule", "ok"); setMsg("规则保存成功"); }) .catch((e: unknown) => { log("iot.rule", "error"); setMsg(e instanceof Error ? e.message : "规则保存失败"); }); return (
} /> {msg ? {msg} : null} d.id} /> 设备控制真实下发到 IoT provider(在线设备可操作);场景/规则存储由后端 M10 提供,当前返回明确待实现。
); }