Commit 42506df2bc1673fd20301b8081729db26177a02b

Authored by boyang
2 parents 07dd077f a11effeb

Merge branch 'by' into warning

Showing 45 changed files with 7922 additions and 687 deletions
.umirc.ts
... ... @@ -141,10 +141,21 @@ export default defineConfig({
141 141 },
142 142 {
143 143 name: '客户管理',
144   - path: '/client',
145   - component: './Client',
  144 + path: '/Client',
146 145 icon: 'BookOutlined',
147 146 access: 'canReadAdminAndSales',
  147 + routes: [
  148 + {
  149 + name: '客户列表',
  150 + path: 'clint',
  151 + component: './Client/Client',
  152 + },
  153 + {
  154 + name: '跟进记录',
  155 + path: 'FollowRecord',
  156 + component: './Client/FollowRecord',
  157 + },
  158 + ],
148 159 },
149 160 {
150 161 name: '打印',
... ...
order-erp.service-1.0-SNAPSHOT.jar 0 → 100644
No preview for this file type
src/pages/Client/Components/ClientDrawer.tsx renamed to src/pages/Client/Client/Components/ClientDrawer.tsx
... ... @@ -6,23 +6,34 @@ import {
6 6 postDistrictSelectByNameAndLevel,
7 7 postDistrictSelOrderProvince,
8 8 postServiceConstClientLevels,
  9 + postServiceConstClientSource,
9 10 postServiceConstTradeStatus,
10 11 } from '@/services';
  12 +
11 13 import { enumToSelect } from '@/utils';
12 14 import {
13 15 DrawerForm,
14   - ProFormDateTimePicker,
  16 + ProFormDatePicker,
15 17 ProFormSelect,
16 18 ProFormText,
17 19 } from '@ant-design/pro-components';
18 20 import { Button, Form, message } from 'antd';
  21 +// import { options } from 'node_modules/axios/index.cjs';
19 22 import { useState } from 'react';
20 23  
21 24 export default ({ optType, record, onFinish }) => {
22 25 const [form] = Form.useForm();
  26 + const requirementsEnum = {
  27 + EXPERIMENTAL_EQUIPMENT: '实验设备',
  28 + EXPERIMENTAL_MATERIALS: '实验材料',
  29 + OTHER: '其他',
  30 + PILOT_TEST_VALIDATION_SERVICES: '中式验证服务',
  31 + };
23 32 //省市区
24 33 const [province, setProvince] = useState('');
25 34 const [city, setCity] = useState('');
  35 + const [showReferrers, setShowReferrers] = useState(false); // 控制显示的状态,初始为false
  36 + const [showQuoteDatetime, setShowQuoteDatetime] = useState(false); // 控制显示的状态,初始为false
26 37 const optTypeEnum = {
27 38 add: {
28 39 text: '新增',
... ... @@ -42,7 +53,7 @@ export default ({ optType, record, onFinish }) => {
42 53 },
43 54 edit: {
44 55 text: '编辑',
45   - button: <a type="primary">编辑</a>,
  56 + button: <a type="link">编辑</a>,
46 57 readonly: false,
47 58 onFinish: async (values) => {
48 59 const res = await postAdminClientModifyClientInfo({
... ... @@ -58,11 +69,43 @@ export default ({ optType, record, onFinish }) =&gt; {
58 69 },
59 70 detail: {
60 71 text: '详情',
61   - button: <a type="primary">详情</a>,
  72 + // button: <a type="primary">详情</a>,
62 73 readonly: true,
63 74 },
64 75 };
65 76  
  77 + const handleSourceChange = (value) => {
  78 + if (value === 'REFERRAL_BY_ACQUAINTANCE') {
  79 + setShowReferrers(true);
  80 + } else {
  81 + setShowReferrers(false);
  82 + }
  83 + // 在这里可以添加其他逻辑,比如根据选择更新其他表单项的值
  84 + };
  85 + const handleSchemeChange = (value) => {
  86 + console.log(value);
  87 + if (value === true) {
  88 + setShowQuoteDatetime(true);
  89 + } else {
  90 + setShowQuoteDatetime(false);
  91 + }
  92 + // 在这里可以添加其他逻辑,比如根据选择更新其他表单项的值
  93 + };
  94 +
  95 + // MODIFIED: 增加处理非 JSON 格式字符串的逻辑
  96 + const parsedRecord = record
  97 + ? {
  98 + ...record,
  99 + requirements: (() => {
  100 + try {
  101 + return JSON.parse(record.requirements); // 尝试解析 JSON
  102 + } catch (error) {
  103 + return record.requirements ? record.requirements.split(',') : []; // 如果不是 JSON,则按逗号分隔字符串
  104 + }
  105 + })(),
  106 + }
  107 + : {}; // 如果 record 为空,返回一个空对象
  108 +
66 109 return (
67 110 <DrawerForm
68 111 title={optTypeEnum[optType].text}
... ... @@ -73,7 +116,7 @@ export default ({ optType, record, onFinish }) =&gt; {
73 116 maxWidth: window.innerWidth * 0.8,
74 117 minWidth: 300,
75 118 }}
76   - initialValues={record}
  119 + initialValues={parsedRecord}
77 120 form={form}
78 121 trigger={optTypeEnum[optType].button}
79 122 autoFocusFirstInput
... ... @@ -98,7 +141,7 @@ export default ({ optType, record, onFinish }) =&gt; {
98 141 },
99 142 ]}
100 143 />
101   - <ProFormText
  144 + {/* <ProFormText
102 145 name="companyName"
103 146 label="单位名称"
104 147 placeholder="请输入单位名称"
... ... @@ -108,7 +151,7 @@ export default ({ optType, record, onFinish }) =&gt; {
108 151 message: '请输入单位名称',
109 152 },
110 153 ]}
111   - />
  154 + /> */}
112 155 <div
113 156 style={{
114 157 display: 'flex',
... ... @@ -260,7 +303,7 @@ export default ({ optType, record, onFinish }) =&gt; {
260 303 />
261 304 </div>
262 305 <ProFormText
263   - name="companyAddress"
  306 + name="detailAddress"
264 307 label="详细地址"
265 308 placeholder="请输入单位地址"
266 309 rules={[
... ... @@ -271,6 +314,17 @@ export default ({ optType, record, onFinish }) =&gt; {
271 314 ]}
272 315 />
273 316 <ProFormText
  317 + name="contacts"
  318 + label="联系人"
  319 + placeholder="请输入联系人"
  320 + rules={[
  321 + {
  322 + required: true,
  323 + message: '请输入联系人',
  324 + },
  325 + ]}
  326 + />
  327 + <ProFormText
274 328 name="phoneNumber"
275 329 label="联系电话"
276 330 placeholder="请输入联系电话"
... ... @@ -281,23 +335,52 @@ export default ({ optType, record, onFinish }) =&gt; {
281 335 },
282 336 ]}
283 337 />
284   - <ProFormText
  338 + <ProFormSelect
285 339 name="source"
286 340 label="客户来源"
287   - placeholder="请输入客户来源"
  341 + placeholder="请选择客户来源"
  342 + request={async () => {
  343 + const res = await postServiceConstClientSource();
  344 + return enumToSelect(res.data);
  345 + }}
  346 + rules={[
  347 + {
  348 + required: true,
  349 + message: '请选择客户来源',
  350 + },
  351 + ]}
  352 + fieldProps={{
  353 + onChange: handleSourceChange, // 添加onChange事件处理函数
  354 + }}
288 355 />
289   - <ProFormText
  356 + {showReferrers && (
  357 + <ProFormText
  358 + name="referrers"
  359 + label="推荐人"
  360 + placeholder="请输入推荐人"
  361 + />
  362 + )}
  363 + <ProFormSelect
290 364 name="requirements"
291 365 label="客户需求"
292 366 placeholder="请输入客户需求"
  367 + valueEnum={requirementsEnum}
  368 + fieldProps={{
  369 + mode: 'multiple',
  370 + }}
293 371 rules={[
294 372 {
295 373 required: true,
296 374 message: '请输入客户需求',
  375 + type: 'array',
297 376 },
298 377 ]}
  378 + // request={async () => {
  379 + // const res = await postServiceConstClientRequirements();
  380 + // console.log(res.data, '5656require');
  381 + // return enumToSelect(res.data);
  382 + // }}
299 383 />
300   - <ProFormText name="referrers" label="推荐人" placeholder="请输入推荐人" />
301 384 <ProFormSelect
302 385 name="hasScheme"
303 386 label="是否已报方案"
... ... @@ -318,12 +401,17 @@ export default ({ optType, record, onFinish }) =&gt; {
318 401 message: '请选择是否已报方案',
319 402 },
320 403 ]}
  404 + fieldProps={{
  405 + onChange: handleSchemeChange, // 添加onChange事件处理函数
  406 + }}
321 407 />
322   - <ProFormDateTimePicker
323   - name="quoteDatetime"
324   - label="报价时间"
325   - placeholder="请输入报价时间"
326   - />
  408 + {showQuoteDatetime && (
  409 + <ProFormDatePicker
  410 + name="quoteDatetime"
  411 + label="报价时间"
  412 + placeholder="请输入报价时间"
  413 + />
  414 + )}
327 415 <ProFormSelect
328 416 name="level"
329 417 label="客户等级"
... ... @@ -336,7 +424,17 @@ export default ({ optType, record, onFinish }) =&gt; {
336 424 ]}
337 425 request={async () => {
338 426 const res = await postServiceConstClientLevels();
339   - return enumToSelect(res.data);
  427 + function enumToSelectLevel(data: any) {
  428 + const order = [
  429 + 'PRIMARY_CLIENT',
  430 + 'SECONDARY_CLIENT',
  431 + 'TERTIARY_CLIENT',
  432 + ];
  433 + return order.map((key) => {
  434 + return { label: data[key], value: key };
  435 + });
  436 + }
  437 + return enumToSelectLevel(res.data);
340 438 }}
341 439 />
342 440 <ProFormSelect
... ...
src/pages/Client/Client/Components/ClientImportModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { orderExport } from '@/services/order';
  3 +import { blobToJson } from '@/utils';
  4 +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components';
  5 +import { Button, Form, message } from 'antd';
  6 +import { RcFile } from 'antd/es/upload';
  7 +import axios from 'axios';
  8 +
  9 +export default ({ reloadTable }) => {
  10 + const [form] = Form.useForm();
  11 + const [messageApi, contextHolder] = message.useMessage();
  12 + const downloadImportTemplate = () => {
  13 + messageApi.open({
  14 + type: 'loading',
  15 + content: '正在导入...',
  16 + duration: 0,
  17 + });
  18 + orderExport(
  19 + '/api/admin/client/downloadImportTemplate',
  20 + '客户导入模板.xlsx',
  21 + 'post',
  22 + {},
  23 + () => {
  24 + messageApi.destroy();
  25 + },
  26 + );
  27 + };
  28 +
  29 + return (
  30 + <ModalForm
  31 + title="导入客户信息"
  32 + trigger={<Button type="primary">导入客户信息</Button>}
  33 + form={form}
  34 + autoFocusFirstInput
  35 + modalProps={{
  36 + destroyOnClose: true,
  37 + onCancel: () => console.log('run'),
  38 + }}
  39 + submitTimeout={2000}
  40 + onFinish={async (values) => {
  41 + const formData = new FormData();
  42 + values.file.forEach((file) => {
  43 + formData.append('file', file.originFileObj as RcFile);
  44 + });
  45 + axios({
  46 + url: '/api/admin/client/importClient',
  47 + method: 'post',
  48 + responseType: 'blob',
  49 + headers: {
  50 + Authorization: localStorage.getItem('token'),
  51 + 'Content-Type':
  52 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  53 + },
  54 + data: formData,
  55 + })
  56 + .then((response) => {
  57 + let data = response.data;
  58 + if (data.type === 'application/json') {
  59 + blobToJson(data).then((dataJson) => {
  60 + if (dataJson?.result === RESPONSE_CODE.SUCCESS) {
  61 + message.success(dataJson?.message);
  62 + reloadTable();
  63 + } else {
  64 + message.error(dataJson?.message);
  65 + }
  66 + });
  67 + } else {
  68 + message.error('上传失败,已下载错误信息表格');
  69 + // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件)
  70 + const blob = new Blob([response.data]); // Excel 的 MIME 类型
  71 + const downloadUrl = window.URL.createObjectURL(blob);
  72 + const a = document.createElement('a');
  73 + a.href = downloadUrl;
  74 + a.download = '银行流水导入模板.xlsx'; // 你可以为文件命名
  75 + document.body.appendChild(a);
  76 + a.click(); // 模拟点击操作来下载文件
  77 + URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存
  78 + document.body.removeChild(a);
  79 + }
  80 + })
  81 + .catch((error) => {
  82 + // 处理错误
  83 + message.error('系统出现异常了,请联系管理员', error);
  84 + })
  85 + .finally(() => {});
  86 + return true;
  87 + }}
  88 + >
  89 + <ProFormUploadDragger max={1} label="上传" name="file" />
  90 + <Button type="link" onClick={downloadImportTemplate}>
  91 + 下载导入模板
  92 + </Button>
  93 + {contextHolder}
  94 + </ModalForm>
  95 + );
  96 +};
... ...
src/pages/Client/Client/Components/ClientInformationModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postAdminClientAddOrModifyClientComunicationInfo,
  4 + postAdminClientQueryClientPage,
  5 + postOrderErpOrderStagesUpload,
  6 + postServiceConstClientWay,
  7 +} from '@/services';
  8 +import { enumToSelect } from '@/utils';
  9 +import {
  10 + ModalForm,
  11 + ProFormDateTimePicker,
  12 + ProFormSelect,
  13 + ProFormText,
  14 + ProFormTextArea,
  15 + ProFormUploadDragger,
  16 +} from '@ant-design/pro-components';
  17 +import { Button, Form, message } from 'antd';
  18 +import { RcFile } from 'antd/es/upload';
  19 +export default ({ data, type, reloadTable }) => {
  20 + const [form] = Form.useForm();
  21 + const onfinish = async (values) => {
  22 + const resSearchId = await postAdminClientQueryClientPage({
  23 + data: {
  24 + groupFilter: 'all',
  25 + },
  26 + });
  27 + const matchingItem = resSearchId.data.data.find(
  28 + (item) => item.id === values.name,
  29 + );
  30 + let matchedId;
  31 + if (matchingItem) {
  32 + matchedId = matchingItem.id; // 匹配成功,取出 id
  33 + values.name = matchingItem.name;
  34 + } else {
  35 + matchedId = null; // 如果没有匹配项,可以设置为 null 或其他值
  36 + }
  37 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  38 + data: {
  39 + ...values,
  40 + clientId: matchedId,
  41 + },
  42 + });
  43 + if (res.result === RESPONSE_CODE.SUCCESS) {
  44 + message.success('新增成功');
  45 + reloadTable();
  46 + return true;
  47 + }
  48 + // 不返回不会关闭弹框
  49 + };
  50 + const editOnfinish = async (values) => {
  51 + // setEditClientId(data.clientId);
  52 + values.clientId = data.clientId;
  53 + console.log(values, '5656editClientId');
  54 +
  55 + // const resSearchId = await postAdminClientQueryClientPage({
  56 + // data: {
  57 + // groupFilter: 'all',
  58 + // },
  59 + // });
  60 + // const matchingItem = resSearchId.data.data.find(
  61 + // (item) => item.id === values.name,
  62 + // );
  63 +
  64 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  65 + data: {
  66 + ...values,
  67 + },
  68 + });
  69 + if (res.result === RESPONSE_CODE.SUCCESS) {
  70 + message.success('新增成功');
  71 + reloadTable();
  72 + return true;
  73 + }
  74 + // 不返回不会关闭弹框
  75 + };
  76 + const optType = {
  77 + add: {
  78 + readOnly: false,
  79 + title: '新增跟进记录',
  80 + button: (
  81 + <Button size={'middle'} type="primary">
  82 + 新增
  83 + </Button>
  84 + ),
  85 + onFinish: onfinish,
  86 + },
  87 + modify: {
  88 + readOnly: false,
  89 + title: '修改跟进记录',
  90 + button: (
  91 + <Button size={'middle'} type="primary">
  92 + 编辑
  93 + </Button>
  94 + ),
  95 + onFinish: editOnfinish,
  96 + },
  97 + detail: {
  98 + readOnly: true,
  99 + title: '查看跟进记录',
  100 + button: (
  101 + <Button size={'middle'} type="primary" color="red">
  102 + 查看
  103 + </Button>
  104 + ),
  105 + onFinish: () => {},
  106 + },
  107 + };
  108 + return (
  109 + <ModalForm
  110 + title={optType[type].title}
  111 + resize={{
  112 + onResize() {
  113 + console.log('resize!');
  114 + },
  115 + maxWidth: window.innerWidth * 0.8,
  116 + minWidth: 400,
  117 + }}
  118 + form={form}
  119 + trigger={optType[type].button}
  120 + autoFocusFirstInput
  121 + drawerProps={{
  122 + destroyOnClose: true,
  123 + }}
  124 + submitTimeout={2000}
  125 + onFinish={optType[type].onFinish}
  126 + >
  127 + <ProFormSelect
  128 + name="name"
  129 + readonly={optType[type].readOnly}
  130 + fieldProps={{
  131 + labelInValue: false,
  132 + disabled: type === 'modify',
  133 + }}
  134 + initialValue={data ? data?.clientName + '' : null}
  135 + label="客户"
  136 + width="sm"
  137 + request={async () => {
  138 + const res = await postAdminClientQueryClientPage({
  139 + data: {
  140 + groupFilter: 'all',
  141 + },
  142 + });
  143 + console.log(data, '5656data?.nameedit');
  144 + // const namesArray = res.data.data.map((item) => item.name);
  145 + // const formattedObject = res.data.data.reduce((acc, name) => {
  146 + // acc[name] = name; // 将名称作为键和值
  147 + // return acc;
  148 + // }, {});
  149 + // console.log(namesArray, '5656namesArray');
  150 + // const formattedObject = res.data.data.reduce((acc, item) => {
  151 + // acc[item.name] = item.name; // 使用 name 作为键,id 作为值
  152 + // return acc;
  153 + // }, {});
  154 + // return enumToSelect(formattedObject);
  155 + const options = res.data.data.reduce((acc, item) => {
  156 + acc.push({ label: item.name, value: item.id }); // 使用 name 作为 label,id 作为 value
  157 + return acc;
  158 + }, []);
  159 + return options;
  160 + }}
  161 + rules={[
  162 + {
  163 + required: true,
  164 + message: '请选择客户',
  165 + },
  166 + ]}
  167 + ></ProFormSelect>
  168 + <ProFormDateTimePicker
  169 + name="datetime"
  170 + label="日期"
  171 + initialValue={data ? data?.datetime + '' : null}
  172 + placeholder="请选择跟进时间"
  173 + width="sm"
  174 + rules={[
  175 + {
  176 + required: true,
  177 + message: '请选择日期',
  178 + },
  179 + ]}
  180 + />
  181 + <ProFormSelect
  182 + name="way"
  183 + width="sm"
  184 + readonly={optType[type].readOnly}
  185 + fieldProps={{
  186 + labelInValue: false,
  187 + }}
  188 + initialValue={data?.way ? data?.way + '' : null}
  189 + label="类型"
  190 + request={async () => {
  191 + const res = await postServiceConstClientWay();
  192 + return enumToSelect(res.data);
  193 + }}
  194 + rules={[
  195 + {
  196 + required: true,
  197 + message: '请选择跟进类型',
  198 + },
  199 + ]}
  200 + ></ProFormSelect>
  201 + <ProFormTextArea
  202 + name="content"
  203 + label="详情"
  204 + placeholder="请输入详情"
  205 + initialValue={data?.content}
  206 + readonly={optType[type].readOnly}
  207 + rules={[
  208 + {
  209 + required: true,
  210 + message: '请输入详情',
  211 + },
  212 + ]}
  213 + ></ProFormTextArea>
  214 + <ProFormUploadDragger
  215 + label="附件"
  216 + name="attachment"
  217 + action="upload.do"
  218 + hidden={optType[type].readOnly}
  219 + onChange={(info) => {
  220 + const uploadFile = async ({ fileList: newFileList }) => {
  221 + if (newFileList.length > 0) {
  222 + const formData = new FormData();
  223 + formData.append('file', newFileList[0].originFileObj as RcFile);
  224 + const res = await postOrderErpOrderStagesUpload({
  225 + data: formData,
  226 + headers: {
  227 + 'Content-Type':
  228 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  229 + },
  230 + });
  231 + const url = res.data;
  232 + console.log('attachments' + JSON.stringify(url));
  233 + form.setFieldValue('attachments', url);
  234 + } else {
  235 + form.setFieldValue('attachments', null);
  236 + }
  237 + };
  238 + uploadFile(info);
  239 + }}
  240 + max={1}
  241 + />
  242 + <a hidden={!optType[type].readOnly} href={data?.attachments} download>
  243 + 下载附件
  244 + </a>
  245 + <ProFormText
  246 + initialValue={data?.attachments}
  247 + name="attachments"
  248 + hidden
  249 + ></ProFormText>
  250 + <ProFormText initialValue={data?.id} name="id" hidden></ProFormText>
  251 + </ModalForm>
  252 + );
  253 +};
