Commit 3401d5476b7e0794284d22d8ea33ca6b548beb96

Authored by 张志伟
2 parents f06bf99a 5bd9b0c0

Merge branch 'd-cas-maintain-config' into 'master'

fix(cas): 优化保养机油配置



See merge request !749
src/pages/cas/afterSaleConfiguration/maintainConfig/api.ts
1 1 import { http } from '@/typing/http';
2 2 import request from '@/utils/request';
3   -import { CAS_HOST, OOP_HOST, PMS_HOST } from '@/utils/host';
  3 +import { CAS_HOST, OOP_HOST, PMS_HOST } from '@/utils/host'; // 列表
4 4  
5 5 // 列表
6 6 export function listApi(params: Maintain.ListParams): http.PromisePageResp<Maintain.ListVO> {
... ... @@ -57,8 +57,10 @@ export interface PartItem {
57 57 partNo?: string;
58 58 /**配件数量 */
59 59 partNumber?: number;
  60 +
60 61 [key: string]: any;
61 62 }
  63 +
62 64 export interface QueryParams {
63 65 current?: number;
64 66 pageSize?: number;
... ... @@ -70,3 +72,17 @@ export interface QueryParams {
70 72 export function getPartItems(params: QueryParams): PromisePageResp<PartItem> {
71 73 return request.get(`${PMS_HOST}/erp/part/list`, { params });
72 74 }
  75 +
  76 +export interface OilItem {
  77 + oilBrandId: number; // 机油品牌id
  78 + oilBrandName: string; // 机油品牌名称
  79 + oilModel: string; // 机油型号
  80 + oilViscosity: string; // 机油粘稠度
  81 + oilLevel: string; // 机油等级
  82 + motorOilType: string; // 机油类型
  83 +}
  84 +
  85 +/** 油料组合 */
  86 +export function oilGroupListApi(): http.PromiseResp<Maintain.OilGroup[]> {
  87 + return request.get(`${CAS_HOST}/erp/basic/maintenance/config/oil/combination`);
  88 +}
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/interface.d.ts
... ... @@ -118,6 +118,7 @@ declare namespace Maintain {
118 118 }
119 119  
120 120 interface OilGroup {
  121 + id: number;
121 122 oilBrandId: number; //机油品牌id
122 123 oilBrandName: string; //机油品牌名称
123 124 oilModel: string; //机油型号名称
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/NewOilModal/index.tsx deleted
1   -import React, { useEffect, useState } from 'react';
2   -import { Form, Modal, Select } from 'antd';
3   -import useInitail from '@/hooks/useInitail';
4   -
5   -import { motorOilTypeData, oilViscosityData } from '@/pages/pms/entity';
6   -import { getBrandApi, getTypes } from '@/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/api';
7   -
8   -interface Props {
9   - selected: Maintain.OilGroup[];
10   - visible: boolean;
11   - onCancel: () => void;
12   - onOk: (data: Maintain.OilGroup[]) => any;
13   - current: Maintain.OilGroup;
14   - setCurrent: (value: any) => any;
15   -}
16   -
17   -function NewOilModal(props: Props) {
18   - const { visible, onCancel, onOk, selected, current, setCurrent } = props;
19   - const [form] = Form.useForm();
20   - const [delay, setDelay] = useState(true);
21   - const { data, setParams: setBrandParams } = useInitail<PmsPartOilSpace.Brand[], object>(getBrandApi, [], {}, delay);
22   - const { data: oilLevelData, setParams: setOilLevelParams } = useInitail<PmsPartOilSpace.Type[], string>(getTypes, [], 'oil_level', delay);
23   - const { data: oilModels, setParams } = useInitail<PmsPartOilSpace.Type[], string>(getTypes, [], 'oil_model', delay);
24   - const { data: motorOilTypeData, setParams: oilType } = useInitail < PmsPartOilSpace.Type[], string> (getTypes, [], 'oil_type', delay);
25   - const { data: oilViscosityData, setParams: oilViscosity } = useInitail < PmsPartOilSpace.Type[], string> (getTypes, [], 'oil_viscosity', delay);
26   - useEffect(() => {
27   - if (visible) {
28   - setDelay(false);
29   - setBrandParams({ oilType: 1 }, true);
30   - oilType('oil_type', true);
31   - oilViscosity('oil_viscosity', true);
32   - setOilLevelParams('oil_level', true);
33   - if (current.oilBrandId) {
34   - form.setFieldsValue({ ...current });
35   - setParams(`oil_model_${current.oilBrandId}`, true);
36   - } else {
37   - form.resetFields();
38   - }
39   - }
40   - }, [visible]);
41   -
42   - function _onOk(value: any) {
43   - const data: Maintain.OilGroup = {
44   - ...value,
45   - oilBrandName: value.oil.label,
46   - oilBrandId: value.oil.value,
47   - defaultUse: false,
48   - };
49   - const index = selected.findIndex((e) => {
50   - return (
51   - e.oilBrandId === value.oil.value &&
52   - e.motorOilType === value.motorOilType &&
53   - e.oilLevel === value.oilLevel &&
54   - e.oilModel === value.oilModel &&
55   - e.oilViscosity === value.oilViscosity
56   - );
57   - });
58   - if (current.index || current.index == 0) {
59   - selected[current.index] = data;
60   - } else if (index > -1) {
61   - selected[index] = data;
62   - } else {
63   - selected.push(data);
64   - }
65   -
66   - setCurrent({});
67   - onOk && onOk(selected);
68   - }
69   -
70   - const layout = {
71   - labelCol: { span: 4 },
72   - wrapperCol: { span: 20 },
73   - };
74   -
75   - return (
76   - <Modal width={650} forceRender title={`${current.oilBrandId ? '编辑' : '添加'}机油`} open={visible} onOk={form.submit} onCancel={onCancel}>
77   - <Form {...layout} labelAlign="left" form={form} onFinish={_onOk} component={false}>
78   - <Form.Item label="机油品牌" name="oil" rules={[{ required: true }]}>
79   - <Select
80   - labelInValue
81   - placeholder="请选择机油品牌"
82   - showSearch
83   - optionFilterProp="children"
84   - onChange={(id) => {
85   - setParams(`oil_model_${id.value}`, true);
86   - form.resetFields(['oilModel']);
87   - }}
88   - >
89   - {data.map((i) => (
90   - <Select.Option value={i.brandId || 0} key={i.brandId || 0}>
91   - {i.brandName || '--'}
92   - </Select.Option>
93   - ))}
94   - </Select>
95   - </Form.Item>
96   - <Form.Item label="机油型号" name="oilModel" rules={[{ required: true }]}>
97   - <Select placeholder="请选择机油型号" showSearch optionFilterProp="children">
98   - {oilModels.map((i) => (
99   - <Select.Option value={i.value || ''} key={i.value || ''}>
100   - {i.value || '--'}
101   - </Select.Option>
102   - ))}
103   - </Select>
104   - </Form.Item>
105   - <Form.Item label="机油类型" name="motorOilType" rules={[{ required: true }]}>
106   - <Select placeholder="请选择机油类型" showSearch optionFilterProp="children">
107   - {motorOilTypeData.map((i) => (
108   - <Select.Option value={i.value || 0} key={i.value || 0}>
109   - {i.value || '--'}
110   - </Select.Option>
111   - ))}
112   - </Select>
113   - </Form.Item>
114   - <Form.Item label="机油等级" name="oilLevel" rules={[{ required: true }]}>
115   - <Select placeholder="请选择机油等级" showSearch optionFilterProp="children">
116   - {oilLevelData.map((i) => (
117   - <Select.Option value={i.value || 0} key={i.value || 0}>
118   - {i.value || '--'}
119   - </Select.Option>
120   - ))}
121   - </Select>
122   - </Form.Item>
123   - <Form.Item label="粘稠度" name="oilViscosity" rules={[{ required: true }]}>
124   - <Select placeholder="请选择粘稠度" showSearch optionFilterProp="children">
125   - {oilViscosityData.map((i) => (
126   - <Select.Option value={i.value || 0} key={i.value || 0}>
127   - {i.value || '--'}
128   - </Select.Option>
129   - ))}
130   - </Select>
131   - </Form.Item>
132   - </Form>
133   - </Modal>
134   - );
135   -}
136   -
137   -export default NewOilModal;
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/OilSelector.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Modal, Spin, Table } from 'antd';
  3 +
  4 +import useInitail from '@/hooks/useInitail';
  5 +
  6 +import { oilGroupListApi } from '@/pages/cas/afterSaleConfiguration/maintainConfig/api';
  7 +import st from './style.less';
  8 +
  9 +const Column = Table.Column;
  10 +
  11 +interface Props {
  12 + visible: boolean;
  13 + selected: Maintain.OilGroup[]; // 已选机油
  14 + onCancel: () => void;
  15 + onConfirm: (selectItems: Maintain.OilGroup[]) => void;
  16 +}
  17 +
  18 +/**
  19 + * 油料选择器
  20 + */
  21 +export default function OilSelector({ visible, selected, onCancel, onConfirm }: Props) {
  22 + const [delay, setDelay] = useState(true);
  23 + const [selectItems, setSelectItems] = useState<Maintain.OilGroup[]>([]);
  24 +
  25 + const { data, loading, setParams } = useInitail(oilGroupListApi, [], undefined, delay);
  26 +
  27 + useEffect(() => {
  28 + if (visible) {
  29 + setDelay(false);
  30 + setParams(undefined, true);
  31 +
  32 + if (selected?.length > 0) {
  33 + setSelectItems(selected);
  34 + }
  35 + }
  36 + }, [visible, selected]);
  37 +
  38 + const handleConfirm = () => {
  39 + onConfirm(selectItems);
  40 + setSelectItems([]);
  41 + };
  42 +
  43 + return (
  44 + <Modal
  45 + title="选择作机油"
  46 + width={780}
  47 + open={visible}
  48 + okButtonProps={{ disabled: selectItems.length === 0 }}
  49 + onOk={handleConfirm}
  50 + onCancel={onCancel}
  51 + destroyOnClose
  52 + >
  53 + <Spin spinning={loading}>
  54 + <Table
  55 + loading={loading}
  56 + dataSource={data}
  57 + rowClassName={st.clickableRow}
  58 + rowKey="id"
  59 + rowSelection={{
  60 + type: 'checkbox',
  61 + selectedRowKeys: selectItems.map((si) => si.id) || [],
  62 + onChange: (selectedRowKeys, selectedRows: Maintain.OilGroup[]) => {
  63 + setSelectItems(selectedRows);
  64 + },
  65 + }}
  66 + onRow={(record) => ({
  67 + onClick: () => {
  68 + if (selectItems.some((si) => si.id === record.id)) {
  69 + setSelectItems([...selectItems.filter((si) => si.id !== record.id)]);
  70 + } else {
  71 + setSelectItems([...selectItems, record]);
  72 + }
  73 + },
  74 + })}
  75 + footer={() => (
  76 + <span>
  77 + 已选:<span className={st.colorPrimary}>{`${selectItems.length} `}</span>项
  78 + </span>
  79 + )}
  80 + >
  81 + <Column title="机油品牌" dataIndex="oilBrandName" />
  82 + <Column title="型号" dataIndex="oilModel" />
  83 + <Column title="类型" dataIndex="motorOilType" />
  84 + <Column title="等级" dataIndex="oilLevel" />
  85 + <Column title="粘稠度" dataIndex="oilViscosity" />
  86 + </Table>
  87 + </Spin>
  88 + </Modal>
  89 + );
  90 +}
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/style.less 0 → 100644
  1 +.clickableRow {
  2 + cursor: pointer;
  3 +}
0 4 \ No newline at end of file
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/index.tsx
1 1 import React, { useEffect, useState } from 'react';
2   -import { Button, Row, Table } from 'antd';
  2 +import { Button, Row, Table, Tag } from 'antd';
3 3 import { MenuOutlined } from '@ant-design/icons';
4 4 import type { SortableContainerProps, SortEnd } from 'react-sortable-hoc';
5 5 import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
6 6 import { arrayMoveImmutable } from 'array-move';
7 7  
8   -import NewOilModal from './components/NewOilModal';
  8 +import OilSelector from './components/OilSelector';
9 9 import OilData from './components/OilData';
10 10  
11 11 import './style.less';
... ... @@ -20,18 +20,36 @@ export interface Props {
20 20 oilGroups: Maintain.OilGroup[];
21 21 capacity: number;
22 22 disabled?: boolean;
23   - onChange?: (data: any[]) => void;
  23 + onChange?: (data: Maintain.OilGroup[]) => void;
24 24 }
25 25  
26   -export default function EngineOilSelector(props: Props) {
27   - const { oilGroups, capacity, disabled, onChange } = props;
28   -
  26 +export default function EngineOilSelector({ oilGroups, capacity, disabled, onChange }: Props) {
29 27 const [visible, setVisible] = useState<boolean>(false);
30   - const [current, setCurrent] = useState({} as Maintain.OilGroup);
31 28 const [oilData, setOilData] = useState<any>({ visible: false, data: {} });
32 29  
33 30 const [dataSource, setDataSource] = useState<any[]>([]);
34 31  
  32 + useEffect(() => {
  33 + const _list = oilGroups.map((e) => {
  34 + return {
  35 + ...e,
  36 + // 拼接 e 中属性为 id值
  37 + id: `${e.oilBrandName}-${e.oilModel}-${e.motorOilType}-${e.oilLevel}-${e.oilViscosity}`
  38 + };
  39 + });
  40 + setDataSource([..._list]);
  41 + }, [oilGroups]);
  42 +
  43 + const handleOilSelect = (selectOils: Maintain.OilGroup[]) => {
  44 + onChange && onChange(selectOils);
  45 + setVisible(false);
  46 + };
  47 +
  48 + const handleOilDelete = (index: number) => {
  49 + oilGroups.splice(index, 1);
  50 + onChange && onChange(oilGroups);
  51 + };
  52 +
35 53 const onSortEnd = ({ oldIndex, newIndex }: SortEnd) => {
36 54 if (oldIndex !== newIndex) {
37 55 const newData = arrayMoveImmutable(dataSource.slice(), oldIndex, newIndex).filter((el: any) => !!el);
... ... @@ -50,41 +68,6 @@ export default function EngineOilSelector(props: Props) {
50 68 return <SortableItem index={index} {...restProps} />;
51 69 };
52 70  
53   - useEffect(() => {
54   - const _list = oilGroups.map((e, i) => {
55   - return {
56   - ...e,
57   - id: i,
58   - };
59   - });
60   - setDataSource([..._list]);
61   - }, [oilGroups]);
62   -
63   - function _onOk(data: Maintain.OilGroup[]) {
64   - onChange && onChange(data);
65   - setVisible(false);
66   - }
67   -
68   - function onDelete(record: Maintain.OilGroup) {
69   - const _items = oilGroups;
70   - const index = _items.findIndex((e) => {
71   - return (
72   - e.oilBrandId === record.oilBrandId &&
73   - e.motorOilType === record.motorOilType &&
74   - e.oilLevel === record.oilLevel &&
75   - e.oilModel === record.oilModel &&
76   - e.oilViscosity === record.oilViscosity
77   - );
78   - });
79   - _items.splice(index, 1);
80   - _onOk(_items);
81   - }
82   -
83   - function edit(record: Maintain.OilGroup, index: number) {
84   - setCurrent({ ...record, oil: { value: record.oilBrandId, label: record.oilBrandName }, index });
85   - setVisible(true);
86   - }
87   -
88 71 return (
89 72 <div style={{ marginTop: 30 }}>
90 73 <Row justify="space-between" align="middle" style={{ marginBottom: 16 }}>
... ... @@ -112,7 +95,22 @@ export default function EngineOilSelector(props: Props) {
112 95 }}
113 96 >
114 97 <Column align="center" className="drag-visible" title="拖拽排序" dataIndex="sort" width={100} render={() => <DragHandle />} />
115   - <Column className="drag-visible" title="推荐顺序" dataIndex="oilIndex" width={100} render={(text, record, index) => <div>{index + 1}</div>} />
  98 + <Column
  99 + className="drag-visible"
  100 + title="推荐顺序"
  101 + dataIndex="oilIndex"
  102 + width={160}
  103 + render={(text, record, index) => (
  104 + <div>
  105 + {index + 1}
  106 + {index === 0 && (
  107 + <Tag style={{ marginLeft: 5 }} color={'#FF9211'}>
  108 + 厂家首保机油
  109 + </Tag>
  110 + )}
  111 + </div>
  112 + )}
  113 + />
116 114 <Column className="drag-visible" title="机油品牌" dataIndex="oilBrandName" />
117 115 <Column className="drag-visible" title="机油型号" dataIndex="oilModel" />
118 116 <Column className="drag-visible" title="机油类型" dataIndex="motorOilType" />
... ... @@ -134,32 +132,20 @@ export default function EngineOilSelector(props: Props) {
134 132 width={150}
135 133 align="center"
136 134 render={(text, record: Maintain.OilGroup, index) => (
137   - <>
138   - <Button onClick={() => edit(record, index)} type="link" size="small">
139   - 编辑
140   - </Button>
141   - <Button onClick={() => onDelete(record)} type="link" danger size="small">
142   - 删除
143   - </Button>
144   - </>
  135 + <Button onClick={() => handleOilDelete(index)} type="link" danger size="small">
  136 + 删除
  137 + </Button>
145 138 )}
146 139 />
147 140 </Table>
148   - <NewOilModal
149   - selected={[...oilGroups]}
150   - onOk={_onOk}
151   - visible={visible}
152   - onCancel={() => setVisible(false)}
153   - current={current}
154   - setCurrent={setCurrent}
155   - />
  141 +
  142 + <OilSelector visible={visible} selected={dataSource} onCancel={() => setVisible(false)} onConfirm={handleOilSelect} />
156 143 <OilData
157 144 visible={oilData.visible}
  145 + data={oilData.data}
158 146 onCancel={() => {
159 147 setOilData({ visible: false, data: {} });
160   - setCurrent({} as Maintain.OilGroup);
161 148 }}
162   - data={oilData.data}
163 149 />
164 150 </div>
165 151 );
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/MachineFilter/components/EngineFilterModal/index.tsx
... ... @@ -4,6 +4,7 @@ import debounce from &#39;lodash/debounce&#39;;
4 4 import Search from 'antd/lib/input/Search';
5 5  
6 6 import { getPartItems } from '../../../../../../api';
  7 +import st from '@/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/EngineOilSelector/components/style.less';
7 8  
8 9 const { Column } = Table;
9 10  
... ... @@ -86,6 +87,9 @@ function EngineOilModal(props: Props) {
86 87 <Table
87 88 dataSource={data}
88 89 loading={loading}
  90 + pagination={{ total, defaultPageSize: 10, current, pageSize, onChange: onPageChange, onShowSizeChange: onPageChange }}
  91 + rowClassName={st.clickableRow}
  92 + rowKey="partCode"
89 93 rowSelection={{
90 94 selectedRowKeys: selectedRow.map((item) => item.partCode),
91 95 onSelect: (row: any, _selected: boolean) => {
... ... @@ -111,8 +115,15 @@ function EngineOilModal(props: Props) {
111 115 setSelectedRow(newData);
112 116 },
113 117 }}
114   - pagination={{ total, defaultPageSize: 10, current, pageSize, onChange: onPageChange, onShowSizeChange: onPageChange }}
115   - rowKey="partCode"
  118 + onRow={(record) => ({
  119 + onClick: () => {
  120 + if (selectedRow.some((si) => si.partCode === record.partCode)) {
  121 + setSelectedRow([...selectedRow.filter((si) => si.partCode !== record.partCode)]);
  122 + } else {
  123 + setSelectedRow([...selectedRow, record]);
  124 + }
  125 + },
  126 + })}
116 127 >
117 128 <Column title="名称" dataIndex="partName" width={250} />
118 129 <Column title="编号" dataIndex="partCode" />
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/components/PartFilter/index.tsx
... ... @@ -105,7 +105,8 @@ export default function PartFilter({ partFilters, brandId, onChange }: Props) {
105 105 }
106 106  
107 107 const EditableCell: React.FC<EditableCellProps> = ({ editing, dataIndex, title, inputType, record, index, children, ...restProps }) => {
108   - const inputNode = <InputNumber />;
  108 + // todo 液态配件可以输入小数
  109 + const inputNode = <InputNumber precision={0} />;
109 110  
110 111 return (
111 112 <td {...restProps}>
... ... @@ -142,8 +143,8 @@ export default function PartFilter({ partFilters, brandId, onChange }: Props) {
142 143 <Table
143 144 dataSource={dataSource}
144 145 bordered
145   - rowClassName="editable-row"
146 146 pagination={false}
  147 + rowClassName="editable-row"
147 148 rowKey={(row) => `${row.partCode}_${row.partName}`}
148 149 components={{
149 150 body: {
... ...
src/pages/cas/afterSaleConfiguration/maintainConfig/subpages/MaintainEdit/index.tsx
1 1 import React, { useEffect, useState } from 'react';
2   -import { Button, Card, Empty, Form, Input, message, Row, Select, Spin, Tabs } from 'antd';
  2 +import { Button, Card, Empty, Form, Input, message, Modal, Row, Select, Spin, Tabs } from 'antd';
3 3 import { PageHeaderWrapper } from '@ant-design/pro-layout';
4 4 import useInitial from '@/hooks/useInitail';
5 5 import { ConnectProps } from '@/typing/common';
... ... @@ -411,8 +411,11 @@ export default function ConfigPage({ match }: Props) {
411 411 }
412 412 })
413 413 .catch((e) => {
414   - message.error(e.message);
415 414 setSubmitting(false);
  415 + Modal.error({
  416 + title: '提示',
  417 + content: e.message,
  418 + });
416 419 });
417 420 }
418 421  
... ...