Commit 301976f1d79b63e6a918d76837478d34c95d573f

Authored by 舒述军
2 parents 84c35dd8 c8e9f248

Merge branch 'master' into order_lzh

Showing 110 changed files with 10026 additions and 192 deletions

Too many changes to show.

To preserve performance only 48 of 110 files are displayed.

config/routers/contract.ts
... ... @@ -59,4 +59,12 @@ export default [
59 59 path: "/contract/kt/itemamount/config", //事项款设置
60 60 component: "./contract/ItemAmountSetting",
61 61 },
  62 + {
  63 + path: "/contract/kt/authorization/setting", //合同授权
  64 + component: "./contract/AuthorizationSetting",
  65 + },
  66 + {
  67 + path: "/contract/kt/expressChargingStandard/setting", //快递收费标准
  68 + component: "./contract/ExpressChargingStandardSetting",
  69 + },
62 70 ];
... ...
config/routers/performance.ts
... ... @@ -70,6 +70,31 @@ export default [
70 70 component: "./performance/SalarySystemSetting",
71 71 },
72 72  
  73 + /** 考评指标 */
  74 + {
  75 + path: "/morax/evaSetting", //考评指标库设置
  76 + component: "./performance/EvaSetting",
  77 + },
  78 + {
  79 + path: "/morax/evaGroupSetting", //考评组设置
  80 + component: "./performance/EvaGroupSetting",
  81 + },
  82 + /** 考评组设置==》编辑新增 */
  83 + {
  84 + path: "/morax/evaGroupSetting/edit/:id?/:read?/:type?",
  85 + component: "./performance/EvaGroupSetting/EditComfirm/index",
  86 + },
  87 + /** 考评数据导入 */
  88 + {
  89 + path: "/morax/evaDataImport",
  90 + component: "./performance/EvaDataImport",
  91 + },
  92 + /** 考评数据导入==> 查看数据清单 */
  93 + {
  94 + path: "/morax/evaDataImport/edit/:id?/:num?",
  95 + component: "./performance/EvaDataImport/EditComfirm/index",
  96 + },
  97 +
