Commit cfb1af9195d2e9dc61b47441ac063a906d71f9ae

Authored by 张志伟
2 parents 749b9772 c9868143

Merge remote-tracking branch 'origin/master' into bug_fix

config/routers/performance.ts
... ... @@ -99,6 +99,11 @@ export default [
99 99 path: '/morax/evaDataImport',
100 100 component: './performance/EvaDataImport',
101 101 },
  102 + /** 数据导入 */
  103 + {
  104 + path: '/morax/DataImport',
  105 + component: './performance/DataImport',
  106 + },
102 107 /** 考评数据导入==> 查看数据清单 */
103 108 {
104 109 path: '/morax/evaDataImport/edit/:id?/:dimensionType?',
... ...
src/components/ApprovalProgress/index.tsx
... ... @@ -43,41 +43,6 @@ export default function ApprovalProgress({ orderNo }: Props) {
43 43 setProgress({
44 44 loading: false,
45 45 data: res.data || [],
46   - // data: [
47   - // {
48   - // // 审批中倒计时
49   - // approveTime: 1709741004000,
50   - // approverName: 'Shinner',
51   - // approverId: 2144,
52   - // status: 1,
53   - // opinion: '测试理由',
54   - // efficientTime: 1709781004000,
55   - // createTime: 1709721004000,
56   - // roleNames: ['销售一级管理', '销售二级管理', '销售三级管理'],
57   - // },
58   - // {
59   - // // 审批中超时
60   - // approveTime: 1799722004000,
61   - // approverName: 'Shinner',
62   - // approverId: 2145,
63   - // status: 1,
64   - // opinion: '测试理由',
65   - // efficientTime: 1709721004000,
66   - // createTime: 1709721004000,
67   - // roleNames: ['销售一级管理', '销售二级管理', '销售三级管理'],
68   - // },
69   - // {
70   - // // 审批结束超时
71   - // approveTime: 1799722004000,
72   - // approverName: 'Shinner',
73   - // approverId: 2146,
74   - // status: 2,
75   - // opinion: '测试理由',
76   - // efficientTime: 1709781004000,
77   - // createTime: 1709721004000,
78   - // roleNames: ['销售一级管理', '销售二级管理', '销售三级管理'],
79   - // },
80   - // ],
81 46 });
82 47 })
83 48 .catch((error) => {
... ...
src/pages/performance/DataImport/api.ts 0 → 100644
  1 +import request from '@/utils/request';
  2 +import { MORAX_HOST } from '@/utils/host';
  3 +import type { Page } from '@/typing/common';
  4 +import type { Data } from 'ahooks/lib/useAntdTable/types';
  5 +
  6 +/**
  7 + * 展厅美化导入记录分页查询
  8 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/showroom-page
  9 + */
  10 +export async function DataImportAPi(params: MDataImport.DataImportListParams) {
  11 + const res = await request.get<Page<MDataImport.DataImportList>>(`${MORAX_HOST}/erp/eval-indicator-import/showroom-page`, {
  12 + params,
  13 + });
  14 + const data = res?.data || { total: 0, list: [], data: [] };
  15 + if (data) {
  16 + const d = data.data || [];
  17 + data.data = d;
  18 + data.list = d;
  19 + }
  20 + return data as Data;
  21 +}
  22 +
  23 +/**
  24 + * 数据导入指标列表
  25 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/indicators
  26 + */
  27 +export async function IndicatorListApi() {
  28 + const res = await request.get<MDataImport.IndicatorList[]>(`${MORAX_HOST}/erp/eval-indicator-import/indicators`);
  29 + return res.data ?? [];
  30 +}
  31 +
  32 +/**
  33 + * 展厅美化导入清单查询
  34 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/showroom-detail
  35 + */
  36 +
  37 +export async function DetailedListAPi(params: MDataImport.DataImportListParams) {
  38 + const res = await request.get<Page<MDataImport.DetailedList>>(`${MORAX_HOST}/erp/eval-indicator-import/showroom-detail`, {
  39 + params,
  40 + });
  41 + const data = res?.data || { total: 0, list: [], data: [] };
  42 + if (data) {
  43 + const d = data.data || [];
  44 + data.data = d;
  45 + data.list = d;
  46 + }
  47 + return data as Data;
  48 +}
  49 +/**
  50 + * 展厅美化导入记录详情查询
  51 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/showroom-import-detail
  52 + */
  53 +
  54 +export async function ImportListDetailApi(id?: number) {
  55 + const res = await request.get<MDataImport.DataImportList>(`${MORAX_HOST}/erp/eval-indicator-import/showroom-import-detail`, { params: { id } });
  56 + return res.data ?? {};
  57 +}
  58 +
  59 +/**
  60 + * 上传展厅美化数据
  61 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/analysis/showroom-shop
  62 + */
  63 +
  64 +export async function UploadImportApi(fid?: string, indicatorCode?: string) {
  65 + const res = await request.get<MDataImport.DataImportList>(`${MORAX_HOST}/erp/eval-indicator-import/analysis/showroom-shop`, {
  66 + params: { fid, indicatorCode },
  67 + });
  68 + return res.data ?? {};
  69 +}
  70 +
  71 +/**
  72 + * 下载展厅美化数据
  73 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/template-file
  74 + */
  75 +
  76 +export async function DownloadApi( indicatorCode?: string) {
  77 + const res = await request.get<any>(`${MORAX_HOST}/erp/eval-indicator-import/template-file`, {
  78 + params: { indicatorCode },
  79 + });
  80 + return res.data ?? {};
  81 +}
  82 +
  83 +/**
  84 + * 删除导入审批
  85 + * http://testgate.feewee.cn/morax/erp/eval-indicator/del-import
  86 + */
  87 +export function deleteApi(params: { id: number }) {
  88 + return request.get(`${MORAX_HOST}/erp/eval-indicator/del-import`, { params });
  89 +}
  90 +/**
  91 + * 撤销审批
  92 + * http://testgate.feewee.cn/morax/erp/eval-indicator/cancel
  93 + */
  94 +export function revokeApi(params: { id: number }) {
  95 + return request.get(`${MORAX_HOST}/erp/eval-indicator/cancel`, { params });
  96 +}
  97 +
  98 +/**
  99 + * 保存展厅美化数据
  100 + * http://testgate.feewee.cn/morax/erp/eval-indicator-import/save-showroom-import
  101 + */
  102 +export function SaveDataApi(params: { key: string }) {
  103 + return request.get(`${MORAX_HOST}/erp/eval-indicator-import/save-showroom-import`, { params });
  104 +}
0 105 \ No newline at end of file
... ...
src/pages/performance/DataImport/components/DetailList.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Table, message, DatePicker, Select } from 'antd';
  3 +import type { ColumnsType } from 'antd/es/table';
  4 +import type { DatePickerProps } from 'antd';
  5 +import { DetailedListAPi } from '../api';
  6 +import { useAntdTable } from 'ahooks';
  7 +import moment from 'moment';
  8 +import useInitial from '@/hooks/useInitail';
  9 +import { getShopApi } from '@/common/api';
  10 +
  11 +type Props = {
  12 + indicator?: MDataImport.IndicatorList;
  13 + onChange?: (value?: any) => void;
  14 +};
  15 +interface DataType {
  16 + key: string;
  17 + name: string;
  18 +}
  19 +export default function TableList({ indicator }: Props) {
  20 + const [monthly, setMonthly] = useState<number>();
  21 + const [shopId, setShopId] = useState<number>();
  22 + const { data } = useInitial(getShopApi, [], {});
  23 + const pickMonth: DatePickerProps['onChange'] = (date, _dateString) => {
  24 + setMonthly(date?.valueOf() ?? 0);
  25 + };
  26 + function shopChange(value: any) {
  27 + setShopId(value);
  28 + }
  29 + //@ts-ignore
  30 + const { tableProps, run } = useAntdTable<any, MDataImport.DataImportListParams[]>(DetailedListAPi, {
  31 + manual: true,
  32 + defaultParams: [
  33 + {
  34 + pageSize: 10,
  35 + current: 1,
  36 + shopId: undefined,
  37 + monthly: Date.now(),
  38 + indicatorCode: indicator?.code || '',
  39 + },
  40 + ],
  41 + onError: (e, _) => {
  42 + message.error(e.message);
  43 + },
  44 + });
  45 + const columns: ColumnsType<DataType> = [
  46 + {
  47 + title: '月度',
  48 + dataIndex: 'dataDate',
  49 + align:'center',
  50 + width: 200,
  51 + key: 'dataDate',
  52 + render: (time: number) => (time ? moment(time).format('YYYY-MM') : '--'),
  53 + },
  54 + {
  55 + title: '门店',
  56 + dataIndex: 'shopName',
  57 + width: 300,
  58 + align:'center',
  59 + key: 'shopName',
  60 + render: (name) => <span>{name || '--'}</span>,
  61 + },
  62 + {
  63 + title: '打分',
  64 + dataIndex: 'score',
  65 + width: 100,
  66 + align:'center',
  67 + key: 'score',
  68 + render: (name) => <span>{name || '--'}</span>,
  69 + },
  70 + {
  71 + title: '总分',
  72 + key: 'totalScore',
  73 + width: 100,
  74 + align:'center',
  75 + dataIndex: 'totalScore',
  76 + render: (name) => <span>{name || '--'}</span>,
  77 + },
  78 + {
  79 + title: '打分人员',
  80 + key: 'graderStaffName',
  81 + width: 200,
  82 + align:'center',
  83 + dataIndex: 'graderStaffName',
  84 + render: (name) => <span>{name || '--'}</span>,
  85 + },
  86 + ];
  87 + useEffect(() => {
  88 + if(indicator?.code){
  89 + run({
  90 + pageSize: 10,
  91 + current: 1,
  92 + monthly: monthly || Date.now(),
  93 + indicatorCode: indicator?.code || '',
  94 + shopId: shopId || undefined,
  95 + });
  96 + }
  97 + }, [indicator?.code, monthly, shopId]);
  98 + return (
  99 + <>
  100 + <div style={{ display: 'flex' }}>
  101 + <DatePicker value={monthly?moment(monthly):undefined} onChange={pickMonth} picker="month" style={{ marginRight: 20 }} />
  102 + <Select allowClear style={{ width: 200, marginRight: 20 }} placeholder="请选择门店" onChange={shopChange}>
  103 + {(data || []).map((shop) => (
  104 + <Select.Option value={shop.id} key={shop.id}>
  105 + {shop.name}
  106 + </Select.Option>
  107 + ))}
  108 + </Select>
  109 + </div>
  110 + <Table columns={columns} {...tableProps} rowKey="id" style={{ marginTop: 20 }} />
  111 + </>
  112 + );
  113 +}
... ...
src/pages/performance/DataImport/components/ExcelTable.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Table, message, Modal } from 'antd';
  3 +import { UploadImportApi, SaveDataApi } from '../api';
  4 +import { useRequest } from 'ahooks';
  5 +import { ErrorType } from '../entity';
  6 +
  7 +import moment from 'moment';
  8 +interface Props {
  9 + fid?: string;
  10 + show?: boolean;
  11 + indicator?: MDataImport.IndicatorList;
  12 + setExcelvisible?: (bool: boolean) => void;
  13 + refresh?: () => void;
  14 +}
  15 +export default function ExcelTable({ fid, show, indicator, setExcelvisible, refresh }: Props) {
  16 + const { data, run, loading } = useRequest<MDataImport.DataImportList, string[]>(UploadImportApi, {
  17 + manual: true,
  18 + onError: (e, _) => {
  19 + message.error(e.message);
  20 + },
  21 + });
  22 +
  23 + useEffect(() => {
  24 + if (show) {
  25 + run(fid || '', indicator?.code || '');
  26 + }
  27 + }, [show, fid, indicator]);
  28 + const savesubmit = () => {
  29 + SaveDataApi({ key: data?.key || '' })
  30 + .then(() => {
  31 + message.success('操作成功');
  32 + setExcelvisible?.(false);
  33 + refresh?.();
  34 + })
  35 + .catch((error) => {
  36 + message.error(error.message);
  37 + setExcelvisible?.(false);
  38 + });
  39 + };
  40 + const tableItem: any = [
  41 + {
  42 + title: '月度',
  43 + align: 'center',
  44 + width: 100,
  45 + dataIndex: 'dataDate',
  46 + key: 'dataDate',
  47 + render: (time: number) => (time ? moment(time).format('YYYY-MM') : '--'),
  48 + },
  49 + {
  50 + title: '门店',
  51 + dataIndex: 'shopName',
  52 + align: 'center',
  53 + key: 'shopName',
  54 + render: (name: any) => <span>{name || '--'}</span>,
  55 + },
  56 + {
  57 + title: '打分',
  58 + width: 100,
  59 + dataIndex: 'score',
  60 + align: 'center',
  61 + key: 'score',
  62 + render: (name: any) => <span>{name || '--'}</span>,
  63 + },
  64 + {
  65 + title: '总分',
  66 + width: 100,
  67 + dataIndex: 'totalScore',
  68 + align: 'center',
  69 + key: 'totalScore',
  70 + render: (name: any) => <span>{name || '--'}</span>,
  71 + },
  72 + {
  73 + title: '打分人员',
  74 + width: 100,
  75 + dataIndex: 'graderStaffName',
  76 + align: 'center',
  77 + key: 'graderStaffName',
  78 + render: (name: any) => <span>{name || '--'}</span>,
  79 + },
  80 + {
  81 + title: '是否识别',
  82 + width: 100,
  83 + dataIndex: 'errorType',
  84 + align: 'center',
  85 + render: (_: any, record: any) => (record.errorType ? <div>未识别</div> : <div>已识别</div>),
  86 + },
  87 + {
  88 + title: '未识别原因',
  89 + width: 150,
  90 + dataIndex: 'errorType',
  91 + align: 'center',
  92 + render: (_: any, record: any) => (record.errorType ? ErrorType[record.errorType] : '--'),
  93 + },
  94 + ];
  95 + return (
  96 + <Modal
  97 + open={show}
  98 + destroyOnClose
  99 + onCancel={() => {
  100 + setExcelvisible?.(false);
  101 + }}
  102 + width="70%"
  103 + keyboard
  104 + onOk={savesubmit}
  105 + >
  106 + <Table loading={loading} dataSource={data?.details} columns={tableItem} pagination={{ pageSizeOptions: [10, 20, 50] }} />
  107 + <div>
  108 + 成功条数: <span style={{ color: '#20c688' }}>{data?.successNum}</span> 条
  109 + </div>
  110 + <div>
  111 + 失败条数: <span style={{ color: '#f4333c' }}>{data?.errorNum}</span> 条
  112 + </div>
  113 + </Modal>
  114 + );
  115 +}
