Commit a46207de authored by 张子雨's avatar 张子雨

feat: 时效2.0开发

parent 2ecb5e84
import React, { useState, useRef } from 'react'; import React, { useState, useRef } from 'react';
import { notification, Button } from 'antd'; import { notification, Button } from 'antd';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import moment from 'moment';
import _ from 'lodash';
import { searchList, auditInfoApi, orderDetail } from '../services'; import { searchList, auditInfoApi, orderDetail } from '../services';
import { columnSticData, appealType } from '../data'; import { columnSticData, appealType } from '../data';
import AuditModal from '../components/auditModal'; import AuditModal from '../components/auditModal';
...@@ -19,6 +21,8 @@ export default () => { ...@@ -19,6 +21,8 @@ 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 viewDetail = async ({ serviceNo }) => { const viewDetail = async ({ serviceNo }) => {
const data = await orderDetail({ serviceNo }); const data = await orderDetail({ serviceNo });
...@@ -53,12 +57,58 @@ export default () => { ...@@ -53,12 +57,58 @@ export default () => {
setAppealDetailModal(true); setAppealDetailModal(true);
setSelectedRow(detailData); setSelectedRow(detailData);
}; };
const renderContent = (record, index, action) => {
if (!time[record.orderId]) {
const serviceTime = moment(record.serviceTime).valueOf() + 24 * 3600 * 1000;
const nowTime = moment(record.nowTime).valueOf();
let timeNumber = (serviceTime - nowTime) / 1000;
time[record.orderId] = setInterval(() => {
if (timeNumber > 0) {
timeNumber -= 1;
// eslint-disable-next-line radix
const hours = parseInt((timeNumber / 3600) % 24)
.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.orderId] = str;
const strings = _.cloneDeep(timeString);
setTimeString(strings);
} else {
clearInterval(time[record.orderId]);
timeString[record.orderId] = '0时0分0秒';
const strings = _.cloneDeep(timeString);
setTimeString(strings);
}
}, 1000);
}
};
const columns = [ const columns = [
{
title: '审核倒计时',
dataIndex: 'serviceTime',
key: 'serviceTime',
hideInSearch: true,
width: 120,
render: (val, record, index, action) => [
<span style={{ color: 'red' }}>
{renderContent(record, index, action)}
{timeString[record.orderId]}
</span>,
],
},
{ {
title: '售后状态', title: '售后状态',
dataIndex: 'serviceStatus', dataIndex: 'serviceStatus',
hideInSearch: true, hideInSearch: true,
width: 100, width: 120,
}, },
...columnSticData, ...columnSticData,
{ {
...@@ -66,7 +116,7 @@ export default () => { ...@@ -66,7 +116,7 @@ export default () => {
dataIndex: 'proofs', dataIndex: 'proofs',
hideInSearch: true, hideInSearch: true,
width: 100, width: 100,
render: (_, r) => <a onClick={() => viewProofs(r.proofs)}>查看凭证</a>, render: (val, r) => <a onClick={() => viewProofs(r.proofs)}>查看凭证</a>,
}, },
{ {
title: '售后申诉', title: '售后申诉',
...@@ -87,7 +137,7 @@ export default () => { ...@@ -87,7 +137,7 @@ export default () => {
dataIndex: 'action', dataIndex: 'action',
width: 250, width: 250,
fixed: 'right', fixed: 'right',
render: (_, r) => [ render: (val, r) => [
<Button key="link1" onClick={() => openAudit(r)} className="mr10" type="primary"> <Button key="link1" onClick={() => openAudit(r)} className="mr10" type="primary">
审核 审核
</Button>, </Button>,
......
import { Form, Button, Input, Select, notification, Upload, Cascader, InputNumber } from 'antd'; import {
Form,
Button,
Input,
Select,
notification,
Upload,
Cascader,
InputNumber,
Popover,
Divider,
} from 'antd';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'dva'; import { connect } from 'dva';
import styles from '../style.less'; import styles from '../style.less';
...@@ -53,6 +64,25 @@ class goodsManage extends Component { ...@@ -53,6 +64,25 @@ class goodsManage extends Component {
const selectW = { width: 250 }; const selectW = { width: 250 };
const iptNumWidth = { width: 118 }; const iptNumWidth = { width: 118 };
const that = this; const that = this;
const content = (
<div>
<Button type="text" onClick={() => this.setArea(1, 'distribution')}>
全部商品配送区域设置
</Button>
<br />
<Button type="text" onClick={() => this.setArea(0, 'distribution')}>
勾选商品配送区域设置
</Button>
<br />
<Button type="text" onClick={() => this.setArea(1, 'after')}>
全部商品售后地址设置
</Button>
<br />
<Button type="text" onClick={() => this.setArea(0, 'after')}>
勾选商品售后地址设置
</Button>
</div>
);
// const uploadProps = { // const uploadProps = {
// name: 'file', // name: 'file',
// async customRequest(info) { // async customRequest(info) {
...@@ -138,15 +168,11 @@ class goodsManage extends Component { ...@@ -138,15 +168,11 @@ class goodsManage extends Component {
</Button> </Button>
</FormItem> </FormItem>
<FormItem style={{ float: 'right' }}> <FormItem style={{ float: 'right' }}>
<Button type="primary" className={styles.button} onClick={() => this.setArea(1)}> <Popover content={content} onVisibleChange={this.handleVisibleChange}>
全部配送不支持配置区域 <Button type="primary" className={styles.button}>
</Button> 批量操作
<Button type="primary" className={styles.button} onClick={() => this.setArea(0)}> </Button>
批量设置不支持配送区域 </Popover>
</Button>
<Button type="primary" className={styles.button}>
批量操作
</Button>
<Button type="primary" className={styles.button} onClick={this.addSpu}> <Button type="primary" className={styles.button} onClick={this.addSpu}>
新增商品 新增商品
</Button> </Button>
......
...@@ -3,7 +3,7 @@ import '@ant-design/compatible/assets/index.css'; ...@@ -3,7 +3,7 @@ import '@ant-design/compatible/assets/index.css';
import { Modal, Input, Select, Cascader, Tag, notification } from 'antd'; import { Modal, Input, Select, Cascader, Tag, notification } from 'antd';
import { da } from 'date-fns/locale'; import { da } from 'date-fns/locale';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { getTemplate } from '../service'; import { getTemplate, getAfterAddress } from '../service';
const { Option } = Select; const { Option } = Select;
...@@ -14,6 +14,7 @@ const TempleatModal = props => { ...@@ -14,6 +14,7 @@ const TempleatModal = props => {
selectedRowKeys, selectedRowKeys,
templateList, templateList,
isALL, isALL,
isType,
} = props; } = props;
const formItemLayout = { const formItemLayout = {
labelCol: { labelCol: {
...@@ -24,27 +25,62 @@ const TempleatModal = props => { ...@@ -24,27 +25,62 @@ const TempleatModal = props => {
}, },
}; };
const handleOk = async () => { const handleOk = async () => {
console.log(props);
validateFields(async (error, fieldsValue) => { validateFields(async (error, fieldsValue) => {
if (!error) { if (!error) {
const data = await getTemplate({ if (isType === 'distribution') {
isAll: isALL, this.setAfterAddress(fieldsValue);
skuIdList: selectedRowKeys, }
templateId: fieldsValue.templateId.key, if (isType === 'after') {
}); this.setTemplate(fieldsValue);
if (data.businessCode === '0000') {
notification.success({ message: '配置成功!' });
resetFields();
props.onCancel();
} }
} }
}); });
}; };
const setAfterAddress = async fieldsValue => {
const data = await getAfterAddress({
// isAll: isALL,
skuIds: selectedRowKeys,
afterAddressId: fieldsValue.templateId.key,
});
if (data.businessCode === '0000') {
notification.success({ message: '配置成功!' });
resetFields();
props.onCancel();
}
};
const setTemplate = async fieldsValue => {
const data = await getTemplate({
isAll: isALL,
skuIdList: selectedRowKeys,
templateId: fieldsValue.templateId.key,
});
if (data.businessCode === '0000') {
notification.success({ message: '配置成功!' });
resetFields();
props.onCancel();
}
};
const title = () => {
if (isType === 'distribution') {
if (isALL) {
return '全部商品配送区域设置';
}
return '勾选商品配送区域设置';
}
if (isType === 'after') {
if (isALL) {
return '全部设置不支持配送区域';
}
return '批量设置不支持配送区域';
}
return '';
};
useEffect(() => {}, []); useEffect(() => {}, []);
return ( return (
<Modal <Modal
title={isALL ? '全部设置不支持配送区域' : '批量设置不支持配送区域'} title={title}
visible={visible} visible={visible}
width="500px" width="500px"
onCancel={props.onCancel} onCancel={props.onCancel}
...@@ -57,11 +93,18 @@ const TempleatModal = props => { ...@@ -57,11 +93,18 @@ const TempleatModal = props => {
rules: [{ required: true, message: '请选择模板!' }], rules: [{ required: true, message: '请选择模板!' }],
})( })(
<Select placeholder="请选择模板" labelInValue allowClear> <Select placeholder="请选择模板" labelInValue allowClear>
{templateList.map(item => ( {isType === 'after' &&
<Option label={item.templateName} value={item.id} key={item.id}> templateList.map(item => (
{item.templateName} <Option label={item.templateName} value={item.id} key={item.id}>
</Option> {item.templateName}
))} </Option>
))}
{isType === 'distribution' &&
templateList.map(item => (
<Option label={item.addressName} value={item.id} key={item.id}>
{item.addressName}
</Option>
))}
</Select>, </Select>,
)} )}
</Form.Item> </Form.Item>
......
...@@ -30,7 +30,14 @@ import { ...@@ -30,7 +30,14 @@ import {
validateSpuInfo, validateSpuInfo,
createEditData, createEditData,
} from './mixin'; } from './mixin';
import { getSpecList, getJdPicList, getBrandList, addGoods, editGoods } from '../service'; import {
getSpecList,
getJdPicList,
getBrandList,
addGoods,
editGoods,
getAfterAddress,
} from '../service';
import styles from '../style.less'; import styles from '../style.less';
import Upload from '../../components/sortablUpload'; import Upload from '../../components/sortablUpload';
import BatchSetting from './batchSetting'; import BatchSetting from './batchSetting';
...@@ -60,17 +67,31 @@ class goodsManage extends Component { ...@@ -60,17 +67,31 @@ class goodsManage extends Component {
skuNameVisible: false, skuNameVisible: false,
productType: 1, productType: 1,
confirmLoading: false, confirmLoading: false,
afterAddressList: {},
}; };
componentDidMount() { componentDidMount() {
this.getSpecData(); this.getSpecData();
this.getBrandData(); this.getBrandData();
this.getAfterAddressData();
} }
componentWillReceiveProps() { componentWillReceiveProps() {
this.setState({ isCancel: false }); this.setState({ isCancel: false });
} }
// 获取售后地址
getAfterAddressData = async () => {
try {
const { data } = await getAfterAddress();
if (data) {
this.setState({ afterAddressList: data });
}
} catch (e) {
console.log(e);
}
};
// 获取规格列表 // 获取规格列表
getSpecData = async () => { getSpecData = async () => {
try { try {
...@@ -497,7 +518,14 @@ class goodsManage extends Component { ...@@ -497,7 +518,14 @@ class goodsManage extends Component {
labelCol: { span: 2 }, labelCol: { span: 2 },
wrapperCol: { span: 22 }, wrapperCol: { span: 22 },
}; };
const { colorImg, productType, normalBrandList, brandList, confirmLoading } = this.state; const {
colorImg,
productType,
normalBrandList,
brandList,
confirmLoading,
afterAddressList,
} = this.state;
const skuSpeFirstKeys = initData.firstSpecList || []; const skuSpeFirstKeys = initData.firstSpecList || [];
const skuSpeSecondKeys = initData.secondSpecList || []; const skuSpeSecondKeys = initData.secondSpecList || [];
const treeDataArray = productType === 2 ? virtualTreeData : treeData; const treeDataArray = productType === 2 ? virtualTreeData : treeData;
...@@ -655,6 +683,28 @@ class goodsManage extends Component { ...@@ -655,6 +683,28 @@ class goodsManage extends Component {
)} )}
</FormItem> </FormItem>
</Col> </Col>
<Col span={10}>
<FormItem label="售后地址" {...formItemLayout}>
{getFieldDecorator('afterAddressId', {
initialValue: this.state.initForm.afterAddressId,
rules: [
{
required: true,
message: '请选择售后地址',
},
],
})(
<Select allowClear style={{ width: 280 }} placeholder="请选择售后地址">
{afterAddressList?.length &&
afterAddressList.map(item => (
<Option key={item.id} value={item.id}>
{item.addressName}
</Option>
))}
</Select>,
)}
</FormItem>
</Col>
{specListData.length {specListData.length
? specListData.map((item, index) => ( ? specListData.map((item, index) => (
<Col span={24}> <Col span={24}>
......
...@@ -11,7 +11,14 @@ import LocalStroage from '@/utils/localStorage'; ...@@ -11,7 +11,14 @@ import LocalStroage from '@/utils/localStorage';
import configApi from '../../../config/env.config'; import configApi from '../../../config/env.config';
import UpdateStock from './UpdateStock'; import UpdateStock from './UpdateStock';
import { spuDetail, categoryList, getVirtualCategory, getTemplateList, specList } from './service'; import {
spuDetail,
categoryList,
getVirtualCategory,
getTemplateList,
specList,
queryAllAfterAddress,
} from './service';
import LogModal from './LogModal'; import LogModal from './LogModal';
import CreateModal from './createModal'; import CreateModal from './createModal';
import { column, JDSHOPID } from './staticdata'; import { column, JDSHOPID } from './staticdata';
...@@ -40,6 +47,7 @@ class goodsManage extends Component { ...@@ -40,6 +47,7 @@ class goodsManage extends Component {
selectedRowKeys: [], selectedRowKeys: [],
isAll: 0, isAll: 0,
templateList: [], templateList: [],
isType: '',
}; };
currentLog = null; currentLog = null;
...@@ -187,12 +195,13 @@ class goodsManage extends Component { ...@@ -187,12 +195,13 @@ class goodsManage extends Component {
}); });
}; };
setArea = async isAll => { setArea = async (isAll, type) => {
// distribution配送区域 after售后地址
if (!this.state.selectedRowKeys.length && !isAll) { if (!this.state.selectedRowKeys.length && !isAll) {
notification.error({ message: '请选择商品' }); notification.error({ message: '请选择商品' });
return; return;
} }
const data = await getTemplateList(); const data = type === 'distribution' ? await getTemplateList() : await queryAllAfterAddress();
if (data.code === '0000' && data.data.length) { if (data.code === '0000' && data.data.length) {
this.setState({ this.setState({
templeatModalVisible: true, templeatModalVisible: true,
...@@ -303,7 +312,7 @@ class goodsManage extends Component { ...@@ -303,7 +312,7 @@ class goodsManage extends Component {
treeData={this.state.treeData} treeData={this.state.treeData}
shopList={this.shopList} shopList={this.shopList}
addSpu={() => this.setState({ createVisible: true, initData: {} })} addSpu={() => this.setState({ createVisible: true, initData: {} })}
setArea={isALL => this.setArea(isALL)} setArea={(isALL, type) => this.setArea(isALL, type)}
/> />
</Card> </Card>
<Spin spinning={this.state.loading}> <Spin spinning={this.state.loading}>
...@@ -384,6 +393,7 @@ class goodsManage extends Component { ...@@ -384,6 +393,7 @@ class goodsManage extends Component {
this.handleSearch(); this.handleSearch();
}} }}
isALL={this.state.isAll} isALL={this.state.isAll}
isType={this.state.isType}
templateList={this.state.templateList} templateList={this.state.templateList}
/> />
</Spin> </Spin>
......
...@@ -179,3 +179,13 @@ export async function queryAllAfterAddress() { ...@@ -179,3 +179,13 @@ export async function queryAllAfterAddress() {
prefix: goodsApi, prefix: goodsApi,
}); });
} }
// 商品售后地址设置
export async function getAfterAddress(params) {
const data = await request.post('/product/api/updateSkuAfterAddress', {
data: stringify(params),
prefix: goodsApi,
headers,
});
return data;
}
...@@ -5,12 +5,12 @@ import { Button, notification } from 'antd'; ...@@ -5,12 +5,12 @@ import { Button, notification } from 'antd';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import _ from 'lodash'; import _ from 'lodash';
// import { searchList, auditInfoApi, orderDetail } from './service'; // import { searchList, auditInfoApi, orderDetail } from './service';
import moment from 'moment';
import { searchList, orderDetail } from './service'; import { searchList, orderDetail } from './service';
import { column } from './data'; import { column } from './data';
import AuditModal from './components/auditModal'; import AuditModal from './components/auditModal';
import DetailTable from './components/detailTable'; import DetailTable from './components/detailTable';
import { dateDiff } from './common'; import { dateDiff } from './common';
import moment from 'moment';
export default () => { export default () => {
const table = useRef(); const table = useRef();
...@@ -104,6 +104,8 @@ export default () => { ...@@ -104,6 +104,8 @@ export default () => {
timeString[record.orderId] = '0时0分0秒'; timeString[record.orderId] = '0时0分0秒';
const strings = _.cloneDeep(timeString); const strings = _.cloneDeep(timeString);
setTimeString(strings); setTimeString(strings);
// eslint-disable-next-line no-unused-expressions
table.current?.reload?.();
} }
}, 1000); }, 1000);
} }
......
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