import { useEffect, useMemo, useRef, useState } from "react"; import { MapPin, Camera, Mic, Send, CalendarDays, CheckCircle2, FileText, ListTodo, Filter, RefreshCw } from "lucide-react"; import { format } from "date-fns"; import { motion } from "motion/react"; import { getWorkOverview, reverseWorkGeocode, saveWorkCheckIn, saveWorkDailyReport, type CreateWorkCheckInPayload, type CreateWorkDailyReportPayload, type WorkHistoryItem, } from "@/lib/auth"; const historyFilters = ["全部", "日报", "外勤打卡"] as const; const defaultCheckInForm: CreateWorkCheckInPayload = { locationText: "", remark: "", }; const defaultReportForm: CreateWorkDailyReportPayload = { workContent: "", tomorrowPlan: "", sourceType: "manual", }; function getCheckInStatus(status?: string) { if (!status) { return "待打卡"; } return status === "updated" ? "已更新" : "已打卡"; } function getReportStatus(status?: string) { if (!status) { return "待提交"; } return status === "reviewed" || status === "已点评" ? "已点评" : "已提交"; } export default function Work() { const hasAutoRefreshedLocation = useRef(false); const [loading, setLoading] = useState(true); const [refreshingLocation, setRefreshingLocation] = useState(false); const [isRecording, setIsRecording] = useState(false); const [submittingCheckIn, setSubmittingCheckIn] = useState(false); const [submittingReport, setSubmittingReport] = useState(false); const [historyFilter, setHistoryFilter] = useState<(typeof historyFilters)[number]>("全部"); const [locationHint, setLocationHint] = useState(""); const [pageError, setPageError] = useState(""); const [checkInError, setCheckInError] = useState(""); const [reportError, setReportError] = useState(""); const [checkInSuccess, setCheckInSuccess] = useState(""); const [reportSuccess, setReportSuccess] = useState(""); const [historyData, setHistoryData] = useState([]); const [checkInStatus, setCheckInStatus] = useState(); const [reportStatus, setReportStatus] = useState(); const [checkInForm, setCheckInForm] = useState(defaultCheckInForm); const [reportForm, setReportForm] = useState(defaultReportForm); const filteredHistory = useMemo(() => { if (historyFilter === "全部") { return historyData; } return historyData.filter((item) => item.type === historyFilter); }, [historyData, historyFilter]); useEffect(() => { void loadOverview(); }, []); useEffect(() => { if (loading || hasAutoRefreshedLocation.current) { return; } hasAutoRefreshedLocation.current = true; void handleRefreshLocation(); }, [loading]); const handleRecord = () => { if (isRecording) { setIsRecording(false); return; } setIsRecording(true); window.setTimeout(() => { setReportForm((prev) => ({ ...prev, workContent: prev.workContent + (prev.workContent ? "\n" : "") + "今天拜访了A市第一人民医院信息科主任,沟通了云桌面扩容需求,对方表示下个月会启动招标流程。", sourceType: "voice_assist", })); setIsRecording(false); }, 2000); }; const handleRefreshLocation = async () => { if (!navigator.geolocation) { setLocationHint("当前浏览器不支持定位,请手动填写当前位置。"); return; } setCheckInError(""); setRefreshingLocation(true); setLocationHint("正在获取当前位置..."); navigator.geolocation.getCurrentPosition( async (position) => { const latitude = Number(position.coords.latitude.toFixed(6)); const longitude = Number(position.coords.longitude.toFixed(6)); try { const displayName = await reverseWorkGeocode(latitude, longitude); setCheckInForm((prev) => ({ ...prev, locationText: displayName || `定位坐标:${latitude}, ${longitude}`, latitude, longitude, })); setLocationHint("定位已刷新,已为你填入具体地点名称。"); } catch { setCheckInForm((prev) => ({ ...prev, locationText: `定位坐标:${latitude}, ${longitude}`, latitude, longitude, })); setLocationHint("已获取坐标,但地点名称解析失败,你也可以手动补充。"); } finally { setRefreshingLocation(false); } }, () => { setLocationHint("定位获取失败,请手动填写当前位置。"); setRefreshingLocation(false); }, { enableHighAccuracy: true, timeout: 10000, }, ); }; const handleCheckInSubmit = async () => { if (submittingCheckIn) { return; } setCheckInError(""); setCheckInSuccess(""); setSubmittingCheckIn(true); try { await saveWorkCheckIn({ locationText: checkInForm.locationText.trim(), remark: checkInForm.remark?.trim() || undefined, longitude: checkInForm.longitude, latitude: checkInForm.latitude, }); await loadOverview(); setCheckInForm(defaultCheckInForm); setCheckInSuccess("打卡已记录,本日可继续新增打卡。"); } catch (error) { setCheckInError(error instanceof Error ? error.message : "打卡提交失败"); } finally { setSubmittingCheckIn(false); } }; const handleReportSubmit = async () => { if (submittingReport) { return; } setReportError(""); setReportSuccess(""); setSubmittingReport(true); try { await saveWorkDailyReport({ workContent: reportForm.workContent.trim(), tomorrowPlan: reportForm.tomorrowPlan.trim(), sourceType: reportForm.sourceType || "manual", }); await loadOverview(); setReportSuccess("日报已保存,今日再次提交会覆盖当天内容。"); } catch (error) { setReportError(error instanceof Error ? error.message : "日报提交失败"); } finally { setSubmittingReport(false); } }; const handleFilterToggle = () => { setHistoryFilter((current) => { const index = historyFilters.indexOf(current); return historyFilters[(index + 1) % historyFilters.length]; }); }; async function loadOverview() { setLoading(true); setPageError(""); try { const data = await getWorkOverview(); setHistoryData(data.history ?? []); setCheckInStatus(data.todayCheckIn?.status); setReportStatus(data.todayReport?.status); setCheckInForm({ locationText: "", remark: "", longitude: undefined, latitude: undefined, }); setReportForm({ workContent: data.suggestedWorkContent || data.todayReport?.workContent || "", tomorrowPlan: data.todayReport?.tomorrowPlan ?? "", sourceType: data.todayReport?.sourceType ?? "manual", }); } catch (error) { setPageError(error instanceof Error ? error.message : "工作台数据加载失败"); setHistoryData([]); setCheckInStatus(undefined); setReportStatus(undefined); } finally { setLoading(false); } } return (

工作台

今天是 {format(new Date(), "yyyy年MM月dd日 EEEE")}

今日工作

外勤打卡

{loading ? "加载中..." : getCheckInStatus(checkInStatus)}

当前位置