... ...
src/pages/performance/DataImport/components/ImportList.tsx 0 → 100644
  1 +import React, { useEffect, useState, useRef } from 'react';
  2 +import { Table, Button, Tag, message, DatePicker, Select, Modal, Upload, Space, Divider, Popconfirm, Typography } from 'antd';
  3 +import type { UploadProps } from 'antd';
  4 +import type { ColumnsType } from 'antd/es/table';
  5 +import { DataImportAPi, ImportListDetailApi, DownloadApi, deleteApi, revokeApi } from '../api';
  6 +import { useAntdTable } from 'ahooks';
  7 +import moment from 'moment';
  8 +import type { DatePickerProps } from 'antd';
  9 +import useInitial from '@/hooks/useInitail';
  10 +import { getShopApi } from '@/common/api';
  11 +import { SelectStatus } from '../entity';
  12 +import { DownloadOutlined, PlusOutlined } from '@ant-design/icons';
  13 +import { useRequest } from 'ahooks';
  14 +import ApprovalProgressModal from '@/components/ApprovalProgressModal';
  15 +import type { ApprovalProgressModalRef } from '@/components/ApprovalProgressModal';
  16 +import dowloader from '@/utils/downloader';
  17 +import { IMGURL } from '@/utils';
  18 +import ExcelTable from './ExcelTable';
  19 +
  20 +type Props = {
  21 + indicator?: MDataImport.IndicatorList;
  22 +};
  23 +interface DataType {
  24 + key: string;
  25 + name: string;
  26 +}
  27 +export default function TableList({ indicator }: Props) {
  28 + const [monthly, setMonthly] = useState<number>();
  29 + const [shopId, setShopId] = useState<number>();
  30 + const [status, setStatus] = useState<number>();
  31 + const [fid, setFid] = useState<string>('');
  32 + const [dataVisible, setDataVisible] = useState<boolean>(false);
  33 + const [excelvisible, setExcelvisible] = useState<boolean>(false);
  34 + const tagColorArr = ['', 'warning', 'processing', 'error', 'success', 'warning'];
  35 +
  36 + const approvalProgressRef = useRef<ApprovalProgressModalRef | null>(null);
  37 +
  38 + const upload: UploadProps = {
  39 + name: 'file',
  40 + action: '/api2/file/upload',
  41 + accept: '.xlsx,.xls',
  42 + maxCount: 1,
  43 + showUploadList: false,
  44 + onChange(info) {
  45 + if (info.file.status !== 'uploading') {
  46 + }
  47 + if (info.file.status === 'done') {
  48 + setFid(info.file.response.data);
  49 + setExcelvisible(true);
  50 + } else if (info.file.status === 'error') {
  51 + message.error(`${info.file.name} 上传失败`);
  52 + }
  53 + },
  54 + };
  55 + const viewProcess = (record: MDataImport.DetailedList) => {
  56 + approvalProgressRef.current?.setApprovalProgressModalInfo({
  57 + visible: true,
  58 + orderNo: record?.approvalNo,
  59 + });
  60 + };
  61 + const pickMonth: DatePickerProps['onChange'] = (date, _dateString) => {
  62 + setMonthly(date?.valueOf() ?? 0);
  63 + };
  64 + function shopChange(value: any) {
  65 + setShopId(value);
  66 + }
  67 + function statusChange(value: any) {
  68 + setStatus(value);
  69 + }
  70 + const { data } = useInitial(getShopApi, [], {});
  71 + //@ts-ignore
  72 + const { tableProps, run, refresh } = useAntdTable<any, MDataImport.DataImportListParams[]>(DataImportAPi, {
  73 + manual: true,
  74 + defaultParams: [
  75 + {
  76 + pageSize: 10,
  77 + current: 1,
  78 + monthly: Date.now(),
  79 + indicatorCode: indicator?.code || '',
  80 + },
  81 + ],
  82 +
  83 + onError: (e, _) => {
  84 + message.error(e.message);
  85 + },
  86 + });
  87 + const {
  88 + run: running,
  89 + mutate,
  90 + loading,
  91 + data: list,
  92 + } = useRequest<MDataImport.DataImportList, (number | undefined)[]>(ImportListDetailApi, {
  93 + manual: true,
  94 + onError: (e, _) => {
  95 + message.error(e.message);
  96 + },
  97 + });
  98 + const deleteData = async (id: number) => {
  99 + const param = { id };
  100 + try {
  101 + const { success } = await deleteApi(param);
  102 + if (success) {
  103 + message.success('删除成功');
  104 + refresh();
  105 + }
  106 + } catch (error: any) {
  107 + message.error(error.message);
  108 + }
  109 + };
  110 + const revoke = async (id: number) => {
  111 + const param = { id };
  112 + try {
  113 + const { success } = await revokeApi(param);
  114 + if (success) {
  115 + message.success('删除成功');
  116 + refresh();
  117 + }
  118 + } catch (error: any) {
  119 + message.error(error.message);
  120 + }
  121 + };
  122 + const detailColumns: ColumnsType<DataType> = [
  123 + {
  124 + title: '月度',
  125 + align: 'center',
  126 + dataIndex: 'dataDate',
  127 + width: 200,
  128 + key: 'dataDate',
  129 + render: (time: number) => (time ? moment(time).format('YYYY-MM') : '--'),
  130 + },
  131 + {
  132 + title: '门店',
  133 + align: 'center',
  134 + dataIndex: 'shopName',
  135 + width: 300,
  136 + key: 'shopName',
  137 + render: (name) => <span>{name || '--'}</span>,
  138 + },
  139 + {
  140 + title: '打分',
  141 + align: 'center',
  142 + dataIndex: 'score',
  143 + width: 100,
  144 + key: 'score',
  145 + render: (name) => <span>{name || '--'}</span>,
  146 + },
  147 + {
  148 + title: '总分',
  149 + align: 'center',
  150 + key: 'totalScore',
  151 + width: 100,
  152 + dataIndex: 'totalScore',
  153 + render: (name) => <span>{name || '--'}</span>,
  154 + },
  155 + {
  156 + title: '打分人员',
  157 + align: 'center',
  158 + key: 'graderStaffName',
  159 + width: 200,
  160 + dataIndex: 'graderStaffName',
  161 + render: (name) => <span>{name || '--'}</span>,
  162 + },
  163 + ];
  164 + const columns: ColumnsType<MDataImport.DetailedList> = [
  165 + {
  166 + title: '导入时间',
  167 + align: 'center',
  168 + width: 300,
  169 + dataIndex: 'createTime',
  170 + key: 'createTime',
  171 + render: (time: number) => (time ? moment(time).format('YYYY-MM-DD hh:mm:ss') : '--'),
  172 + },
  173 + {
  174 + title: '导入人员',
  175 + align: 'center',
  176 + width: 300,
  177 + dataIndex: 'importUserName',
  178 + key: 'importUserName',
  179 + render: (name) => <span>{name || '--'}</span>,
  180 + },
  181 +
  182 + {
  183 + title: '导入数据',
  184 + align: 'center',
  185 + width: 100,
  186 + key: 'num',
  187 + dataIndex: 'num',
  188 + render: (name) => <span>{name + '条' || '--'}</span>,
  189 + },
  190 + {
  191 + title: '成功',
  192 + align: 'center',
  193 + width: 100,
  194 + key: 'successNum',
  195 + dataIndex: 'successNum',
  196 + render: (name) => <span>{name + '条' || '--'}</span>,
  197 + },
  198 + {
  199 + title: '失败',
  200 + align: 'center',
  201 + width: 100,
  202 + key: 'errorNum',
  203 + dataIndex: 'errorNum',
  204 + render: (name) => <span>{name + '条' || '--'}</span>,
  205 + },
  206 + {
  207 + title: '数据清单',
  208 + align: 'center',
  209 + width: 200,
  210 + key: 'importUserId',
  211 + render: (value, record: MDataImport.DetailedList) => {
  212 + return (
  213 + <Button
  214 + type="link"
  215 + onClick={() => {
  216 + {
  217 + setDataVisible(true);
  218 + running(record?.id);
  219 + }
  220 + }}
  221 + >
  222 + 查看
  223 + </Button>
  224 + );
  225 + },
  226 + },
  227 + {
  228 + title: '状态',
  229 + width: 100,
  230 + align: 'center',
  231 + key: 'status',
  232 + dataIndex: 'status',
  233 + render: (text: number) => <Tag color={tagColorArr[text]}>{text ? SelectStatus[text] : '--'}</Tag>,
  234 + },
  235 + {
  236 + title: '操作',
  237 + align: 'center',
  238 + width: 300,
  239 + key: 'tags',
  240 + render: (_: any, record: MDataImport.DetailedList) => {
  241 + return (
  242 + <Space split={<Divider type="vertical" />}>
  243 + {(record.status == 1 || record.status == 3 || record.status == 5) && (
  244 + <Popconfirm title="确定删除,提交后不可更改?" onConfirm={() => deleteData(record?.id || 0)} okText="确定" cancelText="取消">
  245 + <Typography.Link>删除</Typography.Link>
  246 + </Popconfirm>
  247 + )}
  248 + {(record.status == 2 || record.status == 3) && (
  249 + <>
  250 + {record.status == 2 && (
  251 + <Popconfirm title="确定撤销,提交后不可更改?" onConfirm={() => revoke(record?.id || 0)} okText="确定" cancelText="取消">
  252 + <Typography.Link>撤销</Typography.Link>
  253 + </Popconfirm>
  254 + )}
  255 + <Typography.Link
  256 + onClick={() => {
  257 + viewProcess(record);
  258 + }}
  259 + >
  260 + 流程进度
  261 + </Typography.Link>
  262 + </>
  263 + )}
  264 + {record.status == 4 && <div>--</div>}
  265 + </Space>
  266 + );
  267 + },
  268 + },
  269 + ];
  270 +
  271 + useEffect(() => {
  272 + if (indicator?.code) {
  273 + run({
  274 + pageSize: 10,
  275 + current: 1,
  276 + monthly: monthly || Date.now(),
  277 + indicatorCode: indicator?.code || '',
  278 + shopId: shopId || undefined,
  279 + status: status || undefined,
  280 + });
  281 + }
  282 + }, [indicator?.code, monthly, shopId, status]);
  283 + return (
  284 + <>
  285 + <div style={{ display: 'flex' }}>
  286 + <DatePicker value={monthly ? moment(monthly) : undefined} onChange={pickMonth} picker="month" style={{ marginRight: 20 }} />
  287 + <Select allowClear style={{ width: 245, marginRight: 20 }} placeholder="请选择门店" onChange={shopChange}>
  288 + {(data || []).map((shop) => (
  289 + <Select.Option value={shop.id} key={shop.id}>
  290 + {shop.name}
  291 + </Select.Option>
  292 + ))}
  293 + </Select>
  294 + <Select allowClear style={{ width: 120 }} placeholder="状态筛选" onChange={statusChange}>
  295 + {[2, 3, 4, 5].map((text: number) => (
  296 + <Select.Option value={text} key={text}>
  297 + {SelectStatus[text]}
  298 + </Select.Option>
  299 + ))}
  300 + </Select>
  301 + <div style={{ marginLeft: 'auto' }}>
  302 + <Button
  303 + icon={<DownloadOutlined rev="" />}
  304 + type="primary"
  305 + onClick={() => {
  306 + DownloadApi(indicator?.code)
  307 + .then((res) => {
  308 + dowloader.downloadFile({ fileUrl: IMGURL.showImage(res) });
  309 + })
  310 + .catch((e) => {
  311 + message.error(e.message);
  312 + });
  313 + }}
  314 + >
  315 + 下载模版
  316 + </Button>
  317 + <Upload {...upload}>
  318 + <Button style={{ marginLeft: 10 }} icon={<PlusOutlined rev="" />} type="primary">
  319 + 导入
  320 + </Button>
  321 + </Upload>
  322 + </div>
  323 + </div>
  324 +
  325 + <Table rowKey="id" columns={columns} {...tableProps} style={{ marginTop: 20 }} />
  326 + <Modal
  327 + title="数据清单"
  328 + open={dataVisible}
  329 + footer={null}
  330 + destroyOnClose
  331 + onCancel={() => {
  332 + setDataVisible(false);
  333 + mutate(undefined);
  334 + }}
  335 + width="70%"
  336 + keyboard
  337 + >
  338 + <Table
  339 + rowKey="id"
  340 + loading={loading}
  341 + dataSource={list?.details ?? []}
  342 + columns={detailColumns}
  343 + pagination={{ pageSizeOptions: [10, 20, 50] }}
  344 + />
  345 + </Modal>
  346 + <ExcelTable refresh={refresh} setExcelvisible={setExcelvisible} show={excelvisible} fid={fid} indicator={indicator} />
  347 + <ApprovalProgressModal ref={approvalProgressRef} />
  348 + </>
  349 + );
  350 +}
