Merge branch 'develop' into feat/cropper-upgrade

# Conflicts:
#	packages/meta/src/cropperImage/CropperImage.tsx
#	packages/meta/src/cropperImage/demo/basic.tsx
This commit is contained in:
NICE CODE BY DEV 2024-05-14 11:27:13 +08:00
commit d80cab2407
12 changed files with 253 additions and 133 deletions

View File

@ -1,5 +1,21 @@
# @zhst/biz # @zhst/biz
## 0.21.5
### Patch Changes
- fix: 修改 zhst/meta
- Updated dependencies
- @zhst/meta@0.20.3
## 0.21.4
### Patch Changes
- zhst/biz、zhst/meta、zhst/material: 修改 od、修改 boxSelectTree
- Updated dependencies
- @zhst/meta@0.20.2
## 0.21.3 ## 0.21.3
### Patch Changes ### Patch Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@zhst/biz", "name": "@zhst/biz",
"version": "0.21.3", "version": "0.21.5",
"description": "业务库", "description": "业务库",
"keywords": [ "keywords": [
"business", "business",

View File

@ -223,11 +223,6 @@ const BigImageModal: React.FC<BigImageModalProps, BigModalRef> = forwardRef((pro
] ]
} }
// TODO: 页面初始化
useEffect(() => {
}, [dataSource]);
// 暴露 ref 实例 // 暴露 ref 实例
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
ref, ref,

View File

@ -1,15 +1,36 @@
.zhst-biz-box-select-tree-panel { .zhst-biz-box-select-tree-panel {
padding: 0 16px; &-search {
display: flex;
padding: 0 12px;
&-btns-common { &-input {
padding: 4px 8px; margin-right: 4px;
}
&-btns {
flex: none;
}
} }
&-btns-import { &-btns {
padding: 4px 8px; padding: 6px 12px;
display: flex;
justify-content: space-between;
&-common {
padding: 4px 8px;
}
&-import {
padding: 4px 8px;
}
&-divider {
margin: 8px 0;
}
} }
&-btns-divider { &-tree {
margin: 8px 0; padding: 6px 0;
} }
} }

View File

