Commit 4165788f6d566ce28a7dc327dc34ca1650065b37
Merge branch 'master' into cas
Showing
19 changed files
with
266 additions
and
79 deletions
src/pages/performance/EvaDataImport/api.ts
... | ... | @@ -52,3 +52,17 @@ export function evaDataIndApi(): http.PromiseResp<any> { |
52 | 52 | export function saveEvaImportData(params: { key: string }) { |
53 | 53 | return request.get(`${MORAX_HOST}/erp/eval-indicator/save-import`, { params }); |
54 | 54 | } |
55 | + | |
56 | +/** 下载人员模板 | |
57 | + * http://testgate.feewee.cn/morax/erp/eval-indicator/import-detail | |
58 | + */ | |
59 | +export function upLoadStaffApi(): http.PromiseResp<any> { | |
60 | + return request.get(`${MORAX_HOST}/erp/eval-indicator/staff/template-file`, {}); | |
61 | +} | |
62 | + | |
63 | +/** 下载门店模板 | |
64 | + * http://testgate.feewee.cn/morax/erp/eval-indicator/import-detail | |
65 | + */ | |
66 | +export function upLoadShopApi(): http.PromiseResp<any> { | |
67 | + return request.get(`${MORAX_HOST}/erp/eval-indicator/shop/template-file`, {}); | |
68 | +} | ... | ... |
src/pages/performance/EvaDataImport/index.tsx
... | ... | @@ -2,7 +2,8 @@ import React, { useState } from "react"; |
2 | 2 | import { PageHeaderWrapper } from "@ant-design/pro-layout"; |
3 | 3 | import { Button, Card, Table, Row, message, Space, Typography, Divider, Switch, Upload } from "antd"; |
4 | 4 | import usePagination from "@/hooks/usePagination"; |
5 | -import { evaDataListApi } from "./api"; | |
5 | +import useInitial from "@/hooks/useInitail"; | |
6 | +import { evaDataListApi, upLoadStaffApi, upLoadShopApi } from "./api"; | |
6 | 7 | import { UploadOutlined } from "@ant-design/icons"; |
7 | 8 | import type { UploadProps } from "antd"; |
8 | 9 | import { history } from "umi"; |
... | ... | @@ -16,8 +17,12 @@ export default () => { |
16 | 17 | const { loading, list, paginationConfig, setParams, innerParams } = usePagination(evaDataListApi, { |
17 | 18 | pageSize: 10, |
18 | 19 | }); |
20 | + const { data: upLoadStaff, loading: upLoadStaffLoading } = useInitial(upLoadStaffApi, [], {}); | |
21 | + const { data: upLoadShop, loading: upLoadShopLoading } = useInitial(upLoadShopApi, [], {}); | |
19 | 22 | const [fileData, setFileData] = useState({}); |
20 | 23 | const [visible, setVisible] = useState<boolean>(false); |
24 | + console.log("upLoadStaff", upLoadStaff); | |
25 | + console.log("upLoadShop", upLoadShop); | |
21 | 26 | const uploadPerson: UploadProps = { |
22 | 27 | name: "file", |
23 | 28 | action: "/api/morax/erp/eval-indicator/analysis-staff", |
... | ... | @@ -59,21 +64,13 @@ export default () => { |
59 | 64 | <Row style={{ marginBottom: 10 }} justify="space-between"> |
60 | 65 | <Filter setParams={setParams} /> |
61 | 66 | <div> |
62 | - <Button type="default" style={{ marginRight: 10 }}> | |
63 | - <a | |
64 | - href="https://gate.feewee.cn/file/download?fid=74d1d724f9be48baa5921f3782037c3b" | |
65 | - target="_blank" | |
66 | - rel="noreferrer" | |
67 | - > | |
67 | + <Button type="default" style={{ marginRight: 10 }} loading={upLoadStaffLoading}> | |
68 | + <a href={upLoadStaff} target="_blank" rel="noreferrer"> | |
68 | 69 | 下载人员模板 |
69 | 70 | </a> |
70 | 71 | </Button> |
71 | - <Button type="default" style={{ marginRight: 10 }}> | |
72 | - <a | |
73 | - href="https://gate.feewee.cn/file/download?fid=e4eb136962164264a78753bd1d6061f3" | |
74 | - target="_blank" | |
75 | - rel="noreferrer" | |
76 | - > | |
72 | + <Button type="default" style={{ marginRight: 10 }} loading={upLoadShopLoading}> | |
73 | + <a href={upLoadShop} target="_blank" rel="noreferrer"> | |
77 | 74 | 下载门店模板 |
78 | 75 | </a> |
79 | 76 | </Button> |
... | ... | @@ -87,12 +84,7 @@ export default () => { |
87 | 84 | </Upload> |
88 | 85 | </div> |
89 | 86 | </Row> |
90 | - <Table | |
91 | - loading={loading} | |
92 | - rowKey={(row) => `id${row.id}`} | |
93 | - dataSource={list} | |
94 | - pagination={paginationConfig} | |
95 | - > | |
87 | + <Table loading={loading} rowKey={(row) => `id${row.id}`} dataSource={list} pagination={paginationConfig}> | |
96 | 88 | <Column |
97 | 89 | title="导入时间" |
98 | 90 | dataIndex="createTime" | ... | ... |
src/pages/pms/partPlan/CustBuyPlan/subpages/First/components/PartModal.tsx
... | ... | @@ -73,7 +73,7 @@ export default function DetailModal() { |
73 | 73 | align="center" |
74 | 74 | render={r => ( |
75 | 75 | <> |
76 | - <Popconfirm | |
76 | + {/* <Popconfirm | |
77 | 77 | title="确定删除?" |
78 | 78 | onConfirm={() => deletePart(r)} |
79 | 79 | okText="确定" |
... | ... | @@ -81,7 +81,7 @@ export default function DetailModal() { |
81 | 81 | > |
82 | 82 | <a>删除</a> |
83 | 83 | </Popconfirm> |
84 | - <Divider type="vertical" /> | |
84 | + <Divider type="vertical" /> */} | |
85 | 85 | <a onClick={() => onFinish(r)}>完成</a> |
86 | 86 | </> |
87 | 87 | )} | ... | ... |
src/pages/pms/partPlan/PlanManage/api.ts
src/pages/pms/partPlan/PlanManage/components/DetailModal.tsx
... | ... | @@ -6,7 +6,7 @@ import ProgressView from "./ProgressView"; |
6 | 6 | import ShippingDetailModal from './ShippingDetailModal'; |
7 | 7 | import PartDetailModal from './PartDetailModal'; |
8 | 8 | import {flattenDeep} from "@/pages/pms/entity"; |
9 | -import {getDetail, DetailVO} from "@/pages/pms/partPlan/PlanManage/subpages/Detail/api"; | |
9 | +import {getDetail, DetailVO, Item} from "@/pages/pms/partPlan/PlanManage/subpages/Detail/api"; | |
10 | 10 | |
11 | 11 | interface Props { |
12 | 12 | visible: boolean, |
... | ... | @@ -22,12 +22,12 @@ export default function DetailModal(props: Props) { |
22 | 22 | // @ts-ignore |
23 | 23 | const { data: progresss, setParams: setProgresssParams } = useInitial<ProgressVO[], Params>(getProgressDetail, [], params, delay); |
24 | 24 | // @ts-ignore |
25 | - const { data, setParams, loading } = useInitial<DetailVO[], Params>(getDetail, [], params, delay); | |
25 | + const { data, setParams, loading } = useInitial<Item, Params>(getDetail, {}, params, delay); | |
26 | 26 | const [visibleDetail, setVisibleDetail] = useState(false); |
27 | 27 | const [_item, setItem] = useState<SubmitListVO>({}); |
28 | 28 | const [visiblePartDetail, setVisiblePartDetail] = useState(false); |
29 | 29 | const suppliers = useMemo(() => { |
30 | - return flattenDeep(data.map((it: DetailVO) => (it.suppliers || []).map(su => ({...it, ...su})))); | |
30 | + return flattenDeep(data.list?.map((it: DetailVO) => (it.suppliers || []).map(su => ({...it, ...su})))); | |
31 | 31 | }, [data]); |
32 | 32 | |
33 | 33 | useEffect(() => { | ... | ... |
src/pages/pms/partPlan/PlanManage/subpages/Apply/index.tsx
1 | -import {Card, ConfigProvider, Select, Button, message, Popconfirm} from 'antd'; | |
1 | +import {Card, ConfigProvider, Select, Button, message, Popconfirm, Input} from 'antd'; | |
2 | 2 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
3 | 3 | import React, {useEffect, useState} from "react"; |
4 | 4 | import DealerModal from './components/DealerModal'; |
... | ... | @@ -15,7 +15,8 @@ import PartModal from "@/pages/pms/partPlan/PlanManage/subpages/Apply/components |
15 | 15 | import {groupBys, flattenDeep} from '@/pages/pms/entity'; |
16 | 16 | import {PartDetail} from '../../api'; |
17 | 17 | import { history } from 'umi'; |
18 | -import { getDetail, DetailVO, Params as detailParams } from '../Detail/api'; | |
18 | +import { getDetail, Params as detailParams, Item } from '../Detail/api'; | |
19 | +import ImageUpload from '@/pages/decoration/deco/DeoGoodsManagement/components/ImageUpload'; | |
19 | 20 | |
20 | 21 | const { Option } = Select; |
21 | 22 | const apiObj: { [key: number]: any } = { |
... | ... | @@ -25,7 +26,7 @@ const apiObj: { [key: number]: any } = { |
25 | 26 | export default function Index() { |
26 | 27 | const planId = history.location.query; |
27 | 28 | const [detaildelay, setDetaildelay] = useState(true); |
28 | - const { data, setParams: detailsetParams } = useInitial<DetailVO[], detailParams>(getDetail, [], { ...planId }, detaildelay); | |
29 | + const { data, setParams: detailsetParams } = useInitial<Item, detailParams>(getDetail, {}, { ...planId }, detaildelay); | |
29 | 30 | const [delay, setDelay] = useState<boolean>(true); |
30 | 31 | const [loading, setLoading] = useState<boolean>(false); |
31 | 32 | const { data: brands } = useInitial(API.getBrandFilterApi, [], {}); |
... | ... | @@ -39,6 +40,8 @@ export default function Index() { |
39 | 40 | const [visiblePartDetail, setVisiblePartDetail] = useState(false); |
40 | 41 | const partList = flattenDeep(dealerList.map(it => (it.suppliers || []).map((su: any) => (su.storages || []).map((st: any) => (st.parts || []))))); |
41 | 42 | const poolIds = partList.map((it: any) => it.poolId); |
43 | + const [imageVisible, setImageVisible] = useState(true); | |
44 | + const [info, setInfo] = useState<{ remark?: string, fids?: any }>(); | |
42 | 45 | |
43 | 46 | useEffect(() => { |
44 | 47 | if (planId?.planId) { |
... | ... | @@ -48,13 +51,15 @@ export default function Index() { |
48 | 51 | }, []); |
49 | 52 | |
50 | 53 | useEffect(() => { |
51 | - if (data.length) { | |
52 | - setDfParams({brandId: data[0].brandId}); | |
54 | + if (data.list?.length) { | |
55 | + setImageVisible(false); | |
56 | + setDfParams({brandId: data.list[0].brandId}); | |
53 | 57 | setParams({}, true); |
54 | 58 | setDelay(false); |
55 | - setDealerList(data); | |
59 | + setDealerList(data.list); | |
60 | + setInfo({ remark: data.remark, fids: data.fids?.split(',').map(i => `/api/file/show?fid=${i}`) }); | |
56 | 61 | } |
57 | - }, [data.length]); | |
62 | + }, [data.list?.length]); | |
58 | 63 | |
59 | 64 | function onOk(parts: ListVO[] = []) { |
60 | 65 | setDealerList(dealerList.map(it => { |
... | ... | @@ -173,14 +178,15 @@ export default function Index() { |
173 | 178 | apiObj[type]({ |
174 | 179 | planId: Number(planId?.planId), |
175 | 180 | ...dfParams, |
176 | - suppliers | |
177 | - // suppliers: suppliers.map(i => ({ | |
178 | - // settleDealerId: i.settleDealerId, | |
179 | - // settleDealerName: i.settleDealerName, | |
180 | - // supplierId: i.supplierId, | |
181 | - // supplierName: i.supplierName, | |
182 | - // storages: i.storages | |
183 | - // })) | |
181 | + suppliers, | |
182 | + remark: info?.remark, | |
183 | + fids: info?.fids.map((i: any) => { | |
184 | + if (typeof i == 'object') { | |
185 | + return i.url.split('=')[1]; | |
186 | + } else { | |
187 | + return i; | |
188 | + } | |
189 | + }).join() | |
184 | 190 | }).then(() => { |
185 | 191 | setLoading(false); |
186 | 192 | history.goBack(); |
... | ... | @@ -332,12 +338,28 @@ export default function Index() { |
332 | 338 | deletePart={deletePart} |
333 | 339 | /> |
334 | 340 | </div> |
341 | + <div style={{display: 'flex', alignItems: 'flex-start', marginBottom: 20}}> | |
342 | + <span style={{marginRight: 10}}>备注:</span> | |
343 | + <Input.TextArea rows={2} style={{ width: 250 }} value={info?.remark} onChange={e => setInfo({...info, remark: e.target.value})} /> | |
344 | + </div> | |
345 | + <div style={{ display: 'flex', alignItems: 'flex-start' }}> | |
346 | + <span style={{ marginRight: 10 }}>附件:</span> | |
347 | + <ImageUpload | |
348 | + length={6} | |
349 | + clear={imageVisible} | |
350 | + value={info?.fids} | |
351 | + onChange={v => { | |
352 | + const ids = v.fileList.map(it => it?.response?.data || it); | |
353 | + setInfo({ ...info, fids: ids }); | |
354 | + }} | |
355 | + /> | |
356 | + </div> | |
335 | 357 | <div style={{display: 'flex', justifyContent: 'center'}}> |
336 | 358 | <Button |
337 | 359 | disabled={loading} |
338 | 360 | loading={loading} |
339 | 361 | style={{marginRight: 20}} |
340 | - onClick={() => history.goBack()} | |
362 | + onClick={() => { setImageVisible(true); history.goBack(); }} | |
341 | 363 | > |
342 | 364 | 取消 |
343 | 365 | </Button> |
... | ... | @@ -359,7 +381,6 @@ export default function Index() { |
359 | 381 | 确认并提交 |
360 | 382 | </Button> |
361 | 383 | </div> |
362 | - | |
363 | 384 | </Card> |
364 | 385 | </ConfigProvider> |
365 | 386 | </PageHeaderWrapper> | ... | ... |
src/pages/pms/partPlan/PlanManage/subpages/Detail/api.ts
... | ... | @@ -48,9 +48,55 @@ export interface Params { |
48 | 48 | planNo?: string; |
49 | 49 | no?: string; |
50 | 50 | } |
51 | +export interface Item { | |
52 | + /** | |
53 | + * 计划单号 | |
54 | + */ | |
55 | + planNo?: string; | |
56 | + /** | |
57 | + * 品牌ID | |
58 | + */ | |
59 | + brandId?: number; | |
60 | + /** | |
61 | + * 计划日期 | |
62 | + */ | |
63 | + planDate?: string; | |
64 | + /** | |
65 | + * 审核单号 | |
66 | + */ | |
67 | + approvalOrderNo?: string; | |
68 | + /** | |
69 | + * 计划人员 | |
70 | + */ | |
71 | + userName?: string; | |
72 | + /** | |
73 | + * 库销比 | |
74 | + */ | |
75 | + ratio?: number; | |
76 | + /** | |
77 | + * 计划库销比 | |
78 | + */ | |
79 | + planRatio?: number; | |
80 | + /** | |
81 | + * 计划状态 1:待审核2:已通过9:已拒绝 | |
82 | + */ | |
83 | + status?: string; | |
84 | + /** | |
85 | + * 备注 | |
86 | + */ | |
87 | + remark?: string; | |
88 | + /** | |
89 | + * 附件 | |
90 | + */ | |
91 | + fids?: string; | |
92 | + /** | |
93 | + * 计划列表 | |
94 | + */ | |
95 | + list?: DetailVO[]; | |
96 | +} | |
51 | 97 | /** |
52 | 98 | * 查询明细 |
53 | 99 | */ |
54 | -export function getDetail(params?: Params): http.PromiseResp<DetailVO[]> { | |
100 | +export function getDetail(params?: Params): http.PromiseResp<Item> { | |
55 | 101 | return request.get(`${PMS_HOST}/erp/part/plan/get/plan/group/detail`, { params }); |
56 | 102 | } | ... | ... |
src/pages/pms/partPlan/PlanManage/subpages/Detail/index.tsx
1 | -import {Card, ConfigProvider, Spin} from 'antd'; | |
1 | +import { Card, ConfigProvider, Spin, Upload } from 'antd'; | |
2 | 2 | import { PageHeaderWrapper } from '@ant-design/pro-layout'; |
3 | 3 | import React, {useState} from "react"; |
4 | 4 | import useInitial from "@/hooks/useInitail"; |
5 | -import {getDetail, DetailVO, Params, SupplierVO, StorageVO, PartVO} from "./api"; | |
5 | +import { getDetail, Item, Params, SupplierVO, StorageVO, PartVO, DetailVO } from "./api"; | |
6 | 6 | import zhCN from "antd/lib/locale-provider/zh_CN"; |
7 | 7 | import st from "@/pages/pms/partPlan/PlanManage/style.less"; |
8 | 8 | import StepBnt from "@/pages/pms/comonents/StepBnt"; |
... | ... | @@ -14,7 +14,7 @@ import PartDetailModal from './components/PartDetailModal'; |
14 | 14 | |
15 | 15 | export default function Index({ match }: common.ConnectProps) { |
16 | 16 | const { planId } = match.params; |
17 | - const { data, loading } = useInitial<DetailVO[], Params>(getDetail, [], {planId}); | |
17 | + const { data, loading } = useInitial<Item, Params>(getDetail, {}, {planId}); | |
18 | 18 | const [visiblePart, setVisiblePart] = useState(false); |
19 | 19 | const [parts, setParts] = useState<PartVO[]>([]); |
20 | 20 | |
... | ... | @@ -23,7 +23,7 @@ export default function Index({ match }: common.ConnectProps) { |
23 | 23 | <Spin spinning={loading}> |
24 | 24 | <ConfigProvider locale={zhCN}> |
25 | 25 | <Card className={st.page}> |
26 | - {data.map((dealer: DetailVO = {}) => ( | |
26 | + {data.list?.map((dealer: DetailVO = {}) => ( | |
27 | 27 | <div key={`dealer${dealer.settleDealerName}`} style={{ marginTop: 10 }}> |
28 | 28 | <div style={{ fontWeight: "bold" }}>{`商家: ${dealer.settleDealerName || ''}`}</div> |
29 | 29 | {(dealer.suppliers || []).map((supplier: SupplierVO = {}) => { |
... | ... | @@ -57,6 +57,26 @@ export default function Index({ match }: common.ConnectProps) { |
57 | 57 | })} |
58 | 58 | </div> |
59 | 59 | ))} |
60 | + <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 20 }}> | |
61 | + <span style={{ marginRight: 10 }}>备注:{data.remark}</span> | |
62 | + </div> | |
63 | + <div style={{ display: 'flex', alignItems: 'flex-start' }}> | |
64 | + <span style={{ marginRight: 10 }}>附件:</span> | |
65 | + <div style={{display: 'flex'}}> | |
66 | + {data.fids?.split(',').map(i => ( | |
67 | + <Upload | |
68 | + listType="picture-card" | |
69 | + fileList={[{ | |
70 | + uid: '-1', | |
71 | + name: i, | |
72 | + status: 'done', | |
73 | + url: `/api/file/show?fid=${i}`, | |
74 | + }]} | |
75 | + disabled | |
76 | + /> | |
77 | + ))} | |
78 | + </div> | |
79 | + </div> | |
60 | 80 | <PartDetailModal visible={visiblePart} onCancel={() => setVisiblePart(false)} parts={parts} /> |
61 | 81 | <StepBnt |
62 | 82 | disable={false} | ... | ... |
src/pages/pms/partPlan/PlanPool/api.ts
... | ... | @@ -118,7 +118,24 @@ outTime?:string; |
118 | 118 | */ |
119 | 119 | typeName?:string; |
120 | 120 | } |
121 | - | |
121 | +export interface outListVO { | |
122 | + /** | |
123 | + * 时间段 | |
124 | + */ | |
125 | + date?: string; | |
126 | + /** | |
127 | + * 出库数量 | |
128 | + */ | |
129 | + outCnt?: number; | |
130 | + /** | |
131 | + * 最小时间 | |
132 | + */ | |
133 | + min?: string; | |
134 | + /** | |
135 | + * 最大时间 | |
136 | + */ | |
137 | + max?: string; | |
138 | +} | |
122 | 139 | /** |
123 | 140 | * 查询计划池列表 |
124 | 141 | */ |
... | ... | @@ -134,10 +151,14 @@ export function editApi(params: { poolId?: number, partCnt?: number}) { |
134 | 151 | return request.post(`${PMS_HOST}/erp/plan/pool/update/plan`, {...params}); |
135 | 152 | } |
136 | 153 | |
137 | -export function outFlowApi(params: { poolIds?: any, planId?: number, current?: number, pageSize?:number}):http.PromisePageResp<OutItem> { | |
154 | +export function outFlowApi(params: { poolIds?: any, planId?: number}):http.PromiseResp<outListVO[]> { | |
138 | 155 | return request.get(`${PMS_HOST}/erp/storage/out/list`, {params}); |
139 | 156 | } |
140 | 157 | |
158 | +export function outFlowDetailApi(params:any):http.PromiseResp<OutItem[]> { | |
159 | + return request.get(`${PMS_HOST}/erp/storage/out/detail`, {params}); | |
160 | +} | |
161 | + | |
141 | 162 | export function custBuyApi(params: { planWaitListIds?: any}):http.PromiseResp<PartVO[]> { |
142 | 163 | return request.get(`${PMS_HOST}/erp/cus/buy/part/get/buy/part/list`, {params}); |
143 | 164 | } | ... | ... |
src/pages/pms/partPlan/PlanPool/components/AreaTable.tsx
... | ... | @@ -4,6 +4,7 @@ import useInitial from "@/hooks/useInitail"; |
4 | 4 | import {getList, ListVO} from "@/pages/pms/partPlan/PlanPool/api"; |
5 | 5 | import DetailModal from './DetailModal'; |
6 | 6 | import {useStore} from "@/pages/pms/partPlan/PlanPool"; |
7 | +import _ from 'lodash'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | interface Props { |
... | ... | @@ -33,8 +34,8 @@ export default function Index(props: Props = {}) { |
33 | 34 | <Table rowKey={(v: ListVO) => `${v.id}`} scroll={{y: 500, x: 2500}} dataSource={parts || []} pagination={false} loading={loading}> |
34 | 35 | <Column title="区域库" dataIndex="name" fixed="left" /> |
35 | 36 | <Column title="本次计划数量(个)" dataIndex="cnt" fixed="left" /> |
36 | - <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} /> | |
37 | - <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} /> | |
37 | + <Column title="计划前库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : "--")} /> | |
38 | + <Column title="计划后库销比" dataIndex="planRatio" render={t => (t ? t.toFixed(2) : "--")} /> | |
38 | 39 | <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" /> |
39 | 40 | <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} /> |
40 | 41 | <Column title="客户订件金额(元)" dataIndex="buyAmount" /> |
... | ... | @@ -42,7 +43,7 @@ export default function Index(props: Props = {}) { |
42 | 43 | |
43 | 44 | <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" /> |
44 | 45 | <Column title="在库已锁(个)" dataIndex="storageLockedCnt" /> |
45 | - <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} /> | |
46 | + <Column title="近90天月均出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{_.floor(r.outStockCnt/3)}</a> : r.outStockCnt)} /> | |
46 | 47 | {showAnalyse && ( |
47 | 48 | <> |
48 | 49 | <Column | ... | ... |
src/pages/pms/partPlan/PlanPool/components/OutFlowDetailModal.tsx
0 → 100644
1 | +import React, { useEffect, useState } from 'react'; | |
2 | +import { Button, Modal, Table } from 'antd'; | |
3 | +import { outFlowDetailApi, OutItem } from '../api'; | |
4 | +import useInitial from '@/hooks/useInitail'; | |
5 | +import moment from 'moment'; | |
6 | + | |
7 | +const { Column } = Table; | |
8 | +interface Props { | |
9 | + visible?:boolean | |
10 | + setVisible:Function | |
11 | + item?:any | |
12 | +} | |
13 | +export default function Index(props:Props) { | |
14 | + const { visible, setVisible, item } = props; | |
15 | + const [delay, setDelay] = useState(true); | |
16 | + const { data, setParams, loading } = useInitial(outFlowDetailApi, [], {}, delay); | |
17 | + | |
18 | + useEffect(() => { | |
19 | + if (visible && item?.poolIds) { | |
20 | + setParams({ min: undefined, max: undefined, date: undefined, outCnt: undefined, ...item }, true); | |
21 | + setDelay(false); | |
22 | + } else { | |
23 | + setVisible(); | |
24 | + } | |
25 | + }, [visible]); | |
26 | + | |
27 | + return ( | |
28 | + <Modal | |
29 | + title="出库详情" | |
30 | + width={1000} | |
31 | + visible={visible} | |
32 | + maskClosable={false} | |
33 | + onCancel={() => setVisible()} | |
34 | + footer={[ | |
35 | + <Button onClick={() => setVisible()}>取消</Button> | |
36 | + ]} | |
37 | + > | |
38 | + <Table | |
39 | + dataSource={data} | |
40 | + loading={loading} | |
41 | + rowKey={(v: OutItem) => `${v.partId}`} | |
42 | + pagination={false} | |
43 | + scroll={{ y: 400 }} | |
44 | + > | |
45 | + <Column title="配件名称" dataIndex="partName" /> | |
46 | + <Column title="配件编码" dataIndex="partCode" /> | |
47 | + <Column title="出库数量" dataIndex="partCnt" /> | |
48 | + <Column title="出库类型" dataIndex="typeName" /> | |
49 | + <Column title="服务站名称" dataIndex="shopName" /> | |
50 | + <Column title="出库时间" render={r => moment(r.outTime).format('YYYY-MM-DD HH:mm:ss')} /> | |
51 | + </Table> | |
52 | + </Modal> | |
53 | + ); | |
54 | +} | |
0 | 55 | \ No newline at end of file | ... | ... |
src/pages/pms/partPlan/PlanPool/components/OutFlowModal.tsx
1 | 1 | import React, { useEffect, useState } from 'react'; |
2 | 2 | import {Button, Modal, Table} from 'antd'; |
3 | 3 | import {useStore} from '../index'; |
4 | -import { outFlowApi, OutItem } from '../api'; | |
5 | -import usePagination from '@/hooks/usePagination'; | |
4 | +import { outFlowApi, outListVO } from '../api'; | |
5 | +import useInitial from '@/hooks/useInitail'; | |
6 | +import OutFlowDetailModal from './OutFlowDetailModal'; | |
6 | 7 | |
7 | 8 | const {Column} = Table; |
8 | 9 | |
9 | 10 | export default function Index() { |
10 | 11 | const {outVisible, setOutVisible, item} = useStore(); |
11 | 12 | const [delay, setDelay]= useState(true); |
12 | - const { list, setParams, loading, paginationConfig } = usePagination(outFlowApi, [], {delay}); | |
13 | + const { data, setParams, loading } = useInitial(outFlowApi, [], {}, delay); | |
14 | + const [current, setCurrent] = useState<{visible?: boolean, itemData?: any}>(); | |
13 | 15 | |
14 | 16 | useEffect(() => { |
15 | 17 | if (outVisible && item?.poolIds) { |
... | ... | @@ -17,6 +19,11 @@ export default function Index() { |
17 | 19 | setDelay(false); |
18 | 20 | } |
19 | 21 | }, [outVisible]); |
22 | + const total = data | |
23 | + .map(i => i.outCnt) | |
24 | + .reduce((prev, cur) => { | |
25 | + return (prev || 0) + (cur || 0); | |
26 | + }, 0); | |
20 | 27 | |
21 | 28 | return ( |
22 | 29 | <Modal |
... | ... | @@ -29,19 +36,26 @@ export default function Index() { |
29 | 36 | <Button onClick={() => setOutVisible(false)}>取消</Button> |
30 | 37 | ]} |
31 | 38 | > |
39 | + <div style={{marginBottom: 20}}> | |
40 | + 滚动90天出库数: | |
41 | + <span | |
42 | + style={{ color: '#0000FF', cursor: 'pointer' }} | |
43 | + onClick={() => setCurrent({ visible: true, itemData: { poolIds: item?.poolIds } })} | |
44 | + > | |
45 | + {total} | |
46 | + </span> | |
47 | + </div> | |
32 | 48 | <Table |
33 | - dataSource={list} | |
49 | + dataSource={data} | |
34 | 50 | loading={loading} |
35 | - pagination={paginationConfig} | |
36 | - rowKey={(v: OutItem) => `${v.partId}`} | |
51 | + rowKey={(v: outListVO) => `${v.date}`} | |
52 | + pagination={false} | |
53 | + scroll={{y: 400}} | |
37 | 54 | > |
38 | - <Column title="配件编码" dataIndex="partCode" /> | |
39 | - <Column title="配件名称" dataIndex="partName" /> | |
40 | - <Column title="出库数量" dataIndex="partCnt" /> | |
41 | - <Column title="出库类型" dataIndex="typeName" /> | |
42 | - <Column title="服务站名称" dataIndex="shopName" /> | |
43 | - <Column title="出库时间" dataIndex="outTime" /> | |
55 | + <Column title="出库日期" dataIndex="date" /> | |
56 | + <Column title="出库数量" render={r => <a onClick={() => setCurrent({ visible: true, itemData: { ...r, poolIds: item?.poolIds }})}>{r.outCnt}</a>} /> | |
44 | 57 | </Table> |
58 | + <OutFlowDetailModal visible={current?.visible} setVisible={() => setCurrent({visible: false, itemData: undefined})} item={current?.itemData} /> | |
45 | 59 | </Modal> |
46 | 60 | ); |
47 | 61 | } |
48 | 62 | \ No newline at end of file | ... | ... |
src/pages/pms/partPlan/PlanPool/components/PartTable.tsx
... | ... | @@ -4,6 +4,7 @@ import useInitial from "@/hooks/useInitail"; |
4 | 4 | import {getList, ListVO} from "@/pages/pms/partPlan/PlanPool/api"; |
5 | 5 | import DetailModal from './DetailModal'; |
6 | 6 | import {useStore} from "@/pages/pms/partPlan/PlanPool"; |
7 | +import _ from 'lodash'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | interface Props { |
... | ... | @@ -39,8 +40,8 @@ export default function Index(props: Props = {}) { |
39 | 40 | <Column title="来源类型" dataIndex="typeName" /> |
40 | 41 | <Column title="配件类型" dataIndex="partTypeName" /> |
41 | 42 | |
42 | - <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} /> | |
43 | - <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} /> | |
43 | + <Column title="计划前库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : "--")} /> | |
44 | + <Column title="计划后库销比" dataIndex="planRatio" render={t => (t ? t.toFixed(2) : "--")} /> | |
44 | 45 | |
45 | 46 | <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" /> |
46 | 47 | <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} /> |
... | ... | @@ -49,7 +50,7 @@ export default function Index(props: Props = {}) { |
49 | 50 | |
50 | 51 | <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" /> |
51 | 52 | <Column title="在库已锁(个)" dataIndex="storageLockedCnt" /> |
52 | - <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} /> | |
53 | + <Column title="近90天月均出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{_.floor(r.outStockCnt/3)}</a> : r.outStockCnt)} /> | |
53 | 54 | {showAnalyse && ( |
54 | 55 | <> |
55 | 56 | <Column | ... | ... |
src/pages/pms/partPlan/PlanPool/components/SeriesTable.tsx
... | ... | @@ -4,6 +4,7 @@ import useInitial from "@/hooks/useInitail"; |
4 | 4 | import {getList, ListVO} from "@/pages/pms/partPlan/PlanPool/api"; |
5 | 5 | import DetailModal from './DetailModal'; |
6 | 6 | import {useStore} from "@/pages/pms/partPlan/PlanPool"; |
7 | +import _ from 'lodash'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | interface Props { |
... | ... | @@ -34,8 +35,8 @@ export default function Index(props: Props = {}) { |
34 | 35 | <Table rowKey={(v: ListVO) => `${v.id}`} scroll={{y: 500, x: 2500}} dataSource={parts || []} pagination={false} loading={loading}> |
35 | 36 | <Column title="车系" dataIndex="name" fixed="left" /> |
36 | 37 | <Column title="本次计划数量(个)" dataIndex="cnt" fixed="left" /> |
37 | - <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} /> | |
38 | - <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} /> | |
38 | + <Column title="计划前库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : "--")} /> | |
39 | + <Column title="计划后库销比" dataIndex="planRatio" render={t => (t ? t.toFixed(2) : "--")} /> | |
39 | 40 | |
40 | 41 | <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" /> |
41 | 42 | <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} /> |
... | ... | @@ -44,7 +45,7 @@ export default function Index(props: Props = {}) { |
44 | 45 | |
45 | 46 | <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" /> |
46 | 47 | <Column title="在库已锁(个)" dataIndex="storageLockedCnt" /> |
47 | - <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} /> | |
48 | + <Column title="近90天月均出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{_.floor(r.outStockCnt/3)}</a> : r.outStockCnt)} /> | |
48 | 49 | {showAnalyse && ( |
49 | 50 | <> |
50 | 51 | <Column | ... | ... |
src/pages/pms/partPlan/PlanPool/components/StoragePartTable.tsx
... | ... | @@ -4,6 +4,7 @@ import useInitial from "@/hooks/useInitail"; |
4 | 4 | import {getList, ListVO} from "@/pages/pms/partPlan/PlanPool/api"; |
5 | 5 | import {useStore} from "@/pages/pms/partPlan/PlanPool"; |
6 | 6 | import {deleteApi, editApi} from '../api'; |
7 | +import _ from 'lodash'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | const {Item} = Form; |
... | ... | @@ -64,8 +65,8 @@ export default function Index(props: Props = {}) { |
64 | 65 | <Column title="来源类型" dataIndex="typeName" /> |
65 | 66 | <Column title="配件类型" dataIndex="partTypeName" /> |
66 | 67 | |
67 | - <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} /> | |
68 | - <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} /> | |
68 | + <Column title="计划前库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : "--")} /> | |
69 | + <Column title="计划后库销比" dataIndex="planRatio" render={t => (t ? t.toFixed(2) : "--")} /> | |
69 | 70 | |
70 | 71 | <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" /> |
71 | 72 | <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} /> |
... | ... | @@ -73,7 +74,7 @@ export default function Index(props: Props = {}) { |
73 | 74 | <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" /> |
74 | 75 | <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" /> |
75 | 76 | <Column title="在库已锁(个)" dataIndex="storageLockedCnt" /> |
76 | - <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} /> | |
77 | + <Column title="近90天月均出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{_.floor(r.outStockCnt/3)}</a> : r.outStockCnt)} /> | |
77 | 78 | |
78 | 79 | </Table> |
79 | 80 | <Modal | ... | ... |
src/pages/pms/partPlan/PlanPool/components/StorageTable.tsx
... | ... | @@ -4,6 +4,7 @@ import useInitial from "@/hooks/useInitail"; |
4 | 4 | import {getList, ListVO} from "@/pages/pms/partPlan/PlanPool/api"; |
5 | 5 | import DetailModal from './DetailModal'; |
6 | 6 | import {useStore} from "@/pages/pms/partPlan/PlanPool"; |
7 | +import {floor} from 'lodash'; | |
7 | 8 | |
8 | 9 | const { Column } = Table; |
9 | 10 | interface Props { |
... | ... | @@ -33,8 +34,8 @@ export default function Index(props: Props = {}) { |
33 | 34 | <Table rowKey={(v: ListVO) => `${v.id}`} scroll={{y: 500, x: 2500}} dataSource={parts || []} pagination={false} loading={loading}> |
34 | 35 | <Column title="库房" dataIndex="name" fixed="left" /> |
35 | 36 | <Column title="本次计划数量(个)" dataIndex="cnt" fixed="left" /> |
36 | - <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} /> | |
37 | - <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} /> | |
37 | + <Column title="计划前库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : "--")} /> | |
38 | + <Column title="计划后库销比" dataIndex="planRatio" render={t => (t ? t.toFixed(2) : "--")} /> | |
38 | 39 | |
39 | 40 | <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" /> |
40 | 41 | <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} /> |
... | ... | @@ -42,7 +43,7 @@ export default function Index(props: Props = {}) { |
42 | 43 | <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" /> |
43 | 44 | <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" /> |
44 | 45 | <Column title="在库已锁(个)" dataIndex="storageLockedCnt" /> |
45 | - <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} /> | |
46 | + <Column title="近90天月均出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{floor(r.outStockCnt/3)}</a> : r.outStockCnt)} /> | |
46 | 47 | {showAnalyse && ( |
47 | 48 | <> |
48 | 49 | <Column | ... | ... |
src/pages/pms/transfer/transferPool/comonents/PartTable.tsx
... | ... | @@ -22,7 +22,7 @@ export default function Index() { |
22 | 22 | > |
23 | 23 | <Column title="配件名称" dataIndex="name" /> |
24 | 24 | <Column title="配件编码" dataIndex="code" /> |
25 | - <Column title="动态库销比" dataIndex="ratio" /> | |
25 | + <Column title="动态库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : '--')} /> | |
26 | 26 | <Column title="调出池配件数量" dataIndex="transferCnt" /> |
27 | 27 | <Column title="调出库房分析" render={(r:PoolItem) => <a onClick={() => analysis(r, 6)}>查看</a>} /> |
28 | 28 | <Column title="调入库房分析" render={(r:PoolItem) => <a onClick={() => analysis(r, 7)}>查看</a>} /> | ... | ... |
src/pages/pms/transfer/transferPool/comonents/StorageTable.tsx
... | ... | @@ -23,7 +23,7 @@ export default function Index(props: {out?:boolean}) { |
23 | 23 | scroll={{y: 500}} |
24 | 24 | > |
25 | 25 | <Column title={out ? "调出库房" : "调入库房"} dataIndex="name" /> |
26 | - <Column title="动态库销比" dataIndex="ratio" /> | |
26 | + <Column title="动态库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : '--')} /> | |
27 | 27 | <Column title="调出池配件品种" dataIndex="transferKind" /> |
28 | 28 | <Column title="调出池配件数量" dataIndex="transferCnt" /> |
29 | 29 | {out ? | ... | ... |
src/pages/pms/transfer/transferPool/comonents/VehicleTable.tsx
... | ... | @@ -22,7 +22,7 @@ export default function Index() { |
22 | 22 | scroll={{y: 500}} |
23 | 23 | > |
24 | 24 | <Column title="车系" dataIndex="name" /> |
25 | - <Column title="动态库销比" dataIndex="ratio" /> | |
25 | + <Column title="动态库销比" dataIndex="ratio" render={t => (t ? t.toFixed(2) : '--')} /> | |
26 | 26 | <Column title="调出池配件品种" dataIndex="transferKind" /> |
27 | 27 | <Column title="调出池配件数量" dataIndex="transferCnt" /> |
28 | 28 | <Column title="调出库房分析" render={(r) => <a onClick={() => analysis(r, 6)}>查看</a>} /> | ... | ... |