... ...
src/pages/performance/DataImport/components/exhibitionHallFour.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { Radio, Empty } from 'antd';
  3 +import ImportList from './ImportList';
  4 +import DetailList from './DetailList';
  5 +
  6 +type Props = {
  7 + indicator?: MDataImport.IndicatorList;
  8 + onChange?: (value?: any) => void;
  9 +};
  10 +
  11 +export default function ExhibitionHallFour({ indicator }: Props) {
  12 + const [tableType, setTableType] = useState<number>(0);
  13 +
  14 + return (
  15 + <div style={{ flex: 1, overflowX: 'hidden', marginLeft: 20 }}>
  16 + {indicator?.code ? (
  17 + <div>
  18 + <div style={{ fontSize: 18, fontWeight: 'bold' }}>{`指标:${indicator?.name ?? '-'}`}</div>
  19 + <Radio.Group defaultValue="a" buttonStyle="solid" style={{ marginTop: 15, marginBottom: 20 }}>
  20 + <Radio.Button
  21 + value="a"
  22 + style={{ marginRight: 10 }}
  23 + onClick={() => {
  24 + setTableType(0);
  25 + }}
  26 + >
  27 + 导入记录
  28 + </Radio.Button>
  29 +
  30 + <Radio.Button
  31 + value="b"
  32 + onClick={() => {
  33 + setTableType(1);
  34 + }}
  35 + >
  36 + 数据清单
  37 + </Radio.Button>
  38 + </Radio.Group>
  39 + {tableType === 0 ? <ImportList indicator={indicator} /> : <DetailList indicator={indicator} />}
  40 + </div>
  41 + ) : (
  42 + <div style={{ marginTop: '25%', display: 'flex', justifyContent: 'center' }}>
  43 + <Empty description={'请选择指标'} />
  44 + </div>
  45 + )}
  46 + </div>
  47 + );
  48 +}
