powersir 1 рік тому
джерело
коміт
61c72cb887
4 змінених файлів з 217 додано та 22 видалено
  1. +0
    -1
      src/layout/index.tsx
  2. +1
    -1
      src/pages/custom/product/sample/editor/components/ImageStencil.tsx
  3. +17
    -0
      src/pages/custom/product/sample/editor/index.css
  4. +199
    -20
      src/pages/custom/product/sample/editor/index.tsx

+ 0
- 1
src/layout/index.tsx Переглянути файл

@@ -53,7 +53,6 @@ const BasicLayout: React.FC = () => {
useEffect(() => {
if (!currentUserProfile || !menuList?.data) return;
const routes: Menu[] = [];
console.log(menuList.data);

const fixAndPushMenu = (item: Menu) => {
if(!item.parentPaths) {


+ 1
- 1
src/pages/custom/product/sample/editor/components/ImageStencil.tsx Переглянути файл

@@ -127,7 +127,7 @@ export const ImageStencil = forwardRef<Methods, Props>(
}: Props,
ref,
) => {
const { patternUrl } = props;
const { patternUrl } = props as any;
const state = cropper.getState();
const transitions = cropper.getTransitions();
const interactions = cropper.getInteractions();


+ 17
- 0
src/pages/custom/product/sample/editor/index.css Переглянути файл

@@ -0,0 +1,17 @@
:where(.css-dev-only-do-not-override-11asvft).ant-card .ant-card-body {
padding: 0;
border-radius: 0 0 8px 8px;
}

:where(.css-dev-only-do-not-override-phnixs).ant-card .ant-card-body {
padding: 0;
border-radius: 0 0 8px 8px;
}

:where(.css-dev-only-do-not-override-phnixs).ant-list-lg .ant-list-item {
padding: 16px 8px;
}

:where(.css-dev-only-do-not-override-11asvft).ant-list-lg .ant-list-item {
padding: 16px 8px;
}

+ 199
- 20
src/pages/custom/product/sample/editor/index.tsx Переглянути файл

@@ -1,38 +1,217 @@
import React, { useState } from 'react';
import React, { useState, useRef } from 'react';
import { Anchor, Image, Card, List, Button, Upload, Radio } from 'antd';
import { useLocation } from 'react-router-dom';
import type { UploadProps, RadioChangeEvent } from 'antd';
import { CropperRef, Cropper } from 'react-advanced-cropper';
import 'react-advanced-cropper/dist/style.css'
import 'react-advanced-cropper/dist/style.css';
import { ImageStencil } from "./components/ImageStencil";
import { DeleteOutlined, EditOutlined, UploadOutlined } from '@ant-design/icons';
import cn from 'classnames';
import './index.css'
import property from '../../../../../../mock/propertyById.json'

interface SampleProperty {
id: number;
prototypeName: string;
categoryName: string;
prototypeImgs: PropertyImage[];
}

interface PropertyImage {
id: number;
imgUrl: string;
imgType: number;
imgName: string;
locations: ImageLocation[];
}

interface ImageLocation {
id: number;
prototypeImgId: number;
clipHeight: number;
clipWidth: number;
clipX: number;
clipY: number;
cropBoxJson: string;
}

const options = [
{ label: 'Free', value: 0 },
{ label: '1:1', value: 1 },
{ label: '2:3', value: 2/3 },
{ label: '4:3', value: 4/3 },
];

export default () => {
const { search } = useLocation()
const [image] = useState(
const [image, setImage] = useState(
'https://test.vogocm.com:9010/eshop/eshop_img/2023/8/21/20230821114346A053.jpg',
);
const [styleValue, setStyleValue] = useState<number>(0);
const [coordinateInfo, setCoordinateInfo] = useState('');

const [selectImageId, setSelectImageId] = useState<number>();
const cropperRef = useRef<CropperRef>(null);

const sample: SampleProperty = property;

const onChange = (cropper: CropperRef) => {
console.log(cropper.getCoordinates(), cropper.getCanvas());
const coordinates = cropper.getCoordinates();
setCoordinateInfo(`X轴: ${coordinates?.left}px; Y轴: ${coordinates?.top}px; 宽度: ${coordinates?.width}px; 高度: ${coordinates?.height}px;`)
};

const props: UploadProps = {
name: 'file',
action: 'https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188',
headers: {
authorization: 'authorization-text',
},
onChange(info) {
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
//message.success(`${info.file.name} file uploaded successfully`);
} else if (info.file.status === 'error') {
//message.error(`${info.file.name} file upload failed.`);
}
},
};

const onSelectChange = (value: PropertyImage) => {
setImage(value.imgUrl);
setSelectImageId(value.id);
}

const renderListItem = (item: PropertyImage) => {
return (<List.Item>
<Card
hoverable
bordered
style={selectImageId === item.id ? { width: 110, borderColor: "#7c4dff" } : { width: 110 }}
cover={
<img alt={item.imgName}
className='p-1'
src={item.imgUrl}
onClick={() => {
onSelectChange(item)
}}
/>
}
actions={[
<EditOutlined key="edit" />,
<DeleteOutlined key="delete" />,
]}
>
</Card>
</List.Item>)
}

const onStyleChanged = ({ target: { value } }: RadioChangeEvent) => {
setStyleValue(value);
}

return (
<div>
<Cropper
src={image}
className={cn('cropper', `w-[${600}px]`, `h-[${600}px]`)}
onChange={onChange}
stencilProps={{
patternUrl: 'https://test.vogocm.com:9696/image/material/20230413162155A010.png'
}}
stencilComponent={ImageStencil}
defaultCoordinates={{
left: 300,
top: 300,
width: 100,
height: 100,
}}
/>
<div className='flex'>
<Card className='flex-none mb-[10px] w-[270px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div style={{ padding: '20px' }}>
<Anchor
direction="horizontal"
items={[
{
key: 'part-1',
href: '#part-1',
title: '主图',
},
{
key: 'part-2',
href: '#part-2',
title: '属性图',
}
]}
/>
</div>
<div >
<div >
<div id="part-1" >
<List dataSource={sample.prototypeImgs.filter(it => it.imgType === 2)}
grid={{
gutter: 2,
column: 2
}}
header={(
<div className='flex justify-center'>
<Upload {...props}>
<Button icon={<UploadOutlined />}>点击上传主图</Button>
</Upload>
</div>
)}
renderItem={(item) => (renderListItem(item))}

/>
</div>
<div id="part-2">
<List
dataSource={sample.prototypeImgs.filter(it => it.imgType === 1)}
grid={{
gutter: 1,
column: 2,
}}
header={(
<div className='flex justify-center'>
<Upload {...props}>
<Button icon={<UploadOutlined />}>点击上传属性图</Button>
</Upload>
</div>
)}
renderItem={(item) => (renderListItem(item))}
/>
</div>
</div>
</div>
</Card>

<Card className='flex-auto mx-[10px] mb-[10px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className='flex flex-col justify-center'>
<div className='flex justify-center text-3xl p-5 font-extrabold'>工作台</div>
<div className='flex justify-center'>
<Cropper
ref={cropperRef}
src={image}
className={cn('cropper', `w-[600px]`, `h-[${600}px]`)}
onChange={onChange}
stencilProps={{
patternUrl: 'https://test.vogocm.com:9696/image/material/20230413162155A010.png'
}}
aspectRatio={() => {
return styleValue
}}
stencilComponent={ImageStencil}
defaultCoordinates={{
left: 300,
top: 300,
width: 100,
height: 100,
}}
/>
</div>
<div className='flex justify-center p-5'>
{coordinateInfo}
</div>
</div>
</Card>

<Card className='flex-none mb-[10px] w-[270px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'>
<div className='flex justify-center pt-2'>
<Radio.Group options={options}
onChange={onStyleChanged}
value={styleValue}
optionType="button"
buttonStyle="solid">

</Radio.Group>
</div>
</Card>
</div>
)
}

Завантаження…
Відмінити
Зберегти