CREATE TABLE users ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), username text NOT NULL UNIQUE, email text NOT NULL UNIQUE, password_hash text NOT NULL, full_name text, role text NOT NULL DEFAULT 'user', active boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE rooms ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name text NOT NULL, code text, location text, description text, capacity bigint, stage varchar(32), region varchar(64), status text NOT NULL DEFAULT 'active', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE devices ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), device_key text NOT NULL UNIQUE, name text NOT NULL, kind text NOT NULL DEFAULT 'sensor', model text, firmware text, online_status text NOT NULL DEFAULT 'online', last_seen timestamptz, room_id uuid NOT NULL, topic text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_devices_room_id ON devices (room_id); CREATE TABLE sensors ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name text NOT NULL, metric text NOT NULL, unit text, data_type text, device_id uuid NOT NULL, created_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_sensors_device_id ON sensors (device_id); CREATE TABLE thresholds ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name text, min_value double precision NOT NULL, max_value double precision NOT NULL, debounce_seconds bigint NOT NULL DEFAULT 5, severity bigint NOT NULL DEFAULT 3, enabled boolean NOT NULL DEFAULT true, sensor_id uuid NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_thresholds_sensor_id ON thresholds (sensor_id); CREATE TABLE alarms ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), code text, title text, message text, severity text, open boolean NOT NULL DEFAULT true, acknowledged boolean NOT NULL DEFAULT false, acknowledged_at timestamptz, triggered_at timestamptz NOT NULL, resolved_at timestamptz, device_key text, metric text, value double precision, threshold_min double precision, threshold_max double precision ); CREATE INDEX idx_alarms_device_open_triggered ON alarms (device_key, open, triggered_at); CREATE TABLE cameras ( id bigserial PRIMARY KEY, room_id text, code varchar(64) NOT NULL, name varchar(128) NOT NULL, rtsp_url varchar(512), http_url varchar(512), username varchar(64), password_enc varchar(255), position varchar(255), resolution varchar(32), fps bigint, is_online boolean NOT NULL DEFAULT true, gb_device_id varchar(20), gb_channel_id varchar(20), gb_auth_id varchar(20), gb_auth_password varchar(255), gb_stream_type varchar(10), gb_transport varchar(10), gb_alarm_channel_id varchar(20), gb_voice_channel_id varchar(20), gb_manufacturer varchar(64), manufacturer_id varchar(64), enabled boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_cameras_room_id ON cameras (room_id); CREATE TABLE video_clips ( id bigserial PRIMARY KEY, trigger text NOT NULL DEFAULT 'alarm', file_path text, duration_sec real NOT NULL DEFAULT 0, start_at timestamptz NOT NULL, end_at timestamptz, resolution text, size_bytes bigint, notes text, camera_id text NOT NULL, room_id text, alarm_id text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), s3_bucket text, s3_key text ); CREATE INDEX idx_video_clips_alarm_id ON video_clips (alarm_id); CREATE INDEX idx_video_clips_room_id ON video_clips (room_id); CREATE INDEX idx_video_clips_camera_id ON video_clips (camera_id); CREATE TABLE audit_logs ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid, username text, action text NOT NULL, resource text, target_id text, description text, ip_address text, user_agent text, metadata jsonb, created_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_audit_logs_resource_target ON audit_logs (resource, target_id); CREATE INDEX idx_audit_logs_action_created ON audit_logs (action, created_at); CREATE INDEX idx_audit_logs_user_created ON audit_logs (user_id, created_at); CREATE TABLE telemetry ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), device_key text NOT NULL, metric text NOT NULL, value double precision NOT NULL, timestamp timestamptz NOT NULL ); CREATE INDEX idx_telemetry_device_timestamp ON telemetry (device_key, timestamp); CREATE TABLE permissions ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), code text NOT NULL, name text NOT NULL, description text, created_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX idx_permissions_code ON permissions (code); CREATE TABLE role_permissions ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), role text NOT NULL, permission_id uuid NOT NULL, created_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX idx_role_permissions_role_code ON role_permissions (role, permission_id); CREATE TABLE diseases ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name varchar(64) NOT NULL, category varchar(32) NOT NULL, pathogen text NOT NULL, transmission text NOT NULL, medium text NOT NULL, incubation text NOT NULL, symptoms text NOT NULL, high_risk_stage text NOT NULL, high_risk_condition text NOT NULL, lethal_time text NOT NULL, spread_trend text NOT NULL, recurrence text NOT NULL, detection text NOT NULL, prevention text NOT NULL, image_url varchar(512), sort_order bigint NOT NULL DEFAULT 0, enabled boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_diseases_category ON diseases (category); CREATE TABLE knowledge_articles ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), kind varchar(32) NOT NULL, title varchar(128) NOT NULL, summary text NOT NULL, content text NOT NULL, sort_order bigint NOT NULL DEFAULT 0, enabled boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_knowledge_articles_kind ON knowledge_articles (kind); CREATE TABLE inspection_records ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid, room_id uuid, image_url varchar(512), detections jsonb, risk_score double precision, risk_level varchar(16), ai_status varchar(16) NOT NULL DEFAULT 'done', idempotency_key varchar(128), created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX idx_inspection_records_idempotency_key ON inspection_records (idempotency_key); CREATE INDEX idx_inspection_records_room_id ON inspection_records (room_id); CREATE INDEX idx_inspection_records_user_id ON inspection_records (user_id); CREATE TABLE trays ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name varchar(64) NOT NULL, code varchar(64), position varchar(128), room_id uuid NOT NULL, enabled boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_trays_room_id ON trays (room_id); CREATE TABLE batches ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), room_id uuid NOT NULL, name varchar(64) NOT NULL, variety varchar(64), source varchar(128), seed_batch_no varchar(64), quarantine_no varchar(64), instar bigint, entered_at timestamptz, mount_at timestamptz, status varchar(16) NOT NULL DEFAULT 'rearing', note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_batches_room_id ON batches (room_id); CREATE TABLE rearing_records ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), batch_id uuid NOT NULL, record_date timestamptz NOT NULL, instar bigint, mulberry_source varchar(128), density varchar(64), note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_rearing_records_batch_id ON rearing_records (batch_id); CREATE TABLE wechat_bindings ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL, open_id varchar(128) NOT NULL, authorized_templates jsonb, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX idx_wechat_bindings_open_id ON wechat_bindings (open_id); CREATE UNIQUE INDEX idx_wechat_bindings_user_id ON wechat_bindings (user_id); CREATE TABLE weather_alerts ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), disease varchar(64) NOT NULL, level varchar(16) NOT NULL, reason text NOT NULL, snapshot jsonb, created_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE lamp_tests ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), method varchar(32) NOT NULL DEFAULT 'lamp', room_id uuid, batch_id uuid, diseases jsonb, status varchar(16) NOT NULL DEFAULT 'pending', sample_info varchar(255), result varchar(16), result_image_url varchar(512), operator_id uuid, resulted_at timestamptz, cross_status varchar(16) NOT NULL DEFAULT 'pending', cross_reason text, extra_data jsonb, note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_lamp_tests_batch_id ON lamp_tests (batch_id); CREATE INDEX idx_lamp_tests_room_id ON lamp_tests (room_id); CREATE TABLE lamp_test_steps ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), lamp_test_id uuid NOT NULL, step_no bigint NOT NULL, name varchar(64) NOT NULL, done boolean NOT NULL DEFAULT false, done_at timestamptz, note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_lamp_test_steps_lamp_test_id ON lamp_test_steps (lamp_test_id); CREATE TABLE consumables ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), name varchar(64) NOT NULL, category varchar(32) NOT NULL, spec varchar(128), quantity double precision NOT NULL, unit varchar(32), min_quantity double precision NOT NULL, expiry_date timestamptz, supplier varchar(128), note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_consumables_category ON consumables (category); CREATE TABLE consultations ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), room_id uuid, batch_id uuid, lamp_test_id uuid, title varchar(128) NOT NULL, summary text, snapshot jsonb, status varchar(16) NOT NULL DEFAULT 'pending', expert_id uuid, opinion text, plan text, resolved_at timestamptz, archived_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_consultations_lamp_test_id ON consultations (lamp_test_id); CREATE INDEX idx_consultations_batch_id ON consultations (batch_id); CREATE INDEX idx_consultations_room_id ON consultations (room_id); CREATE TABLE spectrum_entries ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), disease varchar(64) NOT NULL, source varchar(128), data_url varchar(512), note text, created_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE trace_records ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), room_id uuid, lamp_test_id uuid, consultation_id uuid, disease varchar(64) NOT NULL, status varchar(16) NOT NULL DEFAULT 'pending', origin varchar(32), confidence double precision, auto_report jsonb, checklist jsonb, analysis_report jsonb, expert_note text, lab_note text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX idx_trace_records_consultation_id ON trace_records (consultation_id); CREATE INDEX idx_trace_records_lamp_test_id ON trace_records (lamp_test_id); CREATE INDEX idx_trace_records_room_id ON trace_records (room_id);