Commit 7af0743423436f3be7e82b2044f92ea9860af3f2

Authored by 杜志良
1 parent cc9f4a1c

feature: 添加机修组分成比例页面

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 +}
... ...