@tsingroc/tsingroc-components 4.3.0 → 4.4.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.
- package/dist/components/Auth.d.ts +2 -2
- package/dist/components/Auth.js +15 -10
- package/dist/components/Auth.js.map +1 -1
- package/dist/components/Calendar.js +1 -1
- package/dist/components/Calendar.js.map +1 -1
- package/dist/components/Header.d.ts +1 -1
- package/dist/components/Header.js.map +1 -1
- package/dist/components/IndicatorLight.js +1 -1
- package/dist/components/IndicatorLight.js.map +1 -1
- package/dist/components/LineChartEditor.js +6 -6
- package/dist/components/LineChartEditor.js.map +1 -1
- package/dist/components/LineChartTable.js +6 -5
- package/dist/components/LineChartTable.js.map +1 -1
- package/dist/components/LinkedECharts.d.ts +17 -0
- package/dist/components/LinkedECharts.js +34 -0
- package/dist/components/LinkedECharts.js.map +1 -0
- package/dist/components/LinkedLineChart.d.ts +3 -3
- package/dist/components/LinkedLineChart.js +8 -59
- package/dist/components/LinkedLineChart.js.map +1 -1
- package/dist/components/QuickDateRangePicker.d.ts +1 -1
- package/dist/components/QuickDateRangePicker.js.map +1 -1
- package/dist/components/SegmentedButtons.js.map +1 -1
- package/dist/components/Sidebar.js +3 -3
- package/dist/components/Sidebar.js.map +1 -1
- package/dist/components/StrictECharts.d.ts +1 -0
- package/dist/components/StrictECharts.js +2 -0
- package/dist/components/StrictECharts.js.map +1 -0
- package/dist/components/TsingrocDatePicker.d.ts +1 -1
- package/dist/components/TsingrocDatePicker.js +1 -1
- package/dist/components/TsingrocDatePicker.js.map +1 -1
- package/dist/components/TsingrocTheme.js +1 -1
- package/dist/components/TsingrocTheme.js.map +1 -1
- package/dist/components/UserButton.js +2 -1
- package/dist/components/UserButton.js.map +1 -1
- package/dist/components/VerticalColorLegend.js +1 -1
- package/dist/components/VerticalColorLegend.js.map +1 -1
- package/dist/components/WeatherMap.js +8 -7
- package/dist/components/WeatherMap.js.map +1 -1
- package/dist/deckgl/TiandituLayer.d.ts +2 -2
- package/dist/deckgl/TiandituLayer.js.map +1 -1
- package/dist/deckgl/WeatherData.js.map +1 -1
- package/dist/echarts/coordinateSystem.js +2 -2
- package/dist/echarts/coordinateSystem.js.map +1 -1
- package/dist/echarts/gl.d.ts +1 -1
- package/dist/echarts/gl.js.map +1 -1
- package/dist/echarts/index.js +1 -0
- package/dist/echarts/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +16 -2
- package/src/components/Auth.tsx +17 -12
- package/src/components/Calendar.tsx +1 -1
- package/src/components/Header.tsx +1 -1
- package/src/components/IndicatorLight.tsx +1 -1
- package/src/components/LineChartEditor.tsx +13 -13
- package/src/components/LineChartTable.tsx +13 -12
- package/src/components/LinkedECharts.tsx +51 -0
- package/src/components/LinkedLineChart.tsx +17 -96
- package/src/components/QuickDateRangePicker.tsx +4 -4
- package/src/components/SegmentedButtons.tsx +1 -1
- package/src/components/Sidebar.tsx +4 -4
- package/src/components/StrictECharts.d.ts +47 -0
- package/src/components/StrictECharts.js +1 -0
- package/src/components/TsingrocDatePicker.tsx +4 -4
- package/src/components/TsingrocTheme.tsx +2 -1
- package/src/components/UserButton.tsx +4 -4
- package/src/components/VerticalColorLegend.tsx +3 -3
- package/src/components/WeatherMap.tsx +13 -12
- package/src/deckgl/TiandituLayer.ts +3 -3
- package/src/deckgl/WeatherData.ts +7 -7
- package/src/echarts/coordinateSystem.ts +3 -3
- package/src/echarts/gl.ts +2 -1
- package/src/echarts/index.ts +1 -0
- package/src/index.ts +13 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { ConfigProvider, Flex, Table, theme, type FlexProps } from "antd";
|
|
2
|
+
import { createStyles } from "antd-style";
|
|
3
|
+
import type { ColumnType, ColumnsType, TableRef } from "antd/es/table";
|
|
3
4
|
import type { ElementEvent, LineSeriesOption } from "echarts";
|
|
4
5
|
import {
|
|
5
|
-
type TdHTMLAttributes,
|
|
6
6
|
useContext,
|
|
7
7
|
useEffect,
|
|
8
8
|
useMemo,
|
|
9
9
|
useRef,
|
|
10
10
|
useState,
|
|
11
|
+
type TdHTMLAttributes,
|
|
11
12
|
} from "react";
|
|
12
|
-
import { createStyles } from "antd-style";
|
|
13
|
-
import EChartsReact from "echarts-for-react";
|
|
14
13
|
|
|
15
14
|
import * as echarts from "../echarts";
|
|
15
|
+
import StrictECharts from "./StrictECharts";
|
|
16
16
|
|
|
17
17
|
export interface LineChartTableProps extends Omit<FlexProps, "children"> {
|
|
18
18
|
/** X 轴的数据。*/
|
|
@@ -70,18 +70,19 @@ function LineChartTable(props: LineChartTableProps) {
|
|
|
70
70
|
const isDark =
|
|
71
71
|
useContext(ConfigProvider.ConfigContext).theme?.algorithm ===
|
|
72
72
|
theme.darkAlgorithm;
|
|
73
|
-
const echartsRef = useRef<
|
|
73
|
+
const echartsRef = useRef<StrictECharts>(null);
|
|
74
74
|
const tableRef = useRef<TableRef>(null);
|
|
75
75
|
type HoverSource = "chart" | "table";
|
|
76
76
|
const [[hoverSource, hoverXIndex, hoverY], setHover] = useState<
|
|
77
77
|
[] | [HoverSource, number] | [HoverSource, number, number]
|
|
78
78
|
>(EMPTY);
|
|
79
|
-
let
|
|
79
|
+
let closestYIndex: number | undefined;
|
|
80
|
+
let closestY: number | undefined;
|
|
80
81
|
if (hoverXIndex !== undefined && hoverY !== undefined) {
|
|
81
82
|
let minDist = Infinity;
|
|
82
83
|
series.forEach((series, index) => {
|
|
83
84
|
const y = series.data[hoverXIndex];
|
|
84
|
-
const dist = Math.abs(y - hoverY
|
|
85
|
+
const dist = Math.abs(y - hoverY);
|
|
85
86
|
if (dist < minDist) {
|
|
86
87
|
closestYIndex = index;
|
|
87
88
|
closestY = y;
|
|
@@ -127,7 +128,7 @@ function LineChartTable(props: LineChartTableProps) {
|
|
|
127
128
|
},
|
|
128
129
|
);
|
|
129
130
|
useEffect(() => {
|
|
130
|
-
const inst = echartsRef.current?.getEchartsInstance()
|
|
131
|
+
const inst = echartsRef.current?.getEchartsInstance().getZr();
|
|
131
132
|
if (!inst) return () => {};
|
|
132
133
|
const onMousemove = (event: ElementEvent) => {
|
|
133
134
|
const inst = echartsRef.current?.getEchartsInstance();
|
|
@@ -199,7 +200,7 @@ function LineChartTable(props: LineChartTableProps) {
|
|
|
199
200
|
className: cx({
|
|
200
201
|
[styles.rowHovered]: data.hover !== undefined,
|
|
201
202
|
}),
|
|
202
|
-
onMouseEnter: () => setHover(["table", index
|
|
203
|
+
onMouseEnter: () => setHover(["table", index as number]),
|
|
203
204
|
onMouseLeave: () => setHover(EMPTY),
|
|
204
205
|
}),
|
|
205
206
|
},
|
|
@@ -218,7 +219,7 @@ function LineChartTable(props: LineChartTableProps) {
|
|
|
218
219
|
[styles.cellHovered]: data.hover === yIndex,
|
|
219
220
|
}),
|
|
220
221
|
onMouseEnter: () =>
|
|
221
|
-
setHover(["table", xIndex
|
|
222
|
+
setHover(["table", xIndex as number, data[`y${series.name}`]]),
|
|
222
223
|
onMouseLeave: () => setHover(EMPTY),
|
|
223
224
|
}),
|
|
224
225
|
}),
|
|
@@ -241,7 +242,7 @@ function LineChartTable(props: LineChartTableProps) {
|
|
|
241
242
|
};
|
|
242
243
|
return (
|
|
243
244
|
<Flex vertical gap={token.marginXS} {...rest}>
|
|
244
|
-
<
|
|
245
|
+
<StrictECharts
|
|
245
246
|
ref={echartsRef}
|
|
246
247
|
option={option}
|
|
247
248
|
theme={isDark ? "dark" : undefined}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as echarts from "echarts";
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useContext,
|
|
6
|
+
useId,
|
|
7
|
+
type ComponentType,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from "react";
|
|
10
|
+
|
|
11
|
+
import StrictECharts, { type StrictEChartsProps } from "./StrictECharts";
|
|
12
|
+
|
|
13
|
+
const LinkContext = createContext<string>("global");
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 联动上下文的 Provider,用于包裹需要联动的图表。
|
|
17
|
+
*/
|
|
18
|
+
export function EChartsLinkProvider(props: { children: ReactNode }) {
|
|
19
|
+
return (
|
|
20
|
+
<LinkContext.Provider value={useId()}>{props.children}</LinkContext.Provider>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 高阶组件,用于为任何签名与 `StrictECharts` 相同的图表组件添加联动功能。
|
|
26
|
+
*/
|
|
27
|
+
export function withEChartsLink(ECharts: ComponentType<StrictEChartsProps>) {
|
|
28
|
+
return forwardRef<StrictECharts, StrictEChartsProps>(
|
|
29
|
+
(props, ref): ReactNode => {
|
|
30
|
+
const group = useContext(LinkContext);
|
|
31
|
+
return (
|
|
32
|
+
<ECharts
|
|
33
|
+
// @ts-expect-error unfixable error
|
|
34
|
+
ref={ref}
|
|
35
|
+
{...props}
|
|
36
|
+
onChartReady={(instance) => {
|
|
37
|
+
instance.group = group;
|
|
38
|
+
echarts.connect(group);
|
|
39
|
+
props.onChartReady?.(instance);
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 具有联动功能的 `StrictECharts` 组件,签名与 `StrictECharts` 完全一致。
|
|
49
|
+
*/
|
|
50
|
+
const LinkedECharts = withEChartsLink(StrictECharts);
|
|
51
|
+
export default LinkedECharts;
|
|
@@ -1,33 +1,17 @@
|
|
|
1
1
|
import { ConfigProvider, theme } from "antd";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type ReactNode,
|
|
5
|
-
useContext,
|
|
6
|
-
useEffect,
|
|
7
|
-
useId,
|
|
8
|
-
useMemo,
|
|
9
|
-
useRef,
|
|
10
|
-
} from "react";
|
|
11
|
-
import EChartsReact, { type EChartsReactProps } from "echarts-for-react";
|
|
12
|
-
import type { LineSeriesOption, Payload } from "echarts";
|
|
2
|
+
import type { LineSeriesOption } from "echarts";
|
|
3
|
+
import { createContext, useContext, type ReactNode } from "react";
|
|
13
4
|
|
|
14
5
|
import * as echarts from "../echarts";
|
|
6
|
+
import LinkedECharts, { EChartsLinkProvider } from "./LinkedECharts";
|
|
7
|
+
import type { StrictEChartsProps } from "./StrictECharts";
|
|
15
8
|
|
|
16
9
|
interface LineChartLinkContext {
|
|
17
|
-
listeners: LinkEventListener[];
|
|
18
10
|
xData: (string | number)[];
|
|
19
11
|
xName: string;
|
|
20
12
|
}
|
|
21
13
|
|
|
22
|
-
type LinkEvent = { sourceId: string } & (
|
|
23
|
-
| { type: "highlight"; xIndex: number }
|
|
24
|
-
| { type: "downplay" }
|
|
25
|
-
| { type: "datazoom"; start: number; end: number }
|
|
26
|
-
);
|
|
27
|
-
type LinkEventListener = (event: LinkEvent) => void;
|
|
28
|
-
|
|
29
14
|
const LineChartLinkContext = createContext<LineChartLinkContext>({
|
|
30
|
-
listeners: [],
|
|
31
15
|
xData: [],
|
|
32
16
|
xName: "时间",
|
|
33
17
|
});
|
|
@@ -50,23 +34,22 @@ export interface LineChartLinkProviderProps {
|
|
|
50
34
|
* 用于包裹需要联动的 {@linkcode LinkedLineChart} 组件。
|
|
51
35
|
*/
|
|
52
36
|
export function LineChartLinkProvider(props: LineChartLinkProviderProps) {
|
|
53
|
-
const listenersRef = useRef<LinkEventListener[]>([]);
|
|
54
|
-
|
|
55
37
|
return (
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
38
|
+
<EChartsLinkProvider>
|
|
39
|
+
<LineChartLinkContext.Provider
|
|
40
|
+
value={{
|
|
41
|
+
xData: props.xData,
|
|
42
|
+
xName: props.xName ?? "时间",
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
{props.children}
|
|
46
|
+
</LineChartLinkContext.Provider>
|
|
47
|
+
</EChartsLinkProvider>
|
|
65
48
|
);
|
|
66
49
|
}
|
|
67
50
|
|
|
68
51
|
export interface LinkedLineChartProps
|
|
69
|
-
extends Omit<
|
|
52
|
+
extends Omit<StrictEChartsProps, "option"> {
|
|
70
53
|
/**
|
|
71
54
|
* Y 轴的名称。
|
|
72
55
|
* @default "数值"
|
|
@@ -98,9 +81,7 @@ function LinkedLineChart(props: LinkedLineChartProps) {
|
|
|
98
81
|
const isDark =
|
|
99
82
|
useContext(ConfigProvider.ConfigContext).theme?.algorithm ===
|
|
100
83
|
theme.darkAlgorithm;
|
|
101
|
-
const
|
|
102
|
-
const { listeners, xData, xName } = useContext(LineChartLinkContext);
|
|
103
|
-
const currentId = useId();
|
|
84
|
+
const { xData, xName } = useContext(LineChartLinkContext);
|
|
104
85
|
const option = echarts.buildEChartsOption(
|
|
105
86
|
{
|
|
106
87
|
backgroundColor: "transparent",
|
|
@@ -151,69 +132,9 @@ function LinkedLineChart(props: LinkedLineChartProps) {
|
|
|
151
132
|
],
|
|
152
133
|
},
|
|
153
134
|
);
|
|
154
|
-
const onEvents = useMemo(
|
|
155
|
-
() => ({
|
|
156
|
-
highlight: (payload: Payload) => {
|
|
157
|
-
const batch = payload.batch;
|
|
158
|
-
if (!batch || batch.length === 0) return;
|
|
159
|
-
listeners.forEach((listener) =>
|
|
160
|
-
listener({
|
|
161
|
-
type: "highlight",
|
|
162
|
-
sourceId: currentId,
|
|
163
|
-
xIndex: batch[0].dataIndex,
|
|
164
|
-
}),
|
|
165
|
-
);
|
|
166
|
-
},
|
|
167
|
-
downplay: () => {
|
|
168
|
-
listeners.forEach((listener) =>
|
|
169
|
-
listener({ type: "downplay", sourceId: currentId }),
|
|
170
|
-
);
|
|
171
|
-
},
|
|
172
|
-
datazoom: (payload: Payload) => {
|
|
173
|
-
listeners.forEach((listener) =>
|
|
174
|
-
listener({
|
|
175
|
-
type: "datazoom",
|
|
176
|
-
sourceId: currentId,
|
|
177
|
-
start: payload.start,
|
|
178
|
-
end: payload.end,
|
|
179
|
-
}),
|
|
180
|
-
);
|
|
181
|
-
},
|
|
182
|
-
}),
|
|
183
|
-
[currentId, listeners],
|
|
184
|
-
);
|
|
185
|
-
useEffect(() => {
|
|
186
|
-
const listener = (event: LinkEvent) => {
|
|
187
|
-
if (event.sourceId === currentId) return;
|
|
188
|
-
const chart = echartsRef.current?.getEchartsInstance();
|
|
189
|
-
if (!chart) return;
|
|
190
|
-
switch (event.type) {
|
|
191
|
-
case "highlight":
|
|
192
|
-
chart.dispatchAction(
|
|
193
|
-
{ type: "showTip", seriesIndex: 0, dataIndex: event.xIndex },
|
|
194
|
-
{ silent: true },
|
|
195
|
-
);
|
|
196
|
-
break;
|
|
197
|
-
case "downplay":
|
|
198
|
-
chart.setOption({ xAxis: { axisPointer: { status: "hide" } } });
|
|
199
|
-
chart.dispatchAction({ type: "hideTip" }, { silent: true });
|
|
200
|
-
break;
|
|
201
|
-
case "datazoom":
|
|
202
|
-
chart.dispatchAction(
|
|
203
|
-
{ type: "dataZoom", start: event.start, end: event.end },
|
|
204
|
-
{ silent: true },
|
|
205
|
-
);
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
listeners.push(listener);
|
|
210
|
-
return () => listeners.splice(listeners.indexOf(listener), 1) && undefined;
|
|
211
|
-
}, [currentId, listeners]);
|
|
212
135
|
return (
|
|
213
|
-
<
|
|
214
|
-
ref={echartsRef}
|
|
136
|
+
<LinkedECharts
|
|
215
137
|
option={option}
|
|
216
|
-
onEvents={onEvents}
|
|
217
138
|
theme={isDark ? "dark" : undefined}
|
|
218
139
|
{...rest}
|
|
219
140
|
/>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Button,
|
|
3
|
-
type ButtonProps,
|
|
4
3
|
DatePicker,
|
|
5
4
|
Space,
|
|
5
|
+
type ButtonProps,
|
|
6
6
|
type SpaceProps,
|
|
7
7
|
} from "antd";
|
|
8
|
+
import type { RangePickerProps } from "antd/es/date-picker";
|
|
8
9
|
import dayjs, { type Dayjs } from "dayjs";
|
|
9
10
|
import type { NoUndefinedRangeValueType } from "rc-picker/lib/PickerInput/RangePicker";
|
|
10
|
-
import type { RangePickerProps } from "antd/es/date-picker";
|
|
11
11
|
import { useState } from "react";
|
|
12
12
|
|
|
13
13
|
export interface QuickDateRangePickerProps
|
|
@@ -72,8 +72,8 @@ function QuickDateRangePicker(props: QuickDateRangePickerProps) {
|
|
|
72
72
|
value={range}
|
|
73
73
|
allowClear={false}
|
|
74
74
|
onChange={(range) => {
|
|
75
|
-
setRange(range
|
|
76
|
-
onChange?.(range
|
|
75
|
+
setRange(range as NoUndefinedRangeValueType<Dayjs>);
|
|
76
|
+
onChange?.(range as NoUndefinedRangeValueType<Dayjs>); // 由于 allowClear=false,这里 range 不可能为 null
|
|
77
77
|
}}
|
|
78
78
|
{...pickerProps}
|
|
79
79
|
/>
|
|
@@ -37,7 +37,7 @@ export function TimeUnitSwitcher(props: TimeUnitSwitcherProps) {
|
|
|
37
37
|
<Radio.Group
|
|
38
38
|
optionType="button"
|
|
39
39
|
options={TIME_UNIT_OPTIONS}
|
|
40
|
-
onChange={(e) => onChange?.(e.target.value)}
|
|
40
|
+
onChange={(e) => onChange?.(e.target.value as "day" | "week" | "month")}
|
|
41
41
|
{...rest}
|
|
42
42
|
/>
|
|
43
43
|
);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Button, Flex, Layout, Menu, type MenuProps } from "antd";
|
|
2
|
+
import { createStyles } from "antd-style";
|
|
3
|
+
import { useState, type CSSProperties, type Key, type ReactNode } from "react";
|
|
1
4
|
import {
|
|
2
5
|
BarChartOutlined,
|
|
3
6
|
LeftOutlined,
|
|
@@ -5,9 +8,6 @@ import {
|
|
|
5
8
|
SwapOutlined,
|
|
6
9
|
TeamOutlined,
|
|
7
10
|
} from "@ant-design/icons";
|
|
8
|
-
import { Button, Flex, Layout, Menu, type MenuProps } from "antd";
|
|
9
|
-
import { type CSSProperties, type Key, type ReactNode, useState } from "react";
|
|
10
|
-
import { createStyles } from "antd-style";
|
|
11
11
|
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
13
|
import { AuthCheck, AuthProvider } from "./Auth";
|
|
@@ -178,7 +178,7 @@ function Sidebar(props: SidebarProps) {
|
|
|
178
178
|
className={cx(styles.sidebarMenu)}
|
|
179
179
|
{...rest}
|
|
180
180
|
/>
|
|
181
|
-
{footer === null ? null : footer
|
|
181
|
+
{footer === null ? null : footer(collapsed)}
|
|
182
182
|
{collapsible && (
|
|
183
183
|
<Button
|
|
184
184
|
className={cx(styles.sidebarBtn)}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ECharts, EChartsOption, init } from "echarts";
|
|
2
|
+
import type { EChartsReactProps as OrigEChartsReactProps } from "echarts-for-react/lib/types";
|
|
3
|
+
import type {
|
|
4
|
+
ECElementEvent,
|
|
5
|
+
ZRElementEventName,
|
|
6
|
+
} from "echarts/types/src/util/types.js";
|
|
7
|
+
import type { PureComponent } from "react";
|
|
8
|
+
|
|
9
|
+
export declare type ECEventDefinition = {
|
|
10
|
+
[K in ZRElementEventName]: (params: ECElementEvent) => boolean | undefined;
|
|
11
|
+
} & {
|
|
12
|
+
rendered: (params: { elapsedTime: number }) => boolean | undefined;
|
|
13
|
+
finished: () => boolean | undefined;
|
|
14
|
+
} & {
|
|
15
|
+
[key: string]: (...args: unknown[]) => boolean | undefined;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export declare type EChartsInitOpts = typeof init extends (
|
|
19
|
+
dom?: infer _,
|
|
20
|
+
theme?: infer _,
|
|
21
|
+
opts?: infer Opts,
|
|
22
|
+
) => unknown
|
|
23
|
+
? Opts
|
|
24
|
+
: never;
|
|
25
|
+
|
|
26
|
+
export declare interface StrictEChartsProps
|
|
27
|
+
extends Omit<OrigEChartsReactProps, "opts" | "shouldSetOption"> {
|
|
28
|
+
readonly option: EChartsOption;
|
|
29
|
+
readonly onEvents?: ECEventDefinition;
|
|
30
|
+
readonly onChartReady?: (instance: ECharts) => void;
|
|
31
|
+
readonly opts?: EChartsInitOpts;
|
|
32
|
+
readonly shouldSetOption?: (
|
|
33
|
+
prevProps: StrictEChartsProps,
|
|
34
|
+
props: StrictEChartsProps,
|
|
35
|
+
) => boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 类型更加严格的 `EChartsReact`,在运行时只是 `EChartsReact` 的别名。
|
|
40
|
+
*/
|
|
41
|
+
declare class StrictECharts extends PureComponent<StrictEChartsProps> {
|
|
42
|
+
constructor(props: StrictEChartsProps);
|
|
43
|
+
ele: HTMLElement;
|
|
44
|
+
getEchartsInstance(): ECharts;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default StrictECharts;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "echarts-for-react";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type DatePickerProps as AntdDatePickerProps,
|
|
3
2
|
Button,
|
|
4
|
-
type ButtonProps,
|
|
5
3
|
DatePicker,
|
|
6
4
|
Space,
|
|
5
|
+
type DatePickerProps as AntdDatePickerProps,
|
|
6
|
+
type ButtonProps,
|
|
7
7
|
} from "antd";
|
|
8
|
-
import { LeftOutlined, RightOutlined } from "@ant-design/icons";
|
|
9
|
-
import type { Dayjs } from "dayjs";
|
|
10
8
|
import type { SpaceCompactProps } from "antd/es/space/Compact";
|
|
9
|
+
import type { Dayjs } from "dayjs";
|
|
11
10
|
import { useState } from "react";
|
|
11
|
+
import { LeftOutlined, RightOutlined } from "@ant-design/icons";
|
|
12
12
|
|
|
13
13
|
export interface DatePickerProps extends Omit<SpaceCompactProps, "onChange"> {
|
|
14
14
|
value?: Dayjs;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ConfigProvider, theme } from "antd";
|
|
2
|
+
import zhCN from "antd/es/locale/zh_CN";
|
|
2
3
|
import dayjs from "dayjs";
|
|
3
4
|
import type { ReactNode } from "react";
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
import "dayjs/locale/zh-cn";
|
|
6
7
|
|
|
7
8
|
export interface TsingrocThemeProps {
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Avatar,
|
|
3
3
|
Button,
|
|
4
|
-
type ButtonProps,
|
|
5
4
|
Dropdown,
|
|
6
|
-
type DropdownProps,
|
|
7
5
|
theme,
|
|
6
|
+
type ButtonProps,
|
|
7
|
+
type DropdownProps,
|
|
8
8
|
} from "antd";
|
|
9
|
+
import type { Account } from "casdoor-js-sdk/lib/esm/sdk";
|
|
9
10
|
import {
|
|
10
11
|
DownOutlined,
|
|
11
12
|
LogoutOutlined,
|
|
12
13
|
UpOutlined,
|
|
13
14
|
UserOutlined,
|
|
14
15
|
} from "@ant-design/icons";
|
|
15
|
-
import type { Account } from "casdoor-js-sdk/lib/esm/sdk";
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
AuthCheck, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
19
|
AuthProvider, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
useAuth,
|
|
20
21
|
type CasdoorAuth,
|
|
21
22
|
type LocalAuth,
|
|
22
|
-
useAuth,
|
|
23
23
|
} from "./Auth";
|
|
24
24
|
|
|
25
25
|
export interface UserButtonProps extends ButtonProps {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { HTMLAttributes } from "react";
|
|
2
1
|
import { theme } from "antd";
|
|
2
|
+
import type { HTMLAttributes } from "react";
|
|
3
3
|
|
|
4
4
|
export interface VerticalColorLegendProps
|
|
5
5
|
extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -10,7 +10,7 @@ export interface VerticalColorLegendProps
|
|
|
10
10
|
function VerticalColorLegend(props: VerticalColorLegendProps) {
|
|
11
11
|
const { title, palette, ...rest } = props;
|
|
12
12
|
const { token } = theme.useToken();
|
|
13
|
-
const max = palette.at(-1)
|
|
13
|
+
const max = (palette.at(-1) as [number, [number, number, number]])[0];
|
|
14
14
|
const min = palette[0][0];
|
|
15
15
|
const range = max - min;
|
|
16
16
|
return (
|
|
@@ -58,7 +58,7 @@ function VerticalColorLegend(props: VerticalColorLegendProps) {
|
|
|
58
58
|
key={i}
|
|
59
59
|
style={{
|
|
60
60
|
position: "relative",
|
|
61
|
-
top: ((max - value) / range) * 100
|
|
61
|
+
top: `${((max - value) / range) * 100}%`,
|
|
62
62
|
}}
|
|
63
63
|
>
|
|
64
64
|
{value.toFixed(1)}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { Button, Flex, Slider, Spin, theme, type ButtonProps } from "antd";
|
|
2
|
+
import { createStyles } from "antd-style";
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import DeckGL from "deck.gl";
|
|
3
5
|
import {
|
|
6
|
+
useMemo,
|
|
7
|
+
useState,
|
|
4
8
|
type CSSProperties,
|
|
5
9
|
type HTMLAttributes,
|
|
6
10
|
type ReactNode,
|
|
7
|
-
useMemo,
|
|
8
|
-
useState,
|
|
9
11
|
} from "react";
|
|
10
12
|
import { MdDewPoint, MdThermostat } from "react-icons/md";
|
|
11
13
|
import {
|
|
@@ -15,10 +17,9 @@ import {
|
|
|
15
17
|
WiRain,
|
|
16
18
|
WiStrongWind,
|
|
17
19
|
} from "react-icons/wi";
|
|
18
|
-
import
|
|
19
|
-
import dayjs from "dayjs";
|
|
20
|
-
import DeckGL from "deck.gl";
|
|
20
|
+
import * as wl from "weatherlayers-gl";
|
|
21
21
|
|
|
22
|
+
import { TiandituLayer } from "../deckgl";
|
|
22
23
|
import {
|
|
23
24
|
extractMagnitudeData,
|
|
24
25
|
extractScalarData,
|
|
@@ -26,7 +27,6 @@ import {
|
|
|
26
27
|
getBounds,
|
|
27
28
|
type WeatherData,
|
|
28
29
|
} from "../deckgl/WeatherData";
|
|
29
|
-
import { TiandituLayer } from "../deckgl";
|
|
30
30
|
import TsingrocTheme from "./TsingrocTheme";
|
|
31
31
|
import VerticalColorLegend from "./VerticalColorLegend";
|
|
32
32
|
|
|
@@ -88,7 +88,7 @@ function WeatherMap(props: WeatherMapProps) {
|
|
|
88
88
|
return adaptiveColorCoding(
|
|
89
89
|
scalarFrame.min,
|
|
90
90
|
scalarFrame.max,
|
|
91
|
-
selectedScalar.adaptivePalette
|
|
91
|
+
selectedScalar.adaptivePalette,
|
|
92
92
|
);
|
|
93
93
|
}, [selectedScalar, scalarFrame]);
|
|
94
94
|
return (
|
|
@@ -141,7 +141,7 @@ function WeatherMap(props: WeatherMapProps) {
|
|
|
141
141
|
tooltip={{
|
|
142
142
|
formatter: (value) =>
|
|
143
143
|
dayjs
|
|
144
|
-
.unix(data.coords.time[value
|
|
144
|
+
.unix(data.coords.time[value as number])
|
|
145
145
|
.format("YYYY-MM-DD HH:mm:ss"),
|
|
146
146
|
}}
|
|
147
147
|
/>
|
|
@@ -298,8 +298,8 @@ interface ScalarInfo {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
const iconSizeFix = (ratio: number): CSSProperties => ({
|
|
301
|
-
fontSize: ratio
|
|
302
|
-
margin: -(1 - 1 / ratio) / 3
|
|
301
|
+
fontSize: `${ratio}em`,
|
|
302
|
+
margin: `${-(1 - 1 / ratio) / 3}em ${-(1 - 1 / ratio) / 2}em`,
|
|
303
303
|
});
|
|
304
304
|
|
|
305
305
|
const TEMPERATURE_ADAPTIVE_PALETTE: AdaptivePalette = {
|
|
@@ -506,6 +506,7 @@ function adaptiveColorCoding(
|
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
// 参考 https://dbba.sacinfo.org.cn/attachment/downloadStdFile?pk=dda6960be9435ed7ab01e336e197cd67a072a28725f03685bfbdaf19cbfeb267
|
|
509
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
509
510
|
function fixedColorCoding<T>(min: number, max: number, palette: [number, T][]) {
|
|
510
511
|
let minIdx = palette.findIndex(([value]) => value > min) - 1;
|
|
511
512
|
if (minIdx < -1) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BitmapLayer, CompositeLayer } from "deck.gl";
|
|
2
|
-
import { TileLayer, type TileLayerProps } from "@deck.gl/geo-layers";
|
|
3
2
|
import type { DefaultProps } from "@deck.gl/core";
|
|
3
|
+
import { TileLayer, type TileLayerProps } from "@deck.gl/geo-layers";
|
|
4
4
|
|
|
5
5
|
export interface TiandituLayerProps {
|
|
6
6
|
tiandituTk: string;
|
|
@@ -14,7 +14,7 @@ export default class TiandituLayer extends CompositeLayer<TiandituLayerProps> {
|
|
|
14
14
|
type: { type: "object", value: "vec" },
|
|
15
15
|
layer: { type: "object", value: "base" },
|
|
16
16
|
};
|
|
17
|
-
renderLayers() {
|
|
17
|
+
renderLayers(): TileLayer {
|
|
18
18
|
const { tiandituTk, type, layer } = this.props;
|
|
19
19
|
const actualType = layer === "base" ? type : "c" + type[0] + "a";
|
|
20
20
|
return new TileLayer(
|
|
@@ -24,7 +24,7 @@ export default class TiandituLayer extends CompositeLayer<TiandituLayerProps> {
|
|
|
24
24
|
maxZoom: 18,
|
|
25
25
|
zoomOffset: 1,
|
|
26
26
|
renderSubLayers,
|
|
27
|
-
}),
|
|
27
|
+
}) as TileLayerProps,
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -42,11 +42,11 @@ export interface WeatherData {
|
|
|
42
42
|
export const getBounds = (data: WeatherData): BitmapBoundingBox => {
|
|
43
43
|
const [lngMin, lngMax] = [
|
|
44
44
|
data.coords.longitude[0],
|
|
45
|
-
data.coords.longitude.at(-1)
|
|
45
|
+
data.coords.longitude.at(-1) as number,
|
|
46
46
|
].sort();
|
|
47
47
|
const [latMin, latMax] = [
|
|
48
48
|
data.coords.latitude[0],
|
|
49
|
-
data.coords.latitude.at(-1)
|
|
49
|
+
data.coords.latitude.at(-1) as number,
|
|
50
50
|
].sort();
|
|
51
51
|
return [lngMin, latMin, lngMax, latMax];
|
|
52
52
|
};
|
|
@@ -69,7 +69,7 @@ export function extractScalarData(
|
|
|
69
69
|
for (let i = 0; i < data.dims.longitude; i++) {
|
|
70
70
|
for (let j = 0; j < data.dims.latitude; j++) {
|
|
71
71
|
for (let t = 0; t < data.dims.time; t++) {
|
|
72
|
-
let value = data.data_vars[variable]
|
|
72
|
+
let value = (data.data_vars[variable] as number[][][])[i][j][t];
|
|
73
73
|
if (value === -9999) value = NaN;
|
|
74
74
|
result[t].image.data[p] = value;
|
|
75
75
|
if (value > result[t].max) result[t].max = value;
|
|
@@ -104,8 +104,8 @@ export function extractVectorData(
|
|
|
104
104
|
for (let i = 0; i < data.dims.longitude; i++) {
|
|
105
105
|
for (let j = 0; j < data.dims.latitude; j++) {
|
|
106
106
|
for (let t = 0; t < data.dims.time; t++) {
|
|
107
|
-
let u = data.data_vars[variableU]
|
|
108
|
-
let v = data.data_vars[variableV]
|
|
107
|
+
let u = (data.data_vars[variableU] as number[][][])[i][j][t];
|
|
108
|
+
let v = (data.data_vars[variableV] as number[][][])[i][j][t];
|
|
109
109
|
if (u === -9999) u = NaN;
|
|
110
110
|
if (v === -9999) v = NaN;
|
|
111
111
|
result[t].data[p] = u;
|
|
@@ -136,8 +136,8 @@ export function extractMagnitudeData(
|
|
|
136
136
|
for (let i = 0; i < data.dims.longitude; i++) {
|
|
137
137
|
for (let j = 0; j < data.dims.latitude; j++) {
|
|
138
138
|
for (let t = 0; t < data.dims.time; t++) {
|
|
139
|
-
let u = data.data_vars[variableU]
|
|
140
|
-
let v = data.data_vars[variableV]
|
|
139
|
+
let u = (data.data_vars[variableU] as number[][][])[i][j][t];
|
|
140
|
+
let v = (data.data_vars[variableV] as number[][][])[i][j][t];
|
|
141
141
|
if (u === -9999) u = NaN;
|
|
142
142
|
if (v === -9999) v = NaN;
|
|
143
143
|
const value = Math.sqrt(u * u + v * v);
|
|
@@ -84,7 +84,7 @@ export function useGrid(option: GridOption): EChartsComponent {
|
|
|
84
84
|
id: gridId + "y",
|
|
85
85
|
type: option.yAxis?.type ?? "value",
|
|
86
86
|
gridId,
|
|
87
|
-
nameGap:
|
|
87
|
+
nameGap: 10,
|
|
88
88
|
...option.yAxis,
|
|
89
89
|
nameTextStyle: {
|
|
90
90
|
align: "left",
|
|
@@ -100,7 +100,7 @@ export function useGrid(option: GridOption): EChartsComponent {
|
|
|
100
100
|
yAxis: [yAxis],
|
|
101
101
|
series: option.series
|
|
102
102
|
?.flatMap((item) => item.series)
|
|
103
|
-
|
|
103
|
+
.map((series) => ({
|
|
104
104
|
...series,
|
|
105
105
|
coordinateSystem: "cartesian2d",
|
|
106
106
|
xAxisId,
|
|
@@ -113,7 +113,7 @@ const MINIMAL_GRID: GridPreset = (grid, xAxis, yAxis) => {
|
|
|
113
113
|
grid.top = 0;
|
|
114
114
|
xAxis.show = false;
|
|
115
115
|
if (
|
|
116
|
-
(xAxis.type === undefined && (xAxis as { data
|
|
116
|
+
(xAxis.type === undefined && (xAxis as { data?: [] }).data !== undefined) ||
|
|
117
117
|
xAxis.type === "category"
|
|
118
118
|
) {
|
|
119
119
|
(xAxis as { boundaryGap: boolean }).boundaryGap = false;
|
package/src/echarts/gl.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { FlowGLSeriesOption as OrigFlowGLSeriesOption } from "echarts";
|
|
1
2
|
import type {
|
|
2
3
|
ComponentOption,
|
|
3
4
|
SeriesOnCartesianOptionMixin,
|
|
4
5
|
SeriesOnGeoOptionMixin,
|
|
5
6
|
} from "echarts/types/src/util/types.js";
|
|
6
|
-
|
|
7
|
+
|
|
7
8
|
import "echarts-gl";
|
|
8
9
|
|
|
9
10
|
import type { EChartsSeries } from ".";
|