... ...
src/pages/Client/Client/Components/ClientModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postAdminClientAddOrModifyClientComunicationInfo,
  4 + postAdminClientQueryClientPage,
  5 + postOrderErpOrderStagesUpload,
  6 + postServiceConstClientWay,
  7 +} from '@/services';
  8 +import { enumToSelect } from '@/utils';
  9 +import {
  10 + ModalForm,
  11 + ProFormDateTimePicker,
  12 + ProFormSelect,
  13 + ProFormText,
  14 + ProFormTextArea,
  15 + ProFormUploadDragger,
  16 +} from '@ant-design/pro-components';
  17 +import { Button, Form, message } from 'antd';
  18 +import { RcFile } from 'antd/es/upload';
  19 +export default ({ data, type, reloadTable }) => {
  20 + const [form] = Form.useForm();
  21 + const onfinish = async (values) => {
  22 + console.log(data, '5656datatest');
  23 + console.log(values, '5656...values');
  24 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  25 + data: {
  26 + ...values,
  27 + id: '',
  28 + clientId: data.id,
  29 + },
  30 + });
  31 + if (res.result === RESPONSE_CODE.SUCCESS) {
  32 + message.success('新增成功');
  33 + reloadTable();
  34 + return true;
  35 + }
  36 + // 不返回不会关闭弹框
  37 + };
  38 + const optType = {
  39 + add: {
  40 + readOnly: false,
  41 + title: '新增跟进记录',
  42 + button: (
  43 + <Button size={'small'} type="link">
  44 + 新增跟进
  45 + </Button>
  46 + ),
  47 + onFinish: onfinish,
  48 + },
  49 + add2: {
  50 + readOnly: false,
  51 + title: '新增跟进记录',
  52 + button: (
  53 + <Button size={'middle'} type="primary">
  54 + 新增跟进
  55 + </Button>
  56 + ),
  57 + onFinish: onfinish,
  58 + },
  59 + modify: {
  60 + readOnly: false,
  61 + title: '修改跟进记录',
  62 + button: (
  63 + <Button size={'small'} type="link">
  64 + 编辑
  65 + </Button>
  66 + ),
  67 + onFinish: onfinish,
  68 + },
  69 + detail: {
  70 + readOnly: true,
  71 + title: '查看跟进记录',
  72 + button: (
  73 + <Button size={'small'} type="link">
  74 + 查看
  75 + </Button>
  76 + ),
  77 + onFinish: () => {},
  78 + },
  79 + };
  80 + return (
  81 + <ModalForm
  82 + title={optType[type].title}
  83 + resize={{
  84 + onResize() {
  85 + console.log('resize!');
  86 + },
  87 + maxWidth: window.innerWidth * 0.8,
  88 + minWidth: 400,
  89 + }}
  90 + form={form}
  91 + trigger={optType[type].button}
  92 + autoFocusFirstInput
  93 + drawerProps={{
  94 + destroyOnClose: true,
  95 + }}
  96 + submitTimeout={2000}
  97 + onFinish={optType[type].onFinish}
  98 + >
  99 + <ProFormSelect
  100 + name="sendStoreCode"
  101 + readonly={optType[type].readOnly}
  102 + fieldProps={{
  103 + labelInValue: false,
  104 + }}
  105 + initialValue={data ? data?.name + '' : null}
  106 + label="客户"
  107 + width="sm"
  108 + request={async () => {
  109 + const res = await postAdminClientQueryClientPage({
  110 + data: {
  111 + groupFilter: 'all',
  112 + },
  113 + });
  114 + console.log(data?.datetime, '5656data?.datetime');
  115 + const namesArray = res.data.data.map((item) => item.name);
  116 + return enumToSelect(namesArray);
  117 + }}
  118 + rules={[
  119 + {
  120 + required: true,
  121 + message: '请选择客户',
  122 + },
  123 + ]}
  124 + disabled
  125 + ></ProFormSelect>
  126 + <ProFormDateTimePicker
  127 + name="datetime"
  128 + label="日期"
  129 + initialValue={data.datetime ? data?.datetime + '' : null}
  130 + placeholder="请选择跟进时间"
  131 + width="sm"
  132 + rules={[
  133 + {
  134 + required: true,
  135 + message: '请选择日期',
  136 + },
  137 + ]}
  138 + />
  139 + <ProFormSelect
  140 + name="way"
  141 + width="sm"
  142 + readonly={optType[type].readOnly}
  143 + fieldProps={{
  144 + labelInValue: false,
  145 + }}
  146 + initialValue={data?.way ? data?.way + '' : null}
  147 + label="类型"
  148 + request={async () => {
  149 + const res = await postServiceConstClientWay();
  150 + return enumToSelect(res.data);
  151 + }}
  152 + rules={[
  153 + {
  154 + required: true,
  155 + message: '请选择跟进类型',
  156 + },
  157 + ]}
  158 + ></ProFormSelect>
  159 + <ProFormTextArea
  160 + name="content"
  161 + label="详情"
  162 + placeholder="请输入详情"
  163 + initialValue={data?.content}
  164 + readonly={optType[type].readOnly}
  165 + rules={[
  166 + {
  167 + required: true,
  168 + message: '请输入详情',
  169 + },
  170 + ]}
  171 + ></ProFormTextArea>
  172 + <ProFormUploadDragger
  173 + label="附件"
  174 + name="attachment"
  175 + action="upload.do"
  176 + hidden={optType[type].readOnly}
  177 + onChange={(info) => {
  178 + const uploadFile = async ({ fileList: newFileList }) => {
  179 + if (newFileList.length > 0) {
  180 + const formData = new FormData();
  181 + formData.append('file', newFileList[0].originFileObj as RcFile);
  182 + const res = await postOrderErpOrderStagesUpload({
  183 + data: formData,
  184 + headers: {
  185 + 'Content-Type':
  186 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  187 + },
  188 + });
  189 + const url = res.data;
  190 + console.log('attachments' + JSON.stringify(url));
  191 + form.setFieldValue('attachments', url);
  192 + } else {
  193 + form.setFieldValue('attachments', null);
  194 + }
  195 + };
  196 + uploadFile(info);
  197 + }}
  198 + max={1}
  199 + />
  200 + <a hidden={!optType[type].readOnly} href={data?.attachments} download>
  201 + 下载附件
  202 + </a>
  203 + <ProFormText
  204 + initialValue={data?.attachments}
  205 + name="attachments"
  206 + hidden
  207 + ></ProFormText>
  208 + <ProFormText initialValue={data?.id} name="id" hidden></ProFormText>
  209 + </ModalForm>
  210 + );
  211 +};
... ...
src/pages/Client/Client/Components/CommunicationHistoryModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postAdminClientAddOrModifyClientComunicationInfo,
  4 + postAdminClientQueryClientComunicationInfo,
  5 + postAdminClientRemoveClientComunicationInfo,
  6 + postServiceConstClientWay,
  7 +} from '@/services';
  8 +import { enumToSelect } from '@/utils';
  9 +import {
  10 + ActionType,
  11 + EditableProTable,
  12 + ModalForm,
  13 + ProFormInstance,
  14 +} from '@ant-design/pro-components';
  15 +import { Descriptions, Popconfirm, message } from 'antd';
  16 +import { useEffect, useRef, useState } from 'react';
  17 +import ClientModal from './ClientModal';
  18 +import InformationHistoryModal from './InformationHistoryModal';
  19 +export default ({ record }) => {
  20 + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  21 + const [dataSource, setDataSource] = useState();
  22 + const ref = useRef<ProFormInstance>();
  23 + const actionRef = useRef<ActionType>();
  24 + const [refreshKey, setRefreshKey] = useState(0); // 用于强制刷新的键
  25 +
  26 + const reloadInformationHistoryModal = () => {
  27 + actionRef.current.reload(); // 重新加载数据
  28 + console.log('5656flush');
  29 +
  30 + // 更新 refreshKey,强制刷新 CommunicationHistoryModal
  31 + setRefreshKey((prevKey) => prevKey + 1);
  32 + };
  33 + const columns = [
  34 + {
  35 + title: '跟进时间',
  36 + dataIndex: 'datetime',
  37 + width: 50,
  38 + valueType: 'dateTime',
  39 + rules: [{ required: true, message: '请选择时间' }],
  40 + },
  41 + {
  42 + title: '跟进人',
  43 + width: 50,
  44 + rules: [{ required: true, message: '请输入跟进人' }],
  45 + dataIndex: 'updateByName',
  46 + },
  47 + {
  48 + title: '跟进方式',
  49 + width: 50,
  50 + dataIndex: 'way',
  51 + rules: [{ required: true, message: '请选择方式' }],
  52 + render: (text, record) => record.wayText, // 显示 wayText
  53 + request: async () => {
  54 + const res = await postServiceConstClientWay();
  55 + return enumToSelect(res.data);
  56 + },
  57 + },
  58 + {
  59 + title: '内容',
  60 + width: 100,
  61 + valueType: 'textarea',
  62 + rules: [{ required: true, message: '请输入内容' }],
  63 + dataIndex: 'content',
  64 + },
  65 + {
  66 + title: '操作',
  67 + valueType: 'option',
  68 + width: 50,
  69 + render: (text, record, _, action) => [
  70 + // <a
  71 + // key="editable"
  72 + // onClick={() => {
  73 + // action?.startEditable?.(record.tid);
  74 + // }}
  75 + // >
  76 + // 编辑
  77 + // </a>,
  78 + <InformationHistoryModal
  79 + // key={'communicationHistory'}
  80 + key={`communicationHistory-${refreshKey}`} // 使用 refreshKey 来强制更新组件
  81 + data={record}
  82 + // reloadTable={() => {
  83 + // actionRef.current.reload();
  84 + // console.log('5656flush');
  85 + // }}
  86 + reloadTable={reloadInformationHistoryModal}
  87 + />,
  88 + <Popconfirm
  89 + key={'delete'}
  90 + title="删除记录"
  91 + description="确认删除记录?"
  92 + onConfirm={async () => {
  93 + setDataSource(dataSource.filter((item) => item.tid !== record.tid));
  94 + const res = await postAdminClientRemoveClientComunicationInfo({
  95 + query: {
  96 + id: record.id,
  97 + },
  98 + });
  99 + if (res.result === RESPONSE_CODE.SUCCESS) {
  100 + message.success(res.message);
  101 + action?.reload();
  102 + } else {
  103 + message.error('删除失败');
  104 + }
  105 + }}
  106 + okText="是"
  107 + cancelText="否"
  108 + >
  109 + <a type={'danger'}>删除</a>
  110 + </Popconfirm>,
  111 + ],
  112 + },
  113 + ];
  114 + const [name, setName] = useState(''); // 客户名称
  115 + const [contacts, setContacts] = useState(''); // 联系人
  116 + const [sourceText, setSourceText] = useState(''); // 来源文本
  117 + const [phoneNumber, setPhoneNumber] = useState(''); // 联系电话
  118 + const [hasSchemeText, setHasSchemeText] = useState(''); // 报方案状态文本
  119 + const [quoteDatetime, setQuoteDatetime] = useState(null); // 报价时间
  120 + const [referrers, setReferrers] = useState(''); // 推荐人
  121 + const [requirementsText, setRequirementsText] = useState(''); // 需求文本
  122 + const [tradeStatusText, setTradeStatusText] = useState(''); // 跟进状态文本
  123 + const [levelText, setLevelText] = useState(''); // 客户等级文本
  124 + const [createTime, setCreateTime] = useState(null); // 最新沟通时间
  125 + const [address, setAddress] = useState(''); // 客户地址
  126 + const [notes, setNotes] = useState(''); // 备注信息
  127 + const [createByName, setCreateByName] = useState(''); // 创建人
  128 + const [latestObject, setLatestObject] = useState(); // 最新跟进时间
  129 + const [recordSave, setRecordSave] = useState(); //新增跟进
  130 + useEffect(() => {
  131 + const request = async () => {
  132 + const resShow = await postAdminClientQueryClientComunicationInfo({
  133 + data: {
  134 + clientId: record.id,
  135 + },
  136 + });
  137 + if (resShow?.data?.data !== null) {
  138 + const data = resShow?.data?.data;
  139 + // const latest = data.reduce((latest: any, current: any) => {
  140 + // return new Date(current.updateTime) > new Date(latest.updateTime) ? current : latest;
  141 + // });
  142 + // const data = [];
  143 + const latestObject2 =
  144 + data?.length > 0
  145 + ? data.reduce((latest, current) =>
  146 + new Date(current.datetime) > new Date(latest.datetime)
  147 + ? current
  148 + : latest,
  149 + )
  150 + : null; // 或返回其他默认值
  151 + setLatestObject(latestObject2?.datetime);
  152 + }
  153 + setRecordSave(record);
  154 + setName(record.name);
  155 + setContacts(record.contacts);
  156 + setSourceText(record.sourceText);
  157 + setPhoneNumber(record.phoneNumber);
  158 + setHasSchemeText(record.hasSchemeText);
  159 + setQuoteDatetime(record.quoteDatetime);
  160 + setReferrers(record.referrers);
  161 + setRequirementsText(record.requirementsText);
  162 + setTradeStatusText(record.tradeStatusText);
  163 + setLevelText(record.levelText);
  164 + setCreateTime(record.createTime);
  165 + setAddress(record.address);
  166 + setNotes(record.notes);
  167 + setCreateByName(record.createByName);
  168 + };
  169 + request();
  170 + }, []);
  171 + const items = [
  172 + {
  173 + key: '1',
  174 + label: '客户名称',
  175 + children: name, // 客户名称
  176 + },
  177 + {
  178 + key: '2',
  179 + label: '联系人',
  180 + children: contacts, // 联系人
  181 + },
  182 + {
  183 + key: '3',
  184 + label: '来源',
  185 + children: sourceText, // 来源文本
  186 + },
  187 + {
  188 + key: '4',
  189 + label: '联系电话',
  190 + children: phoneNumber, // 联系电话
  191 + },
  192 + {
  193 + key: '5',
  194 + label: '是否已报方案',
  195 + children: hasSchemeText, // 报方案状态文本
  196 + },
  197 + {
  198 + key: '6',
  199 + label: '报价时间',
  200 + children: quoteDatetime, // 报价时间
  201 + },
  202 + {
  203 + key: '7',
  204 + label: '推荐人',
  205 + children: referrers, // 推荐人
  206 + },
  207 + {
  208 + key: '8',
  209 + label: '需求',
  210 + children: requirementsText, // 需求文本
  211 + },
  212 + {
  213 + key: '9',
  214 + label: '跟进状态',
  215 + children: tradeStatusText, // 跟进状态文本
  216 + },
  217 + {
  218 + key: '10',
  219 + label: '客户等级',
  220 + children: levelText, // 客户等级文本
  221 + },
  222 + {
  223 + key: '11',
  224 + label: '创建时间',
  225 + children: createTime, // 最新沟通时间
  226 + },
  227 + {
  228 + key: '12',
  229 + label: '客户地址',
  230 + children: address, // 客户地址
  231 + },
  232 + {
  233 + key: '13',
  234 + label: '备注',
  235 + children: notes, // 备注信息
  236 + },
  237 + {
  238 + key: '14',
  239 + label: '创建人',
  240 + children: createByName, // 创建人
  241 + },
  242 + {
  243 + key: '15',
  244 + label: '最新跟进时间',
  245 + children: latestObject, // 最新跟进时间
  246 + },
  247 + ];
  248 + return (
  249 + <ModalForm
  250 + title="客户详情"
  251 + trigger={<a type="primary">查看</a>}
  252 + modalProps={{
  253 + destroyOnClose: true,
  254 + }}
  255 + onFinish={async () => {
  256 + return true;
  257 + }}
  258 + >
  259 + <Descriptions items={items} column={2} />
  260 + <ClientModal
  261 + key={'add'}
  262 + data={recordSave}
  263 + reloadTable={() => {
  264 + actionRef.current?.reload();
  265 + }}
  266 + type={'add2'}
  267 + />
  268 + ,
  269 + <EditableProTable
  270 + rowKey="tid"
  271 + formRef={ref}
  272 + actionRef={actionRef}
  273 + recordCreatorProps={false}
  274 + // recordCreatorProps={{
  275 + // record: () => ({ tid: (Math.random() * 1000000).toFixed(0) }),
  276 + // }}
  277 + loading={false}
  278 + columns={columns}
  279 + request={async () => {
  280 + const res = await postAdminClientQueryClientComunicationInfo({
  281 + data: {
  282 + clientId: record.id,
  283 + },
  284 + });
  285 + if (res.result === RESPONSE_CODE.SUCCESS) {
  286 + console.log(JSON.stringify(res.data));
  287 + return {
  288 + ...res.data,
  289 + data: res.data.data.map((item) => {
  290 + return {
  291 + ...item,
  292 + tid: (Math.random() * 1000000).toFixed(0),
  293 + };
  294 + }),
  295 + };
  296 + } else {
  297 + message.error('获取失败');
  298 + }
  299 + }}
  300 + value={dataSource}
  301 + onChange={setDataSource}
  302 + editable={{
  303 + type: 'multiple',
  304 + editableKeys,
  305 + onSave: async (rowKey, data, row) => {
  306 + console.log(rowKey, data, row);
  307 + if (data?.way === '拜访') {
  308 + data.way = 'VISIT';
  309 + } else if (data?.way === '电话') {
  310 + data.way = 'PHONE';
  311 + } else if (data?.way === '微信') {
  312 + data.way = 'WECHAT';
  313 + } else if (data?.way === '邮件') {
  314 + data.way = 'EMAIL';
  315 + } else if (data?.way === '其他') {
  316 + data.way = 'OTHER';
  317 + }
  318 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  319 + data: {
  320 + ...data,
  321 + clientId: record.id,
  322 + },
  323 + });
  324 + if (res.result === RESPONSE_CODE.SUCCESS) {
  325 + message.success(res.message);
  326 + } else {
  327 + message.error('修改失败');
  328 + }
  329 + actionRef.current?.reload();
  330 + },
  331 + onChange: setEditableRowKeys,
  332 + }}
  333 + />
  334 + {/* <Descriptions title="User Info" items={items} column={2} /> */}
  335 + {/*<ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
  336 + <ProFormField
  337 + ignoreFormItem
  338 + fieldProps={{
  339 + style: {
  340 + width: '100%',
  341 + },
  342 + }}
  343 + mode="read"
  344 + valueType="jsonCode"
  345 + text={JSON.stringify(dataSource)}
  346 + />
  347 + </ProCard>*/}
  348 + </ModalForm>
  349 + );
  350 +};
... ...
src/pages/Client/Client/Components/InformationHistoryModal.tsx 0 → 100644
  1 +// import ClientModal from '@/pages/Client/FollowRecord/Components/ClientModal';
  2 +import ClientInformationModal from '@/pages/Client/Client/Components/ClientInformationModal';
  3 +
  4 +import {
  5 + postAdminClientQueryClientComunicationInfo,
  6 + postAdminClientRemoveClientComunicationInfo,
  7 +} from '@/services/request';
  8 +import { ModalForm } from '@ant-design/pro-components';
  9 +import { Button, Descriptions, Space } from 'antd';
  10 +import { useEffect, useRef, useState } from 'react';
  11 +
  12 +export default ({ data, reloadTable }) => {
  13 + console.log(data, '5656datafirstshowclient');
  14 +
  15 + // const [isModalVisible, setIsModalVisible] = useState(false); // 控制 ClientModal 的显示
  16 + const actionRef = useRef(); // 引用 actionRef,方便调用 reload 方法
  17 +
  18 + const [datetime, setDatetime] = useState(); // 跟进日期
  19 + const [createByName, setCreateByName] = useState(''); // 跟进人员
  20 + const [clientName, setClientName] = useState(''); // 客户名称
  21 + // const [clientAddress, setClientAddress] = useState(''); // 客户地址
  22 + const [way, setWay] = useState(); // 类型
  23 + // const [clientNameLike, setClientNameLike] = useState(''); // 客户名称模糊查询
  24 + // const [clientAddressLike, setClientAddressLike] = useState(''); // 客户地址模糊查询
  25 + // const [tradeStatus, setTradeStatus] = useState(''); // 客户状态
  26 + // const [tradeStatusLike, setTradeStatusLike] = useState(''); // 客户状态模糊查询
  27 + const [content, setContent] = useState(''); // 跟进详情
  28 + const [createTime, setCreateTime] = useState(null); // 创建时间
  29 + const [attachments, setAttachments] = useState(); //附件
  30 + const [attachmentsName, setAttachmentsName] = useState(''); // 附件名称
  31 +
  32 + useEffect(() => {
  33 + const request = async () => {
  34 + console.log(data, '5656datasearch');
  35 + const res = await postAdminClientQueryClientComunicationInfo({
  36 + data: {
  37 + id: data.id,
  38 + },
  39 + });
  40 + console.log(res, '5656res');
  41 + const dataSearch = res.data.data[0];
  42 + if (dataSearch) {
  43 + if (dataSearch.attachments) {
  44 + const url = dataSearch.attachments;
  45 + const match = url.match(/aliyuncs\.com\/(.*?)\?/);
  46 + let decodedStr = '';
  47 +
  48 + if (match) {
  49 + // 获取匹配的字符串并进行解码
  50 + const encodedStr = match[1];
  51 + decodedStr = decodeURIComponent(encodedStr);
  52 + setAttachmentsName(decodedStr); // 设置跟进日期
  53 + }
  54 + }
  55 + setDatetime(dataSearch.datetime); // 设置跟进日期
  56 + // setDateRange(data.dateRange || []); // 设置跟进时间范围
  57 + setCreateByName(dataSearch.createByName); // 设置跟进人员
  58 + setClientName(dataSearch.clientName); // 设置客户名称
  59 + // setClientAddress(data.clientAddress || ''); // 设置客户地址
  60 + // setClientNameLike(data.clientNameLike || ''); // 设置客户名称模糊查询
  61 + // setClientAddressLike(data.clientAddressLike || ''); // 设置客户地址模糊查询
  62 + // setTradeStatus(data.tradeStatus || ''); // 设置客户状态
  63 + // setTradeStatusLike(data.tradeStatusLike || ''); // 设置客户状态模糊查询
  64 + setContent(dataSearch.content); // 设置跟进详情
  65 + setCreateTime(dataSearch.createTime); // 设置创建时间
  66 + setWay(dataSearch.wayText);
  67 + setAttachments(dataSearch.attachments);
  68 + }
  69 + console.log(attachments, '5656attachments');
  70 + };
  71 + request();
  72 + }, []);
  73 + const items = [
  74 + {
  75 + key: '1',
  76 + label: '跟进日期',
  77 + children: datetime, // 跟进日期
  78 + },
  79 + {
  80 + key: '2',
  81 + label: '跟进人员',
  82 + children: createByName, // 跟进人员
  83 + },
  84 + {
  85 + key: '3',
  86 + label: '客户名称',
  87 + children: clientName, // 客户名称
  88 + },
  89 + {
  90 + key: '4',
  91 + label: '跟进详情',
  92 + children: content, // 跟进详情
  93 + },
  94 + {
  95 + key: '5',
  96 + label: '创建时间',
  97 + children: createTime, // 创建时间
  98 + },
  99 + {
  100 + key: '6',
  101 + label: '跟进类型',
  102 + children: way, // 跟进类型
  103 + },
  104 + ];
  105 + const handleDelete = async () => {
  106 + console.log(JSON.stringify(data), '5656record');
  107 + // 调用删除接口
  108 + const success = await postAdminClientRemoveClientComunicationInfo({
  109 + query: {
  110 + id: data.id,
  111 + },
  112 + });
  113 + // setIsModalVisible(false);
  114 + if (success) {
  115 + actionRef?.current?.reload(); // 重新加载表格数据
  116 + }
  117 + };
  118 + return (
  119 + <Space>
  120 + <ModalForm
  121 + title="跟进记录"
  122 + trigger={<Button type="link">查看</Button>}
  123 + submitter={{
  124 + resetButtonProps: {
  125 + style: {
  126 + display: 'none',
  127 + },
  128 + },
  129 + submitButtonProps: {
  130 + style: {
  131 + display: 'none',
  132 + },
  133 + },
  134 + render: (props, defaultDoms) => {
  135 + return [
  136 + ...defaultDoms,
  137 + <>
  138 + <ClientInformationModal
  139 + key={'modify'}
  140 + data={data} // 将表单数据传递给 ClientModal
  141 + reloadTable={() => {
  142 + actionRef?.current?.reload(); // 重新加载表格数据
  143 + props.submit();
  144 + reloadTable();
  145 + console.log('5656close');
  146 + }}
  147 + type={'modify'}
  148 + onFinish={() => {
  149 + // setIsModalVisible(false);
  150 + }} // 关闭 Modal
  151 + style={{ marginRight: '10px' }}
  152 + />
  153 + <Button
  154 + key={'delete'}
  155 + onClick={() => {
  156 + handleDelete();
  157 + props.submit();
  158 + reloadTable();
  159 + }}
  160 + type="primary"
  161 + size="middle"
  162 + danger // 使用 danger 属性来将按钮颜色设置为红色
  163 + style={{ marginLeft: '10px' }}
  164 + onFinish={() => {
  165 + actionRef.current.reload();
  166 + }}
  167 + >
  168 + 删除
  169 + </Button>
  170 + </>,
  171 + ];
  172 + },
  173 + }}
  174 + onFinish={async () => {
  175 + // 提交成功后,显示 ClientDrawer
  176 + // setIsModalVisible(true);
  177 + return true;
  178 + }}
  179 + >
  180 + <Descriptions items={items} column={1} />
  181 + {attachmentsName && (
  182 + <a href={attachments} download>
  183 + 附件:{attachmentsName}
  184 + </a>
  185 + )}
  186 + </ModalForm>
  187 + </Space>
  188 + );
  189 +};
