Commit 95b4583c authored by 武广's avatar 武广

feat: 添加外卖搜索条件

parent 06a12267
......@@ -8,17 +8,20 @@ import { apiGoodsActionBatch } from '../../service';
const ActionBar = options => {
// 上下架
const changeStatus = async state => {
console.log('options.shopId :>> ', options.shopId);
Modal.confirm({
icon: <ExclamationCircleOutlined />,
content: `确认${+state === 6 ? '下架' : '上架'}商品?`,
onOk: async () => {
const res = await apiGoodsActionBatch({
ids: options.selectedRowKeys,
skuIds: options.selectedRowKeys,
type: 2,
productState: +state === 6 ? 7 : 6, // 6:上架,7:下架
shopId: options.shopId,
productStatus: +state === 6 ? 0 : 1, // 6:上架,7:下架
});
if (res.businessCode === '0000' && res.code === '0000') {
options.handleSearch();
message.success('处理成功!');
}
},
});
......
......@@ -21,6 +21,7 @@ const MinimumPurchase = options => {
title="修改最少购买数量"
onOk={handleOk}
maskClosable={false}
keyboard={false}
confirmLoading={options.loading}
destroyOnClose
onCancel={handleCancel}
......@@ -35,7 +36,10 @@ const MinimumPurchase = options => {
<Form.Item
label="最少购买/份"
name="minPurchaseNum"
rules={[{ required: true, message: '请输入最少购买数量!' }]}
rules={[
{ required: true, message: '请输入最少购买数量!' },
{ min: 1, message: '最小输入1' },
]}
>
<Input maxLength={6} type="number" />
</Form.Item>
......
......@@ -24,6 +24,7 @@ const SendModal = options => {
title="设置单点不送"
onOk={handleOk}
maskClosable={false}
keyboard={false}
confirmLoading={options.loading}
destroyOnClose
onCancel={handleCancel}
......
import React, { useState, useEffect } from 'react';
import { Modal, Form, Input, Checkbox, Radio, Switch } from 'antd';
import { Modal, Form, InputNumber, Checkbox, Switch } from 'antd';
import { deepClone } from '@/utils/utils';
import styles from '../../style.less';
import { apiProductStock } from '../../service';
const StockModal = options => {
const [stockType, setStockType] = useState(0);
const [maxStock, setMaxStock] = useState(0);
const [isChecked, setIsChecked] = useState(false);
const [form] = Form.useForm();
const onChangeType = v => {
......@@ -28,13 +30,28 @@ const StockModal = options => {
const values = await form.validateFields();
const params = deepClone(values);
params.autoStock = values.autoStock ? 1 : 0;
console.log('values :>> ', values);
options.confirm({
type: 7,
...values,
...params,
});
};
const getStockInfo = async () => {
const res = await apiProductStock({
skuId: options.skuIds[0],
shopId: options.shopId,
});
if (res && res.code === '0000' && res.businessCode === '0000') {
const info = res.data;
form.setFieldsValue({
autoStockStep: info.autoStockStep,
productStock: info.stock,
autoStock: info.autoStock === 1,
});
setIsChecked(info.autoStock === 1);
}
};
const initialValues = Object.assign(
{
productStock: '',
......@@ -52,12 +69,30 @@ const StockModal = options => {
}
}, [maxStock, stockType]);
useEffect(() => {
if (options.visible) {
setStockType(0);
setMaxStock(0);
setIsChecked(false);
form.resetFields();
if (options.skuIds && options.skuIds.length) {
getStockInfo();
}
}
}, [options.visible]);
const maxStockRule = [];
if (isChecked) {
maxStockRule.push({ required: true, message: '请输入最大库存!' });
}
return (
<Modal
visible={options.visible}
title="修改库存"
onOk={handleOk}
maskClosable={false}
keyboard={false}
confirmLoading={options.loading}
destroyOnClose
onCancel={handleCancel}
......@@ -78,7 +113,12 @@ const StockModal = options => {
wrapperCol={{ span: 8 }}
rules={[{ required: true, message: '请输入剩余库存!' }]}
>
<Input type="number" disabled={stockType > 0} />
<InputNumber
min={0}
max={999999999}
className={styles['stock-box--inputnum']}
disabled={stockType > 0}
/>
</Form.Item>
<div className={styles['stock-box--btns']}>
<Checkbox checked={stockType === 1} onChange={() => onChangeType(1)}>
......@@ -88,15 +128,21 @@ const StockModal = options => {
最大
</Checkbox>
</div>
<Form.Item
label="最大库存"
name="autoStockStep"
rules={[{ required: true, message: '请输入最大库存!' }]}
>
<Input type="number" onChange={onChangeMaxStock} />
<Form.Item label="最大库存" name="autoStockStep" rules={maxStockRule}>
<InputNumber
min={0}
max={999999999}
className={styles['stock-box--inputnum']}
onChange={onChangeMaxStock}
/>
</Form.Item>
<Form.Item label="自动补足" name="autoStock">
<Switch checkedChildren="开启" unCheckedChildren="关闭" />
<Switch
checkedChildren="开启"
checked={isChecked}
unCheckedChildren="关闭"
onChange={setIsChecked}
/>
</Form.Item>
</Form>
<div className={styles['stock-box--red']}>修改成功后,原库存将被替换,请谨慎操作</div>
......
......@@ -25,6 +25,7 @@ const SwitchGroupModal = options => {
title="更改分组"
onOk={handleOk}
maskClosable={false}
keyboard={false}
confirmLoading={options.loading}
destroyOnClose
onCancel={handleCancel}
......
......@@ -8,7 +8,7 @@ import styles from '../../style.less';
const WeekTime = options => {
const [form] = Form.useForm();
const [type, setType] = useState(1);
const [type, setType] = useState(0);
const formItemLayout = {
labelCol: {
......@@ -37,16 +37,13 @@ const WeekTime = options => {
options.cancel(false);
};
const handleOk = async () => {
const values = await form.validateFields();
const params = deepClone(values);
const params = await form.validateFields();
// const params = values;
if (params.saleTimes && params.saleTimes.length) {
params.saleTimes = values.saleTimes.map(item => {
if (item && item.length > 1) {
item[0] = moment(item[0]).format('HH:mm');
item[1] = moment(item[1]).format('HH:mm');
}
return item;
});
params.saleTimes = params.saleTimes.map(item => ({
startTime: moment(item[0]).format('HH:mm'),
endTime: moment(item[1]).format('HH:mm'),
}));
}
options.confirm({
......@@ -57,7 +54,7 @@ const WeekTime = options => {
const initialValues = Object.assign(
{
saleTimeType: 1,
saleTimeType: 0,
saleDates: [],
saleTimes: [[]],
},
......@@ -69,8 +66,9 @@ const WeekTime = options => {
visible={options.visible}
title="售卖时间"
onOk={handleOk}
maskClosable={false}
confirmLoading={options.loading}
maskClosable={false}
keyboard={false}
destroyOnClose
onCancel={handleCancel}
>
......@@ -95,7 +93,7 @@ const WeekTime = options => {
buttonStyle="solid"
/>
</Form.Item>
{type === 2 ? (
{type === 1 ? (
<>
<Form.Item
label="售卖日期"
......
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { Spin, Table, Modal, message, notification } from 'antd';
import { unstable_batchedUpdates } from 'react-dom';
import { MenuOutlined, HolderOutlined, FormOutlined, CloseCircleOutlined } from '@ant-design/icons';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';
......@@ -35,12 +36,15 @@ const Takeaway = options => {
const getDataList = async () => {
setLoading(true);
const params = {
const params = Object.assign({}, options.searchValue, {
pageNo: 1,
productType: 5,
pageSize: 100000,
storageRackId: groupId,
};
});
const productCategoryId = options.searchValue?.productCategoryId || [];
params.productCategoryId =
(productCategoryId.length && productCategoryId[productCategoryId.length - 1]) || '';
const res = await apiTakeawayGoods(params);
setLoading(false);
if (res && res.data) {
......@@ -93,15 +97,19 @@ const Takeaway = options => {
shopId,
};
setActionLoading(true);
const params2 = {
...json,
...params,
};
console.log('params2 :>> ', params2);
const res = await apiGoodsActionBatch(Object.assign({}, json, params));
unstable_batchedUpdates(() => {
setActionLoading(false);
setVisibleWeekTime(false);
setVisibleStock(false);
setVisibleSwitchGroup(false);
setVisibleBuy(false);
setVisibleSend(false);
});
getDataList();
if (res.businessCode === '0000' && res.code === '0000') {
message.success('处理成功!');
}
};
// 显示弹窗
......@@ -133,18 +141,22 @@ const Takeaway = options => {
});
};
// 置顶
const toTop = row => {};
const toTop = oldIndex => {
onSortEnd({ oldIndex, newIndex: 0 });
};
useEffect(() => {
if (groupId) {
getDataList();
}
}, [groupId]);
}, [groupId, options.refresh]);
const actions = {
onShowStockModal,
toTop,
onEdit,
getDataList,
shopId,
};
return (
......@@ -153,6 +165,7 @@ const Takeaway = options => {
<GoodsGroup shopId={shopId} changeShop={setShopId} changeGroup={setGroupId} />
<ActionBar
selectedRowKeys={selectedRowKeys}
shopId={shopId}
handleSearch={getDataList}
openModal={openModal}
newGoods={onNew}
......@@ -182,6 +195,8 @@ const Takeaway = options => {
<StockModal
visible={visibleStock}
loading={actionLoading}
skuIds={selectedRowKeys}
shopId={shopId}
confirm={handleBatchAction}
cancel={setVisibleStock}
/>
......
......@@ -40,6 +40,7 @@ class goodsManage extends Component {
pageNo: 1,
loading: false,
treeData: [],
categoryTree: [],
virtualTreeData: [],
pageSize: 20,
priceInfo: {},
......@@ -63,6 +64,8 @@ class goodsManage extends Component {
isEditDraft: false, // 是否编辑草稿
productType: 1, // 商品类型
takeAway: {}, // 弹窗外卖商品参数
searchValue: {}, // 搜索条件
refresh: '', // 外卖刷新
};
currentLog = null;
......@@ -76,12 +79,15 @@ class goodsManage extends Component {
componentDidMount() {
this.props.goodsManage.tableData = {};
this.categoryList();
this.categoryListByType(this.state.productType);
this.getVirtualCategory();
this.specList();
this.setState({ productType: 5 });
}
handleSearch = page => {
const searchValue = this.searchForm.getFieldsValue();
this.setState({ searchValue });
if (this.state.productType !== 5) {
this.onSelectChange([]);
const currentPage = this.state.pageNo;
this.setState(
......@@ -97,7 +103,7 @@ class goodsManage extends Component {
payload: {
pageNo,
pageSize,
...this.searchForm.getFieldsValue(),
...searchValue,
},
}).finally(() => {
this.setState({
......@@ -106,6 +112,12 @@ class goodsManage extends Component {
});
},
);
} else {
this.setState({
refresh: new Date().getTime(),
searchValue,
});
}
};
onPageChange = page => {
......@@ -270,10 +282,9 @@ class goodsManage extends Component {
}
};
categoryList = async type => {
const api = type ? apiCategoryListType : categoryList;
categoryList = async () => {
try {
const { data: treeData } = await api(type);
const { data: treeData } = await categoryList({});
if (!treeData) return;
this.setState({ treeData });
} catch (e) {
......@@ -281,11 +292,21 @@ class goodsManage extends Component {
}
};
categoryListByType = async type => {
try {
const { data: categoryTree } = await apiCategoryListType(type);
if (!categoryTree) return;
this.setState({ categoryTree });
} catch (e) {
console.log(e);
}
};
changeProductType = e => {
this.setState({
productType: e || 1,
});
this.categoryList(e);
this.categoryListByType(e);
};
getVirtualCategory = async () => {
......@@ -421,7 +442,7 @@ class goodsManage extends Component {
onRef={ref => {
this.searchForm = ref;
}}
treeData={this.state.treeData}
treeData={this.state.categoryTree}
shopList={this.shopList}
checkStock={this.checkEnableUpdateStock}
selectNum={selectedRowKeys.length}
......@@ -430,7 +451,11 @@ class goodsManage extends Component {
/>
</Card>
{this.state.productType === 5 ? (
<Takeaway handleEdit={this.handleTakeawayEdit} />
<Takeaway
handleEdit={this.handleTakeawayEdit}
searchValue={this.state.searchValue}
refresh={this.state.refresh}
/>
) : (
<>
<Spin spinning={this.state.loading}>
......
......@@ -363,3 +363,10 @@ export async function apiStorageList(params) {
headers,
});
}
// 获取库存信息
export async function apiProductStock(data) {
return request.get('/api/merchants/products/sku/getStockInfo', {
prefix: goodsApi,
params: data,
});
}
import React from 'react';
import { Button, Badge, Switch, Modal } from 'antd';
import { Button, Badge, Switch, Modal, message } from 'antd';
import { SortableHandle } from 'react-sortable-hoc';
import { ExclamationCircleOutlined, MenuOutlined } from '@ant-design/icons';
import styles from './style.less';
import { resetTime } from '../../utils/utils';
import { apiChangeStateGoods } from './service';
import { apiChangeStateGoods, apiGoodsActionBatch } from './service';
const { confirm } = Modal;
......@@ -252,22 +252,19 @@ export function takeawayColumn(actions) {
icon: <ExclamationCircleOutlined />,
content: `确认${+state === 6 ? '下架' : '上架'}商品?`,
onOk: async () => {
const res = await apiChangeStateGoods({
skuIds: skuId,
productStatus: +state === 6 ? 7 : 6, // 6:上架,7:下架
const res = await apiGoodsActionBatch({
skuIds: [skuId],
shopId: actions.shopId,
productStatus: +state === 6 ? 0 : 1, // 6:上架,7:下架
type: 2,
});
if (res.businessCode === '0000' && res.code === '0000') {
this.handleSearch();
actions.getDataList();
message.success('处理成功!');
}
},
});
};
const onShowAudit = row => {
this.setState({
auditRow: row,
visibleAuditModal: true,
});
};
const DragHandle = SortableHandle(() => (
<MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
));
......@@ -295,15 +292,9 @@ export function takeawayColumn(actions) {
},
{
title: '售卖价格(元)',
dataIndex: 'marketPrice',
dataIndex: 'salePrice',
width: 150,
align: 'center',
render: (_, row) => (
<div className={styles.price}>
<div>供货价:{(row.supplyPrice || 0).toFixed(2)}</div>
<div>市场价:{(row.marketPrice || 0).toFixed(2)}</div>
</div>
),
},
{
title: '库存',
......@@ -351,7 +342,7 @@ export function takeawayColumn(actions) {
修改库存
</Button>
{index > 0 && (
<Button key="top" className={styles.button} onClick={() => actions.toTop(row)}>
<Button key="top" className={styles.button} onClick={() => actions.toTop(index)}>
置顶
</Button>
)}
......
......@@ -279,4 +279,7 @@
&--red {
color: #ff1616;
}
&--inputnum {
width: 100%;
}
}
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