... ...
src/pages/performance/DataImport/components/truckloadBank.tsx 0 → 100644
  1 +import React from 'react';
  2 +import { Table, message } from 'antd';
  3 +import { IndicatorListApi } from '../api';
  4 +import { useRequest } from 'ahooks';
  5 +
  6 +type Props = {
  7 + value?: MDataImport.IndicatorList;
  8 + onChange?: (value?: any) => void;
  9 +};
  10 +export default function TruckloadBank({ value, onChange }: Props) {
  11 + const Column = Table.Column;
  12 + const { data } = useRequest<MDataImport.IndicatorList[], never[]>(IndicatorListApi, {
  13 + onSuccess: (data, _params) => {
  14 + onChange?.(data?.[0]);
  15 + },
  16 + onError: (e, _) => {
  17 + message.error(e.message);
  18 + },
  19 + });
  20 +
  21 + return (
  22 + <div style={{ width: 200 }}>
  23 + <Table
  24 + rowKey="code"
  25 + pagination={false}
  26 + rowSelection={{
  27 + type: 'radio',
  28 + selectedRowKeys: value?.code ? [value.code] : [],
  29 + onSelect: (record) => onChange?.(record),
  30 + }}
  31 + dataSource={data || []}
  32 + >
  33 + <Column title="指标" dataIndex="name" align="center" render={(text) => text ?? '-'} fixed />
  34 + </Table>
  35 + </div>
  36 + );
  37 +}
