diff --git a/packages/biz/CHANGELOG.md b/packages/biz/CHANGELOG.md index 5fa366f..833cb13 100644 --- a/packages/biz/CHANGELOG.md +++ b/packages/biz/CHANGELOG.md @@ -1,5 +1,47 @@ # @zhst/biz +## 0.9.1 + +### Patch Changes + +- 修改 boxSelectTree 类型提示 +- Updated dependencies + - @zhst/hooks@0.8.2 + - @zhst/func@0.7.3 + - @zhst/meta@0.8.3 + +## 0.9.0 + +### Minor Changes + +- 优化 boxSelectTree 组件,添加可以自定义配置按钮功能 + +### Patch Changes + +- Updated dependencies + - @zhst/hooks@0.8.1 + - @zhst/func@0.7.2 + - @zhst/meta@0.8.2 + +## 0.8.0 + +### Minor Changes + +- @zhst/biz 优化数组件 + +### Patch Changes + +- Updated dependencies + - @zhst/hooks@0.8.0 + - @zhst/func@0.7.1 + - @zhst/meta@0.8.1 + +## 0.7.0 + +### Minor Changes + +- 新增预警记录卡片组件 + ## 0.6.0 ### Minor Changes diff --git a/packages/biz/es/index.d.ts b/packages/biz/es/index.d.ts index ba509c5..259e6bc 100644 --- a/packages/biz/es/index.d.ts +++ b/packages/biz/es/index.d.ts @@ -1,5 +1,8 @@ export { default as BigImageModal } from './BigImageModal'; export { default as BoxSelectTree } from './boxSelectTree'; export { default as Tree } from './tree'; +export type { TreeData } from './tree'; export { default as TreeTransfer } from './treeTransfer'; export { default as TreeTransferModal } from './treeTransferModal'; +export { default as WarningRecordCard } from './WarningRecordCard'; +export type { IRecord, WarningRecordCardProps } from './WarningRecordCard'; diff --git a/packages/biz/es/index.js b/packages/biz/es/index.js index beffc49..7e9350e 100644 --- a/packages/biz/es/index.js +++ b/packages/biz/es/index.js @@ -2,4 +2,5 @@ export { default as BigImageModal } from "./BigImageModal"; export { default as BoxSelectTree } from "./boxSelectTree"; export { default as Tree } from "./tree"; export { default as TreeTransfer } from "./treeTransfer"; -export { default as TreeTransferModal } from "./treeTransferModal"; \ No newline at end of file +export { default as TreeTransferModal } from "./treeTransferModal"; +export { default as WarningRecordCard } from "./WarningRecordCard"; \ No newline at end of file diff --git a/packages/biz/es/useSocket/ws.d.ts b/packages/biz/es/useSocket/ws.d.ts deleted file mode 100644 index 0dc9550..0000000 --- a/packages/biz/es/useSocket/ws.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -declare class Channel { - /** - * io 实例化对象 - */ - ioIns: any; - /** - * 已存在的订阅列表 - */ - listeners: never[]; - /** - * 调试信息 记录订阅/反订阅次数 - */ - subscribeListenerId: never[]; - unSubscribeListenerId: never[]; - init: () => void; - retry: (listener: { - [x: string]: any; - lastRetryInterval: number | undefined; - intervalId: NodeJS.Timeout; - } | undefined) => void; - doEmit: (topic: any, req: any, listenerId: any) => void; - subscribe(topic: any, req: any, handle: any): () => void; - unSubscribe(topic: any, req: any, handleId: any, listenerId: any): void; -} -declare const channelIns: Channel; -export default channelIns; diff --git a/packages/biz/es/utils/constants.d.ts b/packages/biz/es/utils/constants.d.ts index 45a9a99..0180cc0 100644 --- a/packages/biz/es/utils/constants.d.ts +++ b/packages/biz/es/utils/constants.d.ts @@ -21,3 +21,11 @@ export declare const DeviceTab: { REAL_CAMERA_ONLYFACE: number; REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: number; }; +export declare const BOX_TYPE_LIST: { + value: string; + label: string; +}[]; +export declare const ALL_LIST: { + value: string; + label: string; +}[]; diff --git a/packages/biz/es/utils/constants.js b/packages/biz/es/utils/constants.js index 1ad86ba..925bab4 100644 --- a/packages/biz/es/utils/constants.js +++ b/packages/biz/es/utils/constants.js @@ -27,4 +27,17 @@ export var DeviceTab = { REAL_CAMERA_NOFACE: 6, REAL_CAMERA_ONLYFACE: 7, REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: 8 // 只有普通摄像头,没有人脸、没有盒子、直连 -}; \ No newline at end of file +}; + +// 盒子 Tab 切换 +export var BOX_TYPE_LIST = [{ + value: '1', + label: '盒子' +}, { + value: '2', + label: '盒子组' +}]; +export var ALL_LIST = [{ + value: '', + label: '全部' +}]; \ No newline at end of file diff --git a/packages/biz/lib/index.d.ts b/packages/biz/lib/index.d.ts index ba509c5..259e6bc 100644 --- a/packages/biz/lib/index.d.ts +++ b/packages/biz/lib/index.d.ts @@ -1,5 +1,8 @@ export { default as BigImageModal } from './BigImageModal'; export { default as BoxSelectTree } from './boxSelectTree'; export { default as Tree } from './tree'; +export type { TreeData } from './tree'; export { default as TreeTransfer } from './treeTransfer'; export { default as TreeTransferModal } from './treeTransferModal'; +export { default as WarningRecordCard } from './WarningRecordCard'; +export type { IRecord, WarningRecordCardProps } from './WarningRecordCard'; diff --git a/packages/biz/lib/index.js b/packages/biz/lib/index.js index e86160c..82e9b73 100644 --- a/packages/biz/lib/index.js +++ b/packages/biz/lib/index.js @@ -33,7 +33,8 @@ __export(src_exports, { BoxSelectTree: () => import_boxSelectTree.default, Tree: () => import_tree.default, TreeTransfer: () => import_treeTransfer.default, - TreeTransferModal: () => import_treeTransferModal.default + TreeTransferModal: () => import_treeTransferModal.default, + WarningRecordCard: () => import_WarningRecordCard.default }); module.exports = __toCommonJS(src_exports); var import_BigImageModal = __toESM(require("./BigImageModal")); @@ -41,11 +42,13 @@ var import_boxSelectTree = __toESM(require("./boxSelectTree")); var import_tree = __toESM(require("./tree")); var import_treeTransfer = __toESM(require("./treeTransfer")); var import_treeTransferModal = __toESM(require("./treeTransferModal")); +var import_WarningRecordCard = __toESM(require("./WarningRecordCard")); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BigImageModal, BoxSelectTree, Tree, TreeTransfer, - TreeTransferModal + TreeTransferModal, + WarningRecordCard }); diff --git a/packages/biz/lib/useSocket/ws.d.ts b/packages/biz/lib/useSocket/ws.d.ts deleted file mode 100644 index 0dc9550..0000000 --- a/packages/biz/lib/useSocket/ws.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -declare class Channel { - /** - * io 实例化对象 - */ - ioIns: any; - /** - * 已存在的订阅列表 - */ - listeners: never[]; - /** - * 调试信息 记录订阅/反订阅次数 - */ - subscribeListenerId: never[]; - unSubscribeListenerId: never[]; - init: () => void; - retry: (listener: { - [x: string]: any; - lastRetryInterval: number | undefined; - intervalId: NodeJS.Timeout; - } | undefined) => void; - doEmit: (topic: any, req: any, listenerId: any) => void; - subscribe(topic: any, req: any, handle: any): () => void; - unSubscribe(topic: any, req: any, handleId: any, listenerId: any): void; -} -declare const channelIns: Channel; -export default channelIns; diff --git a/packages/biz/lib/utils/constants.d.ts b/packages/biz/lib/utils/constants.d.ts index 45a9a99..0180cc0 100644 --- a/packages/biz/lib/utils/constants.d.ts +++ b/packages/biz/lib/utils/constants.d.ts @@ -21,3 +21,11 @@ export declare const DeviceTab: { REAL_CAMERA_ONLYFACE: number; REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: number; }; +export declare const BOX_TYPE_LIST: { + value: string; + label: string; +}[]; +export declare const ALL_LIST: { + value: string; + label: string; +}[]; diff --git a/packages/biz/lib/utils/constants.js b/packages/biz/lib/utils/constants.js index 6c57f12..733d65a 100644 --- a/packages/biz/lib/utils/constants.js +++ b/packages/biz/lib/utils/constants.js @@ -19,7 +19,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru // src/utils/constants.ts var constants_exports = {}; __export(constants_exports, { + ALL_LIST: () => ALL_LIST, BODY_SEARCH_THRESHOID: () => BODY_SEARCH_THRESHOID, + BOX_TYPE_LIST: () => BOX_TYPE_LIST, DeviceTab: () => DeviceTab, ENTER_CIRCLE: () => ENTER_CIRCLE, GLOBAL_IS_BOX_VMS_SHOW: () => GLOBAL_IS_BOX_VMS_SHOW, @@ -62,9 +64,18 @@ var DeviceTab = { REAL_CAMERA_NOFACE_NOBOX_NODIRECONNECT: 8 // 只有普通摄像头,没有人脸、没有盒子、直连 }; +var BOX_TYPE_LIST = [ + { value: "1", label: "盒子" }, + { value: "2", label: "盒子组" } +]; +var ALL_LIST = [ + { value: "", label: "全部" } +]; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { + ALL_LIST, BODY_SEARCH_THRESHOID, + BOX_TYPE_LIST, DeviceTab, ENTER_CIRCLE, GLOBAL_IS_BOX_VMS_SHOW, diff --git a/packages/biz/package.json b/packages/biz/package.json index ef55f5f..1fdb65b 100644 --- a/packages/biz/package.json +++ b/packages/biz/package.json @@ -1,6 +1,6 @@ { "name": "@zhst/biz", - "version": "0.6.0", + "version": "0.9.1", "description": "业务库", "keywords": [ "business", @@ -47,6 +47,5 @@ "classnames": "^2.5.1", "rc-util": "^5.38.1", "dayjs": "^1.11.10" - } } diff --git a/packages/biz/src/VideoPlayerCard/VideoPlayerCard.tsx b/packages/biz/src/VideoPlayerCard/VideoPlayerCard.tsx new file mode 100644 index 0000000..8319823 --- /dev/null +++ b/packages/biz/src/VideoPlayerCard/VideoPlayerCard.tsx @@ -0,0 +1,103 @@ +import { Card, Space, CardProps, Spin, Button } from 'antd'; +import { theme } from 'antd/lib'; +import { VideoPlayer, type VideoViewRef } from '@zhst/meta'; + +import React, { useState, useEffect, ReactNode, useRef } from 'react'; +import { CloseOutlined, LoadingOutlined } from '@ant-design/icons'; +import './index.less' + +export interface VideoPlayerCardProps { + windowKey?: string; + selectedWindowKey?: string; + showType?: 'video' | "image"; + imgSrc?: string; + videoSrc?: string; + cardProps?: CardProps; + errorReasonText?: string; + isWindowLoading?: boolean; + size?: 'large' | 'small'; + title?: string | ReactNode + handleCloseButtonClick?: (key?: string) => void; + handleWindowClick?: (key?: string) => void; +} + +export const VideoPlayerCard: React.FC = (props) => { + + const componentName = `zhst-biz-video-player-card`; + const { showType, imgSrc, videoSrc, cardProps, isWindowLoading, errorReasonText, size, title, handleCloseButtonClick, handleWindowClick, windowKey, selectedWindowKey = '' } = props; + const [cardContent, setCardContent] = useState(null); + const { useToken } = theme + const { token } = useToken() + const videoRef = useRef(null) + const selectedBorderStyle = { + border: `2px solid ${token.colorPrimary}`, boxShadow: " 0px 2px 9px 0px rgba(0,0,0,0.16)" + } + const cardStyle: React.CSSProperties = { + ...(size === 'large' ? { height: 931 } : { height: 456, cursor: 'pointer' }), + ...(size === 'small' && selectedWindowKey === windowKey ? selectedBorderStyle : {}) + }; + const videoPlayerCardStyle = size === 'small' ? { width: "calc(50% - 20px)" } : { flex: 1 } + + useEffect(() => { + if (!isWindowLoading && (videoSrc || imgSrc)) { + let contentElement: JSX.Element | null = null; + if (videoSrc) { + contentElement = ( + + ); + videoRef.current?.setShowCrop(true) + + } else if (imgSrc) { + contentElement = ( + 首帧图 + ); + } + setCardContent(contentElement); + } else { + setCardContent(null) + } + }, [showType, imgSrc, videoSrc, isWindowLoading]); + + return ( +
{ handleWindowClick?.(windowKey) }} style={videoPlayerCardStyle}> + +
{title}
+
+ +
+ } + style={{ display: "flex", flexDirection: "column", borderRadius: 4, overflow: "hidden", ...cardStyle }} + bodyStyle={{ flex: 1 }} + {...cardProps} + > + {cardContent ? ( + <> + {cardContent} + + ) : ( +
+ { + isWindowLoading ? +
+ } /> +
+ : !!errorReasonText && {errorReasonText} + } +
+ )} + {/* 其他内容 */} +
+
+ ); +}; + +export default VideoPlayerCard; + diff --git a/packages/biz/src/VideoPlayerCard/demo/base.tsx b/packages/biz/src/VideoPlayerCard/demo/base.tsx new file mode 100644 index 0000000..7063d94 --- /dev/null +++ b/packages/biz/src/VideoPlayerCard/demo/base.tsx @@ -0,0 +1,19 @@ + +import React from 'react'; +import { VideoPlayerCard, type VideoPlayerCardProps } from '@zhst/biz'; +import { Space } from 'antd'; + +const mockVideoPlayerCardProps: VideoPlayerCardProps = { + showType: 'image', + // videoSrc: 'https://example.com/video.mp4', + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', // 如果需要在没有视频时显示图片封面 + size: 'small', +}; + +export default () => { + return ( + + + + ) +} diff --git a/packages/biz/src/VideoPlayerCard/index.less b/packages/biz/src/VideoPlayerCard/index.less new file mode 100644 index 0000000..0f87e3e --- /dev/null +++ b/packages/biz/src/VideoPlayerCard/index.less @@ -0,0 +1,30 @@ +.zhst-biz-video-player-card { + .ant-card-head { + padding: 0 20px; + } + + .ant-card-body { + padding: 0; + overflow: hidden; + border-radius: 0; + + .zhst-image__video-view { + height: 100%; + } + } + + .card-close-button { + .ant-btn { + padding: 0 3px; + height: 22px; + color: #00000073; + } + + .ant-btn:hover { + padding: 0 3px; + height: 22px; + color: #000000e0; + } + } + +} \ No newline at end of file diff --git a/packages/biz/src/VideoPlayerCard/index.md b/packages/biz/src/VideoPlayerCard/index.md new file mode 100644 index 0000000..1e900ec --- /dev/null +++ b/packages/biz/src/VideoPlayerCard/index.md @@ -0,0 +1,22 @@ +--- +group: 数据展示 +category: Components +subtitle: 视频播放卡片 +title: VideoPlayerCard 视频播放卡片 +--- + +# VideoPlayerCard 视频播放卡片 + + + + + + +## API + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | + + + + diff --git a/packages/biz/src/VideoPlayerCard/index.tsx b/packages/biz/src/VideoPlayerCard/index.tsx new file mode 100644 index 0000000..20710eb --- /dev/null +++ b/packages/biz/src/VideoPlayerCard/index.tsx @@ -0,0 +1,3 @@ +import VideoPlayerCard from './VideoPlayerCard' +export type { VideoPlayerCardProps } from './VideoPlayerCard' +export default VideoPlayerCard \ No newline at end of file diff --git a/packages/biz/src/WarningRecordCard/WarningRecordCard.tsx b/packages/biz/src/WarningRecordCard/WarningRecordCard.tsx index 9e94dd8..66378a0 100644 --- a/packages/biz/src/WarningRecordCard/WarningRecordCard.tsx +++ b/packages/biz/src/WarningRecordCard/WarningRecordCard.tsx @@ -18,6 +18,8 @@ export interface IRecord { 用于显示 盒子 点位 柜子 等信息 */ warningInfo?: string[] + /* + 右侧 柜子id 显示 /* 盒子 ID */ @@ -30,6 +32,8 @@ export interface IRecord { 柜子id */ cabietId?: string; + /* + 直接传格式化好的时间 /* 右侧 柜子id 显示 */ @@ -38,15 +42,16 @@ export interface IRecord { 直接传格式化好的时间 */ warningTime?: string; - /* + /* 传格时间戳 */ warningTimestamp?: string | number - /* - 传格时间格式 + /* + 传格时间格式 @default YYYY-MM-DD HH:mm:ss */ warningTimeFormat?: string; + }; export interface WarningRecordCardProps { diff --git a/packages/biz/src/WindowToggle/WindowToggle.tsx b/packages/biz/src/WindowToggle/WindowToggle.tsx new file mode 100644 index 0000000..0211f0f --- /dev/null +++ b/packages/biz/src/WindowToggle/WindowToggle.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { Segmented } from 'antd'; +import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'; +import { VideoPlayerCard, VideoPlayerCardProps } from '@zhst/biz'; +import './index.less' +import { theme } from 'antd/lib'; + +type Size = 'large' | 'small' + +interface WindowToggleProps { + dataSource?: VideoPlayerCardProps[]; + handleWindowClick?: (key?: string) => void; + handleCloseButtonClick?: (key?: string) => void; + selectedWindowKey?: string; +} + +export const WindowToggle: React.FC = (props) => { + + const { dataSource = [], handleWindowClick, handleCloseButtonClick, selectedWindowKey } = props + const [size, setSize] = useState("large"); + const { useToken } = theme + const { token } = useToken() + + const getLabelStyle = (isSelected: boolean) => ({ + padding: "0 11px", background: "#fff", + ...(isSelected ? { background: token.colorPrimary, color: '#fff' } : {}), + }); + + + return ( +
+ {/* 切换按钮 */} +
+
}, + { value: 'small', label:
}, + ]} + onChange={(value) => { + // 当一个窗口时 默认 selectedkey 第一条数据的 windowkey + if (value === 'large' && dataSource.length > 0) { + const { windowKey } = dataSource[0] + handleWindowClick?.(windowKey) + } + setSize(value as Size) + }} + /> +
+ +
+ { + dataSource?.map((item, index) => { + if (size === "large" && index > 0) return + return ( + ) + }) + } +
+ + ); +}; + +export default WindowToggle; + diff --git a/packages/biz/src/WindowToggle/demo/base.tsx b/packages/biz/src/WindowToggle/demo/base.tsx new file mode 100644 index 0000000..883b541 --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/base.tsx @@ -0,0 +1,166 @@ + +import React, { useState } from 'react'; +import { IRecord, VideoPlayerCardProps, WindowToggle, useViewLargerImageModal } from '@zhst/biz'; +import { videoData, warningData } from './mock'; +import { Space } from 'antd'; +import dayjs from 'dayjs' +import WarningRecordList from './components/WarningRecordList'; +import './index.less' + + +export default () => { + + // 必须设置初始数据 用于渲染 4个窗口 + const initialVideoDataSource: VideoPlayerCardProps[] = [ + { + windowKey: 'first-window', + }, + { + windowKey: 'second-window', + }, + { + windowKey: 'third-window', + }, + { + windowKey: 'forth-window', + } + ] + const [videoDataSource, setVideoDataSource] = useState(initialVideoDataSource); + const [warningDataSource, setWarningDataSource] = useState(); + const [selectedWindowKey, setSelectedWindowKey] = useState('first-window'); + const [selectedRecordId, setSelectedRecordId] = React.useState() + const [isRecordListLoading, setIsRecordListLoading] = React.useState(false) + // 把弹窗的ref 拿出来 + const viewLargerImageModalRef = useViewLargerImageModal() + + const handleWindowClick = (key?: string) => { + setSelectedWindowKey(key) + } + + const clearWindowData = (key?: string) => { + // 当关闭窗口时 也要刷新 右侧 预警记录接口 不要忘记 + setVideoDataSource((pre) => { + const newVideoDataSource = pre.map((item) => { + if (item.windowKey === key) { + return { windowKey: key }; + } + return item; // 保持不变 + }); + return newVideoDataSource + }) + } + + const handleDownloadImg = (imgSrc?: string) => { + console.log(imgSrc) + // 可以调用 下面 方法关闭弹窗 + // viewLargerImageModalRef.current?.handleCancel() + } + + const onRecordClick = (record?: IRecord) => { + // 点击的时候把数据 拿过来处理一下传给大图弹框 + const { imgSrc, warningType, boxId, position, cabietId, warningTime, warningTimestamp, warningTimeFormat = 'YYYY-MM-DD HH:mm:ss' } = record || {} + const formattedDate = warningTimestamp ? dayjs(warningTimestamp).format(warningTimeFormat) : ''; + const warningTimeShow = warningTime ? warningTime : formattedDate + //用于渲染右侧的 信息 + const warningData = [ + { label: '预警类型', value: warningType }, + { label: '预警时间', value: warningTimeShow }, + { label: '盒子', value: boxId }, + { label: '点位', value: position }, + { label: '柜子ID', value: cabietId }, + ] + // 调用这个方法打开弹框 + viewLargerImageModalRef?.current?.show({ imgSrc: imgSrc, warningData: warningData }) + + setSelectedRecordId(record?.id) + } + + const mockData = () => { + // 请求时需要对应窗口为loading 状态 + setVideoDataSource((pre) => { + const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => { + // 开启loading + if (item.windowKey === selectedWindowKey) { + return { ...item, isWindowLoading: true, title: '' } + } + return item + }); + return newVideoDataSource + }) + + // 模拟 视频数据请求 + setTimeout(() => { + // 对后端返回数据进行处理 组装一套符合属性的 数据 + const newVideoData: VideoPlayerCardProps = { imgSrc: videoData.imgSrc, title: videoData.title, } + setVideoDataSource((pre) => { + const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => { + // 传给 选中的视频窗口 + if (item.windowKey === selectedWindowKey) { + return { ...item, ...newVideoData } + } + return item + }); + return newVideoDataSource + }) + + setVideoDataSource((pre) => { + const newVideoDataSource: VideoPlayerCardProps[] = pre.map((item) => { + // 关闭loading + if (item.windowKey === selectedWindowKey) { + return { ...item, isWindowLoading: false } + } + return item + }); + return newVideoDataSource + }) + + }, 3000); + + // 模拟 预警记录数据请求 + + setIsRecordListLoading(true) + + setTimeout(() => { + const newWarningDataSource: IRecord[] = warningData.map(o => { + return { + imgSrc: o.imgSrc, + id: o.id, + warningType: o.warningType, + boxId: o.boxId, + position: o.position, + cabietId: o.cabietId, + //,`柜子ID: ${o.cabietId}` + warningInfo: [`盒子${o.boxId}`, `位置${o.position}`, `柜子ID${o.cabietId}`], + // cabietText: `柜子ID: ${o.cabietId}`, + warningTimestamp: o.warningTimestamp, + } + }) + setWarningDataSource(newWarningDataSource) + setIsRecordListLoading(false) + }, 1000) + + } + + return ( + +
+ + +
+ +
+ ) +} diff --git a/packages/biz/src/WindowToggle/demo/components/WarningRecordList/WarningRecordList.tsx b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/WarningRecordList.tsx new file mode 100644 index 0000000..f4f8dec --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/WarningRecordList.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import { ViewLargerImageModal, WarningRecordCard, IRecord, ViewLargerImageModalRef } from '@zhst/biz'; +import { Empty, Space, Spin } from 'antd'; +import "./index.less" +import { LoadingOutlined } from '@ant-design/icons'; + + +interface WarningRecordListProps { + dataSource?: IRecord[]; + viewLargerImageModalRef?: React.RefObject; + handleDownloadImg?: (imgSrc?: string) => void; + onRecordClick?: (record?: IRecord) => void; + selectedRecordId?: string; + isRecordListLoading?: boolean; + recordListTitle?: string; + style?: React.CSSProperties; + cardStyle?: React.CSSProperties; + imgStyle?: React.CSSProperties; + largeImageTitle?: string; +} + + +const WarningRecordList: React.FC = (props) => { + + const { + dataSource = [], + viewLargerImageModalRef, + selectedRecordId, + handleDownloadImg, + onRecordClick, + isRecordListLoading, + recordListTitle, + style, + cardStyle, + imgStyle, + largeImageTitle + } = props + + return ( +
+
{recordListTitle}
+
+ { + isRecordListLoading ? +
+ } /> +
+ : (dataSource?.length) > 0 ? + + {dataSource?.map((record, index) => { + if (index > 2) return + return ( { onRecordClick?.(record) }} + selectedRecordId={selectedRecordId} + cardStyle={{ width: 300, height: 264, ...cardStyle }} + imgStyle={{ width: 280, height: 169, ...imgStyle }} + />) + } + + )} + + : +
+ +
+ } +
+ {/* 弹窗 绑定ref 后可以调用 handleCancel方法关闭弹窗 show方法打开弹窗 */} + +
+ ) +}; + +export default WarningRecordList; \ No newline at end of file diff --git a/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.less b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.less new file mode 100644 index 0000000..e348f82 --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.less @@ -0,0 +1,20 @@ +.zhst-biz-warning-record-list { + display: flex; + flex-direction: column; + border-left: solid 1px #00000026; + width: 320px; + + .header { + width: 100%; + height: 48px; + background-color: #EFF2F4; + padding: 10px 20px; + box-sizing: border-box; + } + + .body { + padding: 10px; + overflow: hidden; + flex: 1; + } +} \ No newline at end of file diff --git a/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.tsx b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.tsx new file mode 100644 index 0000000..3e4aa09 --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/components/WarningRecordList/index.tsx @@ -0,0 +1,2 @@ +import WarningRecordList from './WarningRecordList' +export default WarningRecordList \ No newline at end of file diff --git a/packages/biz/src/WindowToggle/demo/index.less b/packages/biz/src/WindowToggle/demo/index.less new file mode 100644 index 0000000..b73ced1 --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/index.less @@ -0,0 +1,5 @@ +#windowtoggle-demo-base { + .dumi-default-previewer-demo>div { + width: 100%; + } +} \ No newline at end of file diff --git a/packages/biz/src/WindowToggle/demo/mock.tsx b/packages/biz/src/WindowToggle/demo/mock.tsx new file mode 100644 index 0000000..4497d61 --- /dev/null +++ b/packages/biz/src/WindowToggle/demo/mock.tsx @@ -0,0 +1,65 @@ +export const videoData = { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + // videoSrc: 'ws://10.0.0.7:9033/flv/File/test/test_h264_1.mp4.flv?ip=127.0.0.1', + title: `盒子1 点位1` +} + +export const warningData = [ + { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + id: '156156ewr1', + warningType: '火焰识别', + boxId: '2', + position: '2', + cabietId: '002', + // warningTime: "2023-03-01 ", + warningTimestamp: Date.now(), + // warningTimeFormat:"YYYY-MM-DD" + }, + { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + id: '156156ewr155', + warningType: '火焰识别', + boxId: '1', + position: '1', + cabietId: '001', + // warningTime: "2023-03-01 ", + warningTimestamp: Date.now(), + // warningTimeFormat:"YYYY-MM-DD" + }, + { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + id: '156156rew155', + warningType: '火焰识别', + boxId: '3', + position: '3', + cabietId: '004', + // warningTime: "2023-03-01 ", + warningTimestamp: Date.now(), + // warningTimeFormat:"YYYY-MM-DD" + }, + { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + id: '15615615ew5', + warningType: '火焰识别', + boxId: '4', + position: '4', + cabietId: '004', + // warningTime: "2023-03-01 ", + warningTimestamp: Date.now(), + // warningTimeFormat:"YYYY-MM-DD" + }, + { + imgSrc: 'https://i.yourimageshare.com/lRHiD2UnAT.png', + id: '15615615sdf5', + warningType: '火焰识别', + boxId: '5', + position: '5', + cabietId: '005', + // warningTime: "2023-03-01 ", + warningTimestamp: Date.now(), + // warningTimeFormat:"YYYY-MM-DD" + } +] + + diff --git a/packages/biz/src/WindowToggle/index.less b/packages/biz/src/WindowToggle/index.less new file mode 100644 index 0000000..61c77bd --- /dev/null +++ b/packages/biz/src/WindowToggle/index.less @@ -0,0 +1,45 @@ +.zhst-biz-window-toggle { + display: flex; + flex-direction: column; + flex: 1; + + .header { + width: 100%; + height: 48px; + background-color: #EFF2F4; + padding: 10px 20px; + box-sizing: border-box; + + .ant-segmented { + padding: 0; + + .ant-segmented-group { + border-radius: 4px; + overflow: hidden; + + .ant-segmented-item { + border-radius: 0; + + .ant-segmented-item-label { + padding: 0; + } + } + } + } + } + + .body { + flex: 1; + width: 100%; + background-color: #E5EAEC; + padding: 10px; + box-sizing: border-box; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + + >div { + margin: 10px; + } + } +} \ No newline at end of file diff --git a/packages/biz/src/WindowToggle/index.md b/packages/biz/src/WindowToggle/index.md new file mode 100644 index 0000000..a0040bf --- /dev/null +++ b/packages/biz/src/WindowToggle/index.md @@ -0,0 +1,22 @@ +--- +group: 数据展示 +category: Components +subtitle: 窗口切换组件 +title: WindowToggle 窗口切换组件 +--- + +# WindowToggle 窗口切换组件 + + + + + + +## API + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | + + + + diff --git a/packages/biz/src/WindowToggle/index.tsx b/packages/biz/src/WindowToggle/index.tsx new file mode 100644 index 0000000..0fa9c9a --- /dev/null +++ b/packages/biz/src/WindowToggle/index.tsx @@ -0,0 +1,2 @@ +import WindowToggle from './WindowToggle' +export default WindowToggle \ No newline at end of file diff --git a/packages/biz/src/boxSelectTree/boxSelectTree.tsx b/packages/biz/src/boxSelectTree/boxSelectTree.tsx index fe3914e..964aa0a 100644 --- a/packages/biz/src/boxSelectTree/boxSelectTree.tsx +++ b/packages/biz/src/boxSelectTree/boxSelectTree.tsx @@ -16,6 +16,9 @@ export interface BoxSelectTreeProps { tabsProps?: TabsProps searchInputProps?: InputProps treeProps?: TreeProps + showOptions?: boolean + customImport?: any + extraBtns?: any } const BoxSelectTree: FC = (props) => { @@ -31,7 +34,10 @@ const BoxSelectTree: FC = (props) => { onCreateSubmit, tabsProps, searchInputProps, - treeProps + treeProps, + customImport, + extraBtns, + showOptions = true } = props const onChange = (key: string) => { @@ -54,6 +60,9 @@ const BoxSelectTree: FC = (props) => { onSearch={onSearch} onItemCheck={onItemCheck} onItemSelect={onItemSelect} + showOptions={showOptions} + customImport={customImport} + extraBtns={extraBtns} /> ) }, @@ -72,6 +81,9 @@ const BoxSelectTree: FC = (props) => { onSearch={onSearch} onItemCheck={onItemCheck} onItemSelect={onItemSelect} + showOptions={showOptions} + customImport={customImport} + extraBtns={extraBtns} /> ) }, diff --git a/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx b/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx index 5aeab5e..b364be3 100644 --- a/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx +++ b/packages/biz/src/boxSelectTree/components/boxPanel/index.tsx @@ -1,7 +1,7 @@ import React, { FC, useState, useRef } from 'react'; import{ Button, Divider, Input, Space, TreeDataNode } from 'antd' import { ModalForm, ModalFormProps, ProFormInstance, ProFormText } from '@ant-design/pro-components' -import { DiffOutlined, SwitcherOutlined } from '@ant-design/icons' +import { ClockCircleOutlined, CloseCircleOutlined, DiffOutlined, FolderAddOutlined, ImportOutlined, SwitcherOutlined } from '@ant-design/icons' import type { TreeProps, InputProps } from 'antd'; import TreeTransferModal from '../../../treeTransferModal' import BoxTree from '../../../tree'; @@ -9,6 +9,7 @@ import BoxTree from '../../../tree'; export interface BoxGroupPanelProps { searchInputProps?: InputProps + showOptions?: boolean treeProps?: TreeProps data: TreeDataNode[] boxDataSource: TreeDataNode[] @@ -19,11 +20,16 @@ export interface BoxGroupPanelProps { onBoxBatchDelete?: (data?: any) => void onBoxDelete?: (data?: any) => void onCreateSubmit?: ModalFormProps['onFinish'] + onClockClick?: () => void + customImport?: any + extraBtns?: any } const BoxGroupPanel: FC = (props) => { const { searchInputProps, + showOptions = true, + extraBtns, data = [], onSearch, treeProps, @@ -32,7 +38,9 @@ const BoxGroupPanel: FC = (props) => { onCreateSubmit, onBoxBatchDelete, onBoxDelete, - boxDataSource + onClockClick, + boxDataSource, + customImport } = props const [isTreeCheckable, setIsTreeCheckable] = useState(false) const [targetItems, setTargetItems] = useState([]); @@ -41,8 +49,7 @@ const BoxGroupPanel: FC = (props) => { const createFormRef = useRef< ProFormInstance<{ name: string; - company?: string; - useMode?: string; + boxList?: any[]; }> >() @@ -76,89 +83,109 @@ const BoxGroupPanel: FC = (props) => { setTargetItems(pre => pre.filter(o => o.key !== key)) } - const onOk = (data: any) => { - console.log('data', data) + // 盒子点击确定 + const onBoxChoiceOk = async (data: any) => { + createFormRef.current?.setFieldValue('boxList', data) + createFormRef.current?.setFieldValue('boxName', 123) + console.log(createFormRef.current?.getFieldValue('boxList')) + setBoxChoiceOpen(false) } - const onReset = () => { + // 盒子选择重置 + const onBoxChoiceReset = () => { setCheckedKeys([]) setTargetItems([]) } return (
+ {/* 盒子选择弹框 */} setBoxChoiceOpen(false)} - onRadioChange={(val) => console.log('radio', val)} // 顶部 radio 事件 + onRadioChange={(e) => console.log('radio', e.target.value)} // 顶部 radio 事件 dataSource={boxDataSource} // 数据源 targetItems={targetItems} // 右侧选中项 checkedKeys={checkedKeys} // 左侧选中 - onReset={onReset} // 重置按钮事件 - onOk={onOk} // 确定按钮事件 + onReset={onBoxChoiceReset} // 重置按钮事件 + onOk={onBoxChoiceOk} // 确定按钮事件 onTreeCheck={onTreeCheck} // 树check选中事件 onItemDelete={onItemDelete} // 右侧点击删除事件 /> - - + + onSearch?.(e)} placeholder='请输入盒子名称' {...searchInputProps} /> - + {customImport || ( + <> + } - submitter={{ - searchConfig: { - submitText: '确定', - resetText: '取消', - }, - }} - onFinish={onCreateSubmit} - > - - - { - createFormRef.current?.setFieldValue('boxList', null) - }} >恢复默认 - setBoxChoiceOpen(true)}>范围选择 - - ) - }} - /> - - - {/* @ts-ignore */} - - - + + + width={'600px'} + formRef={createFormRef} + title="新建组" + modalProps={{ destroyOnClose: true }} + layout='horizontal' + labelCol={{ span: 6 }} + wrapperCol={{ span: 18 }} + trigger={} + submitter={{ + searchConfig: { + submitText: '确定', + resetText: '取消', + }, + }} + onFinish={onCreateSubmit} + > + + + { + createFormRef.current?.setFieldValue('boxList', null) + onBoxChoiceReset() + }} >恢复默认 + setBoxChoiceOpen(true)}>范围选择 + + ) + }} + /> + + + {/* @ts-ignore */} + + + + + )} + {extraBtns} { + const [activeKey, setActiveKey] = useState('1') const [searchType, setSearchType] = useState('1') const [searchVal, setSearchVal] = useState('') const [checkedKeys, setCheckedKeys] = useState([]); @@ -32,18 +34,24 @@ const demo = () => { } return ( -
+
{contextHolder} console.log('搜索', e)} - onCreateSubmit={async () => { return true }} + onCreateSubmit={async (_data) => { + console.log('新建盒子', _data) + return true + }} onItemCheck={onTreeCheck} onItemSelect={e => console.log('onItemSelect', e)} - onTabChange={e => console.log('tabChange', e)} + onTabChange={val => setActiveKey(val)} onBoxDelete={data => console.log('盒子删除', data)} onBoxBatchDelete={onBoxBatchDelete} + tabsProps={{ + activeKey, + }} searchInputProps={{ addonBefore: ( ), onChange: e => setSearchVal(e.target.value), diff --git a/packages/biz/src/boxSelectTree/demo/extraBtns.tsx b/packages/biz/src/boxSelectTree/demo/extraBtns.tsx new file mode 100644 index 0000000..e398407 --- /dev/null +++ b/packages/biz/src/boxSelectTree/demo/extraBtns.tsx @@ -0,0 +1,29 @@ +import React, { useState } from 'react'; +import { BoxSelectTree } from '@zhst/biz'; +import { treeData, boxDataSource } from './mock' +import { Button } from 'antd'; + +const demo = () => { + const [activeKey, setActiveKey] = useState('1') + const [checkedKeys, setCheckedKeys] = useState([]); + + + return ( +
+ 自定义按钮} + tabsProps={{ + activeKey, + }} + treeProps={{ + checkedKeys + }} + /> +
+ ); +}; + +export default demo; diff --git a/packages/biz/src/boxSelectTree/demo/mock.tsx b/packages/biz/src/boxSelectTree/demo/mock.tsx index f60888b..d6bbc91 100644 --- a/packages/biz/src/boxSelectTree/demo/mock.tsx +++ b/packages/biz/src/boxSelectTree/demo/mock.tsx @@ -1,6 +1,6 @@ -import { TreeDataNode } from "antd"; +import { TreeData } from "@zhst/biz"; -export const treeData: TreeDataNode[] = [ +export const boxDataSource: TreeData[] = [ { title: '全部盒子', key: '0-0', @@ -12,10 +12,12 @@ export const treeData: TreeDataNode[] = [ { title: '摄像头1', key: '0-0-0-0', + isCamera: true }, { title: '摄像头2', key: '0-0-0-1', + isCamera: true }, ], }, @@ -25,7 +27,8 @@ export const treeData: TreeDataNode[] = [ children: [ { title: '摄像头4', - key: '0-0-1-0' + key: '0-0-1-0', + isCamera: true } ], }, @@ -34,36 +37,18 @@ export const treeData: TreeDataNode[] = [ ]; -export const boxDataSource: TreeDataNode[] = [ +export const treeData: TreeData[] = [ + { key: '0-1-0', title: '分组0-1-0', isLeaf: true, checkable: false }, + { key: '0-1-1', title: '分组0-1-1', isLeaf: true, checkable: false }, + { key: '0-1-2', title: '分组0-1-2', isLeaf: true, checkable: false }, { - key: '0-0', - title: '分组0-0', - isLeaf: false, - checkable: false, - }, - { - key: '0-1', - title: '分组0-1', + key: '0-1-3', + title: '分组0-1-3', isLeaf: false, children: [ - { key: '0-1-0', title: '分组0-1-0', isLeaf: true, checkable: false }, - { key: '0-1-1', title: '分组0-1-1', isLeaf: true, checkable: false }, - { key: '0-1-2', title: '分组0-1-2', isLeaf: true, checkable: false }, - { - key: '0-1-3', - title: '分组0-1-3', - isLeaf: false, - children: [ - { key: '0-1-3-1', title: '分组0-1-3-1', isLeaf: true }, - { key: '0-1-3-2', title: '分组0-1-3-2', isLeaf: true }, - { key: '0-1-3-3', title: '分组0-1-3-3', isLeaf: true }, - ], - }, + { key: '0-1-3-1', title: '分组0-1-3-1', isLeaf: true, isCamera: true }, + { key: '0-1-3-2', title: '分组0-1-3-2', isLeaf: true, isCamera: true }, + { key: '0-1-3-3', title: '分组0-1-3-3', isLeaf: true, isCamera: true }, ], }, - { key: '0-2', title: '分组0-2', isLeaf: false, checkable: false, }, - { key: '0-3', title: '分组0-3', isLeaf: false, checkable: false, }, - { key: '0-4', title: '分组0-4', isLeaf: false, checkable: false, }, - { key: '0-5', title: '分组0-4', isLeaf: false, checkable: false, }, - { key: '0-6', title: '分组0-4', isLeaf: false, checkable: false, }, ]; diff --git a/packages/biz/src/boxSelectTree/demo/noOptions.tsx b/packages/biz/src/boxSelectTree/demo/noOptions.tsx new file mode 100644 index 0000000..a2e34e7 --- /dev/null +++ b/packages/biz/src/boxSelectTree/demo/noOptions.tsx @@ -0,0 +1,61 @@ +import React, { useState } from 'react'; +import { BoxSelectTree } from '@zhst/biz'; +import { Button, Select, TreeProps } from 'antd'; +import { FilterOutlined } from '@ant-design/icons'; +import { BOX_TYPE_LIST } from '../../utils/constants'; +import { treeData, boxDataSource } from './mock' + +const { Option } = Select + +const demo = () => { + const [activeKey, setActiveKey] = useState('1') + const [searchType, setSearchType] = useState('1') + const [searchVal, setSearchVal] = useState('') + const [checkedKeys, setCheckedKeys] = useState([]); + + const onTreeCheck: TreeProps['onCheck'] = (keys: any) => { + setCheckedKeys(keys) + } + + return ( +
+ console.log('搜索', e)} + onItemCheck={onTreeCheck} + onItemSelect={e => console.log('onItemSelect', e)} + onTabChange={val => setActiveKey(val)} + onBoxDelete={data => console.log('盒子删除', data)} + showOptions={false} + tabsProps={{ + activeKey, + }} + customImport={
+ ); +}; + +export default demo; diff --git a/packages/biz/src/boxSelectTree/index.md b/packages/biz/src/boxSelectTree/index.md index aa8ec86..6948d72 100644 --- a/packages/biz/src/boxSelectTree/index.md +++ b/packages/biz/src/boxSelectTree/index.md @@ -2,7 +2,7 @@ category: Components title: BoxSelectTree 盒子树 demo: - cols: 2 + cols: 4 group: title: 进阶组件 order: 2 @@ -13,7 +13,10 @@ group: ## 代码演示 基本用法 +自定义其它按钮 +不显示其它按钮 +## API | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | @@ -24,3 +27,8 @@ group: | tabsProps | Tabs组件的Props | antd的Tabs组件 | - | - | | searchInputProps | 搜索框的Props | antd的Input组件 | - | - | | onTabChange | tab切换监听 | function: (e) => void | - | - | +| onBoxDelete | 盒子删除事件 | function: (e) => void | - | - | +| onBoxBatchDelete | 盒子批量删除事件 | function: (e) => void | - | - | +| onCreateSubmit | 新建提交事件 | function: (e) => void | - | - | +| showOptions | 展示其它功能按钮 | boolean | true | - | + diff --git a/packages/biz/src/index.tsx b/packages/biz/src/index.tsx index 8d54007..abf2337 100644 --- a/packages/biz/src/index.tsx +++ b/packages/biz/src/index.tsx @@ -1,6 +1,7 @@ export { default as BigImageModal } from './BigImageModal' export { default as BoxSelectTree } from './boxSelectTree' export { default as Tree } from './tree' +export type { TreeData } from './tree' export { default as TreeTransfer } from './treeTransfer' export { default as TreeTransferModal } from './treeTransferModal' export { default as WarningRecordCard } from './WarningRecordCard' diff --git a/packages/biz/src/tree/boxTree.tsx b/packages/biz/src/tree/boxTree.tsx index 425596f..5461434 100644 --- a/packages/biz/src/tree/boxTree.tsx +++ b/packages/biz/src/tree/boxTree.tsx @@ -1,16 +1,18 @@ -import React, { FC } from 'react'; +import React, { FC, useState } from 'react'; import { Tree, Badge, TreeDataNode, Space, TreeProps } from 'antd'; +import theme from 'antd/es/theme' import { CloseOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons' import { ModalForm, ProFormText } from '@ant-design/pro-components'; import './index.less' const componentName = 'zhst-biz-tree' +const { useToken } = theme export interface BoxTreeProps extends TreeProps { data: TreeDataNode[] treeCheckable?: boolean showItemOption?: boolean - treeProps?: TreeProps + customOptions?: any; onItemCheck?: TreeProps['onCheck'] onItemSelect?: TreeProps['onSelect'] onItemSetting?: (_data: any) => void @@ -19,52 +21,86 @@ export interface BoxTreeProps extends TreeProps { } const boxTree: FC = (props) => { - const { onItemSelect, onItemCheck, onItemSetting, onItemDelete, data = [], showItemOption = true, treeCheckable = false, onRenameFinish } = props + const { + onItemSelect, + onItemCheck, + onItemSetting, + onItemDelete, + data = [], + showItemOption = true, + treeCheckable = false, + onRenameFinish, + customOptions + } = props + const { token } = useToken() + const [checkedItem, setCheckedItem] = useState('') + + const cameraStatus = new Map([ + ['0', 'success'], + ['1', 'error'] + ]) return ( { + setCheckedItem(selectedKeys[0]) + onItemSelect?.(selectedKeys, info) + }} onCheck={onItemCheck} treeData={data} titleRender={(_nodeData) => { return (
- {!_nodeData.children && } - {_nodeData.title as any} - {showItemOption && - } - submitter={{ - searchConfig: { - submitText: '确定', - resetText: '取消', - }, - }} - onFinish={async (value) => onRenameFinish?.(value, _nodeData)} - > - - - onItemSetting?.(_nodeData)} /> - onItemDelete?.(_nodeData)} /> - } + {/* @ts-ignore */} + {!_nodeData.children && _nodeData.isCamera && } + + {_nodeData.title as any} + + {showItemOption && ( + + {customOptions || ( + <> + } + submitter={{ + searchConfig: { + submitText: '确定', + resetText: '取消', + }, + }} + onFinish={async (value) => onRenameFinish?.(value, _nodeData)} + > + + + onItemSetting?.(_nodeData)} /> + onItemDelete?.(_nodeData)} /> + + )} + + )}
) }} diff --git a/packages/biz/src/tree/demo/customOptions.tsx b/packages/biz/src/tree/demo/customOptions.tsx new file mode 100644 index 0000000..bcb14fb --- /dev/null +++ b/packages/biz/src/tree/demo/customOptions.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Tree } from '@zhst/biz'; +import { LoadingOutlined, PlayCircleOutlined, SettingOutlined } from '@ant-design/icons'; +import { treeData } from './mock' + +const demo = () => { + return ( +
+ + + + + + )} + /> +
+ ); +}; + +export default demo; diff --git a/packages/biz/src/tree/demo/customTitleRender.tsx b/packages/biz/src/tree/demo/customTitleRender.tsx index 61971a2..95f3cd2 100644 --- a/packages/biz/src/tree/demo/customTitleRender.tsx +++ b/packages/biz/src/tree/demo/customTitleRender.tsx @@ -14,8 +14,11 @@ const demo = () => { diff --git a/packages/biz/src/tree/index.md b/packages/biz/src/tree/index.md index 7a84601..b54b366 100644 --- a/packages/biz/src/tree/index.md +++ b/packages/biz/src/tree/index.md @@ -14,8 +14,15 @@ group: 基本用法 自定义渲染界面 不展示配置项 +自定义配置项 +## API + +**额外参数可以参考 antd - Tree 组件** | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | data | 数据源 | Array[] | [] | - | +| titleRender | 子项自定义 | ReactNode、 undefined | - | - | +| showItemOption | 是否显示额外配置功能 | boolean | true | - | +| customOptions | 自定义配置项 | any | - | - | diff --git a/packages/biz/src/tree/index.tsx b/packages/biz/src/tree/index.tsx index fb90026..1c01493 100644 --- a/packages/biz/src/tree/index.tsx +++ b/packages/biz/src/tree/index.tsx @@ -1,3 +1,10 @@ +import { TreeDataNode } from 'antd'; import BoxTree from './boxTree'; +export interface TreeData extends TreeDataNode { + children?: TreeDataNode['children'] & { + isCamera?: boolean + }[] +} + export default BoxTree; diff --git a/packages/biz/src/treeTransfer/index.md b/packages/biz/src/treeTransfer/index.md index ba09b9d..678b494 100644 --- a/packages/biz/src/treeTransfer/index.md +++ b/packages/biz/src/treeTransfer/index.md @@ -13,6 +13,8 @@ group: 基本用法 和Modal组合使用 +## API + | 参数 | 说明 | 类型 | 默认值 | 版本 | | --- | --- | --- | --- | --- | | data | 数据源 | Array[] | [] | - | diff --git a/packages/biz/src/treeTransferModal/TreeTransferModal.tsx b/packages/biz/src/treeTransferModal/TreeTransferModal.tsx index 565357e..303cd40 100644 --- a/packages/biz/src/treeTransferModal/TreeTransferModal.tsx +++ b/packages/biz/src/treeTransferModal/TreeTransferModal.tsx @@ -1,7 +1,7 @@ import React, { FC, useState } from 'react'; +import { Modal, ModalProps, Radio, RadioGroupProps, Select, SelectProps, TransferProps, TreeDataNode, TreeProps } from 'antd'; import TreeTransfer from '../treeTransfer'; -import { Modal, ModalProps, Radio, RadioGroupProps, TransferProps, TreeDataNode } from 'antd'; -import { TreeProps } from 'antd/lib'; +import { ALL_LIST, BOX_TYPE_LIST } from '../utils/constants'; export interface TreeTransferModalProps { dataSource: TreeDataNode[] @@ -17,7 +17,10 @@ export interface TreeTransferModalProps { open?: boolean onCancel?: ModalProps['onCancel'] onRadioChange?: RadioGroupProps['onChange'] + onSelect?: SelectProps['onSelect'] modalProps?: ModalProps + radioProps?: RadioGroupProps + selectProps?: SelectProps } const TreeTransferModal: FC = (props) => { @@ -31,11 +34,14 @@ const TreeTransferModal: FC = (props) => { onReset, onRadioChange, onTreeCheck, + onSelect, targetItems, modalProps, + radioProps, + selectProps, } = props - const [type, setType] = useState('box') + const [type, setType] = useState('1') return ( = (props) => { {...modalProps} >
- { - setType(e.target.value) - onRadioChange?.(e) - }} - style={{ marginLeft: '24px', padding: '20px 0' }} - value={type} - > - 盒子 - 盒子组 - +
+ { + setType(e.target.value) + onRadioChange?.(e) + }} + style={{ marginLeft: '24px', padding: '20px 0' }} + value={type} + options={BOX_TYPE_LIST} + {...radioProps} + /> +