@ -128,102 +128,109 @@ const BoxPanel: FC<BoxPanelProps> = (props) => {
onTreeCheck={onTreeCheck} // 树check选中事件 onTreeCheck={onTreeCheck} // 树check选中事件
onItemDelete={onItemDelete} // 右侧点击删除事件 onItemDelete={onItemDelete} // 右侧点击删除事件
/> />
<Space size={12} direction='vertical' style={{ width: '100%' }}> <div className={classNames(componentName + '-search')}>
<Space size={4} style={{ width: '100%', justifyContent: 'space-between' }} > <Input
<Input size='middle' onChange={(e) => onSearch?.(e)} placeholder='请输入盒子名称' {...searchInputProps} /> className={classNames(componentName + '-search-input')}
{customImport || ( size='middle'
<> onChange={(e) => onSearch?.(e)}
<Button type="text" onClick={() => onBatch?.() || handleCheckable()} icon={isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />} /> placeholder='请输入盒子名称'
<Button type="text" onClick={() => onClockClick?.()} icon={<ClockCircleOutlined />} /> {...searchInputProps}
</>
)}
</Space>
{/* 是否显示操作按钮 */}
{showOptions && (
<>
<Space align='center'>
<Button className={classNames(componentName + '-btns-common')} type='text' onClick={() => onImport?.()} icon={<ImportOutlined />} ></Button>
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
{onCreate ?
(
<Button className={classNames(componentName + '-btns-common')} onClick={onCreate} type='text' icon={<FolderAddOutlined />} ></Button>
) : (
<ModalForm<{
name: string
boxList?: any[]
}>
className={classNames(componentName + '-create-modal')}
open={onCreate ? false : undefined}
formRef={createFormRef}
title="新建组"
modalProps={{ destroyOnClose: true }}
layout='horizontal'
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
trigger={<Button type='text' className={classNames(componentName + '-btns-common')} icon={<FolderAddOutlined />} ></Button>}
submitter={{
searchConfig: {
submitText: '确定',
resetText: '取消',
},
}}
onFinish={onCreateSubmit}
>
<ProFormText
rules={[
{
required: true,
max: 20,
},
{
pattern: /^[^\s]*$/g,
message: '禁止输入空格'
}
]}
fieldProps={{ showCount: true }}
width="md"
name="name"
label="盒子组名称"
placeholder="请输入盒子名称"
/>
<ProFormText
width="md"
name="boxList"
label="盒子选择"
fieldProps={{
readOnly: true,
value: `已选择${createFormRef.current?.getFieldValue('boxList')?.length || 0}个盒子`,
suffix: (
<Space>
<a onClick={() => {
createFormRef.current?.setFieldValue('boxList', null)
onBoxChoiceReset()
}} ></a>
<a onClick={() => setBoxChoiceOpen(true)}></a>
</Space>
)
}}
/>
</ModalForm>
)
}
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
{/* @ts-ignore */}
<Button className={classNames(componentName + '-btns-common')} danger type='text' icon={<CloseCircleOutlined />} disabled={treeProps?.checkedKeys?.length <= 0} onClick={onBoxBatchDelete} ></Button>
</Space>
<Divider style={{ margin: 0 }} />
</>
)}
{extraBtns}
<BoxTree
treeCheckable={isTreeCheckable}
data={data}
onItemSelect={onItemSelect}
onItemCheck={onItemCheck}
onItemDelete={onBoxDelete}
{...treeProps}
/> />
</Space> {customImport || (
<div
className={classNames(componentName + '-search-btns')}
>
<Button type="text" onClick={() => onBatch?.() || handleCheckable()} icon={isTreeCheckable ? <SwitcherOutlined /> : <DiffOutlined />} />
<Button type="text" onClick={() => onClockClick?.()} icon={<ClockCircleOutlined />} />
</div>
)}
</div>
{/* 是否显示操作按钮 */}
{showOptions && (
<>
<div className={classNames(componentName + '-btns')}>
<Button className={classNames(componentName + '-btns-common')} type='text' onClick={() => onImport?.()} icon={<ImportOutlined />} ></Button>
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
{onCreate ?
(
<Button className={classNames(componentName + '-btns-common')} onClick={onCreate} type='text' icon={<FolderAddOutlined />} ></Button>
) : (
<ModalForm<{
name: string
boxList?: any[]
}>
className={classNames(componentName + '-create-modal')}
open={onCreate ? false : undefined}
formRef={createFormRef}
title="新建组"
modalProps={{ destroyOnClose: true }}
layout='horizontal'
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
trigger={<Button type='text' className={classNames(componentName + '-btns-common')} icon={<FolderAddOutlined />} ></Button>}
submitter={{
searchConfig: {
submitText: '确定',
resetText: '取消',
},
}}
onFinish={onCreateSubmit}
>
<ProFormText
rules={[
{
required: true,
max: 20,
},
{
pattern: /^[^\s]*$/g,
message: '禁止输入空格'
}
]}
fieldProps={{ showCount: true }}
width="md"
name="name"
label="盒子组名称"
placeholder="请输入盒子名称"
/>
<ProFormText
width="md"
name="boxList"
label="盒子选择"
fieldProps={{
readOnly: true,
value: `已选择${createFormRef.current?.getFieldValue('boxList')?.length || 0}个盒子`,
suffix: (
<Space>
<a onClick={() => {
createFormRef.current?.setFieldValue('boxList', null)
onBoxChoiceReset()
}} ></a>
<a onClick={() => setBoxChoiceOpen(true)}></a>
</Space>
)
}}
/>
</ModalForm>
)
}
<Divider className={classNames(componentName + '-btns-divider')} type="vertical" />
{/* @ts-ignore */}
<Button className={classNames(componentName + '-btns-common')} danger type='text' icon={<CloseCircleOutlined />} disabled={treeProps?.checkedKeys?.length <= 0} onClick={onBoxBatchDelete} ></Button>
</div>
<Divider style={{ margin: 0 }} />
</>
)}
{extraBtns}
<BoxTree
className={classNames(componentName + '-tree')}
treeCheckable={isTreeCheckable}
data={data}
onItemSelect={onItemSelect}
onItemCheck={onItemCheck}
onItemDelete={onBoxDelete}
{...treeProps}
/>
</div> </div>
) )
} }

View File

