Commit d82bf5f9 authored by Bill's avatar Bill

fix: 修改品类导航页,筛选掉重复数据

parent a242ccee
import React, { useMemo, useEffect } from 'react';
import { useSelector } from '@lingxi-disign/react';
const keyFunc = {
"secondary": (_props) => {
return {
id: _props.id,
};
},
"flashSale": (_props) => {
return {id: _props.id};
},
"saleRanking": (_props) => {
return {
id: _props.id,
};
},
"brand": (_props) => {
return {id: _props.id};
},
"suggestProduct": (_props) => {
return {
id: _props.id,
};
}
};
export function useFilterSameOption() {
const { pageConfig } = useSelector<any, any>(['pageConfig']);
const sameKeys = useMemo(() => {
if(pageConfig === null) {
return {};
}
const tabChildren = pageConfig?.[4]?.childNodes?.slice(1) || [];
if(tabChildren?.lenth === 0) {
return {};
}
const result = {};
tabChildren.forEach((_nodeKey) => {
if (!pageConfig[_nodeKey]) {
return;
}
const { id } = pageConfig[_nodeKey].props;
const parentType = pageConfig[_nodeKey].otherProps.type;
if (typeof result[`${parentType}_${id}`] === 'undefined') {
result[`${parentType}_${id}`] = [];
}
result[`${parentType}_${id}`].push(id);
const tabItemChild = pageConfig[_nodeKey].childNodes;
tabItemChild.forEach(element => {
const { otherProps: { type }, props, childNodes } = pageConfig[element];
const name = `${parentType}_${id}_${type}`;
if (typeof result[name] === 'undefined') {
result[name] = [];
}
childNodes.forEach(_son => {
const sonData = pageConfig[_son];
const tempData = keyFunc[type]?.(sonData.props);
result[name].push(tempData.id);
});
});
});
console.log(result);
return result;
}, [pageConfig]);
return sameKeys;
}
......@@ -30,7 +30,7 @@ function useGetLayout() {
templateId: id
});
if(code === 1000) {
setInfo(data);
setInfo(data || {});
}
}
fetchData();
......@@ -53,7 +53,7 @@ function useGetLayout() {
};
const grandSonCompoentMap = {
"secondary": 'SecondaryNavigation.Item',
secondary: 'SecondaryNavigation.Item',
flashSale: 'SimpleCommodityList.Item',
saleRanking: 'SimpleCommodityList.Item',
brand: "CategoryList.Item",
......@@ -80,7 +80,7 @@ function useGetLayout() {
visible: _item.visible,
},
otherProps: {
type: 'TabItem'
type: 'tabItem'
},
childNodes: [],
};
......
......@@ -153,7 +153,7 @@ const tab: PageConfigType = {
},
template: template,
otherProps: {
type: 'TabItem'
type: 'tabItem'
},
},
......
......@@ -48,19 +48,40 @@
width: 100%;
background-color: #fafbfc;
display: flex;
flex-direction: row;
flex-direction: column;
align-items: center;
justify-content: center;
height: 96px;
position: relative;
cursor: pointer;
.imageIcon {
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
overflow: hidden;
}
// .imageIcon {
// width: 40px;
// height: 40px;
// display: flex;
// flex-direction: row;
// align-items: center;
// justify-content: center;
// }
.uploadImage {
position: absolute;
bottom: -34px;
left: 0;
right: 0;
padding: 4px;
background: rgba(0,0,0,0.3);
z-index: 99;
text-align: center;
color: #fff;
transition: all 0.6s;
}
&:hover {
.uploadImage {
transform: translateY(-34px);
}
}
}
}
import React, { useContext, useEffect, useMemo, useState } from 'react';
import { changeProps, PageConfigType, SelectedInfoType, StateType, STATE_PROPS, } from '@lingxi-disign/core';
import { changeProps, clearSelectedStatus, PageConfigType, SelectedInfoType, StateType, STATE_PROPS, } from '@lingxi-disign/core';
import { useSelector } from '@lingxi-disign/react';
import cs from 'classnames';
import { usePrevious, useToggle } from '@umijs/hooks';
......@@ -19,6 +19,7 @@ import FormilyUpload from '@/components/UploadFiles/FormilyUploadFiles';
import { useAsyncSelect } from '@/formSchema/effects/useAsyncSelect';
import { PublicApi } from '@/services/api';
import { getAuth } from '@/utils/auth';
import { useFilterSameOption } from '../../common/hooks/useFilterSameOption';
type SettingPanelType = {
selectedInfo: SelectedInfoType,
......@@ -28,7 +29,7 @@ type SettingPanelType = {
}
const ComponentSchema = {
TabItem: tabTitleSchema,
tabItem: tabTitleSchema,
secondaryItem: secondaryTabSchema,
flashSale: blockSchema,
flashSaleItem: flashSaleSchema,
......@@ -43,6 +44,7 @@ const formActions = createFormActions();
const { onFieldInputChange$ } = FormEffectHooks;
const EditPanel = () => {
const userAuth = getAuth();
const sameKeyState = useFilterSameOption();
const fixtureContext = useContext(context);
const { selectedInfo, pageConfig, activeKey, domKey } = useSelector<SettingPanelType, STATE_PROPS | "activeKey" | "domKey">(['selectedInfo', 'pageConfig', 'activeKey', "domKey"]);
const {state: visible, toggle: setVisible } = useToggle(true);
......@@ -51,6 +53,10 @@ const EditPanel = () => {
const [formValue, setFormValue] = useState({});
/** 精选商品type */
const [type, setType] = useState<number>(0);
/**
* 当每次点击selectInfo 时,都把selectInfo.props 映射到formily 的value 上
* 但当一级类型没有被选择的时候,那么必须选择一级导航类型
*/
useEffect(() => {
if (activeKey === null || previousActiveKey !== activeKey) {
if(activeKey === null) {
......@@ -140,7 +146,8 @@ const EditPanel = () => {
}
}, [domKey]);
const handleOncancel = () => {
const handleOnClose = () => {
clearSelectedStatus();
setVisible(false);
};
......@@ -150,14 +157,14 @@ const EditPanel = () => {
});
const renderUploadChild = (value) => {
console.log(value);
const target = value[0];
return (
<div className={styles.image}>
<div className={styles.uploadImage}>上传图片</div>
<div className={styles.imageIcon}>
<Spin spinning={target?.status === 'uploading'}>
{
target ? <img src={target?.url} style={{width: '100%', height: '100%'}} /> : <PlusCircleOutlined />
target?.url ? <img src={target?.url} style={{width: '100%', height: '96px'}} /> : <PlusCircleOutlined />
}
</Spin>
</div>
......@@ -215,10 +222,12 @@ const EditPanel = () => {
changeProps({
treeKey: key,
props: currentProps,
title: values?.title || values?.name || values?.rankProduct?.name || values.productName || values?.brand?.name,
title: values?.title || values?.name || values?.rankProduct?.name || values.productName || values?.brand?.name || values?.blockTitle,
});
setVisible(false);
handleOnClose();
/** 这里reset 是为了修改自定义组件在mutator.change 之后无法setValue 的bug */
formActions.reset();
};
......@@ -230,6 +239,30 @@ const EditPanel = () => {
return data;
};
/**
* 当tab 修改时,这里要把已经添加的tab 给禁用掉
*/
useEffect(() => {
const sameKeyStateKeys = Object.keys(sameKeyState);
if (!activeKey || sameKeyStateKeys.length === 0) {
return;
}
const hasSelectedTabKeys = Object.keys(sameKeyState).filter((_item) => /tabItem_\d+$/.test(_item));
formActions.setFieldState('layout.primary', (state) => {
const tempData = state.originAsyncData;
console.log(state);
FormPath.setIn(state, 'props.enum', tempData.map((_item) => {
return {
// ..._item,
label: _item.name,
value: _item.id,
disabled: hasSelectedTabKeys.includes(`tabItem_${_item.id}`),
};
}));
});
}, [activeKey, sameKeyState]);
useEffect(() => {
if(!activeKey ) {
return;
......@@ -241,7 +274,9 @@ const EditPanel = () => {
memberId: userAuth.memberId,
});
if (code === 1000) {
const source = data.map((_item) => ({label: _item.name, value: _item.id}));
// const source = data.map((_item) => ({label: _item.name, value: _item.id}));
const source = data.map((_item) => ({label: _item.name, value: _item.id, disabled: sameKeyState[`tabItem_${activeKey}_secondary`].includes(_item.id)} ));
formActions.setFieldState('secondary', (state) => {
state.originAsyncData = source;
FormPath.setIn(state, 'props.enum', source);
......@@ -249,7 +284,7 @@ const EditPanel = () => {
}
}
fetchSecondaryOption();
}, [activeKey]);
}, [activeKey, sameKeyState]);
/** 这样写纯粹是为了区分修改tab 跟修改该 二级菜单的,因为如果form 挂载了,那么二级菜单在一级菜单修改时就不会再请求接口了,没想到好的方法 */
const renderForm = () => {
......@@ -283,7 +318,7 @@ const EditPanel = () => {
<div className={className}>
<div className={styles.header}>
<span className={styles.title}>内容</span>
<CloseOutlined onClick={handleOncancel} />
<CloseOutlined onClick={handleOnClose} />
</div>
<div className={styles.content}>
{renderForm()}
......
......@@ -7,14 +7,16 @@ import BrandItem from './brandItem';
import { context } from '../../common/context/context';
import NiceForm from '@/components/NiceForm';
import { PublicApi } from '@/services/api';
import { useFilterSameOption } from '../../common/hooks/useFilterSameOption';
const actions = createFormActions();
const BranchList = (props) => {
const { visible, value, onCancel, onConfirm } = props;
const fixtureContext = useContext(context);
const sameKeyState = useFilterSameOption();
const { activeKey: categoryId } = useSelector<any, "activeKey" >(['activeKey']);
const disabledBrandKeys = useMemo(() => sameKeyState[`tabItem_${categoryId}_brand`], [sameKeyState, categoryId]);
const [dataSource, setDataSource] = useState<any>([]);
const [current, setCurrent] = useState<number>(1);
......@@ -139,9 +141,10 @@ const BranchList = (props) => {
{
dataSource?.map((_item) => {
const isChecked = _item.id === innerCheckedKey?.id;
const isDisabled = disabledBrandKeys.includes(_item.id);
return (
<div key={_item.id} className={styles.branchItem}>
<BrandItem onSelect={onSelect} isChecked={isChecked} name={_item.name} icon={_item.logoUrl} id={_item.id} />
<BrandItem onSelect={onSelect} disabled={isDisabled} isChecked={isChecked} name={_item.name} icon={_item.logoUrl} id={_item.id} />
</div>
);
})
......
......@@ -7,10 +7,11 @@ interface Iprops {
id: number
onSelect?: ((checked: boolean, options: { id: number, icon: string, name: string }) => void) | null,
isChecked?: boolean,
disabled?: boolean
}
const BrandItem: React.FC<Iprops> = (props: Iprops) => {
const { name, icon, id, onSelect, isChecked } = props;
const { name, icon, id, onSelect, isChecked, disabled = false } = props;
const onChecked = (e) => {
onSelect?.(e.target.checked, { id, icon, name });
......@@ -23,7 +24,7 @@ const BrandItem: React.FC<Iprops> = (props: Iprops) => {
return (
<div style={{display: 'flex', alignItems: 'center', padding: '12px', border: '1px solid #F7F8FA', ...checkedStyle}}>
{
onSelect && <Checkbox onChange={onChecked} checked={isChecked} />
onSelect && <Checkbox disabled={disabled} onChange={onChecked} checked={isChecked} />
}
<img src={icon} style={{width: '64px', height: '36px', marginLeft: '12px'}} />
<span style={{marginLeft: '18px', fontSize: '12px', color: '#606266'}}>{name}</span>
......
......@@ -5,6 +5,7 @@ import { context } from '../../common/context/context';
import { Product } from '@/pages/transaction/marketingAbility/marketingActivitiesManagement/activePage/fixtures/components/ProductPanel';
import CommodityDrawer from '../CommodityDrawer';
import { getAuth } from '@/utils/auth';
import { useFilterSameOption } from '../../common/hooks/useFilterSameOption';
interface Iprops {
......@@ -37,7 +38,10 @@ const FormilyCommodity: React.FC<Iprops> & { isFieldComponent: boolean } = (prop
/** 1 级分类 id */
const { activeKey } = useSelector<any, "activeKey" >(['activeKey']);
const fixtureContext = useContext(context);
/** 获取已经选择的id */
const sameKeyState = useFilterSameOption();
const disabledSaleRankingKeys = useMemo(() => sameKeyState[`tabItem_${activeKey}_saleRanking`], [sameKeyState, activeKey]);
console.log(sameKeyState, disabledSaleRankingKeys );
const componentProps = props.props?.['x-component-props'] || {} as { isWithLabels?: boolean };
const { state: productVisible, toggle: setProductVisible } = useToggle();
......@@ -71,8 +75,9 @@ const FormilyCommodity: React.FC<Iprops> & { isFieldComponent: boolean } = (prop
categoryId: activeKey,
memberId: userAuth.memberId,
memberRoleId: userAuth.memberRoleId,
idNotInList: [productProps?.id].concat(disabledSaleRankingKeys).filter(Boolean)
};
}, [fixtureContext?.shopId.toString(), activeKey]);
}, [fixtureContext?.shopId.toString(), activeKey, disabledSaleRankingKeys]);
const onLabelChange = (data) => {
mutators.change({...value, label: data.label});
......
......@@ -9,29 +9,33 @@
display: flex;
flex-direction: row;
align-items: center;
margin-right: -34px;
margin-right: -16px;
flex-wrap: wrap;
.item {
flex-basis: 20%;
padding-right: 16px;
margin-bottom: 12px;
.content {
display: flex;
flex-direction: column;
// align-items: center;
margin-top: 4px;
// background-color: red;
.image {
width: 40px;
// width: 40px;
width: 100%;
height: 40px;
margin-bottom: 4px;
margin-bottom: 8px;
}
.name {
text-align: center;
color: '#601314'
.center {
display: flex;
flex-direction: column;
align-items: center;
}
}
.empty {
......@@ -40,8 +44,7 @@
flex-direction: row;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
height: 66px;
}
}
......
......@@ -35,12 +35,6 @@ const SecondaryNavigation: React.FC<Iprops> & { Item: typeof Item } = (props: Ip
);
};
interface IItemProps {
icon: string,
id: number,
name: string,
}
const Item = (props) => {
const { icon, id, name } = props;
const { onClick, onDrag, onDragEnd, onDragEnter, onDragStart, onMouseOver, getOperateState, className, ...rest} = props as any;
......@@ -64,11 +58,12 @@ const Item = (props) => {
return (
<div className={styles.item} >
<div className={wrapClass}>
<div {...divProps} className={className} style={{width: '40px'}}>
<div className={wrapClass}>
<div {...divProps} className={cs(className, styles.center)}>
<img src={icon} className={styles.image} />
<div className={styles.name}>{name}</div>
</div>
</div>
</div>
);
......
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