Commit 7af0743423436f3be7e82b2044f92ea9860af3f2
1 parent
cc9f4a1c
feature: 添加机修组分成比例页面
Showing
5 changed files
with
404 additions
and
0 deletions
config/routers/cas.ts
... | ... | @@ -246,6 +246,10 @@ export default [ |
246 | 246 | path: '/cas/cassetting/manHoursDiscountConfig/create/:id/:brandId?', //工时减免规则配置 |
247 | 247 | component: './cas/afterSaleConfiguration/manHoursDiscountConfig/subpages/ConfigCreate' |
248 | 248 | }, |
249 | + { | |
250 | + path: '/cas/cassetting/manhoursProportionConfig', // 机修组工时分成比例配置 | |
251 | + component: './cas/afterSaleConfiguration/manhoursProportionConfig' | |
252 | + }, | |
249 | 253 | // { |
250 | 254 | // path: '/cas/part/plantype', // 备件计划类型 |
251 | 255 | // component: './cas/spareParts/PlanType' | ... | ... |
src/pages/cas/afterSaleConfiguration/manhoursProportionConfig/api.ts
0 → 100644
1 | +import { http } from "@/typing/http"; | |
2 | +import request from "@/utils/request"; | |
3 | +import { CAS_HOST } from "@/utils/host"; | |
4 | + | |
5 | +type PromisePageResp<T> = http.PromisePageResp<T>; | |
6 | + | |
7 | +// 列表参数 | |
8 | +interface ListParam { | |
9 | + current?: number; | |
10 | + pageSize?: number; | |
11 | + keyword?: string; | |
12 | + shopId?: number; | |
13 | + groupId?: number; | |
14 | + userId?: number; | |
15 | + userName?: string; | |
16 | + teamId?: number; | |
17 | +} | |
18 | + | |
19 | +// 列表结果 | |
20 | +export interface ListResult { | |
21 | + groupId: number; // 集团id | |
22 | + shopId: number; // 门店id | |
23 | + shopName: string; // 门店名称 | |
24 | + roleCode: string; // 角色编码 | |
25 | + roleName: string; // 角色名称 | |
26 | + teamId: number; // 组id | |
27 | + teamName: string; // 组名 | |
28 | + userInfoVOS: Staff[]; // 组员工信息 | |
29 | +} | |
30 | + | |
31 | +// 机修组员工信息 | |
32 | +interface Staff { | |
33 | + id?: string; // 配置id | |
34 | + staffId: string; // 组员id | |
35 | + staffName: string; // 组员名称 | |
36 | + manHoursProp?: string; // 工时分成占比(以小数表示,如0.5表示50%,全部组员相加为1) | |
37 | +} | |
38 | + | |
39 | +/** 工时分成配置列表 */ | |
40 | +export function getListApi(params: ListParam): PromisePageResp<ListResult[]> { | |
41 | + return request.get(`${CAS_HOST}/erp/team/setting/list`, { params }); | |
42 | +} | |
43 | + | |
44 | +/** 机修施工组 */ | |
45 | +export interface RepairGroup { | |
46 | + id: number; // 小组id | |
47 | + name: string; // 小组名称 | |
48 | + groupId: number; // 集团id | |
49 | + shopId: number; // 门店id | |
50 | + shopName: string; // 门店名称 | |
51 | + roIeCode: string; // 角色编码 | |
52 | + roIeName: string; // 角色名称 | |
53 | + remark: string; // 备注 | |
54 | + staffList: Staff[]; // 组员 | |
55 | +} | |
56 | + | |
57 | +/** 门店机修施工组:列表 */ | |
58 | +export function getShopRepairGroupsApi(shopId: number): PromisePageResp<RepairGroup[]> { | |
59 | + return request.get(`${CAS_HOST}/erp/team/setting/team/list`, { params: { shopId } }); | |
60 | +} | |
61 | + | |
62 | +export interface SaveParams { | |
63 | + shopId: number; // 门店id | |
64 | + shopName: string; // 门店名称 | |
65 | + teamId: string; // 小组id | |
66 | + teamName: string; // 小组名称 | |
67 | + userId?: string; // 用户id | |
68 | + userName?: string; // 用户名称 | |
69 | + groupId?: string; // 集团id | |
70 | + userInfoVOS?: Staff[]; // 各组员分成比例配置 | |
71 | +} | |
72 | + | |
73 | +/** 保存/修改配置 */ | |
74 | +export function saveApi(params: SaveParams) { | |
75 | + return request.post(`${CAS_HOST}/erp/team/setting/save`, params); | |
76 | +} | |
77 | + | |
78 | +export interface DeleteParams { | |
79 | + groupId?: string; // 集团id | |
80 | + shopId?: number; // 门店id | |
81 | + userId?: string; // 用户id | |
82 | + userName?: string; // 用户名称 | |
83 | + current?: number; | |
84 | + pageSize?: number; | |
85 | + id: number; // 配置id | |
86 | +} | |
87 | + | |
88 | +/** 删除配置 */ | |
89 | +export function deleteApi(params: DeleteParams) { | |
90 | + return request.post(`${CAS_HOST}/erp/team/setting/delete`, params); | |
91 | +} | |
92 | + | |
93 | +/** 删除 */ | |
94 | +export function endApi(id?: number): http.PromiseResp<string> { | |
95 | + return request.post(`${CAS_HOST}/erp/help/part/setting/delete`, { id }); | |
96 | +} | |
97 | + | |
98 | +/** | |
99 | + * 查询领辅料角色 | |
100 | + */ | |
101 | + | |
102 | +export interface User { | |
103 | + id: string; | |
104 | + name: string; | |
105 | +} | |
106 | + | |
107 | +export function getUserListApi(): http.PromiseResp<User[]> { | |
108 | + return request.get(`${CAS_HOST}/erp/help/part/setting/role/list`); | |
109 | +} | |
110 | + | |
111 | +/** | |
112 | + * 查询辅料类型 | |
113 | + */ | |
114 | + | |
115 | +export function getTypeListApi(): http.PromiseResp<User[]> { | |
116 | + return request.get(`${CAS_HOST}/erp/help/part/setting/type/list`); | |
117 | +} | ... | ... |
src/pages/cas/afterSaleConfiguration/manhoursProportionConfig/components/Filter.tsx
0 → 100644
1 | +import React, { useState, useEffect } from "react"; | |
2 | +import { Row, Select } from "antd"; | |
3 | +import { LabeledValue } from "antd/lib/select"; | |
4 | + | |
5 | +const Option = Select.Option; | |
6 | + | |
7 | +const userData = [ | |
8 | + { value: 7, label: "工作车辆" }, | |
9 | + { value: 8, label: "员工车辆" }, | |
10 | + { value: 9, label: "大客户" }, | |
11 | +]; | |
12 | + | |
13 | +export interface FilterPara { | |
14 | + discountType?: number; | |
15 | + discountTypeName?: string; | |
16 | + [key: string]: any; | |
17 | +} | |
18 | + | |
19 | +interface Props { | |
20 | + onChange: Function; | |
21 | + filterParam: FilterPara; | |
22 | +} | |
23 | + | |
24 | +export default function Filter({ onChange, filterParam}: Props) { | |
25 | + const [type, setType] = useState<LabeledValue>(); | |
26 | + | |
27 | + useEffect(() => { | |
28 | + if (filterParam) { | |
29 | + filterParam.discountType && filterParam.discountTypeName | |
30 | + ? setType({ | |
31 | + key: `${filterParam.discountType}`, | |
32 | + value: filterParam.discountType, | |
33 | + label: filterParam.discountTypeName, | |
34 | + }) | |
35 | + : null; | |
36 | + } | |
37 | + }, [filterParam]); | |
38 | + | |
39 | + function onTypeChange(value: LabeledValue) { | |
40 | + const _value = value || ({} as LabeledValue); | |
41 | + const { key, label } = _value; | |
42 | + onChange && | |
43 | + onChange( | |
44 | + { discountType: key || undefined, current: 1, discountTypeName: label }, | |
45 | + true | |
46 | + ); | |
47 | + } | |
48 | + | |
49 | + return ( | |
50 | + <Row style={{ width: "100%", alignItems: "center" }}> | |
51 | + <span>客户类型:</span> | |
52 | + <Select | |
53 | + allowClear={false} | |
54 | + placeholder="请选择" | |
55 | + labelInValue | |
56 | + value={type} | |
57 | + onChange={onTypeChange} | |
58 | + style={{ width: 150, marginLeft: 10 }} | |
59 | + > | |
60 | + {userData.map((r) => ( | |
61 | + <Option key={r.value} value={r.value}> | |
62 | + {r.label || ""} | |
63 | + </Option> | |
64 | + ))} | |
65 | + </Select> | |
66 | + </Row> | |
67 | + ); | |
68 | +} | ... | ... |
src/pages/cas/afterSaleConfiguration/manhoursProportionConfig/components/Modal.tsx
0 → 100644
1 | +import React, { useState, useEffect } from "react"; | |
2 | +import "@ant-design/compatible/assets/index.css"; | |
3 | +import { Select, Modal, Form, message } from "antd"; | |
4 | +import * as api from "../api"; | |
5 | +import { ListResult, SaveParams, saveApi, getShopRepairGroupsApi, ShopGroup } from "../api"; | |
6 | +import useInitial from "@/hooks/useInitail"; | |
7 | + | |
8 | +const FormItem = Form.Item; | |
9 | +const { Option } = Select; | |
10 | +const maxFormProps = { | |
11 | + labelCol: { span: 5 }, | |
12 | + wrapperCol: { span: 15 }, | |
13 | +}; | |
14 | + | |
15 | +interface Props { | |
16 | + visible: boolean; | |
17 | + onCancel: () => any; | |
18 | + shopId?: number; | |
19 | + detail?: ListResult; | |
20 | +} | |
21 | + | |
22 | +export default function SaveModal({ visible, onCancel, shopId, detail }: Props) { | |
23 | + const isNew = !detail.id; | |
24 | + | |
25 | + const [form] = Form.useForm(); | |
26 | + | |
27 | + const [confirmLoading, setConfirmLoading] = useState<boolean>(false); | |
28 | + const [userData, setUserData] = useState<api.User[]>([]); | |
29 | + | |
30 | + const { data: userList } = useInitial(getShopRepairGroupsApi, [], { shopId }); | |
31 | + | |
32 | + useEffect(() => { | |
33 | + if (detail.id) { | |
34 | + console.log(detail); | |
35 | + // form.setFieldsValue({ ..._item }); | |
36 | + } else { | |
37 | + form.resetFields(); | |
38 | + } | |
39 | + }, [visible]); | |
40 | + | |
41 | + function save(fieldsValue: any) { | |
42 | + console.log(fieldsValue); | |
43 | + setConfirmLoading(true); | |
44 | + const datas = { | |
45 | + id: detail.id || undefined, | |
46 | + roleCode: fieldsValue.roleCode.value, | |
47 | + partTypes: (fieldsValue.partTypes || []).map((e: any) => e.value), | |
48 | + }; | |
49 | + api | |
50 | + .saveApi(datas) | |
51 | + .then(() => { | |
52 | + message.success("操作成功!"); | |
53 | + setConfirmLoading(false); | |
54 | + onCancel(); | |
55 | + }) | |
56 | + .catch((e) => { | |
57 | + setConfirmLoading(false); | |
58 | + message.error(e.message); | |
59 | + }); | |
60 | + } | |
61 | + | |
62 | + return ( | |
63 | + <Modal | |
64 | + title={`${isNew ? "新增" : "编辑"}工时分成比例`} | |
65 | + width={600} | |
66 | + open={visible} | |
67 | + confirmLoading={confirmLoading} | |
68 | + onOk={() => form.submit()} | |
69 | + onCancel={onCancel} | |
70 | + > | |
71 | + <Form form={form} onFinish={save}> | |
72 | + <FormItem name="roleCode" label="角色" rules={[{ required: true, message: "必填" }]} {...maxFormProps}> | |
73 | + <Select labelInValue placeholder="请选择角色"> | |
74 | + {userData.map((r) => ( | |
75 | + <Select.Option key={r.id} value={r.id}> | |
76 | + {r.name || "--"} | |
77 | + </Select.Option> | |
78 | + ))} | |
79 | + </Select> | |
80 | + </FormItem> | |
81 | + <FormItem | |
82 | + label="可领辅料类型" | |
83 | + name="partTypes" | |
84 | + rules={[{ required: true, message: "该选项为必选项" }]} | |
85 | + {...maxFormProps} | |
86 | + > | |
87 | + <Select placeholder="请选择辅料类型" mode="multiple" labelInValue> | |
88 | + {[].map((r) => ( | |
89 | + <Select.Option key={r.id} value={r.id}> | |
90 | + {r.name || "--"} | |
91 | + </Select.Option> | |
92 | + ))} | |
93 | + </Select> | |
94 | + </FormItem> | |
95 | + </Form> | |
96 | + </Modal> | |
97 | + ); | |
98 | +} | ... | ... |
src/pages/cas/afterSaleConfiguration/manhoursProportionConfig/index.tsx
0 → 100644
1 | +import React, { useState } from "react"; | |
2 | +import { Card, ConfigProvider, Table, Button, Popconfirm, message } from "antd"; | |
3 | +import { PageHeaderWrapper } from "@ant-design/pro-layout"; | |
4 | +import zhCN from "antd/lib/locale-provider/zh_CN"; | |
5 | + | |
6 | +import usePagination from "@/hooks/usePagination"; | |
7 | +// import useInitial from "@/hooks/useInitail"; | |
8 | +import { getListApi, ListResult, deleteApi } from "./api"; | |
9 | + | |
10 | +// import Filter from "./components/Filter"; | |
11 | +import CreateModal from "./components/Modal"; | |
12 | + | |
13 | +const { Column } = Table; | |
14 | + | |
15 | +export default function ManhoursProportionConfig() { | |
16 | + // const { data, loading, setLoading } = useInitial(getListApi, [], {}); | |
17 | + const { loading, setLoading, list, paginationConfig } = usePagination(getListApi, {}); | |
18 | + | |
19 | + const [visible, setVisible] = useState(false); | |
20 | + const [detail, setDetail] = useState<any>({}); | |
21 | + | |
22 | + function handleDelete(row: ListResult) { | |
23 | + const deleteParams = { | |
24 | + id: row.teamId, | |
25 | + }; | |
26 | + deleteApi(deleteParams) | |
27 | + .then((res) => { | |
28 | + message.success("删除成功"); | |
29 | + setLoading(true); | |
30 | + }) | |
31 | + .catch((e) => { | |
32 | + message.error(`删除失败:${e.message}`); | |
33 | + }); | |
34 | + } | |
35 | + | |
36 | + return ( | |
37 | + <PageHeaderWrapper title="机修组工时分成比例配置"> | |
38 | + <Card> | |
39 | + <div | |
40 | + style={{ | |
41 | + display: "flex", | |
42 | + justifyContent: "flex-end", | |
43 | + marginBottom: "20px", | |
44 | + }} | |
45 | + > | |
46 | + {/* <Filter | |
47 | + filterParam={innerParams} | |
48 | + onChange={setParams} | |
49 | + /> */} | |
50 | + <Button type="primary" onClick={() => setVisible(true)}> | |
51 | + 新增 | |
52 | + </Button> | |
53 | + </div> | |
54 | + | |
55 | + <ConfigProvider locale={zhCN}> | |
56 | + <Table | |
57 | + dataSource={list} | |
58 | + loading={loading} | |
59 | + pagination={paginationConfig} | |
60 | + rowKey="teamId" | |
61 | + > | |
62 | + <Column | |
63 | + title="门店" | |
64 | + dataIndex="shopName" | |
65 | + width={200} | |
66 | + /> | |
67 | + <Column | |
68 | + title="机修组" | |
69 | + dataIndex="teamName" | |
70 | + width={200} | |
71 | + /> | |
72 | + <Column | |
73 | + title="分成比例" | |
74 | + dataIndex="shopName" | |
75 | + /> | |
76 | + | |
77 | + <Column | |
78 | + title="操作" | |
79 | + dataIndex="teamId" | |
80 | + align="center" | |
81 | + width={150} | |
82 | + render={(val, record: ListResult) => ( | |
83 | + <> | |
84 | + <Button | |
85 | + size="small" | |
86 | + type="primary" | |
87 | + onClick={() => { | |
88 | + setDetail(record); | |
89 | + setVisible(true); | |
90 | + }} | |
91 | + > | |
92 | + 编辑 | |
93 | + </Button> | |
94 | + <Popconfirm title="确认删除" onConfirm={() => handleDelete(row)}> | |
95 | + <Button danger type="link" size="small" style={{ marginLeft: 10 }}> | |
96 | + 删除 | |
97 | + </Button> | |
98 | + </Popconfirm> | |
99 | + </> | |
100 | + )} | |
101 | + /> | |
102 | + </Table> | |
103 | + </ConfigProvider> | |
104 | + </Card> | |
105 | + | |
106 | + <CreateModal | |
107 | + visible={visible} | |
108 | + detail={detail} | |
109 | + onCancel={() => { | |
110 | + setVisible(false); | |
111 | + setDetail({}); | |
112 | + setLoading(true); | |
113 | + }} | |
114 | + /> | |
115 | + </PageHeaderWrapper> | |
116 | + ); | |
117 | +} | ... | ... |