|
|
@@ -1,18 +1,18 @@ |
|
|
|
import React, { useEffect, useMemo, useState } from 'react' |
|
|
|
import { CloseOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'; |
|
|
|
import { Drawer, Form, Input, Card, Space, Button, Upload, Popconfirm, Modal, FormListOperation, FormListFieldData } from 'antd' |
|
|
|
import { Drawer, Form, Input, Card, Space, Button, Upload, Popconfirm, Modal, FormListOperation, FormListFieldData, Tooltip } from 'antd' |
|
|
|
import type { RcFile, UploadProps } from 'antd/es/upload'; |
|
|
|
import type { UploadFile } from 'antd/es/upload/interface'; |
|
|
|
import './editor.css'; |
|
|
|
|
|
|
|
const layout = { |
|
|
|
labelCol: { span: 4, }, |
|
|
|
wrapperCol: { span: 16 }, |
|
|
|
labelCol: { span: 5, }, |
|
|
|
wrapperCol: { span: 15 }, |
|
|
|
}; |
|
|
|
|
|
|
|
interface AttributeValue { |
|
|
|
id: number; |
|
|
|
attrId: number; |
|
|
|
id?: number; |
|
|
|
attrId?: number; |
|
|
|
valName: string; |
|
|
|
imgId?: number; |
|
|
|
imgUrl?: string; |
|
|
@@ -29,7 +29,6 @@ export interface SampleAttribute { |
|
|
|
interface CreateSampleAttrProps { |
|
|
|
visible: boolean; |
|
|
|
onCancel: (flag?: boolean) => void; |
|
|
|
curRecord?: SampleAttribute[] | null; |
|
|
|
onSave: () => void; |
|
|
|
editData?: SampleAttribute[] | null; |
|
|
|
} |
|
|
@@ -45,7 +44,7 @@ const getBase64 = (file: RcFile): Promise<string> => |
|
|
|
|
|
|
|
const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => { |
|
|
|
|
|
|
|
const { visible, onCancel, curRecord, onSave, editData } = props; |
|
|
|
const { visible, onCancel, onSave, editData } = props; |
|
|
|
const [saveLoading, setSaveLoading] = useState(false); |
|
|
|
const [previewOpen, setPreviewOpen] = useState(false); |
|
|
|
const [previewImage, setPreviewImage] = useState(''); |
|
|
@@ -61,6 +60,9 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => { |
|
|
|
}, [visible]); |
|
|
|
|
|
|
|
async function setInitValue() { |
|
|
|
if (editData) { |
|
|
|
form.setFieldsValue({ attrData: editData }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const save = async (values: any) => { |
|
|
@@ -92,64 +94,59 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => { |
|
|
|
// setFileList(newFileList); |
|
|
|
} |
|
|
|
|
|
|
|
// const [fileList, setFileList] = useState<UploadFile[]>([ |
|
|
|
// { |
|
|
|
// uid: '-1', |
|
|
|
// name: 'image.png', |
|
|
|
// status: 'done', |
|
|
|
// url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png', |
|
|
|
// }, |
|
|
|
// ]); |
|
|
|
|
|
|
|
|
|
|
|
const readerAttrValueEditForm = (subFields: FormListFieldData[], attrVals: AttributeValue[], { remove, add }: FormListOperation, isContainImg: boolean) => { |
|
|
|
return (<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}> |
|
|
|
{subFields.map((subField) => { |
|
|
|
const item = attrVals[subField.key]; |
|
|
|
const uploadFile: UploadFile | null = item.imgUrl && item.imgId ? { |
|
|
|
uid: `${item.imgId}`, |
|
|
|
name: '', |
|
|
|
status: 'done', |
|
|
|
url: item.imgUrl |
|
|
|
} : null |
|
|
|
const fileList: UploadFile[] = []; |
|
|
|
if(uploadFile) { |
|
|
|
fileList.push(uploadFile) |
|
|
|
} |
|
|
|
return ( |
|
|
|
<Space key={subField.key}> |
|
|
|
<Form.Item noStyle name={[subField.name, 'valName']}> |
|
|
|
<Input size='middle' /> |
|
|
|
</Form.Item> |
|
|
|
{isContainImg && <Form.Item noStyle shouldUpdate name={[subField.name, 'imgUrl']}> |
|
|
|
<Upload |
|
|
|
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188" |
|
|
|
listType="picture-card" |
|
|
|
onPreview={handlePreview} |
|
|
|
onChange={handleChange} |
|
|
|
maxCount={1} |
|
|
|
defaultFileList={[...fileList]} |
|
|
|
> |
|
|
|
{fileList.length > 0 ? null : uploadButton} |
|
|
|
</Upload> |
|
|
|
return ( |
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}> |
|
|
|
{subFields.map((subField) => { |
|
|
|
const item = attrVals[subField.key]; |
|
|
|
const uploadFile: UploadFile | null = item && item.imgUrl && item.imgId ? { |
|
|
|
uid: `${item.imgId}`, |
|
|
|
name: '', |
|
|
|
status: 'done', |
|
|
|
url: item.imgUrl |
|
|
|
} : null |
|
|
|
const fileList: UploadFile[] = []; |
|
|
|
if (uploadFile) { |
|
|
|
fileList.push(uploadFile) |
|
|
|
} |
|
|
|
return ( |
|
|
|
<Form.Item {...subField} style={{marginBottom: 0}}> |
|
|
|
<Space key={subField.key}> |
|
|
|
<Form.Item noStyle name={[subField.name, 'valName']}> |
|
|
|
<Input size='middle' /> |
|
|
|
</Form.Item> |
|
|
|
{isContainImg && <Form.Item noStyle shouldUpdate name={[subField.name, 'imgUrl']}> |
|
|
|
<Upload className='attr-image' |
|
|
|
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188" |
|
|
|
listType="picture-card" |
|
|
|
onPreview={handlePreview} |
|
|
|
onChange={handleChange} |
|
|
|
maxCount={1} |
|
|
|
defaultFileList={[...fileList]} |
|
|
|
> |
|
|
|
{fileList.length > 0 ? null : uploadButton} |
|
|
|
</Upload> |
|
|
|
</Form.Item> |
|
|
|
} |
|
|
|
<Popconfirm |
|
|
|
title="删除属性值" |
|
|
|
description="确认是否删除当前属性值?" |
|
|
|
onConfirm={() => { remove(subField.name); }} |
|
|
|
okText="确认" |
|
|
|
cancelText="取消" |
|
|
|
> |
|
|
|
<Tooltip title="删除属性值"> |
|
|
|
<DeleteOutlined className='delete-icon'/> |
|
|
|
</Tooltip> |
|
|
|
</Popconfirm> |
|
|
|
</Space> |
|
|
|
</Form.Item> |
|
|
|
} |
|
|
|
<Popconfirm |
|
|
|
title="删除属性值" |
|
|
|
description="确认是否删除当前属性值?" |
|
|
|
onConfirm={() => { remove(subField.name); }} |
|
|
|
okText="确认" |
|
|
|
cancelText="取消" |
|
|
|
> |
|
|
|
<DeleteOutlined /> |
|
|
|
</Popconfirm> |
|
|
|
</Space> |
|
|
|
) |
|
|
|
})} |
|
|
|
<Button type="dashed" size='middle' onClick={() => add()} block> |
|
|
|
+ 添加自定义值 |
|
|
|
</Button> |
|
|
|
</div>) |
|
|
|
) |
|
|
|
})} |
|
|
|
<Button type="dashed" size='middle' onClick={() => add({ valName: '', imgUrl: '', imgId: 0 })} block> |
|
|
|
+ 添加自定义值 |
|
|
|
</Button> |
|
|
|
</div>) |
|
|
|
} |
|
|
|
|
|
|
|
const renderAttrEditForm = (fields: FormListFieldData[], { remove, add }: FormListOperation, dataSource: SampleAttribute[]) => { |
|
|
@@ -158,35 +155,47 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => { |
|
|
|
{fields.map((field) => { |
|
|
|
const data = dataSource[field.key]; |
|
|
|
return ( |
|
|
|
<Card size="small" title={field.name} key={field.key} |
|
|
|
extra={ |
|
|
|
<Popconfirm |
|
|
|
title="删除属性" |
|
|
|
description="确认是否删除当前属性?" |
|
|
|
onConfirm={() => { remove(field.name); }} |
|
|
|
okText="确认" |
|
|
|
cancelText="取消" |
|
|
|
> |
|
|
|
<CloseOutlined style={{ fontSize: '16px' }} className='hover:(bg-[rgb(94,53,177)]' /> |
|
|
|
</Popconfirm> |
|
|
|
} |
|
|
|
> |
|
|
|
<Form.Item label="属性名称" name={[field.name, 'attrName']}> |
|
|
|
<Input size='middle' /> |
|
|
|
</Form.Item> |
|
|
|
|
|
|
|
<Form.Item label="属性值"> |
|
|
|
<Form.List name={[field.name, 'attrVals']}> |
|
|
|
{(subFields, subOpt) => { |
|
|
|
return readerAttrValueEditForm(subFields, data.attrVals, subOpt, data.isContainImg === 1) |
|
|
|
}} |
|
|
|
</Form.List> |
|
|
|
</Form.Item> |
|
|
|
</Card> |
|
|
|
<Form.Item {...field} style={{marginBottom: 4}}> |
|
|
|
<Card size="small" title={field.name} key={field.key} |
|
|
|
style={{ width: 500 }} |
|
|
|
extra={ |
|
|
|
<Popconfirm |
|
|
|
title="删除属性" |
|
|
|
description="确认是否删除当前属性?" |
|
|
|
onConfirm={() => { remove(field.name); }} |
|
|
|
okText="确认" |
|
|
|
cancelText="取消" |
|
|
|
> |
|
|
|
<Tooltip title="删除属性"> |
|
|
|
<CloseOutlined style={{ fontSize: '16px' }} className='delete-icon' /> |
|
|
|
</Tooltip> |
|
|
|
</Popconfirm> |
|
|
|
} |
|
|
|
> |
|
|
|
<Form.Item label="属性名称" name={[field.name, 'attrName']} labelCol={{ span: 4 }}> |
|
|
|
<Input size='middle' /> |
|
|
|
</Form.Item> |
|
|
|
|
|
|
|
<Form.Item label="属性值" labelCol={{ span: 4 }}> |
|
|
|
<Form.List name={[field.name, 'attrVals']}> |
|
|
|
{(subFields, subOpt) => { |
|
|
|
return readerAttrValueEditForm(subFields, data.attrVals, subOpt, data.isContainImg === 1) |
|
|
|
}} |
|
|
|
</Form.List> |
|
|
|
</Form.Item> |
|
|
|
</Card> |
|
|
|
</Form.Item> |
|
|
|
|
|
|
|
) |
|
|
|
})} |
|
|
|
|
|
|
|
<Button type="dashed" size='middle' onClick={() => add()} block> |
|
|
|
<Button type="dashed" size='middle' onClick={() => add({ |
|
|
|
"prototypeId": 88, |
|
|
|
"attrName": "", |
|
|
|
"isContainImg": 1, |
|
|
|
"attrVals": [ |
|
|
|
] |
|
|
|
},)} block> |
|
|
|
+ 添加属性 |
|
|
|
</Button> |
|
|
|
</div> |
|
|
@@ -212,15 +221,12 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => { |
|
|
|
<Form |
|
|
|
form={form} |
|
|
|
{...layout} |
|
|
|
initialValues={{ editData }} |
|
|
|
onFinish={save} |
|
|
|
labelCol={{ flex: '0 0 100px' }} |
|
|
|
wrapperCol={{ span: 16 }} |
|
|
|
> |
|
|
|
<Form.List name="editData"> |
|
|
|
{(fields, operation) => { |
|
|
|
return renderAttrEditForm(fields, operation, editData!!) |
|
|
|
}} |
|
|
|
<Form.List name="attrData"> |
|
|
|
{(fields, operation) => renderAttrEditForm(fields, operation, form.getFieldsValue()['attrData'])} |
|
|
|
</Form.List> |
|
|
|
|
|
|
|
</Form> |
|
|
|