Commit b19689c219949e29d74c4c895bdb3a17124a5467

Authored by boyang
1 parent 576a38ce

feat: 课题组风险名单

Showing 20 changed files with 1739 additions and 380 deletions
.umirc.ts
... ... @@ -139,9 +139,20 @@ export default defineConfig({
139 139 {
140 140 name: '课题组管理',
141 141 path: '/researchGroup',
142   - component: './ResearchGroup',
143 142 icon: 'AccountBookOutlined',
144 143 access: 'canReadAdminAndSales',
  144 + routes: [
  145 + {
  146 + name: '课题组列表',
  147 + path: 'researchGroup',
  148 + component: './ResearchGroup/ResearchGroup',
  149 + },
  150 + {
  151 + name: '课题组风险名单',
  152 + path: 'researchGroupAccess',
  153 + component: './ResearchGroup/ResearchGroupAccess',
  154 + },
  155 + ],
145 156 },
146 157 {
147 158 name: '分期账单',
... ...
src/pages/Order/OrderList/OrderDrawer.tsx
... ... @@ -768,73 +768,69 @@ export default ({ onClose, data, subOrders, orderOptType }) => {
768 768 }>
769 769 open
770 770 width={1000}
771   - title={drawerTitle}
772   - resize={{
773   - onResize() {
774   - console.log('resize!');
775   - },
776   - maxWidth: window.innerWidth * 0.8,
777   - minWidth: 400,
  771 + modalProps={{
  772 + destroyOnClose: true,
  773 + maskClosable: true,
  774 + title: (
  775 + <div
  776 + style={{ display: 'flex', alignItems: 'center', width: '100%' }}
  777 + >
  778 + <span>{drawerTitle}</span>
  779 + {hasLocalData && (
  780 + <Button
  781 + key="useLocalData"
  782 + type="link"
  783 + onClick={() => {
  784 + useLocalFormData();
  785 + }}
  786 + >
  787 + 使用草稿
  788 + </Button>
  789 + )}
  790 + </div>
  791 + ),
778 792 }}
779 793 onFinishFailed={() => {
780 794 message.error('表单项存在错误,请检查');
781 795 setSubmitBtnLoading(false);
782 796 }}
783 797 submitter={{
784   - render: (props) => {
785   - return [
786   - <Button
787   - key="cancel"
788   - onClick={() => {
789   - onClose();
790   - }}
791   - >
792   - 取消
793   - </Button>,
794   - <Button
795   - key="localSave"
796   - loading={localSaveLoading}
797   - hidden={!optType('add') && !optType('copy')}
798   - onClick={() => {
799   - setLocalSaveLoading(true);
800   - saveFormDataToLocal();
801   - }}
802   - >
803   - 本地保存
804   - </Button>,
805   - <Button
806   - key="ok"
807   - type="primary"
808   - loading={submitBtnLoading}
809   - disabled={optType('after-sales-check')}
810   - onClick={() => {
811   - setSubmitBtnLoading(true);
812   - props.submit();
813   - }}
814   - >
815   - 提交
816   - </Button>,
817   - ];
818   - },
819   - }}
820   - form={form}
821   - autoFocusFirstInput
822   - drawerProps={{
823   - destroyOnClose: true,
824   - maskClosable: false,
825   - extra: [
  798 + render: (props) => [
  799 + <Button
  800 + key="cancel"
  801 + onClick={() => {
  802 + onClose();
  803 + }}
  804 + >
  805 + 取消
  806 + </Button>,
826 807 <Button
827   - key="useLocalData"
828   - hidden={!hasLocalData}
829   - type="link"
  808 + key="localSave"
  809 + loading={localSaveLoading}
  810 + hidden={!optType('add') && !optType('copy')}
830 811 onClick={() => {
831   - useLocalFormData();
  812 + setLocalSaveLoading(true);
  813 + saveFormDataToLocal();
832 814 }}
833 815 >
834   - 使用草稿
  816 + 本地保存
  817 + </Button>,
  818 + <Button
  819 + key="ok"
  820 + type="primary"
  821 + loading={submitBtnLoading}
  822 + disabled={optType('after-sales-check')}
  823 + onClick={() => {
  824 + setSubmitBtnLoading(true);
  825 + props.submit();
  826 + }}
  827 + >
  828 + 提交
835 829 </Button>,
836 830 ],
837 831 }}
  832 + form={form}
  833 + autoFocusFirstInput
838 834 submitTimeout={2000}
839 835 onFinish={async (values) => {
840 836 let res = {};
... ...
src/pages/Order/OrderWarning/components/OrderDrawer.tsx
... ... @@ -11,6 +11,10 @@ import {
11 11 postKingdeeRepMaterialUnit,
12 12 postKingdeeRepMeasureUnit,
13 13 postPrepaidPhoneAvailableList,
  14 + postResearchGroupsNameSet,
  15 + postServiceConstCompanyType,
  16 + postServiceConstOrderSource,
  17 + postServiceConstPlatformType,
14 18 postServiceOrderAddOrder,
15 19 postServiceOrderAfterSalesQuerySnapshotOrder,
16 20 postServiceOrderApplyAfterSales,
... ... @@ -28,17 +32,21 @@ import { getTeacherCustomFieldNumber } from &#39;@/utils/kingdee&#39;;
28 32 import { getSalesCodeOptions } from '@/utils/order';
29 33 import { getDefaultString } from '@/utils/StringUtil';
30 34 import {
31   - DrawerForm,
32 35 FormListActionType,
  36 + ModalForm,
33 37 ProCard,
  38 + ProFormDatePicker,
34 39 ProFormDateTimePicker,
  40 + ProFormDependency,
35 41 ProFormDigit,
36 42 ProFormList,
  43 + ProFormRadio,
37 44 ProFormSelect,
38 45 ProFormText,
39 46 ProFormTextArea,
40 47 ProFormUploadDragger,
41 48 } from '@ant-design/pro-components';
  49 +import { Group } from '@ant-design/pro-form';
42 50 import { Button, Form, message, Modal } from 'antd';
43 51 import { cloneDeep } from 'lodash';
44 52 import { useEffect, useRef, useState } from 'react';
... ... @@ -48,15 +56,15 @@ import {
48 56 INVOCING_STATUS_OPTIONS_OLD,
49 57 PAYEE_OPTIONS,
50 58 PAYMENT_CHANNEL_OPTIONS,
51   - PAYMENT_METHOD_OPTIONS,
  59 + PAYMENT_METHOD_OPTIONS_4_ADD,
52 60 PRODUCT_BELONG_DEPARTMENT_OPTIONS,
53 61 SHIPPING_WAREHOUSE_OPTIONS,
54   -} from '../../constant';
  62 +} from '../constant';
55 63 import KingdeeCustomerModal from './KingdeeCustomerModal';
56 64  
57 65 export default ({ onClose, data, subOrders, orderOptType }) => {
58 66 const [invoicingStatus, setInvoicingStatus] = useState('');
59   - const [salesCodeOptions] = useState([]);
  67 + const [salesCodeOptions, setSalesCodeOptions] = useState([]);
60 68 const [submitBtnLoading, setSubmitBtnLoading] = useState(false);
61 69 const [drawerTitle, setDrawerTitle] = useState('');
62 70 const [hasLocalData, setHasLocalData] = useState(false);
... ... @@ -80,41 +88,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
80 88 const [district, setDistrict] = useState('');
81 89 // const [productCustomerContactOptions, setProductCustomerContactOptions] =
82 90 // useState([]); //客户的收货人选项
83   - const [form] = Form.useForm<{
84   - isLocalData: boolean;
85   - salesCode: '';
86   - customerName: '';
87   - customerContactNumber: '';
88   - institution: '';
89   - institutionContactName: '';
90   - customerShippingAddress: '';
91   - totalPayment: '';
92   - paymentChannel: '';
93   - paymentMethod: '';
94   - productBelongBusiness: '';
95   - invoicingStatus: '';
96   - invoiceIdentificationNumber: '';
97   - invoicingTime: '';
98   - bank: '';
99   - bankAccountNumber: '';
100   - deleteSubOrderLists: [];
101   - filePaths: [];
102   - notes: '';
103   - invoiceFirst: boolean;
104   - list: [
105   - {
106   - productCode: '';
107   - productName: '';
108   - quantity: '';
109   - productPrice: '';
110   - parameters: '';
111   - subOrderPayment: '';
112   - unit: '';
113   - serialNumber: '';
114   - notes: '';
115   - },
116   - ];
117   - }>();
  91 + const [form] = Form.useForm();
118 92 const [accountOptions, setAccountOptions] = useState<any>([]);
119 93  
120 94 let copyData = cloneDeep(data);
... ... @@ -134,7 +108,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
134 108 */
135 109 const loadSalesCodeOptions = async () => {
136 110 let options = await getSalesCodeOptions();
137   - console.log('options ', JSON.stringify(options));
  111 + setSalesCodeOptions(options);
  112 +
138 113 if (optType('copy') || optType('edit')) {
139 114 let includeFlag = false;
140 115 //销售代码校验,如果是旧的销售代码,则提示并清空
... ... @@ -623,6 +598,21 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
623 598 form.setFieldValue('totalPayment', totalPayment);
624 599 }
625 600  
  601 + /*function computeTotalPayment() {
  602 + let list = form.getFieldValue('list');
  603 + let totalPaymentInMicro = 0; // 以"1 万分"为单位计算
  604 +
  605 + list?.forEach((subOrder: any) => {
  606 + let subOrderPayment = subOrder?.subOrderPayment;
  607 + if (subOrderPayment !== '' && subOrderPayment !== undefined) {
  608 + totalPaymentInMicro += Math.round(subOrderPayment * 10000); // 转换成整数(1 万分)
  609 + }
  610 + });
  611 +
  612 + let totalPayment = totalPaymentInMicro / 10000; // 计算完后转换回元
  613 + form.setFieldValue('totalPayment', totalPayment.toFixed(2)); // 保留 4 位小数
  614 + }*/
  615 +
626 616 /**
627 617 * 检查用户额度
628 618 * @param option
... ... @@ -751,18 +741,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
751 741 }
752 742 }
753 743  
754   - const validateContactNumber = (_: any, value: any) => {
755   - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
756   - const phoneRegex = /^\d{1,11}(-\d{1,11})?$/;
757   -
758   - if (emailRegex.test(value) || phoneRegex.test(value)) {
759   - return Promise.resolve();
760   - }
761   - return Promise.reject(
762   - new Error('联系方式必须是邮箱或手机号格式(不能包含空格等特殊符号)'),
763   - );
764   - };
765   -
766 744 /**
767 745 * 刪除草稿数据
768 746 */
... ... @@ -782,22 +760,14 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
782 760  
783 761 return (
784 762 <>
785   - <DrawerForm<{
  763 + <ModalForm<{
786 764 isLocalData: any;
787 765 deleteSubOrderLists: any;
788 766 name: string;
789 767 company: string;
790 768 }>
791 769 open
792   - width="35%"
793   - title={drawerTitle}
794   - resize={{
795   - onResize() {
796   - console.log('resize!');
797   - },
798   - maxWidth: window.innerWidth * 0.8,
799   - minWidth: 400,
800   - }}
  770 + width={1000}
801 771 onFinishFailed={() => {
802 772 message.error('表单项存在错误,请检查');
803 773 setSubmitBtnLoading(false);
... ... @@ -841,21 +811,27 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
841 811 }}
842 812 form={form}
843 813 autoFocusFirstInput
844   - drawerProps={{
  814 + modalProps={{
845 815 destroyOnClose: true,
846   - maskClosable: false,
847   - extra: [
848   - <Button
849   - key="useLocalData"
850   - hidden={!hasLocalData}
851   - type="link"
852   - onClick={() => {
853   - useLocalFormData();
854   - }}
  816 + maskClosable: true,
  817 + title: (
  818 + <div
  819 + style={{ display: 'flex', alignItems: 'center', width: '100%' }}
855 820 >
856   - 使用草稿
857   - </Button>,
858   - ],
  821 + <span>{drawerTitle}</span>
  822 + {hasLocalData && (
  823 + <Button
  824 + key="useLocalData"
  825 + type="link"
  826 + onClick={() => {
  827 + useLocalFormData();
  828 + }}
  829 + >
  830 + 使用草稿
  831 + </Button>
  832 + )}
  833 + </div>
  834 + ),
859 835 }}
860 836 submitTimeout={2000}
861 837 onFinish={async (values) => {
... ... @@ -869,11 +845,46 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
869 845 });
870 846 return item;
871 847 });
872   -
  848 + list = list.map((item, index) => {
  849 + // //记录部门修改时间
  850 + if (
  851 + optType('edit') &&
  852 + copyData?.subOrderInformationLists[index]
  853 + ?.productBelongBusiness &&
  854 + item.productBelongBusiness !==
  855 + copyData?.subOrderInformationLists[index]?.productBelongBusiness
  856 + ) {
  857 + const date = new Date();
  858 + const year = date.getFullYear();
  859 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1
  860 + const day = String(date.getDate()).padStart(2, '0');
  861 + const hours = String(date.getHours()).padStart(2, '0');
  862 + const minutes = String(date.getMinutes()).padStart(2, '0');
  863 + const seconds = String(date.getSeconds()).padStart(2, '0');
  864 +
  865 + const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  866 + values.productBelongBusinessUpdateTime = formattedDate;
  867 + } else if (optType('add') || optType('copy')) {
  868 + const date = new Date();
  869 + const year = date.getFullYear();
  870 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1
  871 + const day = String(date.getDate()).padStart(2, '0');
  872 + const hours = String(date.getHours()).padStart(2, '0');
  873 + const minutes = String(date.getMinutes()).padStart(2, '0');
  874 + const seconds = String(date.getSeconds()).padStart(2, '0');
  875 + const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  876 + values.productBelongBusinessUpdateTime = formattedDate;
  877 + } else {
  878 + values.productBelongBusinessUpdateTime =
  879 + data.productBelongBusinessUpdateTime;
  880 + }
  881 + return item;
  882 + });
873 883 values.list = list;
874 884 values.institution = values.institution?.trim();
875 885 values.institutionContactName = values.institutionContactName?.trim();
876 886 values.customerName = values.customerNameString.trim();
  887 +
877 888 // values.customerShippingAddress =
878 889 // province + city + district + values.customerShippingAddress;
879 890  
... ... @@ -907,7 +918,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
907 918 });
908 919 let diff = originIds.filter((item) => !curIds.includes(item));
909 920 values.deleteSubOrderLists = diff;
910   -
911 921 if (optType('edit')) {
912 922 values.province = province;
913 923 values.city = city;
... ... @@ -1129,7 +1139,10 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1129 1139 console.log(form.getFieldValue('id'));
1130 1140 if (form.getFieldValue('id') !== undefined) {
1131 1141 const resp = await postDistrictSelOrderProvince({
1132   - data: form.getFieldValue('id'),
  1142 + data: {
  1143 + oId: form.getFieldValue('id'),
  1144 + orderType: orderOptType,
  1145 + },
1133 1146 });
1134 1147 if (resp && resp.data) {
1135 1148 if (resp.data.province) {
... ... @@ -1193,10 +1206,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1193 1206 loadAccountOptions(v.target.value);
1194 1207 },
1195 1208 }}
1196   - rules={[
1197   - { required: true, message: '联系方式必填' },
1198   - { validator: validateContactNumber },
1199   - ]}
  1209 + rules={[{ required: true, message: '联系方式必填' }]}
1200 1210 />
1201 1211 <ProFormText
1202 1212 width="lg"
... ... @@ -1206,45 +1216,163 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1206 1216 placeholder="请输入单位"
1207 1217 rules={[{ required: true, message: '单位必填' }]}
1208 1218 />
1209   - <ProFormText
  1219 + {/*<ProFormText
1210 1220 width="lg"
1211 1221 key="institutionContactName"
1212 1222 name="institutionContactName"
1213 1223 label="课题组"
1214 1224 placeholder="请输入课题组"
1215 1225 rules={[{ required: true, message: '课题组必填' }]}
1216   - />
1217   - {/*<ProFormSelect
1218   - key={'institutionContactName'}
  1226 + />*/}
  1227 + <Group>
  1228 + <ProFormSelect
  1229 + request={async () => {
  1230 + const res = await postServiceConstCompanyType();
  1231 + return Object.entries(res?.data).map(([value, label]) => ({
  1232 + label,
  1233 + value,
  1234 + }));
  1235 + }}
1219 1236 width="md"
1220   - showSearch
1221   - name="institutionContactName"
1222   - rules={[{ required: true, message: '请输入课题组名称!' }]}
1223   - request={async (value) => {
1224   - const keywords = value.keyWords;
1225   - const res = await postResearchGroupsNameSet({
1226   - data: {
1227   - groupName: keywords,
1228   - },
1229   - });
1230   - let options = res?.data?.map((c: any) => {
1231   - return {
1232   - label: c,
1233   - value: c,
1234   - key: c,
1235   - };
1236   - });
1237   - return options;
  1237 + onChange={() => {
  1238 + form.setFieldValue('platformType', '');
1238 1239 }}
1239   - fieldProps={{
1240   - filterOption() {
1241   - return true;
1242   - },
  1240 + rules={[{ required: true, message: '单位类型必填' }]}
  1241 + name="companyType"
  1242 + label="单位类型"
  1243 + />
  1244 + <ProFormDependency name={['companyType']}>
  1245 + {({ companyType }) => {
  1246 + const renderInstitutionContactName = () => (
  1247 + <>
  1248 + <ProFormSelect
  1249 + key="institutionContactName"
  1250 + width="md"
  1251 + showSearch
  1252 + name="institutionContactName"
  1253 + rules={[{ required: true, message: '请输入课题组名称!' }]}
  1254 + request={async (value) => {
  1255 + const keywords = value?.keyWords || '';
  1256 + const res = await postResearchGroupsNameSet({
  1257 + data: { status: 'ADD_AUDIT_PASS', groupName: keywords },
  1258 + });
  1259 + return Object.entries(res?.data || {}).map(
  1260 + ([researchGroupsId, researchGroupsName]) => ({
  1261 + label: researchGroupsName,
  1262 + value: researchGroupsName, // 使用 researchGroupsId 作为 value
  1263 + key: researchGroupsId,
  1264 + id: researchGroupsId,
  1265 + }),
  1266 + );
  1267 + }}
  1268 + fieldProps={{
  1269 + filterOption: () => true,
  1270 + onChange: (_, option) => {
  1271 + form.setFieldsValue({
  1272 + researchGroupId: option?.id || '',
  1273 + });
  1274 + },
  1275 + }}
  1276 + debounceTime={1000}
  1277 + label="课题组名称"
  1278 + placeholder="请输入名称"
  1279 + />
  1280 + <ProFormText
  1281 + hidden={true}
  1282 + key="researchGroupId"
  1283 + name="researchGroupId"
  1284 + ></ProFormText>
  1285 + </>
  1286 + );
  1287 + const renderPlatformType = (fieldKey) => (
  1288 + <ProFormSelect
  1289 + key={fieldKey}
  1290 + width="md"
  1291 + showSearch
  1292 + name="platformType"
  1293 + rules={[{ required: true, message: '请选择平台类型!' }]}
  1294 + request={async () => {
  1295 + const res = await postServiceConstPlatformType({
  1296 + query: { companyType },
  1297 + });
  1298 + return Object.entries(res?.data).map(([value, label]) => ({
  1299 + label,
  1300 + value,
  1301 + }));
  1302 + }}
  1303 + fieldProps={{
  1304 + filterOption: (input, option) =>
  1305 + option?.label.toLowerCase().includes(input.toLowerCase()), // 自定义搜索过滤逻辑
  1306 + }}
  1307 + debounceTime={1000}
  1308 + label="平台类型"
  1309 + placeholder="请输入平台类型"
  1310 + />
  1311 + );
  1312 +
  1313 + if (companyType === 'school') {
  1314 + return renderInstitutionContactName();
  1315 + } else if (
  1316 + ['firm', 'ECommercePlatform', 'otherPlatform'].includes(
  1317 + companyType,
  1318 + )
  1319 + ) {
  1320 + return (
  1321 + <Group>
  1322 + {['ECommercePlatform', 'otherPlatform'].includes(
  1323 + companyType,
  1324 + ) && renderPlatformType(`platformType_${companyType}`)}
  1325 + <ProFormText
  1326 + width="md"
  1327 + name="institutionContactName"
  1328 + label="课题组名称"
  1329 + placeholder="请输入名称"
  1330 + />
  1331 + </Group>
  1332 + );
  1333 + } else if (companyType === 'officialWebsite') {
  1334 + return (
  1335 + <Group>
  1336 + <ProFormSelect
  1337 + request={async () => {
  1338 + const res = await postServiceConstOrderSource();
  1339 + return Object.entries(res?.data).map(
  1340 + ([value, label]) => ({
  1341 + label,
  1342 + value,
  1343 + }),
  1344 + );
  1345 + }}
  1346 + width="md"
  1347 + name="orderSource"
  1348 + label="订单来源"
  1349 + />
  1350 + <ProFormDependency name={['orderSource']}>
  1351 + {({ orderSource }) => {
  1352 + if (orderSource === 'school') {
  1353 + return renderInstitutionContactName();
  1354 + } else if (orderSource === 'company') {
  1355 + return (
  1356 + <ProFormText
  1357 + width="md"
  1358 + name="institutionContactName"
  1359 + label="课题组名称"
  1360 + placeholder="请输入名称"
  1361 + />
  1362 + );
  1363 + }
  1364 + return null;
  1365 + }}
  1366 + </ProFormDependency>
  1367 + </Group>
  1368 + );
  1369 + } else {
  1370 + return renderInstitutionContactName();
  1371 + }
1243 1372 }}
1244   - debounceTime={1000}
1245   - label="课题组名称"
1246   - placeholder="请输入名称"
1247   - />*/}
  1373 + </ProFormDependency>
  1374 + </Group>
  1375 +
1248 1376 <div
1249 1377 style={{
1250 1378 display: 'flex',
... ... @@ -1315,7 +1443,10 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1315 1443 console.log(form.getFieldValue('id'));
1316 1444 if (form.getFieldValue('id')) {
1317 1445 const resp = await postDistrictSelOrderProvince({
1318   - data: form.getFieldValue('id'),
  1446 + data: {
  1447 + oId: form.getFieldValue('id'),
  1448 + orderType: orderOptType,
  1449 + },
1319 1450 });
1320 1451 if (
1321 1452 resp.data.province !== null &&
... ... @@ -1375,7 +1506,10 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1375 1506 let districtOptions = [];
1376 1507 if (form.getFieldValue('id')) {
1377 1508 const resp = await postDistrictSelOrderProvince({
1378   - data: form.getFieldValue('id'),
  1509 + data: {
  1510 + oId: form.getFieldValue('id'),
  1511 + orderType: orderOptType,
  1512 + },
1379 1513 });
1380 1514 if (resp.data.city !== null && resp.data.city !== undefined) {
1381 1515 let res = await postDistrictSelectByNameAndLevel({
... ... @@ -1477,7 +1611,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1477 1611 onChange={(val: any) => {
1478 1612 setPaymentMethod(val);
1479 1613 }}
1480   - options={enumToSelect(PAYMENT_METHOD_OPTIONS)}
  1614 + options={enumToSelect(PAYMENT_METHOD_OPTIONS_4_ADD)}
1481 1615 rules={[{ required: true, message: '支付方式必填' }]}
1482 1616 disabled={optType('after-sales-check')}
1483 1617 />
... ... @@ -1561,7 +1695,34 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1561 1695 form.setFieldValue('invoiceFirst', false);
1562 1696 }
1563 1697 }}
1564   - rules={[{ required: true, message: '是否需要开票必填' }]}
  1698 + rules={[
  1699 + { required: true, message: '是否需要开票必填' },
  1700 + {
  1701 + validator: (_, value) => {
  1702 + // 自定义校验逻辑
  1703 + if (
  1704 + form.getFieldValue('paymentMethod') ===
  1705 + 'WITHHOLDING_ADVANCE_DEPOSIT' &&
  1706 + value !== 'UN_INVOICE'
  1707 + ) {
  1708 + return Promise.reject('扣预存订单不能开票');
  1709 + }
  1710 + return Promise.resolve();
  1711 + },
  1712 + },
  1713 + {
  1714 + validator: (_, value) => {
  1715 + // 自定义校验逻辑
  1716 + if (
  1717 + form.getFieldValue('totalPayment') === 0 &&
  1718 + value !== 'UN_INVOICE'
  1719 + ) {
  1720 + return Promise.reject('金额为0订单不能开票');
  1721 + }
  1722 + return Promise.resolve();
  1723 + },
  1724 + },
  1725 + ]}
1565 1726 />
1566 1727 <ProFormSelect
1567 1728 placeholder="是否开票后发货"
... ... @@ -1750,6 +1911,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1750 1911 value: listMeta?.record?.materialId,
1751 1912 }}
1752 1913 fieldProps={{
  1914 + popupMatchSelectWidth: false,
  1915 + listHeight: 400,
  1916 + dropdownStyle: { width: '55%' },
1753 1917 filterOption() {
1754 1918 return true;
1755 1919 },
... ... @@ -1946,6 +2110,76 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1946 2110 rules={[{ required: true, message: '所属事业部必填' }]}
1947 2111 disabled={optType('after-sales-check')}
1948 2112 />,
  2113 +
  2114 + <Group key="selfDevelop">
  2115 + <ProFormRadio.Group
  2116 + key="selfDevelop"
  2117 + name="selfDevelop"
  2118 + label="是否自研产品"
  2119 + initialValue={false}
  2120 + options={[
  2121 + {
  2122 + label: '是',
  2123 + value: true,
  2124 + },
  2125 + {
  2126 + label: '否',
  2127 + value: false,
  2128 + },
  2129 + ]}
  2130 + rules={[{ required: true, message: '是否自研产品必填' }]}
  2131 + />
  2132 + <ProFormDependency name={['selfDevelop']}>
  2133 + {({ selfDevelop }) => {
  2134 + if (selfDevelop) {
  2135 + return (
  2136 + <ProFormDatePicker
  2137 + name="deliveryDatetime"
  2138 + label="产品交期(填写前请先与工程师沟通)"
  2139 + rules={[
  2140 + { required: true, message: '产品交期必填' },
  2141 + ]}
  2142 + />
  2143 + );
  2144 + }
  2145 + }}
  2146 + </ProFormDependency>
  2147 + </Group>,
  2148 + <ProFormRadio.Group
  2149 + key="proxy"
  2150 + name="proxy"
  2151 + label="是否代买代购"
  2152 + //hidden={true}
  2153 + initialValue={true}
  2154 + options={[
  2155 + {
  2156 + label: '是',
  2157 + value: true,
  2158 + },
  2159 + {
  2160 + label: '否',
  2161 + value: false,
  2162 + },
  2163 + ]}
  2164 + />,
  2165 + <ProFormRadio.Group
  2166 + key="discount"
  2167 + name="discount"
  2168 + label="是否竞标/打折"
  2169 + //hidden={true}
  2170 + initialValue={true}
  2171 + options={[
  2172 + {
  2173 + label: '是',
  2174 + value: true,
  2175 + },
  2176 + {
  2177 + label: '否',
  2178 + value: false,
  2179 + },
  2180 + ]}
  2181 + />,
  2182 +
1949 2183 <ProFormSelect
1950 2184 key={'shippingWarehouse' + listMeta.index}
1951 2185 placeholder="请选择发货仓库"
... ... @@ -1997,7 +2231,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1997 2231 }}
1998 2232 actionRef={actionRef}
1999 2233 ></ProFormList>
2000   - </DrawerForm>
  2234 + </ModalForm>
2001 2235 {kingdeeCstomerModalVisible && (
2002 2236 <KingdeeCustomerModal
2003 2237 setVisible={setKingdeeCstomerModalVisible}
... ...
src/pages/ResearchGroup/components/AuditModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/AuditModal.tsx
src/pages/ResearchGroup/components/ImportModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/ImportModal.tsx
src/pages/ResearchGroup/components/PointsExchangeModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/PointsExchangeModal.tsx
src/pages/ResearchGroup/components/PointsExchangeRecordsModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/PointsExchangeRecordsModal.tsx
src/pages/ResearchGroup/components/ResearchGroupAddModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/ResearchGroupAddModal.tsx
src/pages/ResearchGroup/components/ResearchGroupMemberRequestAddModal.tsx renamed to src/pages/ResearchGroup/ResearchGroup/components/ResearchGroupMemberRequestAddModal.tsx
1 1 import { RESPONSE_CODE } from '@/constants/enum';
2 2 import {
3   - postCanrdApiUserAddressList, postCanrdApiUserList,
  3 + postCanrdApiUserAddressList,
  4 + postCanrdApiUserList,
4 5 postResearchGroupMemberRequestsAdd,
5 6 postResearchGroupMemberRequestsDetail,
6 7 postResearchGroupMemberRequestsEdit,
... ... @@ -25,7 +26,7 @@ import { useEffect, useState } from &#39;react&#39;;
25 26 import '../index.less';
26 27  
27 28 // import { cloneDeep } from 'lodash';
28   -export default ({ setVisible, requestId, onClose,type }) => {
  29 +export default ({ setVisible, requestId, onClose, type }) => {
29 30 const [form] = Form.useForm();
30 31 const [memberOptions, setMemberOptions] = useState<any[]>([]);
31 32 const [requestInfo, setRequestInfo] = useState<any>(null);
... ... @@ -201,7 +202,7 @@ export default ({ setVisible, requestId, onClose,type }) =&gt; {
201 202 }
202 203 values.members = memberObjs;
203 204 }
204   -//预存账号对象封装
  205 + //预存账号对象封装
205 206 if (values.accounts) {
206 207 let accountObjs: any[] = [];
207 208 for (let accountOption of accountOptions) {
... ... @@ -349,214 +350,215 @@ export default ({ setVisible, requestId, onClose,type }) =&gt; {
349 350 }}
350 351 />
351 352 </ProForm.Group>
352   - {type==='ADD_ACCOUNT'&&
  353 + {type === 'ADD_ACCOUNT' && (
  354 + <ProFormSelect
  355 + name="accounts"
  356 + key="accounts"
  357 + width="lg"
  358 + showSearch
  359 + label="绑定预存账号(可多选)"
  360 + placeholder="请选择预存账号"
  361 + onChange={(_, option) => {
  362 + autoAccountSelectOptions(option);
  363 + }}
  364 + //rules={[{ required: true, message: '请至少选择绑定一个预存账号' }]}
  365 + fieldProps={{
  366 + mode: 'multiple',
  367 + filterOption() {
  368 + return true;
  369 + },
  370 + optionItemRender(item: any) {
  371 + let name =
  372 + item.label +
  373 + ' | ' +
  374 + item.institution +
  375 + ' | ' +
  376 + item.nowMoney +
  377 + '¥' +
  378 + ' | ' +
  379 + item.phone;
  380 + return (
  381 + <div title={name}>
  382 + <span style={{ color: '#333333' }}>{name}</span>
  383 + </div>
  384 + );
  385 + },
  386 + }}
  387 + rules={[{ required: true, message: '请至少添加一个账号' }]}
  388 + debounceTime={1000}
  389 + request={async (value, {}) => {
  390 + const keywords = value.keyWords;
  391 + let body = {
  392 + keywords: keywords,
  393 + pageSize: 20,
  394 + researchGroupId: undefined,
  395 + };
  396 +
  397 + if (requestCount === 1) {
  398 + body.researchGroupId = form.getFieldValue('groupId');
  399 + }
  400 +
  401 + const res = await postCanrdApiUserList({
  402 + data: body,
  403 + });
  404 + let options = res?.data?.data?.map((c: any) => {
  405 + return {
  406 + ...c,
  407 + label: c.realName,
  408 + value: c.uid,
  409 + key: c.uid,
  410 + };
  411 + });
  412 +
  413 + setRequestCount(requestCount + 1);
  414 + return options;
  415 + }}
  416 + />
  417 + )}
  418 + {type !== 'ADD_ACCOUNT' && (
  419 + <>
353 420 <ProFormSelect
354   - name="accounts"
355   - key="accounts"
356   - width="lg"
357   - showSearch
358   - label="绑定预存账号(可多选)"
359   - placeholder="请选择预存账号"
360   - onChange={(_, option) => {
361   - autoAccountSelectOptions(option);
362   - }}
363   - //rules={[{ required: true, message: '请至少选择绑定一个预存账号' }]}
364   - fieldProps={{
365   - mode: 'multiple',
366   - filterOption() {
367   - return true;
368   - },
369   - optionItemRender(item: any) {
370   - let name =
371   - item.label +
372   - ' | ' +
373   - item.institution +
374   - ' | ' +
375   - item.nowMoney +
376   - '¥' +
377   - ' | ' +
378   - item.phone;
379   - return (
380   - <div title={name}>
381   - <span style={{ color: '#333333' }}>{name}</span>
382   - </div>
383   - );
384   - },
385   - }}
386   - rules={[{ required: true, message: '请至少添加一个账号' }]}
387   - debounceTime={1000}
388   - request={async (value, {}) => {
389   - const keywords = value.keyWords;
390   - let body = {
391   - keywords: keywords,
392   - pageSize: 20,
393   - researchGroupId: undefined,
394   - };
395   -
396   - if (requestCount === 1) {
397   - body.researchGroupId = form.getFieldValue('groupId');
398   - }
399   -
400   - const res = await postCanrdApiUserList({
401   - data: body,
402   - });
403   - let options = res?.data?.data?.map((c: any) => {
404   - return {
405   - ...c,
406   - label: c.realName,
407   - value: c.uid,
408   - key: c.uid,
409   - };
410   - });
411   -
412   - setRequestCount(requestCount + 1);
413   - return options;
414   - }}
  421 + name="members"
  422 + key="members"
  423 + width="lg"
  424 + showSearch
  425 + label="课题组成员"
  426 + placeholder="请添加课题组成员"
  427 + rules={[{ required: true, message: '请至少添加一个成员' }]}
  428 + fieldProps={{
  429 + mode: 'multiple',
  430 + filterOption() {
  431 + return true;
  432 + },
  433 + optionItemRender(item: any) {
  434 + let name = item.realName + ' | ' + item.phone;
  435 + return (
  436 + <div title={name}>
  437 + <span style={{ color: '#333333' }}>{name}</span>
  438 + </div>
  439 + );
  440 + },
  441 + }}
  442 + options={memberOptions}
415 443 />
416   - }
417   - {
418   - type!=='ADD_ACCOUNT'&&
419   - <>
420   - <ProFormSelect
421   - name="members"
422   - key="members"
423   - width="lg"
424   - showSearch
425   - label="课题组成员"
426   - placeholder="请添加课题组成员"
427   - rules={[{ required: true, message: '请至少添加一个成员' }]}
428   - fieldProps={{
429   - mode: 'multiple',
430   - filterOption() {
431   - return true;
432   - },
433   - optionItemRender(item: any) {
434   - let name = item.realName + ' | ' + item.phone;
435   - return (
436   - <div title={name}>
437   - <span style={{ color: '#333333' }}>{name}</span>
  444 +
  445 + <ProCard
  446 + title="选择或自定义课题组成员信息"
  447 + bordered
  448 + tooltip="从【客户信息】选择框中可以直接搜索客户,选中后自动添加到【课题组成员】中。也可以自定义输入【客户名称】和【手机号】,点击添加按钮手动添加到【课题组成员】中。"
  449 + >
  450 + <ProForm.Group>
  451 + <ProFormSelect
  452 + key="customerName"
  453 + label="客户信息(选择)"
  454 + width="lg"
  455 + showSearch
  456 + name="customerName"
  457 + placeholder="请选择客户信息"
  458 + onChange={(_, option) => {
  459 + autoFillCustomerInfo(option);
  460 + }}
  461 + fieldProps={{
  462 + filterOption() {
  463 + return true;
  464 + },
  465 + optionItemRender(item: any) {
  466 + if (item.type === 'add') {
  467 + return (
  468 + <div title={item.name + '(新增客户)'}>
  469 + <span style={{ color: '#333333' }}>
  470 + {item.name}
  471 + </span>
  472 + {' | '}
  473 + <span style={{ color: 'orange' }}>自定义</span>
  474 + </div>
  475 + );
  476 + }
  477 +
  478 + let title = '';
  479 + let spanText = '';
  480 + let realName = item.realName;
  481 + let phone = item.phone;
  482 +
  483 + title =
  484 + getDefaultString(realName) +
  485 + '|' +
  486 + getDefaultString(phone);
  487 +
  488 + spanText =
  489 + getDefaultString(realName) +
  490 + '|' +
  491 + getDefaultString(phone);
  492 + return (
  493 + <div title={title}>
  494 + <span style={{ color: '#333333' }}>{spanText}</span>
438 495 </div>
439   - );
440   - },
  496 + );
  497 + },
  498 + }}
  499 + debounceTime={1000}
  500 + request={async (value, {}) => {
  501 + const keywords = value.keyWords;
  502 + if (keywords === '') {
  503 + return [];
  504 + }
  505 + const res = await postCanrdApiUserAddressList({
  506 + data: { keywords: keywords },
  507 + });
  508 + let options = res?.data?.map((c: any) => {
  509 + return {
  510 + ...c,
  511 + label: c.name,
  512 + value: c.id,
  513 + key: c.id,
  514 + };
  515 + });
  516 +
  517 + //对options去重,realName和phone唯一
  518 + options = deduplicateOptions(options);
  519 +
  520 + //第一个商品默认为要新增客户
  521 + if (keywords.trim() !== '') {
  522 + options.unshift({
  523 + name: keywords,
  524 + type: 'add',
  525 + label: keywords,
  526 + value: 3.1415926,
  527 + key: keywords,
  528 + });
  529 + }
  530 +
  531 + return options;
  532 + }}
  533 + />
  534 + </ProForm.Group>
  535 +
  536 + <ProForm.Group>
  537 + <ProFormText
  538 + name="realName"
  539 + label="客户名称(自定义)"
  540 + placeholder="请输入客户名称"
  541 + rules={[{ required: false, message: '请输入客户名称' }]}
  542 + />
  543 + <ProFormText
  544 + name="phone"
  545 + label="手机号(自定义)"
  546 + width="md"
  547 + placeholder="请输入手机号"
  548 + rules={[{ required: false, message: '请输入手机号' }]}
  549 + />
  550 + </ProForm.Group>
  551 + <Button
  552 + type="primary"
  553 + onClick={() => {
  554 + addCustomMember();
441 555 }}
442   - options={memberOptions}
443   - />
444   -
445   - <ProCard
446   - title="选择或自定义课题组成员信息"
447   - bordered
448   - tooltip="从【客户信息】选择框中可以直接搜索客户,选中后自动添加到【课题组成员】中。也可以自定义输入【客户名称】和【手机号】,点击添加按钮手动添加到【课题组成员】中。"
449 556 >
450   - <ProForm.Group>
451   - <ProFormSelect
452   - key="customerName"
453   - label="客户信息(选择)"
454   - width="lg"
455   - showSearch
456   - name="customerName"
457   - placeholder="请选择客户信息"
458   - onChange={(_, option) => {
459   - autoFillCustomerInfo(option);
460   - }}
461   - fieldProps={{
462   - filterOption() {
463   - return true;
464   - },
465   - optionItemRender(item: any) {
466   - if (item.type === 'add') {
467   - return (
468   - <div title={item.name + '(新增客户)'}>
469   - <span style={{ color: '#333333' }}>{item.name}</span>
470   - {' | '}
471   - <span style={{ color: 'orange' }}>自定义</span>
472   - </div>
473   - );
474   - }
475   -
476   - let title = '';
477   - let spanText = '';
478   - let realName = item.realName;
479   - let phone = item.phone;
480   -
481   - title =
482   - getDefaultString(realName) +
483   - '|' +
484   - getDefaultString(phone);
485   -
486   - spanText =
487   - getDefaultString(realName) +
488   - '|' +
489   - getDefaultString(phone);
490   - return (
491   - <div title={title}>
492   - <span style={{ color: '#333333' }}>{spanText}</span>
493   - </div>
494   - );
495   - },
496   - }}
497   - debounceTime={1000}
498   - request={async (value, {}) => {
499   - const keywords = value.keyWords;
500   - if (keywords === '') {
501   - return [];
502   - }
503   - const res = await postCanrdApiUserAddressList({
504   - data: { keywords: keywords },
505   - });
506   - let options = res?.data?.map((c: any) => {
507   - return {
508   - ...c,
509   - label: c.name,
510   - value: c.id,
511   - key: c.id,
512   - };
513   - });
514   -
515   - //对options去重,realName和phone唯一
516   - options = deduplicateOptions(options);
517   -
518   - //第一个商品默认为要新增客户
519   - if (keywords.trim() !== '') {
520   - options.unshift({
521   - name: keywords,
522   - type: 'add',
523   - label: keywords,
524   - value: 3.1415926,
525   - key: keywords,
526   - });
527   - }
528   -
529   - return options;
530   - }}
531   - />
532   - </ProForm.Group>
533   -
534   - <ProForm.Group>
535   - <ProFormText
536   - name="realName"
537   - label="客户名称(自定义)"
538   - placeholder="请输入客户名称"
539   - rules={[{ required: false, message: '请输入客户名称' }]}
540   - />
541   - <ProFormText
542   - name="phone"
543   - label="手机号(自定义)"
544   - width="md"
545   - placeholder="请输入手机号"
546   - rules={[{ required: false, message: '请输入手机号' }]}
547   - />
548   - </ProForm.Group>
549   - <Button
550   - type="primary"
551   - onClick={() => {
552   - addCustomMember();
553   - }}
554   - >
555   - 添加
556   - </Button>
557   - </ProCard>
558   - </>
559   - }
  557 + 添加
  558 + </Button>
  559 + </ProCard>
  560 + </>
  561 + )}
560 562  
561 563 <ProFormTextArea
562 564 name="requestNotes"
... ...
src/pages/ResearchGroup/constant.tsx renamed to src/pages/ResearchGroup/ResearchGroup/constant.tsx
src/pages/ResearchGroup/index.css renamed to src/pages/ResearchGroup/ResearchGroup/index.css
src/pages/ResearchGroup/index.less renamed to src/pages/ResearchGroup/ResearchGroup/index.less
src/pages/ResearchGroup/index.tsx renamed to src/pages/ResearchGroup/ResearchGroup/index.tsx
... ... @@ -38,7 +38,7 @@ import {
38 38 RESEARCH_GROUP_MEMBER_REQUEST_COLUMNS,
39 39 } from './constant';
40 40 import './index.less';
41   -const PrepaidPage = () => {
  41 +const ResearchGroupListPage = () => {
42 42 const researchGroupActionRef = useRef<ActionType>();
43 43 const memberApplyActionRef = useRef<ActionType>();
44 44 const [researchGroupAddModalVisible, setResearchGroupAddModalVisible] =
... ... @@ -855,4 +855,4 @@ const PrepaidPage = () =&gt; {
855 855 );
856 856 };
857 857  
858   -export default PrepaidPage;
  858 +export default ResearchGroupListPage;
... ...
src/pages/ResearchGroup/ResearchGroupAccess/components/AddModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import {
  3 + postResearchGroupsAccessAddBlackList,
  4 + postResearchGroupsAccessAddWhiteList,
  5 + postResearchGroupsList,
  6 + postResearchGroupsNameSet,
  7 +} from '@/services';
  8 +import { Form, Input, Modal, Select, message } from 'antd';
  9 +import { forwardRef, useImperativeHandle, useState } from 'react';
  10 +
  11 +import '../index.css';
  12 +
  13 +export type AddModalProps = {
  14 + setVisible: (visible: boolean) => void;
  15 +};
  16 +
  17 +export type AddModalRef = {
  18 + show: (accessType: 'WHITELIST' | 'BLACKLIST', onSuccess: () => void) => void;
  19 +};
  20 +
  21 +const AddModal = forwardRef<AddModalRef, AddModalProps>((props, ref) => {
  22 + const { setVisible } = props;
  23 + const [form] = Form.useForm();
  24 + const [visible, setModalVisible] = useState(false);
  25 + const [loading, setLoading] = useState(false);
  26 + const [accessTypeState, setAccessTypeState] = useState<
  27 + 'WHITELIST' | 'BLACKLIST'
  28 + >('WHITELIST');
  29 + const [onSuccessCallback, setOnSuccessCallback] = useState<() => void>(
  30 + () => {},
  31 + );
  32 + const [groupOptions, setGroupOptions] = useState<
  33 + { label: string; value: string; id: string }[]
  34 + >([]);
  35 + const [companyOptions, setCompanyOptions] = useState<
  36 + { label: string; value: string; id: string }[]
  37 + >([]);
  38 + const [searchLoading, setSearchLoading] = useState(false);
  39 + const [companyLoading, setCompanyLoading] = useState(false);
  40 +
  41 + useImperativeHandle(ref, () => ({
  42 + show: (accessType, onSuccess) => {
  43 + form.resetFields();
  44 + setAccessTypeState(accessType);
  45 + setOnSuccessCallback(() => onSuccess);
  46 + setModalVisible(true);
  47 + // 重置选项
  48 + setCompanyOptions([]);
  49 + setGroupOptions([]);
  50 + },
  51 + }));
  52 +
  53 + const handleCancel = () => {
  54 + setModalVisible(false);
  55 + setVisible(false);
  56 + };
  57 +
  58 + const handleOk = async () => {
  59 + try {
  60 + const values = await form.validateFields();
  61 + setLoading(true);
  62 +
  63 + const requestData = {
  64 + ...values,
  65 + accessType: accessTypeState,
  66 + };
  67 +
  68 + let res;
  69 + if (accessTypeState === 'WHITELIST') {
  70 + res = await postResearchGroupsAccessAddWhiteList({ data: requestData });
  71 + } else {
  72 + res = await postResearchGroupsAccessAddBlackList({ data: requestData });
  73 + }
  74 +
  75 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  76 + message.success('添加成功');
  77 + setModalVisible(false);
  78 + setVisible(false);
  79 + onSuccessCallback();
  80 + } else {
  81 + message.error(res?.message || '添加失败');
  82 + }
  83 + } catch (error) {
  84 + console.error('验证表单失败:', error);
  85 + } finally {
  86 + setLoading(false);
  87 + }
  88 + };
  89 +
  90 + // 搜索课题组
  91 + const handleSearch = async (value: string) => {
  92 + if (!value) return;
  93 +
  94 + try {
  95 + setSearchLoading(true);
  96 + // 完全模仿原始代码,使用data包裹参数
  97 + const res = await postResearchGroupsNameSet({
  98 + data: { status: 'ADD_AUDIT_PASS', groupName: value },
  99 + });
  100 +
  101 + if (res?.data) {
  102 + const options = Object.entries(res.data).map(
  103 + ([researchGroupsId, researchGroupsName]) => ({
  104 + label: researchGroupsName as string,
  105 + value: researchGroupsName as string,
  106 + key: researchGroupsId,
  107 + id: researchGroupsId,
  108 + }),
  109 + );
  110 + setGroupOptions(options);
  111 + }
  112 + } catch (error) {
  113 + console.error('获取课题组列表失败', error);
  114 + } finally {
  115 + setSearchLoading(false);
  116 + }
  117 + };
  118 +
  119 + // 根据课题组名称查询单位名称列表
  120 + const fetchCompanyNamesByGroupName = async (groupName: string) => {
  121 + if (!groupName) return;
  122 +
  123 + try {
  124 + setCompanyLoading(true);
  125 + // 使用postResearchGroupsList接口查询单位名称
  126 + const res = await postResearchGroupsList({
  127 + data: {
  128 + current: 1,
  129 + pageSize: 100,
  130 + groupName: groupName,
  131 + },
  132 + });
  133 +
  134 + if (res?.data?.data) {
  135 + // 提取所有相同groupName的不同companyName
  136 + const companySet = new Set<string>();
  137 + const companyIdMap = new Map<string, string>();
  138 +
  139 + // 假设接口返回数据包含列表项,每项有companyName和id
  140 + res.data.data.forEach((item: any) => {
  141 + if (item.groupName === groupName && item.companyName) {
  142 + companySet.add(item.companyName);
  143 + companyIdMap.set(item.companyName, item.id); // 保存id用于提交
  144 + }
  145 + });
  146 +
  147 + // 转换为选项格式
  148 + const companies = Array.from(companySet).map((name) => ({
  149 + label: name,
  150 + value: name,
  151 + id: companyIdMap.get(name) || '',
  152 + }));
  153 +
  154 + setCompanyOptions(companies);
  155 +
  156 + // 如果只有一个选项,自动选中
  157 + if (companies.length === 1) {
  158 + form.setFieldsValue({
  159 + companyName: companies[0].value,
  160 + groupId: companies[0].id,
  161 + });
  162 + }
  163 + }
  164 + } catch (error) {
  165 + console.error('获取单位名称列表失败', error);
  166 + } finally {
  167 + setCompanyLoading(false);
  168 + }
  169 + };
  170 +
  171 + const title =
  172 + accessTypeState === 'WHITELIST' ? '添加课题组白名单' : '添加课题组风险名单';
  173 +
  174 + return (
  175 + <Modal
  176 + title={title}
  177 + open={visible}
  178 + onOk={handleOk}
  179 + onCancel={handleCancel}
  180 + confirmLoading={loading}
  181 + maskClosable={true}
  182 + destroyOnClose
  183 + >
  184 + <Form form={form} layout="vertical" name="add_form" initialValues={{}}>
  185 + <Form.Item name="groupId" style={{ display: 'none' }}>
  186 + <Input type="hidden" />
  187 + </Form.Item>
  188 +
  189 + <Form.Item
  190 + name="groupName"
  191 + label="课题组名称"
  192 + rules={[{ required: true, message: '请输入课题组名称!' }]}
  193 + >
  194 + <Select
  195 + showSearch
  196 + placeholder="请输入名称"
  197 + filterOption={false}
  198 + onSearch={handleSearch}
  199 + loading={searchLoading}
  200 + options={groupOptions}
  201 + onChange={(value, option: any) => {
  202 + // 清空公司选项
  203 + form.setFieldsValue({
  204 + companyName: undefined,
  205 + });
  206 +
  207 + // 保存研究组ID
  208 + if (option) {
  209 + form.setFieldsValue({
  210 + groupId: option.id || '',
  211 + });
  212 +
  213 + // 触发查询关联的单位名称
  214 + fetchCompanyNamesByGroupName(value);
  215 + }
  216 + }}
  217 + />
  218 + </Form.Item>
  219 +
  220 + <Form.Item
  221 + name="companyName"
  222 + label="单位名称"
  223 + rules={[{ required: true, message: '请选择单位名称' }]}
  224 + >
  225 + <Select
  226 + placeholder="请选择单位名称"
  227 + loading={companyLoading}
  228 + options={companyOptions}
  229 + disabled={companyOptions.length === 0}
  230 + onChange={(_, option: any) => {
  231 + if (option && option.id) {
  232 + form.setFieldsValue({
  233 + groupId: option.id,
  234 + });
  235 + }
  236 + }}
  237 + />
  238 + </Form.Item>
  239 +
  240 + <Form.Item name="remark" label="添加原因">
  241 + <Input.TextArea rows={3} placeholder="请输入添加原因" />
  242 + </Form.Item>
  243 + </Form>
  244 + </Modal>
  245 + );
  246 +});
  247 +
  248 +export default AddModal;
... ...
src/pages/ResearchGroup/ResearchGroupAccess/constant.tsx 0 → 100644
  1 +import { formatDateTime } from '@/utils';
  2 +
  3 +export const RESEARCH_GROUP_ACCESS_WHITELIST_COLUMNS = [
  4 + {
  5 + title: '序号',
  6 + dataIndex: 'index',
  7 + valueType: 'index',
  8 + width: 70,
  9 + },
  10 + {
  11 + title: 'ID',
  12 + dataIndex: 'id',
  13 + key: 'id',
  14 + hideInSearch: true,
  15 + hideInTable: true,
  16 + },
  17 + {
  18 + title: '课题组名称',
  19 + dataIndex: 'groupName',
  20 + key: 'groupName',
  21 + fieldProps: {
  22 + placeholder: '请输入课题组名称',
  23 + },
  24 + },
  25 + {
  26 + title: '单位名称',
  27 + dataIndex: 'companyName',
  28 + key: 'companyName',
  29 + hideInSearch: true,
  30 + },
  31 + {
  32 + title: '添加原因',
  33 + dataIndex: 'remark',
  34 + key: 'remark',
  35 + hideInSearch: true,
  36 + },
  37 + {
  38 + title: '添加时间',
  39 + dataIndex: 'createTime',
  40 + key: 'createTime',
  41 + valueType: 'text',
  42 + hideInSearch: true,
  43 + render: (_: any, record: any) =>
  44 + record.createTime ? formatDateTime(record.createTime) : '-',
  45 + },
  46 + {
  47 + title: '添加人',
  48 + dataIndex: 'createByName',
  49 + key: 'createByName',
  50 + hideInSearch: true,
  51 + },
  52 +];
  53 +
  54 +export const RESEARCH_GROUP_ACCESS_BLACKLIST_COLUMNS = [
  55 + {
  56 + title: '序号',
  57 + dataIndex: 'index',
  58 + valueType: 'index',
  59 + width: 70,
  60 + },
  61 + {
  62 + title: 'ID',
  63 + dataIndex: 'id',
  64 + key: 'id',
  65 + hideInSearch: true,
  66 + hideInTable: true,
  67 + },
  68 + {
  69 + title: '课题组名称',
  70 + dataIndex: 'groupName',
  71 + key: 'groupName',
  72 + fieldProps: {
  73 + placeholder: '请输入课题组名称',
  74 + },
  75 + },
  76 + {
  77 + title: '单位名称',
  78 + dataIndex: 'companyName',
  79 + key: 'companyName',
  80 + hideInSearch: true,
  81 + },
  82 + {
  83 + title: '添加原因',
  84 + dataIndex: 'remark',
  85 + key: 'remark',
  86 + hideInSearch: true,
  87 + },
  88 + {
  89 + title: '添加时间',
  90 + dataIndex: 'createTime',
  91 + key: 'createTime',
  92 + valueType: 'text',
  93 + hideInSearch: true,
  94 + render: (_: any, record: any) =>
  95 + record.createTime ? formatDateTime(record.createTime) : '-',
  96 + },
  97 + {
  98 + title: '添加人',
  99 + dataIndex: 'createByName',
  100 + key: 'createByName',
  101 + hideInSearch: true,
  102 + },
  103 +];
... ...
src/pages/ResearchGroup/ResearchGroupAccess/index.css 0 → 100644
  1 +.research-group-index td,
  2 +.research-group-access-container td {
  3 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  4 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  5 + 'WenQuanYi Micro Hei', sans-serif;
  6 + font-size: 13px;
  7 +}
... ...
src/pages/ResearchGroup/ResearchGroupAccess/index.less 0 → 100644
  1 +.research-group-access-container {
  2 + width: 100%;
  3 + padding: 16px;
  4 + background-color: #fff;
  5 +
  6 + .ant-pro-table {
  7 + .ant-pro-card-body {
  8 + padding: 16px;
  9 + }
  10 + }
  11 +}
... ...
src/pages/ResearchGroup/ResearchGroupAccess/index.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { getUserInfo } from '@/utils';
  3 +import { PlusOutlined } from '@ant-design/icons';
  4 +import { ActionType, ProTable } from '@ant-design/pro-components';
  5 +import { Button, Popconfirm, Tabs, message } from 'antd';
  6 +import { useMemo, useRef, useState } from 'react';
  7 +
  8 +import {
  9 + postResearchGroupsAccessBlackList,
  10 + postResearchGroupsAccessDeleteBlackList,
  11 + postResearchGroupsAccessDeleteWhiteList,
  12 + postResearchGroupsAccessWhiteList,
  13 +} from '@/services';
  14 +
  15 +import './index.css';
  16 +import './index.less';
  17 +
  18 +import {
  19 + RESEARCH_GROUP_ACCESS_BLACKLIST_COLUMNS,
  20 + RESEARCH_GROUP_ACCESS_WHITELIST_COLUMNS,
  21 +} from './constant';
  22 +
  23 +import AddModal, { AddModalRef } from './components/AddModal';
  24 +
  25 +const ResearchGroupAccessPage = () => {
  26 + const whitelistActionRef = useRef<ActionType>();
  27 + const blacklistActionRef = useRef<ActionType>();
  28 + const [activeKey, setActiveKey] = useState<string>('1');
  29 + const addModalRef = useRef<AddModalRef>(null);
  30 +
  31 + const reloadWhitelistTable = () => {
  32 + whitelistActionRef.current?.reload();
  33 + };
  34 +
  35 + const reloadBlacklistTable = () => {
  36 + blacklistActionRef.current?.reload();
  37 + };
  38 +
  39 + const handleDeleteWhitelist = async (id: number) => {
  40 + const res = await postResearchGroupsAccessDeleteWhiteList({ data: { id } });
  41 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  42 + message.success('删除成功');
  43 + reloadWhitelistTable();
  44 + } else {
  45 + message.error(res?.message || '删除失败');
  46 + }
  47 + };
  48 +
  49 + const handleDeleteBlacklist = async (id: number) => {
  50 + const res = await postResearchGroupsAccessDeleteBlackList({ data: { id } });
  51 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  52 + message.success('删除成功');
  53 + reloadBlacklistTable();
  54 + } else {
  55 + message.error(res?.message || '删除失败');
  56 + }
  57 + };
  58 +
  59 + const handleAddClick = () => {
  60 + const accessType = activeKey === '1' ? 'WHITELIST' : 'BLACKLIST';
  61 + const onSuccess =
  62 + activeKey === '1' ? reloadWhitelistTable : reloadBlacklistTable;
  63 + addModalRef.current?.show(accessType, onSuccess);
  64 + };
  65 +
  66 + const WhitelistTab = () => {
  67 + // Check if the current user has permission to add/delete
  68 + const hasPermission = useMemo(() => {
  69 + const userInfo = getUserInfo();
  70 + return userInfo?.username === 'canrd' || userInfo?.username === 'D-Tina';
  71 + }, []);
  72 + return (
  73 + <ProTable
  74 + actionRef={whitelistActionRef}
  75 + rowKey="id"
  76 + search={{
  77 + labelWidth: 120,
  78 + defaultCollapsed: false,
  79 + }}
  80 + pagination={{
  81 + pageSize: 10,
  82 + }}
  83 + toolBarRender={() =>
  84 + hasPermission
  85 + ? [
  86 + <Button key="add" type="primary" onClick={handleAddClick}>
  87 + <PlusOutlined /> 添加
  88 + </Button>,
  89 + ]
  90 + : []
  91 + }
  92 + request={async (params) => {
  93 + const { current, pageSize, ...rest } = params;
  94 + const res = await postResearchGroupsAccessWhiteList({
  95 + data: {
  96 + current: current || 1,
  97 + pageSize: pageSize || 10,
  98 + ...rest,
  99 + },
  100 + });
  101 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  102 + return {
  103 + data: res.data?.data || [],
  104 + success: true,
  105 + total: res.data?.total || 0,
  106 + };
  107 + }
  108 + return {
  109 + data: [],
  110 + success: false,
  111 + total: 0,
  112 + };
  113 + }}
  114 + columns={[
  115 + ...RESEARCH_GROUP_ACCESS_WHITELIST_COLUMNS,
  116 + {
  117 + title: '操作',
  118 + dataIndex: 'option',
  119 + valueType: 'option',
  120 + render: (_, record) =>
  121 + hasPermission
  122 + ? [
  123 + <Popconfirm
  124 + key="delete"
  125 + title="确定要删除吗?"
  126 + onConfirm={() => handleDeleteWhitelist(record.id)}
  127 + >
  128 + <a style={{ color: '#ff4d4f' }}>删除</a>
  129 + </Popconfirm>,
  130 + ]
  131 + : [],
  132 + },
  133 + ]}
  134 + />
  135 + );
  136 + };
  137 +
  138 + const BlacklistTab = () => {
  139 + // Check if the current user has permission to add/delete
  140 + const hasPermission = useMemo(() => {
  141 + const userInfo = getUserInfo();
  142 + return userInfo?.username === 'canrd' || userInfo?.username === 'D-Tina';
  143 + }, []);
  144 + return (
  145 + <ProTable
  146 + actionRef={blacklistActionRef}
  147 + rowKey="id"
  148 + search={{
  149 + labelWidth: 120,
  150 + defaultCollapsed: false,
  151 + }}
  152 + pagination={{
  153 + pageSize: 10,
  154 + }}
  155 + toolBarRender={() =>
  156 + hasPermission
  157 + ? [
  158 + <Button key="add" type="primary" onClick={handleAddClick}>
  159 + <PlusOutlined /> 添加
  160 + </Button>,
  161 + ]
  162 + : []
  163 + }
  164 + request={async (params) => {
  165 + const { current, pageSize, ...rest } = params;
  166 + const res = await postResearchGroupsAccessBlackList({
  167 + data: {
  168 + current: current || 1,
  169 + pageSize: pageSize || 10,
  170 + ...rest,
  171 + },
  172 + });
  173 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  174 + return {
  175 + data: res.data?.data || [],
  176 + success: true,
  177 + total: res.data?.total || 0,
  178 + };
  179 + }
  180 + return {
  181 + data: [],
  182 + success: false,
  183 + total: 0,
  184 + };
  185 + }}
  186 + columns={[
  187 + ...RESEARCH_GROUP_ACCESS_BLACKLIST_COLUMNS,
  188 + {
  189 + title: '操作',
  190 + dataIndex: 'option',
  191 + valueType: 'option',
  192 + render: (_, record) =>
  193 + hasPermission
  194 + ? [
  195 + <Popconfirm
  196 + key="delete"
  197 + title="确定要删除吗?"
  198 + onConfirm={() => handleDeleteBlacklist(record.id)}
  199 + >
  200 + <a style={{ color: '#ff4d4f' }}>删除</a>
  201 + </Popconfirm>,
  202 + ]
  203 + : [],
  204 + },
  205 + ]}
  206 + />
  207 + );
  208 + };
  209 +
  210 + // 空函数保留作为回调,但不做任何操作
  211 + // eslint-disable-next-line @typescript-eslint/no-unused-vars
  212 + const setAddModalVisible = (_: boolean) => {
  213 + // 我们不再需要在父组件中跟踪模态框状态
  214 + };
  215 +
  216 + return (
  217 + <div className="research-group-index">
  218 + <Tabs
  219 + defaultActiveKey="whitelist"
  220 + onChange={setActiveKey}
  221 + items={[
  222 + {
  223 + key: 'whitelist',
  224 + label: '课题组白名单',
  225 + children: <WhitelistTab />,
  226 + },
  227 + {
  228 + key: 'blacklist',
  229 + label: '课题组风险名单',
  230 + children: <BlacklistTab />,
  231 + },
  232 + ]}
  233 + />
  234 + <AddModal ref={addModalRef} setVisible={setAddModalVisible} />
  235 + </div>
  236 + );
  237 +};
  238 +
  239 +export default ResearchGroupAccessPage;
... ...
src/services/definition.ts
... ... @@ -4099,6 +4099,79 @@ export interface ResearchGroupRequestsDto {
4099 4099 updateTime?: string;
4100 4100 }
4101 4101  
  4102 +export interface ResearchGroupsAccessDTO {
  4103 + /**
  4104 + * @description
  4105 + * 访问类型: WHITELIST, BLACKLIST
  4106 + */
  4107 + accessType?: string;
  4108 + /**
  4109 + * @description
  4110 + * 单位名称
  4111 + */
  4112 + companyName?: string;
  4113 + /**
  4114 + * @description
  4115 + * 创建人ID
  4116 + */
  4117 + createBy?: string;
  4118 + /**
  4119 + * @description
  4120 + * 创建人姓名
  4121 + */
  4122 + createByName?: string;
  4123 + /**
  4124 + * @description
  4125 + * 创建时间
  4126 + * @format date-time
  4127 + */
  4128 + createTime?: string;
  4129 + /**
  4130 + * @description
  4131 + * 删除标志
  4132 + * @format int32
  4133 + */
  4134 + deleteFlag?: number;
  4135 + /**
  4136 + * @description
  4137 + * 课题组名称
  4138 + */
  4139 + groupName?: string;
  4140 + /**
  4141 + * @description
  4142 + * 主键id
  4143 + * @format int64
  4144 + */
  4145 + id?: number;
  4146 + /**
  4147 + * @description
  4148 + * 添加原因
  4149 + */
  4150 + remark?: string;
  4151 + /**
  4152 + * @description
  4153 + * 更新人ID
  4154 + */
  4155 + updateBy?: string;
  4156 + /**
  4157 + * @description
  4158 + * 更新人姓名
  4159 + */
  4160 + updateByName?: string;
  4161 + /**
  4162 + * @description
  4163 + * 更新时间
  4164 + * @format date-time
  4165 + */
  4166 + updateTime?: string;
  4167 + /**
  4168 + * @description
  4169 + * 版本号
  4170 + * @format int32
  4171 + */
  4172 + version?: number;
  4173 +}
  4174 +
4102 4175 export interface ResearchGroupsDTO {
4103 4176 accounts?: Array<ResearchGroupAccounts>;
4104 4177 /**
... ... @@ -5609,6 +5682,13 @@ export interface SalesRechargePrepaymentUpdateRequest {
5609 5682 salesCode?: string;
5610 5683 }
5611 5684  
  5685 +export interface ServerResultTsgBoolean {
  5686 + data?: boolean;
  5687 + message?: string;
  5688 + /** @format int32 */
  5689 + result?: number;
  5690 +}
  5691 +
5612 5692 /**
5613 5693 * @description
5614 5694 * 开票添加对象
... ...
src/services/request.ts
... ... @@ -134,6 +134,7 @@ import type {
134 134 ResearchGroupMemberRequestDetailRequest,
135 135 ResearchGroupMemberRequestsRequest,
136 136 ResearchGroupRequestsDto,
  137 + ResearchGroupsAccessDTO,
137 138 ResearchGroupsDTO,
138 139 ResetPwdVO,
139 140 SalOrderSaveDto,
... ... @@ -144,6 +145,7 @@ import type {
144 145 SalesRechargePrepaymentUpdateRequest,
145 146 SaveReply,
146 147 ServerResult,
  148 + ServerResultTsgBoolean,
147 149 ShippingWarehouseChangeDto,
148 150 StoreOrderInvoiceRequest,
149 151 SysLogQueryVO,
... ... @@ -14332,6 +14334,432 @@ export const postResearchGroupMemberRequestsList = /* #__PURE__ */ (() =&gt; {
14332 14334 return request;
14333 14335 })();
14334 14336  
  14337 +/** @description request parameter type for postResearchGroupsAccessAddBlackList */
  14338 +export interface PostResearchGroupsAccessAddBlackListOption {
  14339 + /**
  14340 + * @description
  14341 + * request
  14342 + */
  14343 + body: {
  14344 + /**
  14345 + @description
  14346 + request */
  14347 + request: ResearchGroupsAccessDTO;
  14348 + };
  14349 +}
  14350 +
  14351 +/** @description response type for postResearchGroupsAccessAddBlackList */
  14352 +export interface PostResearchGroupsAccessAddBlackListResponse {
  14353 + /**
  14354 + * @description
  14355 + * OK
  14356 + */
  14357 + 200: ServerResultTsgBoolean;
  14358 + /**
  14359 + * @description
  14360 + * Created
  14361 + */
  14362 + 201: any;
  14363 + /**
  14364 + * @description
  14365 + * Unauthorized
  14366 + */
  14367 + 401: any;
  14368 + /**
  14369 + * @description
  14370 + * Forbidden
  14371 + */
  14372 + 403: any;
  14373 + /**
  14374 + * @description
  14375 + * Not Found
  14376 + */
  14377 + 404: any;
  14378 +}
  14379 +
  14380 +export type PostResearchGroupsAccessAddBlackListResponseSuccess =
  14381 + PostResearchGroupsAccessAddBlackListResponse[200];
  14382 +/**
  14383 + * @description
  14384 + * 添加黑名单
  14385 + * @tags research-groups-access-controller
  14386 + * @produces *
  14387 + * @consumes application/json
  14388 + */
  14389 +export const postResearchGroupsAccessAddBlackList = /* #__PURE__ */ (() => {
  14390 + const method = 'post';
  14391 + const url = '/research/groups/access/addBlackList';
  14392 + function request(
  14393 + option: PostResearchGroupsAccessAddBlackListOption,
  14394 + ): Promise<PostResearchGroupsAccessAddBlackListResponseSuccess> {
  14395 + return requester(request.url, {
  14396 + method: request.method,
  14397 + ...option,
  14398 + }) as unknown as Promise<PostResearchGroupsAccessAddBlackListResponseSuccess>;
  14399 + }
  14400 +
  14401 + /** http method */
  14402 + request.method = method;
  14403 + /** request url */
  14404 + request.url = url;
  14405 + return request;
  14406 +})();
  14407 +
  14408 +/** @description request parameter type for postResearchGroupsAccessAddWhiteList */
  14409 +export interface PostResearchGroupsAccessAddWhiteListOption {
  14410 + /**
  14411 + * @description
  14412 + * request
  14413 + */
  14414 + body: {
  14415 + /**
  14416 + @description
  14417 + request */
  14418 + request: ResearchGroupsAccessDTO;
  14419 + };
  14420 +}
  14421 +
  14422 +/** @description response type for postResearchGroupsAccessAddWhiteList */
  14423 +export interface PostResearchGroupsAccessAddWhiteListResponse {
  14424 + /**
  14425 + * @description
  14426 + * OK
  14427 + */
  14428 + 200: ServerResultTsgBoolean;
  14429 + /**
  14430 + * @description
  14431 + * Created
  14432 + */
  14433 + 201: any;
  14434 + /**
  14435 + * @description
  14436 + * Unauthorized
  14437 + */
  14438 + 401: any;
  14439 + /**
  14440 + * @description
  14441 + * Forbidden
  14442 + */
  14443 + 403: any;
  14444 + /**
  14445 + * @description
  14446 + * Not Found
  14447 + */
  14448 + 404: any;
  14449 +}
  14450 +
  14451 +export type PostResearchGroupsAccessAddWhiteListResponseSuccess =
  14452 + PostResearchGroupsAccessAddWhiteListResponse[200];
  14453 +/**
  14454 + * @description
  14455 + * 添加白名单
  14456 + * @tags research-groups-access-controller
  14457 + * @produces *
  14458 + * @consumes application/json
  14459 + */
  14460 +export const postResearchGroupsAccessAddWhiteList = /* #__PURE__ */ (() => {
  14461 + const method = 'post';
  14462 + const url = '/research/groups/access/addWhiteList';
  14463 + function request(
  14464 + option: PostResearchGroupsAccessAddWhiteListOption,
  14465 + ): Promise<PostResearchGroupsAccessAddWhiteListResponseSuccess> {
  14466 + return requester(request.url, {
  14467 + method: request.method,
  14468 + ...option,
  14469 + }) as unknown as Promise<PostResearchGroupsAccessAddWhiteListResponseSuccess>;
  14470 + }
  14471 +
  14472 + /** http method */
  14473 + request.method = method;
  14474 + /** request url */
  14475 + request.url = url;
  14476 + return request;
  14477 +})();
  14478 +
  14479 +/** @description request parameter type for postResearchGroupsAccessBlackList */
  14480 +export interface PostResearchGroupsAccessBlackListOption {
  14481 + /**
  14482 + * @description
  14483 + * request
  14484 + */
  14485 + body: {
  14486 + /**
  14487 + @description
  14488 + request */
  14489 + request: ResearchGroupListRequest;
  14490 + };
  14491 +}
  14492 +
  14493 +/** @description response type for postResearchGroupsAccessBlackList */
  14494 +export interface PostResearchGroupsAccessBlackListResponse {
  14495 + /**
  14496 + * @description
  14497 + * OK
  14498 + */
  14499 + 200: ServerResult;
  14500 + /**
  14501 + * @description
  14502 + * Created
  14503 + */
  14504 + 201: any;
  14505 + /**
  14506 + * @description
  14507 + * Unauthorized
  14508 + */
  14509 + 401: any;
  14510 + /**
  14511 + * @description
  14512 + * Forbidden
  14513 + */
  14514 + 403: any;
  14515 + /**
  14516 + * @description
  14517 + * Not Found
  14518 + */
  14519 + 404: any;
  14520 +}
  14521 +
  14522 +export type PostResearchGroupsAccessBlackListResponseSuccess =
  14523 + PostResearchGroupsAccessBlackListResponse[200];
  14524 +/**
  14525 + * @description
  14526 + * 查询黑名单列表
  14527 + * @tags research-groups-access-controller
  14528 + * @produces *
  14529 + * @consumes application/json
  14530 + */
  14531 +export const postResearchGroupsAccessBlackList = /* #__PURE__ */ (() => {
  14532 + const method = 'post';
  14533 + const url = '/research/groups/access/blackList';
  14534 + function request(
  14535 + option: PostResearchGroupsAccessBlackListOption,
  14536 + ): Promise<PostResearchGroupsAccessBlackListResponseSuccess> {
  14537 + return requester(request.url, {
  14538 + method: request.method,
  14539 + ...option,
  14540 + }) as unknown as Promise<PostResearchGroupsAccessBlackListResponseSuccess>;
  14541 + }
  14542 +
  14543 + /** http method */
  14544 + request.method = method;
  14545 + /** request url */
  14546 + request.url = url;
  14547 + return request;
  14548 +})();
  14549 +
  14550 +/** @description request parameter type for postResearchGroupsAccessDeleteBlackList */
  14551 +export interface PostResearchGroupsAccessDeleteBlackListOption {
  14552 + /**
  14553 + * @description
  14554 + * request
  14555 + */
  14556 + body: {
  14557 + /**
  14558 + @description
  14559 + request */
  14560 + request: ResearchGroupsAccessDTO;
  14561 + };
  14562 +}
  14563 +
  14564 +/** @description response type for postResearchGroupsAccessDeleteBlackList */
  14565 +export interface PostResearchGroupsAccessDeleteBlackListResponse {
  14566 + /**
  14567 + * @description
  14568 + * OK
  14569 + */
  14570 + 200: ServerResultTsgBoolean;
  14571 + /**
  14572 + * @description
  14573 + * Created
  14574 + */
  14575 + 201: any;
  14576 + /**
  14577 + * @description
  14578 + * Unauthorized
  14579 + */
  14580 + 401: any;
  14581 + /**
  14582 + * @description
  14583 + * Forbidden
  14584 + */
  14585 + 403: any;
  14586 + /**
  14587 + * @description
  14588 + * Not Found
  14589 + */
  14590 + 404: any;
  14591 +}
  14592 +
  14593 +export type PostResearchGroupsAccessDeleteBlackListResponseSuccess =
  14594 + PostResearchGroupsAccessDeleteBlackListResponse[200];
  14595 +/**
  14596 + * @description
  14597 + * 删除黑名单
  14598 + * @tags research-groups-access-controller
  14599 + * @produces *
  14600 + * @consumes application/json
  14601 + */
  14602 +export const postResearchGroupsAccessDeleteBlackList = /* #__PURE__ */ (() => {
  14603 + const method = 'post';
  14604 + const url = '/research/groups/access/deleteBlackList';
  14605 + function request(
  14606 + option: PostResearchGroupsAccessDeleteBlackListOption,
  14607 + ): Promise<PostResearchGroupsAccessDeleteBlackListResponseSuccess> {
  14608 + return requester(request.url, {
  14609 + method: request.method,
  14610 + ...option,
  14611 + }) as unknown as Promise<PostResearchGroupsAccessDeleteBlackListResponseSuccess>;
  14612 + }
  14613 +
  14614 + /** http method */
  14615 + request.method = method;
  14616 + /** request url */
  14617 + request.url = url;
  14618 + return request;
  14619 +})();
  14620 +
  14621 +/** @description request parameter type for postResearchGroupsAccessDeleteWhiteList */
  14622 +export interface PostResearchGroupsAccessDeleteWhiteListOption {
  14623 + /**
  14624 + * @description
  14625 + * request
  14626 + */
  14627 + body: {
  14628 + /**
  14629 + @description
  14630 + request */
  14631 + request: ResearchGroupsAccessDTO;
  14632 + };
  14633 +}
  14634 +
  14635 +/** @description response type for postResearchGroupsAccessDeleteWhiteList */
  14636 +export interface PostResearchGroupsAccessDeleteWhiteListResponse {
  14637 + /**
  14638 + * @description
  14639 + * OK
  14640 + */
  14641 + 200: ServerResultTsgBoolean;
  14642 + /**
  14643 + * @description
  14644 + * Created
  14645 + */
  14646 + 201: any;
  14647 + /**
  14648 + * @description
  14649 + * Unauthorized
  14650 + */
  14651 + 401: any;
  14652 + /**
  14653 + * @description
  14654 + * Forbidden
  14655 + */
  14656 + 403: any;
  14657 + /**
  14658 + * @description
  14659 + * Not Found
  14660 + */
  14661 + 404: any;
  14662 +}
  14663 +
  14664 +export type PostResearchGroupsAccessDeleteWhiteListResponseSuccess =
  14665 + PostResearchGroupsAccessDeleteWhiteListResponse[200];
  14666 +/**
  14667 + * @description
  14668 + * 删除白名单
  14669 + * @tags research-groups-access-controller
  14670 + * @produces *
  14671 + * @consumes application/json
  14672 + */
  14673 +export const postResearchGroupsAccessDeleteWhiteList = /* #__PURE__ */ (() => {
  14674 + const method = 'post';
  14675 + const url = '/research/groups/access/deleteWhiteList';
  14676 + function request(
  14677 + option: PostResearchGroupsAccessDeleteWhiteListOption,
  14678 + ): Promise<PostResearchGroupsAccessDeleteWhiteListResponseSuccess> {
  14679 + return requester(request.url, {
  14680 + method: request.method,
  14681 + ...option,
  14682 + }) as unknown as Promise<PostResearchGroupsAccessDeleteWhiteListResponseSuccess>;
  14683 + }
  14684 +
  14685 + /** http method */
  14686 + request.method = method;
  14687 + /** request url */
  14688 + request.url = url;
  14689 + return request;
  14690 +})();
  14691 +
  14692 +/** @description request parameter type for postResearchGroupsAccessWhiteList */
  14693 +export interface PostResearchGroupsAccessWhiteListOption {
  14694 + /**
  14695 + * @description
  14696 + * request
  14697 + */
  14698 + body: {
  14699 + /**
  14700 + @description
  14701 + request */
  14702 + request: ResearchGroupListRequest;
  14703 + };
  14704 +}
  14705 +
  14706 +/** @description response type for postResearchGroupsAccessWhiteList */
  14707 +export interface PostResearchGroupsAccessWhiteListResponse {
  14708 + /**
  14709 + * @description
  14710 + * OK
  14711 + */
  14712 + 200: ServerResult;
  14713 + /**
  14714 + * @description
  14715 + * Created
  14716 + */
  14717 + 201: any;
  14718 + /**
  14719 + * @description
  14720 + * Unauthorized
  14721 + */
  14722 + 401: any;
  14723 + /**
  14724 + * @description
  14725 + * Forbidden
  14726 + */
  14727 + 403: any;
  14728 + /**
  14729 + * @description
  14730 + * Not Found
  14731 + */
  14732 + 404: any;
  14733 +}
  14734 +
  14735 +export type PostResearchGroupsAccessWhiteListResponseSuccess =
  14736 + PostResearchGroupsAccessWhiteListResponse[200];
  14737 +/**
  14738 + * @description
  14739 + * 查询白名单列表
  14740 + * @tags research-groups-access-controller
  14741 + * @produces *
  14742 + * @consumes application/json
  14743 + */
  14744 +export const postResearchGroupsAccessWhiteList = /* #__PURE__ */ (() => {
  14745 + const method = 'post';
  14746 + const url = '/research/groups/access/whiteList';
  14747 + function request(
  14748 + option: PostResearchGroupsAccessWhiteListOption,
  14749 + ): Promise<PostResearchGroupsAccessWhiteListResponseSuccess> {
  14750 + return requester(request.url, {
  14751 + method: request.method,
  14752 + ...option,
  14753 + }) as unknown as Promise<PostResearchGroupsAccessWhiteListResponseSuccess>;
  14754 + }
  14755 +
  14756 + /** http method */
  14757 + request.method = method;
  14758 + /** request url */
  14759 + request.url = url;
  14760 + return request;
  14761 +})();
  14762 +
14335 14763 /** @description request parameter type for postResearchGroupsAdd */
14336 14764 export interface PostResearchGroupsAddOption {
14337 14765 /**
... ...