... ...
src/pages/Client/index.tsx renamed to src/pages/Client/Client/index.tsx
1   -import ClientDrawer from '@/pages/Client/Components/ClientDrawer';
2   -import ClientImportModal from '@/pages/Client/Components/ClientImportModal';
3   -import ClientStatistic from '@/pages/Client/Components/ClientStatistic';
4   -import CommunicationHistoryModal from '@/pages/Client/Components/CommunicationHistoryModal';
  1 +import ButtonConfirm from '@/components/ButtomConfirm';
  2 +import ClientDrawer from '@/pages/Client/Client/Components/ClientDrawer';
  3 +import ClientImportModal from '@/pages/Client/Client/Components/ClientImportModal';
  4 +import ClientModal from '@/pages/Client/Client/Components/ClientModal';
  5 +import CommunicationHistoryModal from '@/pages/Client/Client/Components/CommunicationHistoryModal';
5 6 import {
  7 + postAdminClientDeleteAdminClient,
  8 + postAdminClientGetStatisticalData,
6 9 postAdminClientQueryClientPage,
7   - postServiceConstClientGroupFilters,
8 10 postServiceConstClientLevels,
  11 + postServiceConstClientRequirements,
  12 + postServiceConstClientSource,
9 13 postServiceConstTradeStatus,
10 14 } from '@/services';
11 15 import { orderExport } from '@/services/order';
12 16 import { enumToSelect } from '@/utils';
13 17 import type { ActionType } from '@ant-design/pro-components';
14 18 import { ProTable } from '@ant-design/pro-components';
15   -import { Button, Radio, Space, message } from 'antd';
  19 +import { Badge, Button, Radio, Space, message } from 'antd';
