Commit 0d9e1246a268e7a41bf19ce4eb910a399d1e1a30

Authored by 王强
2 parents d574f792 c6ce5d0f

Merge branch 'bug_fix' of gitlab.feewee.cn:FEV2/fw-cms into ehr

Showing 548 changed files with 32397 additions and 6766 deletions

Too many changes to show.

To preserve performance only 60 of 548 files are displayed.

config/routers/attendance.ts
... ... @@ -4,103 +4,117 @@ export default [
4 4 // component: './attendance/SpecialFestivals'
5 5 // },
6 6 {
7   - path: '/attendance/attend/festivals', //特殊节日设置
8   - component: './attendance/Attend/subpages/SpecialFestivals'
  7 + path: "/attendance/attend/festivals", //特殊节日设置
  8 + component: "./attendance/Attend/subpages/SpecialFestivals",
9 9 },
10 10 {
11   - path: '/attendance/attend/basic', //基础设置
12   - component: './attendance/Attend/subpages/Basic'
  11 + path: "/attendance/attend/basic", //基础设置
  12 + component: "./attendance/Attend/subpages/Basic",
13 13 },
14 14 {
15   - path: '/attendance/attend/roster', //排班设置
16   - component: './attendance/Attend/subpages/Roster'
  15 + path: "/attendance/attend/roster", //排班设置
  16 + component: "./attendance/Attend/subpages/Roster",
17 17 },
18 18 {
19   - path: '/attendance/attend/noclock', //免打卡设置
20   - component: './attendance/Attend/subpages/NoClock'
  19 + path: "/attendance/attend/noclock", //免打卡设置
  20 + component: "./attendance/Attend/subpages/NoClock",
21 21 },
22 22 {
23   - path: '/attendance/attend/minattendance', //最低出勤标准设置;
24   - component: './attendance/Attend/subpages/MinAttendance'
  23 + path: "/attendance/attend/minattendance", //最低出勤标准设置;
  24 + component: "./attendance/Attend/subpages/MinAttendance",
25 25 },
26 26 {
27   - path: '/attendance/attend/clock', //打卡设置
28   - component: './attendance/Attend/subpages/Clock'
  27 + path: "/attendance/attend/clock", //打卡设置
  28 + component: "./attendance/Attend/subpages/Clock",
29 29 },
30 30 {
31   - path: '/attendance/attend/attendancegroup', //考勤组设置
32   - component: './attendance/Attend/subpages/AttendanceGroup'
  31 + path: "/attendance/attend/attendancegroup", //考勤组设置
  32 + component: "./attendance/Attend/subpages/AttendanceGroup",
33 33 },
34 34 {
35   - path: '/attendance/attend/morningevening', //早晚班设置
36   - component: './attendance/Attend/subpages/MorningEvening'
  35 + path: "/attendance/attend/morningevening", //早晚班设置
  36 + component: "./attendance/Attend/subpages/MorningEvening",
37 37 },
38 38 {
39   - path: '/attendance/attend/storeattendancegroup', //门店考勤组设置
40   - component: './attendance/Attend/subpages/StoreattendanceGroup'
  39 + path: "/attendance/attend/storeattendancegroup", //门店考勤组设置
  40 + component: "./attendance/Attend/subpages/StoreattendanceGroup",
41 41 },
42 42 {
43   - path: '/attendance/attend/holiday', //春节设置
44   - component: './attendance/Attend/subpages/Holiday'
  43 + path: "/attendance/attend/holiday", //春节设置
  44 + component: "./attendance/Attend/subpages/Holiday",
45 45 },
46 46 {
47   - path: '/attendance/leave/basic', //请假 基础设置
48   - component: './attendance/Basicleave'
  47 + path: "/attendance/leave/basic", //请假 基础设置
  48 + component: "./attendance/Basicleave",
49 49 },
50 50 {
51   - path: '/attendance/leave/leave', //请假 请假时间设置
52   - component: './attendance/Leave'
  51 + path: "/attendance/leave/leave", //请假 请假时间设置
  52 + component: "./attendance/Leave",
53 53 },
54 54 {
55   - path: '/attendance/leave/blacklist', //请假 年假黑名单设置
56   - component: './attendance/BlackList'
  55 + path: "/attendance/leave/blacklist", //请假 年假黑名单设置
  56 + component: "./attendance/BlackList",
57 57 },
58 58 {
59   - path: '/attendance/material/material', //请假资料要求
60   - component: './attendance/Material'
  59 + path: "/attendance/material/material", //请假资料要求
  60 + component: "./attendance/Material",
61 61 },
62 62 {
63   - path: '/attendance/material/sickleavematerial', //请假资料设置
64   - component: './attendance/SickLeaveMaterial'
  63 + path: "/attendance/sickleavematerial", //请假资料设置
  64 + component: "./attendance/SickLeaveMaterial",
65 65 },
66 66 {
67   - path: '/attendance/material/businessmaterial', //出差资料要求
68   - component: './attendance/BusinessMaterial'
  67 + path: "/attendance/material/businessmaterial", //出差资料要求
  68 + component: "./attendance/BusinessMaterial",
69 69 },
70 70 {
71   - path: '/attendance/material/businesstripmaterial', //出差资料设置
72   - component: './attendance/BusinessTripMaterial'
  71 + path: "/attendance/material/businesstripmaterial", //出差资料设置
  72 + component: "./attendance/BusinessTripMaterial",
73 73 },
74 74 {
75   - path: '/attendance/reimbursement/cateringsubsidies', //餐饮补贴标准
76   - component: './attendance/Reimbursement/subpages/CateringSubsidies'
  75 + path: "/attendance/reimbursement/cateringsubsidies", //餐饮补贴标准
  76 + component: "./attendance/Reimbursement/subpages/CateringSubsidies",
77 77 },
78 78 {
79   - path: '/attendance/reimbursement/roomsubsidies', //住宿标准
80   - component: './attendance/Reimbursement/subpages/RoomSubsidies'
  79 + path: "/attendance/reimbursement/roomsubsidies", //住宿标准
  80 + component: "./attendance/Reimbursement/subpages/RoomSubsidies",
81 81 },
82 82 {
83   - path: '/attendance/reimbursement/method', //报销方式
84   - component: './attendance/Reimbursement/subpages/Method'
  83 + path: "/attendance/reimbursement/method", //报销方式
  84 + component: "./attendance/Reimbursement/subpages/Method",
85 85 },
86 86 {
87   - path: '/attendance/reimbursement/carfee', //加盟车报销标准
88   - component: './attendance/Reimbursement/subpages/CarFee'
  87 + path: "/attendance/reimbursement/carfee", //加盟车报销标准
  88 + component: "./attendance/Reimbursement/subpages/CarFee",
89 89 },
90 90 {
91   - path: '/attendance/fieldservice/fieldexception', //外勤异常设置
92   - component: './attendance/FieldService'
  91 + path: "/attendance/fieldservice/fieldexception", //外勤异常设置
  92 + component: "./attendance/FieldService",
93 93 },
94 94 {
95   - path: '/attendance/fieldservice/work', //外勤任务申请权限设置
96   - component: './attendance/FieldService/subpages/Work'
  95 + path: "/attendance/fieldservice/work", //外勤任务申请权限设置
  96 + component: "./attendance/FieldService/subpages/Work",
97 97 },
98 98 {
99   - path: '/attendance/fieldservice/workaddress', //外勤任务地址设置
100   - component: './attendance/FieldService/subpages/WorkAddress'
  99 + path: "/attendance/fieldservice/workaddress", //外勤任务地址设置
  100 + component: "./attendance/FieldService/subpages/WorkAddress",
101 101 },
  102 +
102 103 {
103   - path: '/attendance/travelsetting/traveladdress', //出差任务地址设置
104   - component: './attendance/TravelSetting/TravelAddress'
  104 + path: "/attendance/TravelModeSettings", //出行方式权限设置
  105 + component: "./attendance/TravelModeSettings",
  106 + },
  107 +
  108 + /**
  109 + * 出差设置
  110 + */
  111 + {
  112 + path: "/attendance/travelsetting/traveladdress", //出差任务地址设置
  113 + component: "./attendance/TravelSetting/TravelAddress",
  114 + },
  115 + //出差异常处罚设置
  116 + {
  117 + path: "/attendance/travelsetting/penaltySetting",
  118 + component: "./attendance/TravelSetting/PenaltySetting",
105 119 },
106 120 ];
... ...
config/routers/cas.ts
... ... @@ -410,5 +410,10 @@ export default [
410 410 {
411 411 path: '/cas/FilmApplication',
412 412 component: './cas/FilmApplication'
  413 + },
  414 + /** 辅料领取设置 */
  415 + {
  416 + path: '/cas/getHelpPart',
  417 + component: './cas/getHelpPart'
413 418 }
414 419 ];
... ...
config/routers/contract.ts
... ... @@ -51,4 +51,8 @@ export default [
51 51 path: "/contract/kt/paint/config", // 油漆配置
52 52 component: "./contract/PaintConfig",
53 53 },
  54 + {
  55 + path: "/contract/kt/cost/config", //费用承担设置
  56 + component: "./contract/BearCostSetting",
  57 + },
