Commit f06bf99ad2d1c82cc94e35e07df18c0f94b98fca
Merge branch 'weeklydata_upload' into 'master'
Weeklydata upload See merge request !748
Showing
10 changed files
with
745 additions
and
2 deletions
config/routers/order3.ts
... | ... | @@ -335,4 +335,14 @@ export default [ |
335 | 335 | path: '/order3/promotionSettings/directCarPromotion', |
336 | 336 | component: './order3/DirectCarPromotion', |
337 | 337 | }, |
338 | + { | |
339 | + // 市占率数据导入 | |
340 | + path: '/order3/weeklydataupload', | |
341 | + component: './order3/WeeklydataUpload', | |
342 | + }, | |
343 | + { | |
344 | + // 车系映射配置 | |
345 | + path: '/order3/seriesmapping', | |
346 | + component: './order3/SeriesMapping', | |
347 | + }, | |
338 | 348 | ]; | ... | ... |
src/pages/order3/SeriesMapping/api.ts
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-03-27 17:40:09 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-18 17:52:00 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/SeriesMapping/api.ts | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import type { http } from '@/typing/http'; | |
12 | +import request from '@/utils/request'; | |
13 | +import { SDS_HOST } from '@/utils/host'; | |
14 | + | |
15 | +export interface series { | |
16 | + seriesId?: number | |
17 | + seriesName?: string | |
18 | + brandId?: number | |
19 | + brandName?: string | |
20 | +} | |
21 | +export interface saveparams { | |
22 | + importBrandName?: string | |
23 | + importSeriesName?: string | |
24 | + series?: series[] | |
25 | +} | |
26 | +/** 列表 */ | |
27 | +export function getList(params: any): http.PromisePageResp<saveparams> { | |
28 | + return request.get(`${SDS_HOST}/erp/series/mapping/get/mapping/list`, { params }); | |
29 | +} | |
30 | +/** 保存 */ | |
31 | +export function saveapi(params: saveparams) { | |
32 | + return request.post(`${SDS_HOST}/erp/series/mapping/save/mapping`, { ...params }); | |
33 | +} | |
34 | +/** 删除 */ | |
35 | +export function delapi(params: saveparams) { | |
36 | + return request.post(`${SDS_HOST}/erp/series/mapping/del/mapping`, { ...params }); | |
37 | +} | |
38 | + | |
39 | +export interface typedata { | |
40 | + value: string; | |
41 | + label: string; | |
42 | + children?: typedata[]; | |
43 | +} | |
44 | +// 车系 | |
45 | +export function getSeries(params: { brands?: string[]; vehicleCategory?: string[]; subdivideCategories?: string[] }): http.PromiseResp<typedata[]> { | |
46 | + return request.post(`${SDS_HOST}/erp/car/data/get/series/by/type`, params); | |
47 | +} | |
48 | +/** | |
49 | + * 类型10区域,20使用省份,30使用城市,40车型类别,50细分大类,60使用性质,70燃料种类,80国别大类,90国别,100排量,110动力类型,120所有权,130驱动形式150车系140品牌 | |
50 | +*/ | |
51 | +export function getTypedata(params: { type: number; queryAll?: boolean; parentTypes?: string[] }): http.PromiseResp<typedata[]> { | |
52 | + return request.post(`${SDS_HOST}/erp/type/settings/get/types`, params); | |
53 | +} | |
0 | 54 | \ No newline at end of file | ... | ... |
src/pages/order3/SeriesMapping/components/ChooseSeriesModal.tsx
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-04-18 17:12:08 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-18 18:25:13 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/SeriesMapping/components/ChooseSeriesModal.tsx | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import React, { useState, useEffect } from 'react'; | |
12 | +import { Table, Modal, Button, Input, Select } from 'antd'; | |
13 | +import usePagination from '@/hooks/usePagination'; | |
14 | +import useInitial from '@/hooks/useInitail'; | |
15 | +import { seriesListApi, getAllBrandApi } from '@/pages/oop/Series/api' | |
16 | + | |
17 | +interface Props { | |
18 | + visible: boolean, | |
19 | + onCancel: () => any, | |
20 | + onOk: (v: Series.seriesListItem[]) => any, | |
21 | +} | |
22 | +const Column = Table.Column; | |
23 | +export default function SeriesList(props: Props) { | |
24 | + const { visible, onCancel, onOk } = props | |
25 | + const { list, paginationConfig, loading, setParams } = usePagination(seriesListApi, { status: 1 }); | |
26 | + const { data: brands } = useInitial(getAllBrandApi, [], {}); | |
27 | + const [selectedSeries, setSelectedSeries] = useState<Series.seriesListItem[]>([]); | |
28 | + | |
29 | + useEffect(() => { | |
30 | + if (!visible) { | |
31 | + setSelectedSeries([]) | |
32 | + } | |
33 | + }, [visible]) | |
34 | + | |
35 | + const _onOk = () => { | |
36 | + onOk(selectedSeries); | |
37 | + onCancel(); | |
38 | + } | |
39 | + return ( | |
40 | + <Modal | |
41 | + title="选择映射车系" | |
42 | + maskClosable={false} | |
43 | + open={visible} | |
44 | + onCancel={onCancel} | |
45 | + width={800} | |
46 | + footer={[ | |
47 | + <Button onClick={onCancel} key={1} >取消</Button>, | |
48 | + <Button onClick={_onOk} key={2} type='primary' disabled={!selectedSeries.length}>确认</Button> | |
49 | + ]} | |
50 | + > | |
51 | + <div style={{ display: 'flex', justifyContent: "start" }}> | |
52 | + <Input | |
53 | + allowClear | |
54 | + style={{ width: 200, marginRight: 10, marginBottom: 10 }} | |
55 | + onChange={e => setParams({ name: e.target.value }, true)} | |
56 | + placeholder="车系名称" | |
57 | + /> | |
58 | + <Select | |
59 | + showSearch | |
60 | + optionFilterProp="children" | |
61 | + placeholder="选择品牌" | |
62 | + allowClear | |
63 | + onChange={val => { setParams({ brandId: val }, true) }} | |
64 | + style={{ width: 200, marginRight: 10, marginBottom: 10 }} | |
65 | + > | |
66 | + {brands.map((item: Series.BrandItem) => <Select.Option key={item.id} value={item.id!}>{item.name}</Select.Option>)} | |
67 | + </Select> | |
68 | + </div> | |
69 | + <Table | |
70 | + dataSource={list} | |
71 | + pagination={paginationConfig} | |
72 | + rowKey={record => Number(record.id)} | |
73 | + loading={loading} | |
74 | + size="small" | |
75 | + rowSelection={{ | |
76 | + type: "checkbox", | |
77 | + selectedRowKeys: selectedSeries.map(i => i.id), | |
78 | + onSelect: (row, _selected) => { | |
79 | + const index = selectedSeries.findIndex(_row => _row.id == row.id); | |
80 | + const newData = [...selectedSeries]; | |
81 | + if (_selected) { | |
82 | + newData.unshift(row); | |
83 | + } else if (index > -1) { | |
84 | + newData.splice(index, 1); | |
85 | + } | |
86 | + setSelectedSeries([...newData]); | |
87 | + }, | |
88 | + onSelectAll: (selected, selectedRows, changeRows) => { | |
89 | + const changedKeys = changeRows.map(row => row.id); | |
90 | + if (selected) { | |
91 | + // 全选 | |
92 | + const _arr = [...selectedSeries, ...changeRows] | |
93 | + setSelectedSeries(_arr); | |
94 | + } else { | |
95 | + // 取消全选 过滤当前页选中数据 | |
96 | + setSelectedSeries(selectedSeries.filter(row => !changedKeys.includes(row.id))) | |
97 | + } | |
98 | + }, | |
99 | + }} | |
100 | + > | |
101 | + <Column title="车系名称" dataIndex="name" /> | |
102 | + <Column title="品牌名称" dataIndex="brandName" /> | |
103 | + <Column title="厂商" dataIndex="factoryName" /> | |
104 | + </Table> | |
105 | + </Modal> | |
106 | + ); | |
107 | +} | ... | ... |
src/pages/order3/SeriesMapping/components/CreateModal.tsx
0 → 100644
1 | +import React, { useState, useEffect } from 'react'; | |
2 | +import { Button, Modal, message, Select,Table } from 'antd'; | |
3 | +import useInitial from '@/hooks/useInitail'; | |
4 | +import type { saveparams } from '../api'; | |
5 | +import { getTypedata, saveapi } from '../api'; | |
6 | +import ChooseSeriesModal from './ChooseSeriesModal'; | |
7 | + | |
8 | +const Column = Table.Column; | |
9 | +const Option = Select.Option; | |
10 | +interface Props { | |
11 | + onCancel: () => any; | |
12 | + visible: boolean; | |
13 | + onRefshing: () => any | |
14 | +} | |
15 | + | |
16 | +export default function UploadModal(props: Props) { | |
17 | + const { onCancel, visible, onRefshing } = props; | |
18 | + const { data: brands } = useInitial(getTypedata, [], {type: 140}); | |
19 | + const [param, setParam] = useState<saveparams>({}) | |
20 | + const [delay, setDelay] = useState(true); | |
21 | + const { data: series, setParams } = useInitial(getTypedata, [], { type: 150 }, delay); | |
22 | + const [loading, setLoading] = useState(false); | |
23 | + const [servisible, setServisible] = useState(false); | |
24 | + | |
25 | + useEffect(() => { | |
26 | + if (!visible) { | |
27 | + setParam({}); | |
28 | + } | |
29 | + }, [visible]); | |
30 | + | |
31 | + const onOk = () => { | |
32 | + if (!param.importBrandName) { | |
33 | + message.error('请选择导入品牌'); | |
34 | + return; | |
35 | + } | |
36 | + if (!param.importSeriesName) { | |
37 | + message.error('请选择导入车系'); | |
38 | + return; | |
39 | + } | |
40 | + if (!param.series?.length) { | |
41 | + message.error('请选择映射车系列表'); | |
42 | + return; | |
43 | + } | |
44 | + setLoading(true); | |
45 | + saveapi(param).then(() => { | |
46 | + setLoading(false); | |
47 | + onRefshing(); | |
48 | + onCancel(); | |
49 | + message.success('操作成功'); | |
50 | + }).catch(e => { | |
51 | + setLoading(false); | |
52 | + message.error(e.message); | |
53 | + }) | |
54 | + } | |
55 | + | |
56 | + return ( | |
57 | + <Modal | |
58 | + title={'新增车系映射'} | |
59 | + open={visible} | |
60 | + width={1000} | |
61 | + keyboard={false} | |
62 | + maskClosable={false} | |
63 | + onCancel={() => onCancel()} | |
64 | + footer={[ | |
65 | + <Button key="close" type="default" onClick={() => onCancel()} loading={loading}> | |
66 | + 关闭 | |
67 | + </Button>, | |
68 | + <Button key="ok" type="primary" onClick={() => onOk()} loading={loading}> | |
69 | + 确认 | |
70 | + </Button>, | |
71 | + ]} | |
72 | + > | |
73 | + <div style={{ display: 'flex', alignItems: 'center', marginBottom: 20 }}> | |
74 | + <div style={{ width: 100, textAlign: 'end' }}>导入品牌:</div> | |
75 | + <Select | |
76 | + value={param.importBrandName} | |
77 | + style={{ flex: 1 }} | |
78 | + placeholder="请选择导入品牌" | |
79 | + onChange={v => { | |
80 | + setParam({ ...param, importBrandName:v }); | |
81 | + setDelay(false); | |
82 | + setParams({ parentTypes: [v], type: 150 }, true) | |
83 | + }} | |
84 | + showSearch | |
85 | + optionFilterProp="children" | |
86 | + > | |
87 | + {brands?.map((it) => ( | |
88 | + <Option key={it.value} value={it.value}> | |
89 | + {it.value} | |
90 | + </Option> | |
91 | + ))} | |
92 | + </Select> | |
93 | + </div> | |
94 | + <div style={{ display: 'flex', alignItems: 'center' }}> | |
95 | + <div style={{ width: 100, textAlign: 'end' }}>导入车系:</div> | |
96 | + <Select | |
97 | + value={param.importSeriesName} | |
98 | + style={{ flex: 1 }} | |
99 | + placeholder="请选择导入车系" | |
100 | + onChange={v => { | |
101 | + setParam({ ...param, importSeriesName: v }); | |
102 | + }} | |
103 | + showSearch | |
104 | + optionFilterProp="children" | |
105 | + > | |
106 | + {series.map((it) => ( | |
107 | + <Option key={it.value} value={it.value}> | |
108 | + {it.value} | |
109 | + </Option> | |
110 | + ))} | |
111 | + </Select> | |
112 | + </div> | |
113 | + <div style={{ display: 'flex', marginTop: 20, marginBottom: 20, alignItems: 'start', width: '100%' }}> | |
114 | + <div style={{ width: 100, textAlign: 'end' }}>映射车系列表:</div> | |
115 | + <div style={{flex: 1}}> | |
116 | + <div style={{display: 'flex', justifyContent: 'end'}}> | |
117 | + <Button onClick={() => setServisible(true)} type='primary' style={{ marginBottom: 10 }}>添加映射车系</Button> | |
118 | + </div> | |
119 | + <Table dataSource={param.series} style={{flex: 1}} scroll={{y: 400}} pagination={false}> | |
120 | + <Column title="品牌名称" dataIndex="brandName" /> | |
121 | + <Column title="车系名称" dataIndex="seriesName" /> | |
122 | + </Table> | |
123 | + </div> | |
124 | + </div> | |
125 | + <ChooseSeriesModal | |
126 | + visible={servisible} | |
127 | + onCancel={() => setServisible(false)} | |
128 | + onOk={s => { | |
129 | + const _s = s.map(i => ({ ...i, seriesName: i.name, seriesId: i.id })) | |
130 | + setParam({ ...param, series: _s }) | |
131 | + }} | |
132 | + /> | |
133 | + </Modal> | |
134 | + ); | |
135 | +} | ... | ... |
src/pages/order3/SeriesMapping/components/MappingSeriesModal.tsx
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-04-18 16:46:23 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-19 09:16:21 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/SeriesMapping/components/MappingSeriesModal.tsx | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import React from 'react'; | |
12 | +import { Button, Modal, Table } from 'antd'; | |
13 | +import type { series } from '../api'; | |
14 | + | |
15 | +const Column = Table.Column; | |
16 | +interface Props { | |
17 | + onCancel: () => any; | |
18 | + visible: boolean; | |
19 | + data: series[] | |
20 | +} | |
21 | + | |
22 | +export default function UploadModal(props: Props) { | |
23 | + const { onCancel, visible, data } = props; | |
24 | + | |
25 | + return ( | |
26 | + <Modal | |
27 | + title={'车系映射列表'} | |
28 | + open={visible} | |
29 | + width={800} | |
30 | + keyboard={false} | |
31 | + maskClosable={false} | |
32 | + onCancel={() => onCancel()} | |
33 | + okButtonProps={{ hidden: true }} | |
34 | + footer={[ | |
35 | + <Button key="close" type="default" onClick={() => onCancel()}> | |
36 | + 关闭 | |
37 | + </Button> | |
38 | + ]} | |
39 | + > | |
40 | + <Table dataSource={data} pagination={false}> | |
41 | + <Column title="品牌名称" dataIndex="brandName" /> | |
42 | + <Column title="车系名称" dataIndex="seriesName" /> | |
43 | + </Table> | |
44 | + </Modal> | |
45 | + ); | |
46 | +} | ... | ... |
src/pages/order3/SeriesMapping/index.tsx
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-04-18 16:00:41 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-19 09:19:51 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/SeriesMapping/index.tsx | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import React, { useState } from 'react' | |
12 | +import { PageHeaderWrapper } from '@ant-design/pro-layout' | |
13 | +import { Button, Card, Table, Select, Popconfirm, message } from 'antd' | |
14 | +import CreateModal from './components/CreateModal'; | |
15 | +import MappingSeriesModal from './components/MappingSeriesModal'; | |
16 | +import usePagination from '@/hooks/usePagination'; | |
17 | +import useInitial from '@/hooks/useInitail'; | |
18 | +import type { saveparams, series } from './api'; | |
19 | +import { getList, getTypedata, delapi } from './api'; | |
20 | + | |
21 | +const { Column } = Table | |
22 | + | |
23 | +export default function Index() { | |
24 | + const [visible, setVisible] = useState < boolean > (false) | |
25 | + const { list, loading, setParams, paginationConfig } = usePagination(getList, {}) | |
26 | + const { data: brands } = useInitial(getTypedata, [], {type: 140}); | |
27 | + const [delay, setDelay] = useState(true); | |
28 | + const { data: series, setParams: seriesQuery, setData } = useInitial(getTypedata, [], { type: 150 }, delay); | |
29 | + const [mappseries, setMappingseries] = useState < { visible: boolean, data: series[] }>({visible: false, data: []}) | |
30 | + | |
31 | + const _del = (p: saveparams) => { | |
32 | + delapi(p).then(() => { | |
33 | + message.success('操作成功'); | |
34 | + setParams({}, true) | |
35 | + }).catch(e => message.error(e.message)) | |
36 | + } | |
37 | + return ( | |
38 | + <PageHeaderWrapper> | |
39 | + <Card> | |
40 | + <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 20 }}> | |
41 | + <div> | |
42 | + <Select | |
43 | + style={{ width: 200, marginRight: 20 }} | |
44 | + placeholder="导入品牌筛选" | |
45 | + onChange={v => { | |
46 | + setParams({ importBrandName: v }, true); | |
47 | + if (v) { | |
48 | + setDelay(false); | |
49 | + seriesQuery({ parentTypes: [v], type: 150 }, true) | |
50 | + } else { | |
51 | + setData([]); | |
52 | + } | |
53 | + }} | |
54 | + showSearch | |
55 | + allowClear | |
56 | + optionFilterProp="children" | |
57 | + > | |
58 | + {brands.map((it) => ( | |
59 | + <Select.Option key={it.value} value={it.value}> | |
60 | + {it.label} | |
61 | + </Select.Option> | |
62 | + ))} | |
63 | + </Select> | |
64 | + {!!series.length && | |
65 | + <Select | |
66 | + style={{ width: 200, marginRight: 20 }} | |
67 | + placeholder="导入车系筛选" | |
68 | + onChange={v => { | |
69 | + setParams({ importSeriesName: v }, true); | |
70 | + }} | |
71 | + showSearch | |
72 | + allowClear | |
73 | + optionFilterProp="children" | |
74 | + > | |
75 | + {series.map((it) => ( | |
76 | + <Select.Option key={it.value} value={it.value}> | |
77 | + {it.label} | |
78 | + </Select.Option> | |
79 | + ))} | |
80 | + </Select> | |
81 | + } | |
82 | + </div> | |
83 | + <div> | |
84 | + <Button type='primary' onClick={() => setVisible(true)}>新增</Button> | |
85 | + </div> | |
86 | + </div> | |
87 | + <Table | |
88 | + dataSource={list} | |
89 | + loading={loading} | |
90 | + pagination={paginationConfig} | |
91 | + rowKey={r => `${r.importBrandName}_${r.importSeriesName}`} | |
92 | + > | |
93 | + <Column title="导入品牌" dataIndex="importBrandName" /> | |
94 | + <Column title="导入车系" dataIndex="importSeriesName" /> | |
95 | + <Column title="映射车系列表" render={r => <a onClick={() => setMappingseries({visible: true, data: r.series})}>查看</a> } /> | |
96 | + <Column | |
97 | + title="操作" | |
98 | + render={r => ( | |
99 | + <Popconfirm title="确认删除?" onConfirm={() => _del(r)}> | |
100 | + <a style={{ color: 'red' }}>删除</a> | |
101 | + </Popconfirm> | |
102 | + )} | |
103 | + /> | |
104 | + </Table> | |
105 | + </Card> | |
106 | + <CreateModal visible={visible} onCancel={() => setVisible(false)} onRefshing={setParams} /> | |
107 | + <MappingSeriesModal visible={mappseries.visible} onCancel={() => setMappingseries({visible: false, data: []})} data={mappseries.data} /> | |
108 | + </PageHeaderWrapper> | |
109 | + ) | |
110 | +} | |
0 | 111 | \ No newline at end of file | ... | ... |
src/pages/order3/WeeklydataUpload/api.ts
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-03-27 17:40:09 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-12 18:30:51 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/WeeklydataUpload/api.ts | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import type { http } from '@/typing/http'; | |
12 | +import request from '@/utils/request'; | |
13 | +import { SDS_HOST } from '@/utils/host'; | |
14 | + | |
15 | +export interface List { | |
16 | + year?: number | |
17 | + week?: number | |
18 | + sourceFid?: string | |
19 | + successCnt?: number | |
20 | + failCnt?: number | |
21 | + failFid?: string | |
22 | + importUserName?: string | |
23 | + creatTime?: string | |
24 | + status?: number // 1处理中2已完成 | |
25 | +} | |
26 | +interface week { | |
27 | + id?: number, | |
28 | + createTime?: number, | |
29 | + updateTime?: number, | |
30 | + createBy?: number, | |
31 | + updateBy?: number, | |
32 | + year?: number, | |
33 | + week?: number, | |
34 | + yearWeek?: number, | |
35 | + startTime?: number, | |
36 | + endTime?: number | |
37 | +} | |
38 | + | |
39 | +interface weekdata { | |
40 | + currentWeek?: week | |
41 | + weekTimes?: week[] | |
42 | +} | |
43 | +interface saveparams { | |
44 | + year?: number | |
45 | + week?: number | |
46 | + sourceFid?: string | |
47 | +} | |
48 | +/** 列表 */ | |
49 | +export function getList(params: any): http.PromisePageResp<List> { | |
50 | + return request.get(`${SDS_HOST}/erp/car/sale/get/import/record/list`, { params }); | |
51 | +} | |
52 | +/** 上传 */ | |
53 | +export function upLoad(params: saveparams) { | |
54 | + return request.post(`${SDS_HOST}/erp/car/sale/import/data`, { ...params }); | |
55 | +} | |
56 | +// 年份数据列表 | |
57 | +export function getyeardata(): http.PromiseResp<number[]> { | |
58 | + return request.get(`${SDS_HOST}/erp/year/week/time/get/years`); | |
59 | +} | |
60 | +// 年份周度数据列表 | |
61 | +export function getweekdata(params: { year: number }): http.PromiseResp<weekdata> { | |
62 | + return request.get(`${SDS_HOST}/erp/year/week/time/get/year/weeks`, { params }); | |
63 | +} | |
0 | 64 | \ No newline at end of file | ... | ... |
src/pages/order3/WeeklydataUpload/components/UploadModal.tsx
0 → 100644
1 | +/* | |
2 | + * @Author: jiangwei jiangwei.feewee.cn | |
3 | + * @Date: 2024-04-16 17:51:11 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-16 19:29:30 | |
6 | + * @FilePath: /fw-cms/src/pages/order3/WeeklydataUpload/components/UploadModal.tsx | |
7 | + * @Description: | |
8 | + * | |
9 | + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. | |
10 | + */ | |
11 | +import React, { useState, useEffect } from 'react'; | |
12 | +import { UploadOutlined } from '@ant-design/icons'; | |
13 | +import FeeweeUploadAttachment from '@/components/FeeweeUploadAttachment'; | |
14 | +import { Button, Modal, message, Select } from 'antd'; | |
15 | +import useInitial from '@/hooks/useInitail'; | |
16 | +import moment from 'moment'; | |
17 | +import { getweekdata, getyeardata, upLoad } from '../api' | |
18 | + | |
19 | +const Option = Select.Option; | |
20 | +interface Props { | |
21 | + onCancel: () => any; | |
22 | + visible: boolean; | |
23 | + onRefshing: Function | |
24 | +} | |
25 | + | |
26 | +export default function UploadModal(props: Props) { | |
27 | + const { onCancel, visible, onRefshing } = props; | |
28 | + const { data: years } = useInitial(getyeardata, [], {}); | |
29 | + const { data: weeks, setParams } = useInitial(getweekdata, {}, { year: Number(moment().format('YYYY')) }); | |
30 | + const [year, setYear] = useState < number > (Number(moment().format('YYYY'))); | |
31 | + const [week, setWeek] = useState < number| undefined >(); | |
32 | + const [fids, setFids] = useState < any[] > ([]); | |
33 | + const [loading, setLoading] = useState(false); | |
34 | + | |
35 | + useEffect(() => { | |
36 | + if (!visible) { | |
37 | + setYear(Number(moment().format('YYYY'))); | |
38 | + setFids([]); | |
39 | + } | |
40 | + }, [visible]); | |
41 | + | |
42 | + useEffect(() => { | |
43 | + if (weeks.currentWeek?.week) { | |
44 | + setWeek(weeks.currentWeek?.week) | |
45 | + } | |
46 | + }, [weeks.currentWeek?.week]) | |
47 | + | |
48 | + const onOk = () => { | |
49 | + if (!fids) { | |
50 | + message.error('请先上传文件'); | |
51 | + return; | |
52 | + } | |
53 | + setLoading(true); | |
54 | + upLoad({ year, week, sourceFid: fids[0] }).then(() => { | |
55 | + setLoading(false); | |
56 | + onRefshing(); | |
57 | + onCancel(); | |
58 | + message.success('操作成功'); | |
59 | + }).catch(e => { | |
60 | + setLoading(false); | |
61 | + message.error(e.message); | |
62 | + }) | |
63 | + } | |
64 | + | |
65 | + return ( | |
66 | + <Modal | |
67 | + title={'市占率数据导入'} | |
68 | + open={visible} | |
69 | + width={800} | |
70 | + keyboard={false} | |
71 | + maskClosable={false} | |
72 | + onCancel={() => onCancel()} | |
73 | + footer={[ | |
74 | + <Button key="close" type="default" onClick={() => onCancel()} loading={loading}> | |
75 | + 关闭 | |
76 | + </Button>, | |
77 | + <Button key="ok" type="primary" onClick={() => onOk()} loading={loading}> | |
78 | + 确认导入 | |
79 | + </Button>, | |
80 | + ]} | |
81 | + > | |
82 | + <div style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}> | |
83 | + <span>导入年份:</span> | |
84 | + <Select | |
85 | + value={year} | |
86 | + style={{ width: 510 }} | |
87 | + placeholder="请选择导入年份" | |
88 | + onChange={v => { | |
89 | + setYear(v); | |
90 | + setParams({ year: v }, true) | |
91 | + }} | |
92 | + showSearch | |
93 | + optionFilterProp="children" | |
94 | + > | |
95 | + {years?.map((it) => ( | |
96 | + <Option key={it} value={it}> | |
97 | + {`${it}年`} | |
98 | + </Option> | |
99 | + ))} | |
100 | + </Select> | |
101 | + </div> | |
102 | + <div style={{ display: 'flex', alignItems: 'center' }}> | |
103 | + <span>导入周度:</span> | |
104 | + <Select | |
105 | + value={week} | |
106 | + style={{ width: 510 }} | |
107 | + placeholder="请选择导入周度" | |
108 | + onChange={setWeek} | |
109 | + showSearch | |
110 | + optionFilterProp="children" | |
111 | + > | |
112 | + {weeks.weekTimes?.map((it) => ( | |
113 | + <Option key={it.id} value={it.week}> | |
114 | + {`第${it.week}周(${moment(it.startTime).format('MM.DD')}-${moment(it.endTime).format('MM.DD')})`} | |
115 | + </Option> | |
116 | + ))} | |
117 | + </Select> | |
118 | + </div> | |
119 | + <div style={{ display: 'flex', alignItems: 'center', marginTop: 10, marginBottom: 20 }}> | |
120 | + <span>导入数据:</span> | |
121 | + <FeeweeUploadAttachment | |
122 | + fidList={fids} | |
123 | + onChange={(fil) => setFids(fil)} | |
124 | + > | |
125 | + {!fids.length && <Button icon={<UploadOutlined rev={undefined} />}>点击上传文件</Button>} | |
126 | + </FeeweeUploadAttachment> | |
127 | + </div> | |
128 | + <a href="https://gate.feewee.cn/file/show?fid=537083857248325" target="_blank" rel="noreferrer">下载导入模版</a> | |
129 | + </Modal> | |
130 | + ); | |
131 | +} | ... | ... |
src/pages/order3/WeeklydataUpload/index.tsx
0 → 100644
1 | +import React, { useState } from 'react' | |
2 | +import { PageHeaderWrapper } from '@ant-design/pro-layout' | |
3 | +import { Button, Card, Table, Tag, Divider, Select } from 'antd' | |
4 | +import UploadModal from './components/UploadModal'; | |
5 | +import usePagination from '@/hooks/usePagination'; | |
6 | +import useInitial from '@/hooks/useInitail'; | |
7 | +import { getList, getyeardata, getweekdata } from './api'; | |
8 | +import moment from 'moment'; | |
9 | + | |
10 | +const { Column } = Table | |
11 | + | |
12 | +export default function Index() { | |
13 | + const [visible, setVisible] = useState < boolean > (false) | |
14 | + const { list, loading, setParams, paginationConfig } = usePagination(getList, {}) | |
15 | + const { data: years } = useInitial(getyeardata, [], {}); | |
16 | + const { data: weeks, setParams: weekQuery } = useInitial(getweekdata, {}, { year: Number(moment().format('YYYY')) }); | |
17 | + return ( | |
18 | + <PageHeaderWrapper> | |
19 | + <Card> | |
20 | + <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 20 }}> | |
21 | + <div> | |
22 | + <Select | |
23 | + style={{ width: 200, marginRight: 20 }} | |
24 | + placeholder="导入年份筛选" | |
25 | + onChange={v => { | |
26 | + setParams({ year: v }, true) | |
27 | + weekQuery({ year: v }, true) | |
28 | + }} | |
29 | + showSearch | |
30 | + allowClear | |
31 | + optionFilterProp="children" | |
32 | + > | |
33 | + {years?.map((it) => ( | |
34 | + <Select.Option key={it} value={it}> | |
35 | + {`${it}年`} | |
36 | + </Select.Option> | |
37 | + ))} | |
38 | + </Select> | |
39 | + <Select | |
40 | + style={{ width: 200 }} | |
41 | + placeholder="导入周度筛选" | |
42 | + onChange={v => { | |
43 | + setParams({ week: v }, true) | |
44 | + }} | |
45 | + showSearch | |
46 | + allowClear | |
47 | + optionFilterProp="children" | |
48 | + > | |
49 | + {weeks.weekTimes?.map((it) => ( | |
50 | + <Select.Option key={it.id} value={it.week}> | |
51 | + {`第${it.week}周(${moment(it.startTime).format('MM.DD')}-${moment(it.endTime).format('MM.DD')})`} | |
52 | + </Select.Option> | |
53 | + ))} | |
54 | + </Select> | |
55 | + </div> | |
56 | + <div> | |
57 | + <Button type='primary' onClick={() => setVisible(true)}>新增导入</Button> | |
58 | + </div> | |
59 | + </div> | |
60 | + <Table | |
61 | + dataSource={list} | |
62 | + loading={loading} | |
63 | + pagination={paginationConfig} | |
64 | + rowKey={r => `${r.sourceFid}`} | |
65 | + > | |
66 | + <Column title="年份/周度" render={r => `${r.year}第${r.week}周(${moment(r.startTime).format('MM.DD')}-${moment(r.endTime).format('MM.DD')})`} /> | |
67 | + <Column title="导入时间" dataIndex="createTime" render={t => moment(t).format('YYYY.MM.DD HH:mm:ss')} /> | |
68 | + <Column title="导入人员" dataIndex="importUserName" /> | |
69 | + <Column title="导入数据" render={r => <span>{(r.successCnt || 0) + (r.failCnt || 0)}条</span>} /> | |
70 | + <Column title="成功" dataIndex="successCnt" render={t => <span>{t}条</span>} /> | |
71 | + <Column title="失败" dataIndex="failCnt" render={r => ( | |
72 | + r.failCnt ? | |
73 | + <> | |
74 | + <span>{r.failCnt}条</span> | |
75 | + <Divider type="vertical" /> | |
76 | + <a href={`https://gate.feewee.cn/file/show?fid=${r.failFid}`} target="_blank" rel="noreferrer">下载</a> | |
77 | + </> | |
78 | + : '--' | |
79 | + )} /> | |
80 | + <Column title="状态" dataIndex="status" render={t => <Tag color={t == 1 ? 'orange' : 'green'}>{t == 1 ? '处理中' : '已完成'}</Tag>} /> | |
81 | + </Table> | |
82 | + </Card> | |
83 | + <UploadModal visible={visible} onCancel={() => setVisible(false)} onRefshing={setParams} /> | |
84 | + </PageHeaderWrapper> | |
85 | + ) | |
86 | +} | |
0 | 87 | \ No newline at end of file | ... | ... |
src/utils/host.ts
1 | 1 | /* |
2 | 2 | * @Author: wangqiang@feewee.cn |
3 | 3 | * @Date: 2022-02-17 10:32:44 |
4 | - * @LastEditors: wangqiang@feewee.cn | |
5 | - * @LastEditTime: 2023-02-14 14:30:06 | |
4 | + * @LastEditors: jiangwei jiangwei.feewee.cn | |
5 | + * @LastEditTime: 2024-04-12 16:52:47 | |
6 | 6 | */ |
7 | 7 | export const HOST = '/admin'; |
8 | 8 | export const VWMS_HOST = '/vwms'; |
... | ... | @@ -88,6 +88,8 @@ export const DALARAN = '/dalaran'; |
88 | 88 | export const AMS_HOST = '/ams'; |
89 | 89 | // 云设备 |
90 | 90 | export const MMD_HOST = '/mmd'; |
91 | +// | |
92 | +export const SDS_HOST = '/sds'; | |
91 | 93 | |
92 | 94 | const host = { |
93 | 95 | admin: '/admin', | ... | ... |