@@ -1,5 +1,5 @@ | |||||
import { PlusOutlined } from '@ant-design/icons'; | |||||
import { Button, message, Input, Drawer, Popconfirm } from 'antd'; | |||||
import { PlusOutlined, DownloadOutlined } from '@ant-design/icons'; | |||||
import { Button, message, Input, Drawer, Popconfirm, Modal, Select } from 'antd'; | |||||
import React, { useState, useRef, useEffect } from 'react'; | import React, { useState, useRef, useEffect } from 'react'; | ||||
import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; | import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; | ||||
import ProTable from '@ant-design/pro-table'; | import ProTable from '@ant-design/pro-table'; | ||||
@@ -14,7 +14,10 @@ import { | |||||
goodsType, | goodsType, | ||||
getBomInfo, | getBomInfo, | ||||
AddBomApi, | AddBomApi, | ||||
getbompage | |||||
getbompage, | |||||
getDevice, | |||||
getGoodsWithDeviceId, | |||||
goodsSimpleExport | |||||
} from './service'; | } from './service'; | ||||
/** | /** | ||||
@@ -122,6 +125,14 @@ const GoodsManage = () => { | |||||
const [getGoodsBoms, setGoodsBoms] = useState(); | const [getGoodsBoms, setGoodsBoms] = useState(); | ||||
/** 商品配方调整新建/更新窗口的弹窗 */ | /** 商品配方调整新建/更新窗口的弹窗 */ | ||||
const [setGoodsBomModalVisible, handleGoodsBomModalVisible] = useState(); | const [setGoodsBomModalVisible, handleGoodsBomModalVisible] = useState(); | ||||
const [deviceData, setDeviceData] = useState([]); | |||||
const [deviceGoodData, setDeviceGoodData] = useState([]); | |||||
const [deviceId, setDeviceId] = useState(''); | |||||
const [deviceName, setDeviceName] = useState(''); | |||||
const [goodsId, setGoodsId] = useState([]); | |||||
const [isDataModalOpen, setIsDataModalOpen] = useState(false); | |||||
const [ids, setIds] =useState(''); | |||||
/** 国际化配置 */ | /** 国际化配置 */ | ||||
useEffect(() => { | useEffect(() => { | ||||
@@ -145,7 +156,41 @@ const GoodsManage = () => { | |||||
}); | }); | ||||
} | } | ||||
initGoodsType(); | initGoodsType(); | ||||
initGetDevice(); | |||||
}, []); | }, []); | ||||
const initGetDevice = () =>{ | |||||
getDevice().then((r) => { | |||||
var arr = r.data; | |||||
if (r.succeeded) { | |||||
var list = []; | |||||
arr.forEach((item) => { | |||||
list.push({ | |||||
value: item.id, | |||||
label: item.deviceName | |||||
}); | |||||
}); | |||||
setDeviceData(list); | |||||
} | |||||
}); | |||||
} | |||||
const initGetdevicegoodsList = (deviceId) =>{ | |||||
getGoodsWithDeviceId(deviceId).then((r) => { | |||||
var arr = r.data; | |||||
if (r.succeeded) { | |||||
var list = []; | |||||
var idList = []; | |||||
arr.forEach((item) => { | |||||
list.push({ | |||||
value: item.id, | |||||
label: item.name | |||||
}); | |||||
idList.push(item.id); | |||||
}); | |||||
setIds(idList); | |||||
setDeviceGoodData(list); | |||||
} | |||||
}); | |||||
} | |||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
title: '主键', | title: '主键', | ||||
@@ -342,6 +387,49 @@ const GoodsManage = () => { | |||||
], | ], | ||||
}, | }, | ||||
]; | ]; | ||||
const handleGoodChange = (value, option) => { | |||||
setGoodsId(value); | |||||
} | |||||
const handleDataDeviceChange = (value, option) => { | |||||
setDeviceId(option?.value); | |||||
setDeviceName(option?.label); | |||||
initGetdevicegoodsList(option?.value); | |||||
} | |||||
const handleDataDownload = async()=>{ | |||||
if(deviceName == '') | |||||
{ | |||||
message.error('请选择一个设备!'); | |||||
return; | |||||
} | |||||
const base64String = await goodsSimpleExport({ goodsId: goodsId, deviceId: deviceId, ids: ids }); | |||||
// 解码 Base64 数据 | |||||
const binaryString = atob(base64String); | |||||
// 转换为 Uint8Array | |||||
const bytes = new Uint8Array(binaryString.length); | |||||
for (let i = 0; i < binaryString.length; i++) { | |||||
bytes[i] = binaryString.charCodeAt(i); | |||||
} | |||||
// 创建 Blob 对象 | |||||
const blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); | |||||
// 创建一个临时的 URL,指向 Blob 对象 | |||||
const url = window.URL.createObjectURL(blob); | |||||
// 创建一个 <a> 元素 | |||||
const link = document.createElement('a'); | |||||
const fileName = "商品.xlsx"; | |||||
link.href = url; | |||||
link.setAttribute('download', fileName); | |||||
// 将 <a> 元素添加到页面中 | |||||
document.body.appendChild(link); | |||||
// 模拟用户点击下载链接,触发文件下载 | |||||
link.click(); | |||||
// 下载完成后,移除 <a> 元素 | |||||
document.body.removeChild(link); | |||||
setDeviceId(''); | |||||
setDeviceName(''); | |||||
setGoodsId([]); | |||||
setIds([]); | |||||
setIsDataModalOpen(false); | |||||
} | |||||
return ( | return ( | ||||
<PageContainer> | <PageContainer> | ||||
<ProTable | <ProTable | ||||
@@ -368,6 +456,14 @@ const GoodsManage = () => { | |||||
> | > | ||||
<PlusOutlined /> 新建 | <PlusOutlined /> 新建 | ||||
</Button>, | </Button>, | ||||
<Button | |||||
key="primary" | |||||
onClick={async () => { | |||||
setIsDataModalOpen(true); | |||||
}} | |||||
> | |||||
<DownloadOutlined /> 下载商品工艺 | |||||
</Button> | |||||
]} | ]} | ||||
request={async (params) => { | request={async (params) => { | ||||
var goodsData = []; | var goodsData = []; | ||||
@@ -451,7 +547,67 @@ const GoodsManage = () => { | |||||
createModalVisible={createModalVisible} | createModalVisible={createModalVisible} | ||||
values={currentRow || {}} | values={currentRow || {}} | ||||
/> | /> | ||||
<Modal | |||||
title="下载商品工艺" | |||||
open={isDataModalOpen} | |||||
footer={false} | |||||
width={450} | |||||
maskClosable={false} | |||||
destroyOnClose={true} | |||||
onCancel={() => { | |||||
setDeviceGoodData([]) | |||||
setDeviceId('') | |||||
setDeviceName('') | |||||
setGoodsId([]) | |||||
setIds('') | |||||
setIsDataModalOpen(false) | |||||
}}> | |||||
<div style={{ marginBottom: 10 }}> | |||||
<span style={{ marginRight: 10 }}><span style={{color:'red',marginRight: 3}}>*</span>选择设备:</span> | |||||
<Select | |||||
showSearch | |||||
allowClear | |||||
style={{ | |||||
width: 300, | |||||
marginRight: 10 | |||||
}} | |||||
placeholder="请选择设备" | |||||
optionFilterProp="children" | |||||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||||
filterSort={(optionA, optionB) => | |||||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||||
} | |||||
onChange={async (value, option) => { handleDataDeviceChange(value, option) }} | |||||
options={deviceData} | |||||
required | |||||
/> | |||||
</div> | |||||
<div style={{ marginBottom: 10 }}> | |||||
<span style={{ marginLeft: 9, marginRight: 10 }}>选择商品:</span> | |||||
<Select | |||||
mode='multiple' | |||||
showSearch | |||||
allowClear | |||||
style={{ | |||||
width: 300, | |||||
marginRight: 10 | |||||
}} | |||||
placeholder="选择商品下载工艺" | |||||
optionFilterProp="children" | |||||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||||
filterSort={(optionA, optionB) => | |||||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||||
} | |||||
onChange={async (value, option) => { handleGoodChange(value, option) }} | |||||
options={deviceGoodData} | |||||
/> | |||||
</div> | |||||
<Button | |||||
icon={<DownloadOutlined />} | |||||
style={{ marginLeft: '22.2%' }} | |||||
onClick = {handleDataDownload} | |||||
>下载</Button> | |||||
</Modal> | |||||
<Drawer | <Drawer | ||||
width={600} | width={600} | ||||
visible={showDetail} | visible={showDetail} | ||||
@@ -87,3 +87,21 @@ export async function getgoodsTaste(data) { | |||||
return request(`/kitchen/api/goodstaste/getlist`); | return request(`/kitchen/api/goodstaste/getlist`); | ||||
} | } | ||||
export async function getDevice() { | |||||
return request(`/kitchen/api/goodstechnology/getDevice`, { | |||||
method: 'Get', | |||||
}); | |||||
} | |||||
export async function getGoodsWithDeviceId(deviceId) { | |||||
return request(`/kitchen/api/goodes/GetGoodsWithDeviceId?deviceId=` + deviceId, { | |||||
method: 'Get' | |||||
}); | |||||
} | |||||
export async function goodsSimpleExport(data) { | |||||
return request(`/kitchen/api/goodes/GoodsSimpleExport`, { | |||||
method: 'POST', | |||||
data: data | |||||
}); | |||||
} |
@@ -0,0 +1,116 @@ | |||||
import React, { useState, useEffect } from 'react'; | |||||
import { Modal, Form, Input, DatePicker, Checkbox, Button, Select, InputNumber, message } from 'antd'; | |||||
import moment from 'moment'; | |||||
import { getGoods } from '../services'; | |||||
const RuleForm = (props) => { | |||||
const { RangePicker } = DatePicker; | |||||
const [checked, setChecked] = useState(false); | |||||
const [dateDisable, setDateDisable] = useState(false); | |||||
const [itemDisable, setItemDisable] = useState(false); | |||||
useEffect(() => { | |||||
const ruleAts = []; | |||||
if (props.values) { | |||||
if (props.values.startAt) { | |||||
props.values.startAt = moment(props.values.startAt); | |||||
} | |||||
ruleAts.push(props.values.startAt); | |||||
if (props.values.endAt) { | |||||
props.values.endAt = moment(props.values.endAt); | |||||
} | |||||
ruleAts.push(props.values.endAt); | |||||
props.values.ruleAt = ruleAts; | |||||
} | |||||
if (props.values.ruleType == 2) { | |||||
setItemDisable(true); | |||||
setDateDisable(true); | |||||
if (props.values.isLong == 1) { | |||||
setChecked(true); | |||||
} else { | |||||
setChecked(false); | |||||
} | |||||
} else { | |||||
setItemDisable(false); | |||||
setDateDisable(false); | |||||
if (props.values.isLong == 1) { | |||||
setChecked(true); | |||||
setDateDisable(true); | |||||
} else { | |||||
setChecked(false); | |||||
setDateDisable(false); | |||||
} | |||||
} | |||||
}, [props.values]); | |||||
const CheckboxChange = (e) => { | |||||
if (e.target.checked) { | |||||
setChecked(true); | |||||
setDateDisable(true); | |||||
} | |||||
else { | |||||
setChecked(false); | |||||
setDateDisable(false); | |||||
} | |||||
} | |||||
const ruleTypeChange = (value) => { | |||||
if (value == 1) { | |||||
setItemDisable(false); | |||||
if (checked) { | |||||
setDateDisable(true); | |||||
} else { | |||||
setDateDisable(false); | |||||
} | |||||
} else { | |||||
setItemDisable(true); | |||||
setDateDisable(true); | |||||
} | |||||
} | |||||
return ( | |||||
<Modal | |||||
title={'编辑销售规则'} | |||||
width={640} | |||||
visible={props.ruleModelVisible} | |||||
bodyStyle={{ padding: '32px 40px 48px' }} | |||||
footer={null} | |||||
onCancel={() => { | |||||
props.onCancel(); | |||||
}} | |||||
destroyOnClose | |||||
> | |||||
<Form | |||||
layout="Horizontal" | |||||
initialValues={props.values} | |||||
onFinish={props.onFinish} | |||||
> | |||||
<Form.Item name="id" hidden={true}> | |||||
<Input /> | |||||
</Form.Item> | |||||
<Form.Item name="ruleType" label="规则类型" rules={[{ required: true }]}> | |||||
<Select style={{ width: '100%' }} onChange={ruleTypeChange}> | |||||
<Select.Option value={1}>时间范围</Select.Option> | |||||
<Select.Option value={2}>每日</Select.Option> | |||||
</Select> | |||||
</Form.Item> | |||||
<Form.Item name="ruleAt" label="销售时间" style={{ marginLeft: '10px' }}> | |||||
<RangePicker showTime format="YYYY-MM-DD HH:mm:ss" style={{ width: '100%' }} disabled={dateDisable} /> | |||||
</Form.Item> | |||||
<Form.Item name="isLong" valuePropName="checked" label="是否长期有效" style={{ marginLeft: '10px' }}> | |||||
<Checkbox style={{ marginLeft: '10px' }} onChange={CheckboxChange} disabled={itemDisable} checked={checked}></Checkbox> | |||||
</Form.Item> | |||||
<Form.Item name="saleCount" label="销售数量" rules={[{ required: true }]}> | |||||
<InputNumber style={{ width: '100%' }} min={0} /> | |||||
</Form.Item> | |||||
<Form.Item style={{ marginLeft: '10px' }}> | |||||
<Button type="primary" htmlType="submit"> | |||||
保存 | |||||
</Button> | |||||
</Form.Item> | |||||
</Form> | |||||
</Modal> | |||||
) | |||||
}; | |||||
export default RuleForm; |
@@ -1,14 +1,16 @@ | |||||
import { PlusOutlined } from '@ant-design/icons'; | import { PlusOutlined } from '@ant-design/icons'; | ||||
import { Tabs, Card, Pagination, Table, message, Button, Popconfirm, Modal } from 'antd'; | |||||
import { Tabs, Card, Pagination, Table, message, Button, Popconfirm, Modal, Form } from 'antd'; | |||||
const { TabPane } = Tabs; | const { TabPane } = Tabs; | ||||
import React, { useState, useRef, useEffect } from 'react'; | import React, { useState, useRef, useEffect } from 'react'; | ||||
import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; | import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; | ||||
import { GetStoreInfoPage, GetStoreGoods, AddStoreGood, UpdateStoreGoods, DelStoreGoods, UpdateStoreGoodsStatusAsync, stopgoods,StoreGoodsAllUpdate } from "./services" | |||||
import { GetStoreInfoPage, GetStoreGoods, AddStoreGood, UpdateStoreGoods, DelStoreGoods, UpdateStoreGoodsStatusAsync, stopgoods,StoreGoodsAllUpdate,UpdateStoreFoodSaleRule } from "./services" | |||||
import ProTable from '@ant-design/pro-table'; | import ProTable from '@ant-design/pro-table'; | ||||
import CreateForm from './components/CreateForm'; | import CreateForm from './components/CreateForm'; | ||||
import LogForm from './components/Logs'; | import LogForm from './components/Logs'; | ||||
import { UnorderedListOutlined } from '@ant-design/icons'; | import { UnorderedListOutlined } from '@ant-design/icons'; | ||||
import { history } from 'umi'; | import { history } from 'umi'; | ||||
import RuleForm from './components/Rule'; | |||||
import moment from 'moment'; | |||||
const key = 'message'; | const key = 'message'; | ||||
//修改 | //修改 | ||||
@@ -22,7 +24,7 @@ const handleUpdate = async (fields) => { | |||||
message.success('修改成功'); | message.success('修改成功'); | ||||
return true; | return true; | ||||
} else { | } else { | ||||
message.success('修改失败'); | |||||
message.error('修改失败'); | |||||
return false; | return false; | ||||
} | } | ||||
}); | }); | ||||
@@ -62,13 +64,14 @@ const storeGoodsInfo = (props) => { | |||||
const [total, SetTotal] = useState(0); | const [total, SetTotal] = useState(0); | ||||
const [loading, SetLoading] = useState(false); | const [loading, SetLoading] = useState(false); | ||||
const [storeId, SetstoreId] = useState(); | const [storeId, SetstoreId] = useState(); | ||||
const [ruleModelVisible, setRuleModelVisible] = useState(false); | |||||
const [ruleRow, setRuleRow] = useState(); | |||||
const [createModalVisible, handleModalVisible] = useState(false); | const [createModalVisible, handleModalVisible] = useState(false); | ||||
const [currentRow, setCurrentRow] = useState(); | const [currentRow, setCurrentRow] = useState(); | ||||
const [currentTabRow, setCurrentTabRow] = useState(); | const [currentTabRow, setCurrentTabRow] = useState(); | ||||
const actionRef = useRef(); | const actionRef = useRef(); | ||||
const [logVisible, SetLogVisible] = useState(false); | const [logVisible, SetLogVisible] = useState(false); | ||||
const [foodId, setFoodId] = useState(); | |||||
useEffect(() => { | useEffect(() => { | ||||
getStoreInfoPageInfo(1); | getStoreInfoPageInfo(1); | ||||
@@ -96,6 +99,26 @@ const storeGoodsInfo = (props) => { | |||||
}; | }; | ||||
const ruleUpdate = async (fields) => { | |||||
try { | |||||
message.loading('正在修改', key); | |||||
message.destroy(key); | |||||
await UpdateStoreFoodSaleRule(JSON.stringify(fields)).then((r) => { | |||||
message.destroy(key); | |||||
if (r.data) { | |||||
message.success('修改成功'); | |||||
return true; | |||||
} else { | |||||
message.error('修改失败'); | |||||
return false; | |||||
} | |||||
}); | |||||
} catch (error) { | |||||
message.error('修改失败请重试!'); | |||||
return false; | |||||
} | |||||
} | |||||
const getStoreInfoPageInfo = async (page) => { | const getStoreInfoPageInfo = async (page) => { | ||||
SetLoading(true); | SetLoading(true); | ||||
try { | try { | ||||
@@ -244,6 +267,16 @@ const storeGoodsInfo = (props) => { | |||||
> | > | ||||
加购商品 | 加购商品 | ||||
</a>, | </a>, | ||||
<a | |||||
key="config" | |||||
onClick={() => { | |||||
setRuleModelVisible(true); | |||||
setFoodId(record.foodId); | |||||
setRuleRow(record.storeFoodSaleRuleDto); | |||||
}} | |||||
> | |||||
销售规则 | |||||
</a> | |||||
], | ], | ||||
}, | }, | ||||
]; | ]; | ||||
@@ -368,6 +401,36 @@ const storeGoodsInfo = (props) => { | |||||
values={currentRow || {}} | values={currentRow || {}} | ||||
/> | /> | ||||
<RuleForm | |||||
onFinish={async (value) => { | |||||
value.storeId = storeId; | |||||
value.foodId = foodId; | |||||
if (value.ruleAt != null) { | |||||
value.startAt = moment(value.ruleAt[0]).format('YYYY-MM-DD HH:mm:ss'); | |||||
value.endAt = moment(value.ruleAt[1]).format('YYYY-MM-DD HH:mm:ss'); | |||||
} | |||||
else { | |||||
value.startAt = moment(new Date(Date.now())).format('YYYY-MM-DD HH:mm:ss'); | |||||
value.endAt = moment(new Date(Date.now())).format('YYYY-MM-DD HH:mm:ss'); | |||||
} | |||||
value.isLong = value.isLong ? '1' : '0'; | |||||
var success = ruleUpdate(value); | |||||
if (success) { | |||||
setFoodId(undefined); | |||||
setRuleModelVisible(false); | |||||
setRuleRow(undefined); | |||||
actionRef.current.reload(); | |||||
} | |||||
}} | |||||
onCancel={() => { | |||||
setFoodId(undefined); | |||||
setRuleModelVisible(false); | |||||
setRuleRow(undefined); | |||||
}} | |||||
ruleModelVisible={ruleModelVisible} | |||||
values={ruleRow || {}} | |||||
/> | |||||
<Modal | <Modal | ||||
destroyOnClose={true} | destroyOnClose={true} | ||||
width={800} | width={800} | ||||
@@ -91,3 +91,10 @@ export function GetRequestLogPageAsync(data) { | |||||
data: data, | data: data, | ||||
}); | }); | ||||
} | } | ||||
export async function UpdateStoreFoodSaleRule(data) { | |||||
return request(`/kitchen/api/Store/UpdateStoreFoodSaleRule`, { | |||||
method: 'post', | |||||
data: data | |||||
}); | |||||
} |