Commit 301976f1d79b63e6a918d76837478d34c95d573f
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
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 "./ShopLimit"; |
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
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) => { |
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
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 | +} | ... | ... |