Commit 41cdb462 authored by 武广's avatar 武广

feat: 添加列表排序

parent 44956568
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -7,7 +7,7 @@ import styles from '../../style.less';
const ItemTypes = {
CARD: 'card',
};
const DragTag = ({ text, id, index, changePosition, selected, groupEdit, changeGroup }) => {
const DragTag = ({ text, id, index, changePosition }) => {
const [isEdit, setIsEdit] = useState(false);
const [inputValue, setInputValue] = useState('');
const refInput = useRef();
......@@ -82,7 +82,7 @@ const DragTag = ({ text, id, index, changePosition, selected, groupEdit, changeG
}}
>
<HolderOutlined className={styles['groupBox-body--tag__move']} />
<span>{text}</span>
<span className={styles['groupBox-body--tag__text']}>{text}</span>
<span>
<FormOutlined className={styles['groupBox-body--tag__edit']} onClick={handleEdit} />
</span>
......
import React, { useState } from 'react';
import { Button, Modal, message, notification, Tag } from 'antd';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import styles from '../../style.less';
import DragTag from './DragTag';
import InsertTag from './InsertTag';
const GoodsGroup = options => {
const [groupEdit, setGroupEdit] = useState(false);
const [selected, setSelected] = useState(0);
const [tags, setTags] = useState([
{
id: 0,
text: '000',
},
{
id: 1,
text: '111',
},
{
id: 2,
text: '000',
},
{
id: 3,
text: '111',
},
{
id: 4,
text: '000',
},
{
id: 5,
text: '111',
},
]);
const changePosition = (dragIndex, hoverIndex) => {
const data = tags.slice();
const temp = data[dragIndex];
// 交换位置
data[dragIndex] = data[hoverIndex];
data[hoverIndex] = temp;
setTags(data);
};
return (
<div className={styles.groupBox}>
<div className={styles['groupBox-title']}>
<div>商品分组</div>
<Button className={styles['groupBox-btn']} onClick={() => setGroupEdit(!groupEdit)}>
{groupEdit ? '完成' : '编辑分组'}
</Button>
</div>
<div className={styles['groupBox-body']}>
{groupEdit ? (
<DndProvider backend={HTML5Backend}>
<div className={styles['groupBox-body--dragbox']}>
{tags.map((item, index) => (
<DragTag
changePosition={changePosition}
index={index}
{...item}
selected={selected}
changeGroup={e => setSelected(e)}
key={item.id}
/>
))}
<InsertTag />
</div>
</DndProvider>
) : (
<div className={styles['groupBox-body--dragbox']}>
{tags.map((item, index) => (
<Tag
onClick={() => setSelected(index)}
className={[
styles['groupBox-body--tag-normal'],
selected === index ? styles['groupBox-body--tag__cur'] : '',
]}
>
<span className={styles['groupBox-body--tag__text']}>{item.text}</span>
</Tag>
))}
<InsertTag />
</div>
)}
</div>
</div>
);
};
export default GoodsGroup;
......@@ -41,6 +41,7 @@ const InsertTag = options => {
{!inputVisible && (
<Tag
className={[styles['groupBox-body--tag'], styles['groupBox-body--new']]}
color="blue"
onClick={showInput}
>
<PlusOutlined /> 添加
......
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { Spin, Button, Modal, message, notification, Tag } from 'antd';
import { PlusOutlined, HolderOutlined, FormOutlined, CloseCircleOutlined } from '@ant-design/icons';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { Spin, Table, Modal, message, notification } from 'antd';
import { MenuOutlined, HolderOutlined, FormOutlined, CloseCircleOutlined } from '@ant-design/icons';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';
import GoodsGroup from './components/GoodsGroup';
import { searchList } from '../service';
import styles from '../style.less';
import DragTag from './components/DragTag';
import InsertTag from './components/InsertTag';
import { takeawayColumn } from '../staticdata';
const Takeaway = options => {
const [groupEdit, setGroupEdit] = useState(false);
const [selected, setSelected] = useState(0);
const actionRef = useRef(null);
const [tableData, setTableData] = useState([]);
const [loading, setLoading] = useState(false);
const rowSelection = {};
const DragHandle = SortableHandle(() => (
<MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
));
const [tags, setTags] = useState([
{
id: 0,
text: '000',
},
{
id: 1,
text: '111',
},
]);
const onSortEnd = ({ oldIndex, newIndex }) => {
if (oldIndex !== newIndex) {
const newData = arrayMoveImmutable(tableData.slice(), oldIndex, newIndex).filter(el => !!el);
setTableData(newData);
}
};
const SortableItem = SortableElement(props => <tr {...props} />);
const SortableBody = SortableContainer(props => <tbody {...props} />);
const DraggableContainer = props => (
<SortableBody
useDragHandle
disableAutoscroll
helperClass={styles['row-dragging']}
onSortEnd={onSortEnd}
{...props}
/>
);
const getDataList = async () => {
setLoading(true);
const res = await searchList({ productType: 1 });
setLoading(false);
if (res && res.data) {
setTableData(res.data.records);
}
};
const changePosition = (dragIndex, hoverIndex) => {
const data = tags.slice();
const temp = data[dragIndex];
// 交换位置
data[dragIndex] = data[hoverIndex];
data[hoverIndex] = temp;
setTags(data);
const DraggableBodyRow = ({ className, style, ...restProps }) => {
// function findIndex base on Table rowKey props and should always be a right array index
const index = tableData.findIndex(x => x.skuId === restProps['data-row-key']);
return <SortableItem index={index} {...restProps} />;
};
useEffect(() => {
getDataList();
}, []);
return (
<div className={styles.takeawayBox}>
<div className={styles.groupBox}>
<div className={styles['groupBox-title']}>
<div>商品分组</div>
<Button className={styles['groupBox-btn']} onClick={() => setGroupEdit(!groupEdit)}>
{groupEdit ? '完成' : '编辑分组'}
</Button>
</div>
<div className={styles['groupBox-body']}>
{groupEdit ? (
<DndProvider backend={HTML5Backend}>
<div className={styles['groupBox-body--dragbox']}>
{tags.map((item, index) => (
<DragTag
changePosition={changePosition}
index={index}
{...item}
selected={selected}
changeGroup={e => setSelected(e)}
key={item.id}
<Spin spinning={loading}>
<GoodsGroup />
<Table
dataSource={tableData}
bordered
columns={takeawayColumn.call(this)}
rowKey={record => record.skuId}
pagination={false}
// scroll={{ x: '100%', y: 500 }}
// rowSelection={rowSelection}
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow,
},
}}
/>
))}
<InsertTag />
</div>
</DndProvider>
) : (
<div className={styles['groupBox-body--dragbox']}>
{tags.map((item, index) => (
<Tag
onClick={() => setSelected(index)}
className={[
styles['groupBox-body--tag-normal'],
selected === index ? styles['groupBox-body--tag__cur'] : '',
]}
>
<span>{item.text}</span>
</Tag>
))}
<InsertTag />
</div>
)}
</div>
</div>
</Spin>
</div>
);
};
......
import React from 'react';
import { Button, Badge, Switch, Modal } from 'antd';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { ExclamationCircleOutlined, MenuOutlined } from '@ant-design/icons';
import styles from './style.less';
import { resetTime } from '../../utils/utils';
import { apiChangeStateGoods, apiQueryLastAuditRecord } from './service';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
const { confirm } = Modal;
......@@ -244,6 +245,188 @@ export function column() {
},
];
}
export function takeawayColumn() {
const onChangeState = async ({ skuId, state }) => {
confirm({
icon: <ExclamationCircleOutlined />,
content: `确认${+state === 6 ? '下架' : '上架'}商品?`,
onOk: async () => {
const res = await apiChangeStateGoods({
ids: skuId,
productState: +state === 6 ? 7 : 6, // 6:上架,7:下架
});
if (res.businessCode === '0000' && res.code === '0000') {
this.handleSearch();
}
},
});
};
const onShowAudit = row => {
this.setState({
auditRow: row,
visibleAuditModal: true,
});
};
const DragHandle = SortableHandle(() => (
<MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
));
return [
{
title: '排序',
dataIndex: 'sort',
width: 60,
align: 'center',
className: [styles['drag-visible'], styles['sort-td']],
render: () => <DragHandle />,
},
{
title: 'SKU编码',
dataIndex: 'skuId',
width: 125,
align: 'center',
render: (_, row) => {
if (row.type === 2) {
return (
<Badge
count={
<div
style={{
color: '#fff',
borderRadius: '3px',
background: '#f5222d',
padding: '2px',
fontSize: '10px',
opacity: 0.7,
}}
>
虚拟
</div>
}
>
<div
style={{
background: '#fbfbfb',
borderRadius: '3px',
padding: '2px',
}}
>
{row.skuId}
</div>
</Badge>
);
}
return (
<div
style={{
background: '#fbfbfb',
borderRadius: '3px',
padding: '2px',
}}
>
{row.skuId}
</div>
);
},
},
{
title: 'SKU商品名称',
width: 135,
align: 'center',
dataIndex: 'skuName',
},
{
title: '供应商价格',
dataIndex: 'marketPrice',
width: 150,
align: 'center',
sorter: (a, b) => a.supplyPrice - b.supplyPrice,
render: (_, row) => (
<div className={styles.price}>
<p>供货价:{(row.supplyPrice || 0).toFixed(2)}</p>
<p>市场价:{(row.marketPrice || 0).toFixed(2)}</p>
</div>
),
},
{
title: '库存',
width: 120,
dataIndex: 'stock',
align: 'center',
sorter: (a, b) => a.stock - b.stock,
render: (_, row) => {
// const stockView = row.productStock;
const stockView = (
<Button type="link" onClick={() => this.onShowStockModal(row)} style={{ padding: 0 }}>
{row.productStock}
</Button>
);
return (
<>
<p>当前库存:{stockView}</p>
<p>可售库存:{_}</p>
{row.type === 1 && row.productStockWarning > 0 && (
<p>预警值:{row.productStockWarning}</p>
)}
</>
);
},
},
{
title: '不支持配送区域',
dataIndex: 'areaTemplateName',
key: 'areaTemplateName',
width: 200,
align: 'center',
},
{
title: '上下架状态',
dataIndex: 'stateDesc', // 5:未上架 ,6 :上架,7:下架
width: 200,
align: 'center',
render: (_, row) => (
<div>
{row.type === 4 && row.state >= 5 ? (
<>
<Switch
checkedChildren="已上架"
checked={row.state === 6}
unCheckedChildren="已下架"
onClick={() => onChangeState(row)}
defaultChecked
/>
</>
) : (
'-'
)}
</div>
),
},
{
title: '审核状态',
dataIndex: 'stateDesc',
width: 200,
align: 'center',
render: (_, row) => (
<div>
<p>{row.state >= 5 ? '审核通过' : _}</p>
<div>
{row.updateState ? (
<Button onClick={() => onShowAudit(row)} type="link">
{row.updateStateDesc}
</Button>
) : (
'--'
)}
</div>
</div>
),
},
];
}
export const disSelectStatus = [2, 5];
export const stateList = [
{ value: 3, label: '待审核' },
......
......@@ -136,7 +136,7 @@
background-color: #fff;
}
.groupBox {
padding: 0 24px;
padding: 0 24px 15px 24px;
&-title {
display: flex;
align-items: center;
......@@ -147,15 +147,15 @@
margin-left: 15px;
}
&-body {
padding: 5px 15px;
padding: 5px 0;
&--tag {
position: relative;
box-sizing: border-box;
height: 28px;
height: 34px;
margin-right: 20px;
padding: 0 15px 0 10px;
font-size: 14px;
line-height: 26px;
line-height: 32px;
&__move {
cursor: move;
}
......@@ -173,13 +173,17 @@
transform: translate(50%, -50%);
cursor: pointer;
}
&__text {
user-select: none;
}
}
&--tag-normal {
position: relative;
height: 28px;
padding: 0 10px;
height: 34px;
margin-right: 0;
padding: 0 20px;
font-size: 14px;
line-height: 26px;
line-height: 32px;
cursor: pointer;
}
&--tag-input {
......@@ -193,6 +197,11 @@
border: 1px solid #1890ff;
}
&--new {
height: 34px;
margin-right: 0 !important;
margin-left: 10px;
padding: 0 15px;
line-height: 32px;
cursor: pointer;
}
&--dragbox {
......@@ -200,3 +209,16 @@
}
}
}
.row-dragging {
background: #fafafa;
border: 1px solid #ccc;
& td {
padding: 16px;
}
}
.drag-visible {
visibility: visible;
}
.sort-td {
text-align: center;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment