@vtx/player 0.0.5 → 0.0.6
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/.eslintignore +11 -0
- package/.eslintrc.js +31 -0
- package/.prettierignore +10 -0
- package/.prettierrc.js +22 -0
- package/.storybook/main.js +58 -0
- package/.storybook/manager.js +7 -0
- package/.storybook/preview-head.html +5 -0
- package/.storybook/preview.js +9 -0
- package/.storybook/proxy.js +6 -0
- package/.storybook/theme.js +8 -0
- package/.stylelintrc.json +13 -0
- package/.vscode/extensions.json +10 -0
- package/.vscode/settings.json +16 -0
- package/README.md +2 -2
- package/commitlint.config.js +10 -0
- package/package.json +98 -100
- package/public/h5player.min.js +311 -0
- package/public/playctrl1/AudioRenderer.js +225 -0
- package/public/playctrl1/DecodeWorker.js +711 -0
- package/public/playctrl1/Decoder.js +1 -0
- package/public/playctrl1/SuperRender_10.js +396 -0
- package/public/playctrl2/Decoder.js +21 -0
- package/public/playctrl2/Decoder.wasm +0 -0
- package/public/playctrl2/Decoder.worker.js +1 -0
- package/public/playctrl3/Decoder.js +21 -0
- package/public/playctrl3/Decoder.wasm +0 -0
- package/public/playctrl3/Decoder.worker.js +1 -0
- package/rollup.config.js +52 -0
- package/src/api/fetch.ts +55 -0
- package/src/api/index.ts +43 -0
- package/{dist/types/api/types.d.ts → src/api/types.ts} +131 -117
- package/src/components/bill-player/index.less +58 -0
- package/src/components/bill-player/index.stories.mdx +24 -0
- package/src/components/bill-player/index.stories.tsx +13 -0
- package/src/components/bill-player/index.tsx +267 -0
- package/src/components/controls/images/arrow.png +0 -0
- package/src/components/controls/images/error.png +0 -0
- package/src/components/controls/index.less +182 -0
- package/src/components/controls/index.tsx +312 -0
- package/src/components/history-control/images/collapse.png +0 -0
- package/src/components/history-control/index.less +211 -0
- package/src/components/history-control/index.stories.mdx +62 -0
- package/src/components/history-control/index.stories.tsx +130 -0
- package/src/components/history-control/index.tsx +368 -0
- package/src/components/history-player/index.less +98 -0
- package/src/components/history-player/index.stories.mdx +38 -0
- package/src/components/history-player/index.stories.tsx +12 -0
- package/src/components/history-player/index.tsx +206 -0
- package/src/components/live-channel-player/index.stories.mdx +29 -0
- package/src/components/live-channel-player/index.stories.tsx +11 -0
- package/src/components/live-channel-player/index.tsx +75 -0
- package/src/components/live-control/index.less +65 -0
- package/src/components/live-control/index.stories.mdx +64 -0
- package/src/components/live-control/index.stories.tsx +61 -0
- package/src/components/live-control/index.tsx +274 -0
- package/src/components/live-player/index.less +71 -0
- package/src/components/live-player/index.stories.mdx +35 -0
- package/src/components/live-player/index.stories.tsx +12 -0
- package/src/components/live-player/index.tsx +118 -0
- package/src/components/player/index.ts +318 -0
- package/src/context/index.ts +13 -0
- package/src/hooks/useSettings.tsx +14 -0
- package/src/icons/index.less +27 -0
- package/src/icons/index.tsx +518 -0
- package/{dist/types/main.d.ts → src/main.ts} +9 -8
- package/src/stories/intro.stories.mdx +16 -0
- package/src/typings/@vtx/utils/index.d.ts +27 -0
- package/src/typings/h5player.d.ts +133 -0
- package/src/utils/index.ts +215 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +24 -0
- package/dist/index.d.ts +0 -225
- package/dist/index.es.js +0 -533
- package/dist/index.es.js.map +0 -1
- package/dist/index.umd.js +0 -533
- package/dist/index.umd.js.map +0 -1
- package/dist/types/api/fetch.d.ts +0 -12
- package/dist/types/api/index.d.ts +0 -16
- package/dist/types/components/bill-player/index.d.ts +0 -21
- package/dist/types/components/controls/index.d.ts +0 -52
- package/dist/types/components/history-control/index.d.ts +0 -39
- package/dist/types/components/history-player/index.d.ts +0 -31
- package/dist/types/components/live-channel-player/index.d.ts +0 -18
- package/dist/types/components/live-control/index.d.ts +0 -37
- package/dist/types/components/live-player/index.d.ts +0 -22
- package/dist/types/components/player/index.d.ts +0 -84
- package/dist/types/context/index.d.ts +0 -8
- package/dist/types/hooks/useSettings.d.ts +0 -9
- package/dist/types/icons/index.d.ts +0 -54
- package/dist/types/utils/index.d.ts +0 -60
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import './index.less';
|
|
2
|
+
|
|
3
|
+
import { useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import Player from '../player';
|
|
6
|
+
import { useRequest } from 'ahooks';
|
|
7
|
+
import { Button, Popover, Slider, Space, Spin } from 'antd';
|
|
8
|
+
|
|
9
|
+
import { cloudControl } from '@/api';
|
|
10
|
+
import { CloudControlCommandType, CloudControlParams } from '@/api/types';
|
|
11
|
+
import {
|
|
12
|
+
CloseIcon,
|
|
13
|
+
TalkDisableIcon,
|
|
14
|
+
TalkIcon,
|
|
15
|
+
VolumeLargeIcon,
|
|
16
|
+
VolumeMutedIcon,
|
|
17
|
+
VolumeSmallIcon,
|
|
18
|
+
} from '@/icons';
|
|
19
|
+
|
|
20
|
+
import arrowImg from './images/arrow.png';
|
|
21
|
+
import errorImg from './images/error.png';
|
|
22
|
+
|
|
23
|
+
interface VolumeControlProps {
|
|
24
|
+
container: HTMLDivElement | null;
|
|
25
|
+
player?: Player;
|
|
26
|
+
defaultValue?: number;
|
|
27
|
+
}
|
|
28
|
+
/** 音量控制 */
|
|
29
|
+
export const VolumeControl = (props: VolumeControlProps) => {
|
|
30
|
+
const { defaultValue = 0, player, container } = props;
|
|
31
|
+
const [value, setValue] = useState(defaultValue);
|
|
32
|
+
const preValueRef = useRef(defaultValue);
|
|
33
|
+
const handleChange = (val: number) => {
|
|
34
|
+
preValueRef.current = val;
|
|
35
|
+
player?.setVolume(val);
|
|
36
|
+
setValue(val);
|
|
37
|
+
};
|
|
38
|
+
const content = (
|
|
39
|
+
<div className="volume-content">
|
|
40
|
+
<span className="value">{value}</span>
|
|
41
|
+
<Slider vertical value={value} onChange={handleChange} max={100} />
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
const handleVisibleChange = (visible: boolean) => {
|
|
45
|
+
if (container) {
|
|
46
|
+
if (visible) {
|
|
47
|
+
container.style.opacity = '1';
|
|
48
|
+
} else {
|
|
49
|
+
container.style.removeProperty('opacity');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const handleMuted = () => {
|
|
54
|
+
if (value === 0) {
|
|
55
|
+
handleChange(preValueRef.current);
|
|
56
|
+
} else {
|
|
57
|
+
handleChange(0);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return (
|
|
61
|
+
<Popover
|
|
62
|
+
title={null}
|
|
63
|
+
content={content}
|
|
64
|
+
overlayClassName="player-control-popover"
|
|
65
|
+
onVisibleChange={handleVisibleChange}
|
|
66
|
+
>
|
|
67
|
+
<div onClick={handleMuted}>
|
|
68
|
+
{value === 0 ? (
|
|
69
|
+
<VolumeMutedIcon />
|
|
70
|
+
) : value > 50 ? (
|
|
71
|
+
<VolumeLargeIcon />
|
|
72
|
+
) : (
|
|
73
|
+
<VolumeSmallIcon />
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
</Popover>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
type SpeedValue = 0.5 | 1 | 2 | 4 | 8;
|
|
81
|
+
interface SpeedControlProps {
|
|
82
|
+
container: HTMLDivElement | null;
|
|
83
|
+
player?: Player;
|
|
84
|
+
defaultValue?: SpeedValue;
|
|
85
|
+
}
|
|
86
|
+
/** 速度控制 */
|
|
87
|
+
export const SpeedControl = (props: SpeedControlProps) => {
|
|
88
|
+
const { defaultValue = 1, player, container } = props;
|
|
89
|
+
const [value, setValue] = useState<SpeedValue>(defaultValue);
|
|
90
|
+
const handleChange = (val: SpeedValue) => {
|
|
91
|
+
player?.setSpeed(val);
|
|
92
|
+
setValue(val);
|
|
93
|
+
};
|
|
94
|
+
const content = () => {
|
|
95
|
+
const list: SpeedValue[] = [0.5, 1, 2, 4, 8];
|
|
96
|
+
return (
|
|
97
|
+
<div className="speed-content">
|
|
98
|
+
{list.map((i) => (
|
|
99
|
+
<div className="item" key={i} onClick={() => handleChange(i)}>{`${i.toFixed(
|
|
100
|
+
1
|
|
101
|
+
)}x`}</div>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
const handleVisibleChange = (visible: boolean) => {
|
|
107
|
+
if (container) {
|
|
108
|
+
if (visible) {
|
|
109
|
+
container.style.opacity = '1';
|
|
110
|
+
} else {
|
|
111
|
+
container.style.removeProperty('opacity');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Popover
|
|
118
|
+
title={null}
|
|
119
|
+
content={content}
|
|
120
|
+
overlayClassName="player-control-popover"
|
|
121
|
+
onVisibleChange={handleVisibleChange}
|
|
122
|
+
>
|
|
123
|
+
<div className="vtx-player-speed-control">{`${value.toFixed(1)}x`}</div>
|
|
124
|
+
</Popover>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
interface ErrorStateProps {
|
|
129
|
+
/** 重试回调 */
|
|
130
|
+
onClick?: () => void;
|
|
131
|
+
}
|
|
132
|
+
export const ErrorState = (props: ErrorStateProps) => {
|
|
133
|
+
const { onClick } = props;
|
|
134
|
+
return (
|
|
135
|
+
<div className="error-container">
|
|
136
|
+
<img src={errorImg} alt="播放错误" />
|
|
137
|
+
<span className="text">视频播放失败,请稍后重试</span>
|
|
138
|
+
{onClick && (
|
|
139
|
+
<Button onClick={() => onClick()} type="primary">
|
|
140
|
+
点击重试
|
|
141
|
+
</Button>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const LoadingState = () => {
|
|
148
|
+
return (
|
|
149
|
+
<div className="loading-container">
|
|
150
|
+
<Spin size="large" />
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
interface PlayerHeaderProps {
|
|
156
|
+
/** 名称 */
|
|
157
|
+
name: string;
|
|
158
|
+
/** 关闭回调 */
|
|
159
|
+
onClose: () => void;
|
|
160
|
+
}
|
|
161
|
+
/** 播放器头部 */
|
|
162
|
+
export const PlayerHeader = (props: PlayerHeaderProps) => {
|
|
163
|
+
const { name, onClose } = props;
|
|
164
|
+
return (
|
|
165
|
+
<div className="vtx-player-header">
|
|
166
|
+
<span className="title">{name}</span>
|
|
167
|
+
<span className="close">
|
|
168
|
+
<CloseIcon
|
|
169
|
+
onClick={(e) => {
|
|
170
|
+
onClose();
|
|
171
|
+
e.stopPropagation();
|
|
172
|
+
}}
|
|
173
|
+
/>
|
|
174
|
+
</span>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
interface TalkControlProps {
|
|
180
|
+
/** 播放器 */
|
|
181
|
+
player?: Player;
|
|
182
|
+
/** 对讲url */
|
|
183
|
+
url: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 对讲控制器
|
|
188
|
+
* @returns
|
|
189
|
+
*/
|
|
190
|
+
export const TalkControl = (props: TalkControlProps) => {
|
|
191
|
+
const { player, url } = props;
|
|
192
|
+
const [active, setActive] = useState(false);
|
|
193
|
+
const handleClick = () => {
|
|
194
|
+
if (active) {
|
|
195
|
+
player?.stopTalk().then(() => setActive(false));
|
|
196
|
+
} else {
|
|
197
|
+
player?.startTalk(url).then(() => setActive(true));
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
return (
|
|
201
|
+
<div>
|
|
202
|
+
{active ? (
|
|
203
|
+
<TalkIcon active={true} onClick={handleClick} />
|
|
204
|
+
) : (
|
|
205
|
+
<TalkDisableIcon active={false} onClick={handleClick} />
|
|
206
|
+
)}
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export type CloudControlType = 'all' | 'onlyFocus' | 'onlyRotate' | 'none';
|
|
212
|
+
export type CloudControlPanelProps = {
|
|
213
|
+
query: Omit<CloudControlParams, 'action' | 'command'>;
|
|
214
|
+
type: CloudControlType;
|
|
215
|
+
};
|
|
216
|
+
/** 云台控制面板 */
|
|
217
|
+
export const CloudControlPanel = (props: CloudControlPanelProps) => {
|
|
218
|
+
const { query, type } = props;
|
|
219
|
+
const { run } = useRequest(cloudControl, { manual: true });
|
|
220
|
+
const handleEvent = (action: 0 | 1, command: CloudControlCommandType) => {
|
|
221
|
+
run({ ...query, action, command });
|
|
222
|
+
};
|
|
223
|
+
return (
|
|
224
|
+
<div className="cloud-control-panel">
|
|
225
|
+
{type !== 'onlyFocus' && (
|
|
226
|
+
<>
|
|
227
|
+
<CloudControlArrow name="up" event={handleEvent} type="UP" />
|
|
228
|
+
<CloudControlArrow name="down" event={handleEvent} type="DOWN" />
|
|
229
|
+
<CloudControlArrow name="left" event={handleEvent} type="LEFT" />
|
|
230
|
+
<CloudControlArrow name="right" event={handleEvent} type="RIGHT" />
|
|
231
|
+
<CloudControlArrow name="left-up" event={handleEvent} type="LEFT_UP" />
|
|
232
|
+
<CloudControlArrow name="left-down" event={handleEvent} type="LEFT_DOWN" />
|
|
233
|
+
<CloudControlArrow name="right-up" event={handleEvent} type="RIGHT_UP" />
|
|
234
|
+
<CloudControlArrow name="right-down" event={handleEvent} type="RIGHT_DOWN" />
|
|
235
|
+
</>
|
|
236
|
+
)}
|
|
237
|
+
{type !== 'onlyRotate' && (
|
|
238
|
+
<Space className="buttons">
|
|
239
|
+
<CloudControlButton
|
|
240
|
+
text="焦距"
|
|
241
|
+
onAddDown={() => handleEvent(1, 'ZOOM_IN')}
|
|
242
|
+
onAddUp={() => handleEvent(0, 'ZOOM_IN')}
|
|
243
|
+
onReduceDown={() => handleEvent(1, 'ZOOM_OUT')}
|
|
244
|
+
onReduceUp={() => handleEvent(0, 'ZOOM_OUT')}
|
|
245
|
+
/>
|
|
246
|
+
<CloudControlButton
|
|
247
|
+
text="光圈"
|
|
248
|
+
onAddDown={() => handleEvent(1, 'IRIS_ENLARGE')}
|
|
249
|
+
onAddUp={() => handleEvent(0, 'IRIS_ENLARGE')}
|
|
250
|
+
onReduceDown={() => handleEvent(1, 'IRIS_REDUCE')}
|
|
251
|
+
onReduceUp={() => handleEvent(0, 'IRIS_REDUCE')}
|
|
252
|
+
/>
|
|
253
|
+
<CloudControlButton
|
|
254
|
+
text="距离"
|
|
255
|
+
onAddDown={() => handleEvent(1, 'FOCUS_NEAR')}
|
|
256
|
+
onAddUp={() => handleEvent(0, 'FOCUS_NEAR')}
|
|
257
|
+
onReduceDown={() => handleEvent(1, 'FOCUS_FAR')}
|
|
258
|
+
onReduceUp={() => handleEvent(0, 'FOCUS_FAR')}
|
|
259
|
+
/>
|
|
260
|
+
</Space>
|
|
261
|
+
)}
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
interface CloudControlArrowProps {
|
|
267
|
+
/** 类名 */
|
|
268
|
+
name?: string;
|
|
269
|
+
/** 鼠标事件 */
|
|
270
|
+
event: (action: 0 | 1, command: CloudControlCommandType) => void;
|
|
271
|
+
type: CloudControlCommandType;
|
|
272
|
+
}
|
|
273
|
+
/** 云台控制箭头 */
|
|
274
|
+
const CloudControlArrow = (props: CloudControlArrowProps) => {
|
|
275
|
+
const { name = '', event, type } = props;
|
|
276
|
+
return (
|
|
277
|
+
<img
|
|
278
|
+
className={`arrow ${name}`}
|
|
279
|
+
src={arrowImg}
|
|
280
|
+
onMouseDown={() => event(1, type)}
|
|
281
|
+
onMouseUp={() => event(0, type)}
|
|
282
|
+
/>
|
|
283
|
+
);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
interface CloudControlButtonProps {
|
|
287
|
+
/** 文本 */
|
|
288
|
+
text: string;
|
|
289
|
+
/** 增加按钮鼠标按下事件 */
|
|
290
|
+
onAddDown: () => void;
|
|
291
|
+
/** 增加按钮鼠标抬起事件 */
|
|
292
|
+
onAddUp: () => void;
|
|
293
|
+
/** 减少按钮鼠标按下事件 */
|
|
294
|
+
onReduceDown: () => void;
|
|
295
|
+
/** 减少按钮鼠标抬起事件 */
|
|
296
|
+
onReduceUp: () => void;
|
|
297
|
+
}
|
|
298
|
+
/** 云台控制按钮 */
|
|
299
|
+
const CloudControlButton = (props: CloudControlButtonProps) => {
|
|
300
|
+
const { text, onAddDown, onAddUp, onReduceDown, onReduceUp } = props;
|
|
301
|
+
return (
|
|
302
|
+
<div className="control-button">
|
|
303
|
+
<span className="icon" onMouseDown={onReduceDown} onMouseUp={onReduceUp}>
|
|
304
|
+
+
|
|
305
|
+
</span>
|
|
306
|
+
<span className="text">{text}</span>
|
|
307
|
+
<span className="icon" onMouseDown={onAddDown} onMouseUp={onAddUp}>
|
|
308
|
+
-
|
|
309
|
+
</span>
|
|
310
|
+
</div>
|
|
311
|
+
);
|
|
312
|
+
};
|
|
Binary file
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
.vtx-history-control {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
background-color: #2b3d51;
|
|
8
|
+
background-image: url('./images/empty.png');
|
|
9
|
+
background-repeat: no-repeat;
|
|
10
|
+
background-position: center;
|
|
11
|
+
|
|
12
|
+
.bottom-controls {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 32px;
|
|
17
|
+
padding: 0 12px;
|
|
18
|
+
background-color: #243241;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.collapse-controls {
|
|
22
|
+
position: absolute;
|
|
23
|
+
bottom: 32px;
|
|
24
|
+
width: 100%;
|
|
25
|
+
background-color: #131d27;
|
|
26
|
+
|
|
27
|
+
.action-bar {
|
|
28
|
+
display: flex;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.collapse-panel-container {
|
|
34
|
+
.panels {
|
|
35
|
+
padding: 12px 20px;
|
|
36
|
+
margin: 0 14px 14px;
|
|
37
|
+
background-color: #141414;
|
|
38
|
+
border: 1px solid rgb(255 255 255 / 20%);
|
|
39
|
+
border-radius: 2px;
|
|
40
|
+
|
|
41
|
+
.time-panel {
|
|
42
|
+
position: relative;
|
|
43
|
+
|
|
44
|
+
.time-line-icon {
|
|
45
|
+
position: absolute;
|
|
46
|
+
top: -10px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.segments {
|
|
50
|
+
position: relative;
|
|
51
|
+
height: 24px;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
|
|
54
|
+
.segment {
|
|
55
|
+
position: absolute;
|
|
56
|
+
height: 24px;
|
|
57
|
+
background-color: rgb(186 231 255 / 100%);
|
|
58
|
+
border-left: 1px solid #141414;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.time-axis {
|
|
63
|
+
position: relative;
|
|
64
|
+
width: 100%;
|
|
65
|
+
|
|
66
|
+
.split-lines {
|
|
67
|
+
height: 30px;
|
|
68
|
+
|
|
69
|
+
&::before {
|
|
70
|
+
position: absolute;
|
|
71
|
+
top: -1px;
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 1px;
|
|
74
|
+
content: '';
|
|
75
|
+
background-color: rgb(255 255 255 / 65%);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.line {
|
|
79
|
+
position: absolute;
|
|
80
|
+
color: white;
|
|
81
|
+
|
|
82
|
+
.number {
|
|
83
|
+
position: absolute;
|
|
84
|
+
color: rgb(255 255 255 / 65%);
|
|
85
|
+
transform: translate(-50%, 6px);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&::before {
|
|
89
|
+
position: absolute;
|
|
90
|
+
width: 1px;
|
|
91
|
+
height: 8px;
|
|
92
|
+
content: '';
|
|
93
|
+
background-color: rgb(255 255 255 / 65%);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.player-container {
|
|
104
|
+
flex-grow: 1;
|
|
105
|
+
width: 100%;
|
|
106
|
+
height: 0;
|
|
107
|
+
padding-bottom: 13px;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.history-url-table {
|
|
112
|
+
border-right: 1px solid #383838;
|
|
113
|
+
border-bottom: 1px solid #383838;
|
|
114
|
+
|
|
115
|
+
.ant-table {
|
|
116
|
+
background: var(--table-bg);
|
|
117
|
+
|
|
118
|
+
.ant-table-container {
|
|
119
|
+
&::before {
|
|
120
|
+
display: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&::after {
|
|
124
|
+
display: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.ant-table-header {
|
|
128
|
+
table {
|
|
129
|
+
border-collapse: collapse;
|
|
130
|
+
|
|
131
|
+
thead {
|
|
132
|
+
th {
|
|
133
|
+
padding: 8px;
|
|
134
|
+
color: rgb(255 255 255 / 85%);
|
|
135
|
+
white-space: no-wrap;
|
|
136
|
+
background-color: rgb(255 255 255 / 7%);
|
|
137
|
+
border: 1px solid #383838;
|
|
138
|
+
|
|
139
|
+
&::before {
|
|
140
|
+
display: none;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.ant-table-body {
|
|
148
|
+
&::-webkit-scrollbar {
|
|
149
|
+
width: 10px;
|
|
150
|
+
height: 10px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
&::-webkit-scrollbar-track {
|
|
154
|
+
background: transparent;
|
|
155
|
+
border-radius: 5px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&::-webkit-scrollbar-thumb {
|
|
159
|
+
background: rgb(255 255 255 / 45%);
|
|
160
|
+
border-radius: 5px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
&::-webkit-scrollbar-corner {
|
|
164
|
+
background-color: transparent;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
168
|
+
background: rgb(255 255 255 / 65%);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
table {
|
|
172
|
+
border-collapse: collapse;
|
|
173
|
+
|
|
174
|
+
tbody {
|
|
175
|
+
tr {
|
|
176
|
+
td {
|
|
177
|
+
padding: 6px 8px;
|
|
178
|
+
font-size: 14px;
|
|
179
|
+
color: rgb(255 255 255 / 65%);
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
background-color: transparent;
|
|
182
|
+
border: 1px solid #383838;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&.active {
|
|
186
|
+
td {
|
|
187
|
+
background-color: #102641;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.play-btn {
|
|
194
|
+
height: fit-content;
|
|
195
|
+
padding: 0 8px;
|
|
196
|
+
font-size: 14px;
|
|
197
|
+
color: rgb(255 255 255 / 65%);
|
|
198
|
+
background: rgb(255 255 255 / 7.8%);
|
|
199
|
+
border: 1px solid rgb(255 255 255 / 20%);
|
|
200
|
+
border-radius: 2px;
|
|
201
|
+
|
|
202
|
+
&.active {
|
|
203
|
+
color: #177ddc;
|
|
204
|
+
border-color: #177ddc;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import HistoryControl from '.';
|
|
2
|
+
import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
|
|
3
|
+
|
|
4
|
+
import * as stories from './index.stories';
|
|
5
|
+
|
|
6
|
+
<Meta title="组件/历史视频控制器" />
|
|
7
|
+
|
|
8
|
+
# 历史视频控制器
|
|
9
|
+
|
|
10
|
+
## 引入
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
import { HistoryControl } from '@vtx/player';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 方法调用
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { HistoryControl } from '@vtx/player';
|
|
20
|
+
|
|
21
|
+
const MyApp = () => {
|
|
22
|
+
const ref = useRef<HistoryControlHandle>(null);
|
|
23
|
+
const params = {};
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<button onClick={() => ref.load(params)}>加载视频</button>
|
|
27
|
+
<HistoryControl ref={ref} />
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 方法类型
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type HistoryControlHandle = {
|
|
37
|
+
load: (channel: ChannelType) => void;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type ChannelType {
|
|
41
|
+
/** 频道号 */
|
|
42
|
+
channelNum: string;
|
|
43
|
+
/** 设备ID */
|
|
44
|
+
deviceId: string;
|
|
45
|
+
/** 协议 */
|
|
46
|
+
protocol?: string;
|
|
47
|
+
/** 开始时间,格式:2022-06-01 00:00:00 */
|
|
48
|
+
beginTime: string;
|
|
49
|
+
/** 结束时间,格式:2022-06-01 23:59:59 */
|
|
50
|
+
endTime: string;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 属性
|
|
55
|
+
|
|
56
|
+
<ArgsTable of={HistoryControl} />
|
|
57
|
+
|
|
58
|
+
## 例子
|
|
59
|
+
|
|
60
|
+
<Canvas>
|
|
61
|
+
<Story name="历史视频控制器" story={stories.Default} />
|
|
62
|
+
</Canvas>
|