73 98 /** 旧 */
74 99 {
75 100 path: "/performance/salaryManage/salaryGroupSetting", //薪酬组设置
... ...
package.json
... ... @@ -54,6 +54,7 @@
54 54 "copy-to-clipboard": "^3.3.1",
55 55 "cos-js-sdk-v5": "0.5.26",
56 56 "currency.js": "^2.0.3",
  57 + "dayjs": "^1.11.7",
57 58 "global": "^4.4.0",
58 59 "image-conversion": "^2.1.1",
59 60 "immer": "^7.0.5",
... ...
src/pages/capital/ReceiveRules/component/SelectGoodsTable.tsx
... ... @@ -74,6 +74,8 @@ const SelectGoodsTable = (props: Props) => {
74 74 };
75 75  
76 76 function saveDate() {
  77 + console.log("🚀 ~ file: SelectGoodsTable.tsx:80 ~ saveDate ~ selectedRow:", selectedRow);
  78 +
77 79 onChange && onChange(selectedRow);
78 80 onCancel();
79 81 }
... ... @@ -87,8 +89,12 @@ const SelectGoodsTable = (props: Props) => {
87 89 selectedRowKeys: selectedRow.map(row => row.code),
88 90 onSelect: (row: any, _selected: boolean) => {
89 91 const index = selectedRow.findIndex((_row) => _row.code == row.code);
  92 + if (!multiple) {
  93 + setSelectedRow([row]);
  94 + return;
  95 + }
90 96 if (_selected) {
91   - selectedRow.unshift(row);
  97 + selectedRow.unshift(row);
92 98 } else if (index > -1) {
93 99 selectedRow.splice(index, 1);
94 100 }
... ...
src/pages/capital/ReceiveRules/subPages/GoodsDimension/components/RenderSelectGoos.tsx
... ... @@ -2,14 +2,17 @@ import SelectGoodsTable from '@/pages/capital/ReceiveRules/component/SelectGoods
2 2 import { Button, Card, Popconfirm, Row, Table } from 'antd';
3 3 import React, { useState } from 'react';
4 4 import { PlusOutlined } from '@ant-design/icons';
  5 +import RenderGoodsSpec from '@/pages/capital/components/RenderGoodsSpec';
5 6  
6 7 const Column = Table.Column;
7 8  
8 9 interface GoodsProps {
9 10 onChange?: Function;
10 11 value?: any;
  12 + multiple?: boolean;
  13 + disabled?: boolean;
11 14 }
12   -function RenderSelectGoos({ onChange, value = [] }: GoodsProps) {
  15 +function RenderSelectGoos({ onChange, value = [], multiple, disabled }: GoodsProps) {
13 16 const [goodsModal, setGoodsModal] = useState({ visible: false });
14 17 function deleteItem(code: string) {
15 18 const newData = value.filter((i: any) => i.code !== code);
... ... @@ -18,11 +21,14 @@ function RenderSelectGoos({ onChange, value = [] }: GoodsProps) {
18 21  
19 22 return (
20 23 <Card>
21   - <Row justify="end" style={{ marginBottom: 10 }}>
22   - <Button type="primary" icon={<PlusOutlined />} onClick={() => setGoodsModal({ visible: true })}>新增</Button>
23   - </Row>
  24 + {!disabled ? (
  25 + <Row justify="end" style={{ marginBottom: 10 }}>
  26 + <Button type="primary" icon={<PlusOutlined />} onClick={() => setGoodsModal({ visible: true })}>新增</Button>
  27 + </Row>
  28 + ) : null}
24 29 <Table
25 30 dataSource={value}
  31 + pagination={multiple ? undefined : false}
26 32 // loading={loading}
27 33 bordered={false}
28 34 size="small"
... ... @@ -31,6 +37,13 @@ function RenderSelectGoos({ onChange, value = [] }: GoodsProps) {
31 37 <Column title="物品名称" dataIndex="name" />
32 38 <Column title="物品编码" dataIndex="code" />
33 39 <Column
  40 + title="型号规格"
  41 + dataIndex="spec"
  42 + width="16%"
  43 + ellipsis
  44 + render={(text, record) => text && <RenderGoodsSpec specList={JSON.parse(text)} />}
  45 + />
  46 + <Column
34 47 align="center"
35 48 title="操作"
36 49 // width={400}
... ... @@ -38,9 +51,11 @@ function RenderSelectGoos({ onChange, value = [] }: GoodsProps) {
38 51 return (
39 52 <>
40 53 <Popconfirm title="确认删除?" onConfirm={() => deleteItem(value.code)}>
41   - <Button type="link">
42   - 删除
43   - </Button>
  54 + {!disabled && (
  55 + <Button type="link">
  56 + 删除
  57 + </Button>
  58 + )}
44 59 </Popconfirm>
45 60 </>
46 61 );
... ... @@ -48,6 +63,7 @@ function RenderSelectGoos({ onChange, value = [] }: GoodsProps) {
48 63 />
49 64 </Table>
50 65 <SelectGoodsTable
  66 + multiple={multiple}
51 67 visible={goodsModal.visible}
52 68 onCancel={() => setGoodsModal({ visible: false })}
53 69 onChange={(v) => onChange && onChange(v)}
... ...
src/pages/contract/AuthorizationSetting/api.ts 0 → 100644
  1 +import { http } from "@/typing/http";
  2 +import request from "@/utils/request";
  3 +import qs from 'qs';
  4 +import { CONTRACT_HOST, HOST } from "@/utils/host";
  5 +import { Any } from "currency.js";
  6 +
  7 +type PrResArr<T> = http.PromiseResp<T[]>;
  8 +
  9 +export interface Item {
  10 + id?:number, //授权ID
  11 + typeName?:string, //合同类型名称
  12 + createTime?:number, //创建时间
  13 + updateTime?:number, //更新时间
  14 + enabled?:boolean, //是否启用
  15 + roles?:Roles[],//授权角色
  16 +}
  17 +export interface Roles {
  18 + roleCode?:string, //角色编码
  19 + roleName?:string, //角色名称
  20 +}
  21 +export interface TypesItem {
  22 + id?: number; // id
  23 + name?: string;
  24 + fixedAmount?: boolean;
  25 + contractableTradeCompCategories?: number[];
  26 + feeType?: string;
  27 + feeTypeValue?: string;
  28 + bizType?: string;
  29 + bizTypeValue?: number;
  30 + subjectType?: string;
  31 + subjectTypeValue?: string;
  32 + servicePlaceTypes?: number[];
  33 +}
  34 +
  35 +export interface PageParams {
  36 + current?: number;
  37 + pageSize?: number;
  38 + contractTypeName?:string //合同类型名称
  39 +}
  40 +export interface SaveParams {
  41 + contractAuthId?: number;
  42 + typeId: number;//合同类型id
  43 + typeName:string //合同类型名称
  44 + roles?:Roles[],//授权角色
  45 +}
  46 +interface DelParams {
  47 + contractAuthId?: number; //合同授权id
  48 +}
  49 +
  50 +export interface DisableParams {
  51 + contractAuthId?: number;//合同授权id
  52 + enabled?: boolean;//是否启用
  53 +}
  54 +
  55 +/**
  56 + * 查询所有角色列表
  57 + */
  58 +export function getAllRoleCodeApi(params: CommonApi.RoleParams): PrResArr<CommonApi.RoleCodeVO> {
  59 + return request.get(`${HOST}/role/listAll`, { params });
  60 +}
  61 +/**
  62 + * 查询合同类型列表
  63 + */
  64 +export function getContractTypes(params: PageParams): http.PromisePageResp<TypesItem> {
  65 + return request.get(`${CONTRACT_HOST}/erp/contract/type/page`, { params });
  66 +}
  67 +
  68 +/**
  69 + * 分页查询合同授权
  70 + */
  71 +export function getContractAuthPage(params?: PageParams): http.PromisePageResp<Item> {
  72 + return request.get(`${CONTRACT_HOST}/erp/contractAuth/page`, {params});
  73 +}
  74 +
  75 +/**
  76 + * 新增合同授权/编辑合同授权
  77 + */
  78 +export function addContractAuth(params?: SaveParams): http.PromisePageResp<Any> {
  79 + return request.post(`${CONTRACT_HOST}/erp/contractAuth/save`, {...params});
  80 +}
  81 +
  82 +/**
  83 + * 删除合同授权
  84 + */
  85 + export function delContractAuth(params?: DelParams): http.PromisePageResp<Any> {
  86 + return request.post(`${CONTRACT_HOST}/erp/contractAuth/delete`, {...params});
  87 +}
  88 +
  89 +/**
  90 + * 启用或禁用
  91 + */
  92 + export function disableContractAuth(params?: DisableParams): http.PromisePageResp<Any> {
  93 + return request.post(`${CONTRACT_HOST}/erp/contractAuth/enableOrDisable`, {...params});
  94 +}
0 95 \ No newline at end of file
... ...
src/pages/contract/AuthorizationSetting/components/AddModel/index.tsx 0 → 100644
  1 +import React, { useCallback, useEffect, useState } from "react";
  2 +import { Modal, Skeleton, Select, Form, message } from "antd";
  3 +import * as API from '../../api';
  4 +
  5 +interface Props{
  6 + visible:boolean;
  7 + row?:API.Item;
  8 + contractTypesList:any[],
  9 + roleList:any[],
  10 + onRefresh: () => void;
  11 + onCancel?: () => void;
  12 +}
  13 +
  14 +function AddModel({visible, row, contractTypesList, roleList, onCancel, onRefresh}:Props) {
  15 + const [form] = Form.useForm();
  16 + const [loading, setLoading] = useState<boolean>(false);
  17 + const {id, roles, typeName } = row || {};
  18 + useEffect(() => {
  19 + if (id) {
  20 + form.setFieldsValue({
  21 + contractType: contractTypesList.filter((item:API.TypesItem) => item.name === typeName).map((i:any) => ({label: i.name, value: i.id}))[0],
  22 + roleCode: roles?.length && roles.map((i:any) => ({label: i.roleName, value: i.roleCode})),
  23 + });
  24 + }
  25 + }, [row]);
  26 +
  27 + /**
  28 + * @description: 表单提交
  29 + * @param {any} feildValue
  30 + * @return {*}
  31 + */
  32 + const handleSave = (feildValue: any) => {
  33 + setLoading(true);
  34 + const { roleCode, contractType } = feildValue;
  35 + const _roleCode = roleCode.length && roleCode.map((item:any) => ({roleCode: item.value, roleName: item.label }));
  36 + const params = {roles: _roleCode, typeId: contractType.value, typeName: contractType.label };
  37 + API.addContractAuth({ ...params, contractAuthId: id })
  38 + .then(res => {
  39 + message.success("操作成功");
  40 + _onCancel();
  41 + setLoading(false);
  42 + onRefresh();
  43 + })
  44 + .catch(err => {
  45 + message.error(err?.message);
  46 + setLoading(false);
  47 + });
  48 + };
  49 + /**
  50 + * @description: 关闭弹框
  51 + * @param {*}
  52 + * @return {*}
  53 + */
  54 + const _onCancel = () => {
  55 + onCancel && onCancel();
  56 + form.resetFields();
  57 + };
  58 +
  59 + return (
  60 + <Modal
  61 + title={`${id ? '编辑':'新增'}合同授权`}
  62 + visible={visible}
  63 + confirmLoading={loading}
  64 + onCancel={_onCancel}
  65 + onOk={form.submit}
  66 + cancelButtonProps={{ hidden: true }}
  67 + width="50%"
  68 + bodyStyle={{minHeight: 300}}
  69 + >
  70 + <Skeleton
  71 + loading={false}
  72 + >
  73 + <Form form={form} onFinish={handleSave} wrapperCol={{ span: 18 }} labelCol={{ span: 4 }}>
  74 + <Form.Item
  75 + label="合同类型"
  76 + name="contractType"
  77 + rules={[{ required: true, message: '请选择合同类型' }]}
  78 + >
  79 + <Select
  80 + placeholder="请选择合同类型"
  81 + showSearch
  82 + allowClear
  83 + optionFilterProp="children"
  84 + labelInValue
  85 + onSelect={(it:any) => {
  86 + const item = contractTypesList.filter((i:any) => it.value === i.id);
  87 + }}
  88 + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0}
  89 + >
  90 + {
  91 + contractTypesList && contractTypesList.map((item:any) => (
  92 + <Select.Option value={item.id} key={item.id}>
  93 + {item.name}
  94 + </Select.Option>
  95 + ))
  96 + }
  97 + </Select>
  98 + </Form.Item>
  99 + <Form.Item
  100 + label="授权角色"
  101 + name="roleCode"
  102 + rules={[{ required: true, message: '请选择授权角色' }]}
  103 + >
  104 + <Select
  105 + placeholder="请选择授权角色(支持多选)"
  106 + mode="multiple"
  107 + showSearch
  108 + allowClear
  109 + showArrow
  110 + optionFilterProp="children"
  111 + labelInValue
  112 + onSelect={(it:any) => {
  113 + const item = roleList.filter((i:any) => it.value === i.roleCode);
  114 + }}
  115 + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0}
  116 + >
  117 + {
  118 + roleList && roleList.map((item:any) => (
  119 + <Select.Option value={item.roleCode} key={item.id}>
  120 + {item.roleName}
  121 + </Select.Option>
  122 + ))
  123 + }
  124 + </Select>
  125 + </Form.Item>
  126 + </Form>
  127 + </Skeleton>
  128 + </Modal>
  129 + );
  130 +}
  131 +
  132 +export default AddModel;
0 133 \ No newline at end of file
... ...
src/pages/contract/AuthorizationSetting/components/Filter/index.tsx 0 → 100644
  1 +import React, { useCallback, useState } from "react";
  2 +import { Row, Col, Select } from "antd";
  3 +import * as common from "@/typing/common";
  4 +import _ from "lodash";
  5 +import * as API from '../../api';
  6 +
  7 +interface Props{
  8 + contractTypesList?:any[],
  9 + setParams:any,
  10 + innerParams?:any,
  11 +}
  12 +
  13 +function Filter({ contractTypesList, innerParams, setParams }:Props) {
  14 + const onChange = _.debounce((contractTypeName: string) => {
  15 + setParams({...innerParams, contractTypeName}, true);
  16 + }, 350);
  17 + return (
  18 + <Row
  19 + style={{ display: 'flex', flex: 1 }}
  20 + >
  21 + <Col span={12}>
  22 + <Select
  23 + placeholder="请选择合同类型"
  24 + showSearch
  25 + optionFilterProp="children"
  26 + allowClear
  27 + style={{ width: 200 }}
  28 + onChange={(contractTypeName) => onChange(contractTypeName)}
  29 + >
  30 + {
  31 + contractTypesList && contractTypesList.map((item:any) => (
  32 + <Select.Option value={item.name} key={item.id}>
  33 + {item.name}
  34 + </Select.Option>
  35 + ))
  36 + }
  37 + </Select>
  38 + </Col>
  39 + </Row>
  40 + );
  41 +}
  42 +
  43 +export default Filter;
0 44 \ No newline at end of file
... ...
src/pages/contract/AuthorizationSetting/components/RolesModel/index.tsx 0 → 100644
  1 +import React, { useCallback, useEffect, useState } from "react";
  2 +import { Modal, Form, message, Table } from "antd";
  3 +import * as API from '../../api';
  4 +
  5 +interface Props{
  6 + visible:boolean;
  7 + roles?:API.Roles[];
  8 + onRefresh: () => void;
  9 + onCancel?: () => void;
  10 +}
  11 +const { Column } = Table;
  12 +
  13 +function RolesModel({visible, roles, onRefresh, onCancel}:Props) {
  14 + return (
  15 + <Modal
  16 + title="授权角色"
  17 + visible={visible}
  18 + onCancel={onCancel}
  19 + >
  20 + <Table
  21 + dataSource={roles}
  22 + rowKey={(item: API.Roles) => `${item.roleCode}`}
  23 +
  24 + >
  25 + <Column title="角色名称" width={200} dataIndex="roleName" render={(t) => t || "-"} />
  26 + <Column title="角色编码" width={200} dataIndex="roleCode" render={(t) => t || "-"} />
  27 + </Table>
  28 + </Modal>
  29 + );
  30 +}
  31 +
  32 +export default RolesModel;
0 33 \ No newline at end of file
... ...
src/pages/contract/AuthorizationSetting/index.tsx 0 → 100644
  1 +import React, { useCallback, useState } from "react";
  2 +import { Button, Card, ConfigProvider, Divider, Input, message, Popconfirm, Select, Table } from "antd";
  3 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  4 +import zhCN from "antd/lib/locale-provider/zh_CN";
  5 +import usePagination from "@/hooks/usePagination";
  6 +import useInitial from "@/hooks/useInitail";
  7 +import { PlusOutlined } from "@ant-design/icons";
  8 +import AddModel from './components/AddModel';
  9 +import RolesModel from './components/RolesModel';
  10 +import Filter from './components/Filter';
  11 +import * as API from './api';
  12 +import _ from "lodash";
  13 +import moment from 'moment';
  14 +import st from "./style.less";
  15 +
  16 +const { Column } = Table;
  17 +function AuthorizationSetting() {
  18 + const [visible, setVisible] = useState<boolean>(false);
  19 + const [searchValue, setSearchValue] = useState<API.Item>({});
  20 + const [rolesVisible, setRolesVisible] = useState<boolean>(false);
  21 + const [row, setRow] = useState<API.Item>();
  22 + const [roles, setRoles] = useState<API.Roles[]>();
  23 + const {data: roleList} = useInitial<CommonApi.RoleCodeVO[], any>(API.getAllRoleCodeApi, [], {});
  24 + const {
  25 + list: authList,
  26 + paginationConfig,
  27 + loading,
  28 + innerParams,
  29 + setParams,
  30 + } = usePagination<API.Item>(API.getContractAuthPage, {current: 1, pageSize: 10});
  31 + const {
  32 + list: contractTypesList,
  33 + } = usePagination<API.TypesItem>(API.getContractTypes, {current: 1, pageSize: 999});
  34 + /**
  35 + * @description: 删除
  36 + * @param {*}
  37 + * @return {*}
  38 + *
  39 + */
  40 + const _delete = (row:API.Item) => {
  41 + const {id} =row;
  42 + API.delContractAuth({contractAuthId: id})
  43 + .then((res) => {
  44 + message.success("操作成功");
  45 + setParams({ ...innerParams }, true);
  46 + })
  47 + .catch((e) => {
  48 + message.error(e.message);
  49 + });
  50 + };
  51 +
  52 + /**
  53 + * @description: 编辑
  54 + * @param {API} row
  55 + * @return {*}
  56 + */
  57 + const edit = async (row:API.Item) => {
  58 + await setRow(row);
  59 + setVisible(true);
  60 + };
  61 +
  62 + /**
  63 + * @description: 禁用启用
  64 + * @param {API} row
  65 + * @return {*}
  66 + */
  67 + const handleDisable = (row:API.Item) => {
  68 + const { id, enabled } = row;
  69 + API.disableContractAuth({contractAuthId: id, enabled: !enabled})
  70 + .then((res) => {
  71 + message.success("操作成功");
  72 + setParams({ ...innerParams }, true);
  73 + })
  74 + .catch((err) => {
  75 + message.error(err.message);
  76 + });
  77 + };
  78 +
  79 + const showRoles = async (row:API.Item) => {
  80 + const {roles} = row;
  81 + try {
  82 + await setRoles(roles);
  83 + } finally {
  84 + setRolesVisible(true);
  85 + }
  86 + };
  87 +
  88 + return (
  89 + <PageHeaderWrapper title="合同授权">
  90 + <ConfigProvider locale={zhCN}>
  91 + <Card className={st.page}>
  92 + <div className={st.header}>
  93 + <Filter
  94 + contractTypesList={contractTypesList}
  95 + setParams={setParams}
  96 + innerParams={innerParams}
  97 + />
  98 + <Button
  99 + type="primary"
  100 + icon={<PlusOutlined />}
  101 + onClick={() => {
  102 + setVisible(true);
  103 + }}
  104 + >
  105 + 新增
  106 + </Button>
  107 + </div>
  108 + <Table
  109 + size="middle"
  110 + loading={loading}
  111 + dataSource={authList}
  112 + pagination={{ ...paginationConfig }}
  113 + scroll={{ y: 800 }}
  114 + rowKey={(item: API.Item) => `${item.id}`}
  115 + onChange={(_pagination) => setParams({ ..._pagination }, true)}
  116 + >
  117 + <Column title="合同类型" width={200} dataIndex="typeName" render={(t) => t || "-"} />
  118 + <Column
  119 + title="授权角色"
  120 + width={200}
  121 + dataIndex="id"
  122 + render={(text, row:API.Item) => (
  123 + <Button
  124 + type="link"
  125 + onClick={() => showRoles(row)}
  126 + >
  127 + 查看
  128 + </Button>
  129 + )}
  130 + />
  131 + <Column title="状态" width={200} dataIndex="enabled" render={(t) => (t?'启用':'禁用')} />
  132 + {/* <Column title="创建时间" width={200} dataIndex="createTime" render={(t) => (t ? moment(t).format('YYYY-MM-DD HH:mm') : "-")} />
  133 + <Column title="更新时间" width={200} dataIndex="updateTime" render={(t) => (t ? moment(t).format('YYYY-MM-DD HH:mm') : "-")} /> */}
  134 + <Column
  135 + title="操作"
  136 + width={100}
  137 + dataIndex="unit"
  138 + render={(text, row:API.Item) => (
  139 + <span>
  140 + <Popconfirm title={`是否${row.enabled ? "禁用?":"启用?"}`} onConfirm={() => handleDisable(row)} okText="确定" cancelText="取消">
  141 + <a
  142 + onClick={(e) => {
  143 + e.preventDefault();
  144 + }}
  145 + style={{ color: "#FAAD14" }}
  146 + >
  147 + {`${row.enabled ? '禁用' :'启用'}`}
  148 + </a>
  149 + </Popconfirm>
  150 + <Divider type="vertical" />
  151 + <Popconfirm title="是否编辑?" onConfirm={() => edit(row)} okText="确定" cancelText="取消">
  152 + <a
  153 + onClick={(e) => {
  154 + e.preventDefault();
  155 + }}
  156 + style={{ color: "#FAAD14" }}
  157 + >
  158 + 编辑
  159 + </a>
  160 + </Popconfirm>
  161 + <Divider type="vertical" />
  162 + <Popconfirm title="是否删除?" onConfirm={() => _delete(row)} okText="确定" cancelText="取消">
  163 + <a
  164 + onClick={(e) => {
  165 + e.preventDefault();
  166 + }}
  167 + style={{ color: "red" }}
  168 + >
  169 + 删除
  170 + </a>
  171 + </Popconfirm>
  172 + </span>
  173 +
  174 + )}
  175 + />
  176 + </Table>
  177 + <AddModel
  178 + visible={visible}
  179 + contractTypesList={contractTypesList}
  180 + roleList={roleList}
  181 + row={row}
  182 + onCancel={() => {
  183 + setVisible(false);
  184 + setRow(undefined);
  185 + }}
  186 + onRefresh={() => setParams({ ...innerParams }, true)}
  187 + />
  188 + <RolesModel
  189 + visible={rolesVisible}
  190 + roles={roles}
  191 + onCancel={() => {
  192 + setRolesVisible(false);
  193 + setRoles(undefined);
  194 + }}
  195 + onRefresh={() => setParams({ ...innerParams }, true)}
  196 + />
  197 + </Card>
  198 + </ConfigProvider>
  199 + </PageHeaderWrapper>
  200 + );
  201 +}
  202 +export default AuthorizationSetting;
... ...
src/pages/contract/AuthorizationSetting/style.css 0 → 100644
  1 +.page {
  2 + position: relative;
  3 +}
  4 +.page .header {
  5 + margin-bottom: 10px;
  6 + height: 32px;
  7 + display: flex;
  8 + flex-direction: row;
  9 + justify-content: space-between;
  10 +}
  11 +.page .header .add {
  12 + position: absolute;
  13 + right: 28px;
  14 + top: 24px;
  15 + z-index: 10;
  16 +}
  17 +.table :global .ant-table table {
  18 + width: 100%;
  19 + border-collapse: collapse;
  20 + text-align: center;
  21 + border-radius: 4px 4px 0 0;
  22 +}
  23 +.table :global .ant-table-thead > tr > th,
  24 +.table :global .ant-table-tbody > tr > td {
  25 + padding: 16px 16px;
  26 + word-break: break-word;
  27 + text-align: center;
  28 + -ms-word-break: break-all;
  29 +}
  30 +.table .cover {
  31 + align-items: center;
  32 + height: 68px;
  33 +}
  34 +.table .cover img {
  35 + border-radius: 4%;
  36 + height: 100%;
  37 + width: auto;
  38 + min-width: 100px;
  39 + max-width: 100px;
  40 +}
... ...
src/pages/contract/AuthorizationSetting/style.less 0 → 100644
  1 +//@import '~antd/lib/style/themes/default.less';
  2 +
  3 +.page {
  4 + position: relative;
  5 +
  6 + .header {
  7 + margin-bottom: 10px;
  8 + height: 32px;
  9 + display: flex;
  10 + flex-direction: row;
  11 + justify-content: space-between;
  12 + .add {
  13 + position: absolute;
  14 + right: 28px;
  15 + top: 24px;
  16 + z-index: 10;
  17 + }
  18 + }
  19 +
  20 + }
  21 + .table {
  22 + :global {
  23 + .ant-table table {
  24 + width: 100%;
  25 + border-collapse: collapse;
  26 + text-align: center;
  27 + border-radius: 4px 4px 0 0;
  28 + }
  29 + .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
  30 + padding: 16px 16px;
  31 + word-break: break-word;
  32 + text-align: center;
  33 + -ms-word-break: break-all;
  34 + }
  35 + }
  36 + .cover {
  37 + align-items: center;
  38 + height: 68px;
  39 + img {
  40 + border-radius: 4%;
  41 + height: 100%;
  42 + width: auto;
  43 + min-width: 100px;
  44 + max-width: 100px;
  45 + }
  46 + }
  47 + }
  48 +
0 49 \ No newline at end of file
... ...
src/pages/contract/ExpressChargingStandardSetting/api.ts 0 → 100644
  1 +import { http } from "@/typing/http";
  2 +import request from "@/utils/request";
  3 +import qs from 'qs';
  4 +import { CONTRACT_HOST, HOST, FINANCE2_HOST } from "@/utils/host";
  5 +import { Any } from "currency.js";
  6 +
  7 +type PrResArr<T> = http.PromiseResp<T[]>;
  8 +
  9 +export interface PageParams {
  10 + current?: number;
  11 + pageSize?: number;
  12 + tradeCompId?:number; //合同类型名称
  13 + sendAreaNo?:string; //寄件地区编号
  14 + arriveAreaNo?:string; //到达地区编号
  15 +}
  16 +
  17 +export interface SaveParams {
  18 + expressChargeStandardId?:number; //id,提供该参数将执行编辑操作
  19 + tradeCompId:number; //往来单位id
  20 + tradeCompName:string; //往来单位名称
  21 + sendAreaNo:string; //寄件地区编号
  22 + sendAreaName:string; //寄件地区名称
  23 + firstWeight:number; //首重
  24 + continuedWeight:number; //续重
  25 + arriveAreas:ArriveAreas[]; //到达地区
  26 +}
  27 +
  28 +export interface DelParams {
  29 + expressChargeStandardId:number; //快递收费标准id
  30 +}
  31 +
  32 +export interface ArriveAreas {
  33 + arriveAreaNo:string; //到达地区编号
  34 + arriveAreaName:string; //到达地区名称
  35 +}
  36 +
  37 +export interface Item {
  38 + id?:number;
  39 + tradeCompName?:string; //往来单位名称
  40 + tradeCompShortName?:string; //往来单位简称
  41 + sendAreaName?:string; //寄件地区名称
  42 + arriveAreaName?:string; //到达地区名称
  43 + firstWeight?:number; //首重
  44 + continuedWeight?:number; //续重
  45 +}
  46 +
  47 +/**
  48 + * 分页查询快递收费标准
  49 + */
  50 + export function getStandardPage(params?: PageParams): http.PromisePageResp<Item> {
  51 + return request.get(`${CONTRACT_HOST}/erp/express/charge/standard/page`, { params });
  52 +}
  53 +
  54 +/**
  55 + * 新增/编辑快递收费标准
  56 + */
  57 + export function addStandardSave(params: SaveParams): http.PromiseResp<any> {
  58 + return request.post(`${CONTRACT_HOST}/erp/express/charge/standard/save`, { ...params });
  59 +}
  60 +
  61 +/**
  62 + * 删除快递收费标准
  63 + */
  64 + export function delStandard(params: DelParams): http.PromiseResp<void> {
  65 + return request.post(`${CONTRACT_HOST}/erp/express/charge/standard/delete`, { ...params });
  66 +}
  67 +
  68 +/**获取往来单位列表*/
  69 +export function fetchComps(params?: any): http.PromiseResp<BearCostSetting.Comp[]> {
  70 + return request.get(`${FINANCE2_HOST}/common/trade/company/list`, {params });
  71 +}
  72 +
  73 +/**
  74 + * 城市列表
  75 + */
  76 + export function getCityLsit(): http.PromiseResp<any> {
  77 + const params = { pbh: 0 };
  78 + return request.get(`/oop/select/region`, { params });
  79 +}
0 80 \ No newline at end of file
... ...
src/pages/contract/ExpressChargingStandardSetting/components/AddModel/index.tsx 0 → 100644
  1 +import React, { useCallback, useEffect, useState } from "react";
  2 +import { Modal, Skeleton, Select, Form, message, InputNumber } from "antd";
  3 +import * as API from '../../api';
  4 +import _ from "lodash";
  5 +
  6 +interface Props {
  7 + visible:boolean;
  8 + row?:API.Item;
  9 + compList:any[];
  10 + cityList:any[];
  11 + onCancel:()=>void;
  12 + onRefresh:() => void;
  13 +
  14 +}
  15 +
  16 +function AddModel({visible, row, compList, cityList, onCancel, onRefresh}:Props) {
  17 + const [form] = Form.useForm();
  18 + const [loading, setLoading] = useState<boolean>(false);
  19 + const { id } = row || {};
  20 + useEffect(() => {
  21 + if (id) {
  22 + const { tradeCompName, sendAreaName, firstWeight, continuedWeight, arriveAreaName } = row || {};
  23 + form.setFieldsValue({
  24 + tradeComp: compList.filter(it => tradeCompName === it.name).map(item => ({value: item.id, label: item.name}))[0],
  25 + sendArea: cityList.filter(it => sendAreaName === it.fullName).map(item => ({value: item.bh, label: item.fullName}))[0],
  26 + firstWeight,
  27 + continuedWeight,
  28 + arriveAreas: cityList.filter(it => arriveAreaName === it.fullName).map(item => ({value: item.bh, label: item.fullName}))[0]
  29 +
  30 + });
  31 + }
  32 + }, [row]);
  33 +
  34 + /**
  35 + * @description: 确定
  36 + * @param {*}
  37 + * @return {*}
  38 + */
  39 + const handleSave = (feildValue:any) => {
  40 + setLoading(true);
  41 + const {tradeComp, sendArea, arriveAreas, firstWeight, continuedWeight} = feildValue;
  42 + const _arriveAreas = id ? [{ ...arriveAreas }].map(item => ({arriveAreaNo: item.value, arriveAreaName: item.label}))
  43 + : arriveAreas.length && arriveAreas.map((item:any) => ({arriveAreaNo: item.value, arriveAreaName: item.label}));
  44 +
  45 + const params = {
  46 + expressChargeStandardId: id,
  47 + tradeCompId: tradeComp.value,
  48 + tradeCompName: tradeComp.label,
  49 + tradeCompShortName: compList && compList.filter(item => item.id == tradeComp.value)[0].shortName,
  50 + sendAreaNo: sendArea.value,
  51 + sendAreaName: sendArea.label,
  52 + firstWeight,
  53 + continuedWeight,
  54 + arriveAreas: _arriveAreas
  55 + };
  56 + API.addStandardSave({ ...params })
  57 + .then(res => {
  58 + message.success("操作成功");
  59 + _onCancel();
  60 + setLoading(false);
  61 + onRefresh();
  62 + }).catch(err => {
  63 + message.error(err?.message);
  64 + setLoading(false);
  65 + });
  66 + };
  67 + /**
  68 + * @description: 关闭弹框
  69 + * @param {*}
  70 + * @return {*}
  71 + */
  72 + const _onCancel = () => {
  73 + onCancel && onCancel();
  74 + form.resetFields();
  75 + };
  76 +
  77 + return (
  78 + <Modal
  79 + title={`${id ? '编辑':'新增'}快递收费标准`}
  80 + visible={visible}
  81 + confirmLoading={loading}
  82 + onCancel={_onCancel}
  83 + onOk={form.submit}
  84 + cancelButtonProps={{ hidden: true }}
  85 + width="50%"
  86 + bodyStyle={{minHeight: 300}}
  87 + >
  88 + <Skeleton loading={false}>
  89 + <Form form={form} onFinish={handleSave} wrapperCol={{ span: 18 }} labelCol={{ span: 4 }}>
  90 + <Form.Item
  91 + label="快递公司"
  92 + name="tradeComp"
  93 + rules={[{required: true, message: '请选择快递公司'}]}
  94 + >
  95 + <Select
  96 + placeholder="请选择快递公司"
  97 + showSearch
  98 + allowClear
  99 + optionFilterProp="children"
  100 + labelInValue
  101 + onSelect={(it:any) => {
  102 + const item = compList.filter((i:any) => it.value === i.id);
  103 + }}
  104 + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0}
  105 + >
  106 + {
  107 + compList.map(item => (
  108 + <Select.Option value={item.id} key={item.id}>
  109 + {item.name}
  110 + </Select.Option>
  111 + ))
  112 + }
  113 + </Select>
  114 + </Form.Item>
  115 + <Form.Item
  116 + label="寄件地区"
  117 + name="sendArea"
  118 + rules={[{required: true, message: '请选择寄件地区'}]}
  119 + >
  120 + <Select
  121 + placeholder="请选择寄件地区"
  122 + showSearch
  123 + allowClear
  124 + optionFilterProp="children"
  125 + labelInValue
  126 + onSelect={(it:any) => {
  127 + const item = cityList.filter((i:any) => it.value === i.id);
  128 + }}
  129 + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0}
  130 + >
  131 + {
  132 + cityList.map(item => (
  133 + <Select.Option value={item.bh} key={item.bh}>
  134 + {item.fullName}
  135 + </Select.Option>
  136 + ))
  137 + }
  138 + </Select>
  139 + </Form.Item>
  140 + <Form.Item
  141 + label="到达地区"
  142 + name="arriveAreas"
  143 + rules={[{required: true, message: '请选择到达地区'}]}
  144 + >
  145 + <Select
  146 + placeholder={`请选择到达地区${id ? '' : '(支持多选)'}`}
  147 + mode={id ? undefined : 'multiple'}
  148 + showSearch
  149 + allowClear
  150 + showArrow
  151 + optionFilterProp="children"
  152 + labelInValue
  153 + onSelect={(it:any) => {
  154 + const item = cityList.filter((i:any) => it.value === i.id);
  155 + }}
  156 + filterOption={(input, option: any) => option?.children.indexOf(input) >= 0}
  157 + >
  158 + {
  159 + cityList.map(item => (
  160 + <Select.Option value={item.bh} key={item.bh}>
  161 + {item.fullName}
  162 + </Select.Option>
  163 + ))
  164 + }
  165 + </Select>
  166 + </Form.Item>
  167 + <Form.Item
  168 + label="首重"
  169 + name="firstWeight"
  170 + rules={[{required: true, message: '请填写首重'}]}
  171 + >
  172 + <InputNumber placeholder="请填写" addonAfter="元" max={100000000} min={0} precision={2} />
  173 + </Form.Item>
  174 + <Form.Item
  175 + label="续重"
  176 + name="continuedWeight"
  177 + rules={[{required: true, message: '请填写续重'}]}
  178 + >
  179 + <InputNumber placeholder="请填写" addonAfter="元/kg" max={100000000} min={0} precision={2} />
  180 + </Form.Item>
  181 + </Form>
  182 + </Skeleton>
  183 + </Modal>
  184 + );
  185 +}
  186 +
  187 +export default AddModel;
0 188 \ No newline at end of file
... ...
src/pages/contract/ExpressChargingStandardSetting/components/Filter/index.tsx 0 → 100644
  1 +import React, { useCallback, useState } from "react";
  2 +import { Row, Col, Select } from "antd";
  3 +import _ from "lodash";
  4 +
  5 +interface Props {
  6 + setParams:any;
  7 + innerParams:any;
  8 + cityList:any[];
  9 + compList:BearCostSetting.Comp[];
  10 +}
  11 +
  12 +interface SearchData {
  13 + tradeCompId?:number;//往来单位id
  14 + sendAreaNo?:string;//寄件地区编号
  15 + arriveAreaNo?:string;//到达地区编号
  16 +}
  17 +
  18 +function Filter({ compList, cityList, setParams, innerParams }:Props) {
  19 + const [searchData, setSearchData] = useState<SearchData>({});
  20 + return (
  21 + <Row style={{flex: 1}}>
  22 + <Col span={8} style={{marginRight: 10}}>
  23 + <Select
  24 + placeholder="请选择快递公司"
  25 + showSearch
  26 + optionFilterProp="children"
  27 + allowClear
  28 + style={{ minWidth: 260, maxWidth: 280 }}
  29 + onChange={(tradeCompId) => {
  30 + setSearchData({...searchData, tradeCompId});
  31 + setParams({...innerParams, ...searchData, tradeCompId}, true);
  32 + }}
  33 + >
  34 + {
  35 + compList.map(item => (
  36 + <Select.Option value={item.id} key={item.id}>
  37 + {item.name}
  38 + </Select.Option>
  39 + ))
  40 + }
  41 + </Select>
  42 + </Col>
  43 + <Col span={6} style={{marginRight: 10}}>
  44 + <Select
  45 + placeholder="请选择寄件地区"
  46 + showSearch
  47 + optionFilterProp="children"
  48 + allowClear
  49 + style={{ width: 200 }}
  50 + onChange={(sendAreaNo) => {
  51 + setSearchData({...searchData, sendAreaNo});
  52 + setParams({...innerParams, ...searchData, sendAreaNo}, true);
  53 + }}
  54 + >
  55 + {
  56 + cityList.map(item => (
  57 + <Select.Option value={item.bh} key={item.bh}>
  58 + {item.fullName}
  59 + </Select.Option>
  60 + ))
  61 + }
  62 + </Select>
  63 + </Col>
  64 + <Col span={6} style={{marginRight: 10}}>
  65 + <Select
  66 + placeholder="请选择到达地区"
  67 + showSearch
  68 + optionFilterProp="children"
  69 + allowClear
  70 + style={{ width: 200 }}
  71 + onChange={(arriveAreaNo) => {
  72 + setSearchData({...searchData, arriveAreaNo});
  73 + setParams({...innerParams, ...searchData, arriveAreaNo}, true);
  74 + }}
  75 + >
  76 + {
  77 + cityList.map(item => (
  78 + <Select.Option value={item.bh} key={item.bh}>
  79 + {item.fullName}
  80 + </Select.Option>
  81 + ))
  82 + }
  83 + </Select>
  84 + </Col>
  85 + </Row>
  86 + );
  87 +}
  88 +
  89 +export default Filter;
0 90 \ No newline at end of file
... ...
src/pages/contract/ExpressChargingStandardSetting/index.tsx 0 → 100644
  1 +import React, { useState } from "react";
  2 +import { Button, Card, ConfigProvider, Divider, message, Popconfirm, Table } from "antd";
  3 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  4 +import zhCN from "antd/lib/locale-provider/zh_CN";
  5 +import usePagination from "@/hooks/usePagination";
  6 +import useInitial from "@/hooks/useInitail";
  7 +import { PlusOutlined } from "@ant-design/icons";
  8 +import AddModel from './components/AddModel';
  9 +import Filter from './components/Filter';
  10 +import * as API from './api';
  11 +import _ from "lodash";
  12 +import st from "./style.less";
  13 +
  14 +interface Props {
  15 +}
  16 +
  17 +const { Column } = Table;
  18 +
  19 +function expressChargingStandard(props:Props) {
  20 + const [visible, setVisible] = useState<boolean>(false);
  21 + const {
  22 + list: standardList,
  23 + loading,
  24 + paginationConfig,
  25 + innerParams,
  26 + setParams,
  27 + setLoading
  28 + } = usePagination<API.Item>(API.getStandardPage, {current: 1, pageSize: 10});
  29 + const { data: cityList, loading: cityLoading } = useInitial(API.getCityLsit, [], {});
  30 + const { data: compList, loading: compLoading } = useInitial(API.fetchComps, [], {types: '88'});
  31 + const [row, setRow] = useState<API.Item>();
  32 + /**
  33 + * @description: 编辑
  34 + * @param {*} _
  35 + * @return {*}
  36 + */
  37 + const edit = _.debounce(async (row:API.Item) => {
  38 + await setRow({...row});
  39 + setVisible(true);
  40 + }, 800);
  41 +
  42 + /**
  43 + * @description: 删除
  44 + * @param {*} _
  45 + * @return {*}
  46 + */
  47 + const _delete = _.debounce((row:API.Item) => {
  48 + const {id} = row;
  49 + if (!id) return;
  50 + setLoading(true);
  51 + API.delStandard({expressChargeStandardId: id})
  52 + .then(res => {
  53 + message.success("操作成功");
  54 + setParams({...innerParams}, true);
  55 + setLoading(false);
  56 + }).catch(err => {
  57 + message.error(err?.message);
  58 + setLoading(false);
  59 + });
  60 + }, 800);
  61 +
  62 + return (
  63 + <PageHeaderWrapper
  64 + loading={cityLoading || compLoading}
  65 + title="快递收费标准配置"
  66 + >
  67 + <ConfigProvider locale={zhCN}>
  68 + <Card className={st.page}>
  69 + <div className={st.header}>
  70 + <Filter
  71 + cityList={cityList || []}
  72 + compList={compList || []}
  73 + setParams={setParams}
  74 + innerParams={innerParams}
  75 + />
  76 + <Button
  77 + type="primary"
  78 + icon={<PlusOutlined />}
  79 + onClick={() => {
  80 + setVisible(true);
  81 + }}
  82 + >
  83 + 新增
  84 + </Button>
  85 + </div>
  86 + <Table
  87 + size="middle"
  88 + loading={loading}
  89 + dataSource={standardList}
  90 + pagination={{ ...paginationConfig }}
  91 + scroll={{ y: 800 }}
  92 + rowKey={(item: API.Item) => `${item.id}`}
  93 + onChange={(_pagination) => setParams({ ..._pagination }, true)}
  94 + >
  95 + <Column title="快递公司" width={200} dataIndex="tradeCompName" render={(t:any) => t || "-"} />
  96 + <Column title="寄件地区" width={200} dataIndex="sendAreaName" render={(t:any) => t || '-'} />
  97 + <Column title="到达地区" width={200} dataIndex="arriveAreaName" render={(t:any) => t || '-'} />
  98 + <Column title="首重(元)" width={200} dataIndex="firstWeight" render={(t:any) => t || '-'} />
  99 + <Column title="续重(元/kg)" width={200} dataIndex="continuedWeight" render={(t:any) => t || '-'} />
  100 + <Column
  101 + title="操作"
  102 + width={100}
  103 + dataIndex="unit"
  104 + render={(text, row:API.Item) => (
  105 + <span>
  106 + <Popconfirm title="是否编辑?" onConfirm={() => edit(row)} okText="确定" cancelText="取消">
  107 + <a
  108 + onClick={(e) => {
  109 + e.preventDefault();
  110 + }}
  111 + style={{ color: "#FAAD14" }}
  112 + >
  113 + 编辑
  114 + </a>
  115 + </Popconfirm>
  116 + <Divider type="vertical" />
  117 + <Popconfirm title="是否删除?" onConfirm={() => _delete(row)} okText="确定" cancelText="取消">
  118 + <a
  119 + onClick={(e) => {
  120 + e.preventDefault();
  121 + }}
  122 + style={{ color: "red" }}
  123 + >
  124 + 删除
  125 + </a>
  126 + </Popconfirm>
  127 + </span>
  128 +
  129 + )}
  130 + />
  131 + </Table>
  132 + <AddModel
  133 + visible={visible}
  134 + row={row}
  135 + compList={compList || []}
  136 + cityList={cityList || []}
  137 + onCancel={() => {
  138 + setVisible(false);
  139 + setRow(undefined);
  140 + }}
  141 + onRefresh={() => setParams({ ...innerParams }, true)}
  142 + />
  143 + </Card>
  144 + </ConfigProvider>
  145 + </PageHeaderWrapper>
  146 + );
  147 +}
  148 +
  149 +export default expressChargingStandard;
0 150 \ No newline at end of file
... ...
src/pages/contract/ExpressChargingStandardSetting/style.less 0 → 100644
  1 +//@import '~antd/lib/style/themes/default.less';
  2 +
  3 +.page {
  4 + position: relative;
  5 +
  6 + .header {
  7 + margin-bottom: 10px;
  8 + height: 32px;
  9 + display: flex;
  10 + flex-direction: row;
  11 + justify-content: space-between;
  12 + .add {
  13 + position: absolute;
  14 + right: 28px;
  15 + top: 24px;
  16 + z-index: 10;
  17 + }
  18 + }
  19 +
  20 + }
  21 + .table {
  22 + :global {
  23 + .ant-table table {
  24 + width: 100%;
  25 + border-collapse: collapse;
  26 + text-align: center;
  27 + border-radius: 4px 4px 0 0;
  28 + }
  29 + .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
  30 + padding: 16px 16px;
  31 + word-break: break-word;
  32 + text-align: center;
  33 + -ms-word-break: break-all;
  34 + }
  35 + }
  36 + .cover {
  37 + align-items: center;
  38 + height: 68px;
  39 + img {
  40 + border-radius: 4%;
  41 + height: 100%;
  42 + width: auto;
  43 + min-width: 100px;
  44 + max-width: 100px;
  45 + }
  46 + }
  47 + }
  48 +
0 49 \ No newline at end of file
... ...
src/pages/coupon/CouponConfig/components/FullReduce.tsx
... ... @@ -8,6 +8,7 @@ import ShopLimit from &quot;./ShopLimit&quot;;
8 8 import useInitail from "@/hooks/useInitail";
9 9 import { PaymentTypeEnum } from '@/pages/coupon/CashChange/api';
10 10 import { RightOutlined } from '@ant-design/icons';
  11 +import RenderSelectGoos from '@/pages/capital/ReceiveRules/subPages/GoodsDimension/components/RenderSelectGoos';
11 12  
12 13 const Option = Select.Option;
13 14 interface Props {
... ... @@ -170,6 +171,12 @@ export default function FullReduce({
170 171 />
171 172 </Form.Item>
172 173 )}
  174 + {/* 实物兑换券选择兑换物品 */}
  175 + {classifyInfo.code === "dhyhq" && (
  176 + <Form.Item label="兑换物品" name="amsCode" extra={<span style={{ fontSize: 12 }}>*兑换物品仅限一个</span>} rules={[{ required: true, message: '请选择' }]}>
  177 + <RenderSelectGoos multiple={false} disabled={readonly} />
  178 + </Form.Item>
  179 + )}
173 180 <Form.Item
174 181 label="优惠券券面金额"
175 182 name="amount"
... ...
src/pages/coupon/CouponConfig/index.tsx
... ... @@ -32,6 +32,7 @@ export default function UpsertCoupon({ visible, onCancel, onSave, remark, disabl
32 32 classifyCode: data.classifyCode ? { value: data.classifyCode, label: data.classifyName } : undefined,
33 33 exchangeTypeId: data.exchangeTypeId ? { value: data.exchangeTypeId, label: data.exchangeTypeName } : undefined,
34 34 orgList: data.orgList ? data.orgList.map((i) => ({ value: i.orgId, label: i.orgName })) : undefined,
  35 + amsCode: data.amsCode ? [{ code: data.amsCode, name: data.amsName, spec: data.amsSpec }] : undefined,
35 36 });
36 37 setLoading(false);
37 38 }).catch((e) => {
... ... @@ -72,6 +73,7 @@ export default function UpsertCoupon({ visible, onCancel, onSave, remark, disabl
72 73 exchangeTypeId: fields.exchangeTypeId && fields.exchangeTypeId.value,
73 74 exchangeTypeName: fields.exchangeTypeId && fields.exchangeTypeId.label,
74 75 schemeList: fields.schemeList ? fields.schemeList.map((i: MktConponSpace.LimitList) => ({ ...i, externalRely: i.externalRely || false })) : [],
  76 + amsCode: fields.amsCode && fields.amsCode.map((i: { code: string; }) => i.code).join(','),
75 77 remark,
76 78 };
77 79 setSaveLoading(true);
... ...
src/pages/coupon/CouponOperation/components/CouponLog.tsx
... ... @@ -109,7 +109,7 @@ function CouponLog({ couponLog, setCouponLog, onChange }: Props) {
109 109 <Table
110 110 dataSource={data}
111 111 loading={loading}
112   - rowKey={(record) => `id${record.type}`}
  112 + rowKey="id"
113 113 >
114 114 <Column
115 115 title="日志类型"
... ...
src/pages/finance/FinanceInvestor/components/Filter.tsx
... ... @@ -8,26 +8,11 @@ const { Option } = Select;
8 8 const Search = Input.Search;
9 9  
10 10 export default function AccountList() {
11   - // const { setVisible, setParams, innerParams, dealerLoading, dealerList } = useStore();
12 11 const { triggerModal, brands, financeList, setInvestList, companys, dealers } = useStore();
13   - // investList,
14   - // setInvestList,
15 12 // 存储删选条件
16 13 const [filterParams, setFilterParams] = useState({});
17 14  
18   - console.log("投资主体11列表", financeList);
19   -
20   - // function searchType(accountType: number) {
21   - // setParams({ accountType }, true);
22   - // }
23   -
24   - // _onSelectSubject;
25   - // const fetchListByName = debounce(value => {
26   - // setParams({ keywords: value }, true);
27   - // }, 500);
28   -
29 15 useEffect(() => {
30   - console.log("筛选参数filterParams", filterParams);
31 16 let originList = financeList;
32 17 let res = [];
33 18 if (filterParams.brandId) {
... ... @@ -41,7 +26,6 @@ export default function AccountList() {
41 26 if (filterParams.includeId) {
42 27 //删选包含商家 includeId
43 28 originList = originList.filter((item) => item.includeDealers?.find((y) => y.id === filterParams.includeId));
44   - console.log("筛选输入:", originList);
45 29 }
46 30 if (filterParams.creditDealerId) {
47 31 //删选授信商家 creditDealerId
... ...
src/pages/finance/SpecialAccount/FactoryBill/components/Filter.tsx
1 1 import React, { useCallback } from "react";
2   -import { Button, Col, Row, Select } from "antd";
  2 +import { Button, Row, Select } from "antd";
3 3 import { useStore } from "../index";
4 4  
5 5 const { Option } = Select;
... ... @@ -10,61 +10,47 @@ export default function Filter() {
10 10 const searchDealer = useCallback((dealerId) => {
11 11 setDealerId(dealerId);
12 12 }, []);
13   -
  13 +
14 14 const searchBrand = useCallback((brandId) => {
15 15 setBrandId(brandId);
16 16 }, []);
17 17  
18 18 return (
19   - <div
20   - style={{
21   - display: "flex",
22   - flexDirection: "row",
23   - justifyContent: "space-between",
24   - alignItems: "center",
25   - marginBottom: 20,
26   - }}
27   - >
28   - <Row style={{ display: "flex", flex: 1, alignItems: "center" }}>
29   - <div>商家:</div>
30   - <Col span={6}>
31   - <Select
32   - placeholder="请选择商家"
33   - showSearch
34   - optionFilterProp="children"
35   - onChange={searchDealer}
36   - // value={dealerId && dealerId > 0 ? dealerId : undefined}
37   - style={{ width: 300 }}
38   - >
39   - {dealerList.map((dealer) => (
40   - <Option value={dealer.id} key={dealer.id}>
41   - {dealer.name}
42   - </Option>
43   - ))}
44   - </Select>
45   - </Col>
46   - <div style={{ marginLeft: 20 }}>品牌:</div>
47   - <Col span={6}>
48   - <Select
49   - placeholder="请选择品牌"
50   - loading={brandLoading}
51   - allowClear
52   - optionFilterProp="children"
53   - onChange={searchBrand}
54   - value={brandId && brandId > 0 ? brandId : undefined}
55   - style={{ width: 160 }}
56   - >
57   - {brandList.map((brand) => (
58   - <Option value={brand.id} key={brand.id}>
59   - {brand.name}
60   - </Option>
61   - ))}
62   - </Select>
63   - </Col>
  19 + <Row justify="space-between" style={{ marginBottom: 10 }}>
  20 + <Row justify="start">
  21 + <Select
  22 + placeholder="请选择商家"
  23 + showSearch
  24 + optionFilterProp="children"
  25 + onChange={searchDealer}
  26 + style={{ width: 200 }}
  27 + >
  28 + {dealerList.map((dealer) => (
  29 + <Option value={dealer.id} key={dealer.id}>
  30 + {dealer.name}
  31 + </Option>
  32 + ))}
  33 + </Select>
  34 + <Select
  35 + placeholder="请选择品牌"
  36 + loading={brandLoading}
  37 + allowClear
  38 + optionFilterProp="children"
  39 + onChange={searchBrand}
  40 + value={brandId && brandId > 0 ? brandId : undefined}
  41 + style={{ width: 200,marginLeft:100 }}
  42 + >
  43 + {brandList.map((brand) => (
  44 + <Option value={brand.id} key={brand.id}>
  45 + {brand.name}
  46 + </Option>
  47 + ))}
  48 + </Select>
64 49 </Row>
  50 +
65 51 <Button type="primary" hidden={!dealerId} onClick={() => setVisible(true)}>
66 52 新增
67 53 </Button>
68   - </div>
  54 + </Row>
69 55 );
70 56 }
... ...
src/pages/identify/IdentifyAudit/components/List.tsx
... ... @@ -27,11 +27,21 @@ export default function IdentifyAuditList() {
27 27 >
28 28 <Table.Column title="资料编码" dataIndex="identifyCode" align="left" />
29 29 <Table.Column title="资料名称" dataIndex="identifyName" align="left" />
30   - {pagination.innerParams.type === Type.会员认证 ? (
31   - <Table.Column title="会员号" dataIndex="memberId" align="left" />
  30 + {pagination.innerParams.type !== Type.员工认证 ? (
  31 + <Table.Column
  32 + title="会员号"
  33 + dataIndex="memberId"
  34 + align="left"
  35 + render={(memberId) => memberId ?? "-"}
  36 + />
32 37 ) : null}
33   - {pagination.innerParams.type === Type.员工认证 ? (
34   - <Table.Column title="员工ID" dataIndex="staffId" align="left" />
  38 + {pagination.innerParams.type !== Type.会员认证 ? (
  39 + <Table.Column
  40 + title="员工ID"
  41 + dataIndex="staffId"
  42 + align="left"
  43 + render={(staffId) => staffId ?? "-"}
  44 + />
35 45 ) : null}
36 46 {pagination.innerParams.type === Type.车辆认证 ? (
37 47 <Table.Column title="VIN" dataIndex="vin" align="left" />
... ...
src/pages/identify/IdentifyAudit/components/Modal.tsx
... ... @@ -2,7 +2,7 @@
2 2 * @Author: wangqiang@feewee.cn
3 3 * @Date: 2023-02-10 17:52:44
4 4 * @LastEditors: wangqiang@feewee.cn
5   - * @LastEditTime: 2023-02-11 16:46:04
  5 + * @LastEditTime: 2023-03-01 14:04:28
6 6 */
7 7 import {
8 8 Button,
... ... @@ -139,12 +139,12 @@ export default function IdentifyAuditModal() {
139 139 <ProDescriptions.Item label="资料名称">
140 140 {current?.identifyName || "-"}
141 141 </ProDescriptions.Item>
142   - {pagination.innerParams?.type === Type.会员认证 ? (
  142 + {pagination.innerParams?.type !== Type.员工认证 ? (
143 143 <ProDescriptions.Item label="会员ID">
144 144 {current?.memberId || "-"}
145 145 </ProDescriptions.Item>
146 146 ) : null}
147   - {pagination.innerParams?.type === Type.员工认证 ? (
  147 + {pagination.innerParams?.type !== Type.会员认证 ? (
148 148 <ProDescriptions.Item label="员工ID">
149 149 {current?.staffId || "-"}
150 150 </ProDescriptions.Item>
... ...
src/pages/mkt/ActivityCreate/BasicInformation/components/ImageUploader/index.tsx
... ... @@ -161,7 +161,7 @@ export default function Detail({ form, readOnly, bizType }: Props) {
161 161 return e && e.fileList;
162 162 }}
163 163 >
164   - <Upload maxCount={10} multiple {...videoProps}>
  164 + <Upload maxCount={1} multiple {...videoProps}>
165 165 {uploadButton}
166 166 </Upload>
167 167 </FormItem>
... ...
src/pages/mkt/ActivityCreate/BasicInformation/index.tsx
... ... @@ -86,7 +86,6 @@ function Index({ onNext }: Props) {
86 86 // }
87 87 // }
88 88 params.bizType = undefined;
89   - params.activityName = undefined;
90 89 params.activityType = undefined;
91 90 params.address = undefined;
92 91 params.addressType = undefined;
... ... @@ -170,7 +169,7 @@ function Index({ onNext }: Props) {
170 169 </Select>
171 170 </FormItem>
172 171 <FormItem name="activityName" label="活动名称" {...formRules.activityName}>
173   - <Input placeholder="输入活动名称" disabled={readOnly} />
  172 + <Input placeholder="输入活动名称" disabled={readOnly && !changeEnable} />
174 173 </FormItem>
175 174 <FormItem label="活动描述">
176 175 <BraftEditor
... ...
src/pages/mkt/ActivityCreate/ExternalPromotion/components/ActivityScope/index.tsx
... ... @@ -710,7 +710,7 @@ function Index() {
710 710 {({ getFieldValue }) => (getFieldValue("goalType") === 2 ? (
711 711 <Form.Item name="goalJoinLimit" rules={[{ required: true, message: "请选择活动报名条件" }]}>
712 712 <Radio.Group
713   - disabled={readOnly}
  713 + disabled={readOnly && !changeEnable}
714 714 onChange={(v) => {
715 715 setGoalJoinLimit(v.target.value);
716 716 if (v.target.value === 1) {
... ... @@ -739,7 +739,7 @@ function Index() {
739 739 {bizType !== 2 && (
740 740 <Form.Item name="nonGoalJoin" valuePropName="checked">
741 741 <Checkbox
742   - disabled={readOnly || disable || JoinLimit === 1}
  742 + disabled={(readOnly && !changeEnable) || disable || JoinLimit === 1}
743 743 onChange={(v) => {
744 744 if (v.target.checked) {
745 745 form.setFieldsValue({ nonGoalBrowse: true });
... ... @@ -754,7 +754,7 @@ function Index() {
754 754 <div style={{ marginTop: 35, color: '#666' }}>*活动页面展示(C端---{'>'}霏车车小程序)</div>
755 755 <Form.Item name="publicity" valuePropName="checked">
756 756 <Checkbox
757   - disabled={readOnly || [5, 6, 9].includes(activityType || 0)}
  757 + disabled={(readOnly && !changeEnable) || [5, 6, 9].includes(activityType || 0)}
758 758 onChange={(v) => {
759 759 if (v.target.checked) {
760 760 form.setFieldsValue({ nonGoalBrowse: true });
... ... @@ -767,7 +767,7 @@ function Index() {
767 767 </Form.Item>
768 768 <div style={{ marginTop: 30, color: '#666' }}>*车系详情中"查看优惠"页面展示活动信息</div>
769 769 <Form.Item name="nonGoalBrowse" valuePropName="checked">
770   - <Checkbox disabled={readOnly || (disable && JoinLimit !== 1) || (!!nonGoalLimit.nonGoalJoin || !!nonGoalLimit.publicity)}> 非目标客户可查看</Checkbox>
  770 + <Checkbox disabled={(readOnly && !changeEnable) || (disable && JoinLimit !== 1) || (!!nonGoalLimit.nonGoalJoin || !!nonGoalLimit.publicity)}> 非目标客户可查看</Checkbox>
771 771 </Form.Item>
772 772  
773 773 <Form.Item style={{ marginTop: 30, textAlign: "center" }}>
... ...
src/pages/performance/CompensateGroupConfig/components/DraftList.tsx
... ... @@ -89,7 +89,7 @@ export default ({ type }: Props) =&gt; {
89 89 新增
90 90 </Button>
91 91 </Row>
92   - <Table loading={loading} rowKey={(row) => `id${row.id}`} dataSource={list} pagination={paginationConfig}>
  92 + <Table loading={loading} rowKey={(row) => `id${row.draftId}`} dataSource={list} pagination={paginationConfig}>
93 93 <Column title="薪酬组名称" dataIndex="name" align="center" render={(name) => name || ""} />
94 94 <Column title="岗位" dataIndex="postName" align="center" />
95 95 <Column
... ...
src/pages/performance/CompensateGroupConfig/interface.d.ts
... ... @@ -125,9 +125,9 @@ declare namespace CompensateConfig {
125 125 settings: Settings[];
126 126 id?: number;
127 127 name: string;
128   - ladderParams?: CommissionParams[];
  128 + ladderParams: CommissionParams[];
129 129 commissionParams: CommissionParams[];
130   - conds?: Conds[];
  130 + conds: Conds[];
131 131 }
132 132 interface Conds {
133 133 indicatorCode: string;
... ...
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, num } = 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 + console.log('num', num);
  39 + const { data, errMsg, setParams, loading } = useInitail(evaDataDetailApi, {}, {}, delay);
  40 + console.log(isArray(data));
  41 + useEffect(() => {
  42 + if (isArray(data)) {
  43 + setNewData(data);
  44 + }
  45 + }, [data]);
  46 +
  47 + return (
  48 + <PageHeaderWrapper title="考评数据导入">
  49 + <Card>
  50 + <Table loading={loading} rowKey={(row) => `id${id}`} dataSource={newData} pagination={{ total: num }}>
  51 + <Column title="归属人员" dataIndex="userName" align="center" render={(name) => <span>{name || "--"}</span>} />
  52 + <Column title="归属门店" dataIndex="shopName" align="center" render={(name) => <span>{name || "--"}</span>} />
  53 + <Column
  54 + title="指标名称"
  55 + dataIndex="indicatorName"
  56 + align="center"
  57 + render={(name) => <span>{name || "--"}</span>}
  58 + />
  59 + <Column
  60 + title="指标值"
  61 + dataIndex="indicatorValue"
  62 + align="center"
  63 + render={(num, record: any) => (
  64 + <span>
  65 + {num !== undefined
  66 + ? `${num}${
  67 + record.dataType == 1 ? "台" : record.dataType == 2 ? "%" : record.dataType == 3 ? "元" : ""
  68 + }`
  69 + : "--"}
  70 + </span>
  71 + )}
  72 + />
  73 + <Column
  74 + title="考核周期"
  75 + dataIndex="dataDate"
  76 + align="center"
  77 + render={(time: number) => (time ? moment(time).format("YYYY-MM-DD") : "--")}
  78 + />
  79 + {/* <Column title="更新日期" dataIndex="dataDate" align="center" render={(time: number) => ""} /> */}
  80 + <Column
  81 + title="是否导入"
  82 + dataIndex="errorType"
  83 + align="center"
  84 + render={(_: any, record: any) =>
  85 + record.errorType ? <div className={st.no}>未导入</div> : <div className={st.yes}>已导入</div>
  86 + }
  87 + />
  88 + <Column
  89 + title="未导入原因"
  90 + dataIndex="errorType"
  91 + align="center"
  92 + render={(_: any, record: any) => (record.errorType ? ReasonsEnum[record.errorType] : "--")}
  93 + />
  94 + </Table>
  95 + <Row justify="center">
  96 + <Button type="default" size="large" onClick={() => history.goBack()} style={{ marginRight: 50, width: 200 }}>
  97 + 返回
  98 + </Button>
  99 + </Row>
  100 + </Card>
  101 + </PageHeaderWrapper>
  102 + );
  103 +}
  104 +export default (props: Props) => (
  105 + <Provider>
  106 + <Index {...props} />
  107 + </Provider>
  108 +);
... ...
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 +}
  47 +
  48 +/**
  49 + * 保存上传人员数据
  50 + * http://testgate.feewee.cn/morax/erp/eval-indicator/save-import
  51 + */
  52 +export function saveEvaImportData(params: { key: string }) {
  53 + return request.get(`${MORAX_HOST}/erp/eval-indicator/save-import`, { params });
  54 +}
... ...
src/pages/performance/EvaDataImport/components/FileDatailsModal.tsx 0 → 100644
  1 +import React, { useState, useEffect } from "react";
  2 +import {
  3 + Table,
  4 + Input,
  5 + InputNumber,
  6 + Popconfirm,
  7 + Form,
  8 + Typography,
  9 + Button,
  10 + message,
  11 + Space,
  12 + Divider,
  13 + Modal,
  14 + Card,
  15 +} from "antd";
  16 +import { cloneDeep } from "lodash";
  17 +import { KpiGroupSetteing } from "@/pages/performance/KpiGroupSetting/interface";
  18 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  19 +import { render } from "react-dom";
  20 +import moment from "moment";
  21 +import { ReasonsEnum } from "../entity";
  22 +import { saveEvaImportData } from "../api";
  23 +import { history } from "umi";
  24 +import st from "./style.less";
  25 +
  26 +const Column = Table.Column;
  27 +
  28 +interface Props {
  29 + visible: boolean;
  30 + fileData: any;
  31 + tarOnCancel: Function;
  32 + setParams: Function;
  33 + innerParams: any;
  34 +}
  35 +const TargetModal = ({ visible, fileData, tarOnCancel, setParams, innerParams }: Props) => {
  36 + const [loading, setLoading] = useState<boolean>(false);
  37 + const onOk = async (key: string) => {
  38 + const pa = { key };
  39 + setLoading(true);
  40 + try {
  41 + const { success } = await saveEvaImportData(pa);
  42 + if (success) {
  43 + setLoading(false);
  44 + message.success(`数据上传成功`, 5);
  45 + // 重新刷新列表
  46 + setParams({ ...innerParams }, true);
  47 + tarOnCancel && tarOnCancel();
  48 + }
  49 + } catch (error: any) {
  50 + setLoading(false);
  51 + message.error(error.message);
  52 + }
  53 + };
  54 + return (
  55 + <>
  56 + <Modal
  57 + title="导入数据详情"
  58 + visible={visible}
  59 + onCancel={() => tarOnCancel()}
  60 + maskClosable={false}
  61 + width={1500}
  62 + onOk={() => onOk(fileData.key)}
  63 + confirmLoading={loading}
  64 + >
  65 + <Table bordered dataSource={fileData.details} pagination={{ total: fileData.num }}>
  66 + <Column title="归属人员" dataIndex="userName" align="center" render={(name) => <span>{name || "--"}</span>} />
  67 + <Column title="归属门店" dataIndex="shopName" align="center" render={(name) => <span>{name || "--"}</span>} />
  68 + <Column
  69 + title="指标名称"
  70 + dataIndex="indicatorName"
  71 + align="center"
  72 + render={(name) => <span>{name || "--"}</span>}
  73 + />
  74 + {/* <Column
  75 + title="指标值"
  76 + dataIndex="indicatorValue"
  77 + align="center"
  78 + render={(num, record: any) => (
  79 + <span>
  80 + {num !== undefined
  81 + ? `${num}${
  82 + record.dataType == 1 ? "台" : record.dataType == 2 ? "%" : record.dataType == 3 ? "元" : ""
  83 + }`
  84 + : "--"}
  85 + </span>
  86 + )}
  87 + /> */}
  88 + <Column
  89 + title="考核周期"
  90 + dataIndex="dataDate"
  91 + align="center"
  92 + render={(time: number) => (time ? moment(time).format("YYYY-MM-DD") : "--")}
  93 + />
  94 + <Column
  95 + title="是否导入"
  96 + dataIndex="errorType"
  97 + align="center"
  98 + render={(_: any, record: any) =>
  99 + record.errorType ? <div className={st.no}>未导入</div> : <div className={st.yes}>已导入</div>
  100 + }
  101 + />
  102 + <Column
  103 + title="未导入原因"
  104 + dataIndex="errorType"
  105 + align="center"
  106 + render={(_: any, record: any) => (record.errorType ? ReasonsEnum[record.errorType] : "--")}
  107 + />
  108 + </Table>
  109 + <div>
  110 + 成功条数: <span style={{ color: "#20c688" }}>{fileData.successNum}</span> 条
  111 + </div>
  112 + <div>
  113 + 失败条数: <span style={{ color: "#f4333c" }}>{fileData.errorNum}</span> 条
  114 + </div>
  115 + </Modal>
  116 + </>
  117 + );
  118 +};
  119 +
  120 +export default TargetModal;
... ...
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 + console.log(moment(value[0]).unix() * 1000);
  39 + console.log(moment(value[1]).unix() * 1000);
  40 + }
  41 + };
  42 +
  43 + return (
  44 + <Row justify="start" style={{ marginBottom: 20 }}>
  45 + <Select
  46 + allowClear
  47 + placeholder="请选择指标名称"
  48 + style={{ width: 150, marginRight: 10, marginBottom: 10 }}
  49 + onChange={(value) => {
  50 + setParams({ indicatorCode: value }, true);
  51 + }}
  52 + showSearch
  53 + optionFilterProp="children"
  54 + >
  55 + {data.map((item: any) => (
  56 + <Option value={item.code} key={item.code}>
  57 + {item.name}
  58 + </Option>
  59 + ))}
  60 + </Select>
  61 + <Select
  62 + allowClear
  63 + placeholder="请选择导入人员"
  64 + style={{ width: 150, marginRight: 10, marginBottom: 10 }}
  65 + onChange={(value) => {
  66 + setParams({ userId: value }, true);
  67 + }}
  68 + showSearch
  69 + optionFilterProp="children"
  70 + >
  71 + {list.map((item) => (
  72 + <Option value={item.id} key={item.id}>
  73 + {item.name}
  74 + </Option>
  75 + ))}
  76 + </Select>
  77 + <RangePicker
  78 + // showTime={{ format: "HH:mm:ss" }}
  79 + // format="YYYY-MM-DD HH:mm:ss"
  80 + onChange={onChange}
  81 + style={{ height: 32 }}
  82 + />
  83 + </Row>
  84 + );
  85 +}
... ...
src/pages/performance/EvaDataImport/components/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/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 +import FileDatailsModal from './components/FileDatailsModal';
  12 +
  13 +const Column = Table.Column;
  14 +
  15 +export default () => {
  16 + const { loading, list, paginationConfig, setParams, innerParams } = usePagination(evaDataListApi, {
  17 + pageSize: 10,
  18 + });
  19 + const [fileData, setFileData] = useState({});
  20 + const [visible, setVisible] = useState<boolean>(false);
  21 + const uploadPerson: UploadProps = {
  22 + name: "file",
  23 + action: "/api/morax/erp/eval-indicator/analysis-staff",
  24 + maxCount: 1,
  25 + showUploadList: false,
  26 + onChange(info) {
  27 + if (info.file.status !== "uploading") {
  28 + console.log(info.file, info.fileList);
  29 + }
  30 + if (info.file.status === "done") {
  31 + setFileData(info.file.response.data);
  32 + setVisible(true);
  33 + } else if (info.file.status === "error") {
  34 + message.error(`${info.file.name} 上传失败`);
  35 + }
  36 + },
  37 + };
  38 + const uploadShop: UploadProps = {
  39 + name: "file",
  40 + action: "/api/morax/erp/eval-indicator/analysis-shop",
  41 + maxCount: 1,
  42 + showUploadList: false,
  43 + onChange(info) {
  44 + if (info.file.status !== "uploading") {
  45 + console.log(info.file, info.fileList);
  46 + }
  47 + if (info.file.status === "done") {
  48 + setFileData(info.file.response.data);
  49 + setVisible(true);
  50 + } else if (info.file.status === "error") {
  51 + message.error(`${info.file.name} 上传失败`);
  52 + }
  53 + },
  54 + };
  55 +
  56 + return (
  57 + <PageHeaderWrapper title="考评数据导入">
  58 + <Card>
  59 + <Row style={{ marginBottom: 10 }} justify="space-between">
  60 + <Filter setParams={setParams} />
  61 + <div>
  62 + <Button type="default" style={{ marginRight: 10 }}>
  63 + <a
  64 + href="https://gate.feewee.cn/file/download?fid=74d1d724f9be48baa5921f3782037c3b"
  65 + target="_blank"
  66 + rel="noreferrer"
  67 + >
  68 + 下载人员模板
  69 + </a>
  70 + </Button>
  71 + <Button type="default" style={{ marginRight: 10 }}>
  72 + <a
  73 + href="https://gate.feewee.cn/file/download?fid=e4eb136962164264a78753bd1d6061f3"
  74 + target="_blank"
  75 + rel="noreferrer"
  76 + >
  77 + 下载门店模板
  78 + </a>
  79 + </Button>
  80 + <Upload {...uploadPerson}>
  81 + <Button type="primary" style={{ marginRight: 10 }}>
  82 + 按人员导入
  83 + </Button>
  84 + </Upload>
  85 + <Upload {...uploadShop}>
  86 + <Button type="primary">按门店导入</Button>
  87 + </Upload>
  88 + </div>
  89 + </Row>
  90 + <Table
  91 + loading={loading}
  92 + rowKey={(row) => `id${row.id}`}
  93 + dataSource={list}
  94 + pagination={paginationConfig}
  95 + >
  96 + <Column
  97 + title="导入时间"
  98 + dataIndex="createTime"
  99 + align="center"
  100 + render={(time: number) => (time ? moment(time).format("YYYY-MM-DD") : "--")}
  101 + />
  102 + <Column
  103 + title="导入人员"
  104 + dataIndex="importUserName"
  105 + align="center"
  106 + render={(name) => <span>{name || "--"}</span>}
  107 + />
  108 + <Column
  109 + title="指标名称"
  110 + dataIndex="indicatorName"
  111 + align="center"
  112 + render={(name) => <span>{name || "--"}</span>}
  113 + />
  114 + <Column
  115 + title="导入数据"
  116 + dataIndex="num"
  117 + align="center"
  118 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  119 + />
  120 + <Column
  121 + title="成功"
  122 + dataIndex="successNum"
  123 + align="center"
  124 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  125 + />
  126 + <Column
  127 + title="失败"
  128 + dataIndex="errorNum"
  129 + align="center"
  130 + render={(num) => <span>{num !== undefined ? `${num}条` : "--"}</span>}
  131 + />
  132 + <Column
  133 + title="数据清单"
  134 + align="center"
  135 + dataIndex="enable"
  136 + width={150}
  137 + render={(text: boolean, record: any) => (
  138 + <Space split={<Divider type="vertical" />}>
  139 + <Typography.Link
  140 + onClick={() => {
  141 + history.push(`/morax/evaDataImport/edit/${record.id}/${record.num}`);
  142 + }}
  143 + >
  144 + 查看
  145 + </Typography.Link>
  146 + </Space>
  147 + )}
  148 + />
  149 + </Table>
  150 + <FileDatailsModal
  151 + visible={visible}
  152 + tarOnCancel={() => setVisible(false)}
  153 + fileData={fileData}
  154 + setParams={setParams}
  155 + innerParams={innerParams}
  156 + />
  157 + </Card>
  158 + </PageHeaderWrapper>
  159 + );
  160 +};
... ...
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/api.ts 0 → 100644
  1 +import { http } from "@/typing/http";
  2 +import request from "@/utils/request";
  3 +import { EHR_HOST, MORAX_HOST } from "@/utils/host";
  4 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  5 +
  6 +/**
  7 + * 考评详情
  8 + * http://testgate.feewee.cn/morax/erp/eval/group
  9 + */
  10 +export function queryDetailListApi(id: number): http.PromiseResp<EvaGroupSetteing.EvaGroupDetail> {
  11 + return request.get(`${MORAX_HOST}/erp/eval/group`, { params: { id } });
  12 +}
  13 +/**
  14 + * 考评草稿详情
  15 + * http://testgate.feewee.cn/morax/erp/setting-draft/eval-detail
  16 + */
  17 +export function draftQueryDetailListApi(id: number): http.PromiseResp<EvaGroupSetteing.EvaGroupDetail> {
  18 + return request.get(`${MORAX_HOST}/erp/setting-draft/eval-detail`, { params: { id } });
  19 +}
  20 +
  21 +/**
  22 + * 获取岗位下的绩效组指标
  23 + * http://testgate.feewee.cn/morax/erp/eval/post/indicator
  24 + * @param postId
  25 + * @returns
  26 + */
  27 +export function queryPostIndicatorApi(params?: { postId: number; }): http.PromiseResp<EvaGroupSetteing.IndicatorByPost[]> {
  28 + return request.get(`${MORAX_HOST}/erp/eval/post/indicator`, { params });
  29 +}
  30 +
  31 +/**
  32 + * 获取岗位下的绩效组指标
  33 + * http://testgate.feewee.cn/morax/erp/eval/shop/indicator
  34 + * @param postId
  35 + * @returns
  36 + */
  37 +export function queryShopIndicatorApi(params?: any): http.PromiseResp<EvaGroupSetteing.IndicatorByPost[]> {
  38 + return request.get(`${MORAX_HOST}/erp/eval/shop/indicator`, { params });
  39 +}
  40 +
  41 +/**
  42 + * 考评组保存
  43 + * http://testgate.feewee.cn/morax/erp/eval/group/{submit}
  44 + */
  45 +export function saveEvaGroupConfig(params: EvaGroupSetteing.EvaGroupSaveParams, submit: number): http.PromiseResp<any> {
  46 + return request.post(`${MORAX_HOST}/erp/eval/group/${submit}`, params);
  47 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddCommissionParamsModal.tsx 0 → 100755
  1 +import React, { useEffect, useState } from "react";
  2 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  3 +import { saveRewardsListApi } from "../RewardsList/api";
  4 +import { useStore } from "../index";
  5 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "@/pages/performance/EvaGroupSetting/EditComfirm/api";
  6 +import _ from "lodash";
  7 +import useInitail from "@/hooks/useInitail";
  8 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  9 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  10 +
  11 +const Option = Select.Option;
  12 +interface Props {
  13 + // visible: boolean;
  14 + // onCancel: Function;
  15 + // postId?: number;
  16 + // shopIds?: string;
  17 + // onOk: (vales: any) => void;
  18 + // currentItem: KpiGroupSetteing.Item;
  19 + // comItem: KpiGroupSetteing.CommissionParams;
  20 + addComVisible: boolean;
  21 + onCancel: Function;
  22 + postId?: number;
  23 + shopIds?: string;
  24 + onOk: (vales: any) => void;
  25 + comItem: Commission;
  26 + setItemId: Function;
  27 + scopeType: number;
  28 +}
  29 +type Commission = EvaGroupSetteing.CommissionParams;
  30 +export default function AddCommissionParamsModal(props: Props) {
  31 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  32 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  33 + const [form] = Form.useForm();
  34 + const { selectedIndicators, setParamAlias, setSelectedIndicators } = useStore();
  35 +
  36 + const [isTarget, setIsTarget] = useState(false);
  37 + // console.log(form);
  38 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  39 + const [delay, setDelay] = useState(true);
  40 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  41 + const [targetType, setTargetType] = useState<number>();
  42 + // 保存选中指标是否考评类型
  43 + const [codeType, setCodeType] = useState<number>();
  44 + const [dataType, setDataType] = useState<number>();
  45 + // 保存过滤后指标列表
  46 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  47 + const [indicatorName, setIndicatorName] = useState("");
  48 + const [id, setId] = useState(0);
  49 + const {
  50 + data: indicatorsList,
  51 + setParams,
  52 + loading,
  53 + } = useInitail(
  54 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  55 + [],
  56 + scopeType == 1 ? { postId } : {},
  57 + delay
  58 + );
  59 + useEffect(() => {
  60 + setParams(scopeType == 1 ? { postId } : {}, true);
  61 + setDelay(false);
  62 + setTargetType(1);
  63 + }, [addComVisible]);
  64 + // 修改
  65 +
  66 + useEffect(() => {
  67 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  68 + const res = indicatorsList.filter((item) => !selectedIndicators.find((y) => y === item.code));
  69 + setNewIndicators([...res]);
  70 + console.log("selectedIndicators", selectedIndicators);
  71 + }
  72 + if (addComVisible && comItem.code) {
  73 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  74 + console.log("indTar", indTar);
  75 + console.log("comItem.targetType", comItem.targetType);
  76 + setTargetType(indTar);
  77 + setIndicatorName(comItem.name);
  78 + setDataType(comItem.dataType);
  79 + setCodeType(comItem.codeType);
  80 + form.setFieldsValue({
  81 + ...comItem,
  82 + commissionParams: {
  83 + value: comItem.code,
  84 + label: comItem.name,
  85 + },
  86 + });
  87 + }
  88 + if (comItem.targetValue && comItem.targetCalcType) {
  89 + setIsTarget(true);
  90 + }
  91 + }, [indicatorsList]);
  92 + useEffect(() => {
  93 + if (targetType === TargetTypeEnum["无"]) {
  94 + setIsTarget(false);
  95 + }
  96 + }, [targetType]);
  97 + useEffect(() => {
  98 + setIsTarget(false);
  99 + }, [id]);
  100 + // 校验表单数据
  101 + function transformDTO(formData: any) {
  102 + let detail = {};
  103 + _.each(formData, (value: any, key: string) => {
  104 + switch (key) {
  105 + case "commissionParams":
  106 + const _options = value || {};
  107 + console.log(_options);
  108 + detail.code = _options.key;
  109 + detail.name = _options.label[0];
  110 + detail.code = _options.value;
  111 + break;
  112 + default:
  113 + detail[key] = value;
  114 + break;
  115 + }
  116 + });
  117 + return detail;
  118 + }
  119 + function handSubmit(fieldsValue: any) {
  120 + const pa: any = transformDTO(fieldsValue);
  121 + pa.targetType = targetType;
  122 + pa.codeType = codeType;
  123 + pa.dataType = dataType;
  124 + console.log("100pa", pa);
  125 + const newItemId = pa.code;
  126 + // 编辑时,不需要push id
  127 + if (!comItem.code) {
  128 + const tmpIds = [...selectedIndicators];
  129 + tmpIds.push(newItemId);
  130 + setSelectedIndicators([...tmpIds]);
  131 + } else {
  132 + pa.code = comItem.code;
  133 + pa.name = comItem.name;
  134 + }
  135 + onOk(pa);
  136 + onCancel && onCancel();
  137 + }
  138 + return (
  139 + <Modal
  140 + visible={addComVisible}
  141 + title={`${comItem.code ? "编辑" : "新增"}固定得分指标`}
  142 + maskClosable={false}
  143 + afterClose={() => {
  144 + form.resetFields();
  145 + onCancel();
  146 + }}
  147 + onCancel={() => onCancel()}
  148 + onOk={form.submit}
  149 + width={1000}
  150 + >
  151 + <Spin spinning={loading}>
  152 + <Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} onFinish={handSubmit}>
  153 + <Form.Item name="commissionParams" label="计分指标" rules={[{ required: true, message: "计分指标" }]}>
  154 + <Select
  155 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  156 + labelInValue
  157 + disabled={!!comItem.code}
  158 + onChange={(value, Option: any) => {
  159 + setTargetType(Option.targetType);
  160 + setItemId(Option.key);
  161 + setId(Option.key);
  162 + setIndicatorName(Option.children);
  163 + setParamAlias(Option.name);
  164 + setCodeType(Option.codeType);
  165 + setDataType(Option.dataType);
  166 + }}
  167 + showSearch
  168 + optionFilterProp="children"
  169 + >
  170 + {newIndicators.map((item) => (
  171 + <Option
  172 + value={item.code}
  173 + key={item.id}
  174 + targetType={item.targetType}
  175 + dataType={item.dataType}
  176 + codeType={item.codeType}
  177 + name={item.name}
  178 + >
  179 + {item.name}{item.codeType == 2 ? '*' : ''}
  180 + </Option>
  181 + ))}
  182 + </Select>
  183 + </Form.Item>
  184 + <div style={{ display: "flex", justifyContent: "flex-start" }}>
  185 + <Form.Item
  186 + name="proportion"
  187 + label="占比"
  188 + rules={[
  189 + { pattern: percent, message: "请输入大于0小于等于100的数(最多保留两位小数)" },
  190 + { required: true, message: "请输入占比数" },
  191 + ]}
  192 + style={{ width: "100%" }}
  193 + >
  194 + <InputNumber style={{ width: "100%" }} addonAfter="%" />
  195 + </Form.Item>
  196 + </div>
  197 + <Form.Item name="cap" label="是否封顶" rules={[{ required: true, message: "请选择" }]}>
  198 + <Radio.Group>
  199 + <Radio value>是</Radio>
  200 + <Radio value={false}>否</Radio>
  201 + </Radio.Group>
  202 + </Form.Item>
  203 + {(targetType === TargetTypeEnum["百分比"] ||
  204 + targetType === TargetTypeEnum["金额"] ||
  205 + targetType === TargetTypeEnum["数量"]) && (
  206 + <div style={{ marginLeft: 65 }}>
  207 + <Button type="link" onClick={() => setIsTarget(true)}>
  208 + 考核目标值设置(可选项)
  209 + </Button>
  210 + {isTarget && (
  211 + <Button type="link" onClick={() => setIsTarget(false)}>
  212 + 删除该项考核目标设置
  213 + </Button>
  214 + )}
  215 + </div>
  216 + )}
  217 + {isTarget && (
  218 + <>
  219 + <Form.Item label="考核目标名称" name="targetName">
  220 + <Select disabled defaultValue={indicatorName} />
  221 + </Form.Item>
  222 + <Form.Item
  223 + label="考核目标计算类型"
  224 + name="targetCalcType"
  225 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  226 + >
  227 + <Radio.Group>
  228 + <Radio value={1}>考核目标值计算 </Radio>
  229 + <Radio value={2}>最低要求计算</Radio>
  230 + </Radio.Group>
  231 + </Form.Item>
  232 + <Form.Item
  233 + label="考核目标值"
  234 + name="targetValue"
  235 + rules={[
  236 + { required: true, message: "请输入考核目标值" },
  237 + {
  238 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  239 + message:
  240 + targetType === TargetTypeEnum["百分比"]
  241 + ? "请输入大于0小于等于100的数(保留两位小数)"
  242 + : "请输入大于0的数(保留两位小数)",
  243 + },
  244 + ]}
  245 + >
  246 + <InputNumber
  247 + placeholder="请输入考核目标值"
  248 + style={{ width: "100%" }}
  249 + addonAfter={
  250 + targetType === TargetTypeEnum["百分比"]
  251 + ? "%"
  252 + : targetType === TargetTypeEnum["金额"]
  253 + ? "元"
  254 + : "数量"
  255 + }
  256 + />
  257 + </Form.Item>
  258 + </>
  259 + )}
  260 + </Form>
  261 + </Spin>
  262 + </Modal>
  263 + );
  264 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddCommissionParamsModalSal.tsx 0 → 100755
  1 +import React, { useEffect, useState } from "react";
  2 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  3 +import { saveRewardsListApi } from "../RewardsList/api";
  4 +import { useStore } from "../index";
  5 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "@/pages/performance/EvaGroupSetting/EditComfirm/api";
  6 +import _ from "lodash";
  7 +import useInitail from "@/hooks/useInitail";
  8 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  9 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  10 +
  11 +const Option = Select.Option;
  12 +interface Props {
  13 + // visible: boolean;
  14 + // onCancel: Function;
  15 + // postId?: number;
  16 + // shopIds?: string;
  17 + // onOk: (vales: any) => void;
  18 + // currentItem: KpiGroupSetteing.Item;
  19 + // comItem: KpiGroupSetteing.CommissionParams;
  20 + addComVisible: boolean;
  21 + onCancel: Function;
  22 + postId?: number;
  23 + shopIds?: string;
  24 + onOk: (vales: any) => void;
  25 + comItem: Commission;
  26 + setItemId: Function;
  27 + scopeType: number;
  28 +}
  29 +type Commission = EvaGroupSetteing.CommissionParams;
  30 +export default function AddCommissionParamsModal(props: Props) {
  31 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  32 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  33 + const [form] = Form.useForm();
  34 + const { selectedIndicatorSal, setCommissionParamAlias, setSelectedIndicatorsSal } = useStore();
  35 +
  36 + const [isTarget, setIsTarget] = useState(false);
  37 + // console.log(form);
  38 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  39 + const [delay, setDelay] = useState(true);
  40 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  41 + const [targetType, setTargetType] = useState<number>();
  42 + // 保存选中指标是否考评类型
  43 + const [codeType, setCodeType] = useState<number>();
  44 + const [dataType, setDataType] = useState<number>();
  45 + // 保存过滤后指标列表
  46 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  47 + const [indicatorName, setIndicatorName] = useState("");
  48 + const [id, setId] = useState(0);
  49 + const {
  50 + data: indicatorsList,
  51 + setParams,
  52 + loading,
  53 + } = useInitail(
  54 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  55 + [],
  56 + scopeType == 1 ? { postId } : {},
  57 + delay
  58 + );
  59 + useEffect(() => {
  60 + setParams(scopeType == 1 ? { postId } : {}, true);
  61 + setDelay(false);
  62 + setTargetType(1);
  63 + }, [addComVisible]);
  64 + // 修改
  65 +
  66 + useEffect(() => {
  67 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  68 + const res = indicatorsList.filter((item) => !selectedIndicatorSal.find((y) => y === item.code));
  69 + setNewIndicators([...res]);
  70 + }
  71 + if (addComVisible && comItem.code) {
  72 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  73 + console.log("indTar", indTar);
  74 + console.log("comItem.targetType", comItem.targetType);
  75 + setTargetType(indTar);
  76 + setIndicatorName(comItem.name);
  77 + setDataType(comItem.dataType);
  78 + setCodeType(comItem.codeType);
  79 + form.setFieldsValue({
  80 + ...comItem,
  81 + commissionParams: {
  82 + value: comItem.code,
  83 + label: comItem.name,
  84 + },
  85 + });
  86 + }
  87 + if (comItem.targetValue && comItem.targetCalcType) {
  88 + setIsTarget(true);
  89 + }
  90 + }, [indicatorsList]);
  91 + useEffect(() => {
  92 + if (targetType === TargetTypeEnum["无"]) {
  93 + setIsTarget(false);
  94 + }
  95 + }, [targetType]);
  96 + useEffect(() => {
  97 + setIsTarget(false);
  98 + }, [id]);
  99 + // 校验表单数据
  100 + function transformDTO(formData: any) {
  101 + let detail = {};
  102 + _.each(formData, (value: any, key: string) => {
  103 + switch (key) {
  104 + case "commissionParams":
  105 + const _options = value || {};
  106 + detail.code = _options.key;
  107 + detail.name = _options.label[0];
  108 + detail.code = _options.value;
  109 + break;
  110 + default:
  111 + detail[key] = value;
  112 + break;
  113 + }
  114 + });
  115 + return detail;
  116 + }
  117 + function handSubmit(fieldsValue: any) {
  118 + const pa: any = transformDTO(fieldsValue);
  119 + pa.targetType = targetType;
  120 + pa.codeType = codeType;
  121 + pa.dataType = dataType;
  122 + console.log("100pa", pa);
  123 + const newItemId = pa.code;
  124 + // 编辑时,不需要push id
  125 + if (!comItem.code) {
  126 + const tmpIds = [...selectedIndicatorSal];
  127 + tmpIds.push(newItemId);
  128 + setSelectedIndicatorsSal([...tmpIds]);
  129 + } else {
  130 + pa.code = comItem.code;
  131 + pa.name = comItem.name;
  132 + }
  133 + onOk(pa);
  134 + onCancel && onCancel();
  135 + }
  136 + return (
  137 + <Modal
  138 + visible={addComVisible}
  139 + title={`${comItem.code ? "编辑" : "新增"}固定得分指标`}
  140 + maskClosable={false}
  141 + afterClose={() => {
  142 + form.resetFields();
  143 + onCancel();
  144 + }}
  145 + onCancel={() => onCancel()}
  146 + onOk={form.submit}
  147 + width={1000}
  148 + >
  149 + <Spin spinning={loading}>
  150 + <Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} onFinish={handSubmit}>
  151 + <Form.Item name="commissionParams" label="计分指标" rules={[{ required: true, message: "计分指标" }]}>
  152 + <Select
  153 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  154 + labelInValue
  155 + disabled={!!comItem.code}
  156 + onChange={(value, Option: any) => {
  157 + setTargetType(Option.targetType);
  158 + setItemId(Option.key);
  159 + setId(Option.key);
  160 + setIndicatorName(Option.children);
  161 + setCommissionParamAlias(Option.name);
  162 + setCodeType(Option.codeType);
  163 + setDataType(Option.dataType);
  164 + }}
  165 + showSearch
  166 + optionFilterProp="children"
  167 + >
  168 + {newIndicators.map((item) => (
  169 + <Option
  170 + value={item.code}
  171 + key={item.id}
  172 + targetType={item.targetType}
  173 + dataType={item.dataType}
  174 + codeType={item.codeType}
  175 + name={item.name}
  176 + >
  177 + {item.name}
  178 + {item.codeType == 2 ? "*" : ""}
  179 + </Option>
  180 + ))}
  181 + </Select>
  182 + </Form.Item>
  183 + <div style={{ display: "flex", justifyContent: "flex-start" }}>
  184 + <Form.Item
  185 + name="proportion"
  186 + label="占比"
  187 + rules={[
  188 + { pattern: percent, message: "请输入大于0小于等于100的数(最多保留两位小数)" },
  189 + { required: true, message: "请输入占比数" },
  190 + ]}
  191 + style={{ width: "100%" }}
  192 + >
  193 + <InputNumber style={{ width: "100%" }} addonAfter="%" />
  194 + </Form.Item>
  195 + </div>
  196 + <Form.Item name="cap" label="是否封顶" rules={[{ required: true, message: "请选择" }]}>
  197 + <Radio.Group>
  198 + <Radio value>是</Radio>
  199 + <Radio value={false}>否</Radio>
  200 + </Radio.Group>
  201 + </Form.Item>
  202 + {(targetType === TargetTypeEnum["百分比"] ||
  203 + targetType === TargetTypeEnum["金额"] ||
  204 + targetType === TargetTypeEnum["数量"]) && (
  205 + <div style={{ marginLeft: 65 }}>
  206 + <Button type="link" onClick={() => setIsTarget(true)}>
  207 + 考核目标值设置(可选项)
  208 + </Button>
  209 + {isTarget && (
  210 + <Button type="link" onClick={() => setIsTarget(false)}>
  211 + 删除该项考核目标设置
  212 + </Button>
  213 + )}
  214 + </div>
  215 + )}
  216 + {isTarget && (
  217 + <>
  218 + <Form.Item label="考核目标名称" name="targetName">
  219 + <Select disabled defaultValue={indicatorName} />
  220 + </Form.Item>
  221 + <Form.Item
  222 + label="考核目标计算类型"
  223 + name="targetCalcType"
  224 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  225 + >
  226 + <Radio.Group>
  227 + <Radio value={1}>考核目标值计算 </Radio>
  228 + <Radio value={2}>最低要求计算</Radio>
  229 + </Radio.Group>
  230 + </Form.Item>
  231 + <Form.Item
  232 + label="考核目标值"
  233 + name="targetValue"
  234 + rules={[
  235 + { required: true, message: "请输入考核目标值" },
  236 + {
  237 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  238 + message:
  239 + targetType === TargetTypeEnum["百分比"]
  240 + ? "请输入大于0小于等于100的数(保留两位小数)"
  241 + : "请输入大于0的数(保留两位小数)",
  242 + },
  243 + ]}
  244 + >
  245 + <InputNumber
  246 + placeholder="请输入考核目标值"
  247 + style={{ width: "100%" }}
  248 + addonAfter={
  249 + targetType === TargetTypeEnum["百分比"]
  250 + ? "%"
  251 + : targetType === TargetTypeEnum["金额"]
  252 + ? "元"
  253 + : "数量"
  254 + }
  255 + />
  256 + </Form.Item>
  257 + </>
  258 + )}
  259 + </Form>
  260 + </Spin>
  261 + </Modal>
  262 + );
  263 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddCondModal.tsx 0 → 100755
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  5 +import { saveRewardsListApi } from "../RewardsList/api";
  6 +import { useStore } from "../index";
  7 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "../api";
  8 +import _ from "lodash";
  9 +import useInitail from "@/hooks/useInitail";
  10 +import CondLaddersTable from "./CondLaddersTable";
  11 +import CommissionParams from "@/pages/performance/KpiGroupSetting/EditComfirm/components/CommissionParams";
  12 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  13 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  14 +// import { transformDTOCond } from "../../entity";
  15 +
  16 +const Option = Select.Option;
  17 +interface Props {
  18 + addComVisible: boolean;
  19 + onCancel: Function;
  20 + postId?: number;
  21 + shopIds?: string;
  22 + onOk: (vales: any) => void;
  23 + comItem: Commission;
  24 + setItemId: Function;
  25 + scopeType: number;
  26 +}
  27 +type Commission = EvaGroupSetteing.CommissionParams;
  28 +export default function AddCondModal(props: Props) {
  29 + const { selectedIndicatorsConds, setSelectedIndicatorsConds, setPreconditionAlias } = useStore();
  30 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  31 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  32 + const [form] = Form.useForm();
  33 + const [isTarget, setIsTarget] = useState(false);
  34 + // console.log(form);
  35 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  36 + const [delay, setDelay] = useState(true);
  37 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  38 + const [targetType, setTargetType] = useState<number>();
  39 + // 保存选中指标是否考评类型
  40 + const [codeType, setCodeType] = useState<number>();
  41 + const [dataType, setDataType] = useState<number>();
  42 + // 保存过滤后指标列表
  43 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  44 + const [name, setIndicatorName] = useState("");
  45 + const [id, setId] = useState(0);
  46 + const {
  47 + data: indicatorsList,
  48 + setParams,
  49 + loading,
  50 + } = useInitail(
  51 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  52 + [],
  53 + scopeType == 1 ? { postId } : {},
  54 + delay
  55 + );
  56 + useEffect(() => {
  57 + setParams(scopeType == 1 ? { postId } : {}, true);
  58 + setDelay(false);
  59 + setTargetType(1);
  60 + }, [addComVisible]);
  61 + // 修改
  62 +
  63 + useEffect(() => {
  64 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  65 + const res = indicatorsList.filter((item) => !selectedIndicatorsConds.find((y) => y === item.code));
  66 + setNewIndicators([...res]);
  67 + }
  68 + if (addComVisible && comItem.code) {
  69 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  70 + console.log("indTar", indTar);
  71 + console.log("comItem.targetType", comItem.targetType);
  72 + setTargetType(indTar);
  73 + setIndicatorName(comItem.name);
  74 + setDataType(comItem.dataType);
  75 + setCodeType(comItem.codeType);
  76 + form.setFieldsValue({
  77 + ...comItem,
  78 + conds: {
  79 + value: comItem.code,
  80 + label: comItem.name,
  81 + },
  82 + });
  83 + }
  84 + if (comItem.targetValue && comItem.targetCalcType) {
  85 + setIsTarget(true);
  86 + }
  87 + }, [indicatorsList]);
  88 + useEffect(() => {
  89 + if (targetType === TargetTypeEnum["无"]) {
  90 + setIsTarget(false);
  91 + }
  92 + }, [targetType]);
  93 + useEffect(() => {
  94 + setIsTarget(false);
  95 + }, [id]);
  96 + // 校验表单数据
  97 + function transformDTO(formData: any) {
  98 + console.log("前置条件", formData);
  99 + let detail: any = {};
  100 + _.each(formData, (value: any, key: string) => {
  101 + switch (key) {
  102 + case "conds":
  103 + const _options = value || {};
  104 + detail.name = _options.label[0];
  105 + detail.code = _options.value;
  106 + break;
  107 + default:
  108 + detail[key] = value;
  109 + break;
  110 + }
  111 + });
  112 + return detail;
  113 + }
  114 + function handSubmit(fieldsValue: any) {
  115 + const pa: any = transformDTO(fieldsValue);
  116 + pa.targetType = targetType;
  117 + pa.codeType = codeType;
  118 + pa.dataType = dataType;
  119 + console.log("前置条件", pa);
  120 + const newItemId = pa.code;
  121 + // 编辑时,不需要push id
  122 + if (!comItem.code) {
  123 + const tmpIds = [...selectedIndicatorsConds];
  124 + tmpIds.push(newItemId);
  125 + setSelectedIndicatorsConds([...tmpIds]);
  126 + } else {
  127 + pa.code = comItem.code;
  128 + pa.name = comItem.name;
  129 + }
  130 + onOk(pa);
  131 + onCancel && onCancel();
  132 + }
  133 + return (
  134 + <Modal
  135 + visible={addComVisible}
  136 + title={`${comItem.code ? "编辑" : "新增"}前置条件`}
  137 + maskClosable={false}
  138 + afterClose={() => {
  139 + form.resetFields();
  140 + onCancel();
  141 + }}
  142 + onCancel={() => onCancel()}
  143 + onOk={form.submit}
  144 + width={1000}
  145 + >
  146 + <Spin spinning={loading}>
  147 + <Form
  148 + form={form}
  149 + labelCol={{ span: 6 }}
  150 + wrapperCol={{ span: 18 }}
  151 + onFinish={handSubmit}
  152 + initialValues={{
  153 + ladders: [{ lower: 0, scorePercent: 0, key: 0 }],
  154 + }}
  155 + >
  156 + <Form.Item name="conds" label="前置条件配置" rules={[{ required: true, message: "前置条件配置" }]}>
  157 + <Select
  158 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  159 + labelInValue
  160 + disabled={!!comItem.code}
  161 + onChange={(value, Option: any) => {
  162 + setTargetType(Option.targetType);
  163 + // 最外层id
  164 + setItemId(Option.key);
  165 + // 列表id
  166 + setId(Option.key);
  167 + setIndicatorName(Option.children);
  168 + setPreconditionAlias(Option.name);
  169 + setCodeType(Option.codeType);
  170 + setDataType(Option.dataType);
  171 + }}
  172 + showSearch
  173 + optionFilterProp="children"
  174 + >
  175 + {newIndicators.map((item) => (
  176 + <Option
  177 + value={item.code}
  178 + key={item.id}
  179 + targetType={item.targetType}
  180 + codeType={item.codeType}
  181 + dataType={item.dataType}
  182 + name={item.name}
  183 + >
  184 + {item.name}
  185 + {item.codeType == 2 ? "*" : ""}
  186 + </Option>
  187 + ))}
  188 + </Select>
  189 + </Form.Item>
  190 + {(targetType === TargetTypeEnum["百分比"] ||
  191 + targetType === TargetTypeEnum["金额"] ||
  192 + targetType === TargetTypeEnum["数量"]) && (
  193 + <div style={{ marginLeft: 65 }}>
  194 + <Button type="link" onClick={() => setIsTarget(true)}>
  195 + 考核目标值设置(可选项)
  196 + </Button>
  197 + {isTarget && (
  198 + <Button type="link" onClick={() => setIsTarget(false)}>
  199 + 删除该项考核目标设置
  200 + </Button>
  201 + )}
  202 + </div>
  203 + )}
  204 + {isTarget && (
  205 + <>
  206 + <Form.Item label="考核目标名称" name="targetName">
  207 + <Select disabled defaultValue={name} />
  208 + </Form.Item>
  209 + <Form.Item
  210 + label="考核目标计算类型"
  211 + name="targetCalcType"
  212 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  213 + >
  214 + <Radio.Group>
  215 + <Radio value={1}>考核目标值计算 </Radio>
  216 + <Radio value={2}>最低要求计算</Radio>
  217 + </Radio.Group>
  218 + </Form.Item>
  219 + <Form.Item
  220 + label="考核目标值"
  221 + name="targetValue"
  222 + rules={[
  223 + { required: true, message: "请输入考核目标值" },
  224 + {
  225 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  226 + message:
  227 + targetType === TargetTypeEnum["百分比"]
  228 + ? "请输入大于0小于等于100的数(保留两位小数)"
  229 + : "请输入大于0的数(保留两位小数)",
  230 + },
  231 + ]}
  232 + >
  233 + <InputNumber
  234 + placeholder="请输入考核目标值"
  235 + style={{ width: "100%" }}
  236 + addonAfter={
  237 + targetType === TargetTypeEnum["百分比"]
  238 + ? "%"
  239 + : targetType === TargetTypeEnum["金额"]
  240 + ? "元"
  241 + : "数量"
  242 + }
  243 + />
  244 + </Form.Item>
  245 + </>
  246 + )}
  247 + <Form.Item name="ladders" label="前置条件阶梯" rules={[{ required: true, message: "前置条件阶梯" }]}>
  248 + <CondLaddersTable visible={addComVisible} />
  249 + </Form.Item>
  250 + </Form>
  251 + </Spin>
  252 + </Modal>
  253 + );
  254 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddCondModalSal.tsx 0 → 100755
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  5 +import { saveRewardsListApi } from "../RewardsList/api";
  6 +import { useStore } from "../index";
  7 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "../api";
  8 +import _ from "lodash";
  9 +import useInitail from "@/hooks/useInitail";
  10 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  11 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  12 +// import { transformDTOCond } from "../../entity";
  13 +
  14 +const Option = Select.Option;
  15 +interface Props {
  16 + addComVisible: boolean;
  17 + onCancel: Function;
  18 + postId?: number;
  19 + shopIds?: string;
  20 + onOk: (vales: any) => void;
  21 + comItem: Commission;
  22 + setItemId: Function;
  23 + scopeType: number;
  24 +}
  25 +type Commission = EvaGroupSetteing.CommissionParams;
  26 +export default function AddCondModal(props: Props) {
  27 + const { selectedIndicatorsCondsSal, setSelectedIndicatorsCondsSal, setPreconditionAliasSal } = useStore();
  28 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  29 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  30 + const [form] = Form.useForm();
  31 + const [isTarget, setIsTarget] = useState(false);
  32 + // console.log(form);
  33 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  34 + const [delay, setDelay] = useState(true);
  35 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  36 + const [targetType, setTargetType] = useState<number>();
  37 + // 保存选中指标是否考评类型
  38 + const [codeType, setCodeType] = useState<number>();
  39 + const [dataType, setDataType] = useState<number>();
  40 + // 保存过滤后指标列表
  41 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  42 + const [name, setIndicatorName] = useState("");
  43 + const [id, setId] = useState(0);
  44 + const {
  45 + data: indicatorsList,
  46 + setParams,
  47 + loading,
  48 + } = useInitail(
  49 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  50 + [],
  51 + scopeType == 1 ? { postId } : {},
  52 + delay
  53 + );
  54 + useEffect(() => {
  55 + setParams(scopeType == 1 ? { postId } : {}, true);
  56 + setDelay(false);
  57 + setTargetType(1);
  58 + }, [addComVisible]);
  59 + // 修改
  60 +
  61 + useEffect(() => {
  62 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  63 + const res = indicatorsList.filter((item) => !selectedIndicatorsCondsSal.find((y) => y === item.code));
  64 + setNewIndicators([...res]);
  65 + }
  66 + if (addComVisible && comItem.code) {
  67 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  68 + console.log("indTar", indTar);
  69 + console.log("comItem.targetType", comItem.targetType);
  70 + setTargetType(indTar);
  71 + setIndicatorName(comItem.name);
  72 + setDataType(comItem.dataType);
  73 + setCodeType(comItem.codeType);
  74 + form.setFieldsValue({
  75 + ...comItem,
  76 + conds: {
  77 + value: comItem.code,
  78 + label: comItem.name,
  79 + },
  80 + });
  81 + }
  82 + if (comItem.targetValue && comItem.targetCalcType) {
  83 + setIsTarget(true);
  84 + }
  85 + }, [indicatorsList]);
  86 + useEffect(() => {
  87 + if (targetType === TargetTypeEnum["无"]) {
  88 + setIsTarget(false);
  89 + }
  90 + }, [targetType]);
  91 + useEffect(() => {
  92 + setIsTarget(false);
  93 + }, [id]);
  94 + // 校验表单数据
  95 + function transformDTO(formData: any) {
  96 + console.log("前置条件", formData);
  97 + let detail: any = {};
  98 + _.each(formData, (value: any, key: string) => {
  99 + switch (key) {
  100 + case "conds":
  101 + const _options = value || {};
  102 + detail.name = _options.label[0];
  103 + detail.code = _options.value;
  104 + break;
  105 + default:
  106 + detail[key] = value;
  107 + break;
  108 + }
  109 + });
  110 + return detail;
  111 + }
  112 + function handSubmit(fieldsValue: any) {
  113 + const pa: any = transformDTO(fieldsValue);
  114 + pa.targetType = targetType;
  115 + pa.codeType = codeType;
  116 + pa.dataType = dataType;
  117 + console.log("前置条件", pa);
  118 + const newItemId = pa.code;
  119 + // 编辑时,不需要push id
  120 + if (!comItem.code) {
  121 + const tmpIds = [...selectedIndicatorsCondsSal];
  122 + tmpIds.push(newItemId);
  123 + setSelectedIndicatorsCondsSal([...tmpIds]);
  124 + } else {
  125 + pa.code = comItem.code;
  126 + pa.name = comItem.name;
  127 + }
  128 + onOk(pa);
  129 + onCancel && onCancel();
  130 + }
  131 + return (
  132 + <Modal
  133 + visible={addComVisible}
  134 + title={`${comItem.code ? "编辑" : "新增"}前置条件`}
  135 + maskClosable={false}
  136 + afterClose={() => {
  137 + form.resetFields();
  138 + onCancel();
  139 + }}
  140 + onCancel={() => onCancel()}
  141 + onOk={form.submit}
  142 + width={1000}
  143 + >
  144 + <Spin spinning={loading}>
  145 + <Form
  146 + form={form}
  147 + labelCol={{ span: 6 }}
  148 + wrapperCol={{ span: 18 }}
  149 + onFinish={handSubmit}
  150 + initialValues={{
  151 + ladders: [{ lower: 0, scorePercent: 0, key: 0 }],
  152 + }}
  153 + >
  154 + <Form.Item name="conds" label="前置条件配置" rules={[{ required: true, message: "前置条件配置" }]}>
  155 + <Select
  156 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  157 + labelInValue
  158 + disabled={!!comItem.code}
  159 + onChange={(value, Option: any) => {
  160 + setTargetType(Option.targetType);
  161 + // 最外层id
  162 + setItemId(Option.key);
  163 + // 列表id
  164 + setId(Option.key);
  165 + setIndicatorName(Option.children);
  166 + setPreconditionAliasSal(Option.name);
  167 + setCodeType(Option.codeType);
  168 + setDataType(Option.dataType);
  169 + }}
  170 + showSearch
  171 + optionFilterProp="children"
  172 + >
  173 + {newIndicators.map((item) => (
  174 + <Option
  175 + value={item.code}
  176 + key={item.id}
  177 + targetType={item.targetType}
  178 + codeType={item.codeType}
  179 + dataType={item.dataType}
  180 + name={item.name}
  181 + >
  182 + {item.name}
  183 + {item.codeType == 2 ? "*" : ""}
  184 + </Option>
  185 + ))}
  186 + </Select>
  187 + </Form.Item>
  188 + <Form.Item
  189 + label="前置条件值类型"
  190 + name="condType"
  191 + rules={[{ required: true, message: "请选择前置条件值类型" }]}
  192 + >
  193 + <Radio.Group>
  194 + <Radio value={1}>满足目标 </Radio>
  195 + <Radio value={2}>满足排名率</Radio>
  196 + </Radio.Group>
  197 + </Form.Item>
  198 + <Form.Item
  199 + noStyle
  200 + shouldUpdate={(prevValues, currentValues) => prevValues.condType !== currentValues.condType}
  201 + >
  202 + {({ getFieldValue }) => {
  203 + const condType = getFieldValue("condType");
  204 + return (
  205 + <Form.Item name="condValue" label="条件值" rules={[{ required: true, message: "请输入条件值" }]}>
  206 + <InputNumber
  207 + placeholder="请输入条件值"
  208 + style={{ width: "100%" }}
  209 + addonAfter={
  210 + !comItem.code
  211 + ? isTarget
  212 + ? "%"
  213 + : condType == 2
  214 + ? "%"
  215 + : dataType == 1
  216 + ? "台"
  217 + : dataType == 3
  218 + ? "元"
  219 + : "%"
  220 + : comItem.targetValue
  221 + ? "%"
  222 + : comItem.condType == 2
  223 + ? "%"
  224 + : comItem.dataType == 1
  225 + ? "台"
  226 + : comItem.dataType == 3
  227 + ? "元"
  228 + : "%"
  229 + }
  230 + />
  231 + </Form.Item>
  232 + );
  233 + }}
  234 + </Form.Item>
  235 + {(targetType === TargetTypeEnum["百分比"] ||
  236 + targetType === TargetTypeEnum["金额"] ||
  237 + targetType === TargetTypeEnum["数量"]) && (
  238 + <div style={{ marginLeft: 65 }}>
  239 + <Button type="link" onClick={() => setIsTarget(true)}>
  240 + 考核目标值设置(可选项)
  241 + </Button>
  242 + {isTarget && (
  243 + <Button type="link" onClick={() => setIsTarget(false)}>
  244 + 删除该项考核目标设置
  245 + </Button>
  246 + )}
  247 + </div>
  248 + )}
  249 + {isTarget && (
  250 + <>
  251 + <Form.Item label="考核目标名称" name="targetName">
  252 + <Select disabled defaultValue={name} />
  253 + </Form.Item>
  254 + <Form.Item
  255 + label="考核目标计算类型"
  256 + name="targetCalcType"
  257 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  258 + >
  259 + <Radio.Group>
  260 + <Radio value={1}>考核目标值计算 </Radio>
  261 + <Radio value={2}>最低要求计算</Radio>
  262 + </Radio.Group>
  263 + </Form.Item>
  264 + <Form.Item
  265 + label="考核目标值"
  266 + name="targetValue"
  267 + rules={[
  268 + { required: true, message: "请输入考核目标值" },
  269 + {
  270 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  271 + message:
  272 + targetType === TargetTypeEnum["百分比"]
  273 + ? "请输入大于0小于等于100的数(保留两位小数)"
  274 + : "请输入大于0的数(保留两位小数)",
  275 + },
  276 + ]}
  277 + >
  278 + <InputNumber
  279 + placeholder="请输入考核目标值"
  280 + style={{ width: "100%" }}
  281 + addonAfter={
  282 + targetType === TargetTypeEnum["百分比"]
  283 + ? "%"
  284 + : targetType === TargetTypeEnum["金额"]
  285 + ? "元"
  286 + : "数量"
  287 + }
  288 + />
  289 + </Form.Item>
  290 + </>
  291 + )}
  292 + </Form>
  293 + </Spin>
  294 + </Modal>
  295 + );
  296 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddEvaGroupModal.tsx 0 → 100644
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button, DatePicker } from "antd";
  5 +import { saveRewardsListApi } from "../RewardsList/api";
  6 +import { useStore } from "../index";
  7 +import _ from "lodash";
  8 +import useInitail from "@/hooks/useInitail";
  9 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  10 +import * as api from "@/pages/performance/KpiGroupSetting/EditComfirm/api";
  11 +import ShopSelectNew from "@/components/ShopSelectNew";
  12 +import PersonModal from "@/pages/performance/KpiGroupSetting/components/PersonModal";
  13 +import { transformDTO } from "../entity";
  14 +import IndivatorsTable from "./IndivatorsTable";
  15 +import RewardsTableSal from "./RewardsTableSal";
  16 +import moment from "moment";
  17 +import { getManagerRoleListApi } from "@/common/api";
  18 +
  19 +const Option = Select.Option;
  20 +const { RangePicker } = DatePicker;
  21 +interface Props {
  22 + visible: boolean;
  23 + onCancel: Function;
  24 + onOk: (vales: any) => void;
  25 + evaItem: EvaGroupSetteing.EvalGroups;
  26 + scopeType: number;
  27 + setScopeType: Function;
  28 +}
  29 +
  30 +export default function AddIndicatorsModal(props: Props) {
  31 + const { postList, readOnly } = useStore();
  32 + const [roleList, setRoleList] = useState<any>([]);
  33 +
  34 + const { visible, onCancel, onOk, evaItem, scopeType, setScopeType } = props;
  35 +
  36 + const [form] = Form.useForm();
  37 + // 选择岗位id
  38 + const [postId, setPostId] = useState<number>();
  39 +
  40 + // 门店列表
  41 + const [shopList, setShopList] = useState<EvaGroupSetteing.ShopList[]>([]);
  42 +
  43 + // 人员查看模块
  44 + const [personModal, setPersonModal] = useState<EvaGroupSetteing.Person>({
  45 + visible: false,
  46 + postId: undefined,
  47 + shopIds: "",
  48 + });
  49 +
  50 + // visible变化时(修改等)
  51 + useEffect(() => {
  52 + getRoleList();
  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 + }
  61 + if (evaItem.shop && evaItem.post) {
  62 + const shopIds = evaItem.shop.map((item) => item.value);
  63 + const postId = evaItem.post.value;
  64 + setPersonModal({
  65 + postId,
  66 + shopIds: shopIds.join(","),
  67 + visible: false,
  68 + });
  69 + }
  70 + console.log("evaItem", evaItem);
  71 + form.setFieldsValue({
  72 + ...evaItem,
  73 + });
  74 + }
  75 + }, [visible]);
  76 +
  77 + // 查询门店
  78 + useEffect(() => {
  79 + if (evaItem.post) {
  80 + getDealerList(evaItem.post.value);
  81 + }
  82 + }, [evaItem]);
  83 + console.log("shopList", shopList);
  84 +
  85 + // 查询管理角色
  86 + function getRoleList() {
  87 + getManagerRoleListApi()
  88 + .then((res) => {
  89 + setRoleList(res.data || []);
  90 + })
  91 + .catch((e) => {
  92 + message.error(e.message);
  93 + });
  94 + }
  95 +
  96 + // 根据岗位查门店
  97 + function getDealerList(postId: number) {
  98 + api
  99 + .queryShopByPost(postId)
  100 + .then((res) => {
  101 + setShopList(res.data || []);
  102 + })
  103 + .catch((e) => {
  104 + message.error(e.message);
  105 + });
  106 + }
  107 + // 人员查看
  108 + const personView = () => {
  109 + if (!personModal.postId) {
  110 + message.error("请选择岗位");
  111 + return;
  112 + }
  113 + if (!personModal.shopIds) {
  114 + message.error("请选择门店");
  115 + return;
  116 + }
  117 + setPersonModal({ ...personModal, visible: true });
  118 + };
  119 +
  120 + function handSubmit(fieldsValue: any) {
  121 + const res = transformDTO(fieldsValue);
  122 + let pa = { ...res, force: true };
  123 + onOk(pa);
  124 + console.log("考评组", pa);
  125 + onCancel && onCancel();
  126 + }
  127 +
  128 + return (
  129 + <Modal
  130 + title={`${evaItem.name ? "编辑" : "新增"}考评组`}
  131 + visible={visible}
  132 + maskClosable={false}
  133 + afterClose={() => {
  134 + form.resetFields();
  135 + onCancel();
  136 + }}
  137 + onCancel={() => onCancel()}
  138 + onOk={form.submit}
  139 + width={1400}
  140 + >
  141 + <Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 16 }} onFinish={handSubmit}>
  142 + <Form.Item name="name" label="考评组名称" rules={[{ required: true, message: "请输入名称" }]}>
  143 + <Input placeholder="请输入考评组名称" disabled={readOnly} />
  144 + </Form.Item>
  145 + <Form.Item label="考评时间" name="time" rules={[{ required: true, message: "请选择考评时间" }]}>
  146 + <RangePicker
  147 + style={{ width: 900 }}
  148 + disabled={readOnly}
  149 + disabledDate={(current) => current && current < moment().add(-1, "days").endOf("day")}
  150 + />
  151 + </Form.Item>
  152 + <Form.Item label="考评范围" name="scopeType" rules={[{ required: true, message: "请选择考评范围" }]}>
  153 + <Radio.Group disabled={readOnly} onChange={(e) => setScopeType(e.target.value)}>
  154 + <Radio value={1}>人员考评</Radio>
  155 + <Radio value={2}>门店考评</Radio>
  156 + </Radio.Group>
  157 + </Form.Item>
  158 + <Form.Item
  159 + noStyle
  160 + shouldUpdate={(prevValues, currentValues) => prevValues.scopeType !== currentValues.scopeType}
  161 + >
  162 + {({ getFieldValue }) =>
  163 + getFieldValue("scopeType") === 1 ? (
  164 + <Form.Item name="post" label="岗位" rules={[{ required: true, message: "请选择岗位" }]}>
  165 + <Select
  166 + labelInValue
  167 + placeholder="请选择岗位"
  168 + allowClear
  169 + disabled={readOnly}
  170 + showSearch
  171 + optionFilterProp="children"
  172 + onChange={(post: { label: string; value: number; key: number }) => {
  173 + setPersonModal({
  174 + postId: post.value,
  175 + visible: false,
  176 + shopIds: "",
  177 + });
  178 + setPostId(post.value);
  179 + form.setFieldsValue({ shop: [] });
  180 + // 根据岗位查门店
  181 + if (post) {
  182 + getDealerList(post.value);
  183 + }
  184 + }}
  185 + >
  186 + {postList.map((item) => (
  187 + <Option value={item.id}>{item.postName}</Option>
  188 + ))}
  189 + </Select>
  190 + </Form.Item>
  191 + ) : null
  192 + }
  193 + </Form.Item>
  194 +
  195 + <Form.Item
  196 + noStyle
  197 + shouldUpdate={(prevValues, currentValues) => prevValues.scopeType !== currentValues.scopeType}
  198 + >
  199 + {({ getFieldValue }) => {
  200 + const scopeType = getFieldValue("scopeType");
  201 + return (
  202 + <Form.Item name="shop" label="门店" rules={[{ required: true, message: "请选择门店" }]}>
  203 + <ShopSelectNew
  204 + multiple
  205 + disabled={readOnly}
  206 + shopIds={scopeType === 1 ? shopList.map((item) => item.shopId) : []}
  207 + type={scopeType === 1 ? 2 : 1}
  208 + onChange={(
  209 + shops: {
  210 + key: number;
  211 + label: string;
  212 + value: number;
  213 + }[]
  214 + ) => {
  215 + const shopIds = shops.map((item) => item.value).join(",");
  216 + setPersonModal({ ...personModal, shopIds });
  217 + }}
  218 + />
  219 + </Form.Item>
  220 + );
  221 + }}
  222 + </Form.Item>
  223 + <Form.Item
  224 + noStyle
  225 + shouldUpdate={(prevValues, currentValues) => prevValues.scopeType !== currentValues.scopeType}
  226 + >
  227 + {({ getFieldValue }) =>
  228 + getFieldValue("scopeType") === 1 ? (
  229 + <div style={{ marginBottom: 20, marginLeft: 250 }}>
  230 + <a onClick={() => personView()}>{`人员查看 >`}</a>
  231 + </div>
  232 + ) : null
  233 + }
  234 + </Form.Item>
  235 + <Form.Item
  236 + noStyle
  237 + shouldUpdate={(prevValues, currentValues) => prevValues.scopeType !== currentValues.scopeType}
  238 + >
  239 + {({ getFieldValue }) =>
  240 + getFieldValue("scopeType") === 2 ? (
  241 + <Form.Item name="role" label="门店奖惩分配" rules={[{ required: true, message: "请选择管理角色" }]}>
  242 + <Select
  243 + labelInValue
  244 + placeholder="请选择管理角色"
  245 + allowClear
  246 + disabled={readOnly}
  247 + showSearch
  248 + optionFilterProp="children"
  249 + >
  250 + {roleList.map((item) => (
  251 + <Option value={item.roleCode}>{item.roleName}</Option>
  252 + ))}
  253 + </Select>
  254 + </Form.Item>
  255 + ) : null
  256 + }
  257 + </Form.Item>
  258 +
  259 + <Form.Item noStyle shouldUpdate={(prevValues, currentValues) => prevValues.rewards !== currentValues.rewards}>
  260 + {({ getFieldValue }) => {
  261 + const rewards = getFieldValue("rewards");
  262 + return (
  263 + <Form.Item name="indicators" label="考评指标" rules={[{ required: !(rewards && rewards.length > 0) }]}>
  264 + <IndivatorsTable postId={postId} personModal={personModal} scopeType={scopeType} />
  265 + </Form.Item>
  266 + );
  267 + }}
  268 + </Form.Item>
  269 + <Form.Item
  270 + noStyle
  271 + shouldUpdate={(prevValues, currentValues) => prevValues.indicators !== currentValues.indicators}
  272 + >
  273 + {({ getFieldValue }) => {
  274 + const indicators = getFieldValue("indicators");
  275 + return (
  276 + <Form.Item name="rewards" label="考评奖惩" rules={[{ required: !(indicators && indicators.length > 0) }]}>
  277 + <RewardsTableSal postId={postId} personModal={personModal} scopeType={scopeType} />
  278 + </Form.Item>
  279 + );
  280 + }}
  281 + </Form.Item>
  282 + </Form>
  283 +
  284 + <PersonModal item={personModal} setPersonModal={setPersonModal} />
  285 + </Modal>
  286 + );
  287 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddIndicatorsModal.tsx 0 → 100755
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  5 +import { saveRewardsListApi } from "../RewardsList/api";
  6 +import { useStore } from "../index";
  7 +import { queryPostIndicatorApi } from "@/pages/performance/KpiGroupSetting/EditComfirm/api";
  8 +import _ from "lodash";
  9 +import useInitail from "@/hooks/useInitail";
  10 +import LadderTable from "@/pages/performance/EvaGroupSetting/EditComfirm/components/LadderTable";
  11 +import CommissionParams from "@/pages/performance/EvaGroupSetting/EditComfirm/components/CommissionParams";
  12 +import LadderParams from "@/pages/performance/EvaGroupSetting/EditComfirm/components/LadderParams";
  13 +import Conds from "@/pages/performance/EvaGroupSetting/EditComfirm/components/Conds";
  14 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  15 +
  16 +const Option = Select.Option;
  17 +interface Props {
  18 + visible: boolean;
  19 + onCancel: Function;
  20 + postId?: number;
  21 + shopIds?: string;
  22 + onOk: (vales: any) => void;
  23 + currentItem: EvaGroupSetteing.Indicators;
  24 + comItem: EvaGroupSetteing.CommissionParams;
  25 + scopeType: number;
  26 +}
  27 +
  28 +export default function AddIndicatorsModal(props: Props) {
  29 + const [form] = Form.useForm();
  30 + // console.log(form);
  31 + const { paramAlias, setParamAlias, preconditionAlias, setPreconditionAlias } = useStore();
  32 +
  33 + // 是否为百分比
  34 + const { visible, onCancel, postId, shopIds, onOk, currentItem, comItem, scopeType } = props;
  35 + const [isPercent, setIsPercent] = useState<number>(0);
  36 + const [delay, setDelay] = useState(true);
  37 + // 显示前置条件
  38 + const [condsVisible, setCondsVisible] = useState(false);
  39 + // 判断占比相加是否为100
  40 + const [isHundred, setIsHundred] = useState(false);
  41 + // 保存过滤后指标列表
  42 + // const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  43 + const [id, setItemId] = useState<number>();
  44 +
  45 + // 修改
  46 + useEffect(() => {
  47 + if (visible && currentItem.name) {
  48 + setParamAlias(currentItem.paramAlias);
  49 + form.setFieldsValue({
  50 + ...currentItem,
  51 + });
  52 + }
  53 + if (currentItem.conds && currentItem.conds.length > 0) {
  54 + setPreconditionAlias(currentItem.preconditionAlias);
  55 + setCondsVisible(true);
  56 + } else {
  57 + setCondsVisible(false);
  58 + }
  59 + }, [visible]);
  60 +
  61 + // useEffect(() => {
  62 + // if (indicatorsList && indicatorsList.length > 0 && !currentItem.id) {
  63 + // const res = indicatorsList.filter((item) => !selectedIndicators.find((y) => Number(y) === item.id));
  64 + // setNewIndicators([...res]);
  65 + // }
  66 + // }, [indicatorsList]);
  67 + // 校验表单数据
  68 + function transformDTO(formData: any) {
  69 + console.log("InformData", formData);
  70 + let detail = {};
  71 + _.each(formData, (value: any, key: string) => {
  72 + switch (key) {
  73 + case "commissionParams":
  74 + const _options = value || {};
  75 + detail.indicatorId = _options.key;
  76 + detail.name = _options.label;
  77 + detail.code = _options.value;
  78 + break;
  79 + default:
  80 + detail[key] = value;
  81 + break;
  82 + }
  83 + });
  84 + return formData;
  85 + }
  86 + function handSubmit(fieldsValue: any) {
  87 + console.log(fieldsValue);
  88 + const pa: any = transformDTO(fieldsValue);
  89 + // pa.targetType = targetType;
  90 + // pa.id = id;
  91 + pa.paramAlias = paramAlias;
  92 + if (pa?.ladderParams && pa?.ladderParams.length > 0) {
  93 + if (isPercent == 0) {
  94 + pa.laddersType = currentItem.laddersType;
  95 + } else {
  96 + pa.laddersType = isPercent;
  97 + }
  98 + }
  99 + console.log("大", pa);
  100 + let hundred = 0;
  101 + if (pa?.commissionParams) {
  102 + hundred = pa?.commissionParams.reduce((data: number, item: EvaGroupSetteing.CommissionParams) => {
  103 + return data + item.proportion;
  104 + }, 0);
  105 + }
  106 + if (pa?.ladderParams) {
  107 + hundred = pa?.ladderParams.reduce((data: number, item: EvaGroupSetteing.CommissionParams) => {
  108 + return data + item.proportion;
  109 + }, 0);
  110 + }
  111 + //设置conds的sort
  112 + if (pa?.conds && pa?.conds.length > 0) {
  113 + pa?.conds.forEach((item: any, index: number) => {
  114 + Object.assign(item, { sort: index + 1 });
  115 + });
  116 + pa.preconditionAlias = preconditionAlias;
  117 + }
  118 + console.log("cond", pa?.conds);
  119 +
  120 + // 校验标准分不能大于绩效分值
  121 + const indicatorValue = pa.baseScore;
  122 + if (!!pa.ladders && pa.ladders.length > 0) {
  123 + const _indicatorLadders: any[] = pa.ladders;
  124 + const res = _indicatorLadders.every((x, index) => {
  125 + if (x.standardScore <= indicatorValue) {
  126 + return true;
  127 + }
  128 + message.error(`第${index + 1}组标准分不满足条件: 标准分不能大于绩效分值`, 3);
  129 + return false;
  130 + });
  131 + const _result = verifySteps(_indicatorLadders);
  132 + if (!(res && _result)) {
  133 + return;
  134 + }
  135 + }
  136 +
  137 + const newItemId = pa.id;
  138 + // 编辑时,不需要push id
  139 + // if (currentItem.id) {
  140 + // const tmpIds = [...selectedIndicators];
  141 + // tmpIds.push(newItemId);
  142 + // setSelectedIndicators([...tmpIds]);
  143 + // setSelectedIndicatorsConds([...tmpIds]);
  144 + // }
  145 + if (hundred === 100) {
  146 + setIsHundred(false);
  147 + onOk(pa);
  148 + console.log(pa);
  149 + onCancel && onCancel();
  150 + } else {
  151 + setIsHundred(true);
  152 + }
  153 + }
  154 +
  155 + // 校验阶梯越小,标准分越小
  156 + const verifySteps = (_indicatorLadders: any[]) => {
  157 + let res = true;
  158 + _indicatorLadders.forEach((item, index) => {
  159 + if (index > 0) {
  160 + const curScore = item.standardScore;
  161 + const lastScore = _indicatorLadders[index - 1].standardScore;
  162 + if (curScore < lastScore) {
  163 + message.error(`第${index + 1}组标准分不满足条件: 阶梯越小,标准分越小`, 3);
  164 + res = false;
  165 + }
  166 + }
  167 + });
  168 + return res;
  169 + };
  170 + return (
  171 + <Modal
  172 + title={`${currentItem.name ? "编辑" : "新增"}指标`}
  173 + visible={visible}
  174 + maskClosable={false}
  175 + afterClose={() => {
  176 + form.resetFields();
  177 + onCancel();
  178 + }}
  179 + onCancel={() => onCancel()}
  180 + onOk={form.submit}
  181 + width={1200}
  182 + >
  183 + <Form
  184 + form={form}
  185 + labelCol={{ span: 6 }}
  186 + wrapperCol={{ span: 18 }}
  187 + onFinish={handSubmit}
  188 + initialValues={{
  189 + ladders: [{ lower: 0, standardScore: 0, key: 0 }],
  190 + }}
  191 + >
  192 + <Form.Item name="name" label="指标名称" rules={[{ required: true, message: "请选择指标" }]}>
  193 + <Input placeholder="请输入指标名称" />
  194 + </Form.Item>
  195 +
  196 + <Form.Item label="绩效分值" name="baseScore" rules={[{ required: true, message: "请输入绩效分值" }]}>
  197 + <InputNumber placeholder="请输入" style={{ width: "100%" }} addonAfter="分" />
  198 + </Form.Item>
  199 + <Form.Item name="scoreWay" label="计算方式" rules={[{ required: true, message: "请选择计算方式" }]}>
  200 + <Select placeholder="选择计算方式">
  201 + <Option value={1} key={1}>
  202 + 台阶得分
  203 + </Option>
  204 + <Option value={2} key={2}>
  205 + 固定得分
  206 + </Option>
  207 + </Select>
  208 + </Form.Item>
  209 + <div style={{ marginLeft: 218, marginBottom: 20 }}>
  210 + <span>是否添加前置条件设置:</span>
  211 + <Radio.Group
  212 + onChange={(e) => {
  213 + setCondsVisible(e.target.value);
  214 + }}
  215 + value={condsVisible}
  216 + >
  217 + <Radio value>是</Radio>
  218 + <Radio value={false}>否</Radio>
  219 + </Radio.Group>
  220 + </div>
  221 + {condsVisible && (
  222 + <Form.Item name="conds" label="前置条件">
  223 + <Conds postId={postId} shopIds={shopIds} setItemId={setItemId} scopeType={scopeType} />
  224 + </Form.Item>
  225 + )}
  226 + <Form.Item noStyle shouldUpdate={(prevValues, currentValues) => prevValues.scoreWay !== currentValues.scoreWay}>
  227 + {({ getFieldValue }) =>
  228 + getFieldValue("scoreWay") === 1 ? (
  229 + <>
  230 + <Form.Item
  231 + name="ladderParams"
  232 + label="台阶得分"
  233 + rules={[{ required: true, message: "请增加台阶得分指标" }]}
  234 + >
  235 + <LadderParams
  236 + postId={postId}
  237 + shopIds={shopIds}
  238 + setItemId={setItemId}
  239 + isHundred={isHundred}
  240 + scopeType={scopeType}
  241 + />
  242 + </Form.Item>
  243 + <Form.Item name="ladders" label="台阶得分阶梯" rules={[{ required: true, message: "台阶得分阶梯" }]}>
  244 + <LadderTable visible isPercent={isPercent} laddersType={currentItem.laddersType} />
  245 + </Form.Item>
  246 + </>
  247 + ) : getFieldValue("scoreWay") === 2 ? (
  248 + <Form.Item
  249 + name="commissionParams"
  250 + label="固定得分"
  251 + rules={[{ required: true, message: "请增加固定得分指标" }]}
  252 + >
  253 + <CommissionParams
  254 + postId={postId}
  255 + shopIds={shopIds}
  256 + setItemId={setItemId}
  257 + isHundred={isHundred}
  258 + scopeType={scopeType}
  259 + />
  260 + </Form.Item>
  261 + ) : null
  262 + }
  263 + </Form.Item>
  264 + <Form.Item
  265 + noStyle
  266 + shouldUpdate={(prevValues, currentValues) => prevValues.ladderParams !== currentValues.ladderParams}
  267 + >
  268 + {({ getFieldValue }) => {
  269 + const ladderParams = getFieldValue("ladderParams");
  270 + if (ladderParams && ladderParams.length > 0) {
  271 + console.log("ladderParams", ladderParams);
  272 + if (ladderParams.length > 1) {
  273 + setIsPercent(2);
  274 + } else if (ladderParams[0].targetValue) {
  275 + setIsPercent(2);
  276 + } else if (ladderParams[0].dataType === 2) {
  277 + setIsPercent(2);
  278 + } else if (ladderParams[0].dataType === 1 || ladderParams[0].dataType === 3) {
  279 + setIsPercent(1);
  280 + }
  281 + }
  282 + return null;
  283 + }}
  284 + </Form.Item>
  285 + </Form>
  286 + </Modal>
  287 + );
  288 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddLadderParamsModal.tsx 0 → 100755
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  5 +import { useStore } from "../index";
  6 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "../api";
  7 +import _ from "lodash";
  8 +import useInitail from "@/hooks/useInitail";
  9 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  10 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  11 +
  12 +const Option = Select.Option;
  13 +interface Props {
  14 + addComVisible: boolean;
  15 + onCancel: Function;
  16 + postId?: number;
  17 + shopIds?: string;
  18 + onOk: (vales: any) => void;
  19 + comItem: Commission;
  20 + setItemId: Function;
  21 + scopeType: number;
  22 +}
  23 +type Commission = EvaGroupSetteing.CommissionParams;
  24 +export default function AddLadderParamsModal(props: Props) {
  25 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  26 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  27 + const [form] = Form.useForm();
  28 + const { selectedIndicatorsLadder, setSelectedIndicatorsLadder, setParamAlias } = useStore();
  29 +
  30 + const [isTarget, setIsTarget] = useState(false);
  31 + const [dataType, setDataType] = useState<number>(2);
  32 + // console.log(form);
  33 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  34 + const [delay, setDelay] = useState(true);
  35 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  36 + const [targetType, setTargetType] = useState<number>();
  37 + // 保存选中指标是否考评类型
  38 + const [codeType, setCodeType] = useState<number>();
  39 + // 保存过滤后指标列表
  40 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  41 + const [name, setIndicatorName] = useState("");
  42 + const [id, setId] = useState(0);
  43 + const {
  44 + data: indicatorsList,
  45 + setParams,
  46 + loading,
  47 + } = useInitail(
  48 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  49 + [],
  50 + scopeType == 1 ? { postId } : {},
  51 + delay
  52 + );
  53 + useEffect(() => {
  54 + setParams(scopeType == 1 ? { postId } : {}, true);
  55 + setDelay(false);
  56 + setTargetType(1);
  57 + }, [addComVisible]);
  58 + // 修改
  59 +
  60 + useEffect(() => {
  61 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  62 + const res = indicatorsList.filter((item) => !selectedIndicatorsLadder.find((y) => y === item.code));
  63 + setNewIndicators([...res]);
  64 + }
  65 + if (addComVisible && comItem.code) {
  66 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  67 + console.log("indTar", indTar);
  68 + console.log("comItem.targetType", comItem.targetType);
  69 + setTargetType(indTar);
  70 + setIndicatorName(comItem.name);
  71 + setCodeType(comItem.codeType);
  72 + form.setFieldsValue({
  73 + ...comItem,
  74 + ladderParams: {
  75 + value: comItem.code,
  76 + label: comItem.name,
  77 + dataType: comItem.dataType,
  78 + },
  79 + });
  80 + }
  81 + if (comItem.targetValue && comItem.targetCalcType) {
  82 + setIsTarget(true);
  83 + }
  84 + }, [indicatorsList]);
  85 + useEffect(() => {
  86 + if (targetType === TargetTypeEnum["无"]) {
  87 + setIsTarget(false);
  88 + }
  89 + }, [targetType]);
  90 + useEffect(() => {
  91 + setIsTarget(false);
  92 + }, [id]);
  93 + // 校验表单数据
  94 + function transformDTO(formData: any) {
  95 + let detail = {};
  96 + _.each(formData, (value: any, key: string) => {
  97 + switch (key) {
  98 + case "ladderParams":
  99 + const _options = value || {};
  100 + detail.name = _options.label[0];
  101 + detail.code = _options.value;
  102 + break;
  103 + default:
  104 + detail[key] = value;
  105 + break;
  106 + }
  107 + });
  108 + return detail;
  109 + }
  110 + function handSubmit(fieldsValue: any) {
  111 + const pa: any = transformDTO(fieldsValue);
  112 + pa.targetType = targetType;
  113 + pa.codeType = codeType;
  114 + if (comItem.dataType) {
  115 + pa.dataType = comItem.dataType;
  116 + }
  117 + if (!comItem.dataType) {
  118 + pa.dataType = dataType;
  119 + }
  120 + console.log("100pa", pa);
  121 + const newItemId = pa.code;
  122 + // 编辑时,不需要push id
  123 + if (!comItem.code) {
  124 + const tmpIds = [...selectedIndicatorsLadder];
  125 + tmpIds.push(newItemId);
  126 + setSelectedIndicatorsLadder([...tmpIds]);
  127 + } else {
  128 + pa.code = comItem.code;
  129 + pa.name = comItem.name;
  130 + }
  131 + onOk(pa);
  132 + onCancel && onCancel();
  133 + }
  134 + return (
  135 + <Modal
  136 + visible={addComVisible}
  137 + title={`${comItem.code ? "编辑" : "新增"}台阶得分指标`}
  138 + maskClosable={false}
  139 + afterClose={() => {
  140 + form.resetFields();
  141 + onCancel();
  142 + }}
  143 + onCancel={() => onCancel()}
  144 + onOk={form.submit}
  145 + width={1000}
  146 + >
  147 + <Spin spinning={loading}>
  148 + <Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} onFinish={handSubmit}>
  149 + <Form.Item name="ladderParams" label="计分指标" rules={[{ required: true, message: "计分指标" }]}>
  150 + <Select
  151 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  152 + labelInValue
  153 + disabled={!!comItem.code}
  154 + onChange={(value, Option: any) => {
  155 + setTargetType(Option.targetType);
  156 + setItemId(Option.key);
  157 + setId(Option.key);
  158 + setIndicatorName(Option.children);
  159 + setParamAlias(Option.name);
  160 + setDataType(Option.dataType);
  161 + setCodeType(Option.codeType);
  162 + }}
  163 + showSearch
  164 + optionFilterProp="children"
  165 + >
  166 + {newIndicators.map((item) => (
  167 + <Option
  168 + value={item.code}
  169 + key={item.code}
  170 + targetType={item.targetType}
  171 + dataType={item.dataType}
  172 + codeType={item.codeType}
  173 + name={item.name}
  174 + >
  175 + {item.name}
  176 + {item.codeType == 2 ? "*" : ""}
  177 + </Option>
  178 + ))}
  179 + </Select>
  180 + </Form.Item>
  181 + <div style={{ display: "flex", justifyContent: "flex-start" }}>
  182 + <Form.Item
  183 + name="proportion"
  184 + label="占比"
  185 + rules={[
  186 + { pattern: percent, message: "请输入大于0小于等于100的数(最多保留两位小数)" },
  187 + { required: true, message: "请输入占比数" },
  188 + ]}
  189 + style={{ width: "100%" }}
  190 + >
  191 + <InputNumber style={{ width: "100%" }} addonAfter="%" />
  192 + </Form.Item>
  193 + </div>
  194 + <Form.Item name="cap" label="是否封顶" rules={[{ required: true, message: "请选择" }]}>
  195 + <Radio.Group>
  196 + <Radio value>是</Radio>
  197 + <Radio value={false}>否</Radio>
  198 + </Radio.Group>
  199 + </Form.Item>
  200 + {(targetType === TargetTypeEnum["百分比"] ||
  201 + targetType === TargetTypeEnum["金额"] ||
  202 + targetType === TargetTypeEnum["数量"]) && (
  203 + <div style={{ marginLeft: 65 }}>
  204 + <Button type="link" onClick={() => setIsTarget(true)}>
  205 + 考核目标值设置(可选项)
  206 + </Button>
  207 + {isTarget && (
  208 + <Button type="link" onClick={() => setIsTarget(false)}>
  209 + 删除该项考核目标设置
  210 + </Button>
  211 + )}
  212 + </div>
  213 + )}
  214 + {isTarget && (
  215 + <>
  216 + <Form.Item label="考核目标名称" name="targetName">
  217 + <Select disabled defaultValue={name} />
  218 + </Form.Item>
  219 + <Form.Item
  220 + label="考核目标计算类型"
  221 + name="targetCalcType"
  222 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  223 + >
  224 + <Radio.Group>
  225 + <Radio value={1}>考核目标值计算 </Radio>
  226 + <Radio value={2}>最低要求计算</Radio>
  227 + </Radio.Group>
  228 + </Form.Item>
  229 + <Form.Item
  230 + label="考核目标值"
  231 + name="targetValue"
  232 + rules={[
  233 + { required: true, message: "请输入考核目标值" },
  234 + {
  235 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  236 + message:
  237 + targetType === TargetTypeEnum["百分比"]
  238 + ? "请输入大于0小于等于100的数(保留两位小数)"
  239 + : "请输入大于0的数(保留两位小数)",
  240 + },
  241 + ]}
  242 + >
  243 + <InputNumber
  244 + placeholder="请输入考核目标值"
  245 + style={{ width: "100%" }}
  246 + addonAfter={
  247 + targetType === TargetTypeEnum["百分比"]
  248 + ? "%"
  249 + : targetType === TargetTypeEnum["金额"]
  250 + ? "元"
  251 + : "数量"
  252 + }
  253 + />
  254 + </Form.Item>
  255 + </>
  256 + )}
  257 + </Form>
  258 + </Spin>
  259 + </Modal>
  260 + );
  261 +}
... ...
src/pages/performance/EvaGroupSetting/EditComfirm/components/AddLadderParamsModalSal.tsx 0 → 100755
  1 +/* eslint-disable no-return-assign */
  2 +/* eslint-disable no-return-assign */
  3 +import React, { useEffect, useState } from "react";
  4 +import { Modal, Form, Select, InputNumber, message, Spin, Radio, Input, Button } from "antd";
  5 +import { useStore } from "../index";
  6 +import { queryPostIndicatorApi, queryShopIndicatorApi } from "../api";
  7 +import _ from "lodash";
  8 +import useInitail from "@/hooks/useInitail";
  9 +import { EvaGroupSetteing } from "@/pages/performance/EvaGroupSetting/interface";
  10 +import { TargetType, TargetTypeEnum } from "@/pages/performance/entity";
  11 +
  12 +const Option = Select.Option;
  13 +interface Props {
  14 + addComVisible: boolean;
  15 + onCancel: Function;
  16 + postId?: number;
  17 + shopIds?: string;
  18 + onOk: (vales: any) => void;
  19 + comItem: Commission;
  20 + setItemId: Function;
  21 + scopeType: number;
  22 +}
  23 +type Commission = EvaGroupSetteing.CommissionParams;
  24 +export default function AddLadderParamsModal(props: Props) {
  25 + const percent = /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/;
  26 + const Momney = /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/;
  27 + const [form] = Form.useForm();
  28 + const { selectedIndicatorsLadderSal, setSelectedIndicatorsLadderSal, setLadderParamAlias } = useStore();
  29 +
  30 + const [isTarget, setIsTarget] = useState(false);
  31 + const [dataType, setDataType] = useState<number>(2);
  32 + // console.log(form);
  33 + const { addComVisible, onCancel, postId, shopIds, onOk, comItem, setItemId, scopeType } = props;
  34 + const [delay, setDelay] = useState(true);
  35 + // 保存选中绩效指标需要配置的绩效考核目标值类型
  36 + const [targetType, setTargetType] = useState<number>();
  37 + // 保存选中指标是否考评类型
  38 + const [codeType, setCodeType] = useState<number>();
  39 + // 保存过滤后指标列表
  40 + const [newIndicators, setNewIndicators] = useState<EvaGroupSetteing.IndicatorByPost[]>([]);
  41 + const [name, setIndicatorName] = useState("");
  42 + const [id, setId] = useState(0);
  43 + const {
  44 + data: indicatorsList,
  45 + setParams,
  46 + loading,
  47 + } = useInitail(
  48 + scopeType == 1 ? queryPostIndicatorApi : queryShopIndicatorApi,
  49 + [],
  50 + scopeType == 1 ? { postId } : {},
  51 + delay
  52 + );
  53 + useEffect(() => {
  54 + setParams(scopeType == 1 ? { postId } : {}, true);
  55 + setDelay(false);
  56 + setTargetType(1);
  57 + }, [addComVisible]);
  58 + // 修改
  59 +
  60 + useEffect(() => {
  61 + if (indicatorsList && indicatorsList.length > 0 && !comItem.code) {
  62 + const res = indicatorsList.filter((item) => !selectedIndicatorsLadderSal.find((y) => y === item.code));
  63 + setNewIndicators([...res]);
  64 + }
  65 + if (addComVisible && comItem.code) {
  66 + const indTar = indicatorsList.find((item) => item.code == comItem.code)?.targetType;
  67 + console.log("indTar", indTar);
  68 + console.log("comItem.targetType", comItem.targetType);
  69 + setTargetType(indTar);
  70 + setIndicatorName(comItem.name);
  71 + setCodeType(comItem.codeType);
  72 + form.setFieldsValue({
  73 + ...comItem,
  74 + ladderParams: {
  75 + value: comItem.code,
  76 + label: comItem.name,
  77 + dataType: comItem.dataType,
  78 + },
  79 + });
  80 + }
  81 + if (comItem.targetValue && comItem.targetCalcType) {
  82 + setIsTarget(true);
  83 + }
  84 + }, [indicatorsList]);
  85 + useEffect(() => {
  86 + if (targetType === TargetTypeEnum["无"]) {
  87 + setIsTarget(false);
  88 + }
  89 + }, [targetType]);
  90 + useEffect(() => {
  91 + setIsTarget(false);
  92 + }, [id]);
  93 + // 校验表单数据
  94 + function transformDTO(formData: any) {
  95 + let detail = {};
  96 + _.each(formData, (value: any, key: string) => {
  97 + switch (key) {
  98 + case "ladderParams":
  99 + const _options = value || {};
  100 + detail.name = _options.label[0];
  101 + detail.code = _options.value;
  102 + break;
  103 + default:
  104 + detail[key] = value;
  105 + break;
  106 + }
  107 + });
  108 + return detail;
  109 + }
  110 + function handSubmit(fieldsValue: any) {
  111 + const pa: any = transformDTO(fieldsValue);
  112 + pa.targetType = targetType;
  113 + pa.codeType = codeType;
  114 + if (comItem.dataType) {
  115 + pa.dataType = comItem.dataType;
  116 + }
  117 + if (!comItem.dataType) {
  118 + pa.dataType = dataType;
  119 + }
  120 + console.log("100pa", pa);
  121 + const newItemId = pa.code;
  122 + // 编辑时,不需要push id
  123 + if (!comItem.code) {
  124 + const tmpIds = [...selectedIndicatorsLadderSal];
  125 + tmpIds.push(newItemId);
  126 + setSelectedIndicatorsLadderSal([...tmpIds]);
  127 + } else {
  128 + pa.code = comItem.code;
  129 + pa.name = comItem.name;
  130 + }
  131 + onOk(pa);
  132 + onCancel && onCancel();
  133 + }
  134 + return (
  135 + <Modal
  136 + visible={addComVisible}
  137 + title={`${comItem.code ? "编辑" : "新增"}台阶得分指标`}
  138 + maskClosable={false}
  139 + afterClose={() => {
  140 + form.resetFields();
  141 + onCancel();
  142 + }}
  143 + onCancel={() => onCancel()}
  144 + onOk={form.submit}
  145 + width={1000}
  146 + >
  147 + <Spin spinning={loading}>
  148 + <Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} onFinish={handSubmit}>
  149 + <Form.Item name="ladderParams" label="计分指标" rules={[{ required: true, message: "计分指标" }]}>
  150 + <Select
  151 + placeholder="选择指标(*为考评指标,无*为绩效指标)"
  152 + labelInValue
  153 + disabled={!!comItem.code}
  154 + onChange={(value, Option: any) => {
  155 + setTargetType(Option.targetType);
  156 + setItemId(Option.key);
  157 + setId(Option.key);
  158 + setIndicatorName(Option.children);
  159 + setLadderParamAlias(Option.name);
  160 + setDataType(Option.dataType);
  161 + setCodeType(Option.codeType);
  162 + }}
  163 + showSearch
  164 + optionFilterProp="children"
  165 + >
  166 + {newIndicators.map((item) => (
  167 + <Option
  168 + value={item.code}
  169 + key={item.code}
  170 + targetType={item.targetType}
  171 + dataType={item.dataType}
  172 + codeType={item.codeType}
  173 + name={item.name}
  174 + >
  175 + {item.name}
  176 + {item.codeType == 2 ? "*" : ""}
  177 + </Option>
  178 + ))}
  179 + </Select>
  180 + </Form.Item>
  181 + <div style={{ display: "flex", justifyContent: "flex-start" }}>
  182 + <Form.Item
  183 + name="proportion"
  184 + label="占比"
  185 + rules={[
  186 + { pattern: percent, message: "请输入大于0小于等于100的数(最多保留两位小数)" },
  187 + { required: true, message: "请输入占比数" },
  188 + ]}
  189 + style={{ width: "100%" }}
  190 + >
  191 + <InputNumber style={{ width: "100%" }} addonAfter="%" />
  192 + </Form.Item>
  193 + </div>
  194 + <Form.Item name="cap" label="是否封顶" rules={[{ required: true, message: "请选择" }]}>
  195 + <Radio.Group>
  196 + <Radio value>是</Radio>
  197 + <Radio value={false}>否</Radio>
  198 + </Radio.Group>
  199 + </Form.Item>
  200 + {(targetType === TargetTypeEnum["百分比"] ||
  201 + targetType === TargetTypeEnum["金额"] ||
  202 + targetType === TargetTypeEnum["数量"]) && (
  203 + <div style={{ marginLeft: 65 }}>
  204 + <Button type="link" onClick={() => setIsTarget(true)}>
  205 + 考核目标值设置(可选项)
  206 + </Button>
  207 + {isTarget && (
  208 + <Button type="link" onClick={() => setIsTarget(false)}>
  209 + 删除该项考核目标设置
  210 + </Button>
  211 + )}
  212 + </div>
  213 + )}
  214 + {isTarget && (
  215 + <>
  216 + <Form.Item label="考核目标名称" name="targetName">
  217 + <Select disabled defaultValue={name} />
  218 + </Form.Item>
  219 + <Form.Item
  220 + label="考核目标计算类型"
  221 + name="targetCalcType"
  222 + rules={[{ required: true, message: "请选择考核目标计算类型" }]}
  223 + >
  224 + <Radio.Group>
  225 + <Radio value={1}>考核目标值计算 </Radio>
  226 + <Radio value={2}>最低要求计算</Radio>
  227 + </Radio.Group>
  228 + </Form.Item>
  229 + <Form.Item
  230 + label="考核目标值"
  231 + name="targetValue"
  232 + rules={[
  233 + { required: true, message: "请输入考核目标值" },
  234 + {
  235 + pattern: targetType === TargetTypeEnum["百分比"] ? percent : Momney,
  236 + message:
  237 + targetType === TargetTypeEnum["百分比"]
  238 + ? "请输入大于0小于等于100的数(保留两位小数)"
  239 + : "请输入大于0的数(保留两位小数)",
  240 + },
  241 + ]}
  242 + >
  243 + <InputNumber
  244 + placeholder="请输入考核目标值"
  245 + style={{ width: "100%" }}
  246 + addonAfter={
  247 + targetType === TargetTypeEnum["百分比"]
  248 + ? "%"
  249 + : targetType === TargetTypeEnum["金额"]
  250 + ? "元"
  251 + : "数量"
  252 + }
  253 + />
  254 + </Form.Item>
  255 + </>
  256 + )}
  257 + </Form>
  258 + </Spin>
  259 + </Modal>
  260 + );
  261 +}
... ...