diff --git a/.fatherrc.ts b/.fatherrc.ts index db700bd..fd064d8 100644 --- a/.fatherrc.ts +++ b/.fatherrc.ts @@ -1,5 +1,15 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md + esm: { + output: 'es', + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', + }, + cjs: { + output: 'lib', + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', + }, }); diff --git a/package.json b/package.json index 63dc05d..f844aff 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "dumi": "^2.2.13", "eslint": "^8.23.0", "father": "^4.1.0", + "father-plugin-less": "^0.0.2", "husky": "^8.0.1", "lerna": "^8.0.0", "lint-staged": "^13.0.3", diff --git a/packages/biz/.fatherrc.ts b/packages/biz/.fatherrc.ts index 447d06b..b0341a2 100644 --- a/packages/biz/.fatherrc.ts +++ b/packages/biz/.fatherrc.ts @@ -1,13 +1,16 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md esm: { output: 'es', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, cjs: { output: 'lib', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, + plugins: ['father-plugin-less'], }); diff --git a/packages/biz/package.json b/packages/biz/package.json index 89fd91f..5346957 100644 --- a/packages/biz/package.json +++ b/packages/biz/package.json @@ -35,6 +35,7 @@ "registry": "http://10.0.0.77:4874" }, "devDependencies": { + "@swc/core": "^1.3.9", "@zhst/types": "workspace:^" }, "dependencies": { diff --git a/packages/biz/src/BigImage/BigImage.tsx b/packages/biz/src/BigImage/BigImage.tsx new file mode 100644 index 0000000..e4eb4cd --- /dev/null +++ b/packages/biz/src/BigImage/BigImage.tsx @@ -0,0 +1,304 @@ +import React, { forwardRef, useImperativeHandle, useRef } from 'react' +import { + ConfigProvider, + Descriptions, + CropperImage, + AttachImage, + VideoPlayer, + RelatedImage, + Radio, + Tooltip, + Button, + Tabs +} from '@zhst/meta'; +import classNames from 'classnames' +import { IconFont } from '@zhst/icon' +import { BigImageProps, BigImageRef } from './interface' +import CombineImage from './components/CombineImage' +import './index.less' + +const DescriptionsItem = Descriptions.Item + +export const componentPrefix = 'zhst-big-image' + +const initialStyle ={ + fontSize: '12px' +} + +const BigImage = forwardRef((props, ref) => { + const { + // ------------ 通用配置 ------------------- + type, + viewHeight, + width = '100%', + children, + // ------------ 顶部按钮 ----------------- + topButtonRender, + // ------------ 描述 ----------------- + descriptionList = [], + showDescription, + // ------------- tab 导航 ---------------- + customTabBarExtraContent, + tabProps, + onTabChange, + // ------------- 场景图 ------------- + cropperImageProps = { + cropButtonList: [] + }, + // ----------------- 对比图 --------------------- + combineImageProps, + // ------------ 视频模式 ----------------- + videoProps, + // ------------ view 操作按钮 ----------------- + showModeChange, + modeButtonGroupProps, + viewTopModeButtonList = [ + { + key: 'image', + label: '图片' + }, + { + key: 'video', + label: '视频' + } + ], + // ------------------ 翻页 ---------------------- + showNavigation, + prevButtonProps, + onPrevButtonClick, + onNextButtonClick, + nextButtonProps, + // ------------------ 人脸碰撞模型 ----------------- + relatedImageProps, + isRelated = false, + theme, + } = props + const combineImageRef = useRef(null) + const videoPlayerRef = useRef(null) + const cropperImageRef = useRef(null) + + cropperImageProps.cropButtonList = cropperImageProps?.cropButtonList || [ + { + key: 'auto', + icon: , + label: '智能框选', + }, + { + key: 'custom', + icon: , + label: '手动框选', + } + ]; + + // ------------------- 初始化模式 ---------------------- + const initMode = (type: BigImageProps['type'] = 'normal') => { + switch (type) { + case 'compater': + return ( + + ) + case 'normal': + return ( +
+ + {/* // ------------ 显示条件:当不为编辑状态,并且有图片值 ----------------- */} + {!cropperImageProps?.editAble && cropperImageProps?.attachImageData && ( + <> + +
{`人脸质量分:${(Number(cropperImageProps?.score) as number).toFixed(2)}`}
+ + )} + {/* // ------------ 场景图绘制工具栏 ----------------- */} + {cropperImageProps?.showEditTools && ( +
+ + {cropperImageProps?.cropButtonList?.map(btn => ( + + {/* @ts-ignore */} +
{btn.icon} {btn.label}
+
+ ))} +
+
+ )} +
+
+ ) + case 'video': + return ( + // @ts-ignore + + ) + } + } + + // 暴露 ref 实例 + useImperativeHandle(ref, () => ({ + // @ts-ignore + cropperImageRef: cropperImageRef?.current, + videoPlayerRef: videoPlayerRef?.current, + combineImageRef: combineImageRef?.current, + })); + + return ( +
+
+ {topButtonRender} +
+ {showDescription && ( +
+ + {descriptionList.map(descriptions => ( + + {descriptions?.children?.map(item => ( + {item.children} + ))} + + ))} + +
+ )} + +
+ {/* ---------------- view 视图左上角导航按钮 ------------------ */} + {showModeChange && ( +
+ + {viewTopModeButtonList?.map(btn => ( + + {/* @ts-ignore */} + {btn.icon} {btn.label} + + ))} + +
+ )} + {/* --------------------------------- 视频播放模式 --------------------------------- */} + {initMode(type)} + {/* 切换按钮组件 */} + {/* ----------------------------------- 上一张按钮 ---------------------------------- */} + {showNavigation && ( +
+ {/* ----------------------------------- 人脸碰撞组件 ---------------------------------- */} + {isRelated && ( + // @ts-ignore + + )} + {children} +
+ ) +}) + +export default BigImage diff --git a/packages/biz/src/BigImage/components/CombineImage/index.less b/packages/biz/src/BigImage/components/CombineImage/index.less new file mode 100644 index 0000000..3768471 --- /dev/null +++ b/packages/biz/src/BigImage/components/CombineImage/index.less @@ -0,0 +1,3 @@ +.zhst-big-image-combime-image { + background-color: #f7f7f7; +} diff --git a/packages/biz/src/BigImage/components/CombineImage/index.tsx b/packages/biz/src/BigImage/components/CombineImage/index.tsx new file mode 100644 index 0000000..aaef71c --- /dev/null +++ b/packages/biz/src/BigImage/components/CombineImage/index.tsx @@ -0,0 +1,82 @@ + +import React, { FC, useRef, forwardRef, useImperativeHandle } from 'react'; +import { CompareImage, Flex, Progress, ProgressProps, CompareImageProps } from '@zhst/meta' +import './index.less' + +export interface ComBineImageProps { + height?: string | number + data: { + imgSummary: string; + compaterImage: string; + imageKey: string; + score: number; + } + prevDisable?: boolean; + nextDisable?: boolean; + onPre?: () => void; + onNext?: () => void; + openRoll?: boolean + targetImageProps?: CompareImageProps + sourceImageProps?: CompareImageProps +} + +const conicColors: ProgressProps['strokeColor'] = { + '0%': '#42E2AC', + '50%': '#DFAF2E', + '100%': '#F95C55', +}; + +const componentName = 'zhst-big-image-combime-image' + +const ComBineImage: FC = forwardRef((props, ref) => { + const { + height, + data, + prevDisable, + nextDisable, + onNext, + onPre, + openRoll + } = props + const { imgSummary, compaterImage, score } = data + const targetImageRef = useRef(null) + const compareImageRef = useRef(null) + + useImperativeHandle(ref, () => ({ + compareImageRef, + targetImageRef + })); + + return ( + + + + + + ) +}) + +export default ComBineImage diff --git a/packages/biz/src/BigImage/components/navigation/index.less b/packages/biz/src/BigImage/components/navigation/index.less new file mode 100644 index 0000000..46fe9e5 --- /dev/null +++ b/packages/biz/src/BigImage/components/navigation/index.less @@ -0,0 +1,44 @@ +.zhst-image__nav { + position: absolute; + display: flex; + width: 48px; + height: 100%; + flex-shrink: 0; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 0; + + &>button { + & span { + display: flex; + } + } + + :global { + i:hover { + color: #fff !important; + } + } + + &--disable { + :global { + i { + color: #f0f0f0; + cursor: not-allowed !important; + } + } + } + + &--hide { + display: none; + } + + &-prev { + left: 12px; + } + + &-next { + right: 12px; + } +} diff --git a/packages/biz/src/BigImage/components/navigation/index.tsx b/packages/biz/src/BigImage/components/navigation/index.tsx new file mode 100644 index 0000000..43589fc --- /dev/null +++ b/packages/biz/src/BigImage/components/navigation/index.tsx @@ -0,0 +1,40 @@ +// !! 已废弃 +import * as React from 'react'; +import classnames from 'classnames'; +import { Button } from '@zhst/meta'; +import { IconFont } from '@zhst/icon' +import './index.less'; + +const componentName = `zhst-image__nav`; + +const Navigation: React.FC<{ + show?: boolean; + onClick?: React.MouseEventHandler; + prev?: boolean; + next?: boolean; + disabled?: boolean; + className?: string; + color?: string; + hoverColor?: string; +}> = (props) => { + const { show, prev, next, disabled, onClick, className, color } = props; + + return ( +
+ +
+ ); +}; + +export default Navigation; diff --git a/packages/biz/src/BigImage/demo/imgs/photo-1503185912284-5271ff81b9a8.webp b/packages/biz/src/BigImage/demo/imgs/photo-1503185912284-5271ff81b9a8.webp new file mode 100644 index 0000000..c628fe9 Binary files /dev/null and b/packages/biz/src/BigImage/demo/imgs/photo-1503185912284-5271ff81b9a8.webp differ diff --git a/packages/biz/src/BigImage/demo/index.tsx b/packages/biz/src/BigImage/demo/index.tsx new file mode 100644 index 0000000..45c37ed --- /dev/null +++ b/packages/biz/src/BigImage/demo/index.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { BigImage } from '@zhst/biz' +import { Space, Switch } from '@zhst/meta' +import { pick, get } from '@zhst/func' +import { BIG_IMAGE_DATA, attributeList } from '../mock' +import Img from './imgs/photo-1503185912284-5271ff81b9a8.webp' + +const BigModal = (props: any) => { + const { + } = props + const [dataSource, setDataSource] = useState(BIG_IMAGE_DATA) + const [showDesc, setShowDesc] = useState(true) + const [type, setType] = useState('normal') + const modalRef = useRef(null) + + return ( +
+ + 显示属性: setShowDesc(pre => !pre)} /> + + setType(newVal === '1'? 'normal': 'compater')} + // ------------ 属性列表 ----------------- + showDescription={showDesc} + descriptionList={attributeList} + // ------------ 图片/视频切换 ----------------- + viewTopModeButtonList={[ + { + key: 'image', + label: '图片' + }, + { + key: 'video', + label: '视频' + } + ]} + modeButtonGroupProps={{ + defaultValue: 'image', + onChange: e => console.log('模式切换', e) + }} + // ------------ 导航功能 ----------------- + showNavigation + onPrevButtonClick={val => console.log('pre', val)} + onNextButtonClick={val => console.log('next', val)} + // ------------ 场景图功能 ----------------- + cropperImageProps={{ + url: Img, + score: 50, + odList: get(dataSource, 'odRect', []), + attachImageData: get(dataSource, 'attachImg', []), + }} + // ------------ 对比图模式 ----------------- + combineImageProps={{ + data: pick(dataSource, 'compaterImage', 'imgSummary', 'imageKey', 'score'), + }} + // ------------ 视频模块 ----------------- + videoProps={{ + url: get(dataSource, 'flvUrl', '') + }} + > + +
+ ) +} + +export default BigModal diff --git a/packages/biz/src/BigImage/demo/oldData.tsx b/packages/biz/src/BigImage/demo/oldData.tsx new file mode 100644 index 0000000..364345e --- /dev/null +++ b/packages/biz/src/BigImage/demo/oldData.tsx @@ -0,0 +1,128 @@ +// @ts-nocheck +import React, { useState } from 'react'; +import { BigImageModal } from '@zhst/biz' +import { Button, DescriptionsProps } from '@zhst/meta' +import { IMAGE_DATA, BIG_IMAGE_DATA } from '../mock' +import bigImageModalAdapter from '../util/bigImageModalAdapter' +import { get } from '@zhst/func'; + +const descriptionList: DescriptionsProps['items'] = [ + { + title: '人员属性', + children: [ + { + key: '1', + label: '性别', + children: '男', + }, + { + key: '2', + label: '年龄', + children: '成年', + }, + { + key: '3', + label: '帽子', + children: '无', + }, + { + key: '4', + label: '上身颜色', + children: '灰', + }, + { + key: '5', + label: '下身颜色', + children: '蓝色', + }, + { + key: '6', + label: '附着物', + children: '无', + }, + { + key: '7', + label: '骑行', + children: '否', + }, + ] + } +]; + +// 适配器,适配老接口 +const NewImageModal = bigImageModalAdapter(BigImageModal, { + oldMode: true +}) + +const BigModal = (props) => { + const { + onClose, + isArchiveDetail = false, + specialTitle = '对比图2', + transformPropFunc, + screenshotButtonRender, + showLowFaceTip = false + } = props + const [visible, setVisible] = useState(false) + const [selectIndex, setSelectIndex] = useState(0) + const [dataSource, setDataSource] = useState(IMAGE_DATA.dataSource) + const [dataSources, setDataSources] = useState(IMAGE_DATA.dataSource) + const [selectItem, setSelectItem] = useState({}) + + return ( +
+ + onClose} + descriptionConfig={{ data: descriptionList }} + visible={visible} + isArchiveDetail={isArchiveDetail} + ToolProps={{ + // renderLeft: leftOperateBar({ disableBtn, onActionClick: onBigImageActionClick }), + // renderRight: rightOperateBar({ + // disableBtn, + // onActionClick: onBigImageActionClick, + // isArchiveDetail, + // }), + // renderVideoBtn: !disableBtn.includes(OPT['PLAY_VIDEO']), + // disableVideo: disableVideo, + }} + selectIndex={selectIndex} + onSelectIndexChange={(index: number) => { + index > 0 && index < dataSources.length && setSelectIndex(index); + }} + // tabsFilter={tabsFilter} + specialTitle={specialTitle} + transformPropFunc={async (item: any) => { + let bigImageInfo = !!transformPropFunc && (await transformPropFunc(item)); + setSelectItem({ ...bigImageInfo }); + return { ...bigImageInfo }; + }} + screenshotButtonRender={screenshotButtonRender} + //@ts-ignore + transformVideoPropFunc={async (item) => { + const { maxDuration: duration = 20 } = item || {}; + const time = get(item, 'timestamp'); + const cameraId = get(item, 'cameraId'); + const { url: flvUrl } = { + url: 'url', + downloadUrl: 'url', + }; + return { + flvUrl, + maxDuration: duration, + }; + }} + nullDialogProp={{ + emptyText: showLowFaceTip ? '目标图人脸质量较低,暂无聚类数据' : '暂无数据', + }} + /> +
+ ) +} + +export default BigModal diff --git a/packages/biz/src/BigImage/demo/withEdit.tsx b/packages/biz/src/BigImage/demo/withEdit.tsx new file mode 100644 index 0000000..0c0bb4d --- /dev/null +++ b/packages/biz/src/BigImage/demo/withEdit.tsx @@ -0,0 +1,89 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { BigImage } from '@zhst/biz' +import { Space, Switch, Button } from '@zhst/meta' +import { pick, get } from '@zhst/func' +import { BIG_IMAGE_DATA, attributeList } from '../mock' +import Img from './imgs/photo-1503185912284-5271ff81b9a8.webp' + +const testOd = [ + { + "id": "456", + "x": 0.58543766, + "y": 0.3203356, + "w": 0.052037954, + "h": 0.2664015 + } +] + +const BigModal = (props: any) => { + const { + } = props + const [dataSource, setDataSource] = useState(BIG_IMAGE_DATA) + const [showDesc, setShowDesc] = useState(true) + const [editAble, setEditAble] = useState(false) + const [odList, setOdList] = useState(get(dataSource, 'odRect', [])) + const [type, setType] = useState('normal') + const bigImageRef = useRef(null) + + return ( +
+ + 显示属性: setShowDesc(pre => !pre)} /> + 打开编辑模式: setEditAble(pre => !pre)} /> + + + setType(newVal === '1'? 'normal': 'compater')} + // ------------ 属性列表 ----------------- + showDescription={showDesc} + descriptionList={attributeList} + // ------------ 图片/视频切换 ----------------- + viewTopModeButtonList={[ + { + key: 'image', + label: '图片' + }, + { + key: 'video', + label: '视频' + } + ]} + modeButtonGroupProps={{ + defaultValue: 'image', + onChange: e => console.log('模式切换', e) + }} + // ------------ 导航功能 ----------------- + showNavigation + onPrevButtonClick={val => console.log('pre', val)} + onNextButtonClick={val => console.log('next', val)} + // ------------ 场景图功能 ----------------- + cropperImageProps={{ + editAble, + url: Img, + score: 50, + odList: odList, + showEditTools: editAble, + attachImageData: get(dataSource, 'attachImg', []), + onCropperTypeChange: v => console.log('框选模式', v), + onExitEdit: () => setEditAble(pre => !pre) + }} + // ------------ 对比图模式 ----------------- + combineImageProps={{ + data: pick(dataSource, 'compaterImage', 'imgSummary', 'imageKey', 'score'), + }} + // ------------ 视频模块 ----------------- + videoProps={{ + url: get(dataSource, 'flvUrl', '') + }} + > + +
+ ) +} + +export default BigModal diff --git a/packages/biz/src/BigImage/demo/withRelatedImage.tsx b/packages/biz/src/BigImage/demo/withRelatedImage.tsx new file mode 100644 index 0000000..7f9b2d1 --- /dev/null +++ b/packages/biz/src/BigImage/demo/withRelatedImage.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { BigImage } from '@zhst/biz' +import { Button, Space, Switch } from '@zhst/meta' +import { pick, get } from '@zhst/func' +import { BIG_IMAGE_DATA, attributeList, RELATED_IMAGES } from '../mock' + +const BigModal = (props: any) => { + const { + } = props + const [visible, setVisible] = useState(true) + const [dataSource, setDataSource] = useState(BIG_IMAGE_DATA) + const [selectedItemKey, setSelectedItemKey] = useState() + const [showFaceModel, setShowFaceModel] = useState(true) + const [type, setType] = useState('normal') + const modalRef = useRef(null) + + return ( +
+ + 显示人脸碰撞模型: setShowFaceModel(pre => !pre)} /> + + setVisible(false)} + showModeChange + onTabChange={(newVal, oldVal) => setType(newVal === '1'? 'normal': 'compater')} + // ------------ 图片/视频切换 ----------------- + viewTopModeButtonList={[ + { + key: 'image', + label: '图片' + }, + { + key: 'video', + label: '视频' + } + ]} + modeButtonGroupProps={{ + defaultValue: 'image', + onChange: e => console.log('模式切换', e) + }} + // ------------ 场景图功能 ----------------- + cropperImageProps={{ + url: "https://gw.alipayobjects.com/zos/antfincdn/LlvErxo8H9/photo-1503185912284-5271ff81b9a8.webp", + score: 50, + odList: get(dataSource, 'odRect', []), + attachImageData: get(dataSource, 'attachImg', []), + }} + // ------------ 对比图模式 ----------------- + combineImageProps={{ + data: pick(dataSource, 'compaterImage', 'imgSummary', 'imageKey', 'score'), + }} + // ------------ 视频模块 ----------------- + videoProps={{ + url: get(dataSource, 'flvUrl', '') + }} + // ------------ 人脸碰撞模型 ----------------- + isRelated={showFaceModel} + relatedImageProps={{ + activeTab: 'related', + selectedItemKey, + data: RELATED_IMAGES, + onCancel: () => console.log('取消关联'), + onConnect: () => console.log('关联'), + onTabChange: (newVal, oldVal) => console.log('tab切换', newVal, oldVal), + onItemSelected: (item) => setSelectedItemKey(item.key) + }} + > + +
+ ) +} + +export default BigModal diff --git a/packages/biz/src/BigImage/images/emptyImage.png b/packages/biz/src/BigImage/images/emptyImage.png new file mode 100644 index 0000000..9762957 Binary files /dev/null and b/packages/biz/src/BigImage/images/emptyImage.png differ diff --git a/packages/biz/src/BigImage/images/percent_background.png b/packages/biz/src/BigImage/images/percent_background.png new file mode 100644 index 0000000..ebde317 Binary files /dev/null and b/packages/biz/src/BigImage/images/percent_background.png differ diff --git a/packages/biz/src/BigImage/index.less b/packages/biz/src/BigImage/index.less new file mode 100644 index 0000000..0737bce --- /dev/null +++ b/packages/biz/src/BigImage/index.less @@ -0,0 +1,132 @@ +.zhst-big-image { + .zhst-dialog-content { + box-shadow: 0 4px 12px rgb(0 0 0 / 20%); + } + + .zhst-tabs .zhst-tabs-nav-wrap { + background-color: #f6f6f6; + } + + &-view { + &-btns { + margin-bottom: 16px; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + } + &-desc { + margin-bottom: 16px; + padding: 16px 16px 0 16px; + background-color: #f7f7f7; + .zhst-descriptions-header { + margin-bottom: 8px; + } + .zhst-descriptions-title { + font-size: 14px; + } + } + // ------------ tab ----------------- + .zhst-tabs-nav { + margin-bottom: 8px; + .zhst-tabs-tab { + &:not(:first-child) { + margin-left: 24px; + } + padding: 0; + padding-bottom: 4px; + } + &::before { + display: none; + } + } + &-container { + position: relative; + min-height: 440px; + width: 100%; + margin-bottom: 16px; + font-size: 0; + &-modeNav { + padding: 2px; + position: absolute; + top: 4px; + left: 4px; + z-index: 10; + border-radius: 4px; + } + &__nav { + position: absolute; + z-index: 99; + top: 50%; + width: 40px !important; + height: 40px !important; + background: #d9d9d9; + border-radius: 100%; + cursor: pointer; + transform: translateY(-50%); + + &>button { + display: flex; + align-items: center; + color: #fff !important; + } + + &--disabled { + opacity: 0.3; + + &>button { + color: #fff !important; + } + } + } + + &__nav:hover { + background: #09f; + color: #fff !important; + } + // ------------ 导航 ----------------- + &-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + background-color: rgba(255, 255, 255, 0.8); + &:hover { + opacity: 0.8; + background-color: rgba(255, 255, 255, 0.8)!important; + } + &_left { + left: 8px; + } + &_right { + right: 8px; + } + } + } + // ------------ 场景图 ----------------- + &-cropper-btn { + position: absolute; + top: 4px; + right: 4px; + &_close { + margin-left: 4px; + vertical-align: top; + } + &-group { + .zhst-radio-button-wrapper { + display: inline-flex; + font-size: 12px; + color: #191919; + background-color: rgba(255, 255, 255, 0.8) + } + &-radio { + display: inline-flex; + align-items: center; + .anticon { + margin-right: 4px; + } + } + } + } + } +} + diff --git a/packages/biz/src/BigImage/index.md b/packages/biz/src/BigImage/index.md new file mode 100644 index 0000000..35f72a4 --- /dev/null +++ b/packages/biz/src/BigImage/index.md @@ -0,0 +1,96 @@ +--- +group: 进阶组件 +category: Components +subtitle: 大图组件 +toc: content +title: BigImage 大图组件 +--- + +## 大图弹框 + +基本 +人脸碰撞模型 +编辑模式 + +### API + +| 参数 | 说明 | 类型 | 默认值 | 版本 | +| --- | --- | --- | --- | --- | +| type | 当前模式 | 'compater'、'normal'、'video' | - | | +| viewHeight | 视图高度 | string、number | - | | +| width | 宽度 | string、number | - | | +| showDescription | 描述列表显示\隐藏 | boolean | false | | +| descriptionsProps | 描述列表透传 | | antd - DescriptionsProps | | +| descriptionList | 描述列表数据(见下文) | | IDescriptionList | | +| topButtonRender | 顶部按钮 | | ReactNode、string | | +| customTabBarExtraContent | 自定义tab尾部导航插槽 | | ReactNode、 string | | +| onTabChange | tab事件监听 | | antd - TabsProps['onChange'] | | +| tabProps | tab透传 | | antd - TabsProps | | +| showModeChange | 是否显示模式切换按钮 | | boolean | | +| viewTopModeButtonList | 模式切换按钮列表 | | TypeRadio[] | | +| modeButtonGroupProps | 模式切换按钮组透传 | RadioGroupProps | - | | +| isRelated | 人脸碰撞模型显示\隐藏 | boolean | | | +| relatedImageProps | 人脸碰撞模型透传 | zhst/meta - RelatedImageProps | | | +| cropperImageProps | 场景图模式透传 | ICropperImageProps | | | +| combineImageProps | 对比图模式透传 | ComBineImageProps | | | +| videoProps | 视频模式透传 | videoProps | | | +| showNavigation | 是否展示导航 | boolean | | | +| prevButtonProps | 前翻箭头透传 | prevButtonProps | | | +| onPrevButtonClick | 前翻箭头点击事件 | () => void; | | | +| nextButtonProps | 下翻箭头透传 | () => void; | | | +| onNextButtonClick | 下翻箭头点击事件 | () => void; | | | +| children | | ReactNode | | | + +### IDescriptionList + +```ts +interface IDescriptionList { + title: string; + showTitle?: boolean; + props?: DescriptionsProps + children: DescriptionsProps['items'] +}[] +``` + +### + +```ts +interface ICropperImageProps extends CropperImageProps { + showEditTools?: boolean // 是否展示编辑按钮 + editAble?: boolean // 是否开启编辑模式 + score?: string | number // 分数 + btnGroupProps?: BtnGroupProps; // crop 场景图模式下的按钮拓展 + cropButtonList?: TypeRadio[] // 编辑按钮列表 + onCropperTypeChange?: (type: RadioProps['onChange']) => void + onExitEdit?: ButtonProps['onClick'] // 退出编辑模式 + attachImageData?: AttachImageProps['data'] // 左下角预览图 + attachImageProps?: AttachImageProps // 左下角预览图透传 +} +``` + +## 设计方案 + +结合当下的业务场景,目前大图组件有三种模式 + +1. 场景图模式 + - +2. 对比图模式 +3. 视频模式 + +场景图和视频模式,支持用户编辑圈选 + +三种模式状态下,都会有外层模块的嵌套,目前有以下几种: + +1. 描述模块 +2. 顶部拓展 + - 目前仅支持自定义 + - 默认下边间距 16px +3. tabs 切换 + - 默认下间距:16px + - 支持自定义文案 + - 支持自定义数量 + - 支持后方插槽 +4. 人脸碰撞模型 + - 支持用户自定义传入数据 + +本来想通过插件的形式按需加载 diff --git a/packages/biz/src/BigImage/index.tsx b/packages/biz/src/BigImage/index.tsx new file mode 100644 index 0000000..0175f85 --- /dev/null +++ b/packages/biz/src/BigImage/index.tsx @@ -0,0 +1,5 @@ +import BigImage from "./BigImage"; + +export type { BigImageProps, BigImageRef } from './BigImage' + +export default BigImage diff --git a/packages/biz/src/BigImage/interface.ts b/packages/biz/src/BigImage/interface.ts new file mode 100644 index 0000000..c98d3cc --- /dev/null +++ b/packages/biz/src/BigImage/interface.ts @@ -0,0 +1,84 @@ +import { ReactNode } from 'react' +import { + ButtonProps, + RadioProps, + RadioGroupProps, + VideoViewProps, + DescriptionsProps, + TabsProps, + RelatedImageProps, + BtnGroupProps, + CropperImageProps, + VideoViewRef, + AttachImageProps +} from '@zhst/meta' +import { ComBineImageProps } from './components/CombineImage' + +export type TypeRadio = { + label?: string; + key: string; + tooltipTxt?: string; + onClick?: ButtonProps['onClick'] + icon?: ReactNode | string; + props?: ButtonProps +} + +type TypePlugin = 'compater' | 'normal' | 'video' | 'faceMode' + +export interface BigImageProps { + type?: TypePlugin // 当前 tab + viewHeight?: string | number; + width?: string | number + typePlugins?: TypePlugin[] // TODO: 开启插件类型 + // ------------ 描述列表 ----------------- + showDescription?: boolean; + descriptionsProps?: DescriptionsProps + descriptionList?: { + title: string; + showTitle?: boolean; + props?: DescriptionsProps + children: DescriptionsProps['items'] + }[] + // ------------------ 顶部按钮列表 + topButtonRender?: ReactNode | string + // ---------------- Tabs 导航 ------------------ + customTabBarExtraContent?: string | ReactNode + onTabChange?: TabsProps['onChange'] + tabProps?: TabsProps + // ------------ 图片 | 视频切换导航 ----------------- + showModeChange?: boolean + viewTopModeButtonList?: TypeRadio[] + modeButtonGroupProps?: RadioGroupProps + // ----------------- 人脸碰转 ----------------- + isRelated?: boolean // 人脸碰撞功能打开 + relatedImageProps?: RelatedImageProps + // -------------------------- crop 场景图模式 ----------------------- + cropperImageProps?: CropperImageProps & { + showEditTools?: boolean + editAble?: boolean + score?: string | number + btnGroupProps?: BtnGroupProps; // crop 场景图模式下的按钮拓展 + cropButtonList?: TypeRadio[] + onCropperTypeChange?: (type: RadioProps['onChange']) => void + onExitEdit?: ButtonProps['onClick'] + attachImageData?: AttachImageProps['data'] + attachImageProps?: AttachImageProps + } + // -------------------- 对比图模式 ------------------------- + combineImageProps?: ComBineImageProps + // ------------ 导航 ----------------- + showNavigation?: boolean // 是否展示导航箭头 + prevButtonProps?: any; + onPrevButtonClick?: () => void; + nextButtonProps?: any + onNextButtonClick?: () => void; + theme?: any + children?: React.ReactNode + // ------------ 视频模式 ----------------- + videoProps?: VideoViewProps +} + +export interface BigImageRef { + videoPlayerRef: VideoViewRef + combineImageRef: any +} diff --git a/packages/biz/src/BigImage/mock.ts b/packages/biz/src/BigImage/mock.ts new file mode 100644 index 0000000..1d31763 --- /dev/null +++ b/packages/biz/src/BigImage/mock.ts @@ -0,0 +1,292 @@ +import imageUrl from './demo/imgs/photo-1503185912284-5271ff81b9a8.webp' + +export const IMAGE_DATA = { + "enAbleDeleteFeature": true, + "tabsFilter": [ + "COMPATER", + "NORMAL" + ], + "selectIndex": 4, + "disableBtn": [ + 0, + 1, + 4, + 20 + ], + "dataSource": { + "objectId": "1742110565582518272", + "condition": { + "featureInfo": null, + "featureData": "AAAAAAAAAAAAAAAAAAAAAAA==", + "imageData": "", + "alg": "VERSION_REID_HEAD_ATTR", + "rect": { + "x": 0.271875, + "y": 0.32222223, + "w": 0.2859375, + "h": 0.67777777 + }, + "objectImageUrl": "singer-20240102/1/129529/1742047651878156288.jpg", + "srcImageUrl": "singer-20240102/1/129529/1742047652511496192.jpg" + }, + "score": 0.7163062, + "timestamp": 1704186491979, + "deviceId": "129533", + "id": "129533", + "name": "4楼门口过道人脸", + "dirid": "0", + "status": "1", + "longitude": 120.125, + "latitude": 30.280500411987305, + "caseId": "0", + "caseGroup": "", + "isDeleted": "DEVICEMANAGER_BOOL_DEFAULT", + "objectIndex": { + "objectId": "1742110565582518272", + "solutionId": "1", + "deviceId": "129533", + "fragmentId": "0" + }, + "objectType": "OBJECT_TYPE_PEDESTRAIN", + "isObjectTrack": true, + "pathId": "1742110532019697664", + "frameInfo": { + "frameId": "0", + "frameTimestamp": "1704186491979", + "width": 0, + "height": 0, + "originWidth": 1920, + "originHeight": 1080, + "offsetTime": "24714687", + "skipNumber": "0" + }, + "level": 1, + "bboxInFrame": { + "x": 0.603125, + "y": 0.3314815, + "w": 0.0578125, + "h": 0.2712963 + }, + "bboxExtInFrame": { + "x": 0.546875, + "y": 0.2638889, + "w": 0.17135416, + "h": 0.40648147 + }, + "objectImageKey": "", + "objectExtImageKey": "http://10.0.0.7:30003/file/singer-20240102/1/129533/1742110565582518272.jpg", + "frameImageKey": "http://10.0.0.7:30003/file/singer-20240102/1/129533/1742110565603489792.jpg", + "confidence": 0.817271, + "sourceObjectId": "1742110565603489792", + "storeTimestamp": "0", + "gbNumber": "", + "qualityScore": 0, + "subObjectCount": 1, + "subObjectType": [ + "OBJECT_TYPE_FACE" + ], + "subObjectIds": [ + "1742110532015503360" + ], + "solutionId": "1", + "fragmentId": "0", + "contrastKey": "singer-20240102/1/129533/1742110565582518272.jpg", + "compaterImages": [ + "http://10.0.0.7:30003/file/singer-20240102/1/129529/1742047651878156288.jpg" + ], + "imgSummary": "singer-20240102/1/129533/1742110565582518272.jpg", + "imageKey": "http://10.0.0.7:30003/file/singer-20240102/1/129533/1742110565582518272.jpg", + "srcImageUrl": "http://10.0.0.7:30003/file/singer-20240102/1/129533/1742110565603489792.jpg", + "algorithmVersion": "VERSION_REID_HEAD_ATTR", + "cameraId": "129533", + "cameraName": "4楼门口过道人脸" + }, + "isArchiveDetail": false, + "ToolProps": { + "renderVideoBtn": true, + "disableVideo": false + }, + "specialTitle": "" +} + +export const RELATED_IMAGES = [ + { key: '123', url: imageUrl }, + { key: '22', url: imageUrl }, + { key: '22122333', url: imageUrl }, + { key: '2212243', url: imageUrl }, + { key: '224523433', url: imageUrl }, + { key: '224235453', url: imageUrl }, + { key: '245423', url: imageUrl }, + { key: '224233543', url: imageUrl }, + { key: '22452343', url: imageUrl }, + { key: '22323243', url: imageUrl }, + { key: '2236456', url: imageUrl }, + { key: '224563', url: imageUrl }, + { key: '24565423', url: imageUrl }, + { key: '245645623', url: imageUrl }, + { key: '2456435623', url: imageUrl }, + { key: '2323', url: imageUrl } +] + +export const BIG_IMAGE_DATA = { + imageKey: imageUrl, + imgSummary: imageUrl, + flvUrl: 'ws://10.0.0.120:9033/flv/HaikangNvr/45.flv?ip=10.0.2.103&stime=1712539148&etime=1712539168', + compaterImage: imageUrl, + odRect: [ + { + id: '123', + "x":0.5445312, + "y":0.19166666, + "w":0.08671875, + "h":0.40138888 + }, + { + "id": "123", + "x": 0.5519352, + "y": 0.2965385, + "w": 0.05185461, + "h": 0.24698898, + }, + { + "id": "456", + "x": 0.58543766, + "y": 0.3203356, + "w": 0.052037954, + "h": 0.2664015 + } + ], + attachImg: [ + { + "url": imageUrl, + "label": "形体" + },{ + "url": imageUrl, + "label": "人脸" + } + ], + score: 60, // 人脸质量分 + showScore: true, // 人脸质量分 + cameraPosition: 'string', // 摄像头位置 + time: '2022-01-01', // 摄像头拍摄时间 + objects: [ + { + "objectIndex": { + "objectId": "1746832189053474816", + "solutionId": "0", + "deviceId": "0", + "fragmentId": "0" + }, + "objectType": "OBJECT_TYPE_PEDESTRAIN", + "sourceObjectId": "0", + "level": 0, + "confidence": 0.881164, + "frameInfo": { + "frameId": "0", + "frameTimestamp": "1705312223057", + "width": 0, + "height": 0, + "originWidth": 0, + "originHeight": 0, + "offsetTime": "0", + "skipNumber": "0" + }, + "infoOnSource": { + "bboxInFrame": { + "bboxRatio": { + "x": 0.61418945, + "y": 0.34309354, + "w": 0.067661405, + "h": 0.34659258 + }, + }, + "countInSource": 0, + "indexInSource": 0 + }, + "qualityScore": 0, + } + ] +} + +export const attributeList = [ + { + title: '人员属性', + children: [ + { + key: '1', + label: '性别', + children: '男', + }, + { + key: '2', + label: '年龄', + children: '成年', + }, + { + key: '3', + label: '帽子', + children: '无', + }, + { + key: '4', + label: '上身颜色', + children: '灰', + }, + { + key: '5', + label: '下身颜色', + children: '蓝色', + }, + { + key: '6', + label: '附着物', + children: '无', + }, + { + key: '7', + label: '骑行', + children: '否', + }, + ] + }, + { + title: '社区规范', + children: [ + { + key: '1', + label: '性别', + children: '男', + }, + { + key: '2', + label: '年龄', + children: '成年', + }, + { + key: '3', + label: '帽子', + children: '无', + }, + { + key: '4', + label: '上身颜色', + children: '灰', + }, + { + key: '5', + label: '下身颜色', + children: '蓝色', + }, + { + key: '6', + label: '附着物', + children: '无', + }, + { + key: '7', + label: '骑行', + children: '否', + }, + ] + } +]; diff --git a/packages/biz/src/BigImage/util/bigImageModalAdapter.tsx b/packages/biz/src/BigImage/util/bigImageModalAdapter.tsx new file mode 100644 index 0000000..c341455 --- /dev/null +++ b/packages/biz/src/BigImage/util/bigImageModalAdapter.tsx @@ -0,0 +1,195 @@ +/** + * 适配老的大屏组件数据格式传入 + */ +import React, { } from 'react'; +import { AlgorithmVersionStr, HumanProperty, ObjectType, Rect, IScreenshotButtonProp } from '@zhst/types' +import { VideoViewProps, ImgViewProps, VideoViewRef, ImgViewRef } from '@zhst/meta' + +export type TAB_TYPE = 'COMPATER' | 'NORMAL' | 'TRACK'; +export type MODEL_TYPE = 'VIDEO' | 'IMAGE'; + +export interface CarouselProps { + hasPre?: boolean; + hasNext?: boolean; + selectIndex: number; + setSelectIndex: React.Dispatch>; + dataSource: Array<{ + key: string; + url: string; + }>; +} + +export type ISelectItem = Partial> & + Partial>; + +/** + * 描述列表 description + */ +export interface HeaderProps { + value: TAB_TYPE; + onChange: (type: TAB_TYPE) => void; + tabsFilter: TAB_TYPE[]; +} + +export interface ParamProps { + tab: string; + selectItem: ISelectItem; + imgViewRef: React.MutableRefObject; + VideoViewRef: React.MutableRefObject; + model: MODEL_TYPE; + setModel: React.Dispatch>; + /* 可观测值 */ + scale$: number; + showCrop$: boolean; +} + +/** + * 工具栏 + */ +export interface ToolProps { + renderRight?: (props: ParamProps) => React.ReactNode; + renderLeft?: (props: ParamProps) => React.ReactNode; + renderVideoBtn?: boolean; + param: ParamProps; + disableVideo: boolean; +} + + +export interface BigImageData { + //imageKey 小图 + extendRectList: (Rect & { algorithmVersion: AlgorithmVersionStr; imageKey: string })[]; + rectList: (Rect & { algorithmVersion: AlgorithmVersionStr; imageKey: string })[]; + attachImg: { url: string; label: '形体' | '人脸' }[]; + odRect: Rect; + compaterImages: string[] // 目标图列表 + constractKey: string; // 当前比较中的目标图 + frameImageKey: string; // 场景图 + imageKey?: string; // 大图 + imgSummary: string; // 摘要图 + objectExtImageKey: string; //比对到的目标图扩展图 === imgSummary + + attributeList: { label: string; list: any[] }[]; + archiveImages?: any; + spaceName: string; + + objectIndex?: { + deviceId: string; + fragmentId: string; + objectId: string; + solutionId: string; + } + + objectType: ObjectType; + objectId: string; //这张摘要本身的Id + bodyObjectId?: string; + faceObjectId?: string; //这张摘要下的人脸Id(如果有) + sourceObjectId?: string; //这张摘要上游的形体Id(如果有) + cameraId: string; + cameraName: string; + selectIndex: number; + humanProperty: HumanProperty; + qualityScore?: number; //人脸质量分 + score: number; // 相似度 + timestamp: string; + bodyImageUrl: string; + faceImageUrl: string; + algorithmVersion: AlgorithmVersionStr; + + bodySpaceName: string; + faceSpaceName: string; + position: { + lat: number + lng: number + } + + solutionId?: string; + [index: string]: any; +} + + +interface IOldImageData { + visible?: boolean; // 显示隐藏弹框 + defaultModel?: MODEL_TYPE; // 视频模式 | 图片模式 + onClose?: () => void; // 关闭弹框 + isLoading?: boolean; // 是否加载中 + hasPre?: boolean; // 向前翻页 + hasNext?: boolean; // 向后翻页 + selectIndex?: number; // 选中的数据(dataSource为数组情况下) + onSelectIndexChange?: (i: number) => void; // 修改当前下标 + dataSource: BigImageData[]; // 数据1 + dataSources: BigImageData[]; // 数据2 + relatedData?: BigImageData[]; // 数据3 + transformPropFunc: (item: any) => ISelectItem; // 格式化数据方法 + transformVideoPropFunc: ( + item: ISelectItem + ) => Promise>; // 视频模式格式化数据方法 + screenshotButtonRender?: (screenshotButtonProp: IScreenshotButtonProp) => React.ReactElement; + showTool?: boolean; // 是否显示底部菜单 + showCarousel?: boolean; // + imgViewProp?: Partial; // 图片模式的配置 + videoViewProp?: Partial; // 视频模式的配置 + ToolProps?: Partial; // 底部菜单的配置 + nullDialogProp?: { + emptyText?: string; + }; // 暂无数据的配置 + showHeader?: boolean; // 是否显示 description + tabsFilter?: TAB_TYPE[]; // tabs 过滤 + useVirtual?: boolean; // 是否显示虚拟 + loadNext?: (i: number) => Promise; // 下一个 + loadPre?: (i: number) => Promise; // 前一个 + children: React.ReactNode; // 子元素 + title?: string; // 标题 + specialTitle?: string; // 对比图模式下标题 + isRelated?: boolean; + carouselProp?: Partial; +} + + +export interface ImageModalDataProps { + targetData: BigImageData[] + compactData: BigImageData[] +} + +export interface ModalAdapterConfigProps { + oldMode?: boolean; // 是否是老模式 +} + +/** + * 兼容老数据格式 + * @param _data 老数据格式 + * @returns newData + */ +const translateOldImageData = (_data: IOldImageData) => { + return { + ..._data, + open: _data.visible, + onCancel: _data.onClose + } +} + +/** + * 大图组件适配器,兼容老接口 + * @param Cmp 大图组件 + * @param config 额外配置 + * @returns 大图组件 + */ +const adapter = (Cmp: any, config: ModalAdapterConfigProps): any => { + const { oldMode = false } = config + + return (props: IOldImageData) => { + const newProps = oldMode ? translateOldImageData(props) : props + console.log('adapter----适配数据', props, newProps) + + // 该属性已经废弃 + delete newProps.visible + + return ( + + ) + } +} + + +export default adapter diff --git a/packages/biz/src/BigImage/util/interface.ts b/packages/biz/src/BigImage/util/interface.ts new file mode 100644 index 0000000..393119f --- /dev/null +++ b/packages/biz/src/BigImage/util/interface.ts @@ -0,0 +1,36 @@ +export interface IBigImageModalData { + imageKey?: string // 目标图 + imgSummary?: string // 大图 + flvUrl?: string // 视频链接 + compaterImages?: string[] // 对比图 + odRect?: { // od 框数据 + "x": number + "y": number + "w": number + "h": number + [key: string]: string | number; // 拓展参数 + }[], + attachImg?: { // 小图,只有在场景图模式生效(人脸、形体) + "url": string + "label": string + [key: string]: string + }[], + score?: number | string // 人脸质量分 + showScore?: boolean // 人脸质量分 + cameraPosition?: string // 摄像头位置 + time?: string // 摄像头拍摄时间 + objects: { // 拓展参数、可以自由支配 + objectIndex: { + [key: string]: any + }, + objectType: string + sourceObjectId: string + level: number + confidence: number + infoOnSource: { + [key: string]: any + }, + qualityScore: number + [key: string]: any + }[] +} diff --git a/packages/biz/src/index.tsx b/packages/biz/src/index.tsx index a07df83..b880f8e 100644 --- a/packages/biz/src/index.tsx +++ b/packages/biz/src/index.tsx @@ -1,5 +1,7 @@ export { default as BigImageModal } from './BigImageModal' export type { BigImageModalProps } from './BigImageModal' +export { default as BigImage } from './BigImage' +export type { BigImageProps, BigImageRef } from './BigImage' export { default as BoxSelectTree } from './boxSelectTree' export type { BoxSelectTreeProps } from './boxSelectTree' export { default as Tree } from './tree' diff --git a/packages/hooks/es/useSocket/index.d.ts b/packages/hooks/es/useSocket/index.d.ts index cb0ff5c..e69de29 100644 --- a/packages/hooks/es/useSocket/index.d.ts +++ b/packages/hooks/es/useSocket/index.d.ts @@ -1 +0,0 @@ -export {}; diff --git a/packages/hooks/lib/useSocket/index.d.ts b/packages/hooks/lib/useSocket/index.d.ts index cb0ff5c..e69de29 100644 --- a/packages/hooks/lib/useSocket/index.d.ts +++ b/packages/hooks/lib/useSocket/index.d.ts @@ -1 +0,0 @@ -export {}; diff --git a/packages/icon/.fatherrc.ts b/packages/icon/.fatherrc.ts index 447d06b..b0341a2 100644 --- a/packages/icon/.fatherrc.ts +++ b/packages/icon/.fatherrc.ts @@ -1,13 +1,16 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md esm: { output: 'es', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, cjs: { output: 'lib', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, + plugins: ['father-plugin-less'], }); diff --git a/packages/icon/es/index.less b/packages/icon/es/index.less deleted file mode 100644 index 23f5dce..0000000 --- a/packages/icon/es/index.less +++ /dev/null @@ -1,3 +0,0 @@ -.icon:hover { - color: #6accca !important; -} diff --git a/packages/map/.fatherrc.ts b/packages/map/.fatherrc.ts index 447d06b..b0341a2 100644 --- a/packages/map/.fatherrc.ts +++ b/packages/map/.fatherrc.ts @@ -1,13 +1,16 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md esm: { output: 'es', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, cjs: { output: 'lib', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, + plugins: ['father-plugin-less'], }); diff --git a/packages/map/src/drawControl/DrawControl.tsx b/packages/map/src/drawControl/DrawControl.tsx index 7e2bbfe..2cbcf3e 100644 --- a/packages/map/src/drawControl/DrawControl.tsx +++ b/packages/map/src/drawControl/DrawControl.tsx @@ -1,7 +1,7 @@ /** * Created by jiangzhixiong on 2024/05/21 */ -import { forwardRef, useImperativeHandle, useRef, } from 'react' +import { forwardRef, useImperativeHandle, useRef, } from 'react' import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { DragCircleMode, @@ -14,12 +14,11 @@ import drawRectMode from 'mapbox-gl-draw-rectangle-mode' // @ts-ignore import drawStaticMode from '@mapbox/mapbox-gl-draw-static-mode' // @ts-ignore -import drawCircleMode from './Draw/drawCircleMode.draw.js' +import drawCircleMode from './mode/drawCircleMode.draw.js' import { useControl } from 'react-map-gl'; import type { ControlPosition } from 'react-map-gl'; -import { MapContextValue } from 'react-map-gl/dist/esm/components/map'; -export type DrawControlProps = ConstructorParameters[0] & { +export interface DrawControlProps extends MapboxDraw { position?: ControlPosition; onCreate?: (evt: {features: object[]}) => void; onUpdate?: (evt: {features: object[]; action: string}) => void; @@ -38,6 +37,7 @@ export interface DrawControlRefProps { } } +// @ts-ignore const DrawControl = forwardRef((props, ref) => { const drawRef = useRef(null) @@ -45,12 +45,13 @@ const DrawControl = forwardRef((props, re () => { let draw = new MapboxDraw( { + // @ts-ignore modes: { ...MapboxDraw.modes, // draw_line_select: drawLineSelectMode, draw_rect: drawRectMode, drag_circle: DragCircleMode, - draw_circle : drawCircleMode, + draw_circle: drawCircleMode, direct_select: DirectMode, simple_select: SimpleSelectMode, static: drawStaticMode, @@ -62,7 +63,7 @@ const DrawControl = forwardRef((props, re drawRef.current = draw return draw }, - (context: MapContextValue) => { + (context: any) => { const { map } = context map.on('draw.create', e => props.onCreate?.(e)); map.on('draw.update', e => props.onUpdate?.(e)); @@ -98,11 +99,4 @@ const DrawControl = forwardRef((props, re return null; }) -DrawControl.defaultProps = { - onCreate: () => {}, - onUpdate: () => {}, - onDelete: () => {}, - -}; - export default DrawControl diff --git a/packages/map/src/drawControl/Draw/constants.js b/packages/map/src/drawControl/demo/Draw/constants.js similarity index 100% rename from packages/map/src/drawControl/Draw/constants.js rename to packages/map/src/drawControl/demo/Draw/constants.js diff --git a/packages/map/src/drawControl/Draw/doubleClickZoom.js b/packages/map/src/drawControl/demo/Draw/doubleClickZoom.js similarity index 100% rename from packages/map/src/drawControl/Draw/doubleClickZoom.js rename to packages/map/src/drawControl/demo/Draw/doubleClickZoom.js diff --git a/packages/map/src/drawControl/Draw/drawCircleMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawCircleMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawCircleMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawCircleMode.draw.js diff --git a/packages/map/src/drawControl/Draw/drawDirectMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawDirectMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawDirectMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawDirectMode.draw.js diff --git a/packages/map/src/drawControl/Draw/drawLineSelectMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawLineSelectMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawLineSelectMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawLineSelectMode.draw.js diff --git a/packages/map/src/drawControl/Draw/drawRectMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawRectMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawRectMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawRectMode.draw.js diff --git a/packages/map/src/drawControl/Draw/drawSimpleSelectMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawSimpleSelectMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawSimpleSelectMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawSimpleSelectMode.draw.js diff --git a/packages/map/src/drawControl/Draw/drawStaticMode.draw.js b/packages/map/src/drawControl/demo/Draw/drawStaticMode.draw.js similarity index 100% rename from packages/map/src/drawControl/Draw/drawStaticMode.draw.js rename to packages/map/src/drawControl/demo/Draw/drawStaticMode.draw.js diff --git a/packages/map/src/drawControl/Draw/index.ts b/packages/map/src/drawControl/demo/Draw/index.ts similarity index 100% rename from packages/map/src/drawControl/Draw/index.ts rename to packages/map/src/drawControl/demo/Draw/index.ts diff --git a/packages/map/src/drawControl/mode/doubleClickZoom.js b/packages/map/src/drawControl/mode/doubleClickZoom.js new file mode 100644 index 0000000..4e747e1 --- /dev/null +++ b/packages/map/src/drawControl/mode/doubleClickZoom.js @@ -0,0 +1,24 @@ +const doubleClickZoom = { + enable(ctx) { + setTimeout(() => { + if ( + !ctx.map || + !ctx.map.doubleClickZoom || + !ctx._ctx || + !ctx._ctx.store || + !ctx._ctx.store.getInitialConfigValue + ) + return; + if (!ctx._ctx.store.getInitialConfigValue('doubleClickZoom')) return; + ctx.map.doubleClickZoom.enable(); + }, 0); + }, + disable(ctx) { + setTimeout(() => { + if (!ctx.map || !ctx.map.doubleClickZoom) return; + ctx.map.doubleClickZoom.disable(); + }, 0); + }, +}; + +export default doubleClickZoom; diff --git a/packages/map/src/drawControl/mode/drawCircleMode.draw.js b/packages/map/src/drawControl/mode/drawCircleMode.draw.js new file mode 100644 index 0000000..fca766e --- /dev/null +++ b/packages/map/src/drawControl/mode/drawCircleMode.draw.js @@ -0,0 +1,69 @@ +import MapboxDraw from '@mapbox/mapbox-gl-draw'; +import doubleClickZoom from './doubleClickZoom'; +import * as turf from '@turf/turf'; +const { circle, distance, helpers: turfHelpers } = turf; +const drawCircleMode = { ...MapboxDraw.modes.draw_polygon }; +drawCircleMode.onSetup = function () { + const polygon = this.newFeature({ + type: 'Feature', + properties: { + isCircle: true, + center: [], + }, + geometry: { + type: 'Polygon', + coordinates: [], + }, + }); + + this.addFeature(polygon); + + this.clearSelectedFeatures(); + doubleClickZoom.disable(this); + // dragPan.disable(this); + this.updateUIClasses({ mouse: 'add' }); + this.activateUIButton('Polygon'); + this.setActionableState({ + trash: true, + }); + + return { + polygon, + currentVertexPosition: 0, + }; +}; +drawCircleMode.onClick = drawCircleMode.onTap = function (state, e) { + const currentCenter = state.polygon.properties.center; + if (currentCenter.length === 0) { + // dragPan.disable(this) + state.polygon.properties.center = [e.lngLat.lng, e.lngLat.lat]; + } else { + // dragPan.enable(this); + return this.changeMode('simple_select', { featureIds: [state.polygon.id] }); + } +}; +drawCircleMode.onDrag = drawCircleMode.onMouseMove = function (state, e) { + const center = state.polygon.properties.center; + if (center.length > 0) { + const distanceInKm = distance( + turfHelpers.point(center), + turfHelpers.point([e.lngLat.lng, e.lngLat.lat]), + { + units: 'kilometers', + } + ); + const circleFeature = circle(center, distanceInKm); + state.polygon.incomingCoords(circleFeature.geometry.coordinates); + state.polygon.properties.radiusInKm = distanceInKm; + state.polygon.properties.lastClickCoord = [e.lngLat.lng, e.lngLat.lat]; + } +}; +//它决定当前 Drew 数据存储中的哪些特性将在地图上呈现。 +//所有传递给“显示”的特性都将被渲染,因此可以为每个内部特性传递多个显示特性。 +//有关如何制作显示特性的建议,请参阅‘ styling-pull’in‘ API.md’ +drawCircleMode.toDisplayFeatures = function (state, geojson, display) { + const isActivePolygon = geojson.properties.id === state.polygon.id; + geojson.properties.active = isActivePolygon ? 'true' : 'false'; + display(geojson); +}; +export default drawCircleMode; diff --git a/packages/material/.fatherrc.ts b/packages/material/.fatherrc.ts index 447d06b..b0341a2 100644 --- a/packages/material/.fatherrc.ts +++ b/packages/material/.fatherrc.ts @@ -1,13 +1,16 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md esm: { output: 'es', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, cjs: { output: 'lib', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, + plugins: ['father-plugin-less'], }); diff --git a/packages/meta/.fatherrc.ts b/packages/meta/.fatherrc.ts index 447d06b..b0341a2 100644 --- a/packages/meta/.fatherrc.ts +++ b/packages/meta/.fatherrc.ts @@ -1,13 +1,16 @@ -import { defineConfig } from 'father'; +import { defineConfig } from 'father-plugin-less'; export default defineConfig({ // more father config: https://github.com/umijs/father/blob/master/docs/config.md esm: { output: 'es', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, cjs: { output: 'lib', - ignores: ['**/demo/*', 'src/**/demo/*'] + ignores: ['**/demo/*', 'src/**/demo/*'], + transformer: 'babel', }, + plugins: ['father-plugin-less'], }); diff --git a/packages/meta/es/BigImagePreview/components/BtnGroup/index.less b/packages/meta/es/BigImagePreview/components/BtnGroup/index.less deleted file mode 100644 index db03187..0000000 --- a/packages/meta/es/BigImagePreview/components/BtnGroup/index.less +++ /dev/null @@ -1,51 +0,0 @@ -.zhst-image__btn-group { - // display: flex; - width: 30px; - box-shadow: 0 2px 6px 0 rgb(0 0 0 / 40%); - - &__item { - display: flex; - width: 30px; - height: 30px; - align-items: center; - justify-content: center; - background: #000; - - &>button { - padding: 0; - color: #fff; - - &:hover { - color: #09f; - } - - &:active { - color: #09f; - } - - &:focus { - color: #fff; - } - - &>span { - display: flex; - } - } - - &--active { - &>button { - color: #09f; - } - } - } - - &--circle { - background-color: none; - box-shadow: none; - } - - &--circle &__item { - margin-bottom: 4px; - border-radius: 50%; - } -} diff --git a/packages/meta/es/BigImagePreview/index.less b/packages/meta/es/BigImagePreview/index.less deleted file mode 100644 index 5a940fe..0000000 --- a/packages/meta/es/BigImagePreview/index.less +++ /dev/null @@ -1,54 +0,0 @@ -.zhst-image__img-view { - position: relative; - width: calc(100%); - height: 100%; - font-size: 0; - - &__face-score { - position: absolute; - right: 20px; - bottom: 80px; - color: red; - font-family: 'Microsoft YaHei'; - font-size: 19px; - font-weight: bold; - } - - &-opt { - position: absolute; - z-index: 99; - top: 0; - } - - &-crop-opt { - position: absolute; - z-index: 99; - top: 0; - right: 0; - } - - &-align { - position: absolute; - top: 0; - left: 0; - pointer-events: none; - } - - &-main { - width: 100%; - height: 100%; - font-size: 0; - - &--cursor { - & canvas { - min-height: 320px; - cursor: pointer; - } - } - } - - &-screenshot { - position: absolute; - z-index: 10; - } -} diff --git a/packages/meta/es/CompareImage/CompareImage.js b/packages/meta/es/CompareImage/CompareImage.js index e0357b8..479c247 100644 --- a/packages/meta/es/CompareImage/CompareImage.js +++ b/packages/meta/es/CompareImage/CompareImage.js @@ -16,8 +16,12 @@ var CompareImage = /*#__PURE__*/forwardRef(function (props, ref) { var customizePrefixCls = props.prefixCls, _props$label = props.label, label = _props$label === void 0 ? '标题' : _props$label, + _props$width = props.width, + width = _props$width === void 0 ? '400' : _props$width, + height = props.height, _props$openRoll = props.openRoll, openRoll = _props$openRoll === void 0 ? true : _props$openRoll, + labelColor = props.labelColor, _props$url = props.url, url = _props$url === void 0 ? '' : _props$url, _props$score = props.score, @@ -33,6 +37,7 @@ var CompareImage = /*#__PURE__*/forwardRef(function (props, ref) { getPrefixCls = _useContext.getPrefixCls; var componentName = getPrefixCls('image__compater-view', customizePrefixCls); var imgContainerRef = useRef(null); + var containerRef = useRef(null); var imgInsRef = useRef(null); var _useState = useState(0), _useState2 = _slicedToArray(_useState, 2), @@ -47,8 +52,10 @@ var CompareImage = /*#__PURE__*/forwardRef(function (props, ref) { setScale(get(data, 'scale', 0)); }); if (generateImg(url)) { + console.log('containerRef', containerRef); imgInsRef.current = new Viewer(imgContainerRef.current, { - image: generateImg(url) + image: generateImg(url), + height: parseInt(height) }); } return function () { @@ -74,9 +81,15 @@ var CompareImage = /*#__PURE__*/forwardRef(function (props, ref) { }; }); return /*#__PURE__*/React.createElement("div", { - className: classNames("".concat(componentName, "__container")) + className: classNames("".concat(componentName, "__container")), + style: { + width: "".concat(parseInt(width), "px") + } }, label && /*#__PURE__*/React.createElement("div", { - className: classNames("".concat(componentName, "__label")) + className: classNames("".concat(componentName, "__label")), + style: { + backgroundColor: labelColor + } }, label), !url ? /*#__PURE__*/React.createElement("div", { className: classNames("".concat(componentName, "__empty")) }, /*#__PURE__*/React.createElement("img", { diff --git a/packages/meta/es/CompareImage/components/CornerScore/index.less b/packages/meta/es/CompareImage/components/CornerScore/index.less deleted file mode 100644 index cb8bf35..0000000 --- a/packages/meta/es/CompareImage/components/CornerScore/index.less +++ /dev/null @@ -1,21 +0,0 @@ -.zhst-image__CornerScore { - position: absolute; - right: 0; - bottom: 0; - width: 56px; - height: 22px; - line-height: 22px; - text-align: right; - padding-right: 1px; - background-size: 100%; - background-image: url('data: image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAsCAYAAAC9rDzHAAAByUlEQVR4Xu2cO08DMRCEJy0tlNBCSwmU0EIJLbS0UEILLTX/Fo3kk1AUHrrsjB3dWIoUnZTdvfnOZ6+1mxXGGHsADgEcA9hvnyMAvJ7xiwKrjuoQ0HmDxu8ZMxToAZDQrgAE2gxg6z9xAjwFcAvgoCDumGgKuADeA7iI6vUKqAFyE/KU12U9uMmiGuBr4Ong0bIS4A2Aa234sa4CyFzuPfLqFVABfGg5nv4OFu5BAZAbl4+F62q7fQVAJul3tjtYuCMFwEcATNozDAooAL7ltMVATngS8+kLP54UMzAAjc9VABrFVrgKQIWqRpsBaBRb4SoAFaoabQagUWyFqwBUqGq0GYBGsRWuAlChqtFmABrFVrgKQIWqRpsBaBRb4SoAFaoabVYDZLU1K9EyTApUA2RzyrMp9rgRlBWylIIlFRkmBapnIIuZ0hJmgkc3lQBTzGQEN7mqApjNSwd4VTOQr8yXFDL1IbjtDOTMY/dR1r0+/LZaA1n7yb6/wOsEb+4rlMDYdZR0oSO4uZuYtEkPAO17CP9dA3nCwll3Mlj8iw/nL4ABN/gj8hPAgBsc3KY1kJuTs7Y5yV+B7BBA5nKXrSUsKcGOgJvC/ALSJBp5mBHCFAAAAABJRU5ErkJggg=='); - z-index: 99; - - &>span { - padding-right: 6px; - line-height: 22px; - font-size: 12px; - vertical-align: middle; - color: rgba(255, 255, 255, 100%); - } -} diff --git a/packages/meta/es/CompareImage/index.less b/packages/meta/es/CompareImage/index.less deleted file mode 100644 index ec4db9d..0000000 --- a/packages/meta/es/CompareImage/index.less +++ /dev/null @@ -1,144 +0,0 @@ -.zhst-image__compater-view { - display: flex; - width: 100%; - align-items: center; - justify-content: center; - - &>div:first-child { - margin-right: 25px; - } - - &>div:last-child { - margin-left: 25px; - } - - &__container { - font-size: 0; - position: relative; - box-sizing: content-box; - border: 1px solid #f0f0f0; - } - - &__view { - min-width: 345px; - min-height: 450px; - } - - &__label { - position: absolute; - z-index: 99; - top: 0; - left: 0; - display: flex; - font-size: 16px; - height: 34px; - align-items: center; - justify-content: center; - - // width: 48px; - padding: 0 6px; - background: #09f; - color: #fff; - } - - &__tool { - display: flex; - width: 100%; - height: 40px; - align-items: center; - justify-content: center; - background: #f9f9f9; - - i, - span { - color: #333 !important; - } - - i { - margin-right: 4px; - } - - &>*:not(:last-child) { - margin-right: 20px; - } - - &__scale { - display: inline-block; - width: 38px; - height: 16px; - - // margin-left: 15px; - box-sizing: content-box; - border: 1px solid rgb(77 77 77 / 100%); - background: rgb(255 255 255 / 100%); - border-radius: 2px; - color: #4d4d4d; - cursor: default; - font-size: 12px; - line-height: 16px; - text-align: center; - } - - &__line { - width: 1px; - height: 14px; - background: #e6e6e6; - } - } - - &__empty { - position: absolute; - z-index: 9; - display: flex; - width: 100%; - height: 100%; - flex-direction: column; - align-items: center; - justify-content: center; - background: #f9f9f9; - transform: translateY(-100%); - - &>img { - margin-bottom: 12px; - width: 140px; - height: 80px; - } - - &--text { - color: #999; - font-size: 14px; - line-height: 22px; - } - } - - &__scoll-module { - position: absolute; - padding: 12px; - bottom: 48px; - display: flex; - width: 100%; - align-items: flex-end; - justify-content: space-between; - pointer-events: none; - box-sizing: border-box; - - &__btn { - width: 56px; - height: 56px; - opacity: 0.4; - pointer-events: all; - - &>span { - display: flex; - align-items: center; - justify-content: center; - } - } - - &__btn:hover { - opacity: 0.6; - background-color: #09f !important; - color: #fff !important; - } - } -} diff --git a/packages/meta/es/VideoPlayer/components/Loading/index.less b/packages/meta/es/VideoPlayer/components/Loading/index.less deleted file mode 100644 index b6c11a2..0000000 --- a/packages/meta/es/VideoPlayer/components/Loading/index.less +++ /dev/null @@ -1,53 +0,0 @@ -.zhst-image__video-view__player-mask { - position: absolute; - width: 100%; - height: 100%; - z-index: 99; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: rgb(4 4 4 / 70%); - - &--bg { - z-index: 999; - background-color: rgb(4 4 4 / 100%); - } - - i { - cursor: pointer; - } - - &-title { - margin-top: 12px; - color: #fff; - text-align: center; - - & a { - color: #09f; - cursor: pointer; - text-decoration: underline; - } - } -} - -.zhst-image__video-view__icon-wraper { - display: flex; - width: 80px; - height: 80px; - align-items: center; - justify-content: center; - background-color: rgb(255 255 255 / 10%); - border-radius: 50%; - cursor: pointer; - line-height: 80px; - text-align: center; - - // &:hover { - // background: #0099ff; - // } -} diff --git a/packages/meta/es/VideoPlayer/components/Progress/index.less b/packages/meta/es/VideoPlayer/components/Progress/index.less deleted file mode 100644 index e922211..0000000 --- a/packages/meta/es/VideoPlayer/components/Progress/index.less +++ /dev/null @@ -1,49 +0,0 @@ -.zhst-image__range { - position: relative; - - &--no-slider { - .next-range-slider { - display: none; - } - } - - & .next-range .next-range-track { - height: 8px; - margin-top: -4px; - border-radius: 8px; - } - - & .next-range .next-range-selected { - height: 8px; - margin-top: -4px; - border-radius: 8px; - } - - & .next-range .next-range-slider-inner { - width: 14px; - height: 14px; - border-color: #fff; - margin-top: -7px; - margin-left: -7px; - background-color: #0098ff; - } - - & .next-range .next-range-slider { - width: 14px; - height: 14px; - margin-top: -7px; - margin-left: -7px; - } - - & .next-range.simulation-click>.next-range-slider-inner { - border: 2px solid #fff !important; - } - - & .next-range .next-range-frag.next-range-active .next-range-slider .next-range-slider-inner { - border: 2px solid #fff !important; - } - - & .next-range .next-range-slider.next-range-slider-moving .next-range-slider-inner { - border: 2px solid #fff !important; - } -} diff --git a/packages/meta/es/VideoPlayer/index.less b/packages/meta/es/VideoPlayer/index.less deleted file mode 100644 index 2630aa1..0000000 --- a/packages/meta/es/VideoPlayer/index.less +++ /dev/null @@ -1,73 +0,0 @@ -.zhst-image__video-view { - position: relative; - overflow: hidden; - background-color: #333; - - // &-flv { - // width: 85%; - // } - &-screenshot { - position: absolute; - z-index: 10; - } - - &-crop-container { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - } - - &-align { - position: absolute; - top: 0; - left: 0; - pointer-events: none; - } - - &-opt { - position: absolute; - z-index: 99; - bottom: 0; - display: flex; - width: 100%; - height: 32px; - box-sizing: border-box; - align-items: center; - padding: 0 12px 0 24px; - background-color: rgb(0 0 0 / 80%); - line-height: 32px; - - &>div:first-child { - display: flex; - align-items: center; - margin-right: 12px; - } - - &>div:last-child { - display: flex; - align-items: center; - margin-left: 12px; - } - - &-range { - display: flex; - height: 32px; - flex: 1; - align-items: center; - line-height: 32px; - text-align: center; - - &>div:first-child { - flex: 1; - } - - &>div:last-child { - width: 100px; - margin-left: 8px; - color: #fff; - } - } - } -} diff --git a/packages/meta/es/index.js b/packages/meta/es/index.js index dfd5478..bc3fa06 100644 --- a/packages/meta/es/index.js +++ b/packages/meta/es/index.js @@ -9,6 +9,7 @@ export { default as VideoPlayer } from "./VideoPlayer"; // antd export { default as Tabs } from "./tabs"; export { default as Tree } from "./tree"; +export { default as Spin } from "./spin"; export { default as message } from "./message"; export { default as Button } from "./button"; export { default as Image } from "./image"; diff --git a/packages/meta/src/CompareImage/CompareImage.tsx b/packages/meta/src/CompareImage/CompareImage.tsx index 5c72f65..49b2102 100644 --- a/packages/meta/src/CompareImage/CompareImage.tsx +++ b/packages/meta/src/CompareImage/CompareImage.tsx @@ -17,6 +17,9 @@ export interface CompareImageProps { * @default "默认值" */ label?: string; + labelColor?: string; + width?: string; + height?: string showTools?: boolean; prefixCls?: string; openRoll?: boolean; //开启翻页 @@ -39,7 +42,10 @@ const CompareImage = forwardRef((props, const { prefixCls: customizePrefixCls, label = '标题', + width = '400', + height, openRoll = true, + labelColor, url = '', score = 0, preDisable, @@ -69,11 +75,10 @@ const CompareImage = forwardRef((props, } ); - if (generateImg(url)) { - imgInsRef.current = new Viewer(imgContainerRef.current, { - image: generateImg(url), - }); - } + imgInsRef.current = new Viewer(imgContainerRef.current, { + image: url, + height: parseInt(height!), + }); return () => { handleTransformChange?.remove(); @@ -96,8 +101,8 @@ const CompareImage = forwardRef((props, })); return ( -
- {label &&
{label}
} +
+ {label &&
{label}
} {!url ? (
((props, style={{ width: '56px' }} icon={} > - */}