Commit 9b46a3c5 authored by 前端-钟卫鹏's avatar 前端-钟卫鹏
parents 92484dc7 9008755a
......@@ -60,10 +60,10 @@
"@ctrl/tinycolor": "^3.4.0",
"@formily/antd": "^1.3.3",
"@formily/antd-components": "^1.3.3",
"@lingxi-disign/core": "^1.0.6",
"@lingxi-disign/react": "^1.0.7",
"@lingxi-disign/react-web": "^1.0.2",
"@lingxi-disign/ui": "^1.0.6",
"@lingxi-disign/core": "^1.7.3",
"@lingxi-disign/react": "^1.7.6",
"@lingxi-disign/react-web": "^1.7.2",
"@lingxi-disign/ui": "^1.7.2",
"@turf/turf": "^6.4.0",
"@types/crypto-js": "^4.0.1",
"@types/js-cookie": "^2.2.6",
......
......@@ -15,6 +15,7 @@ import CustomCheckbox from '../components/CustomCheckbox';
import BraftEditor from 'braft-editor';
import { setFormStatus } from '../utils/utils';
import useCustomValidator from '../hooks/useValidator'
import styles from '../index.less'
const actions = createFormActions();
......@@ -81,14 +82,7 @@ const AdvertisementInfo = () => {
editable={isAdd || isEdit}
expressionScope={{
label: (
<div>
{
isAdd || isEdit
? <span style={{color: '#ff4d4f'}}>* </span>
: null
}
栏目
</div>
<div className={styles.custom_label}>栏目</div>
)
}}
>
......
......@@ -4,6 +4,7 @@ import { Card, Select, Input, Button } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ReutrnEle from '@/components/ReturnEle';
import { usePageStatus } from '@/hooks/usePageStatus';
import { validatorAllTrim } from '@/utils/regExp';
import { history, Prompt } from 'umi';
import { PublicApi } from '@/services/api';
import useCustomValidator from '../hooks/useValidator'
......@@ -51,6 +52,10 @@ const schema = {
{
limitByte: true, // 自定义校验规则
maxByte: 20,
},
{
validator: value => value.trim().length === 0,
message: '栏目名称不可为空',
}
]
},
......
import React, { useEffect, useState } from 'react';
import { FilterTable, SchemaFlexRowLayout } from '../components/FilterTable';
import { Card, Input, Button, Table, Space, Popconfirm } from 'antd';
import { createVirtualBox, createFormActions, FormEffectHooks, createEffectHook, registerFormFields, connect } from '@formily/antd';
import { history, Link } from 'umi';
import React, { useEffect, useState, useRef } from 'react';
import { Card, Button, Popconfirm, Row, Col } from 'antd';
import { createFormActions } from '@formily/antd';
import { history, Link } from 'umi';
import { PublicApi } from '@/services/api';
import StatusSwitch from '@/components/StatusSwitch';
import columnManagementSchemat from './schema';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { PlusOutlined } from '@ant-design/icons'
import { ColumnType } from 'antd/lib/table/interface'
import { getTableDataSource } from '../utils/utils';
import TablePagination from '../components/TablePagination';
import CustomSearch from '../components/CustomSearch';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import NiceForm from '@/components/NiceForm';
import EyePreview from '@/components/EyePreview'
import { ISchema } from '@formily/antd';
import { StandardTable } from 'god'
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
const { onFieldValueChange$ } = FormEffectHooks
// const { Search } = Input;
const SchemaButton = createVirtualBox('button', Button);
const SchemaTable = createVirtualBox('SchemaTable', Table);
// registerFormFields({ FlexRowLayout: connect()(FlexRowLayout) })
const formActions = createFormActions();
const actions = createFormActions();
const getData = async (params) => {
......@@ -23,126 +23,168 @@ const getData = async (params) => {
return res.data
}
const columnList: React.FC<{}> = () => {
const columnEffects = () => () => {
onFieldValueChange$('pagination').subscribe((state) => {
handleSearch({...state.value})
})
}
useEffect(() => {
const params = {
current: 1,
pageSize: 10
const schema: ISchema = {
type: 'object',
properties: {
megalayout: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
grid: true
},
properties: {
ctl: {
type: 'object',
"x-component": "Children",
"x-component-props": {
children: "{{controllerBtns}}"
}
},
name: {
type: 'string',
"x-component": "Search",
"x-mega-props": {
},
"x-component-props": {
placeholder: '栏目名称',
advanced: false
}
}
}
}
getTableDataSource(actions, params, getData);
}, [])
const handleModify = (value) => {
const { id, status } = value;
const postData = {
id: id,
enableStatus: (status ^ 1),
}
//@ts-ignore
PublicApi.postManageMemberColumnUpdateStatus(postData).
then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
})
}
// 栏目删除
const handleRemove = (id: number) => {
PublicApi.postManageMemberColumnDelete({id: id})
.then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
})
}
}
}
const controllerBtns = <Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/contentAbility/columnsManagement/add')}
type="primary"
icon={<PlusOutlined />}
>
新建
</Button>
</Col>
</Row>
const columnList: React.FC<{}> = () => {
const ref = useRef<any>({})
// 停用/启用
const handleModify = async (record: any) => {
await PublicApi.postManageMemberColumnUpdateStatus({
id: record.id,
enableStatus: record.status === 1 ? 0 : 1
})
ref.current.reload()
}
const handleSearch = async (params) => {
const title = actions.getFieldValue('search');
const postData = {
name: title || '',
current: 1,
pageSize: 10,
...params,
// 栏目删除
const handleRemove = async (id: number) => {
const res = await PublicApi.postManageMemberColumnDelete({ id })
if (res.code === 1000) {
ref.current.reload()
}
getTableDataSource(actions, postData, getData);
}
// 重设页码
const resetPagination = (params) => {
const paginationValue = actions.getFieldValue('pagination');
actions.setFieldValue('pagination', {
...paginationValue,
...params
// 获取列表
const fetchData = (params: any) => {
return new Promise((resolve) => {
PublicApi.getManageMemberColumnPage(params).then(res => {
resolve(res.data)
})
})
}
const columns: ColumnType<any>[] = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: '栏目名称',
dataIndex: 'name',
key: 'name',
render: (text: any, record: any) => (
<EyePreview url={`/memberCenter/contentAbility/columnsManagement/detail?id=${record.id}&preview=1`}>
{text}
</EyePreview>
)
},
{
title: '栏目分类',
align: 'center',
dataIndex: 'type',
key: 'type',
render: (text) => text === 1 ? '市场行情' : '资讯'
},
{
title: '栏目排序',
align: 'center',
dataIndex: 'sort',
key: 'sort',
},
{
title: '状态',
align: 'center',
dataIndex: 'status',
key: 'status',
render: (text: any, record: any) => (
<StatusSwitch
fieldNames="status"
handleConfirm={() => handleModify(record)}
record={record}
/>
)
},
{
title: '操作',
align: 'center',
key: 'operate',
dataIndex: 'operate',
render: (_, record) => !record.status && (
<>
<Button type='link' onClick={() => history.push(`/memberCenter/contentAbility/columnsManagement/detail?id=${record.id}`)}>修改</Button>
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => handleRemove(record.id)}
>
<Button type='link'>删除</Button>
</Popconfirm>
</>
)
}
]
return (
<Card>
<FilterTable
schema={columnManagementSchemat}
components={{CustomSearch, TablePagination, SchemaButton, Table}}
actions={actions}
expressionScope={{
goToCreate: () => {
// console.log("goToCreate")
history.push(`/memberCenter/contentAbility/columnsManagement/add`)
},
search: (value) => {
resetPagination({current: 1})
handleSearch({title: value, current: 1 });
},
renderOperation: (val, record) => {
return (
// 无效 status == 0 可以删除修改该
<Space>
{
record.status === 0
? <>
<Link to={`/memberCenter/contentAbility/columnsManagement/detail?id=${record.id}`}>编辑</Link>
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => handleRemove(record.id)}
okText="是"
cancelText="否"
>
<a>删除</a>
</Popconfirm>
</>
: null
}
</Space>
)
},
renderStatus: (text, record) => {
return (
<StatusSwitch
handleConfirm={() => handleModify(record)}
record={record}
fieldNames="status"
/>
)
},
reset: () => {
actions.setFieldValue('search');
resetPagination({current: 1})
handleSearch({current: 1})
},
// paginationChange: (page: number, pageSize: number) => {
// paginationChange(page, pageSize)
// }
}}
effects={columnEffects()}
/>
</Card>
<PageHeaderWrapper>
<Card>
<StandardTable
tableProps={{ rowKey: 'id' }}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
expressionScope={{ controllerBtns }}
onSubmit={values => ref.current.reload(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'name', FORM_FILTER_PATH)
}}
schema={schema}
>
</NiceForm>
}
/>
</Card>
</PageHeaderWrapper>
)
}
export default columnList
\ No newline at end of file
export default columnList
.custom_label {
position: relative;
font-size: 12px;
color: #909399;
&::after {
position: absolute;
display: inline-block;
margin-right: 4px;
color: #ff4d4f;
font-size: 12px;
font-family: SimSun, sans-serif;
line-height: 1;
content: '*';
top: 4px;
right: -22px;
}
}
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import { FilterTable, SchemaFlexRowLayout, SchemaFlexColumnLayout } from '../components/FilterTable';
import { Card, Input, Button, Table, Dropdown, Menu, Select, Space, Modal, Popconfirm } from 'antd';
import { createVirtualBox, createFormActions, FormEffectHooks, createEffectHook } from '@formily/antd';
......@@ -15,11 +15,6 @@ import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
const { onFormInit$, onFieldValueChange$ } = FormEffectHooks
const { Search } = Input;
const SchemaButton = createVirtualBox('button', Button);
const SchemaTable = createVirtualBox('SchemaTable', Table);
const SchemaDropDown = createVirtualBox('SchemaDropDown', Dropdown.Button);
const actions = createFormActions();
......@@ -34,31 +29,16 @@ interface optionsType {
value: string | number
}
const useGetColumns = () => {
const [state, setState] = useState<optionsType[]>([]);
useEffect(() => {
async function getAllColumns() {
const res = await PublicApi.getManageMemberColumnAll();
console.log(res);
const options = res.data.map((item) => ({label: item.name, value: item.id}));
// setTableStatus("column", "options", options);
setState(options)
}
getAllColumns();
}, [])
return state;
}
const getData = async (params: any) => {
const res = await PublicApi.getManageMemberInformationPage(params);
return res.data
}
const Infomation = () => {
const columns = useGetColumns();
const [selectedRow, setSelectedRow] = useState<any[]>([]);
// const [roleSelection, roleSelectCtl] = useRowSelectionTable()
// const refkeys = useRef([])
const selectedRowRef = useRef<any[]>([])
const columnsOptionsRef = useRef<any[]>([])
useEffect(() => {
const params = {
......@@ -68,6 +48,16 @@ const Infomation = () => {
getTableDataSource(actions, params, getData);
}, [])
useEffect(() => {
PublicApi.getManageMemberColumnAll().then((res) => {
const { code, data } = res
console.log(res);
if (code === 1000) {
columnsOptionsRef.current = data.map((item) => ({label: item.name, value: item.id}));
}
});
}, [])
const infomationEffects = () => () => {
onFormInit$().subscribe(() => {
actions.setFieldState('FILTERS', state => {
......@@ -121,12 +111,13 @@ const Infomation = () => {
// 批量删除
const batchDelete = () => {
const rows = selectedRow
const rows = selectedRowRef.current
handleBatch(rows, 1);
}
// type 1-批量删除 2-批量上架 3-批量下架
const handleBatch = (row, type) => {
console.log(`handleBatch type`, type)
PublicApi.postManageMemberInformationBatch({ids: row, type: type})
.then((data) => {
const paginationValue = actions.getFieldValue('pagination');
......@@ -231,12 +222,12 @@ const Infomation = () => {
batchGrounding: () => {
console.log("批量上架");
const rows = selectedRow
const rows = selectedRowRef.current
handleBatch(rows, 2);
},
undercarriage: () => {
console.log("批量下架")
const rows = selectedRow
const rows = selectedRowRef.current
handleBatch(rows, 3);
},
menu: () => {
......@@ -269,15 +260,18 @@ const Infomation = () => {
keys = keys.filter((_item) => _item !== record.id);
}
setSelectedRow(keys)
selectedRowRef.current = keys
},
onSelectAll: (selected, checkedRows, changeRows) => {
const changeRowKey = changeRows.filter((_item) => _item).map((item) => item.id);
let keys = Array.from(new Set([...changeRowKey, ...selectedRow]))
if(selected) {
setSelectedRow(keys)
selectedRowRef.current = keys
} else {
const removeKeys = keys.filter((_item) => !changeRowKey.includes(_item));
setSelectedRow(removeKeys)
selectedRowRef.current = removeKeys
}
},
selectedRowKeys: selectedRow
......@@ -287,7 +281,7 @@ const Infomation = () => {
const visible = !state.visible;
state.visible = visible;
if(visible) {
setFormStatus(actions, 'columns', "options", columns);
setFormStatus(actions, 'columns', "options", columnsOptionsRef.current);
}
actions.setFieldState('HIGHT_FILTER_BTN', (state) => {
//@ts-ignore
......@@ -296,7 +290,6 @@ const Infomation = () => {
)
})
});
},
}}
effects={infomationEffects()}
......
......@@ -15,6 +15,8 @@ import infomationInfoSchema from './schema/infomationInfoSchema';
import CustomUpload from '../components/WrapCustomUpload';
import useCustomValidator from '../hooks/useValidator'
import { COLUMN_CATEGORY } from '../constant';
import cx from 'classnames';
import styles from '../index.less'
const actions = createFormActions();
const { onFieldValueChange$, onFieldInputChange$ } = FormEffectHooks
......@@ -221,12 +223,7 @@ const InfomationInfo = () => {
setLabelIds(value);
},
label: (
<div>
{
(isAdd || isEdit) && [1, 2, 3, 4, 6].includes(recommendLabelValue)
? <span style={{color: '#ff4d4f'}}>* </span>
: null
}
<div className={cx((isAdd || isEdit) && [1, 2, 3, 4, 6].includes(recommendLabelValue) && styles.custom_label)}>
图片
</div>
)
......
......@@ -226,17 +226,17 @@ const schema = {
title: '摘要',
"x-component": 'TextArea',
"x-component-props": {
placeholder: "最长300个字符,150个汉字",
placeholder: "最长400个字符,200个汉字",
rows: 5,
},
"x-rules": [
{
"required": true,
"message": "最长300个字符,150个汉字"
"message": "最长400个字符,200个汉字"
},
{
limitByte: true,
maxByte: 300
maxByte: 400
}
],
},
......
......@@ -5,7 +5,7 @@ import { FormEffectHooks } from '@formily/antd'
import { StandardTable } from 'god';
import { LAYOUT_TYPE } from '@/constants'
import { PublicApi } from '@/services/api';
import { formatTimeString } from '@/utils'
import moment from 'moment'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import Search from '@/components/NiceForm/components/Search';
......@@ -57,19 +57,20 @@ const CommodityDrawer: React.FC<CommodityDrawerProps> = (props: CommodityDrawerP
<>
{record?.activityList?.map((item, index) => {
return (
<div key={index} style={{ marginBottom: 8 }}>
<a key={index} style={{ marginBottom: 8 }} href={`/memberCenter/marketingAbility/selfManagement/search/preview?id=${item.id}`} target={"_blank"}>
<Space direction='horizontal'>
<img src={ActivityImage} style={{ width: 24, height: 24, borderRadius: 4 }} />
<span>{item?.name}</span>
<div className={styles['defaultTag']}>{item?.type}</div>
<StatusTag title={item?.belongType === 1 ? '平台活动' : '商家活动'} type={item?.belongType === 1 ? 'primary' : 'success'} />
<div style={{color: '#301333'}}>有效期:{item.startTime && moment(item.startTime).format('YYYY-MM-DD HH:mm:ss')}{item.endTime && moment(item.endTime).format('YYYY-MM-DD HH:mm:ss')} </div>
</Space>
</div>
)
</a>
);
})}
</>
);
}
};
const columns = [
{
......
......@@ -34,7 +34,8 @@ const Environment_MAPS = {
const Property_MAPS = {
1: 'B端商城',
2: 'C端商城',
3: '自营商城',
3: 'B端自营商城',
4: 'C端自营商城',
}
const Title_MAPS = {
......@@ -71,13 +72,19 @@ const MixDrawer: React.FC<MixDrawerProps> = (props: MixDrawerProps) => {
let _fetch;
switch (type) {
case 1:
_params.type = 1;
_params.environment = 4;
_params.property = property;
if (layoutType !== 'own') {
_params.type = 1;
_params.environment = 4;
_params.property = property;
_fetch = PublicApi.getManageShopListAdorn;
} else {
_fetch = PublicApi.getManageWebShopWebFindAppSelfShopByCurrMember;
}
if (keyWord) {
_params.name = keyWord
}
_fetch = PublicApi.getManageShopListAdorn;
break;
case 3:
if (keyWord) {
......@@ -110,7 +117,11 @@ const MixDrawer: React.FC<MixDrawerProps> = (props: MixDrawerProps) => {
_params.shopId = shopId
_params.idNotInList = selectId
}
_fetch = PublicApi.getManageContentInformationListAdorn;
if (layoutType !== 'own') {
_fetch = PublicApi.getManageContentInformationListAdorn;
} else {
_fetch = PublicApi.getManageMemberInformationListAdorn
}
break;
// 品牌
case 6:
......
......@@ -77,6 +77,7 @@
&-record {
&-shop {
width: 100%;
height: 56px;
border: 1px solid #EDEEEF;
display: flex;
......@@ -102,6 +103,7 @@
}
&-integral {
width: 100%;
height: 56px;
border: 1px solid #EDEEEF;
display: flex;
......@@ -140,6 +142,7 @@
}
&-activity {
width: 100%;
height: 56px;
border: 1px solid #EDEEEF;
display: flex;
......@@ -185,6 +188,7 @@
}
&-commodity {
&-box {
margin-bottom: 16px;
......@@ -196,6 +200,7 @@
}
&-detail {
width: 100%;
height: 80px;
border: 1px solid #F7F8FA;
display: flex;
......@@ -239,6 +244,7 @@
}
&-activityList {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
......
import { ISchema } from "@formily/antd";
export const bannerSchema: ISchema = {
type: 'Object',
properties: {
layout: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
labelAlign: "top"
},
properties: {
name: {
type: 'string',
title: '名称',
'x-rules': [
{
required: true,
message: '请输入名称',
},
],
},
img: {
type: 'string',
title: '图标',
'x-rules': [
{
required: true,
message: '请上传图标',
},
],
"x-component": 'FormilyUpload',
"x-component-props": {
renderUploadChild: '{{renderUploadChild}}',
showFiles: false,
customizeItemRender: null,
children: null,
maxCount: 1,
},
},
typeWrap: {
type: 'object',
"x-component": 'flex-layout',
"x-component-props": {
rowStyle: {
justifyContent: 'flex-start',
alignItems: 'flex-start',
},
},
properties: {
type: {
type: 'string',
title: '导航链接',
enum: [],
'x-linkages': [
{
type: 'value:visible',
target: 'recordDetail',
condition: "{{$value !== 4}}"
},
],
'x-rules': [
{
required: true,
message: '请选择导航链接',
},
],
'x-component-props': {
style: {
width: 320,
marginRight: 12
}
}
},
sumbit: {
'x-component': 'Children',
'x-component-props': {
children: '{{SelectBtn}}',
},
'x-mega-props': {
span: 1,
},
},
}
},
recordDetail: {
'x-component': 'recordDetail',
},
}
}
}
};
......@@ -135,7 +135,7 @@ const BottomNavigationClient: React.FC<BottomNavigationClientProps> = (props: Bo
<div className={styles['bottomNavigationClient']}>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>名称</div>
<Input key={`${selectedKey}-name`} disabled={type === 1} defaultValue={name} onBlur={_onChangeName} />
<Input key={`${selectedKey}-name`} maxLength={4} disabled={type === 1} defaultValue={name} onBlur={_onChangeName} />
</div>
<div className={styles['bottomNavigationClient-box']}>
<div className={styles['bottomNavigationClient-box-label']}>链接</div>
......
......@@ -54,15 +54,15 @@ const TyleList_Own = [
label: '积分兑换',
},
{
value: 2,
label: '公司介绍',
value: 4,
label: '行情资讯',
},
{
value: 3,
label: '成为会员',
},
{
value: 4,
value: 2,
label: '公司介绍',
},
]
......@@ -190,7 +190,7 @@ const CardNavItem: React.FC<CardNavItemProps> = (props: CardNavItemProps) => {
let getFn
if (layoutType === LAYOUT_TYPE.channel) {
getFn = PublicApi.getSearchChannelCommodityTemplateGetFirstCategoryListByMemberId
} else if (layoutType === LAYOUT_TYPE.shop) {
} else {
params.memberRoleId = memberRoleId
getFn = PublicApi.getSearchCommodityTemplateGetFirstCategoryListByMemberId
}
......@@ -318,12 +318,15 @@ const CardNavItem: React.FC<CardNavItemProps> = (props: CardNavItemProps) => {
const handleSumit = (values) => {
const newProps: any = {
...values,
icon: values.icon[0].url
icon: values.icon[0].url,
empty: false
}
if (values.channel && values.type === 3) {
newProps.id = values.channel
} else if (values.type === 2 || values.type === 5) {
newProps.id = record.id
} else if (values.type === 2) {
newProps.id = record ? record?.id : undefined
} else if (values.type === 5) {
newProps.id = record ? record?.shopId : undefined
}
changeProps({
......
......@@ -39,7 +39,7 @@ const SuggestProductCommodity: React.FC<SuggestProductCommodityProps> = (props:
const { memberId, memberRoleId } = getAuth() || {}
useEffect(() => {
if (id && id != record[0]?.id) {
if (id && id != record.id) {
const _params: any = {
shopId,
idInList: id,
......@@ -56,13 +56,18 @@ const SuggestProductCommodity: React.FC<SuggestProductCommodityProps> = (props:
case LAYOUT_TYPE.shop:
getFn = PublicApi.getMarketingAdornGoodsListAdorn
break
case LAYOUT_TYPE.own:
_params.memberId = memberId
_params.memberRoleId = memberRoleId
getFn = PublicApi.getMarketingAdornGoodsListAdorn
break
default:
break;
}
getFn && getFn(_params).then((res) => {
if (res.code === 1000) {
setRecord(res.data.data);
setRecord(res.data.data[0]);
}
}).catch(err => console.log(err))
} else if (!id) {
......@@ -145,19 +150,19 @@ const SuggestProductCommodity: React.FC<SuggestProductCommodityProps> = (props:
}
}
const _record = record[0];
// const _record = record[0];
return (
<div className={styles['suggestProductCommodity']}>
{id && record ? (
<>
<div className={styles['suggestProductCommodity-detail']}>
<img src={_record?.mainPic} />
<img src={record?.mainPic} />
<div className={styles['suggestProductCommodity-detail-right']}>
<Tooltip title={_record?.name}>
<div className={styles['suggestProductCommodity-detail-right-title']}>{_record?.name}</div>
<Tooltip title={record?.name}>
<div className={styles['suggestProductCommodity-detail-right-title']}>{record?.name}</div>
</Tooltip>
<div className={styles['suggestProductCommodity-detail-right-price']}>{_record?.min ? `¥ ${priceFormat(_record?.min)}` : ''}</div>
<div className={styles['suggestProductCommodity-detail-right-price']}>{record?.min ? `¥ ${priceFormat(record?.min)}` : ''}</div>
</div>
<div className={styles['suggestProductCommodity-detail-cover']} onClick={() => { setCommodityVisible(true) }}>
<div className={styles['suggestProductCommodity-detail-cover-bottom']}>
......@@ -167,7 +172,7 @@ const SuggestProductCommodity: React.FC<SuggestProductCommodityProps> = (props:
</div>
<div className={styles['suggestProductCommodity-box']}>
<div className={styles['suggestProductCommodity-box-label']}>商品活动</div>
{_record?.activityList?.map((item, index) => {
{record?.activityList?.map((item, index) => {
return (
<div className={styles['suggestProductCommodity-activityList']} key={index} onClick={() => { _handleToDetailPage(item.id, item.belongType) }}>
<img src={ActivityImage} />
......@@ -187,6 +192,7 @@ const SuggestProductCommodity: React.FC<SuggestProductCommodityProps> = (props:
ref={saveEditInputRef}
key={index}
size="small"
maxLength={16}
className={styles['tag-input']}
defaultValue={editInputValue}
onChange={_handleEditInputChange}
......
......@@ -10,7 +10,7 @@
// 500 error
// .wrapper{
// }
.errorBox{
width: 100%;
......@@ -27,4 +27,5 @@
.white-wrap {
background: #fff;
}
\ No newline at end of file
}
......@@ -11,8 +11,8 @@ class Index extends Component<{}, {}> {
margin: '-24px',
}}
>
<img
src="https://shushangyun01.oss-cn-shenzhen.aliyuncs.com/a121f49434074532837012acf75e52011601275036112.png"
<img
src="https://shushangyun01.oss-cn-shenzhen.aliyuncs.com/a121f49434074532837012acf75e52011601275036112.png"
width="100%"
height="auto"
/>
......
import React, { useEffect, useState } from 'react';
import { updatePageConfig } from '@lingxi-disign/core';
import { updatePageConfig } from '@lingxi-disign/react';
import { cloneDeep } from 'lodash';
import pageConfig from '../schema/pageConfig';
import { PublicApi } from '@/services/api';
......@@ -123,7 +123,6 @@ function useGetLayout() {
...config
};
setDataSourceFromRequest(dataFromRequest);
console.log("newConfig", newConfig);
updatePageConfig(newConfig);
}, [info]);
......
......@@ -17,6 +17,8 @@ import Submit from '@/components/NiceForm/components/Submit';
import StatusTag from '@/components/StatusTag';
import CustomInputSearch from '@/components/NiceForm/components/CustomInputSearch';
import CustomCategorySearch from '@/components/NiceForm/components/CustomCategorySearch';
import defaultActivityImage from '@/assets/activity/ActivityImage.svg';
import moment from 'moment';
// import { serviceAdvertConfig } from '@/pages/editor/channelEdit/defaultData';
interface CommodityDrawerProps {
......@@ -28,6 +30,8 @@ interface CommodityDrawerProps {
selectType?: 'radio' | 'checkbox',
service?: ((data: any) => Promise<any>) | null,
formEffects?: (context: any, formAction: any) => void,
/** 格式化s搜索参数 */
formatedFilterParams?: (params: any) => any
}
const _returnCategoryList = (list: any, obj: any) => {
......@@ -38,7 +42,7 @@ const _returnCategoryList = (list: any, obj: any) => {
};
const CommodityDrawer: React.FC<CommodityDrawerProps> = (props: CommodityDrawerProps) => {
const { visible, onClose, onConfirm, selectId, filterParam, selectType = 'radio', service = null, formEffects } = props;
const { visible, onClose, onConfirm, selectId, filterParam, selectType = 'radio', service = null, formEffects, formatedFilterParams = () => {} } = props;
const { query: { shopId } }: any = history.location;
const [selectedRowKeys, setSelectedRowKeys] = useState<any>(selectId ? [selectId] : []);
const [selectedRows, setSelectedRows] = useState<any>([]);
......@@ -54,14 +58,15 @@ const CommodityDrawer: React.FC<CommodityDrawerProps> = (props: CommodityDrawerP
<>
{record?.activityList?.map((item, index) => {
return (
<div key={index} style={{ marginBottom: 8 }}>
<a key={index} style={{ marginBottom: 8 }} href={`/memberCenter/marketingAbility/selfManagement/search/preview?id=${item.id}`} target={"_blank"}>
<Space direction='horizontal'>
<img src={''} style={{ width: 24, height: 24, borderRadius: 4 }} />
<img src={defaultActivityImage} style={{ width: 24, height: 24, borderRadius: 4 }} />
<span>{item?.name}</span>
<div className={styles['defaultTag']}>{item?.type}</div>
<StatusTag title={item?.belongType === 1 ? '平台活动' : '商家活动'} type={item?.belongType === 1 ? 'primary' : 'success'} />
<div style={{color: '#301333'}}>有效期:{item.startTime && moment(item.startTime).format('YYYY-MM-DD HH:mm:ss')}{item.endTime && moment(item.endTime).format('YYYY-MM-DD HH:mm:ss')} </div>
</Space>
</div>
</a>
);
})}
</>
......@@ -132,11 +137,12 @@ const CommodityDrawer: React.FC<CommodityDrawerProps> = (props: CommodityDrawerP
};
const fetchTableData = async (params: any) => {
const formated = formatedFilterParams?.(params) || filterParam || {}
const _params = {
...params,
// ...params,
shopId,
idNotInList: Array.isArray(selectId) ? selectId : [selectId],
...filterParam
...formated
};
const fetchService = service || PublicApi.getMarketingAdornChannelGoodsListAdorn;
const { data } = await fetchService(_params);
......
......@@ -30,7 +30,7 @@ type SettingPanelType = {
}
const ComponentSchema = {
tabItem: tabTitleSchema,
// tabItem: tabTitleSchema,
secondaryItem: secondaryTabSchema,
flashSale: blockSchema,
flashSaleItem: flashSaleSchema,
......@@ -62,7 +62,7 @@ const EditPanel = () => {
* 但当一级类型没有被选择的时候,那么必须选择一级导航类型
*/
useEffect(() => {
if (activeKey === null || previousActiveKey !== activeKey) {
if (activeKey === null && previousActiveKey !== activeKey) {
if(activeKey === null) {
message.info("请先选择一级导航类型");
}
......@@ -115,8 +115,8 @@ const EditPanel = () => {
},
},
suggestProduct: {
type: selectedInfo.props.type || 1,
num: selectedInfo.props.num || 50,
type: selectedInfo?.props?.type || 1,
num: selectedInfo?.props?.num || 50,
title: selectedInfo.props.title,
},
suggestProductItem: {
......@@ -137,7 +137,6 @@ const EditPanel = () => {
message.info("当前商品展示类型为自动排序,不能进行单个商品设置");
return;
}
setFormValue(tempFormValue[componentType]);
setSchema(targetSchema);
setVisible(true);
......@@ -184,7 +183,6 @@ const EditPanel = () => {
const key = activeKey === null ? domKey : selectedInfo?.selectedKey || domKey;
const componentType: keyof typeof ComponentSchema = activeKey === null ? 'tabItem' : (selectedInfo as any)?.otherProps?.type;
console.log(values);
const formValueToProps = {
tabItem: {
name: values.title,
......@@ -223,7 +221,7 @@ const EditPanel = () => {
};
const currentProps = type === 0 && componentType.includes('suggestProduct') ? formValueToProps['suggestProduct'] : formValueToProps[componentType];
if(componentType === 'suggestProduct' || type === 0) {
if(componentType.includes('suggestProduct') && type === 0) {
setType(values.type);
}
changeProps({
......@@ -348,7 +346,7 @@ const EditPanel = () => {
</div>
<div className={styles.footer}>
<Space>
<Button onClick={() => setVisible(false)}>取消</Button>
<Button onClick={handleOnClose}>取消</Button>
<Button type="primary" onClick={() => formActions.submit()}>确认</Button>
</Space>
</div>
......
......@@ -15,6 +15,12 @@ export const tabTitleSchema: ISchema = {
type: 'string',
title: '类型',
enum: [],
"x-rules": [
{
required: true,
message: '请选择一级品类'
}
]
},
title: {
type: 'string',
......@@ -40,6 +46,12 @@ export const secondaryTabSchema: ISchema = {
type: 'string',
title: '类型',
enum: [],
"x-rules": [
{
required: true,
message: '请选择二级类型'
}
]
},
title: {
type: 'string',
......@@ -56,6 +68,12 @@ export const secondaryTabSchema: ISchema = {
children: null,
maxCount: 1,
},
"x-rules": [
{
required: true,
message: '请上传图片'
}
]
}
}
}
......@@ -77,8 +95,13 @@ export const blockSchema: ISchema = {
blockTitle: {
type: 'string',
title: '标题',
'x-rules': [
{
required: true,
message: '请填写标题'
}
]
},
}
}
}
......@@ -124,10 +147,19 @@ export const saleRankSchema: ISchema = {
rankProduct: {
type: 'object',
"x-component": 'FormilyCommodity',
"x-component-props": {
commodityKey: 'saleRanking'
}
},
sale: {
type: 'string',
title: '销量',
"x-rules": [
{
required: true,
message: '请填写销量',
}
]
}
}
......@@ -147,7 +179,6 @@ export const branchSchema: ISchema = {
labelAlign: "top"
},
properties: {
brand: {
type: 'object',
// title: '',
......@@ -209,7 +240,7 @@ export const productListSchema: ISchema = {
}
};
/** 销量排行schema */
/** 精选商品schema */
export const commoditySchema: ISchema = {
type: 'Object',
properties: {
......@@ -225,10 +256,9 @@ export const commoditySchema: ISchema = {
"x-component": 'FormilyCommodity',
'x-component-props': {
isWithLabels: true,
commodityKey: 'suggestProduct'
}
},
}
}
}
......
......@@ -9,6 +9,13 @@ import { useFilterSameOption } from '../../common/hooks/useFilterSameOption';
import { PublicApi } from '@/services/api';
import { searchBrandOptionEffect, searchCustomerCategoryOptionEffect } from './effect';
type ComponentTypeProps = {
activityType: number,
commodityKey: 'saleRanking' | 'suggestProduct',
isWithLabels?: boolean
} & {
[key: string]: any
}
interface Iprops {
value: {
id: number,
......@@ -21,11 +28,7 @@ interface Iprops {
label: string[],
},
props: {
['x-component-props']: {
activityType: number,
} & {
[key: string]: any
},
['x-component-props']: ComponentTypeProps,
},
mutators: {
change: (params: any) => void
......@@ -43,9 +46,9 @@ const FormilyCommodity: React.FC<Iprops> & { isFieldComponent: boolean } = (prop
const isSelfMall = useMemo(() => fixtureContext.isSelfMall, [fixtureContext.isSelfMall]);
/** 获取已经选择的id */
const sameKeyState = useFilterSameOption();
const disabledSaleRankingKeys = useMemo(() => sameKeyState[`tabItem_${activeKey}_saleRanking`], [sameKeyState, activeKey]);
const componentProps = props.props?.['x-component-props'] || {} as ComponentTypeProps;
const disabledSaleRankingKeys = useMemo(() => sameKeyState[`tabItem_${activeKey}_${componentProps.commodityKey}`], [sameKeyState, activeKey]);
console.log(sameKeyState, disabledSaleRankingKeys );
const componentProps = props.props?.['x-component-props'] || {} as { isWithLabels?: boolean };
const { state: productVisible, toggle: setProductVisible } = useToggle();
const productProps = useMemo(() => ({
......@@ -72,15 +75,22 @@ const FormilyCommodity: React.FC<Iprops> & { isFieldComponent: boolean } = (prop
setProductVisible(false);
};
const filterParam = useMemo(() => {
return {
const formatSearchParams = (params) => {
const idInList = typeof params.id !== 'undefined' && params.id ? { idInList: [params.id] } : {}
const { id, ...rest } = params;
const idNotInList = Array.from(new Set([productProps?.id].concat(disabledSaleRankingKeys).filter(Boolean)));
const common = {
shopId: fixtureContext?.shopId.toString(),
customerCategoryId: activeKey,
memberId: userAuth.memberId,
memberRoleId: userAuth.memberRoleId,
idNotInList: [productProps?.id].concat(disabledSaleRankingKeys).filter(Boolean)
};
}, [fixtureContext?.shopId.toString(), activeKey, disabledSaleRankingKeys, isSelfMall]);
idNotInList: idNotInList,
...rest,
...idInList,
}
return common
}
const restProps = useMemo(() => {
const data = {
......@@ -116,13 +126,13 @@ const FormilyCommodity: React.FC<Iprops> & { isFieldComponent: boolean } = (prop
return (
<div>
<Product activityImage={''} onEdit={onEdit} {...productProps} isWithLabels={componentProps.isWithLabels || false} onLabelChange={onLabelChange} />
<Product onEdit={onEdit} {...productProps} isWithLabels={componentProps.isWithLabels || false} onLabelChange={onLabelChange} />
<CommodityDrawer
{...restProps}
visible={productVisible}
onClose={onClose}
onConfirm={onOk}
filterParam={filterParam}
formatedFilterParams={formatSearchParams}
selectId={productProps?.id?.toString()}
/>
</div>
......
......@@ -37,10 +37,11 @@ const FormilyActivityProduct: React.FC<Iprops> & { isFieldComponent: boolean } =
/** 1 级分类 id */
const { activeKey } = useSelector<any, "activeKey" >(['activeKey']);
const fixtureContext = useContext(context);
/** 是否是自营商城 */
const isSelfMall = useMemo(() => fixtureContext.isSelfMall, [fixtureContext.isSelfMall]);
const ignoresFilters = ['activityType'];
const componentProps = props.props?.['x-component-props'] || {} as { activityType?: number, isWithLabels: boolean };
const activityImage = "logo.png";
const { state: productVisible, toggle: setProductVisible } = useToggle();
/** @tofixed activityId */
const cacheProductList = useMemo(() => [{ ...value }], [value]);
......@@ -66,10 +67,12 @@ const FormilyActivityProduct: React.FC<Iprops> & { isFieldComponent: boolean } =
const fetchData = async (params: GetMarketingAdornMerchantActivityListAdornRequest) => {
const withActivityType = componentProps?.activityType ? { activityType: componentProps?.activityType } : {};
/** 自营商城,b端,c端需要带一级品类,不明白为啥要这么设计 */
const withCategoryId = isSelfMall ? { categoryId: activeKey } : {};
const common = {
...params,
shopId: fixtureContext?.shopId.toString(),
// categoryId: activeKey,
...withCategoryId,
...withActivityType
};
const isWithActivityType = common;
......@@ -78,7 +81,7 @@ const FormilyActivityProduct: React.FC<Iprops> & { isFieldComponent: boolean } =
return (
<div style={{ position: 'relative' }}>
<Product activityImage={''} onEdit={onEdit} {...productProps} isWithLabels={componentProps.isWithLabels || false} />
<Product onEdit={onEdit} {...productProps} isWithLabels={componentProps.isWithLabels || false} />
<ActivityProductDrawer
ignoresFilters={ignoresFilters}
activityImage={activityImage}
......
......@@ -274,7 +274,6 @@ const CustomizeTabs: React.FC<Iprops> & { TabItem: typeof TabItem } = (props: Ip
...cloneDeepPageConfig,
...finalData,
};
console.log("fuckNewConfig", newConfigData);
createActions({ type: 'onChangeTabKey', payload: { activeKey: matches?.[1] === 'undefined' ? null : matches?.[1] , domKey: matches?.[2], pageConfig: newConfigData, hasRequestTabKey: concatActiveKey } });
setActiveKey(activeKey);
};
......
......@@ -77,7 +77,7 @@ const CategoryNavigation = () => {
}, [info]);
const onSave = async (pageConfig, rest) => {
const hasRequestTabKey = rest.hasRequestTabKey.map((_item: string) => _item.match(/id_(.*)\/\.\$(\d+)/)?.[1]) || [];
const hasRequestTabKey = rest.hasRequestTabKey?.map((_item: string) => _item.match(/id_(.*)\/\.\$(\d+)/)?.[1]) || [];
/** domKey 从7开始都是tab 的值 */
const tabChildren = pageConfig[4].childNodes.slice(1);
......@@ -120,6 +120,7 @@ const CategoryNavigation = () => {
return tabProps;
});
const postData = { style: 0, category: result.filter(Boolean) };
console.log(result, postData);
const service = isSelfMall ? PublicApi.postTemplateAdornAppSelfSave : PublicApi.postTemplateAdornAppChannelSave;
const { data, code } = await service({
templateId: Number(id),
......
......@@ -102,21 +102,6 @@ const OwnMallTempleteEdit: React.FC<ShopPreviewPropsType> = props => {
}, []);
/**
* 获取渠道信息
*/
const fetchChannelInfo = (): Promise<any> => {
return new Promise(resolve => {
PublicApi.getTemplateWebMemberChannelWebFindCurrMemberChannel().then(
res => {
if (res.code === 1000) {
resolve(res.data);
}
},
);
});
};
/**
* 获取app装修信息
*/
const getAppConfig = (): Promise<any> => {
......@@ -172,10 +157,8 @@ const OwnMallTempleteEdit: React.FC<ShopPreviewPropsType> = props => {
const param: any = {
current: 1,
pageSize: 1,
sortType: 2,
recommendLabel: [2, 3],
};
const res = await PublicApi.getManageContentInformationPage(param);
const res = await PublicApi.getManageMemberInformationListAdorn(param);
message.destroy()
if (res.code === 1000 && res.data.data) {
return res.data.data[0].title;
......@@ -986,7 +969,7 @@ const OwnMallTempleteEdit: React.FC<ShopPreviewPropsType> = props => {
memberRoleId,
};
const _detailsData = await PublicApi.getMarketingAdornChannelGoodsListAdorn(
const _detailsData = await PublicApi.getMarketingAdornGoodsListAdorn(
param,
);
_detailsData.data.data?.forEach((child, childIndex) => {
......
......@@ -115,8 +115,8 @@ const Information: React.FC = () => {
<div className={cx(styles.information_list_item_item)}>
<span className={styles.date}>{moment(item.collectTime).format("YYYY-MM-DD HH:mm")}</span>
</div>
<div className={cx(styles.information_list_item_item, styles.float_right)} onClick={() => handleCancelCollect(item)}>
<div className={cx(styles.collection_state)}>
<div className={cx(styles.information_list_item_item, styles.float_right)}>
<div className={cx(styles.collection_state)} onClick={() => handleCancelCollect(item)}>
<StarFilled />
<label>收藏</label>
</div>
......
import React, { useEffect, useState } from 'react';
import omit from 'lodash/omit';
import { updatePageConfig } from '@lingxi-disign/core';
import { updatePageConfig } from '@lingxi-disign/react';
import DEFAULT_DATA from '../mock/index.json';
import { GetTemplateWebActivityPageGetResponse } from '@/services/Template2Api';
import { usePageStatus } from '@/hooks/usePageStatus';
......
......@@ -82,6 +82,7 @@
align-items: center;
width: 100%;
margin-bottom: 8px;
color: #303133;
.activityImg {
width: 24px;
......
......@@ -6,7 +6,8 @@ import { Input, Tag, Space } from 'antd';
import { unstable_batchedUpdates } from 'react-dom';
import { priceFormat } from '@/utils/numberFomat';
import styles from './product.less';
import defaultActivityImage from '@/assets/activity/ActivityImage.svg'
// import { } from 'umi'
interface Iprops {
onEdit?: ((data: { id: number, activityId: number}) => void) | null,
......@@ -23,13 +24,13 @@ interface Iprops {
}[],
/** 是否有标签 */
isWithLabels: boolean,
activityImage: string,
activityImage?: string,
label: string[],
onLabelChange?: ((data: { id: number, activityId: number, label: string[] }) => void) | null
}
const Product: React.FC<Iprops> = (props: Iprops) => {
const { onEdit, onRemove, productName, productImgUrl, id, activityId, price, activityList, isWithLabels, activityImage, label, onLabelChange = null } = props;
const { onEdit, onRemove, productName, productImgUrl, id, activityId, price, activityList, isWithLabels, activityImage = defaultActivityImage, label, onLabelChange = null } = props;
const [inputVisible, setInputVisible] = useState<boolean>(false);
const [inputValue, setInputValue] = useState<string>("");
const inputRef = useRef<(Input) | null>(null);
......@@ -163,11 +164,11 @@ const Product: React.FC<Iprops> = (props: Iprops) => {
{
activityList?.map((_item) => {
return (
<div className={styles.activityItem} key={_item.id}>
<a className={styles.activityItem} key={_item.id} href={`/memberCenter/marketingAbility/selfManagement/search/preview?id=${_item.id}`} target={"_blank"}>
<img className={styles.activityImg} src={activityImage} />
<span className={styles.activityName}>{_item.name}</span>
<StatusTag type="danger" title={_item.type}></StatusTag>
</div>
</a>
);
})
}
......
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