Commit 5fd4d7fc948ddee569bdc9bf85de9c4405ca4d07

Authored by 王强
2 parents 1248f1eb 6f86f8a0

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

Showing 54 changed files with 1605 additions and 1208 deletions
config/routers/angel.ts
... ... @@ -10,8 +10,8 @@ export default [
10 10 component: './carinsur/PurchaseConfig',
11 11 },
12 12 {
13   - path: '/angel/loan/client/config', //贷款客户保险要求配置
14   - component: './carinsur/LoanClientConfig',
  13 + path: '/angel/loanClientRequires', // 贷款期客户保险配置
  14 + component: './carinsur/LoanClientRequires',
15 15 },
16 16  
17 17 {
... ...
config/routers/contract.ts
... ... @@ -99,4 +99,8 @@ export default [
99 99 path: '/contract/kt/stampmatter', //盖章事项
100 100 component: './contract/StampMatter',
101 101 },
  102 + {
  103 + path: '/contract/foodWhiteList', // 就餐白名单
  104 + component: './contract/FoodWhiteList',
  105 + },
102 106 ];
... ...
src/components/Condition/BrandToSeries/index.tsx
... ... @@ -5,47 +5,50 @@ import * as API from './api';
5 5  
6 6 interface BrandToSeriesProps extends CascaderProps {
7 7 /** 第一层 品牌列表 */
8   - brandList?: API.Brand[] | API.optionItem[],
9   - labelInValue?: boolean,
10   - value?: any[],
11   - onChange?: (value: any, ...other: any) => any,
  8 + brandList?: API.Brand[] | API.optionItem[];
  9 + labelInValue?: boolean;
  10 + value?: any[];
  11 + onChange?: (value: any, ...other: any) => any;
12 12 /** 是否授权品牌(授权品牌接口是admin,非授权品牌接口是oop) */
13   - authBrand?: boolean
  13 + authBrand?: boolean;
  14 + placeholder?: string;
14 15 }
15 16  
16 17 /**
17 18 * 基于Cascader封装的品牌车系级联选择框
18 19 */
19 20 export default function BrandToSeries(props: BrandToSeriesProps) {
20   - const { value = [], onChange, labelInValue, brandList, placeholder = "请选择品牌/车系", authBrand, ...other } = props;
  21 + const { value = [], onChange, labelInValue, brandList, placeholder = '请选择品牌/车系', authBrand, ...other } = props;
21 22 const [options, setOptions] = useState<any[]>([]);
22 23 const [selected, setSelected] = useState<any[]>([]);
23 24  
24 25 useEffect(() => {
25 26 if (!brandList) {
26 27 const brandApi: any = authBrand ? API.authBrandsApi : API.brandByOopApi;
27   - brandApi().then(res => {
28   - const { data = [] } = res;
29   - const _data = data.map(brand => ({ id: brand.brandId || brand.id, name: brand.brandName || brand.name, isLeaf: false }));
30   - setOptions([..._data]);
31   - }).catch(e => {
32   - message.error(e.message);
33   - });
  28 + brandApi()
  29 + .then((res) => {
  30 + const { data = [] } = res;
  31 + const _data = data.map((brand) => ({ id: brand.brandId || brand.id, name: brand.brandName || brand.name, isLeaf: false }));
  32 + setOptions([..._data]);
  33 + })
  34 + .catch((e) => {
  35 + message.error(e.message);
  36 + });
34 37 } else {
35   - setOptions(brandList.map(brand => ({ id: brand.brandId || brand.id, name: brand.brandName || brand.name, isLeaf: false })))
  38 + setOptions(brandList.map((brand) => ({ id: brand.brandId || brand.id, name: brand.brandName || brand.name, isLeaf: false })));
36 39 }
37   - }, [])
  40 + }, []);
38 41  
39 42 useEffect(() => {
40 43 if (selected.length === 0 && value.length > 0) {
41 44 const valueBrandId = labelInValue ? value[0].id : value[0];
42   - loadData(options.filter(item => item.id === valueBrandId));
  45 + loadData(options.filter((item) => item.id === valueBrandId));
43 46 }
44 47 if (value[1] !== selected[1]) {
45   - const _value = labelInValue ? value.map(item => item.id) : value;
  48 + const _value = labelInValue ? value.map((item) => item.id) : value;
46 49 setSelected(_value);
47 50 }
48   - }, [value[1]])
  51 + }, [value[1]]);