@ -56,6 +56,7 @@ const demo = () => {
addonBefore: ( addonBefore: (
<Select <Select
value={searchType} value={searchType}
dropdownMatchSelectWidth={false}
onChange={_type => { onChange={_type => {
setSearchType(_type) setSearchType(_type)
setSearchVal('') setSearchVal('')

View File

@ -1,5 +1,23 @@
# @zhst/material # @zhst/material
## 0.17.4
### Patch Changes
- fix: 修改 zhst/meta
- Updated dependencies
- @zhst/meta@0.20.3
- @zhst/biz@0.21.5
## 0.17.3
### Patch Changes
- zhst/biz、zhst/meta、zhst/material: 修改 od、修改 boxSelectTree
- Updated dependencies
- @zhst/meta@0.20.2
- @zhst/biz@0.21.4
## 0.17.2 ## 0.17.2
### Patch Changes ### Patch Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@zhst/material", "name": "@zhst/material",
"version": "0.17.2", "version": "0.17.4",
"description": "物料库", "description": "物料库",
"keywords": [ "keywords": [
"business", "business",

View File

@ -1,5 +1,21 @@
# @zhst/utils # @zhst/utils
## 0.20.3
### Patch Changes
- fix: 修改 zhst/meta
- Updated dependencies
- @zhst/meta@0.20.3
## 0.20.2
### Patch Changes
- zhst/biz、zhst/meta、zhst/material: 修改 od、修改 boxSelectTree
- Updated dependencies
- @zhst/meta@0.20.2
## 0.20.1 ## 0.20.1
### Patch Changes ### Patch Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@zhst/meta", "name": "@zhst/meta",
"version": "0.20.1", "version": "0.20.3",
"description": "原子组件", "description": "原子组件",
"keywords": [ "keywords": [
"meta", "meta",

View File

@ -100,6 +100,7 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
const currentShapeRef = useRef<any>(null) const currentShapeRef = useRef<any>(null)
const imageRef = useRef<HTMLDivElement>(null) const imageRef = useRef<HTMLDivElement>(null)
const viewerRef = useRef<any>(null) const viewerRef = useRef<any>(null)
const currentFabricRef = useRef<CanvasPro>(null)
// 自定义弹框 // 自定义弹框
const alginContainerRef: any = useRef(null); const alginContainerRef: any = useRef(null);
@ -118,6 +119,7 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
// 监听形状选择事件 // 监听形状选择事件
imageRectRef.current = addEventListenerWrapper(imageRef.current, EVENT_SHAPE_SELECT, (e: { detail: any; }) => { imageRectRef.current = addEventListenerWrapper(imageRef.current, EVENT_SHAPE_SELECT, (e: { detail: any; }) => {
// 选中的od // 选中的od
<<<<<<< HEAD
const id = e.detail; const id = e.detail;
if (id) { if (id) {
// 获取选中的形状 // 获取选中的形状
@ -140,6 +142,18 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
// getTransformRect(imageRectRef.current.image, ) // getTransformRect(imageRectRef.current.image, )
id && onShapeSelected?.(id, { ..._data, imageRect, originData: selectRectData }) id && onShapeSelected?.(id, { ..._data, imageRect, originData: selectRectData })
} }
=======
const id = e.detail;
if (id) {
const selectRectData = odList!.filter(_od => _od.id === id)?.[0]
const _data = percentToLength(selectRectData, viewerRef.current.canvas)
const imageRect = getImageDataByPosition(
{ x: _data.x, y: _data.y, w: _data.w, h: _data.h },
{ canvas: viewerRef.current.canvas }
)
id && onShapeSelected?.(id, { ..._data, imageRect, originData: selectRectData })
}
>>>>>>> develop
}) })
return () => { return () => {
@ -157,19 +171,28 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
// 初始化 - 编辑器 // 初始化 - 编辑器
useEffect(() => { useEffect(() => {
const _viewer = viewerRef?.current || {} const _viewer = viewerRef?.current || {}
// 判断是否可编辑 // 判断是否可编辑 - 非编辑态
if (!editAble) { if (!editAble) {
_viewer.clearShape()
// 判定是否存在od框 // 判定是否存在od框
odList && odList.forEach(_od => { odList && odList.forEach(_od => {
_viewer?.addShape?.(_od); _viewer?.addShape?.(_od);
}) })
return return
} else { } else {
<<<<<<< HEAD
// 编辑模式 // 编辑模式
_viewer?.clearShape?.(); _viewer?.clearShape?.();
if (type === 'rect') { if (type === 'rect') {
// 编辑模式 - 矩形绘制 // 编辑模式 - 矩形绘制
=======
// 编辑态
const { targetTransform = {} } = _viewer
if (type === 'rect') {
_viewer.clearShape()
>>>>>>> develop
currentShapeRef.current = initRect() currentShapeRef.current = initRect()
// cropEndRef.current = addEventListenerWrapper(imageRef.current, EVENT_CROP_END, (event: { detail: any; }) => { // cropEndRef.current = addEventListenerWrapper(imageRef.current, EVENT_CROP_END, (event: { detail: any; }) => {
// const data = event.detail; // const data = event.detail;
@ -303,7 +326,8 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
const { containerData = {}, targetTransform = {} } = viewer const { containerData = {}, targetTransform = {} } = viewer
const imageSize = viewer.getImgSize() const imageSize = viewer.getImgSize()
let currentFabric: CanvasPro = new fabric.Canvas( // @ts-ignore
currentFabricRef.current = new fabric.Canvas(
canvasRef.current, canvasRef.current,
{ {
backgroundColor: 'transparent', backgroundColor: 'transparent',
@ -312,6 +336,7 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
selection: false, selection: false,
} }
) )
const currentFabric = currentFabricRef.current
// 事件监听: 鼠标抬起事件 // 事件监听: 鼠标抬起事件
currentFabric.on('mouse:down', function(options) { currentFabric.on('mouse:down', function(options) {
@ -411,6 +436,10 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
viewerRef, viewerRef,
rotateTo: (val) => { rotateTo: (val) => {
viewerRef.current.rotateTo((pre: any) => pre + val) viewerRef.current.rotateTo((pre: any) => pre + val)
},
clearShape: () => {
viewerRef.current?.clearShape?.();
currentFabricRef.current?.clear()
} }
})); }));

View File

@ -8,6 +8,23 @@ export default () => {
const [editAble, setEditAble] = useState(false) const [editAble, setEditAble] = useState(false)
const cropperRef = useRef(null) const cropperRef = useRef(null)
const [imgUrl, setImgUrl] = useState('') const [imgUrl, setImgUrl] = useState('')
const [odList, setOdList] = useState([
{
"id": "123",
"x": 0.5519352,
"y": 0.2965385,
"w": 0.05185461,
"h": 0.24698898,
selectAble: false,
},
{
"id": "456",
"x": 0.58543766,
"y": 0.3203356,
"w": 0.052037954,
"h": 0.2664015
}
])
const [selectedItem, setSelectedItem] = useState<any>() const [selectedItem, setSelectedItem] = useState<any>()
return ( return (
@ -15,26 +32,8 @@ export default () => {
<Space> <Space>
<Button onClick={() => setType('line')}></Button> <Button onClick={() => setType('line')}></Button>
<Button onClick={() => setType('rect')}></Button> <Button onClick={() => setType('rect')}></Button>
<Button onClick={() => setEditAble(pre => !pre)}>{!editAble ? '不可编辑' : '可编辑'}</Button> <Button onClick={() => {
<Button setOdList([
onClick={() => {
console.log('cropperRef?.current', cropperRef?.current.rotateTo(90))
console.log('cropper', cropperRef?.current)
}}
></Button>
</Space>
<div style={{ width: 800, height: 600 }}>
<CropperImage
ref={cropperRef}
type={type}
odList={[
{
"id": "123",
h: 0.30666666666666664,
w: 0.27170650730411683,
x: 0.19064741035856572,
y: 0.09703124999999999,
},
{ {
"id": "456", "id": "456",
"x": 0.58543766, "x": 0.58543766,
@ -42,7 +41,25 @@ export default () => {
"w": 0.052037954, "w": 0.052037954,
"h": 0.2664015 "h": 0.2664015
} }
]} ])
}}></Button>
<Button onClick={() => setEditAble(pre => !pre)}>{!editAble ? '不可编辑' : '可编辑'}</Button>
<Button
onClick={() => {
cropperRef?.current.rotateTo(90)
}}
></Button>
<Button
onClick={() => {
cropperRef?.current.clearShape()
}}
></Button>
</Space>
<div style={{ width: 800, height: 600 }}>
<CropperImage
ref={cropperRef}
type={type}
odList={odList}
editAble={editAble} editAble={editAble}
url="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" url="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
onMouseUp={data => console.log('箭头绘制结束:', data)} onMouseUp={data => console.log('箭头绘制结束:', data)}