Commit 373c4702 authored by 李腾's avatar 李腾

Merge branch 'master' of git.quantgroup.cn:ui/merchant-manage-ui into feature/serviceGoods20220804

parents 1a04ac87 501554e9
...@@ -3,14 +3,13 @@ const isPre = process.env.PRE_ENV === 'pre'; ...@@ -3,14 +3,13 @@ const isPre = process.env.PRE_ENV === 'pre';
const envAPi = { const envAPi = {
api: 'https://backstms-xyqb.liangkebang.net', api: 'https://backstms-xyqb.liangkebang.net',
kdspOpApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net',
kdspApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspApi: 'https://sc-op-api-xyqb.liangkebang.net',
goodsApi: 'https://sc-merchant-api-xyqb.liangkebang.net', goodsApi: 'https://sc-op-api-xyqb.liangkebang.net',
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net',
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net',
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net',
querysApi: 'https://sc-settlement-api-xyqb.liangkebang.net', querysApi: 'https://sc-settlement-api-xyqb.liangkebang.net',
// goodsApi: '//192.168.188.111:7000',
prologueDomain: 'https://mall-xyqb.liangkebang.net', prologueDomain: 'https://mall-xyqb.liangkebang.net',
// qiniuHost: 'https://appsync.lkbang.net',
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: 'https://opapi-xyqb.liangkebang.net', opapiHost: 'https://opapi-xyqb.liangkebang.net',
}; };
......
...@@ -11,6 +11,7 @@ import ProofsModal from '../components/proofsModal'; ...@@ -11,6 +11,7 @@ import ProofsModal from '../components/proofsModal';
import { getDetail } from '../../afterSale/appeal/services'; import { getDetail } from '../../afterSale/appeal/services';
import AppealDetail from '../../afterSale/components/detail'; import AppealDetail from '../../afterSale/components/detail';
import AfterLog from '../components/AfterLog'; import AfterLog from '../components/AfterLog';
import styles from '../styles.less';
const { Countdown } = Statistic; const { Countdown } = Statistic;
...@@ -25,8 +26,6 @@ export default () => { ...@@ -25,8 +26,6 @@ export default () => {
const [auditInfo, setAuditInfo] = useState({}); const [auditInfo, setAuditInfo] = useState({});
const [appealDetailModal, setAppealDetailModal] = useState(false); const [appealDetailModal, setAppealDetailModal] = useState(false);
const [selectedRow, setSelectedRow] = useState({}); const [selectedRow, setSelectedRow] = useState({});
const [timeString, setTimeString] = useState({});
const [time, setTime] = useState({});
const [afterVisible, setAfterVisible] = useState(false); const [afterVisible, setAfterVisible] = useState(false);
const [afterList, setAfterList] = useState([]); const [afterList, setAfterList] = useState([]);
const viewDetail = async ({ serviceNo }) => { const viewDetail = async ({ serviceNo }) => {
...@@ -73,7 +72,15 @@ export default () => { ...@@ -73,7 +72,15 @@ export default () => {
}; };
const openLogistics = r => { const openLogistics = r => {
confirm({ confirm({
content: '请在48小时内完成物流包裹拦截,确认是否需要进行物流拦截?', title: '温馨提示',
okText: '确认拦截',
cancelText: '取消拦截',
content: (
<div>
请48小时内自行联系物流公司进行物流拦截,系统监测拦截成功后
<span className={styles.redTipBold}>自动同意</span>退款
</div>
),
async onOk() { async onOk() {
const data = await logisticsIntercept({ serviceNo: r.serviceNo }); const data = await logisticsIntercept({ serviceNo: r.serviceNo });
if (data.businessCode === '0000') { if (data.businessCode === '0000') {
...@@ -88,39 +95,6 @@ export default () => { ...@@ -88,39 +95,6 @@ export default () => {
}, },
}); });
}; };
// const renderContent = (record, index, action) => {
// if (!time[record.serviceNo]) {
// const serviceTime = moment(record.approvalEndTime).valueOf();
// const nowTime = moment(record.nowTime).valueOf();
// let timeNumber = (serviceTime - nowTime) / 1000;
// time[record.serviceNo] = setInterval(() => {
// if (timeNumber > 0) {
// timeNumber -= 1;
// // eslint-disable-next-line radix
// const hours = parseInt(timeNumber / 3600)
// .toString()
// .padStart(2, '0');
// // eslint-disable-next-line radix
// const minutes = parseInt((timeNumber / 60) % 60)
// .toString()
// .padStart(2, '0');
// // eslint-disable-next-line radix
// const seconds = parseInt(timeNumber % 60)
// .toString()
// .padStart(2, '0');
// const str = `${hours}时${minutes}分${seconds}秒`;
// timeString[record.serviceNo] = str;
// const strings = _.cloneDeep(timeString);
// setTimeString(strings);
// } else {
// clearInterval(time[record.serviceNo]);
// timeString[record.serviceNo] = '0时0分0秒';
// const strings = _.cloneDeep(timeString);
// setTimeString(strings);
// }
// }, 1000);
// }
// };
const columns = [ const columns = [
{ {
title: '审核倒计时', title: '审核倒计时',
...@@ -128,12 +102,6 @@ export default () => { ...@@ -128,12 +102,6 @@ export default () => {
key: 'serviceTime', key: 'serviceTime',
hideInSearch: true, hideInSearch: true,
width: 150, width: 150,
// render: (val, record, index, action) => [
// <span style={{ color: 'red' }}>
// {renderContent(record, index, action)}
// {timeString[record.serviceNo]}
// </span>,
// ],
render: (val, record) => { render: (val, record) => {
const serviceTime = moment(record.approvalEndTime).valueOf(); const serviceTime = moment(record.approvalEndTime).valueOf();
return ( return (
......
...@@ -3,9 +3,11 @@ import { Form } from '@ant-design/compatible'; ...@@ -3,9 +3,11 @@ import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Modal, Input, Cascader, notification, InputNumber } from 'antd'; import { Modal, Input, Cascader, notification, InputNumber } from 'antd';
import { shopAudit } from '../services'; import { shopAudit } from '../services';
import styles from '../styles.less';
const FormItem = Form.Item; const FormItem = Form.Item;
const { TextArea } = Input; const { TextArea } = Input;
const { confirm } = Modal;
const AuditModal = props => { const AuditModal = props => {
const { const {
visible, visible,
...@@ -13,6 +15,7 @@ const AuditModal = props => { ...@@ -13,6 +15,7 @@ const AuditModal = props => {
form: { getFieldDecorator, getFieldValue, validateFields, resetFields }, form: { getFieldDecorator, getFieldValue, validateFields, resetFields },
formData = {}, formData = {},
} = props; } = props;
const handleCancel = isSuccess => { const handleCancel = isSuccess => {
resetFields(); resetFields();
onCancel(isSuccess); onCancel(isSuccess);
...@@ -57,9 +60,7 @@ const AuditModal = props => { ...@@ -57,9 +60,7 @@ const AuditModal = props => {
], ],
}, },
]; ];
const handleOk = () => { const submitCheckResult = async fieldsValue => {
validateFields(async (error, fieldsValue) => {
if (!error) {
const { auditResult } = fieldsValue; const { auditResult } = fieldsValue;
const data = await shopAudit({ const data = await shopAudit({
...fieldsValue, ...fieldsValue,
...@@ -71,6 +72,32 @@ const AuditModal = props => { ...@@ -71,6 +72,32 @@ const AuditModal = props => {
notification.success({ message: '审核成功' }); notification.success({ message: '审核成功' });
handleCancel(true); handleCancel(true);
} }
};
const handleOk = () => {
validateFields((error, fieldsValue) => {
if (!error) {
const { auditResult } = fieldsValue;
// 如果为仅退款 并且 审核同意 弹出二次确认提示
if (+formData.serviceType === 1 && auditResult?.[0] === 1) {
confirm({
title: '温馨提示',
content: (
<div>
当前类型为【<span className={styles.redTipBold}>仅退款</span>
】,请核查该订单物流状态,如有在途物流,务必自行拦截后点击确认;
</div>
),
okText: '确认退款',
onOk() {
submitCheckResult(fieldsValue);
},
onCancel() {
handleCancel(true);
},
});
} else {
submitCheckResult(fieldsValue);
}
} }
}); });
}; };
...@@ -89,9 +116,23 @@ const AuditModal = props => { ...@@ -89,9 +116,23 @@ const AuditModal = props => {
onOk={() => handleOk()} onOk={() => handleOk()}
onCancel={() => handleCancel()} onCancel={() => handleCancel()}
> >
{+formData.serviceType === 1 && (
<div className={styles.redTip}>
温馨提示:当前售后类型为用户未收到产品,申请
<span className={styles.redTipBold}>仅退款</span>
,请务必检查此单物流状态后审核。
</div>
)}
<Form {...layout} name="formData"> <Form {...layout} name="formData">
<FormItem label="审核结果"> <FormItem label="审核结果">
{getFieldDecorator('auditResult')( {getFieldDecorator('auditResult', {
rules: [
{
required: true,
message: '请选择审核结果!',
},
],
})(
<Cascader <Cascader
allowClear allowClear
showSearch showSearch
......
...@@ -6,6 +6,18 @@ export const appealType = { ...@@ -6,6 +6,18 @@ export const appealType = {
0: '未申诉', 0: '未申诉',
}; };
export const columnSticData = [ export const columnSticData = [
{
title: '售后类型',
dataIndex: 'serviceType',
hideInSearch: true,
width: 120,
render: serviceType => {
if (+serviceType === 1) {
return <span style={{ color: '#ff1616' }}>仅退款</span>;
}
return <span>退货退款</span>;
},
},
{ {
title: '订单ID', title: '订单ID',
dataIndex: 'orderNo', dataIndex: 'orderNo',
...@@ -97,16 +109,6 @@ export const columnSticData = [ ...@@ -97,16 +109,6 @@ export const columnSticData = [
valueType: 'date', valueType: 'date',
hideInTable: true, hideInTable: true,
}, },
{
title: '售后类型',
dataIndex: 'serviceType',
hideInSearch: true,
width: 120,
valueEnum: {
1: '仅退款',
2: '退货退款',
},
},
{ {
title: '售后原因', title: '售后原因',
dataIndex: 'serviceReason', dataIndex: 'serviceReason',
......
...@@ -21,3 +21,12 @@ ...@@ -21,3 +21,12 @@
display: inherit; display: inherit;
margin: 20px auto; margin: 20px auto;
} }
.redTip {
color: #ff4d4f;
font-size: 14px;
}
.redTipBold {
color: #ff1616;
font-weight: bold;
}
...@@ -5,15 +5,19 @@ import { ...@@ -5,15 +5,19 @@ import {
Select, Select,
notification, notification,
Upload, Upload,
Tag,
Cascader, Cascader,
InputNumber, InputNumber,
Popover, Popover,
Divider, Divider,
} from 'antd'; } from 'antd';
import React, { Component } from 'react'; import React, { Component, useState } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import { saveAs } from 'file-saver';
import { format } from 'date-fns';
import styles from '../style.less'; import styles from '../style.less';
import { stateList } from '../staticdata'; import { stateList } from '../staticdata';
import { apiGoodsInfosExport } from '../service';
const FormItem = Form.Item; const FormItem = Form.Item;
const { Option } = Select; const { Option } = Select;
...@@ -23,6 +27,10 @@ const { Option } = Select; ...@@ -23,6 +27,10 @@ const { Option } = Select;
class goodsManage extends Component { class goodsManage extends Component {
formRef = React.createRef(); formRef = React.createRef();
state = {
loading: false,
};
componentDidMount() { componentDidMount() {
this.props.onRef(this); this.props.onRef(this);
this.handleSearch(); this.handleSearch();
...@@ -59,6 +67,33 @@ class goodsManage extends Component { ...@@ -59,6 +67,33 @@ class goodsManage extends Component {
this.props.setArea(isAll, type); this.props.setArea(isAll, type);
}; };
// 验证是否可以修改库存
checkEnableUpdateStock = () => {
if (this.props.selectNum) {
this.props.checkStock();
} else {
notification.info({ message: '请选择' });
}
};
// 导出明细
onExportGoodsInfo = async () => {
this.setState({
loading: true,
});
const form = this.formRef?.current?.getFieldValue();
const res = await apiGoodsInfosExport(form);
this.setState({
loading: false,
});
if (res) {
const blob = new Blob([res]);
saveAs(blob, `商品明细-${format(new Date(), 'yyyyMMdd')}.xlsx`);
} else {
notification.error({ message: '下载失败' });
}
};
render() { render() {
const { treeData } = this.props; const { treeData } = this.props;
const selectW = { width: 250 }; const selectW = { width: 250 };
...@@ -81,6 +116,10 @@ class goodsManage extends Component { ...@@ -81,6 +116,10 @@ class goodsManage extends Component {
<Button style={{ border: 'none' }} onClick={() => this.setArea(0, 'after')}> <Button style={{ border: 'none' }} onClick={() => this.setArea(0, 'after')}>
勾选商品售后地址设置 勾选商品售后地址设置
</Button> </Button>
<br />
<Button style={{ border: 'none' }} onClick={() => this.checkEnableUpdateStock()}>
勾选商品库存修改
</Button>
</div> </div>
); );
// const uploadProps = { // const uploadProps = {
...@@ -173,19 +212,21 @@ class goodsManage extends Component { ...@@ -173,19 +212,21 @@ class goodsManage extends Component {
<Button onClick={() => this.onReset()} type="primary" className={styles.button}> <Button onClick={() => this.onReset()} type="primary" className={styles.button}>
重置 重置
</Button> </Button>
<Button
loading={this.state.loading}
onClick={() => this.onExportGoodsInfo()}
className={styles.button}
>
导出
</Button>
</FormItem> </FormItem>
<FormItem style={{ float: 'right' }}> <FormItem style={{ float: 'right' }}>
<Popover content={content} onVisibleChange={this.handleVisibleChange}> <Popover content={content} onVisibleChange={this.handleVisibleChange}>
<Button type="primary" className={styles.button}> <Button type="primary" className={styles.button}>
批量操作 批量设置
</Button> </Button>
</Popover> </Popover>
<Button type="primary" className={styles.button} onClick={this.addSpu}> {this.props.selectNum > 0 && <Tag color="green">已选商品 {this.props.selectNum}</Tag>}
新增商品
</Button>
<Button type="primary" className={styles.button} onClick={this.props.serviceVisbleOpen}>
新增服务类商品
</Button>
{/* <Button {/* <Button
className={styles.button} className={styles.button}
type="primary" type="primary"
......
import { Form } from '@ant-design/compatible'; import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css'; import '@ant-design/compatible/assets/index.css';
import { Modal, InputNumber, notification, Input, Radio } from 'antd'; import { Modal, InputNumber, notification, Input, Radio } from 'antd';
import React from 'react'; import React, { useState } from 'react';
import { updateStock } from '../service'; import { apiCreateGoodsLog } from '../service';
import styles from '../style.less';
import { isNumberSection } from '@/utils/validator';
const UpdateStock = props => { const UpdateStock = props => {
const { getFieldDecorator, validateFields, resetFields, getFieldValue } = props.form; const { getFieldDecorator, validateFields, resetFields, getFieldValue } = props.form;
const valueInfo = props.info; const valueInfo = props.info;
getFieldDecorator('stockChangeType', { initialValue: 1 });
const [loading, setLoading] = useState(false);
const submit = async () => { const submit = async () => {
validateFields(async (err, { stock, changeReason, stockChangeType }) => { validateFields(async (err, { stock, changeReason, changeType }) => {
if (err) return; if (err) return;
const error = await updateStock({ setLoading(true);
stock, const params = {
id: valueInfo.id, afterChange: stock,
supplierId: valueInfo.supplierId, supplierId: valueInfo.supplierId,
stockChangeType, productIdType: 2,
changeType,
changeReason, changeReason,
}); productIds: props.skuIds,
if (!error) { };
notification.success({ message: '操作成功!' }); console.log('params :>> ', params);
const res = await apiCreateGoodsLog(params);
if (res?.businessCode === '0000') {
notification.success({ message: '库存更改申请已提交!' });
props.onCancel('success'); props.onCancel('success');
resetFields(); resetFields();
} }
setLoading(false);
}); });
}; };
const onCancel = () => { const onCancel = () => {
...@@ -31,48 +40,84 @@ const UpdateStock = props => { ...@@ -31,48 +40,84 @@ const UpdateStock = props => {
}; };
const formItemLayout = { const formItemLayout = {
labelCol: { labelCol: {
span: 8, span: 7,
}, },
wrapperCol: { wrapperCol: {
span: 16, span: 15,
}, },
}; };
const validatorCallback = (rule, value, callback) => { const validatorCallback = (rule, value, callback) => {
// 减库存存时,校验可售库存-输入值>=0,即可售库存不可为负; // 减库存存时,校验可售库存-输入值>=0,即可售库存不可为负;
const stockChangeType = getFieldValue('stockChangeType'); const changeType = getFieldValue('changeType');
const increment = valueInfo.marketableStock - value; const increment = valueInfo.marketableStock - value;
return !stockChangeType && increment < 0 ? callback(new Error(rule.message)) : callback(); console.log('value :>> ', value, valueInfo.marketableStock);
console.log('valueInfo :>> ', valueInfo, increment);
return +changeType === 29 && increment < 0 ? callback(new Error(rule.message)) : callback();
}; };
return ( return (
<Modal title="修改库存" visible={props.visible} onCancel={onCancel} onOk={submit} width={400}> <Modal
title="修改库存"
visible={props.visible}
okButtonProps={{ loading, disabled: valueInfo.status === 1 }}
onCancel={onCancel}
onOk={submit}
width={500}
>
<Form {...formItemLayout}> <Form {...formItemLayout}>
{valueInfo.curStock ? (
<Form.Item label="当前库存:">
<span>{valueInfo.curStock}</span>
</Form.Item>
) : (
<Form.Item label="可修改库存商品数:">
<span>{props.skuIds.length}</span>
</Form.Item>
)}
<Form.Item label="变更类型:"> <Form.Item label="变更类型:">
{getFieldDecorator('stockChangeType', { {getFieldDecorator('changeType', {
rules: [{ required: true, message: '请选择类型!' }], rules: [{ required: true, message: '请选择类型!' }],
initialValue: valueInfo.changeType || 28,
})( })(
<Radio.Group> <Radio.Group disabled={valueInfo.status === 1}>
<Radio value={1}>增库存</Radio> <Radio value={28}>增库存</Radio>
<Radio value={0}>减库存</Radio> <Radio value={29}>减库存</Radio>
<Radio value={30}>使用新值</Radio>
</Radio.Group>, </Radio.Group>,
)} )}
<div className={styles.stockTip}>库存变更审批通过后生效</div>
</Form.Item> </Form.Item>
<Form.Item label="库存数:"> <Form.Item label="库存数:">
{getFieldDecorator('stock', { {getFieldDecorator('stock', {
rules: [ rules: [
{ required: true, message: '请输入库存!' }, { required: true, message: '请输入库存!' },
{ validator: validatorCallback, message: '减库存,输入库存数不可大于可售库存!' }, { validator: validatorCallback, message: '减库存,输入库存数不可大于可售库存!' },
{ validator: isNumberSection, min: 1, max: 500, message: '请输入1-500的整数' },
], ],
validateTrigger: ['onSubmit'], validateTrigger: ['onSubmit', 'onChange'],
})(<InputNumber min={0} precision={0} placeholder="请输入库存" style={{ width: 200 }} />)} initialValue: valueInfo.stock,
})(
<InputNumber
min={0}
precision={0}
placeholder="请输入库存"
disabled={valueInfo.status === 1}
style={{ width: 200 }}
/>,
)}
</Form.Item> </Form.Item>
<Form.Item label="变更原因:"> <Form.Item label="变更原因:">
{getFieldDecorator('changeReason', { {getFieldDecorator('changeReason', {
rules: [{ required: true, message: '请输入变更原因!' }], rules: [{ required: true, message: '请输入变更原因!' }],
initialValue: valueInfo.changeReason, initialValue: valueInfo.changeReason,
})(<Input.TextArea />)} })(<Input.TextArea disabled={valueInfo.status === 1} maxLength={50} />)}
</Form.Item> </Form.Item>
{valueInfo.stateDesc && (
<div className={styles.stockErrMsg}>
{valueInfo.stateDesc}{valueInfo.rejectReason}
</div>
)}
</Form> </Form>
</Modal> </Modal>
); );
......
...@@ -18,6 +18,8 @@ import { ...@@ -18,6 +18,8 @@ import {
getTemplateList, getTemplateList,
specList, specList,
queryAllAfterAddress, queryAllAfterAddress,
apiEnableUpdataStock,
apiQueryLastChangeLog,
} from './service'; } from './service';
import LogModal from './LogModal'; import LogModal from './LogModal';
import CreateModal from './createModal'; import CreateModal from './createModal';
...@@ -48,6 +50,7 @@ class goodsManage extends Component { ...@@ -48,6 +50,7 @@ class goodsManage extends Component {
selectedRowKeys: [], selectedRowKeys: [],
isAll: 0, isAll: 0,
templateList: [], templateList: [],
stockSkuIds: [],
isType: '', isType: '',
serviceVisble: false, serviceVisble: false,
...@@ -68,6 +71,7 @@ class goodsManage extends Component { ...@@ -68,6 +71,7 @@ class goodsManage extends Component {
} }
handleSearch = page => { handleSearch = page => {
this.onSelectChange([]);
const currentPage = this.state.pageNo; const currentPage = this.state.pageNo;
this.setState( this.setState(
{ {
...@@ -222,6 +226,28 @@ class goodsManage extends Component { ...@@ -222,6 +226,28 @@ class goodsManage extends Component {
filterShopList = (list = [], isEdit) => filterShopList = (list = [], isEdit) =>
list.filter(item => isEdit || !JDSHOPID.includes(item.id)); list.filter(item => isEdit || !JDSHOPID.includes(item.id));
// 验证是否可以修改库存
checkEnableUpdateStock = async () => {
const ids = this.state.selectedRowKeys.join(',');
if (ids) {
const res = await apiEnableUpdataStock(ids);
if (res.data) {
if (res.data.successSkuIds?.length) {
this.setState({
priceInfo: {},
stockSkuIds: res.data.successSkuIds,
});
this.openModal({}, 1);
} else {
const message = res.data.failedInfoList[0]?.message || '未存在可修改库存的商品';
notification.info({ message });
}
}
} else {
notification.info({ message: '请选择' });
}
};
openModal = ( openModal = (
{ {
skuId, skuId,
...@@ -232,6 +258,7 @@ class goodsManage extends Component { ...@@ -232,6 +258,7 @@ class goodsManage extends Component {
supplierId, supplierId,
stock, stock,
productStock, productStock,
state,
}, },
isStock, isStock,
) => { ) => {
...@@ -250,10 +277,39 @@ class goodsManage extends Component { ...@@ -250,10 +277,39 @@ class goodsManage extends Component {
marketPrice, marketPrice,
salePrice, salePrice,
supplierId, supplierId,
state,
}, },
}); });
}; };
onShowStockModal = async row => {
const res = await apiQueryLastChangeLog(row.skuId);
let priceInfo = {
id: row.skuId,
curStock: row.productStock,
supplierId: row.supplierId,
marketableStock: row.stock,
};
if (res.data && [1, 3].includes(+res.data.status)) {
priceInfo = Object.assign(
{
changeReason: res.data.changeReason,
stock: +res.data.afterChange,
changeType: res.data.changeType,
status: res.data.status,
stateDesc: res.data.statusDesc,
rejectReason: res.data.rejectReason,
},
priceInfo,
);
}
this.setState({
updateStockVisible: true,
priceInfo,
stockSkuIds: [row.skuId],
});
};
cancel = query => { cancel = query => {
this.setState({ updateStockVisible: false }); this.setState({ updateStockVisible: false });
if (query) { if (query) {
...@@ -316,11 +372,6 @@ class goodsManage extends Component { ...@@ -316,11 +372,6 @@ class goodsManage extends Component {
} }
}; };
serviceVisbleOpen = () => {
console.log('============>open');
this.serviceVisbleClose(true);
};
serviceVisbleClose = (flag, refresh) => { serviceVisbleClose = (flag, refresh) => {
this.setState({ this.setState({
serviceVisble: flag, serviceVisble: flag,
...@@ -343,6 +394,20 @@ class goodsManage extends Component { ...@@ -343,6 +394,20 @@ class goodsManage extends Component {
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Spin spinning={this.state.createloading}> <Spin spinning={this.state.createloading}>
<Button
type="primary"
className={styles.button}
onClick={() => this.setState({ createVisible: true, initData: {} })}
>
新增商品
</Button>
<Button
type="primary"
className={styles.button}
onClick={() => this.serviceVisbleClose(true)}
>
新增服务类商品
</Button>
<Card> <Card>
<SearchForm <SearchForm
handleSearch={this.handleSearch} handleSearch={this.handleSearch}
...@@ -353,9 +418,10 @@ class goodsManage extends Component { ...@@ -353,9 +418,10 @@ class goodsManage extends Component {
}} }}
treeData={this.state.treeData} treeData={this.state.treeData}
shopList={this.shopList} shopList={this.shopList}
addSpu={() => this.setState({ createVisible: true, initData: {} })} checkStock={this.checkEnableUpdateStock}
// addSpu={() => this.setState({ createVisible: true, initData: {} })}
selectNum={selectedRowKeys.length}
setArea={(isALL, type) => this.setArea(isALL, type)} setArea={(isALL, type) => this.setArea(isALL, type)}
serviceVisbleOpen={this.serviceVisbleOpen}
/> />
</Card> </Card>
<Spin spinning={this.state.loading}> <Spin spinning={this.state.loading}>
...@@ -425,6 +491,7 @@ class goodsManage extends Component { ...@@ -425,6 +491,7 @@ class goodsManage extends Component {
<UpdateStock <UpdateStock
visible={this.state.updateStockVisible} visible={this.state.updateStockVisible}
skuIds={this.state.stockSkuIds}
info={this.state.priceInfo} info={this.state.priceInfo}
onCancel={this.cancel} onCancel={this.cancel}
/> />
......
...@@ -197,3 +197,36 @@ export async function getAfterAddress(params) { ...@@ -197,3 +197,36 @@ export async function getAfterAddress(params) {
}); });
return data; return data;
} }
/**
* 商品是否可以做库存变更
* skuIds: 多个用英文逗号隔开
*/
export const apiEnableUpdataStock = skuIds =>
request.get(`/api/kdsp/sku/can/stockChange?skuIds=${skuIds}`, {
prefix: goodsApi,
});
// 商品明细导出
export const apiGoodsInfosExport = params =>
request.post('/api/kdsp/sku/export', {
prefix: goodsApi,
data: params,
responseType: 'arrayBuffer',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
// 新建商品审核记录
export const apiCreateGoodsLog = params =>
request.post('/api/kdsp/product/audit/create', {
data: params,
prefix: goodsApi,
});
// 查询sku最后一条库存变更记录
export const apiQueryLastChangeLog = skuId =>
request.get(`/api/kdsp/sku/last/stockChange/record?skuId=${skuId}`, {
prefix: goodsApi,
});
...@@ -108,13 +108,12 @@ export function column() { ...@@ -108,13 +108,12 @@ export function column() {
align: 'center', align: 'center',
sorter: (a, b) => a.stock - b.stock, sorter: (a, b) => a.stock - b.stock,
render: (_, row) => { render: (_, row) => {
// const stockView = // const stockView = row.productStock;
// row.state !== 4 ? ( const stockView = (
// <a onClick={() => this.openModal(row, 'productStock')}>{row.productStock}</a> <Button type="link" onClick={() => this.onShowStockModal(row)} style={{ padding: 0 }}>
// ) : ( {row.productStock}
// <span>{row.productStock}</span> </Button>
// ); );
const stockView = row.productStock;
return ( return (
<> <>
<p>当前库存:{stockView}</p> <p>当前库存:{stockView}</p>
......
...@@ -99,3 +99,14 @@ ...@@ -99,3 +99,14 @@
.sizeTitle { .sizeTitle {
font-size: 12px; font-size: 12px;
} }
.stockTip {
color: #d9363e;
line-height: 1;
}
.stockErrMsg {
box-sizing: border-box;
padding-left: 30%;
color: #d9363e;
line-height: 1;
}
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
const TableList = ref => { const TableList = ref => {
const actionRef = useRef(null); const actionRef = useRef(null);
const columns = [ const columns = [
{ {
title: '批次号', title: '批次号',
...@@ -99,7 +100,7 @@ const TableList = ref => { ...@@ -99,7 +100,7 @@ const TableList = ref => {
<Button <Button
type="primary" type="primary"
style={{ style={{
marginRottom: '10px', marginRight: '10px',
}} }}
onClick={() => { onClick={() => {
downUploadeOrder({ batchNo: record.batchNo, status: 0 }); downUploadeOrder({ batchNo: record.batchNo, status: 0 });
......
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
import { Modal, notification, Input } from 'antd';
import React, { useState } from 'react';
import { apiDelayDeliverGoods } from '../service';
const UpdateStock = props => {
const { getFieldDecorator, validateFields, resetFields } = props.form;
const valueInfo = {};
const [loading, setLoading] = useState(false);
const submit = async () => {
validateFields(async (err, { remark }) => {
if (err) return;
setLoading(true);
const params = {
orderIds: [props.orderId],
operationType: 5,
remark,
};
console.log('params :>> ', params);
const res = await apiDelayDeliverGoods(params);
if (res?.businessCode === '0000') {
notification.success({ message: '提交成功!' });
props.onCancel('success');
resetFields();
}
setLoading(false);
});
};
const onCancel = () => {
props.onCancel();
resetFields();
};
const formItemLayout = {
labelCol: {
span: 7,
},
wrapperCol: {
span: 15,
},
};
return (
<Modal
title="异常订单报备"
visible={props.visible}
okButtonProps={{ loading }}
onCancel={onCancel}
onOk={submit}
width={500}
>
<Form {...formItemLayout}>
<Form.Item label="异常原因:">
{getFieldDecorator('remark', {
rules: [{ required: true, message: '请输入异常原因!' }],
initialValue: valueInfo.remark,
})(<Input.TextArea maxLength={30} showCount />)}
</Form.Item>
</Form>
</Modal>
);
};
export default Form.create()(UpdateStock);
import { Button, notification } from 'antd'; import { Button, notification, Modal } from 'antd';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
...@@ -8,6 +8,7 @@ import LogisticsForm from './components/LogisticsForm'; ...@@ -8,6 +8,7 @@ import LogisticsForm from './components/LogisticsForm';
import style from './styles.less'; import style from './styles.less';
import PopoverDom from './components/PreviewImage'; import PopoverDom from './components/PreviewImage';
import LogisticsCom from './components/LogisticsCom'; import LogisticsCom from './components/LogisticsCom';
import DelayDeliverGoods from './components/DelayDeliverGoods';
import { import {
queryToSend, queryToSend,
queryExpress, queryExpress,
...@@ -17,6 +18,8 @@ import { ...@@ -17,6 +18,8 @@ import {
getJDLogisticsInfo, getJDLogisticsInfo,
} from './service'; } from './service';
const { confirm } = Modal;
const TableList = props => { const TableList = props => {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD';
const [companys, setCompanys] = useState([]); const [companys, setCompanys] = useState([]);
...@@ -37,6 +40,9 @@ const TableList = props => { ...@@ -37,6 +40,9 @@ const TableList = props => {
const [orderStatus, setorderStatus] = useState(1); const [orderStatus, setorderStatus] = useState(1);
const [endTimeStr, setEndTimeStr] = useState(moment().format(dateFormat)); const [endTimeStr, setEndTimeStr] = useState(moment().format(dateFormat));
const [visibleDelay, setVisibleDelay] = useState(false);
const [delayOrderIDs, setDelayOrderIDs] = useState(0);
// const startDisabledDate = current => // const startDisabledDate = current =>
// current && (endTime.diff(current, 'days') > 30 || endTime.diff(current, 'days') < 0); // current && (endTime.diff(current, 'days') > 30 || endTime.diff(current, 'days') < 0);
// const endDisabledDate = current => // const endDisabledDate = current =>
...@@ -68,6 +74,29 @@ const TableList = props => { ...@@ -68,6 +74,29 @@ const TableList = props => {
setLogisticsComList(tempObj); setLogisticsComList(tempObj);
}; };
const onDelay = (id, state, content) => {
if (state === 1) {
confirm({
title: '提示',
content,
cancelButtonProps: {
style: {
display: 'none',
},
},
});
} else {
setDelayOrderIDs(id);
setVisibleDelay(true);
}
};
const onCancelDelay = e => {
setVisibleDelay(false);
if (e && actionRef.current) {
actionRef.current.reload();
}
};
const renderContent = (record, key) => { const renderContent = (record, key) => {
if (record.mchOrderSkuVoList) { if (record.mchOrderSkuVoList) {
return record?.mchOrderSkuVoList.map((item, index) => ( return record?.mchOrderSkuVoList.map((item, index) => (
...@@ -295,6 +324,15 @@ const TableList = props => { ...@@ -295,6 +324,15 @@ const TableList = props => {
{props.type === 2 ? '更新物流信息' : '填写物流信息'} {props.type === 2 ? '更新物流信息' : '填写物流信息'}
</Button> </Button>
)} )}
{props.type !== 2 && (
<Button
type="primary"
className={+record.delayStatus === 1 ? style.btnWarning : ''}
onClick={() => onDelay(record.orderId, +record.delayStatus, record.delayRemark)}
>
{+record.delayStatus === 1 ? '异常订单已报备' : '异常订单报备'}
</Button>
)}
</React.Fragment> </React.Fragment>
), ),
}, },
...@@ -406,6 +444,11 @@ const TableList = props => { ...@@ -406,6 +444,11 @@ const TableList = props => {
value={LogisticsComList} value={LogisticsComList}
key={LogisticsComList.key} key={LogisticsComList.key}
/> />
<DelayDeliverGoods
visible={visibleDelay}
orderId={delayOrderIDs}
onCancel={e => onCancelDelay(e)}
/>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
}; };
......
...@@ -144,3 +144,10 @@ export async function downUploadeOrder(params) { ...@@ -144,3 +144,10 @@ export async function downUploadeOrder(params) {
}; };
saveAs(blob, `批量发货-${status[params.status]}-${format(new Date(), 'yyyyMMddHHmmss')}.xlsx`); saveAs(blob, `批量发货-${status[params.status]}-${format(new Date(), 'yyyyMMddHHmmss')}.xlsx`);
} }
// 延迟发货
export function apiDelayDeliverGoods(data) {
return request.post('/api/kdsp/order/operation/record/create', {
data,
prefix: config.kdspApi,
});
}
...@@ -27,3 +27,12 @@ ...@@ -27,3 +27,12 @@
} }
} }
} }
.btnWarning {
background-color: rgb(247, 143, 74);
border-color: rgb(247, 143, 74);
}
.btnWarning:hover,
.btnWarning:focus {
background-color: rgb(253, 168, 111);
border-color: rgb(253, 168, 111);
}
...@@ -172,6 +172,24 @@ export const isIntegerNotZero = (rule, value, callback) => { ...@@ -172,6 +172,24 @@ export const isIntegerNotZero = (rule, value, callback) => {
} }
}; };
/**
* 验证 数字区间
* rule.min: 0
* rule.max: 100
*/
export const isNumberSection = (rule, value, callback) => {
if (['', undefined, null].includes(value)) {
callback();
}
if (!Number(value)) {
callback(new Error('请输入数字'));
} else if (rule.min > +value || rule.max < +value) {
callback(new Error(rule.message || `请输入${rule.min}-${rule.max}区间的数字`));
} else {
callback();
}
};
// 验证是否整数,非必填 // 验证是否整数,非必填
export function isIntegerNotMust(rule, value, callback) { export function isIntegerNotMust(rule, value, callback) {
if (!value) { if (!value) {
......
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