54 58 ];
... ...
config/routers/crm_new.ts
... ... @@ -73,4 +73,12 @@ export default [
73 73 path: '/crm/onlineShopImport', // 网销店导入
74 74 component: './crm_new/OnlineImport',
75 75 },
  76 + {
  77 + path: '/crm/threePartyPlatformClue', // 三方平台线索配置
  78 + component: './crm_new/ThreePartyPlatformClue',
  79 + },
  80 + {
  81 + path: '/crm/closeClue', // 暂停区域线索站岗分配
  82 + component: './crm_new/Settings/subpages/CloseClue',
  83 + },
76 84 ];
77 85 \ No newline at end of file
... ...
config/routers/ehr.ts
1 1 /*
2 2 * @Date: 2020-10-12 11:02:39
3 3 * @LastEditors: wangqiang@feewee.cn
4   - * @LastEditTime: 2022-11-16 11:29:59
  4 + * @LastEditTime: 2023-01-16 09:16:49
5 5 */
6 6 export default [
7 7 // 人力资源管理系统
... ... @@ -50,10 +50,6 @@ export default [
50 50 component: "./ehr/ProbationSetting/PeriodSetting",
51 51 },
52 52 {
53   - path: "/ehr/standardSetting/questionBank", // 标准设置-考试题库设置
54   - component: "./ehr/StandardSetting/QuestionBank",
55   - },
56   - {
57 53 path: "/ehr/interviewSetting/interviewScoreSetting", // 面试设置-面试打分项
58 54 component: "./ehr/InterviewSetting/InterviewScoreSetting",
59 55 },
... ... @@ -209,5 +205,33 @@ export default [
209 205 {
210 206 path: "/ehr/socialCommerce/accumulationFundDeduction", // 公积金扣款标准
211 207 component: "./ehr/SocialCommerce/AccumulationFundDeduction",
212   - }
  208 + },
  209 + {
  210 + path: "/ehr/programOfStudy/abilityTypeSettings", // 能力提升业务类型配置
  211 + component: "./ehr/ProgramOfStudy/AbilityTypeSettings",
  212 + },
  213 + {
  214 + path: "/ehr/programOfStudy/permissionsSettings", // 学习项目编辑权限设置
  215 + component: "./ehr/ProgramOfStudy/PermissionsSettings",
  216 + },
  217 + {
  218 + path: "/ehr/programOfStudy/settings", // 学习项目设置
  219 + component: "./ehr/ProgramOfStudy/Settings",
  220 + },
  221 + {
  222 + path: "/ehr/authentication/settings", // 角色认证设置
  223 + component: "./ehr/Authentication/Settings",
  224 + },
  225 + {
  226 + path: "/ehr/authentication/manage", // 认证管理
  227 + component: "./ehr/Authentication/Manage",
  228 + },
  229 + {
  230 + path: "/ehr/programOfStudy/questionBank", // 考试题库设置
  231 + component: "./ehr/ProgramOfStudy/QuestionBank",
  232 + },
  233 + {
  234 + path: "/ehr/programOfStudy/examHistory", // 考试记录
  235 + component: "./ehr/ProgramOfStudy/ExamHistory",
  236 + },
213 237 ];
... ...
config/routers/finance.ts
... ... @@ -24,6 +24,14 @@ export default [
24 24 component: "finance/CompanyRelationAuth",
25 25 },
26 26 {
  27 + path: "/finance2/companyRelationAuth/create", //往来单位关系设置==》新增
  28 + component: "finance/CompanyRelationCreate",
  29 + },
  30 + {
  31 + path: "/finance2/companyRelationAuth/edit", //往来单位关系设置==》编辑
  32 + component: "finance/CompanyRelationCreate/components/RelationshipSettingsEdit",
  33 + },
  34 + {
27 35 path: "/finance2/specialAccountSetting/deductAccount", //划扣专用账户
28 36 component: "./finance/SpecialAccount/DeductAccount",
29 37 },
... ... @@ -76,6 +84,26 @@ export default [
76 84 component: "./finance/Reimburse/ReimburseFeeMaterial",
77 85 },
78 86 {
  87 + path: "/finance2/reimburse/cateringsubsidies", //餐饮补贴标准
  88 + component: "./finance/Reimburse/CateringSubsidies",
  89 + },
  90 + {
  91 + path: "/finance2/reimburse/roomsubsidies", //住宿标准
  92 + component: "./finance/Reimburse/RoomSubsidies",
  93 + },
  94 + {
  95 + path: "/finance2/reimburse/method", //餐饮费用报销方式
  96 + component: "./finance/Reimburse/Method",
  97 + },
  98 + {
  99 + path: "/finance2/reimburse/carfee", //里程计费标准
  100 + component: "./finance/Reimburse/CarFee",
  101 + },
  102 + {
  103 + path: "/finance2/reimburse/fieldservice", //外勤报销
  104 + component: "./finance/Reimburse/FieldService",
  105 + },
  106 + {
79 107 path: "/finance2/financeConfig", //财务配置
80 108 component: "./finance/FinanceConfig",
81 109 },
... ... @@ -139,4 +167,8 @@ export default [
139 167 path: "/finance2/PaymentAllocation", // 款项配置
140 168 component: "./finance/PaymentAllocation",
141 169 },
  170 + {
  171 + path: "/finance2/financePaymentConfirmConfig", // 付款前款项确认配置
  172 + component: "./finance/BeforePaymentConfirmConfig",
  173 + },