16 20 import { useEffect, useRef, useState } from 'react';
17 21  
18 22 const columns = [
... ... @@ -25,23 +29,30 @@ const columns = [
25 29 {
26 30 title: '客户名称',
27 31 dataIndex: 'name',
28   - width: 100,
  32 + width: 150,
29 33 ellipsis: true,
30 34 hideInSearch: true,
31 35 },
  36 + // {
  37 + // title: '单位名称',
  38 + // width: 150,
  39 + // ellipsis: true,
  40 + // dataIndex: 'companyName',
  41 + // hideInSearch: true,
  42 + // },
32 43 {
33   - title: '单位名称',
34   - width: 150,
  44 + title: '客户地址',
  45 + width: 250,
35 46 ellipsis: true,
36   - dataIndex: 'companyName',
37   - hideInSearch: true,
  47 + dataIndex: 'address',
  48 + hideInSearch: false,
38 49 },
39 50 {
40   - title: '单位地址',
41   - width: 250,
  51 + title: '联系人',
  52 + width: 150,
42 53 ellipsis: true,
43   - dataIndex: 'companyAddressText',
44   - hideInSearch: true,
  54 + dataIndex: 'contacts',
  55 + hideInSearch: false,
45 56 },
46 57 {
47 58 title: '联系电话',
... ... @@ -54,10 +65,20 @@ const columns = [
54 65 title: '客户来源',
55 66 width: 150,
56 67 ellipsis: true,
57   - dataIndex: 'source',
  68 + dataIndex: 'sourceText',
58 69 hideInSearch: true,
59 70 },
60 71 {
  72 + title: '客户来源',
  73 + valueType: 'select',
  74 + hideInTable: true,
  75 + dataIndex: 'source',
  76 + request: async () => {
  77 + const res = await postServiceConstClientSource();
  78 + return enumToSelect(res.data);
  79 + },
  80 + },
  81 + {
61 82 title: '推荐人',
62 83 dataIndex: 'referrers',
63 84 width: 150,
... ... @@ -66,12 +87,28 @@ const columns = [
66 87 },
67 88 {
68 89 title: '客户需求',
69   - dataIndex: 'requirements',
70   - width: 150,
  90 + width: 240,
71 91 ellipsis: true,
  92 + dataIndex: 'requirementsText',
72 93 hideInSearch: true,
73 94 },
74 95 {
  96 + title: '客户需求',
  97 + dataIndex: 'requirements',
  98 + valueType: 'select',
  99 + hideInTable: true,
  100 + request: async () => {
  101 + const res = await postServiceConstClientRequirements();
  102 + // function enumToSelect(data: any) {
  103 + // const keys = Object.keys(data);
  104 + // return keys.map((value) => {
  105 + // return { label: data[value], value: value };
  106 + // });
  107 + // }
  108 + return enumToSelect(res.data);
  109 + },
  110 + },
  111 + {
75 112 title: '是否已报方案',
76 113 width: 150,
77 114 ellipsis: true,
... ... @@ -84,7 +121,7 @@ const columns = [
84 121 width: 150,
85 122 ellipsis: true,
86 123 dataIndex: 'quoteDatetime',
87   - valueType: 'dateTime',
  124 + valueType: 'date',
88 125 hideInSearch: true,
89 126 },
90 127 {
... ... @@ -111,26 +148,35 @@ const columns = [
111 148 hideInSearch: true,
112 149 },
113 150 {
114   - title: '最新进时间',
  151 + title: '最新进时间',
115 152 key: 'since',
116 153 width: 150,
117 154 ellipsis: true,
118   - dataIndex: 'latestCommunicationTime',
  155 + dataIndex: 'updateTime',
119 156 valueType: 'dateTime',
120 157 hideInSearch: true,
121 158 },
  159 + // {
  160 + // title: '最新跟进时间',
  161 + // key: 'since',
  162 + // width: 150,
  163 + // ellipsis: true,
  164 + // dataIndex: 'latestCommunicationTime',
  165 + // valueType: 'dateTime',
  166 + // hideInSearch: true,
  167 + // },
122 168 {
123 169 title: '客户名称',
124 170 dataIndex: 'nameLike',
125 171 valueType: 'Text',
126 172 hideInTable: true,
127 173 },
128   - {
129   - title: '单位名称',
130   - dataIndex: 'companyNameLike',
131   - valueType: 'Text',
132   - hideInTable: true,
133   - },
  174 + // {
  175 + // title: '单位名称',
  176 + // dataIndex: 'companyNameLike',
  177 + // valueType: 'Text',
  178 + // hideInTable: true,
  179 + // },
134 180 {
135 181 title: '联系电话',
136 182 dataIndex: 'phoneNumberLike',
... ... @@ -141,6 +187,7 @@ const columns = [
141 187 title: '是否已报方案',
142 188 dataIndex: 'hasScheme',
143 189 valueType: 'select',
  190 + width: 1550,
144 191 valueEnum: {
145 192 true: {
146 193 text: '是',
... ... @@ -160,7 +207,14 @@ const columns = [
160 207 hideInTable: true,
161 208 request: async () => {
162 209 const res = await postServiceConstClientLevels();
163   - return enumToSelect(res.data);
  210 + // 明确指定所需的顺序(后端返回顺序正确,直接修改enumToSelect没作用)
  211 + function enumToSelectLevel(data: any) {
  212 + const order = ['PRIMARY_CLIENT', 'SECONDARY_CLIENT', 'TERTIARY_CLIENT'];
  213 + return order.map((key) => {
  214 + return { label: data[key], value: key };
  215 + });
  216 + }
  217 + return enumToSelectLevel(res.data);
164 218 },
165 219 },
166 220 {
... ... @@ -192,13 +246,25 @@ const columns = [
192 246 title: '操作',
193 247 valueType: 'option',
194 248 key: 'option',
195   - width: 150,
  249 + width: 200,
196 250 render: (text, record, index, action) => {
197   - console.log(JSON.stringify(record));
  251 + const handleDelete = async () => {
  252 + console.log(JSON.stringify(record), '5656record1');
  253 + // 调用删除接口
  254 + const success = await postAdminClientDeleteAdminClient({
  255 + query: {
  256 + id: record.id,
  257 + },
  258 + });
  259 + if (success) {
  260 + action.reload(); // 刷新表格
  261 + }
  262 + };
  263 + console.log(JSON.stringify(record), '5656record2');
198 264 return [
199 265 <CommunicationHistoryModal
200 266 key={'communicationHistory'}
201   - clientId={record.id}
  267 + record={record}
202 268 />,
203 269 <ClientDrawer
204 270 key={'detail'}
... ... @@ -208,6 +274,14 @@ const columns = [
208 274 action.reload();
209 275 }}
210 276 ></ClientDrawer>,
  277 + <ClientModal
  278 + key={'add'}
  279 + data={record}
  280 + reloadTable={() => {
  281 + action?.reload();
  282 + }}
  283 + type={'add'}
  284 + />,
211 285 <ClientDrawer
212 286 key={'edit'}
213 287 record={record}
... ... @@ -216,6 +290,18 @@ const columns = [
216 290 action.reload();
217 291 }}
218 292 ></ClientDrawer>,
  293 + // <a key={'delete'} onClick={handleDelete}>
  294 + // 删除
  295 + // </a>,
  296 + <ButtonConfirm
  297 + key="delete"
  298 + className="p-0"
  299 + title={'删除该客户,客户下的跟进记录会一并删除'}
  300 + text="删除"
  301 + onConfirm={async () => {
  302 + handleDelete();
  303 + }}
  304 + />,
219 305 ];
220 306 },
221 307 },
... ... @@ -224,23 +310,74 @@ const columns = [
224 310 export default () => {
225 311 const [messageApi, contextHolder] = message.useMessage();
226 312 const [groupFilter, setGroupFilter] = useState('All');
227   - const [groupFilterOptions, setGroupFilterDataOptions] = useState([]);
  313 + // const [groupFilterOptions, setGroupFilterDataOptions] = useState([]);
228 314 const actionRef = useRef<ActionType>();
  315 + //获得预警/全部数量
  316 + const [clientStatistic, setClientStatistic] = useState([]);
  317 + // const [allClientStatistic, setAllClientStatistic] = useState([]);
  318 + const [warningClientStatistic, setWarningClientStatistic] = useState([]);
  319 + // const reloadTable = () => {
  320 + // actionRef.current?.reload();
  321 + // };
229 322 useEffect(() => {
230   - const pullGroupFilterDataOptions = async () => {
231   - const res = await postServiceConstClientGroupFilters();
232   - console.log('setGroupFilterDataOptions' + JSON.stringify(res.data));
233   - setGroupFilterDataOptions(enumToSelect(res.data));
  323 + const pullStatistic = async () => {
  324 + let statisticalData = await postAdminClientGetStatisticalData();
  325 + console.log('stati' + JSON.stringify(statisticalData.data));
  326 + setClientStatistic(statisticalData.data);
  327 + setWarningClientStatistic(statisticalData.data[1].value);
  328 + // setAllClientStatistic(statisticalData.data[0].value);
  329 + setTimeout(() => {
  330 + console.log(clientStatistic, '5656groupFilterOptions1');
  331 + // groupFilterOptions[0].label = groupFilterOptions[0].label + '(' + clientStatistic + ')';
  332 + }, 100);
  333 + actionRef.current?.reload(); // 可能需要在这里刷新
234 334 };
235   - pullGroupFilterDataOptions();
  335 + pullStatistic();
236 336 }, []);
  337 + const groupFilterOptions = [
  338 + {
  339 + value: 'All',
  340 + label: <span>全部</span>,
  341 + },
  342 + {
  343 + value: 'WARNING_CLIENT',
  344 + label: (
  345 + <span>
  346 + 预警客户
  347 + <Badge count={warningClientStatistic} style={{ marginLeft: 8 }} />
  348 + </span>
  349 + ),
  350 + },
  351 + ];
  352 + // useEffect(() => {
  353 + // const pullGroupFilterDataOptions = async () => {
  354 + // const res = await postServiceConstClientGroupFilters();
  355 + // // console.log('setGroupFilterDataOptions' + JSON.stringify(res.data));
  356 + // const select = enumToSelect(res.data);
  357 + // console.log(select, '5656selet');
  358 + // setGroupFilterDataOptions(select);
  359 + // };
  360 + // pullGroupFilterDataOptions();
  361 + // }, []);
237 362 useEffect(() => {
  363 + // console.log(groupFilterOptions, '5656groupFilterOptions2');
  364 + console.log(clientStatistic, '5656clientStatistic');
  365 + console.log(warningClientStatistic, '5656warningClientStatistic');
238 366 actionRef.current?.reload();
239 367 }, [groupFilter]);
240 368 return (
241 369 <>
242 370 <Space direction="vertical" size="middle" style={{ display: 'flex' }}>
243   - <ClientStatistic></ClientStatistic>
  371 + <div key={'groupFilter'}>
  372 + <Radio.Group
  373 + options={groupFilterOptions}
  374 + onChange={(e) => {
  375 + setGroupFilter(e.target.value);
  376 + }}
  377 + value={groupFilter}
  378 + optionType="button"
  379 + />
  380 + </div>
244 381 <ProTable
245 382 columns={columns}
246 383 actionRef={actionRef}
... ... @@ -256,6 +393,7 @@ export default () =&gt; {
256 393 return data;
257 394 }}
258 395 search={{
  396 + labelWidth: 'auto',
259 397 optionRender: (searchConfig, formProps, dom) => [
260 398 ...dom.reverse(),
261 399 <Button
... ... @@ -273,6 +411,7 @@ export default () =&gt; {
273 411 'POST',
274 412 values,
275 413 () => {
  414 + console.log(searchConfig, '5656searchConfig');
276 415 messageApi.destroy();
277 416 },
278 417 );
... ... @@ -323,16 +462,6 @@ export default () =&gt; {
323 462 dateFormatter="string"
324 463 headerTitle="高级表格"
325 464 toolBarRender={() => [
326   - <div key={'groupFilter'}>
327   - <Radio.Group
328   - options={groupFilterOptions}
329   - onChange={(e) => {
330   - setGroupFilter(e.target.value);
331   - }}
332   - value={groupFilter}
333   - optionType="button"
334   - />
335   - </div>,
336 465 <ClientDrawer
337 466 optType={'add'}
338 467 key="button"
... ... @@ -340,7 +469,12 @@ export default () =&gt; {
340 469 actionRef.current.reload();
341 470 }}
342 471 ></ClientDrawer>,
343   - <ClientImportModal key="import" />,
  472 + <ClientImportModal
  473 + key="import"
  474 + reloadTable={() => {
  475 + actionRef.current.reload();
  476 + }}
  477 + />,
344 478 ]}
345 479 />
346 480 </Space>
... ...
src/pages/Client/Components/ClientStatistic.tsx deleted 100644 → 0
1   -import { postAdminClientGetStatisticalData } from '@/services';
2   -import { StatisticCard } from '@ant-design/pro-components';
3   -import { useEffect, useState } from 'react';
4   -
5   -export default () => {
6   - const [clientStatistic, setClientStatistic] = useState([]);
7   - useEffect(() => {
8   - const pullStatistic = async () => {
9   - let statisticalData = await postAdminClientGetStatisticalData();
10   - console.log('stati' + JSON.stringify(statisticalData.data));
11   - setClientStatistic(statisticalData.data);
12   - };
13   - pullStatistic();
14   - }, []);
15   - return (
16   - <StatisticCard.Group>
17   - {clientStatistic.map((stat, index) => (
18   - <StatisticCard
19   - key={index}
20   - statistic={{
21   - title: stat.title,
22   - tip: stat.tip || '', // 如果tip不存在,则使用空字符串
23   - value: stat.value,
24   - status: stat.status || 'default', // 如果status不存在,则使用'default'
25   - }}
26   - />
27   - ))}
28   - </StatisticCard.Group>
29   - );
30   -};
src/pages/Client/Components/CommunicationHistoryModal.tsx deleted 100644 → 0
1   -import { RESPONSE_CODE } from '@/constants/enum';
2   -import {
3   - postAdminClientAddOrModifyClientComunicationInfo,
4   - postAdminClientQueryClientComunicationInfo,
5   - postAdminClientRemoveClientComunicationInfo,
6   -} from '@/services';
7   -import {
8   - ActionType,
9   - EditableProTable,
10   - ModalForm,
11   - ProFormInstance,
12   -} from '@ant-design/pro-components';
13   -import { Popconfirm, message } from 'antd';
14   -import { useEffect, useRef, useState } from 'react';
15   -export default ({ clientId }) => {
16   - const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
17   - const [dataSource, setDataSource] = useState();
18   - const ref = useRef<ProFormInstance>();
19   - const actionRef = useRef<ActionType>();
20   - const columns = [
21   - {
22   - title: '跟进时间',
23   - dataIndex: 'datetime',
24   - width: 50,
25   - valueType: 'dateTime',
26   - rules: [{ required: true, message: '请选择时间' }],
27   - },
28   - {
29   - title: '方式',
30   - width: 50,
31   - dataIndex: 'way',
32   - rules: [{ required: true, message: '请选择方式' }],
33   - },
34   - {
35   - title: '内容',
36   - width: 100,
37   - valueType: 'textarea',
38   - rules: [{ required: true, message: '请输入内容' }],
39   - dataIndex: 'content',
40   - },
41   - {
42   - title: '操作',
43   - valueType: 'option',
44   - width: 50,
45   - render: (text, record, _, action) => [
46   - <a
47   - key="editable"
48   - onClick={() => {
49   - action?.startEditable?.(record.tid);
50   - }}
51   - >
52   - 编辑
53   - </a>,
54   - <Popconfirm
55   - key={'delete'}
56   - title="删除记录"
57   - description="确认删除记录?"
58   - onConfirm={async () => {
59   - setDataSource(dataSource.filter((item) => item.tid !== record.tid));
60   - const res = await postAdminClientRemoveClientComunicationInfo({
61   - query: {
62   - id: record.id,
63   - },
64   - });
65   - if (res.result === RESPONSE_CODE.SUCCESS) {
66   - message.success(res.message);
67   - action?.reload();
68   - } else {
69   - message.error('删除失败');
70   - }
71   - }}
72   - okText="是"
73   - cancelText="否"
74   - >
75   - <a type={'danger'}>删除</a>
76   - </Popconfirm>,
77   - ],
78   - },
79   - ];
80   -
81   - useEffect(() => {
82   - console.log('clientId', clientId);
83   - }, []);
84   - return (
85   - <ModalForm
86   - title="跟进记录"
87   - trigger={<a type="primary">跟进记录</a>}
88   - modalProps={{
89   - destroyOnClose: true,
90   - }}
91   - >
92   - <EditableProTable
93   - rowKey="tid"
94   - formRef={ref}
95   - actionRef={actionRef}
96   - recordCreatorProps={{
97   - record: () => ({ tid: (Math.random() * 1000000).toFixed(0) }),
98   - }}
99   - loading={false}
100   - columns={columns}
101   - request={async () => {
102   - const res = await postAdminClientQueryClientComunicationInfo({
103   - data: {
104   - clientId: clientId,
105   - },
106   - });
107   - if (res.result === RESPONSE_CODE.SUCCESS) {
108   - console.log(JSON.stringify(res.data));
109   - return {
110   - ...res.data,
111   - data: res.data.data.map((item) => {
112   - return {
113   - ...item,
114   - tid: (Math.random() * 1000000).toFixed(0),
115   - };
116   - }),
117   - };
118   - } else {
119   - message.error('获取失败');
120   - }
121   - }}
122   - value={dataSource}
123   - onChange={setDataSource}
124   - editable={{
125   - type: 'multiple',
126   - editableKeys,
127   - onSave: async (rowKey, data, row) => {
128   - console.log(rowKey, data, row);
129   - const res = await postAdminClientAddOrModifyClientComunicationInfo({
130   - data: {
131   - ...data,
132   - clientId: clientId,
133   - },
134   - });
135   - if (res.result === RESPONSE_CODE.SUCCESS) {
136   - message.success(res.message);
137   - } else {
138   - message.error('修改失败');
139   - }
140   - actionRef.current?.reload();
141   - },
142   - onChange: setEditableRowKeys,
143   - }}
144   - />
145   - {/*<ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
146   - <ProFormField
147   - ignoreFormItem
148   - fieldProps={{
149   - style: {
150   - width: '100%',
151   - },
152   - }}
153   - mode="read"
154   - valueType="jsonCode"
155   - text={JSON.stringify(dataSource)}
156   - />
157   - </ProCard>*/}
158   - </ModalForm>
159   - );
160   -};
src/pages/Client/Components/ClientImportModal.tsx renamed to src/pages/Client/FollowRecord/Components/ClientImportModal.tsx
src/pages/Client/FollowRecord/Components/ClientModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postAdminClientAddOrModifyClientComunicationInfo,
  4 + postAdminClientQueryClientPage,
  5 + postOrderErpOrderStagesUpload,
  6 + postServiceConstClientWay,
  7 +} from '@/services';
  8 +import { enumToSelect } from '@/utils';
  9 +import {
  10 + ModalForm,
  11 + ProFormDateTimePicker,
  12 + ProFormSelect,
  13 + ProFormText,
  14 + ProFormTextArea,
  15 + ProFormUploadDragger,
  16 +} from '@ant-design/pro-components';
  17 +import { Button, Form, message } from 'antd';
  18 +import { RcFile } from 'antd/es/upload';
  19 +export default ({ data, type, reloadTable }) => {
  20 + const [form] = Form.useForm();
  21 + const onfinish = async (values) => {
  22 + const resSearchId = await postAdminClientQueryClientPage({
  23 + data: {
  24 + groupFilter: 'all',
  25 + },
  26 + });
  27 + const matchingItem = resSearchId.data.data.find(
  28 + (item) => item.id === values.name,
  29 + );
  30 + let matchedId;
  31 + if (matchingItem) {
  32 + matchedId = matchingItem.id; // 匹配成功,取出 id
  33 + values.name = matchingItem.name;
  34 + } else {
  35 + matchedId = null; // 如果没有匹配项,可以设置为 null 或其他值
  36 + }
  37 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  38 + data: {
  39 + ...values,
  40 + clientId: matchedId,
  41 + },
  42 + });
  43 + if (res.result === RESPONSE_CODE.SUCCESS) {
  44 + message.success('新增成功');
  45 + reloadTable();
  46 + return true;
  47 + }
  48 + // 不返回不会关闭弹框
  49 + };
  50 + const editOnfinish = async (values) => {
  51 + // setEditClientId(data.clientId);
  52 + values.clientId = data.clientId;
  53 + console.log(values, '5656editClientId');
  54 +
  55 + // const resSearchId = await postAdminClientQueryClientPage({
  56 + // data: {
  57 + // groupFilter: 'all',
  58 + // },
  59 + // });
  60 + // const matchingItem = resSearchId.data.data.find(
  61 + // (item) => item.id === values.name,
  62 + // );
  63 +
  64 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  65 + data: {
  66 + ...values,
  67 + },
  68 + });
  69 + if (res.result === RESPONSE_CODE.SUCCESS) {
  70 + message.success('新增成功');
  71 + reloadTable();
  72 + return true;
  73 + }
  74 + // 不返回不会关闭弹框
  75 + };
  76 + const optType = {
  77 + add: {
  78 + readOnly: false,
  79 + title: '新增跟进记录',
  80 + button: (
  81 + <Button size={'middle'} type="primary">
  82 + 新增
  83 + </Button>
  84 + ),
  85 + onFinish: onfinish,
  86 + },
  87 + modify: {
  88 + readOnly: false,
  89 + title: '修改跟进记录',
  90 + button: (
  91 + <Button size={'middle'} type="primary">
  92 + 编辑
  93 + </Button>
  94 + ),
  95 + onFinish: editOnfinish,
  96 + },
  97 + detail: {
  98 + readOnly: true,
  99 + title: '查看跟进记录',
  100 + button: (
  101 + <Button size={'middle'} type="primary" color="red">
  102 + 查看
  103 + </Button>
  104 + ),
  105 + onFinish: () => {},
  106 + },
  107 + };
  108 + return (
  109 + <ModalForm
  110 + title={optType[type].title}
  111 + resize={{
  112 + onResize() {
  113 + console.log('resize!');
  114 + },
  115 + maxWidth: window.innerWidth * 0.8,
  116 + minWidth: 400,
  117 + }}
  118 + form={form}
  119 + trigger={optType[type].button}
  120 + autoFocusFirstInput
  121 + drawerProps={{
  122 + destroyOnClose: true,
  123 + }}
  124 + submitTimeout={2000}
  125 + onFinish={optType[type].onFinish}
  126 + >
  127 + <ProFormSelect
  128 + name="name"
  129 + readonly={optType[type].readOnly}
  130 + fieldProps={{
  131 + labelInValue: false,
  132 + disabled: type === 'modify',
  133 + }}
  134 + initialValue={data ? data?.clientName + '' : null}
  135 + label="客户"
  136 + width="sm"
  137 + request={async () => {
  138 + const res = await postAdminClientQueryClientPage({
  139 + data: {
  140 + groupFilter: 'all',
  141 + },
  142 + });
  143 + console.log(data, '5656data?.nameedit');
  144 + // const namesArray = res.data.data.map((item) => item.name);
  145 + // const formattedObject = res.data.data.reduce((acc, name) => {
  146 + // acc[name] = name; // 将名称作为键和值
  147 + // return acc;
  148 + // }, {});
  149 + // console.log(namesArray, '5656namesArray');
  150 + // const formattedObject = res.data.data.reduce((acc, item) => {
  151 + // acc[item.name] = item.name; // 使用 name 作为键,id 作为值
  152 + // return acc;
  153 + // }, {});
  154 + // return enumToSelect(formattedObject);
  155 + const options = res.data.data.reduce((acc, item) => {
  156 + acc.push({ label: item.name, value: item.id }); // 使用 name 作为 label,id 作为 value
  157 + return acc;
  158 + }, []);
  159 + return options;
  160 + }}
  161 + rules={[
  162 + {
  163 + required: true,
  164 + message: '请选择客户',
  165 + },
  166 + ]}
  167 + ></ProFormSelect>
  168 + <ProFormDateTimePicker
  169 + name="datetime"
  170 + label="日期"
  171 + initialValue={data ? data?.datetime + '' : null}
  172 + placeholder="请选择跟进时间"
  173 + width="sm"
  174 + rules={[
  175 + {
  176 + required: true,
  177 + message: '请选择日期',
  178 + },
  179 + ]}
  180 + />
  181 + <ProFormSelect
  182 + name="way"
  183 + width="sm"
  184 + readonly={optType[type].readOnly}
  185 + fieldProps={{
  186 + labelInValue: false,
  187 + }}
  188 + initialValue={data?.way ? data?.way + '' : null}
  189 + label="类型"
  190 + request={async () => {
  191 + const res = await postServiceConstClientWay();
  192 + return enumToSelect(res.data);
  193 + }}
  194 + rules={[
  195 + {
  196 + required: true,
  197 + message: '请选择跟进类型',
  198 + },
  199 + ]}
  200 + ></ProFormSelect>
  201 + <ProFormTextArea
  202 + name="content"
  203 + label="详情"
  204 + placeholder="请输入详情"
  205 + initialValue={data?.content}
  206 + readonly={optType[type].readOnly}
  207 + rules={[
  208 + {
  209 + required: true,
  210 + message: '请输入详情',
  211 + },
  212 + ]}
  213 + ></ProFormTextArea>
  214 + <ProFormUploadDragger
  215 + label="附件"
  216 + name="attachment"
  217 + action="upload.do"
  218 + hidden={optType[type].readOnly}
  219 + onChange={(info) => {
  220 + const uploadFile = async ({ fileList: newFileList }) => {
  221 + if (newFileList.length > 0) {
  222 + const formData = new FormData();
  223 + formData.append('file', newFileList[0].originFileObj as RcFile);
  224 + const res = await postOrderErpOrderStagesUpload({
  225 + data: formData,
  226 + headers: {
  227 + 'Content-Type':
  228 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  229 + },
  230 + });
  231 + const url = res.data;
  232 + console.log('attachments' + JSON.stringify(url));
  233 + form.setFieldValue('attachments', url);
  234 + } else {
  235 + form.setFieldValue('attachments', null);
  236 + }
  237 + };
  238 + uploadFile(info);
  239 + }}
  240 + max={1}
  241 + />
  242 + <a hidden={!optType[type].readOnly} href={data?.attachments} download>
  243 + 下载附件
  244 + </a>
  245 + <ProFormText
  246 + initialValue={data?.attachments}
  247 + name="attachments"
  248 + hidden
  249 + ></ProFormText>
  250 + <ProFormText initialValue={data?.id} name="id" hidden></ProFormText>
  251 + </ModalForm>
  252 + );
  253 +};
... ...
src/pages/Client/FollowRecord/Components/CommunicationHistoryModal.tsx 0 → 100644
  1 +import ClientModal from '@/pages/Client/FollowRecord/Components/ClientModal';
  2 +import {
  3 + postAdminClientQueryClientComunicationInfo,
  4 + postAdminClientRemoveClientComunicationInfo,
  5 +} from '@/services/request';
  6 +import { ModalForm } from '@ant-design/pro-components';
  7 +import { Button, Descriptions, Space } from 'antd';
  8 +import { useEffect, useRef, useState } from 'react';
  9 +
  10 +export default ({ data, reloadTable }) => {
  11 + console.log(data, '5656datafirstshowgenjin');
  12 +
  13 + // const [isModalVisible, setIsModalVisible] = useState(false); // 控制 ClientModal 的显示
  14 + const actionRef = useRef(); // 引用 actionRef,方便调用 reload 方法
  15 +
  16 + const [datetime, setDatetime] = useState(); // 跟进日期
  17 + const [createByName, setCreateByName] = useState(''); // 跟进人员
  18 + const [clientName, setClientName] = useState(''); // 客户名称
  19 + // const [clientAddress, setClientAddress] = useState(''); // 客户地址
  20 + const [way, setWay] = useState(); // 类型
  21 + // const [clientNameLike, setClientNameLike] = useState(''); // 客户名称模糊查询
  22 + // const [clientAddressLike, setClientAddressLike] = useState(''); // 客户地址模糊查询
  23 + // const [tradeStatus, setTradeStatus] = useState(''); // 客户状态
  24 + // const [tradeStatusLike, setTradeStatusLike] = useState(''); // 客户状态模糊查询
  25 + const [content, setContent] = useState(''); // 跟进详情
  26 + const [createTime, setCreateTime] = useState(null); // 创建时间
  27 + const [attachments, setAttachments] = useState(); //附件
  28 + const [attachmentsName, setAttachmentsName] = useState(''); // 附件名称
  29 +
  30 + useEffect(() => {
  31 + const request = async () => {
  32 + console.log(data, '5656datasearch');
  33 + const res = await postAdminClientQueryClientComunicationInfo({
  34 + data: {
  35 + id: data.id,
  36 + },
  37 + });
  38 + console.log(res, '5656res');
  39 + const dataSearch = res.data.data[0];
  40 + if (dataSearch) {
  41 + if (dataSearch.attachments) {
  42 + const url = dataSearch.attachments;
  43 + const match = url.match(/aliyuncs\.com\/(.*?)\?/);
  44 + let decodedStr = '';
  45 +
  46 + if (match) {
  47 + // 获取匹配的字符串并进行解码
  48 + const encodedStr = match[1];
  49 + decodedStr = decodeURIComponent(encodedStr);
  50 + setAttachmentsName(decodedStr); // 设置跟进日期
  51 + }
  52 + }
  53 + setDatetime(dataSearch.datetime); // 设置跟进日期
  54 + // setDateRange(data.dateRange || []); // 设置跟进时间范围
  55 + setCreateByName(dataSearch.createByName); // 设置跟进人员
  56 + setClientName(dataSearch.clientName); // 设置客户名称
  57 + // setClientAddress(data.clientAddress || ''); // 设置客户地址
  58 + // setClientNameLike(data.clientNameLike || ''); // 设置客户名称模糊查询
  59 + // setClientAddressLike(data.clientAddressLike || ''); // 设置客户地址模糊查询
  60 + // setTradeStatus(data.tradeStatus || ''); // 设置客户状态
  61 + // setTradeStatusLike(data.tradeStatusLike || ''); // 设置客户状态模糊查询
  62 + setContent(dataSearch.content); // 设置跟进详情
  63 + setCreateTime(dataSearch.createTime); // 设置创建时间
  64 + setWay(dataSearch.wayText);
  65 + setAttachments(dataSearch.attachments);
  66 + }
  67 + console.log(attachments, '5656attachments');
  68 + };
  69 + request();
  70 + }, []);
  71 + const items = [
  72 + {
  73 + key: '1',
  74 + label: '跟进日期',
  75 + children: datetime, // 跟进日期
  76 + },
  77 + {
  78 + key: '2',
  79 + label: '跟进人员',
  80 + children: createByName, // 跟进人员
  81 + },
  82 + {
  83 + key: '3',
  84 + label: '客户名称',
  85 + children: clientName, // 客户名称
  86 + },
  87 + {
  88 + key: '4',
  89 + label: '跟进详情',
  90 + children: content, // 跟进详情
  91 + },
  92 + {
  93 + key: '5',
  94 + label: '创建时间',
  95 + children: createTime, // 创建时间
  96 + },
  97 + {
  98 + key: '6',
  99 + label: '跟进类型',
  100 + children: way, // 跟进类型
  101 + },
  102 + ];
  103 + const handleDelete = async () => {
  104 + console.log(JSON.stringify(data), '5656record');
  105 + // 调用删除接口
  106 + const success = await postAdminClientRemoveClientComunicationInfo({
  107 + query: {
  108 + id: data.id,
  109 + },
  110 + });
  111 + // setIsModalVisible(false);
  112 + if (success) {
  113 + actionRef?.current?.reload(); // 重新加载表格数据
  114 + }
  115 + };
  116 + return (
  117 + <Space>
  118 + <ModalForm
  119 + title="跟进记录"
  120 + trigger={<Button type="link">查看</Button>}
  121 + submitter={{
  122 + resetButtonProps: {
  123 + style: {
  124 + display: 'none',
  125 + },
  126 + },
  127 + submitButtonProps: {
  128 + style: {
  129 + display: 'none',
  130 + },
  131 + },
  132 + render: (props, defaultDoms) => {
  133 + return [
  134 + ...defaultDoms,
  135 + <>
  136 + <ClientModal
  137 + key={'modify'}
  138 + data={data} // 将表单数据传递给 ClientModal
  139 + reloadTable={() => {
  140 + actionRef?.current?.reload(); // 重新加载表格数据
  141 + props.submit();
  142 + reloadTable();
  143 + console.log('5656close');
  144 + }}
  145 + type={'modify'}
  146 + onFinish={() => {
  147 + // setIsModalVisible(false);
  148 + }} // 关闭 Modal
  149 + style={{ marginRight: '10px' }}
  150 + />
  151 + <Button
  152 + key={'delete'}
  153 + onClick={() => {
  154 + handleDelete();
  155 + props.submit();
  156 + reloadTable();
  157 + }}
  158 + type="primary"
  159 + size="middle"
  160 + danger // 使用 danger 属性来将按钮颜色设置为红色
  161 + style={{ marginLeft: '10px' }}
  162 + onFinish={() => {
  163 + actionRef.current.reload();
  164 + }}
  165 + >
  166 + 删除
  167 + </Button>
  168 + </>,
  169 + ];
  170 + },
  171 + }}
  172 + onFinish={async () => {
  173 + // 提交成功后,显示 ClientDrawer
  174 + // setIsModalVisible(true);
  175 + return true;
  176 + }}
  177 + >
  178 + <Descriptions items={items} column={1} />
  179 + {attachmentsName && (
  180 + <a href={attachments} download>
  181 + 附件:{attachmentsName}
  182 + </a>
  183 + )}
  184 + </ModalForm>
  185 + </Space>
  186 + );
  187 +};
... ...
src/pages/Client/FollowRecord/index.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import ClientModal from '@/pages/Client/FollowRecord/Components/ClientModal';
  3 +import CommunicationHistoryModal from '@/pages/Client/FollowRecord/Components/CommunicationHistoryModal';
  4 +import {
  5 + postAdminClientQueryClientComunicationInfo,
  6 + postAdminClientRemoveClientComunicationInfo,
  7 + postServiceConstClientWay,
  8 + postServiceConstTradeStatus,
  9 +} from '@/services';
  10 +import { enumToSelect } from '@/utils';
  11 +import type { ActionType } from '@ant-design/pro-components';
  12 +import { ProTable } from '@ant-design/pro-components';
  13 +import { Button, Space, message } from 'antd';
  14 +import { useRef, useState } from 'react';
  15 +
  16 +export default () => {
  17 + const actionRef = useRef<ActionType>();
  18 + const [refreshKey, setRefreshKey] = useState(0); // 用于强制刷新的键
  19 +
  20 + const reload = () => {
  21 + actionRef.current.reload(); // 重新加载数据
  22 + console.log('5656flush');
  23 +
  24 + // 更新 refreshKey,强制刷新 CommunicationHistoryModal
  25 + setRefreshKey((prevKey) => prevKey + 1);
  26 + };
  27 + //biaoji
  28 + const columns = [
  29 + {
  30 + title: '跟进日期',
  31 + key: 'datetime',
  32 + width: 150,
  33 + ellipsis: true,
  34 + dataIndex: 'datetime',
  35 + valueType: 'dateTime',
  36 + hideInSearch: true,
  37 + // search: {
  38 + // transform: (value) => {
  39 + // if (value) {
  40 + // return {
  41 + // createTimeGe: value[0],
  42 + // createTimeLe: value[1],
  43 + // };
  44 + // }
  45 + // },
  46 + // },
  47 + },
  48 + {
  49 + title: '跟进时间',
  50 + dataIndex: 'dateRange',
  51 + valueType: 'dateRange',
  52 + hideInTable: true,
  53 + search: {
  54 + transform: (value) => {
  55 + if (value) {
  56 + return {
  57 + dateTimeGe: value[0],
  58 + dateTimeLe: value[1],
  59 + };
  60 + }
  61 + },
  62 + },
  63 + },
  64 + {
  65 + title: '跟进人员',
  66 + dataIndex: 'updateByName',
  67 + width: 100,
  68 + ellipsis: true,
  69 + hideInSearch: false,
  70 + },
  71 + {
  72 + title: '客户名称',
  73 + dataIndex: 'clientName',
  74 + width: 150,
  75 + ellipsis: true,
  76 + hideInSearch: true,
  77 + },
  78 + {
  79 + title: '客户地址',
  80 + dataIndex: 'clientAddress',
  81 + width: 250,
  82 + ellipsis: true,
  83 + hideInSearch: true,
  84 + },
  85 + {
  86 + title: '跟进类型',
  87 + dataIndex: 'wayText',
  88 + width: 100,
  89 + ellipsis: true,
  90 + hideInSearch: true,
  91 + },
  92 + {
  93 + title: '跟进类型',
  94 + dataIndex: 'way',
  95 + width: 100,
  96 + ellipsis: true,
  97 + hideInSearch: false,
  98 + hideInTable: true,
  99 + request: async () => {
  100 + const res = await postServiceConstClientWay();
  101 + return enumToSelect(res.data);
  102 + },
  103 + },
  104 + {
  105 + title: '客户名称',
  106 + dataIndex: 'clientNameLike',
  107 + width: 150,
  108 + ellipsis: true,
  109 + hideInSearch: false,
  110 + hideInTable: true,
  111 + },
  112 + {
  113 + title: '客户地址',
  114 + dataIndex: 'clientAddressLike',
  115 + width: 250,
  116 + ellipsis: true,
  117 + hideInSearch: false,
  118 + hideInTable: true,
  119 + },
  120 + {
  121 + title: '客户状态',
  122 + dataIndex: 'tradeStatus',
  123 + width: 100,
  124 + ellipsis: true,
  125 + hideInSearch: true,
  126 + },
  127 + {
  128 + title: '客户状态',
  129 + dataIndex: 'tradeStatusLike',
  130 + width: 100,
  131 + ellipsis: true,
  132 + hideInSearch: false,
  133 + hideInTable: true,
  134 + request: async () => {
  135 + const res = await postServiceConstTradeStatus();
  136 + return enumToSelect(res.data);
  137 + },
  138 + },
  139 + {
  140 + title: '跟进详情',
  141 + dataIndex: 'content',
  142 + width: 250,
  143 + ellipsis: true,
  144 + hideInSearch: false,
  145 + },
  146 + {
  147 + title: '创建时间',
  148 + dataIndex: 'createTime',
  149 + width: 150,
  150 + ellipsis: true,
  151 + hideInSearch: true,
  152 + },
  153 + {
  154 + title: '附件',
  155 + dataIndex: 'attachments',
  156 + width: 150,
  157 + ellipsis: true,
  158 + hideInSearch: true,
  159 + hideInTable: true,
  160 + },
  161 + {
  162 + title: '操作',
  163 + valueType: 'option',
  164 + key: 'option',
  165 + width: 150,
  166 + render: (text, record, index, action) => {
  167 + const handleDelete = async () => {
  168 + // console.log(JSON.stringify(record), '5656record');
  169 + // 调用删除接口
  170 + const success = await postAdminClientRemoveClientComunicationInfo({
  171 + query: {
  172 + id: record.id,
  173 + },
  174 + });
  175 + if (success) {
  176 + action.reload(); // 刷新表格
  177 + }
  178 + };
  179 + return [
  180 + <CommunicationHistoryModal
  181 + // key={'communicationHistory'}
  182 + key={`communicationHistory-${refreshKey}`} // 使用 refreshKey 来强制更新组件
  183 + data={record}
  184 + // reloadTable={() => {
  185 + // actionRef.current.reload();
  186 + // console.log('5656flush');
  187 + // }}
  188 + reloadTable={reload}
  189 + />,
  190 + <>
  191 + <Button
  192 + key={'delete'}
  193 + onClick={() => {
  194 + handleDelete();
  195 + actionRef.current.reload();
  196 + }}
  197 + // reloadTable={() => {
  198 + // actionRef.current.reload();
  199 + // }}
  200 + type="link"
  201 + size="middle"
  202 + // 使用 danger 属性来将按钮颜色设置为红色
  203 + // onFinish={() => {
  204 + // actionRef.current.reload();
  205 + // }}
  206 + >
  207 + 删除
  208 + </Button>
  209 + </>,
  210 + ];
  211 + },
  212 + },
  213 + ];
  214 +
  215 + // useEffect(() => {
  216 + // const pullGroupFilterDataOptions = async () => {
  217 + // const res = await postServiceConstClientGroupFilters();
  218 + // console.log('setGroupFilterDataOptions' + JSON.stringify(res.data));
  219 + // setGroupFilterDataOptions(enumToSelect(res.data));
  220 + // };
  221 + // pullGroupFilterDataOptions();
  222 + // }, []);
  223 + // useEffect(() => {
  224 + // actionRef.current?.reload();
  225 + // }, [groupFilter]);
  226 + return (
  227 + <>
  228 + <Space direction="vertical" size="middle" style={{ display: 'flex' }}>
  229 + <ProTable
  230 + columns={columns}
  231 + actionRef={actionRef}
  232 + cardBordered
  233 + request={async (params) => {
  234 + const res = await postAdminClientQueryClientComunicationInfo({
  235 + data: {
  236 + ...params,
  237 + },
  238 + });
  239 + console.log(params, '5656566params');
  240 + if (res.result === RESPONSE_CODE.SUCCESS) {
  241 + console.log(JSON.stringify(res.data));
  242 + return {
  243 + ...res.data,
  244 + data: res.data.data.map((item) => {
  245 + return {
  246 + ...item,
  247 + tid: (Math.random() * 1000000).toFixed(0),
  248 + };
  249 + }),
  250 + };
  251 + } else {
  252 + message.error('获取失败');
  253 + }
  254 + }}
  255 + search={{
  256 + optionRender: (searchConfig, formProps, dom) => [...dom.reverse()],
  257 + }}
  258 + scroll={{
  259 + x: 1400,
  260 + }}
  261 + editable={{
  262 + type: 'multiple',
  263 + }}
  264 + columnsState={{
  265 + persistenceKey: 'pro-table-singe-demos',
  266 + persistenceType: 'localStorage',
  267 + defaultValue: {
  268 + option: { fixed: 'right', disable: true },
  269 + },
  270 + onChange(value) {
  271 + console.log('value: ', value);
  272 + },
  273 + }}
  274 + rowKey="id"
  275 + options={{
  276 + setting: {
  277 + listsHeight: 400,
  278 + },
  279 + }}
  280 + form={{
  281 + // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
  282 + syncToUrl: (values, type) => {
  283 + if (type === 'get') {
  284 + return {
  285 + ...values,
  286 + created_at: [values.startTime, values.endTime],
  287 + };
  288 + }
  289 + return values;
  290 + },
  291 + }}
  292 + pagination={{
  293 + pageSize: 5,
  294 + onChange: (page) => console.log(page),
  295 + }}
  296 + dateFormatter="string"
  297 + headerTitle="高级表格"
  298 + toolBarRender={() => [
  299 + <ClientModal
  300 + key={'add'}
  301 + reloadTable={() => {
  302 + actionRef.current.reload();
  303 + }}
  304 + type={'add'}
  305 + />,
  306 + ]}
  307 + />
  308 + </Space>
  309 + {/* {contextHolder} */}
  310 + </>
  311 + );
  312 +};
... ...
src/pages/Order/Order/components/ConfirmReceiptModal.tsx
... ... @@ -107,8 +107,8 @@ export default ({ data, onClose }) =&gt; {
107 107 setPreviewOpen(true);
108 108 setPreviewTitle(
109 109 file.name ||
110   - file.originFileObj?.name ||
111   - file.url!.substring(file.url!.lastIndexOf('/') + 1),
  110 + file.originFileObj?.name ||
  111 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
112 112 );
113 113 };
114 114  
... ...
src/pages/Order/Order/components/DeliverModal.tsx
... ... @@ -260,7 +260,7 @@ const DeliverModal = ({
260 260 serialNumber: item.serialNumber,
261 261 packageNumber:
262 262 item.packageNumber === null ||
263   - item.packageNumber === undefined
  263 + item.packageNumber === undefined
264 264 ? 1
265 265 : item.packageNumber,
266 266 logisticsNotes: item.logisticsNotes,
... ...
src/pages/Order/Order/components/FeedbackRegistrationModal.tsx 0 → 100644
  1 +import { postServiceOrderFeedbackRegistration } from '@/services/request';
  2 +import { Input, Modal } from 'antd';
  3 +import { useState } from 'react';
  4 +
  5 +// import { cloneDeep } from 'lodash';
  6 +export default ({ subOrders, onClose }) => {
  7 + const [isModalOpen] = useState(true);
  8 + const { TextArea } = Input;
  9 + const [textValue, setTextValue] = useState('');
  10 +
  11 + const handleOk = async () => {
  12 + console.log(textValue); // 处理输入的文本
  13 + console.log(subOrders, '5656subOrders');
  14 + let res = await postServiceOrderFeedbackRegistration({
  15 + data: {
  16 + id: subOrders[0].id,
  17 + feedbackRegistrationContent: textValue,
  18 + },
  19 + });
  20 + console.log(res, '5656res');
  21 + onClose();
  22 + // setIsModalOpen(false);
  23 + // onClose();
  24 + };
  25 + const handleCancel = () => {
  26 + onClose();
  27 + // setIsModalOpen(false);
  28 + // onClose();
  29 + };
  30 + const handleChange = (e) => {
  31 + setTextValue(e.target.value);
  32 + };
  33 + return (
  34 + <>
  35 + {/* <ModalForm<{
  36 + filePaths: any;
  37 + }>
  38 + width={500}
  39 + open
  40 + title="回访登记"
  41 + form={form}
  42 + autoFocusFirstInput
  43 + modalProps={{
  44 + okText: '提交',
  45 + cancelText: '取消',
  46 + destroyOnClose: true,
  47 + onCancel: () => {
  48 + setVisible(false);
  49 + },
  50 + }}
  51 + onFinish={async () => {
  52 + onClose();
  53 + }}
  54 + onOpenChange={setVisible}
  55 + >
  56 + <TextArea rows={6} placeholder="请输入" />
  57 + </ModalForm> */}
  58 + <Modal
  59 + title="回访登记"
  60 + open={isModalOpen}
  61 + onOk={handleOk}
  62 + onCancel={handleCancel}
  63 + >
  64 + <TextArea
  65 + rows={6}
  66 + placeholder="请输入"
  67 + onChange={handleChange}
  68 + value={textValue}
  69 + />
  70 + </Modal>
  71 + </>
  72 + );
  73 +};
... ...
src/pages/Order/Order/components/FinancialDrawer.tsx
... ... @@ -144,107 +144,107 @@ export default ({
144 144  
145 145 {invoicingStatus !== 'UN_INVOICE'
146 146 ? [
147   - <ProFormDatePicker
148   - key="invoicingTime"
149   - width="lg"
150   - name="invoicingTime"
151   - label="开票时间"
152   - disabled={isEdit}
153   - rules={[
154   - { required: !isEdit ? true : false, message: '这是必填项' },
155   - ]}
156   - initialValue={subOrders[0]?.invoicingTime}
157   - />,
158   - <ProFormText
159   - key="purchaser"
160   - width="lg"
161   - name="purchaser"
162   - label="抬头名称"
163   - disabled={isEdit}
164   - rules={[
165   - { required: !isEdit ? true : false, message: '这是必填项' },
166   - ]}
167   - initialValue={subOrders[0]?.purchaser}
168   - />,
169   - <ProFormDatePicker
170   - key="financialReceiptIssuanceTime"
171   - width="lg"
172   - name="financialReceiptIssuanceTime"
173   - label="开收据时间"
174   - initialValue={subOrders[0]?.financialReceiptIssuanceTime}
175   - />,
176   - <ProFormDatePicker
177   - key="collectMoneyTime"
178   - width="lg"
179   - name="collectMoneyTime"
180   - label="收款时间"
181   - initialValue={subOrders[0]?.collectMoneyTime}
182   - />,
183   - <ProFormText
184   - width="lg"
185   - key="invoiceNumber"
186   - name="invoiceNumber"
187   - label="发票号码"
188   - initialValue={subOrders[0]?.invoiceNumber}
189   - rules={[{ required: true, message: '发票号码必填' }]}
190   - />,
191   - <div
192   - key="salesChooseReceivingCompany"
193   - hidden={subOrders[0].receivingCompany === null}
194   - >
195   - <span className={'pl-2 text-xs text-gray-400'}>
196   - 销售申请开票时选择了:
197   - {enumValueToLabel(
198   - subOrders[0].receivingCompany,
199   - getReceivingCompanyOptions(PAYEE_OPTIONS),
200   - )}
201   - </span>
202   - <span
203   - hidden={subOrders[0].receivingCompany === 'ANY'}
204   - className={
205   - 'pl-2 text-xs text-[#1677ff] cursor-pointer hover:text-[#64abf7]'
206   - }
207   - onClick={() => {
208   - chooseReceivingCompany(subOrders[0].receivingCompany);
209   - }}
  147 + <ProFormDatePicker
  148 + key="invoicingTime"
  149 + width="lg"
  150 + name="invoicingTime"
  151 + label="开票时间"
  152 + disabled={isEdit}
  153 + rules={[
  154 + { required: !isEdit ? true : false, message: '这是必填项' },
  155 + ]}
  156 + initialValue={subOrders[0]?.invoicingTime}
  157 + />,
  158 + <ProFormText
  159 + key="purchaser"
  160 + width="lg"
  161 + name="purchaser"
  162 + label="抬头名称"
  163 + disabled={isEdit}
  164 + rules={[
  165 + { required: !isEdit ? true : false, message: '这是必填项' },
  166 + ]}
  167 + initialValue={subOrders[0]?.purchaser}
  168 + />,
  169 + <ProFormDatePicker
  170 + key="financialReceiptIssuanceTime"
  171 + width="lg"
  172 + name="financialReceiptIssuanceTime"
  173 + label="开收据时间"
  174 + initialValue={subOrders[0]?.financialReceiptIssuanceTime}
  175 + />,
  176 + <ProFormDatePicker
  177 + key="collectMoneyTime"
  178 + width="lg"
  179 + name="collectMoneyTime"
  180 + label="收款时间"
  181 + initialValue={subOrders[0]?.collectMoneyTime}
  182 + />,
  183 + <ProFormText
  184 + width="lg"
  185 + key="invoiceNumber"
  186 + name="invoiceNumber"
  187 + label="发票号码"
  188 + initialValue={subOrders[0]?.invoiceNumber}
  189 + rules={[{ required: true, message: '发票号码必填' }]}
  190 + />,
  191 + <div
  192 + key="salesChooseReceivingCompany"
  193 + hidden={subOrders[0].receivingCompany === null}
210 194 >
211   - 选择
212   - </span>
213   - </div>,
214   - <ProFormSelect
215   - key="payee"
216   - placeholder="选择收款单位"
217   - name="payee"
218   - width="lg"
219   - showSearch
220   - label="收款单位"
221   - options={enumToSelect(PAYEE_OPTIONS)}
222   - initialValue={subOrders[0]?.payee}
223   - rules={[{ required: true, message: '收款单位必填' }]}
224   - />,
225   -
226   - <div id="total-payment" key="money">
227   - <ProFormDigit
228   - key="money"
229   - name="money"
  195 + <span className={'pl-2 text-xs text-gray-400'}>
  196 + 销售申请开票时选择了:
  197 + {enumValueToLabel(
  198 + subOrders[0].receivingCompany,
  199 + getReceivingCompanyOptions(PAYEE_OPTIONS),
  200 + )}
  201 + </span>
  202 + <span
  203 + hidden={subOrders[0].receivingCompany === 'ANY'}
  204 + className={
  205 + 'pl-2 text-xs text-[#1677ff] cursor-pointer hover:text-[#64abf7]'
  206 + }
  207 + onClick={() => {
  208 + chooseReceivingCompany(subOrders[0].receivingCompany);
  209 + }}
  210 + >
  211 + 选择
  212 + </span>
  213 + </div>,
  214 + <ProFormSelect
  215 + key="payee"
  216 + placeholder="选择收款单位"
  217 + name="payee"
230 218 width="lg"
231   - label="金额"
232   - rules={[{ required: true, message: '金额必填' }]}
233   - tooltip="点击计算,合计所有子订单对应主订单总额"
234   - fieldProps={{
235   - addonAfter: (
236   - <Button
237   - className="rounded-l-none"
238   - type="primary"
239   - onClick={computeTotalPayment}
240   - >
241   - 计算
242   - </Button>
243   - ),
244   - }}
245   - />
246   - </div>,
247   - ]
  219 + showSearch
  220 + label="收款单位"
  221 + options={enumToSelect(PAYEE_OPTIONS)}
  222 + initialValue={subOrders[0]?.payee}
  223 + rules={[{ required: true, message: '收款单位必填' }]}
  224 + />,
  225 +
  226 + <div id="total-payment" key="money">
  227 + <ProFormDigit
  228 + key="money"
  229 + name="money"
  230 + width="lg"
  231 + label="金额"
  232 + rules={[{ required: true, message: '金额必填' }]}
  233 + tooltip="点击计算,合计所有子订单对应主订单总额"
  234 + fieldProps={{
  235 + addonAfter: (
  236 + <Button
  237 + className="rounded-l-none"
  238 + type="primary"
  239 + onClick={computeTotalPayment}
  240 + >
  241 + 计算
  242 + </Button>
  243 + ),
  244 + }}
  245 + />
  246 + </div>,
  247 + ]
248 248 : ''}
249 249  
250 250 <ProFormSelect
... ...
src/pages/Order/Order/components/FinancialEditDrawer.tsx
... ... @@ -130,24 +130,24 @@ export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) =&gt; {
130 130 width="lg"
131 131 name="financialReceiptIssuanceTime"
132 132 label="开收据时间"
133   - // rules={[
134   - // {
135   - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
136   - // message: '开收据时间必填',
137   - // },
138   - // ]}
  133 + // rules={[
  134 + // {
  135 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  136 + // message: '开收据时间必填',
  137 + // },
  138 + // ]}
139 139 />
140 140 <ProFormDatePicker
141 141 key="collectMoneyTime"
142 142 width="lg"
143 143 name="collectMoneyTime"
144 144 label="收款时间"
145   - // rules={[
146   - // {
147   - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
148   - // message: '收款时间必填',
149   - // },
150   - // ]}
  145 + // rules={[
  146 + // {
  147 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  148 + // message: '收款时间必填',
  149 + // },
  150 + // ]}
151 151 />
152 152 </DrawerForm>
153 153 );
... ...
src/pages/Order/Order/components/ImagesViewerModal.tsx
... ... @@ -3,7 +3,7 @@ import { Button, Divider, Image, Modal } from &#39;antd&#39;;
3 3 import { useEffect, useState } from 'react';
4 4 export default ({ setVisible, optType, onClose, orderRow }) => {
5 5 const [images, setImages] = useState<any[]>([]);
6   - const [title, setTitle] = useState("收货凭证");
  6 + const [title, setTitle] = useState('收货凭证');
7 7 const handleOk = () => {
8 8 onClose();
9 9 setVisible(false);
... ... @@ -23,7 +23,7 @@ export default ({ setVisible, optType, onClose, orderRow }) =&gt; {
23 23 }
24 24 useEffect(() => {
25 25 if (optType === 'shippingReceipt') {
26   - setTitle("收货凭证");
  26 + setTitle('收货凭证');
27 27 getImages();
28 28 } else if (optType === 'paymentReceipt') {
29 29 let paymentReceiptsImagesList: any[] = [];
... ... @@ -34,7 +34,6 @@ export default ({ setVisible, optType, onClose, orderRow }) =&gt; {
34 34 paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)];
35 35 setImages(paymentReceiptsImagesList);
36 36 }
37   -
38 37 }, []);
39 38  
40 39 return (
... ...
src/pages/Order/Order/components/ModifiedDiffModal.tsx
... ... @@ -106,7 +106,7 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
106 106 onClick={() => {
107 107 window.open(
108 108 '/previewApi/onlinePreview?url=' +
109   - encodeURIComponent(Base64.encode(item)),
  109 + encodeURIComponent(Base64.encode(item)),
110 110 );
111 111 }}
112 112 >
... ...
src/pages/Order/Order/components/OrderDrawer copy.tsx
... ... @@ -554,7 +554,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
554 554 onChange={(_, option) => {
555 555 autoFillSalesInfo(option);
556 556 }}
557   - // disabled={mainInfoDisbled}
  557 + // disabled={mainInfoDisbled}
558 558 />
559 559  
560 560 <ProFormText
... ... @@ -642,7 +642,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
642 642 },
643 643 }}
644 644 debounceTime={1000}
645   - request={async (value, { }) => {
  645 + request={async (value, {}) => {
646 646 const keywords = value.keyWords;
647 647 const res = await postKingdeeRepCustomer({
648 648 data: { search: keywords },
... ... @@ -740,7 +740,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
740 740 </Button>
741 741 ),
742 742 }}
743   - // disabled={mainInfoDisbled}
  743 + // disabled={mainInfoDisbled}
744 744 />
745 745 </div>
746 746  
... ... @@ -752,7 +752,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
752 752 label="支付渠道"
753 753 options={enumToSelect(PAYMENT_CHANNEL_OPTIONS)}
754 754 rules={[{ required: true, message: '支付渠道必填' }]}
755   - // disabled={mainInfoDisbled}
  755 + // disabled={mainInfoDisbled}
756 756 />
757 757 <ProFormSelect
758 758 placeholder="请输入支付方式"
... ... @@ -762,7 +762,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
762 762 label="支付方式"
763 763 options={enumToSelect(PAYMENT_METHOD_OPTIONS)}
764 764 rules={[{ required: true, message: '支付方式必填' }]}
765   - // disabled={mainInfoDisbled}
  765 + // disabled={mainInfoDisbled}
766 766 />
767 767 <ProFormSelect
768 768 placeholder="选择是否需要开票"
... ... @@ -1094,7 +1094,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1094 1094 options={enumToSelect(PRODUCT_BELONG_DEPARTMENT_OPTIONS)}
1095 1095 initialValue={'EXPERIMENTAL_CONSUMABLES'}
1096 1096 rules={[{ required: true, message: '所属事业部必填' }]}
1097   - // disabled={mainInfoDisbled}
  1097 + // disabled={mainInfoDisbled}
1098 1098 />,
1099 1099 <ProFormTextArea
1100 1100 key={'notes' + listMeta.index}
... ...
src/pages/Order/Order/components/OrderDrawer.tsx
... ... @@ -557,9 +557,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
557 557 form.setFieldValue(
558 558 'customerShippingAddress',
559 559 getDefaultString(option.province) +
560   - getDefaultString(option.city) +
561   - getDefaultString(option.district) +
562   - getDefaultString(option.detail),
  560 + getDefaultString(option.city) +
  561 + getDefaultString(option.district) +
  562 + getDefaultString(option.detail),
563 563 );
564 564 form.setFieldValue('customerNameString', option.realName);
565 565  
... ... @@ -642,11 +642,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
642 642  
643 643 message.error(
644 644 '用户余额不足,当前预减的金额为:' +
645   - data.subPrice +
646   - ',当前账号余额为:' +
647   - data.nowMoney +
648   - ',当前账号可赊账额度为:' +
649   - data.creditLimit,
  645 + data.subPrice +
  646 + ',当前账号余额为:' +
  647 + data.nowMoney +
  648 + ',当前账号可赊账额度为:' +
  649 + data.creditLimit,
650 650 );
651 651 return false;
652 652 }
... ... @@ -1111,7 +1111,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1111 1111 },
1112 1112 }}
1113 1113 debounceTime={1000}
1114   - request={async (value, { }) => {
  1114 + request={async (value, {}) => {
1115 1115 const keywords = value.keyWords;
1116 1116 if (keywords === '') {
1117 1117 return [];
... ... @@ -1867,7 +1867,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1867 1867 placeholder="请输入商品参数"
1868 1868 disabled={
1869 1869 productParametersDisabledFlagList[listMeta.index] !==
1870   - false || optType('after-sales-check')
  1870 + false || optType('after-sales-check')
1871 1871 }
1872 1872 />,
1873 1873 <ProFormDigit
... ... @@ -1920,7 +1920,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1920 1920 placeholder="请输入商品单位"
1921 1921 disabled={
1922 1922 productParametersDisabledFlagList[listMeta.index] !==
1923   - false || optType('after-sales-check')
  1923 + false || optType('after-sales-check')
1924 1924 }
1925 1925 rules={[{ required: true, message: '商品单位必填' }]}
1926 1926 />,
... ...
src/pages/Order/Order/components/UploadPayBillModal.tsx
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postServiceOrderFileProcess,
  4 + postServiceOrderUploadPaymentReceipt,
  5 +} from '@/services';
  6 +import { transImageFile } from '@/utils';
  7 +import { PlusOutlined } from '@ant-design/icons';
1 8 import { ModalForm } from '@ant-design/pro-components';
2 9 import { Form, Modal, Upload, UploadFile, UploadProps, message } from 'antd';
3 10 import { RcFile } from 'antd/lib/upload';
4 11 import { cloneDeep } from 'lodash';
5 12 import { useEffect, useRef, useState } from 'react';
6 13 import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../../constant';
7   -import { PlusOutlined } from '@ant-design/icons';
8   -import { transImageFile } from '@/utils';
9   -import { postServiceOrderFileProcess, postServiceOrderUploadPaymentReceipt } from '@/services';
10   -import { RESPONSE_CODE } from '@/constants/enum';
11 14  
12 15 // import { cloneDeep } from 'lodash';
13 16 export default ({ setVisible, subOrders, mainOrder, onClose }) => {
... ... @@ -25,7 +28,9 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
25 28 reader.onerror = (error) => reject(error);
26 29 });
27 30  
28   - const subOrderIds = subOrders?.map((item: any) => { return item.id });
  31 + const subOrderIds = subOrders?.map((item: any) => {
  32 + return item.id;
  33 + });
29 34 const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致
30 35 const handleBeforeUpload = (file: any) => {
31 36 setFileList([...fileList, file]);
... ... @@ -80,6 +85,7 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
80 85  
81 86 if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) {
82 87 message.info('发货照片数量不能超过3');
  88 + console.log(mainOrder);
83 89 return;
84 90 }
85 91 fileListObj.current = filteredArray;
... ... @@ -105,8 +111,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
105 111 setPreviewOpen(true);
106 112 setPreviewTitle(
107 113 file.name ||
108   - file.originFileObj?.name ||
109   - file.url!.substring(file.url!.lastIndexOf('/') + 1),
  114 + file.originFileObj?.name ||
  115 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
110 116 );
111 117 };
112 118 const props: UploadProps = {
... ... @@ -128,7 +134,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
128 134 };
129 135  
130 136 useEffect(() => {
131   -
132 137 document.addEventListener('paste', onPaste);
133 138 return () => {
134 139 document.removeEventListener('paste', onPaste);
... ... @@ -211,14 +216,9 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
211 216 }}
212 217 onOpenChange={setVisible}
213 218 >
214   -
215   - <div className="pb-4 text-xs decoration-gray-50">
216   - 可复制照片粘贴
217   - </div>
  219 + <div className="pb-4 text-xs decoration-gray-50">可复制照片粘贴</div>
218 220 <Upload {...props}>
219   - {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER
220   - ? uploadButton
221   - : ''}
  221 + {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER ? uploadButton : ''}
222 222 </Upload>
223 223 </ModalForm>
224 224  
... ...
src/pages/Order/Order/index.css
1 1 .order-page-container .ant-table .ant-table-middle {
2 2 margin-inline: 0 !important;
3 3 }
  4 +
4 5 .order-page-container td {
5   - font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', 'WenQuanYi Micro Hei', sans-serif;
  6 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  7 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  8 + 'WenQuanYi Micro Hei', sans-serif;
6 9 font-size: 13px;
7 10 }
  11 +
8 12 #total-payment .ant-input-number-group-addon {
9 13 padding: 0 !important;
10 14 }
  15 +
11 16 .order-page-container table:hover,
12 17 .order-page-container tr:hover,
13 18 .order-page-container thead:hover {
14 19 background: none !important;
15 20 }
  21 +
16 22 #main-table .ant-table-tbody > tr.ant-table-row:hover > td {
17 23 background: none !important;
18 24 }
  25 +
19 26 .order-page-container .ant-pro-card {
20 27 background-color: transparent;
21 28 }
  29 +
22 30 #main-table .ant-table-tbody .ant-table-cell {
23 31 padding: 10px 0 0;
24 32 }
  33 +
25 34 .order-page-container .ant-pagination {
26 35 background-color: #fff !important;
27 36 padding: 10px;
28 37 border-radius: 8px;
29 38 }
  39 +
30 40 .order-page-container .ant-pro-table .ant-form {
31 41 background-color: #fff;
32 42 border-radius: 8px;
33 43 }
  44 +
34 45 #main-table .ant-table-tbody {
35 46 background-color: #f5f5f5;
36 47 }
  48 +
37 49 .order-page-container .ant-pro-card-body {
38 50 padding: 0 !important;
39 51 }
  52 +
40 53 .order-page-container .ant-table-thead .ant-table-cell {
41 54 background-color: #fff !important;
42 55 border-radius: 8px !important;
43 56 }
  57 +
44 58 #sub-table tbody td {
45 59 padding: 10px 0 !important;
46 60 }
  61 +
47 62 #sub-table tbody tr:first-child td:first-child {
48 63 border-top-left-radius: 8px;
49 64 }
  65 +
50 66 #sub-table tbody tr:first-child td:nth-child(2) {
51 67 border-top-right-radius: 8px;
52 68 }
  69 +
53 70 #sub-table tbody tr:last-child td:first-child {
54 71 border-bottom-left-radius: 8px;
55 72 }
  73 +
56 74 #sub-table tbody tr:last-child td:nth-child(2) {
57 75 border-bottom-right-radius: 8px;
58 76 }
  77 +
59 78 #sub-table tbody tr td:first-child {
60 79 border-top: 1px solid #d7d6d6;
  80 +
61 81 /* 设置行与行之间分割线的颜色 */
62 82 border-bottom: 1px solid #d7d6d6;
  83 +
63 84 /* 设置行与行之间分割线的颜色 */
64 85 border-left: 1px solid #d7d6d6;
  86 +
65 87 /* 设置行与行之间分割线的颜色 */
66 88 }
  89 +
67 90 #sub-table tbody tr td:nth-child(2) {
68 91 border-top: 1px solid #d7d6d6;
  92 +
69 93 /* 设置行与行之间分割线的颜色 */
70 94 border-bottom: 1px solid #d7d6d6;
  95 +
71 96 /* 设置行与行之间分割线的颜色 */
72 97 border-right: 1px solid #d7d6d6;
  98 +
73 99 /* 设置行与行之间分割线的颜色 */
74 100 }
... ...
src/pages/Order/Order/index.tsx
... ... @@ -111,6 +111,7 @@ import CheckModal from &#39;./components/CheckModal&#39;;
111 111 import ConfirmReceiptModal from './components/ConfirmReceiptModal';
112 112 import DeliverInfoDrawer from './components/DeliverInfoDrawer';
113 113 import DeliverModal from './components/DeliverModal';
  114 +import FeedbackRegistrationModal from './components/FeedbackRegistrationModal';
114 115 import FinancialDrawer from './components/FinancialDrawer';
115 116 import FinancialEditDrawer from './components/FinancialEditDrawer';
116 117 import FinancialMergeDrawer from './components/FinancialMergeDrawer';
... ... @@ -146,6 +147,10 @@ const OrderPage = () =&gt; {
146 147 useState<boolean>(false);
147 148 const [uploadPayBillModalVisible, setUploadPayBillModalVisible] =
148 149 useState<boolean>(false);
  150 + const [
  151 + feedbackRegistrationModalVisible,
  152 + setFeedbackRegistrationModalVisible,
  153 + ] = useState<boolean>(false);
149 154 const [modifiedDiffModalVisible, setModifiedDiffModalVisible] =
150 155 useState<boolean>(false);
151 156 const [financialReceiptsModalVisible, setFinancialReceiptsModalVisible] =
... ... @@ -690,7 +695,7 @@ const OrderPage = () =&gt; {
690 695 * @param optRecord
691 696 */
692 697 function getOrderStatusTag(optRecord: any): import('react').ReactNode {
693   - console.log(optRecord);
  698 + console.log(optRecord, '5656optRecord');
694 699  
695 700 const orderStatus = optRecord.orderStatus;
696 701 const paymentMethod = optRecord.paymentMethod;
... ... @@ -2095,6 +2100,20 @@ const OrderPage = () =&gt; {
2095 2100 ) : (
2096 2101 ''
2097 2102 )}
  2103 + {optRecord.paths?.includes('feedbackRegistration') ? (
  2104 + <Button
  2105 + className="p-0"
  2106 + type="link"
  2107 + onClick={() => {
  2108 + createOptObject(optRecord.id, record.id);
  2109 + setFeedbackRegistrationModalVisible(true);
  2110 + }}
  2111 + >
  2112 + 回访登记
  2113 + </Button>
  2114 + ) : (
  2115 + ''
  2116 + )}
2098 2117  
2099 2118 {optRecord.paths?.includes('confirmInvoice') ? (
2100 2119 <ButtonConfirm
... ... @@ -2316,6 +2335,31 @@ const OrderPage = () =&gt; {
2316 2335 ) : (
2317 2336 ''
2318 2337 )}
  2338 +
  2339 + {isAdmin() || isSales() ? (
  2340 + <Flex title={optRecord.notes} className="pt-2">
  2341 + <div className="flex items-center">
  2342 + <div className="flex items-center max-w-[500px]">
  2343 + <div className="max-w-md overflow-hidden whitespace-no-wrap overflow-ellipsis">
  2344 + <Tooltip
  2345 + title={optRecord.feedbackRegistrationContent}
  2346 + placement="topLeft"
  2347 + >
  2348 + <span className="text-[#8C8C8C] mr-3">
  2349 + 产品回访登记:
  2350 + {optRecord.feedbackRegistrationContent === undefined ||
  2351 + optRecord.feedbackRegistrationContent === null
  2352 + ? '暂无'
  2353 + : optRecord.feedbackRegistrationContent}
  2354 + </span>
  2355 + </Tooltip>
  2356 + </div>
  2357 + </div>
  2358 + </div>
  2359 + </Flex>
  2360 + ) : (
  2361 + ''
  2362 + )}
2319 2363 </>
2320 2364 );
2321 2365 };
... ... @@ -5285,6 +5329,24 @@ const OrderPage = () =&gt; {
5285 5329 }}
5286 5330 />
5287 5331 )}
  5332 + {feedbackRegistrationModalVisible && (
  5333 + <FeedbackRegistrationModal
  5334 + setVisible={(val: boolean) => {
  5335 + setFeedbackRegistrationModalVisible(val);
  5336 + if (!val) {
  5337 + clearOptObject();
  5338 + }
  5339 + }}
  5340 + subOrders={buildSubOrders()}
  5341 + mainOrder={buildMainOrder()}
  5342 + onClose={() => {
  5343 + setFeedbackRegistrationModalVisible(false);
  5344 + clearOptObject();
  5345 + refreshTable();
  5346 + }}
  5347 + />
  5348 + )}
  5349 +
