Commit 500d928d4fb00c1a260fd4a7cbc12782b5f8fe7b

Authored by 张志伟
2 parents 11117108 db42ca00

Merge branch 'pms' into 'master'

Pms

预付款账号配置

See merge request !203
src/pages/pms/comonents/ImageUpload.tsx 0 → 100644
  1 +import { PlusOutlined } from '@ant-design/icons';
  2 +import { Modal, Upload, message } from 'antd';
  3 +import type { RcFile } from 'antd/es/upload';
  4 +import type { UploadFile } from 'antd/es/upload/interface';
  5 +import React, { useEffect, useState } from 'react';
  6 +import { UploadChangeParam } from 'antd/lib/upload';
  7 +
  8 +interface Props{
  9 + max?:number // 限制上传的数量
  10 + onChange?: (info: string[]) => any, //上传文件改变时的回调
  11 + value?: string[] // 上传成功后后端返回的文件地址 eg: "ea47b5706a874fbc91bd45cb142eeb55"
  12 + disabled?: boolean
  13 +}
  14 +
  15 +function Index(props: Props) {
  16 + const { max = 1, onChange, value = [], disabled= false } = props;
  17 + const [previewOpen, setPreviewOpen] = useState(false);
  18 + const [previewImage, setPreviewImage] = useState('');
  19 + const [fileList, setFileList] = useState<UploadFile[]>([]);
  20 +
  21 + useEffect(() => {
  22 + setFileList(value.map(i => (
  23 + {
  24 + uid: i,
  25 + name: i,
  26 + status: 'done',
  27 + url: `/api/file/show?fid=${i}`,
  28 + }
  29 + )));
  30 + }, [value.length]);
  31 +
  32 + const getBase64 = (file: RcFile): Promise<string> => new Promise((resolve, reject) => {
  33 + const reader = new FileReader();
  34 + reader.readAsDataURL(file);
  35 + reader.onload = () => resolve(reader.result as string);
  36 + reader.onerror = error => reject(error);
  37 + });
  38 +// 预览图片
  39 + const handlePreview = async (file: UploadFile) => {
  40 + if (!file.url && !file.preview) {
  41 + file.preview = await getBase64(file.originFileObj as RcFile);
  42 + }
  43 +
  44 + setPreviewImage(file.url || (file.preview as string));
  45 + setPreviewOpen(true);
  46 + };
  47 +// 关闭预览
  48 + const handleCancel = () => setPreviewOpen(false);
  49 +// 上传文件改变
  50 + function handleChange(info: UploadChangeParam) {
  51 + const { file: { status, response }, fileList } = info;
  52 + if (status !== 'uploading' && response) {
  53 + const { success, result, data } = response;
  54 + if (status === 'done' && success) {
  55 + onChange && onChange([...value, data]);
  56 + } else if (response && !success) {
  57 + message.error(`${info.file.name} 上传失败: ${result}`);
  58 + }
  59 + }
  60 + setFileList(fileList);
  61 + }
  62 +// 移除文件
  63 + function handleRemove(file: any) {
  64 + const files = fileList.filter(i => i.uid != file.uid);
  65 + const fids = files.map(i => i.uid);
  66 + onChange && onChange(fids);
  67 + }
  68 +
  69 + const uploadButton = (
  70 + <div>
  71 + <PlusOutlined />
  72 + <div style={{ marginTop: 8 }}>上传</div>
  73 + </div>
  74 + );
  75 + return (
  76 + <div>
  77 + <Upload
  78 + action="/api/file/upload"
  79 + listType="picture-card"
  80 + disabled={disabled}
  81 + fileList={fileList}
  82 + onPreview={handlePreview}
  83 + onChange={handleChange}
  84 + onRemove={handleRemove}
  85 + >
  86 + {fileList.length >= max ? null : uploadButton}
  87 + </Upload>
  88 + <Modal open={previewOpen} footer={null} onCancel={handleCancel}>
  89 + <img alt="example" style={{ width: '100%' }} src={previewImage} />
  90 + </Modal>
  91 + </div>
  92 + );
  93 +}
  94 +
  95 +export default Index;
0 96 \ No newline at end of file
... ...
src/pages/pms/partPlan/PlanManage/subpages/Apply/index.tsx
... ... @@ -16,7 +16,7 @@ import {groupBys, flattenDeep} from &#39;@/pages/pms/entity&#39;;
16 16 import {PartDetail} from '../../api';
17 17 import { history } from 'umi';
18 18 import { getDetail, Params as detailParams, Item } from '../Detail/api';
19   -import ImageUpload from '@/pages/decoration/deco/DeoGoodsManagement/components/ImageUpload';
  19 +import ImageUpload from '@/pages/pms/comonents/ImageUpload';
