Commit 3f897e55 authored by 前端-黄佳鑫's avatar 前端-黄佳鑫

feat: 完善质检单管理合质检单协调接口接入

parent 4e7a52e1
......@@ -43,7 +43,7 @@ const config: any = {
// layout: {},
esbuild: {},
// 打开msfu会导致样式异常, 无法获得正常的样式变量
// mfsu: {},
mfsu: {},
antd: {},
locale: {
default: 'zh-CN',
......
......@@ -30,7 +30,7 @@ import QualityRoute from './qualityRoute';
// const isDev = process.env.NODE_ENV === 'development'
const isDev = true
const isDev = false
const homeRoute = {
path: `/memberCenter/home`,
name: 'home',
......
......@@ -26,40 +26,54 @@ const Routes = {
},
{
path: '/memberCenter/quality/qualityManage/srm/add',
name: '新增质检单管理(SRM)',
name: '新增质检单(SRM)',
component: '@/pages/quality/qualityManage/srm/add',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/srm/formed',
name: '生成质检单(SRM)',
component: '@/pages/quality/qualityManage/srm/add',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/srm/edit',
name: '编辑质检单管理(SRM)',
name: '编辑质检单(SRM)',
component: '@/pages/quality/qualityManage/srm/add',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/b2b',
name: '新增质检单管理(B2B)',
name: '质检单管理(B2B)',
component: '@/pages/quality/qualityManage/b2b',
},
{
path: '/memberCenter/quality/qualityManage/b2b/preview',
name: '质检单管理(SRM)',
name: '质检单管理详情(B2B)',
component: '@/pages/quality/qualityManage/detail',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/b2b/formed',
name: '生成质检单(B2B)',
component: '@/pages/quality/qualityManage/b2b/add',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/b2b/add',
name: '新增质检单管理(SRM)',
name: '新增质检单管理(B2B)',
component: '@/pages/quality/qualityManage/b2b/add',
hideInMenu: true,
noMargin: true,
},
{
path: '/memberCenter/quality/qualityManage/b2b/edit',
name: '编辑质检单管理(SRM)',
name: '编辑质检单管理(B2B)',
component: '@/pages/quality/qualityManage/b2b/add',
hideInMenu: true,
noMargin: true,
......
/** 详情通用 - 基本信息 */
import React, { Fragment, ReactNode } from 'react';
import { Row, Col } from 'antd';
import { Row, Col, Empty } from 'antd';
import Card from '../card';
import style from './index.less';
......@@ -30,31 +30,34 @@ const GeneralLayout: React.FC<GeneraInfoProps> = (props: any) => {
title={title}
extra={extra}
>
<Row gutter={[8, 8]}>
{effect.length > count && effect.map((item, index) => (
<Col key={`effect_${index + 1}`} span={span}>
{item.col.map((it, idx) => (
<Fragment key={`effect_col_${idx + 1}`}>
{visible ? <>
{it.extra && (
<>
<Row gutter={[8, 8]}>
{effect.length > count && effect.map((item, index) => (
<Col key={`effect_${index + 1}`} span={span}>
{item.col.map((it, idx) => (
<Fragment key={`effect_col_${idx + 1}`}>
{visible ? <>
{it.extra && (
<div className={style.cell}>
{it.label && <h5 className={style.label}>{it.label}: </h5>}
<h5 className={style.content}>{it.extra}</h5>
</div>
)}
</>
:
<div className={style.cell}>
{it.label && <h5 className={style.label}>{it.label}: </h5>}
<h5 className={style.content}>{it.extra}</h5>
</div>
)}
</>
:
<div className={style.cell}>
{it.label && <h5 className={style.label}>{it.label}: </h5>}
<h5 className={style.content}>{it.extra}</h5>
</div>
}
</Fragment>
}
</Fragment>
))}
</Col>
))}
</Row>
))}
</Col>
))}
</Row>
{effect.length === count && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
</>
</Card>
)
}
......
......@@ -11,25 +11,34 @@ const { RangePicker } = DatePicker;
const DateRangePickerUnix = (props) => {
const { value, mutators } = props
const { placeholder, dataSource, ...rest } = props.props["x-component-props"] || {}
const { placeholder, dataSource, showTime = true, format, ...rest } = props.props["x-component-props"] || {}
const handleChange = (dates, dateString) => {
if(dateString.length === 2) {
mutators.change([dateString[0] ? moment(dateString[0]).format('x') : null, dateString[1] ? moment(dateString[1]).format('x') : null]);
if (dateString.length === 2) {
if (format) {
mutators.change([dateString[0] ? moment(dateString[0]).format('YYYY-MM-DD') : null, dateString[1] ? moment(dateString[1]).format('YYYY-MM-DD') : null]);
} else {
mutators.change([dateString[0] ? moment(dateString[0]).format('x') : null, dateString[1] ? moment(dateString[1]).format('x') : null]);
}
}
}
let v = []
if(value.length) {
let startTime = moment(Number(value[0])).format('YYYY-MM-DD HH:mm:ss')
let endTime = moment(Number(value[1])).format('YYYY-MM-DD HH:mm:ss')
v = [moment(startTime, 'YYYY-MM-DD HH:mm:ss'), moment(endTime, 'YYYY-MM-DD HH:mm:ss')]
if (value.length) {
if (format) {
v = [moment(value[0]), moment(value[1])]
} else {
let startTime = moment(Number(value[0])).format('YYYY-MM-DD HH:mm:ss')
let endTime = moment(Number(value[1])).format('YYYY-MM-DD HH:mm:ss')
v = [moment(startTime, 'YYYY-MM-DD HH:mm:ss'), moment(endTime, 'YYYY-MM-DD HH:mm:ss')]
}
}
return (
<RangePicker
showTime={true}
style={{minWidth: 160}}
showTime={showTime}
style={{ minWidth: 160 }}
placeholder={placeholder}
onChange={handleChange}
value={v}
......
......@@ -11,6 +11,7 @@ import { AddedContext } from '@/components/DetailLayout/components/context';
import { getAuth } from '@/utils/auth';
import { getOrderQualityDetail, postOrderQualitySaveOrUpdate } from '@/services/OrderNewV2Api';
import moment from 'moment';
import { isEmpty } from 'lodash';
export const layout: any = {
colon: false,
......@@ -57,19 +58,19 @@ const QualityManageSrmAdded = (props: any) => {
const [dataSource, setDataSource] = useState<any>({});
const [percent, setPercent] = useState<number>(0);
const [loading, setLoading] = useState<boolean>(false);
const [urls, setUrls] = useState<any[]>([]);
/**计算输入框输入了百分之多少 */
const onFieldsChange = () => {
const allValues = form.getFieldsValue();
const values = Object.values(allValues);
console.log(values)
let num = 0;
values.forEach(_item => {
if (_item) {
if (_item && !isEmpty(_item)) {
num += 1
}
})
setPercent(Number(((num / values.length) * 100)))
}
const handleSubmit = () => {
......@@ -125,6 +126,7 @@ const QualityManageSrmAdded = (props: any) => {
return
}
const { data } = res;
setUrls(data?.urls);
setDataSource(data)
form.setFieldsValue({
qualityNo: data?.qualityNo,
......@@ -146,6 +148,22 @@ const QualityManageSrmAdded = (props: any) => {
}
}, [id])
const getEnclosureUrls = (data) => {
setUrls(data)
form.setFieldsValue({
"urls": data
})
}
const removeEnclosureUrls = (index) => {
const files = [...urls];
files.splice(index, 1);
setUrls(files);
form.setFieldsValue({
"urls": files
})
}
return (
<AddedContext.Provider value={{ form, dataSource }}>
<PeripheralLayout
......@@ -177,7 +195,11 @@ const QualityManageSrmAdded = (props: any) => {
<Form form={form} {...layout} onFieldsChange={() => onFieldsChange()}>
<BasicInfo />
<QualityMaterial />
<Attachment />
<Attachment
enclosureUrls={urls || []}
getEnclosureUrls={getEnclosureUrls}
removeEnclosureUrls={removeEnclosureUrls}
/>
</Form>
}
/>
......
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import CardLayout from '@/components/CardLayout';
import { PlusOutlined } from '@ant-design/icons';
import { Button, Form, Input, message, Select, Space, Table } from 'antd';
......@@ -7,51 +7,16 @@ import { AddedContext } from '@/components/DetailLayout/components/context';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import TableModal from '@/pages/transaction/components/tableModal';
import { getProductGoodsGetDoesNotFreezeGoodsList, getProductSelectGetSelectBrand } from '@/services/ProductV2Api';
import { getProductSelectGetSelectBrand } from '@/services/ProductV2Api';
import { useAsyncInitSelect } from '@/formSchema/effects/useAsyncInitSelect';
import { useCustomerCategoriesBusinessEffects } from '@/formSchema/effects/useCustomerCategoriesBusinessEffects';
import { fetchTreeData, useAsyncCascader } from '@/formSchema/effects/useAsyncCascader';
import DetectionDrawer from '../detectionDrawer';
import DetectionDrawer, { DetectionType } from '../../../components/detectionDrawer';
import { isEmpty } from 'lodash';
import { getProductCommodityCommonGetCommodityListBySellerToQuality } from '@/services/ProductV2Api';
import { Item } from '@/components/ButtonTabs';
interface QualityMaterialLayoutProps { }
export type DetectionType = {
index: number,
/** 收货数量 */
receiveCount?: number,
/** 质检单编号 */
qualityNo?: string,
/** 供应商 */
vendorMemberName?: string,
/** 供应商会员id */
vendorMemberId: number,
/** 供应商角色id */
vendorRoleId: number,
/** 送检数量 */
submissionCount: number,
/** 抽样数量 */
samplesCount: number,
/** 让步接收数量 */
concessionToReceiveCount: number,
/** 批次判定 */
batchJudgmentType: string,
/** 允收数量 */
acceptanceCount: number,
/** 拒收数量 */
rejectCount: number,
/** 品类id */
categoryId: number,
/** 检验方式 */
inspectionType?: number,
/** 质检单物料信息不良记录 */
qualityOrderProductBadRecordVOS?: any[],
/** 质检单物料信息检验记录 */
qualityOrderProductTestRecordVOS?: any[],
}
const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any) => {
const { form, dataSource } = useContext(AddedContext);
const [current, setCurrent] = useState<number>(1);
......@@ -59,6 +24,11 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
const [visible, setVisible] = useState<boolean>(false);
const [detectionVisible, setDetectionVisible] = useState<boolean>(false);
const [detection, setDetection] = useState<DetectionType>();
const handleOnShowSizeChange = (current, _size) => {
setCurrent(current)
}
// 当前表格数据的下标
const _index = (index: number) => {
return Number(((current - 1) * 10) + index);
......@@ -146,6 +116,7 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
skuId: _item?.id,
productName: _item?.name,
type: _item?.type,
categoryId: _item?.customerCategoryId,
category: _item?.customerCategoryName,
brand: _item?.brandName,
unit: _item?.unitName,
......@@ -167,6 +138,7 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
skuId: _item?.skuId,
productName: _item?.productName,
type: _item?.type,
categoryId: _item?.categoryId,
category: _item?.category,
brand: _item?.brand,
unit: _item?.unit,
......@@ -520,7 +492,14 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
useEffect(() => {
if (dataSource) {
setDataSource(dataSource?.qualityOrderProductVOS)
setDataSource((dataSource?.qualityOrderProductVOS || []).map(_item => {
return {
..._item,
skuId: Number(_item?.skuId),
qualityOrderProductBadRecordVOS: _item?.qualityOrderProductBadRecordDetailVOS,
qualityOrderProductTestRecordVOS: _item?.qualityOrderProductTestRecordDetailVOS,
}
}))
}
}, [dataSource])
......@@ -553,6 +532,7 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
rowKey={(_record, index) => index}
pagination={{
size: 'small',
onChange: handleOnShowSizeChange
}}
/>
</Space>
......
......@@ -71,7 +71,7 @@ const QualityManageB2BTable: React.FC<{}> = () => {
>
<Button type='link'>提交</Button>
</Popconfirm>
<Button type='link' href={`srm/edit?id=${record?.id}`}>修改</Button>
<Button type='link' href={`b2b/edit?id=${record?.id}`}>修改</Button>
<Popconfirm
title='是否删除!'
okText='是'
......@@ -152,6 +152,8 @@ const QualityManageB2BTable: React.FC<{}> = () => {
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ['质检开始时间', '质检结束时间'],
showTime: false,
format: 'YYYY-MM-DD'
}
},
}
......
......@@ -77,4 +77,5 @@ export const operation: ColumnType<any> = {
title: '操作',
key: 'operation',
dataIndex: 'operation',
width: 165,
}
import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import React, { Fragment, useEffect, useState } from 'react';
import { Button, message, Typography } from 'antd';
import { history, Link, useIntl } from 'umi';
import { ColumnType } from 'antd/lib/table';
......@@ -289,22 +289,30 @@ const QualityManageDetail = (props) => {
]
/** 附件 */
const handleFileEffect = (data: any) => {
setFileEffect([
{
col: [
{
extra: <Typography.Link
style={{ display: 'block', paddingBottom: '8px' }}
href={`/api/contract/contractTemplate/downloadContract?contractName=${'不良品记录.pdf'}&contractUrl=${''}`}
target="_blank"
>
<LinkOutlined />
不良品记录.pdf
</Typography.Link>
},
]
}
])
if (data.urls) {
setFileEffect([
{
col: [
{
extra: <>
{data.urls.map((item: any, index: number) => (
<Typography.Link
style={{ display: 'block', paddingBottom: '8px' }}
key={`link_${index + 1}`}
href={`/api/contract/contractTemplate/downloadContract?contractName=${item.name}&contractUrl=${item.url}`}
target="_blank"
>
<LinkOutlined />
{item.name}
</Typography.Link>
))}
</>
},
]
}
])
}
}
const handleInnerLog = async () => {
......
......@@ -4,7 +4,7 @@ import { ColumnType } from 'antd/lib/table/interface';
import { createTime, digest, endTime, operation, outerStatusName, qualityNo, receiveNo, startTime, qualityTypeName, vendorMemberName } from '../columns';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { Link, history } from 'umi';
import { getOrderQualityGetB2BQualityOrderPage } from '@/services/OrderNewV2Api';
import { getOrderQualityGetQualityOrderPage } from '@/services/OrderNewV2Api';
const QualityManageSearchTable: React.FC<{}> = () => {
......@@ -39,7 +39,7 @@ const QualityManageSearchTable: React.FC<{}> = () => {
},
{
...operation,
render: (_text) => <Link to={'seach/detail'}>售后处理</Link>
render: (_text, record) => <Link to={`seach/detail?id=${record?.id}`}>售后处理</Link>
},
]
......@@ -105,6 +105,8 @@ const QualityManageSearchTable: React.FC<{}> = () => {
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ['质检开始时间', '质检结束时间'],
showTime: false,
format: 'YYYY-MM-DD'
}
},
outerStatus: {
......@@ -128,7 +130,7 @@ const QualityManageSearchTable: React.FC<{}> = () => {
}
}
}}
fetch={getOrderQualityGetB2BQualityOrderPage}
fetch={getOrderQualityGetQualityOrderPage}
/>
)
}
......
......@@ -166,7 +166,7 @@ const QualityManageSrmAdded = (props: any) => {
}
return (
<AddedContext.Provider value={{ form, dataSource }}>
<AddedContext.Provider value={{ form, dataSource, PATH }}>
<PeripheralLayout
hideBreak
detail={props?.route?.name}
......
.detection-drawer {
:global {
.ant-drawer-body {
padding: 16px !important;
}
.ant-space-vertical {
width: 100%;
}
.ant-form-item {
margin-bottom: 0px;
}
.ant-radio-wrapper {
padding: 6px 16px;
border-radius: 4px;
border: 1px solid #F5F6F7;
background-color: #F5F6F7;
margin-right: 16px;
}
.ant-radio-wrapper-checked {
border: 1px solid #00A98F;
background-color: rgba(0, 169, 143, 0.04);
span {
color: #00A98F;
}
}
.ant-table-wrapper {
.ant-form-item {
margin-bottom: 0px;
}
}
.ant-input-number {
width: 100%;
}
}
.info {
span {
display: inline-block;
&:first-child {
color: #91959B;
font-size: 12px;
width: 144px;
}
&:last-child {
color: #303133;
font-size: 12px;
font-weight: 400;
}
}
}
.vertical {
color: #252D37;
font-size: 14px;
position: relative;
padding-left: 8px;
&::after {
content: '';
height: 14px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border-left: 2px solid @main-color;
transform: scaleY(1);
opacity: 1;
transition: transform .15s cubic-bezier(.645, .045, .355, 1), opacity .15s cubic-bezier(.645, .045, .355, 1);
}
}
}
......@@ -11,45 +11,11 @@ import { getProductGoodsGetDoesNotFreezeGoodsList, getProductSelectGetSelectBran
import { useAsyncInitSelect } from '@/formSchema/effects/useAsyncInitSelect';
import { useCustomerCategoriesBusinessEffects } from '@/formSchema/effects/useCustomerCategoriesBusinessEffects';
import { fetchTreeData, useAsyncCascader } from '@/formSchema/effects/useAsyncCascader';
import DetectionDrawer from '../detectionDrawer';
import DetectionDrawer, { DetectionType } from '../../../components/detectionDrawer';
import { isEmpty } from 'lodash';
interface QualityMaterialLayoutProps { }
export type DetectionType = {
index: number,
/** 收货数量 */
receiveCount?: number,
/** 质检单编号 */
qualityNo?: string,
/** 供应商 */
vendorMemberName?: string,
/** 供应商会员id */
vendorMemberId: number,
/** 供应商角色id */
vendorRoleId: number,
/** 送检数量 */
submissionCount: number,
/** 抽样数量 */
samplesCount: number,
/** 让步接收数量 */
concessionToReceiveCount: number,
/** 批次判定 */
batchJudgmentType: string,
/** 允收数量 */
acceptanceCount: number,
/** 拒收数量 */
rejectCount: number,
/** 品类id */
categoryId: number,
/** 检验方式 */
inspectionType?: number,
/** 质检单物料信息不良记录 */
qualityOrderProductBadRecordVOS?: any[],
/** 质检单物料信息检验记录 */
qualityOrderProductTestRecordVOS?: any[],
}
const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any) => {
const { form, dataSource } = useContext(AddedContext);
const [current, setCurrent] = useState<number>(1);
......@@ -57,6 +23,11 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
const [visible, setVisible] = useState<boolean>(false);
const [detectionVisible, setDetectionVisible] = useState<boolean>(false);
const [detection, setDetection] = useState<DetectionType>();
const handleOnShowSizeChange = (current, _size) => {
setCurrent(current)
}
// 当前表格数据的下标
const _index = (index: number) => {
return Number(((current - 1) * 10) + index);
......@@ -522,6 +493,7 @@ const QualityMaterialLayout: React.FC<QualityMaterialLayoutProps> = (props: any)
rowKey={(_record, index) => index}
pagination={{
size: 'small',
onChange: handleOnShowSizeChange
}}
/>
</Space>
......
......@@ -150,6 +150,8 @@ const QualityManageSrmTable: React.FC<{}> = () => {
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ['质检开始时间', '质检结束时间'],
showTime: false,
format: 'YYYY-MM-DD'
}
},
}
......
......@@ -38,8 +38,8 @@ const QualitySynergyDetail = (props) => {
pathname,
} = history.location;
const intl = useIntl()
const [path] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const [pathPci] = useState(pathname.split('/')[pathname.split('/').length - 2]);
const [PATH] = useState(pathname.split('/')[pathname.split('/').length - 1]);
const [PATHPCI] = useState(pathname.split('/')[pathname.split('/').length - 2]);
const [dataSource, setDataSource] = useState<any>();
const [basicEffect, setBasicEffect] = useState<any>([]);
const [fileEffect, setFileEffect] = useState<any>([]);
......@@ -54,7 +54,6 @@ const QualitySynergyDetail = (props) => {
{ id: 3, name: intl.formatMessage({ id: 'purchaseOrder.showDataSourceName3' }) },
])
const [checkedId, setCheckedId] = useState<number>()
console.log(path, pathPci);
/** 获取基本信息 */
const handleBasicEffect = (data: any) => {
......@@ -351,12 +350,24 @@ const QualitySynergyDetail = (props) => {
}
}
const handleInnerLog = async () => {
return new Promise(resolve => {
getOrderQualityCollaborateGetInnerLog({ id: id.toString() }).then((res: any) => {
const data = {
totalCount: res.data?.length,
data: res.data
}
resolve(data)
})
})
}
return (
<PeripheralLayout
detail={props?.route?.name}
tabLink={[
{ title: '基本信息', id: 'basicInfo' },
{ title: (path === 'preview' ? '质检物料' : '质检商品'), id: 'qualityMaterial' },
{ title: (PATHPCI === 'srm' ? '质检物料' : '质检商品'), id: 'qualityMaterial' },
{ title: '附件', id: 'attachment' },
{ title: '流转记录', id: 'recordLyout' }
]}
......@@ -370,12 +381,10 @@ const QualitySynergyDetail = (props) => {
/>
{/* 质检物料 */}
<QualityMaterial
title={(path === 'preview' ? '质检物料' : '质检商品')}
title={(PATHPCI === 'srm' ? '质检物料' : '质检商品')}
anchor='qualityMaterial'
selectedRow={(path === 'preview' ? false : true)}
columns={columns}
fetch={dataSource?.qualityOrderProductVOS}
controllerBtns={path !== 'preview' && controllerBtns}
dataSource={dataSource?.qualityOrderProductVOS || []}
/>
{/* 附件 */}
<Attachment
......@@ -388,8 +397,7 @@ const QualitySynergyDetail = (props) => {
anchor="recordLyout"
title='流转记录'
columns={recordLyoutColumns}
id={Number(id)}
fetch={getOrderQualityCollaborateGetInnerLog}
fetchTableData={handleInnerLog}
/>
{/* 检验记录弹窗 */}
<DetectionDrawer
......
......@@ -11,7 +11,7 @@ const QualitySynergySearchTable: React.FC<{}> = () => {
const columns: ColumnType<any>[] = [
{
...qualityNo,
render: (_text) => <Link to={'seach/preview'}>{_text}</Link>
render: (_text, record) => <Link to={`seach/preview?id=${record?.id}`}>{_text}</Link>
},
{
...digest,
......@@ -101,6 +101,8 @@ const QualitySynergySearchTable: React.FC<{}> = () => {
"x-component": "DateRangePickerUnix",
"x-component-props": {
placeholder: ['质检开始时间', '质检结束时间'],
showTime: false,
format: 'YYYY-MM-DD'
}
},
outerStatus: {
......
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