49 52  
50 53 function loadData(selectedOptions?: CascaderOptionType[]) {
51 54 if (selectedOptions && selectedOptions.length > 0) {
... ... @@ -53,23 +56,25 @@ export default function BrandToSeries(props: BrandToSeriesProps) {
53 56 const targetOption = selectedOptions[length - 1];
54 57 targetOption.loading = true;
55 58 if (length === 1) {
56   - API.getSeriesApi(targetOption.id).then(res => {
57   - const { data = [] } = res;
58   - targetOption.loading = false;
59   - targetOption.children = data.map((list, index) => ({
60   - id: list.id,
61   - name: list.name,
62   - }));
63   - setOptions([...options])
64   - }).catch(e => {
65   - message.error(e.message);
66   - });
  59 + API.getSeriesApi(targetOption.id)
  60 + .then((res) => {
  61 + const { data = [] } = res;
  62 + targetOption.loading = false;
  63 + targetOption.children = data.map((list, index) => ({
  64 + id: list.id,
  65 + name: list.name,
  66 + }));
  67 + setOptions([...options]);
  68 + })
  69 + .catch((e) => {
  70 + message.error(e.message);
  71 + });
67 72 }
68 73 }
69 74 }
70 75  
71 76 function _onChange(value: string[], selectedOptions: any[] = []) {
72   - const _value = labelInValue ? selectedOptions.map(item => ({ id: item.id, name: item.name })) : value;
  77 + const _value = labelInValue ? selectedOptions.map((item) => ({ id: item.id, name: item.name })) : value;
73 78 setSelected(value || []);
74 79 onChange && onChange(_value || [], selectedOptions);
75 80 }
... ... @@ -82,9 +87,8 @@ export default function BrandToSeries(props: BrandToSeriesProps) {
82 87 loadData={loadData}
83 88 value={selected.length <= 0 ? undefined : selected}
84 89 onChange={_onChange}
85   - fieldNames={{ value: 'id', label: 'name', }}
  90 + fieldNames={{ value: 'id', label: 'name' }}
86 91 notFoundContent="暂无数据"
87 92 />
88   -
89 93 );
90 94 }
... ...
src/pages/approval/ApprovalSetting/subpages/components/CommonSettingForm.tsx
... ... @@ -17,7 +17,7 @@ interface TableRoleItem {
17 17  
18 18 interface Props {
19 19 small?: boolean;
20   - shopBizTypes: string[];
  20 + shopBizTypes: number[]; // 从预设条件为门店的选项值中提取 bizType 交集
21 21 roles: ApprovalSetting.ApprovalRoleItem[][];
22 22 setRoles: (value: ApprovalSetting.ApprovalRoleItem[][]) => void;
23 23 groupRoot?: boolean;
... ... @@ -99,7 +99,7 @@ export default function CommonSettingForm({ small = false, shopBizTypes, roles,
99 99 roleListHook
100 100 .run({
101 101 configuredRoleCodes: ids.join(','),
102   - shopBizTypes: shopBizTypes.join(','),
  102 + // shopBizTypes: shopBizTypes.join(','), // 门店业态和门店预设条件去掉后,审批配置此接口不传此参数
103 103 })
104 104 .then((res) => {
105 105 setRoleList(res ?? []);
... ...
src/pages/approval/ApprovalSetting/subpages/components/DefaultFlowNewOrEdit.tsx
... ... @@ -16,7 +16,6 @@ import {
16 16 BrandSelector,
17 17 RPTypesSelector,
18 18 BizTypeSelector,
19   - ShopBizTypeSelector,
20 19 OfficeWordTypeSelector,
21 20 ContractTypeSelector,
22 21 } from './Selectors';
... ... @@ -81,6 +80,17 @@ export default function DefaultSettingNewOrEdit(props: Props) {
81 80 }
82 81 });
83 82 const newCondVals = (data?.conditionValues ?? []).concat(essVals);
  83 + // idOrCode to idOrCode--bizType
  84 + newCondVals.forEach((n) => {
  85 + if (n.flowTriggerDto.type === TriggerType.门店) {
  86 + const value = JSON.parse(n.value).map((i: FlowSetting.CondValItem) => ({
  87 + idOrCode: `${i.idOrCode}--${i.bizType}`,
  88 + name: i.name,
  89 + bizType: i.bizType,
  90 + }));
  91 + n.value = JSON.stringify(value);
  92 + }
  93 + });
84 94 setConditionVals(newCondVals);
85 95  
86 96 setRoles(data?.approvalRoles ?? []);
... ... @@ -101,17 +111,36 @@ export default function DefaultSettingNewOrEdit(props: Props) {
101 111 }
102 112 }, [visible, data]);
103 113  
104   - // 获取已配置的门店业态条件值
  114 + // 从已选择门店中自动计算 bizType 交集
105 115 const shopBizTypes = useMemo(() => {
106   - const currType = conditionVals.find((i) => i.flowTriggerDto.type === TriggerType.门店业态);
107   - if (!currType) return [];
108   - try {
109   - const options = JSON.parse(currType.value);
110   - return options.map((i: FlowSetting.CondValItem) => i.idOrCode);
111   - } catch {
112   - return [];
113   - }
  116 + const shopCondVals = conditionVals.filter((i) => i.flowTriggerDto.type === TriggerType.门店);
  117 + if (!shopCondVals.length) return [];
  118 + const bizTypeSet = new Set<number>();
  119 + shopCondVals.forEach((s) => {
  120 + try {
  121 + const options = JSON.parse(s.value);
  122 + options.forEach((o: FlowSetting.CondValItem) => {
  123 + bizTypeSet.add(o.bizType!);
  124 + });
  125 + } catch {}
  126 + });
  127 + return Array.from(bizTypeSet.values());
114 128 }, [conditionVals]);
  129 + // 计算最新 bizType 交集
  130 + const getShopBizTypes = (cVals: ApprovalSetting.ConditionVal[]) => {
  131 + const shopCondVals = cVals.filter((i) => i.flowTriggerDto.type === TriggerType.门店);
  132 + if (!shopCondVals.length) return [];
  133 + const bizTypeSet = new Set<number>();
  134 + shopCondVals.forEach((s) => {
  135 + try {
  136 + const options = JSON.parse(s.value);
  137 + options.forEach((o: FlowSetting.CondValItem) => {
  138 + bizTypeSet.add(o.bizType!);
  139 + });
  140 + } catch {}
  141 + });
  142 + return Array.from(bizTypeSet.values());
  143 + };
115 144  
116 145 const hide = () => {
117 146 onCancel && onCancel();
... ... @@ -128,6 +157,17 @@ export default function DefaultSettingNewOrEdit(props: Props) {
128 157 message.error('请填写全部触发条件的对应值');
129 158 return;
130 159 }
  160 + // idOrCode--bizType to idOrCode
  161 + conditionVals.forEach((n) => {
  162 + if (n.flowTriggerDto.type === TriggerType.门店) {
  163 + const value = JSON.parse(n.value).map((i: FlowSetting.CondValItem) => ({
  164 + idOrCode: i.idOrCode.split('--')[0]!,
  165 + name: i.name,
  166 + bizType: i.bizType,
  167 + }));
  168 + n.value = JSON.stringify(value);
  169 + }
  170 + });
131 171 form.validateFields().then((values) => {
132 172 const { seniorApprove } = values;
133 173 if (!seniorApprove && roles.length === 0) {
... ... @@ -146,35 +186,39 @@ export default function DefaultSettingNewOrEdit(props: Props) {
146 186 });
147 187 };
148 188  
149   - // 门店业态值只要变化则清空已添加审批角色列表
150   - const clearRoles = () => {
151   - setRoles([]);
152   - };
153   -
154   - // 选择|取消选择门店业态
155   - const handleShopBizTypeChange = (value: number) => {
156   - const currType = (selectList.find((i) => i.value === value) ?? {}).extral;
157   - if (currType?.type === TriggerType.门店业态) {
158   - clearRoles();
159   - }
  189 + // 门店业态值减少时交互:旧业态值不存在于新业态值数组
  190 + const clearRoles = (newCondVals: ApprovalSetting.ConditionVal[]) => {
  191 + const oldShopBizTypes = [...shopBizTypes];
  192 + const newShopBizTypes = getShopBizTypes(newCondVals);
  193 + oldShopBizTypes.forEach((i) => {
  194 + if (!newShopBizTypes.includes(i)) {
  195 + // 清空已添加审批角色列表
  196 + setRoles([]);
  197 + }
  198 + });
160 199 };
161 200  
162 201 const onConditionChange = (item: ApprovalSetting.ConditionVal, values: any, index: number) => {
163   - if (item.flowTriggerDto.type === TriggerType.门店业态) {
164   - // 审批角色清空
165   - clearRoles();
166   - // 门店组件清空
167   - const shopValIdx = conditionVals.findIndex((i) => i.flowTriggerDto.type === TriggerType.门店);
168   - if (shopValIdx > -1) {
169   - conditionVals[shopValIdx].value = '';
170   - }
171   - }
172   - const newValue = Array.isArray(values) ? values.map((i) => ({ idOrCode: i.value, name: i.label })) : values;
173 202 const { value, flowTriggerDto } = item;
  203 +
  204 + // idOrCode--bizType
  205 + let newValue;
  206 + if (flowTriggerDto.type === TriggerType.门店) {
  207 + newValue = Array.isArray(values)
  208 + ? values.map((i) => {
  209 + const currBizType = i.value.split('--')[1]!;
  210 + return { idOrCode: i.value, name: i.label, bizType: Number(currBizType) };
  211 + })
  212 + : values;
  213 + } else {
  214 + newValue = Array.isArray(values) ? values.map((i) => ({ idOrCode: i.value, name: i.label })) : values;
  215 + }
  216 +
  217 + // 计算新条件值
  218 + const newCondVals = [...conditionVals];
174 219 if (flowTriggerDto && [2, 3, 4, 5, 6, 7, 8].includes(flowTriggerDto.judgeRule ?? 0)) {
175 220 const _item = { ...item, value: JSON.stringify(newValue) };
176   - conditionVals[index] = _item;
177   - setConditionVals([...conditionVals]);
  221 + newCondVals[index] = _item;
178 222 } else {
179 223 const _item = {
180 224 ...item,
... ... @@ -183,9 +227,16 @@ export default function DefaultSettingNewOrEdit(props: Props) {
183 227 ...newValue,
184 228 }),
185 229 };
186   - conditionVals[index] = _item;
187   - setConditionVals([...conditionVals]);
  230 + newCondVals[index] = _item;
  231 + }
  232 +
  233 + // 门店业态值减少时交互
  234 + if (flowTriggerDto.type === TriggerType.门店) {
  235 + clearRoles(newCondVals);
188 236 }
  237 +
  238 + // 更新条件值
  239 + setConditionVals(newCondVals);
189 240 };
190 241  
191 242 // 选择需要配置的预设条件
... ... @@ -194,6 +245,10 @@ export default function DefaultSettingNewOrEdit(props: Props) {
194 245 const currVal = conditionVals.find((c) => c.flowTriggerDto.id === i);
195 246 return { value: currVal ? currVal.value : '', flowTriggerDto: preCondition.find((p) => p.id === i)! };
196 247 });
  248 +
  249 + // 门店业态值减少时交互
  250 + clearRoles(tempVals);
  251 +
197 252 setConditionVals(tempVals);
198 253 };
199 254  
... ... @@ -207,6 +262,7 @@ export default function DefaultSettingNewOrEdit(props: Props) {
207 262 cancelButtonProps={{ disabled: loading }}
208 263 onCancel={hide}
209 264 onOk={onSave}
  265 + destroyOnClose
210 266 >
211 267 <Form form={form}>
212 268 <Form.Item name="id" hidden />
... ... @@ -214,15 +270,7 @@ export default function DefaultSettingNewOrEdit(props: Props) {
214 270 <Input placeholder="请输入" maxLength={64} />
215 271 </Form.Item>
216 272 <Form.Item label="触发条件" name="conditions" rules={[{ required: false, message: '请选择需要配置的条件' }]}>
217   - <Select
218   - mode="multiple"
219   - style={{ width: '100%' }}
220   - allowClear
221   - placeholder="请选择"
222   - onChange={onSelectCondition}
223   - onSelect={handleShopBizTypeChange}
224   - onDeselect={handleShopBizTypeChange}
225   - >
  273 + <Select mode="multiple" style={{ width: '100%' }} allowClear placeholder="请选择" onChange={onSelectCondition}>
226 274 {selectList.map((item: SelectItem) => (
227 275 <Option value={item.value} key={item.value} extral={item.extral} disabled={item.extral.essential}>
228 276 {item.label}
... ... @@ -290,7 +338,6 @@ export default function DefaultSettingNewOrEdit(props: Props) {
290 338 labelInValue
291 339 multiple
292 340 initType={1}
293   - bizTypes={shopBizTypes.join(',')}
294 341 value={
295 342 originalData.length > 0
296 343 ? originalData.map((i: any) => ({
... ... @@ -371,9 +418,6 @@ export default function DefaultSettingNewOrEdit(props: Props) {
371 418 {type === TriggerType['报销类型'] && (
372 419 <BizTypeSelector visible={type === TriggerType['报销类型']} index={index} item={item} onChange={onConditionChange} />
373 420 )}
374   - {type === TriggerType['门店业态'] && (
375   - <ShopBizTypeSelector visible={type === TriggerType['门店业态']} index={index} item={item} onChange={onConditionChange} />
376   - )}
377 421 {type === TriggerType['工作类型'] && (
378 422 <OfficeWordTypeSelector visible={type === TriggerType['工作类型']} index={index} item={item} onChange={onConditionChange} />
379 423 )}
... ...
src/pages/approval/FlowSetting/interface.d.ts
... ... @@ -138,5 +138,6 @@ declare namespace FlowSetting {
138 138 interface CondValItem {
139 139 idOrCode: string;
140 140 name: string;
  141 + bizType?: number; // 预设条件为门店时会手动赋值
141 142 }
142 143 }
... ...
src/pages/approval/FlowSetting/subpages/ConditionSetting/components/CustomFlowNewOrEdit.tsx
... ... @@ -16,7 +16,6 @@ import {
16 16 BrandSelector,
17 17 RPTypesSelector,
18 18 BizTypeSelector,
19   - ShopBizTypeSelector,
20 19 OfficeWordTypeSelector,
21 20 ContractTypeSelector,
22 21 } from '@/pages/approval/ApprovalSetting/subpages/components/Selectors';
... ... @@ -52,7 +51,7 @@ export default function CustomFlowNewOrEdit(props: Props) {
52 51 const [form] = Form.useForm();
53 52  
54 53 // 触发条件对应表单值
55   - const [conditionVals, setConditionVals] = useState<ApprovalSetting.ConditionVal[]>([]);
  54 + const [conditionVals, setConditionVals] = useState<FlowSetting.ConditionVal[]>([]);
56 55 // 条件审批配置-->默认审批流程-->附加审批角色
57 56 const [roles, setRoles] = useState<FlowSetting.ApprovalRoleItem[][]>([]);
58 57  
... ... @@ -86,7 +85,7 @@ export default function CustomFlowNewOrEdit(props: Props) {
86 85 setSelectList(tempData);
87 86  
88 87 // 主要条件要必选
89   - const essVals: ApprovalSetting.ConditionVal[] = [];
  88 + const essVals: FlowSetting.ConditionVal[] = [];
90 89 preCondition.forEach((i) => {
91 90 const currVal = (data?.conditionValues ?? []).find((c) => c.flowTriggerDto.id === i.id);
92 91 if (i.essential && !currVal) {
... ... @@ -98,6 +97,17 @@ export default function CustomFlowNewOrEdit(props: Props) {
98 97 }
99 98 });
100 99 const newCondVals = (data?.conditionValues ?? []).concat(essVals);
  100 + // idOrCode to idOrCode--bizType
  101 + newCondVals.forEach((n) => {
  102 + if (n.flowTriggerDto.type === TriggerType.门店) {
  103 + const value = JSON.parse(n.value).map((i: FlowSetting.CondValItem) => ({
  104 + idOrCode: `${i.idOrCode}--${i.bizType}`,
  105 + name: i.name,
  106 + bizType: i.bizType,
  107 + }));
  108 + n.value = JSON.stringify(value);
  109 + }
  110 + });
101 111 setConditionVals(newCondVals);
102 112  
103 113 setRoles(data?.approvalRoles ?? []);
... ... @@ -119,17 +129,36 @@ export default function CustomFlowNewOrEdit(props: Props) {
119 129 }
120 130 }, [visible, data]);
121 131  
122   - // 获取已配置的门店业态条件值
  132 + // 从已选择门店中自动计算 bizType 交集
123 133 const shopBizTypes = useMemo(() => {
124   - const currType = conditionVals.find((i) => i.flowTriggerDto.type === TriggerType.门店业态);
125   - if (!currType) return [];
126   - try {
127   - const options = JSON.parse(currType.value);
128   - return options.map((i: FlowSetting.CondValItem) => i.idOrCode);
129   - } catch {
130   - return [];
131   - }
  134 + const shopCondVals = conditionVals.filter((i) => i.flowTriggerDto.type === TriggerType.门店);
  135 + if (!shopCondVals.length) return [];
  136 + const bizTypeSet = new Set<number>();
  137 + shopCondVals.forEach((s) => {
  138 + try {
  139 + const options = JSON.parse(s.value);
  140 + options.forEach((o: FlowSetting.CondValItem) => {
  141 + bizTypeSet.add(o.bizType!);
  142 + });
  143 + } catch {}
  144 + });
  145 + return Array.from(bizTypeSet.values());
132 146 }, [conditionVals]);
  147 + // 计算最新 bizType 交集
  148 + const getShopBizTypes = (cVals: FlowSetting.ConditionVal[]) => {
  149 + const shopCondVals = cVals.filter((i) => i.flowTriggerDto.type === TriggerType.门店);
  150 + if (!shopCondVals.length) return [];
  151 + const bizTypeSet = new Set<number>();
  152 + shopCondVals.forEach((s) => {
  153 + try {
  154 + const options = JSON.parse(s.value);
  155 + options.forEach((o: FlowSetting.CondValItem) => {
  156 + bizTypeSet.add(o.bizType!);
  157 + });
  158 + } catch {}
  159 + });
  160 + return Array.from(bizTypeSet.values());
  161 + };
133 162  
134 163 const hide = () => {
135 164 onCancel && onCancel();
... ... @@ -147,6 +176,17 @@ export default function CustomFlowNewOrEdit(props: Props) {
147 176 message.error('请填写全部触发条件的对应值');
148 177 return;
149 178 }
  179 + // idOrCode--bizType to idOrCode
  180 + conditionVals.forEach((n) => {
  181 + if (n.flowTriggerDto.type === TriggerType.门店) {
  182 + const value = JSON.parse(n.value).map((i: FlowSetting.CondValItem) => ({
  183 + idOrCode: i.idOrCode.split('--')[0]!,
  184 + name: i.name,
  185 + bizType: i.bizType,
  186 + }));
  187 + n.value = JSON.stringify(value);
  188 + }
  189 + });
150 190 form.validateFields().then((values) => {
151 191 const params = {
152 192 ...values,
... ... @@ -159,35 +199,39 @@ export default function CustomFlowNewOrEdit(props: Props) {
159 199 });
160 200 };
161 201  
162   - // 门店业态值只要变化则清空已添加审批角色列表
163   - const clearRoles = () => {
164   - setRoles([]);
165   - };
166   -
167   - // 选择|取消选择门店业态
168   - const handleShopBizTypeChange = (value: number) => {
169   - const currType = (selectList.find((i) => i.value === value) ?? {}).extral;
170   - if (currType?.type === TriggerType.门店业态) {
171   - clearRoles();
172   - }
  202 + // 门店业态值减少时交互:旧业态值不存在于新业态值数组
  203 + const clearRoles = (newCondVals: FlowSetting.ConditionVal[]) => {
  204 + const oldShopBizTypes = [...shopBizTypes];
  205 + const newShopBizTypes = getShopBizTypes(newCondVals);
  206 + oldShopBizTypes.forEach((i) => {
  207 + if (!newShopBizTypes.includes(i)) {
  208 + // 清空已添加审批角色列表
  209 + setRoles([]);
  210 + }
  211 + });
173 212 };
174 213  
175   - const onConditionChange = (item: ApprovalSetting.ConditionVal, values: any, index: number) => {
  214 + const onConditionChange = (item: FlowSetting.ConditionVal, values: any, index: number) => {
176 215 const { value, flowTriggerDto } = item;
177   - if (item.flowTriggerDto.type === TriggerType.门店业态) {
178   - // 审批角色清空
179   - clearRoles();
180   - // 门店组件清空
181   - const shopValIdx = conditionVals.findIndex((i) => i.flowTriggerDto.type === TriggerType.门店);
182   - if (shopValIdx > -1) {
183   - conditionVals[shopValIdx].value = '';
184   - }
  216 +
  217 + // idOrCode--bizType
  218 + let newValue;
  219 + if (flowTriggerDto.type === TriggerType.门店) {
  220 + newValue = Array.isArray(values)
  221 + ? values.map((i) => {
  222 + const currBizType = i.value.split('--')[1]!;
  223 + return { idOrCode: i.value, name: i.label, bizType: Number(currBizType) };
  224 + })
  225 + : values;
  226 + } else {
  227 + newValue = Array.isArray(values) ? values.map((i) => ({ idOrCode: i.value, name: i.label })) : values;
185 228 }
186   - const newValue = Array.isArray(values) ? values.map((i) => ({ idOrCode: i.value, name: i.label })) : values;
  229 +
  230 + // 计算新条件值
  231 + const newCondVals = [...conditionVals];
187 232 if (flowTriggerDto && [2, 3, 4, 5, 6, 7, 8].includes(flowTriggerDto.judgeRule ?? 0)) {
188 233 const _item = { ...item, value: JSON.stringify(newValue) };
189   - conditionVals[index] = _item;
190   - setConditionVals([...conditionVals]);
  234 + newCondVals[index] = _item;
191 235 } else {
192 236 const _item = {
193 237 ...item,
... ... @@ -196,9 +240,16 @@ export default function CustomFlowNewOrEdit(props: Props) {
196 240 ...newValue,
197 241 }),
198 242 };
199   - conditionVals[index] = _item;
200   - setConditionVals([...conditionVals]);
  243 + newCondVals[index] = _item;
201 244 }
  245 +
  246 + // 门店业态值减少时交互
  247 + if (flowTriggerDto.type === TriggerType.门店) {
  248 + clearRoles(newCondVals);
  249 + }
  250 +
  251 + // 更新条件值
  252 + setConditionVals(newCondVals);
202 253 };
203 254  
204 255 // 选择需要配置的预设条件
... ... @@ -207,6 +258,10 @@ export default function CustomFlowNewOrEdit(props: Props) {
207 258 const currVal = conditionVals.find((c) => c.flowTriggerDto?.id == i);
208 259 return { value: currVal ? currVal.value : '', flowTriggerDto: preCondition.find((p) => p.id === i)! };
209 260 });
  261 +
  262 + // 门店业态值减少时交互
  263 + clearRoles(tempVals);
  264 +
210 265 setConditionVals(tempVals);
211 266 };
212 267  
... ... @@ -220,6 +275,7 @@ export default function CustomFlowNewOrEdit(props: Props) {
220 275 cancelButtonProps={{ disabled: loading }}
221 276 onCancel={hide}
222 277 onOk={handleSaveFlow}
  278 + destroyOnClose
223 279 >
224 280 <Form form={form}>
225 281 <Form.Item name="id" hidden />
... ... @@ -227,15 +283,7 @@ export default function CustomFlowNewOrEdit(props: Props) {
227 283 <Input placeholder="请输入" maxLength={64} />
228 284 </Form.Item>
229 285 <Form.Item label="触发条件" name="conditions" rules={[{ required: true, message: '请选择需要配置的条件' }]}>
230   - <Select
231   - mode="multiple"
232   - allowClear
233   - style={{ width: '100%' }}
234   - placeholder="请选择"
235   - onChange={handleSelectCondition}
236   - onSelect={handleShopBizTypeChange}
237   - onDeselect={handleShopBizTypeChange}
238   - >
  286 + <Select mode="multiple" allowClear style={{ width: '100%' }} placeholder="请选择" onChange={handleSelectCondition}>
239 287 {selectList.map((item: SelectItem) => (
240 288 <Option value={item.value} key={item.value} extral={item.extral} disabled={item.extral.essential}>
241 289 {item.label}
... ... @@ -244,7 +292,7 @@ export default function CustomFlowNewOrEdit(props: Props) {
244 292 </Select>
245 293 </Form.Item>
246 294  
247   - {conditionVals.map((item: ApprovalSetting.ConditionVal, index: number) => {
  295 + {conditionVals.map((item: FlowSetting.ConditionVal, index: number) => {
248 296 const { flowTriggerDto, value } = item;
249 297 const originalData = JSON.parse(value || '{}'); // 触发的条件选的值
250 298 const { name, judgeRule = 0, type, id } = flowTriggerDto ?? {}; // 触发条件信息
... ... @@ -303,7 +351,6 @@ export default function CustomFlowNewOrEdit(props: Props) {
303 351 labelInValue
304 352 multiple
305 353 initType={1}
306   - bizTypes={shopBizTypes.join(',')}
307 354 value={
308 355 originalData.length > 0
309 356 ? originalData.map((i: any) => ({
... ... @@ -384,9 +431,6 @@ export default function CustomFlowNewOrEdit(props: Props) {
384 431 {type === TriggerType['报销类型'] && (
385 432 <BizTypeSelector visible={type === TriggerType['报销类型']} index={index} item={item} onChange={onConditionChange} />
386 433 )}
387   - {type === TriggerType['门店业态'] && (
388   - <ShopBizTypeSelector visible={type === TriggerType['门店业态']} index={index} item={item} onChange={onConditionChange} />
389   - )}
390 434 {type === TriggerType['工作类型'] && (
391 435 <OfficeWordTypeSelector visible={type === TriggerType['工作类型']} index={index} item={item} onChange={onConditionChange} />
392 436 )}
... ...
src/pages/approval/FlowSetting/subpages/ConditionSetting/components/RolesSettingForm.tsx
... ... @@ -15,7 +15,7 @@ interface TableRoleItem {
15 15 }
16 16  
17 17 interface Props {
18   - shopBizTypes: number[]; // 预设条件门店业态-联动
  18 + shopBizTypes: number[]; // 从预设条件为门店的选项值中提取 bizType 交集
19 19 roles: FlowSetting.ApprovalRoleItem[][];
20 20 setRoles: (value: FlowSetting.ApprovalRoleItem[][]) => void;
21 21 }
... ...
src/pages/approval/components/ShopSelectByBizType/api.ts
1 1 import type { http } from '@/typing/http';
2 2 import request from '@/utils/request';
3   -import { OOP_HOST, } from '@/utils/host';
  3 +import { OOP_HOST } from '@/utils/host';
4 4  
5 5 type P<T> = http.PromiseResp<T>;
6 6  
7 7 export interface QueryParams {
8   - groupId?: number // 集团id
9   - keyword?: string // 查询门店
10   - bizTypes?: string // 门店业态筛选
  8 + groupId?: number; // 集团id
  9 + keyword?: string; // 查询门店
  10 + bizTypes?: string; // 门店业态筛选
  11 + allType?: boolean; // 是否为全业态
11 12 }
12 13  
13 14 export interface ShopItem {
14   - value?: number,
15   - label?: string,
16   - bizType?: number,
17   - children?: ShopItem[]
  15 + value?: number;
  16 + label?: string;
  17 + bizType?: number;
  18 + children?: ShopItem[];
18 19 }
19 20  
20 21 /**
... ... @@ -33,4 +34,4 @@ export function getShopListByBizTypeApi(params: QueryParams): P&lt;ShopItem[]&gt; {
33 34 */
34 35 export function getShopListByDealerApi(params: QueryParams): P<ShopItem[]> {
35 36 return request.get(`${OOP_HOST}/select/dealers/shops`, { params });
36   -}
37 37 \ No newline at end of file
  38 +}
... ...
src/pages/approval/components/ShopSelectByBizType/index.tsx
... ... @@ -16,7 +16,6 @@ interface Props {
16 16 multiple?: boolean;
17 17 labelInValue?: boolean;
18 18 initType?: 1 | 2;
19   - bizTypes?: string; // 支持门店业态筛选
20 19 disabled?: boolean;
21 20 /** 📢 以下2个属性 仅同时使用一个 📢 */
22 21 showIds?: number[]; // 仅显示项目ID列表
... ... @@ -44,16 +43,15 @@ export interface ShopSelectRef {
44 43 export default forwardRef(ShopSelectByBizType);
45 44  
46 45 function ShopSelectByBizType(
47   - { value = [], onChange, multiple = false, labelInValue = false, initType = 1, bizTypes, disabled = false, showIds, hiddenIds, disabledIds }: Props,
  46 + { value = [], onChange, multiple = false, labelInValue = false, initType = 1, disabled = false, showIds, hiddenIds, disabledIds }: Props,
48 47 ref: Ref<ShopSelectRef>,
49 48 ) {
50 49 if (showIds?.length && hiddenIds?.length) {
51 50 console.error(`(<ShopSelectByBizType>):\`showIds\` 和 \`hiddenIds\` 不能同时传入。`);
52 51 }
53 52  
54   - const [delay, setDelay] = useState(true);
55   - const { data: byBizTypeList, loading: byBizTypeLoading, setParams: setBizTypeParams } = useInitail(getShopListByBizTypeApi, [], {}, delay);
56   - const { data: byDealerList, loading: byDealerLoading, setParams: setDealerParams } = useInitail(getShopListByDealerApi, [], {}, delay);
  53 + const { data: byBizTypeList, loading: byBizTypeLoading } = useInitail(getShopListByBizTypeApi, [], { allType: true });
  54 + const { data: byDealerList, loading: byDealerLoading } = useInitail(getShopListByDealerApi, [], {});
57 55 const [type, setType] = useState<1 | 2>(initType);
58 56 const [values, setValues] = useState<LabeledValue[]>(value);
59 57 const [checkInfo, setCheckInfo] = useState({
... ... @@ -63,12 +61,6 @@ function ShopSelectByBizType(
63 61 const allValues = useRef<LabeledValue[]>([]); // 为了方便全选按钮被点击时赋值,将所有人员再计算list的时候,顺便赋值给该变量
64 62  
65 63 useEffect(() => {
66   - setDelay(false);
67   - setBizTypeParams({ bizTypes }, true);
68   - setDealerParams({ bizTypes }, true);
69   - }, [bizTypes]);
70   -
71   - useEffect(() => {
72 64 if (value.length > 0) {
73 65 setValues(value);
74 66 setCheckInfo({
... ... @@ -115,8 +107,8 @@ function ShopSelectByBizType(
115 107 (children || [])
116 108 .filter((child) => !child.disabled)
117 109 .map((shop) => ({
118   - label: `${shop.shopName}`,
119   - value: shop.shopId,
  110 + label: shop.title,
  111 + value: shop.value,
120 112 })),
121 113 );
122 114 if (index === byBizTypeList.length - 1) {
... ... @@ -143,8 +135,8 @@ function ShopSelectByBizType(
143 135 // 将商家下的门店赋值给allValues
144 136 allValues.current = allValues.current.concat(
145 137 (children || []).map((shop) => ({
146   - label: shop.shopName,
147   - value: shop.shopId,
  138 + label: shop.title,
  139 + value: shop.value,
148 140 })),
149 141 );
150 142 if (index === byDealerList.length - 1) {
... ... @@ -228,6 +220,7 @@ function ShopSelectByBizType(
228 220 }
229 221  
230 222 function processingChildrenData(data: ShopItem, showIds?: number[], hiddenIds?: number[], disabledIds?: number[]): DataItem[] | undefined {
  223 + // todo hiddenIds 需要拼接 bizType 处理
231 224 let _data: ShopItem[] | undefined, _children: DataItem[] | undefined;
232 225  
233 226 if (showIds?.length) {
... ... @@ -244,8 +237,9 @@ function processingChildrenData(data: ShopItem, showIds?: number[], hiddenIds?:
244 237 return {
245 238 pid: data.value,
246 239 title: shop.label,
247   - value: shop.value,
248   - key: shop.value,
  240 + // value: idOrCode to idOrCode--bizType
  241 + value: `${shop.value}--${shop.bizType}`,
  242 + key: `${shop.value}--${shop.bizType}`,
249 243 isLeaf: true,
250 244 level: 2,
251 245 disabled: disabledIds?.includes(shop.value || -1),
... ...
src/pages/attendance/Attend/subpages/Roster/api.ts
... ... @@ -18,6 +18,21 @@ export interface SettingItem {
18 18 posts: Post[];
19 19 month: string[];
20 20 effectMonth: string;
  21 + confirmType?: number; // 确认类型(-1:待办未推送, 0:未确认, 1:主动确认, 2:到期系统自动确认)
  22 +}
  23 +
  24 +export enum ConfirmType {
  25 + 待办未推送 = -1,
  26 + 未确认 = 0,
  27 + 主动确认 = 1,
  28 + 到期系统自动确认 = 2,
  29 +}
  30 +
  31 +export enum ConfirmTypeColor {
  32 + '#999' = -1,
  33 + '#FF921C' = 0,
  34 + '#4189FD' = 1,
  35 + '#F4333C' = 2,
21 36 }
22 37  
23 38 export interface Shop {
... ... @@ -61,6 +76,7 @@ export interface SepcialSettingsItem {
61 76 shops?: Shop[];
62 77 posts?: Post[];
63 78 restMode?: number[];
  79 + confirmType?: number; // 确认类型(-1:待办未推送, 0:未确认, 1:主动确认, 2:到期系统自动确认)
64 80 }
65 81  
66 82 export enum RestMode {
... ... @@ -102,3 +118,21 @@ export function deleteSpecialItemApi(id: number): http.PromiseResp&lt;string&gt; {
102 118 export function deleteSettingItemApi(id: number): http.PromiseResp<string> {
103 119 return request.get(`${ATTENDANCE_HOST}/erp/schedule/setting/del`, { params: { id } });
104 120 }
  121 +
  122 +/**
  123 + * @description: 确认排班配置
  124 + * @param {number} id
  125 + * @return {http.PromiseResp<string>}
  126 + */
  127 +export function confirmSettingItemApi(id: number): http.PromiseResp<string> {
  128 + return request.get(`${ATTENDANCE_HOST}/erp/schedule/setting/confirmConfig`, { params: { id } });
  129 +}
  130 +
  131 +/**
  132 + * @description: 确认特殊排班配置
  133 + * @param {number} id
  134 + * @return {http.PromiseResp<string>}
  135 + */
  136 +export function confirmSpecialSettingItemApi(id: number): http.PromiseResp<string> {
  137 + return request.get(`${ATTENDANCE_HOST}/erp/schedule/special/setting/confirmConfig`, { params: { id } });
  138 +}
... ...
src/pages/attendance/Attend/subpages/Roster/components/Settings/index.tsx
... ... @@ -2,7 +2,7 @@ import usePagination from &#39;@/hooks/usePagination&#39;;
2 2 import moment from 'moment';
3 3 import React, { useState } from 'react';
4 4 import * as API from '../../api';
5   -import { Button, Popconfirm, Select, Table, message } from 'antd';
  5 +import { Badge, Button, Divider, Popconfirm, Select, Table, message } from 'antd';
6 6 import SaveModal from './SaveModal';
7 7 import DetailModal from './DetailModal';
8 8 import TableArrayColumnFormat from '@/pages/ehr/components/TableArrayColumnFormat';
... ... @@ -37,6 +37,20 @@ export default function Settings() {
37 37 });
38 38 }
39 39  
  40 + function confirmItem(id: number) {
  41 + const hide = message.loading('确认中,请稍后...', 0);
  42 + API.confirmSettingItemApi(id)
  43 + .then((res) => {
  44 + hide();
  45 + message.success(res.result);
  46 + setLoading(true);
  47 + })
  48 + .catch((error) => {
  49 + hide();
  50 + message.error(error.message ?? '确认失败');
  51 + });
  52 + }
  53 +
40 54 return (
41 55 <>
42 56 <div
... ... @@ -71,72 +85,81 @@ export default function Settings() {
71 85 </Button>
72 86 </div>
73 87 <Table loading={loading} dataSource={list} pagination={paginationConfig} rowKey="id">
74   - <Column
75   - title="适用门店"
76   - dataIndex="shops"
77   - render={(shops?: API.Shop[]) => <TableArrayColumnFormat data={shops ?? []} key="shopId" showKey="shopName" unit="个门店" />}
78   - />
79   - <Column
80   - title="适用岗位"
81   - dataIndex="posts"
82   - render={(posts?: API.Post[]) => <TableArrayColumnFormat data={posts ?? []} key="postId" showKey="postName" unit="个岗位" />}
83   - />
84   - <Column title="月休息天数" dataIndex="monthRestCnt" width="10%" align="center" render={(text, row: any) => <div>{row.monthRestCnt}天</div>} />
85   - <Column
86   - title="最大连续休息天数"
87   - dataIndex="restContinuousCnt"
88   - width="10%"
89   - align="center"
90   - render={(text, row: any) => (
91   - <div>
92   - {row.restContinuousCnt
93   - ? row.continuousType === 0
94   - ? `${row.restContinuousCnt}天`
95   - : `${Math.floor((row.restContinuousCnt * row.monthRestCnt) / 100)}天(百分比计算)`
96   - : '--'}
97   - </div>
  88 + <Table.Column
  89 + title="适用范围"
  90 + render={(record: API.SettingItem) => (
  91 + <span>
  92 + <span className="span_limit_1">
  93 + <span style={{ color: '#999' }}>适用门店:</span>
  94 + <TableArrayColumnFormat data={record.shops ?? []} key="shopId" showKey="shopName" unit="个门店" />
  95 + </span>
  96 + <span className="span_limit_1">
  97 + <span style={{ color: '#999' }}>适用岗位:</span>
  98 + <TableArrayColumnFormat data={record.posts ?? []} key="postId" showKey="postName" unit="个岗位" />
  99 + </span>
  100 + </span>
98 101 )}
99 102 />
100   - <Column
101   - title={`排班表设置时间(${moment(date).subtract(1, 'M').format('YYYY年MM月')}倒数后多少天)`}
102   - dataIndex="scheduleDays"
103   - width="16%"
104   - align="center"
105   - render={(text, row: any) => <div>{row.scheduleDays}天</div>}
  103 + <Table.Column
  104 + title="配置"
  105 + render={(record: API.SettingItem) => (
  106 + <span>
  107 + <span className="span_limit_1">
  108 + <span style={{ color: '#999' }}>月休息天数:</span>
  109 + <span style={{ color: '#333' }}>{record.monthRestCnt || '-'}天</span>
  110 + </span>
  111 + <span className="span_limit_1">
  112 + <span style={{ color: '#999' }}>最大连续休息天数:</span>
  113 + <span style={{ color: '#333' }}>
  114 + {record.restContinuousCnt
  115 + ? record.continuousType === 0
  116 + ? `${record.restContinuousCnt}天`
  117 + : `${Math.floor((record.restContinuousCnt * record.monthRestCnt) / 100)}天(百分比计算)`
  118 + : '--'}
  119 + </span>
  120 + </span>
  121 + <span className="span_limit_1">
  122 + <span style={{ color: '#999' }}>{`排班表设置时间(${moment(date).subtract(1, 'M').format('YYYY年MM月')}倒数后多少天)`}:</span>
  123 + <span style={{ color: '#333' }}>{record.scheduleDays || '-'}天</span>
  124 + </span>
  125 + <span className="span_limit_1">
  126 + <span style={{ color: '#999' }}>每月可主动调休次数:</span>
  127 + <span style={{ color: '#333' }}>{record.changeRestCnt || '-'}次</span>
  128 + </span>
  129 + </span>
  130 + )}
106 131 />
107 132 <Column
108   - title="每月可主动调休次数"
109   - dataIndex="changeRestCnt"
110   - width="16%"
111   - align="center"
112   - render={(text, row: any) => <div>{row.changeRestCnt ? `${row.changeRestCnt}次` : '--'}</div>}
  133 + title="状态"
  134 + dataIndex="confirmType"
  135 + render={(confirmType: number) =>
  136 + Number.isFinite(confirmType) ? <Badge color={API.ConfirmTypeColor[confirmType]} text={API.ConfirmType[confirmType]} /> : '-'
  137 + }
113 138 />
114   - {/* <Column
115   - title="最大连续上班天数(可跨月)"
116   - dataIndex="restFrequency"
117   - width="16%"
118   - align="center"
119   - render={(text, row: any) => <div>{row.restFrequency ? `${row.restFrequency}天/次` : '--'}</div>}
120   - /> */}
121 139 <Column
122   - width="10%"
123 140 title="操作"
124 141 align="center"
125 142 render={(text, record: API.SettingItem) => (
126 143 <>
127   - <Button
128   - type="link"
  144 + {record.confirmType === API.ConfirmType.未确认 ? (
  145 + <>
  146 + <Popconfirm placement="top" title="确定确认?" onConfirm={() => confirmItem(record.id)}>
  147 + <a>确认</a>
  148 + </Popconfirm>
  149 + <Divider type="vertical" />
  150 + </>
  151 + ) : null}
  152 + <a
129 153 onClick={() => {
130 154 setItem(record);
131 155 setVisible(true);
132 156 }}
133 157 >
134 158 编辑
135   - </Button>
  159 + </a>
  160 + <Divider type="vertical" />
136 161 <Popconfirm placement="top" title="确认删除?" onConfirm={() => deleteItem(record.id)}>
137   - <Button type="link" danger>
138   - 删除
139   - </Button>
  162 + <a style={{ color: 'red' }}>删除</a>
140 163 </Popconfirm>
141 164 </>
142 165 )}
... ...
src/pages/attendance/Attend/subpages/Roster/components/SpecialSettings/index.tsx
1 1 import React, { useEffect, useState } from 'react';
2 2 import * as API from '../../api';
3 3 import usePagination from '@/hooks/usePagination';
4   -import { Button, Divider, Form, Modal, Popconfirm, Popover, Select, Spin, Table, message } from 'antd';
  4 +import { Badge, Button, Divider, Form, Modal, Popconfirm, Popover, Select, Spin, Table, message } from 'antd';
5 5 import { formatObjText } from '@/utils/utils';
6 6 import ShopSelectNew from '@/components/ShopSelectNew';
7 7 import PostSelectNew from '@/components/PostSelectNew';
... ... @@ -46,6 +46,20 @@ export default function SpecialSettings() {
46 46 });
47 47 }
48 48  
  49 + function confirmItem(id: number) {
  50 + const hide = message.loading('确认中,请稍后...', 0);
  51 + API.confirmSpecialSettingItemApi(id)
  52 + .then((res) => {
  53 + hide();
  54 + message.success(res.result);
  55 + pagination.setLoading(true);
  56 + })
  57 + .catch((error) => {
  58 + hide();
  59 + message.error(error.message ?? '确认失败');
  60 + });
  61 + }
  62 +
49 63 function closeModal() {
50 64 setOpen(false);
51 65 setCurrent(undefined);
... ... @@ -106,9 +120,24 @@ export default function SpecialSettings() {
106 120 render={(restMode: number[]) => (restMode?.length ? restMode.map((mode) => API.RestMode[mode]).join(' + ') : '-')}
107 121 />
108 122 <Table.Column
  123 + title="状态"
  124 + dataIndex="confirmType"
  125 + render={(confirmType: number) =>
  126 + Number.isFinite(confirmType) ? <Badge color={API.ConfirmTypeColor[confirmType]} text={API.ConfirmType[confirmType]} /> : '-'
  127 + }
  128 + />
  129 + <Table.Column
109 130 title="操作"
110 131 render={(record: API.SepcialSettingsItem) => (
111 132 <>
  133 + {record.confirmType === API.ConfirmType.未确认 ? (
  134 + <>
  135 + <Popconfirm placement="top" title="确定确认?" onConfirm={() => confirmItem(record.id ?? -1)}>
  136 + <a>确认</a>
  137 + </Popconfirm>
  138 + <Divider type="vertical" />
  139 + </>
  140 + ) : null}
112 141 <a onClick={() => openModal(record)}>编辑</a>
113 142 <Divider type="vertical" />
114 143 <Popconfirm title="确定删除该配置?" onConfirm={() => deleteItem(record.id ?? -1)}>
... ...
src/pages/carinsur/LoanClientConfig/api.ts deleted
1   -import { http } from '@/typing/http';
2   -import request from '@/utils/request';
3   -import { ANGEL_Host, FVM_HOST } from "@/utils/host";
4   -import * as IF from './interface';
5   -
6   -/**
7   - * 查询列表
8   - */
9   -export function getPageListApi(brandId?: IF.QueryParams): http.PromisePageResp<IF.Item> {
10   - return request.get(`${ANGEL_Host}/loancusinsureqconfig/page`, { params: brandId });
11   -}
12   -/**查询配置授权车型 */
13   -export function getSpecListApi(additionalId?: number): http.PromiseResp<IF.Option[]> {
14   - return request.get(`${FVM_HOST}/erp/subsidy/additional/auth/spec/list`, { params: { additionalId } });
15   -}
16   -
17   -/**
18   - * 保存
19   - */
20   -export function saveApi(params: IF.SaveParams): http.PromiseResp<void> {
21   - return request.post(`${ANGEL_Host}/loancusinsureqconfig/save`, params);
22   -}
23   -
24   -// 配置删除
25   -export function deleteApi(id: number): http.PromiseResp<null> {
26   - return request.post(`${ANGEL_Host}/loancusinsureqconfig/delete`, {id});
27   -}
src/pages/carinsur/LoanClientConfig/components/EditModal.tsx deleted
1   -import React, { useState, useEffect } from "react";
2   -import { message, Modal, Select, Form, DatePicker, InputNumber, Spin, Space, Radio } from "antd";
3   -import { saveApi } from "../api";
4   -import moment from "moment";
5   -import { getSeriesApi } from "@/common/api";
6   -import * as IF from "../interface";
7   -
8   -const RangePicker = DatePicker.RangePicker;
9   -interface Props {
10   - visible: boolean;
11   - onCancel: Function;
12   - item: IF.Item;
13   - fetchList: () => any;
14   - brandList: CommonApi.OptionVO[];
15   -}
16   -
17   -const formItemLayout = {
18   - labelCol: {
19   - xs: { span: 24 },
20   - sm: { span: 6 },
21   - md: { span: 6 },
22   - },
23   - wrapperCol: {
24   - xs: { span: 24 },
25   - sm: { span: 15 },
26   - md: { span: 15 },
27   - },
28   -};
29   -
30   -const Item = Form.Item;
31   -
32   -function SaveModal(props: Props) {
33   - const { item, onCancel, fetchList, visible, brandList } = props;
34   - const [loading, setLoading] = useState(false);
35   - const [initLoading, setInitLoading] = useState(false);
36   - const [form] = Form.useForm();
37   - const [seriesList, setSeriesList] = useState<CommonApi.OptionVO[]>([]);
38   - // const [seriesId, setSeriesId] = useState<number>();
39   - // const [specData, setSpecData] = useState<IF.Option[]>([]);
40   -
41   - useEffect(() => {
42   - if (visible && item.id) {
43   - form.setFieldsValue({
44   - startDate: [item.startDate && moment(item.startDate), item.endDate && moment(item.endDate)],
45   - brandId: { value: item.brandId, label: item.brandName, key: item.brandId },
46   - seriesId: item.series?.map((item) => ({ value: item.seriesId, label: item.seriesName, key: item.seriesId })),
47   - subsidyType: item.subsidyType,
48   - needBuyTci: item.needBuyTci,
49   - needBuyVci: item.needBuyVci,
50   - vciReqAmount: item.vciReqAmount && item.vciReqAmount,
51   - });
52   -
53   - item.brandId && getSeries(item.brandId);
54   - // setInitLoading(true);
55   - } else {
56   - // setSpecData([]);
57   - // setSeriesId(undefined);
58   - setSeriesList([]);
59   - }
60   - }, [visible]);
61   -
62   - function getSeries(brandId: number) {
63   - getSeriesApi(brandId)
64   - .then((res) => {
65   - setSeriesList(res.data || []);
66   - })
67   - .catch((err) => {
68   - message.error(err.message);
69   - });
70   - }
71   -
72   - function submit() {
73   - form.validateFields().then((fields) => {
74   - // 车系
75   - const series = fields.seriesId.map((item:any) => ({ seriesId: item.key, seriesName: item.label }));
76   - const params: IF.SaveParams = {
77   - id: item && item.id,
78   - ...fields,
79   - brandId: fields.brandId.value,
80   - brandName: fields.brandId.label,
81   - series,
82   - startDate: fields.startDate[0].valueOf(),
83   - endDate: fields.startDate[1].valueOf(),
84   - };
85   - setLoading(true);
86   - saveApi(params)
87   - .then(() => {
88   - message.success("保存成功");
89   - fetchList();
90   - onCancel();
91   - setLoading(false);
92   - })
93   - .catch((e) => {
94   - setLoading(false);
95   - message.error(e.message);
96   - });
97   - });
98   - }
99   -
100   - return (
101   - <Modal title={item.id ? "编辑" : "新增"} width={700} visible={visible} maskClosable={false} afterClose={() => form.resetFields()} onCancel={() => onCancel()} onOk={() => form.submit()} confirmLoading={loading}>
102   - <Spin spinning={initLoading}>
103   - <Form form={form} {...formItemLayout} onFinish={submit}>
104   - <Item label="有效期" name="startDate" rules={[{ required: true, message: "请选择生效时间" }]}>
105   - <RangePicker disabledDate={(current) => !!current && current < moment().startOf("day")} style={{ width: "100%" }} format="YYYY-MM-DD" />
106   - </Item>
107   - <Item label="适用品牌" name="brandId" rules={[{ required: true, message: "请选择品牌" }]}>
108   - <Select
109   - optionFilterProp="children"
110   - placeholder="请选择品牌"
111   - labelInValue
112   - showSearch
113   - onChange={(v: any) => {
114   - getSeries(v.value);
115   - form.setFieldsValue({ seriesId: undefined, specList: undefined });
116   - }}
117   - >
118   - {brandList.map((i) => (
119   - <Select.Option value={i.id} key={i.id}>
120   - {i.name}
121   - </Select.Option>
122   - ))}
123   - </Select>
124   - </Item>
125   -
126   - <Item label="适用车系" name="seriesId" rules={[{ required: true, message: "请选择车系" }]}>
127   - <Select
128   - mode="multiple"
129   - optionFilterProp="children"
130   - placeholder="请选择车系"
131   - notFoundContent="暂无数据"
132   - labelInValue
133   - showSearch
134   - onChange={(v: any) => {
135   - // setSeriesId(v.value);
136   - // form.setFieldsValue({ specList: undefined });
137   - }}
138   - >
139   - {seriesList.map((i) => (
140   - <Select.Option value={i.id} key={i.id}>
141   - {i.name}
142   - </Select.Option>
143   - ))}
144   - </Select>
145   - </Item>
146   - {/* 交强险 */}
147   - <Item name="needBuyTci" label="要求购买交强险" rules={[{ required: true, message: "请选择是否要求购买交强险" }]}>
148   - <Radio.Group
149   - options={[
150   - { label: "是", value: true },
151   - { label: "否", value: false },
152   - ]}
153   - />
154   - </Item>
155   - {/* 商业险 */}
156   - <Item name="needBuyVci" label="要求购买商业险" rules={[{ required: true, message: "请选择是否要求购买交强险" }]}>
157   - <Radio.Group
158   - options={[
159   - { label: "是", value: true },
160   - { label: "否", value: false },
161   - ]}
162   - />
163   - </Item>
164   -
165   - <Item noStyle shouldUpdate={(prevValues, curValues) => prevValues.needBuyVci !== curValues.needBuyVci}>
166   - {({ getFieldValue }) => {
167   - const type = getFieldValue("needBuyVci");
168   - return type ? (
169   - <Form.Item label="商业险要求金额(>=)">
170   - <Space>
171   - <Item
172   - name="vciReqAmount"
173   - noStyle
174   - rules={[
175   - { required: true, message: "请输入" },
176   - { pattern: /^(?!(0[0-9]{0,}$))[0-9]{1,}[.]{0,}[0-9]{0,}$/, message: "请输入正数" },
177   - ]}
178   - >
179   - <InputNumber style={{ width: "100%" }} placeholder="请输入" precision={2} />
180   - </Item>
181   - <span>元</span>
182   - </Space>
183   - </Form.Item>
184   - ) : null;
185   - }}
186   - </Item>
187   - </Form>
188   - </Spin>
189   - </Modal>
190   - );
191   -}
192   -
193   -export default SaveModal;
src/pages/carinsur/LoanClientConfig/components/SpecModal.tsx deleted
1   -import React, { useState, useEffect } from "react";
2   -import "@ant-design/compatible/assets/index.css";
3   -import { Modal, Button, Table } from "antd";
4   -
5   -import * as IF from "../interface";
6   -
7   -interface Props {
8   - visible: boolean;
9   - onCancel: () => any;
10   - item: IF.Item;
11   -}
12   -
13   -function SpecModal(props: Props) {
14   - const { visible, onCancel, item } = props;
15   - const [tableList, setTableList] = useState<IF.SeriesItem[]>([]);
16   - useEffect(() => {
17   - let list = [];
18   - if (item.series) {
19   - for (let i = 0; i < item.series.length; i++) {
20   - let obj = { ...item.series[i] };
21   - obj.brandName = item.brandName;
22   - list.push(obj);
23   - }
24   - setTableList([...tableList, ...list]);
25   - } else {
26   - setTableList([]);
27   - }
28   - }, [item.id]);
29   - const columns = [
30   - {
31   - title: "品牌",
32   - dataIndex: "brandName",
33   - },
34   - {
35   - title: "适用车系",
36   - dataIndex: "seriesName",
37   - },
38   - ];
39   -
40   - return (
41   - <Modal
42   - title="车辆信息"
43   - style={{ width: 400 }}
44   - maskClosable={false}
45   - visible={visible}
46   - onCancel={() => onCancel()}
47   - footer={
48   - <Button type="default" onClick={() => onCancel()}>
49   - 取消
50   - </Button>
51   - }
52   - >
53   - <Table columns={columns} dataSource={tableList} rowKey={record => record.seriesId} />
54   - </Modal>
55   - );
56   -}
57   -
58   -export default React.memo(SpecModal);
src/pages/carinsur/LoanClientConfig/index.tsx deleted
1   -import React, { useState } from "react";
2   -import { PlusOutlined } from "@ant-design/icons";
3   -import { Button, Card, Divider, message, Popconfirm, Table, Select } from "antd";
4   -import { PageHeaderWrapper } from "@ant-design/pro-layout";
5   -import usePagination from "@/hooks/usePagination";
6   -import SaveModal from "./components/EditModal";
7   -import SpecModal from "./components/SpecModal";
8   -import { deleteApi, getPageListApi } from "./api";
9   -import * as IF from "./interface";
10   -import useInitial from "@/hooks/useInitail";
11   -import { getBrandFilterApi } from "@/common/api";
12   -import moment from "moment";
13   -
14   -const Column = Table.Column;
15   -
16   -export default function StorageList() {
17   - const { list, paginationConfig, loading, setLoading, setParams, innerParams } = usePagination<StorageMaintain.Item>(getPageListApi, {});
18   - const [specVisible, setSpecVisible] = useState(false);
19   - const { data: brandList } = useInitial<CommonApi.OptionVO[], {}>(getBrandFilterApi, [], {});
20   - const [visible, setVisible] = useState(false);
21   - const [item, setItem] = useState<IF.Item>({});
22   -
23   - /**删除 */
24   - function handleDelete(item: IF.Item) {
25   - item.id &&
26   - deleteApi(item.id)
27   - .then((res) => {
28   - setLoading(true);
29   - message.success("操作成功");
30   - })
31   - .catch((e) => {
32   - message.error(e.message);
33   - });
34   - }
35   -
36   - return (
37   - <PageHeaderWrapper title="贷款客户保险要求配置">
38   - <Card>
39   - <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", marginBottom: 20 }}>
40   - <div style={{ display: "flex", flexDirection: "row" }}>
41   - <Select style={{ width: 250 }} placeholder="请选择品牌" value={innerParams.brandId} onChange={(v) => setParams({ ...innerParams, brandId: v }, true)} allowClear>
42   - {brandList.map((item) => (
43   - <Select.Option value={item.id} key={item.id}>
44   - {item.name}
45   - </Select.Option>
46   - ))}
47   - </Select>
48   - </div>
49   - <Button
50   - type="primary"
51   - icon={<PlusOutlined />}
52   - onClick={() => {
53   - setVisible(true);
54   - setItem({});
55   - }}
56   - >
57   - 新增
58   - </Button>
59   - </div>
60   - <Table size="small" loading={loading} pagination={paginationConfig} rowKey={(item) => String(item.id)} dataSource={list} onChange={(_pagination) => setParams({ ..._pagination }, true)}>
61   - <Column title="品牌" width="10%" align="center" dataIndex="brandName" />
62   - <Column
63   - title="适用车系"
64   - width="10%"
65   - align="center"
66   - render={(text, record: IF.Item) => (
67   - <Button
68   - type="link"
69   - onClick={() => {
70   - setSpecVisible(true);
71   - setItem(record);
72   - }}
73   - >
74   - 查看
75   - </Button>
76   - )}
77   - />
78   - <Column
79   - title="有效期"
80   - width="16%"
81   - align="center"
82   - render={(text, record: IF.Item) => <span>{`${(record.startDate && moment(record.startDate).format("YYYY-MM-DD")) || "——"}~${(record.endDate && moment(record.endDate).format("YYYY-MM-DD")) || "——"}`}</span>}
83   - />
84   - <Column title="要求购买交强险" dataIndex="needBuyTci" width="10%" align="center" render={(text) => (text ? <span>是</span> : <span>否</span>)} />
85   - <Column title="要求购买商业险" dataIndex="needBuyVci" width="10%" align="center" render={(text) => (text ? <span>是</span> : <span>否</span>)} />
86   - <Column
87   - title="商业险要求金额(>=)"
88   - dataIndex="vciReqAmount"
89   - width="10%"
90   - align="center"
91   - render={(text: number) => {
92   - return text > 0? <span>{`${text || 0}元`}</span> :"--";
93   - }}
94   - />
95   -
96   - <Column
97   - title="操作"
98   - align="center"
99   - width="15%"
100   - render={(text, record: IF.Item) => (
101   - <>
102   - <Button
103   - type="link"
104   - style={{ padding: 0 }}
105   - onClick={() => {
106   - setVisible(true);
107   - setItem(record);
108   - }}
109   - >
110   - 编辑
111   - </Button>
112   - <Divider type="vertical" />
113   - <Popconfirm placement="top" title="确认删除?" onConfirm={() => handleDelete(record)}>
114   - <Button type="link" style={{ padding: 0 }}>
115   - 删除
116   - </Button>
117   - </Popconfirm>
118   - </>
119   - )}
120   - />
121   - </Table>
122   - </Card>
123   - <SaveModal
124   - visible={visible}
125   - brandList={brandList}
126   - item={item}
127   - fetchList={() => setLoading(true)}
128   - onCancel={() => {
129   - setVisible(false);
130   - setItem({});
131   - }}
132   - />
133   - {/* {specModal} */}
134   -
135   - <SpecModal
136   - visible={specVisible}
137   - item={item}
138   - onCancel={() => {
139   - setSpecVisible(false);
140   - setItem({});
141   - }}
142   - />
143   - </PageHeaderWrapper>
144   - );
145   -}
src/pages/carinsur/LoanClientConfig/interface.d.ts deleted
1   -/**
2   - * 查询参数
3   - */
4   -export interface QueryParams {
5   - brandId?: number,
6   - current?: number,
7   - pageSize?: number,
8   -}
9   -
10   -// export interface QueryParams {
11   -// brandId?: number;
12   -// }
13   -/**
14   - * 列表项
15   - */
16   -export interface Item {
17   - id?: number;
18   - brandId?: number;
19   - brandName?: string;
20   - seriesName?: string;
21   - startDate?: number;
22   - endDate?: number;
23   - subsidyAmount?: number;
24   - subsidyType?: number;
25   - needBuyTci?: boolean; //是否要求买交强险
26   - needBuyVci?: boolean; // 是否要求买商业险
27   - series?: { seriesId: number; seriesName: string; brandName?: string }[];
28   - vciReqAmount?: number;
29   - name?:string;
30   -}
31   -
32   -export interface SaveParams {
33   - id?: number;
34   - brandId?: number;
35   - brandName?: string;
36   - series?: { seriesId: number; seriesName: string }[];
37   - startDate?: number;
38   - endDate?: number;
39   - needBuyTci?: boolean;
40   - needBuyVci?: boolean;
41   - vciReqAmount?: number; //商业险补贴金额
42   - subsidyType?: number; //补贴类型 1增购补贴、2大客户购车补贴、3置换补贴、4最美职业补贴
43   - subsidyAmount?: number; //补贴金额
44   -}
45   -
46   -interface SeriesItem {
47   - seriesId: number;
48   - seriesName: string;
49   - brandName?: string;
50   -}
51   -
52   -interface SimilarItem {
53   - brandId: number,
54   - brandName: string,
55   -}
56   -/**
57   - * 授权参数
58   - */
59   -export interface ShopItem {
60   - shopId?: number, // 所属门店
61   - shopName?: string
62   -}
63   -
64   -export interface SelecSpecParams {
65   - seriesId: number, //车系id
66   - startTime: number, // 开始时间
67   - endTime: number, //结束时间
68   - additionalId?: number, //配置id(编辑使用)
69   -}
70   -/**
71   - * 选项
72   - */
73   -export interface CustomerOption {
74   - customerType: number,
75   - typeName?: string
76   -}
77   -
78   -export interface Option {
79   - specId?: number,
80   - specName?: string
81   -}
82 0 \ No newline at end of file
src/pages/carinsur/LoanClientRequires/api.ts 0 → 100644
  1 +import type { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import type { IdNameOption, ShopOption } from '../entity';
  4 +import { ANGEL_Host } from '@/utils/host';
  5 +import type { Pagination } from '@/typing/common';
  6 +
  7 +export interface LoanType {
  8 + type: number;
  9 + amount: number;
  10 +}
  11 +export interface brandSeriesItem {
  12 + id: number;
  13 + name: string;
  14 + series: IdNameOption[];
  15 +}
  16 +export interface Item {
  17 + id?: number;
  18 + allBrandSeries: boolean;
  19 + brandSeries: brandSeriesItem[];
  20 + useShopIds: ShopOption[];
  21 + newTci: LoanType;
  22 + newVci: LoanType;
  23 + newTai: LoanType;
  24 + reNewTci: LoanType;
  25 + reNewVci: LoanType;
  26 + reNewTai: LoanType;
  27 +}
  28 +
  29 +export interface PageParams extends Pagination {
  30 + shopId?: number;
  31 + brandId?: number;
  32 + seriesId?: number;
  33 +}
  34 +
  35 +/**
  36 + * 分页查询
  37 + */
  38 +export function getLCRPage(params?: PageParams): http.PromisePageResp<Item> {
  39 + return request.get(`${ANGEL_Host}/loancusinsureq/page`, { params });
  40 +}
  41 +
  42 +/**
  43 + * 新增/编辑
  44 + */
  45 +export function addLCR(data?: Item): http.PromiseResp<void> {
  46 + return request.post(`${ANGEL_Host}/loancusinsureq/add`, data);
  47 +}
  48 +
  49 +/**
  50 + * 删除
  51 + */
  52 +export function delLCR(id: number): http.PromisePageResp<void> {
  53 + return request.post(`${ANGEL_Host}/loancusinsureq/delete`, { id });
  54 +}
... ...
src/pages/carinsur/LoanClientRequires/components/AddModal/index.tsx 0 → 100644
  1 +import React, { useEffect, memo } from 'react';
  2 +import { Modal, Form, message, Radio } from 'antd';
  3 +import * as API from '../../api';
  4 +import { useRequest } from 'umi';
  5 +import BrandSeriesFormItem from '../BrandSeriesFormItem';
  6 +import ShopSelectorByAll from '../ShopSelectorByAll';
  7 +import LoanTypeFormItem from '../LoanTypeFormItem';
  8 +import type { LabeledValue } from 'antd/lib/select';
  9 +import st from './style.less';
  10 +
  11 +interface Props {
  12 + visible: boolean;
  13 + row?: API.Item;
  14 + onCancel: () => void;
  15 + onRefresh: () => void;
  16 +}
  17 +
  18 +function AddModal({ visible, row, onCancel, onRefresh }: Props) {
  19 + const { id } = row ?? {};
  20 + const [form] = Form.useForm();
  21 +
  22 + const saveHook = useRequest(API.addLCR, {
  23 + manual: true,
  24 + throwOnError: true,
  25 + });
  26 +
  27 + useEffect(() => {
  28 + if (visible) {
  29 + if (row) {
  30 + form.setFieldsValue({
  31 + ...row,
  32 + useShopIds: row.useShopIds.map((i) => ({ label: i.shopName, value: i.shopId })),
  33 + });
  34 + } else {
  35 + form.setFieldsValue({
  36 + allBrandSeries: true,
  37 + });
  38 + }
  39 + } else {
  40 + form.resetFields();
  41 + }
  42 + }, [visible, row]);
  43 +
  44 + const handleSave = (feildValue: any) => {
  45 + saveHook
  46 + .run({
  47 + ...feildValue,
  48 + useShopIds: feildValue.useShopIds.map((i: LabeledValue) => ({ shopId: i.value, shopName: i.label })),
  49 + brandSeries: feildValue.allBrandSeries ? [] : feildValue.brandSeries,
  50 + })
  51 + .then(() => {
  52 + message.success('操作成功');
  53 + onCancel();
  54 + onRefresh();
  55 + })
  56 + .catch((e) => {
  57 + message.error(e.message);
  58 + });
  59 + };
  60 +
  61 + return (
  62 + <Modal title={`${id ? '编辑' : '新增'}`} open={visible} confirmLoading={saveHook.loading} onCancel={onCancel} onOk={form.submit} width={1000}>
  63 + <Form form={form} onFinish={handleSave} labelCol={{ span: 4 }} wrapperCol={{ span: 18 }}>
  64 + <Form.Item name="id" hidden />
  65 + <Form.Item label="适用品牌车系" name="allBrandSeries" rules={[{ required: true, message: '请选择' }]}>
  66 + <Radio.Group>
  67 + <Radio value={true}>全部品牌全部车系</Radio>
  68 + <Radio value={false}>指定</Radio>
  69 + </Radio.Group>
  70 + </Form.Item>
  71 + <Form.Item
  72 + noStyle
  73 + shouldUpdate={(prev, curr) => {
  74 + // 切换全部|部分时交互未清空部分品牌部分车系数据
  75 + return prev.allBrandSeries !== curr.allBrandSeries;
  76 + }}
  77 + >
  78 + {({ getFieldValue }) => {
  79 + const allBrandSeries = getFieldValue('allBrandSeries');
  80 + if (allBrandSeries) {
  81 + return null;
  82 + }
  83 + return (
  84 + <Form.Item className={st.hidden} label={<></>} name="brandSeries" rules={[{ required: true, message: '请至少添加一种适应品牌车系' }]}>
  85 + <BrandSeriesFormItem />
  86 + </Form.Item>
  87 + );
  88 + }}
  89 + </Form.Item>
  90 + <Form.Item label="适用门店" name="useShopIds" rules={[{ required: true, message: '请选择' }]}>
  91 + <ShopSelectorByAll />
  92 + </Form.Item>
  93 + <LoanTypeFormItem form={form} key="newTci" name="newTci" label="新保交强险" />
  94 + <LoanTypeFormItem form={form} key="newVci" name="newVci" label="新保商业险" />
  95 + <LoanTypeFormItem form={form} key="newTai" name="newTai" label="新保驾意险" />
  96 + <LoanTypeFormItem form={form} key="reNewTci" name="reNewTci" label="续保交强险" />
  97 + <LoanTypeFormItem form={form} key="reNewVci" name="reNewVci" label="续保商业险" />
  98 + <LoanTypeFormItem form={form} key="reNewTai" name="reNewTai" label="续保驾意险" />
  99 + </Form>
  100 + </Modal>
  101 + );
  102 +}
  103 +
  104 +export default memo(AddModal);
... ...
src/pages/carinsur/LoanClientRequires/components/AddModal/style.less 0 → 100644
  1 +.hidden {
  2 + :global {
  3 + .ant-form-item-required {
  4 + visibility: hidden;
  5 + }
  6 + }
  7 +}
0 8 \ No newline at end of file
... ...
src/pages/carinsur/LoanClientRequires/components/BrandSeriesAddModal.tsx 0 → 100644
  1 +import React, { useEffect } from 'react';
  2 +import { Modal, Form, Select } from 'antd';
  3 +import type { brandSeriesItem } from '../api';
  4 +import type { LabeledValue } from 'antd/lib/select';
  5 +import SeriesSelectorByAll from './SeriesSelectorByAll';
  6 +import _ from 'lodash';
  7 +
  8 +interface Props {
  9 + brands?: CommonApi.OptionVO[];
  10 + visible: boolean;
  11 + value?: brandSeriesItem;
  12 + onCancel: () => void;
  13 + onChange: (data: brandSeriesItem) => void;
  14 +}
  15 +const FormItem = Form.Item;
  16 +
  17 +export default function Index({ brands, visible, value, onCancel, onChange }: Props) {
  18 + const [form] = Form.useForm();
  19 +
  20 + useEffect(() => {
  21 + if (visible && value) {
  22 + const { id, name, series } = value;
  23 + form.setFieldsValue({
  24 + brand: { label: name, value: id },
  25 + series: series.map((i) => ({ label: i.name, value: i.id })),
  26 + });
  27 + } else {
  28 + form.resetFields();
  29 + }
  30 + }, [visible]);
  31 +
  32 + const closeModal = () => {
  33 + onCancel();
  34 + form.resetFields();
  35 + };
  36 +
  37 + function handleSave(feildValue: any) {
  38 + const { brand, series } = feildValue;
  39 + onChange &&
  40 + onChange({
  41 + id: brand.value,
  42 + name: brand.label,
  43 + series: series.map((i: LabeledValue) => ({ id: i.value, name: i.label })),
  44 + });
  45 + closeModal();
  46 + }
  47 +
  48 + return (
  49 + <Modal title={`${value ? '编辑' : '添加'}适用品牌车系`} style={{ width: 600 }} open={visible} onCancel={closeModal} onOk={form.submit}>
  50 + <Form form={form} labelCol={{ span: '6' }} onFinish={handleSave}>
  51 + <FormItem label="品牌" name="brand" rules={[{ required: true, message: '请选择品牌' }]}>
  52 + <Select
  53 + disabled={!!value} // 编辑时不可编辑品牌
  54 + placeholder="请选择"
  55 + options={brands}
  56 + fieldNames={{ label: 'name', value: 'id' }}
  57 + showSearch
  58 + labelInValue
  59 + optionFilterProp="children"
  60 + />
  61 + </FormItem>
  62 + <Form.Item
  63 + noStyle
  64 + shouldUpdate={(prev, curr) => {
  65 + if (!_.isEqual(prev.brand, curr.brand)) {
  66 + if (value) {
  67 + form.setFieldValue('series', value.id === curr.brand.value ? value.series.map((i) => ({ label: i.name, value: i.id })) : []);
  68 + } else {
  69 + form.setFieldValue('series', []);
  70 + }
  71 + }
  72 + return !_.isEqual(prev.brand, curr.brand);
  73 + }}
  74 + >
  75 + {({ getFieldValue }) => {
  76 + const brandId = (getFieldValue('brand') ?? {}).value;
  77 + return (
  78 + <FormItem label="车系" name="series" rules={[{ required: true, message: '请选择车系' }]}>
  79 + <SeriesSelectorByAll brandId={brandId} disabled={!brandId} disabledTip="请先选择品牌" />
  80 + </FormItem>
  81 + );
  82 + }}
  83 + </Form.Item>
  84 + </Form>
  85 + </Modal>
  86 + );
  87 +}
... ...
src/pages/carinsur/LoanClientRequires/components/BrandSeriesFormItem.tsx 0 → 100644
  1 +import React, { useEffect, useMemo, useState } from 'react';
  2 +import { Table, Divider, Popconfirm, Button, Row } from 'antd';
  3 +import { PlusOutlined } from '@ant-design/icons';
  4 +import BrandSeriesAddModal from './BrandSeriesAddModal';
  5 +import type { brandSeriesItem } from '../api';
  6 +import TextWithMore from '@/components/TextWithMore';
  7 +import useInitial from '@/hooks/useInitail';
  8 +import { getBrandFilterApi } from '@/common/api';
  9 +
  10 +const { Column } = Table;
  11 +
  12 +interface Props {
  13 + readOnly?: boolean;
  14 + value?: brandSeriesItem[];
  15 + onChange?: (data: brandSeriesItem[]) => void;
  16 +}
  17 +
  18 +export default function Index({ readOnly = false, value = [], onChange }: Props) {
  19 + const [delay, setDelay] = useState(true);
  20 + const { data: brands, setParams } = useInitial(getBrandFilterApi, [], {}, delay);
  21 +
  22 + useEffect(() => {
  23 + if (!readOnly) {
  24 + setDelay(false);
  25 + setParams(undefined, true);
  26 + }
  27 + }, []);
  28 +
  29 + const theRestBrands = useMemo(() => {
  30 + const selectedBrands = value.map((i) => i.id);
  31 + return brands.filter((b) => !selectedBrands.includes(b.id!));
  32 + }, [value, brands]);
  33 +
  34 + // 新增 | 编辑
  35 + const [addModal, setAddModal] = useState<{
  36 + visible: boolean;
  37 + row?: brandSeriesItem;
  38 + }>({
  39 + visible: false,
  40 + });
  41 +
  42 + const handleEdit = (row: brandSeriesItem) => {
  43 + setAddModal({
  44 + visible: true,
  45 + row,
  46 + });
  47 + };
  48 +
  49 + const handleDelete = (row: brandSeriesItem) => {
  50 + const newVal = [...value];
  51 + const currIdx = newVal.findIndex((i) => i.id === row.id);
  52 + newVal.splice(currIdx, 1);
  53 + onChange && onChange(newVal);
  54 + };
  55 +
  56 + const handleUpdate = (res: brandSeriesItem) => {
  57 + const newVal = [...value];
  58 + const currIdx = newVal.findIndex((i) => i.id === res.id); // 品牌 id
  59 + if (currIdx > -1) {
  60 + newVal[currIdx] = res;
  61 + } else {
  62 + newVal.push(res);
  63 + }
  64 + onChange && onChange(newVal);
  65 + };
  66 +
  67 + return (
  68 + <>
  69 + {!readOnly && (
  70 + <Row align="middle" justify="end" style={{ marginBottom: 20 }}>
  71 + <Button
  72 + type="primary"
  73 + icon={<PlusOutlined />}
  74 + onClick={() => {
  75 + setAddModal({
  76 + visible: true,
  77 + });
  78 + }}
  79 + >
  80 + 添加
  81 + </Button>
  82 + </Row>
  83 + )}
  84 + <Table dataSource={value} rowKey="id" size="small">
  85 + <Column title="品牌" dataIndex="name" width={200} render={(t) => t || '-'} />
  86 + <Column title="车系" dataIndex="series" width={200} render={(t) => <TextWithMore title="车系" dataIndex="name" list={t} />} />
  87 + {!readOnly && (
  88 + <Column
  89 + title="操作"
  90 + width={100}
  91 + dataIndex="unit"
  92 + render={(text, row: brandSeriesItem) => (
  93 + <span>
  94 + <a
  95 + onClick={() => {
  96 + handleEdit(row);
  97 + }}
  98 + >
  99 + 编辑
  100 + </a>
  101 + <Divider type="vertical" />
  102 + <Popconfirm title="是否删除?" onConfirm={() => handleDelete(row)} okText="确定" cancelText="取消">
  103 + <a
  104 + onClick={(e) => {
  105 + e.preventDefault();
  106 + }}
  107 + style={{ color: 'red' }}
  108 + >
  109 + 删除
  110 + </a>
  111 + </Popconfirm>
  112 + </span>
  113 + )}
  114 + />
  115 + )}
  116 + </Table>
  117 + <BrandSeriesAddModal
  118 + brands={theRestBrands}
  119 + visible={addModal.visible}
  120 + value={addModal.row}
  121 + onCancel={() => setAddModal({ visible: false })}
  122 + onChange={handleUpdate}
  123 + />
  124 + </>
  125 + );
  126 +}
... ...
src/pages/carinsur/LoanClientRequires/components/BrandSeriesModal.tsx 0 → 100644
  1 +import React from 'react';
  2 +import { Modal } from 'antd';
  3 +import BrandSeriesFormItem from './BrandSeriesFormItem';
  4 +import type { brandSeriesItem } from '../api';
  5 +
  6 +interface Props {
  7 + brandSeriesModal: { visible: boolean; brandSeries?: brandSeriesItem[] };
  8 + onCancel: () => void;
  9 +}
  10 +
  11 +export default function Index({ brandSeriesModal, onCancel }: Props) {
  12 + const { visible, brandSeries = [] } = brandSeriesModal;
  13 + return (
  14 + <Modal title="适用品牌车系" open={visible} onCancel={() => onCancel()} footer={null} width={600}>
  15 + <BrandSeriesFormItem value={brandSeries} readOnly />
  16 + </Modal>
  17 + );
  18 +}
... ...
src/pages/carinsur/LoanClientRequires/components/Filter/index.tsx 0 → 100644
  1 +import React, { memo } from 'react';
  2 +import { Row, Select } from 'antd';
  3 +import _ from 'lodash';
  4 +import type { PageParams } from '../../api';
  5 +import { getShopApi } from '@/common/api';
  6 +import useInitial from '@/hooks/useInitail';
  7 +import BrandToSeries from '@/components/Condition/BrandToSeries';
  8 +
  9 +interface Props {
  10 + innerParams?: any;
  11 + setParams: (params: PageParams, refreshing: boolean) => void;
  12 +}
  13 +
  14 +function Filter({ innerParams, setParams }: Props) {
  15 + const { data: shops } = useInitial<CommonApi.OptionVO[], undefined>(getShopApi, [], undefined);
  16 +
  17 + const onChange = _.debounce((newParams) => {
  18 + setParams({ ...innerParams, ...newParams }, true);
  19 + }, 600);
  20 +
  21 + return (
  22 + <Row style={{ display: 'flex', flex: 1 }}>
  23 + <BrandToSeries
  24 + //@ts-ignore
  25 + style={{ width: 260 }}
  26 + placeholder="筛选品牌车系"
  27 + onChange={(v) => onChange({ brandId: v[0], seriesId: v && v.length === 2 ? v[1] : undefined })}
  28 + />
  29 + <Select
  30 + style={{ width: 260, marginLeft: 20 }}
  31 + showSearch
  32 + allowClear
  33 + placeholder="筛选门店"
  34 + options={shops}
  35 + fieldNames={{ label: 'name', value: 'id' }}
  36 + onChange={(value) => {
  37 + onChange({ shopId: value });
  38 + }}
  39 + />
  40 + </Row>
  41 + );
  42 +}
  43 +
  44 +export default Filter;
... ...
src/pages/carinsur/LoanClientRequires/components/LoanTypeFormItem.tsx 0 → 100644
  1 +import { Form, InputNumber, Radio } from 'antd';
  2 +import React from 'react';
  3 +import { LoanTypeEnum } from '../../entity';
  4 +
  5 +interface Props {
  6 + form: any;
  7 + name: string;
  8 + label: string;
  9 +}
  10 +
  11 +export default function Index({ form, name, label }: Props) {
  12 + return (
  13 + <Form.Item label={label} name={[name, 'type']} rules={[{ required: true, message: '请选择' }]}>
  14 + <Radio.Group>
  15 + <Radio value={LoanTypeEnum.无要求}>无要求</Radio>
  16 + <Radio value={LoanTypeEnum.购买即可}>购买即可</Radio>
  17 + <Radio value={LoanTypeEnum.保费有要求}>
  18 + <div style={{ display: 'flex', alignItems: 'center', flexDirection: 'row' }}>
  19 + <span>保费有要求</span>
  20 + <Form.Item
  21 + noStyle
  22 + shouldUpdate={(prev, curr) => {
  23 + if (prev[name] && curr[name] && prev[name].type !== curr[name].type && curr[name].type !== LoanTypeEnum.保费有要求) {
  24 + form.setFieldValue([name, 'amount'], undefined);
  25 + }
  26 + return prev[name] !== curr[name];
  27 + }}
  28 + >
  29 + {({ getFieldValue }) => {
  30 + const type = (getFieldValue(name) ?? {}).type;
  31 + if (type !== LoanTypeEnum.保费有要求) return null;
  32 + return (
  33 + <Form.Item
  34 + style={{ marginBottom: 0, marginLeft: 10 }}
  35 + name={[name, 'amount']}
  36 + required
  37 + rules={[{ required: true, message: '请填写金额' }]}
  38 + >
  39 + <InputNumber addonBefore="≥" addonAfter="元" style={{ width: 200 }} min={0.01} precision={2} placeholder="请填写金额" />
  40 + </Form.Item>
  41 + );
  42 + }}
  43 + </Form.Item>
  44 + </div>
  45 + </Radio>
  46 + </Radio.Group>
  47 + </Form.Item>
  48 + );
  49 +}
... ...
src/pages/carinsur/LoanClientRequires/components/SeriesSelectorByAll.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Select, Spin } from 'antd';
  3 +import type { LabelInValueType } from 'rc-select/lib/Select';
  4 +import { getSeriesApi } from '@/common/api';
  5 +import useInitial from '@/hooks/useInitail';
  6 +
  7 +interface Props {
  8 + brandId: number; // 根据品牌 id 筛选车系
  9 + value?: LabelInValueType[];
  10 + onChange?: (value: LabelInValueType[]) => void;
  11 + disabled?: boolean;
  12 + disabledTip?: string;
  13 + defaultTip?: string;
  14 + style?: React.CSSProperties;
  15 +}
  16 +
  17 +export default function Index({
  18 + brandId,
  19 + value = [],
  20 + onChange,
  21 + disabled = false,
  22 + disabledTip = '请选择车系',
  23 + defaultTip = '请选择车系',
  24 + style,
  25 +}: Props) {
  26 + const [delay, setDelay] = useState(true);
  27 + const [allList, setAllList] = useState<any[]>([]);
  28 + const { data: list, setParams, loading } = useInitial<CommonApi.OptionVO[], number>(getSeriesApi, [], brandId, delay);
  29 +
  30 + useEffect(() => {
  31 + if (brandId) {
  32 + setParams(brandId, true);
  33 + setDelay(false);
  34 + }
  35 + }, [brandId]);
  36 +
  37 + useEffect(() => {
  38 + if (list && list.length > 0) {
  39 + // @ts-ignore
  40 + const newPostList = [{ id: -1, name: '全部车系' }].concat(list); // 前端手动在列表头部增加一个 {id: -1, name: '全部车系'} 的选项
  41 + setAllList(newPostList);
  42 + } else {
  43 + setAllList([]);
  44 + }
  45 + }, [list]);
  46 +
  47 + return (
  48 + <Spin spinning={loading && !disabled}>
  49 + <Select
  50 + labelInValue
  51 + value={value}
  52 + mode="multiple"
  53 + onChange={(value) => {
  54 + if (value && value.findIndex((i) => i.value === -1) > -1) {
  55 + onChange && onChange([{ key: '-1', label: '全部车系', value: -1 }]);
  56 + } else {
  57 + onChange && onChange(value);
  58 + }
  59 + }}
  60 + style={style || { flex: 1 }}
  61 + allowClear
  62 + placeholder={disabled ? disabledTip : defaultTip}
  63 + showSearch
  64 + optionFilterProp="children"
  65 + disabled={disabled}
  66 + // getPopupContainer={(triggerNode) => triggerNode.parentNode}
  67 + >
  68 + {allList.map((brand) => (
  69 + <Select.Option key={brand.id} value={brand.id!} disabled={value.findIndex((i) => i.value === -1) > -1 && brand.id !== -1}>
  70 + {brand.name}
  71 + </Select.Option>
  72 + ))}
  73 + </Select>
  74 + </Spin>
  75 + );
  76 +}
... ...
src/pages/carinsur/LoanClientRequires/components/ShopSelectorByAll.tsx 0 → 100644
  1 +import React, { useEffect, useState } from 'react';
  2 +import { Select, Spin } from 'antd';
  3 +import type { LabelInValueType } from 'rc-select/lib/Select';
  4 +import { getShopApi } from '@/common/api';
  5 +import useInitial from '@/hooks/useInitail';
  6 +
  7 +interface Props {
  8 + value?: LabelInValueType[];
  9 + onChange?: (value: LabelInValueType[]) => void;
  10 + disabled?: boolean;
  11 + disabledTip?: string;
  12 + defaultTip?: string;
  13 + style?: React.CSSProperties;
  14 +}
  15 +
  16 +export default function Index({ value = [], onChange, disabled = false, disabledTip = '请选择门店', defaultTip = '请选择门店', style }: Props) {
  17 + const [delay, setDelay] = useState(true);
  18 + const [allList, setAllList] = useState<any[]>([]);
  19 + const { data: list, setParams, loading } = useInitial<CommonApi.OptionVO[], undefined>(getShopApi, [], undefined, delay);
  20 +
  21 + useEffect(() => {
  22 + if (list && list.length > 0) {
  23 + // @ts-ignore
  24 + const newPostList = [{ id: -1, name: '全部门店' }].concat(list); // 前端手动在列表头部增加一个 {id: -1, name: '全部门店'} 的选项
  25 + setAllList(newPostList);
  26 + } else {
  27 + setAllList([]);
  28 + }
  29 + }, [list]);
  30 +
  31 + useEffect(() => {
  32 + setParams(undefined, true);
  33 + setDelay(false);
  34 + }, []);
  35 +
  36 + return (
  37 + <Spin spinning={loading && !disabled}>
  38 + <Select
  39 + labelInValue
  40 + value={value}
  41 + mode="multiple"
  42 + onChange={(value) => {
  43 + if (value && value.findIndex((i) => i.value === -1) > -1) {
  44 + onChange && onChange([{ key: '-1', label: '全部门店', value: -1 }]);
  45 + } else {
  46 + onChange && onChange(value);
  47 + }
  48 + }}
  49 + style={style || { flex: 1 }}
  50 + allowClear
  51 + placeholder={disabled ? disabledTip : defaultTip}
  52 + showSearch
  53 + optionFilterProp="children"
  54 + disabled={disabled}
  55 + // getPopupContainer={(triggerNode) => triggerNode.parentNode}
  56 + >
  57 + {allList.map((brand) => (
  58 + <Select.Option key={brand.id} value={brand.id!} disabled={value.findIndex((i) => i.value === -1) > -1 && brand.id !== -1}>
  59 + {brand.name}
  60 + </Select.Option>
  61 + ))}
  62 + </Select>
  63 + </Spin>
  64 + );
  65 +}
... ...
src/pages/carinsur/LoanClientRequires/index.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { Button, Card, ConfigProvider, Divider, message, Popconfirm, Row, 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 { PlusOutlined } from '@ant-design/icons';
  7 +import AddModal from './components/AddModal';
  8 +import Filter from './components/Filter';
  9 +import * as API from './api';
  10 +import _ from 'lodash';
  11 +import TextWithMore from '@/components/TextWithMore';
  12 +import { LoanTypeEnum } from '../entity';
  13 +import BrandSeriesModal from './components/BrandSeriesModal';
  14 +
  15 +const { Column } = Table;
  16 +
  17 +export default function Index() {
  18 + // 新增 | 编辑
  19 + const [addModal, setAddModal] = useState<{
  20 + visible: boolean;
  21 + row?: API.Item;
  22 + }>({
  23 + visible: false,
  24 + });
  25 + // 查看部分品牌车系
  26 + const [brandSeriesModal, setBrandSeriesModal] = useState<{
  27 + visible: boolean;
  28 + brandSeries?: API.brandSeriesItem[];
  29 + }>({
  30 + visible: false,
  31 + brandSeries: [],
  32 + });
  33 +
  34 + const { list, paginationConfig, loading, innerParams, setParams } = usePagination<API.Item>(API.getLCRPage);
  35 +
  36 + const handleDelete = (row: API.Item) => {
  37 + const { id } = row;
  38 + API.delLCR(id!)
  39 + .then((res) => {
  40 + message.success(res.result);
  41 + setParams({ ...innerParams }, true);
  42 + })
  43 + .catch((e) => {
  44 + message.error(e.message);
  45 + });
  46 + };
  47 +
  48 + const handleEdit = (row: API.Item) => {
  49 + setAddModal({
  50 + visible: true,
  51 + row,
  52 + });
  53 + };
  54 +
  55 + const renderLoanTypeEle = (value: API.LoanType) => {
  56 + return value ? (value.type !== LoanTypeEnum.保费有要求 ? LoanTypeEnum[value.type] : `保费 ≥ ${value.amount}元`) : '--';
  57 + };
  58 +
  59 + return (
  60 + <PageHeaderWrapper title="贷款期客户保险要求">
  61 + <ConfigProvider locale={zhCN}>
  62 + <Card>
  63 + <Row align="middle" justify="space-between" style={{ marginBottom: 20 }}>
  64 + <Filter innerParams={innerParams} setParams={setParams} />
  65 + <Button
  66 + type="primary"
  67 + icon={<PlusOutlined />}
  68 + onClick={() => {
  69 + setAddModal({
  70 + visible: true,
  71 + });
  72 + }}
  73 + >
  74 + 新增
  75 + </Button>
  76 + </Row>
  77 + <Table
  78 + loading={loading}
  79 + dataSource={list}
  80 + pagination={paginationConfig}
  81 + scroll={{ y: 800 }}
  82 + rowKey="id"
  83 + onChange={(_pagination) => setParams({ ..._pagination }, true)}
  84 + >
  85 + <Column
  86 + title="适用品牌车系"
  87 + dataIndex="allBrandSeries"
  88 + render={(value, row: API.Item) =>
  89 + value ? (
  90 + '全部品牌全部车系'
  91 + ) : (
  92 + <a
  93 + onClick={(e) => {
  94 + e.preventDefault();
  95 + setBrandSeriesModal({ visible: true, brandSeries: row.brandSeries });
  96 + }}
  97 + >
  98 + 查看
  99 + </a>
  100 + )
  101 + }
  102 + />
  103 + <Column
  104 + title="适用门店"
  105 + dataIndex="useShopIds"
  106 + render={(value) => <TextWithMore title="适用门店" dataIndex="shopName" list={value} unit="个门店" />}
  107 + />
  108 + <Column title="新保交强险" dataIndex="newTci" render={renderLoanTypeEle} />
  109 + <Column title="新保商业险" dataIndex="newVci" render={renderLoanTypeEle} />
  110 + <Column title="新保驾意险" dataIndex="newTai" render={renderLoanTypeEle} />
  111 + <Column title="续保交强险" dataIndex="reNewTci" render={renderLoanTypeEle} />
  112 + <Column title="续保商业险" dataIndex="reNewVci" render={renderLoanTypeEle} />
  113 + <Column title="续保驾意险" dataIndex="reNewTai" render={renderLoanTypeEle} />
  114 + <Column
  115 + title="操作"
  116 + dataIndex="btns"
  117 + render={(text, row: API.Item) => (
  118 + <span>
  119 + <a
  120 + onClick={(e) => {
  121 + e.preventDefault();
  122 + handleEdit(row);
  123 + }}
  124 + >
  125 + 编辑
  126 + </a>
  127 + <Divider type="vertical" />
  128 + <Popconfirm title="是否删除?" onConfirm={() => handleDelete(row)}>
  129 + <a
  130 + onClick={(e) => {
  131 + e.preventDefault();
  132 + }}
  133 + style={{ color: 'red' }}
  134 + >
  135 + 删除
  136 + </a>
  137 + </Popconfirm>
  138 + </span>
  139 + )}
  140 + />
  141 + </Table>
  142 + </Card>
  143 + <AddModal
  144 + visible={addModal.visible}
  145 + row={addModal.row}
  146 + onCancel={() => {
  147 + setAddModal({ visible: false });
  148 + }}
  149 + onRefresh={() => setParams({ ...innerParams }, true)}
  150 + />
  151 + <BrandSeriesModal
  152 + brandSeriesModal={brandSeriesModal}
  153 + onCancel={() => {
  154 + setBrandSeriesModal({ visible: false });
  155 + }}
  156 + />
  157 + </ConfigProvider>
  158 + </PageHeaderWrapper>
  159 + );
  160 +}
... ...
src/pages/carinsur/entity.ts 0 → 100644
  1 +export interface ShopOption {
  2 + shopId: number;
  3 + shopName: string;
  4 +}
  5 +export interface IdNameOption {
  6 + id: number;
  7 + name: string;
  8 +}
  9 +export enum LoanTypeEnum {
  10 + '购买即可' = 1,
  11 + '保费有要求',
  12 + '无要求',
  13 +}
0 14 \ No newline at end of file
... ...
src/pages/contract/ExpressLogisticsArticleSetting/components/UserAddModal.tsx
... ... @@ -40,7 +40,7 @@ export default function UserAddModal({ visible, value, onCancel, onChange }: Pro
40 40 name="userName"
41 41 rules={[
42 42 { required: true, message: '请填写姓名' },
43   - { max: 20, message: '输入长度应该小于20' },
  43 + { max: 32, message: '输入长度应该小于32' },
44 44 { whitespace: true, message: '不能输入空白字符' },
45 45 ]}
46 46 >
... ... @@ -55,7 +55,7 @@ export default function UserAddModal({ visible, value, onCancel, onChange }: Pro
55 55 pattern: /^((\+86)|(86))?(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/,
56 56 message: '请输入有效的电话号码',
57 57 },
58   - { max: 20, message: '输入长度应该小于20' },
  58 + { max: 16, message: '输入长度应该小于16' },
59 59 { whitespace: true, message: '不能输入空白字符' },
60 60 ]}
61 61 >
... ...
src/pages/contract/FoodWhiteList/api.ts 0 → 100644
  1 +import type { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { OA_HOST } from '@/utils/host';
  4 +import type { Pagination } from '@/typing/common';
  5 +
  6 +export interface Item {
  7 + id?: number;
  8 + name: string;
  9 + mobile: string;
  10 + remark: string;
  11 +}
  12 +
  13 +export interface PageParams extends Pagination {
  14 + name?: string;
  15 + mobile?: string;
  16 + remark?: string;
  17 +}
  18 +
  19 +/**
  20 + * 分页查询
  21 + */
  22 +export function getFoodWhitePage(params?: PageParams): http.PromisePageResp<Item> {
  23 + return request.get(`${OA_HOST}/contract/erp/repast/white/page`, { params });
  24 +}
  25 +
  26 +/**
  27 + * 新增/编辑
  28 + */
  29 +export function addFoodWhite(data?: Item): http.PromiseResp<void> {
  30 + return request.post(`${OA_HOST}/contract/erp/repast/white/save`, data);
  31 +}
  32 +
  33 +/**
  34 + * 删除
  35 + */
  36 +export function delFoodWhite(id: number): http.PromisePageResp<void> {
  37 + return request.post(`${OA_HOST}/contract/erp/repast/white/delete`, { id });
  38 +}
... ...
src/pages/contract/FoodWhiteList/components/AddModal/index.tsx 0 → 100644
  1 +import React, { useEffect, memo } from 'react';
  2 +import { Modal, Form, message, Input } from 'antd';
  3 +import * as API from '../../api';
  4 +import { useRequest } from 'umi';
  5 +
  6 +interface Props {
  7 + visible: boolean;
  8 + row?: API.Item;
  9 + onCancel: () => void;
  10 + onRefresh: () => void;
  11 +}
  12 +
  13 +function AddModal({ visible, row, onCancel, onRefresh }: Props) {
  14 + const { id } = row ?? {};
  15 + const [form] = Form.useForm();
  16 +
  17 + const saveHook = useRequest(API.addFoodWhite, {
  18 + manual: true,
  19 + throwOnError: true,
  20 + });
  21 +
  22 + useEffect(() => {
  23 + if (visible) {
  24 + if (row) {
  25 + form.setFieldsValue(row);
  26 + }
  27 + } else {
  28 + form.resetFields();
  29 + }
  30 + }, [visible, row]);
  31 +
  32 + const handleSave = (feildValue: any) => {
  33 + saveHook
  34 + .run(feildValue)
  35 + .then(() => {
  36 + message.success('操作成功');
  37 + onCancel();
  38 + onRefresh();
  39 + })
  40 + .catch((e) => {
  41 + message.error(e.message);
  42 + });
  43 + };
  44 +
  45 + return (
  46 + <Modal title={`${id ? '编辑' : '新增'}`} open={visible} confirmLoading={saveHook.loading} onCancel={onCancel} onOk={form.submit} width={600}>
  47 + <Form form={form} onFinish={handleSave} labelCol={{ span: 4 }} wrapperCol={{ span: 18 }}>
  48 + <Form.Item name="id" hidden />
  49 + <Form.Item
  50 + label="姓名"
  51 + name="name"
  52 + rules={[
  53 + { required: true, message: '请填写姓名' },
  54 + { max: 32, message: '输入长度应该小于32' },
  55 + { whitespace: true, message: '不能输入空白字符' },
  56 + ]}
  57 + >
  58 + <Input placeholder="请填写" />
  59 + </Form.Item>
  60 + <Form.Item
  61 + label="手机号"
  62 + name="mobile"
  63 + rules={[
  64 + { required: true, message: '请填写联系电话' },
  65 + {
  66 + pattern: /^((\+86)|(86))?(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/,
  67 + message: '请输入有效的电话号码',
  68 + },
  69 + { max: 16, message: '输入长度应该小于16' },
  70 + { whitespace: true, message: '不能输入空白字符' },
  71 + ]}
  72 + >
  73 + <Input placeholder="请填写" />
  74 + </Form.Item>
  75 + <Form.Item label="备注" name="remark" rules={[{ required: true, message: '请填写' }]}>
  76 + <Input.TextArea placeholder="请填写" maxLength={64} />
  77 + </Form.Item>
  78 + </Form>
  79 + </Modal>
  80 + );
  81 +}
  82 +
  83 +export default memo(AddModal);
... ...
src/pages/contract/FoodWhiteList/components/Filter/index.tsx 0 → 100644
  1 +import React from 'react';
  2 +import { Input, Row } from 'antd';
  3 +import _ from 'lodash';
  4 +import type { PageParams } from '../../api';
  5 +
  6 +interface Props {
  7 + innerParams?: any;
  8 + setParams: (params: PageParams, refreshing: boolean) => void;
  9 +}
  10 +
  11 +function Filter({ innerParams, setParams }: Props) {
  12 + const onChange = _.debounce((newParams) => {
  13 + setParams({ ...innerParams, ...newParams }, true);
  14 + }, 600);
  15 +
  16 + return (
  17 + <Row style={{ display: 'flex', flex: 1 }}>
  18 + <Input
  19 + style={{ width: 200 }}
  20 + allowClear
  21 + placeholder="搜索姓名"
  22 + onChange={(e) => {
  23 + onChange({ name: e.target.value });
  24 + }}
  25 + />
  26 + <Input
  27 + style={{ width: 200, marginLeft: 20 }}
  28 + allowClear
  29 + placeholder="搜索手机号"
  30 + onChange={(e) => {
  31 + onChange({ mobile: e.target.value });
  32 + }}
  33 + />
  34 + </Row>
  35 + );
  36 +}
  37 +
  38 +export default Filter;
... ...
src/pages/contract/FoodWhiteList/index.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { Button, Card, ConfigProvider, Divider, message, Popconfirm, Row, 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 { PlusOutlined } from '@ant-design/icons';
  7 +import AddModal from './components/AddModal';
  8 +import Filter from './components/Filter';
  9 +import * as API from './api';
  10 +import _ from 'lodash';
  11 +
  12 +const { Column } = Table;
  13 +
  14 +export default function Index() {
  15 + // 新增 | 编辑
  16 + const [addModal, setAddModal] = useState<{
  17 + visible: boolean;
  18 + row?: API.Item;
  19 + }>({
  20 + visible: false,
  21 + });
  22 +
  23 + const { list, paginationConfig, loading, innerParams, setParams } = usePagination<API.Item>(API.getFoodWhitePage);
  24 +
  25 + const handleDelete = (row: API.Item) => {
  26 + const { id } = row;
  27 + API.delFoodWhite(id!)
  28 + .then((res) => {
  29 + message.success(res.result);
  30 + setParams({ ...innerParams }, true);
  31 + })
  32 + .catch((e) => {
  33 + message.error(e.message);
  34 + });
  35 + };
  36 +
  37 + const handleEdit = (row: API.Item) => {
  38 + setAddModal({
  39 + visible: true,
  40 + row,
  41 + });
  42 + };
  43 +
  44 + return (
  45 + <PageHeaderWrapper title="就餐白名单">
  46 + <ConfigProvider locale={zhCN}>
  47 + <Card>
  48 + <Row align="middle" justify="space-between" style={{ marginBottom: 20 }}>
  49 + <Filter innerParams={innerParams} setParams={setParams} />
  50 + <Button
  51 + type="primary"
  52 + icon={<PlusOutlined />}
  53 + onClick={() => {
  54 + setAddModal({
  55 + visible: true,
  56 + });
  57 + }}
  58 + >
  59 + 新增
  60 + </Button>
  61 + </Row>
  62 + <Table
  63 + loading={loading}
  64 + dataSource={list}
  65 + pagination={paginationConfig}
  66 + rowKey="id"
  67 + onChange={(_pagination) => setParams({ ..._pagination }, true)}
  68 + >
  69 + <Column title="姓名" dataIndex="name" />
  70 + <Column title="手机号" dataIndex="mobile" />
  71 + <Column title="备注" dataIndex="remark" />
  72 + <Column
  73 + title="操作"
  74 + dataIndex="btns"
  75 + render={(text, row: API.Item) => (
  76 + <span>
  77 + <a
  78 + onClick={(e) => {
  79 + e.preventDefault();
  80 + handleEdit(row);
  81 + }}
  82 + >
  83 + 编辑
  84 + </a>
  85 + <Divider type="vertical" />
  86 + <Popconfirm title="是否删除?" onConfirm={() => handleDelete(row)}>
  87 + <a
  88 + onClick={(e) => {
  89 + e.preventDefault();
  90 + }}
  91 + style={{ color: 'red' }}
  92 + >
  93 + 删除
  94 + </a>
  95 + </Popconfirm>
  96 + </span>
  97 + )}
  98 + />
  99 + </Table>
  100 + </Card>
  101 + <AddModal
  102 + visible={addModal.visible}
  103 + row={addModal.row}
  104 + onCancel={() => {
  105 + setAddModal({ visible: false });
  106 + }}
  107 + onRefresh={() => setParams({ ...innerParams }, true)}
  108 + />
  109 + </ConfigProvider>
  110 + </PageHeaderWrapper>
  111 + );
  112 +}
... ...
src/pages/decoration/deco/DecorationPromotion/DecorateFullFree/components/Modal.tsx
... ... @@ -8,7 +8,7 @@ import ShopDetail from &#39;./ShopDetail&#39;;
8 8 import AddBrand from './AddBrand';
9 9 import AddSerie from './AddSerie';
10 10 import AddSpec from './AddSpec';
11   -import ShopSelect from '@/components/ShopSelectNew';
  11 +import ShopSelect from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
12 12  
13 13 const FormItem = Form.Item;
14 14 const { RangePicker } = DatePicker;
... ... @@ -316,7 +316,7 @@ export default function AddModal(props: Props) {
316 316 &nbsp;元(包含)&nbsp;&nbsp;送&nbsp;&nbsp;
317 317 <InputNumber defaultValue={item.expect} onChange={(value) => _changeTwo(value, index)} min={0} />
318 318 &nbsp;元 &nbsp;&nbsp;
319   - <DeleteOutlined onClick={() => deleteItem(index)} style={{ color: 'red', fontSize: 16 }} />
  319 + <DeleteOutlined rev={undefined} onClick={() => deleteItem(index)} style={{ color: 'red', fontSize: 16 }} />
320 320 </div>
321 321 ))}
322 322 <Button type="primary" style={{ marginTop: 20 }} onClick={addList}>
... ... @@ -328,7 +328,7 @@ export default function AddModal(props: Props) {
328 328 <RangePicker format="YYYY-MM-DD" disabledDate={(current) => disalbeTime(current)} />
329 329 </Form.Item>
330 330 <FormItem label="适用门店" name="applyShops" rules={[{ required: true, message: '请选择门店' }]}>
331   - <ShopSelect multiple />
  331 + <ShopSelect />
332 332 </FormItem>
333 333 <FormItem name="decos" label="必选装潢">
334 334 <Tabs type="card">
... ...
src/pages/decoration/deco/DecorationPromotion/DecorationPackage/components/Modal.tsx
1 1 import React, { useEffect, useState } from 'react';
2   -import { Modal, Form, Input, DatePicker, Select, InputNumber, Button, message } from 'antd';
  2 +import { Modal, Form, Input, DatePicker, InputNumber, Button, message } from 'antd';
3 3 import { DeleteOutlined } from '@ant-design/icons';
4 4 import moment from 'moment';
5 5 import { useStore } from '../index';
6   -import { getShopApi } from "@/common/api";
7   -import useInitial from '@/hooks/useInitail';
8 6 import * as API from '../api';
9   -import ShopSelect from "@/components/ShopSelectNew";
  7 +import ShopSelect from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
10 8  
11 9 const FormItem = Form.Item;
12   -const { Option } = Select;
13 10 const { RangePicker } = DatePicker;
14 11  
15 12 interface Props {
16   - setLoading: (value:any) => any
  13 + setLoading: (value: any) => any
17 14 }
18 15  
19   -export default function AddModal(props:Props) {
  16 +export default function AddModal(props: Props) {
20 17 const {setLoading} = props;
21   - const { data: shopData } = useInitial(getShopApi, [], {});
22 18 const [form] = Form.useForm();
23   - const { visible, setVisible, confirLoading, current = {} } = useStore();
  19 + const { visible, setVisible, confirLoading } = useStore();
24 20 const [discountList, setDiscountList] = useState<any>([]);
25 21  
26 22 useEffect(() => {
... ... @@ -122,6 +118,7 @@ export default function AddModal(props:Props) {
122 118 />
123 119 &nbsp;元 &nbsp;&nbsp;
124 120 <DeleteOutlined
  121 + rev={undefined}
125 122 onClick={() => deleteItem(index)}
126 123 style={{ color: "red", fontSize: 16 }}
127 124 />
... ... @@ -137,7 +134,7 @@ export default function AddModal(props:Props) {
137 134 name="applyShops"
138 135 rules={[{ required: true, message: "请选择门店" }]}
139 136 >
140   - <ShopSelect multiple />
  137 + <ShopSelect />
141 138 </FormItem>
142 139 </Form>
143 140 </Modal>
... ...
src/pages/decoration/deco/DecorationPromotion/SPPManage/subPage/AddPage.tsx
1 1 import React, { useState } from 'react';
2   -import { Button, DatePicker, Input, Select, Card, Form, message} from 'antd';
  2 +import { Button, DatePicker, Input, Card, Form, message} from 'antd';
3 3 import moment from 'moment';
4   -import {getShopApi} from '@/common/api';
5   -import useInitial from '@/hooks/useInitail';
6 4 import ShopDetail from './ShopDetail';
7 5 import * as API from '../api';
8 6 import { useStore } from "../index";
9   -import ShopSelect from "@/components/ShopSelectNew";
  7 +import ShopSelect from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
10 8  
11 9 const { RangePicker } = DatePicker;
12   -const { Option } = Select;
13   -
14 10 const FormItem = Form.Item;
15 11  
16 12 interface Props {
... ... @@ -19,13 +15,11 @@ interface Props {
19 15  
20 16 export default function AddPage({onReturn}: Props) {
21 17 const { setCurrentBreadcrumb} = useStore();
22   - const {data: shopData} = useInitial(getShopApi, [], {});
23 18 const [specData, setSpecData] = useState<any>([]);
24   -
25 19 const [form] = Form.useForm();
26 20  
27   - const onFinish = (value:any) => {
28   - specData.map((res:any) => {
  21 + const onFinish = (value: any) => {
  22 + specData.map((res: any) => {
29 23 res.goodsId = res.id;
30 24 return res;
31 25 });
... ... @@ -47,7 +41,7 @@ export default function AddPage({onReturn}: Props) {
47 41 });
48 42 };
49 43  
50   - const disalbeTime = (current:any) => {
  44 + const disalbeTime = (current: any) => {
51 45 return current && current <moment().subtract(1, "days"); //当天之前的不可选,不包括当天
52 46 //return current && current < moment().endOf(‘day');当天之前的不可选,包括当天
53 47 };
... ... @@ -82,22 +76,7 @@ export default function AddPage({onReturn}: Props) {
82 76 name="applyShops"
83 77 rules={[{ required: true, message: "请选择门店" }]}
84 78 >
85   - <ShopSelect multiple />
86   - {/* <Select
87   - optionFilterProp="children"
88   - mode="multiple"
89   - labelInValue
90   - allowClear
91   - style={{ width: 300 }}
92   - placeholder="请选择门店"
93   - >
94   - {shopData &&
95   - shopData.map((shop: any) => (
96   - <Option value={shop.id} key={shop.id}>
97   - {shop.name}
98   - </Option>
99   - ))}
100   - </Select> */}
  79 + <ShopSelect />
101 80 </FormItem>
102 81 <FormItem name="goods" label="装潢促销">
103 82 <ShopDetail
... ...
src/pages/decoration/deco/DeoGoodsManagement/components/AddShop.tsx
1   -import React, { useEffect, useState } from "react";
2   -import {
3   - Modal,
4   - Form,
5   - Input,
6   - DatePicker,
7   - Select,
8   - InputNumber,
9   - Button,
10   - message,
11   -} from "antd";
12   -import { DeleteOutlined } from "@ant-design/icons";
13   -import moment from "moment";
14   -import { useStore } from "../index";
15   -import { getShopApi } from "@/common/api";
  1 +import React, { useEffect } from "react";
  2 +import { Modal, Form, message } from "antd";
16 3 import useInitial from "@/hooks/useInitail";
17 4 import * as API from "../api";
18   -import ShopSelect from "@/components/ShopSelectNew";
  5 +import SelectorWithFull from '@/components/SelectorWithFull';
  6 +import { getShops } from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew/api';
19 7  
20 8 const FormItem = Form.Item;
21 9  
... ... @@ -29,7 +17,7 @@ export default function AddModal(props: Props) {
29 17 const { current, setCurrent, setLoading } = props;
30 18 const [form] = Form.useForm();
31 19  
32   - const {data: afterList} = useInitial(getShopApi, [], {})
  20 + const { data } = useInitial(getShops, [], {})
33 21  
34 22 useEffect(() => {
35 23 form.resetFields();
... ... @@ -39,11 +27,11 @@ export default function AddModal(props: Props) {
39 27 const _list = (value.applyShops || []).map((e: any) => {
40 28 return {
41 29 goodsId: current.goodsId,
42   - shopId: e.shopId
  30 + shopId: e.value
43 31 }
44 32 })
45 33 API.upListApi({goods: _list })
46   - .then((res) => {
  34 + .then(() => {
47 35 setCurrent({ visible: false, goodsId: undefined });
48 36 setLoading(true);
49 37 })
... ... @@ -52,18 +40,26 @@ export default function AddModal(props: Props) {
52 40  
53 41 return (
54 42 <Modal
55   - visible={current.visible}
  43 + open={current.visible}
56 44 onCancel={() => setCurrent({visible: false, goosId: undefined})}
57 45 width={800}
58 46 onOk={() => form.submit()}
59 47 >
60   - <Form form={form} onFinish={handleSave}>
  48 + <Form form={form} onFinish={handleSave} labelCol={{span: 3}} wrapperCol={{span: 18}}>
61 49 <FormItem
62 50 label="适用门店"
63 51 name="applyShops"
64 52 rules={[{ required: true, message: "请选择门店" }]}
65 53 >
66   - <ShopSelect multiple style={{width: 500}} type={2} shopIds={afterList.map(e => e.id)} />
  54 + <SelectorWithFull
  55 + treeNodeFilterProp="label"
  56 + labelInValue
  57 + data={data}
  58 + multiple
  59 + allowClear
  60 + autoClearSearchValue={false}
  61 + placeholder="请选择门店或输入关键词筛选"
  62 + />
67 63 </FormItem>
68 64 </Form>
69 65 </Modal>
... ...
src/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew/api.ts 0 → 100644
  1 +import type { http } from "@/typing/http";
  2 +import request from "@/utils/request";
  3 +import { DECORATION } from "@/utils/host";
  4 +
  5 +export interface Shop {
  6 + value: number;
  7 + label: string;
  8 +}
  9 +export function getShops(): http.PromiseResp<Shop[]> {
  10 + return request.get(`${DECORATION}/deco/common/get/group/deco/shops`)
  11 +}
0 12 \ No newline at end of file
... ...
src/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew/index.tsx 0 → 100644
  1 +import useInitial from '@/hooks/useInitail';
  2 +import React from 'react';
  3 +import type { Shop } from './api';
  4 +import { getShops } from './api';
  5 +import SelectorWithFull from '@/components/SelectorWithFull';
  6 +import st from './style.less'
  7 +
  8 +interface Props {
  9 + value?: Shop[]
  10 + onChange?: (v: Shop[]) => void
  11 +}
  12 +
  13 +export default function ShopSelect(props: Props) {
  14 + const { value, onChange } = props;
  15 + const { data } = useInitial(getShops, [], {})
  16 + return (
  17 + <SelectorWithFull
  18 + treeNodeFilterProp="label"
  19 + value={value}
  20 + onChange={onChange}
  21 + labelInValue
  22 + data={data}
  23 + multiple
  24 + allowClear
  25 + autoClearSearchValue={false}
  26 + placeholder="请选择门店或输入关键词筛选"
  27 + className={st.select_deco}
  28 + />
  29 + )
  30 +}
0 31 \ No newline at end of file
... ...
src/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew/style.less 0 → 100644
  1 +.select_deco {
  2 + margin-bottom: 20px;
  3 +}
0 4 \ No newline at end of file
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/DecoContent/index.tsx
1 1 import { Button, Checkbox, Popconfirm, Cascader, Divider, Input, message, Radio, Row, Spin, Table } from 'antd';
2   -import { CheckboxChangeEvent } from 'antd/lib/checkbox';
  2 +import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
3 3 import React from 'react';
4 4 import { useStore } from '../../index';
5   -import { WorkItem, getSeriesApi, getSpecApi } from '../../../../api';
  5 +import type { WorkItem} from '../../../../api';
  6 +import { getSeriesApi, getSpecApi } from '../../../../api';
6 7 import ShopModal from '../../../../../common/Shop';
7 8  
8 9 const { Search } = Input;
... ... @@ -14,14 +15,13 @@ interface Props {
14 15  
15 16 type TableType = '列表' | '选择';
16 17  
17   -function Deco({ type = 1, multiple = true }: Props) {
  18 +function Deco({ multiple = true }: Props) {
18 19 const {
19 20 list,
20 21 setParams,
21 22 decoSelected: selected,
22 23 setDecoSelected: setSelected,
23 24 loading,
24   - paginationConfig,
25 25 brandOptions,
26 26 setBrandOptions,
27 27 } = useStore();
... ... @@ -55,7 +55,7 @@ function Deco({ type = 1, multiple = true }: Props) {
55 55 setParams({ keywords: e }, true);
56 56 }
57 57  
58   - function filterBySeries(value: any[], selectedOptions: any) {
  58 + function filterBySeries(value: any[]) {
59 59 if (value.length > 0) {
60 60 const seriesFilter = {
61 61 brandId: value[0],
... ... @@ -87,7 +87,7 @@ function Deco({ type = 1, multiple = true }: Props) {
87 87 getSeriesApi(targetOption.id)
88 88 .then((res: any) => {
89 89 const { data = [] } = res;
90   - targetOption.children = data.map((list: any, index: any) => ({
  90 + targetOption.children = data.map((list: any) => ({
91 91 id: list.id,
92 92 name: list.name,
93 93 isLeaf: false,
... ... @@ -104,7 +104,7 @@ function Deco({ type = 1, multiple = true }: Props) {
104 104 const { data = [] } = res;
105 105 targetOption.loading = false;
106 106 targetOption.children = [];
107   - data.forEach((list, index) => {
  107 + data.forEach((list) => {
108 108 targetOption.children.push({
109 109 id: list.id,
110 110 name: list.name,
... ... @@ -215,7 +215,7 @@ function Deco({ type = 1, multiple = true }: Props) {
215 215 当前选择({selected.length} 个)
216 216 </Radio.Button>
217 217 </Radio.Group>
218   - <Row>
  218 + <Row align="middle">
219 219 {multiple ? (
220 220 <Checkbox className="ShopSelectNew_checkbox" indeterminate={checkInfo.indeterminate} checked={checkInfo.checkAll} onChange={checkAll}>
221 221 全选
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/ShopContent/api.ts deleted
1   -/*
2   - * @Date: 2021-07-08 16:53:36
3   - * @LastEditors: wangqiang@feewee.cn
4   - * @LastEditTime: 2022-05-25 11:32:53
5   - */
6   -import type { http } from "@/typing/http";
7   -import request from "@/utils/request";
8   -import { OOP_HOST } from "@/utils/host";
9   -import type { LabelValueType } from "rc-tree-select/lib/interface";
10   -
11   -export interface QueryParams {
12   - type: 1 | 2; // 1 集团维度 2 自定义门店维度
13   - shops?: string; // 门店集合 ,分割
14   - keywords?: string; // 门店关键字搜索
15   - bizTypes?: string; // 业态类型集合 ,分割
16   - brands?: string; // 品牌id集合 ,分割
17   - regions?: string; // 区域编码集合 ,分割
18   - dealers?: string; // 商家id集合 ,分割
19   -}
20   -
21   -export interface ShopItem {
22   - shopId: number; //门店id
23   - shopFullName?: string; //门店全称
24   - shopShortName?: string; //门店简称
25   - casShopId?: number; //对应售后门店id(只有售前业态门店有)
26   - casShopName?: string; //对应售后门店名称
27   - bizType?: number; //业态类型
28   - region?: Region;
29   - dealer?: DealerOrBrand;
30   - brandList?: DealerOrBrand[]; //只有售前业态门店有
31   -}
32   -export interface Value extends ShopItem, LabelValueType {}
33   -
34   -export enum BizType {
35   - "新车销售" = 1,
36   - "售后",
37   - "二手车",
38   - "租车",
39   - "交付中心"
40   -}
41   -
42   -export interface Region {
43   - bh?: string; // 区域编码
44   - name?: string; // 区域名称
45   - fullName?: string; // 区域全称
46   -}
47   -
48   -export interface DealerOrBrand {
49   - id?: number;
50   - name?: string;
51   -}
52   -
53   -/**
54   - * @description: 门店选择列表
55   - * @param {QueryParams} params
56   - * @return {http.PromiseResp<ShopItem[]>}
57   - */
58   -export function getShopListApi(
59   - params: QueryParams
60   -): http.PromiseResp<ShopItem[]> {
61   - return request.get(`${OOP_HOST}/select/shop/classify`, { params });
62   -}
63   -
64   -export interface Option {
65   - bizList?: Biz[];
66   - regionList?: Region[];
67   - brandList?: DealerOrBrand[];
68   - dealerList?: DealerOrBrand[];
69   -}
70   -
71   -export interface Biz {
72   - type?: number;
73   - name?: string;
74   -}
75   -
76   -/**
77   - * @description: 门店选择条件
78   - * @param {QueryParams} params
79   - * @return {http.PromiseResp<Option>}
80   - */
81   -export function getShopListChooseOptionsApi(
82   - params: QueryParams
83   -): http.PromiseResp<Option> {
84   - return request.get(`${OOP_HOST}/select/shop/filters`, { params });
85   -}
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/ShopContent/index.tsx deleted
1   -import useInitial from '@/hooks/useInitail';
2   -import { Button, Checkbox, Divider, Input, Popconfirm, Popover, Radio, Row, Select, Spin, Table } from 'antd';
3   -import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
4   -import { debounce } from 'lodash';
5   -import React from 'react';
6   -import type { ShopItem, DealerOrBrand, Value} from './api';
7   -import { BizType, getShopListChooseOptionsApi, getShopListApi } from './api';
8   -import { useStore } from '../../index';
9   -
10   -interface Props {
11   - type?: 1 | 2; // 1 集团维度 2 自定义门店维度
12   - multiple?: boolean;
13   -}
14   -
15   -type TableType = '列表' | '选择';
16   -
17   -function Shop({ type = 1, multiple = true }: Props) {
18   - const { shopSelected: selected, setShopSelected: setSelected } = useStore();
19   - const optionInitial = useInitial(getShopListChooseOptionsApi, {}, { type });
20   - const listInitial = useInitial(getShopListApi, [], {
21   - type,
22   - bizTypes: '1,2,3,5',
23   - });
24   - const [checkInfo, setCheckInfo] = React.useState({
25   - indeterminate: false,
26   - checkAll: false,
27   - });
28   - const fetchListByName = debounce((keywords) => {
29   - listInitial.setParams({ type, keywords }, true);
30   - // setCheckInfo({
31   - // indeterminate: false,
32   - // checkAll: false,
33   - // });
34   - // setSelected([]);
35   - }, 500);
36   -
37   - const [tableType, setTableType] = React.useState<TableType>('列表');
38   -
39   - React.useEffect(() => {
40   - setCheckInfo({
41   - indeterminate: selected.length > 0 && listInitial.data.length !== selected.length,
42   - checkAll: selected.length > 0 && listInitial.data.length === selected.length,
43   - });
44   - }, [selected, listInitial.data]);
45   -
46   - /**
47   - * @description: 当一个门店被点击时,触发该回调函数。
48   - * @param {ShopItem} record 当前门店数据
49   - * @param {boolean} _selected 是否选中
50   - * @param {Object[]} selectedRows 已被选择的数据
51   - * @param {Event} nativeEvent 点击事件
52   - */
53   - const onSelect = (record: ShopItem, _selected: boolean, selectedRows: Object[], nativeEvent: Event) => {
54   - if (multiple) {
55   - if (_selected) {
56   - // 若被选择,则将该数据处理后,插入已选择列表中
57   - setSelected([...selected, { ...record, value: record.shopId, label: record.shopShortName }]);
58   - } else {
59   - // 若被取消选择,则将该数据,从已选择列表中删除
60   - setSelected(selected.filter((item) => item.shopId !== record.shopId));
61   - }
62   - } else {
63   - true;
64   - if (_selected) {
65   - setSelected([{ ...record, value: record.shopId, label: record.shopShortName }]);
66   - } else {
67   - setSelected([]);
68   - }
69   - }
70   - };
71   -
72   - /**
73   - * @description: 当全选CheckBox被点击时,调用该回调函数
74   - * @description: 只有 多选才会调用该全选函数,故起函数内部不需要判断是否多选情况
75   - * @param {boolean} _selected 是否选中
76   - * @param {ShopItem[]} selectedRows 已被选择的数据列表
77   - * @param {ShopItem[]} changeRows 点击全选CheckBox后,受影响的数据列表。该数据与_selected参数共同使用,可以得知是应该将changeRows数据加入已选中数据还是删除
78   - */
79   - const onSelectAll = (_selected: boolean, selectedRows: ShopItem[], changeRows: ShopItem[]) => {
80   - if (_selected) {
81   - // 若选中全选CheckBox,则将changeRows中的还未被选入selected中的数据插入
82   - setSelected(
83   - selected.concat(
84   - changeRows.map((row) => ({
85   - ...row,
86   - value: row.shopId,
87   - label: row.shopShortName,
88   - })),
89   - ),
90   - );
91   - } else {
92   - // 若取消选择全选CheckBox,则将changeRows中的数据全部从selected中删除
93   - const cancelIds = changeRows.map((row) => row.shopId);
94   - // @ts-ignore
95   - setSelected(selected.filter((item) => !cancelIds.includes(item.value)));
96   - }
97   - };
98   -
99   - const rowClick = (record: Value) => {
100   - if (multiple) {
101   - if (selected.some((item) => item.value === record.shopId)) {
102   - setSelected(selected.filter((item) => item.value !== record.shopId));
103   - } else {
104   - setSelected(
105   - selected.concat({
106   - ...record,
107   - value: record.shopId,
108   - label: record.shopShortName,
109   - }),
110   - );
111   - }
112   - } else {
113   - setSelected([{ ...record, value: record.shopId, label: record.shopShortName }]);
114   - }
115   - };
116   -
117   - const checkAll = (e: CheckboxChangeEvent) => {
118   - const checked = e.target.checked;
119   - setSelected(
120   - checked
121   - ? listInitial.data.map((item) => ({
122   - ...item,
123   - value: item.shopId,
124   - label: item.shopShortName,
125   - }))
126   - : [],
127   - );
128   - };
129   -
130   - return (
131   - <div>
132   - <>
133   - <Row justify="space-between">
134   - <Radio.Group buttonStyle="solid" value={tableType} onChange={(e) => setTableType(e.target.value)}>
135   - <Radio.Button value="列表">列表</Radio.Button>
136   - <Radio.Button value="选择" disabled={!selected.length}>
137   - 当前选择({selected.length} 个)
138   - </Radio.Button>
139   - </Radio.Group>
140   - <Row>
141   - {multiple ? (
142   - <Checkbox className="ShopSelectNew_checkbox" indeterminate={checkInfo.indeterminate} checked={checkInfo.checkAll} onChange={checkAll}>
143   - 全选
144   - </Checkbox>
145   - ) : null}
146   - <Popconfirm
147   - title="确定清空已选择门店?"
148   - disabled={!selected.length}
149   - onConfirm={() => {
150   - setSelected([]);
151   - setTableType('列表');
152   - }}
153   - >
154   - <Button danger type="link" disabled={!selected.length}>
155   - 清空
156   - </Button>
157   - </Popconfirm>
158   - </Row>
159   - </Row>
160   - <Divider />
161   - </>
162   - <Spin spinning={optionInitial.loading}>
163   - <Row justify="start" align="middle" style={{ display: tableType === '列表' ? 'flex' : 'none' }} className="ShopSelectNew_Filter_Container">
164   - <Input
165   - allowClear
166   - placeholder="请输入门店名查询"
167   - // value={listInitial.params.keywords}
168   - onChange={(e) => fetchListByName(e.target.value)}
169   - style={{ maxWidth: 260, marginRight: 10, marginBottom: 10 }}
170   - />
171   - <Select
172   - allowClear
173   - placeholder="请选择业态"
174   - mode="multiple"
175   - value={listInitial.params.bizTypes ? listInitial.params.bizTypes.split(',') : undefined}
176   - onChange={(bizs) => listInitial.setParams({ type, bizTypes: bizs?.join(',') }, true)}
177   - // value="1"
178   - // disabled
179   - showSearch
180   - optionFilterProp="children"
181   - style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }}
182   - getPopupContainer={(triggerNode) => triggerNode.parentNode}
183   - >
184   - {optionInitial.data.bizList
185   - ?.filter((item) => item.type !== 4)
186   - .map((biz) => (
187   - <Select.Option key={biz.type} value={'' + biz.type!}>
188   - {biz.name}
189   - </Select.Option>
190   - ))}
191   - </Select>
192   - <Select
193   - allowClear
194   - placeholder="请选择区域"
195   - mode="multiple"
196   - value={listInitial.params.regions ? listInitial.params.regions.split(',') : undefined}
197   - onChange={(regions) => listInitial.setParams({ type, regions: regions?.join(',') }, true)}
198   - showSearch
199   - optionFilterProp="children"
200   - style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }}
201   - getPopupContainer={(triggerNode) => triggerNode.parentNode}
202   - >
203   - {optionInitial.data.regionList?.map((region) => (
204   - <Select.Option key={region.bh} value={region.bh!}>
205   - {region.fullName}
206   - </Select.Option>
207   - ))}
208   - </Select>
209   - <Select
210   - allowClear
211   - placeholder="请选择品牌"
212   - mode="multiple"
213   - value={listInitial.params.brands ? listInitial.params.brands.split(',') : undefined}
214   - onChange={(brandList) => listInitial.setParams({ type, brands: brandList?.join(',') }, true)}
215   - showSearch
216   - optionFilterProp="children"
217   - style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }}
218   - getPopupContainer={(triggerNode) => triggerNode.parentNode}
219   - >
220   - {optionInitial.data.brandList?.map((brand) => (
221   - <Select.Option key={brand.id} value={'' + brand.id!}>
222   - {brand.name}
223   - </Select.Option>
224   - ))}
225   - </Select>
226   - <Select
227   - allowClear
228   - placeholder="请选择商家"
229   - mode="multiple"
230   - value={listInitial.params.dealers ? listInitial.params.dealers.split(',') : undefined}
231   - onChange={(dealerList) => listInitial.setParams({ type, dealers: dealerList?.join(',') }, true)}
232   - showSearch
233   - optionFilterProp="children"
234   - style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }}
235   - getPopupContainer={(triggerNode) => triggerNode.parentNode}
236   - >
237   - {optionInitial.data.dealerList?.map((dealer) => (
238   - <Select.Option key={dealer.id} value={'' + dealer.id!}>
239   - {dealer.name}
240   - </Select.Option>
241   - ))}
242   - </Select>
243   - </Row>
244   - </Spin>
245   - <Table
246   - dataSource={tableType === '列表' ? listInitial.data : selected}
247   - rowKey="shopId"
248   - size="small"
249   - loading={listInitial.loading}
250   - onRow={(record) => ({
251   - onClick: () => rowClick(record),
252   - })}
253   - rowSelection={{
254   - type: multiple ? 'checkbox' : 'radio',
255   - selectedRowKeys: selected.map((item) => item.value || item.shopId || -1),
256   - onSelect,
257   - onSelectAll,
258   - }}
259   - >
260   - <Table.Column title="门店名称" dataIndex="shopFullName" align="left" render={(shopFullName) => shopFullName || '-'} />
261   - <Table.Column title="门店简称" dataIndex="shopShortName" align="left" render={(shopFullName) => shopFullName || '-'} />
262   - <Table.Column title="门店业态" dataIndex="bizType" align="left" render={(bizType) => (bizType ? BizType[bizType] : '-')} />
263   - <Table.Column title="归属公司" dataIndex="dealer" align="left" render={(dealer) => dealer?.name || '-'} />
264   - <Table.Column title="门店区域" dataIndex="region" align="left" render={(region) => region?.fullName || '-'} />
265   - <Table.Column
266   - title="授权品牌"
267   - dataIndex="brandList"
268   - align="left"
269   - render={(brandList: DealerOrBrand[]) =>
270   - brandList?.length ? (
271   - <Popover
272   - placement="topLeft"
273   - content={
274   - <span>
275   - {brandList?.map((brand) => (
276   - <div key={brand.id}>{brand.name}</div>
277   - ))}
278   - </span>
279   - }
280   - >
281   - <span className="span_limit_1">{brandList?.map((brand) => brand.name).join(';')}</span>
282   - </Popover>
283   - ) : (
284   - '-'
285   - )
286   - }
287   - />
288   - <Table.Column title="对应售后门店" dataIndex="casShopName" align="left" render={(casShopName) => casShopName || '-'} />
289   - </Table>
290   - </div>
291   - );
292   -}
293   -
294   -export default Shop;
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/Step2.tsx
1 1 import React from 'react';
2 2 import { Card, Button } from 'antd';
3   -import ShopContent from './ShopContent';
  3 +import ShopContent from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
4 4 import DecoContent from './DecoContent';
5   -
  5 +import { useStore } from '../index'
6 6 interface Props {
7 7 onNext: () => any;
8 8 onBack: () => any;
... ... @@ -19,10 +19,10 @@ export default function Step2(props: Props) {
19 19 disabled,
20 20 way,
21 21 } = props;
22   -
  22 + const { shopSelected, setShopSelected } = useStore();
23 23 return (
24 24 <Card bordered={false}>
25   - {way === 1 ? <DecoContent /> : <ShopContent />}
  25 + {way === 1 ? <DecoContent /> : <ShopContent value={shopSelected} onChange={setShopSelected} />}
26 26  
27 27 <div style={{ display: "flex", justifyContent: "center" }}>
28 28 <Button loading={loading} style={{ width: 120 }} onClick={onBack}>
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/Step3.tsx
1 1 import React from "react";
2 2 import { Card, Button } from "antd";
3   -import ShopContent from "./ShopContent";
  3 +import ShopContent from "@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew";
4 4 import DecoContent from "./DecoContent";
5   -
  5 +import { useStore } from '../index'
6 6 interface Props {
7 7 onNext: () => any;
8 8 onBack: () => any;
... ... @@ -13,10 +13,10 @@ interface Props {
13 13  
14 14 export default function Step3(props: Props) {
15 15 const { onNext, onBack, loading, disabled, way} = props;
16   -
  16 + const { shopSelected, setShopSelected } = useStore();
17 17 return (
18 18 <Card bordered={false}>
19   - {way === 1 ? <ShopContent /> : <DecoContent />}
  19 + {way === 1 ? <ShopContent value={shopSelected} onChange={setShopSelected} /> : <DecoContent />}
20 20  
21 21 <div style={{ display: "flex", justifyContent: "center" }}>
22 22 <Button loading={loading} style={{ width: 120 }} onClick={onBack}>
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/index.tsx
1   -import React, { useEffect, useState } from 'react';
  1 +import React, { useState } from 'react';
2 2 import { Card, Steps, message, Tabs, Form } from 'antd';
3 3 import { PageHeaderWrapper } from '@ant-design/pro-layout';
4 4 import Step1 from './components/Step1';
... ... @@ -38,7 +38,7 @@ const Index = () =&gt; {
38 38 }
39 39 form
40 40 .validateFields(names)
41   - .then((res) => {
  41 + .then(() => {
42 42 setCurrent(cur);
43 43 setWay(form.getFieldValue('way'));
44 44 })
... ... @@ -57,8 +57,6 @@ const Index = () =&gt; {
57 57 }
58 58  
59 59 function _save() {
60   - console.log('门店', shopSelected);
61   - console.log('装潢', decoSelected);
62 60 if (shopSelected.length === 0) {
63 61 message.error('请选择门店');
64 62 return;
... ... @@ -70,12 +68,12 @@ const Index = () =&gt; {
70 68 const _list = { goods: [] } as API.UpParams;
71 69 for (let i = 0; i < decoSelected.length; i++) {
72 70 for (let j = 0; j < shopSelected.length; j++) {
73   - _list.goods.push({ goodsId: decoSelected[i].id, shopId: shopSelected[j].shopId });
  71 + _list.goods.push({ goodsId: decoSelected[i].id, shopId: shopSelected[j].value });
74 72 }
75 73 }
76 74 setSubmitLoading(true);
77 75 API.upListApi({ ..._list })
78   - .then((res) => {
  76 + .then(() => {
79 77 setCurrent(3);
80 78 setSubmitLoading(false);
81 79 })
... ... @@ -98,7 +96,7 @@ const Index = () =&gt; {
98 96 <TabPane key="0">
99 97 <Step1
100 98 form={form}
101   - onValuesChange={(changeValue, values) => {
  99 + onValuesChange={(changeValue) => {
102 100 setWay(changeValue.way || 1);
103 101 }}
104 102 disabled={disabled}
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/putOnShelves/components/DecoContent/index.tsx
1 1 import { Button, Checkbox, Popconfirm, Cascader, Divider, Input, message, Radio, Row, Spin, Table } from 'antd';
2   -import { CheckboxChangeEvent } from 'antd/lib/checkbox';
  2 +import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
3 3 import React from 'react';
4 4 import { useStore } from '../../index';
5   -import { WorkItem, getSeriesApi, getSpecApi } from '../../../../api';
  5 +import type { WorkItem} from '../../../../api';
  6 +import { getSeriesApi, getSpecApi } from '../../../../api';
6 7 import ShopModal from '../../../../../common/Shop';
7 8  
8 9 const { Search } = Input;
... ... @@ -21,7 +22,6 @@ function Deco({ type = 1, multiple = true }: Props) {
21 22 decoSelected: selected,
22 23 setDecoSelected: setSelected,
23 24 loading,
24   - paginationConfig,
25 25 brandOptions,
26 26 setBrandOptions,
27 27 } = useStore();
... ... @@ -54,7 +54,7 @@ function Deco({ type = 1, multiple = true }: Props) {
54 54 setParams({ keywords: e }, true);
55 55 }
56 56  
57   - function filterBySeries(value: any[], selectedOptions: any) {
  57 + function filterBySeries(value: any[]) {
58 58 if (value.length > 0) {
59 59 const seriesFilter = {
60 60 brandId: value[0],
... ... @@ -86,7 +86,7 @@ function Deco({ type = 1, multiple = true }: Props) {
86 86 getSeriesApi(targetOption.id)
87 87 .then((res: any) => {
88 88 const { data = [] } = res;
89   - targetOption.children = data.map((list: any, index: any) => ({
  89 + targetOption.children = data.map((list: any) => ({
90 90 id: list.id,
91 91 name: list.name,
92 92 isLeaf: false,
... ... @@ -103,7 +103,7 @@ function Deco({ type = 1, multiple = true }: Props) {
103 103 const { data = [] } = res;
104 104 targetOption.loading = false;
105 105 targetOption.children = [];
106   - data.forEach((list, index) => {
  106 + data.forEach((list) => {
107 107 targetOption.children.push({
108 108 id: list.id,
109 109 name: list.name,
... ... @@ -214,7 +214,7 @@ function Deco({ type = 1, multiple = true }: Props) {
214 214 当前选择({selected.length} 个)
215 215 </Radio.Button>
216 216 </Radio.Group>
217   - <Row>
  217 + <Row align="middle">
218 218 {multiple ? (
219 219 <Checkbox className="ShopSelectNew_checkbox" indeterminate={checkInfo.indeterminate} checked={checkInfo.checkAll} onChange={checkAll}>
220 220 全选
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/putOnShelves/components/Step2.tsx
1 1 import React from 'react';
2 2 import { Card, Button } from 'antd';
3   -import ShopContent from './ShopContent';
  3 +import ShopContent from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
4 4 import DecoContent from './DecoContent';
  5 +import { useStore } from '../index'
5 6  
6 7 interface Props {
7 8 onNext: () => any;
... ... @@ -19,10 +20,11 @@ export default function Step2(props: Props) {
19 20 disabled,
20 21 way,
21 22 } = props;
  23 + const { shopSelected, setShopSelected } = useStore();
22 24  
23 25 return (
24 26 <Card bordered={false}>
25   - {way === 1 ? <DecoContent /> : <ShopContent />}
  27 + {way === 1 ? <DecoContent /> : <ShopContent value={shopSelected} onChange={setShopSelected} />}
26 28  
27 29 <div style={{ display: "flex", justifyContent: "center" }}>
28 30 <Button loading={loading} style={{ width: 120 }} onClick={onBack}>
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/putOnShelves/components/Step3.tsx
1 1 import React from "react";
2 2 import { Card, Button } from "antd";
3   -import ShopContent from "./ShopContent";
  3 +import ShopContent from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew';
4 4 import DecoContent from "./DecoContent";
  5 +import { useStore } from '../index'
5 6  
6 7 interface Props {
7 8 onNext: () => any;
... ... @@ -13,10 +14,11 @@ interface Props {
13 14  
14 15 export default function Step3(props: Props) {
15 16 const { onNext, onBack, loading, disabled, way} = props;
  17 + const { shopSelected, setShopSelected } = useStore();
16 18  
17 19 return (
18 20 <Card bordered={false}>
19   - {way === 1 ? <ShopContent /> : <DecoContent />}
  21 + {way === 1 ? <ShopContent value={shopSelected} onChange={setShopSelected} /> : <DecoContent />}
20 22  
21 23 <div style={{ display: "flex", justifyContent: "center" }}>
22 24 <Button loading={loading} style={{ width: 120 }} onClick={onBack}>
... ...
src/pages/decoration/deco/DeoGoodsManagement/subpages/putOnShelves/index.tsx
1   -import React, { useEffect, useState } from 'react';
  1 +import React, { useState } from 'react';
2 2 import { Card, Steps, message, Tabs, Form } from 'antd';
3 3 import { PageHeaderWrapper } from '@ant-design/pro-layout';
4 4 import Step1 from './components/Step1';
... ... @@ -38,7 +38,7 @@ const Index = () =&gt; {
38 38 }
39 39 form
40 40 .validateFields(names)
41   - .then((res) => {
  41 + .then(() => {
42 42 setCurrent(cur);
43 43 setWay(form.getFieldValue('way'));
44 44 })
... ... @@ -72,13 +72,13 @@ const Index = () =&gt; {
72 72 for (let j = 0; j < shopSelected.length; j++) {
73 73 _list.goods.push({
74 74 goodsId: decoSelected[i].id,
75   - shopId: shopSelected[j].shopId,
  75 + shopId: shopSelected[j].value,
76 76 });
77 77 }
78 78 }
79 79 setSubmitLoading(true);
80 80 API.downListApi({ ..._list })
81   - .then((res) => {
  81 + .then(() => {
82 82 setCurrent(3);
83 83 setSubmitLoading(false);
84 84 })
... ...
src/pages/decoration/deco/DeoGoodsManagement/useStore.ts
  1 +/*
  2 + * @Author: jiangwei jiangwei.feewee.cn
  3 + * @Date: 2024-03-27 17:14:09
  4 + * @LastEditors: jiangwei jiangwei.feewee.cn
  5 + * @LastEditTime: 2024-03-27 17:15:50
  6 + * @FilePath: /fw-cms/src/pages/decoration/deco/DeoGoodsManagement/useStore.ts
  7 + * @Description:
  8 + *
  9 + * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
  10 + */
1 11 import { useState, useEffect } from 'react';
2 12 import type { Option } from './interface.d';
3 13 import { message } from 'antd';
... ... @@ -5,7 +15,7 @@ import usePagination from &#39;@/hooks/usePagination&#39;;
5 15 import useInitial from '@/hooks/useInitail';
6 16 import * as api from './api';
7 17 import { getGroupCasBrandApi } from '@/common/api';
8   -import type { Value } from '@/pages/decoration/deco/DeoGoodsManagement/subpages/pullOffShelves/components/ShopContent/api';
  18 +import type { Shop } from '@/pages/decoration/deco/DeoGoodsManagement/components/ShopConentNew/api';
9 19  
10 20 export default function useStore() {
11 21 const [currentType, setCurrentType] = useState<number>(0);
... ... @@ -16,7 +26,7 @@ export default function useStore() {
16 26  
17 27 const pagnation = usePagination(api.getShop, { bizType: 0, pageSize: 9999 });
18 28 // 门店选择
19   - const [shopSelected, setShopSelected] = useState<Value[]>([]);
  29 + const [shopSelected, setShopSelected] = useState<Shop[]>([]);
20 30 // 装潢选择
21 31 const [decoSelected, setDecoSelected] = useState<api.WorkItem[]>([]);
22 32 // 装潢分类
... ...
src/pages/finance/entitys.ts
... ... @@ -222,9 +222,9 @@ export const ExpireRepayRuleObj: { [key: string]: any }[] = [
222 222 // 配置类型(不可编辑):1 收入录入,2 付款申请,3 缴费申请,4 事项申请(See: 财务款项配置类型)
223 223 export enum ConfigTypeEnum {
224 224 '收入录入' = 1,
225   - '付款申请',
226   - '缴费申请',
227   - '事项申请',
  225 + // '付款申请',
  226 + '缴费申请' = 3,
  227 + '付款申请' = 4,
228 228 }
229 229  
230 230 export const ConfigType = [
... ... @@ -232,17 +232,17 @@ export const ConfigType = [
232 232 label: '收入录入',
233 233 value: ConfigTypeEnum['收入录入'],
234 234 },
235   - {
236   - label: '原付款申请',
237   - value: ConfigTypeEnum['付款申请'],
238   - },
  235 + // {
  236 + // label: '原付款申请',
  237 + // value: ConfigTypeEnum['付款申请'],
  238 + // },
239 239 {
240 240 label: '缴费申请',
241 241 value: ConfigTypeEnum['缴费申请'],
242 242 },
243 243 {
244 244 label: '付款申请',
245   - value: ConfigTypeEnum['事项申请'],
  245 + value: ConfigTypeEnum['付款申请'],
246 246 },
247 247 ];
248 248 /**
... ...