@@ -1,6 +1,7 @@ | |||
import React, { useState, useEffect, useRef } from 'react'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import { Form, Input, Select, InputNumber, TreeSelect, message, Button, Modal, Radio, Upload, Switch } from 'antd'; | |||
import { Form, Input, Select, InputNumber, Space, Tag, message, Button, Modal, Switch, Drawer, Table } from 'antd'; | |||
import { PlusOutlined } from '@ant-design/icons'; | |||
import quickAPI from "../../service"; | |||
import indexStyles from "../../index.less"; | |||
import StepsButton from "../StepsButton"; | |||
@@ -13,39 +14,39 @@ const BomConfig = (props) => { | |||
const [editBomForm] = Form.useForm(); | |||
const optionsWithDisabled = [ | |||
{ | |||
label: '新建配方', | |||
value: true, | |||
}, | |||
{ | |||
label: '选择配方', | |||
value: false, | |||
const onFinish = async (values) => { | |||
if (values.id) { | |||
quickAPI.UpdateBom(values).then((r) => { | |||
if (r.data) { | |||
message.success('修改成功'); | |||
} else { | |||
message.error('修改失败请重试!'); | |||
} | |||
//刷新数据 | |||
actionRef.current.reload(); | |||
setIsShowModal(false); | |||
}); | |||
} else { | |||
quickAPI.AddBom(values).then((r) => { | |||
if (r.data) { | |||
message.success('添加成功'); | |||
//刷新数据 | |||
actionRef.current.reload(); | |||
setIsShowModal(false); | |||
} else { | |||
message.error('添加失败请重试!'); | |||
} | |||
}); | |||
} | |||
]; | |||
const [isCreate, setIsCreate] = useState(props.bomConfig.id ? false : true); | |||
const onChangeState = ({ target: { value } }) => { | |||
setIsCreate(value); | |||
let emptyObj = { | |||
id: "", | |||
code: "", | |||
name: "", | |||
bomTypeList: [], | |||
sort: 0 | |||
} | |||
props.onFinishForm('bomConfig', emptyObj); | |||
editBomForm.setFieldsValue(emptyObj); | |||
setSelectRowKeys([]); | |||
setSelectedRows([]); | |||
} | |||
const onFinish = (values) => { | |||
props.onFinishForm('bomConfig', values, true); | |||
} | |||
const columns = [ | |||
{ | |||
title: '主键', | |||
dataIndex: 'id', | |||
hideInTable: true, | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '配方编码', | |||
dataIndex: 'code', | |||
@@ -57,21 +58,81 @@ const BomConfig = (props) => { | |||
dataIndex: 'name', | |||
hideInForm: true, | |||
hideInSearch: true, | |||
} | |||
}, | |||
{ | |||
title: '排序', | |||
dataIndex: 'sort', | |||
hideInForm: true, | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '配方分类', | |||
dataIndex: 'bomTypeList', | |||
search: false, | |||
width: 450, | |||
render: (_, record) => ( | |||
<Space> | |||
{ | |||
bomtype.filter(x => { | |||
let findId = record.bomTypeList.find(findItem => findItem === x.id); | |||
let findBomType = bomtype.find(bomItem => bomItem.id === findId); | |||
return findBomType != null || undefined; | |||
}).map(item => ( | |||
<Tag color="#87d068" key={item.id}> | |||
{item.name} | |||
</Tag> | |||
)) | |||
} | |||
</Space> | |||
), | |||
}, | |||
{ | |||
title: '配方类型', | |||
dataIndex: 'isMain', | |||
hideInForm: true, | |||
valueEnum: { | |||
false: { | |||
text: '辅料配方', | |||
status: 'Processing', | |||
}, | |||
true: { | |||
text: '主料配方', | |||
status: 'Success', | |||
}, | |||
}, | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a | |||
key="primary3" | |||
type="primary" | |||
onClick={() => { | |||
setIsShowModal(true); | |||
setCurrentOption(record); | |||
editBomForm.setFieldsValue(record); | |||
}} | |||
> | |||
更新 | |||
</a> | |||
], | |||
}, | |||
]; | |||
const [currentPage, setCurrentPage] = useState(0); | |||
const [pageSize, setPageSize] = useState(5); | |||
const [selectedRowsState, setSelectedRows] = useState(props.bomConfig.id ? [props.bomConfig] : []); | |||
const [selectedRowKeys, setSelectRowKeys] = useState(props.bomConfig.id ? [props.bomConfig.id] : []); | |||
const [selectedRows, setSetSelectedRows] = useState([]); | |||
const [selectedRowKeys, setSelectRowKeys] = useState([]); | |||
//配方类型 | |||
const [bomtype, setBomtype] = useState([]); | |||
//是否展示配方弹窗 | |||
const [isShowBomModal, setIsShowBomModal] = useState(false); | |||
/** | |||
* 获取菜谱分类 | |||
* 获取配方分类 | |||
*/ | |||
const onFetchBomType = async () => { | |||
const response = await quickAPI.GetBomTypePage({ | |||
@@ -83,48 +144,133 @@ const BomConfig = (props) => { | |||
} | |||
} | |||
//当前操作的配方对象 | |||
const [currentOption, setCurrentOption] = useState({ id: '' }); | |||
//是否显示 新增/编辑 菜谱弹窗 | |||
const [isShowModal, setIsShowModal] = useState(false); | |||
const actionRef = useRef(); | |||
//商品绑定菜谱弹窗 | |||
const [showMenuDrawer, setShowMenuDrawer] = useState(false); | |||
//当前选中的商品 | |||
const [currentSelectedFood, setCurrentSelectedFood] = useState(''); | |||
//商品下拉列表 | |||
const [foodDropDown, setFoodDropDown] = useState([]); | |||
//某商品下面的配方列表 | |||
const [bomBelongToGoods, setBomBelongToGoods] = useState([]); | |||
const goodsBomColumns = [ | |||
{ | |||
title: '配方名称', | |||
dataIndex: 'name', | |||
hideInForm: true, | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a | |||
key="primary3" | |||
type="primary" | |||
onClick={() => { | |||
props.onBomRelationGoods(record.foodMenuId, record.goodsId, record, false); | |||
}} | |||
> | |||
移除配方 | |||
</a> | |||
], | |||
} | |||
] | |||
/** | |||
* 初始化商品下拉列表 | |||
*/ | |||
const initFoodDropDown = () => { | |||
const goodsArray = []; | |||
props.foodMenuConfig.forEach(menuItem => { | |||
const foodMenuId = menuItem.id; | |||
if (menuItem.goodsConfig) { | |||
menuItem.goodsConfig.forEach(goodsItem => { | |||
goodsItem.foodMenuId = foodMenuId; | |||
const findRepet = goodsArray.find(item => item.id === goodsItem.id); | |||
if (!findRepet) { | |||
goodsArray.push(goodsItem); | |||
} | |||
}); | |||
} | |||
}); | |||
if (!currentSelectedFood) { | |||
setCurrentSelectedFood(goodsArray[0].id); | |||
} | |||
setFoodDropDown(goodsArray); | |||
} | |||
//根据商品ID渲染配方列表 | |||
const initGoodsBom = () => { | |||
const findGoods = foodDropDown.find(item => item.id === currentSelectedFood); | |||
if (findGoods && findGoods.bomConfig) { | |||
setBomBelongToGoods(findGoods.bomConfig); | |||
} else { | |||
setBomBelongToGoods([]); | |||
} | |||
} | |||
/** | |||
* 配方关联商品 | |||
*/ | |||
const bomRelationGoods = () => { | |||
const findGoods = foodDropDown.find(item => item.id === currentSelectedFood); | |||
if (findGoods) { | |||
selectedRows.forEach(item => { | |||
item.foodMenuId = findGoods.foodMenuId; | |||
item.goodsId = findGoods.id; | |||
}); | |||
props.onBomRelationGoods(findGoods.foodMenuId, findGoods.id, selectedRows); | |||
} | |||
} | |||
useEffect(() => { | |||
onFetchBomType(); | |||
}, []); | |||
return <> | |||
<div className={indexStyles.choose_change_state}> | |||
<Radio.Group | |||
options={optionsWithDisabled} | |||
onChange={onChangeState} | |||
value={isCreate} | |||
optionType="button" | |||
buttonStyle="solid" | |||
/> | |||
</div> | |||
useEffect(() => { | |||
initFoodDropDown(); | |||
}, [props.foodMenuConfig]); | |||
useEffect(() => { | |||
initGoodsBom(); | |||
}, [foodDropDown, currentSelectedFood]); | |||
<div className={indexStyles.common_row}> | |||
return <> | |||
<Modal width={600} title={currentOption.id ? '编辑配方' : '新增配方'} visible={isShowModal} footer={false} onCancel={() => setIsShowModal(false)}> | |||
<Form | |||
labelCol={{ span: 4 }} | |||
layout="horizontal" | |||
preserve={false} | |||
initialValues={props.bomConfig} | |||
onFinish={onFinish} | |||
style={{ width: '600px', marginRight: '30px' }} | |||
form={editBomForm} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="code" label="配方编码" rules={[{ required: true }]} > | |||
<Input placeholder="配方编码" disabled={!isCreate || props.bomConfig.id} /> | |||
<Input placeholder="配方编码" /> | |||
</Form.Item> | |||
<Form.Item name="name" label="配方名称" rules={[{ required: true }]}> | |||
<Input placeholder="配方名称" disabled={!isCreate || props.bomConfig.id} /> | |||
<Input placeholder="配方名称" /> | |||
</Form.Item> | |||
<div className={indexStyles.add_row_content}> | |||
<Form.Item name="bomTypeList" label="配方类型" rules={[{ required: true }]}> | |||
<Select | |||
disabled={!isCreate || props.bomConfig.id} | |||
style={{ width: '75%' }} | |||
style={{ width: '70%' }} | |||
mode="multiple" | |||
allowClear > | |||
allowClear | |||
> | |||
{bomtype.map((item, index) => { | |||
return ( | |||
<Select.Option index={item.id} value={item.id} key={item.id}> | |||
@@ -134,135 +280,168 @@ const BomConfig = (props) => { | |||
})} | |||
</Select> | |||
</Form.Item> | |||
<Button disabled={!isCreate || props.bomConfig.id} type="primary" className={indexStyles.add_row_btn} onClick={() => setIsShowBomModal(true)} >添加配方类型</Button> | |||
<Button type="primary" className={indexStyles.add_row_btn} onClick={() => setIsShowBomModal(true)} >添加配方类型</Button> | |||
</div> | |||
<Form.Item name="isMain" label="配方类型" > | |||
<Switch disabled={!isCreate || props.bomConfig.id} checkedChildren="主料" unCheckedChildren="辅料" /> | |||
<Switch checkedChildren="主料" unCheckedChildren="辅料" /> | |||
</Form.Item> | |||
<Form.Item name="sort" label="排序" rules={[{ required: true }]}> | |||
<InputNumber placeholder="排序" min={1} disabled={!isCreate || props.bomConfig.id} /> | |||
<InputNumber placeholder="排序" min={1} /> | |||
</Form.Item> | |||
<Form.Item> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev}></StepsButton> | |||
<Button type="primary" htmlType="submit"> | |||
确定 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Modal | |||
title="新建配方类型" | |||
width={640} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
visible={isShowBomModal} | |||
footer={null} | |||
onCancel={() => { | |||
setIsShowBomModal(false); | |||
<Modal | |||
title="新建配方类型" | |||
width={640} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
visible={isShowBomModal} | |||
footer={null} | |||
onCancel={() => { | |||
setIsShowBomModal(false); | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
initialValues={props?.values} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.CreateBomType(values); | |||
if (response.data) { | |||
message.success('配方类别添加成功'); | |||
setIsShowBomModal(false); | |||
onFetchBomType(); | |||
} else { | |||
message.error(response.errors || '配方类别添加失败'); | |||
} | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
initialValues={props?.values} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.CreateBomType(values); | |||
if (response.data) { | |||
message.success('配方类别添加成功'); | |||
setIsShowBomModal(false); | |||
onFetchBomType(); | |||
} else { | |||
message.error(response.errors || '配方类别添加失败'); | |||
} | |||
}} | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="配方类型名称" rules={[{ required: true, max: 64, whitespace: true }]}> | |||
<Input placeholder="请输入配方类型名称" /> | |||
</Form.Item> | |||
<Form.Item | |||
name="pertain" | |||
label="归属" | |||
defaultValue={props?.values?.pertain} | |||
rules={[{ required: true, message: '请选择类型归属' }]} > | |||
<Select placeholder="请选择类型归属"> | |||
<Option value="1">无</Option> | |||
<Option value="2">TMC </Option> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
defaultValue={props?.values?.status} | |||
rules={[{ required: true, message: '请选择状态' }]} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="配方类型名称" rules={[{ required: true, max: 64, whitespace: true }]}> | |||
<Input placeholder="请输入配方类型名称" /> | |||
</Form.Item> | |||
<Form.Item | |||
name="pertain" | |||
label="归属" | |||
defaultValue={props?.values?.pertain} | |||
rules={[{ required: true, message: '请选择类型归属' }]} > | |||
<Select placeholder="请选择类型归属"> | |||
<Option value="1">无</Option> | |||
<Option value="2">TMC </Option> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
defaultValue={props?.values?.status} | |||
rules={[{ required: true, message: '请选择状态' }]} | |||
> | |||
<Select placeholder="请选择状态"> | |||
<Option value="0">正常</Option> | |||
<Option value="1">停用</Option> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Select placeholder="请选择状态"> | |||
<Option value="0">正常</Option> | |||
<Option value="1">停用</Option> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
{ | |||
!isCreate && <ProTable | |||
headerTitle="配方列表" | |||
rowKey="id" | |||
pagination={{ | |||
current: currentPage, | |||
pageSize: pageSize, | |||
onChange: (page, pageSize) => { | |||
setCurrentPage(page); | |||
setPageSize(pageSize); | |||
} | |||
}} | |||
search={false} | |||
//数据绑定 | |||
request={async (params) => { | |||
var goodsBomsData = []; | |||
var total = 0; | |||
await quickAPI.GetBomPage(params).then((r) => { | |||
goodsBomsData = r.data.data; | |||
total = r.data.total; | |||
}); | |||
return { | |||
data: goodsBomsData, | |||
success: true, | |||
total: total, | |||
}; | |||
<ProTable | |||
actionRef={actionRef} | |||
style={{ width: '100%' }} | |||
headerTitle="配方列表" | |||
rowKey="id" | |||
pagination={{ | |||
current: currentPage, | |||
pageSize: pageSize, | |||
onChange: (page, pageSize) => { | |||
setCurrentPage(page); | |||
setPageSize(pageSize); | |||
} | |||
}} | |||
search={false} | |||
//数据绑定 | |||
request={async (params) => { | |||
var goodsBomsData = []; | |||
var total = 0; | |||
await quickAPI.GetBomPage(params).then((r) => { | |||
goodsBomsData = r.data.data; | |||
total = r.data.total; | |||
}); | |||
return { | |||
data: goodsBomsData, | |||
success: true, | |||
total: total, | |||
}; | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
type: 'checkbox', | |||
onChange: (selectedRowKeys, selectedRows) => { | |||
setSelectRowKeys(selectedRowKeys); | |||
setSetSelectedRows(selectedRows); | |||
}, | |||
selectedRowKeys: selectedRowKeys | |||
}} | |||
toolBarRender={() => [ | |||
<Button key="button" icon={<PlusOutlined />} type="primary" onClick={() => { | |||
editBomForm.resetFields(); | |||
setCurrentOption({ id: '' }); | |||
setIsShowModal(true); | |||
}}> | |||
新建 | |||
</Button>, | |||
<Button key="button" type="primary" onClick={() => { | |||
setShowMenuDrawer(true); | |||
}}> | |||
关联商品 | |||
</Button>, | |||
]} | |||
/> | |||
<Drawer width={600} title="配方关联商品" placement="right" onClose={() => setShowMenuDrawer(false)} visible={showMenuDrawer}> | |||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px' }}> | |||
<div style={{ marginRight: '10px' }}> | |||
当前商品: | |||
</div> | |||
<Select | |||
style={{ | |||
width: '300px', | |||
marginRight: '10px' | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
type: 'radio', | |||
onChange: (selectedRowKeys, selectedRows) => { | |||
setSelectRowKeys(selectedRowKeys); | |||
setSelectedRows(selectedRows); | |||
if (selectedRows.length > 0) { | |||
props.onFinishForm('bomConfig', selectedRows[0]); | |||
editBomForm.setFieldsValue(selectedRows[0]); | |||
} else { | |||
let emptyObj = { | |||
id: "", | |||
code: "", | |||
name: "", | |||
bomTypeList: [], | |||
sort: 0 | |||
} | |||
editBomForm.setFieldsValue(emptyObj); | |||
props.onFinishForm('bomConfig', emptyObj); | |||
} | |||
}, | |||
selectedRowKeys: selectedRowKeys | |||
onChange={(item) => { | |||
setCurrentSelectedFood(item); | |||
}} | |||
/> | |||
} | |||
</div> | |||
placeholder="请选择商品" | |||
value={currentSelectedFood} | |||
> | |||
{ | |||
foodDropDown.map(item => { | |||
return <Option key={item.id} value={item.id}>{item.name}</Option> | |||
}) | |||
} | |||
</Select> | |||
<Button onClick={bomRelationGoods}>确定关联</Button> | |||
</div> | |||
<Table rowKey="id" columns={goodsBomColumns} dataSource={bomBelongToGoods} /> | |||
</Drawer> | |||
<StepsButton foodMenuConfig={props.foodMenuConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
</> | |||
} | |||
@@ -224,7 +224,7 @@ const DeviceConfig = (props) => { | |||
const [pageSize, setPageSize] = useState(10); | |||
useEffect(() => { | |||
if (props.deviceConfig.id) { | |||
if (props.deviceConfig?.id) { | |||
setSelectRowKeys([props.deviceConfig.id]); | |||
} | |||
onFetchOrgTree(); | |||
@@ -280,7 +280,7 @@ const DeviceConfig = (props) => { | |||
</Button> | |||
]} | |||
/> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<StepsButton deviceConfig={props.deviceConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<Modal width={600} title={currentOption.id ? '编辑设备' : '新增设备'} visible={isShowModal} footer={false} onCancel={() => setIsShowModal(false)}> | |||
<Form | |||
layout="Horizontal" | |||
@@ -166,7 +166,7 @@ const FoodMenuConfig = (props) => { | |||
]} | |||
/> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<StepsButton foodMenuConfig={props.foodMenuConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<Modal width={600} title={currentOption.id ? '编辑菜谱' : '新增菜谱'} visible={isShowModal} footer={false} onCancel={() => setIsShowModal(false)}> | |||
<Form | |||
@@ -1,7 +1,7 @@ | |||
import React, { useState, useEffect, useRef } from 'react'; | |||
import { PlusOutlined, UploadOutlined } from '@ant-design/icons'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import { Form, Input, Select, InputNumber, TreeSelect, message, Button, Modal, Radio, Upload, Switch } from 'antd'; | |||
import { Form, Input, Select, InputNumber, message, Button, Modal, Drawer, Upload, Switch, Table } from 'antd'; | |||
import quickAPI from "../../service"; | |||
import StepsButton from "../StepsButton"; | |||
import indexStyles from "../../index.less"; | |||
@@ -11,7 +11,7 @@ const key = 'message'; | |||
const GoodsConfig = (props) => { | |||
const { Option, OptGroup } = Select; | |||
const [url, setUrl] = useState(props.goodsConfig.imgUrl); | |||
const [url, setUrl] = useState(); | |||
//商品单位 | |||
const [goodsUnit, setGoodsUnit] = useState([]); | |||
//商品大类 | |||
@@ -201,17 +201,13 @@ const GoodsConfig = (props) => { | |||
dataIndex: 'goodsTypeName', | |||
hideInForm: true, | |||
hideInSearch: true, | |||
// valueEnum: goodsTypes | |||
}, | |||
{ | |||
title: '商品类型', | |||
dataIndex: 'goodsTypeId', | |||
hideInForm: true, | |||
hideInTable: true, | |||
// hideInSearch: true, | |||
// valueEnum: goodsTypes, | |||
}, | |||
{ | |||
title: '商品属性', | |||
dataIndex: 'goodsAttribute', | |||
@@ -274,6 +270,41 @@ const GoodsConfig = (props) => { | |||
const actionRef = useRef(); | |||
const [selectedRowKeys, setSelectRowKeys] = useState([]); | |||
const [selectedRows, setSetSelectedRows] = useState([]); | |||
//商品绑定菜谱弹窗 | |||
const [showMenuDrawer, setShowMenuDrawer] = useState(false); | |||
const [menuFoodList, setMenuFoodList] = useState([]); | |||
//当前菜谱 | |||
const [currentFoodMenu, setCurrentFoodMenu] = useState(props.foodMenuConfig[0].id); | |||
const menuFoodsColumns = [ | |||
{ | |||
title: '名称', | |||
dataIndex: 'name', | |||
valueType: 'textarea', | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a onClick={() => { | |||
props.onAddGoodsToFoodMenu(currentFoodMenu, record, false); | |||
}}> | |||
移出菜谱 | |||
</a> | |||
] | |||
} | |||
] | |||
/** | |||
* 将商品添加到菜谱 | |||
* @param {*} goods | |||
*/ | |||
const addGoodsToFoodMenu = () => { | |||
props.onAddGoodsToFoodMenu(currentFoodMenu, selectedRows); | |||
} | |||
useEffect(() => { | |||
onFetchGoodsUnit(); | |||
@@ -281,6 +312,15 @@ const GoodsConfig = (props) => { | |||
onFetchGoodsSmallTypeList(); | |||
}, []); | |||
useEffect(() => { | |||
const findFoodMenu = props.foodMenuConfig.find(item => item.id === currentFoodMenu); | |||
if (findFoodMenu) { | |||
setMenuFoodList(findFoodMenu.goodsConfig); | |||
} else { | |||
setMenuFoodList([]); | |||
} | |||
}, [props.foodMenuConfig, currentFoodMenu]); | |||
return <> | |||
<Modal width={600} title={currentOption.id ? '编辑商品' : '新增商品'} visible={isShowModal} footer={false} onCancel={() => setIsShowModal(false)}> | |||
<Form | |||
@@ -457,6 +497,7 @@ const GoodsConfig = (props) => { | |||
type: 'checkbox', | |||
onChange: (selectedRowKeys, selectedRows) => { | |||
setSelectRowKeys(selectedRowKeys); | |||
setSetSelectedRows(selectedRows); | |||
}, | |||
selectedRowKeys: selectedRowKeys | |||
}} | |||
@@ -467,11 +508,16 @@ const GoodsConfig = (props) => { | |||
setIsShowModal(true); | |||
}}> | |||
新建 | |||
</Button> | |||
</Button>, | |||
<Button key="button" type="primary" onClick={() => { | |||
setShowMenuDrawer(true); | |||
}}> | |||
关联菜谱 | |||
</Button>, | |||
]} | |||
/> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<StepsButton foodMenuConfig={props.foodMenuConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<Modal | |||
title='新建商品单位' | |||
@@ -486,7 +532,6 @@ const GoodsConfig = (props) => { | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
onFinish={async (values) => { | |||
@@ -640,6 +685,33 @@ const GoodsConfig = (props) => { | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Drawer width={600} title="商品添加到菜谱" placement="right" onClose={() => setShowMenuDrawer(false)} visible={showMenuDrawer}> | |||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px' }}> | |||
<div style={{ marginRight: '10px' }}> | |||
当前菜谱: | |||
</div> | |||
<Select | |||
style={{ | |||
width: '300px', | |||
marginRight: '10px' | |||
}} | |||
onChange={(item) => { | |||
setCurrentFoodMenu(item); | |||
}} | |||
placeholder="请选择菜谱" | |||
value={currentFoodMenu} | |||
> | |||
{ | |||
props.foodMenuConfig.map(item => { | |||
return <Option key={item.id} value={item.id}>{item.name}</Option> | |||
}) | |||
} | |||
</Select> | |||
<Button onClick={addGoodsToFoodMenu}>确定添加</Button> | |||
</div> | |||
<Table rowKey="id" columns={menuFoodsColumns} dataSource={menuFoodList} /> | |||
</Drawer> | |||
</> | |||
} | |||
@@ -1,10 +1,12 @@ | |||
import React, { useState, useEffect, useRef } from 'react'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import { Form, Input, Select, InputNumber, TreeSelect, message, Button, Modal, Radio, Upload, Switch, Row, Col } from 'antd'; | |||
import { Form, Input, Select, Drawer, message, Button, Modal, Row, Col, Table } from 'antd'; | |||
import ProForm, { ProFormSelect, ProFormText, ProFormDigit } from '@ant-design/pro-form'; | |||
import quickAPI from "../../service"; | |||
import indexStyles from "../../index.less"; | |||
import StepsButton from "../StepsButton"; | |||
import { PlusOutlined } from '@ant-design/icons'; | |||
const { Option, OptGroup } = Select; | |||
const fieldLabels = { | |||
@@ -25,49 +27,35 @@ const MaterialConfig = (props) => { | |||
const [materialForm] = Form.useForm(); | |||
const [currentPage, setCurrentPage] = useState(0); | |||
const [pageSize, setPageSize] = useState(5); | |||
const [selectedRowsState, setSelectedRows] = useState(props.materialConfig.id ? [props.materialConfig] : []); | |||
const [selectedRowKeys, setSelectRowKeys] = useState(props.materialConfig.id ? [props.materialConfig.id] : []); | |||
const optionsWithDisabled = [ | |||
{ | |||
label: '新建物料', | |||
value: true, | |||
}, | |||
{ | |||
label: '选择物料', | |||
value: false, | |||
} | |||
]; | |||
const [currentPage, setCurrentPage] = useState(1); | |||
const [pageSize, setPageSize] = useState(10); | |||
const [isCreate, setIsCreate] = useState(props.materialConfig.id ? false : true); | |||
const [selectedRows, setSetSelectedRows] = useState([]); | |||
const [selectedRowKeys, setSelectRowKeys] = useState([]); | |||
const actionRef = useRef(); | |||
const onChangeState = ({ target: { value } }) => { | |||
setIsCreate(value); | |||
let emptyObj = { | |||
id: "", | |||
code: "", | |||
name: "", | |||
specs: "", | |||
aittribute: "", | |||
price: 0, | |||
netrecovery: 0, | |||
typeID: "", | |||
stockUint: "", | |||
outstockUint: "", | |||
proportion: 1, | |||
status: "" | |||
const onFinish = async (values) => { | |||
if (values.id) { | |||
quickAPI.UpdateMaterial(values).then((r) => { | |||
if (r.data) { | |||
message.success('修改成功'); | |||
setIsShowModal(false); | |||
actionRef.current.reload(); | |||
} else { | |||
message.error('修改失败请重试!'); | |||
} | |||
}); | |||
} else { | |||
quickAPI.AddMaterial(values).then((r) => { | |||
if (r.data) { | |||
message.success('添加成功'); | |||
setIsShowModal(false); | |||
actionRef.current.reload(); | |||
} else { | |||
message.error('添加失败请重试!'); | |||
} | |||
}); | |||
} | |||
props.onFinishForm('materialConfig', emptyObj); | |||
materialForm.setFieldsValue(emptyObj); | |||
setSelectRowKeys([]); | |||
setSelectedRows([]); | |||
} | |||
const onFinish = (values) => { | |||
props.onFinishForm('materialConfig', values, true); | |||
} | |||
const columns = [ | |||
@@ -114,6 +102,24 @@ const MaterialConfig = (props) => { | |||
}, | |||
}, | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a | |||
key="primary3" | |||
type="primary" | |||
onClick={() => { | |||
setIsShowModal(true); | |||
setCurrentOption(record); | |||
materialForm.setFieldsValue(record); | |||
}} | |||
> | |||
更新 | |||
</a> | |||
], | |||
}, | |||
]; | |||
const [materialTypeList, setMaterialTypeList] = useState([]); | |||
@@ -154,23 +160,107 @@ const MaterialConfig = (props) => { | |||
const [showMaterialTypeModal, setShowMaterialTypeModal] = useState(false); | |||
const [showMaterialUnitModal, setShowMaterialUnitModal] = useState(false); | |||
//当前操作的物料对象 | |||
const [currentOption, setCurrentOption] = useState({ id: '' }); | |||
//是否显示 新增/编辑 物料弹窗 | |||
const [isShowModal, setIsShowModal] = useState(false); | |||
//物料绑定配方弹窗 | |||
const [showMenuDrawer, setShowMenuDrawer] = useState(false); | |||
//当前选中的配方 | |||
const [currentSelectedBom, setCurrentSelectedBom] = useState(''); | |||
//配方下拉列表 | |||
const [bomDropDown, setBomDropDown] = useState([]); | |||
//某配方下面的物料列表 | |||
const [materialBelongToBom, setMaterialBelongToBom] = useState([]); | |||
const materialColumns = [ | |||
{ | |||
title: '物料名称', | |||
dataIndex: 'name', | |||
ellipsis: true, | |||
formItemProps: { | |||
rules: [ | |||
{ | |||
required: true, | |||
message: '名称为必填项', | |||
}, | |||
], | |||
}, | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a | |||
key="primary3" | |||
type="primary" | |||
onClick={() => { | |||
const findBom = bomDropDown.find(item => item.id === currentSelectedBom); | |||
if (findBom) { | |||
props.onMaterialRelationBom(findBom.foodMenuId, findBom.goodsId, findBom.id, record, false); | |||
} | |||
}} | |||
> | |||
移除物料 | |||
</a> | |||
], | |||
}, | |||
]; | |||
/** | |||
* 初始化配方列表 | |||
*/ | |||
const initBomList = () => { | |||
const bomList = []; | |||
props.foodMenuConfig?.forEach(foodMenuItem => { | |||
foodMenuItem.goodsConfig?.forEach(goodsItem => { | |||
goodsItem.bomConfig?.forEach(bomItem => { | |||
const findBom = bomList.find(item => item.id === bomItem.id); | |||
if (!findBom) { | |||
bomItem.goodsId = goodsItem.id; | |||
bomList.push(bomItem); | |||
} | |||
}); | |||
}) | |||
}); | |||
if (!currentSelectedBom) { | |||
setCurrentSelectedBom(bomList[0]?.id); | |||
} | |||
setBomDropDown(bomList); | |||
} | |||
const onMaterialRelationBom = () => { | |||
const findBom = bomDropDown.find(item => item.id === currentSelectedBom); | |||
if (findBom) { | |||
props.onMaterialRelationBom(findBom.foodMenuId, findBom.goodsId, findBom.id, selectedRows); | |||
} | |||
} | |||
const initBomMaterial = () => { | |||
const findMaterial = bomDropDown.find(item => item.id === currentSelectedBom); | |||
if (findMaterial && findMaterial.materialConfig) { | |||
setMaterialBelongToBom(findMaterial.materialConfig); | |||
} else { | |||
setMaterialBelongToBom([]); | |||
} | |||
} | |||
useEffect(() => { | |||
onFetchMaterialTypeList(); | |||
onFetchMaterialUnit(); | |||
}, []); | |||
return <> | |||
<div className={indexStyles.choose_change_state}> | |||
<Radio.Group | |||
options={optionsWithDisabled} | |||
onChange={onChangeState} | |||
value={isCreate} | |||
optionType="button" | |||
buttonStyle="solid" | |||
/> | |||
</div> | |||
useEffect(() => { | |||
initBomList(); | |||
}, [props.foodMenuConfig]); | |||
<div className={indexStyles.common_row}> | |||
useEffect(() => { | |||
initBomMaterial(); | |||
}, [bomDropDown, currentSelectedBom]); | |||
return <> | |||
<Modal width={800} title={currentOption.id ? '编辑物料' : '新增物料'} visible={isShowModal} footer={false} onCancel={() => setIsShowModal(false)}> | |||
<ProForm | |||
form={materialForm} | |||
labelCol={{ span: 6 }} | |||
@@ -179,12 +269,11 @@ const MaterialConfig = (props) => { | |||
initialValues={props.materialConfig} | |||
onFinish={onFinish} | |||
submitter={false} | |||
style={{ width: '800px', marginRight: '30px', flexShrink: 0 }} | |||
> | |||
<Row gutter={16}> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormText | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.code} | |||
name="code" | |||
rules={[ | |||
@@ -199,7 +288,6 @@ const MaterialConfig = (props) => { | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormText name="id" hidden={true} /> | |||
<ProFormText | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.name} | |||
name="name" | |||
rules={[ | |||
@@ -213,7 +301,6 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormText | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.specs} | |||
name="specs" | |||
rules={[ | |||
@@ -227,7 +314,6 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormSelect | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.aittribute} | |||
name="aittribute" | |||
rules={[ | |||
@@ -255,7 +341,6 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormDigit | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.price} | |||
name="price" | |||
placeholder="请输入成本价" | |||
@@ -264,7 +349,6 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormDigit | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.netrecovery} | |||
name="netrecovery" | |||
min={1} | |||
@@ -276,7 +360,6 @@ const MaterialConfig = (props) => { | |||
<div className={indexStyles.add_row_content}> | |||
<ProFormSelect | |||
style={{ width: '65%' }} | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.typeID} | |||
name="typeID" | |||
rules={[ | |||
@@ -288,14 +371,13 @@ const MaterialConfig = (props) => { | |||
options={materialTypeList} | |||
placeholder="请选择物料类别" | |||
/> | |||
<Button onClick={() => setShowMaterialTypeModal(true)} disabled={!isCreate || props.materialConfig.id} type="primary" className={indexStyles.add_row_btn}>添加类别</Button> | |||
<Button onClick={() => setShowMaterialTypeModal(true)} type="primary" className={indexStyles.add_row_btn}>添加类别</Button> | |||
</div> | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<div className={indexStyles.add_row_content}> | |||
<ProFormSelect | |||
style={{ width: '65%' }} | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.stockUint} | |||
name="stockUint" | |||
rules={[ | |||
@@ -307,7 +389,7 @@ const MaterialConfig = (props) => { | |||
options={materialUnitList} | |||
placeholder="请选择单位" | |||
/> | |||
<Button onClick={() => setShowMaterialUnitModal(true)} disabled={!isCreate || props.materialConfig.id} type="primary" className={indexStyles.add_row_btn}>添加单位</Button> | |||
<Button onClick={() => setShowMaterialUnitModal(true)} type="primary" className={indexStyles.add_row_btn}>添加单位</Button> | |||
</div> | |||
</Col> | |||
@@ -315,7 +397,6 @@ const MaterialConfig = (props) => { | |||
<div className={indexStyles.add_row_content}> | |||
<ProFormSelect | |||
style={{ width: '65%' }} | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.OutstockUint} | |||
name="outstockUint" | |||
options={materialUnitList} | |||
@@ -327,12 +408,11 @@ const MaterialConfig = (props) => { | |||
]} | |||
placeholder="请选择出库单位" | |||
/> | |||
<Button onClick={() => setShowMaterialUnitModal(true)} disabled={!isCreate || props.materialConfig.id} type="primary" className={indexStyles.add_row_btn}>添加单位</Button> | |||
<Button onClick={() => setShowMaterialUnitModal(true)} type="primary" className={indexStyles.add_row_btn}>添加单位</Button> | |||
</div> | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormDigit | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.proportion} | |||
name="proportion" | |||
rules={[ | |||
@@ -346,7 +426,6 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
<Col lg={12} md={12} sm={24}> | |||
<ProFormSelect | |||
disabled={!isCreate || props.materialConfig.id} | |||
label={fieldLabels.status} | |||
name="status" | |||
rules={[ | |||
@@ -370,166 +449,199 @@ const MaterialConfig = (props) => { | |||
</Col> | |||
</Row> | |||
<Form.Item> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev}></StepsButton> | |||
<Button type="primary" htmlType="submit"> | |||
确定 | |||
</Button> | |||
</Form.Item> | |||
</ProForm> | |||
</Modal> | |||
{ | |||
!isCreate && <ProTable | |||
headerTitle="物料列表" | |||
rowKey="id" | |||
search={{ | |||
labelWidth: 120, | |||
}} | |||
request={async (params) => { | |||
let UserData = []; | |||
let total = 0; | |||
await quickAPI.GetMaterialPage(params).then((r) => { | |||
UserData = r.data.data; | |||
total = r.data.total; | |||
}); | |||
return { | |||
data: UserData, | |||
success: true, | |||
total: total, | |||
}; | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
type: 'radio', | |||
onChange: (selectedRowKeys, selectedRows) => { | |||
setSelectRowKeys(selectedRowKeys); | |||
setSelectedRows(selectedRows); | |||
if (selectedRows.length > 0) { | |||
props.onFinishForm('materialConfig', selectedRows[0]); | |||
materialForm.setFieldsValue(selectedRows[0]); | |||
} else { | |||
let emptyObj = { | |||
id: "", | |||
code: "", | |||
name: "", | |||
specs: "", | |||
aittribute: "", | |||
price: 0, | |||
netrecovery: 0, | |||
typeID: "", | |||
stockUint: "", | |||
outstockUint: "", | |||
proportion: 1, | |||
status: "" | |||
} | |||
materialForm.setFieldsValue(emptyObj); | |||
props.onFinishForm('materialConfig', emptyObj); | |||
} | |||
}, | |||
selectedRowKeys: selectedRowKeys | |||
}} | |||
/> | |||
} | |||
<Modal | |||
title="添加物料单位" | |||
width={640} | |||
visible={showMaterialUnitModal} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
footer={null} | |||
onCancel={() => { | |||
setShowMaterialUnitModal(false) | |||
<ProTable | |||
actionRef={actionRef} | |||
headerTitle="物料列表" | |||
rowKey="id" | |||
search={{ | |||
labelWidth: 120, | |||
}} | |||
pagination={{ | |||
current: currentPage, | |||
pageSize: pageSize, | |||
onChange: (page, pageSize) => { | |||
setCurrentPage(page); | |||
setPageSize(pageSize); | |||
} | |||
}} | |||
request={async (params) => { | |||
let UserData = []; | |||
let total = 0; | |||
await quickAPI.GetMaterialPage(params).then((r) => { | |||
UserData = r.data.data; | |||
total = r.data.total; | |||
}); | |||
return { | |||
data: UserData, | |||
success: true, | |||
total: total, | |||
}; | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
type: 'checkbox', | |||
onChange: (selectedRowKeys, selectedRows) => { | |||
setSelectRowKeys(selectedRowKeys); | |||
setSetSelectedRows(selectedRows); | |||
}, | |||
selectedRowKeys: selectedRowKeys | |||
}} | |||
toolBarRender={() => [ | |||
<Button key="button" icon={<PlusOutlined />} type="primary" onClick={() => { | |||
materialForm.resetFields(); | |||
setCurrentOption({ id: '' }); | |||
setIsShowModal(true); | |||
}}> | |||
新建 | |||
</Button>, | |||
<Button key="button" type="primary" onClick={() => { | |||
setShowMenuDrawer(true); | |||
}}> | |||
关联配方 | |||
</Button>, | |||
]} | |||
/> | |||
<Modal | |||
title="添加物料单位" | |||
width={640} | |||
visible={showMaterialUnitModal} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
footer={null} | |||
onCancel={() => { | |||
setShowMaterialUnitModal(false) | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.AddMaterialUnit(values); | |||
if (response.data) { | |||
message.success('添加成功'); | |||
setShowMaterialUnitModal(false); | |||
onFetchMaterialUnit(); | |||
} else { | |||
message.error(response.errors || '物料单位添加失败'); | |||
} | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.AddMaterialUnit(values); | |||
if (response.data) { | |||
message.success('添加成功'); | |||
setShowMaterialUnitModal(false); | |||
onFetchMaterialUnit(); | |||
} else { | |||
message.error(response.errors || '物料单位添加失败'); | |||
} | |||
}} | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="物料单位名称" rules={[{ required: true, max: 64 }]}> | |||
<Input placeholder="物料单位名称" /> | |||
</Form.Item> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
rules={[{ required: true, message: '请选择状态' }]} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="物料单位名称" rules={[{ required: true, max: 64 }]}> | |||
<Input placeholder="物料单位名称" /> | |||
</Form.Item> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
rules={[{ required: true, message: '请选择状态' }]} | |||
> | |||
<Select placeholder="请选择状态"> | |||
<OptGroup> | |||
<Select.Option value="0">正常</Select.Option> | |||
<Select.Option value="1">停用</Select.Option> | |||
</OptGroup> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Modal | |||
title="添加物料分类" | |||
width={640} | |||
visible={showMaterialTypeModal} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
footer={null} | |||
onCancel={() => { | |||
setShowMaterialTypeModal(false); | |||
<Select placeholder="请选择状态"> | |||
<OptGroup> | |||
<Select.Option value="0">正常</Select.Option> | |||
<Select.Option value="1">停用</Select.Option> | |||
</OptGroup> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Modal | |||
title="添加物料分类" | |||
width={640} | |||
visible={showMaterialTypeModal} | |||
bodyStyle={{ padding: '32px 40px 48px' }} | |||
footer={null} | |||
onCancel={() => { | |||
setShowMaterialTypeModal(false); | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.AddMaterialType(values); | |||
if (response.data) { | |||
message.success('添加成功'); | |||
setShowMaterialTypeModal(false); | |||
onFetchMaterialTypeList(); | |||
} else { | |||
message.error(response.errors || '物料分类添加失败'); | |||
} | |||
}} | |||
destroyOnClose | |||
maskClosable={false} | |||
> | |||
<Form | |||
layout="vertical" | |||
preserve={false} | |||
onFinish={async (values) => { | |||
const response = await quickAPI.AddMaterialType(values); | |||
if (response.data) { | |||
message.success('添加成功'); | |||
setShowMaterialTypeModal(false); | |||
onFetchMaterialTypeList(); | |||
} else { | |||
message.error(response.errors || '物料分类添加失败'); | |||
} | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="物料分类名称" rules={[{ required: true, max: 64, whitespace: true }]}> | |||
<Input placeholder="请输入物物料分类称" /> | |||
</Form.Item> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
rules={[{ required: true, message: '请选择物料分类状态' }]} | |||
> | |||
<Select placeholder="请选择物料分类状态"> | |||
<OptGroup> | |||
<Select.Option value="0">正常</Select.Option> | |||
<Select.Option value="1">停用</Select.Option> | |||
</OptGroup> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
<Drawer width={600} title="物料关联配方" placement="right" onClose={() => setShowMenuDrawer(false)} visible={showMenuDrawer}> | |||
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px' }}> | |||
<div style={{ marginRight: '10px' }}> | |||
当前配方: | |||
</div> | |||
<Select | |||
style={{ | |||
width: '300px', | |||
marginRight: '10px' | |||
}} | |||
onChange={(item) => { | |||
console.log('setCurrentSelectedBom', item); | |||
setCurrentSelectedBom(item); | |||
}} | |||
placeholder="请选择配方" | |||
value={currentSelectedBom} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="物料分类名称" rules={[{ required: true, max: 64, whitespace: true }]}> | |||
<Input placeholder="请输入物物料分类称" /> | |||
</Form.Item> | |||
{ | |||
bomDropDown.map(item => { | |||
return <Option key={item.id} value={item.id}>{item.name}</Option> | |||
}) | |||
} | |||
</Select> | |||
<Button onClick={onMaterialRelationBom}>确定关联</Button> | |||
</div> | |||
<Table rowKey="id" columns={materialColumns} dataSource={materialBelongToBom} /> | |||
</Drawer> | |||
<Form.Item | |||
name="status" | |||
label="状态" | |||
rules={[{ required: true, message: '请选择物料分类状态' }]} | |||
> | |||
<Select placeholder="请选择物料分类状态"> | |||
<OptGroup> | |||
<Select.Option value="0">正常</Select.Option> | |||
<Select.Option value="1">停用</Select.Option> | |||
</OptGroup> | |||
</Select> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
</div> | |||
<StepsButton foodMenuConfig={props.foodMenuConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
</> | |||
} | |||
@@ -1,9 +1,81 @@ | |||
import { Button } from 'antd'; | |||
import styles from "./index.less"; | |||
import { notification } from 'antd'; | |||
const StepsButton = (props) => { | |||
const onClickNext = () => { | |||
switch (props.current) { | |||
case 0: | |||
if (props.storeConfig?.id) { | |||
props.next(); | |||
} else { | |||
notification.error({ | |||
message: '门店配置出错', | |||
description: '请选择门店!', | |||
placement: 'topRight' | |||
}); | |||
} | |||
break; | |||
case 1: | |||
if (props.deviceConfig?.id) { | |||
props.next(); | |||
} else { | |||
notification.error({ | |||
message: '设备配置出错', | |||
description: '请选择设备!', | |||
placement: 'topRight' | |||
}); | |||
} | |||
break; | |||
case 2: | |||
if (props.foodMenuConfig?.length > 0) { | |||
props.next(); | |||
} else { | |||
notification.error({ | |||
message: '菜谱配置出错', | |||
description: '请至少选择一个菜谱!', | |||
placement: 'topRight' | |||
}); | |||
} | |||
break; | |||
case 3: | |||
for(let i = 0; i < props.foodMenuConfig.length; i++) { | |||
const goodsList = props.foodMenuConfig[i]?.goodsConfig; | |||
if (!goodsList || goodsList?.length === 0) { | |||
notification.error({ | |||
message: '商品配置出错', | |||
description: `请为菜谱【${props.foodMenuConfig[i].name}】添加商品!`, | |||
placement: 'topRight' | |||
}); | |||
return; | |||
} | |||
} | |||
props.next(); | |||
break; | |||
case 4: | |||
for(let i = 0; i < props.foodMenuConfig.length; i++) { | |||
const goodsList = props.foodMenuConfig[i]?.goodsConfig; | |||
for(let j = 0; j < goodsList.length; j++) { | |||
const bomList = goodsList[j]?.bomConfig; | |||
if (!bomList || bomList?.length === 0) { | |||
console.log('bomList', bomList); | |||
notification.error({ | |||
message: '配方配置出错', | |||
description: `请为商品【${goodsList[j].name}】添加配方!`, | |||
placement: 'topRight' | |||
}); | |||
return; | |||
} | |||
} | |||
} | |||
props.next(); | |||
break; | |||
case 5: | |||
props.next(); | |||
break; | |||
} | |||
} | |||
const StepsButton = (props) => { | |||
return <div className={styles.steps_btns}> | |||
{props.current > 0 && ( | |||
<Button | |||
@@ -17,7 +89,7 @@ const StepsButton = (props) => { | |||
)} | |||
{props.current < props.steps.length - 1 && ( | |||
<Button type="primary" htmlType="submit" onClick={props.next}> | |||
<Button type="primary" htmlType="submit" onClick={onClickNext}> | |||
下一步:{props.steps[props.current + 1]} | |||
</Button> | |||
)} | |||
@@ -297,7 +297,7 @@ const StoreConfig = (props) => { | |||
</Button> | |||
]} | |||
/> | |||
<StepsButton current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
<StepsButton storeConfig={props.storeConfig} current={props.current} steps={props.steps} prev={props.prev} next={props.next}></StepsButton> | |||
</> | |||
} | |||
@@ -1,4 +1,4 @@ | |||
import { Steps, Card } from 'antd'; | |||
import { Steps, Card, message } from 'antd'; | |||
import React, { useState, useEffect } from 'react'; | |||
import styles from "./index.less"; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
@@ -19,43 +19,8 @@ const QuickStart = () => { | |||
storeConfig: {}, | |||
deviceConfig: {}, | |||
foodMenuConfig: [], | |||
goodsConfig: { | |||
id: "", | |||
name: "", | |||
goodsUintId: "", | |||
price: 0, | |||
vipPrice: 0, | |||
parentTypeID: "", | |||
goodsTypeId: "", | |||
goodsAttribute: 0, | |||
status: 0, | |||
imgUrl: "", | |||
isWeigh: "" | |||
}, | |||
bomConfig: { | |||
id: "", | |||
code: "", | |||
name: "", | |||
bomTypeList: [], | |||
sort: 0 | |||
}, | |||
materialConfig: { | |||
id: "", | |||
code: "", | |||
name: "", | |||
specs: "", | |||
aittribute: "", | |||
price: 0, | |||
netrecovery: 0, | |||
typeID: "", | |||
stockUint: "", | |||
outstockUint: "", | |||
proportion: 1, | |||
status: "" | |||
} | |||
}); | |||
//每个页面点击下一步时触发 | |||
const onSelectedChange = (configType, payload) => { | |||
const tempQuick = JSON.parse(JSON.stringify(quickStartObj)); | |||
switch (configType) { | |||
@@ -66,13 +31,69 @@ const QuickStart = () => { | |||
tempQuick.deviceConfig = payload; | |||
break; | |||
case 'foodMenuConfig': | |||
console.log('payload>>>>', payload); | |||
tempQuick.foodMenuConfig = payload; | |||
break; | |||
} | |||
setQuickStartObj(tempQuick); | |||
} | |||
//将商品添加到菜谱 | |||
const onAddGoodsToFoodMenu = (foodMenuId, goods, isAdd = true) => { | |||
const tempQuick = JSON.parse(JSON.stringify(quickStartObj)); | |||
const findFoodMenu = tempQuick.foodMenuConfig.find(item => item.id === foodMenuId); | |||
if (isAdd && findFoodMenu) { | |||
findFoodMenu.goodsConfig = goods; | |||
} else { | |||
const findIndex = findFoodMenu.goodsConfig.findIndex(item => item.id === goods.id); | |||
if (findIndex > -1) { | |||
findFoodMenu.goodsConfig.splice(findIndex, 1); | |||
} | |||
} | |||
setQuickStartObj(tempQuick); | |||
} | |||
//配方关联商品 | |||
const onBomRelationGoods = (foodMenuId, goodsId, bom, isAdd = true) => { | |||
const tempQuick = JSON.parse(JSON.stringify(quickStartObj)); | |||
tempQuick.foodMenuConfig.forEach(findFoodMenu => { | |||
const goodsInfo = findFoodMenu.goodsConfig.find(item => item.id === goodsId); | |||
if (goodsInfo) { | |||
if (isAdd) { | |||
goodsInfo.bomConfig = bom; | |||
} else { | |||
const findIndex = goodsInfo.bomConfig.findIndex(item => item.id === bom.id); | |||
if (findIndex > -1) { | |||
goodsInfo.bomConfig.splice(findIndex, 1); | |||
} | |||
} | |||
setQuickStartObj(tempQuick); | |||
} | |||
}) | |||
} | |||
//物料关联配方 | |||
const onMaterialRelationBom = (foodMenuId, goodsId, bomId, material, isAdd = true) => { | |||
const tempQuick = JSON.parse(JSON.stringify(quickStartObj)); | |||
const findFoodMenu = tempQuick.foodMenuConfig.find(item => item.id === foodMenuId); | |||
if (findFoodMenu) { | |||
const findGoods = findFoodMenu.goodsConfig.find(item => item.id === goodsId); | |||
if (findGoods) { | |||
const findBom = findGoods.bomConfig.find(item => item.id === bomId); | |||
if (findBom) { | |||
if (isAdd) { | |||
findBom.materialConfig = material; | |||
} else { | |||
const findMaterialIndex = findBom.materialConfig.findIndex(item => item.id === material.id); | |||
if (findMaterialIndex > -1) { | |||
findBom.materialConfig.splice(findMaterialIndex, 1); | |||
} | |||
} | |||
setQuickStartObj(tempQuick); | |||
} | |||
} | |||
} | |||
} | |||
//下一步 | |||
const next = () => { | |||
setCurrent(current + 1); | |||
@@ -81,7 +102,7 @@ const QuickStart = () => { | |||
//上一步 | |||
const prev = () => { | |||
setCurrent(current - 1); | |||
}; | |||
}; | |||
const stepsText = ['门店配置', '设备配置', '菜谱配置', '商品配置', '配方配置', '物料配置', '确认配置']; | |||
@@ -89,10 +110,10 @@ const QuickStart = () => { | |||
<StoreConfig storeConfig={quickStartObj.storeConfig} current={current} steps={stepsText} next={next} onSelectedChange={onSelectedChange}></StoreConfig>, | |||
<DeviceConfig deviceConfig={quickStartObj.deviceConfig} current={current} steps={stepsText} prev={prev} next={next} onSelectedChange={onSelectedChange} ></DeviceConfig>, | |||
<FoodMenuConfig foodMenuConfig={quickStartObj.foodMenuConfig} current={current} steps={stepsText} prev={prev} next={next} onSelectedChange={onSelectedChange}></FoodMenuConfig>, | |||
<GoodsConfig goodsConfig={quickStartObj.goodsConfig} current={current} steps={stepsText} onSelectedChange={onSelectedChange} prev={prev}></GoodsConfig>, | |||
<BomConfig bomConfig={quickStartObj.bomConfig} current={current} steps={stepsText} onSelectedChange={onSelectedChange} prev={prev}></BomConfig>, | |||
<MaterialConfig materialConfig={quickStartObj.materialConfig} current={current} steps={stepsText} onSelectedChange={onSelectedChange} prev={prev}></MaterialConfig>, | |||
<ConfirmConfig quickStartObj={quickStartObj} current={current} steps={stepsText} onSelectedChange={onSelectedChange} prev={prev}></ConfirmConfig> | |||
<GoodsConfig foodMenuConfig={quickStartObj.foodMenuConfig} current={current} steps={stepsText} onAddGoodsToFoodMenu={onAddGoodsToFoodMenu} prev={prev} next={next} ></GoodsConfig>, | |||
<BomConfig foodMenuConfig={quickStartObj.foodMenuConfig} current={current} steps={stepsText} prev={prev} next={next} onBomRelationGoods={onBomRelationGoods}></BomConfig>, | |||
<MaterialConfig foodMenuConfig={quickStartObj.foodMenuConfig} current={current} steps={stepsText} onMaterialRelationBom={onMaterialRelationBom} prev={prev} next={next}></MaterialConfig>, | |||
<ConfirmConfig quickStartObj={quickStartObj} current={current} steps={stepsText} prev={prev}></ConfirmConfig> | |||
]; | |||
useEffect(() => { | |||
@@ -109,6 +130,7 @@ const QuickStart = () => { | |||
<div className={styles.steps_content}>{stepsContent[current]}</div> | |||
</Card> | |||
</PageContainer> | |||
} | |||
export default QuickStart; |
@@ -273,6 +273,30 @@ export default { | |||
}); | |||
}, | |||
/** | |||
* 添加配方 | |||
* @param {*} data | |||
* @returns | |||
*/ | |||
AddBom(data) { | |||
return request(`/kitchen/api/bom/add`, { | |||
method: 'Post', | |||
data: data, | |||
}); | |||
}, | |||
/** | |||
* 更新配方 | |||
* @param {*} data | |||
* @returns | |||
*/ | |||
UpdateBom(data) { | |||
return request(`/kitchen/api/bom/update`, { | |||
method: 'Post', | |||
data: data, | |||
}); | |||
}, | |||
/** | |||
* 获取菜谱分类 | |||
* @param {*} data | |||
@@ -293,6 +317,26 @@ export default { | |||
}); | |||
}, | |||
/**添加物料 */ | |||
AddMaterial(params) { | |||
return request('/kitchen/api/product/', { | |||
method: 'POST', | |||
data: { | |||
...params, | |||
}, | |||
}); | |||
}, | |||
/**修改物料 */ | |||
UpdateMaterial(params) { | |||
return request('/kitchen/api/product/', { | |||
method: 'PUT', | |||
data: { | |||
...params, | |||
}, | |||
}); | |||
}, | |||
/**获取物料基础信息 */ | |||
GetMaterialPage(params) { | |||
return request('/kitchen/api/product/product-list', { | |||