feat(zhst/material): 升级智能柜的算法配置面板

This commit is contained in:
NICE CODE BY DEV 2024-06-28 11:56:15 +08:00
parent 7f64ffe221
commit b5a74de4d9
8 changed files with 175 additions and 130 deletions

View File

@ -1,8 +1,9 @@
import React, { forwardRef, ReactNode, useContext, useImperativeHandle } from 'react'; import React, { forwardRef, memo, ReactNode, useContext, useImperativeHandle } from 'react';
import { Button, Flex, Image } from "antd";
import theme from 'antd/es/theme' import theme from 'antd/es/theme'
import { CropperImage, ConfigProvider } from '@zhst/meta' import { CameraOutlined } from '@ant-design/icons'
import type { CropperImageProps } from '@zhst/meta' import { Flex, Button, Image } from 'antd'
import { VideoPlayer, ConfigProvider } from '@zhst/meta'
import type { VideoViewProps } from '@zhst/meta'
import { AlgorithmConfigImg, ErrorImage } from '../utils/base64Images' import { AlgorithmConfigImg, ErrorImage } from '../utils/base64Images'
import AlgorithmTable from './components/algorithmTable' import AlgorithmTable from './components/algorithmTable'
import TimeTemplateTable from './components/timeTemplateTable'; import TimeTemplateTable from './components/timeTemplateTable';
@ -10,10 +11,11 @@ import { AlgorithmTableProps } from './components/algorithmTable/AlgorithmTable'
import { TimeTemplateTableProps } from './components/timeTemplateTable/TimeTemplateTable'; import { TimeTemplateTableProps } from './components/timeTemplateTable/TimeTemplateTable';
import classNames from 'classnames'; import classNames from 'classnames';
import './index.less' import './index.less'
import { Alert } from 'antd';
const { useToken } = theme const { useToken } = theme
const Title = (props: any) => <h2 style={{ color: 'rgba(0, 0, 0, 0.88)' }} {...props}>{props.children}</h2> const Title = memo((props: any) => (<h2 style={{ color: 'rgba(0, 0, 0, 0.88)' }} {...props}>{props.children}</h2>))
export interface AlgorithmConfigProps { export interface AlgorithmConfigProps {
onAddAlgorithm?: () => void onAddAlgorithm?: () => void
@ -43,13 +45,18 @@ export interface AlgorithmConfigProps {
id: string; id: string;
name: string; name: string;
}[] }[]
algorithmTableProps?: AlgorithmTableProps<any> algorithmTableProps?: Partial<AlgorithmTableProps<any>>
timeTemplateTableProps?: TimeTemplateTableProps<any> timeTemplateTableProps?: Partial<TimeTemplateTableProps<any>>
cropperImageProps?: CropperImageProps
selectedKey?: string selectedKey?: string
rowKey?: string rowKey?: string
type: AlgorithmTableProps<any>['tableType'] type: AlgorithmTableProps<any>['tableType']
title?:string; // boxList列表的属性名称【点位列表、盒子列表】 title?:string; // boxList列表的属性名称【点位列表、盒子列表】
/**
* @description
*/
videoUrl?: string
videoProps?: Partial<VideoViewProps>
errorMessage?: string;
onSelect?: (key: string, info?: any) => void onSelect?: (key: string, info?: any) => void
/** /**
* / * /
@ -59,6 +66,12 @@ export interface AlgorithmConfigProps {
* *
*/ */
onLoadMoreButtonClick?: () => void; onLoadMoreButtonClick?: () => void;
/**
* box
* @param data box详情
* @returns
*/
customBoxItemRender?: (data?: any) => void
/** /**
* *
*/ */
@ -79,15 +92,18 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
const { const {
algorithmTableDataSource = [], algorithmTableDataSource = [],
timeTemplateDataSource = [], timeTemplateDataSource = [],
drawListener,
cropperImageProps = {},
algorithmTableProps, algorithmTableProps,
timeTemplateTableProps, timeTemplateTableProps,
videoProps,
selectedKey, selectedKey,
customBoxItemRender,
errorMessage,
boxList = [], boxList = [],
type = 'multiple', type = 'single',
rowKey = 'id', rowKey = 'id',
onSelect, title='盒子名称', onSelect,
title='盒子名称',
videoUrl,
showLoadMoreButton, showLoadMoreButton,
onLoadMoreButtonClick, onLoadMoreButtonClick,
customBatchCenterContent, customBatchCenterContent,
@ -96,21 +112,19 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
} = props } = props
const { getPrefixCls } = useContext(ConfigContext); const { getPrefixCls } = useContext(ConfigContext);
const componentName = getPrefixCls('material-algo', customizePrefixCls); const componentName = getPrefixCls('material-algo', customizePrefixCls);
const { token } = useToken() const { token } = useToken()
// @ts-ignore
const { type: cropType } = cropperImageProps
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
})) }))
return ( return (
<Flex className={componentName} style={{ border: `1px solid ${token.colorBorder}`, backgroundColor: token.colorBgBase }}> <Flex className={componentName} style={{ backgroundColor: token.colorBgBase }}>
<div className={classNames(`${componentName}-left`)} title={title} style={{ position: 'relative', width: '13.9%' }}> <div className={classNames(`${componentName}-left`)} title={title} style={{ position: 'relative' }}>
<Title className={classNames(`${componentName}-title`)}>{title}</Title> <Title className={classNames(`${componentName}-title`)}>{title}</Title>
<div className={classNames(`${componentName}-left-list`)} style={{ borderTop: `1px solid ${token.colorBorder}` }}> <div className={classNames(`${componentName}-left-list`)}>
{boxList.map(item => { {boxList.map(item => {
return ( return (
customBoxItemRender?.(item) || (
<p <p
// @ts-ignore // @ts-ignore
key={item[rowKey]} key={item[rowKey]}
@ -118,7 +132,7 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
onClick={() => onSelect?.(item[rowKey], item)} onClick={() => onSelect?.(item[rowKey], item)}
style={{ style={{
margin: 0, margin: 0,
padding: `${token.paddingXXS}px ${token.paddingLG}px`, padding: `${token.paddingXXS}px`,
cursor: 'pointer', cursor: 'pointer',
// @ts-ignore // @ts-ignore
color: selectedKey === item[rowKey] ? token.colorPrimary : token.colorText, color: selectedKey === item[rowKey] ? token.colorPrimary : token.colorText,
@ -136,7 +150,8 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
e.target.style.color = token.colorText e.target.style.color = token.colorText
e.target.style.backgroundColor = null e.target.style.backgroundColor = null
}} }}
>{item.name}</p> ><CameraOutlined style={{ marginRight: 8 }} />{item.name}</p>
)
) )
})} })}
</div> </div>
@ -146,13 +161,13 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
</div> </div>
)} )}
</div> </div>
<div style={{ boxSizing: 'border-box', width: '46.3%', textAlign: 'center', borderLeft: `1px solid ${token.colorBorder}`, borderRight: `1px solid ${token.colorBorder}` }}> <div className={classNames(`${componentName}-middle`)} style={{ boxSizing: 'border-box', width: '46.3%', textAlign: 'center', }}>
{errorMessage && <Alert style={{ marginBottom: 16 }} message={`错误代码:${errorMessage || '-'}`} type="error" showIcon />}
{/* 单个配置 */} {/* 单个配置 */}
{type === 'single' ? ( {type === 'single' ? (
<CropperImage <VideoPlayer
type="line" url={videoUrl!}
onCropEnd={drawListener} {...videoProps}
{...cropperImageProps}
/> />
) : ( ) : (
<div className={classNames(`${componentName}-middle-cont`)}> <div className={classNames(`${componentName}-middle-cont`)}>
@ -175,10 +190,10 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
) )
} }
</div> </div>
<div style={{ width: '39.8%' }} > <div className={classNames(`${componentName}-right`)} >
<div> <div>
<Title className={classNames(`${componentName}-title`)}></Title> <Title className={classNames(`${componentName}-title`)}></Title>
<div style={{ padding: `${token.paddingMD}px ${token.paddingSM}px`, borderTop: `1px solid ${token.colorBorder}`, borderBottom: `1px solid ${token.colorBorder}` }}> <div >
<TimeTemplateTable <TimeTemplateTable
dataSource={timeTemplateDataSource} dataSource={timeTemplateDataSource}
{...timeTemplateTableProps} {...timeTemplateTableProps}
@ -187,9 +202,10 @@ const AlgorithmConfig = forwardRef<AlgorithmConfigRef, AlgorithmConfigProps>((pr
</div> </div>
<div> <div>
<Title className={classNames(`${componentName}-title`)}></Title> <Title className={classNames(`${componentName}-title`)}></Title>
<div style={{ padding: `${token.paddingMD}px ${token.paddingSM}px`, borderTop: `1px solid ${token.colorBorder}` }}> <div >
<AlgorithmTable <AlgorithmTable
dataSource={algorithmTableDataSource} dataSource={algorithmTableDataSource}
timeTemplateData={timeTemplateDataSource}
tableType={type} tableType={type}
{...algorithmTableProps} {...algorithmTableProps}
/> />

View File

@ -1,27 +1,24 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { DeleteFilled, EditFilled, ImportOutlined, PlusCircleFilled } from '@ant-design/icons';
import type { ParamsType, ProColumns, ProTableProps } from '@ant-design/pro-components'; import type { ParamsType, ProColumns, ProTableProps } from '@ant-design/pro-components';
import { import {
ProTable, ProTable,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { Popconfirm, Select, Space, Switch } from 'antd'; import { Button, ButtonProps, Popconfirm, Select, Space, Switch } from 'antd';
import { ConfigProvider } from '@zhst/meta' import { ConfigProvider } from '@zhst/meta'
import theme from 'antd/es/theme'
import { AnyObject } from 'antd/es/_util/type'; import { AnyObject } from 'antd/es/_util/type';
import { SelectProps } from 'antd/lib'; import { SelectProps } from 'antd/lib';
import SchemaFormModal from '../schemaFormModal';
import classNames from 'classnames'; import classNames from 'classnames';
import './index.less' import './index.less'
const { useToken } = theme
const { ConfigContext } = ConfigProvider const { ConfigContext } = ConfigProvider
export interface AlgorithmTableProps<DataSource, Params extends ParamsType = ParamsType, ValueType = "text"> extends ProTableProps<DataSource, Params, ValueType> { export interface AlgorithmTableProps<DataSource, Params extends ParamsType = ParamsType, ValueType = "text"> extends ProTableProps<DataSource, Params, ValueType> {
onAddAlgorithm?: (id?: string, record?: any) => void onAddAlgorithm?: (id?: string, record?: any) => void
onItemSwitch?: (status?: boolean, id?: string, info?: any) => void onItemSwitch?: (status?: boolean, id?: string, info?: any) => void
onItemEdit?: (values?: any, info?: any) => void onItemEdit?: (values?: any, type?: 'edit' | 'delete' | 'draw' | 'switch' | 'runCycle', info?: any ) => void
onItemDelete?: (id?: string, info?: any) => void onItemDelete?: (id?: string, info?: any) => void
onSortSelect?: SelectProps['onChange'] onSortSelect?: SelectProps['onChange']
onReuse?: ButtonProps['onClick']
onDraw?: (id: any, info?: any) => void onDraw?: (id: any, info?: any) => void
selectedKey?: string selectedKey?: string
sortList?: { sortList?: {
@ -29,87 +26,90 @@ export interface AlgorithmTableProps<DataSource, Params extends ParamsType = Par
value: string; value: string;
}[] }[]
tableType?: 'multiple' | 'single' // 多选/单选 tableType?: 'multiple' | 'single' // 多选/单选
timeTemplateData?: any[]
} }
const AlgorithmTable= <DataSource extends AnyObject = AnyObject>( const AlgorithmTable= <DataSource extends AnyObject = AnyObject>(
props: AlgorithmTableProps<DataSource, ParamsType, 'text'> props: AlgorithmTableProps<DataSource, ParamsType, 'text'>
) => { ) => {
const { const {
onAddAlgorithm,
onItemSwitch,
onItemEdit, onItemEdit,
onItemDelete,
onSortSelect, onSortSelect,
selectedKey, onReuse,
onDraw, timeTemplateData = [],
tableType = 'multiple',
sortList = [], sortList = [],
prefixCls: customizePrefixCls prefixCls: customizePrefixCls
} = props } = props
const { getPrefixCls } = useContext(ConfigContext); const { getPrefixCls } = useContext(ConfigContext);
const componentName = getPrefixCls('material-algo-algoTable', customizePrefixCls); const componentName = getPrefixCls('material-algo-algoTable', customizePrefixCls);
const { token } = useToken()
const columns: ProColumns<DataSource>[] = [ const columns: ProColumns<DataSource>[] = [
{ {
editable: false,
title: '算法名称', title: '算法名称',
dataIndex: 'templateName', dataIndex: 'templateName',
}, },
{ {
disable: true,
title: '运行周期', title: '运行周期',
key: 'runCycle',
dataIndex: 'runCycle', dataIndex: 'runCycle',
valueType: 'select', render: (_, record) => {
valueEnum: { return (
1: { text: '黑夜' }, <Select
0: { text: '白天' }, style={{ width: 120 }}
placeholder="运行周期"
defaultValue={record.runCycle}
onChange={value => onItemEdit?.(value, 'runCycle', record)}
>
{timeTemplateData.map(o => (
<Select.Option key={o.id} >{o.templateName}</Select.Option>
))}
</Select>
)
}, },
}, },
// { {
// title: '算力占用', editable: false,
// dataIndex: 'powerOccupy', title: '启动状态',
// }, dataIndex: 'status',
render: (_, record) => <Switch defaultChecked={record.status} onChange={_status => onItemEdit?.(_status, 'switch', record)} />
},
{ {
title: '操作', title: '操作',
key: 'option', key: 'option',
valueType: 'option', valueType: 'option',
fixed: 'right', fixed: 'right',
width: '120px', width: 140,
render: (_DOM, record) => [ render: (_DOM, record) => [
<Switch value={record.status} onChange={_status => onItemSwitch?.(_status, record.id, record)} />, <a onClick={() => onItemEdit?.(record.id, 'draw', record)}></a>,
<a onClick={() => onDraw?.(record.id, record)} style={{ display: tableType === 'single' ? 'block' : 'none' }} href="#"><ImportOutlined /></a>, <a onClick={() => onItemEdit?.(record.id, 'edit', record)}></a>,
<SchemaFormModal
type={record.templateType}
onFinish={async (values) => onItemEdit?.(values, record)}
trigger={<a href="#"><EditFilled /></a>}
/>
,
<Popconfirm <Popconfirm
title="确定删除吗?" title="确定删除吗?"
onConfirm={() => onItemDelete?.(record.id, record)} onConfirm={() => onItemEdit?.(record.id, 'delete', record)}
> >
<a href="#"><DeleteFilled /></a> <a style={{ color: 'red' }}></a>
</Popconfirm>, </Popconfirm>,
], ],
}, },
]; ];
console.log('123', 123)
return ( return (
<div className={componentName}> <div className={componentName}>
<Space className={classNames(`${componentName}-top`)} size={16}> <Space className={classNames(`${componentName}-top`)} size={16}>
<Select <Select
className={classNames(`${componentName}-top-select`)} className={classNames(`${componentName}-top-select`)}
value={selectedKey} placeholder="新增算法"
onChange={onSortSelect} onChange={onSortSelect}
options={sortList} options={sortList}
/> />
<PlusCircleFilled className={classNames(`${componentName}-top-plus`)} onClick={() => onAddAlgorithm?.(selectedKey)} style={{ color: token.colorPrimary, cursor: 'pointer' }} /> <Button onClick={onReuse}></Button>
</Space> </Space>
<ProTable<DataSource> <ProTable<DataSource>
columns={columns} columns={columns}
bordered scroll={{ y: 400, x: 600 }}
scroll={{ y: 240, x: 600 }}
dataSource={[]} dataSource={[]}
cardProps={{ cardProps={{
bodyStyle: { bodyStyle: {

View File

@ -3,7 +3,7 @@
margin-bottom: 12px; margin-bottom: 12px;
&-select { &-select {
width: 320px; width: 160px;
} }
&-plus { &-plus {

View File

@ -5,8 +5,7 @@ import {
ProTable, ProTable,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { AnyObject } from 'antd/es/_util/type'; import { AnyObject } from 'antd/es/_util/type';
import { InputNumber } from 'antd'; import './index.less'
export interface TimeTemplateTableProps<DataSource, Params extends ParamsType = ParamsType, ValueType = "text"> extends ProTableProps<DataSource, Params, ValueType> { export interface TimeTemplateTableProps<DataSource, Params extends ParamsType = ParamsType, ValueType = "text"> extends ProTableProps<DataSource, Params, ValueType> {
onItemBlur?: (value?: number | string, id?: any, record?: any) => void, onItemBlur?: (value?: number | string, id?: any, record?: any) => void,
} }
@ -14,10 +13,6 @@ export interface TimeTemplateTableProps<DataSource, Params extends ParamsType =
const TimeTemplateTable = <DataSource extends AnyObject = AnyObject>( const TimeTemplateTable = <DataSource extends AnyObject = AnyObject>(
props: TimeTemplateTableProps<DataSource, ParamsType, 'text'> props: TimeTemplateTableProps<DataSource, ParamsType, 'text'>
) => { ) => {
const {
onItemBlur,
} = props
const columns: ProColumns<DataSource>[] = [ const columns: ProColumns<DataSource>[] = [
{ {
@ -32,28 +27,17 @@ const TimeTemplateTable = <DataSource extends AnyObject = AnyObject>(
title: '布控星期', title: '布控星期',
dataIndex: 'arrangeDay', dataIndex: 'arrangeDay',
}, },
// TODO: 暂时先注释后续在做这个功能
// {
// title: '算力占用',
// dataIndex: 'powerOccupy',
// },
{
title: '配置路数',
key: 'option',
valueType: 'option',
render: (_, record) => <InputNumber value={record.lineNum} onBlur={e => onItemBlur?.(e.target.value, record.id, record)} min={0} />,
},
]; ];
return ( return (
<ProTable<DataSource> <ProTable<DataSource>
className='time-template-table'
columns={columns} columns={columns}
cardProps={{ cardProps={{
bodyStyle: { bodyStyle: {
padding: 0 padding: 0
} }
}} }}
bordered
scroll={{ y: 95 }} scroll={{ y: 95 }}
toolbar={undefined} toolbar={undefined}
rowKey="id" rowKey="id"

View File

@ -0,0 +1,3 @@
.time-template-table {
margin-bottom: 32px;
}

View File

@ -2,7 +2,7 @@ import React, { useRef, useState } from 'react';
import { AlgorithmConfig, AlgorithmConfigRef } from '@zhst/material'; import { AlgorithmConfig, AlgorithmConfigRef } from '@zhst/material';
import type { AlgorithmConfigProps } from '@zhst/material'; import type { AlgorithmConfigProps } from '@zhst/material';
import { Button, Space, Switch } from 'antd'; import { Button, Space, Switch } from 'antd';
import { CropperImageRefProps } from '@zhst/meta'; import { CropperImageRefProps, VideoViewRef } from '@zhst/meta';
const algorithmTableDataSource: any = [] const algorithmTableDataSource: any = []
@ -20,7 +20,7 @@ for (let i = 0; i < 100; i += 1) {
odRect:{ odRect:{
"x":0.553125,"y":0.29722223,"w":0.048958335,"h":0.2462963 "x":0.553125,"y":0.29722223,"w":0.048958335,"h":0.2462963
}, },
runCycle: i % 2 !== 0 ? '白天' : '黑夜', runCycle: String(i),
creator: Math.floor(Math.random() * 20), creator: Math.floor(Math.random() * 20),
}); });
timeTemplateDataSource.push({ timeTemplateDataSource.push({
@ -38,6 +38,8 @@ for (let i = 0; i < 100; i += 1) {
}) })
} }
export const VIDEO_URL = `ws://10.0.0.7:9033/flv/File/test/test_h264_${Math.floor(Math.random() * 6) + 1}.mp4.flv?ip=127.0.0.1`
const demo = () => { const demo = () => {
const [algorithmTableList, setAlgorithmTableList] = useState(algorithmTableDataSource) const [algorithmTableList, setAlgorithmTableList] = useState(algorithmTableDataSource)
const [timeTemplateData, setTimeTemplateData] = useState(timeTemplateDataSource) const [timeTemplateData, setTimeTemplateData] = useState(timeTemplateDataSource)
@ -45,14 +47,15 @@ const demo = () => {
const [selectedKey, setSelectedKey] = useState('1') const [selectedKey, setSelectedKey] = useState('1')
const [cropType, setCropType] = useState<'line' | 'rect'>('line') const [cropType, setCropType] = useState<'line' | 'rect'>('line')
const [algorithmSelectedKey, setAlgorithmSelectedKey] = useState('1') const [algorithmSelectedKey, setAlgorithmSelectedKey] = useState('1')
const [tableType, setTableType] = useState<AlgorithmConfigProps['type']>('multiple') const [tableType, setTableType] = useState<AlgorithmConfigProps['type']>('single')
const [editAble, setEditAble] = useState(false) const [editAble, setEditAble] = useState(false)
const algorithmConfigRef = useRef<AlgorithmConfigRef>(null) const algorithmConfigRef = useRef<AlgorithmConfigRef>(null)
const cropperImageRef = useRef<CropperImageRefProps>(null) const videoRef = useRef<VideoViewRef>(null)
const [videoUrl, setVideoUrl] = useState('')
const [odList, setOdList] = useState([])
// 绘画事件 // 绘画事件
const handleDraw = (id: any, info: any) => { const handleDraw = (id: any, info: any) => {
console.log('cropperImageRef', cropperImageRef)
setEditAble(true) setEditAble(true)
setCropType('line') setCropType('line')
} }
@ -75,15 +78,41 @@ const demo = () => {
selectedKey={selectedKey} selectedKey={selectedKey}
onSelect={key => { onSelect={key => {
setSelectedKey(key) setSelectedKey(key)
setVideoUrl(VIDEO_URL)
setOdList([
{
"id": "123",
"x": 0.5519352,
"y": 0.2965385,
"w": 0.05185461,
"h": 0.24698898,
selectAble: false,
},
{
"id": "456",
"x": 0.58543766,
"y": Math.random(),
"w": 0.052037954,
"h": 0.2664015
}
])
// setTimeTemplateData([]) // setTimeTemplateData([])
// setTableList([]) // setTableList([])
// setBoxList([]) // setBoxList([])
}} }}
videoUrl={videoUrl}
videoProps={{
ref: videoRef,
onCropChange: (showCrop, normalizationRect) => {
console.log('showCrop', showCrop, normalizationRect)
},
showOD: true,
odList
}}
type={tableType} type={tableType}
// 算法模块 // 算法模块
algorithmTableProps={{ algorithmTableProps={{
onItemSwitch: (status, id) => { onItemSwitch: (status, id) => {
console.log('算法状态 switch 变更')
setAlgorithmTableList((pre: any[]) => { setAlgorithmTableList((pre: any[]) => {
let arr = pre.map(o => { let arr = pre.map(o => {
if (o.id === id) { if (o.id === id) {
@ -94,30 +123,25 @@ const demo = () => {
return arr return arr
}) })
}, },
onItemEdit: async (values, itemInfo) => { onItemEdit: async (values, type, info) => {
console.log('算法单项编辑表单提交', values, itemInfo) videoRef.current?.setShowCrop(true)
console.log('算法单项编辑表单提交', videoRef, info)
return true return true
}, },
onDraw: (id, info) => handleDraw(id, info), onDraw: (id, info) => handleDraw(id, info),
onItemDelete: (id, itemInfo) => console.log('删除', id, itemInfo), onItemDelete: (id, itemInfo) => console.log('删除', id, itemInfo),
onAddAlgorithm: (id) => console.log('添加模板', id), onAddAlgorithm: (id) => console.log('添加模板', id),
selectedKey: algorithmSelectedKey, selectedKey: algorithmSelectedKey,
onSortSelect: (value) => setAlgorithmSelectedKey(value), // onSortSelect: (value) => setAlgorithmSelectedKey(value),
sortList: [ sortList: [
{ label: '白天', value: '1' }, { label: '火焰识别', value: '1' },
{ label: '黑夜', value: '2' }, { label: '人脸识别', value: '2' },
] ]
}} }}
// 时间模板模块 // 时间模板模块
timeTemplateTableProps={{ timeTemplateTableProps={{
onItemBlur: (val, id, itemInfo) => console.log('失焦事件', val, id, itemInfo), onItemBlur: (val, id, itemInfo) => console.log('失焦事件', val, id, itemInfo),
}} }}
cropperImageProps={{
type: cropType,
editAble,
ref: cropperImageRef,
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
}}
/> />
</Space> </Space>
); );

View File

@ -1,21 +1,38 @@
.zhst-material-algo { .zhst-material-algo {
display: flex;
&-title { &-title {
margin: 18px 16px; margin: 16px 0;
margin-top: 0;
font-size: 14px; font-size: 14px;
} }
&-left { &-left {
flex: 0 0 240px;
border-right: 1px solid #e5e5e5;
&-list { &-list {
padding-bottom: 36px; padding-bottom: 36px;
max-height: 612px; max-height: 892px;
overflow-y: scroll; overflow-y: scroll;
box-sizing: 'border-box'; box-sizing: 'border-box';
} }
} }
&-middle { &-middle {
display: flex;
flex-direction: column;
flex: 0 0 1040px;
margin: 0 24px;
height: auto;
&-cont { &-cont {
align-items: center;
padding: 84px; padding: 84px;
border: 1px solid #e5e5e5;
border-radius: 8px;
overflow: hidden;
} }
} }
&-right {
height: auto;
}
} }

View File

@ -358,6 +358,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
if (!isReady) return; if (!isReady) return;
if (showCrop) { if (showCrop) {
// 编辑状态
handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, () => { handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, () => {
setCropRect(null); setCropRect(null);
}); });
@ -372,7 +373,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
alignRef?.current?.forceAlign?.(); alignRef?.current?.forceAlign?.();
}); });
let video: any = videoRef.current; let video: any = videoRef.current;
//计算 limitcroppbox //计算 limit crop box
let scale = Math.min( let scale = Math.min(
video.offsetWidth / video.videoWidth, video.offsetWidth / video.videoWidth,
video.offsetHeight / video.videoHeight video.offsetHeight / video.videoHeight
@ -435,8 +436,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
height: _element.clientHeight, height: _element.clientHeight,
backgroundColor: 'transparent' backgroundColor: 'transparent'
}); });
// 预览状态
// 判定是否存在od框
showOD && odList?.forEach(_od => { showOD && odList?.forEach(_od => {
cropInsRef?.current?.addShape(_od); cropInsRef?.current?.addShape(_od);
}) })
@ -447,7 +447,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
cropInsRef?.current?.destroy?.(); cropInsRef?.current?.destroy?.();
cropInsRef.current = null; cropInsRef.current = null;
}; };
}, [showCrop, isReady]); }, [showCrop, isReady, odList]);
const latestCropRect = useLatest(cropRect); const latestCropRect = useLatest(cropRect);
@ -507,6 +507,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
// 监听showCrop、cropRect - 监听是否可编辑、绘制的矩形 // 监听showCrop、cropRect - 监听是否可编辑、绘制的矩形
useEffect(() => { useEffect(() => {
//计算归一化crop rect //计算归一化crop rect
// ! 待优化
let normalizationRect = null; let normalizationRect = null;
if (showCrop && cropRect) { if (showCrop && cropRect) {
let video: any = videoRef.current; let video: any = videoRef.current;