Browse Source

update:attr editor

dev
powersir 1 year ago
parent
commit
d2b53c7450
2 changed files with 148 additions and 92 deletions
  1. +117
    -92
      src/pages/custom/product/sample/components/attr-editor.tsx
  2. +31
    -0
      src/pages/custom/product/sample/components/editor.css

+ 117
- 92
src/pages/custom/product/sample/components/attr-editor.tsx View File

@@ -3,11 +3,11 @@ 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 } from 'antd'
import type { RcFile, UploadProps } from 'antd/es/upload'; import type { RcFile, UploadProps } from 'antd/es/upload';
import type { UploadFile } from 'antd/es/upload/interface'; import type { UploadFile } from 'antd/es/upload/interface';
import './editor.css';


const layout = { const layout = {
labelCol: { span: 4, },
labelCol: { span: 4, },
wrapperCol: { span: 16 }, wrapperCol: { span: 16 },
bordered: false,
}; };


interface AttributeValue { interface AttributeValue {
@@ -83,89 +83,114 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => {
}; };


const uploadButton = ( const uploadButton = (
<div>
<div className='flex'>
<PlusOutlined /> <PlusOutlined />
<div style={{ marginTop: 8 }}>上传</div>
<div style={{ marginLeft: 8 }}>上传</div>
</div> </div>
); );
const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => { const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
// setFileList(newFileList);
} }


const readerAttrValueEditForm = (subFields: FormListFieldData[], {remove, add}: FormListOperation, isContainImg: boolean) => {
// 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 }}> return (<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}>
{subFields.map((subField) => (
<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}
showUploadList={false}
maxCount={1}
>
{uploadButton}
</Upload>
</Form.Item>
{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)
} }
<Popconfirm
title="删除属性值"
description="确认是否删除当前属性值?"
onConfirm={() => { remove(subField.name); }}
okText="确认"
cancelText="取消"
>
<CloseOutlined/>
</Popconfirm>
</Space>
))}
<Button type="dashed" size='middle' onClick={() => add()} block>
+ 添加自定义值
</Button>
</div>)
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>
</Form.Item>
}
<Popconfirm
title="删除属性值"
description="确认是否删除当前属性值?"
onConfirm={() => { remove(subField.name); }}
okText="确认"
cancelText="取消"
>
<DeleteOutlined />
</Popconfirm>
</Space>
)
})}
<Button type="dashed" size='middle' onClick={() => add()} block>
+ 添加自定义值
</Button>
</div>)
} }


const renderAttrEditForm = (fields: FormListFieldData[], {remove, add}: FormListOperation, dataSource: SampleAttribute[]) => {
return (
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
{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="取消"
>
<DeleteOutlined 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) => readerAttrValueEditForm(subFields, subOpt, data.isContainImg === 1)}
</Form.List>
</Form.Item>
</Card>
)})}

<Button type="dashed" size='middle' onClick={() => add()} block>
+ 添加属性
</Button>
</div>
)
const renderAttrEditForm = (fields: FormListFieldData[], { remove, add }: FormListOperation, dataSource: SampleAttribute[]) => {
return (
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
{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>
)
})}

<Button type="dashed" size='middle' onClick={() => add()} block>
+ 添加属性
</Button>
</div>
)
} }


return ( return (
@@ -177,29 +202,29 @@ const SampleAttrEditor: React.FC<CreateSampleAttrProps> = (props) => {
onClose={() => { onCancel() }} onClose={() => { onCancel() }}
extra={ extra={
<Space> <Space>
<Button type="primary" size='middle' onClick={() => {save}}>
<Button type="primary" size='middle' onClick={() => { save }}>
保存 保存
</Button> </Button>
</Space> </Space>
} }
destroyOnClose destroyOnClose
> >
<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>
</Form>
</Drawer>
<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>
</Form>
</Drawer>
<Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handleCancel}> <Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handleCancel}>
<img alt="example" style={{ width: '100%' }} src={previewImage} /> <img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal> </Modal>


+ 31
- 0
src/pages/custom/product/sample/components/editor.css View File

@@ -0,0 +1,31 @@
:where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-circle-wrapper .ant-upload.ant-upload-select {
height: 40px;
margin-inline-end: 8px;
margin-bottom: 0;
text-align: center;
vertical-align: top;
background-color: rgba(0, 0, 0, 0.02);
border: 1px dashed #d9d9d9;
border-radius: 4px;
cursor: pointer;
transition: border-color 0.3s;
}


:where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item-container, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-circle-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item-container, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload-list.ant-upload-list-picture-circle .ant-upload-list-item-container, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper.ant-upload-picture-circle-wrapper .ant-upload-list.ant-upload-list-picture-circle .ant-upload-list-item-container {
display: inline-block;
width: 40px;
height: 40px;
margin-block: 0 8px;
margin-inline: 0 8px;
margin: 0 2px;
vertical-align: top;
}


:where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper .ant-upload-list.ant-upload-list-picture .ant-upload-list-item, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item, :where(.css-dev-only-do-not-override-11asvft).ant-upload-wrapper .ant-upload-list.ant-upload-list-picture-circle .ant-upload-list-item {
position: relative;
padding: 1px;
border: 1px solid #d9d9d9;
border-radius: 2px;
}

Loading…
Cancel
Save