diff --git a/package.json b/package.json index ae72266..0b5400b 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "@dnd-kit/utilities": "^3.2.2", "@umijs/route-utils": "^2.2.2", "antd": "^5.2.2", + "antd-img-crop": "^4.23.0", "braft-editor": "^2.3.9", "classnames": "^2.3.2", "lodash": "^4.17.21", diff --git a/src/pages/BusinessList/add.tsx b/src/pages/BusinessList/add.tsx index 706b70a..a4b42d8 100644 --- a/src/pages/BusinessList/add.tsx +++ b/src/pages/BusinessList/add.tsx @@ -14,9 +14,43 @@ import { } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-layout'; import { Button, Col, message, Row } from 'antd'; -import Upload, { RcFile } from 'antd/es/upload'; +import Upload, { RcFile, UploadFile } from 'antd/es/upload'; import moment from 'moment'; import React, { useRef, useState } from 'react'; +import { CSS } from '@dnd-kit/utilities'; +import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'; +import { DndContext, DragEndEvent, PointerSensor, useSensor } from '@dnd-kit/core'; + +interface DraggableUploadListItemProps { + originNode: React.ReactElement>; + file: UploadFile; +} + +const DraggableUploadListItem = ({ originNode, file }: DraggableUploadListItemProps) => { + let { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ + id: file.uid, + }); + + const style: React.CSSProperties = { + transform: CSS.Translate.toString(transform), + transition, + cursor: 'move', + }; + + return ( +
+ {/* hide error tooltip when dragging */} + {file.status === 'error' && isDragging ? originNode.props.children : originNode} +
+ ); +}; const Detail: React.FC = () => { const [cities] = useState(() => getCities()) @@ -55,6 +89,20 @@ const Detail: React.FC = () => { } } + const sensor = useSensor(PointerSensor, { + activationConstraint: { distance: 10 }, + }); + + const onDragEnd = ({ active, over }: DragEndEvent, fieldName: string) => { + if (active.id !== over?.id) { + const arr = formRef.current?.getFieldValue(fieldName) || [] + const activeIndex = arr.findIndex((i: any) => i.uid === active.id); + const overIndex = arr.findIndex((i: any) => i.uid === over?.id); + const newArr = arrayMove(arr, activeIndex, overIndex) + formRef.current?.setFieldValue(fieldName, newArr) + } + }; + return ( = () => { - { - - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - listType: 'picture-card', - }} - rules={[ - { required: true, message: '请上传商户图片' }, - ]} - /> + onDragEnd(event, "pbcBusinessImage")}> + i.uid) : []} strategy={verticalListSortingStrategy}> + , + action: process.env.BASE_URL + '/oss/imgUpload', + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M || Upload.LIST_IGNORE; + }, + onPreview: async (file) => { + + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + listType: 'picture-card', + }} + rules={[ + { required: true, message: '请上传商户图片' }, + ]} + /> + + - { - - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - listType: 'picture-card', - }} - rules={[ - { required: true, message: '请上传商户海报' }, - ]} - /> + onDragEnd(event, "pbcBusinessPosterUrl")}> + i.uid) : []} strategy={verticalListSortingStrategy}> + , + action: process.env.BASE_URL + '/oss/imgUpload', + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M || Upload.LIST_IGNORE; + }, + onPreview: async (file) => { + + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + listType: 'picture-card', + }} + rules={[ + { required: true, message: '请上传商户海报' }, + ]} + /> + + @@ -395,38 +455,44 @@ const Detail: React.FC = () => { - { - - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - listType: 'picture-card', - }} - rules={[ - { required: true, message: '请上传营业执照' }, - ]} - /> + onDragEnd(event, "pbcBusinessLicenseUrl")}> + i.uid) : []} strategy={verticalListSortingStrategy}> + , + action: process.env.BASE_URL + '/oss/imgUpload', + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M || Upload.LIST_IGNORE; + }, + onPreview: async (file) => { + + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + listType: 'picture-card', + }} + rules={[ + { required: true, message: '请上传营业执照' }, + ]} + /> + + diff --git a/src/pages/BusinessList/detail.tsx b/src/pages/BusinessList/detail.tsx index 62de7dd..2681cd0 100644 --- a/src/pages/BusinessList/detail.tsx +++ b/src/pages/BusinessList/detail.tsx @@ -12,11 +12,44 @@ import { ProFormUploadButton, } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-layout'; +import { DndContext, DragEndEvent, PointerSensor, useSensor } from '@dnd-kit/core'; +import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { useAccess, useParams, useSearchParams } from '@umijs/max'; -import { Button, Image, message, Tag } from 'antd'; -import { RcFile } from 'antd/es/upload'; +import { Button, Form, Image, message, Tag } from 'antd'; +import { RcFile, UploadFile } from 'antd/es/upload'; import React, { useEffect, useState } from 'react'; +import { CSS } from '@dnd-kit/utilities'; +interface DraggableUploadListItemProps { + originNode: React.ReactElement>; + file: UploadFile; +} + +const DraggableUploadListItem = ({ originNode, file }: DraggableUploadListItemProps) => { + let { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ + id: file.uid, + }); + + const style: React.CSSProperties = { + transform: CSS.Translate.toString(transform), + transition, + cursor: 'move', + }; + + return ( +
+ {/* hide error tooltip when dragging */} + {file.status === 'error' && isDragging ? originNode.props.children : originNode} +
+ ); +}; const Detail: React.FC = () => { const params = useParams(); const [searchParams] = useSearchParams(); @@ -25,6 +58,7 @@ const Detail: React.FC = () => { const [cities] = useState(() => getCities()) const [info, setInfo] = useState({}); + const [form1] = Form.useForm(); const getInfo = () => { if (params.id) { @@ -40,6 +74,20 @@ const Detail: React.FC = () => { getInfo(); }, []); + const sensor = useSensor(PointerSensor, { + activationConstraint: { distance: 10 }, + }); + + const onDragEnd = ({ active, over }: DragEndEvent, fieldName: string) => { + if (active.id !== over?.id) { + const arr = form1.getFieldValue(fieldName) || [] + const activeIndex = arr.findIndex((i: any) => i.uid === active.id); + const overIndex = arr.findIndex((i: any) => i.uid === over?.id); + const newArr = arrayMove(arr, activeIndex, overIndex) + form1.setFieldValue(fieldName, newArr) + } + }; + return ( = () => { ); }, - renderFormItem: (text, props) => { + renderFormItem: (text, props: any) => { + console.log(props.id) return ( - } - title={
点击上传图片
} - fieldProps={{ - name: 'file', - accept: 'image/*', - listType: 'picture-card', - headers: { - authorization: localStorage.getItem('token') ?? '', - }, - beforeUpload(file: RcFile) { - const isLt2M = file.size / 1024 / 1024 < 10; - if (!isLt2M) { - message.error('图片大小不能超过10MB!'); - } - return isLt2M; - }, - onPreview: async (file) => { - console.log(file); - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - }} - action={process.env.BASE_URL + '/oss/imgUpload'} - onChange={(a: any) => { - props?.fieldProps.onChange(a.fileList); - }} - /> + onDragEnd(event, props.id)}> + i.uid) : []} strategy={verticalListSortingStrategy}> + } + title={
点击上传图片
} + fieldProps={{ + name: 'file', + accept: 'image/*', + multiple: true, + listType: 'picture-card', + headers: { + authorization: localStorage.getItem('token') ?? '', + }, + itemRender: (originNode, file) => , + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M; + }, + onPreview: async (file) => { + console.log(file); + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + }} + action={'/oss/imgUpload'} + onChange={(a: any) => { + props?.fieldProps.onChange(a.fileList); + }} + /> +
+
); }, }, @@ -113,6 +168,7 @@ const Detail: React.FC = () => { editable={ access.businessSave && isEdit ? { + form: form1, onSave: async (key, record: any, originRow) => { let pbcState = record.pbcState; let pbcBusinessLogo = ""; @@ -348,8 +404,9 @@ const Detail: React.FC = () => { valueTypeMap={{ upload: { render: (text) => { - return text.length > 0 ? ( - + console.log(text) + return text.length > 0 ? text.map((e: any) => + ) : ( ); @@ -361,10 +418,10 @@ const Detail: React.FC = () => { {...props?.fieldProps} icon={} title={
点击上传图片
} - max={1} fieldProps={{ name: 'file', accept: 'image/*', + multiple: true, listType: 'picture-card', headers: { authorization: localStorage.getItem('token') ?? '', @@ -386,7 +443,7 @@ const Detail: React.FC = () => { } }, }} - action={process.env.BASE_URL + '/oss/imgUpload'} + action={'/oss/imgUpload'} onChange={(a: any) => { props?.fieldProps.onChange(a.fileList); }} @@ -426,20 +483,19 @@ const Detail: React.FC = () => { }, ] : [], - pbcBusinessLicenseUrl: info.pbcBusinessLicenseUrl - ? [ - { - uid: '-1', - name: 'image.png', - status: 'done', - url: info.pbcBusinessLicenseUrl, - }, - ] - : [], + pbcBusinessLicenseUrl: info.pbcBusinessLicenseUrl ? info.pbcBusinessLicenseUrl.split(',').map((e, index) => { + return { + uid: '-' + (index+1), + name: 'image.png', + status: 'done', + url: e, + } + }) : [], }} editable={ access.businessSave && isEdit ? { + form: form1, onSave: async (key, record: any, originRow) => { let pbcBusinessHeadUserNoFrontUrl = ""; if ( @@ -467,17 +523,20 @@ const Detail: React.FC = () => { pbcBusinessHeadUserNoBackUrl = record[key][0].response.data; } } - let pbcBusinessLicenseUrl = ""; + const pbcBusinessLicenseUrl = []; if ( key === 'pbcBusinessLicenseUrl' && record[key] && record[key].length > 0 ) { - if (record[key][0].uid === '-1') { - pbcBusinessLicenseUrl = record[key][0].url; - } - if (record[key][0].response && record[key][0].response.retcode) { - pbcBusinessLicenseUrl = record[key][0].response.data; + for (let i = 0; i < record[key].length; i++) { + const element = record[key][i]; + if (element.uid === '-1') { + pbcBusinessLicenseUrl.push(element.url) + } + if (element.response && element.response.retcode) { + pbcBusinessLicenseUrl.push(element.response.data) + } } } await adminChangeBusinessInfoUsingPost({ @@ -489,7 +548,7 @@ const Detail: React.FC = () => { pbcBusinessHeadUserNoBackUrl: key === 'pbcBusinessHeadUserNoBackUrl' ? pbcBusinessHeadUserNoBackUrl : undefined, pbcBusinessLicenseUrl: - key === 'pbcBusinessLicenseUrl' ? pbcBusinessLicenseUrl : undefined, + key === 'pbcBusinessLicenseUrl' ? pbcBusinessLicenseUrl.join(',') : undefined, }) .then((res) => { if (res.retcode) { @@ -545,6 +604,9 @@ const Detail: React.FC = () => { key: 'pbcBusinessHeadUserNoBackUrl', dataIndex: 'pbcBusinessHeadUserNoBackUrl', span: 1, + fieldProps: { + max: 1 + }, valueType: 'upload', }, { @@ -552,6 +614,9 @@ const Detail: React.FC = () => { key: 'pbcBusinessHeadUserNoFrontUrl', dataIndex: 'pbcBusinessHeadUserNoFrontUrl', span: 2, + fieldProps: { + max: 1 + }, valueType: 'upload', }, { diff --git a/src/pages/ProductList/add.tsx b/src/pages/ProductList/add.tsx index 9b3cd96..ec99c4e 100644 --- a/src/pages/ProductList/add.tsx +++ b/src/pages/ProductList/add.tsx @@ -5,7 +5,6 @@ import { getRecordByL3CategoryIdUsingGet } from '@/services/pop-b2b2c/pbcCommonD import { addOrUpdateProductForAdminUsingPost } from '@/services/pop-b2b2c/pbcProductController'; import { getCities } from '@/utils/cities'; import { - FormListActionType, ProCard, ProForm, ProFormCascader, @@ -18,9 +17,43 @@ import { ProFormUploadButton, } from '@ant-design/pro-components'; import { PageContainer } from '@ant-design/pro-layout'; +import { DndContext, DragEndEvent, PointerSensor, useSensor } from '@dnd-kit/core'; +import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { Button, Col, message, Row } from 'antd'; -import Upload, { RcFile } from 'antd/es/upload'; +import Upload, { RcFile, UploadFile } from 'antd/es/upload'; import React, { useRef, useState } from 'react'; +import { CSS } from '@dnd-kit/utilities'; + +interface DraggableUploadListItemProps { + originNode: React.ReactElement>; + file: UploadFile; +} + +const DraggableUploadListItem = ({ originNode, file }: DraggableUploadListItemProps) => { + let { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ + id: file.uid, + }); + + const style: React.CSSProperties = { + transform: CSS.Translate.toString(transform), + transition, + cursor: 'move', + }; + + return ( +
+ {/* hide error tooltip when dragging */} + {file.status === 'error' && isDragging ? originNode.props.children : originNode} +
+ ); +}; const Detail: React.FC = () => { const [cities] = useState(() => getCities()) @@ -63,7 +96,7 @@ const Detail: React.FC = () => { console.log(values.colorItems) console.log(values.specItems) const specItems: API.PbcProductCommonData[] = [] - if (colorData != null && values.colorItems && values.colorItems.length > 0) { + if (colorData && values.colorItems && values.colorItems.length > 0) { for (let i = 0; i < values.colorItems.length; i++) { const element = values.colorItems[i]; specItems.push({ @@ -75,7 +108,7 @@ const Detail: React.FC = () => { }) } } - if (commonDataList != null) { + if (commonDataList) { for (let i = 0; i < commonDataList.length; i++) { const element = commonDataList[i]; console.log(values[`value${i}`]) @@ -119,6 +152,20 @@ const Detail: React.FC = () => { } } + const sensor = useSensor(PointerSensor, { + activationConstraint: { distance: 10 }, + }); + + const onDragEnd = ({ active, over }: DragEndEvent, fieldName: string) => { + if (active.id !== over?.id) { + const arr = formRef.current?.getFieldValue(fieldName) || [] + const activeIndex = arr.findIndex((i: any) => i.uid === active.id); + const overIndex = arr.findIndex((i: any) => i.uid === over?.id); + const newArr = arrayMove(arr, activeIndex, overIndex) + formRef.current?.setFieldValue(fieldName, newArr) + } + }; + return ( = () => { ]} /> - {colorData != null ? + {colorData ? = () => { : null} - { - - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - listType: 'picture-card', - }} - rules={[ - { required: true, message: '请上传相册图' }, - ]} - /> + onDragEnd(event, "pbcProductImages")}> + i.uid) : []} strategy={verticalListSortingStrategy}> + , + action: process.env.BASE_URL + '/oss/imgUpload', + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M || Upload.LIST_IGNORE; + }, + onPreview: async (file) => { + + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + listType: 'picture-card', + }} + rules={[ + { required: true, message: '请上传相册图' }, + ]} + /> + + - { - - if (file.uid === '-1') { - window.open(file.url); - } - if (file.response && file.response.retcode) { - window.open(file.response.data); - } - }, - listType: 'picture-card', - }} - rules={[ - { required: true, message: '请上传详情图' }, - ]} - /> + onDragEnd(event, "pbcProductDetailImages")}> + i.uid) : []} strategy={verticalListSortingStrategy}> + , + action: process.env.BASE_URL + '/oss/imgUpload', + beforeUpload(file: RcFile) { + const isLt2M = file.size / 1024 / 1024 < 10; + if (!isLt2M) { + message.error('图片大小不能超过10MB!'); + } + return isLt2M || Upload.LIST_IGNORE; + }, + onPreview: async (file) => { + + if (file.uid === '-1') { + window.open(file.url); + } + if (file.response && file.response.retcode) { + window.open(file.response.data); + } + }, + listType: 'picture-card', + }} + rules={[ + { required: true, message: '请上传详情图' }, + ]} + /> + + - {commonDataList != null ? commonDataList.map((e, index) => + {commonDataList ? commonDataList.map((e, index) => = (props) => { onFinish={(value) => { let pbcCategoryImage = "" if (value.pbcCategoryImage && value.pbcCategoryImage.length > 0) { - if (value.pbcCategoryImage[0].uid == '-1') { + if (value.pbcCategoryImage[0].uid === '-1') { pbcCategoryImage = value.pbcCategoryImage[0].url; } if (