5288 5350 {invoicingDrawerFormVisible && (
5289 5351 <InvoicingDrawerForm
5290 5352 dataList={
... ...
src/pages/Order/OrderWarning/components/CheckModal.tsx
... ... @@ -235,8 +235,8 @@ export default ({
235 235 setPreviewOpen(true);
236 236 setPreviewTitle(
237 237 file.name ||
238   - file.originFileObj?.name ||
239   - file.url!.substring(file.url!.lastIndexOf('/') + 1),
  238 + file.originFileObj?.name ||
  239 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
240 240 );
241 241 };
242 242  
... ...
src/pages/Order/OrderWarning/components/ConfirmReceiptModal.tsx
... ... @@ -107,8 +107,8 @@ export default ({ data, onClose }) =&gt; {
107 107 setPreviewOpen(true);
108 108 setPreviewTitle(
109 109 file.name ||
110   - file.originFileObj?.name ||
111   - file.url!.substring(file.url!.lastIndexOf('/') + 1),
  110 + file.originFileObj?.name ||
  111 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
112 112 );
113 113 };
114 114  
... ...
src/pages/Order/OrderWarning/components/DeliverModal.tsx
... ... @@ -260,7 +260,7 @@ const DeliverModal = ({
260 260 serialNumber: item.serialNumber,
261 261 packageNumber:
262 262 item.packageNumber === null ||
263   - item.packageNumber === undefined
  263 + item.packageNumber === undefined
264 264 ? 1
265 265 : item.packageNumber,
266 266 logisticsNotes: item.logisticsNotes,
... ...
src/pages/Order/OrderWarning/components/FeedbackRegistrationModal.tsx 0 → 100644
  1 +import { postServiceOrderFeedbackRegistration } from '@/services/request';
  2 +import { Input, Modal } from 'antd';
  3 +import { useState } from 'react';
  4 +
  5 +// import { cloneDeep } from 'lodash';
  6 +export default ({ subOrders, onClose }) => {
  7 + const [isModalOpen] = useState(true);
  8 + const { TextArea } = Input;
  9 + const [textValue, setTextValue] = useState('');
  10 +
  11 + const handleOk = async () => {
  12 + console.log(textValue); // 处理输入的文本
  13 + console.log(subOrders, '5656subOrders');
  14 + let res = await postServiceOrderFeedbackRegistration({
  15 + data: {
  16 + id: subOrders[0].id,
  17 + feedbackRegistrationContent: textValue,
  18 + },
  19 + });
  20 + console.log(res, '5656res');
  21 + onClose();
  22 + // setIsModalOpen(false);
  23 + // onClose();
  24 + };
  25 + const handleCancel = () => {
  26 + onClose();
  27 + // setIsModalOpen(false);
  28 + // onClose();
  29 + };
  30 + const handleChange = (e) => {
  31 + setTextValue(e.target.value);
  32 + };
  33 + return (
  34 + <>
  35 + {/* <ModalForm<{
  36 + filePaths: any;
  37 + }>
  38 + width={500}
  39 + open
  40 + title="回访登记"
  41 + form={form}
  42 + autoFocusFirstInput
  43 + modalProps={{
  44 + okText: '提交',
  45 + cancelText: '取消',
  46 + destroyOnClose: true,
  47 + onCancel: () => {
  48 + setVisible(false);
  49 + },
  50 + }}
  51 + onFinish={async () => {
  52 + onClose();
  53 + }}
  54 + onOpenChange={setVisible}
  55 + >
  56 + <TextArea rows={6} placeholder="请输入" />
  57 + </ModalForm> */}
  58 + <Modal
  59 + title="回访登记"
  60 + open={isModalOpen}
  61 + onOk={handleOk}
  62 + onCancel={handleCancel}
  63 + >
  64 + <TextArea
  65 + rows={6}
  66 + placeholder="请输入"
  67 + onChange={handleChange}
  68 + value={textValue}
  69 + />
  70 + </Modal>
  71 + </>
  72 + );
  73 +};
... ...
src/pages/Order/OrderWarning/components/FinancialDrawer.tsx
... ... @@ -144,107 +144,107 @@ export default ({
144 144  
145 145 {invoicingStatus !== 'UN_INVOICE'
146 146 ? [
147   - <ProFormDatePicker
148   - key="invoicingTime"
149   - width="lg"
150   - name="invoicingTime"
151   - label="开票时间"
152   - disabled={isEdit}
153   - rules={[
154   - { required: !isEdit ? true : false, message: '这是必填项' },
155   - ]}
156   - initialValue={subOrders[0]?.invoicingTime}
157   - />,
158   - <ProFormText
159   - key="purchaser"
160   - width="lg"
161   - name="purchaser"
162   - label="抬头名称"
163   - disabled={isEdit}
164   - rules={[
165   - { required: !isEdit ? true : false, message: '这是必填项' },
166   - ]}
167   - initialValue={subOrders[0]?.purchaser}
168   - />,
169   - <ProFormDatePicker
170   - key="financialReceiptIssuanceTime"
171   - width="lg"
172   - name="financialReceiptIssuanceTime"
173   - label="开收据时间"
174   - initialValue={subOrders[0]?.financialReceiptIssuanceTime}
175   - />,
176   - <ProFormDatePicker
177   - key="collectMoneyTime"
178   - width="lg"
179   - name="collectMoneyTime"
180   - label="收款时间"
181   - initialValue={subOrders[0]?.collectMoneyTime}
182   - />,
183   - <ProFormText
184   - width="lg"
185   - key="invoiceNumber"
186   - name="invoiceNumber"
187   - label="发票号码"
188   - initialValue={subOrders[0]?.invoiceNumber}
189   - rules={[{ required: true, message: '发票号码必填' }]}
190   - />,
191   - <div
192   - key="salesChooseReceivingCompany"
193   - hidden={subOrders[0].receivingCompany === null}
194   - >
195   - <span className={'pl-2 text-xs text-gray-400'}>
196   - 销售申请开票时选择了:
197   - {enumValueToLabel(
198   - subOrders[0].receivingCompany,
199   - getReceivingCompanyOptions(PAYEE_OPTIONS),
200   - )}
201   - </span>
202   - <span
203   - hidden={subOrders[0].receivingCompany === 'ANY'}
204   - className={
205   - 'pl-2 text-xs text-[#1677ff] cursor-pointer hover:text-[#64abf7]'
206   - }
207   - onClick={() => {
208   - chooseReceivingCompany(subOrders[0].receivingCompany);
209   - }}
  147 + <ProFormDatePicker
  148 + key="invoicingTime"
  149 + width="lg"
  150 + name="invoicingTime"
  151 + label="开票时间"
  152 + disabled={isEdit}
  153 + rules={[
  154 + { required: !isEdit ? true : false, message: '这是必填项' },
  155 + ]}
  156 + initialValue={subOrders[0]?.invoicingTime}
  157 + />,
  158 + <ProFormText
  159 + key="purchaser"
  160 + width="lg"
  161 + name="purchaser"
  162 + label="抬头名称"
  163 + disabled={isEdit}
  164 + rules={[
  165 + { required: !isEdit ? true : false, message: '这是必填项' },
  166 + ]}
  167 + initialValue={subOrders[0]?.purchaser}
  168 + />,
  169 + <ProFormDatePicker
  170 + key="financialReceiptIssuanceTime"
  171 + width="lg"
  172 + name="financialReceiptIssuanceTime"
  173 + label="开收据时间"
  174 + initialValue={subOrders[0]?.financialReceiptIssuanceTime}
  175 + />,
  176 + <ProFormDatePicker
  177 + key="collectMoneyTime"
  178 + width="lg"
  179 + name="collectMoneyTime"
  180 + label="收款时间"
  181 + initialValue={subOrders[0]?.collectMoneyTime}
  182 + />,
  183 + <ProFormText
  184 + width="lg"
  185 + key="invoiceNumber"
  186 + name="invoiceNumber"
  187 + label="发票号码"
  188 + initialValue={subOrders[0]?.invoiceNumber}
  189 + rules={[{ required: true, message: '发票号码必填' }]}
  190 + />,
  191 + <div
  192 + key="salesChooseReceivingCompany"
  193 + hidden={subOrders[0].receivingCompany === null}
210 194 >
211   - 选择
212   - </span>
213   - </div>,
214   - <ProFormSelect
215   - key="payee"
216   - placeholder="选择收款单位"
217   - name="payee"
218   - width="lg"
219   - showSearch
220   - label="收款单位"
221   - options={enumToSelect(PAYEE_OPTIONS)}
222   - initialValue={subOrders[0]?.payee}
223   - rules={[{ required: true, message: '收款单位必填' }]}
224   - />,
225   -
226   - <div id="total-payment" key="money">
227   - <ProFormDigit
228   - key="money"
229   - name="money"
  195 + <span className={'pl-2 text-xs text-gray-400'}>
  196 + 销售申请开票时选择了:
  197 + {enumValueToLabel(
  198 + subOrders[0].receivingCompany,
  199 + getReceivingCompanyOptions(PAYEE_OPTIONS),
  200 + )}
  201 + </span>
  202 + <span
  203 + hidden={subOrders[0].receivingCompany === 'ANY'}
  204 + className={
  205 + 'pl-2 text-xs text-[#1677ff] cursor-pointer hover:text-[#64abf7]'
  206 + }
  207 + onClick={() => {
  208 + chooseReceivingCompany(subOrders[0].receivingCompany);
  209 + }}
  210 + >
  211 + 选择
  212 + </span>
  213 + </div>,
  214 + <ProFormSelect
  215 + key="payee"
  216 + placeholder="选择收款单位"
  217 + name="payee"
230 218 width="lg"
231   - label="金额"
232   - rules={[{ required: true, message: '金额必填' }]}
233   - tooltip="点击计算,合计所有子订单对应主订单总额"
234   - fieldProps={{
235   - addonAfter: (
236   - <Button
237   - className="rounded-l-none"
238   - type="primary"
239   - onClick={computeTotalPayment}
240   - >
241   - 计算
242   - </Button>
243   - ),
244   - }}
245   - />
246   - </div>,
247   - ]
  219 + showSearch
  220 + label="收款单位"
  221 + options={enumToSelect(PAYEE_OPTIONS)}
  222 + initialValue={subOrders[0]?.payee}
  223 + rules={[{ required: true, message: '收款单位必填' }]}
  224 + />,
  225 +
  226 + <div id="total-payment" key="money">
  227 + <ProFormDigit
  228 + key="money"
  229 + name="money"
  230 + width="lg"
  231 + label="金额"
  232 + rules={[{ required: true, message: '金额必填' }]}
  233 + tooltip="点击计算,合计所有子订单对应主订单总额"
  234 + fieldProps={{
  235 + addonAfter: (
  236 + <Button
  237 + className="rounded-l-none"
  238 + type="primary"
  239 + onClick={computeTotalPayment}
  240 + >
  241 + 计算
  242 + </Button>
  243 + ),
  244 + }}
  245 + />
  246 + </div>,
  247 + ]
248 248 : ''}
249 249  
250 250 <ProFormSelect
... ...
src/pages/Order/OrderWarning/components/FinancialEditDrawer.tsx
... ... @@ -130,24 +130,24 @@ export default ({ mainOrder, subOrders, setVisible, isMainOrder, onClose }) =&gt; {
130 130 width="lg"
131 131 name="financialReceiptIssuanceTime"
132 132 label="开收据时间"
133   - // rules={[
134   - // {
135   - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
136   - // message: '开收据时间必填',
137   - // },
138   - // ]}
  133 + // rules={[
  134 + // {
  135 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  136 + // message: '开收据时间必填',
  137 + // },
  138 + // ]}
139 139 />
140 140 <ProFormDatePicker
141 141 key="collectMoneyTime"
142 142 width="lg"
143 143 name="collectMoneyTime"
144 144 label="收款时间"
145   - // rules={[
146   - // {
147   - // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
148   - // message: '收款时间必填',
149   - // },
150   - // ]}
  145 + // rules={[
  146 + // {
  147 + // required: !isMainOrder && invoicingStatus === 'UN_INVOICE',
  148 + // message: '收款时间必填',
  149 + // },
  150 + // ]}
151 151 />
152 152 </DrawerForm>
153 153 );
... ...
src/pages/Order/OrderWarning/components/ImagesViewerModal.tsx
... ... @@ -3,7 +3,7 @@ import { Button, Divider, Image, Modal } from &#39;antd&#39;;
3 3 import { useEffect, useState } from 'react';
4 4 export default ({ setVisible, optType, onClose, orderRow }) => {
5 5 const [images, setImages] = useState<any[]>([]);
6   - const [title, setTitle] = useState("收货凭证");
  6 + const [title, setTitle] = useState('收货凭证');
7 7 const handleOk = () => {
8 8 onClose();
9 9 setVisible(false);
... ... @@ -23,7 +23,7 @@ export default ({ setVisible, optType, onClose, orderRow }) =&gt; {
23 23 }
24 24 useEffect(() => {
25 25 if (optType === 'shippingReceipt') {
26   - setTitle("收货凭证");
  26 + setTitle('收货凭证');
27 27 getImages();
28 28 } else if (optType === 'paymentReceipt') {
29 29 let paymentReceiptsImagesList: any[] = [];
... ... @@ -34,7 +34,6 @@ export default ({ setVisible, optType, onClose, orderRow }) =&gt; {
34 34 paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)];
35 35 setImages(paymentReceiptsImagesList);
36 36 }
37   -
38 37 }, []);
39 38  
40 39 return (
... ...
src/pages/Order/OrderWarning/components/ModifiedDiffModal.tsx
... ... @@ -106,7 +106,7 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
106 106 onClick={() => {
107 107 window.open(
108 108 '/previewApi/onlinePreview?url=' +
109   - encodeURIComponent(Base64.encode(item)),
  109 + encodeURIComponent(Base64.encode(item)),
110 110 );
111 111 }}
112 112 >
... ...
src/pages/Order/OrderWarning/components/OrderDrawer.tsx
... ... @@ -556,9 +556,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
556 556 form.setFieldValue(
557 557 'customerShippingAddress',
558 558 getDefaultString(option.province) +
559   - getDefaultString(option.city) +
560   - getDefaultString(option.district) +
561   - getDefaultString(option.detail),
  559 + getDefaultString(option.city) +
  560 + getDefaultString(option.district) +
  561 + getDefaultString(option.detail),
562 562 );
563 563 form.setFieldValue('customerNameString', option.realName);
564 564  
... ... @@ -641,11 +641,11 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
641 641  
642 642 message.error(
643 643 '用户余额不足,当前预减的金额为:' +
644   - data.subPrice +
645   - ',当前账号余额为:' +
646   - data.nowMoney +
647   - ',当前账号可赊账额度为:' +
648   - data.creditLimit,
  644 + data.subPrice +
  645 + ',当前账号余额为:' +
  646 + data.nowMoney +
  647 + ',当前账号可赊账额度为:' +
  648 + data.creditLimit,
649 649 );
650 650 return false;
651 651 }
... ... @@ -1110,7 +1110,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1110 1110 },
1111 1111 }}
1112 1112 debounceTime={1000}
1113   - request={async (value, { }) => {
  1113 + request={async (value, {}) => {
1114 1114 const keywords = value.keyWords;
1115 1115 if (keywords === '') {
1116 1116 return [];
... ... @@ -1865,7 +1865,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1865 1865 placeholder="请输入商品参数"
1866 1866 disabled={
1867 1867 productParametersDisabledFlagList[listMeta.index] !==
1868   - false || optType('after-sales-check')
  1868 + false || optType('after-sales-check')
1869 1869 }
1870 1870 />,
1871 1871 <ProFormDigit
... ... @@ -1918,7 +1918,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1918 1918 placeholder="请输入商品单位"
1919 1919 disabled={
1920 1920 productParametersDisabledFlagList[listMeta.index] !==
1921   - false || optType('after-sales-check')
  1921 + false || optType('after-sales-check')
1922 1922 }
1923 1923 rules={[{ required: true, message: '商品单位必填' }]}
1924 1924 />,
... ...
src/pages/Order/OrderWarning/components/UploadPayBillModal.tsx
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postServiceOrderFileProcess,
  4 + postServiceOrderUploadPaymentReceipt,
  5 +} from '@/services';
  6 +import { transImageFile } from '@/utils';
  7 +import { PlusOutlined } from '@ant-design/icons';
1 8 import { ModalForm } from '@ant-design/pro-components';
2 9 import { Form, Modal, Upload, UploadFile, UploadProps, message } from 'antd';
3 10 import { RcFile } from 'antd/lib/upload';
4 11 import { cloneDeep } from 'lodash';
5 12 import { useEffect, useRef, useState } from 'react';
6 13 import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../../constant';
7   -import { PlusOutlined } from '@ant-design/icons';
8   -import { transImageFile } from '@/utils';
9   -import { postServiceOrderFileProcess, postServiceOrderUploadPaymentReceipt } from '@/services';
10   -import { RESPONSE_CODE } from '@/constants/enum';
11 14  
12 15 // import { cloneDeep } from 'lodash';
13 16 export default ({ setVisible, subOrders, mainOrder, onClose }) => {
... ... @@ -25,7 +28,9 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
25 28 reader.onerror = (error) => reject(error);
26 29 });
27 30  
28   - const subOrderIds = subOrders?.map((item: any) => { return item.id });
  31 + const subOrderIds = subOrders?.map((item: any) => {
  32 + return item.id;
  33 + });
29 34 const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致
30 35 const handleBeforeUpload = (file: any) => {
31 36 setFileList([...fileList, file]);
... ... @@ -105,8 +110,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
105 110 setPreviewOpen(true);
106 111 setPreviewTitle(
107 112 file.name ||
108   - file.originFileObj?.name ||
109   - file.url!.substring(file.url!.lastIndexOf('/') + 1),
  113 + file.originFileObj?.name ||
  114 + file.url!.substring(file.url!.lastIndexOf('/') + 1),
110 115 );
111 116 };
112 117 const props: UploadProps = {
... ... @@ -128,7 +133,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
128 133 };
129 134  
130 135 useEffect(() => {
131   -
132 136 document.addEventListener('paste', onPaste);
133 137 return () => {
134 138 document.removeEventListener('paste', onPaste);
... ... @@ -206,19 +210,15 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
206 210 }
207 211 } else {
208 212 message.success('上传失败');
  213 + console.log(mainOrder);
209 214 }
210 215 onClose();
211 216 }}
212 217 onOpenChange={setVisible}
213 218 >
214   -
215   - <div className="pb-4 text-xs decoration-gray-50">
216   - 可复制照片粘贴
217   - </div>
  219 + <div className="pb-4 text-xs decoration-gray-50">可复制照片粘贴</div>
218 220 <Upload {...props}>
219   - {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER
220   - ? uploadButton
221   - : ''}
  221 + {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER ? uploadButton : ''}
222 222 </Upload>
223 223 </ModalForm>
224 224  
... ...
src/pages/Order/OrderWarning/index.tsx
... ... @@ -103,6 +103,7 @@ import CheckModal from &#39;./components/CheckModal&#39;;
103 103 import ConfirmReceiptModal from './components/ConfirmReceiptModal';
104 104 import DeliverInfoDrawer from './components/DeliverInfoDrawer';
105 105 import DeliverModal from './components/DeliverModal';
  106 +import FeedbackRegistrationModal from './components/FeedbackRegistrationModal';
106 107 import FinancialDrawer from './components/FinancialDrawer';
107 108 import FinancialEditDrawer from './components/FinancialEditDrawer';
108 109 import FinancialMergeDrawer from './components/FinancialMergeDrawer';
... ... @@ -136,6 +137,10 @@ const OrderPage = () =&gt; {
136 137 useState<boolean>(false);
137 138 const [uploadPayBillModalVisible, setUploadPayBillModalVisible] =
138 139 useState<boolean>(false);
  140 + const [
  141 + feedbackRegistrationModalVisible,
  142 + setFeedbackRegistrationModalVisible,
  143 + ] = useState<boolean>(false);
139 144 const [modifiedDiffModalVisible, setModifiedDiffModalVisible] =
140 145 useState<boolean>(false);
141 146 const [financialReceiptsModalVisible, setFinancialReceiptsModalVisible] =
... ... @@ -2255,6 +2260,30 @@ const OrderPage = () =&gt; {
2255 2260 ) : (
2256 2261 ''
2257 2262 )}
  2263 + {isAdmin() || isSales() ? (
  2264 + <Flex title={optRecord.notes} className="pt-2">
  2265 + <div className="flex items-center">
  2266 + <div className="flex items-center max-w-[500px]">
  2267 + <div className="max-w-md overflow-hidden whitespace-no-wrap overflow-ellipsis">
  2268 + <Tooltip
  2269 + title={optRecord.feedbackRegistrationContent}
  2270 + placement="topLeft"
  2271 + >
  2272 + <span className="text-[#8C8C8C] mr-3">
  2273 + 产品回访登记:
  2274 + {optRecord.feedbackRegistrationContent === undefined ||
  2275 + optRecord.feedbackRegistrationContent === null
  2276 + ? '暂无'
  2277 + : optRecord.feedbackRegistrationContent}
  2278 + </span>
  2279 + </Tooltip>
  2280 + </div>
  2281 + </div>
  2282 + </div>
  2283 + </Flex>
  2284 + ) : (
  2285 + ''
  2286 + )}
2258 2287 </>
2259 2288 );
2260 2289 };
... ... @@ -4980,6 +5009,23 @@ const OrderPage = () =&gt; {
4980 5009 }}
4981 5010 />
4982 5011 )}
  5012 + {feedbackRegistrationModalVisible && (
  5013 + <FeedbackRegistrationModal
  5014 + setVisible={(val: boolean) => {
  5015 + setFeedbackRegistrationModalVisible(val);
  5016 + if (!val) {
  5017 + clearOptObject();
  5018 + }
  5019 + }}
  5020 + subOrders={buildSubOrders()}
  5021 + mainOrder={buildMainOrder()}
  5022 + onClose={() => {
  5023 + setFeedbackRegistrationModalVisible(false);
  5024 + clearOptObject();
  5025 + refreshTable();
  5026 + }}
  5027 + />
  5028 + )}
4983 5029 {invoicingDrawerFormVisible && (
4984 5030 <InvoicingDrawerForm
4985 5031 dataList={
... ... @@ -5552,6 +5598,23 @@ const OrderPage = () =&gt; {
5552 5598 }}
5553 5599 />
5554 5600 )}
  5601 + {feedbackRegistrationModalVisible && (
  5602 + <FeedbackRegistrationModal
  5603 + setVisible={(val: boolean) => {
  5604 + setFeedbackRegistrationModalVisible(val);
  5605 + if (!val) {
  5606 + clearOptObject();
  5607 + }
  5608 + }}
  5609 + subOrders={buildSubOrders()}
  5610 + mainOrder={buildMainOrder()}
  5611 + onClose={() => {
  5612 + setFeedbackRegistrationModalVisible(false);
  5613 + clearOptObject();
  5614 + refreshTable2();
  5615 + }}
  5616 + />
  5617 + )}
5555 5618 {invoicingDrawerFormVisible && (
5556 5619 <InvoicingDrawerForm
5557 5620 dataList={
... ...
src/pages/Order/WarningWhitelist/index.css deleted 100644 → 0
src/pages/Order/WarningWhitelist/index.less deleted 100644 → 0
src/pages/Order/WarningWhitelist/index.tsx
1   -import {
2   - ActionType,
3   - ModalForm,
4   - ProColumns,
5   - ProFormText,
6   - ProTable,
7   -} from '@ant-design/pro-components';
8   -import {
9   - Button,
10   - Checkbox,
11   - Divider,
12   - Dropdown,
13   - Flex,
14   - FloatButton,
15   - Image,
16   - MenuProps,
17   - Modal,
18   - Popconfirm,
19   - Radio,
20   - Space,
21   - Spin,
22   - Tag,
23   - Tooltip,
24   - message,
25   - Tabs,
26   -} from 'antd';
27 1 import ButtonConfirm from '@/components/ButtomConfirm';
28 2 import { RESPONSE_CODE } from '@/constants/enum';
29 3 import {
30   - postOldInvoicingWhiteListBatchAdd,
31   - postOldInvoicingWhiteListPage,
32   - postOldInvoicingWhiteListRemove,
33   - postServiceOrderWarningUserWhiteLists,
  4 + postServiceOrderAddWarningOrderWhiteList,
34 5 postServiceOrderAddWarningUserWhiteList,
  6 + postServiceOrderDeleteWarningOrderWhiteList,
35 7 postServiceOrderDeleteWarningUserWhiteList,
36 8 postServiceOrderWarningOrderWhiteLists,
37   - postServiceOrderAddWarningOrderWhiteList,
38   - postServiceOrderDeleteWarningOrderWhiteList,
  9 + postServiceOrderWarningUserWhiteLists,
39 10 } from '@/services';
40 11 import { PlusOutlined } from '@ant-design/icons';
  12 +import {
  13 + ActionType,
  14 + ModalForm,
  15 + ProColumns,
  16 + ProFormText,
  17 + ProTable,
  18 +} from '@ant-design/pro-components';
  19 +import { Button, Tabs, message } from 'antd';
41 20 import { useRef } from 'react';
42 21 export const waitTimePromise = async (time: number = 100) => {
43 22 return new Promise((resolve) => {
... ... @@ -134,9 +113,9 @@ const WarningWhitelist = () =&gt; {
134 113 search: {
135 114 transform: (value) => {
136 115 if (value) {
137   - console.log(value, '5656valueid')
  116 + console.log(value, '5656valueid');
138 117 return {
139   - orderId: Number(value)
  118 + orderId: Number(value),
140 119 };
141 120 }
142 121 },
... ... @@ -186,7 +165,7 @@ const WarningWhitelist = () =&gt; {
186 165 title={'确认删除此项吗?'}
187 166 text="删除"
188 167 onConfirm={async () => {
189   - console.log(record.orderId, '5656idoreder')
  168 + console.log(record.orderId, '5656idoreder');
190 169 await postServiceOrderDeleteWarningOrderWhiteList({
191 170 query: {
192 171 orderId: record.orderId,
... ... @@ -213,7 +192,7 @@ const WarningWhitelist = () =&gt; {
213 192 const res = await postServiceOrderWarningUserWhiteLists({
214 193 data: { ...params },
215 194 });
216   - console.log(res.data, '5656res.data')
  195 + console.log(res.data, '5656res.data');
217 196 return res.data;
218 197 }}
219 198 rowKey="id"
... ... @@ -281,7 +260,7 @@ const WarningWhitelist = () =&gt; {
281 260 ]}
282 261 />
283 262 </div>
284   - )
  263 + ),
285 264 },
286 265 {
287 266 key: 2,
... ... @@ -334,7 +313,7 @@ const WarningWhitelist = () =&gt; {
334 313 console.log(values, '5656values');
335 314 const res = await postServiceOrderAddWarningOrderWhiteList({
336 315 data: {
337   - orderId: values.orderIdsText
  316 + orderId: values.orderIdsText,
338 317 },
339 318 });
340 319 if (res.result === RESPONSE_CODE.SUCCESS) {
... ... @@ -361,9 +340,9 @@ const WarningWhitelist = () =&gt; {
361 340 ]}
362 341 />
363 342 </div>
364   - )
365   - }
366   - ]
  343 + ),
  344 + },
  345 + ];
367 346 return (
368 347 <div>
369 348 <Tabs
... ... @@ -374,6 +353,6 @@ const WarningWhitelist = () =&gt; {
374 353 }}
375 354 />
376 355 </div>
377   - )
378   -}
379   -export default WarningWhitelist
  356 + );
  357 +};
  358 +export default WarningWhitelist;
... ...
src/pages/OrderReport/components/OrderStatisticCard.tsx
... ... @@ -310,59 +310,44 @@ export default ({ data, statisticsMethod, reFreshData }) =&gt; {
310 310 <ProCard
311 311 className="order-statictis-card"
312 312 bordered
313   - title={<CardTitle title='待开票订单' />}
  313 + title={<CardTitle title="待开票订单" />}
314 314 >
315   - <CardContent
316   - content={data?.waitInvoicingCount}
317   - />
  315 + <CardContent content={data?.waitInvoicingCount} />
318 316 </ProCard>
319 317 <ProCard
320 318 className="order-statictis-card"
321 319 bordered
322   - title={<CardTitle title='待开票订单总金额' />}
  320 + title={<CardTitle title="待开票订单总金额" />}
323 321 >
324   - <CardContent
325   - unit="¥"
326   - content={data?.waitInvoicingPriceSum}
327   - />
  322 + <CardContent unit="¥" content={data?.waitInvoicingPriceSum} />
328 323 </ProCard>
329 324 <ProCard
330 325 className="order-statictis-card"
331 326 bordered
332   - title={<CardTitle title='已开票未回款订单' />}
  327 + title={<CardTitle title="已开票未回款订单" />}
333 328 >
334   - <CardContent
335   - content={data?.invoicedNotReiceptCount}
336   - />
  329 + <CardContent content={data?.invoicedNotReiceptCount} />
337 330 </ProCard>
338 331 <ProCard
339 332 className="order-statictis-card"
340 333 bordered
341   - title={<CardTitle title='已开票未回款订单总金额' />}
  334 + title={<CardTitle title="已开票未回款订单总金额" />}
342 335 >
343   - <CardContent
344   - unit="¥"
345   - content={data?.invoicedNotReiceptPriceSum}
346   - />
  336 + <CardContent unit="¥" content={data?.invoicedNotReiceptPriceSum} />
347 337 </ProCard>
348 338 <ProCard
349 339 className="order-statictis-card"
350 340 bordered
351   - title={<CardTitle title='已开票已回款订单' />}
  341 + title={<CardTitle title="已开票已回款订单" />}
352 342 >
353   - <CardContent
354   - content={data?.invoicedAndReiceptedCount}
355   - />
  343 + <CardContent content={data?.invoicedAndReiceptedCount} />
356 344 </ProCard>
357 345 <ProCard
358 346 className="order-statictis-card"
359 347 bordered
360   - title={<CardTitle title='已开票已回款订单总金额' />}
  348 + title={<CardTitle title="已开票已回款订单总金额" />}
361 349 >
362   - <CardContent
363   - unit="¥"
364   - content={data?.invoicedAndReiceptedPriceSum}
365   - />
  350 + <CardContent unit="¥" content={data?.invoicedAndReiceptedPriceSum} />
366 351 </ProCard>
367 352 </ProCard>
368 353  
... ...
src/pages/Prepaid/index.tsx
1 1 import ButtonConfirm from '@/components/ButtomConfirm';
2 2 import EllipsisDiv from '@/components/Div/EllipsisDiv';
3 3 import { RESPONSE_CODE } from '@/constants/enum';
4   -import { } from '@/pages/Invoice/constant';
  4 +import {} from '@/pages/Invoice/constant';
5 5 import {
6 6 postCanrdApiUserList,
7 7 postPrepaidDelete,
... ...
src/services/definition.ts
... ... @@ -94,36 +94,33 @@ export interface AdminAuthUserVO {
94 94 export interface AdminClientDto {
95 95 /**
96 96 * @description
97   - * 市
98   - */
99   - city?: string;
100   - /**
101   - * @description
102   - * 单位地址
  97 + * 客户地址
103 98 */
104   - companyAddress?: string;
  99 + address?: string;
105 100 /**
106 101 * @description
107   - * 单位地址
  102 + *
108 103 */
109   - companyAddressText?: string;
  104 + city?: string;
110 105 companyId?: string;
111 106 /**
112 107 * @description
113   - * 单位名称
  108 + * 联系人
114 109 */
115   - companyName?: string;
116 110 contacts?: string;
117   - createBy?: string;
  111 + createByName?: string;
118 112 /** @format date-time */
119 113 createTime?: string;
120 114 /**
121 115 * @description
  116 + * 详细地址
  117 + */
  118 + detailAddress?: string;
  119 + /**
  120 + * @description
122 121 * 区
123 122 */
124 123 district?: string;
125   - /** @format int32 */
126   - enableFlag?: number;
127 124 /**
128 125 * @description
129 126 * 是否已报方案
... ... @@ -144,9 +141,7 @@ export interface AdminClientDto {
144 141 * 客户等级
145 142 */
146 143 levelText?: string;
147   - modifyBy?: string;
148   - /** @format date-time */
149   - modifyTime?: string;
  144 + logicDelete?: boolean;
150 145 /**
151 146 * @description
152 147 * 名称
... ... @@ -157,6 +152,7 @@ export interface AdminClientDto {
157 152 * 备注
158 153 */
159 154 notes?: string;
  155 + paths?: Array<string>;
160 156 /**
161 157 * @description
162 158 * 电话号码
... ... @@ -180,16 +176,26 @@ export interface AdminClientDto {
180 176 referrers?: string;
181 177 /**
182 178 * @description
183   - * 需求
  179 + * 客户需求
184 180 */
185 181 requirements?: string;
186 182 /**
187 183 * @description
  184 + * 客户需求
  185 + */
  186 + requirementsText?: string;
  187 + /**
  188 + * @description
188 189 * 来源
189 190 */
190 191 source?: string;
191 192 /**
192 193 * @description
  194 + * 来源
  195 + */
  196 + sourceText?: string;
  197 + /**
  198 + * @description
193 199 * 跟进状态
194 200 */
195 201 tradeStatus?: string;
... ... @@ -198,8 +204,9 @@ export interface AdminClientDto {
198 204 * 跟进状态
199 205 */
200 206 tradeStatusText?: string;
201   - /** @format int32 */
202   - version?: number;
  207 + updateByName?: string;
  208 + /** @format date-time */
  209 + updateTime?: string;
203 210 }
204 211  
205 212 export interface AdminDeptQueryVO {
... ... @@ -2818,6 +2825,7 @@ export interface QueryBankStatementDto {
2818 2825 }
2819 2826  
2820 2827 export interface QueryClientDto {
  2828 + address?: string;
2821 2829 companyAddressLike?: string;
2822 2830 companyIds?: Array<number>;
2823 2831 companyNameLike?: string;
... ... @@ -2829,6 +2837,7 @@ export interface QueryClientDto {
2829 2837 createTimeLe?: string;
2830 2838 /** @format int32 */
2831 2839 current?: number;
  2840 + detailAddress?: string;
2832 2841 /** @format int32 */
2833 2842 end?: number;
2834 2843 groupFilter?: string;
... ... @@ -2838,6 +2847,8 @@ export interface QueryClientDto {
2838 2847 /** @format int32 */
2839 2848 pageSize?: number;
2840 2849 phoneNumber?: string;
  2850 + requirements?: string;
  2851 + source?: string;
2841 2852 /** @format int32 */
2842 2853 start?: number;
2843 2854 /** @format int32 */
... ... @@ -2846,10 +2857,18 @@ export interface QueryClientDto {
2846 2857 }
2847 2858  
2848 2859 export interface QueryCommunicationInfoDto {
  2860 + clientAddressLike?: string;
2849 2861 /** @format int64 */
2850 2862 clientId?: number;
  2863 + clientIdIn?: Array<number>;
  2864 + clientNameLike?: string;
2851 2865 content?: string;
2852 2866 createByName?: string;
  2867 + createByNameIn?: Array<string>;
  2868 + /** @format date-time */
  2869 + createTimeGe?: string;
  2870 + /** @format date-time */
  2871 + createTimeLe?: string;
2853 2872 /** @format int32 */
2854 2873 current?: number;
2855 2874 /** @format date-time */
... ... @@ -2864,6 +2883,7 @@ export interface QueryCommunicationInfoDto {
2864 2883 start?: number;
2865 2884 /** @format int32 */
2866 2885 total?: number;
  2886 + tradeStatusLike?: string;
2867 2887 way?: string;
2868 2888 }
2869 2889  
... ... @@ -3201,10 +3221,16 @@ export interface QueryUseOldInvoicingDto {
3201 3221  
3202 3222 export interface QueryWarningOrderWhiteListDto {
3203 3223 createByName?: string;
  3224 + /** @format date-time */
  3225 + createTimeGe?: string;
  3226 + /** @format date-time */
  3227 + createTimeLe?: string;
3204 3228 /** @format int32 */
3205 3229 current?: number;
3206 3230 /** @format int32 */
3207 3231 end?: number;
  3232 + /** @format int64 */
  3233 + orderId?: number;
3208 3234 /** @format int32 */
3209 3235 pageSize?: number;
3210 3236 /** @format int32 */
... ... @@ -3683,6 +3709,7 @@ export interface SubOrder {
3683 3709 deadline?: string;
3684 3710 ext?: string;
3685 3711 extendField?: string;
  3712 + feedbackRegistrationContent?: string;
3686 3713 /** @format date-time */
3687 3714 financialReceiptIssuanceTime?: string;
3688 3715 fullPaymentStatus?: string;
... ... @@ -4103,14 +4130,30 @@ export interface View {
4103 4130 }
4104 4131  
4105 4132 export interface WarningOrderWhiteListDto {
  4133 + createByName?: string;
  4134 + /** @format date-time */
  4135 + createTime?: string;
  4136 + logicDelete?: boolean;
4106 4137 /** @format int64 */
4107 4138 orderId?: number;
  4139 + paths?: Array<string>;
4108 4140 salesCode?: string;
  4141 + updateByName?: string;
  4142 + /** @format date-time */
  4143 + updateTime?: string;
4109 4144 }
4110 4145  
4111 4146 export interface WarningUserWhiteListDto {
  4147 + createByName?: string;
  4148 + /** @format date-time */
  4149 + createTime?: string;
4112 4150 /** @format int64 */
4113 4151 id?: number;
  4152 + logicDelete?: boolean;
  4153 + paths?: Array<string>;
  4154 + updateByName?: string;
  4155 + /** @format date-time */
  4156 + updateTime?: string;
4114 4157 userName?: string;
4115 4158 }
4116 4159  
... ... @@ -4133,16 +4176,29 @@ export interface ApiOrderConfirmReceiveRequest {
4133 4176 }
4134 4177  
4135 4178 export interface ClientCommunicationInfo {
  4179 + attachments?: string;
  4180 + /**
  4181 + * @description
  4182 + * 客户地址
  4183 + */
  4184 + clientAddress?: string;
4136 4185 /** @format int64 */
4137 4186 clientId?: number;
4138 4187 /**
4139 4188 * @description
  4189 + * 客户名称
  4190 + */
  4191 + clientName?: string;
  4192 + /**
  4193 + * @description
4140 4194 * 内容
4141 4195 */
4142 4196 content?: string;
4143 4197 createByName?: string;
4144 4198 /** @format date-time */
4145 4199 createTime?: string;
  4200 + /** @format int64 */
  4201 + dateRange?: number;
4146 4202 /**
4147 4203 * @description
4148 4204 * 跟进时间
... ... @@ -4152,6 +4208,11 @@ export interface ClientCommunicationInfo {
4152 4208 /** @format int64 */
4153 4209 id?: number;
4154 4210 logicDelete?: boolean;
  4211 + /**
  4212 + * @description
  4213 + * 客户状态
  4214 + */
  4215 + tradeStatus?: string;
4155 4216 updateByName?: string;
4156 4217 /** @format date-time */
4157 4218 updateTime?: string;
... ... @@ -4160,6 +4221,11 @@ export interface ClientCommunicationInfo {
4160 4221 * 方式
4161 4222 */
4162 4223 way?: string;
  4224 + /**
  4225 + * @description
  4226 + * 方式
  4227 + */
  4228 + wayText?: string;
4163 4229 }
4164 4230  
4165 4231 export interface CompanyInfo {
... ... @@ -4718,6 +4784,20 @@ export interface UserAddressSaveRequest {
4718 4784 institutionContactName?: string;
4719 4785 }
4720 4786  
  4787 +export interface FeedbackRegistrationDTO {
  4788 + /**
  4789 + * @description
  4790 + * 回访登记内容
  4791 + */
  4792 + feedbackRegistrationContent?: string;
  4793 + /**
  4794 + * @description
  4795 + * 子订单id
  4796 + * @format int64
  4797 + */
  4798 + id?: number;
  4799 +}
  4800 +
4721 4801 export interface UploadPaymentReceiptDTO {
4722 4802 /**
4723 4803 * @description
... ...
src/services/request.ts
... ... @@ -53,6 +53,7 @@ import type {
53 53 DistrictDo,
54 54 DistrictSearchDo,
55 55 Dto,
  56 + FeedbackRegistrationDTO,
56 57 InventoryMaterialStockReq,
57 58 InvoiceDto,
58 59 InvoiceRecordDTO,
... ... @@ -64,6 +65,7 @@ import type {
64 65 MaterialUnitListRes,
65 66 MeasureUnitListRes,
66 67 MessageQueryDTO,
  68 + ModelAndView,
67 69 OrderAddVO,
68 70 OrderAuditLogQueryVO,
69 71 OrderBaseInfoQueryVO,
... ... @@ -360,6 +362,79 @@ export const postAdminClientAddOrModifyClientComunicationInfo =
360 362 return request;
361 363 })();
362 364  
  365 +/** @description request parameter type for postAdminClientDeleteAdminClient */
  366 +export interface PostAdminClientDeleteAdminClientOption {
  367 + /**
  368 + * @description
  369 + * id
  370 + * @format int64
  371 + */
  372 + query?: {
  373 + /**
  374 + @description
  375 + id
  376 + @format int64 */
  377 + id?: number;
  378 + };
  379 +}
  380 +
  381 +/** @description response type for postAdminClientDeleteAdminClient */
  382 +export interface PostAdminClientDeleteAdminClientResponse {
  383 + /**
  384 + * @description
  385 + * OK
  386 + */
  387 + 200: ServerResult;
  388 + /**
  389 + * @description
  390 + * Created
  391 + */
  392 + 201: any;
  393 + /**
  394 + * @description
  395 + * Unauthorized
  396 + */
  397 + 401: any;
  398 + /**
  399 + * @description
  400 + * Forbidden
  401 + */
  402 + 403: any;
  403 + /**
  404 + * @description
  405 + * Not Found
  406 + */
  407 + 404: any;
  408 +}
  409 +
  410 +export type PostAdminClientDeleteAdminClientResponseSuccess =
  411 + PostAdminClientDeleteAdminClientResponse[200];
  412 +/**
  413 + * @description
  414 + * 删除客户
  415 + * @tags 客户管理
  416 + * @produces *
  417 + * @consumes application/json
  418 + */
  419 +export const postAdminClientDeleteAdminClient = /* #__PURE__ */ (() => {
  420 + const method = 'post';
  421 + const url = '/admin/client/deleteAdminClient';
  422 + function request(
  423 + option?: PostAdminClientDeleteAdminClientOption,
  424 + ): Promise<PostAdminClientDeleteAdminClientResponseSuccess> {
  425 + return requester(request.url, {
  426 + method: request.method,
  427 + ...option,
  428 + }) as unknown as Promise<PostAdminClientDeleteAdminClientResponseSuccess>;
  429 + }
  430 +
  431 + /** http method */
  432 + request.method = method;
  433 + /** request url */
  434 + request.url = url;
  435 + return request;
  436 +})();
  437 +
363 438 /** @description response type for postAdminClientDownloadImportTemplate */
364 439 export interface PostAdminClientDownloadImportTemplateResponse {
365 440 /**
... ... @@ -518,7 +593,7 @@ export type PostAdminClientGetStatisticalDataResponseSuccess =
518 593 PostAdminClientGetStatisticalDataResponse[200];
519 594 /**
520 595 * @description
521   - * 修改跟进信息
  596 + * 全部与预警客户个数
522 597 * @tags 客户管理
523 598 * @produces *
524 599 * @consumes application/json
... ... @@ -3237,9 +3312,7 @@ export interface GetErrorResponse {
3237 3312 * @description
3238 3313 * OK
3239 3314 */
3240   - 200: {
3241   - [propertyName: string]: any;
3242   - };
  3315 + 200: ModelAndView;
3243 3316 /**
3244 3317 * @description
3245 3318 * Unauthorized
... ... @@ -3260,9 +3333,9 @@ export interface GetErrorResponse {
3260 3333 export type GetErrorResponseSuccess = GetErrorResponse[200];
3261 3334 /**
3262 3335 * @description
3263   - * error
  3336 + * errorHtml
3264 3337 * @tags basic-error-controller
3265   - * @produces *
  3338 + * @produces text/html
3266 3339 */
3267 3340 export const getError = /* #__PURE__ */ (() => {
3268 3341 const method = 'get';
... ... @@ -3286,9 +3359,7 @@ export interface PutErrorResponse {
3286 3359 * @description
3287 3360 * OK
3288 3361 */
3289   - 200: {
3290   - [propertyName: string]: any;
3291   - };
  3362 + 200: ModelAndView;
3292 3363 /**
3293 3364 * @description
3294 3365 * Created
... ... @@ -3314,9 +3385,9 @@ export interface PutErrorResponse {
3314 3385 export type PutErrorResponseSuccess = PutErrorResponse[200];
3315 3386 /**
3316 3387 * @description
3317   - * error
  3388 + * errorHtml
3318 3389 * @tags basic-error-controller
3319   - * @produces *
  3390 + * @produces text/html
3320 3391 * @consumes application/json
3321 3392 */
3322 3393 export const putError = /* #__PURE__ */ (() => {
... ... @@ -3341,9 +3412,7 @@ export interface PostErrorResponse {
3341 3412 * @description
3342 3413 * OK
3343 3414 */
3344   - 200: {
3345   - [propertyName: string]: any;
3346   - };
  3415 + 200: ModelAndView;
3347 3416 /**
3348 3417 * @description
3349 3418 * Created
... ... @@ -3369,9 +3438,9 @@ export interface PostErrorResponse {
3369 3438 export type PostErrorResponseSuccess = PostErrorResponse[200];
3370 3439 /**
3371 3440 * @description
3372   - * error
  3441 + * errorHtml
3373 3442 * @tags basic-error-controller
3374   - * @produces *
  3443 + * @produces text/html
3375 3444 * @consumes application/json
3376 3445 */
3377 3446 export const postError = /* #__PURE__ */ (() => {
... ... @@ -3396,9 +3465,7 @@ export interface DeleteErrorResponse {
3396 3465 * @description
3397 3466 * OK
3398 3467 */
3399   - 200: {
3400   - [propertyName: string]: any;
3401   - };
  3468 + 200: ModelAndView;
3402 3469 /**
3403 3470 * @description
3404 3471 * No Content
... ... @@ -3419,9 +3486,9 @@ export interface DeleteErrorResponse {
3419 3486 export type DeleteErrorResponseSuccess = DeleteErrorResponse[200];
3420 3487 /**
3421 3488 * @description
3422   - * error
  3489 + * errorHtml
3423 3490 * @tags basic-error-controller
3424   - * @produces *
  3491 + * @produces text/html
3425 3492 */
3426 3493 export const deleteError = /* #__PURE__ */ (() => {
3427 3494 const method = 'delete';
... ... @@ -3445,9 +3512,7 @@ export interface OptionsErrorResponse {
3445 3512 * @description
3446 3513 * OK
3447 3514 */
3448   - 200: {
3449   - [propertyName: string]: any;
3450   - };
  3515 + 200: ModelAndView;
3451 3516 /**
3452 3517 * @description
3453 3518 * No Content
... ... @@ -3468,9 +3533,9 @@ export interface OptionsErrorResponse {
3468 3533 export type OptionsErrorResponseSuccess = OptionsErrorResponse[200];
3469 3534 /**
3470 3535 * @description
3471   - * error
  3536 + * errorHtml
3472 3537 * @tags basic-error-controller
3473   - * @produces *
  3538 + * @produces text/html
3474 3539 * @consumes application/json
3475 3540 */
3476 3541 export const optionsError = /* #__PURE__ */ (() => {
... ... @@ -3495,9 +3560,7 @@ export interface HeadErrorResponse {
3495 3560 * @description
3496 3561 * OK
3497 3562 */
3498   - 200: {
3499   - [propertyName: string]: any;
3500   - };
  3563 + 200: ModelAndView;
3501 3564 /**
3502 3565 * @description
3503 3566 * No Content
... ... @@ -3518,9 +3581,9 @@ export interface HeadErrorResponse {
3518 3581 export type HeadErrorResponseSuccess = HeadErrorResponse[200];
3519 3582 /**
3520 3583 * @description
3521   - * error
  3584 + * errorHtml
3522 3585 * @tags basic-error-controller
3523   - * @produces *
  3586 + * @produces text/html
3524 3587 * @consumes application/json
3525 3588 */
3526 3589 export const headError = /* #__PURE__ */ (() => {
... ... @@ -3545,9 +3608,7 @@ export interface PatchErrorResponse {
3545 3608 * @description
3546 3609 * OK
3547 3610 */
3548   - 200: {
3549   - [propertyName: string]: any;
3550   - };
  3611 + 200: ModelAndView;
3551 3612 /**
3552 3613 * @description
3553 3614 * No Content
... ... @@ -3568,9 +3629,9 @@ export interface PatchErrorResponse {
3568 3629 export type PatchErrorResponseSuccess = PatchErrorResponse[200];
3569 3630 /**
3570 3631 * @description
3571   - * error
  3632 + * errorHtml
3572 3633 * @tags basic-error-controller
3573   - * @produces *
  3634 + * @produces text/html
3574 3635 * @consumes application/json
3575 3636 */
3576 3637 export const patchError = /* #__PURE__ */ (() => {
... ... @@ -13049,6 +13110,168 @@ export const postServiceConstClientLevels = /* #__PURE__ */ (() =&gt; {
13049 13110 return request;
13050 13111 })();
13051 13112  
  13113 +/** @description response type for postServiceConstClientRequirements */
  13114 +export interface PostServiceConstClientRequirementsResponse {
  13115 + /**
  13116 + * @description
  13117 + * OK
  13118 + */
  13119 + 200: ServerResult;
  13120 + /**
  13121 + * @description
  13122 + * Created
  13123 + */
  13124 + 201: any;
  13125 + /**
  13126 + * @description
  13127 + * Unauthorized
  13128 + */
  13129 + 401: any;
  13130 + /**
  13131 + * @description
  13132 + * Forbidden
  13133 + */
  13134 + 403: any;
  13135 + /**
  13136 + * @description
  13137 + * Not Found
  13138 + */
  13139 + 404: any;
  13140 +}
  13141 +
  13142 +export type PostServiceConstClientRequirementsResponseSuccess =
  13143 + PostServiceConstClientRequirementsResponse[200];
  13144 +/**
  13145 + * @description
  13146 + * 客户需求
  13147 + * @tags front-const-controller
  13148 + * @produces *
  13149 + * @consumes application/json
  13150 + */
  13151 +export const postServiceConstClientRequirements = /* #__PURE__ */ (() => {
  13152 + const method = 'post';
  13153 + const url = '/service/const/clientRequirements';
  13154 + function request(): Promise<PostServiceConstClientRequirementsResponseSuccess> {
  13155 + return requester(request.url, {
  13156 + method: request.method,
  13157 + }) as unknown as Promise<PostServiceConstClientRequirementsResponseSuccess>;
  13158 + }
  13159 +
  13160 + /** http method */
  13161 + request.method = method;
  13162 + /** request url */
  13163 + request.url = url;
  13164 + return request;
  13165 +})();
  13166 +
  13167 +/** @description response type for postServiceConstClientSource */
  13168 +export interface PostServiceConstClientSourceResponse {
  13169 + /**
  13170 + * @description
  13171 + * OK
  13172 + */
  13173 + 200: ServerResult;
  13174 + /**
  13175 + * @description
  13176 + * Created
  13177 + */
  13178 + 201: any;
  13179 + /**
  13180 + * @description
  13181 + * Unauthorized
  13182 + */
  13183 + 401: any;
  13184 + /**
  13185 + * @description
  13186 + * Forbidden
  13187 + */
  13188 + 403: any;
  13189 + /**
  13190 + * @description
  13191 + * Not Found
  13192 + */
  13193 + 404: any;
  13194 +}
  13195 +
  13196 +export type PostServiceConstClientSourceResponseSuccess =
  13197 + PostServiceConstClientSourceResponse[200];
  13198 +/**
  13199 + * @description
  13200 + * 客户来源
  13201 + * @tags front-const-controller
  13202 + * @produces *
  13203 + * @consumes application/json
  13204 + */
  13205 +export const postServiceConstClientSource = /* #__PURE__ */ (() => {
  13206 + const method = 'post';
  13207 + const url = '/service/const/clientSource';
  13208 + function request(): Promise<PostServiceConstClientSourceResponseSuccess> {
  13209 + return requester(request.url, {
  13210 + method: request.method,
  13211 + }) as unknown as Promise<PostServiceConstClientSourceResponseSuccess>;
  13212 + }
  13213 +
  13214 + /** http method */
  13215 + request.method = method;
  13216 + /** request url */
  13217 + request.url = url;
  13218 + return request;
  13219 +})();
  13220 +
  13221 +/** @description response type for postServiceConstClientWay */
  13222 +export interface PostServiceConstClientWayResponse {
  13223 + /**
  13224 + * @description
  13225 + * OK
  13226 + */
  13227 + 200: ServerResult;
  13228 + /**
  13229 + * @description
  13230 + * Created
  13231 + */
  13232 + 201: any;
  13233 + /**
  13234 + * @description
  13235 + * Unauthorized
  13236 + */
  13237 + 401: any;
  13238 + /**
  13239 + * @description
  13240 + * Forbidden
  13241 + */
  13242 + 403: any;
  13243 + /**
  13244 + * @description
  13245 + * Not Found
  13246 + */
  13247 + 404: any;
  13248 +}
  13249 +
  13250 +export type PostServiceConstClientWayResponseSuccess =
  13251 + PostServiceConstClientWayResponse[200];
  13252 +/**
  13253 + * @description
  13254 + * 类型
  13255 + * @tags front-const-controller
  13256 + * @produces *
  13257 + * @consumes application/json
  13258 + */
  13259 +export const postServiceConstClientWay = /* #__PURE__ */ (() => {
  13260 + const method = 'post';
  13261 + const url = '/service/const/clientWay';
  13262 + function request(): Promise<PostServiceConstClientWayResponseSuccess> {
  13263 + return requester(request.url, {
  13264 + method: request.method,
  13265 + }) as unknown as Promise<PostServiceConstClientWayResponseSuccess>;
  13266 + }
  13267 +
  13268 + /** http method */
  13269 + request.method = method;
  13270 + /** request url */
  13271 + request.url = url;
  13272 + return request;
  13273 +})();
  13274 +
13052 13275 /** @description response type for postServiceConstGetPayeeEnum */
13053 13276 export interface PostServiceConstGetPayeeEnumResponse {
13054 13277 /**
... ... @@ -17062,13 +17285,13 @@ export const postServiceOrderConfirmReceipt = /* #__PURE__ */ (() =&gt; {
17062 17285 export interface PostServiceOrderDeleteWarningOrderWhiteListOption {
17063 17286 /**
17064 17287 * @description
17065   - * id
  17288 + * orderId
17066 17289 */
17067 17290 body?: {
17068 17291 /**
17069 17292 @description
17070   - id */
17071   - id?: number;
  17293 + orderId */
  17294 + orderId?: number;
17072 17295 };
17073 17296 }
17074 17297  
... ... @@ -17540,6 +17763,77 @@ export const postServiceOrderExportTemplate = /* #__PURE__ */ (() =&gt; {
17540 17763 return request;
17541 17764 })();
17542 17765  
  17766 +/** @description request parameter type for postServiceOrderFeedbackRegistration */
  17767 +export interface PostServiceOrderFeedbackRegistrationOption {
  17768 + /**
  17769 + * @description
  17770 + * dto
  17771 + */
  17772 + body: {
  17773 + /**
  17774 + @description
  17775 + dto */
  17776 + dto: FeedbackRegistrationDTO;
  17777 + };
  17778 +}
  17779 +
  17780 +/** @description response type for postServiceOrderFeedbackRegistration */
  17781 +export interface PostServiceOrderFeedbackRegistrationResponse {
  17782 + /**
  17783 + * @description
  17784 + * OK
  17785 + */
  17786 + 200: ServerResult;
  17787 + /**
  17788 + * @description
  17789 + * Created
  17790 + */
  17791 + 201: any;
  17792 + /**
  17793 + * @description
  17794 + * Unauthorized
  17795 + */
  17796 + 401: any;
  17797 + /**
  17798 + * @description
  17799 + * Forbidden
  17800 + */
  17801 + 403: any;
  17802 + /**
  17803 + * @description
  17804 + * Not Found
  17805 + */
  17806 + 404: any;
  17807 +}
  17808 +
  17809 +export type PostServiceOrderFeedbackRegistrationResponseSuccess =
  17810 + PostServiceOrderFeedbackRegistrationResponse[200];
  17811 +/**
  17812 + * @description
  17813 + * 回访登记
  17814 + * @tags 内部订单
  17815 + * @produces *
  17816 + * @consumes application/json
  17817 + */
  17818 +export const postServiceOrderFeedbackRegistration = /* #__PURE__ */ (() => {
  17819 + const method = 'post';
  17820 + const url = '/service/order/feedbackRegistration';
  17821 + function request(
  17822 + option: PostServiceOrderFeedbackRegistrationOption,
  17823 + ): Promise<PostServiceOrderFeedbackRegistrationResponseSuccess> {
  17824 + return requester(request.url, {
  17825 + method: request.method,
  17826 + ...option,
  17827 + }) as unknown as Promise<PostServiceOrderFeedbackRegistrationResponseSuccess>;
  17828 + }
  17829 +
  17830 + /** http method */
  17831 + request.method = method;
  17832 + /** request url */
  17833 + request.url = url;
  17834 + return request;
  17835 +})();
  17836 +
17543 17837 /** @description request parameter type for postServiceOrderFileProcess */
17544 17838 export interface PostServiceOrderFileProcessOption {
17545 17839 /**
... ...