Commit 1938a03b0760af65e4aa3a11df72f7aa97c1bb57

Authored by 曾国涛
1 parent c8960b07

feat: 客户管理模块开发

.umirc.ts
@@ -86,13 +86,13 @@ export default defineConfig({ @@ -86,13 +86,13 @@ export default defineConfig({
86 icon: 'BookOutlined', 86 icon: 'BookOutlined',
87 access: 'canReadAdmin', 87 access: 'canReadAdmin',
88 }, 88 },
89 - /*{ 89 + {
90 name: '客户管理', 90 name: '客户管理',
91 path: '/client', 91 path: '/client',
92 component: './Client', 92 component: './Client',
93 icon: 'BookOutlined', 93 icon: 'BookOutlined',
94 access: 'canReadAdmin', 94 access: 'canReadAdmin',
95 - },*/ 95 + },
96 { 96 {
97 name: '打印', 97 name: '打印',
98 path: '/print', 98 path: '/print',
src/pages/Client/Components/ClientDrawer.tsx
  1 +import { RESPONSE_CODE } from '@/constants/enum';
1 import { 2 import {
  3 + postAdminClientAddAdminClient,
  4 + postDistrictSelectByLevel,
  5 + postDistrictSelectByNameAndLevel,
  6 + postDistrictSelOrderProvince,
2 postServiceConstClientLevels, 7 postServiceConstClientLevels,
3 postServiceConstTradeStatus, 8 postServiceConstTradeStatus,
4 } from '@/services'; 9 } from '@/services';
@@ -9,14 +14,18 @@ import { @@ -9,14 +14,18 @@ import {
9 ProFormSelect, 14 ProFormSelect,
10 ProFormText, 15 ProFormText,
11 } from '@ant-design/pro-components'; 16 } from '@ant-design/pro-components';
12 -import { Form, message } from 'antd'; 17 +import { Button, Form, message } from 'antd';
  18 +import { useState } from 'react';
13 19
14 -export default () => { 20 +export default ({ record }) => {
15 const [form] = Form.useForm<{ name: string; company: string }>(); 21 const [form] = Form.useForm<{ name: string; company: string }>();
16 - 22 + //省市区
  23 + const [province, setProvince] = useState('');
  24 + const [city, setCity] = useState('');
  25 + const [setDistrict] = useState('');
17 return ( 26 return (
18 <DrawerForm 27 <DrawerForm
19 - title="新建表单" 28 + title={record ? '详情' : '编辑'}
20 resize={{ 29 resize={{
21 onResize() { 30 onResize() {
22 console.log('resize!'); 31 console.log('resize!');
@@ -24,35 +33,226 @@ export default () =&gt; { @@ -24,35 +33,226 @@ export default () =&gt; {
24 maxWidth: window.innerWidth * 0.8, 33 maxWidth: window.innerWidth * 0.8,
25 minWidth: 300, 34 minWidth: 300,
26 }} 35 }}
  36 + initialValues={record}
27 form={form} 37 form={form}
28 - trigger={<a type="primary">新增客户</a>} 38 + trigger={
  39 + record ? (
  40 + <a type="primary">详情</a>
  41 + ) : (
  42 + <Button type="primary">新增</Button>
  43 + )
  44 + }
29 autoFocusFirstInput 45 autoFocusFirstInput
30 drawerProps={{ 46 drawerProps={{
31 destroyOnClose: true, 47 destroyOnClose: true,
32 }} 48 }}
33 submitTimeout={2000} 49 submitTimeout={2000}
  50 + width={500}
  51 + readonly={!!record}
34 onFinish={async (values) => { 52 onFinish={async (values) => {
35 - console.log(values);  
36 - message.success('提交成功');  
37 - // 不返回不会关闭弹框  
38 - return true; 53 + const res = await postAdminClientAddAdminClient({
  54 + data: values,
  55 + });
  56 + if (res.result === RESPONSE_CODE.SUCCESS) {
  57 + message.success('新增成功');
  58 + // 不返回不会关闭弹框
  59 + return true;
  60 + }
39 }} 61 }}
40 > 62 >
41 - <ProFormText name="name" label="客户名称" placeholder="请输入名称" /> 63 + <ProFormText
  64 + name="name"
  65 + label="客户名称"
  66 + placeholder="请输入名称"
  67 + rules={[
  68 + {
  69 + required: true,
  70 + message: '请输入客户名称',
  71 + },
  72 + ]}
  73 + />
42 <ProFormText 74 <ProFormText
43 name="companyName" 75 name="companyName"
44 label="单位名称" 76 label="单位名称"
45 placeholder="请输入单位名称" 77 placeholder="请输入单位名称"
  78 + rules={[
  79 + {
  80 + required: true,
  81 + message: '请输入单位名称',
  82 + },
  83 + ]}
46 /> 84 />
  85 + <div
  86 + style={{
  87 + display: 'flex',
  88 + justifyContent: 'space-between',
  89 + width: 340,
  90 + }}
  91 + >
  92 + <ProFormSelect
  93 + name="province"
  94 + key="province"
  95 + width={100}
  96 + label="省"
  97 + allowClear={false}
  98 + onChange={(value) => {
  99 + console.log(value);
  100 +
  101 + if (value !== undefined || value !== null) {
  102 + console.log('setProvince');
  103 +
  104 + setProvince(value);
  105 + }
  106 + }}
  107 + placeholder="请选择"
  108 + rules={[
  109 + {
  110 + required: true,
  111 + message: '请选择!',
  112 + },
  113 + ]}
  114 + request={async () => {
  115 + let province = [];
  116 + let res = await postDistrictSelectByLevel({ data: 1 });
  117 + if (res) {
  118 + res.data.forEach((item) => {
  119 + province.push({ value: item.district, label: item.district });
  120 + });
  121 + }
  122 + return province;
  123 + }}
  124 + />
  125 + <ProFormSelect
  126 + key={province}
  127 + name="city"
  128 + width={100}
  129 + label="市"
  130 + allowClear={false}
  131 + disabled={province === ''}
  132 + placeholder="请选择"
  133 + onChange={(value) => {
  134 + if (value !== undefined || value !== null) {
  135 + setCity(value);
  136 + }
  137 + }}
  138 + rules={[
  139 + {
  140 + required: true,
  141 + message: '请选择!',
  142 + },
  143 + ]}
  144 + request={async () => {
  145 + let cityOptions = [];
  146 + console.log(form.getFieldValue('id'));
  147 + if (form.getFieldValue('id')) {
  148 + const resp = await postDistrictSelOrderProvince({
  149 + data: form.getFieldValue('id'),
  150 + });
  151 + if (
  152 + resp.data.province !== null &&
  153 + resp.data.province !== undefined
  154 + ) {
  155 + console.log('province is ok');
  156 + let res = await postDistrictSelectByNameAndLevel({
  157 + data: { district: resp.data.province, level: 1 },
  158 + });
  159 + if (res && res.data) {
  160 + cityOptions = res.data.map((item) => ({
  161 + value: item.district,
  162 + label: item.district,
  163 + }));
  164 + }
  165 + }
  166 + }
  167 + if (province !== '') {
  168 + console.log(province);
  169 + console.log('province is okk');
  170 + let res = await postDistrictSelectByNameAndLevel({
  171 + data: { district: province, level: 1 },
  172 + });
  173 + if (res && res.data) {
  174 + cityOptions = res.data.map((item) => ({
  175 + value: item.district,
  176 + label: item.district,
  177 + }));
  178 + }
  179 + }
  180 + return cityOptions;
  181 + }}
  182 + />
  183 + <ProFormSelect
  184 + key={city ? city.toString() : 'district'}
  185 + name="district"
  186 + width={100}
  187 + label="区"
  188 + allowClear={false}
  189 + onChange={(value) => {
  190 + if (value !== undefined || value !== null) {
  191 + setDistrict(value);
  192 + }
  193 + }}
  194 + disabled={city === ''}
  195 + placeholder="请选择"
  196 + rules={[
  197 + {
  198 + required: true,
  199 + message: '请选择!',
  200 + },
  201 + ]}
  202 + request={async () => {
  203 + let districtOptions = [];
  204 + if (form.getFieldValue('id')) {
  205 + const resp = await postDistrictSelOrderProvince({
  206 + data: form.getFieldValue('id'),
  207 + });
  208 + if (resp.data.city !== null && resp.data.city !== undefined) {
  209 + let res = await postDistrictSelectByNameAndLevel({
  210 + data: { district: resp.data.city, level: 2 },
  211 + });
  212 + if (res && res.data) {
  213 + districtOptions = res.data.map((item) => ({
  214 + value: item.district,
  215 + label: item.district,
  216 + }));
  217 + }
  218 + }
  219 + }
  220 + if (city !== '') {
  221 + let res = await postDistrictSelectByNameAndLevel({
  222 + data: { district: city, level: 2 },
  223 + });
  224 + if (res && res.data) {
  225 + districtOptions = res.data.map((item) => ({
  226 + value: item.district,
  227 + label: item.district,
  228 + }));
  229 + }
  230 + }
  231 + return districtOptions;
  232 + }}
  233 + />
  234 + </div>
47 <ProFormText 235 <ProFormText
48 name="companyAddress" 236 name="companyAddress"
49 - label="单位地址" 237 + label="详细地址"
50 placeholder="请输入单位地址" 238 placeholder="请输入单位地址"
  239 + rules={[
  240 + {
  241 + required: true,
  242 + message: '请输入单位地址',
  243 + },
  244 + ]}
51 /> 245 />
52 <ProFormText 246 <ProFormText
53 name="phoneNumber" 247 name="phoneNumber"
54 label="联系电话" 248 label="联系电话"
55 placeholder="请输入联系电话" 249 placeholder="请输入联系电话"
  250 + rules={[
  251 + {
  252 + required: true,
  253 + message: '请输入联系电话',
  254 + },
  255 + ]}
56 /> 256 />
57 <ProFormText 257 <ProFormText
58 name="source" 258 name="source"
@@ -63,6 +263,12 @@ export default () =&gt; { @@ -63,6 +263,12 @@ export default () =&gt; {
63 name="requirements" 263 name="requirements"
64 label="客户需求" 264 label="客户需求"
65 placeholder="请输入客户需求" 265 placeholder="请输入客户需求"
  266 + rules={[
  267 + {
  268 + required: true,
  269 + message: '请输入客户需求',
  270 + },
  271 + ]}
66 /> 272 />
67 <ProFormText name="referrers" label="推荐人" placeholder="请输入推荐人" /> 273 <ProFormText name="referrers" label="推荐人" placeholder="请输入推荐人" />
68 <ProFormSelect 274 <ProFormSelect
@@ -79,6 +285,12 @@ export default () =&gt; { @@ -79,6 +285,12 @@ export default () =&gt; {
79 value: false, 285 value: false,
80 }, 286 },
81 ]} 287 ]}
  288 + rules={[
  289 + {
  290 + required: true,
  291 + message: '请选择是否已报方案',
  292 + },
  293 + ]}
82 /> 294 />
83 <ProFormDateTimePicker 295 <ProFormDateTimePicker
84 name="quoteDatetime" 296 name="quoteDatetime"
@@ -89,6 +301,12 @@ export default () =&gt; { @@ -89,6 +301,12 @@ export default () =&gt; {
89 name="level" 301 name="level"
90 label="客户等级" 302 label="客户等级"
91 placeholder="请输入客户等级" 303 placeholder="请输入客户等级"
  304 + rules={[
  305 + {
  306 + required: true,
  307 + message: '请输入客户等级',
  308 + },
  309 + ]}
92 request={async () => { 310 request={async () => {
93 const res = await postServiceConstClientLevels(); 311 const res = await postServiceConstClientLevels();
94 return enumToSelect(res.data); 312 return enumToSelect(res.data);
@@ -98,6 +316,12 @@ export default () =&gt; { @@ -98,6 +316,12 @@ export default () =&gt; {
98 name="tradeStatus" 316 name="tradeStatus"
99 label="跟进状态" 317 label="跟进状态"
100 placeholder="请输入跟进状态" 318 placeholder="请输入跟进状态"
  319 + rules={[
  320 + {
  321 + required: true,
  322 + message: '请输入跟进状态',
  323 + },
  324 + ]}
101 request={async () => { 325 request={async () => {
102 const res = await postServiceConstTradeStatus(); 326 const res = await postServiceConstTradeStatus();
103 return enumToSelect(res.data); 327 return enumToSelect(res.data);
src/pages/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 () => {
  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 + } else {
  63 + message.error(dataJson?.message);
  64 + }
  65 + });
  66 + } else {
  67 + message.error('上传失败,已下载错误信息表格');
  68 + // 创建一个新的 Blob 对象,它包含了服务器响应的数据(即你的 Excel 文件)
  69 + const blob = new Blob([response.data]); // Excel 的 MIME 类型
  70 + const downloadUrl = window.URL.createObjectURL(blob);
  71 + const a = document.createElement('a');
  72 + a.href = downloadUrl;
  73 + a.download = '银行流水导入模板.xlsx'; // 你可以为文件命名
  74 + document.body.appendChild(a);
  75 + a.click(); // 模拟点击操作来下载文件
  76 + URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存
  77 + document.body.removeChild(a);
  78 + }
  79 + })
  80 + .catch((error) => {
  81 + // 处理错误
  82 + message.error('系统出现异常了,请联系管理员', error);
  83 + })
  84 + .finally(() => {});
  85 + return true;
  86 + }}
  87 + >
  88 + <ProFormUploadDragger max={1} label="上传" name="file" />
  89 + <Button type="link" onClick={downloadImportTemplate}>
  90 + 下载导入模板
  91 + </Button>
  92 + {contextHolder}
  93 + </ModalForm>
  94 + );
  95 +};
src/pages/Client/Components/CommunicationHistoryModal.tsx 0 → 100644
  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: 50,
  37 + rules: [{ required: true, message: '请输入内容' }],
  38 + dataIndex: 'content',
  39 + },
  40 + {
  41 + title: '操作',
  42 + valueType: 'option',
  43 + width: 50,
  44 + render: (text, record, _, action) => [
  45 + <a
  46 + key="editable"
  47 + onClick={() => {
  48 + action?.startEditable?.(record.tid);
  49 + }}
  50 + >
  51 + 编辑
  52 + </a>,
  53 + <Popconfirm
  54 + key={'delete'}
  55 + title="删除记录"
  56 + description="确认删除记录?"
  57 + onConfirm={async () => {
  58 + setDataSource(dataSource.filter((item) => item.tid !== record.tid));
  59 + const res = await postAdminClientRemoveClientComunicationInfo({
  60 + query: {
  61 + id: record.id,
  62 + },
  63 + });
  64 + if (res.result === RESPONSE_CODE.SUCCESS) {
  65 + message.success(res.message);
  66 + action?.reload();
  67 + } else {
  68 + message.error('删除失败');
  69 + }
  70 + }}
  71 + okText="是"
  72 + cancelText="否"
  73 + >
  74 + <a type={'danger'}>删除</a>
  75 + </Popconfirm>,
  76 + ],
  77 + },
  78 + ];
  79 +
  80 + useEffect(() => {
  81 + console.log('clientId', clientId);
  82 + }, []);
  83 + return (
  84 + <ModalForm
  85 + title="跟进记录"
  86 + trigger={<a type="primary">跟进记录</a>}
  87 + modalProps={{
  88 + destroyOnClose: true,
  89 + }}
  90 + >
  91 + <EditableProTable
  92 + rowKey="tid"
  93 + formRef={ref}
  94 + actionRef={actionRef}
  95 + recordCreatorProps={{
  96 + record: () => ({ tid: (Math.random() * 1000000).toFixed(0) }),
  97 + }}
  98 + loading={false}
  99 + columns={columns}
  100 + request={async () => {
  101 + const res = await postAdminClientQueryClientComunicationInfo({
  102 + data: {
  103 + clientId: clientId,
  104 + },
  105 + });
  106 + if (res.result === RESPONSE_CODE.SUCCESS) {
  107 + console.log(JSON.stringify(res.data));
  108 + return {
  109 + ...res.data,
  110 + data: res.data.data.map((item) => {
  111 + return {
  112 + ...item,
  113 + tid: (Math.random() * 1000000).toFixed(0),
  114 + };
  115 + }),
  116 + };
  117 + } else {
  118 + message.error('获取失败');
  119 + }
  120 + }}
  121 + value={dataSource}
  122 + onChange={setDataSource}
  123 + editable={{
  124 + type: 'multiple',
  125 + editableKeys,
  126 + onSave: async (rowKey, data, row) => {
  127 + console.log(rowKey, data, row);
  128 + const res = await postAdminClientAddOrModifyClientComunicationInfo({
  129 + data: {
  130 + ...data,
  131 + clientId: clientId,
  132 + },
  133 + });
  134 + if (res.result === RESPONSE_CODE.SUCCESS) {
  135 + message.success(res.message);
  136 + } else {
  137 + message.error('修改失败');
  138 + }
  139 + actionRef.current?.reload();
  140 + },
  141 + onChange: setEditableRowKeys,
  142 + }}
  143 + />
  144 + {/*<ProCard title="表格数据" headerBordered collapsible defaultCollapsed>
  145 + <ProFormField
  146 + ignoreFormItem
  147 + fieldProps={{
  148 + style: {
  149 + width: '100%',
  150 + },
  151 + }}
  152 + mode="read"
  153 + valueType="jsonCode"
  154 + text={JSON.stringify(dataSource)}
  155 + />
  156 + </ProCard>*/}
  157 + </ModalForm>
  158 + );
  159 +};
src/pages/Client/index.tsx
1 import ClientDrawer from '@/pages/Client/Components/ClientDrawer'; 1 import ClientDrawer from '@/pages/Client/Components/ClientDrawer';
2 -import { postAdminClientQueryClientPage } from '@/services';  
3 -import { EllipsisOutlined } from '@ant-design/icons'; 2 +import ClientImportModal from '@/pages/Client/Components/ClientImportModal';
  3 +import CommunicationHistoryModal from '@/pages/Client/Components/CommunicationHistoryModal';
  4 +import {
  5 + postAdminClientQueryClientPage,
  6 + postServiceConstClientLevels,
  7 + postServiceConstTradeStatus,
  8 +} from '@/services';
  9 +import { orderExport } from '@/services/order';
  10 +import { enumToSelect } from '@/utils';
4 import type { ActionType } from '@ant-design/pro-components'; 11 import type { ActionType } from '@ant-design/pro-components';
5 import { ProTable } from '@ant-design/pro-components'; 12 import { ProTable } from '@ant-design/pro-components';
6 -import { Button, Dropdown } from 'antd'; 13 +import { Button, message } from 'antd';
7 import { useRef } from 'react'; 14 import { useRef } from 'react';
8 15
9 -export const waitTimePromise = async (time: number = 100) => {  
10 - return new Promise((resolve) => {  
11 - setTimeout(() => {  
12 - resolve(true);  
13 - }, time);  
14 - });  
15 -};  
16 -  
17 -export const waitTime = async (time: number = 100) => {  
18 - await waitTimePromise(time);  
19 -};  
20 -  
21 const columns = [ 16 const columns = [
22 { 17 {
23 dataIndex: 'index', 18 dataIndex: 'index',
@@ -27,163 +22,250 @@ const columns = [ @@ -27,163 +22,250 @@ const columns = [
27 { 22 {
28 title: '客户名称', 23 title: '客户名称',
29 dataIndex: 'name', 24 dataIndex: 'name',
  25 + hideInSearch: true,
30 }, 26 },
31 { 27 {
32 title: '单位名称', 28 title: '单位名称',
33 dataIndex: 'companyName', 29 dataIndex: 'companyName',
  30 + hideInSearch: true,
34 }, 31 },
35 { 32 {
36 title: '单位地址', 33 title: '单位地址',
37 dataIndex: 'companyName', 34 dataIndex: 'companyName',
  35 + hideInSearch: true,
38 }, 36 },
39 { 37 {
40 title: '联系电话', 38 title: '联系电话',
41 dataIndex: 'phoneNumber', 39 dataIndex: 'phoneNumber',
  40 + hideInSearch: true,
42 }, 41 },
43 { 42 {
44 title: '客户来源', 43 title: '客户来源',
45 - dataIndex: 'sourceText', 44 + dataIndex: 'source',
  45 + hideInSearch: true,
46 }, 46 },
47 { 47 {
48 title: '推荐人', 48 title: '推荐人',
49 dataIndex: 'referrers', 49 dataIndex: 'referrers',
  50 + hideInSearch: true,
50 }, 51 },
51 { 52 {
52 title: '客户需求', 53 title: '客户需求',
53 dataIndex: 'requirements', 54 dataIndex: 'requirements',
  55 + hideInSearch: true,
54 }, 56 },
55 { 57 {
56 title: '是否已报方案', 58 title: '是否已报方案',
57 dataIndex: 'hasSchemeText', 59 dataIndex: 'hasSchemeText',
  60 + hideInSearch: true,
58 }, 61 },
59 { 62 {
60 title: '报价时间', 63 title: '报价时间',
61 key: 'since', 64 key: 'since',
62 dataIndex: 'quoteDatetime', 65 dataIndex: 'quoteDatetime',
63 valueType: 'dateTime', 66 valueType: 'dateTime',
  67 + hideInSearch: true,
64 }, 68 },
65 { 69 {
66 title: '跟进状态', 70 title: '跟进状态',
67 dataIndex: 'tradeStatusText', 71 dataIndex: 'tradeStatusText',
  72 + hideInSearch: true,
68 }, 73 },
69 { 74 {
70 title: '客户等级', 75 title: '客户等级',
71 dataIndex: 'levelText', 76 dataIndex: 'levelText',
  77 + hideInSearch: true,
72 }, 78 },
73 { 79 {
74 title: '创建时间', 80 title: '创建时间',
75 key: 'since', 81 key: 'since',
76 dataIndex: 'createTime', 82 dataIndex: 'createTime',
77 valueType: 'dateTime', 83 valueType: 'dateTime',
  84 + hideInSearch: true,
78 }, 85 },
79 { 86 {
80 title: '最新跟进时间', 87 title: '最新跟进时间',
81 key: 'since', 88 key: 'since',
82 dataIndex: 'latestCommunicationTime', 89 dataIndex: 'latestCommunicationTime',
83 valueType: 'dateTime', 90 valueType: 'dateTime',
  91 + hideInSearch: true,
  92 + },
  93 + {
  94 + title: '客户名称',
  95 + dataIndex: 'nameLike',
  96 + valueType: 'Text',
  97 + hideInTable: true,
  98 + },
  99 + {
  100 + title: '单位名称',
  101 + dataIndex: 'companyNameLike',
  102 + valueType: 'Text',
  103 + hideInTable: true,
  104 + },
  105 + {
  106 + title: '联系电话',
  107 + dataIndex: 'phoneNumberLike',
  108 + valueType: 'Text',
  109 + hideInTable: true,
  110 + },
  111 + {
  112 + title: '是否已报方案',
  113 + dataIndex: 'hasScheme',
  114 + valueType: 'select',
  115 + valueEnum: {
  116 + true: {
  117 + text: '是',
  118 + value: true,
  119 + },
  120 + false: {
  121 + text: '否',
  122 + value: false,
  123 + },
  124 + },
  125 + hideInTable: true,
  126 + },
  127 + {
  128 + title: '客户等级',
  129 + dataIndex: 'level',
  130 + valueType: 'select',
  131 + hideInTable: true,
  132 + request: async () => {
  133 + const res = await postServiceConstClientLevels();
  134 + return enumToSelect(res.data);
  135 + },
  136 + },
  137 + {
  138 + title: '跟进状态',
  139 + dataIndex: 'tradeStatus',
  140 + valueType: 'select',
  141 + hideInTable: true,
  142 + request: async () => {
  143 + const res = await postServiceConstTradeStatus();
  144 + return enumToSelect(res.data);
  145 + },
  146 + },
  147 + {
  148 + title: '创建时间',
  149 + valueType: 'dateRange',
  150 + width: 200,
  151 + hideInTable: true,
  152 + search: {
  153 + transform: (value) => {
  154 + if (value) {
  155 + return {
  156 + createTimeGe: value[0],
  157 + createTimeLe: value[1],
  158 + };
  159 + }
  160 + },
  161 + },
84 }, 162 },
85 { 163 {
86 title: '操作', 164 title: '操作',
87 valueType: 'option', 165 valueType: 'option',
88 key: 'option', 166 key: 'option',
89 - render: (text, record, _, action) => [  
90 - <a  
91 - key="editable"  
92 - onClick={() => {  
93 - action?.startEditable?.(record.id);  
94 - }}  
95 - >  
96 - 查询详情  
97 - </a>,  
98 - <a href={record.url} target="_blank" rel="noopener noreferrer" key="view">  
99 - 跟进记录  
100 - </a>,  
101 - ], 167 + render: (text, record) => {
  168 + console.log(JSON.stringify(record));
  169 + return [
  170 + <CommunicationHistoryModal
  171 + key={'communicationHistory'}
  172 + clientId={record.id}
  173 + />,
  174 + <ClientDrawer key={'detail'} record={record}></ClientDrawer>,
  175 + ];
  176 + },
102 }, 177 },
103 ]; 178 ];
104 179
105 export default () => { 180 export default () => {
  181 + const [messageApi, contextHolder] = message.useMessage();
106 const actionRef = useRef<ActionType>(); 182 const actionRef = useRef<ActionType>();
107 return ( 183 return (
108 - <ProTable  
109 - columns={columns}  
110 - actionRef={actionRef}  
111 - cardBordered  
112 - request={async (params) => {  
113 - const res = await postAdminClientQueryClientPage({  
114 - data: {  
115 - ...params, 184 + <>
  185 + <ProTable
  186 + columns={columns}
  187 + actionRef={actionRef}
  188 + cardBordered
  189 + request={async (params) => {
  190 + const res = await postAdminClientQueryClientPage({
  191 + data: {
  192 + ...params,
  193 + },
  194 + });
  195 + const data = res.data;
  196 + return data;
  197 + }}
  198 + search={{
  199 + defaultCollapsed: false,
  200 + optionRender: (searchConfig, formProps, dom) => [
  201 + ...dom.reverse(),
  202 + <Button
  203 + key="out"
  204 + onClick={() => {
  205 + const values = searchConfig?.form?.getFieldsValue();
  206 + messageApi.open({
  207 + type: 'loading',
  208 + content: '导出中...',
  209 + duration: 0,
  210 + });
  211 + orderExport(
  212 + '/api/admin/client/exportClients',
  213 + '客户信息.xlsx',
  214 + 'POST',
  215 + values,
  216 + () => {
  217 + messageApi.destroy();
  218 + },
  219 + );
  220 + }}
  221 + >
  222 + 导出
  223 + </Button>,
  224 + ],
  225 + }}
  226 + editable={{
  227 + type: 'multiple',
  228 + }}
  229 + columnsState={{
  230 + persistenceKey: 'pro-table-singe-demos',
  231 + persistenceType: 'localStorage',
  232 + defaultValue: {
  233 + option: { fixed: 'right', disable: true },
  234 + },
  235 + onChange(value) {
  236 + console.log('value: ', value);
  237 + },
  238 + }}
  239 + rowKey="id"
  240 + options={{
  241 + setting: {
  242 + listsHeight: 400,
116 }, 243 },
117 - });  
118 - const data = res.data.data;  
119 - return data;  
120 - }}  
121 - editable={{  
122 - type: 'multiple',  
123 - }}  
124 - columnsState={{  
125 - persistenceKey: 'pro-table-singe-demos',  
126 - persistenceType: 'localStorage',  
127 - defaultValue: {  
128 - option: { fixed: 'right', disable: true },  
129 - },  
130 - onChange(value) {  
131 - console.log('value: ', value);  
132 - },  
133 - }}  
134 - rowKey="id"  
135 - search={{  
136 - labelWidth: 'auto',  
137 - }}  
138 - options={{  
139 - setting: {  
140 - listsHeight: 400,  
141 - },  
142 - }}  
143 - form={{  
144 - // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下  
145 - syncToUrl: (values, type) => {  
146 - if (type === 'get') {  
147 - return {  
148 - ...values,  
149 - created_at: [values.startTime, values.endTime],  
150 - };  
151 - }  
152 - return values;  
153 - },  
154 - }}  
155 - pagination={{  
156 - pageSize: 5,  
157 - onChange: (page) => console.log(page),  
158 - }}  
159 - dateFormatter="string"  
160 - headerTitle="高级表格"  
161 - toolBarRender={() => [  
162 - <ClientDrawer key="button" />,  
163 - <Dropdown  
164 - key="menu"  
165 - menu={{  
166 - items: [  
167 - {  
168 - label: '1st item',  
169 - key: '1',  
170 - },  
171 - {  
172 - label: '2nd item',  
173 - key: '1',  
174 - },  
175 - {  
176 - label: '3rd item',  
177 - key: '1',  
178 - },  
179 - ],  
180 - }}  
181 - >  
182 - <Button>  
183 - <EllipsisOutlined />  
184 - </Button>  
185 - </Dropdown>,  
186 - ]}  
187 - /> 244 + }}
  245 + form={{
  246 + // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
  247 + syncToUrl: (values, type) => {
  248 + if (type === 'get') {
  249 + return {
  250 + ...values,
  251 + created_at: [values.startTime, values.endTime],
  252 + };
  253 + }
  254 + return values;
  255 + },
  256 + }}
  257 + pagination={{
  258 + pageSize: 5,
  259 + onChange: (page) => console.log(page),
  260 + }}
  261 + dateFormatter="string"
  262 + headerTitle="高级表格"
  263 + toolBarRender={() => [
  264 + <ClientDrawer key="button"></ClientDrawer>,
  265 + <ClientImportModal key="import" />,
  266 + ]}
  267 + />
  268 + {contextHolder}
  269 + </>
188 ); 270 );
189 }; 271 };
src/services/definition.ts
@@ -86,27 +86,36 @@ export interface AdminAuthUserVO { @@ -86,27 +86,36 @@ export interface AdminAuthUserVO {
86 export interface AdminClientDto { 86 export interface AdminClientDto {
87 /** 87 /**
88 * @description 88 * @description
89 - * 公司地址 89 + * 市
  90 + */
  91 + city?: string;
  92 + /**
  93 + * @description
  94 + * 单位地址
90 */ 95 */
91 companyAddress?: string; 96 companyAddress?: string;
92 companyId?: string; 97 companyId?: string;
93 /** 98 /**
94 * @description 99 * @description
95 - * 公司名称 100 + * 单位名称
96 */ 101 */
97 companyName?: string; 102 companyName?: string;
98 contacts?: string; 103 contacts?: string;
99 createBy?: string; 104 createBy?: string;
100 /** @format date-time */ 105 /** @format date-time */
101 createTime?: string; 106 createTime?: string;
  107 + /**
  108 + * @description
  109 + * 区
  110 + */
  111 + district?: string;
102 /** @format int32 */ 112 /** @format int32 */
103 enableFlag?: number; 113 enableFlag?: number;
104 /** 114 /**
105 * @description 115 * @description
106 * 是否已报方案 116 * 是否已报方案
107 - * @format int32  
108 */ 117 */
109 - hasScheme?: number; 118 + hasScheme?: boolean;
110 hasSchemeText?: string; 119 hasSchemeText?: string;
111 /** @format date-time */ 120 /** @format date-time */
112 latestCommunicationTime?: string; 121 latestCommunicationTime?: string;
@@ -140,6 +149,11 @@ export interface AdminClientDto { @@ -140,6 +149,11 @@ export interface AdminClientDto {
140 phoneNumber?: string; 149 phoneNumber?: string;
141 /** 150 /**
142 * @description 151 * @description
  152 + * 省
  153 + */
  154 + province?: string;
  155 + /**
  156 + * @description
143 * 报价时间 157 * 报价时间
144 * @format date-time 158 * @format date-time
145 */ 159 */
@@ -161,11 +175,6 @@ export interface AdminClientDto { @@ -161,11 +175,6 @@ export interface AdminClientDto {
161 source?: string; 175 source?: string;
162 /** 176 /**
163 * @description 177 * @description
164 - * 来源  
165 - */  
166 - sourceText?: string;  
167 - /**  
168 - * @description  
169 * 跟进状态 178 * 跟进状态
170 */ 179 */
171 tradeStatus?: string; 180 tradeStatus?: string;
@@ -1917,7 +1926,7 @@ export interface QueryClientDto { @@ -1917,7 +1926,7 @@ export interface QueryClientDto {
1917 current?: number; 1926 current?: number;
1918 /** @format int32 */ 1927 /** @format int32 */
1919 end?: number; 1928 end?: number;
1920 - hasScheme?: string; 1929 + hasScheme?: boolean;
1921 level?: string; 1930 level?: string;
1922 namelike?: string; 1931 namelike?: string;
1923 /** @format int32 */ 1932 /** @format int32 */
@@ -1930,6 +1939,25 @@ export interface QueryClientDto { @@ -1930,6 +1939,25 @@ export interface QueryClientDto {
1930 tradeStatus?: string; 1939 tradeStatus?: string;
1931 } 1940 }
1932 1941
  1942 +export interface QueryCommunicationInfoDto {
  1943 + clientId?: string;
  1944 + content?: string;
  1945 + /** @format int32 */
  1946 + current?: number;
  1947 + /** @format date-time */
  1948 + datetime?: string;
  1949 + /** @format int32 */
  1950 + end?: number;
  1951 + id?: string;
  1952 + /** @format int32 */
  1953 + pageSize?: number;
  1954 + /** @format int32 */
  1955 + start?: number;
  1956 + /** @format int32 */
  1957 + total?: number;
  1958 + way?: string;
  1959 +}
  1960 +
1933 export interface QueryCustomerInformationDto { 1961 export interface QueryCustomerInformationDto {
1934 /** 1962 /**
1935 * @description 1963 * @description
@@ -2699,6 +2727,34 @@ export interface ApiOrderConfirmReceiveRequest { @@ -2699,6 +2727,34 @@ export interface ApiOrderConfirmReceiveRequest {
2699 subOrderIds?: Array<number>; 2727 subOrderIds?: Array<number>;
2700 } 2728 }
2701 2729
  2730 +export interface ClientCommunicationInfo {
  2731 + clientId?: string;
  2732 + /**
  2733 + * @description
  2734 + * 内容
  2735 + */
  2736 + content?: string;
  2737 + createByName?: string;
  2738 + /** @format date-time */
  2739 + createTime?: string;
  2740 + /**
  2741 + * @description
  2742 + * 跟进时间
  2743 + * @format date-time
  2744 + */
  2745 + datetime?: string;
  2746 + id?: string;
  2747 + logicDelete?: boolean;
  2748 + updateByName?: string;
  2749 + /** @format date-time */
  2750 + updateTime?: string;
  2751 + /**
  2752 + * @description
  2753 + * 方式
  2754 + */
  2755 + way?: string;
  2756 +}
  2757 +
2702 export interface TsgFile { 2758 export interface TsgFile {
2703 absolute?: boolean; 2759 absolute?: boolean;
2704 absoluteFile?: TsgFile; 2760 absoluteFile?: TsgFile;
@@ -2963,10 +3019,6 @@ export interface SalesRechargePrepaymentUpdateRequest { @@ -2963,10 +3019,6 @@ export interface SalesRechargePrepaymentUpdateRequest {
2963 salesCode?: string; 3019 salesCode?: string;
2964 } 3020 }
2965 3021
2966 -export type ServerResultSimplePageUtilsAdminClientDto = ServerResult<  
2967 - SimplePageUtils<AdminClientDto>  
2968 ->;  
2969 -export type SimplePageUtilsAdminClientDto = SimplePageUtils<AdminClientDto>;  
2970 /** 3022 /**
2971 * @description 3023 * @description
2972 * 开票添加对象 3024 * 开票添加对象
@@ -3143,14 +3195,3 @@ export interface Dto { @@ -3143,14 +3195,3 @@ export interface Dto {
3143 */ 3195 */
3144 subOrderIds?: Array<string>; 3196 subOrderIds?: Array<string>;
3145 } 3197 }
3146 -  
3147 -export interface SimplePageUtils<AdminClientDto = any> {  
3148 - /** @format int64 */  
3149 - count?: number;  
3150 - data?: Array<AdminClientDto>;  
3151 - /** @format int64 */  
3152 - pageSize?: number;  
3153 - specialPath?: Array<string>;  
3154 - /** @format int64 */  
3155 - total?: number;  
3156 -}  
src/services/request.ts
@@ -35,6 +35,7 @@ import type { @@ -35,6 +35,7 @@ import type {
35 CancelInvoiceAndBankStatementDto, 35 CancelInvoiceAndBankStatementDto,
36 CancelSendOrderDto, 36 CancelSendOrderDto,
37 CaptchaMessageVO, 37 CaptchaMessageVO,
  38 + ClientCommunicationInfo,
38 CommonAuditRequest, 39 CommonAuditRequest,
39 CustomFieldRes, 40 CustomFieldRes,
40 CustomerCustomerListReq, 41 CustomerCustomerListReq,
@@ -81,6 +82,7 @@ import type { @@ -81,6 +82,7 @@ import type {
81 QueryAnnexDto, 82 QueryAnnexDto,
82 QueryBankStatementDto, 83 QueryBankStatementDto,
83 QueryClientDto, 84 QueryClientDto,
  85 + QueryCommunicationInfoDto,
84 QueryCustomerInformationDto, 86 QueryCustomerInformationDto,
85 QueryHistoryRecordDto, 87 QueryHistoryRecordDto,
86 QueryInvoiceDetailDto, 88 QueryInvoiceDetailDto,
@@ -107,7 +109,6 @@ import type { @@ -107,7 +109,6 @@ import type {
107 SaveReply, 109 SaveReply,
108 ServerResult, 110 ServerResult,
109 ShippingWarehouseChangeDto, 111 ShippingWarehouseChangeDto,
110 - SimplePageUtils,  
111 StoreOrderInvoiceRequest, 112 StoreOrderInvoiceRequest,
112 SysLogQueryVO, 113 SysLogQueryVO,
113 SystemCustomFieldReq, 114 SystemCustomFieldReq,
@@ -173,7 +174,7 @@ export type PostAdminClientAddAdminClientResponseSuccess = @@ -173,7 +174,7 @@ export type PostAdminClientAddAdminClientResponseSuccess =
173 PostAdminClientAddAdminClientResponse[200]; 174 PostAdminClientAddAdminClientResponse[200];
174 /** 175 /**
175 * @description 176 * @description
176 - * 客户管理 177 + * 添加客户
177 * @tags 客户管理 178 * @tags 客户管理
178 * @produces * 179 * @produces *
179 * @consumes application/json 180 * @consumes application/json
@@ -197,6 +198,489 @@ export const postAdminClientAddAdminClient = /* #__PURE__ */ (() =&gt; { @@ -197,6 +198,489 @@ export const postAdminClientAddAdminClient = /* #__PURE__ */ (() =&gt; {
197 return request; 198 return request;
198 })(); 199 })();
199 200
  201 +/** @description request parameter type for postAdminClientAddClientComunicationInfo */
  202 +export interface PostAdminClientAddClientComunicationInfoOption {
  203 + /**
  204 + * @description
  205 + * dto
  206 + */
  207 + body: {
  208 + /**
  209 + @description
  210 + dto */
  211 + dto: QueryCommunicationInfoDto;
  212 + };
  213 +}
  214 +
  215 +/** @description response type for postAdminClientAddClientComunicationInfo */
  216 +export interface PostAdminClientAddClientComunicationInfoResponse {
  217 + /**
  218 + * @description
  219 + * OK
  220 + */
  221 + 200: ServerResult;
  222 + /**
  223 + * @description
  224 + * Created
  225 + */
  226 + 201: any;
  227 + /**
  228 + * @description
  229 + * Unauthorized
  230 + */
  231 + 401: any;
  232 + /**
  233 + * @description
  234 + * Forbidden
  235 + */
  236 + 403: any;
  237 + /**
  238 + * @description
  239 + * Not Found
  240 + */
  241 + 404: any;
  242 +}
  243 +
  244 +export type PostAdminClientAddClientComunicationInfoResponseSuccess =
  245 + PostAdminClientAddClientComunicationInfoResponse[200];
  246 +/**
  247 + * @description
  248 + * 添加跟进信息
  249 + * @tags 客户管理
  250 + * @produces *
  251 + * @consumes application/json
  252 + */
  253 +export const postAdminClientAddClientComunicationInfo = /* #__PURE__ */ (() => {
  254 + const method = 'post';
  255 + const url = '/admin/client/addClientComunicationInfo';
  256 + function request(
  257 + option: PostAdminClientAddClientComunicationInfoOption,
  258 + ): Promise<PostAdminClientAddClientComunicationInfoResponseSuccess> {
  259 + return requester(request.url, {
  260 + method: request.method,
  261 + ...option,
  262 + }) as unknown as Promise<PostAdminClientAddClientComunicationInfoResponseSuccess>;
  263 + }
  264 +
  265 + /** http method */
  266 + request.method = method;
  267 + /** request url */
  268 + request.url = url;
  269 + return request;
  270 +})();
  271 +
  272 +/** @description request parameter type for postAdminClientAddOrModifyClientComunicationInfo */
  273 +export interface PostAdminClientAddOrModifyClientComunicationInfoOption {
  274 + /**
  275 + * @description
  276 + * dto
  277 + */
  278 + body: {
  279 + /**
  280 + @description
  281 + dto */
  282 + dto: ClientCommunicationInfo;
  283 + };
  284 +}
  285 +
  286 +/** @description response type for postAdminClientAddOrModifyClientComunicationInfo */
  287 +export interface PostAdminClientAddOrModifyClientComunicationInfoResponse {
  288 + /**
  289 + * @description
  290 + * OK
  291 + */
  292 + 200: ServerResult;
  293 + /**
  294 + * @description
  295 + * Created
  296 + */
  297 + 201: any;
  298 + /**
  299 + * @description
  300 + * Unauthorized
  301 + */
  302 + 401: any;
  303 + /**
  304 + * @description
  305 + * Forbidden
  306 + */
  307 + 403: any;
  308 + /**
  309 + * @description
  310 + * Not Found
  311 + */
  312 + 404: any;
  313 +}
  314 +
  315 +export type PostAdminClientAddOrModifyClientComunicationInfoResponseSuccess =
  316 + PostAdminClientAddOrModifyClientComunicationInfoResponse[200];
  317 +/**
  318 + * @description
  319 + * 修改跟进信息
  320 + * @tags 客户管理
  321 + * @produces *
  322 + * @consumes application/json
  323 + */
  324 +export const postAdminClientAddOrModifyClientComunicationInfo =
  325 + /* #__PURE__ */ (() => {
  326 + const method = 'post';
  327 + const url = '/admin/client/addOrModifyClientComunicationInfo';
  328 + function request(
  329 + option: PostAdminClientAddOrModifyClientComunicationInfoOption,
  330 + ): Promise<PostAdminClientAddOrModifyClientComunicationInfoResponseSuccess> {
  331 + return requester(request.url, {
  332 + method: request.method,
  333 + ...option,
  334 + }) as unknown as Promise<PostAdminClientAddOrModifyClientComunicationInfoResponseSuccess>;
  335 + }
  336 +
  337 + /** http method */
  338 + request.method = method;
  339 + /** request url */
  340 + request.url = url;
  341 + return request;
  342 + })();
  343 +
  344 +/** @description response type for postAdminClientDownloadImportTemplate */
  345 +export interface PostAdminClientDownloadImportTemplateResponse {
  346 + /**
  347 + * @description
  348 + * OK
  349 + */
  350 + 200: any;
  351 + /**
  352 + * @description
  353 + * Created
  354 + */
  355 + 201: any;
  356 + /**
  357 + * @description
  358 + * Unauthorized
  359 + */
  360 + 401: any;
  361 + /**
  362 + * @description
  363 + * Forbidden
  364 + */
  365 + 403: any;
  366 + /**
  367 + * @description
  368 + * Not Found
  369 + */
  370 + 404: any;
  371 +}
  372 +
  373 +export type PostAdminClientDownloadImportTemplateResponseSuccess =
  374 + PostAdminClientDownloadImportTemplateResponse[200];
  375 +/**
  376 + * @description
  377 + * 下载导入模板
  378 + * @tags 客户管理
  379 + * @produces *
  380 + * @consumes application/json
  381 + */
  382 +export const postAdminClientDownloadImportTemplate = /* #__PURE__ */ (() => {
  383 + const method = 'post';
  384 + const url = '/admin/client/downloadImportTemplate';
  385 + function request(): Promise<PostAdminClientDownloadImportTemplateResponseSuccess> {
  386 + return requester(request.url, {
  387 + method: request.method,
  388 + }) as unknown as Promise<PostAdminClientDownloadImportTemplateResponseSuccess>;
  389 + }
  390 +
  391 + /** http method */
  392 + request.method = method;
  393 + /** request url */
  394 + request.url = url;
  395 + return request;
  396 +})();
  397 +
  398 +/** @description request parameter type for postAdminClientExportClients */
  399 +export interface PostAdminClientExportClientsOption {
  400 + /**
  401 + * @description
  402 + * dto
  403 + */
  404 + body: {
  405 + /**
  406 + @description
  407 + dto */
  408 + dto: QueryClientDto;
  409 + };
  410 +}
  411 +
  412 +/** @description response type for postAdminClientExportClients */
  413 +export interface PostAdminClientExportClientsResponse {
  414 + /**
  415 + * @description
  416 + * OK
  417 + */
  418 + 200: any;
  419 + /**
  420 + * @description
  421 + * Created
  422 + */
  423 + 201: any;
  424 + /**
  425 + * @description
  426 + * Unauthorized
  427 + */
  428 + 401: any;
  429 + /**
  430 + * @description
  431 + * Forbidden
  432 + */
  433 + 403: any;
  434 + /**
  435 + * @description
  436 + * Not Found
  437 + */
  438 + 404: any;
  439 +}
  440 +
  441 +export type PostAdminClientExportClientsResponseSuccess =
  442 + PostAdminClientExportClientsResponse[200];
  443 +/**
  444 + * @description
  445 + * 导出客户信息
  446 + * @tags 客户管理
  447 + * @produces *
  448 + * @consumes application/json
  449 + */
  450 +export const postAdminClientExportClients = /* #__PURE__ */ (() => {
  451 + const method = 'post';
  452 + const url = '/admin/client/exportClients';
  453 + function request(
  454 + option: PostAdminClientExportClientsOption,
  455 + ): Promise<PostAdminClientExportClientsResponseSuccess> {
  456 + return requester(request.url, {
  457 + method: request.method,
  458 + ...option,
  459 + }) as unknown as Promise<PostAdminClientExportClientsResponseSuccess>;
  460 + }
  461 +
  462 + /** http method */
  463 + request.method = method;
  464 + /** request url */
  465 + request.url = url;
  466 + return request;
  467 +})();
  468 +
  469 +/** @description request parameter type for postAdminClientImportClient */
  470 +export interface PostAdminClientImportClientOption {
  471 + /**
  472 + * @description
  473 + * file
  474 + */
  475 + formData: {
  476 + /**
  477 + @description
  478 + file */
  479 + file: File;
  480 + };
  481 +}
  482 +
  483 +/** @description response type for postAdminClientImportClient */
  484 +export interface PostAdminClientImportClientResponse {
  485 + /**
  486 + * @description
  487 + * OK
  488 + */
  489 + 200: ServerResult;
  490 + /**
  491 + * @description
  492 + * Created
  493 + */
  494 + 201: any;
  495 + /**
  496 + * @description
  497 + * Unauthorized
  498 + */
  499 + 401: any;
  500 + /**
  501 + * @description
  502 + * Forbidden
  503 + */
  504 + 403: any;
  505 + /**
  506 + * @description
  507 + * Not Found
  508 + */
  509 + 404: any;
  510 +}
  511 +
  512 +export type PostAdminClientImportClientResponseSuccess =
  513 + PostAdminClientImportClientResponse[200];
  514 +/**
  515 + * @description
  516 + * 导入客户
  517 + * @tags 客户管理
  518 + * @produces *
  519 + * @consumes multipart/form-data
  520 + */
  521 +export const postAdminClientImportClient = /* #__PURE__ */ (() => {
  522 + const method = 'post';
  523 + const url = '/admin/client/importClient';
  524 + function request(
  525 + option: PostAdminClientImportClientOption,
  526 + ): Promise<PostAdminClientImportClientResponseSuccess> {
  527 + return requester(request.url, {
  528 + method: request.method,
  529 + ...option,
  530 + }) as unknown as Promise<PostAdminClientImportClientResponseSuccess>;
  531 + }
  532 +
  533 + /** http method */
  534 + request.method = method;
  535 + /** request url */
  536 + request.url = url;
  537 + return request;
  538 +})();
  539 +
  540 +/** @description request parameter type for postAdminClientModifyClientComunicationInfo */
  541 +export interface PostAdminClientModifyClientComunicationInfoOption {
  542 + /**
  543 + * @description
  544 + * dto
  545 + */
  546 + body: {
  547 + /**
  548 + @description
  549 + dto */
  550 + dto: QueryCommunicationInfoDto;
  551 + };
  552 +}
  553 +
  554 +/** @description response type for postAdminClientModifyClientComunicationInfo */
  555 +export interface PostAdminClientModifyClientComunicationInfoResponse {
  556 + /**
  557 + * @description
  558 + * OK
  559 + */
  560 + 200: ServerResult;
  561 + /**
  562 + * @description
  563 + * Created
  564 + */
  565 + 201: any;
  566 + /**
  567 + * @description
  568 + * Unauthorized
  569 + */
  570 + 401: any;
  571 + /**
  572 + * @description
  573 + * Forbidden
  574 + */
  575 + 403: any;
  576 + /**
  577 + * @description
  578 + * Not Found
  579 + */
  580 + 404: any;
  581 +}
  582 +
  583 +export type PostAdminClientModifyClientComunicationInfoResponseSuccess =
  584 + PostAdminClientModifyClientComunicationInfoResponse[200];
  585 +/**
  586 + * @description
  587 + * 修改跟进信息
  588 + * @tags 客户管理
  589 + * @produces *
  590 + * @consumes application/json
  591 + */
  592 +export const postAdminClientModifyClientComunicationInfo =
  593 + /* #__PURE__ */ (() => {
  594 + const method = 'post';
  595 + const url = '/admin/client/modifyClientComunicationInfo';
  596 + function request(
  597 + option: PostAdminClientModifyClientComunicationInfoOption,
  598 + ): Promise<PostAdminClientModifyClientComunicationInfoResponseSuccess> {
  599 + return requester(request.url, {
  600 + method: request.method,
  601 + ...option,
  602 + }) as unknown as Promise<PostAdminClientModifyClientComunicationInfoResponseSuccess>;
  603 + }
  604 +
  605 + /** http method */
  606 + request.method = method;
  607 + /** request url */
  608 + request.url = url;
  609 + return request;
  610 + })();
  611 +
  612 +/** @description request parameter type for postAdminClientQueryClientComunicationInfo */
  613 +export interface PostAdminClientQueryClientComunicationInfoOption {
  614 + /**
  615 + * @description
  616 + * dto
  617 + */
  618 + body: {
  619 + /**
  620 + @description
  621 + dto */
  622 + dto: QueryCommunicationInfoDto;
  623 + };
  624 +}
  625 +
  626 +/** @description response type for postAdminClientQueryClientComunicationInfo */
  627 +export interface PostAdminClientQueryClientComunicationInfoResponse {
  628 + /**
  629 + * @description
  630 + * OK
  631 + */
  632 + 200: ServerResult;
  633 + /**
  634 + * @description
  635 + * Created
  636 + */
  637 + 201: any;
  638 + /**
  639 + * @description
  640 + * Unauthorized
  641 + */
  642 + 401: any;
  643 + /**
  644 + * @description
  645 + * Forbidden
  646 + */
  647 + 403: any;
  648 + /**
  649 + * @description
  650 + * Not Found
  651 + */
  652 + 404: any;
  653 +}
  654 +
  655 +export type PostAdminClientQueryClientComunicationInfoResponseSuccess =
  656 + PostAdminClientQueryClientComunicationInfoResponse[200];
  657 +/**
  658 + * @description
  659 + * 获取跟进信息
  660 + * @tags 客户管理
  661 + * @produces *
  662 + * @consumes application/json
  663 + */
  664 +export const postAdminClientQueryClientComunicationInfo =
  665 + /* #__PURE__ */ (() => {
  666 + const method = 'post';
  667 + const url = '/admin/client/queryClientComunicationInfo';
  668 + function request(
  669 + option: PostAdminClientQueryClientComunicationInfoOption,
  670 + ): Promise<PostAdminClientQueryClientComunicationInfoResponseSuccess> {
  671 + return requester(request.url, {
  672 + method: request.method,
  673 + ...option,
  674 + }) as unknown as Promise<PostAdminClientQueryClientComunicationInfoResponseSuccess>;
  675 + }
  676 +
  677 + /** http method */
  678 + request.method = method;
  679 + /** request url */
  680 + request.url = url;
  681 + return request;
  682 + })();
  683 +
200 /** @description request parameter type for postAdminClientQueryClientPage */ 684 /** @description request parameter type for postAdminClientQueryClientPage */
201 export interface PostAdminClientQueryClientPageOption { 685 export interface PostAdminClientQueryClientPageOption {
202 /** 686 /**
@@ -217,7 +701,7 @@ export interface PostAdminClientQueryClientPageResponse { @@ -217,7 +701,7 @@ export interface PostAdminClientQueryClientPageResponse {
217 * @description 701 * @description
218 * OK 702 * OK
219 */ 703 */
220 - 200: ServerResult<SimplePageUtils<AdminClientDto>>; 704 + 200: ServerResult;
221 /** 705 /**
222 * @description 706 * @description
223 * Created 707 * Created
@@ -268,6 +752,80 @@ export const postAdminClientQueryClientPage = /* #__PURE__ */ (() =&gt; { @@ -268,6 +752,80 @@ export const postAdminClientQueryClientPage = /* #__PURE__ */ (() =&gt; {
268 return request; 752 return request;
269 })(); 753 })();
270 754
  755 +/** @description request parameter type for postAdminClientRemoveClientComunicationInfo */
  756 +export interface PostAdminClientRemoveClientComunicationInfoOption {
  757 + /**
  758 + * @description
  759 + * id
  760 + * @format int64
  761 + */
  762 + query?: {
  763 + /**
  764 + @description
  765 + id
  766 + @format int64 */
  767 + id?: number;
  768 + };
  769 +}
  770 +
  771 +/** @description response type for postAdminClientRemoveClientComunicationInfo */
  772 +export interface PostAdminClientRemoveClientComunicationInfoResponse {
  773 + /**
  774 + * @description
  775 + * OK
  776 + */
  777 + 200: ServerResult;
  778 + /**
  779 + * @description
  780 + * Created
  781 + */
  782 + 201: any;
  783 + /**
  784 + * @description
  785 + * Unauthorized
  786 + */
  787 + 401: any;
  788 + /**
  789 + * @description
  790 + * Forbidden
  791 + */
  792 + 403: any;
  793 + /**
  794 + * @description
  795 + * Not Found
  796 + */
  797 + 404: any;
  798 +}
  799 +
  800 +export type PostAdminClientRemoveClientComunicationInfoResponseSuccess =
  801 + PostAdminClientRemoveClientComunicationInfoResponse[200];
  802 +/**
  803 + * @description
  804 + * 删除跟进信息
  805 + * @tags 客户管理
  806 + * @produces *
  807 + * @consumes application/json
  808 + */
  809 +export const postAdminClientRemoveClientComunicationInfo =
  810 + /* #__PURE__ */ (() => {
  811 + const method = 'post';
  812 + const url = '/admin/client/removeClientComunicationInfo';
  813 + function request(
  814 + option?: PostAdminClientRemoveClientComunicationInfoOption,
  815 + ): Promise<PostAdminClientRemoveClientComunicationInfoResponseSuccess> {
  816 + return requester(request.url, {
  817 + method: request.method,
  818 + ...option,
  819 + }) as unknown as Promise<PostAdminClientRemoveClientComunicationInfoResponseSuccess>;
  820 + }
  821 +
  822 + /** http method */
  823 + request.method = method;
  824 + /** request url */
  825 + request.url = url;
  826 + return request;
  827 + })();
  828 +
271 /** @description request parameter type for postApiLocalStorageUpload */ 829 /** @description request parameter type for postApiLocalStorageUpload */
272 export interface PostApiLocalStorageUploadOption { 830 export interface PostApiLocalStorageUploadOption {
273 /** 831 /**