... ...
src/pages/performance/DataImport/entity.ts 0 → 100644
  1 +import e from 'express';
  2 +
  3 +export enum SelectStatus{
  4 + '未发布'=1,
  5 + '审批中',
  6 + '审批拒绝',
  7 + '审批同意',
  8 + '撤销审批'
  9 +}
  10 +export enum ErrorType{
  11 + '-' = 0,
  12 + '未匹配到人员',
  13 + '未匹配到门店',
  14 + '未匹配到指标',
  15 + '数据重复',
  16 + '时间错误'
  17 +}
... ...
src/pages/performance/DataImport/index.css 0 → 100644
src/pages/performance/DataImport/index.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { PageHeaderWrapper } from '@ant-design/pro-layout';
  3 +import { Card } from 'antd';
  4 +import TruckloadBank from './components/truckloadBank';
  5 +import ExhibitionHallFour from './components/exhibitionHallFour';
  6 +
  7 +export default () => {
  8 + const [indicator, setIndicator] = useState<MDataImport.IndicatorList>();
  9 + const onChange = (value?: MDataImport.IndicatorList) => {
  10 + setIndicator(value);
  11 + };
  12 + return (
  13 + <PageHeaderWrapper title="自定义数据导入">
  14 + <Card>
  15 + <div style={{ display: 'flex' }}>
  16 + <TruckloadBank value={indicator} onChange={onChange} />
  17 + <ExhibitionHallFour indicator={indicator} onChange={onChange} />
  18 + </div>
  19 + </Card>
  20 + </PageHeaderWrapper>
  21 + );
  22 +};