20 20  
21 21 const { Option } = Select;
22 22 const apiObj: { [key: number]: any } = {
... ... @@ -40,7 +40,6 @@ export default function Index() {
40 40 const [visiblePartDetail, setVisiblePartDetail] = useState(false);
41 41 const partList = flattenDeep(dealerList.map(it => (it.suppliers || []).map((su: any) => (su.storages || []).map((st: any) => (st.parts || [])))));
42 42 const poolIds = partList.map((it: any) => it.poolId);
43   - const [imageVisible, setImageVisible] = useState(true);
44 43 const [info, setInfo] = useState<{ remark?: string, fids?: any }>();
45 44  
46 45 useEffect(() => {
... ... @@ -52,12 +51,11 @@ export default function Index() {
52 51  
53 52 useEffect(() => {
54 53 if (data.list?.length) {
55   - setImageVisible(false);
56 54 setDfParams({brandId: data.list[0].brandId});
57 55 setParams({}, true);
58 56 setDelay(false);
59 57 setDealerList(data.list);
60   - setInfo({ remark: data.remark, fids: data.fids?.split(',').map(i => `/api/file/show?fid=${i}`) });
  58 + setInfo({ remark: data.remark, fids: data.fids?.split(',') });
61 59 }
62 60 }, [data.list?.length]);
63 61  
... ... @@ -180,13 +178,7 @@ export default function Index() {
180 178 ...dfParams,
181 179 suppliers,
182 180 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()
  181 + fids: info?.fids.join()
190 182 }).then(() => {
191 183 setLoading(false);
192 184 history.goBack();
... ... @@ -200,61 +192,63 @@ export default function Index() {
200 192 <PageHeaderWrapper title="配件计划管理">
201 193 <ConfigProvider locale={zhCN}>
202 194 <Card className={st.page}>
203   - <div style={{ display: 'flex', flexDirection: 'column', marginTop: 20, marginBottom: 20 }}>
204   - <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
205   - <Select
206   - placeholder="请选择品牌"
207   - onSearch={() => {}}
208   - showSearch
209   - filterOption={(input: any, option: any) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
210   - style={{ width: 200, marginBottom: 20 }}
211   - value={dfParams.brandId}
212   - onChange={brandId => {
  195 + <div style={{ display: 'flex', alignItems: 'flex-start', marginBottom: 20 }}>
  196 + <span style={{ marginRight: 10 }}>配件:</span>
  197 + <div style={{ display: 'flex', flexDirection: 'column' }}>
  198 + <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
  199 + <Select
  200 + placeholder="请选择品牌"
  201 + onSearch={() => {}}
  202 + showSearch
  203 + filterOption={(input: any, option: any) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
  204 + style={{ width: 200, marginBottom: 20 }}
  205 + value={dfParams.brandId}
  206 + onChange={brandId => {
213 207 setDfParams({ ...dfParams, brandId });
214 208 setParams({}, true);
215 209 setDelay(false);
216 210 setDealerList([]);
217 211 }}
218   - >
219   - {brands.map((item: any) => (
220   - <Option value={item.id} key={item.id}>
221   - {item.name}
222   - </Option>
  212 + >
  213 + {brands.map((item: any) => (
  214 + <Option value={item.id} key={item.id}>
  215 + {item.name}
  216 + </Option>
223 217 ))}
224   - </Select>
225   - <a
226   - style={{marginLeft: 20, marginBottom: 20}}
227   - onClick={() => {
  218 + </Select>
  219 + <a
  220 + style={{marginLeft: 20, marginBottom: 20}}
  221 + onClick={() => {
228 222 if (!dfParams.brandId) {
229 223 message.error('请选择品牌');
230 224 return;
231 225 }
232 226 setVisibleDealer(true);
233 227 }}
234   - >
235   - 添加采购商家
236   - </a>
237   - </div>
238   - {dealerList.map((dealer: any = {}) => (
239   - <div key={`dealer${dealer.settleDealerId}`} style={{ marginTop: 10 }}>
240   - <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
241   - <div style={{ fontWeight: "bold" }}>{`商家: ${dealer.settleDealerName || ''}`}</div>
242   - <a style={{marginLeft: 40}} onClick={() => { setVisibleSupplier(true); setDealer(dealer); }}>
243   - 添加指定供应商
244   - </a>
245   - <Popconfirm
246   - title="是否删除"
247   - onConfirm={() => setDealerList(dealerList.filter(it => it.settleDealerId!=dealer.settleDealerId))}
248   - okText="确定"
249   - cancelText="取消"
250   - style={{marginLeft: 20}}
251   - >
252   - <Button type="link" danger>
253   - 删除
254   - </Button>
255   - </Popconfirm>
256   - </div>
257   - {(dealer.suppliers || []).map((supplier: any = {}) => {
  228 + >
  229 + 添加采购商家
  230 + </a>
  231 + </div>
  232 + {dealerList.map((dealer: any = {}) => (
  233 + <div key={`dealer${dealer.settleDealerId}`} style={{ marginTop: 10 }}>
  234 + <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
  235 + <div style={{ fontWeight: "bold" }}>{`商家: ${dealer.settleDealerName || ''}`}</div>
  236 + <a style={{marginLeft: 40}} onClick={() => { setVisibleSupplier(true); setDealer(dealer); }}>
  237 + 添加指定供应商
  238 + </a>
  239 + <Popconfirm
  240 + title="是否删除"
  241 + onConfirm={() => setDealerList(dealerList.filter(it => it.settleDealerId!=dealer.settleDealerId))}
  242 + okText="确定"
  243 + cancelText="取消"
  244 + style={{marginLeft: 20}}
  245 + >
  246 + <Button type="link" danger>
  247 + 删除
  248 + </Button>
  249 + </Popconfirm>
  250 + </div>
  251 + {(dealer.suppliers || []).map((supplier: any = {}) => {
258 252 const paList: any[] = flattenDeep((supplier.storages || []).map((st: any) => (st.parts || [])));
259 253 return (
260 254 <div key={`supplier${supplier.supplierId}`} style={{ marginTop: 10, marginLeft: 40 }}>
... ... @@ -307,50 +301,49 @@ export default function Index() {
307 301 </div>
308 302 );
309 303 })}
310   - </div>
  304 + </div>
311 305 ))}
312   - <DealerModal
313   - dealerList={dealerList}
314   - visible={visibleDealer}
315   - onCancel={() => setVisibleDealer(false)}
316   - onOk={onOkDealer}
317   - />
318   - <SuppModal
319   - brandId={dfParams.brandId}
320   - supplierList={dealer.suppliers || []}
321   - visible={visibleSupplier}
322   - onCancel={() => setVisibleSupplier(false)}
323   - onOk={onOkSupplier}
324   - />
325   - <PartModal
326   - visible={visiblePart}
327   - onCancel={() => setVisiblePart(false)}
328   - parts={parts.filter(it => !poolIds.includes(it.poolId))}
329   - onOk={onOk}
330   - setParams={setParams}
331   - />
332   - <PartDetailModal
333   - visible={visiblePartDetail}
334   - onCancel={() => setVisiblePartDetail(false)}
335   - dealer={dealer.dealer}
336   - supplier={dealer.supplier}
337   - storage={dealer.storage}
338   - deletePart={deletePart}
339   - />
  306 + <DealerModal
  307 + dealerList={dealerList}
  308 + visible={visibleDealer}
  309 + onCancel={() => setVisibleDealer(false)}
  310 + onOk={onOkDealer}
  311 + />
  312 + <SuppModal
  313 + brandId={dfParams.brandId}
  314 + supplierList={dealer.suppliers || []}
  315 + visible={visibleSupplier}
  316 + onCancel={() => setVisibleSupplier(false)}
  317 + onOk={onOkSupplier}
  318 + />
  319 + <PartModal
  320 + visible={visiblePart}
  321 + onCancel={() => setVisiblePart(false)}
  322 + parts={parts.filter(it => !poolIds.includes(it.poolId))}
  323 + onOk={onOk}
  324 + setParams={setParams}
  325 + />
  326 + <PartDetailModal
  327 + visible={visiblePartDetail}
  328 + onCancel={() => setVisiblePartDetail(false)}
  329 + dealer={dealer.dealer}
  330 + supplier={dealer.supplier}
  331 + storage={dealer.storage}
  332 + deletePart={deletePart}
  333 + />
  334 + </div>
340 335 </div>
341 336 <div style={{display: 'flex', alignItems: 'flex-start', marginBottom: 20}}>
342 337 <span style={{marginRight: 10}}>备注:</span>
343   - <Input.TextArea rows={2} style={{ width: 250 }} value={info?.remark} onChange={e => setInfo({...info, remark: e.target.value})} />
  338 + <Input.TextArea rows={4} style={{ width: 250 }} value={info?.remark} onChange={e => setInfo({...info, remark: e.target.value})} />
344 339 </div>
345 340 <div style={{ display: 'flex', alignItems: 'flex-start' }}>
346 341 <span style={{ marginRight: 10 }}>附件:</span>
347 342 <ImageUpload
348   - length={6}
349   - clear={imageVisible}
  343 + max={6}
350 344 value={info?.fids}
351   - onChange={v => {
352   - const ids = v.fileList.map(it => it?.response?.data || it);
353   - setInfo({ ...info, fids: ids });
  345 + onChange={v => {
  346 + setInfo({ ...info, fids: v });
354 347 }}
355 348 />
356 349 </div>
... ... @@ -359,7 +352,7 @@ export default function Index() {
359 352 disabled={loading}
360 353 loading={loading}
361 354 style={{marginRight: 20}}
362   - onClick={() => { setImageVisible(true); history.goBack(); }}
  355 + onClick={() => { history.goBack(); }}
363 356 >
364 357 取消
365 358 </Button>
... ...
src/pages/pms/partPlan/PlanManage/subpages/Detail/index.tsx
1   -import { Card, ConfigProvider, Spin, Upload } from 'antd';
  1 +import { Card, ConfigProvider, Spin } 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";
... ... @@ -11,6 +11,7 @@ import {common} from &quot;@/typing/common&quot;;
11 11 import {flattenDeep} from "@/pages/pms/entity";
12 12 import {sum} from "lodash";
13 13 import PartDetailModal from './components/PartDetailModal';
  14 +import ImageUpload from '@/pages/pms/comonents/ImageUpload';
14 15  
15 16 export default function Index({ match }: common.ConnectProps) {
16 17 const { planId } = match.params;
... ... @@ -62,20 +63,7 @@ export default function Index({ match }: common.ConnectProps) {
62 63 </div>
63 64 <div style={{ display: 'flex', alignItems: 'flex-start' }}>
64 65 <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>
  66 + <ImageUpload value={data.fids?.split(',')} disabled />
79 67 </div>
80 68 <PartDetailModal visible={visiblePart} onCancel={() => setVisiblePart(false)} parts={parts} />
81 69 <StepBnt
... ...
src/pages/pms/purchase/PurchaseRecord/comonents/PayApplyModal.tsx
1 1 import React, {useEffect, useState} from 'react';
2 2 import {Modal, Form, Input, Button, message, DatePicker} from 'antd';
3 3 import {RightOutlined} from '@ant-design/icons';
4   -import ImageUpload from '@/pages/decoration/deco/DeoGoodsManagement/components/ImageUpload';
  4 +import ImageUpload from '@/pages/pms/comonents/ImageUpload';
5 5 import {purchasePayApply, PageV0} from '../api';
6 6 import PurchasePartModal from './PurchasePartModal';
7 7  
... ... @@ -14,7 +14,6 @@ interface Props{
14 14 export default function Index(props:Props) {
15 15 const [form] = Form.useForm();
16 16 const {visible, onCancel, item} = props;
17   - const [imageVisible, setImageVisible] = useState(true);
18 17 const [btnloading, setBtnloading] = useState(false);
19 18 const [partVisible, setPartVisible] = useState(false);
20 19 const [itemPurchaseId, setItemPurchaseId] = useState<number>();
... ... @@ -44,7 +43,7 @@ export default function Index(props:Props) {
44 43 payAmount: fileds.payAmount,
45 44 payDays: fileds.payDays.format('YYYY-MM-DD'),
46 45 remark: fileds.remark || undefined,
47   - fids: (!!fileds.fids && fileds.fids.fileList.map((i:any) => i.response.data)) || undefined
  46 + fids: fileds.fids
48 47 };
49 48  
50 49 purchasePayApply(params).then(res => {
... ... @@ -66,7 +65,7 @@ export default function Index(props:Props) {
66 65 maskClosable={false}
67 66 width={600}
68 67 footer={[
69   - <Button loading={btnloading} onClick={() => { onCancel(); setImageVisible(false); }}>取消</Button>,
  68 + <Button loading={btnloading} onClick={() => { onCancel(); }}>取消</Button>,
70 69 <Button
71 70 loading={btnloading}
72 71 type="primary"
... ... @@ -131,7 +130,7 @@ export default function Index(props:Props) {
131 130 <span style={{color: "#0000FF", cursor: "pointer"}} onClick={() => { setPartVisible(true); setItemPurchaseId(item?.purchaseId); }}>查看<RightOutlined /></span>
132 131 </Item>
133 132 <Item label="附件" name="fids">
134   - <ImageUpload length={6} clear={imageVisible} />
  133 + <ImageUpload max={6} />
135 134 </Item>
136 135 </Form>
137 136 <PurchasePartModal itemPurchaseId={itemPurchaseId} visible={partVisible} onCancel={() => setPartVisible(false)} />
... ...
src/pages/pms/storage/StorageManage/subpages/LocationManage/index.tsx
... ... @@ -39,7 +39,6 @@ export default function RepertoryIndex({ match }: common.ConnectProps) {
39 39 <Search
40 40 allowClear
41 41 placeholder="根据件号|编码|名称|库位"
42   - onChange={(e) => _onChange({ keyword: e.target.value })}
43 42 onSearch={(value) => _onChange({ keywords: value })}
44 43 style={{ maxWidth: 300 }}
45 44 />
... ... @@ -60,7 +59,7 @@ export default function RepertoryIndex({ match }: common.ConnectProps) {
60 59 <ItemDetailModal
61 60 storageId={id}
62 61 visible={view}
63   - onCancel={() => { setView(false) }}
  62 + onCancel={() => { setView(false); }}
64 63 fetchList={() => setLoading(true)}
65 64 />
66 65 <UploadModal
... ... @@ -68,7 +67,7 @@ export default function RepertoryIndex({ match }: common.ConnectProps) {
68 67 pagination={paginationConfig}
69 68 loading={loading}
70 69 visible={visible}
71   - onCancel={() => { setVisible(false) }}
  70 + onCancel={() => { setVisible(false); }}
72 71 setParams={setParams}
73 72 />
74 73 <UploadMoreModal
... ...
src/pages/pms/storage/areaStorageSetting/index.tsx
... ... @@ -9,7 +9,6 @@ import CreatModal from &#39;./components/CreateModal&#39;;
9 9 import * as api from '../StorageManage/api';
10 10  
11 11 function AreaStorageSetting() {
12   - // 获取仓库信息
13 12 const { list: storageList } = usePagination<any>(api.getStoragePage);
14 13  
15 14 const { list, loading, setLoading, paginationConfig, setParams } = usePagination<AreaStorageSettingSpace.item>(getAreaStorageList, { current: 1, pageSize: 10 });
... ...
src/pages/pms/storage/partShop/components/StorageFlowModal.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Modal, Button, Select, DatePicker, message } from 'antd';
  3 +import { getList } from './api';
  4 +import useInitial from "@/hooks/useInitail";
  5 +import { useStore } from '../index';
  6 +import moment from 'moment';
  7 +
  8 +interface Props {
  9 + visible: boolean,
  10 + onCancel: () => any,
  11 +}
  12 +const Option = Select.Option;
  13 +export default function Upload(props: Props) {
  14 + const { storages: storageList } = useStore();
  15 + const { visible, onCancel } = props;
  16 + const [storageid, setStorageid] = useState<number>();
  17 + const [delay, setDelay] = useState(true);
  18 + const { data, setParams, setData } = useInitial(getList, 0, {}, delay);
  19 + const [date, setDate] = useState<{ startTime?: number, endTime?:number }>();
  20 +
  21 + useEffect(() => {
  22 + if (!visible) {
  23 + setStorageid(undefined);
  24 + setDate({startTime: undefined, endTime: undefined});
  25 + setData(0);
  26 + }
  27 + }, [visible]);
  28 +
  29 + return (
  30 + <Modal
  31 + maskClosable
  32 + title="库房流水批量导出"
  33 + visible={visible}
  34 + onCancel={onCancel}
  35 + width={800}
  36 + footer={[
  37 + <Button onClick={onCancel}>取消</Button>,
  38 + ]}
  39 + >
  40 + <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
  41 + <span style={{ paddingLeft: 30 }}>选择库房:</span>
  42 + <Select
  43 + placeholder="请选择库房"
  44 + value={storageid}
  45 + style={{ width: 250 }}
  46 + onChange={setStorageid}
  47 + showSearch
  48 + optionFilterProp="children"
  49 + >
  50 + {storageList.map(it => (
  51 + <Option key={it.id} value={it.id || -1}>{it.storageName || ''}</Option>
  52 + ))}
  53 + </Select>
  54 + </div>
  55 + <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
  56 + <span style={{ paddingLeft: 30 }}>开始时间:</span>
  57 + <DatePicker
  58 + value={date?.startTime && moment(date.startTime) || undefined}
  59 + style={{ width: 250 }}
  60 + onChange={(d, ds) => {
  61 + setDate({ startTime: moment(ds).startOf('day').valueOf(), endTime: undefined });
  62 + }}
  63 + />
  64 + </div>
  65 + <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
  66 + <span style={{ paddingLeft: 30 }}>结束时间:</span>
  67 + <DatePicker
  68 + value={date?.endTime && moment(date.endTime) || undefined}
  69 + style={{ width: 250 }}
  70 + onChange={(d, ds) => {
  71 + if (!storageid || !date?.startTime) {
  72 + message.error("请先选择库房或开始时间");
  73 + return;
  74 + }
  75 + setDate({ ...date, endTime: moment(ds).startOf('day').valueOf() });
  76 + setDelay(false);
  77 + setParams({
  78 + storageId: storageid,
  79 + }, true);
  80 + }}
  81 + />
  82 + </div>
  83 + <div style={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap' }}>
  84 + {!!data && (
  85 + <a
  86 + href={`/api/pms/erp/storage/out/export/stock/record?storageId=${storageid}&startTime=${date?.startTime}&endTime=${date?.endTime}`}
  87 + style={{ marginRight: 20, marginBottom: 10 }}
  88 + target="_blank"
  89 + rel="noopener noreferrer"
  90 + >
  91 + {`${storageList.find(it => it.id == storageid)?.storageName}流水记录.xlsx`}
  92 + </a>
  93 + )}
  94 + </div>
  95 + </Modal>
  96 + );
  97 +}
0 98 \ No newline at end of file
... ...
src/pages/pms/storage/partShop/components/UploadMoreModal.tsx
... ... @@ -17,7 +17,7 @@ export default function Upload(props: Props) {
17 17 const [storageid, setStorageid] = useState<number>();
18 18 const [storageName, setStorageName] = useState<string>();
19 19 const [delay, setDelay] = useState(true);
20   - const { data: total, setParams } = useInitial(getList, 0, storageid, delay);
  20 + const { data: total, setParams } = useInitial(getList, 0, {}, delay);
21 21 const [pagesize, setPagesize] = useState(1000);
22 22 const [list, setList] = useState<number[]>([]);
23 23  
... ... @@ -51,7 +51,7 @@ export default function Upload(props: Props) {
51 51 setStorageid(value);
52 52 setStorageName(storagename?.storageName);
53 53 setDelay(false);
54   - setParams(value, true);
  54 + setParams({storageId: value}, true);
55 55 };
56 56  
57 57 return (
... ...
src/pages/pms/storage/partShop/components/api.tsx
... ... @@ -2,8 +2,8 @@ import request from &#39;@/utils/request&#39;;
2 2 import { PMS_HOST } from '@/utils/host';
3 3 import {http} from "@/typing/http";
4 4  
5   -export function getList(params?: number) {
6   - return request.get(`${PMS_HOST}/erp/part/shop/get/stock/cnt`, {params: {storageId: params}});
  5 +export function getList(params?: { storageId?: number, startTime?:number, endTime?:number}):http.PromiseResp<number> {
  6 + return request.get(`${PMS_HOST}/erp/part/shop/get/stock/cnt`, {params});
7 7 }
8 8 interface Params{
9 9 user:string
... ...
src/pages/pms/storage/partShop/index.tsx
... ... @@ -8,6 +8,7 @@ import store from &#39;./store&#39;;
8 8 import { createStore } from '@/hooks/moz';
9 9 import ImportModal from './components/UploadExcel';
10 10 import UploadMoreModal from './components/UploadMoreModal';
  11 +import StorageFlowModal from './components/StorageFlowModal';
11 12  
12 13 export const { Provider, useStore } = createStore(store);
13 14  
... ... @@ -16,6 +17,7 @@ function PartShop() {
16 17 const [more, setMore] = useState(false);
17 18 const [stock, setStock] = useState(false);
18 19 const [islock, setIslock] = useState(false);
  20 + const [storageFlowVisible, setStorageFlowVisible] = useState(false);
19 21  
20 22 return (
21 23 <PageHeaderWrapper title={`服务站配件${fw ? '(霏微)': ''}`}>
... ... @@ -66,6 +68,14 @@ function PartShop() {
66 68 >
67 69 库存批量导出
68 70 </Button>
  71 + <Button
  72 + type="primary"
  73 + icon={<DownloadOutlined />}
  74 + onClick={() => setStorageFlowVisible(true)}
  75 + style={{marginLeft: 10}}
  76 + >
  77 + 库房流水导出
  78 + </Button>
69 79 </div>
70 80 </div>
71 81 <List />
... ... @@ -76,6 +86,7 @@ function PartShop() {
76 86 islock={islock}
77 87 setIslock={setIslock}
78 88 />
  89 + <StorageFlowModal visible={storageFlowVisible} onCancel={() => setStorageFlowVisible(false)} />
79 90 </Card>
80 91 </PageHeaderWrapper>
81 92 );
... ...
src/pages/pms/transfer/HuolalaSetting/api.ts
... ... @@ -96,7 +96,6 @@ export interface saveParams{
96 96 interface queryList {
97 97 current?:number
98 98 pageSize?:number
99   - sysId?:number
100 99 }
101 100 // 查询财务账户信息列表
102 101 export function getList(params: Params):http.PromisePageResp<ListVO> {
... ... @@ -104,7 +103,7 @@ export function getList(params: Params):http.PromisePageResp&lt;ListVO&gt; {
104 103 }
105 104 // 新增/编辑API
106 105 export function saveApi(params: saveParams) {
107   - return request.post(`${PMS_HOST}/erp/finance/account/exit`, {...params});
  106 + return request.post(`${PMS_HOST}/erp/finance/account/save`, {...params});
108 107 }
109 108 // 推待办角色列表
110 109 export function roleListApi(params: queryList): http.PromisePageResp<Role.Info> {
... ... @@ -112,5 +111,5 @@ export function roleListApi(params: queryList): http.PromisePageResp&lt;Role.Info&gt;
112 111 }
113 112 // 删除API
114 113 export function deleteApi(params: {id: number}) {
115   - return request.post(`${PMS_HOST}/erp/finance/account/delete`, {...params});
  114 + return request.post(`${PMS_HOST}/erp/finance/account/delete`, {...params}, {contentType: 'form-urlencoded'});
116 115 }
117 116 \ No newline at end of file
... ...
src/pages/pms/transfer/HuolalaSetting/components/AccountModal.tsx 0 → 100644
  1 +import React, { useEffect } from 'react';
  2 +import { Form, Button, Modal, Input } from 'antd';
  3 +
  4 +const Item = Form.Item;
  5 +
  6 +interface Props {
  7 + visible?: boolean,
  8 + onCancel: Function,
  9 + onOk: Function,
  10 + accounts: string[]
  11 +}
  12 +
  13 +export default function Index(props: Props) {
  14 + const { visible, onCancel, onOk, accounts } = props;
  15 + const [form] = Form.useForm();
  16 +
  17 + useEffect(() => {
  18 + if (!visible) {
  19 + form.resetFields();
  20 + }
  21 + }, [visible]);
  22 +
  23 + const onSave = () => {
  24 + form.validateFields().then(files => {
  25 + onOk(files.account);
  26 + onCancel();
  27 + });
  28 + };
  29 +
  30 + return (
  31 + <Modal
  32 + title="发单账号"
  33 + open={visible}
  34 + maskClosable={false}
  35 + onCancel={() => onCancel()}
  36 + footer={[
  37 + <Button onClick={() => onCancel()}>取消</Button>,
  38 + <Button type="primary" htmlType="submit" onClick={() => onSave()}>确定</Button>
  39 + ]}
  40 + >
  41 + <Form
  42 + form={form}
  43 + labelCol={{ span: 5 }}
  44 + wrapperCol={{ span: 12 }}
  45 + >
  46 + <Item
  47 + label="发单账号"
  48 + name="account"
  49 + rules={[
  50 + { required: true, message: "请填写发单账号" },
  51 + () => ({
  52 + validator(_, value) {
  53 + if (value.length != 11) {
  54 + return Promise.reject(new Error('发单账号不符合要求'));
  55 + } else if (accounts.includes(value)) {
  56 + return Promise.reject(new Error('发单账号重复'));
  57 + }
  58 + return Promise.resolve();
  59 + },
  60 + }),
  61 + ]}
  62 + >
  63 + <Input />
  64 + </Item>
  65 + </Form>
  66 + </Modal>
  67 + );
  68 +}
... ...
src/pages/pms/transfer/HuolalaSetting/components/AddModal.tsx
... ... @@ -2,58 +2,68 @@ import React, { useEffect, useState } from &#39;react&#39;;
2 2 import {Form, Button, InputNumber, Modal, message, Input } from 'antd';
3 3 import PmsSelect from '@/pages/pms/comonents/PmsSelect';
4 4 import { ListVO, saveApi, roleListApi } from '../api';
5   -import { getPageListApi, Item as item } from "@/pages/pms/partPlan/PlanSupplier/api";
  5 +import {getContactUnit, ContactItem} from '@/pages/pms/transfer/transferManage/api';
6 6 import {getShopApi} from '@/pages/pms/storage/partShop/api';
7 7 import usePagination from '@/hooks/usePagination';
8 8 import useInitail from '@/hooks/useInitail';
  9 +import AccountModal from './AccountModal';
9 10  
10 11 const Item = Form.Item;
11 12  
12 13 interface Props{
13 14 visible?:boolean,
14 15 onCancel: Function,
15   - item?:ListVO
  16 + item?:ListVO,
  17 + onRefreshing: Function
16 18 }
17 19  
18 20 export default function Index(props:Props) {
19   - const { list: suppliers } = usePagination<item>(getPageListApi, { supplierType: 40, pageSize: 500 });
20 21 const { data: shops } = useInitail<PmsStoragePartShop.Option[], {}>(getShopApi, [], {});
21   - const { list } = usePagination<Role.Info>(roleListApi, { pageSize: 500, sysId: 229 });
  22 + const { data: suppliers } = useInitail<ContactItem[], { compTypes: number }>(getContactUnit, [], { compTypes: 130});
  23 + const { list } = usePagination<Role.Info>(roleListApi, { pageSize: 500 });
22 24 const [loading, setLoading] = useState(false);
23   - const { visible, onCancel, item } = props;
  25 + const { visible, onCancel, item, onRefreshing } = props;
24 26 const [form] = Form.useForm();
  27 + const [accountVisible, setAccountVisible] = useState(false);
  28 + const [accounts, setAccounts] = useState<string[]>([]);
25 29  
26 30 useEffect(() => {
27 31 if (visible && item?.id) {
  32 + setAccounts(item.account?.split(',') || []);
28 33 form.setFieldsValue({
29 34 supplierId: item.supplierId,
30 35 shopId: item.shopId,
31 36 minAmount: item.minAmount,
32 37 roleCode: item.roleCode,
33   - account: item.account
34 38 });
35 39 }
36 40 if (!visible) {
37 41 form.resetFields();
  42 + setAccounts([]);
38 43 }
39 44 }, [visible]);
40 45  
41 46 const onSave = () => {
  47 + if (!accounts.length) {
  48 + message.error('填写发单账号');
  49 + return;
  50 + }
42 51 form.validateFields().then(files => {
43 52 const params = {
44 53 id: item?.id,
45 54 supplierId: files.supplierId,
46   - supplierName: suppliers.find(i => i.supplierId == files.supplierId)?.supplierName,
  55 + supplierName: suppliers.find(i => i.id == files.supplierId)?.compName,
47 56 shopId: files.shopId,
48 57 minAmount: files.minAmount,
49 58 roleCode: files.roleCode,
50 59 roleName: list.find(i => i.roleCode == files.roleCode)?.roleName,
51   - account: files.account
  60 + account: accounts.join()
52 61 };
53 62 setLoading(true);
54 63 saveApi(params).then(res => {
55 64 message.success("保存成功");
56 65 setLoading(false);
  66 + onRefreshing();
57 67 onCancel();
58 68 }).catch(e => {
59 69 message.error(e.message);
... ... @@ -62,10 +72,15 @@ export default function Index(props:Props) {
62 72 });
63 73 };
64 74  
  75 + const onOk = (v: any) => {
  76 + setAccounts([...accounts, v]);
  77 + };
  78 +
65 79 return (
66 80 <Modal
67 81 title={item?.id ? "编辑货拉拉账户配置" : "新增货拉拉账户配置"}
68   - visible={visible}
  82 + open={visible}
  83 + width={500}
69 84 maskClosable={false}
70 85 onCancel={() => onCancel()}
71 86 footer={[
... ... @@ -81,9 +96,7 @@ export default function Index(props:Props) {
81 96 <Item label="往来单位" name="supplierId" rules={[{required: true, message: "请选择往来单位"}]}>
82 97 <PmsSelect
83 98 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 }))}
  99 + options={suppliers.map((item) => ({ value: item.id, label: item.compName }))}
87 100 />
88 101 </Item>
89 102 <Item label="签约门店" name="shopId" rules={[{ required: true, message: "请选择签约门店" }]}>
... ... @@ -98,13 +111,35 @@ export default function Index(props:Props) {
98 111 <Item label="推待办角色" name="roleCode" rules={[{ required: true, message: "请选择推办角色" }]}>
99 112 <PmsSelect
100 113 placeholder="选择待办角色"
101   - options={list.map(item => ({value: item.roleCode, label: item.roleName}))}
  114 + options={list.filter(i => i.roleType != 1).map(item => ({value: item.roleCode, label: item.roleName}))}
102 115 />
103 116 </Item>
104   - <Item label="发单账号" name="account" rules={[{ required: true, message: "请填写发单账号" }]}>
105   - <Input />
  117 + <Item
  118 + label="发单账号"
  119 + name="account"
  120 + labelCol={{ span: 5 }}
  121 + wrapperCol={{ span: 19 }}
  122 + >
  123 + {accounts.length ? (
  124 + <div>
  125 + {accounts.map((i, index) => (
  126 + <div style={{display: 'flex', alignItems: 'center', marginBottom: 5}} key={i}>
  127 + <Input value={i} disabled style={{width: 226}} />
  128 + <span style={{ color: '#FF4D4F', marginLeft: 10, cursor: 'pointer' }} onClick={() => setAccounts(accounts.filter(it => it != i))}>删除</span>
  129 + {index == accounts.length - 1 && <span style={{ color: '#FAAD14', marginLeft: 10, cursor: 'pointer' }} onClick={() => setAccountVisible(true)}>添加</span>}
  130 + </div>
  131 + ))}
  132 + </div>
  133 + )
  134 + : (
  135 + <div style={{display: 'flex', alignItems: 'center'}}>
  136 + <Input disabled style={{width: 226}} />
  137 + <span style={{ color: '#FAAD14', marginLeft: 10, cursor: 'pointer'}} onClick={() => setAccountVisible(true)}>添加</span>
  138 + </div>
  139 + )}
106 140 </Item>
107 141 </Form>
  142 + <AccountModal visible={accountVisible} onCancel={() => setAccountVisible(false)} onOk={onOk} accounts={accounts} />
108 143 </Modal>
109 144 );
110 145 }
... ...
src/pages/pms/transfer/HuolalaSetting/components/ChargeModal.tsx
1   -import React from 'react';
2   -import { Form, Button, InputNumber, Modal } from 'antd';
  1 +import React, { useEffect } from 'react';
  2 +import { Form, Button, InputNumber, Modal, Input } from 'antd';
3 3 import PmsSelect from '@/pages/pms/comonents/PmsSelect';
  4 +import ImageUpload from '@/pages/pms/comonents/ImageUpload';
  5 +import {ListVO} from '../api';
4 6  
5 7 const Item = Form.Item;
6 8  
7 9 interface Props {
8 10 visible?: boolean,
9 11 onCancel: Function,
10   - item?: any
  12 + item?: ListVO
11 13 }
12 14 export default function Index(props: Props) {
13 15 const { visible, onCancel, item } = props;
14 16 const [form] = Form.useForm();
15 17  
  18 + useEffect(() => {
  19 + if (visible && item?.id) {
  20 + form.setFieldsValue({
  21 + supplierName: item.supplierName,
  22 + amount: item.amount,
  23 + shopName: item.shopName
  24 + });
  25 + }
  26 + if (!visible) {
  27 + form.resetFields();
  28 + }
  29 + }, [visible]);
  30 +
16 31 const onSave = () => {
17   - const params = {id: item.id};
  32 + const params = {id: item?.id};
18 33 console.log(params);
19 34 };
20 35  
21 36 return (
22 37 <Modal
23 38 title="预付款充值申请"
24   - visible={visible}
  39 + open={visible}
25 40 maskClosable={false}
26 41 onCancel={() => onCancel()}
27 42 footer={[
... ... @@ -34,13 +49,13 @@ export default function Index(props: Props) {
34 49 labelCol={{ span: 7 }}
35 50 wrapperCol={{ span: 12 }}
36 51 >
37   - <Item label="往来单位" name="supplierName" rules={[{ required: true, message: "请选择往来单位" }]}>
38   - <PmsSelect />
  52 + <Item label="往来单位" name="supplierName">
  53 + <Input disabled />
39 54 </Item>
40   - <Item label="往来单位类型" name="shopName" rules={[{ required: true, message: "请选择签约门店" }]}>
41   - <PmsSelect />
  55 + <Item label="往来单位类型" name="shopName">
  56 + <Input disabled />
42 57 </Item>
43   - <Item label="账户余额" name="amount" rules={[{ required: true, message: "请填写金额" }]}>
  58 + <Item label="账户余额" name="amount">
44 59 <InputNumber style={{ width: '100%' }} addonAfter="元" disabled />
45 60 </Item>
46 61 <Item label="充值金额" name="awaitAmount" rules={[{ required: true, message: "请填写金额" }]}>
... ... @@ -50,16 +65,16 @@ export default function Index(props: Props) {
50 65 <InputNumber style={{ width: '100%' }} addonAfter="元" disabled />
51 66 </Item>
52 67 <Item label="结算门店" name="shopName" rules={[{ required: true, message: "请选择推办角色" }]}>
53   - <PmsSelect />
  68 + <Input disabled />
54 69 </Item>
55   - <Item label="发票金额要求比例" name="role" rules={[{ required: true, message: "请选择推办角色" }]}>
56   - <PmsSelect />
  70 + <Item label="发票金额要求比例" name="role">
  71 + <Input disabled />
57 72 </Item>
58   - <Item label="结算方式" name="role" rules={[{ required: true, message: "请选择推办角色" }]}>
  73 + <Item label="结算方式" name="role" rules={[{ required: true, message: "请选择结算方式" }]}>
59 74 <PmsSelect />
60 75 </Item>
61 76 <Item label="附件" name="files">
62   - <PmsSelect />
  77 + <ImageUpload max={5} />
63 78 </Item>
64 79 </Form>
65 80 </Modal>
... ...
src/pages/pms/transfer/HuolalaSetting/index.tsx
... ... @@ -11,16 +11,14 @@ export default function Index() {
11 11 const {list, loading, paginationConfig, setParams} = usePagination<ListVO>(getList, [], {});
12 12 const [current, setCurrent] = useState<{ visible: boolean, item: ListVO }>({visible: false, item: {}});
13 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 14 return (
16 15 <PageHeaderWrapper title="货拉拉账户配置">
17 16 <Card
18 17 extra={<Button type="primary" onClick={() => setCurrent({visible: true, item: {}})}>新增</Button>}
19 18 >
20   - <Table dataSource={data} rowKey="id" loading={loading} pagination={paginationConfig}>
  19 + <Table dataSource={list} rowKey="id" loading={loading} pagination={paginationConfig}>
21 20 <Column title="往来单位" dataIndex="supplierName" />
22 21 <Column title="签约门店" dataIndex="shopName" />
23   - <Column title="当前余额(元)" dataIndex="amount" />
24 22 <Column title="低余额推待办(元)" dataIndex="minAmount" />
25 23 <Column title="推待办角色" dataIndex="roleName" />
26 24 <Column title="发单账号" dataIndex="account" />
... ... @@ -28,8 +26,8 @@ export default function Index() {
28 26 title="操作"
29 27 render={r => (
30 28 <div style={{display: 'flex', flexWrap: 'wrap', alignItems: 'center'}}>
31   - <a onClick={() => setChargeInfo({visible: true, item: r})}>预付款充值申请</a>
32   - <Divider type="vertical" />
  29 + {/* <a onClick={() => setChargeInfo({visible: true, item: r})}>预付款充值申请</a>
  30 + <Divider type="vertical" /> */}
33 31 <a onClick={() => setCurrent({visible: true, item: r})}>编辑</a>
34 32 <Divider type="vertical" />
35 33 <Popconfirm
... ... @@ -47,7 +45,7 @@ export default function Index() {
47 45 )}
48 46 />
49 47 </Table>
50   - <AddModal visible={current.visible} item={current.item} onCancel={() => setCurrent({ visible: false, item: {} })} />
  48 + <AddModal visible={current.visible} item={current.item} onCancel={() => setCurrent({ visible: false, item: {} })} onRefreshing={() => setParams({}, true)} />
51 49 <ChargeModal visible={chargeInfo.visible} item={chargeInfo.item} onCancel={() => setChargeInfo({ visible: false, item: {} })} />
52 50 </Card>
53 51 </PageHeaderWrapper>
... ...
src/pages/pms/transfer/transferManage/TransferDetail/index.tsx
... ... @@ -8,7 +8,7 @@ import usePagination from &#39;@/hooks/usePagination&#39;;
8 8 import useInitial from '@/hooks/useInitail';
9 9 import TransferPartDetailModal from './comonents/TransferPartDetailModal';
10 10 import TransferSeqModal from './comonents/TransferSeqModal';
11   -import ImageUpload from '@/pages/decoration/deco/DeoGoodsManagement/components/ImageUpload';
  11 +import ImageUpload from '@/pages/pms/comonents/ImageUpload';
12 12 import SupplierDealer from './comonents/SupplierDealer';
13 13  
14 14 const {Option} = Select;
... ... @@ -48,7 +48,6 @@ export default function Index({onCancel}:any) {
48 48 const [tslist, setTslist]= useState<any[]>([]);
49 49 const [rmark, setRmark] = useState<string>();
50 50 const [btnloading, setBtnloading] = useState(false);
51   - const [imageVisible, setImageVisible] = useState(true);
52 51 const {data: contactList} = useInitial<ContactItem[], {compTypes: number}>(getContactUnit, [], {compTypes: 130});
53 52 const [freight, setFreight] = useState<number>();
54 53 const [clear, setClear] = useState(false);
... ... @@ -72,13 +71,12 @@ export default function Index({onCancel}:any) {
72 71 // 编辑时设置初始值
73 72 useEffect(() => {
74 73 if (editTransfer?.transferId && editTransfer?.transfers?.length) {
75   - setImageVisible(false);
76 74 setTransferList(editTransfer?.transfers?.map(i => ({oSId: i.outStorageId, iSId: i.inStorageId, parts: i.transferPoolIds, freight: i.freightId, supplierId: i.supplierId, payDealerId: i.payDealerId})) || []);
77 75 setMethod(transferMethodid[editTransfer?.method || 0]);
78 76 setChecked(!editTransfer.isReimburse);
79 77 setMethodDetail(editTransfer.transferUserId);
80 78 setTslist(editTransfer?.transferSeqList?.map(i => i.storageId) || []);
81   - form.setFieldsValue({remark: editTransfer.remark, transferfile: editTransfer.fids?.map(i => `/api/file/show?fid=${i}`)});
  79 + form.setFieldsValue({remark: editTransfer.remark, transferfile: editTransfer.fids});
82 80 } else {
83 81 form.resetFields();
84 82 }
... ... @@ -197,18 +195,8 @@ export default function Index({onCancel}:any) {
197 195 amountList: shopList.length && shopList.map(i => ({shopId: i.shopId, proportion: i.proportion})) || undefined, //摊销门店
198 196 transferSeqList: tslist.length && tslist.map((i, index) => ({seq: index, storageId: i})) || undefined, //调运顺序
199 197 remark: rmark || undefined,
200   - fids: fileds.transferfile ? (fileds.transferfile.fileList ?
201   - fileds.transferfile.fileList.map((i:any) => {
202   - if (i.response) {
203   - return i.response.data;
204   - } else {
205   - return i.fid.split('=')[1];
206   - }
207   - })
208   - :
209   - editTransfer?.fids) : undefined
  198 + fids: fileds.transferfile
210 199 };
211   -
212 200 setBtnloading(true);
213 201 submitTransfer(params).then(res => {
214 202 message.success('提交成功');
... ... @@ -406,14 +394,14 @@ return (
406 394 <TextArea value={rmark} onChange={(e) => setRmark(e.target.value)} rows={2} allowClear style={{width: 250, }} />
407 395 </Item>
408 396 <Item name="transferfile" label="附件">
409   - <ImageUpload length={6} clear={imageVisible} />
  397 + <ImageUpload max={6} />
410 398 </Item>
411 399 </Form>
412 400  
413 401 <div style={{display: 'flex', justifyContent: 'center', marginTop: 20}}>
414 402 <Popconfirm
415 403 title="确认放弃?"
416   - onConfirm={() => { onCancel(); setTransferList([]); setMethod(undefined); setEditTransfer(undefined); setImageVisible(false); }}
  404 + onConfirm={() => { onCancel(); setTransferList([]); setMethod(undefined); setEditTransfer(undefined); }}
417 405 okText="确认"
418 406 cancelText="取消"
419 407 >
... ...