Commit 042464df authored by GuanHua's avatar GuanHua

feat: app店铺模板装修

parent fe3f8ec9
...@@ -16,7 +16,7 @@ interface ToolBarPropsType { ...@@ -16,7 +16,7 @@ interface ToolBarPropsType {
} }
const ToolBar: React.FC<ToolBarPropsType> = (props) => { const ToolBar: React.FC<ToolBarPropsType> = (props) => {
const { type = 1, title = "首页", showActions, templateId } = props const { type = 1, title = "首页", showActions, templateId, layoutType } = props
const [saveLoading, setSaveLoading] = useState<boolean>(false) const [saveLoading, setSaveLoading] = useState<boolean>(false)
const { componentConfigs } = useSelector<ComponentConfigsType, STATE_PROPS>(['componentConfigs']) const { componentConfigs } = useSelector<ComponentConfigsType, STATE_PROPS>(['componentConfigs'])
...@@ -39,54 +39,36 @@ const ToolBar: React.FC<ToolBarPropsType> = (props) => { ...@@ -39,54 +39,36 @@ const ToolBar: React.FC<ToolBarPropsType> = (props) => {
const handleSave = useCallback(() => { const handleSave = useCallback(() => {
const param: any = { const param: any = {
templateId: Number(templateId), templateId: Number(templateId),
appEnterpriseBO: {},
} }
if(layoutType === LAYOUT_TYPE.shop) {
param.appStoreBO = {}
Object.keys(componentConfigs).forEach(key => { Object.keys(componentConfigs).forEach(key => {
const componentConfigsItem = componentConfigs[key] const componentConfigsItem = componentConfigs[key]
if(componentConfigsItem.componentType) { if(componentConfigsItem.componentType) {
switch(componentConfigsItem.componentType) { switch(componentConfigsItem.componentType) {
case PROPS_TYPES.mobileHeaderNav: case PROPS_TYPES.mobileShopHeaderNav:
param.appEnterpriseBO.topBO = { param.appStoreBO.backdropBO = {
style: componentConfigsItem.props.styleTheme || 0, status: false,
status: true, backdrop: componentConfigsItem.props.backdrop || ''
topDetailsBOList: componentConfigsItem.props.dataList || []
} }
break break
case PROPS_TYPES.mobileBanner: case PROPS_TYPES.mobileBanner:
param.appEnterpriseBO.advertBO = { param.appStoreBO.advertBO = {
status: componentConfigsItem.props.visible || true, status: false,
advertDetailsBOList: componentConfigsItem.props.dataList || [] advertDetailsBOList: componentConfigsItem.props.dataList || []
} }
break break
case PROPS_TYPES.mobileQuickNav: case PROPS_TYPES.mobileQuickNav:
param.appEnterpriseBO.functionBO = { param.appStoreBO.functionBO = {
status: componentConfigsItem.props.visible || true, status: false,
functionDetailsBO: componentConfigsItem.props.dataList || [] functionDetailsBO: componentConfigsItem.props.dataList || []
} }
break break
case PROPS_TYPES.mobileShowCase: case PROPS_TYPES.mobileShopCommodity:
param.appEnterpriseBO.showcaseBO = { param.appStoreBO.productBO = {
style: componentConfigsItem.props.styleTheme || 0, status: false,
status: componentConfigsItem.props.visible || true, title: componentConfigsItem.props.title,
showcaseDetailsBO: componentConfigsItem.props.dataList || [] productIdList: componentConfigsItem.props.productIdList,
}
break
case PROPS_TYPES.mobileRecommentShops:
param.appEnterpriseBO.storeBO = {
status: componentConfigsItem.props.visible || true,
storeIdList: componentConfigsItem.props.dataList ? componentConfigsItem.props.dataList.map(item => item.selectId) : []
}
break
case PROPS_TYPES.mobileQuality:
param.appEnterpriseBO.excellentBO = {
status: componentConfigsItem.props.visible || true,
excellentDetailsBO: componentConfigsItem.props.dataList || []
}
break
case PROPS_TYPES.mobileBottomNavigation:
param.appEnterpriseBO.bottomBO = {
status: true,
bottomDetailsBOList: componentConfigsItem.props.dataList || []
} }
break break
default: default:
...@@ -94,18 +76,30 @@ const ToolBar: React.FC<ToolBarPropsType> = (props) => { ...@@ -94,18 +76,30 @@ const ToolBar: React.FC<ToolBarPropsType> = (props) => {
} }
} }
}) })
} else if(layoutType=== LAYOUT_TYPE.channel) {
param.appChannelBO = {}
}
console.log(JSON.stringify(param), "param") console.log(JSON.stringify(param), "param")
saveAppEnterprise(param) saveAppEnterprise(param)
}, [componentConfigs]) }, [componentConfigs])
const saveAppEnterprise = (param) => { const saveAppEnterprise = (param) => {
PublicApi.postTemplateAdornAppEnterpriseSave(param).then(res => { let postFn
if(layoutType=== LAYOUT_TYPE.shop) {
postFn = PublicApi.postTemplateAdornAppStoreSave
} else if(layoutType=== LAYOUT_TYPE.channel) {
postFn = PublicApi.postTemplateAdornAppChannelSave
}
if(postFn) {
postFn(param).then(res => {
if(res.code === 1000) { if(res.code === 1000) {
message.destroy() message.destroy()
message.success("保存成功") message.success("保存成功")
} }
}) })
} }
}
return ( return (
<div className={styles.toolbar}> <div className={styles.toolbar}>
......
...@@ -51,14 +51,6 @@ const RedirectTypeList = [ ...@@ -51,14 +51,6 @@ const RedirectTypeList = [
label: '积分详情', label: '积分详情',
}, },
{ {
value: 3,
label: '店铺主页',
},
{
value: 4,
label: '资讯详情',
},
{
value: 5, value: 5,
label: '不跳转', label: '不跳转',
}, },
......
...@@ -29,50 +29,27 @@ interface QuickNavPropsType { ...@@ -29,50 +29,27 @@ interface QuickNavPropsType {
visible: boolean, visible: boolean,
} }
// 跳转类型:1-商品 2-分类 3-积分兑换 4-公司介绍 5-成为会员 12-外部链接(可多个)
const RedirectTypeList = [ const RedirectTypeList = [
{ {
value: 1, value: 1,
label: '找现货', label: '商品',
}, },
{ {
value: 2, value: 2,
label: '找供应', label: '分类',
}, },
{ {
value: 3, value: 3,
label: '发布求购', label: '积分兑换',
}, },
{ {
value: 4, value: 4,
label: '求购列表', label: '公司介绍',
}, },
{ {
value: 5, value: 5,
label: '换积分', label: '成为会员',
},
{
value: 6,
label: '找店铺',
},
{
value: 7,
label: '看资讯',
},
{
value: 8,
label: '授信申请',
},
{
value: 9,
label: '人气店铺',
},
{
value: 10,
label: '求购动态',
},
{
value: 11,
label: '最新成交',
}, },
{ {
value: 12, value: 12,
...@@ -234,6 +211,26 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => { ...@@ -234,6 +211,26 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => {
} }
/** /**
* 修改广告链接
* @param value
* @param id
*/
const handleUrlChange = (value: string, id: number) => {
console.log(value, "value")
const newList = [...list]
newList.map(item => {
if (item.id === id) {
item.url = `https://${value}`
}
})
setList(newList)
changeProps({
props:Object.assign({ ...props }, { dataList: newList })
})
}
/**
* 添加广告 * 添加广告
*/ */
const handleAddItem = () => { const handleAddItem = () => {
...@@ -253,6 +250,14 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => { ...@@ -253,6 +250,14 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => {
}) })
} }
const judgedItemNotInList = (item, type: number) => {
if(item.value === type) {
return true
}
return list.every(listItem => listItem.type !== item.value)
}
return ( return (
<div className={styles.setting}> <div className={styles.setting}>
{/* <div className={styles.hideModule}> {/* <div className={styles.hideModule}>
...@@ -308,11 +313,21 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => { ...@@ -308,11 +313,21 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => {
<div className={styles.setting_line_addItem_line_brief}> <div className={styles.setting_line_addItem_line_brief}>
<Select style={{ width: '100%' }} value={item.type || undefined} onChange={(value) => handleTypeChange(value, item.id)}> <Select style={{ width: '100%' }} value={item.type || undefined} onChange={(value) => handleTypeChange(value, item.id)}>
{ {
RedirectTypeList.map(item => (<Select.Option value={item.value} key={`redirect_type_${item.value}`}>{item.label}</Select.Option>)) RedirectTypeList.map(selectItem => judgedItemNotInList(selectItem, item.type) && (<Select.Option value={selectItem.value} key={`redirect_type_${selectItem.value}`}>{selectItem.label}</Select.Option>))
} }
</Select> </Select>
</div> </div>
</div> </div>
{
item.type === 12 && (
<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 addonBefore="https://" value={item.url} onChange={(e) => handleUrlChange(e.target.value, item.id)} />
</div>
</div>
)
}
<div className={styles.setting_line_addItem_line}> <div className={styles.setting_line_addItem_line}>
<div className={styles.setting_line_addItem_line_label}>图标:</div> <div className={styles.setting_line_addItem_line_label}>图标:</div>
<div className={styles.setting_line_addItem_line_brief}> <div className={styles.setting_line_addItem_line_brief}>
...@@ -340,7 +355,9 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => { ...@@ -340,7 +355,9 @@ const QuickNav: React.FC<QuickNavPropsType> = (props) => {
</div> </div>
))} ))}
</ReactSortable> </ReactSortable>
<Button className={styles.selectBtn} icon={<PlusOutlined />} onClick={handleAddItem}>添加功能模块</Button> {
list.length <=5 && <Button className={styles.selectBtn} icon={<PlusOutlined />} onClick={handleAddItem}>添加功能模块</Button>
}
</div> </div>
) )
} }
......
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} />
export const promptCommodityColumn = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 80,
},
{
title: "商品图片",
dataIndex: "mainPic",
render: (mainPic: string) => showMainPic(mainPic)
},
{
title: "商品名称",
dataIndex: "name",
width: 280,
ellipsis: true,
},
{
title: "品类",
render: (_, record) => record.customerCategory ? record.customerCategory.name : "",
ellipsis: true,
},
{
title: "品牌",
render: (_, record) => record.brand ? record.brand.name : "",
ellipsis: true,
},
{
title: "价格",
dataIndex: "min",
render: (_, record) => ${priceFormat(record.min)}`
},
]
export default promptCommodityColumn
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;
}
...@@ -3,6 +3,8 @@ import { SelectedInfoType, clearSelectedStatus, PROPS_TYPES } from 'lingxi-edito ...@@ -3,6 +3,8 @@ import { SelectedInfoType, clearSelectedStatus, PROPS_TYPES } from 'lingxi-edito
import HeaderNav from './components/headerNav' import HeaderNav from './components/headerNav'
import Banner from './components/banner' import Banner from './components/banner'
import QuickNav from './components/quickNav' import QuickNav from './components/quickNav'
import HeadBackground from './components/headBackground'
import RecommendCommodity from './components/recommendCommodity'
import BottomNavigation from './components/bottomNavigation' import BottomNavigation from './components/bottomNavigation'
import styles from './index.less' import styles from './index.less'
...@@ -19,6 +21,10 @@ const PropsSettings: React.FC<PropsSettingsPropsType> = (props) => { ...@@ -19,6 +21,10 @@ const PropsSettings: React.FC<PropsSettingsPropsType> = (props) => {
if (componentType) { if (componentType) {
switch (componentType.type) { switch (componentType.type) {
case PROPS_TYPES.mobileShopHeaderNav:
return <HeadBackground {...initProps} />
case PROPS_TYPES.mobileShopCommodity:
return <RecommendCommodity {...initProps} />
case PROPS_TYPES.mobileHeaderNav: case PROPS_TYPES.mobileHeaderNav:
return <HeaderNav {...initProps} /> return <HeaderNav {...initProps} />
case PROPS_TYPES.mobileBanner: case PROPS_TYPES.mobileBanner:
......
...@@ -5,7 +5,6 @@ import SettingList from '../../../../components/SettingList' ...@@ -5,7 +5,6 @@ import SettingList from '../../../../components/SettingList'
import GoodsItem from './GoodsItem' import GoodsItem from './GoodsItem'
import SettingPanel from '../../../../components/SettingPanel' import SettingPanel from '../../../../components/SettingPanel'
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons' import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'
import { GetTemplatePlatformFindGoodsListResponseDetail } from '@/services/TemplateApi'
import { PublicApi } from '@/services/api' import { PublicApi } from '@/services/api'
import { filterProps } from '../../../../utils' import { filterProps } from '../../../../utils'
import styles from './index.less' import styles from './index.less'
...@@ -37,7 +36,7 @@ const GoodsSetting: React.FC<GoodsSettingPropsType> = (props) => { ...@@ -37,7 +36,7 @@ const GoodsSetting: React.FC<GoodsSettingPropsType> = (props) => {
const { templateid, categoryid, goodsList = [], templateType } = props const { templateid, categoryid, goodsList = [], templateType } = props
const [current, setCurrent] = useState<number>(1) const [current, setCurrent] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(10) const [pageSize, setPageSize] = useState<number>(10)
const [noSelectGoods, setNoSelectGoods] = useState<GetTemplatePlatformFindGoodsListResponseDetail[]>([]) const [noSelectGoods, setNoSelectGoods] = useState<any[]>([])
const [selectList, setSelectList] = useState<any>([]) const [selectList, setSelectList] = useState<any>([])
const [selectGoodsList, setSelectGoodsList] = useState<any>(goodsList) const [selectGoodsList, setSelectGoodsList] = useState<any>(goodsList)
const [goodsIds, setGoodsIds] = useState<any>([]) const [goodsIds, setGoodsIds] = useState<any>([])
...@@ -240,7 +239,7 @@ const GoodsSetting: React.FC<GoodsSettingPropsType> = (props) => { ...@@ -240,7 +239,7 @@ const GoodsSetting: React.FC<GoodsSettingPropsType> = (props) => {
postFn(param).then(res => { postFn(param).then(res => {
if (res.code === 1000) { if (res.code === 1000) {
resolve() resolve(true)
} else { } else {
reject() reject()
} }
......
...@@ -21,6 +21,7 @@ export const mobileShopHeaderNav = { ...@@ -21,6 +21,7 @@ export const mobileShopHeaderNav = {
key: "1", key: "1",
"1": { "1": {
"componentName": "MobileShopHeaderNav", "componentName": "MobileShopHeaderNav",
"componentType": PROPS_TYPES.mobileShopHeaderNav,
"title": "背景图编辑", "title": "背景图编辑",
"canEdit": true, "canEdit": true,
"canHide": false, "canHide": false,
......
...@@ -25,7 +25,7 @@ import { ...@@ -25,7 +25,7 @@ import {
import Loading from '../../editor/components/Loading' import Loading from '../../editor/components/Loading'
import { PublicApi } from '@/services/api' import { PublicApi } from '@/services/api'
import { LAYOUT_TYPE } from '@/constants' import { LAYOUT_TYPE } from '@/constants'
import { GetTemplateAdornAppStoreFindResponse } from '@/services/TemplateApi' import { GetTemplateAdornAppStoreFindResponse, GetTemplateWebMemberShopWebFindByMemberIdAndRoleIdResponse } from '@/services/TemplateApi'
// import { GlobalConfig } from '@/global/config' // import { GlobalConfig } from '@/global/config'
import MobileSettingPanel from '../../editor/mobileSettingPanel' import MobileSettingPanel from '../../editor/mobileSettingPanel'
import { getAuth } from '@/utils/auth' import { getAuth } from '@/utils/auth'
...@@ -67,7 +67,7 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => { ...@@ -67,7 +67,7 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
/** /**
* 获取店铺信息 * 获取店铺信息
*/ */
const fetchShopInfo = () => { const fetchShopInfo = (): Promise<GetTemplateWebMemberShopWebFindByMemberIdAndRoleIdResponse> => {
return new Promise((resolve) => { return new Promise((resolve) => {
const param: any = { const param: any = {
memberId, memberId,
...@@ -191,73 +191,35 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => { ...@@ -191,73 +191,35 @@ const mobileShopTempleteEdit: React.FC<ShopPreviewPropsType> = (props) => {
const getComponentsConfig = async () => { const getComponentsConfig = async () => {
try { try {
// const appConfig = await getAppShopConfig() const appConfig = await getAppShopConfig()
// console.log(appConfig, "appConfig") console.log(appConfig, "appConfig")
//店铺信息 //店铺信息
const shopInfo = await fetchShopInfo() const shopInfo = await fetchShopInfo()
mobileShopHeaderNav[mobileShopHeaderNav.key].props.shopInfo = shopInfo mobileShopHeaderNav[mobileShopHeaderNav.key].props.shopInfo = shopInfo
// if(appConfig?.topBO) {
// // 顶部导航
// mobileHeaderNav[mobileHeaderNav.key].props.styleTheme = appConfig?.topBO.style
// mobileHeaderNav[mobileHeaderNav.key].props.dataList = appConfig?.topBO.topDetailsBOList
// }
// if(appConfig?.advertBO) { mobileShopCommodityList[mobileShopCommodityList.key].props.storeId = shopInfo.id
// // 轮播广告
// mobileBanner[mobileBanner.key].props = {
// visible: appConfig.advertBO.status,
// dataList: appConfig.advertBO.advertDetailsBOList
// }
// }
// if(appConfig?.functionBO) { if(appConfig?.backdropBO) {
// // 功能入口 mobileShopHeaderNav[mobileShopHeaderNav.key].props.backdrop = appConfig?.backdropBO.backdrop
// mobileQuickNav[mobileQuickNav.key].props = { }
// visible: appConfig.functionBO.status,
// dataList: appConfig.functionBO.functionDetailsBO,
// }
// }
// if(appConfig?.showcaseBO) {
// // 橱窗推荐
// mobileShowCase[mobileShowCase.key].props = {
// visible: appConfig?.showcaseBO.status,
// dataList: appConfig?.showcaseBO.showcaseDetailsBO,
// }
// }
// if(appConfig?.storeBO) {
// const storeBOParam = {
// current: 1,
// pageSize: 100,
// idList: appConfig?.storeBO.storeIdList || [],
// }
// console.log(storeBOParam, "storeBOParam")
// const storeBORes = await getRecommendShopList(storeBOParam)
// // 推荐店铺 if(appConfig?.advertBO) {
// mobileRecommendShops[mobileRecommendShops.key].props = { mobileBanner[mobileBanner.key].props.dataList = appConfig?.advertBO.advertDetailsBOList
// visible: appConfig?.storeBO.status, }
// dataList: getStoreBOList(storeBORes),
// }
// }
// if(appConfig?.excellentBO) { if(appConfig?.functionBO) {
// // 优质推荐 mobileQuickNav[mobileQuickNav.key].props.dataList = appConfig?.functionBO.functionDetailsBO
// mobileQuality[mobileQuality.key].props = { }
// visible: appConfig?.excellentBO.status,
// dataList: await getExcellentDetailsBO(appConfig?.excellentBO.excellentDetailsBO),
// }
// }
// if(appConfig?.bottomBO) { if(appConfig?.productBO) {
// // 底部导航 mobileShopCommodityList[mobileShopCommodityList.key].props = {
// mobileBottomNavigation[mobileBottomNavigation.key].props = { title: appConfig.productBO.title,
// visible: appConfig?.bottomBO.status, productIdList: appConfig.productBO.productIdList
// dataList: appConfig?.bottomBO.bottomDetailsBOList, }
// } } else {
// } mobileShopCommodityList[mobileShopCommodityList.key].props.title = '热销商品'
}
const config = { const config = {
...mallLayoutConfig, ...mallLayoutConfig,
......
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