Commit 82ac825a88de73cf37ba61e9d129e3fc93bfe52d

Authored by 张志伟
2 parents c5627a8e bef418e5

Merge branch 'cas' into 'master'

Cas

add

See merge request !194
Showing 28 changed files with 790 additions and 108 deletions
config/routers/pms.ts
... ... @@ -163,4 +163,8 @@ export default [
163 163 path: '/pms/transfer/storageOverStock', // 可调出配件
164 164 component: './pms/transfer/StorageOverStock'
165 165 },
  166 + {
  167 + path: '/pms/transfer/huolalaSetting', // 货拉拉账户配置
  168 + component: './pms/transfer/HuolalaSetting'
  169 + },
166 170 ];
... ...
src/pages/pms/partPlan/PlanManage/api.ts
... ... @@ -26,7 +26,7 @@ export interface ListVO {
26 26 planDate?: string; // 计划日期
27 27 approvalOrderNo?: string; // 审核单号
28 28 userName?: string; // 计划人员
29   - status?: string; // 计划状态 1:待审核2:已通过9:已拒绝
  29 + status?: number; // 计划状态 1:待审核2:已通过9:已拒绝
30 30 settleShopId?: string; // 结算门店门店id
31 31 settleShopName?: string; // 结算门店名称
32 32 prepayToken?: string; // 预付token
... ...
src/pages/pms/partPlan/PlanManage/index.tsx
... ... @@ -13,6 +13,7 @@ import DetailModal from "@/pages/pms/partPlan/PlanManage/components/DetailModal"
13 13  
14 14 // 计划状态 1:待审核2:已通过3待付款4已付款9:已拒绝
15 15 const statusName: {[key: number]: string} = {
  16 + 0: '草稿',
16 17 1: '待审核',
17 18 2: '已通过',
18 19 3: '待付款',
... ... @@ -69,6 +70,7 @@ export default function Index() {
69 70 onChange={v => setParams({status: v }, true)}
70 71 optionFilterProp="children"
71 72 >
  73 + <Select.Option value={0} key={0}>草稿</Select.Option>
72 74 <Select.Option value={1} key={1}>待审核</Select.Option>
73 75 <Select.Option value={2} key={2}>已通过</Select.Option>
74 76 <Select.Option value={9} key={9}>已拒绝</Select.Option>
... ... @@ -95,9 +97,16 @@ export default function Index() {
95 97 fixed="right"
96 98 render={(text, _item: ListVO) => (
97 99 <>
98   - <a onClick={() => history.push(`/pms/partPlan/planManage/detail/${_item.planId}`)}>
99   - 查看
100   - </a>
  100 + {[0, 9].includes(_item.status || 0) ? (
  101 + <a onClick={() => history.push(`/pms/partPlan/planManage/apply?planId=${_item.planId}`)}>
  102 + 编辑
  103 + </a>
  104 + )
  105 + : (
  106 + <a onClick={() => history.push(`/pms/partPlan/planManage/detail/${_item.planId}`)}>
  107 + 查看
  108 + </a>
  109 + )}
101 110 <Divider type="vertical" />
102 111 <a onClick={() => {
103 112 setItem(_item);
... ...
src/pages/pms/partPlan/PlanManage/subpages/Apply/api.ts
... ... @@ -16,3 +16,9 @@ export interface SaveParams {
16 16 export function saveApi(params?: SaveParams): http.PromiseResp<void> {
17 17 return request.post(`${PMS_HOST}/erp/plan/pool/save/plan`, params);
18 18 }
  19 +/**
  20 + * 草稿
  21 + */
  22 +export function draftApi(params?: SaveParams): http.PromiseResp<void> {
  23 + return request.post(`${PMS_HOST}/erp/plan/pool/save/draft`, params);
  24 +}
... ...
src/pages/pms/partPlan/PlanManage/subpages/Apply/components/DealerModal.tsx
... ... @@ -11,9 +11,9 @@ interface Props {
11 11 }
12 12 const {Option} = Select;
13 13 export default function Index({ onCancel, visible, onOk, dealerList = [] }: Props) {
14   - const [dealer, setDealer] = useState<any>({dealerId: null, dealerName: null});
  14 + const [dealer, setDealer] = useState<any>({ settleDealerId: null, settleDealerName: null});
15 15 const { data: dealers } = useInitail<CommonApi.OptionVO[], CommonApi.DealerParam>(getDealerApi, [], {});
16   - const suIds = dealerList.map(it => it.dealerId);
  16 + const suIds = dealerList.map(it => it.settleDealerId);
17 17  
18 18 useEffect(() => {
19 19 if (!visible) {
... ... @@ -22,7 +22,7 @@ export default function Index({ onCancel, visible, onOk, dealerList = [] }: Prop
22 22 }, [visible]);
23 23  
24 24 const handSave = () => {
25   - if (!dealer.dealerId) {
  25 + if (!dealer.settleDealerId) {
26 26 message.error('请选择采购商家');
27 27 return;
28 28 }
... ... @@ -40,7 +40,7 @@ export default function Index({ onCancel, visible, onOk, dealerList = [] }: Prop
40 40 <Button key="cancel" onClick={onCancel}>取消</Button>,
41 41 <Button
42 42 key="submit"
43   - disabled={!dealer.dealerId}
  43 + disabled={!dealer.settleDealerId}
44 44 onClick={handSave}
45 45 type="primary"
46 46 htmlType="submit"
... ... @@ -52,14 +52,14 @@ export default function Index({ onCancel, visible, onOk, dealerList = [] }: Prop
52 52 <div style={{display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: 10}}>
53 53 <span>商家:</span>
54 54 <Select
55   - value={dealer.dealerId}
  55 + value={dealer.settleDealerId}
56 56 style={{ width: 250 }}
57 57 placeholder="请选择商家"
58 58 showSearch
59 59 optionFilterProp="children"
60   - onChange={(dealerId) => {
61   - const d = dealers.find(it => it.id == dealerId) || {};
62   - setDealer({dealerId, dealerName: d.name});
  60 + onChange={(settleDealerId) => {
  61 + const d = dealers.find(it => it.id == settleDealerId) || {};
  62 + setDealer({ settleDealerId, settleDealerName: d.name});
63 63 }}
64 64 >
65 65 {dealers.filter(it => !suIds.includes(it.id)).map((b) => (
... ...
src/pages/pms/partPlan/PlanManage/subpages/Apply/index.tsx
... ... @@ -8,16 +8,24 @@ import {throttle, sum} from &#39;lodash&#39;;
8 8 import useInitial from "@/hooks/useInitail";
9 9 import * as API from "@/common/api";
10 10 import {getList, Params, ListVO} from "@/pages/pms/partPlan/PlanPool/api";
11   -import {saveApi} from './api';
  11 +import {saveApi, draftApi} from './api';
12 12 import zhCN from "antd/lib/locale-provider/zh_CN";
13 13 import st from "@/pages/pms/partPlan/PlanManage/style.less";
14   -import StepBnt from "@/pages/pms/comonents/StepBnt";
15 14 import PartModal from "@/pages/pms/partPlan/PlanManage/subpages/Apply/components/PartModal";
16 15 import {groupBys, flattenDeep} from '@/pages/pms/entity';
17 16 import {PartDetail} from '../../api';
  17 +import { history } from 'umi';
  18 +import { getDetail, DetailVO, Params as detailParams } from '../Detail/api';
18 19  
19 20 const { Option } = Select;
  21 +const apiObj: { [key: number]: any } = {
  22 + 1: saveApi,
  23 + 2: draftApi
  24 +};
20 25 export default function Index() {
  26 + const planId = history.location.query;
  27 + const [detaildelay, setDetaildelay] = useState(true);
  28 + const { data, setParams: detailsetParams } = useInitial<DetailVO[], detailParams>(getDetail, [], { ...planId }, detaildelay);
21 29 const [delay, setDelay] = useState<boolean>(true);
22 30 const [loading, setLoading] = useState<boolean>(false);
23 31 const { data: brands } = useInitial(API.getBrandFilterApi, [], {});
... ... @@ -32,9 +40,25 @@ export default function Index() {
32 40 const partList = flattenDeep(dealerList.map(it => (it.suppliers || []).map((su: any) => (su.storages || []).map((st: any) => (st.parts || [])))));
33 41 const poolIds = partList.map((it: any) => it.poolId);
34 42  
  43 + useEffect(() => {
  44 + if (planId?.planId) {
  45 + setDetaildelay(false);
  46 + detailsetParams({ ...planId }, true);
  47 + }
  48 + }, []);
  49 +
  50 + useEffect(() => {
  51 + if (data.length) {
  52 + setDfParams({brandId: data[0].brandId});
  53 + setParams({}, true);
  54 + setDelay(false);
  55 + setDealerList(data);
  56 + }
  57 + }, [data.length]);
  58 +
35 59 function onOk(parts: ListVO[] = []) {
36 60 setDealerList(dealerList.map(it => {
37   - if (it.dealerId == dealer.dealerId) {
  61 + if (it.settleDealerId == dealer.settleDealerId) {
38 62 return {
39 63 ...it,
40 64 suppliers: (it.suppliers || []).map((su: any) => {
... ... @@ -64,7 +88,7 @@ export default function Index() {
64 88  
65 89 function onOkSupplier(supplier: any = {}) {
66 90 setDealerList(dealerList.map(it => {
67   - if (it.dealerId == dealer.dealerId) {
  91 + if (it.settleDealerId == dealer.settleDealerId) {
68 92 return {
69 93 ...it,
70 94 suppliers: [...(it.suppliers || []), supplier]
... ... @@ -76,7 +100,7 @@ export default function Index() {
76 100  
77 101 function deleteSupplier(dealer: any = {}, supplier: any = {}) {
78 102 setDealerList(dealerList.map(it => {
79   - if (it.dealerId == dealer.dealerId) {
  103 + if (it.settleDealerId == dealer.settleDealerId) {
80 104 return {
81 105 ...it,
82 106 suppliers: (it.suppliers || []).filter((su: any) => su.supplierId != supplier.supplierId)
... ... @@ -88,7 +112,7 @@ export default function Index() {
88 112  
89 113 function deletePart(dealer: any = {}, supplier: any = {}, storage: any = {}, part: any = {}) {
90 114 setDealerList(dealerList.map(it => {
91   - if (it.dealerId == dealer.dealerId) {
  115 + if (it.settleDealerId == dealer.settleDealerId) {
92 116 return {
93 117 ...it,
94 118 suppliers: (it.suppliers || []).map((su: any) => {
... ... @@ -116,7 +140,7 @@ export default function Index() {
116 140  
117 141 function deleteStorage(dealer: any = {}, supplier: any = {}, storage: any = {}) {
118 142 setDealerList(dealerList.map(it => {
119   - if (it.dealerId == dealer.dealerId) {
  143 + if (it.settleDealerId == dealer.settleDealerId) {
120 144 return {
121 145 ...it,
122 146 suppliers: (it.suppliers || []).map((su: any) => {
... ... @@ -134,31 +158,33 @@ export default function Index() {
134 158 }));
135 159 }
136 160  
137   - // useEffect(() => {
138   - // if (dfParams.brandId) {
139   - // setParams(dfParams, true);
140   - // setDelay(false);
141   - // }
142   - // }, [dfParams.brandId]);
143   -
144   - const onSubmit = throttle(() => {
  161 + const onSubmit = throttle((isSave) => {
145 162 setLoading(true);
146 163 let suppliers = flattenDeep(dealerList.map(de => (de.suppliers || []).map((su: any) => ({...de, ...su}))));
147 164 suppliers = suppliers.map(su => ({
148 165 ...su,
149   - settleDealerId: su.dealerId,
  166 + settleDealerId: su.settleDealerId,
150 167 storages: (su.storages || []).map((st: any) => ({
151 168 storageId: st.storageId,
152 169 poolIds: (st.parts || []).map((pa: any) => pa.poolId)
153 170 }))
154 171 }));
155   - saveApi({
  172 + const type = isSave ? 1 : 2;
  173 + apiObj[type]({
  174 + planId: Number(planId?.planId),
156 175 ...dfParams,
157 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 + // }))
158 184 }).then(() => {
159 185 setLoading(false);
160   - history.back();
161   - }).catch(e => {
  186 + history.goBack();
  187 + }).catch((e: any) => {
162 188 setLoading(false);
163 189 message.error(e.message);
164 190 });
... ... @@ -204,15 +230,15 @@ export default function Index() {
204 230 </a>
205 231 </div>
206 232 {dealerList.map((dealer: any = {}) => (
207   - <div key={`dealer${dealer.dealerId}`} style={{ marginTop: 10 }}>
  233 + <div key={`dealer${dealer.settleDealerId}`} style={{ marginTop: 10 }}>
208 234 <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
209   - <div style={{ fontWeight: "bold" }}>{`商家: ${dealer.dealerName || ''}`}</div>
  235 + <div style={{ fontWeight: "bold" }}>{`商家: ${dealer.settleDealerName || ''}`}</div>
210 236 <a style={{marginLeft: 40}} onClick={() => { setVisibleSupplier(true); setDealer(dealer); }}>
211 237 添加指定供应商
212 238 </a>
213 239 <Popconfirm
214 240 title="是否删除"
215   - onConfirm={() => setDealerList(dealerList.filter(it => it.dealerId!=dealer.dealerId))}
  241 + onConfirm={() => setDealerList(dealerList.filter(it => it.settleDealerId!=dealer.settleDealerId))}
216 242 okText="确定"
217 243 cancelText="取消"
218 244 style={{marginLeft: 20}}
... ... @@ -224,8 +250,6 @@ export default function Index() {
224 250 </div>
225 251 {(dealer.suppliers || []).map((supplier: any = {}) => {
226 252 const paList: any[] = flattenDeep((supplier.storages || []).map((st: any) => (st.parts || [])));
227   - // const paList: any[] = pas.length > 0 ? pas[0] : [];
228   - console.log('pas', paList);
229 253 return (
230 254 <div key={`supplier${supplier.supplierId}`} style={{ marginTop: 10, marginLeft: 40 }}>
231 255 <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
... ... @@ -247,7 +271,7 @@ export default function Index() {
247 271 </div>
248 272 <div style={{display: 'flex', marginLeft: 40, marginTop: 10}}>
249 273 <div style={{marginRight: 20}}>
250   - {`总金额: ${sum(paList.map((it: any) => (it.price || 0) * (it.count || 0))).toFixed(2)}元`}
  274 + {`总金额: ${sum(paList.map((it: any) => (it.price || 0) * (it.count || it.partCnt || 0))).toFixed(2)}元`}
251 275 </div>
252 276 <div>{`品种数: ${[...new Set((paList || []).map((i: PartDetail) => i.partCode))].length}种`}</div>
253 277 </div>
... ... @@ -255,7 +279,7 @@ export default function Index() {
255 279 <div key={`storage${storage.storageId}`} style={{ marginTop: 10, marginLeft: 60 }}>
256 280 <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
257 281 <div style={{ fontWeight: "bold" }}>{`发运库房: ${storage.storageName || ''}`}</div>
258   - <div style={{marginLeft: 20}}>{`总金额: ${sum((storage.parts || []).map((it: any) => (it.price || 0) * (it.count || 0))).toFixed(2)}元`}</div>
  282 + <div style={{marginLeft: 20}}>{`总金额: ${sum((storage.parts || []).map((it: any) => (it.price || 0) * (it.count || it.partCnt || 0))).toFixed(2)}元`}</div>
259 283 <div style={{marginLeft: 20}}>{`品种数: ${[...new Set((storage.parts || []).map((i: PartDetail) => i.partCode))].length}种`}</div>
260 284 <a style={{marginLeft: 20}} onClick={() => { setVisiblePartDetail(true); setDealer({dealer, supplier, storage }); }}>
261 285 查看配件
... ... @@ -308,11 +332,34 @@ export default function Index() {
308 332 deletePart={deletePart}
309 333 />
310 334 </div>
311   - <StepBnt
312   - disable={loading}
313   - bntLoading={loading}
314   - submit={onSubmit}
315   - />
  335 + <div style={{display: 'flex', justifyContent: 'center'}}>
  336 + <Button
  337 + disabled={loading}
  338 + loading={loading}
  339 + style={{marginRight: 20}}
  340 + onClick={() => history.goBack()}
  341 + >
  342 + 取消
  343 + </Button>
  344 + <Button
  345 + disabled={loading}
  346 + loading={loading}
  347 + onClick={() => onSubmit(false)}
  348 + type="primary"
  349 + style={{marginRight: 20}}
  350 + >
  351 + 暂存为草稿
  352 + </Button>
  353 + <Button
  354 + disabled={loading}
  355 + loading={loading}
  356 + onClick={() => onSubmit(true)}
  357 + type="primary"
  358 + >
  359 + 确认并提交
  360 + </Button>
  361 + </div>
  362 +
316 363 </Card>
317 364 </ConfigProvider>
318 365 </PageHeaderWrapper>
... ...
src/pages/pms/partPlan/PlanManage/subpages/Detail/api.ts
... ... @@ -7,6 +7,7 @@ import { PMS_HOST } from &#39;@/utils/host&#39;;
7 7 */
8 8 export interface DetailVO {
9 9 brandName?: string; // 品牌名称
  10 + brandId?: number; // 品牌ID
10 11 settleDealerName?: string; // 结算商家
11 12 settleShopName?: string; // 结算门店
12 13 suppliers?: SupplierVO[]; // 配件集合
... ...
src/pages/pms/partPlan/PlanPool/api.ts
1 1 import { http } from '@/typing/http';
2 2 import request from '@/utils/request';
3 3 import { PMS_HOST } from '@/utils/host';
  4 +import { PartVO } from '@/pages/pms/partPlan/CustBuyPlan/api';
4 5  
5 6 export interface Params {
6 7 brandId?: number, // 品牌ID
... ... @@ -18,6 +19,7 @@ export interface Params {
18 19  
19 20 export interface ListVO {
20 21 poolId: number; // 计划池id
  22 + poolIds?: string,
21 23 id?: number;
22 24 name?: string; // 名称
23 25 code?: string; // 编码
... ... @@ -61,7 +63,60 @@ export interface ListVO {
61 63 unit?: string; // 采购规格(配件展示)
62 64 splitUnit?: string; // 拆分件规格(配件展示)
63 65 splitCnt?: number; // 拆分件数量(配件展示)
64   - partType?:number
  66 + partType?:number,
  67 + planWaitListIds?:string
  68 +}
  69 +
  70 +export interface OutItem{
  71 + /**
  72 + * 配件ID
  73 + */
  74 +partId?:number;
  75 +/**
  76 + * 配件编码
  77 + */
  78 +partCode?:string;
  79 +/**
  80 + * 配件名称
  81 + */
  82 +partName?:string;
  83 +/**
  84 + * 出库数量
  85 + */
  86 +partCnt?:number;
  87 +/**
  88 + * 成本价
  89 + */
  90 +costPrice?:number;
  91 +/**
  92 + * 出库类型1工单2装潢
  93 + */
  94 +type?:number;
  95 +/**
  96 + * 出库类型ID
  97 + */
  98 +typeId?:string;
  99 +/**
  100 + * 服务站id
  101 + */
  102 +shopId?:number;
  103 +/**
  104 + * 服务站名称
  105 + */
  106 +shopName?:string;
  107 +/**
  108 + * 集团ID
  109 + */
  110 +groupId?:number;
  111 +/**
  112 + * 出库时间
  113 + */
  114 +outTime?:string;
  115 +
  116 +/**
  117 + * 类型名称
  118 + */
  119 +typeName?:string;
65 120 }
66 121  
67 122 /**
... ... @@ -74,6 +129,15 @@ export function getList(params: Params): http.PromiseResp&lt;ListVO[]&gt; {
74 129 export function deleteApi(params: {poolId: number}) {
75 130 return request.post(`${PMS_HOST}/erp/plan/pool/delete/plan`, {...params});
76 131 }
  132 +
77 133 export function editApi(params: { poolId?: number, partCnt?: number}) {
78 134 return request.post(`${PMS_HOST}/erp/plan/pool/update/plan`, {...params});
79 135 }
  136 +
  137 +export function outFlowApi(params: { poolIds?: any, planId?: number, current?: number, pageSize?:number}):http.PromisePageResp<OutItem> {
  138 + return request.get(`${PMS_HOST}/erp/storage/out/list`, {params});
  139 +}
  140 +
  141 +export function custBuyApi(params: { planWaitListIds?: any}):http.PromiseResp<PartVO[]> {
  142 + return request.get(`${PMS_HOST}/erp/cus/buy/part/get/buy/part/list`, {params});
  143 +}
... ...
src/pages/pms/partPlan/PlanPool/components/AreaTable.tsx
... ... @@ -14,7 +14,7 @@ interface Props {
14 14 id?: number, // 上一个列表ID
15 15 }
16 16 export default function Index(props: Props = {}) {
17   - const { dfParams, key } = useStore();
  17 + const { dfParams, key, setItem, setOutVisible, setCustVisible } = useStore();
18 18 const {showAnalyse=true} = props;
19 19 const { data: parts, setParams, loading } = useInitial(getList, [], {...dfParams, ...props});
20 20 const [visible, setVisible] = useState(false);
... ... @@ -23,7 +23,6 @@ export default function Index(props: Props = {}) {
23 23 const [id, setId] = useState<number>();
24 24  
25 25 useEffect(() => {
26   - console.log('dfParams11', dfParams, key, props);
27 26 if (key == props.type) {
28 27 setParams(dfParams, true);
29 28 }
... ... @@ -37,13 +36,13 @@ export default function Index(props: Props = {}) {
37 36 <Column title="计划前库销比" dataIndex="ratio" render={t => (t || 0).toFixed(2)} />
38 37 <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} />
39 38 <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" />
40   - <Column title="客户订件数量(个)" dataIndex="buyCnt" />
  39 + <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} />
41 40 <Column title="客户订件金额(元)" dataIndex="buyAmount" />
42 41 <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" />
43 42  
44 43 <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" />
45 44 <Column title="在库已锁(个)" dataIndex="storageLockedCnt" />
46   - <Column title="滚动90天出库(个)" dataIndex="outStockCnt" />
  45 + <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} />
47 46 {showAnalyse && (
48 47 <>
49 48 <Column
... ...
src/pages/pms/partPlan/PlanPool/components/CustBuyModal.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Button, Modal, Table } from 'antd';
  3 +import { useStore } from '../index';
  4 +import { custBuyApi } from '../api';
  5 +import { PartVO } from '@/pages/pms/partPlan/CustBuyPlan/api';
  6 +import useInitial from '@/hooks/useInitail';
  7 +
  8 +const { Column } = Table;
  9 +
  10 +export default function Index() {
  11 + const { custVisible, setCustVisible, item } = useStore();
  12 + const [delay, setDelay] = useState(true);
  13 + const { data, setParams, loading } = useInitial(custBuyApi, [], {}, delay);
  14 +
  15 + useEffect(() => {
  16 + if (custVisible && item?.planWaitListIds) {
  17 + setParams({ planWaitListIds: item.planWaitListIds }, true);
  18 + setDelay(false);
  19 + }
  20 + }, [custVisible]);
  21 +
  22 + return (
  23 + <Modal
  24 + title="客户订件详情"
  25 + width={1100}
  26 + visible={custVisible}
  27 + maskClosable={false}
  28 + onCancel={() => setCustVisible(false)}
  29 + footer={[
  30 + <Button onClick={() => setCustVisible(false)}>取消</Button>
  31 + ]}
  32 + >
  33 + <Table
  34 + rowKey={(v: PartVO) => `${v.waitListIds}`}
  35 + dataSource={data}
  36 + pagination={false}
  37 + loading={loading}
  38 + scroll={{x: 1400, y: 500}}
  39 + >
  40 + <Column title="时间" dataIndex="planTime" />
  41 + <Column title="VIN" dataIndex="typeId" />
  42 + <Column title="工单号" dataIndex="remark" />
  43 + <Column title="车牌号" dataIndex="plateNo" />
  44 + <Column title="配件编码" dataIndex="partCode" />
  45 + <Column title="配件名称" dataIndex="partName" />
  46 + <Column title="接车服务顾问" dataIndex="userName" />
  47 + <Column title="门店名称" dataIndex="shopName" />
  48 + <Column title="库房名称" dataIndex="storageName" />
  49 + <Column title="订件数量" dataIndex="splitCnt" />
  50 + <Column title="采购单价" dataIndex="price" />
  51 + <Column title="采购数量" dataIndex="cnt" />
  52 + </Table>
  53 + </Modal>
  54 + );
  55 +}
0 56 \ No newline at end of file
... ...
src/pages/pms/partPlan/PlanPool/components/OutFlowModal.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import {Button, Modal, Table} from 'antd';
  3 +import {useStore} from '../index';
  4 +import { outFlowApi, OutItem } from '../api';
  5 +import usePagination from '@/hooks/usePagination';
  6 +
  7 +const {Column} = Table;
  8 +
  9 +export default function Index() {
  10 + const {outVisible, setOutVisible, item} = useStore();
  11 + const [delay, setDelay]= useState(true);
  12 + const { list, setParams, loading, paginationConfig } = usePagination(outFlowApi, [], {delay});
  13 +
  14 + useEffect(() => {
  15 + if (outVisible && item?.poolIds) {
  16 + setParams({poolIds: item.poolIds}, true);
  17 + setDelay(false);
  18 + }
  19 + }, [outVisible]);
  20 +
  21 + return (
  22 + <Modal
  23 + title={`${item?.partName}滚动90天出库流水`}
  24 + width={1000}
  25 + visible={outVisible}
  26 + maskClosable={false}
  27 + onCancel={() => setOutVisible(false)}
  28 + footer={[
  29 + <Button onClick={() => setOutVisible(false)}>取消</Button>
  30 + ]}
  31 + >
  32 + <Table
  33 + dataSource={list}
  34 + loading={loading}
  35 + pagination={paginationConfig}
  36 + rowKey={(v: OutItem) => `${v.partId}`}
  37 + >
  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" />
  44 + </Table>
  45 + </Modal>
  46 + );
  47 +}
0 48 \ No newline at end of file
... ...
src/pages/pms/partPlan/PlanPool/components/PartTable.tsx
... ... @@ -16,7 +16,7 @@ interface Props {
16 16 id?: number, // 上一个列表ID
17 17 }
18 18 export default function Index(props: Props = {}) {
19   - const { dfParams, key } = useStore();
  19 + const { dfParams, key, setItem, setOutVisible, setCustVisible } = useStore();
20 20 const {showAnalyse=true} = props;
21 21 const { data: parts, setParams, loading } = useInitial(getList, [], {...dfParams, ...props});
22 22 const [visible, setVisible] = useState(false);
... ... @@ -43,13 +43,13 @@ export default function Index(props: Props = {}) {
43 43 <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} />
44 44  
45 45 <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" />
46   - <Column title="客户订件数量(个)" dataIndex="buyCnt" />
  46 + <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} />
47 47 <Column title="客户订件金额(元)" dataIndex="buyAmount" />
48 48 <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" />
49 49  
50 50 <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" />
51 51 <Column title="在库已锁(个)" dataIndex="storageLockedCnt" />
52   - <Column title="滚动90天出库(个)" dataIndex="outStockCnt" />
  52 + <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} />
53 53 {showAnalyse && (
54 54 <>
55 55 <Column
... ...
src/pages/pms/partPlan/PlanPool/components/SeriesTable.tsx
... ... @@ -15,7 +15,7 @@ interface Props {
15 15 id?: number, // 上一个列表ID
16 16 }
17 17 export default function Index(props: Props = {}) {
18   - const { dfParams, key } = useStore();
  18 + const { dfParams, key, setItem, setOutVisible, setCustVisible } = useStore();
19 19 const {showAnalyse=true} = props;
20 20 const { data: parts, setParams, loading } = useInitial(getList, [], {...dfParams, ...props});
21 21 const [visible, setVisible] = useState(false);
... ... @@ -38,13 +38,13 @@ export default function Index(props: Props = {}) {
38 38 <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} />
39 39  
40 40 <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" />
41   - <Column title="客户订件数量(个)" dataIndex="buyCnt" />
  41 + <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} />
42 42 <Column title="客户订件金额(元)" dataIndex="buyAmount" />
43 43 <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" />
44 44  
45 45 <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" />
46 46 <Column title="在库已锁(个)" dataIndex="storageLockedCnt" />
47   - <Column title="滚动90天出库(个)" dataIndex="outStockCnt" />
  47 + <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} />
48 48 {showAnalyse && (
49 49 <>
50 50 <Column
... ...
src/pages/pms/partPlan/PlanPool/components/StoragePartTable.tsx
... ... @@ -12,11 +12,11 @@ interface Props {
12 12 type?: number, // 类型1区域库2库房3车系4车型5配件
13 13 }
14 14 export default function Index(props: Props = {}) {
15   - const { dfParams, key } = useStore();
  15 + const { dfParams, key, setItem, setOutVisible, setCustVisible } = useStore();
16 16 const [form] = Form.useForm();
17 17 const { data: parts, setParams, loading } = useInitial(getList, [], dfParams);
18 18 const [visible, setVisible] = useState(false);
19   - const [item, setItem] = useState<ListVO>();
  19 + const [itemPrice, setItemPrice] = useState<ListVO>();
20 20  
21 21 useEffect(() => {
22 22 if (key == props.type) {
... ... @@ -25,8 +25,8 @@ export default function Index(props: Props = {}) {
25 25 }, [dfParams, key]);
26 26  
27 27 useEffect(() => {
28   - if (visible && item?.poolId) {
29   - form.setFieldsValue({cnt: item.cnt});
  28 + if (visible && itemPrice?.poolId) {
  29 + form.setFieldsValue({ cnt: itemPrice.cnt});
30 30 } else {
31 31 form.resetFields;
32 32 }
... ... @@ -43,7 +43,7 @@ export default function Index(props: Props = {}) {
43 43 fixed="left"
44 44 render={r => (
45 45 <>
46   - <a onClick={() => { setVisible(true); setItem(r); }}>编辑</a>
  46 + <a onClick={() => { setVisible(true); setItemPrice(r); }}>编辑</a>
47 47 <Divider type="vertical" />
48 48 <Popconfirm
49 49 title="确认删除?"
... ... @@ -68,12 +68,12 @@ export default function Index(props: Props = {}) {
68 68 <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} />
69 69  
70 70 <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" />
71   - <Column title="客户订件数量(个)" dataIndex="buyCnt" />
  71 + <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} />
72 72 <Column title="客户订件金额(元)" dataIndex="buyAmount" />
73 73 <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" />
74 74 <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" />
75 75 <Column title="在库已锁(个)" dataIndex="storageLockedCnt" />
76   - <Column title="滚动90天出库(个)" dataIndex="outStockCnt" />
  76 + <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} />
77 77  
78 78 </Table>
79 79 <Modal
... ... @@ -90,7 +90,7 @@ export default function Index(props: Props = {}) {
90 90 htmlType="submit"
91 91 onClick={() => {
92 92 form.validateFields().then(fields => {
93   - editApi({poolId: item?.poolId, partCnt: fields.cnt}).then(res => {
  93 + editApi({ poolId: itemPrice?.poolId, partCnt: fields.cnt}).then(res => {
94 94 setVisible(false);
95 95 message.success("操作成功");
96 96 setParams({}, true);
... ...
src/pages/pms/partPlan/PlanPool/components/StorageTable.tsx
... ... @@ -14,7 +14,7 @@ interface Props {
14 14 id?: number, // 上一个列表ID
15 15 }
16 16 export default function Index(props: Props = {}) {
17   - const { dfParams, key } = useStore();
  17 + const { dfParams, key, setItem, setOutVisible, setCustVisible } = useStore();
18 18 const {showAnalyse=true} = props;
19 19 const { data: parts, setParams, loading } = useInitial(getList, [], {...dfParams, ...props});
20 20 const [visible, setVisible] = useState(false);
... ... @@ -37,12 +37,12 @@ export default function Index(props: Props = {}) {
37 37 <Column title="计划后库销比" dataIndex="planeRatio" render={t => (t || 0).toFixed(2)} />
38 38  
39 39 <Column title="本次计划金额(元)" dataIndex="thisTimeAmount" />
40   - <Column title="客户订件数量(个)" dataIndex="buyCnt" />
  40 + <Column title="客户订件数量(个)" render={r => (r.buyCnt ? <a onClick={() => { setCustVisible(true); setItem(r); }}>{r.buyCnt}</a> : r.buyCnt)} />
41 41 <Column title="客户订件金额(元)" dataIndex="buyAmount" />
42 42 <Column title="在途未锁(个)" dataIndex="onTheWayUnlockCnt" />
43 43 <Column title="在库未锁(个)" dataIndex="storageUnlockCnt" />
44 44 <Column title="在库已锁(个)" dataIndex="storageLockedCnt" />
45   - <Column title="滚动90天出库(个)" dataIndex="outStockCnt" />
  45 + <Column title="滚动90天出库(个)" render={r => (r.outStockCnt ? <a onClick={() => { setOutVisible(true); setItem(r); }}>{r.outStockCnt}</a> : r.outStockCnt)} />
46 46 {showAnalyse && (
47 47 <>
48 48 <Column
... ...
src/pages/pms/partPlan/PlanPool/index.tsx
... ... @@ -11,6 +11,8 @@ import st from &quot;@/pages/pms/partPlan/PlanShipping/style.less&quot;;
11 11 import Filter from './components/Filter';
12 12 import {createStore} from "@/hooks/moz";
13 13 import store from "./useStore";
  14 +import OutFlowModal from './components/OutFlowModal';
  15 +import CustBuyModal from './components/CustBuyModal';
14 16  
15 17 export const { Provider, useStore } = createStore(store);
16 18  
... ... @@ -38,6 +40,8 @@ function Index() {
38 40 <StoragePartTable type={6} />
39 41 </Tabs.TabPane>
40 42 </Tabs>
  43 + <OutFlowModal />
  44 + <CustBuyModal />
41 45 </Card>
42 46 </ConfigProvider>
43 47 </PageHeaderWrapper>
... ...
src/pages/pms/partPlan/PlanPool/useStore.ts
1 1 import { useState } from 'react';
2 2 import useInitail from "@/hooks/useInitail";
3 3 import { getPartTypeApi } from '@/pages/pms/part/Repertory/api';
  4 +import {ListVO} from './api';
4 5  
5 6 export default function useStore() {
6 7 const [dfParams, setDfParams] = useState<any>({});
7 8 const [key, setKey] = useState<any>('1');
8 9 const { data: partTypeData } = useInitail(getPartTypeApi, [], {});
  10 + const [outVisible, setOutVisible] = useState(false);
  11 + const [custVisible, setCustVisible] = useState(false);
  12 + const [item, setItem] = useState<ListVO>();
9 13  
10 14 return {
11 15 dfParams,
12 16 setDfParams,
13 17 key,
14 18 setKey,
15   - partTypeData
  19 + partTypeData,
  20 + outVisible,
  21 + setOutVisible,
  22 + item,
  23 + setItem,
  24 + custVisible,
  25 + setCustVisible,
16 26 };
17 27 }
... ...
src/pages/pms/storage/partShop/api.ts
... ... @@ -42,6 +42,12 @@ export function getLockDetail(params?: PmsStoragePartShop.LockParams): http.Prom
42 42 export function getFlowDetail(params?: PmsStoragePartShop.FlowParams): http.PromisePageResp<PmsStoragePartShop.FlowVO> {
43 43 return request.get(`${PMS_HOST}/erp/part/shop/get/record`, { params });
44 44 }
  45 +/**
  46 + * 查询门店备件锁库流水明细列表
  47 + */
  48 +export function getLockFlowDetail(params?: PmsStoragePartShop.FlowParams): http.PromisePageResp<PmsStoragePartShop.FlowVO> {
  49 + return request.get(`${PMS_HOST}/erp/part/shop/get/lock/record`, { params });
  50 +}
45 51 // 释放库存
46 52 export function unLock(params: PmsStoragePartShop.unLock): http.PromiseResp<string> {
47 53 return request.post(`${PMS_HOST}/erp/part/shop/cancel/lock`, { ...params }, { contentType: "form-urlencoded" });
... ...
src/pages/pms/storage/partShop/components/Filter.tsx
... ... @@ -32,14 +32,14 @@ export default function Filter() {
32 32 return (
33 33 <div>
34 34 <Search
35   - style={{ width: 200, marginRight: 10 }}
  35 + style={{ width: 180, marginRight: 10, marginBottom: 10 }}
36 36 allowClear
37 37 enterButton
38 38 placeholder="配件编码|名称"
39 39 onSearch={v => handleChangeKeywords(v)}
40 40 />
41 41 <PmsSelect
42   - style={{ width: 180, marginRight: 10}}
  42 + style={{ width: 180, marginRight: 10, marginBottom: 10 }}
43 43 allowClear
44 44 value={innerParams.shopId}
45 45 onChange={value => {
... ... @@ -52,7 +52,7 @@ export default function Filter() {
52 52 .map((item: PmsStoragePartShop.Option) => ({value: item.id, label: item.name}))}
53 53 />
54 54 <PmsSelect
55   - style={{ width: 150, marginRight: 10}}
  55 + style={{ width: 180, marginRight: 10, marginBottom: 10 }}
56 56 allowClear
57 57 value={innerParams.storageId}
58 58 onChange={value => {
... ... @@ -66,7 +66,7 @@ export default function Filter() {
66 66 />
67 67 <PmsSelect
68 68 allowClear
69   - style={{ width: 150, marginRight: 10}}
  69 + style={{ width: 180, marginRight: 10, marginBottom: 10 }}
70 70 onChange={(type) => {
71 71 setParams({ ...innerParams, current: 1, type }, true);
72 72 }}
... ... @@ -77,7 +77,7 @@ export default function Filter() {
77 77 allowClear
78 78 placeholder="有无库存筛选"
79 79 onChange={v => isStock(v)}
80   - style={{ width: 150, marginRight: 10 }}
  80 + style={{ width: 180, marginRight: 10, marginBottom: 10 }}
81 81 options={[
82 82 {value: 1, label: "有库存"},
83 83 {value: 0, label: "无库存"},
... ... @@ -87,7 +87,7 @@ export default function Filter() {
87 87 placeholder="排序方式"
88 88 defaultValue={18}
89 89 onChange={v => isSorter(v)}
90   - style={{ width: 150 }}
  90 + style={{ width: 180 }}
91 91 options={[
92 92 {value: 18, label: "总库存降序"},
93 93 {value: 21, label: "锁定库存降序"},
... ...
src/pages/pms/storage/partShop/components/List.tsx
... ... @@ -4,6 +4,7 @@ import { useStore } from &#39;../index&#39;;
4 4 import LockDetailModal from './LockDetailModal';
5 5 import FlowDetailModal from './FlowDetailModal';
6 6 import PartShopModal from './PartShopModal';
  7 +import LockFlowModal from './LockFlowModal';
7 8  
8 9 const { Column } = Table;
9 10  
... ... @@ -11,6 +12,7 @@ export default function Filter() {
11 12 const { setParams, loading, paginationConfig, list, setVisible, setItem, item, fw, setIsprice} = useStore();
12 13 const [visibleLockDetail, setVisibleLockDetail] = useState(false);
13 14 const [visibleFlowDetail, setVisibleFlowDetail] = useState(false);
  15 + const [visibleLockFlow, setVisibleLockFlow] = useState(false);
14 16  
15 17 return (
16 18 <div>
... ... @@ -43,6 +45,14 @@ export default function Filter() {
43 45 title="入库流水"
44 46 render={(t, it: PartRepertorySpace.Item) => <a onClick={() => { setVisibleFlowDetail(true); setItem({...it, isOut: false}); }}>查看</a>}
45 47 />
  48 + <Column
  49 + title="锁库流水"
  50 + render={(t, it: PartRepertorySpace.Item) => <a onClick={() => { setVisibleLockFlow(true); setItem({...it, isLock: true}); }}>查看</a>}
  51 + />
  52 + <Column
  53 + title="释放流水"
  54 + render={(t, it: PartRepertorySpace.Item) => <a onClick={() => { setVisibleLockFlow(true); setItem({...it, isLock: false}); }}>查看</a>}
  55 + />
46 56 {fw ? (
47 57 <Column
48 58 title="操作"
... ... @@ -65,6 +75,7 @@ export default function Filter() {
65 75 </Table>
66 76 <LockDetailModal item={item} visible={visibleLockDetail} onCancel={() => setVisibleLockDetail(false)} />
67 77 <FlowDetailModal item={item} visible={visibleFlowDetail} onCancel={() => setVisibleFlowDetail(false)} />
  78 + <LockFlowModal item={item} visible={visibleLockFlow} onCancel={() => setVisibleLockFlow(false)} />
68 79 <PartShopModal />
69 80 </div>
70 81 );
... ...
src/pages/pms/storage/partShop/components/LockFlowModal.tsx 0 → 100644
  1 +import React, {useEffect, useState} from 'react';
  2 +import {Modal, Table, Button} from 'antd';
  3 +import { getLockFlowDetail } from '@/pages/pms/storage/partShop/api';
  4 +import usePagination from '@/hooks/usePagination';
  5 +
  6 +interface Props {
  7 + item?: any
  8 + visible: boolean
  9 + onCancel: () => any
  10 +}
  11 +const {Column} = Table;
  12 +export default function Index(props: Props) {
  13 + const {item, visible, onCancel} = props;
  14 + const [delay, setDelay] = useState(true);
  15 + const { list, loading, setParams, paginationConfig, setList } = usePagination<PmsStoragePartShop.FlowVO>(getLockFlowDetail, {}, { delay });
  16 +
  17 + useEffect(() => {
  18 + if (item.shopId && item.partId && visible) {
  19 + setParams({ partId: item.partId, shopId: item.shopId, isLock: item.isLock }, true);
  20 + setDelay(false);
  21 + } else {
  22 + setList([]);
  23 + }
  24 + }, [visible, item.partId]);
  25 +
  26 + return (
  27 + <Modal
  28 + title={`${item.isLock ? '锁定库存' : '释放库存'}流水`}
  29 + width={1000}
  30 + visible={visible}
  31 + maskClosable={false}
  32 + onCancel={onCancel}
  33 + footer={[
  34 + <Button key="1" onClick={onCancel}>取消</Button>,
  35 + ]}
  36 + >
  37 + <Table
  38 + loading={loading}
  39 + dataSource={list}
  40 + rowKey={(v: PmsStoragePartShop.FlowVO) => `${v.type}_${v.typeId}`}
  41 + pagination={paginationConfig}
  42 + >
  43 + <Column title="配件数量" dataIndex="partCnt" />
  44 + <Column title="单号" dataIndex="remark" render={t => t || "--"} />
  45 + <Column
  46 + title="详情"
  47 + dataIndex="text"
  48 + width={350}
  49 + render={(t: string, it: PmsStoragePartShop.FlowVO) => {
  50 + const obj = JSON.parse(t || '{}');
  51 + return (
  52 + <div>
  53 + {!!obj.type && <div>{`类型: ${obj.type}`}</div>}
  54 + {!!obj.serviceCatName && <div>{`进站类型: ${obj.serviceCatName}`}</div>}
  55 + {!!obj.exclusiveAdviser && <div>{`专属顾问: ${obj.exclusiveAdviser}`}</div>}
  56 + {!!obj.shopLinkmanName && <div>{`服务顾问: ${obj.shopLinkmanName}`}</div>}
  57 + {!!obj.receiverName && <div>{`服务顾问: ${obj.receiverName}`}</div>}
  58 + {!!obj.plateNo && <div>{`车牌号: ${obj.plateNo}`}</div>}
  59 + {!!obj.ownerName && <div>{`车主: ${obj.ownerName}`}</div>}
  60 + {!!obj.vin && <div>{`VIN: ${obj.vin}`}</div>}
  61 + {!!obj.userName && <div>{`操作账号: ${obj.userName}`}</div>}
  62 + {!!obj.fixRemark && <div>{`备注: ${obj.fixRemark}`}</div>}
  63 + </div>
  64 + );
  65 + }}
  66 + />
  67 + <Column title={`${item.isLock ? '锁库' : '释放'}时间`} dataIndex="recordTime" />
  68 + </Table>
  69 + </Modal>
  70 + );
  71 +}
0 72 \ No newline at end of file
... ...
src/pages/pms/storage/partShop/index.tsx
1 1 import React, {useState} from 'react';
2   -import { PlusOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons';
  2 +import { PlusOutlined, DownloadOutlined, UploadOutlined } from '@ant-design/icons';
3 3 import { Card, Button } from 'antd';
4 4 import { PageHeaderWrapper } from '@ant-design/pro-layout';
5 5 import Filter from './components/Filter';
... ... @@ -20,53 +20,51 @@ function PartShop() {
20 20 return (
21 21 <PageHeaderWrapper title={`服务站配件${fw ? '(霏微)': ''}`}>
22 22 <Card>
23   - <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
  23 + <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 20 }}>
24 24 <Filter />
25   - <div style={{display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
  25 + <div style={{ display: 'flex', alignItems: 'center'}}>
  26 + <Button
  27 + type="primary"
  28 + icon={<PlusOutlined />}
  29 + onClick={() => { setVisible(true); setIsadd(true); }}
  30 + >
  31 + 新增
  32 + </Button>
26 33 {fw && (
27   - <>
28   - <Button
29   - icon={(<PlusOutlined />)}
30   - type="primary"
31   - onClick={() => setImportVisible(true)}
32   - >
33   - 导入
34   - </Button>
35   - <Button
36   - icon={(<PlusOutlined />)}
37   - type="primary"
38   - onClick={() => { setImportVisible(true); setStock(true); }}
39   - style={{marginLeft: 10}}
40   - >
41   - 调运库存导入
42   - </Button>
43   - </>
44   - )}
45   - {/* {!fw && ( */}
46 34 <Button
  35 + icon={<UploadOutlined />}
47 36 type="primary"
48   - icon={<VerticalAlignBottomOutlined />}
49   - onClick={() => { setMore(true); setIslock(true); }}
  37 + onClick={() => setImportVisible(true)}
  38 + style={{ marginLeft: 10 }}
  39 + >
  40 + 导入
  41 + </Button>
  42 + )}
  43 + {fw && (
  44 + <Button
  45 + icon={<UploadOutlined />}
  46 + type="primary"
  47 + onClick={() => { setImportVisible(true); setStock(true); }}
50 48 style={{marginLeft: 10}}
51 49 >
52   - 锁件批量导出
  50 + 调运库存导入
53 51 </Button>
54   - {/* )} */}
  52 + )}
55 53 <Button
56 54 type="primary"
57   - icon={<VerticalAlignBottomOutlined />}
58   - onClick={() => setMore(true)}
  55 + icon={<DownloadOutlined />}
  56 + onClick={() => { setMore(true); setIslock(true); }}
59 57 style={{marginLeft: 10}}
60 58 >
61   - 库存批量导出
  59 + 锁件批量导出
62 60 </Button>
63 61 <Button
64 62 type="primary"
65   - icon={<PlusOutlined />}
66   - onClick={() => { setVisible(true); setIsadd(true); }}
67   - style={{ marginLeft: 10}}
  63 + icon={<DownloadOutlined />}
  64 + onClick={() => setMore(true)}
  65 + style={{marginLeft: 10}}
68 66 >
69   - 新增
  67 + 库存批量导出
70 68 </Button>
71 69 </div>
72 70 </div>
... ...
src/pages/pms/storage/partShop/interface.d.ts
... ... @@ -21,7 +21,8 @@ declare namespace PmsStoragePartShop {
21 21 actualStock?: number,
22 22 shopId?: number, // 服务站ID
23 23 shopName?: string // 服务站名称
24   - isOut?: boolean
  24 + isOut?: boolean,
  25 + isLock?:boolean
25 26 }
26 27  
27 28 interface Params {
... ... @@ -77,6 +78,7 @@ declare namespace PmsStoragePartShop {
77 78 isOut?: boolean, // 出入库
78 79 current?: number
79 80 pageSize?:number
  81 + isLock?:boolean // 锁库 ?释放
80 82 }
81 83  
82 84 /**
... ...
src/pages/pms/transfer/HuolalaSetting/api.ts 0 → 100644
  1 +import { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { PMS_HOST, HOST } from '@/utils/host';
  4 +
  5 +export interface ListVO{
  6 + /**
  7 + * 财务账户信息id
  8 + */
  9 + id?:number
  10 + /**
  11 + * 往来单位id
  12 + */
  13 + supplierId?:number
  14 + /**
  15 + * 往来单位名称
  16 + */
  17 + supplierName?:string
  18 + /**
  19 + * 签约门店id
  20 + */
  21 + shopId?:number
  22 + /**
  23 + * 签约门店名称
  24 + */
  25 + shopName?:string;
  26 + /**
  27 + * 当前余额
  28 + */
  29 + amount?:number;
  30 + /**
  31 + * 待到账金额
  32 + */
  33 + awaitAmount?:number;
  34 + /**
  35 + * 低余额推待办
  36 + */
  37 + minAmount?:number;
  38 + /**
  39 + * 推待办角色编码
  40 + */
  41 + roleCode?:string;
  42 + /**
  43 + * 推待办角色名称
  44 + */
  45 + roleName?:string;
  46 + /**
  47 + * 发单账号
  48 + */
  49 + account?:string;
  50 + /**
  51 + * 集团id
  52 + */
  53 + groupId?:number;
  54 + /**
  55 + * 创建时间
  56 + */
  57 + time?:string;
  58 +}
  59 +interface Params{
  60 + current?:number,
  61 + pageSize?:number
  62 +}
  63 +export interface saveParams{
  64 + //财务账户信息id
  65 + id?:number;
  66 + /**
  67 + * 往来单位id
  68 + */
  69 + supplierId?:number;
  70 + /**
  71 + * 往来单位名称
  72 + */
  73 + supplierName?:string;
  74 + /**
  75 + * 签约门店id
  76 + */
  77 + shopId?:number;
  78 + /**
  79 + * 低余额推待办
  80 + */
  81 + minAmount?:number;
  82 + /**
  83 + * 推待办角色编码
  84 + */
  85 + roleCode?:string;
  86 + /**
  87 + * 推待办角色名称
  88 + */
  89 + roleName?:string;
  90 + /**
  91 + * 发单账号
  92 + */
  93 + // @NotBlank(message = "发单账号不能为空")
  94 + account?:string;
  95 +}
  96 +interface queryList {
  97 + current?:number
  98 + pageSize?:number
  99 + sysId?:number
  100 +}
  101 +// 查询财务账户信息列表
  102 +export function getList(params: Params):http.PromisePageResp<ListVO> {
  103 + return request.get(`${PMS_HOST}/erp/finance/account/get/page`, {params});
  104 +}
  105 +// 新增/编辑API
  106 +export function saveApi(params: saveParams) {
  107 + return request.post(`${PMS_HOST}/erp/finance/account/exit`, {...params});
  108 +}
  109 +// 推待办角色列表
  110 +export function roleListApi(params: queryList): http.PromisePageResp<Role.Info> {
  111 + return request.get(`${HOST}/role/list`, { params });
  112 +}
  113 +// 删除API
  114 +export function deleteApi(params: {id: number}) {
  115 + return request.post(`${PMS_HOST}/erp/finance/account/delete`, {...params});
  116 +}
0 117 \ No newline at end of file
... ...
src/pages/pms/transfer/HuolalaSetting/components/AddModal.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import {Form, Button, InputNumber, Modal, message, Input } from 'antd';
  3 +import PmsSelect from '@/pages/pms/comonents/PmsSelect';
  4 +import { ListVO, saveApi, roleListApi } from '../api';
  5 +import { getPageListApi, Item as item } from "@/pages/pms/partPlan/PlanSupplier/api";
  6 +import {getShopApi} from '@/pages/pms/storage/partShop/api';
  7 +import usePagination from '@/hooks/usePagination';
  8 +import useInitail from '@/hooks/useInitail';
  9 +
  10 +const Item = Form.Item;
  11 +
  12 +interface Props{
  13 + visible?:boolean,
  14 + onCancel: Function,
  15 + item?:ListVO
  16 +}
  17 +
  18 +export default function Index(props:Props) {
  19 + const { list: suppliers } = usePagination<item>(getPageListApi, { supplierType: 40, pageSize: 500 });
  20 + const { data: shops } = useInitail<PmsStoragePartShop.Option[], {}>(getShopApi, [], {});
  21 + const { list } = usePagination<Role.Info>(roleListApi, { pageSize: 500, sysId: 229 });
  22 + const [loading, setLoading] = useState(false);
  23 + const { visible, onCancel, item } = props;
  24 + const [form] = Form.useForm();
  25 +
  26 + useEffect(() => {
  27 + if (visible && item?.id) {
  28 + form.setFieldsValue({
  29 + supplierId: item.supplierId,
  30 + shopId: item.shopId,
  31 + minAmount: item.minAmount,
  32 + roleCode: item.roleCode,
  33 + account: item.account
  34 + });
  35 + }
  36 + if (!visible) {
  37 + form.resetFields();
  38 + }
  39 + }, [visible]);
  40 +
  41 + const onSave = () => {
  42 + form.validateFields().then(files => {
  43 + const params = {
  44 + id: item?.id,
  45 + supplierId: files.supplierId,
  46 + supplierName: suppliers.find(i => i.supplierId == files.supplierId)?.supplierName,
  47 + shopId: files.shopId,
  48 + minAmount: files.minAmount,
  49 + roleCode: files.roleCode,
  50 + roleName: list.find(i => i.roleCode == files.roleCode)?.roleName,
  51 + account: files.account
  52 + };
  53 + setLoading(true);
  54 + saveApi(params).then(res => {
  55 + message.success("保存成功");
  56 + setLoading(false);
  57 + onCancel();
  58 + }).catch(e => {
  59 + message.error(e.message);
  60 + setLoading(false);
  61 + });
  62 + });
  63 + };
  64 +
  65 + return (
  66 + <Modal
  67 + title={item?.id ? "编辑货拉拉账户配置" : "新增货拉拉账户配置"}
  68 + visible={visible}
  69 + maskClosable={false}
  70 + onCancel={() => onCancel()}
  71 + footer={[
  72 + <Button loading={loading} onClick={() => onCancel()}>取消</Button>,
  73 + <Button loading={loading} type="primary" htmlType="submit" onClick={() => onSave()}>保存</Button>
  74 + ]}
  75 + >
  76 + <Form
  77 + form={form}
  78 + labelCol={{span: 5}}
  79 + wrapperCol={{span: 12}}
  80 + >
  81 + <Item label="往来单位" name="supplierId" rules={[{required: true, message: "请选择往来单位"}]}>
  82 + <PmsSelect
  83 + placeholder="选择往来单位"
  84 + options={suppliers.filter((item, index, self) => {
  85 + return self.findIndex(el => el.supplierId == item.supplierId) === index;
  86 + }).map((item) => ({ value: item.supplierId, label: item.supplierName }))}
  87 + />
  88 + </Item>
  89 + <Item label="签约门店" name="shopId" rules={[{ required: true, message: "请选择签约门店" }]}>
  90 + <PmsSelect
  91 + placeholder="选择签约门店"
  92 + options={shops.map((item: PmsStoragePartShop.Option) => ({ value: item.id, label: item.name }))}
  93 + />
  94 + </Item>
  95 + <Item label="推待办余额" name="minAmount" rules={[{ required: true, message: "请填写金额" }]}>
  96 + <InputNumber style={{width: '100%'}} addonAfter="元" />
  97 + </Item>
  98 + <Item label="推待办角色" name="roleCode" rules={[{ required: true, message: "请选择推办角色" }]}>
  99 + <PmsSelect
  100 + placeholder="选择待办角色"
  101 + options={list.map(item => ({value: item.roleCode, label: item.roleName}))}
  102 + />
  103 + </Item>
  104 + <Item label="发单账号" name="account" rules={[{ required: true, message: "请填写发单账号" }]}>
  105 + <Input />
  106 + </Item>
  107 + </Form>
  108 + </Modal>
  109 + );
  110 +}
... ...
src/pages/pms/transfer/HuolalaSetting/components/ChargeModal.tsx 0 → 100644
  1 +import React from 'react';
  2 +import { Form, Button, InputNumber, Modal } from 'antd';
  3 +import PmsSelect from '@/pages/pms/comonents/PmsSelect';
  4 +
  5 +const Item = Form.Item;
  6 +
  7 +interface Props {
  8 + visible?: boolean,
  9 + onCancel: Function,
  10 + item?: any
  11 +}
  12 +export default function Index(props: Props) {
  13 + const { visible, onCancel, item } = props;
  14 + const [form] = Form.useForm();
  15 +
  16 + const onSave = () => {
  17 + const params = {id: item.id};
  18 + console.log(params);
  19 + };
  20 +
  21 + return (
  22 + <Modal
  23 + title="预付款充值申请"
  24 + visible={visible}
  25 + maskClosable={false}
  26 + onCancel={() => onCancel()}
  27 + footer={[
  28 + <Button onClick={() => onCancel()}>取消</Button>,
  29 + <Button type="primary" htmlType="submit" onClick={() => onSave()}>提交申请</Button>
  30 + ]}
  31 + >
  32 + <Form
  33 + form={form}
  34 + labelCol={{ span: 7 }}
  35 + wrapperCol={{ span: 12 }}
  36 + >
  37 + <Item label="往来单位" name="supplierName" rules={[{ required: true, message: "请选择往来单位" }]}>
  38 + <PmsSelect />
  39 + </Item>
  40 + <Item label="往来单位类型" name="shopName" rules={[{ required: true, message: "请选择签约门店" }]}>
  41 + <PmsSelect />
  42 + </Item>
  43 + <Item label="账户余额" name="amount" rules={[{ required: true, message: "请填写金额" }]}>
  44 + <InputNumber style={{ width: '100%' }} addonAfter="元" disabled />
  45 + </Item>
  46 + <Item label="充值金额" name="awaitAmount" rules={[{ required: true, message: "请填写金额" }]}>
  47 + <InputNumber style={{ width: '100%' }} addonAfter="元" />
  48 + </Item>
  49 + <Item label="账户到账金额" name="awaitAmount" rules={[{ required: true, message: "请填写金额" }]}>
  50 + <InputNumber style={{ width: '100%' }} addonAfter="元" disabled />
  51 + </Item>
  52 + <Item label="结算门店" name="shopName" rules={[{ required: true, message: "请选择推办角色" }]}>
  53 + <PmsSelect />
  54 + </Item>
  55 + <Item label="发票金额要求比例" name="role" rules={[{ required: true, message: "请选择推办角色" }]}>
  56 + <PmsSelect />
  57 + </Item>
  58 + <Item label="结算方式" name="role" rules={[{ required: true, message: "请选择推办角色" }]}>
  59 + <PmsSelect />
  60 + </Item>
  61 + <Item label="附件" name="files">
  62 + <PmsSelect />
  63 + </Item>
  64 + </Form>
  65 + </Modal>
  66 + );
  67 +}
... ...
src/pages/pms/transfer/HuolalaSetting/index.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { Card, Button, Table, Divider, Popconfirm, message } from 'antd';
  3 +import { PageHeaderWrapper } from '@ant-design/pro-layout';
  4 +import AddModal from './components/AddModal';
  5 +import ChargeModal from './components/ChargeModal';
  6 +import {getList, ListVO, deleteApi} from './api';
  7 +import usePagination from '@/hooks/usePagination';
  8 +
  9 +const Column = Table.Column;
  10 +export default function Index() {
  11 + const {list, loading, paginationConfig, setParams} = usePagination<ListVO>(getList, [], {});
  12 + const [current, setCurrent] = useState<{ visible: boolean, item: ListVO }>({visible: false, item: {}});
  13 + const [chargeInfo, setChargeInfo] = useState<{ visible: boolean, item: ListVO }>({visible: false, item: {}});
  14 + const data = [{id: 1, supplierName: "货拉拉", shopName: "不过承诺书可能单纯迪士尼才", amount: 3000, minAmount: 1500, roleName: "计划制定员", account: "15725173,16638183"}];
  15 + return (
  16 + <PageHeaderWrapper title="货拉拉账户配置">
  17 + <Card
  18 + extra={<Button type="primary" onClick={() => setCurrent({visible: true, item: {}})}>新增</Button>}
  19 + >
  20 + <Table dataSource={data} rowKey="id" loading={loading} pagination={paginationConfig}>
  21 + <Column title="往来单位" dataIndex="supplierName" />
  22 + <Column title="签约门店" dataIndex="shopName" />
  23 + <Column title="当前余额(元)" dataIndex="amount" />
  24 + <Column title="低余额推待办(元)" dataIndex="minAmount" />
  25 + <Column title="推待办角色" dataIndex="roleName" />
  26 + <Column title="发单账号" dataIndex="account" />
  27 + <Column
  28 + title="操作"
  29 + render={r => (
  30 + <div style={{display: 'flex', flexWrap: 'wrap', alignItems: 'center'}}>
  31 + <a onClick={() => setChargeInfo({visible: true, item: r})}>预付款充值申请</a>
  32 + <Divider type="vertical" />
  33 + <a onClick={() => setCurrent({visible: true, item: r})}>编辑</a>
  34 + <Divider type="vertical" />
  35 + <Popconfirm
  36 + title="确认删除"
  37 + onConfirm={() => {
  38 + deleteApi({id: r.id}).then(res => {
  39 + message.success('操作成功');
  40 + setParams({}, true);
  41 + }).catch(e => message.error(e.message));
  42 + }}
  43 + >
  44 + <a>删除</a>
  45 + </Popconfirm>
  46 + </div>
  47 + )}
  48 + />
  49 + </Table>
  50 + <AddModal visible={current.visible} item={current.item} onCancel={() => setCurrent({ visible: false, item: {} })} />
  51 + <ChargeModal visible={chargeInfo.visible} item={chargeInfo.item} onCancel={() => setChargeInfo({ visible: false, item: {} })} />
  52 + </Card>
  53 + </PageHeaderWrapper>
  54 + );
  55 +}
... ...
src/pages/pms/transfer/transferPool/comonents/Filiter.tsx
... ... @@ -26,9 +26,9 @@ export default function Index() {
26 26 <Input.Search
27 27 allowClear
28 28 enterButton
29   - placeholder="输入关键词进行搜索"
  29 + placeholder="输入关键词搜索"
30 30 onSearch={(value, event) => setParams({keywords: value}, true)}
31   - style={{ width: 220, marginRight: 10 }}
  31 + style={{ width: 200, marginRight: 10, marginBottom: 10 }}
32 32 />
33 33 <PmsSelect
34 34 style={{width: 200, marginRight: 10}}
... ...