Commit 2683f4317154b8a2584303c368a3f6a5563929d0

Authored by 曾柯
1 parent d3a736bf

考评数据导入

config/routers/performance.ts
... ... @@ -84,6 +84,16 @@ export default [
84 84 path: "/morax/evaGroupSetting/edit/:id?/:read?/:type?",
85 85 component: "./performance/EvaGroupSetting/EditComfirm/index",
86 86 },
  87 + /** 考评数据导入 */
  88 + {
  89 + path: "/morax/evaDataImport",
  90 + component: "./performance/EvaDataImport",
  91 + },
  92 + /** 考评数据导入==> 查看数据清单 */
  93 + {
  94 + path: "/morax/evaDataImport/edit/:id?",
  95 + component: "./performance/EvaDataImport/EditComfirm/index",
  96 + },
87 97  
88 98 /** 旧 */
89 99 {
... ...
src/pages/performance/EvaDataImport/EditComfirm/index.tsx 0 → 100644
  1 +import React, { useState, useEffect } from "react";
  2 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  3 +import { Button, Card, Table, Row, message, Space, Typography, Divider, Switch, Upload } from "antd";
  4 +import usePagination from "@/hooks/usePagination";
  5 +import { evaDataDetailApi } from "../api";
  6 +import { UploadOutlined } from "@ant-design/icons";
  7 +import type { UploadProps } from "antd";
  8 +import useInitail from "@/hooks/useInitail";
  9 +import { createStore } from "@/hooks/moz";
  10 +import { common } from "@/typing/common";
  11 +import store from "./store";
  12 +import { isArray } from "lodash";
  13 +import moment from "moment";
  14 +import { ReasonsEnum } from "../entity";
  15 +import { history } from "umi";
  16 +import st from "./style.less";
  17 +
  18 +const Column = Table.Column;
  19 +export const { Provider, useStore } = createStore(store);
  20 +
  21 +interface Props extends common.ConnectProps {}
  22 +
  23 +function Index(props: Props) {
  24 + const { setId, configId } = useStore();
  25 + const [delay, setDelay] = useState(true);
  26 + const [newData, setNewData] = useState<any>([]);
  27 + const { match } = props;
  28 + const { id } = match.params;
  29 + useEffect(() => {
  30 + setId(id);
  31 + }, [id]);
  32 + useEffect(() => {
  33 + if (configId) {
  34 + setParams({ id: configId }, true);
  35 + setDelay(false);
  36 + }
  37 + }, [configId]);
  38 + const { data, errMsg, setParams, loading } = useInitail(evaDataDetailApi, {}, {}, delay);
  39 + console.log(isArray(data));
  40 + useEffect(() => {
  41 + if (isArray(data)) {
  42 + setNewData(data);
  43 + }
  44 + }, [data]);
  45 +
  46 + return (
  47 + <PageHeaderWrapper title="考评数据导入">
  48 + <Card>
  49 + <Table loading={loading} rowKey={(row) => `id${id}`} dataSource={newData}>
  50 + <Column title="归属人员" dataIndex="userName" align="center" render={(name) => <span>{name || "--"}</span>} />
  51 + <Column title="归属门店" dataIndex="shopName" align="center" render={(name) => <span>{name || "--"}</span>} />
  52 + <Column
  53 + title="指标名称"
  54 + dataIndex="indicatorName"
  55 + align="center"
  56 + render={(name) => <span>{name || "--"}</span>}
  57 + />
  58 + <Column
  59 + title="指标值"
  60 + dataIndex="indicatorValue"
  61 + align="center"
  62 + render={(num, record: any) => (
  63 + <span>
  64 + {num !== undefined
  65 + ? `${num}${
  66 + record.dataType == 1 ? "台" : record.dataType == 2 ? "%" : record.dataType == 3 ? "元" : ""
  67 + }`
  68 + : "--"}
  69 + </span>
  70 + )}
  71 + />
  72 + <Column
  73 + title="考核周期"
  74 + dataIndex="dataDate"
  75 + align="center"
  76 + render={(time: number) => (time ? moment(time).format("YYYY-MM-DD") : "--")}
  77 + />
  78 + {/* <Column title="更新日期" dataIndex="dataDate" align="center" render={(time: number) => ""} /> */}
  79 + <Column
  80 + title="是否导入"
  81 + dataIndex="errorType"
  82 + align="center"
  83 + render={(_: any, record: any) => (record.errorType ? <div className={st.no}>未导入</div> : <div className={st.yes}>已导入</div>)}
  84 + />
  85 + <Column
  86 + title="未导入原因"
  87 + dataIndex="errorType"
  88 + align="center"
  89 + render={(_: any, record: any) => (record.errorType ? ReasonsEnum[record.errorType] : "--")}
  90 + />
  91 + </Table>
  92 + <Row justify="center">
  93 + <Button type="default" size="large" onClick={() => history.goBack()} style={{ marginRight: 50, width: 200 }}>
  94 + 返回
  95 + </Button>
  96 + </Row>
  97 + </Card>
  98 + </PageHeaderWrapper>
  99 + );
  100 +}
  101 +export default (props: Props) => (
  102 + <Provider>
  103 + <Index {...props} />
  104 + </Provider>
  105 +);
... ...
src/pages/performance/EvaDataImport/EditComfirm/store.ts 0 → 100644
  1 +import { useEffect, useState } from "react";
  2 +import useInitail from "@/hooks/useInitail";
  3 +import usePagination from "@/hooks/usePagination";
  4 +import { getAllPostListApi, getManagerRoleListApi } from "@/common/api";
  5 +
  6 +export default function useStore() {
  7 + const [configId, setId] = useState<number>(0);
  8 +
  9 + return {
  10 + configId,
  11 + setId,
  12 + };
  13 +}
... ...
src/pages/performance/EvaDataImport/EditComfirm/style.less 0 → 100644
  1 +.no {
  2 + width: 47px;
  3 + height: 18px;
  4 + margin: 0 auto;
  5 + color: #f4333c;
  6 + font-weight: 500;
  7 + font-size: 12px;
  8 + line-height: 18px;
  9 + border: 1px solid #f8797f;
  10 + border-radius: 2px;
  11 +}
  12 +.yes {
  13 + width: 47px;
  14 + height: 18px;
  15 + margin: 0 auto;
  16 + color: #20c688;
  17 + font-weight: 500;
  18 + font-size: 12px;
  19 + line-height: 18px;
  20 + border: 1px solid #6ddab2;
  21 + border-radius: 2px;
  22 +}
... ...
src/pages/performance/EvaDataImport/api.ts 0 → 100644
  1 +import request from "@/utils/request";
  2 +import { DALARAN, MORAX_HOST, CRM_HOST } from "@/utils/host";
  3 +import { http } from "@/typing/http";
  4 +
  5 +evaDataListApi;
  6 +
  7 +export interface PageParams {
  8 + current?: number;
  9 + pageSize?: number;
  10 +}
  11 +
  12 +/** 考评指标库列表
  13 + * http://testgate.feewee.cn/morax/erp/eval/indicator/page
  14 + */
  15 +export function evaDataListApi(params: EvaData.EvaDataListParams): http.PromisePageResp<EvaData.EvaDataItems> {
  16 + return request.get(`${MORAX_HOST}/erp/eval-indicator/import-page`, { params });
  17 +}
  18 +
  19 +/**
  20 + * @description: 第三方渠道导入人员
  21 + */
  22 +export function saveImportPersonApi(params: any) {
  23 + return request.post<string>(`${MORAX_HOST}/erp/eval-indicator/staff-indicator`, params, {
  24 + contentType: "form-data",
  25 + });
  26 +}
  27 +
  28 +/**
  29 + * 第三方渠道导入门店
  30 + */
  31 +export function saveImportShopApi(params: { file: any[] }): http.PromiseResp<EvaData.ImportShop> {
  32 + return request.post(`${MORAX_HOST}/erp/eval-indicator/shop-indicator`, params, {
  33 + contentType: "form-data",
  34 + });
  35 +}
  36 +
  37 +/** 导入记录详情查询
  38 + * http://testgate.feewee.cn/morax/erp/eval-indicator/import-detail
  39 + */
  40 +export function evaDataDetailApi(params: { id: number }): http.PromisePageResp<any> {
  41 + return request.get(`${MORAX_HOST}/erp/eval-indicator/import-detail`, { params });
  42 +}
  43 +
  44 +export function evaDataIndApi(): http.PromiseResp<any> {
  45 + return request.get(`${MORAX_HOST}/erp/eval-indicator/indicators`, {});
  46 +}
... ...
src/pages/performance/EvaDataImport/components/Filter.tsx 0 → 100644
  1 +import React, { useState, useEffect, useCallback } from "react";
  2 +import { Table, Row, Input, Select, DatePicker } from "antd";
  3 +import type { DatePickerProps, RangePickerProps } from "antd/es/date-picker";
  4 +// import { ApprovalType, Approval_Status } from "../entity";
  5 +import _ from "lodash";
  6 +import usePagination from "@/hooks/usePagination";
  7 +import { systemListApi } from "@/pages/admin/Privilege/api";
  8 +import { getStaffApi } from "@/common/api";
  9 +import { evaDataIndApi } from "../api";
  10 +import useInitial from "@/hooks/useInitail";
  11 +import moment from "moment";
  12 +
  13 +const { RangePicker } = DatePicker;
  14 +
  15 +const { Option } = Select;
  16 +interface Props {
  17 + setParams: any;
  18 +}
  19 +
  20 +export default function Filter({ setParams }: Props) {
  21 + // const { list: syslist } = usePagination(systemListApi, {
  22 + // current: 1,
  23 + // pageSize: 500,
  24 + // });
  25 + const { list } = usePagination(getStaffApi, { current: 1, pageSize: 1000 });
  26 + const { data } = useInitial(evaDataIndApi, [], {});
  27 +
  28 + // const seachOnchange = useCallback(
  29 + // _.debounce((param) => {
  30 + // setParams({ ...param }, true);
  31 + // }, 800),
  32 + // [setParams]
  33 + // );
  34 + const onChange = (value: RangePickerProps["value"], dateString: [string, string] | string) => {
  35 + console.log("Selected Time: ", value);
  36 + if (value) {
  37 + setParams({ startTime: moment(value[0]).unix() * 1000, endTime: moment(value[1]).unix() * 1000 }, true);
  38 + }
  39 + };
  40 +
  41 + return (
  42 + <Row justify="start" style={{ marginBottom: 20 }}>
  43 + <Select
  44 + allowClear
  45 + placeholder="请选择指标名称"
  46 + style={{ width: 150, marginRight: 10, marginBottom: 10 }}
  47 + onChange={(value) => {
  48 + setParams({ indicatorCode: value }, true);
  49 + }}
  50 + showSearch
  51 + optionFilterProp="children"
  52 + >
  53 + {data.map((item: any) => (
  54 + <Option value={item.code} key={item.code}>
  55 + {item.name}
  56 + </Option>
  57 + ))}
  58 + </Select>
  59 + <Select
  60 + allowClear
  61 + placeholder="请选择导入人员"
  62 + style={{ width: 150, marginRight: 10, marginBottom: 10 }}
  63 + onChange={(value) => {
  64 + setParams({ userId: value }, true);
  65 + }}
  66 + showSearch
  67 + optionFilterProp="children"
  68 + >
  69 + {list.map((item) => (
  70 + <Option value={item.id} key={item.id}>
  71 + {item.name}
  72 + </Option>
  73 + ))}
  74 + </Select>
  75 + <RangePicker onChange={onChange} style={{ height: 32 }} />
  76 + </Row>
  77 + );
  78 +}
... ...
src/pages/performance/EvaDataImport/entity.ts 0 → 100644
  1 +export enum ReasonsEnum {
  2 + "未匹配到人员" = 1,
  3 + "未匹配到门店" = 2,
  4 + "未匹配到指标" = 3,
  5 + "重复" = 4,
  6 +}
... ...
src/pages/performance/EvaDataImport/index.tsx 0 → 100644
  1 +import React, { useState } from "react";
  2 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  3 +import { Button, Card, Table, Row, message, Space, Typography, Divider, Switch, Upload } from "antd";
  4 +import usePagination from "@/hooks/usePagination";
  5 +import { evaDataListApi } from "./api";
  6 +import { UploadOutlined } from "@ant-design/icons";
  7 +import type { UploadProps } from "antd";
  8 +import { history } from "umi";
  9 +import moment from "moment";
  10 +import Filter from './components/Filter';
  11 +
  12 +const Column = Table.Column;
  13 +
  14 +export default () => {
  15 + const { loading, list, paginationConfig, setParams, innerParams } = usePagination(evaDataListApi, {
  16 + pageSize: 10,
  17 + enable: true,
  18 + });
  19 + const uploadPerson: UploadProps = {
  20 + name: "file",
  21 + action: "/api/morax/erp/eval-indicator/staff-indicator",
  22 + maxCount: 1,
  23 + showUploadList: false,
  24 + onChange(info) {
  25 + if (info.file.status !== "uploading") {
  26 + console.log(info.file, info.fileList);
  27 + }
  28 + if (info.file.status === "done") {
  29 + message.success(`${info.file.name} 导入成功`);
  30 + setParams({ ...innerParams }, true);
  31 + } else if (info.file.status === "error") {
  32 + message.error(`${info.file.name} 导入失败`);
  33 + }
  34 + },
  35 + };
  36 + const uploadShop: UploadProps = {
  37 + name: "file",
  38 + action: "/api/morax/erp/eval-indicator/shop-indicator",
  39 + maxCount: 1,
  40 + showUploadList: false,
  41 + onChange(info) {
  42 + if (info.file.status !== "uploading") {
  43 + console.log(info.file, info.fileList);
  44 + }
  45 + if (info.file.status === "done") {
  46 + message.success(`${info.file.name} 导入成功`);
  47 + setParams({ ...innerParams }, true);
  48 + } else if (info.file.status === "error") {
  49 + message.error(`${info.file.name} 导入失败`);
  50 + }
  51 + },
  52 + };
  53 +
  54 + return (
  55 + <PageHeaderWrapper title="考评数据导入">
  56 + <Card>
  57 + <Row style={{ marginBottom: 10 }} justify='space-between'>
  58 + <Filter setParams={setParams} />
  59 + <div>
  60 + <Button type="default" style={{ marginRight: 10 }}>
  61 + <a href="http://testgate.feewee.cn/morax/erp/eval-indicator/staff/template-file">下载人员模板</a>
  62 + </Button>
  63 + <Button type="default" style={{ marginRight: 10 }}>
  64 + <a href="http://testgate.feewee.cn/morax/erp/eval-indicator/shop/template-file">下载门店模板</a>
  65 + </Button>
  66 + <Upload {...uploadPerson}>
  67 + <Button type="primary" style={{ marginRight: 10 }}>
  68 + 按人员导入
  69 + </Button>
  70 + </Upload>
  71 + <Upload {...uploadShop}>
  72 + <Button type="primary">按门店导入</Button>
  73 + </Upload>
  74 + </div>
  75 + </Row>
  76 +
  77 + <Table
  78 + loading={loading}
  79 + rowKey={(row) => `id${row.indicatorCode}`}
  80 + dataSource={list}
  81 + pagination={paginationConfig}
  82 + >
  83 + <Column
  84 + title="导入时间"
  85 + dataIndex="createTime"
  86 + align="center"
  87 + render={(time: number) => (time ? moment(time).format("YYYY-MM-DD") : "--")}
  88 + />
  89 + <Column
  90 + title="导入人员"
  91 + dataIndex="importUserName"
  92 + align="center"
  93 + render={(name) => <span>{name || "--"}</span>}
  94 + />
  95 + <Column
  96 + title="指标名称"
  97 + dataIndex="indicatorName"
  98 + align="center"
  99 + render={(name) => <span>{name || "--"}</span>}
  100 + />
  101 + <Column
  102 + title="导入数据"
  103 + dataIndex="num"
  104 + align="center"
  105 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  106 + />
  107 + <Column
  108 + title="成功"
  109 + dataIndex="successNum"
  110 + align="center"
  111 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  112 + />
  113 + <Column
  114 + title="失败"
  115 + dataIndex="errorNum"
  116 + align="center"
  117 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  118 + />
  119 + <Column
  120 + title="数据清单"
  121 + align="center"
  122 + dataIndex="enable"
  123 + width={150}
  124 + render={(text: boolean, record: KpiSetteing.KpiListItems) => (
  125 + <Space split={<Divider type="vertical" />}>
  126 + <Typography.Link
  127 + onClick={() => {
  128 + history.push(`/morax/evaDataImport/edit/${record.id}`);
  129 + }}
  130 + >
  131 + 查看
  132 + </Typography.Link>
  133 + </Space>
  134 + )}
  135 + />
  136 + </Table>
  137 + </Card>
  138 + </PageHeaderWrapper>
  139 + );
  140 +};
... ...
src/pages/performance/EvaDataImport/interface.ts 0 → 100644
  1 +declare namespace EvaData {
  2 + interface EvaDataListParams {
  3 + current?: number;
  4 + pageSize?: number;
  5 + indicatorCode?: number;
  6 + userId?: number;
  7 + startTime?: string;
  8 + endTime?: string;
  9 + groupId?: number;
  10 + }
  11 + /**
  12 + * 数据库列表项
  13 + */
  14 + interface EvaDataItems {
  15 + id: number;
  16 + importUserId: number;
  17 + importUserName: string;
  18 + shopId: number;
  19 + shopName: string;
  20 + dimensionType: number;
  21 + indicatorCode: string;
  22 + indicatorName: string;
  23 + valueType: number;
  24 + dataDate: string;
  25 + num: number;
  26 + successNum: number;
  27 + errorNum: number;
  28 + groupId: number;
  29 + yn: boolean;
  30 + }
  31 + /**
  32 + * 导入人员
  33 + */
  34 + interface ImportPerson {
  35 + staffName: string;
  36 + shopName: string;
  37 + indicatorName: string;
  38 + indicatorValue: string;
  39 + applyTime: string;
  40 + }
  41 + /**
  42 + * 导入门店
  43 + */
  44 + interface ImportShop {
  45 + shopName: string;
  46 + indicatorName: string;
  47 + indicatorValue: string;
  48 + }
  49 + interface ImportParams {
  50 + file: any;
  51 + }
  52 + interface EvaDataDetai {
  53 + evalIndicatorImportRecordId: number;
  54 + userId: number;
  55 + userName: string;
  56 + shopId: number;
  57 + shopName: string;
  58 + indicatorName: string;
  59 + indicatorCode: string;
  60 + indicatorValue: string;
  61 + valueType: number;
  62 + dataDate: string;
  63 + groupId: number;
  64 + yn: boolean;
  65 + errorMsg: string;
  66 + }
  67 +}
0 68 \ No newline at end of file
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddEvaGroupModal.tsx
... ... @@ -51,6 +51,13 @@ export default function AddIndicatorsModal(props: Props) {
51 51 useEffect(() => {
52 52 getRoleList();
53 53 if (visible && evaItem.name) {
  54 + if (evaItem.shop) {
  55 + const shopIds = evaItem.shop.map((item) => item.value);
  56 + setPersonModal({
  57 + shopIds: shopIds.join(","),
  58 + visible: false,
  59 + });
  60 + }
54 61 if (evaItem.shop && evaItem.post) {
55 62 const shopIds = evaItem.shop.map((item) => item.value);
56 63 const postId = evaItem.post.value;
... ...
src/pages/performance/EvaGroupSetting/components/NormalList.tsx
... ... @@ -70,7 +70,7 @@ export default ({ type }: Props) =&gt; {
70 70 render={(_: any, record: EvaGroupSetteing.EvaGroupListItems) => (
71 71 <Typography.Link
72 72 onClick={() => {
73   - history.push(`/morax/evaGroupSetting/edit/${record.draftId}/true/${type}`);
  73 + history.push(`/morax/evaGroupSetting/edit/${record.id}/true/${type}`);
74 74 }}
75 75 >
76 76 查看
... ...
src/pages/performance/EvaSetting/index.tsx
... ... @@ -34,7 +34,7 @@ export default () =&gt; {
34 34 // 重新刷新列表
35 35 setParams({ ...innerParams }, true);
36 36 }
37   - } catch (error) {
  37 + } catch (error: any) {
38 38 message.error(error.message);
39 39 }
40 40 };
... ... @@ -78,7 +78,21 @@ export default () =&gt; {
78 78 title="上报数据范围"
79 79 dataIndex="dataScopeTypes"
80 80 align="center"
81   - render={(dataScopeTypes) => (dataScopeTypes ? (dataScopeTypes[0] == 1 ? "考核人" : dataScopeTypes[0] == 2 ? "考核门店" : "考核人;考核门店") : "--")}
  81 + render={(dataScopeTypes) => {
  82 + if (dataScopeTypes) {
  83 + if (dataScopeTypes.length == 1) {
  84 + if (dataScopeTypes[0] == 1) {
  85 + return "考核人";
  86 + } else {
  87 + return "考核门店";
  88 + }
  89 + } else {
  90 + return "考核人;考核门店";
  91 + }
  92 + } else {
  93 + return "--";
  94 + }
  95 + }}
82 96 />
83 97 <Column
84 98 title="是否设置目标要求"
... ...
src/pages/performance/EvaSetting/interface.ts
... ... @@ -17,6 +17,7 @@ declare namespace EvaSetteing {
17 17 * 指标库列表项
18 18 */
19 19 interface EvaListItems {
  20 + id: number;
20 21 sysId: number; //归属系统id
21 22 sysPrefix: string; // 归属系统前缀
22 23 sysName: string; //归属系统名称
... ...
src/pages/performance/KpiSetting/index.tsx
... ... @@ -78,7 +78,21 @@ export default () =&gt; {
78 78 title="上报数据范围"
79 79 dataIndex="dataScopeTypes"
80 80 align="center"
81   - render={(dataScopeTypes) => (dataScopeTypes ? (dataScopeTypes[0] == 1 ? "考核人" : dataScopeTypes[0] == 2 ? "考核门店" : "考核人;考核门店") : "--")}
  81 + render={(dataScopeTypes) => {
  82 + if (dataScopeTypes) {
  83 + if (dataScopeTypes.length == 1) {
  84 + if (dataScopeTypes[0] == 1) {
  85 + return "考核人";
  86 + } else {
  87 + return "考核门店";
  88 + }
  89 + } else {
  90 + return "考核人;考核门店";
  91 + }
  92 + } else {
  93 + return "--";
  94 + }
  95 + }}
82 96 />
83 97 <Column title="指标类型" dataIndex="dataType" align="center" render={(type) => DataTypeEnum[type]} />
84 98 <Column
... ...