... ...
src/pages/performance/DataImport/interface.d.ts 0 → 100644
  1 +declare namespace MDataImport {
  2 + /**
  3 + * 展厅美化导入记录分页查询参数
  4 + */
  5 + interface DataImportListParams {
  6 + current: number;
  7 + pageSize: number;
  8 + indicatorCode?: string;
  9 + shopId?: number;
  10 + monthly?: number;
  11 + sorter?: any;
  12 + filter?: any;
  13 + extra?: any;
  14 + [key: string]: any;
  15 + }
  16 +
  17 + /**
  18 + * 展厅美化导入记录分页查询数据
  19 + */
  20 + interface DataImportList {
  21 + id?: number;
  22 + importUserId?: number;
  23 + importUserName?: string;
  24 + shopId?: number;
  25 + shopName?: string;
  26 + dimensionType?: string;
  27 + indicatorCode?: string;
  28 + indicatorName?: string;
  29 + valueType?: number;
  30 + dataDate?: string;
  31 + num?: number;
  32 + successNum?: number;
  33 + errorNum?: number;
  34 + groupId?: number;
  35 + createTime?: string;
  36 + key?: string;
  37 + status?: string;
  38 + approvalNo?: string;
  39 + dataTimeType?: string;
  40 + details?: [];
  41 + }
  42 + /**
  43 + * 数据导入指标列表数据
  44 + */
  45 + interface IndicatorList {
  46 + id?: number;
  47 + code?: string;
  48 + name?: 'melda.sanford';
  49 + }
  50 + /**
  51 + * 数据清单列表数据
  52 + */
  53 + interface DetailedList {
  54 + id?: number;
  55 + recordId?: number;
  56 + indicatorName?: string;
  57 + indicatorCode?: string;
  58 + shopId?: number;
  59 + shopName?: string;
  60 + score?: number;
  61 + totalScore?: number;
  62 + graderStaffName?: string;
  63 + graderStaffId?: number;
  64 + stageStartDataDate?: string;
  65 + stageEndDataDate?: string;
  66 + dataDate?: string;
  67 + errorType?: string;
  68 + valid?: boolean;
  69 + yn?: boolean;
  70 + approvalNo?: string;
  71 + status: number;
  72 + }
  73 +}
