提交 185fd540 作者: ZhangLingKun

功能:租赁订单发货

上级 92214722
...@@ -13,3 +13,5 @@ export type BackEndLoginType = InterFunction< ...@@ -13,3 +13,5 @@ export type BackEndLoginType = InterFunction<
nickName: null; nickName: null;
} }
>; >;
// 上传图片
export type uploadOssType = InterFunction<any, NonNullable<unknown>>;
import { InterListFunction } from '~/api/interface'; import { InterFunction, InterListFunction } from '~/api/interface';
// web 租赁订单-分页-列表 // web 租赁订单-分页-列表
export type listOfRentalOrdersType = InterListFunction< export type listOfRentalOrdersType = InterListFunction<
{ {
...@@ -79,3 +79,263 @@ export type listOfRentalOrdersType = InterListFunction< ...@@ -79,3 +79,263 @@ export type listOfRentalOrdersType = InterListFunction<
nickName: string; nickName: string;
} }
>; >;
// 后台管理 租赁订单-分页-列表
export type listPcWechatOrderType = InterListFunction<
{
buyerAccount?: string;
endTime?: string;
orderNo?: string;
startTime?: string;
tranStatus?: string;
wareNo?: string;
wareTitle?: string;
},
{
id: number;
orderNo: string;
createTime: string;
wareInfoId: null;
wareNo: string;
wareTitle: string;
wareImg: string;
skuInfoId: null;
skuTitle: null;
repoAccountId: null;
uid: string;
buyerName: string;
buyerPhone: string;
unitPrice: number;
wareNum: number;
shouldPay: number;
actualPay: number;
orderType: null;
deposit: number;
rentPrice: null;
startDate: null;
endDate: null;
payDay: null;
tranStatus: string;
exWare: null;
remark: string;
pfRemark: null;
shutReason: null;
payNo: null;
payTime: null;
sendWareTime: null;
receipt: {
id: number;
receiptMethod: number;
takeName: string;
takePhone: string;
region: string;
detailAddress: string;
repoName: null;
repoAddress: null;
bookPhone: null;
sendExCode: null;
sendExNo: null;
sendAddress: null;
renMethod: null;
renPhone: null;
renName: null;
renExCode: null;
renExNo: null;
renAddress: null;
renRepoName: null;
renRepoAddr: null;
renRepoPhone: null;
};
orderRefund: null;
express: null;
refundExpress: null;
vcus: null;
returnTime: null;
couponId: null;
specsId: null;
balance: null;
doing: string;
waiting: string;
leaseOrderStatus: string;
nickName: string;
}
>;
// web/小程序——订单详情
export type orderDetailType = InterFunction<
{ orderNo: string },
{
actualPay: number;
balance: number;
buyerName: string;
buyerPhone: string;
couponId: number;
createTime: string;
deposit: number;
doing: string;
endDate: string;
exWare: number;
express: {
logisticCode: string;
shipperCode: string;
stateEx: string;
traces: Array<{
acceptStation: string;
acceptTime: string;
action: string;
location: string;
}>;
};
id: number;
leaseOrderStatus: string;
nickName: string;
orderNo: string;
orderRefund: {
actualRefund: number;
createTime: string;
id: number;
orderInfo: {};
orderInfoId: number;
orderVcu: {
id: number;
imgs: Array<string>;
orderInfoId: number;
remark: string;
vcuSatus: number;
vcuType: number;
videoUrl: string;
};
pfRemark: string;
reason: string;
refundCash: {
amtPaid: number;
cashAmt: number;
createUser: number;
id: number;
opName: string;
opNo: string;
orderNo: string;
payMethod: number;
payNo: string;
payTime: string;
refundNo: string;
remark: string;
voucher: Array<string>;
wareTitle: string;
};
refundNo: string;
refundStatus: number;
rlogs: Array<{
createTime: string;
msg: string;
opAccount: string;
opName: string;
}>;
shouldRefund: number;
};
orderType: number;
payDay: number;
payNo: string;
payTime: string;
pfRemark: string;
receipt: {
bookPhone: string;
detailAddress: string;
id: number;
receiptMethod: number;
region: string;
renAddress: string;
renExCode: string;
renExNo: string;
renMethod: number;
renName: string;
renPhone: string;
renRepoAddr: string;
renRepoName: string;
renRepoPhone: string;
repoAddress: string;
repoName: string;
sendAddress: string;
sendExCode: string;
sendExNo: string;
takeName: string;
takePhone: string;
};
refundExpress: {
logisticCode: string;
shipperCode: string;
stateEx: string;
traces: Array<{
acceptStation: string;
acceptTime: string;
action: string;
location: string;
}>;
};
remark: string;
rentPrice: number;
repoAccountId: number;
returnTime: string;
sendWareTime: string;
shouldPay: number;
shutReason: string;
skuInfoId: number;
skuTitle: string;
specsId: number;
startDate: string;
tranStatus: string;
uid: string;
unitPrice: number;
vcus: Array<{
id: number;
imgs: Array<string>;
orderInfoId: number;
remark: string;
vcuSatus: number;
vcuType: number;
videoUrl: string;
}>;
waiting: string;
wareDescription: string;
wareImg: string;
wareInfoId: number;
wareNo: string;
wareNum: number;
wareTitle: string;
}
>;
// 后台管理——发货-订单/ 卖家发货
export type sendOrderWareType = InterFunction<
{
authPwd: string;
imgs: Array<string>;
orderInfoId: number;
orderRefundId: number;
remark: string;
renAddress: string;
renName: string;
renPhone: string;
sendAddress: string;
sendExCode: string;
sendExNo: string;
vcuSatus: number;
videoUrl: string;
},
NonNullable<unknown>
>;
// 订单状态-字典
export type listTranStatusType = InterFunction<
NonNullable<unknown>,
{
status: string;
doing: string;
waiting: string;
leaseOrderStatus: string;
}[]
>;
// v1.0.1 物流公司列表-字典
export type listExpressInfoType = InterFunction<
NonNullable<unknown>,
{
exName: string;
exCode: string;
}[]
>;
import axios from '../request'; import axios from '../request';
import { BackEndLoginType } from '~/api/interface/commonType'; import { BackEndLoginType, uploadOssType } from '~/api/interface/commonType';
export class CommonAPI { export class CommonAPI {
// 用户登录 // 用户登录
static BackEndLogin: BackEndLoginType = (params) => static BackEndLogin: BackEndLoginType = (params) =>
axios.post('/userapp/auth/backEndLogin', params); axios.post('/userapp/auth/backEndLogin', params);
// 上传图片
static uploadOss: uploadOssType = (data) => axios.post('/pms/upload/oss', data);
} }
import axios from '../request'; import axios from '../request';
import { listOfRentalOrdersType } from '~/api/interface/orderManageType'; import {
listExpressInfoType,
listOfRentalOrdersType,
listPcWechatOrderType,
listTranStatusType,
orderDetailType,
sendOrderWareType,
} from '~/api/interface/orderManageType';
export class OrderManageAPI { export class OrderManageAPI {
// web 租赁订单-分页-列表 // web 租赁订单-分页-列表
static listOfRentalOrders: listOfRentalOrdersType = (params) => static listOfRentalOrders: listOfRentalOrdersType = (params) =>
axios.post('/oms/RentalOrders/listOfRentalOrders', params); axios.post('/oms/RentalOrders/listOfRentalOrders', params);
// 后台管理 租赁订单-分页-列表
static listPcWechatOrder: listPcWechatOrderType = (params) =>
axios.post('/oms/RentalOrders/listPcWechatOrder', params);
// web/小程序——订单详情
static orderDetail: orderDetailType = (params) =>
axios.get('/oms/RentalOrders/orderDetail', { params });
// 订单状态-字典
static listTranStatus: listTranStatusType = (params) =>
axios.get('/oms/RentalOrders/listTranStatus', { params });
// 后台管理——发货-订单/ 卖家发货
static sendOrderWare: sendOrderWareType = (params) =>
axios.post('/oms/RentalOrders/sendOrderWare', params);
// v1.0.1 物流公司列表-字典
static listExpressInfo: listExpressInfoType = (params) =>
axios.get('/oms/express/listExpressInfo', { params });
} }
...@@ -35,9 +35,9 @@ service.interceptors.response.use( ...@@ -35,9 +35,9 @@ service.interceptors.response.use(
return Promise.resolve(data); return Promise.resolve(data);
} }
// 重新登录? // 重新登录?
if (['605', '603', '602', '4004', '607'].includes(data.code)) { if (['605', '603', '602', '4004', '607', '2014', '2013'].includes(data.code)) {
message.error(data.message).then(); message.error(data.message).then();
Cookies.remove('SXTB-TOKEN'); Cookies.remove('SHAREFLY-TOKEN');
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1000); }, 1000);
......
.message-box-wrap {
position: relative;
background: #f3f6ff;
height: auto;
padding: 20px 10px;
border-radius: 5px;
.message-action{
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background: #ffffff;
height: 80px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
align-items: center;
}
.message-box {
width: 100%;
height: 400px;
overflow-y: scroll;
position: relative;
box-sizing: border-box;
padding-bottom: 100px;
.flex-start {
justify-content: flex-start;
}
.flex-end {
justify-content: flex-end;
}
.message-box-item {
width: 100%;
height: auto;
position: relative;
box-sizing: border-box;
display: flex;
align-items: flex-start;
flex-wrap: nowrap;
margin: 20px 0 50px 0;
.item-userImg {
width: 32px;
height: 32px;
border-radius: 50%;
background-image: url("https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/mine_user.png");
background-size: 100% 100%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.item-content {
flex: 1;
padding: 10px;
margin: 0 10px;
border-radius: 5px;
background: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
word-break: break-all;
line-height: 16px;
max-width: 60%;
}
.item-time {
position: absolute;
top: -20px;
left: 0;
width: 100%;
text-align: center;
color: #999999;
font-size: 13px;
transform: scale(0.8);
}
}
}
}
import { useEffect, useState } from 'react';
import './index.scss';
import { Button, Input } from 'antd';
function MessageBox() {
const [messageList, setMessageList] = useState<any[]>([]);
useEffect(() => {
setMessageList([{ type: 0 }, { type: 1 }, { type: 0 }, { type: 1 }]);
}, []);
return (
<div className={'message-box-wrap'}>
<div className={'message-box'}>
{messageList.map((i, j) => (
<div className={`message-box-item ${i.type === 0 ? 'flex-start' : 'flex-end'}`} key={j}>
<div className={'item-time'}>2021-01-01 12:00:00</div>
{i.type === 0 && <div className={'item-userImg'}></div>}
<div className={'item-content'}>
红鲤鱼家有头小绿驴叫驴屡屡,绿鲤鱼家有头小红驴叫吕里里,红鲤鱼说它家的驴屡屡要比绿鲤鱼家的吕里里绿,绿鲤鱼说它家的吕里里要比红鲤鱼家的驴屡屡红
</div>
{i.type === 1 && <div className={'item-userImg'}></div>}
</div>
))}
</div>
<div className='message-action'>
<Input.TextArea
placeholder={'请输入消息内容'}
maxLength={50}
style={{ width: '60%', marginRight: '15px' }}
showCount
/>
<Button type={'primary'}>发送</Button>
</div>
</div>
);
}
export default MessageBox;
...@@ -2,4 +2,9 @@ ...@@ -2,4 +2,9 @@
.ant-upload-wrapper .ant-upload-list .ant-upload-list-item-container { .ant-upload-wrapper .ant-upload-list .ant-upload-list-item-container {
//width: 200px !important; //width: 200px !important;
} }
.ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item-container, .ant-upload-wrapper.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select {
width: 50px !important;
height: 50px !important;
}
} }
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import { message, Upload, UploadProps } from 'antd'; import { message, Upload, UploadProps } from 'antd';
// import { UploadFile } from "antd/es/upload/interface"; // import { UploadFile } from "antd/es/upload/interface";
import { CommonAPI } from '~/api';
import './index.scss'; import './index.scss';
interface PropsType { interface PropsType {
listType?: 'text' | 'picture' | 'picture-card'; // 上传列表的内建样式 listType?: 'text' | 'picture' | 'picture-card'; // 上传列表的内建样式
fileSize?: number; // 文件大小 fileSize?: number; // 文件大小
fileType?: string[]; // 上传文件类型 fileType?: string[]; // 上传文件类型
fileUpload: boolean; // 是否上传到服务器(返回文件流还是返回上传后的地址)
fileLength?: number; // 最大上传文件数量 fileLength?: number; // 最大上传文件数量
children: React.ReactNode; // 上传按钮 children: React.ReactNode; // 上传按钮
onChange?: (fileList: any[]) => void; // 上传文件改变时的状态 onChange?: (
onRemove?: (fileList: any[]) => void; fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => void; // 上传文件改变时的状态
defaultFileList?: any[]; // 默认文件列表
} }
export const Uploader: React.FC<PropsType> = (props) => { export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = { Uploader.defaultProps = {
...@@ -20,15 +29,25 @@ export const Uploader: React.FC<PropsType> = (props) => { ...@@ -20,15 +29,25 @@ export const Uploader: React.FC<PropsType> = (props) => {
fileType: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'], fileType: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {}, onChange: () => {},
onRemove: () => {}, defaultFileList: [],
}; };
const { fileType, children, listType, fileSize, fileLength, onChange, onRemove } = props; const {
fileType = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'],
children,
listType,
fileSize,
fileUpload,
fileLength,
onChange,
defaultFileList,
} = props;
const [fileList, setFileList] = useState<any[]>([]); const [fileList, setFileList] = useState<any[]>([]);
// 上传文件配置 // 上传文件配置
const uploadProps: UploadProps = { const uploadProps: UploadProps = {
listType, listType,
fileList, fileList,
beforeUpload: (res) => { beforeUpload: (res) => {
// console.log(fileType, res.type);
const isType = fileType?.includes(res.type); const isType = fileType?.includes(res.type);
const isSize = res.size / 1024 / 1024 < (fileSize || 2); const isSize = res.size / 1024 / 1024 < (fileSize || 2);
if (!isType) { if (!isType) {
...@@ -45,21 +64,66 @@ export const Uploader: React.FC<PropsType> = (props) => { ...@@ -45,21 +64,66 @@ export const Uploader: React.FC<PropsType> = (props) => {
message.error(`最多上传${fileLength || 1}个文件`).then(); message.error(`最多上传${fileLength || 1}个文件`).then();
return; return;
} }
setFileList([...fileList, res.file]); if (fileUpload) {
onChange?.([...fileList, res.file]); // 上传到服务器
const formData = new FormData();
formData.append('uploadFile', res.file);
CommonAPI.uploadOss(formData).then(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(val: { result: { filePath: string } }) => {
setFileList([
...fileList,
{
id: new Date().getTime(),
uid: new Date().getTime(),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
name: res.file.name,
url: val.result.filePath,
},
]);
onChange?.([
...fileList,
{
id: new Date().getTime(),
uid: new Date().getTime(),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
name: res.file.name,
url: val.result.filePath,
},
]);
},
);
} else {
setFileList([...fileList, res.file]);
onChange?.([...fileList, res.file]);
}
}, },
onRemove: (res) => { onRemove: (res) => {
const newFileList = fileList.filter((item) => item.uid !== res.uid); const newFileList = fileList.filter((item) => item.uid !== res.uid);
setFileList(newFileList); setFileList(newFileList);
onRemove?.(newFileList);
}, },
// onPreview: { onPreview }, // onPreview: { onPreview },
}; };
useEffect(() => {
// 如果有默认文件列表
if (defaultFileList?.length) {
setFileList(defaultFileList);
}
}, []);
return ( return (
<div className='uploader-view'> <div className='uploader-view'>
<Upload {...uploadProps} style={{ width: '100%' }}> {listType === 'text' ? (
<>{fileList.length < (fileLength || 1) && children}</> <Upload {...uploadProps} style={{ width: '100%' }}>
</Upload> <>{fileList.length < (fileLength || 1) && children}</>
</Upload>
) : (
<Upload {...uploadProps} style={{ width: '100%' }}>
{fileList.length < (fileLength || 1) && children}
</Upload>
)}
</div> </div>
); );
}; };
import { InterListType, InterReqType } from '~/api/interface';
import { listPcWechatOrderType, sendOrderWareType } from '~/api/interface/orderManageType';
import React, { useEffect } from 'react';
import { Col, Form, Input, message, Modal, Radio, Row, Select } from 'antd';
import { Uploader } from '~/components/uploader';
import { PlusOutlined } from '@ant-design/icons';
import { OrderManageAPI } from '~/api';
// 表格数据类型
type TableType = InterListType<listPcWechatOrderType>;
// 请求数据的类型
type ReqType = InterReqType<sendOrderWareType>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const DetailDeliver: React.FC<propType> = (props) => {
DetailDeliver.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 物流列表
const [expressList, setExpressList] = React.useState<{ label: string; value: string }[]>([]);
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
// console.log('确认事件 --->', values);
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await OrderManageAPI.sendOrderWare({
...values,
orderInfoId: Number(data?.id),
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// 获取物流信息
const getListExpressInfo = async () => {
const res = await OrderManageAPI.listExpressInfo({});
if (res && res.code === '200') {
setExpressList(res.result.map((item) => ({ label: item.exName, value: item.exCode })));
// console.log(res);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
if (!data) return;
getListExpressInfo().then();
// console.log('data --->', data);
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={600}
>
<Form
name='addForm'
form={form}
labelAlign='right'
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item label='收货地址' labelCol={{ span: 4 }}>
{data?.receipt?.takeName} {data?.receipt?.takePhone} {data?.receipt?.detailAddress}
</Form.Item>
<Form.Item label='发货方式' labelCol={{ span: 4 }}>
物流发货
</Form.Item>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='物流单号'
name='sendExNo'
rules={[{ required: true, message: '请输入物流单号' }]}
>
<Input placeholder={'请输入物流单号'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='物流公司'
name='sendExCode'
rules={[{ required: true, message: '请选择物流公司' }]}
>
<Select placeholder={'请选择物流公司'} options={expressList} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还联系人'
name='renName'
rules={[{ required: true, message: '请输入归还联系人' }]}
>
<Input placeholder={'请输入归还联系人'} maxLength={20} allowClear />
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='归还电话'
name='renPhone'
rules={[
{ required: true, message: '请输入归还联系人电话' },
// 校验手机号
() => ({
validator(_, value) {
if (!value || /^1[3-9]\d{9}$/.test(value)) {
return Promise.resolve();
}
return Promise.reject('请输入正确的手机号');
},
}),
]}
>
<Input
placeholder={'请输入归还联系人电话'}
maxLength={20}
allowClear
type={'number'}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='归还地址'
name='renAddress'
rules={[{ required: true, message: '请输入归还地址' }]}
>
<Input placeholder={'请输入归还地址'} maxLength={20} allowClear />
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='质检照片'
name='imgs'
rules={[{ required: true, message: '请上传质检照片' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={3}
onChange={(e) => {
form.setFieldValue(
'imgs',
e.map((item) => item.url),
);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='质检视频'
name='videoUrl'
rules={[{ required: true, message: '请上传质检视频' }]}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={10}
onChange={(e) => {
form.setFieldValue('videoUrl', e[0].url);
}}
>
<PlusOutlined />
</Uploader>
</Form.Item>
</Col>
</Row>
<Row gutter={{ xs: 8, sm: 16, md: 24 }}>
<Col span={11}>
<Form.Item
label='设备状态'
name='vcuSatus'
rules={[{ required: true, message: '请选择设备状态' }]}
initialValue={0}
>
<Radio.Group
options={[
{ label: '正常', value: 0 },
{ label: '故障', value: 1 },
]}
onChange={(e) => {
form.setFieldValue('vcuSatus', e.target.value);
}}
/>
</Form.Item>
</Col>
<Col span={11}>
<Form.Item
label='操作密码'
name='authPwd'
rules={[{ required: true, message: '请输入操作密码' }]}
>
<Input.Password
placeholder={'请输入操作密码'}
maxLength={20}
allowClear
autoComplete='new-password'
/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
);
};
export default DetailDeliver;
import MessageBox from '~/components/messageBox';
function DetailMessageBox() {
return (
<div className={'detail-delivery detail-half'}>
<div className={'detail-title'}>订单动态</div>
<MessageBox />
</div>
);
}
export default DetailMessageBox;
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
} }
.detail-half { .detail-half {
width: 50%; flex: 1;
} }
.detail-title { .detail-title {
......
import { useEffect } from 'react'; import { useEffect, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom';
import { Button } from 'antd'; import { Button } from 'antd';
import './index.scss'; import './index.scss';
import DetailDelivery from '~/pages/orderManage/productOrder/comp/detailDelivery'; import DetailDelivery from '~/pages/orderManage/productOrder/comp/detailDelivery';
import DetailPurchaser from '~/pages/orderManage/productOrder/comp/detailPurchaser'; import DetailPurchaser from '~/pages/orderManage/productOrder/comp/detailPurchaser';
import DetailInformation from '~/pages/orderManage/productOrder/comp/detailInformation'; import DetailInformation from '~/pages/orderManage/productOrder/comp/detailInformation';
import { OrderManageAPI } from '~/api';
import { InterDataType } from '~/api/interface';
import { orderDetailType } from '~/api/interface/orderManageType';
// import DetailMessageBox from '~/pages/orderManage/equipmentOrder/comp/detailMessageBox';
// 接口返回的类型
type DataType = InterDataType<orderDetailType>;
function EquipmentOrderDetail() { function EquipmentOrderDetail() {
// 路由钩子 // 路由钩子
...@@ -12,26 +19,38 @@ function EquipmentOrderDetail() { ...@@ -12,26 +19,38 @@ function EquipmentOrderDetail() {
// 参数钩子 // 参数钩子
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
// 接收到的参数 // 接收到的参数
const id = searchParams.get('id'); const orderNo = searchParams.get('orderNo') as string;
// 返回上一页 // 返回上一页
const handleBack = () => { const handleBack = () => {
navigate(-1); navigate(-1);
}; };
// 订单详情
const [orderDetail, setOrderDetail] = useState<DataType>(null!);
// 获取订单详情
const getOrderDetail = async () => {
const res = await OrderManageAPI.orderDetail({
orderNo: orderNo,
});
if (res && res.code === '200') {
setOrderDetail(res.result);
console.log('获取订单详情 --->', res.result);
}
};
// componentDidMount // componentDidMount
useEffect(() => { useEffect(() => {
console.log('拿到的id是 --->', id); getOrderDetail().then();
}, [id]); }, [orderNo]);
return ( return (
<div className={'order-detail'}> <div className={'order-detail'}>
<div className={'order-head'}> <div className={'order-head'}>
<div className='head-text'> <div className='head-text'>
<div> <div>
<span>订单编号:R2023051916330461</span> <span>订单编号:{orderDetail?.orderNo}</span>
<span>合同编号:UAV202334741131</span> <span style={{ display: 'none' }}>合同编号:UAV202334741131</span>
</div> </div>
<div> <div>
<span>当前状态:交易完成</span> <span>当前状态:{orderDetail?.waiting}</span>
<span>创建时间:2023-02-18 10:41:16</span> <span>创建时间:{orderDetail?.createTime}</span>
</div> </div>
</div> </div>
<Button type={'primary'} onClick={() => handleBack()}> <Button type={'primary'} onClick={() => handleBack()}>
...@@ -39,8 +58,9 @@ function EquipmentOrderDetail() { ...@@ -39,8 +58,9 @@ function EquipmentOrderDetail() {
</Button> </Button>
</div> </div>
<div className={'detail-wrap'}> <div className={'detail-wrap'}>
<DetailPurchaser /> <DetailPurchaser detail={orderDetail} />
<DetailDelivery /> <DetailDelivery />
{/*<DetailMessageBox />*/}
<DetailInformation /> <DetailInformation />
</div> </div>
</div> </div>
......
...@@ -5,32 +5,40 @@ import { ColumnsType } from 'antd/es/table'; ...@@ -5,32 +5,40 @@ import { ColumnsType } from 'antd/es/table';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import qs from 'query-string'; import qs from 'query-string';
import { InterListType, InterReqType } from '~/api/interface'; import { InterListType, InterReqType } from '~/api/interface';
import { listOfRentalOrdersType } from '~/api/interface/orderManageType'; import { listPcWechatOrderType } from '~/api/interface/orderManageType';
import { OrderManageAPI } from '~/api'; import { OrderManageAPI } from '~/api';
import DetailDeliver from '~/pages/orderManage/equipmentOrder/comp/detailDeliver';
// 表格数据类型 // 表格数据类型
type TableType = InterListType<listOfRentalOrdersType>; type TableType = InterListType<listPcWechatOrderType>;
// 请求数据的类型 // 请求数据的类型
type ReqType = InterReqType<listOfRentalOrdersType>; type ReqType = InterReqType<listPcWechatOrderType>;
// 搜索表单的数据 // 搜索表单的数据
let query: ReqType = {}; let query: ReqType = {};
// 订单状态
// 订单状态搜索列表 const orderStatus = [
const statusCodeButtonList = [ { value: '100', label: '等待买家付款', button: '关闭订单' },
{ value: -1, label: '全部订单' }, { value: '200', label: '等待卖家发货', button: '去发货' },
{ value: 0, label: '沟通意向' }, { value: '300', label: '待买家收货' },
{ value: 1, label: '签约付款' }, { value: '400', label: '待归还' },
{ value: 2, label: '待发货' }, { value: '500', label: '等待卖家确认', button: '确认收货' },
{ value: 3, label: '待收货' }, { value: '600', label: '交易完成' },
{ value: 4, label: '已完成' }, { value: '700', label: '退款中' },
{ value: 5, label: '已关闭' }, { value: '999', label: '订单关闭' },
{ value: '1000', label: '已取消' },
]; ];
function EquipmentOrderView() { function EquipmentOrderView() {
// 路由钩子 // 路由钩子
const navigate = useNavigate(); const navigate = useNavigate();
// 发货弹窗是否显示
const [deliverVisible, setDeliverVisible] = useState<boolean>(false);
// 当前选择的是第几个按钮 // 当前选择的是第几个按钮
const [statusCodeButtonIndex, setStatusCodeButtonIndex] = useState<number>(0); const [statusCodeButtonIndex, setStatusCodeButtonIndex] = useState<number>(0);
// 订单状态搜索列表
const [tranStatusList, setTranStatusList] = useState<
{ value: string | undefined; label: string }[]
>([]);
// 表格分页配置 // 表格分页配置
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
total: 0, total: 0,
...@@ -40,10 +48,12 @@ function EquipmentOrderView() { ...@@ -40,10 +48,12 @@ function EquipmentOrderView() {
}); });
// 表格数据 // 表格数据
const [tableData, setTableData] = useState<TableType>([]); const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>(); // 用于编辑
// 加载列表 // 加载列表
const getTableList = async (value = {}) => { const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可 // 只需要修改这个地方的接口即可
const res = await OrderManageAPI.listOfRentalOrders({ const res = await OrderManageAPI.listPcWechatOrder({
pageNo: pagination.current, pageNo: pagination.current,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
...value, ...value,
...@@ -58,7 +68,7 @@ function EquipmentOrderView() { ...@@ -58,7 +68,7 @@ function EquipmentOrderView() {
totalPage, totalPage,
}); });
setTableData(list); setTableData(list);
console.log('加载列表 --->', list); // console.log('加载列表 --->', list);
} }
}; };
// 翻页 // 翻页
...@@ -73,17 +83,56 @@ function EquipmentOrderView() { ...@@ -73,17 +83,56 @@ function EquipmentOrderView() {
}; };
// 订单状态筛选 // 订单状态筛选
const statusChangeEvent = (i: number) => { const statusChangeEvent = (i: number) => {
console.log('订单状态筛选 --->', i); if (i === statusCodeButtonIndex) {
setStatusCodeButtonIndex(i); setStatusCodeButtonIndex(0);
} else {
setStatusCodeButtonIndex(i);
}
query = { ...query, tranStatus: tranStatusList[i].value };
getTableList().then();
}; };
// 跳转订单详情 // 跳转订单详情
const handleDetail = (record: TableType[0]) => { const handleDetail = (record: TableType[0]) => {
console.log('跳转订单详情 --->', record.id); const search = { id: record.id, orderNo: record.orderNo };
navigate(`/orderManage/equipmentOrder/detail?${qs.stringify({ id: record.id })}`); navigate(`/orderManage/equipmentOrder/detail?${qs.stringify(search)}`);
};
// 获取订单状态
const getOrderStatus = async () => {
const res = await OrderManageAPI.listTranStatus({});
if (res && res.code === '200') {
const arr = res.result.map((item) => ({ value: item.status, label: item.waiting }));
setTranStatusList([{ value: undefined, label: '全部订单' }, ...arr]);
// console.log('getOrderStatus --->', arr);
}
};
// 是否显示按钮
const showStatusButton = (code: string) => {
return orderStatus
.filter((i) => i.button)
.map((i) => i.value)
.includes(code);
};
// 转化按钮文字
const getStatusButton = (code: string) => {
return orderStatus.filter((i) => i.button).find((i) => i.value === code)?.button || code;
};
// 点击事件
const handleAction = (data: TableType[0]) => {
const { tranStatus } = data;
setEditData(data);
if (tranStatus === '200') {
setDeliverVisible(true);
}
};
// 关闭弹窗
const handleClosed = () => {
setEditData(undefined);
setDeliverVisible(false);
}; };
// componentDidMount // componentDidMount
useEffect(() => { useEffect(() => {
query = {}; query = {};
getOrderStatus().then();
getTableList().then(); getTableList().then();
}, []); }, []);
// 表格结构 // 表格结构
...@@ -132,7 +181,7 @@ function EquipmentOrderView() { ...@@ -132,7 +181,7 @@ function EquipmentOrderView() {
}, },
{ {
title: '订单状态', title: '订单状态',
dataIndex: 'leaseOrderStatus', dataIndex: 'waiting',
align: 'center', align: 'center',
}, },
{ {
...@@ -176,8 +225,18 @@ function EquipmentOrderView() { ...@@ -176,8 +225,18 @@ function EquipmentOrderView() {
dataIndex: 'action', dataIndex: 'action',
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
width: '130px',
render: (_text, record) => ( render: (_text, record) => (
<> <>
{showStatusButton(record?.tranStatus) && (
<Button
type={'link'}
disabled={['999', '1000'].includes(record?.tranStatus)}
onClick={() => handleAction(record)}
>
{getStatusButton(record?.tranStatus)}
</Button>
)}
<Button type={'link'} onClick={() => handleDetail(record)}> <Button type={'link'} onClick={() => handleDetail(record)}>
详情 详情
</Button> </Button>
...@@ -218,13 +277,13 @@ function EquipmentOrderView() { ...@@ -218,13 +277,13 @@ function EquipmentOrderView() {
searchData={onFinish} searchData={onFinish}
sufFixBtn={ sufFixBtn={
<> <>
{statusCodeButtonList?.map((i, j) => { {tranStatusList?.map((i, j) => {
return ( return (
<Button <Button
key={j} key={j}
type={j === statusCodeButtonIndex ? 'primary' : 'default'} type={j === statusCodeButtonIndex ? 'primary' : 'default'}
onClick={() => statusChangeEvent(j)} onClick={() => statusChangeEvent(j)}
style={{ marginTop: '5px' }} style={{ marginTop: '5px', marginBottom: '5px' }}
> >
{i.label} {i.label}
</Button> </Button>
...@@ -250,6 +309,8 @@ function EquipmentOrderView() { ...@@ -250,6 +309,8 @@ function EquipmentOrderView() {
}} }}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }} // rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/> />
{/*发货弹窗*/}
<DetailDeliver open={deliverVisible} title={'发货'} data={editData} closed={handleClosed} />
</> </>
); );
} }
......
...@@ -47,7 +47,9 @@ function DetailInformation() { ...@@ -47,7 +47,9 @@ function DetailInformation() {
<div className={'detail-text'}> <div className={'detail-text'}>
<span className={'item'}>订单编号:UD202302181041156087</span> <span className={'item'}>订单编号:UD202302181041156087</span>
<span className={'item'}>创建时间:2023-02-18 10:41:16</span> <span className={'item'}>创建时间:2023-02-18 10:41:16</span>
<span className={'item'}>合同编号:UAV202334741131</span> <span className={'item'} style={{ display: 'none' }}>
合同编号:UAV202334741131
</span>
</div> </div>
<Table <Table
style={{ margin: '20px auto', width: '90%' }} style={{ margin: '20px auto', width: '90%' }}
......
import React from 'react'; import React from 'react';
import { Button, Image } from 'antd'; import { Button, Image } from 'antd';
import { orderDetailType } from '~/api/interface/orderManageType';
import { InterDataType } from '~/api/interface';
function DetailPurchaser() { // 接口返回的类型
type DataType = InterDataType<orderDetailType>;
// 参数类型
type PropsType = {
detail: DataType;
};
const DetailPurchaser: React.FC<PropsType> = (props) => {
const { detail } = props;
return ( return (
<div className={'detail-purchaser detail-half'}> <div className={'detail-purchaser detail-half'}>
<div className={'detail-title'}>买家信息</div> <div className={'detail-title'}>买家信息</div>
<div className={'detail-text'}>UID: UID4460817</div> <div className={'detail-text'}>UID: {detail?.uid}</div>
<div className={'detail-text'}>企业: 浙江科比特创新科技有限公司</div> <div className={'detail-text'}>企业: 浙江科比特创新科技有限公司</div>
<div className={'detail-text'}>备注: 测试单,不用管</div> <div className={'detail-text'}>备注: {detail?.remark}</div>
<div className={'detail-title'}>合同信息</div> <div style={{ display: 'none' }}>
<div className={'detail-text'}>合同编号: UAV202334741131</div> <div className={'detail-title'}>合同信息</div>
<div className={'detail-text'}>合同状态: 已归档</div> <div className={'detail-text'}>合同编号: UAV202334741131</div>
<div className={'detail-text'}> <div className={'detail-text'}>合同状态: 已归档</div>
合同操作: <div className={'detail-text'}>
<Button type={'link'}>平台签署</Button> 合同操作:
<Button type={'link'}>查看</Button> <Button type={'link'}>平台签署</Button>
<Button type={'link'}>下载</Button> <Button type={'link'}>查看</Button>
<Button type={'link'}>下载</Button>
</div>
</div> </div>
<div className={'detail-title'}>付款凭证</div> <div style={{ display: 'none' }}>
<div className={'detail-text'}>预付款:</div> <div className={'detail-title'}>付款凭证</div>
<div className={'detail-image'}> <div className={'detail-text'}>预付款:</div>
{[ <div className={'detail-image'}>
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', {[
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
].map((i, j) => ( 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
<Image key={j} className={'image'} src={i} alt='付款凭证' /> ].map((i, j) => (
))} <Image key={j} className={'image'} src={i} alt='付款凭证' />
</div> ))}
<div className={'detail-text'}>尾款:</div> </div>
<div className={'detail-image'}> <div className={'detail-text'}>尾款:</div>
{[ <div className={'detail-image'}>
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', {[
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
].map((i, j) => ( 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
<Image key={j} className={'image'} src={i} alt='付款凭证' /> ].map((i, j) => (
))} <Image key={j} className={'image'} src={i} alt='付款凭证' />
</div> ))}
<div className={'detail-text'}>全款:</div> </div>
<div className={'detail-image'}> <div className={'detail-text'}>全款:</div>
{[ <div className={'detail-image'}>
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', {[
'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png', 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
].map((i, j) => ( 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/infrastructure-05-05.png',
<Image key={j} className={'image'} src={i} alt='付款凭证' /> ].map((i, j) => (
))} <Image key={j} className={'image'} src={i} alt='付款凭证' />
))}
</div>
</div> </div>
</div> </div>
); );
} };
export default DetailPurchaser; export default DetailPurchaser;
...@@ -21,7 +21,7 @@ const AddEditModal: React.FC<propType> = (props) => { ...@@ -21,7 +21,7 @@ const AddEditModal: React.FC<propType> = (props) => {
}; };
// 参数 // 参数
const { title, open, closed, data } = props; const { title, open, closed, data } = props;
/// 表单钩子 // 表单钩子
const [form] = Form.useForm<ReqType>(); const [form] = Form.useForm<ReqType>();
// 关闭弹窗 // 关闭弹窗
const handleCancel = () => { const handleCancel = () => {
......
...@@ -11,6 +11,7 @@ export default defineConfig({ ...@@ -11,6 +11,7 @@ export default defineConfig({
host: '0.0.0.0', host: '0.0.0.0',
proxy: { proxy: {
'/api': { '/api': {
// target: 'http://192.168.3.111:8077',后端女
target: 'https://test.iuav.shop', target: 'https://test.iuav.shop',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/api/, ''),
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论