Commit b4b939f3 authored by GuanHua's avatar GuanHua

feat: app渠道商城装修页面开发

parent a3bf07f3
......@@ -79,6 +79,48 @@ const ToolBar: React.FC<ToolBarPropsType> = (props) => {
} else if(layoutType=== LAYOUT_TYPE.channel) {
param.appChannelBO = {}
console.log(componentConfigs, "componentConfigs")
Object.keys(componentConfigs).forEach(key => {
const componentConfigsItem = componentConfigs[key]
if(componentConfigsItem.componentType) {
switch(componentConfigsItem.componentType) {
case PROPS_TYPES.mobileHeaderNav:
param.appChannelBO.topBO = {
status: false,
style: componentConfigsItem.props.styleTheme,
topDetailsBOList: componentConfigsItem.props.dataList || []
}
break
case PROPS_TYPES.mobileBanner:
param.appChannelBO.advertBO = {
status: false,
advertDetailsBOList: componentConfigsItem.props.dataList || []
}
break
case PROPS_TYPES.mobileChannelGoodsCard:
param.appChannelBO.productBO = {
status: false,
productDetailsBOList: componentConfigsItem.props.dataList || []
}
break
case PROPS_TYPES.moibileChannelInformation:
param.appChannelBO.informationBO = {
status: false,
title: componentConfigsItem.props.title,
informationIdList: componentConfigsItem.props.informationIdList || []
}
break
case PROPS_TYPES.mobileBottomNavigation:
param.appChannelBO.bottomBO = {
status: false,
bottomDetailsBOList: componentConfigsItem.props.dataList || []
}
break
default:
break
}
}
})
}
console.log(JSON.stringify(param), "param")
saveAppEnterprise(param)
......
......@@ -23,11 +23,12 @@ export interface InformationItemType {
interface MobileChannelInformationPropsType {
className?: string,
title: string,
dataList: InformationItemType[]
}
const MobileChannelInformation: React.FC<MobileChannelInformationPropsType> = (props) => {
const { className, dataList, ...others} = props
const { className, title, dataList, ...others} = props
const renderChildren = ({ getPrefixCls }: any) => {
const prefixCls = getPrefixCls("channel-information");
......@@ -36,7 +37,7 @@ const MobileChannelInformation: React.FC<MobileChannelInformationPropsType> = (p
return (
<div className={classNameString} {...others}>
<div className={styles["lingxi-channel-information-title"]}>
<span>行业资讯</span>
<span>{title}</span>
</div>
<div className={styles["lingxi-channel-information-scrollview"]}>
<div className={styles["lingxi-channel-information-list"]}>
......
......@@ -53,13 +53,15 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
initDataList()
}, [dataList])
const initDataList = () => {
const initDataList = async () => {
if(dataList) {
const newDataList = dataList.map((item: DataItemType, index: number) => {
const newDataList: DataItemType[] = []
for(let index = 0; index < dataList.length; index += 1) {
const item = dataList[index]
item.id = index + 1
item.expand = item.expand || false
return item
})
newDataList.push(item)
}
setList(newDataList)
}
}
......@@ -69,10 +71,6 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
for(const item of newList) {
if (item.id === id) {
item.expand = expand
// 获取当前选择链接的信息
if(!isEmpty(item.productIdList) && !item.productList) {
item.productList = await getSelectInfo(item)
}
} else {
item.expand = false
}
......@@ -83,28 +81,6 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
})
}
/**
* 根据选中的类型和id获取信息
* @param data
*/
const getSelectInfo = (data: DataItemType): Promise<any[] | undefined> => {
return new Promise((resolve) => {
const param: any = {
current: 1,
pageSize: 100,
idInList: data.productIdList,
channelMemberId,
}
PublicApi.postSearchMobileShopChannelGetCommodityList(param).then(res => {
message.destroy()
resolve(res.data.data)
}).catch(() => {
resolve(undefined)
})
})
}
const sortUp = (index: number, item: DataItemType) => {
const newList = JSON.parse(JSON.stringify(list))
const tempItem = JSON.parse(JSON.stringify(item))
......@@ -195,25 +171,13 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
item.productList = item.productList ? item.productList.filter(selectInfoItem => selectInfoItem.id !== delelteId) : undefined
}
})
console.log(newList, "newList")
setList(newList)
changeProps({
props:Object.assign({ ...props }, { dataList: newList })
})
}
const changeBrandData = (list: any[] | undefined) => {
if(list) {
let newList: any[] = []
list.forEach((item) => {
if(item.brandResponseList) {
newList = [...newList, ...item.brandResponseList]
}
});
return newList
}
return []
}
/**
* 根据类型显示选择的信息
* @param type 1-商品详情 2-积分详情 3-店铺主页 4-资讯详情 5-不跳转
......@@ -223,8 +187,8 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
return (
<div>
{
item.productList && item.productList.map(selectItem => (
<div className={styles.setting_line_addItem_line} key={selectItem.id}>
item.productList && item.productList.map((selectItem, selectIndex) => (
<div className={styles.setting_line_addItem_line} key={`${selectItem.id}${selectIndex}`}>
<div className={styles.setting_line_addItem_line_label}></div>
<div className={styles.setting_line_addItem_line_brief}>
<div className={styles.selectInfoBox}>
......@@ -263,7 +227,12 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
const newList = [...list]
for(const item of newList) {
if (item.id === currentInfo?.id) {
item.productIdList = [...item.productIdList, ...productRowCtl.selectedRowKeys]
if(item.productIdList) {
item.productIdList = [...item.productIdList, ...productRowCtl.selectedRowKeys]
} else {
item.productIdList = [...productRowCtl.selectedRowKeys]
}
if(item.productList) {
item.productList = [...item.productList, ...selectResult]
} else {
......@@ -292,11 +261,15 @@ const ChannelGoods: React.FC<QualityPropsType> = (props) => {
const fetchTableList = async (param: any) => {
const params: any = {
...param,
// priceTypeList: [1],
priceTypeList: [1],
idNotInList: currentInfo.productIdList,
channelMemberId,
}
const res = await PublicApi.postSearchMobileShopChannelGetCommodityList(params, {ctlType: 'none'})
const headers = {
"type": "3"
}
const res = await PublicApi.postSearchMobileShopChannelGetCommodityList(params, { headers })
message.destroy()
return res.data
}
......
import React from 'react'
import { numFormat, priceFormat } from '@/utils/numberFomat'
import ImageBox from '@/components/ImageBox'
const showMainPic = (mainPic: string) => <ImageBox width={32} height={32} imgUrl={mainPic} />
const informationColumn = [
{
title: "资讯图片",
dataIndex: "imageUrl",
render: (imageUrl: string) => showMainPic(imageUrl)
},
{
title: "资讯标题",
dataIndex: "title",
width: 360,
ellipsis: true,
},
]
export default informationColumn
import { ISchema } from '@formily/antd'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import { PublicApi } from '@/services/api'
export const formProduct: ISchema = {
type: 'object',
properties: {
name: {
type: 'string',
'x-component': 'ModalSearch',
'x-component-props': {
placeholder: '搜索',
align: 'flex-left',
},
},
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
style: {
marginRight: 0
}
},
colStyle: {
marginTop: 20,
},
},
properties: {
customerCategoryId: {
type: 'string',
"x-component": 'SearchSelect',
"x-component-props": {
placeholder: '请选择品类',
className: 'fixed-ant-selected-down', // 该类强制将显示的下拉框出现在select下, 只有这里出现问题, ??
queryParams: {
storeId: 2,
},
fetchSearch: PublicApi.getProductSelectGetSelectCategory,
style: {
width: 160
}
}
},
brandId: {
type: 'string',
"x-component": 'SearchSelect',
"x-component-props": {
placeholder: '请选择品牌',
queryParams: {
storeId: 2,
},
fetchSearch: PublicApi.getSearchMobileShopStoreGetBrand,
style: {
width: 160
}
}
},
submit: {
"x-component": 'Submit',
"x-mega-props": {
span: 1
},
"x-component-props": {
children: '查询'
}
}
}
}
}
}
export const basicSchema: ISchema = {
type: 'object',
properties: {
name: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
placeholder: '搜索',
align: 'flex-left',
},
},
}
}
@import "../../../../../../global/styles/utils.less";
@import "../../common.less";
.selectBtn {
display: block;
width: 100%;
background-color: #FAFBFC;
border: 1px dashed #D8DDE6;
}
.uploadPreview {
border: 1px solid #EBECF0;
}
import React, { useState } from 'react'
import { Button, Input, message } from 'antd'
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons'
import { changeProps } from 'lingxi-editor-core'
import ImageBox from '@/components/ImageBox'
import isEmpty from 'lodash/isEmpty'
import ModalTable from '@/components/ModalTable'
import { PublicApi } from '@/services/api'
import { FORM_FILTER_PATH } from '@/formSchema/const'
import cx from 'classnames'
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch'
import SearchSelect from '@/components/NiceForm/components/SearchSelect'
import Search from '@/components/NiceForm/components/Search'
import Submit from '@/components/NiceForm/components/Submit'
import { basicSchema } from './contant/schema'
import informationColumn from './contant/column'
import arrowRightIcon from '@/assets/icons/arrow_right.png'
import arrowLeftIcon from '@/assets/icons/arrow_left.png'
import styles from './index.less'
interface DataItemType {
sort: number,
id: number,
name: string,
img: string,
type: number,
expand: boolean,
selectInfo?: any
}
interface BannerPropsType {
dataList: DataItemType[],
selectInfo?: any,
informationIdList: number[],
storeId: number,
title: string,
}
const ChannelInformation: React.FC<BannerPropsType> = (props) => {
const { title, informationIdList, dataList } = props
const [expandState, setExpandState] = useState<boolean>(true)
const [modalVisible, setModalVisible] = useState<boolean>(false)
const [recommendTitle, setRecommendTitle] = useState<string>(title)
const [productRowSelection, productRowCtl] = useRowSelectionTable()
/**
* 修改名称
* @param value
* @param id
*/
const handleNameChange = (value: string) => {
setRecommendTitle(value)
changeProps({
props:Object.assign({ ...props }, { title: value })
})
}
const getDataListByList = (list) => {
let result: any = []
if(list) {
list.forEach((listItem) => {
if (listItem.productList && listItem.productList.length > 0) {
result = [...result, ...listItem.productList]
}
})
}
return result
}
/**
* 删除已选商品
*/
const handleDeleteItem = (id: number) => {
let informationIds = [...informationIdList]
informationIds = informationIds.filter(item => item !== id)
const informationList = []
dataList.forEach((listItem: any) => {
if(listItem.id !== id) {
informationList.push(listItem)
}
})
changeProps({
props:Object.assign({ ...props }, {
informationIdList: informationIds,
dataList: informationList,
})
})
}
/**
* 根据类型显示选择的信息
* @param type 1-商品详情 2-积分详情 3-店铺主页 4-资讯详情 5-不跳转
*/
const renderSelectItemByType = (list: any[]) => {
// const selectList = getDataListByList(list)
return (
<div>
{
list && list.map(selectItem => (
<div className={styles.setting_line_addItem_line} key={selectItem.id}>
<div className={styles.setting_line_addItem_line_label}></div>
<div className={styles.setting_line_addItem_line_brief}>
<div className={styles.selectInfoBox}>
<ImageBox direction="column" width={60} height={60} imgUrl={selectItem.imageUrl}/>
<div className={cx(styles.selectInfo, styles.shop)}>
<div className={styles.selectInfo_name}>{selectItem.title}</div>
</div>
<div className={styles.selectInfoBox_delete} onClick={() => handleDeleteItem(selectItem.id)}>
<DeleteOutlined />
</div>
</div>
</div>
</div>
))
}
</div>
)
}
/**
* 打开选择模态框
* @param sort
* @param type
*/
const handleOpenSelectModal = () => {
setModalVisible(true)
}
const fetchCategoryByCommodityId = (idList: number[]) => {
return new Promise((resolve) => {
const param = {
idList
}
PublicApi.postSearchMobileShopStoreGetCategoryByCommodityId(param).then((res) => {
message.destroy()
if (res.code === 1000) {
resolve(changeData(res.data))
} else {
resolve([])
}
}).catch(() => {
resolve([])
})
})
}
const changeData = (dataList) => {
if(dataList) {
return dataList.map((dataItem) => {
return {
categoryId: dataItem.id,
categoryName: dataItem.name,
categoryImage: dataItem.imageUrl || "",
productList: dataItem.commodityResponseList ? dataItem.commodityResponseList.map((commodityItem) => {
return {
id: commodityItem.id,
name: commodityItem.name,
sellPoints: commodityItem.sellingPoint,
min: commodityItem.min,
unitName: commodityItem.unitName,
sold: commodityItem.sold,
mainPic: commodityItem.mainPic,
}
}) : []
}
})
}
return []
}
const handleModalOk = async () => {
let selectedRowKeys = productRowCtl.selectedRowKeys
const selectResult = productRowCtl.selectRow
if (!selectedRowKeys || isEmpty(selectedRowKeys)) {
message.info("请选择")
return null
}
if(informationIdList) {
selectedRowKeys = [...informationIdList, ...selectedRowKeys]
} else {
selectedRowKeys = [...selectedRowKeys]
}
changeProps({
props:Object.assign({ ...props }, {
informationIdList: selectedRowKeys,
dataList: [...dataList, ...selectResult],
})
})
setModalVisible(false)
productRowCtl.setSelectRow([])
productRowCtl.setSelectedRowKeys([])
}
const handleModalCancel = async () => {
setModalVisible(false)
}
/**
* 获取模态框数据
* @param param
*/
const fetchTableList = async (param: any) => {
const params: any = {
...param,
idList: informationIdList,
}
const res = await PublicApi.getManageContentInformationPageByIdNotIn(params, {ctlType: 'none'})
return res.data
}
return (
<div className={styles.setting}>
{/* <div className={styles.hideModule}>
<Checkbox checked={!visible} onChange={handleHideChange}>隐藏整个模块</Checkbox>
</div> */}
<div className={styles.setting_line}>
<div className={styles.setting_line_main}>
<div className={styles.setting_line_name} >
<div style={{ flex: 1 }} onClick={() => setExpandState(!expandState)}>
{
expandState ? <img className={styles.icon} src={arrowLeftIcon} /> : <img className={styles.icon} src={arrowRightIcon} />
}
<span>{title}</span>
</div>
</div>
{
expandState && (
<div className={styles.setting_line_addItem}>
<div className={styles.setting_line_addItem_line}>
<div className={styles.setting_line_addItem_line_label}>标题:</div>
<div className={styles.setting_line_addItem_line_brief}>
<Input value={recommendTitle} onChange={(e) => handleNameChange(e.target.value)} />
</div>
</div>
<div className={styles.setting_line_addItem_line}>
<div className={styles.setting_line_addItem_line_label}>推荐资讯:</div>
<div className={styles.setting_line_addItem_line_brief}>
<Button className={styles.selectBtn} icon={<PlusOutlined />} onClick={() => handleOpenSelectModal()}>选择资讯</Button>
</div>
</div>
{
(dataList && dataList.length > 0) ? renderSelectItemByType(dataList) : null
}
</div>
)
}
</div>
</div>
<ModalTable
modalTitle="选择商品"
width={600}
confirm={handleModalOk}
cancel={handleModalCancel}
scroll={{ y: 400 }}
visible={modalVisible}
columns={informationColumn}
rowSelection={productRowSelection}
fetchTableData={params => fetchTableList(params)}
formilyProps={
{
ctx: {
schema: basicSchema,
components: { ModalSearch: Search, SearchSelect, Submit } ,
effects: ($, actions) => {
actions.reset()
useStateFilterSearchLinkageEffect(
$,
actions,
'name',
FORM_FILTER_PATH,
);
}
}
}
}
resetModal={{
destroyOnClose: true
}}
tableProps={{
rowKey: 'id',
onRow: (record) => ({
onClick: () => {
if(!productRowCtl.selectRow.includes(record)) {
productRowCtl.setSelectRow([...productRowCtl.selectRow, record]);
productRowCtl.setSelectedRowKeys([...productRowCtl.selectRow.map(item => item.id), record.id]);
} else {
productRowCtl.setSelectRow(productRowCtl.selectRow.filter(selectRowItem => selectRowItem.id !== record.id));
productRowCtl.setSelectedRowKeys(productRowCtl.selectedRowKeys.filter(selectedRowKeysItem => selectedRowKeysItem !== record.id))
}
},
})
}}
/>
</div>
)
}
export default ChannelInformation
......@@ -202,6 +202,8 @@ const RecommendCommodity: React.FC<BannerPropsType> = (props) => {
})
})
setModalVisible(false)
productRowCtl.setSelectRow([])
productRowCtl.setSelectedRowKeys([])
}
const handleModalCancel = async () => {
......
import React from 'react'
import { SelectedInfoType, clearSelectedStatus, PROPS_TYPES } from 'lingxi-editor-core';
import { SelectedInfoType, PROPS_TYPES } from 'lingxi-editor-core';
import HeaderNav from './components/headerNav'
import Banner from './components/banner'
import QuickNav from './components/quickNav'
......@@ -7,8 +7,8 @@ import HeadBackground from './components/headBackground'
import RecommendCommodity from './components/recommendCommodity'
import BottomNavigation from './components/bottomNavigation'
import MobileChannelGoods from './components/channelGoods'
import MobileChannelInformation from './components/channelInformation'
import styles from './index.less'
import { ConsoleSqlOutlined } from '@ant-design/icons';
interface PropsSettingsPropsType {
selectedInfo: SelectedInfoType | undefined,
......@@ -35,6 +35,8 @@ const PropsSettings: React.FC<PropsSettingsPropsType> = (props) => {
return <QuickNav {...initProps} />
case PROPS_TYPES.mobileChannelGoodsCard:
return <MobileChannelGoods {...initProps} />
case PROPS_TYPES.moibileChannelInformation:
return <MobileChannelInformation {...initProps} />
case PROPS_TYPES.mobileBottomNavigation:
return <BottomNavigation {...initProps} />
default:
......
......@@ -121,16 +121,16 @@ export const mobileChannelGoodsCard = {
"canHide": false,
"props": {
dataList: [
{
style: 0,
title: "电气电工",
viceTitle: "ELECTRICAL",
},
{
style: 1,
title: "机械设备",
viceTitle: "EQUIPMENT",
}
// {
// style: 0,
// title: "电气电工",
// viceTitle: "ELECTRICAL",
// },
// {
// style: 1,
// title: "机械设备",
// viceTitle: "EQUIPMENT",
// }
]
}
}
......@@ -140,17 +140,17 @@ export const mobileChannelInformation = {
key: "6",
"6": {
"componentName": "MobileChannelInformation",
"componentType": PROPS_TYPES.mobileBanner,
"componentType": PROPS_TYPES.moibileChannelInformation,
"title": "行业资讯",
"canEdit": true,
"canHide": false,
"props": {
title: "行业资讯",
dataList: []
}
}
}
export const mobileBottomNavigation = {
key: "7",
"7": {
......
......@@ -102,41 +102,22 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
* 根据选中的类型和id获取信息
* @param data
*/
const getSelectInfo = (data): Promise<any[] | undefined> => {
const getSelectInfo = (data, channelMemberId): Promise<any[] | undefined> => {
return new Promise((resolve) => {
let getFn: any = null
const param: any = {
current: 1,
pageSize: 100,
idInList: data.productIdList,
priceTypeList: [1],
channelMemberId,
}
switch(data.type) {
case 1:
param.idInList = data.recommend
getFn = PublicApi.postSearchMobileShopEnterpriseGetCommodityList
break
case 2:
param.idList = data.recommend
getFn = PublicApi.getTemplateWebMemberShopWebRecommendList
break
case 3:
param.idList = data.recommend
getFn = PublicApi.postSearchMobileShopEnterpriseGetCategoryBrand
break
case 4:
param.idList = data.recommend
getFn = PublicApi.getManageContentInformationPageByIdIn
break
default:
break
}
getFn ? getFn(param).then(res => {
PublicApi.postSearchMobileShopChannelGetCommodityList(param).then(res => {
message.destroy()
resolve(data.type === 3 ? res.data : res.data.data)
resolve(res.data.data)
}).catch(() => {
resolve(undefined)
}) : resolve(undefined)
})
})
}
......@@ -208,6 +189,34 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
}
const getProductInfo = async (dataList, channelMemberId) => {
const newDataList: any[] = []
for(let index = 0; index < dataList.length; index += 1) {
const item = dataList[index]
if (item.productIdList && item.productIdList.length > 0) {
item.productList = await getSelectInfo(item, channelMemberId)
}
newDataList.push(item)
}
return newDataList
}
const getInformationInfo = async (ids: number[]) => {
if (ids && ids.length > 0) {
const params: any = {
current: 1,
pageSize: 100,
idList: ids,
}
const res = await PublicApi.getManageContentInformationPageByIdIn(params, {ctlType: 'none'})
if(res.code === 1000) {
return res.data.data
}
}
return []
}
const getComponentsConfig = async () => {
try {
const appConfig = await getAppChannelConfig()
......@@ -217,17 +226,30 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
const channelInfo = await fetchChannelInfo()
mobileChannelHeaderNav[mobileChannelHeaderNav.key].props.name = channelInfo.memberName
if(channelInfo.memberId) {
if (channelInfo.memberId) {
const categoryList = await getCustomerCategoryTreeById(channelInfo.memberId)
mobileChannelCategory[mobileChannelCategory.key].props.dataList = categoryList
mobileChannelGoodsCard[mobileChannelGoodsCard.key].props.channelMemberId = channelInfo.memberId
if (appConfig?.productBO) {
mobileChannelGoodsCard[mobileChannelGoodsCard.key].props.dataList = await getProductInfo(appConfig?.productBO.productDetailsBOList, channelInfo.memberId)
}
}
if(appConfig?.advertBO) {
if (appConfig?.advertBO) {
mobileBanner[mobileBanner.key].props.dataList = appConfig?.advertBO.advertDetailsBOList
}
if (appConfig?.informationBO) {
mobileChannelInformation[mobileChannelInformation.key].props.title = appConfig?.informationBO.title
mobileChannelInformation[mobileChannelInformation.key].props.informationIdList = appConfig?.informationBO.informationIdList
mobileChannelInformation[mobileChannelInformation.key].props.dataList = await getInformationInfo(appConfig?.informationBO.informationIdList)
}
if (appConfig?.bottomBO) {
mobileBottomNavigation[mobileBottomNavigation.key].props.dataList = appConfig?.bottomBO.bottomDetailsBOList
}
const config = {
...mallLayoutConfig,
...mobileChannelHeaderNav,
......@@ -249,7 +271,7 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
return !loading ? (
<LegoProvider initState={{ componentConfigs: componentConfigs }} config={config}>
<div className={styles['wrapper']}>
<ToolBar type={1} title="渠道商城-首页" showActions={true} layoutType={LAYOUT_TYPE.shop} templateId={id} />
<ToolBar type={1} title="渠道商城-首页" showActions={true} layoutType={LAYOUT_TYPE.channel} templateId={id} />
<div className={styles['content']}>
<AllComponents />
<div className={styles['app-wrapper']}>
......
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