142 174 ];
143 175 \ No newline at end of file
... ...
config/routers/pms.ts
... ... @@ -44,12 +44,16 @@ export default [
44 44 component: './pms/storage/partShop'
45 45 },
46 46 {
  47 + path: '/pms/storage/areaStorage', // 区域库设置
  48 + component: './pms/storage/areaStorageSetting'
  49 + },
  50 + {
47 51 path: '/pms/partPlan/partSetting', // 配件设置
48 52 component: './pms/partPlan/Setting'
49 53 },
50 54 {
51   - path: '/pms/partPlan/planManage', // 制定配件计划
52   - component: './pms/partPlan/PlanManage'
  55 + path: '/pms/partPlan/amountPlan', // 指定金额计划
  56 + component: './pms/partPlan/AmountPlan'
53 57 },
54 58 {
55 59 path: '/pms/partPlan/shipment', // 配件发运单
... ... @@ -60,10 +64,6 @@ export default [
60 64 component: './pms/partPlan/PlanSupplier'
61 65 },
62 66 {
63   - path: '/pms/partPlan/progress', // 计划进度
64   - component: './pms/partPlan/Progress'
65   - },
66   - {
67 67 path: '/pms/partPlan/minRatioPlan', // 最低库销比计划
68 68 component: './pms/partPlan/MinRatioPlan'
69 69 },
... ... @@ -80,13 +80,33 @@ export default [
80 80 component: './pms/partPlan/CustBuyPlan'
81 81 },
82 82 {
  83 + path: '/pms/partPlan/appointPart', // 指定配件
  84 + component: './pms/partPlan/AppointPart'
  85 + },
  86 + {
  87 + path: '/pms/partPlan/planPool', // 计划池
  88 + component: './pms/partPlan/PlanPool'
  89 + },
  90 + {
  91 + path: '/pms/partPlan/planManage', // 计划管理
  92 + component: './pms/partPlan/PlanManage'
  93 + },
  94 + {
  95 + path: '/pms/partPlan/planManage/apply', // 计划管理-->申请
  96 + component: './pms/partPlan/PlanManage/subpages/Apply'
  97 + },
  98 + {
  99 + path: '/pms/partPlan/planManage/detail/:planId', // 计划管理-->申请
  100 + component: './pms/partPlan/PlanManage/subpages/Detail'
  101 + },
  102 + {
83 103 path: '/pms/partPlan/fwCustBuyPlan', // 客户订件计划(霏微)
84 104 component: './pms/partPlan/CustBuyPlan'
85 105 },
86   - // {
87   - // path: '/pms/partPlan/appointPart', // 指定配件
88   - // component: './pms/partPlan/AppointPart'
89   - // },
  106 + {
  107 + path: '/pms/partPlan/appointPart', // 指定配件
  108 + component: './pms/partPlan/AppointPart'
  109 + },
90 110 {
91 111 path: '/pms/part/priceSettingTodo',
92 112 component: './pms/part/PriceSettingTodo'
... ... @@ -103,4 +123,40 @@ export default [
103 123 path: '/pms/part/minRatio', // 最低库销比设置
104 124 component: './pms/part/MinRatio'
105 125 },
  126 + // {
  127 + // path: '/pms/partPlan/orderPart', // 工单缺件(霏微)
  128 + // component: './pms/partPlan/OrderPart'
  129 + // },
  130 + {
  131 + path: '/pms/transfer/transferPool', // 调拨池
  132 + component: './pms/transfer/transferPool'
  133 + },
  134 + {
  135 + path: '/pms/transfer/transferManage', // 调拨管理
  136 + component: './pms/transfer/transferManage'
  137 + },
  138 + {
  139 + path: '/pms/partPlan/orderPart', // 工单缺件(霏微)
  140 + component: './pms/partPlan/OrderPart'
  141 + },
  142 + {
  143 + path: '/pms/transfer/setting', // 指定人员调运费用设置
  144 + component: './pms/transfer/Setting'
  145 + },
  146 + {
  147 + path: '/pms/purchase/purchaseRecord', // 采购-->配件采购申请记录
  148 + component: './pms/purchase/PurchaseRecord'
  149 + },
  150 + {
  151 + path: '/pms/purchase/pool', // 采购-->工单缺件外采池
  152 + component: './pms/purchase/PurchasePool'
  153 + },
  154 + {
  155 + path: '/pms/storage/partFlow', // 配件出入库流水
  156 + component: './pms/storage/partFlow'
  157 + },
  158 + {
  159 + path: '/pms/partPlan/storageOverStock', // 可调出配件
  160 + component: './pms/partPlan/StorageOverStock'
  161 + },
106 162 ];
... ...
config/routers/vms.ts
... ... @@ -27,4 +27,8 @@ export default [
27 27 path: '/vms/vehicle/maintain', // 车辆资产维护
28 28 component: './vms/VehicleMaintenance',
29 29 },
  30 + {
  31 + path: '/vms/operation/trackPlayback', // 轨迹回放
  32 + component: './vms/OperationAdministration',
  33 + },
30 34 ];
31 35 \ No newline at end of file
... ...
package.json
... ... @@ -34,6 +34,7 @@
34 34 "not ie <= 10"
35 35 ],
36 36 "dependencies": {
  37 + "@amap/amap-jsapi-loader": "^1.0.1",
37 38 "@ant-design/colors": "^6.0.0",
38 39 "@ant-design/compatible": "^1.0.1",
39 40 "@ant-design/pro-descriptions": "^1.9.10",
... ...
src/common/interface.d.ts
... ... @@ -33,9 +33,10 @@ declare namespace CommonApi {
33 33 }
34 34  
35 35 interface OptionVO {
36   - id: number;
37   - name: string;
  36 + id?: number;
  37 + name?: string;
38 38 thumbnail?: string; //品牌缩略图
  39 + brandName?:string
39 40 }
40 41  
41 42 interface BrandVO {
... ...
src/components/FeeweeUploadAttachment/index.tsx
1 1 /*
2 2 * @Date: 2021-01-05 14:24:23
3 3 * @LastEditors: wangqiang@feewee.cn
4   - * @LastEditTime: 2022-11-10 10:19:56
  4 + * @LastEditTime: 2022-12-21 09:42:29
5 5 */
6 6 import React, { useEffect, useRef, useState } from "react";
7 7 import { message, Popover, Spin, Upload } from "antd";
... ... @@ -195,10 +195,10 @@ export default function FeeweeUploadAttachment({
195 195 try {
196 196 removingFileFidList.current.push(file?.response.fid);
197 197 setLoading(true);
198   - await deleteFileApi(file?.response.fid);
199   - if (useCos) {
200   - await deleteCOSFile(file?.response.data);
201   - }
  198 + // await deleteFileApi(file?.response.fid);
  199 + // if (useCos) {
  200 + // await deleteCOSFile(file?.response.data);
  201 + // }
202 202 onChange &&
203 203 onChange((fidList || []).filter((fid) => fid !== file?.response.fid));
204 204 return Promise.resolve();
... ...
src/components/GlobalHeader/index.less
... ... @@ -41,11 +41,13 @@
41 41 height: 100%;
42 42 overflow: hidden;
43 43 .action {
44   - display: inline-block;
  44 + display: inline-flex;
45 45 height: 100%;
46 46 padding: 0 12px;
47 47 cursor: pointer;
48 48 transition: all 0.3s;
  49 + align-items: center;
  50 +
49 51 > i {
50 52 color: @text-color;
51 53 vertical-align: middle;
... ...
src/components/ShopSelectNew/index.tsx
... ... @@ -2,7 +2,7 @@
2 2 * @Author: wangqiang@feewee.cn
3 3 * @Date: 2022-05-25 09:14:31
4 4 * @LastEditors: wangqiang@feewee.cn
5   - * @LastEditTime: 2022-10-13 14:47:51
  5 + * @LastEditTime: 2023-01-05 11:03:13
6 6 */
7 7 import useInitial from "@/hooks/useInitail";
8 8 import { Tag } from "antd";
... ... @@ -170,10 +170,16 @@ function ShopSelectNew(
170 170 return (
171 171 <div style={style}>
172 172 <span
173   - className="ant-input-affix-wrapper"
  173 + className={`ant-input-affix-wrapper${
  174 + disabled ? " ant-input-affix-wrapper_disabled" : ""
  175 + }`}
174 176 onClick={disabled ? undefined : openModal}
175 177 >
176   - <div className="ShopSelectNew_Container">
  178 + <div
  179 + className={`ShopSelectNew_Container${
  180 + disabled ? " ShopSelectNew_Container_disabled" : ""
  181 + }`}
  182 + >
177 183 {value?.length ? (
178 184 multiple ? (
179 185 value.map((item) => (
... ... @@ -182,6 +188,12 @@ function ShopSelectNew(
182 188 closable={
183 189 !disabled && !disabledShopIds.includes(+item.value!)
184 190 }
  191 + style={{
  192 + backgroundColor: disabled
  193 + ? "rgb(245, 245, 245)"
  194 + : undefined,
  195 + color: disabled ? "#bfbfbf" : undefined,
  196 + }}
185 197 key={item.value}
186 198 onClose={() => del(item)}
187 199 >
... ...
src/components/ShopSelectNew/style.less
... ... @@ -27,6 +27,19 @@
27 27 color: #ccc;
28 28 }
29 29 }
  30 +
  31 + .ShopSelectNew_Container_disabled {
  32 + cursor: not-allowed;
  33 + }
  34 +}
  35 +
  36 +.ant-input-affix-wrapper_disabled {
  37 + background-color: rgb(245, 245, 245);
  38 + cursor: not-allowed;
  39 + &:hover {
  40 + border-color: #d9d9d9 !important;
  41 + cursor: not-allowed !important;
  42 + }
30 43 }
31 44  
32 45 .ShopSelectNew_checkbox {
... ...
src/hooks/useMenuElement.ts
... ... @@ -2,20 +2,22 @@ import { useState, useEffect } from &#39;react&#39;;
2 2 import { http } from '@/typing/http';
3 3 import request from '@/utils/request';
4 4 import { message } from 'antd';
  5 +import { history } from 'umi';
5 6  
6 7 /**获取列表 */
7   -function getMenuElemntApi(path: string): http.PromiseResp<string[]> {
8   - return request.get(`/admin/menu/page/elements`, { params: { path }});
  8 +function getMenuElemntApi(code: string): http.PromiseResp<string[]> {
  9 + return request.get(`/admin/menu/page/elements`, { params: { code }});
9 10 }
10 11  
11 12 /**
12   - * @param {path} —当前页面资源名称
  13 + * @param {code} —当前页面资源编码
13 14 */
14   -export default function useMenuElement<T>(path: string) {
  15 +export default function useMenuElement<T>(code?: string) {
15 16 const [elements, setElements] = useState<string[]>([]);
  17 + const { fp_code } = history.location.query as any;
16 18  
17 19 useEffect(() => {
18   - getMenuElemntApi(path).then(res => {
  20 + getMenuElemntApi(code || fp_code).then(res => {
19 21 setElements(res.data || []);
20 22 }).catch(e => {
21 23 message.error(`获取页面权限:${e.message}`)
... ...
src/hooks/usePagination.ts
1 1 import { http } from "@/typing/http";
2 2 import { useState, useEffect, useRef } from "react";
3   -import { common } from "@/typing/common";
  3 +import * as common from "@/typing/common";
4 4 import { message } from "antd";
5 5 import { TablePaginationConfig } from "antd/lib/table";
6 6 import produce, { Draft } from "immer";
... ...
src/layouts/BasicLayout.tsx
... ... @@ -56,7 +56,7 @@ const BasicLayout: React.FC&lt;BasicLayoutProps&gt; = ({ dispatch, children, ...other
56 56 if (menuItemProps.isUrl) {
57 57 return defaultDom;
58 58 }
59   - return <Link to={menuItemProps.path || ""}>{defaultDom}</Link>;
  59 + return <Link to={menuItemProps.path ? `${menuItemProps.path}?fp_code=${menuItemProps.code}` : ""}>{defaultDom}</Link>;
60 60 }}
61 61 breadcrumbRender={(routers = []) => [
62 62 {
... ...
src/layouts/api.ts
... ... @@ -6,6 +6,8 @@ export interface MenuItem {
6 6 name?: string,
7 7 path?: string,
8 8 children?: Array<MenuItem>
  9 + code?: string // 资源编码
  10 + classify?: string // 资源分类
9 11 }
10 12  
11 13 export function userMenuApi() {
... ...
src/pages/Login/index.tsx
... ... @@ -78,6 +78,7 @@ const LoginPage = () =&gt; {
78 78 message.success('登录成功!');
79 79 // 登录成功后,清除缓存;
80 80 sessionStorage.clear();
  81 +
81 82 // localforage.clear();
82 83 } else {
83 84 setQrStatusCode(response.code);
... ... @@ -147,7 +148,7 @@ const LoginPage = () =&gt; {
147 148 <CheckCircleFilled className={styles.icon} />
148 149 </>
149 150 ) : (
150   - <span>{qrDesc(qrStatusCode)}</span>
  151 + <span>{qrDesc(qrStatusCode)}</span>
151 152 )}
152 153 </div>
153 154 {showRefresh(qrStatusCode) ? (
... ...
src/pages/activity/Article/components/List.tsx
... ... @@ -23,7 +23,7 @@ interface Props {
23 23 export default function List(props: Props) {
24 24 const { list = [], pagination = false, loading, onRefreshing } = props;
25 25  
26   - const { elements } = useMenuElement("article");
  26 + const { elements } = useMenuElement();
27 27  
28 28 function checkArticle(e: any, row: IF.ListVO) {
29 29 e.preventDefault();
... ...
src/pages/activity/Assisting/components/List.tsx
... ... @@ -29,7 +29,7 @@ export default function List(props: Props) {
29 29  
30 30 const [rankVisible, setRankVisible] = useState(false);
31 31  
32   - const { elements } = useMenuElement("assisting");
  32 + const { elements } = useMenuElement();
33 33  
34 34 function viewRegister(e: any, record: IF.ListVO) {
35 35 e.preventDefault();
... ...
src/pages/activity/Offline/components/List.tsx
... ... @@ -27,7 +27,7 @@ export default function List(props: Props) {
27 27 const { list = [], pagination = false, loading, onRefreshing, match } = props;
28 28 const { subType } = match.params;
29 29  
30   - const { elements } = useMenuElement(subType);
  30 + const { elements } = useMenuElement();
31 31  
32 32  
33 33 const [registerVisible, setRegisterVisible] = useState(false);
... ...
src/pages/activity/autoShow/index.tsx
... ... @@ -13,7 +13,7 @@ const { Column } = Table;
13 13  
14 14 function AutoShow() {
15 15 const { list, loading, setParams, paginationConfig, innerParams, setLoading } = usePagination<API.AutoShowItem>(API.queryAutoShowList, {});
16   - const { elements = [] } = useMenuElement('autoShow');
  16 + const { elements = [] } = useMenuElement();
17 17  
18 18 /** 查看明细 */
19 19 function viewList(record: API.AutoShowItem) {
... ...
src/pages/admin/Privilege/components/PrivileList.tsx
... ... @@ -173,24 +173,32 @@ export default function PrivileList() {
173 173 loading={privileList.loading}
174 174 childrenColumnName="other"
175 175 >
176   - <Column title="资源名称" dataIndex="privilegeName" width="20%" />
  176 + <Column title="资源名称" dataIndex="privilegeName" />
177 177 <Column
178 178 title="资源类型"
179   - width={100}
180 179 dataIndex="privilegeType"
181 180 render={(text, record: Privilege.PrivilegeData) => `${PrivilegeType[record.privilegeType || 0]}`}
182 181 />
183   - <Column title="资源路径" dataIndex="privilegeUrl" width="20%" />
  182 + <Column title="资源路径" dataIndex="privilegeUrl" />
  183 + <Column
  184 + title="资源编码"
  185 + dataIndex="privilegeCode"
  186 + render={(text) => `${text || "-"}`}
  187 + />
  188 + <Column
  189 + title="资源分类"
  190 + dataIndex="privilegeClassify"
  191 + render={(text) => `${text || "-"}`}
  192 + />
184 193 <Column
185 194 title="备注"
186 195 dataIndex="remark"
187 196 render={(text) => `${text || "-"}`}
188 197 />
189   - <Column title="序号" width={60} dataIndex="orderBy" />
  198 + <Column title="序号" dataIndex="orderBy" />
190 199 <Column
191 200 title="状态"
192 201 dataIndex="status"
193   - width={100}
194 202 render={(val) => {
195 203 switch (val) {
196 204 case -1:
... ... @@ -206,7 +214,6 @@ export default function PrivileList() {
206 214 />
207 215 <Column
208 216 title="子资源"
209   - width={80}
210 217 dataIndex="childNum"
211 218 render={(text, record: Privilege.PrivilegeData) => (
212 219 <a onClick={() => handleViewChildren(record)}>{text || 0}</a>
... ... @@ -214,7 +221,6 @@ export default function PrivileList() {
214 221 />
215 222 <Column
216 223 title="操作"
217   - width="16%"
218 224 render={(text, record: Privilege.PrivilegeData) => (
219 225 <>
220 226 <a
... ...
src/pages/admin/Privilege/components/PrivileModal.tsx
... ... @@ -25,6 +25,8 @@ export default function PrivileModal() {
25 25 remark: item.remark,
26 26 orderBy: item.orderBy || 0,
27 27 parentName: name,
  28 + privilegeCode: item.privilegeCode,
  29 + privilegeClassify: item.privilegeClassify
28 30 });
29 31 }
30 32 }, [privileModal.visible]);
... ... @@ -92,6 +94,16 @@ export default function PrivileModal() {
92 94 <FormItem label="资源路径" rules={[{ required: true, message: '请输入资源路径' }]} name="privilegeUrl">
93 95 <Input placeholder="请输入资源路径" />
94 96 </FormItem>
  97 + {
  98 + privileModal.item.id ? (
  99 + <FormItem label="资源编码" rules={[{ required: true, message: '请输入资源编码' }]} name="privilegeCode">
  100 + <Input placeholder="请输入资源编码" />
  101 + </FormItem>
  102 + ) : null
  103 + }
  104 + <FormItem name="privilegeClassify" label="资源分类">
  105 + <Input placeholder="请输入资源分类" />
  106 + </FormItem>
95 107 <FormItem noStyle shouldUpdate={(prevValues, currentValues) => prevValues.privilegeType != currentValues.privilegeType}>
96 108 {({ getFieldValue }): any => {
97 109 const type = getFieldValue("privilegeType");
... ...
src/pages/admin/Privilege/interface.d.ts
... ... @@ -67,6 +67,8 @@ declare namespace Privilege {
67 67 childNum?: number
68 68 /** 子资源列表 */
69 69 // children?: PrivilegeData[]
  70 + privilegeCode?: string // 资源编码
  71 + privilegeClassify?: string // 资源分配
70 72 }
71 73  
72 74 interface SystemData {
... ... @@ -105,6 +107,8 @@ declare namespace Privilege {
105 107 privilegeType: number,
106 108 privilegeUrl: string
107 109 remark: string
  110 + privilegeCode?: string // 资源编码
  111 + privilegeClassify?: string // 资源分配
108 112 }
109 113  
110 114 interface RouterStackParams {
... ...
src/pages/admin/Role/components/RoleFilter.tsx
... ... @@ -24,7 +24,14 @@ export default function RoleFilter() {
24 24 <RadioButton value={0}>禁用</RadioButton>
25 25 {/* <RadioButton value={-1}>已删除</RadioButton> */}
26 26 </RadioGroup>
27   - <Select allowClear placeholder="请选择系统" style={{ width: 200, marginRight: 10, marginBottom: 10 }} onChange={sysId => setParams({ ...innerParams, sysId, current: 1 }, true)}>
  27 + <Select
  28 + allowClear
  29 + showSearch
  30 + optionFilterProp="children"
  31 + placeholder="请选择系统"
  32 + style={{ width: 200, marginRight: 10, marginBottom: 10 }}
  33 + onChange={sysId => setParams({ ...innerParams, sysId, current: 1 }, true)}
  34 + >
28 35 {(systems || []).map((i: Privilege.SystemListVO) => (<Option value={i.id || 0} key={i.id}>{i.sysName || '--'}</Option>))}
29 36 </Select>
30 37 <Search
... ...
src/pages/admin/Role/components/RoleList.tsx
... ... @@ -37,8 +37,7 @@ export default function RoleList() {
37 37 message.success(record.status ? "禁用成功" : "启用成功")
38 38 const tempList = list.map((item: any) => {
39 39 if (item.id === record.id) {
40   - item.status = record.status === 0 ? 1 : 0
41   - return item;
  40 + return { ...item, status: record.status === 0 ? 1 : 0 };
42 41 }
43 42 return item;
44 43 });
... ...
src/pages/admin/Role/components/RoleModal.tsx
... ... @@ -104,7 +104,7 @@ export default function RoleModal() {
104 104 hasFeedback
105 105 rules={[{ required: true, message: "请选择角色类型" }]}
106 106 >
107   - <Select style={{ width: "100%" }} placeholder="请选择角色类型">
  107 + <Select disabled={!!currentItem.id} style={{ width: "100%" }} placeholder="请选择角色类型">
108 108 {[1, 2, 3].map((item) => (
109 109 <Option key={item} value={item}>
110 110 {RoleTypeEnum[item]}
... ... @@ -141,10 +141,10 @@ export default function RoleModal() {
141 141 <div>
142 142 <FormItem
143 143 name="roleRangeType"
144   - label="数据范围唯一性"
  144 + label="门店角色唯一性"
145 145 hasFeedback
146 146 rules={[
147   - { required: true, message: "请选择角色数据范围唯一性" },
  147 + { required: true, message: "请选择门店角色唯一性" },
148 148 ]}
149 149 >
150 150 <Radio.Group
... ... @@ -193,15 +193,15 @@ export default function RoleModal() {
193 193 return d && d != 99 ? (
194 194 <FormItem
195 195 name="userRangeType"
196   - label="跨数据范围授权"
  196 + label="跨门店授权"
197 197 hasFeedback
198 198 rules={[
199   - { required: true, message: "请选择角色数据范围输入类型" },
  199 + { required: true, message: "请选择是否允许跨门店授权" },
200 200 ]}
201 201 >
202 202 <Select
203 203 style={{ width: "100%" }}
204   - placeholder="请选择角色数据范围输入类型"
  204 + placeholder="请选择是否允许跨门店授权"
205 205 >
206 206 {[1, 2].map((item) => (
207 207 <Option key={item} value={item}>
... ...
src/pages/admin/RoleManagementGroup/components/Modal.tsx
... ... @@ -2,7 +2,7 @@
2 2 * @Author: wangqiang@feewee.cn
3 3 * @Date: 2022-06-29 10:44:56
4 4 * @LastEditors: wangqiang@feewee.cn
5   - * @LastEditTime: 2022-07-01 16:13:26
  5 + * @LastEditTime: 2022-11-30 14:34:02
6 6 */
7 7 import {
8 8 Button,
... ... @@ -139,12 +139,7 @@ export default function RoleManagementGrooupModal() {
139 139 />
140 140 </Form.Item>
141 141 <Divider orientation="left">管理组</Divider>
142   - <Form.List
143   - name="roleList"
144   - rules={[
145   - { validator: groupValidator },
146   - ]}
147   - >
  142 + <Form.List name="roleList" rules={[{ validator: groupValidator }]}>
148 143 {(fields, { add, remove }, { errors }) => (
149 144 <>
150 145 {fields.map((field, index) => {
... ... @@ -152,11 +147,17 @@ export default function RoleManagementGrooupModal() {
152 147 <Form.Item
153 148 {...field}
154 149 style={{ flex: 1 }}
155   - label={`${number2text(index + 1)}级管理组`}
  150 + label={
  151 + index > 0 ? `${number2text(index)}级管理` : "基础角色组"
  152 + }
156 153 rules={[
157 154 {
158 155 required: true,
159   - message: `请选择${number2text(index + 1)}级管理组`,
  156 + message: `请选择${
  157 + index > 0
  158 + ? `${number2text(index)}级管理`
  159 + : "基础角色组"
  160 + }`,
160 161 },
161 162 ]}
162 163 >
... ... @@ -221,7 +222,9 @@ function SelectRoleGroup({
221 222 optionFilterProp="label"
222 223 mode={index === 0 ? "multiple" : undefined}
223 224 style={{ flex: 1 }}
224   - placeholder={`请选择${number2text(index + 1)}级管理组`}
  225 + placeholder={`请选择${
  226 + index > 0 ? `${number2text(index)}级管理` : "基础角色组"
  227 + }`}
225 228 onBlur={() => {
226 229 formatRoleList(form.getFieldValue("roleList") || []);
227 230 }}
... ...
src/pages/admin/employee/store.ts
... ... @@ -7,7 +7,7 @@ import useMenuElement from &#39;@/hooks/useMenuElement&#39;;
7 7 import { debounce } from 'lodash';
8 8  
9 9 export default function useStore() {
10   - const { elements } = useMenuElement('EmployeeManagement');
  10 + const { elements } = useMenuElement();
11 11 const pagination = usePagination(employeeListApi, {});
12 12 const [authVisible, setAuthVisible] = useState(false);
13 13 const [currnetUser, setCurrentUser] = useState<Employee>({});
... ...
src/pages/approval/FlowSetting/api.ts
... ... @@ -121,7 +121,10 @@ export function getAbilityPage(): http.PromiseResp&lt;PartStorageSpace.AbilityPageV
121 121 /**
122 122 * 款项列表
123 123 * /common/refundable/types
  124 + * https://admin.feewee.cn/api/finance2/common/refundable/types
  125 + * /common/rpTypes
124 126 */
125 127 export function getFoundPage(): http.PromiseResp<PartStorageSpace.FoundPageVO[]> {
126   - return request.get(`${FINANCE2_HOST}/common/refundable/types`);
  128 + // return request.get(`${FINANCE2_HOST}/common/refundable/types`);
  129 + return request.get(`${FINANCE2_HOST}/common/rpTypes`);
127 130 }
128 131 \ No newline at end of file
... ...
src/pages/approval/FlowSetting/components/Modal.tsx
... ... @@ -12,7 +12,6 @@ import {
12 12 } from "antd";
13 13 import { TriggerType, TriggerAll } from "../entity";
14 14 import _ from "lodash";
15   -// ShopSelect;
16 15 import ShopSelect from "@/components/ShopSelect";
17 16  
18 17 interface PostItem {
... ... @@ -357,32 +356,9 @@ export default function setModal(props: Props) {
357 356 : []
358 357 }
359 358 onChange={(value) => {
360   - console.log("value:", value);
361 359 onChange(data, value, index);
362 360 }}
363 361 />
364   - {/* <Select
365   - disabled={readOnly}
366   - optionFilterProp="children"
367   - labelInValue
368   - value={
369   - originalData.length > 0
370   - ? originalData.map((i: any) => ({
371   - value: i.idOrCode,
372   - label: i.name,
373   - }))
374   - : []
375   - }
376   - mode="multiple"
377   - placeholder="请选择门店"
378   - onChange={(value) => onChange(data, value, index)}
379   - >
380   - {allShopList.map((item) => (
381   - <Option value={item.id} key={item.id}>
382   - {item.name}
383   - </Option>
384   - ))}
385   - </Select> */}
386 362 </div>
387 363 )}
388 364 {type === TriggerType["角色"] && (
... ...
src/pages/attendance/Attend/subpages/AttendanceGroup/api.ts
1   -import { http } from "@/typing/http";
  1 +import { http,PromisePageResp } from "@/typing/http";
2 2 import request from "@/utils/request";
3   -import { ATTENDANCE_HOST } from '@/utils/host';
  3 +import { ATTENDANCE_HOST } from "@/utils/host";
4 4  
5 5 type P<T> = http.PromiseResp<T>;
6   -//type Page<T> = http.PromisePageResp<T>;
  6 +//type Page<T> = http.PromisePageResp<T>;
7 7  
8 8 export interface Item {
9   - id?: number, // 考勤组配置id
10   - name?: number, // 考勤组类型1:正常班次 2:早班 3:晚班
11   - common?: boolean, // 是否集团默认通用配置
12   - cycleTimes?: number, // 打卡周期次数
13   - clockCycle?: number, // 打卡周期
14   - clockInCycles?: Detail[]
  9 + id?: number; // 考勤组配置id
  10 + name?: number; // 考勤组类型1:正常班次 2:早班 3:晚班
  11 + desc?: string;
  12 + common?: boolean; // 是否集团默认通用配置
  13 + cycleTimes?: number; // 打卡周期次数
  14 + timeList: timeList[];
  15 + shops?: Shops[];
15 16 }
16 17  
  18 +interface timeList {
  19 + clockTime?: number; //打卡时间
  20 + noticeType?:number;//
  21 +}
  22 +interface Shops {
  23 + shopId?: number; //适配门店
  24 + shopName?: string; //门店名称
  25 +}
17 26 export interface Detail {
18   - id?: number, // 考勤周期id
19   - clockBeginTime?: number, // 打卡开始时间(例如:9:00)
20   - noticeAdvanceTime?: number, // 待办提前通知时间(分钟)
21   - noticeType?: number, // 待办通知类型 1:提前通知 2:延后通知
22   - defectTime?: number, // 严重迟到时间判定(分钟)
23   - lackTime?: number, //缺卡判定时间(分钟)
  27 + id?: number; // 考勤周期id
  28 + clockBeginTime?: number; // 打卡开始时间(例如:9:00)
  29 + noticeAdvanceTime?: number; // 待办提前通知时间(分钟)
  30 + noticeType?: number; // 待办通知类型 1:提前通知 2:延后通知
  31 + defectTime?: number; // 严重迟到时间判定(分钟)
  32 + lackTime?: number; //缺卡判定时间(分钟)
24 33 }
25 34  
26 35 /**
27 36 * 考勤组类型1:正常班次 2:早班 3:晚班
28 37 */
29 38 export const typeEnum: { [key: number]: string } = {
30   - 0: '',
31   - 1: '正常班次',
32   - 2: '早班',
33   - 3: '晚班',
  39 + 0: "",
  40 + 1: "正常班次",
  41 + 2: "早班",
  42 + 3: "晚班",
34 43 };
35 44  
36   -/**查询考勤组配置*/
37   -export function fetchList(): P<Item[]> {
38   - return request.get(`${ATTENDANCE_HOST}/setting/clock/in/attendance/group/list`);
  45 +/**分页查询考勤组配置列表
  46 + * /attendance/group/setting/getList
  47 +*/
  48 +// export function fetchList(): PromisePageResp<Item[]> {
  49 +export function fetchList(): PromisePageResp<Item> {
  50 + return request.get(`${ATTENDANCE_HOST}/attendance/group/setting/getList`);
39 51 }
40 52  
41   -/**删除考勤组配置*/
  53 +/**删除考勤组配置
  54 + * /attendance/group/setting/del
  55 +*/
42 56 export function deleteApi(id?: number): P<void> {
43   - return request.post(`${ATTENDANCE_HOST}/setting/clock/in/attendance/group/remove?id=${id}`, {id});
  57 + return request.post(`${ATTENDANCE_HOST}/attendance/group/setting/del?id=${id}`, { id });
44 58 }
45 59  
46   -/**查询考勤组配置详情*/
  60 +/**查询考勤组配置详情
  61 + * /attendance/group/setting/getDetail
  62 +*/
47 63 export function fetchDetail(id: number): P<Item> {
48   - return request.get(`${ATTENDANCE_HOST}/setting/clock/in/attendance/group/detail`, {params: {id}});
  64 + return request.get(`${ATTENDANCE_HOST}/attendance/group/setting/getDetail`, { params: { id } });
49 65 }
50 66  
51 67 /**保存考勤组配置*/
52 68 export function saveApi(params?: Item): P<void> {
53   - return request.post(`${ATTENDANCE_HOST}/setting/clock/in/attendance/group/save`, params);
54   -}
55 69 \ No newline at end of file
  70 + return request.post(`${ATTENDANCE_HOST}/attendance/group/setting/saveOrUpdate`, params);
  71 +}
  72 +
  73 +interface BaseSettingItem {
  74 + id?: number;
  75 + noticeTime?: number; //待办提前通知时间(分钟)
  76 + defectTime?: number; //严重迟到时间判定(分钟)
  77 + lackTime?: number; //缺卡判定时间
  78 +}
  79 +/**获取考勤组基础设置
  80 + * /attendance/base/setting/get
  81 + */
  82 +export function fetchBaseSettingApi(): P<BaseSettingItem> {
  83 + return request.get(`${ATTENDANCE_HOST}/attendance/base/setting/get`);
  84 +}
  85 +
  86 +/**保存/更新考勤组基础设置*/
  87 +export function saveOrUpdateApi(params?: BaseSettingItem): P<void> {
  88 + return request.post(`${ATTENDANCE_HOST}/attendance/base/setting/saveOrUpdate`, params);
  89 +}
... ...
src/pages/attendance/Attend/subpages/AttendanceGroup/components/GroupDetail/Modal.tsx
... ... @@ -31,12 +31,12 @@ function SelectModal({ onCancel, onOk, row = {}, visible, value = [] }: Props) {
31 31  
32 32 function handSave(feilds: any) {
33 33 const newRow = {
34   - id: row.id || value.length + 1,
  34 + id: row.id,
35 35 defectTime: feilds.defectTime,
36 36 clockBeginTime: time,
37 37 noticeType: feilds.noticeType,
38 38 noticeAdvanceTime: feilds.noticeAdvanceTime,
39   - lackTime: feilds.lackTime
  39 + lackTime: feilds.lackTime,
40 40 };
41 41 onOk && onOk(newRow);
42 42 onCancel && onCancel();
... ... @@ -45,7 +45,7 @@ function SelectModal({ onCancel, onOk, row = {}, visible, value = [] }: Props) {
45 45 return (
46 46 <Modal
47 47 width={700}
48   - visible={visible}
  48 + open={visible}
49 49 title="打卡时间"
50 50 onCancel={onCancel}
51 51 onOk={form.submit}
... ... @@ -77,39 +77,6 @@ function SelectModal({ onCancel, onOk, row = {}, visible, value = [] }: Props) {
77 77 <Option value={2}>延后通知</Option>
78 78 </Select>
79 79 </FormItem>
80   - <FormItem
81   - label="待办通知"
82   - rules={[{ required: true, message: "请填写待办通知" }]}
83   - name="noticeAdvanceTime"
84   - >
85   - <InputNumber
86   - min={0}
87   - style={{ width: 200 }}
88   - formatter={(value) => `${value}分钟`}
89   - />
90   - </FormItem>
91   - <FormItem
92   - label="严重迟到判定"
93   - rules={[{ required: true, message: "请填写严重迟到判定" }]}
94   - name="defectTime"
95   - >
96   - <InputNumber
97   - min={0}
98   - style={{ width: 200 }}
99   - formatter={(value) => `${value}分钟`}
100   - />
101   - </FormItem>
102   - <FormItem
103   - label="缺卡时间判定"
104   - rules={[{ required: true, message: "请填写缺卡时间判定" }]}
105   - name="lackTime"
106   - >
107   - <InputNumber
108   - min={0}
109   - style={{ width: 200 }}
110   - formatter={(value) => `${value}分钟`}
111   - />
112   - </FormItem>
113 80 </Form>
114 81 </Modal>
115 82 );
... ...
src/pages/attendance/Attend/subpages/AttendanceGroup/components/GroupDetail/index.tsx
1 1 import React, { useCallback, useState, memo, Ref, forwardRef } from "react";
2   -import { Card, Button, Table, Divider, Popconfirm} from "antd";
  2 +import { Card, Button, Table, Divider, Popconfirm } from "antd";
3 3 import { PlusOutlined } from "@ant-design/icons";
4 4 import Modal from "./Modal";
5 5  
6 6 const { Column } = Table;
7 7  
8   -function GroupDetail(
9   - { value = [], onChange, disabled }: any,
10   - ref: Ref<any>
11   -) {
  8 +function GroupDetail({ value = [], onChange, disabled }: any, ref: Ref<any>) {
12 9 const [visiData, setVisiData] = useState<{
13 10 visible: boolean;
14 11 row: any;
15 12 }>({ visible: false, row: {} });
16 13  
17 14 function onDelete(id: number) {
18   - const newValue = value.filter((val:any) => val.id != id);
  15 + const newValue=[...value];
  16 + newValue.splice(id, 1);
19 17 onChange && onChange(newValue);
20 18 }
21 19  
22 20 const onOk = useCallback(
23 21 (newRow: any) => {
24 22 const newValue = [...value];
25   - const index = newValue.findIndex((val) => val.id == newRow.id);
26   - if (index > -1) {
27   - newValue.splice(index, 1, newRow);
28   - } else {
  23 + if (newRow.id === -1) {
29 24 newValue.push(newRow);
  25 + } else {
  26 + newValue.splice(newRow.id, 1, newRow);
30 27 }
  28 +
31 29 onChange && onChange(newValue);
32 30 },
33 31 [value]
34 32 );
35 33  
36 34 /** 切换弹窗显示 */
37   - const triggerModal = useCallback(
38   - (row: any= {}, visible: boolean = false) => {
39   - setVisiData({ visible, row });
40   - },
41   - []
42   - );
  35 + const triggerModal = useCallback((row: any = {}, visible: boolean = false) => {
  36 + setVisiData({ visible, row });
  37 + }, []);
43 38  
44 39 return (
45 40 <Card
... ... @@ -53,11 +48,7 @@ function GroupDetail(
53 48 flexDirection: "row",
54 49 }}
55 50 >
56   - <Button
57   - type="primary"
58   - icon={<PlusOutlined />}
59   - onClick={() => triggerModal({}, true)}
60   - >
  51 + <Button type="primary" icon={<PlusOutlined />} onClick={() => triggerModal({ id: -1 }, true)}>
61 52 新增
62 53 </Button>
63 54 </div>
... ... @@ -65,20 +56,13 @@ function GroupDetail(
65 56 }
66 57 >
67 58 <Table
68   - rowKey="id"
  59 + rowKey={(record: any) => `${record.id}_${record.noticeType}_${record.clockBeginTime}`}
69 60 dataSource={value}
70 61 pagination={false}
71 62 bordered
72 63 size="small"
73 64 >
74   - <Column
75   - title="打卡时间"
76   - dataIndex="clockBeginTime"
77   - width="20%"
78   - ellipsis
79   - align="center"
80   - //render={(text: any, record: any) => moment(text).format("HH:mm")}
81   - />
  65 + <Column title="打卡时间" dataIndex="clockBeginTime" width="20%" ellipsis align="center" />
82 66 <Column
83 67 title="待办通知类型"
84 68 dataIndex="noticeType"
... ... @@ -86,38 +70,24 @@ function GroupDetail(
86 70 render={(text: any, record: any) => (text === 1 ? "提前通知" : "延后通知")}
87 71 align="center"
88 72 />
89   - <Column
90   - title="待办通知"
91   - dataIndex="noticeAdvanceTime"
92   - ellipsis
93   - render={(text: any, record: any) => `${text}分钟`}
94   - align="center"
95   - />
96   - <Column title="严重迟到判定" align="center" dataIndex="defectTime" ellipsis render={(text: any, record: any) => `${text}分钟`} />
97   - <Column title="缺卡时间判定" align="center" dataIndex="lackTime" ellipsis render={(text: any, record: any) => `${text}分钟`} />
98 73 {!disabled && (
99 74 <Column
100 75 title="操作"
101 76 align="center"
102   - width="20%"
  77 + width="30%"
103 78 dataIndex="accountNo"
104 79 render={(no, row: any, i) => (
105 80 <>
106 81 <a
107 82 onClick={(e) => {
108 83 e.preventDefault();
109   - triggerModal(row, true);
  84 + triggerModal({ ...row, id: i }, true);
110 85 }}
111 86 >
112 87 编辑
113 88 </a>
114 89 <Divider type="vertical" />
115   - <Popconfirm
116   - title="是否删除?"
117   - onConfirm={() => onDelete(row.id)}
118   - okText="确定"
119   - cancelText="取消"
120   - >
  90 + <Popconfirm title="是否删除?" onConfirm={() => onDelete(i)} okText="确定" cancelText="取消">
121 91 <a onClick={(e) => e.preventDefault()}>删除</a>
122 92 </Popconfirm>
123 93 </>
... ... @@ -125,13 +95,7 @@ function GroupDetail(
125 95 />
126 96 )}
127 97 </Table>
128   - <Modal
129   - row={visiData.row}
130   - visible={visiData.visible}
131   - onCancel={triggerModal}
132   - onOk={onOk}
133   - value={value}
134   - />
  98 + <Modal row={visiData.row} visible={visiData.visible} onCancel={triggerModal} onOk={onOk} value={value} />
135 99 </Card>
136 100 );
137 101 }
... ...
src/pages/attendance/Attend/subpages/AttendanceGroup/components/GroupModal.tsx
1   -import React, {useEffect } from "react";
2   -import { Modal, Form, Select, message, Radio, InputNumber } from "antd";
3   -import GroupDetail from './GroupDetail/index';
4   -import * as API from '../api';
  1 +import React, { useEffect, useState } from "react";
  2 +import { Modal, Form, Select, message, Radio, Input } from "antd";
  3 +import GroupDetail from "./GroupDetail/index";
  4 +import * as API from "../api";
  5 +import ShopSelectNew from "@/components/ShopSelectNew";
5 6  
6 7 const FormItem = Form.Item;
7 8 const { Option } = Select;
... ... @@ -14,17 +15,27 @@ interface Props {
14 15 setLoading: (loading: boolean) => void;
15 16 }
16 17  
17   -export default function GroupModal(props:Props) {
  18 +export default function GroupModal(props: Props) {
18 19 const { visible, setVisible, current, setCurrent, setLoading } = props;
19 20 const [form] = Form.useForm();
  21 + const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
20 22  
21 23 useEffect(() => {
22 24 if (current) {
23 25 form.setFieldsValue({
  26 + ...current,
24 27 cycleTimes: current.cycleTimes,
25   - name: current.name,
  28 + name: 1,
26 29 common: current.common,
27 30 clockInCycles: current.clockInCycles,
  31 + shops:
  32 + current.shops &&
  33 + current.shops.map((item: any) => ({
  34 + ...item,
  35 + shopShortName: item.shopName,
  36 + label: item.shopName,
  37 + value: item.shopId,
  38 + })),
28 39 });
29 40 } else {
30 41 form.resetFields();
... ... @@ -32,17 +43,25 @@ export default function GroupModal(props:Props) {
32 43 }, [visible]);
33 44  
34 45 function submit(item: any) {
  46 + setConfirmLoading(true);
  47 + const { shops = [], clockInCycles = [] } = item;
  48 +
35 49 const param = {
36 50 id: current.id,
37 51 ...item,
  52 + shops: shops.map((item) => ({ shopId: item.value, shopName: item.label })),
  53 + cycleTimes: clockInCycles.length,
38 54 };
39 55 API.saveApi(param)
40 56 .then((res) => {
  57 + setConfirmLoading(false);
41 58 message.success("保存成功");
42 59 setVisible(false);
43 60 setLoading(true);
44 61 })
45 62 .catch((err) => {
  63 + setConfirmLoading(false);
  64 +
46 65 message.error(err.message);
47 66 });
48 67 }
... ... @@ -54,59 +73,56 @@ export default function GroupModal(props:Props) {
54 73  
55 74 return (
56 75 <Modal
57   - title={`${current.id ? "编辑" : "新增"}考勤`}
58   - visible={visible}
  76 + title={`${current.id ? "编辑" : "新增"}考勤组`}
  77 + open={visible}
59 78 onOk={form.submit}
60 79 onCancel={onCancel}
  80 + confirmLoading={confirmLoading}
61 81 maskClosable={false}
62 82 afterClose={() => {
63 83 setCurrent({});
  84 + form.resetFields();
64 85 }}
65 86 width="60%"
66 87 >
67   - <Form
68   - form={form}
69   - onFinish={submit}
70   - labelCol={{ span: 6 }}
71   - wrapperCol={{ span: 15 }}
72   - >
73   - <FormItem
74   - name="cycleTimes"
75   - label="打卡周期次数"
76   - rules={[{ required: true, message: "请填写打开周期次数" }]}
77   - >
78   - <InputNumber
79   - min={0}
80   - style={{ width: 200 }}
81   - formatter={(value) => `${value}次`}
82   - parser={(value: any) => value.replace("次", "")}
83   - disabled={current.id}
84   - />
85   - </FormItem>
86   - <FormItem
87   - name="name"
88   - label="考勤类型"
89   - rules={[{ required: true, message: "请填写考勤类型" }]}
  88 + <Form form={form} onFinish={submit} labelCol={{ span: 6 }} wrapperCol={{ span: 20 }}>
  89 +
  90 + <Form.Item
  91 + name="attendanceGroupName"
  92 + label="考勤组名称"
  93 + rules={[{ required: true, message: "请输入考勤组名称" }]}
90 94 >
91   - <Select style={{ width: 200 }}>
  95 + <Input style={{ width: "100%" }} />
  96 + </Form.Item>
  97 + <FormItem name="name" label="班组类型" rules={[{ required: true, message: "班组类型" }]}>
  98 + <Select>
92 99 <Option value={1}>正常班次</Option>
93 100 </Select>
94 101 </FormItem>
95   - <FormItem
96   - name="common"
97   - label="是否集团通用配置"
98   - rules={[{ required: true, message: "请选择集团通用配置" }]}
99   - >
  102 + <FormItem name="common" label="是否集团通用配置" rules={[{ required: true, message: "请选择集团通用配置" }]}>
100 103 <Radio.Group>
101 104 <Radio value>是</Radio>
102 105 <Radio value={false}>否</Radio>
103 106 </Radio.Group>
104 107 </FormItem>
105   - <FormItem
106   - name="clockInCycles"
107   - label="打卡周期明细"
108   - rules={[{ required: true, message: "请填写打卡周期明细" }]}
109   - >
  108 +
  109 + <Form.Item noStyle shouldUpdate={(prevValues, currentValues) => prevValues.common !== currentValues.common}>
  110 + {({ getFieldValue }) => {
  111 + const _common = getFieldValue("common");
  112 + if (!_common) {
  113 + return (
  114 + <>
  115 + <Form.Item name="shops" label="适用门店">
  116 + <ShopSelectNew multiple />
  117 + </Form.Item>
  118 + </>
  119 + );
  120 + }
  121 + return null;
  122 + }}
  123 + </Form.Item>
  124 +
  125 + <FormItem name="clockInCycles" label="打卡周期明细" rules={[{ required: true, message: "请填写打卡周期明细" }]}>
110 126 <GroupDetail />
111 127 </FormItem>
112 128 </Form>
... ...
src/pages/attendance/Attend/subpages/AttendanceGroup/components/TimeConfig.tsx 0 → 100644
  1 +import { Button, Form, InputNumber, message, Popconfirm, Radio, Row, Select } from "antd";
  2 +import React, { useEffect, useState } from "react";
  3 +import useInitial from "@/hooks/useInitail";
  4 +import { fetchBaseSettingApi, saveOrUpdateApi } from "@/pages/attendance/Attend/subpages/AttendanceGroup/api";
  5 +
  6 +const FormItem = Form.Item;
  7 +
  8 +export default function TimeConfig() {
  9 + const [form] = Form.useForm();
  10 + const [edit, setEdit] = useState<boolean>(false);
  11 + const [reset, setReset] = useState<boolean>(false);
  12 + const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
  13 + const { data } = useInitial(fetchBaseSettingApi, {}, null);
  14 +
  15 + useEffect(() => {
  16 + form.setFieldsValue({ ...data });
  17 + }, [data]);
  18 + useEffect(() => {
  19 + if (reset) {
  20 + form.setFieldsValue({ ...data });
  21 + }
  22 + }, [reset]);
  23 + function submit(item: any) {
  24 + setConfirmLoading(true);
  25 + const param = {
  26 + ...item,
  27 + id: data.id,
  28 + };
  29 +
  30 + saveOrUpdateApi(param)
  31 + .then((res) => {
  32 + setConfirmLoading(false);
  33 + setEdit(false);
  34 + message.success("保存成功");
  35 + })
  36 + .catch((err) => {
  37 + setConfirmLoading(false);
  38 + message.error(err.message);
  39 + });
  40 + }
  41 +
  42 + function handleEdit() {
  43 + if (edit) {
  44 + setEdit(false);
  45 + } else {
  46 + setEdit(true);
  47 + }
  48 + }
  49 +
  50 + return (
  51 + <div>
  52 + <Form form={form} onFinish={submit} labelCol={{ span: 6 }} wrapperCol={{ span: 15 }}>
  53 + <div
  54 + style={{
  55 + display: "flex",
  56 + justifyContent: "flex-start",
  57 + alignItems: "center",
  58 + marginTop: 20,
  59 + paddingLeft: "20%",
  60 + }}
  61 + >
  62 + <span style={{ color: "#ff4d4f" }}>*</span> 打卡时间要求:
  63 + <div>
  64 + <span style={{ marginRight: 5, marginLeft: 5 }}> 提前</span>
  65 + <FormItem
  66 + name="onDutyNoticeTime"
  67 + label="打卡时间要求"
  68 + noStyle
  69 + rules={[{ required: true, message: "请填写打卡时间要求" }]}
  70 + >
  71 + <InputNumber
  72 + min={0}
  73 + style={{ width: 200 }}
  74 + formatter={(value) => `${value}分钟`}
  75 + parser={(value: any) => value.replace("分钟", "")}
  76 + disabled={!edit}
  77 + />
  78 + </FormItem>
  79 + <span style={{ marginLeft: 5 }}>
  80 + 到应打卡时间 <span style={{ color: "#999999" }}>(除最后一次应打卡)</span>
  81 + </span>
  82 + </div>
  83 + </div>
  84 +
  85 + <div
  86 + style={{
  87 + display: "flex",
  88 + justifyContent: "flex-start",
  89 + alignItems: "center",
  90 + marginTop: 20,
  91 + paddingLeft: "20%",
  92 + }}
  93 + >
  94 + <span style={{ color: "#ff4d4f" }}>*</span> 最后一次应打卡时间要求:
  95 + <div>
  96 + <span style={{ marginRight: 5, marginLeft: 5 }}> 应打卡时间延后</span>
  97 + <FormItem
  98 + name="offDutyNoticeTime"
  99 + label="打卡时间要求"
  100 + noStyle
  101 + rules={[{ required: true, message: "请填写打卡时间要求" }]}
  102 + >
  103 + <InputNumber
  104 + min={0}
  105 + style={{ width: 200 }}
  106 + formatter={(value) => `${value}分钟`}
  107 + parser={(value: any) => value.replace("分钟", "")}
  108 + disabled={!edit}
  109 + />
  110 + </FormItem>
  111 + <span style={{ color: "#999999", marginLeft: 5 }}>(当天仅一次打卡不计此情况)</span>
  112 + </div>
  113 + </div>
  114 +
  115 + <div
  116 + style={{
  117 + display: "flex",
  118 + justifyContent: "flex-start",
  119 + alignItems: "center",
  120 + marginTop: 20,
  121 + paddingLeft: "20%",
  122 + }}
  123 + >
  124 + <span style={{ color: "#ff4d4f" }}>*</span> 严重迟到判定:
  125 + <div>
  126 + <span style={{ marginLeft: 5, marginRight: 5 }}>在应打卡时间延后</span>
  127 +
  128 + <FormItem name="defectTime" noStyle rules={[{ required: true, message: "请填写严重迟到时间判定(分钟)" }]}>
  129 + <InputNumber
  130 + min={0}
  131 + style={{ width: 200 }}
  132 + formatter={(value) => `${value}分钟`}
  133