... ...
src/pages/performance/EvaDataImport/index.tsx
... ... @@ -51,7 +51,7 @@ export default () =&gt; {
51 51 }
52 52 const uploadPerson: UploadProps = {
53 53 name: 'file',
54   - action: '/api/morax/erp/eval-indicator/analysis-staff',
  54 + action: '/api/morax/erp/eval-indicator/analysis-staff',
55 55 maxCount: 1,
56 56 showUploadList: false,
57 57 // 设置headers里的token
... ... @@ -62,6 +62,7 @@ export default () =&gt; {
62 62 }
63 63 if (info.file.status === 'done') {
64 64 setFileData(info.file.response.data);
  65 +
65 66 setVisible(true);
66 67 } else if (info.file.status === 'error') {
67 68 message.error(`${info.file.name} 上传失败`);
... ...
src/pages/performance/KpiGroupSetting/EditComfirm/components/IndivatorsTable.tsx
... ... @@ -199,7 +199,7 @@ const IndivatorsTable = ({ value, onChange, personModal }: Props) =&gt; {
199 199 return _columns;
200 200 };
201 201 const onChangePag = (page: number, pageSize: number) => {
202   - console.log(page, pageSize, value);
  202 + console.log(page, pageSize, value,'0000000');
203 203 setPage(page - 1);
204 204 };
205 205 return (
... ...
src/pages/performance/KpiSetting/components/EditModal.tsx
... ... @@ -210,7 +210,7 @@ export default function EditModal({ onClose, setItem, item, roleList }: Props) {
210 210 >
211 211 {({ getFieldValue }) => {
212 212 return getFieldValue('roleType') === 3 ? (
213   - <Form.Item name="roles" label="适用角色" rules={[{ required: true }]}>
  213 + <Form.Item name="roles" label="适用角色1" rules={[{ required: true }]}>
214 214 <Select
215 215 placeholder="请选择角色"
216 216 showSearch
... ...