@qhr123/sa2kit 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import '../chunk-BJTO5JO5.mjs';
2
- import { useEffect, useCallback, useRef } from 'react';
2
+ import React5, { useEffect, useCallback, useRef, useState } from 'react';
3
3
 
4
4
  // src/analytics/types.ts
5
5
  var EventType = /* @__PURE__ */ ((EventType2) => {
@@ -1840,10 +1840,686 @@ var DesktopDeviceAdapter = class {
1840
1840
  return navigator.userAgent;
1841
1841
  }
1842
1842
  };
1843
+ var StatCard = ({
1844
+ title,
1845
+ value,
1846
+ subtitle,
1847
+ icon,
1848
+ trend,
1849
+ className = ""
1850
+ }) => {
1851
+ return /* @__PURE__ */ React5.createElement(
1852
+ "div",
1853
+ {
1854
+ className: `bg-white rounded-lg shadow-sm p-6 border border-gray-200 hover:shadow-md transition-shadow ${className}`
1855
+ },
1856
+ /* @__PURE__ */ React5.createElement("div", { className: "flex items-start justify-between" }, /* @__PURE__ */ React5.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-gray-600 mb-1" }, title), /* @__PURE__ */ React5.createElement("p", { className: "text-3xl font-bold text-gray-900" }, value.toLocaleString()), subtitle && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-gray-500 mt-2" }, subtitle), trend && /* @__PURE__ */ React5.createElement("div", { className: "flex items-center mt-2" }, /* @__PURE__ */ React5.createElement(
1857
+ "span",
1858
+ {
1859
+ className: `text-sm font-medium ${trend.isPositive ? "text-green-600" : "text-red-600"}`
1860
+ },
1861
+ trend.isPositive ? "\u2191" : "\u2193",
1862
+ " ",
1863
+ Math.abs(trend.value),
1864
+ "%"
1865
+ ), /* @__PURE__ */ React5.createElement("span", { className: "text-sm text-gray-500 ml-2" }, "vs \u4E0A\u5468"))), icon && /* @__PURE__ */ React5.createElement("div", { className: "flex-shrink-0 bg-gradient-to-br from-purple-500 to-indigo-600 rounded-lg p-3" }, /* @__PURE__ */ React5.createElement("div", { className: "text-white text-2xl" }, icon)))
1866
+ );
1867
+ };
1868
+ var EventList = ({
1869
+ events,
1870
+ loading = false,
1871
+ onEventClick,
1872
+ className = ""
1873
+ }) => {
1874
+ if (loading) {
1875
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-lg shadow-sm p-6 ${className}` }, /* @__PURE__ */ React5.createElement("div", { className: "animate-pulse space-y-4" }, [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ React5.createElement("div", { key: i, className: "h-16 bg-gray-200 rounded" }))));
1876
+ }
1877
+ if (events.length === 0) {
1878
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-lg shadow-sm p-12 text-center ${className}` }, /* @__PURE__ */ React5.createElement("div", { className: "text-gray-400 text-5xl mb-4" }, "\u{1F4CA}"), /* @__PURE__ */ React5.createElement("p", { className: "text-gray-600 text-lg font-medium" }, "\u6682\u65E0\u6570\u636E"), /* @__PURE__ */ React5.createElement("p", { className: "text-gray-500 text-sm mt-2" }, "\u5C1D\u8BD5\u8C03\u6574\u7B5B\u9009\u6761\u4EF6"));
1879
+ }
1880
+ const getPlatformColor = (platform) => {
1881
+ const colors = {
1882
+ web: "bg-blue-100 text-blue-800",
1883
+ mobile: "bg-green-100 text-green-800",
1884
+ miniapp: "bg-purple-100 text-purple-800",
1885
+ desktop: "bg-gray-100 text-gray-800"
1886
+ };
1887
+ return colors[platform] || "bg-gray-100 text-gray-800";
1888
+ };
1889
+ const getEventTypeColor = (eventType) => {
1890
+ const colors = {
1891
+ page_view: "bg-indigo-100 text-indigo-800",
1892
+ click: "bg-amber-100 text-amber-800",
1893
+ error: "bg-red-100 text-red-800",
1894
+ performance: "bg-cyan-100 text-cyan-800",
1895
+ api_call: "bg-emerald-100 text-emerald-800"
1896
+ };
1897
+ return colors[eventType] || "bg-gray-100 text-gray-800";
1898
+ };
1899
+ const formatTimestamp2 = (timestamp) => {
1900
+ const date = new Date(timestamp);
1901
+ const now = /* @__PURE__ */ new Date();
1902
+ const diff = now.getTime() - date.getTime();
1903
+ const minutes = Math.floor(diff / 6e4);
1904
+ const hours = Math.floor(minutes / 60);
1905
+ const days = Math.floor(hours / 24);
1906
+ if (minutes < 1) return "\u521A\u521A";
1907
+ if (minutes < 60) return `${minutes}\u5206\u949F\u524D`;
1908
+ if (hours < 24) return `${hours}\u5C0F\u65F6\u524D`;
1909
+ if (days < 7) return `${days}\u5929\u524D`;
1910
+ return date.toLocaleDateString("zh-CN");
1911
+ };
1912
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-lg shadow-sm overflow-hidden ${className}` }, /* @__PURE__ */ React5.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React5.createElement("table", { className: "min-w-full divide-y divide-gray-200" }, /* @__PURE__ */ React5.createElement("thead", { className: "bg-gray-50" }, /* @__PURE__ */ React5.createElement("tr", null, /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u4E8B\u4EF6"), /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u5E73\u53F0"), /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u9875\u9762"), /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u7528\u6237"), /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u65F6\u95F4"), /* @__PURE__ */ React5.createElement("th", { className: "px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider" }, "\u64CD\u4F5C"))), /* @__PURE__ */ React5.createElement("tbody", { className: "bg-white divide-y divide-gray-200" }, events.map((event) => /* @__PURE__ */ React5.createElement(
1913
+ "tr",
1914
+ {
1915
+ key: event.id,
1916
+ className: "hover:bg-gray-50 cursor-pointer transition-colors",
1917
+ onClick: () => onEventClick?.(event)
1918
+ },
1919
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4 whitespace-nowrap" }, /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React5.createElement(
1920
+ "span",
1921
+ {
1922
+ className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getEventTypeColor(
1923
+ event.eventType
1924
+ )} w-fit mb-1`
1925
+ },
1926
+ event.eventType
1927
+ ), /* @__PURE__ */ React5.createElement("span", { className: "text-sm text-gray-900" }, event.eventName))),
1928
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4 whitespace-nowrap" }, /* @__PURE__ */ React5.createElement(
1929
+ "span",
1930
+ {
1931
+ className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getPlatformColor(
1932
+ event.platform
1933
+ )}`
1934
+ },
1935
+ event.platform
1936
+ )),
1937
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4" }, /* @__PURE__ */ React5.createElement("div", { className: "text-sm text-gray-900 max-w-xs truncate" }, event.pageUrl || "-"), event.pageTitle && /* @__PURE__ */ React5.createElement("div", { className: "text-xs text-gray-500 max-w-xs truncate" }, event.pageTitle)),
1938
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4 whitespace-nowrap" }, /* @__PURE__ */ React5.createElement("div", { className: "text-sm text-gray-900" }, event.userId || "\u6E38\u5BA2"), /* @__PURE__ */ React5.createElement("div", { className: "text-xs text-gray-500" }, event.deviceId.slice(0, 8), "...")),
1939
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4 whitespace-nowrap" }, /* @__PURE__ */ React5.createElement("div", { className: "text-sm text-gray-900" }, formatTimestamp2(event.timestamp)), /* @__PURE__ */ React5.createElement("div", { className: "text-xs text-gray-500" }, new Date(event.timestamp).toLocaleTimeString("zh-CN"))),
1940
+ /* @__PURE__ */ React5.createElement("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm font-medium" }, /* @__PURE__ */ React5.createElement(
1941
+ "button",
1942
+ {
1943
+ onClick: (e) => {
1944
+ e.stopPropagation();
1945
+ onEventClick?.(event);
1946
+ },
1947
+ className: "text-indigo-600 hover:text-indigo-900"
1948
+ },
1949
+ "\u8BE6\u60C5"
1950
+ ))
1951
+ ))))));
1952
+ };
1953
+ var FilterPanel = ({
1954
+ onFilterChange,
1955
+ initialFilters = {},
1956
+ className = ""
1957
+ }) => {
1958
+ const [filters, setFilters] = useState(initialFilters);
1959
+ const handleDatePreset = (preset) => {
1960
+ const now = /* @__PURE__ */ new Date();
1961
+ let startDate = /* @__PURE__ */ new Date();
1962
+ switch (preset) {
1963
+ case "today":
1964
+ startDate.setHours(0, 0, 0, 0);
1965
+ break;
1966
+ case "yesterday":
1967
+ startDate.setDate(now.getDate() - 1);
1968
+ startDate.setHours(0, 0, 0, 0);
1969
+ now.setDate(now.getDate() - 1);
1970
+ now.setHours(23, 59, 59, 999);
1971
+ break;
1972
+ case "week":
1973
+ startDate.setDate(now.getDate() - 7);
1974
+ break;
1975
+ case "month":
1976
+ startDate.setMonth(now.getMonth() - 1);
1977
+ break;
1978
+ default:
1979
+ return;
1980
+ }
1981
+ const newFilters = {
1982
+ ...filters,
1983
+ dateRange: {
1984
+ startDate: startDate.toISOString(),
1985
+ endDate: now.toISOString()
1986
+ }
1987
+ };
1988
+ setFilters(newFilters);
1989
+ onFilterChange(newFilters);
1990
+ };
1991
+ const handleFilterChange = (key, value) => {
1992
+ const newFilters = {
1993
+ ...filters,
1994
+ [key]: value || void 0
1995
+ };
1996
+ setFilters(newFilters);
1997
+ onFilterChange(newFilters);
1998
+ };
1999
+ const handleReset = () => {
2000
+ const emptyFilters = {};
2001
+ setFilters(emptyFilters);
2002
+ onFilterChange(emptyFilters);
2003
+ };
2004
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-xl shadow-sm border border-gray-200 ${className}` }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between mb-4 p-4 bg-gradient-to-r from-gray-50 to-gray-100 -m-6 mb-4 rounded-t-xl border-b border-gray-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement(
2005
+ "svg",
2006
+ {
2007
+ className: "w-5 h-5 text-indigo-600",
2008
+ fill: "none",
2009
+ stroke: "currentColor",
2010
+ viewBox: "0 0 24 24"
2011
+ },
2012
+ /* @__PURE__ */ React5.createElement(
2013
+ "path",
2014
+ {
2015
+ strokeLinecap: "round",
2016
+ strokeLinejoin: "round",
2017
+ strokeWidth: 2,
2018
+ d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
2019
+ }
2020
+ )
2021
+ ), /* @__PURE__ */ React5.createElement("h3", { className: "text-sm font-semibold text-gray-900" }, "\u7B5B\u9009\u6761\u4EF6")), /* @__PURE__ */ React5.createElement(
2022
+ "button",
2023
+ {
2024
+ onClick: handleReset,
2025
+ className: "text-xs px-3 py-1 text-gray-600 hover:text-indigo-600 hover:bg-indigo-50 rounded-lg transition-colors"
2026
+ },
2027
+ "\u91CD\u7F6E"
2028
+ )), /* @__PURE__ */ React5.createElement("div", { className: "p-4 space-y-4" }, /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-semibold text-gray-700 mb-2" }, "\u65F6\u95F4\u8303\u56F4"), /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-2 gap-2" }, [
2029
+ { label: "\u4ECA\u5929", value: "today" },
2030
+ { label: "\u6628\u5929", value: "yesterday" },
2031
+ { label: "7\u5929", value: "week" },
2032
+ { label: "30\u5929", value: "month" }
2033
+ ].map((preset) => /* @__PURE__ */ React5.createElement(
2034
+ "button",
2035
+ {
2036
+ key: preset.value,
2037
+ onClick: () => handleDatePreset(preset.value),
2038
+ className: "px-3 py-1.5 text-xs font-medium border border-gray-300 rounded-lg hover:bg-indigo-50 hover:border-indigo-500 hover:text-indigo-700 transition-colors"
2039
+ },
2040
+ preset.label
2041
+ )))), /* @__PURE__ */ React5.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-medium text-gray-700 mb-1.5" }, "\u5F00\u59CB\u65F6\u95F4"), /* @__PURE__ */ React5.createElement(
2042
+ "input",
2043
+ {
2044
+ type: "datetime-local",
2045
+ value: filters.dateRange?.startDate ? new Date(filters.dateRange.startDate).toISOString().slice(0, 16) : "",
2046
+ onChange: (e) => handleFilterChange("dateRange", {
2047
+ ...filters.dateRange,
2048
+ startDate: e.target.value ? new Date(e.target.value).toISOString() : void 0
2049
+ }),
2050
+ className: "w-full px-2 py-1.5 text-xs border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"
2051
+ }
2052
+ )), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-medium text-gray-700 mb-1.5" }, "\u7ED3\u675F\u65F6\u95F4"), /* @__PURE__ */ React5.createElement(
2053
+ "input",
2054
+ {
2055
+ type: "datetime-local",
2056
+ value: filters.dateRange?.endDate ? new Date(filters.dateRange.endDate).toISOString().slice(0, 16) : "",
2057
+ onChange: (e) => handleFilterChange("dateRange", {
2058
+ ...filters.dateRange,
2059
+ endDate: e.target.value ? new Date(e.target.value).toISOString() : void 0
2060
+ }),
2061
+ className: "w-full px-2 py-1.5 text-xs border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"
2062
+ }
2063
+ ))), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-semibold text-gray-700 mb-2" }, "\u4E8B\u4EF6\u7C7B\u578B"), /* @__PURE__ */ React5.createElement(
2064
+ "select",
2065
+ {
2066
+ value: filters.eventType || "",
2067
+ onChange: (e) => handleFilterChange("eventType", e.target.value),
2068
+ className: "w-full px-2 py-1.5 text-xs border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"
2069
+ },
2070
+ /* @__PURE__ */ React5.createElement("option", { value: "" }, "\u5168\u90E8"),
2071
+ /* @__PURE__ */ React5.createElement("option", { value: "page_view" }, "\u9875\u9762\u6D4F\u89C8"),
2072
+ /* @__PURE__ */ React5.createElement("option", { value: "click" }, "\u70B9\u51FB"),
2073
+ /* @__PURE__ */ React5.createElement("option", { value: "search" }, "\u641C\u7D22"),
2074
+ /* @__PURE__ */ React5.createElement("option", { value: "login" }, "\u767B\u5F55"),
2075
+ /* @__PURE__ */ React5.createElement("option", { value: "logout" }, "\u767B\u51FA"),
2076
+ /* @__PURE__ */ React5.createElement("option", { value: "error" }, "\u9519\u8BEF"),
2077
+ /* @__PURE__ */ React5.createElement("option", { value: "performance" }, "\u6027\u80FD"),
2078
+ /* @__PURE__ */ React5.createElement("option", { value: "api_call" }, "API \u8C03\u7528"),
2079
+ /* @__PURE__ */ React5.createElement("option", { value: "custom" }, "\u81EA\u5B9A\u4E49")
2080
+ )), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-semibold text-gray-700 mb-2" }, "\u5E73\u53F0"), /* @__PURE__ */ React5.createElement(
2081
+ "select",
2082
+ {
2083
+ value: filters.platform || "",
2084
+ onChange: (e) => handleFilterChange("platform", e.target.value),
2085
+ className: "w-full px-2 py-1.5 text-xs border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"
2086
+ },
2087
+ /* @__PURE__ */ React5.createElement("option", { value: "" }, "\u5168\u90E8"),
2088
+ /* @__PURE__ */ React5.createElement("option", { value: "web" }, "Web"),
2089
+ /* @__PURE__ */ React5.createElement("option", { value: "mobile" }, "Mobile"),
2090
+ /* @__PURE__ */ React5.createElement("option", { value: "miniapp" }, "\u5C0F\u7A0B\u5E8F"),
2091
+ /* @__PURE__ */ React5.createElement("option", { value: "desktop" }, "Desktop")
2092
+ )), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("label", { className: "block text-xs font-semibold text-gray-700 mb-2" }, "\u7528\u6237ID"), /* @__PURE__ */ React5.createElement(
2093
+ "input",
2094
+ {
2095
+ type: "text",
2096
+ value: filters.userId || "",
2097
+ onChange: (e) => handleFilterChange("userId", e.target.value),
2098
+ placeholder: "\u8F93\u5165\u7528\u6237ID",
2099
+ className: "w-full px-2 py-1.5 text-xs border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 placeholder:text-gray-400"
2100
+ }
2101
+ ))), /* @__PURE__ */ React5.createElement("div", { className: "px-4 py-3 bg-gray-50 -mx-6 -mb-6 mt-4 rounded-b-xl border-t border-gray-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement(
2102
+ "div",
2103
+ {
2104
+ className: `w-2 h-2 rounded-full ${Object.keys(filters).length > 0 ? "bg-green-500" : "bg-gray-300"}`
2105
+ }
2106
+ ), /* @__PURE__ */ React5.createElement("p", { className: "text-xs text-gray-600" }, Object.keys(filters).length === 0 ? "\u672A\u5E94\u7528\u7B5B\u9009" : `${Object.keys(filters).length} \u4E2A\u7B5B\u9009`))));
2107
+ };
2108
+ var PieChart = ({ data, title, className = "" }) => {
2109
+ const total = data.reduce((sum, item) => sum + item.value, 0);
2110
+ const colors = [
2111
+ "bg-blue-500",
2112
+ "bg-green-500",
2113
+ "bg-purple-500",
2114
+ "bg-yellow-500",
2115
+ "bg-pink-500",
2116
+ "bg-indigo-500",
2117
+ "bg-red-500",
2118
+ "bg-cyan-500"
2119
+ ];
2120
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-lg shadow-sm p-6 ${className}` }, title && /* @__PURE__ */ React5.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-4" }, title), /* @__PURE__ */ React5.createElement("div", { className: "space-y-3" }, data.map((item, index) => {
2121
+ const percentage = total > 0 ? (item.value / total * 100).toFixed(1) : 0;
2122
+ return /* @__PURE__ */ React5.createElement("div", { key: index }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between text-sm mb-1" }, /* @__PURE__ */ React5.createElement("span", { className: "text-gray-700 font-medium" }, item.name), /* @__PURE__ */ React5.createElement("span", { className: "text-gray-600" }, item.value.toLocaleString(), " (", percentage, "%)")), /* @__PURE__ */ React5.createElement("div", { className: "w-full bg-gray-200 rounded-full h-2" }, /* @__PURE__ */ React5.createElement(
2123
+ "div",
2124
+ {
2125
+ className: `h-2 rounded-full ${colors[index % colors.length]}`,
2126
+ style: { width: `${percentage}%` }
2127
+ }
2128
+ )));
2129
+ })));
2130
+ };
2131
+ var BarChart = ({ data, title, className = "" }) => {
2132
+ const maxValue = Math.max(...data.map((item) => item.value), 1);
2133
+ return /* @__PURE__ */ React5.createElement("div", { className: `bg-white rounded-lg shadow-sm p-6 ${className}` }, title && /* @__PURE__ */ React5.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-4" }, title), /* @__PURE__ */ React5.createElement("div", { className: "space-y-4" }, data.map((item, index) => {
2134
+ const percentage = item.value / maxValue * 100;
2135
+ return /* @__PURE__ */ React5.createElement("div", { key: index, className: "flex items-center gap-4" }, /* @__PURE__ */ React5.createElement("div", { className: "w-32 text-sm text-gray-700 font-medium truncate" }, item.name), /* @__PURE__ */ React5.createElement("div", { className: "flex-1 flex items-center gap-2" }, /* @__PURE__ */ React5.createElement("div", { className: "flex-1 bg-gray-200 rounded-full h-8 relative overflow-hidden" }, /* @__PURE__ */ React5.createElement(
2136
+ "div",
2137
+ {
2138
+ className: "h-full bg-gradient-to-r from-indigo-500 to-purple-600 flex items-center justify-end px-3",
2139
+ style: { width: `${percentage}%`, minWidth: "40px" }
2140
+ },
2141
+ /* @__PURE__ */ React5.createElement("span", { className: "text-xs text-white font-semibold" }, item.value.toLocaleString())
2142
+ ))));
2143
+ })));
2144
+ };
2145
+ var AnalyticsDashboard = ({
2146
+ apiBaseUrl = "/api/analytics",
2147
+ className = ""
2148
+ }) => {
2149
+ const [stats, setStats] = useState(null);
2150
+ const [events, setEvents] = useState([]);
2151
+ const [filters, setFilters] = useState({});
2152
+ const [loading, setLoading] = useState(true);
2153
+ const [selectedEvent, setSelectedEvent] = useState(null);
2154
+ const [currentPage, setCurrentPage] = useState(1);
2155
+ const [totalEvents, setTotalEvents] = useState(0);
2156
+ const pageSize = 20;
2157
+ const loadStats = async () => {
2158
+ try {
2159
+ const params = new URLSearchParams();
2160
+ if (filters.dateRange?.startDate) {
2161
+ params.append("startDate", filters.dateRange.startDate);
2162
+ }
2163
+ if (filters.dateRange?.endDate) {
2164
+ params.append("endDate", filters.dateRange.endDate);
2165
+ }
2166
+ if (filters.platform) {
2167
+ params.append("platform", filters.platform);
2168
+ }
2169
+ const response = await fetch(`${apiBaseUrl}/stats?${params}`);
2170
+ const data = await response.json();
2171
+ if (data.success) {
2172
+ setStats(data.data);
2173
+ }
2174
+ } catch (error) {
2175
+ console.error("Failed to load stats:", error);
2176
+ }
2177
+ };
2178
+ const loadEvents = async () => {
2179
+ try {
2180
+ setLoading(true);
2181
+ const params = new URLSearchParams();
2182
+ if (filters.dateRange?.startDate) {
2183
+ params.append("startDate", filters.dateRange.startDate);
2184
+ }
2185
+ if (filters.dateRange?.endDate) {
2186
+ params.append("endDate", filters.dateRange.endDate);
2187
+ }
2188
+ if (filters.eventType) {
2189
+ params.append("eventType", filters.eventType);
2190
+ }
2191
+ if (filters.platform) {
2192
+ params.append("platform", filters.platform);
2193
+ }
2194
+ if (filters.userId) {
2195
+ params.append("userId", filters.userId);
2196
+ }
2197
+ params.append("limit", pageSize.toString());
2198
+ params.append("offset", ((currentPage - 1) * pageSize).toString());
2199
+ params.append("orderBy", "timestamp");
2200
+ params.append("orderDirection", "desc");
2201
+ const response = await fetch(`${apiBaseUrl}/query?${params}`);
2202
+ const data = await response.json();
2203
+ if (data.success) {
2204
+ setEvents(data.data);
2205
+ setTotalEvents(data.total);
2206
+ }
2207
+ } catch (error) {
2208
+ console.error("Failed to load events:", error);
2209
+ } finally {
2210
+ setLoading(false);
2211
+ }
2212
+ };
2213
+ useEffect(() => {
2214
+ loadStats();
2215
+ loadEvents();
2216
+ }, [filters, currentPage]);
2217
+ const handleFilterChange = (newFilters) => {
2218
+ setFilters(newFilters);
2219
+ setCurrentPage(1);
2220
+ };
2221
+ const handleEventClick = (event) => {
2222
+ setSelectedEvent(event);
2223
+ };
2224
+ const closeEventDetail = () => {
2225
+ setSelectedEvent(null);
2226
+ };
2227
+ const totalPages = Math.ceil(totalEvents / pageSize);
2228
+ return /* @__PURE__ */ React5.createElement("div", { className: `space-y-6 ${className}` }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 text-sm text-gray-600" }, /* @__PURE__ */ React5.createElement(
2229
+ "svg",
2230
+ {
2231
+ className: "w-5 h-5 text-indigo-600",
2232
+ fill: "none",
2233
+ stroke: "currentColor",
2234
+ viewBox: "0 0 24 24"
2235
+ },
2236
+ /* @__PURE__ */ React5.createElement(
2237
+ "path",
2238
+ {
2239
+ strokeLinecap: "round",
2240
+ strokeLinejoin: "round",
2241
+ strokeWidth: 2,
2242
+ d: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
2243
+ }
2244
+ )
2245
+ ), /* @__PURE__ */ React5.createElement("span", { className: "font-medium" }, "\u5B9E\u65F6\u6570\u636E\u76D1\u63A7")), totalEvents > 0 && /* @__PURE__ */ React5.createElement("span", { className: "text-xs px-2 py-1 bg-indigo-100 text-indigo-700 rounded-full font-medium" }, totalEvents.toLocaleString(), " \u6761\u8BB0\u5F55")), /* @__PURE__ */ React5.createElement(
2246
+ "button",
2247
+ {
2248
+ onClick: () => {
2249
+ loadStats();
2250
+ loadEvents();
2251
+ },
2252
+ className: "flex items-center gap-2 px-4 py-2 text-sm bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transition-all duration-200 shadow-sm hover:shadow-md"
2253
+ },
2254
+ /* @__PURE__ */ React5.createElement("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement(
2255
+ "path",
2256
+ {
2257
+ strokeLinecap: "round",
2258
+ strokeLinejoin: "round",
2259
+ strokeWidth: 2,
2260
+ d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
2261
+ }
2262
+ )),
2263
+ /* @__PURE__ */ React5.createElement("span", null, "\u5237\u65B0\u6570\u636E")
2264
+ )), /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-12 gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "col-span-12 xl:col-span-3" }, /* @__PURE__ */ React5.createElement(FilterPanel, { onFilterChange: handleFilterChange, initialFilters: filters })), /* @__PURE__ */ React5.createElement("div", { className: "col-span-12 xl:col-span-9 space-y-6" }, loading && !stats ? /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4" }, [1, 2, 3, 4].map((i) => /* @__PURE__ */ React5.createElement(
2265
+ "div",
2266
+ {
2267
+ key: i,
2268
+ className: "bg-white rounded-xl shadow-sm border border-gray-200 p-6 animate-pulse"
2269
+ },
2270
+ /* @__PURE__ */ React5.createElement("div", { className: "h-4 bg-gray-200 rounded w-20 mb-3" }),
2271
+ /* @__PURE__ */ React5.createElement("div", { className: "h-8 bg-gray-200 rounded w-24 mb-2" }),
2272
+ /* @__PURE__ */ React5.createElement("div", { className: "h-3 bg-gray-200 rounded w-16" })
2273
+ ))) : stats ? /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 animate-fade-in" }, /* @__PURE__ */ React5.createElement(
2274
+ StatCard,
2275
+ {
2276
+ title: "\u603B\u4E8B\u4EF6\u6570",
2277
+ value: stats.totalEvents,
2278
+ subtitle: "\u6240\u6709\u5E73\u53F0",
2279
+ icon: "\u{1F4C8}",
2280
+ className: "hover:scale-105 transition-transform duration-200"
2281
+ }
2282
+ ), /* @__PURE__ */ React5.createElement(
2283
+ StatCard,
2284
+ {
2285
+ title: "\u72EC\u7ACB\u7528\u6237",
2286
+ value: stats.uniqueUsers,
2287
+ subtitle: "\u53BB\u91CD\u7EDF\u8BA1",
2288
+ icon: "\u{1F465}",
2289
+ className: "hover:scale-105 transition-transform duration-200"
2290
+ }
2291
+ ), /* @__PURE__ */ React5.createElement(
2292
+ StatCard,
2293
+ {
2294
+ title: "\u4F1A\u8BDD\u6570",
2295
+ value: stats.uniqueSessions,
2296
+ subtitle: "\u7528\u6237\u4F1A\u8BDD",
2297
+ icon: "\u{1F517}",
2298
+ className: "hover:scale-105 transition-transform duration-200"
2299
+ }
2300
+ ), /* @__PURE__ */ React5.createElement(
2301
+ StatCard,
2302
+ {
2303
+ title: "\u8BBE\u5907\u6570",
2304
+ value: stats.uniqueDevices,
2305
+ subtitle: "\u72EC\u7ACB\u8BBE\u5907",
2306
+ icon: "\u{1F4F1}",
2307
+ className: "hover:scale-105 transition-transform duration-200"
2308
+ }
2309
+ )) : null, stats && /* @__PURE__ */ React5.createElement("div", { className: "space-y-6 animate-fade-in" }, /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-1 xl:grid-cols-2 gap-6" }, /* @__PURE__ */ React5.createElement("div", { className: "transform hover:scale-[1.02] transition-transform duration-200" }, /* @__PURE__ */ React5.createElement(
2310
+ PieChart,
2311
+ {
2312
+ title: "\u5E73\u53F0\u5206\u5E03",
2313
+ data: stats.eventsByPlatform.map((item) => ({
2314
+ name: item.platform,
2315
+ value: item.count
2316
+ }))
2317
+ }
2318
+ )), /* @__PURE__ */ React5.createElement("div", { className: "transform hover:scale-[1.02] transition-transform duration-200" }, /* @__PURE__ */ React5.createElement(
2319
+ BarChart,
2320
+ {
2321
+ title: "\u4E8B\u4EF6\u7C7B\u578B Top 10",
2322
+ data: stats.eventsByType.slice(0, 10).map((item) => ({
2323
+ name: item.eventType,
2324
+ value: item.count
2325
+ }))
2326
+ }
2327
+ ))), stats.topPages.length > 0 && /* @__PURE__ */ React5.createElement("div", { className: "transform hover:scale-[1.02] transition-transform duration-200" }, /* @__PURE__ */ React5.createElement(
2328
+ BarChart,
2329
+ {
2330
+ title: "\u70ED\u95E8\u9875\u9762 Top 10",
2331
+ data: stats.topPages.slice(0, 10).map((item) => ({
2332
+ name: item.pageUrl,
2333
+ value: item.count
2334
+ }))
2335
+ }
2336
+ ))), /* @__PURE__ */ React5.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React5.createElement("h3", { className: "text-lg font-semibold text-gray-900 flex items-center gap-2" }, /* @__PURE__ */ React5.createElement(
2337
+ "svg",
2338
+ {
2339
+ className: "w-5 h-5 text-indigo-600",
2340
+ fill: "none",
2341
+ stroke: "currentColor",
2342
+ viewBox: "0 0 24 24"
2343
+ },
2344
+ /* @__PURE__ */ React5.createElement(
2345
+ "path",
2346
+ {
2347
+ strokeLinecap: "round",
2348
+ strokeLinejoin: "round",
2349
+ strokeWidth: 2,
2350
+ d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
2351
+ }
2352
+ )
2353
+ ), "\u4E8B\u4EF6\u8BB0\u5F55"), totalEvents > 0 && !loading && /* @__PURE__ */ React5.createElement("span", { className: "text-sm text-gray-500" }, "\u663E\u793A ", (currentPage - 1) * pageSize + 1, "-", Math.min(currentPage * pageSize, totalEvents), " / ", totalEvents.toLocaleString())), /* @__PURE__ */ React5.createElement("div", { className: "animate-fade-in" }, /* @__PURE__ */ React5.createElement(EventList, { events, loading, onEventClick: handleEventClick })), totalPages > 1 && /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between bg-gradient-to-r from-gray-50 to-gray-100 px-6 py-4 rounded-xl border border-gray-200" }, /* @__PURE__ */ React5.createElement("div", { className: "hidden sm:block text-sm text-gray-600" }, "\u7B2C ", /* @__PURE__ */ React5.createElement("span", { className: "font-semibold text-gray-900" }, currentPage), " \u9875\uFF0C\u5171", " ", /* @__PURE__ */ React5.createElement("span", { className: "font-semibold text-gray-900" }, totalPages), " \u9875"), /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React5.createElement(
2354
+ "button",
2355
+ {
2356
+ onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
2357
+ disabled: currentPage === 1,
2358
+ className: "flex items-center gap-1 px-4 py-2 text-sm font-medium bg-white border border-gray-300 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 hover:border-indigo-500 transition-all duration-200"
2359
+ },
2360
+ /* @__PURE__ */ React5.createElement("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement(
2361
+ "path",
2362
+ {
2363
+ strokeLinecap: "round",
2364
+ strokeLinejoin: "round",
2365
+ strokeWidth: 2,
2366
+ d: "M15 19l-7-7 7-7"
2367
+ }
2368
+ )),
2369
+ /* @__PURE__ */ React5.createElement("span", { className: "hidden sm:inline" }, "\u4E0A\u4E00\u9875")
2370
+ ), /* @__PURE__ */ React5.createElement("div", { className: "sm:hidden px-4 py-2 text-sm text-gray-600" }, currentPage, " / ", totalPages), /* @__PURE__ */ React5.createElement(
2371
+ "button",
2372
+ {
2373
+ onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
2374
+ disabled: currentPage === totalPages,
2375
+ className: "flex items-center gap-1 px-4 py-2 text-sm font-medium bg-white border border-gray-300 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 hover:border-indigo-500 transition-all duration-200"
2376
+ },
2377
+ /* @__PURE__ */ React5.createElement("span", { className: "hidden sm:inline" }, "\u4E0B\u4E00\u9875"),
2378
+ /* @__PURE__ */ React5.createElement("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement(
2379
+ "path",
2380
+ {
2381
+ strokeLinecap: "round",
2382
+ strokeLinejoin: "round",
2383
+ strokeWidth: 2,
2384
+ d: "M9 5l7 7-7 7"
2385
+ }
2386
+ ))
2387
+ )))))), selectedEvent && /* @__PURE__ */ React5.createElement(
2388
+ "div",
2389
+ {
2390
+ className: "fixed inset-0 bg-black bg-opacity-60 backdrop-blur-sm flex items-center justify-center z-50 p-4 animate-fade-in",
2391
+ onClick: closeEventDetail
2392
+ },
2393
+ /* @__PURE__ */ React5.createElement(
2394
+ "div",
2395
+ {
2396
+ className: "bg-white rounded-2xl shadow-2xl max-w-3xl w-full max-h-[85vh] overflow-hidden animate-slide-up",
2397
+ onClick: (e) => e.stopPropagation()
2398
+ },
2399
+ /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-r from-indigo-600 to-purple-600 px-6 py-4 flex items-center justify-between" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-3 text-white" }, /* @__PURE__ */ React5.createElement("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement(
2400
+ "path",
2401
+ {
2402
+ strokeLinecap: "round",
2403
+ strokeLinejoin: "round",
2404
+ strokeWidth: 2,
2405
+ d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
2406
+ }
2407
+ )), /* @__PURE__ */ React5.createElement("h3", { className: "text-xl font-semibold" }, "\u4E8B\u4EF6\u8BE6\u60C5")), /* @__PURE__ */ React5.createElement(
2408
+ "button",
2409
+ {
2410
+ onClick: closeEventDetail,
2411
+ className: "text-white hover:bg-white hover:bg-opacity-20 rounded-full p-2 transition-all duration-200"
2412
+ },
2413
+ /* @__PURE__ */ React5.createElement("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React5.createElement(
2414
+ "path",
2415
+ {
2416
+ strokeLinecap: "round",
2417
+ strokeLinejoin: "round",
2418
+ strokeWidth: 2,
2419
+ d: "M6 18L18 6M6 6l12 12"
2420
+ }
2421
+ ))
2422
+ )),
2423
+ /* @__PURE__ */ React5.createElement("div", { className: "p-6 overflow-auto max-h-[calc(85vh-80px)]" }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-5" }, /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl p-4 border border-blue-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React5.createElement(
2424
+ "svg",
2425
+ {
2426
+ className: "w-5 h-5 text-indigo-600",
2427
+ fill: "none",
2428
+ stroke: "currentColor",
2429
+ viewBox: "0 0 24 24"
2430
+ },
2431
+ /* @__PURE__ */ React5.createElement(
2432
+ "path",
2433
+ {
2434
+ strokeLinecap: "round",
2435
+ strokeLinejoin: "round",
2436
+ strokeWidth: 2,
2437
+ d: "M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
2438
+ }
2439
+ )
2440
+ ), /* @__PURE__ */ React5.createElement("h4", { className: "font-semibold text-gray-900" }, "\u57FA\u7840\u4FE1\u606F")), /* @__PURE__ */ React5.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600" }, "\u4E8B\u4EF6ID"), /* @__PURE__ */ React5.createElement("code", { className: "text-xs bg-white px-2 py-1 rounded border border-blue-200 font-mono text-gray-800" }, selectedEvent.id.slice(0, 16), "...")), /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-2 gap-3 pt-2" }, /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u4E8B\u4EF6\u7C7B\u578B"), /* @__PURE__ */ React5.createElement("span", { className: "inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-indigo-100 text-indigo-800" }, selectedEvent.eventType)), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u4E8B\u4EF6\u540D\u79F0"), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-gray-900 truncate" }, selectedEvent.eventName))))), /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React5.createElement("div", { className: "bg-gray-50 rounded-lg p-3 border border-gray-200" }, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u5E73\u53F0"), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-semibold text-gray-900" }, selectedEvent.platform)), /* @__PURE__ */ React5.createElement("div", { className: "bg-gray-50 rounded-lg p-3 border border-gray-200" }, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u5E94\u7528\u7248\u672C"), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-semibold text-gray-900" }, selectedEvent.appVersion))), /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-br from-purple-50 to-pink-50 rounded-xl p-4 border border-purple-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React5.createElement(
2441
+ "svg",
2442
+ {
2443
+ className: "w-5 h-5 text-purple-600",
2444
+ fill: "none",
2445
+ stroke: "currentColor",
2446
+ viewBox: "0 0 24 24"
2447
+ },
2448
+ /* @__PURE__ */ React5.createElement(
2449
+ "path",
2450
+ {
2451
+ strokeLinecap: "round",
2452
+ strokeLinejoin: "round",
2453
+ strokeWidth: 2,
2454
+ d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
2455
+ }
2456
+ )
2457
+ ), /* @__PURE__ */ React5.createElement("h4", { className: "font-semibold text-gray-900" }, "\u7528\u6237\u4FE1\u606F")), /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-2 gap-3" }, /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u7528\u6237ID"), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-gray-900" }, selectedEvent.userId || /* @__PURE__ */ React5.createElement("span", { className: "text-gray-400" }, "\u6E38\u5BA2"))), /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u4F1A\u8BDDID"), /* @__PURE__ */ React5.createElement("code", { className: "text-xs bg-white px-2 py-1 rounded border border-purple-200 font-mono text-gray-800 block truncate" }, selectedEvent.sessionId.slice(0, 12), "..."))), /* @__PURE__ */ React5.createElement("div", { className: "mt-3 pt-3 border-t border-purple-200" }, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u8BBE\u5907ID"), /* @__PURE__ */ React5.createElement("code", { className: "text-xs bg-white px-2 py-1 rounded border border-purple-200 font-mono text-gray-800 block truncate" }, selectedEvent.deviceId))), (selectedEvent.pageUrl || selectedEvent.pageTitle) && /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-br from-green-50 to-emerald-50 rounded-xl p-4 border border-green-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React5.createElement(
2458
+ "svg",
2459
+ {
2460
+ className: "w-5 h-5 text-green-600",
2461
+ fill: "none",
2462
+ stroke: "currentColor",
2463
+ viewBox: "0 0 24 24"
2464
+ },
2465
+ /* @__PURE__ */ React5.createElement(
2466
+ "path",
2467
+ {
2468
+ strokeLinecap: "round",
2469
+ strokeLinejoin: "round",
2470
+ strokeWidth: 2,
2471
+ d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
2472
+ }
2473
+ )
2474
+ ), /* @__PURE__ */ React5.createElement("h4", { className: "font-semibold text-gray-900" }, "\u9875\u9762\u4FE1\u606F")), selectedEvent.pageTitle && /* @__PURE__ */ React5.createElement("div", { className: "mb-2" }, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u9875\u9762\u6807\u9898"), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-gray-900" }, selectedEvent.pageTitle)), selectedEvent.pageUrl && /* @__PURE__ */ React5.createElement("div", null, /* @__PURE__ */ React5.createElement("span", { className: "text-xs font-medium text-gray-600 block mb-1" }, "\u9875\u9762URL"), /* @__PURE__ */ React5.createElement("code", { className: "text-xs bg-white px-2 py-1 rounded border border-green-200 font-mono text-gray-800 block break-all" }, selectedEvent.pageUrl))), /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-br from-amber-50 to-yellow-50 rounded-xl p-4 border border-amber-200" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 mb-2" }, /* @__PURE__ */ React5.createElement(
2475
+ "svg",
2476
+ {
2477
+ className: "w-5 h-5 text-amber-600",
2478
+ fill: "none",
2479
+ stroke: "currentColor",
2480
+ viewBox: "0 0 24 24"
2481
+ },
2482
+ /* @__PURE__ */ React5.createElement(
2483
+ "path",
2484
+ {
2485
+ strokeLinecap: "round",
2486
+ strokeLinejoin: "round",
2487
+ strokeWidth: 2,
2488
+ d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
2489
+ }
2490
+ )
2491
+ ), /* @__PURE__ */ React5.createElement("h4", { className: "font-semibold text-gray-900" }, "\u65F6\u95F4\u4FE1\u606F")), /* @__PURE__ */ React5.createElement("p", { className: "text-sm font-medium text-gray-900" }, new Date(selectedEvent.timestamp).toLocaleString("zh-CN", {
2492
+ year: "numeric",
2493
+ month: "long",
2494
+ day: "numeric",
2495
+ hour: "2-digit",
2496
+ minute: "2-digit",
2497
+ second: "2-digit"
2498
+ }))), selectedEvent.properties && Object.keys(selectedEvent.properties).length > 0 && /* @__PURE__ */ React5.createElement("div", { className: "bg-gradient-to-br from-gray-50 to-slate-50 rounded-xl p-4 border border-gray-300" }, /* @__PURE__ */ React5.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ React5.createElement(
2499
+ "svg",
2500
+ {
2501
+ className: "w-5 h-5 text-gray-600",
2502
+ fill: "none",
2503
+ stroke: "currentColor",
2504
+ viewBox: "0 0 24 24"
2505
+ },
2506
+ /* @__PURE__ */ React5.createElement(
2507
+ "path",
2508
+ {
2509
+ strokeLinecap: "round",
2510
+ strokeLinejoin: "round",
2511
+ strokeWidth: 2,
2512
+ d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"
2513
+ }
2514
+ )
2515
+ ), /* @__PURE__ */ React5.createElement("h4", { className: "font-semibold text-gray-900" }, "\u81EA\u5B9A\u4E49\u5C5E\u6027")), /* @__PURE__ */ React5.createElement("pre", { className: "text-xs bg-white p-4 rounded-lg border border-gray-200 overflow-auto max-h-48 font-mono text-gray-800" }, JSON.stringify(selectedEvent.properties, null, 2)))))
2516
+ )
2517
+ ));
2518
+ };
1843
2519
 
1844
2520
  // src/analytics/index.ts
1845
2521
  var ANALYTICS_VERSION = "1.0.0";
1846
2522
 
1847
- export { ANALYTICS_VERSION, Analytics, CatchError, DesktopDeviceAdapter, DesktopNetworkAdapter, DesktopStorageAdapter, EventPriority, EventQueue, EventType, MiniappDeviceAdapter, MiniappNetworkAdapter, MiniappStorageAdapter, MobileDeviceAdapter, MobileNetworkAdapter, MobileStorageAdapter, Track, TrackClick, TrackPerformance, Uploader, WebDeviceAdapter, WebNetworkAdapter, WebStorageAdapter, createAnalytics, createDesktopConfig, createMiniappConfig, createMobileConfig, createWebConfig, debounce, deepClone, formatEvent, formatTimestamp, generateUniqueId, getAllInstanceKeys, getAnalyticsInstance, getBatchSize, getCurrentPageTitle, getCurrentPageUrl, getEventSize, getGlobalAnalytics, getPageDuration, getReferrer, isAnalyticsInitialized, isDevelopment, isMobile, mergeEventProperties, resetAllAnalytics, resetAnalytics, safeParse, safeStringify, sanitizeEvent, setGlobalAnalytics, throttle, useAnalytics, useAutoTracking, useErrorTracking, usePageDuration, usePageView, usePerformanceTracking, useTrackClick, useTrackEvent, validateEvent, validateEvents, webAdapter };
2523
+ export { ANALYTICS_VERSION, Analytics, AnalyticsDashboard, BarChart, CatchError, DesktopDeviceAdapter, DesktopNetworkAdapter, DesktopStorageAdapter, EventList, EventPriority, EventQueue, EventType, FilterPanel, MiniappDeviceAdapter, MiniappNetworkAdapter, MiniappStorageAdapter, MobileDeviceAdapter, MobileNetworkAdapter, MobileStorageAdapter, PieChart, StatCard, Track, TrackClick, TrackPerformance, Uploader, WebDeviceAdapter, WebNetworkAdapter, WebStorageAdapter, createAnalytics, createDesktopConfig, createMiniappConfig, createMobileConfig, createWebConfig, debounce, deepClone, formatEvent, formatTimestamp, generateUniqueId, getAllInstanceKeys, getAnalyticsInstance, getBatchSize, getCurrentPageTitle, getCurrentPageUrl, getEventSize, getGlobalAnalytics, getPageDuration, getReferrer, isAnalyticsInitialized, isDevelopment, isMobile, mergeEventProperties, resetAllAnalytics, resetAnalytics, safeParse, safeStringify, sanitizeEvent, setGlobalAnalytics, throttle, useAnalytics, useAutoTracking, useErrorTracking, usePageDuration, usePageView, usePerformanceTracking, useTrackClick, useTrackEvent, validateEvent, validateEvents, webAdapter };
1848
2524
  //# sourceMappingURL=index.mjs.map
1849
2525
  //# sourceMappingURL=index.mjs.map