Commit 946cea22 authored by 武广's avatar 武广

Merge branch 'feature/addr20221031' into 'master'

Feature/addr20221031

See merge request !64
parents baa19369 d8defddc
import React, { forwardRef } from 'react';
import { Checkbox } from 'antd';
import { RightOutlined, DownOutlined, LoadingOutlined } from '@ant-design/icons';
import debounce from 'lodash/debounce';
import styles from './index.less';
const CustomTree = forwardRef(props => {
const { treeData } = props;
const onChange = () => {
props.onChange(treeData.key, !treeData.checked, treeData.level, treeData.children);
};
const onVisible = debounce(e => {
e.persist();
if (treeData.isLoading) return;
props.onVisibleChildren(
treeData.key,
!treeData.visibleChildren,
treeData.children,
treeData.checked,
);
}, 100);
const renderIcon = () => {
if (treeData.children && treeData.isLoading) {
return <LoadingOutlined />;
}
if (treeData.isLeaf) {
return (
<div onClick={onVisible} className={styles.CBIcon}>
{treeData.visibleChildren ? <DownOutlined /> : <RightOutlined />}
</div>
);
}
return <span />;
};
return (
<div key={`key${treeData.key}`}>
<div className={styles['ccheck-box']}>
<div className={styles['ccheck-box--expand']}>{renderIcon()}</div>
<Checkbox
onChange={onChange}
indeterminate={!treeData.checked && treeData.indeterminate}
checked={treeData.checked}
/>
<div className={styles['ccheck-box--label']} onClick={onVisible}>
{props.label}
{treeData.isLeaf && treeData.value && treeData.value.length > 0
? `(${treeData.value.length})`
: ''}
</div>
</div>
</div>
);
});
export default CustomTree;
This diff is collapsed.
.tree-box {
position: relative;
:global(.ant-col) {
display: flex;
}
&--wrapper {
position: relative;
}
}
.ccheck-box {
position: relative;
display: flex;
box-sizing: border-box;
width: max-content;
padding-right: 0;
padding-left: 22px;
&--expand {
position: absolute;
left: 0;
z-index: 1;
cursor: pointer;
}
&--childrens {
position: relative;
left: 100%;
z-index: 2;
display: flex;
flex-direction: column;
box-sizing: border-box;
width: max-content;
padding-left: 4px;
background-color: #fff;
box-shadow: 0 0 3px #ccc;
:global(.ant-checkbox-wrapper) {
margin-left: 0;
}
}
&--label {
padding: 0 10px;
cursor: pointer;
}
}
.CBIcon {
font-size: 12px;
}
.tree-children-box {
position: absolute;
top: 0;
left: 100%;
z-index: 2;
display: flex;
padding: 0 10px;
background-color: #fff;
box-shadow: 0 0 3px #ccc;
}
.tree-children-wrapper {
display: flex;
flex-direction: column;
max-height: 220px;
padding-left: 5px;
overflow-y: auto;
border-left: 1px solid #ccc;
&:first-child {
border: 0;
}
}
......@@ -97,13 +97,16 @@ const LogModal = props => {
useEffect(() => {
if (!props.id) return;
handleSearch();
// 20221108 临时隐藏商品详情,默认切换到审核详情 by liteng
// handleSearch();
bundleOnTabChange('1');
}, [props.id]);
const { visible } = props;
return (
<Modal title="日志详情" visible={visible} footer={null} onCancel={bundleOnCancel} width="800px">
<Tabs type="card" onChange={bundleOnTabChange} activeKey={tabActiveKey}>
<Tabs.TabPane tab="商品详情" key="0">
{/* 20221108 临时隐藏商品详情 by liteng */}
{/* <Tabs.TabPane tab="商品详情" key="0">
<Table
dataSource={tableData.records}
bordered
......@@ -122,7 +125,7 @@ const LogModal = props => {
className={styles.pagination}
/>
)}
</Tabs.TabPane>
</Tabs.TabPane> */}
<Tabs.TabPane tab="审核详情" key="1">
<Table
dataSource={merchantList}
......
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Modal, Input, Select, Cascader, Tag, notification } from 'antd';
import { Modal, Input, Select, Cascader, Tag, notification, Tree, Col, Row } from 'antd';
import React, { useState, useEffect } from 'react';
import { el } from 'date-fns/locale';
import { areaList, getAddTemplate, forbiddenAddress } from '../services';
const { Option } = Select;
import CustomTree from '@/components/CustomTree';
const AddAreaModal = props => {
const {
......@@ -13,9 +12,9 @@ const AddAreaModal = props => {
form: { getFieldDecorator, validateFields, resetFields, setFieldsValue },
templateData,
} = props;
const [addList, setAddList] = useState([]);
const [selectedList, setSelectedList] = useState([]);
const [selected, setSelect] = useState([]);
const [treeData, setTreeData] = useState([]);
const formItemLayout = {
labelCol: {
span: 6,
......@@ -24,76 +23,46 @@ const AddAreaModal = props => {
span: 16,
},
};
const getAreaList = async () => {
if (!addList.length) {
const data = await areaList();
const newData = [];
data.map(item =>
newData.push({
label: item.addrName,
value: item.addrId,
addressId: item.addrId,
addressLevel: item.addrLevel,
isLeaf: item.addrLevel === 4,
}),
);
setAddList(newData);
}
};
const onChange = (value, selectedOptions) => {
setSelect([...selectedOptions]);
};
// 加载
const loadData = async selectedOptions => {
const targetOption = selectedOptions.slice(-1)[0];
targetOption.loading = true;
const data = await areaList({ parentId: targetOption.addressId });
if (!data.length) {
targetOption.loading = false;
} else {
const newData = [];
data.map(itemData =>
newData.push({
label: itemData.addrName,
value: itemData.addrId,
addressId: itemData.addrId,
addressLevel: itemData.addrLevel,
isLeaf: false,
}),
);
targetOption.children = newData;
targetOption.loading = false;
setAddList([...addList]);
const filterData = arr =>
arr.map(item => ({
label: item.addrName,
key: Number(item.addrId),
level: item.addrLevel,
children: [],
// value: props.templateData.list.filter(item => item.)
}));
const loadProvice = async () => {
const data = await areaList();
if (data && data.length) {
const arr = filterData(data);
setTreeData(arr);
}
};
// 限制区域删除
const preventDefault = val => {
const newArr = selectedList.filter(item => item !== val);
setSelectedList([...newArr]);
};
const onCancel = () => {
setSelectedList([]);
resetFields();
setSelect([]);
props.onSubmit();
};
const handleOk = async () => {
const { length } = selectedList;
// if (!selectedList.length) {
// notification.error({ message: '请选择限制区域!' });
// return;
// }
const handleOk = () => {
validateFields(async (error, fieldsValue) => {
const newData = [];
selectedList.map(itemData =>
newData.push({
addressId: itemData.addressId,
addressLevel: itemData.addressLevel,
addressName: itemData.addressName,
}),
);
const getValues = (list, level) => {
list.forEach(itemData => {
if (itemData.checked) {
newData.push({
addressId: itemData.key,
addressLevel: itemData.level || level,
addressName: itemData.label,
});
} else if (itemData.children && itemData.children.length) {
getValues(itemData.children, level + 1);
}
});
};
if (!error) {
console.log('fieldsValue :>> ', fieldsValue);
getValues(fieldsValue.list, 1);
if (props.templateData.status) {
const data = await forbiddenAddress({
templateId: props.templateData.id,
......@@ -117,45 +86,38 @@ const AddAreaModal = props => {
}
});
};
// 判断是否重复
const getChilds = select => {
const reslutData = selectedList.filter(
item =>
!select.addressName.includes(item.addressName) &&
!item.addressName.includes(select.addressName),
);
reslutData.push(select);
return reslutData;
const onLoadData = async ({ key }) => {
const res = await areaList({ parentId: key });
return res || [];
};
const onPopupVisibleChange = labels => {
if (!labels && selected?.length) {
const select = selected.slice(-1)[0];
const arr = selected.map(x => x.label);
select.addressName = arr.join('/');
const reslutData = getChilds(select);
// 用中文字符排序
const resultArray = reslutData.sort((param1, param2) =>
param1.addressName.localeCompare(param2.addressName, 'zh'),
);
setSelectedList([...resultArray]);
setSelect([]);
}
};
useEffect(() => {
getAreaList();
if (props.templateData) {
setSelectedList(props.templateData.list);
let arr = [];
const dealData = list =>
list.map(item => {
item.key = +item.addressId;
item.label = item.addressName;
item.indeterminate = !item.isForbidden;
item.checked = item.isForbidden;
item.children && item.children.length && dealData(item.children);
return item;
});
arr = dealData(props.templateData.list || []);
setSelectedList(arr);
}
}, [props.templateData]);
useEffect(() => {
// console.log(selectedList)
}, [selectedList]);
props.visible && loadProvice();
}, [props.visible]);
return (
<Modal
title={props.templateData.status ? '编辑限制区域配送模板' : '添加限制区域配送模板'}
maskClosable={false}
visible={visible}
width="500px"
width="800px"
onCancel={() => onCancel()}
onOk={() => handleOk()}
>
......@@ -167,21 +129,10 @@ const AddAreaModal = props => {
})(<Input placeholder="请填写模板名称" maxLength={20} />)}
</Form.Item>
<Form.Item label="限制配送区域">
{getFieldDecorator('name')(
<Cascader
options={addList}
loadData={loadData}
onChange={(val, label) => onChange(val, label)}
allowClear={false}
changeOnSelect
onDropdownVisibleChange={onPopupVisibleChange}
/>,
)}
{selectedList?.map((selItem, selIndex) => (
<Tag closable key={selItem.addressId} onClose={() => preventDefault(selItem)}>
{selItem.addressName}
</Tag>
))}
{getFieldDecorator('list', {
rules: [{ required: true, message: '请选择限制配送区域!', type: 'array' }],
initialValue: selectedList,
})(<CustomTree treeData={treeData} loadData={onLoadData} valueKey="addressId" />)}
</Form.Item>
</Form>
</Modal>
......
......@@ -55,7 +55,7 @@ const TableList = props => {
),
]}
/>
<AddArea visible={visible} onSubmit={reload} templateData={templateData} />
{visible && <AddArea visible={visible} onSubmit={reload} templateData={templateData} />}
</PageHeaderWrapper>
);
};
......
......@@ -57,6 +57,41 @@ export function toThousands(data, num) {
export const formatTime = (time, crm = 'YYYY-MM-DD HH:mm:ss') => time.format(crm);
export const resetTime = (time, crm = 'YYYY-MM-DD HH:mm:ss') => moment(time, crm);
// 返回传递给他的任意对象的类
export function isClass(o) {
if (o === null) return 'Null';
if (o === undefined) return 'Undefined';
return Object.prototype.toString.call(o).slice(8, -1);
}
// 深拷贝
export function deepClone(obj) {
let result;
const oClass = isClass(obj);
// 确定result的类型
if (oClass === 'Object') {
result = {};
} else if (oClass === 'Array') {
result = [];
} else {
return obj;
}
// eslint-disable-next-line no-restricted-syntax
for (const key in obj) {
if ({}.hasOwnProperty.call(obj, key)) {
const copy = obj[key];
if (isClass(copy) === 'Object') {
result[key] = deepClone(copy); // 递归调用
} else if (isClass(copy) === 'Array') {
result[key] = deepClone(copy);
} else {
result[key] = obj[key];
}
}
}
return result;
}
export const getClientInfo = () => {
if (window.innerHeight !== undefined) {
return {
......
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