注:本页面模块主要是使用 useImperativeHandle ,

一、概述

1、要点

hooks 中的暴露事情件方法useImperativeHandle,需要和forwardRef、ref 结合一起使用。

1、外层校验的时候会校验里面所有需要校验的验证

2、基础使用

二、demo案例

1、场景

1、弹框打开,调用详情,获取不同的'部门信息'

2、部分信息支持删除数据,至少要保留一条数据

3、弹框保存时需要进行表单校验(每个事业部下form必填、行业信息必填)

2、效果图

(1)页面

(2)校验提示

3、代码

(1)目录

(2)父级弹框

  const handleChangeToCustomer = async (record: Record) => {// console.log('karla:变更为新客户', record.toData());const { custCode } = record.toData();// 1、获取'客户信息'const res = await queryBecomeCustInfo({custCode,});// 2、获取'客户信息'失败if (res.failed) {message.error(intl.get(`${modelPrompt}.api.tips.error`).d('程序出错'), 1.5, 'top');return;}// 3、组装数据const detailInfo = res || {};// 4、弹框打开Modal.open({title: intl.get(`${modelPrompt}.path.button.changeCustomer`).d('渠道-变更为客户'),style: { width: '80vw' },className: 'modal_custom_class',children: <ChannelToCustomerModal ref={modalRef} detailInfo={detailInfo} />,onOk: async () => {// 1、检查 ref 是否存在if (!modalRef.current) {message.error('表单组件未加载完成,请稍后重试', 1.5, 'top');return false;}// 执行表单验证const isValid = await modalRef.current.validate();console.log('提交校验', isValid);if (!isValid) {return false; // 阻止弹框关闭}// 2、安全获取表单数据const formData = modalRef.current.getRecordData();// 3、提交表单数据const params = {custCode,custManageList: formData.manageList,};// 4、调用'保存'接口const res = await becomeCustomer(params);if (res.failed) {message.error(res.message, 1.5, 'top');return false;}// 5、操作成功// message.success('操作成功', 1.5, 'top');openDefault.open();return true;},});};

(3)modal 内容页面

main.tsx
/*** @author wb01975* @description 渠道变为客户** @remark 此模块为重构,原逻辑代码未删除* 1、原先逻辑是有弹框,提示用户是带入'渠道'信息,或者带入'客户'信息;新逻辑:默认带入了'渠道'信息。* 2、增加了多条事业部信息只,支持删除,最多删除一条信息。*/
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { message } from 'choerodon-ui/pro';
import { handleTreeReturnData } from '@/utils';
import Header from './components/header/main';
import { Elevator } from './components/elevator/main';
import { General } from './components/general/main';
import { Overseas } from './components/overseas/main';interface ChannelManageItem {belongDivision: string;[key: string]: any;
}interface DetailInfo {custChannelManageList?: ChannelManageItem[];[key: string]: any;
}interface HandelModalProps {detailInfo: DetailInfo;
}interface ModalRef {getRecordData: () => { manageList: ChannelManageItem[] };setRecordData: (val: ChannelManageItem[]) => void;validate: () => Promise<boolean>;
}interface DivisionRef {validate: () => Promise<boolean>;
}type ComponentType = 'overseas' | 'general' | 'elevator';export const ChannelToCustomerModal = forwardRef<ModalRef, HandelModalProps>((props, ref) => {const { detailInfo } = props;// console.log('详情', detailInfo);const [manageList, setManageList] = useState<ChannelManageItem[]>([]); // '事业部'数据/*** @description 定义动态 ref 容器,存储所有子组件的 ref* 键:子组件唯一标识(如 "overseas_0"、"general_1")* 值:子组件实例(包含 validate 方法)*/const componentRefs = useRef<{ [key: string]: DivisionRef | null }>({});// 生成子组件唯一标识(确保类型安全)const getRefKey = (type: ComponentType, index: number): string => `${type}_${index}`;/** 获取表单数据 */const getRecordData = (): { manageList: ChannelManageItem[] } => {// console.log('获取表单数据:', manageList);return { manageList: [...manageList] }; // 返回最新数据};/** 设置表单数据 */const setRecordData = (val: ChannelManageItem[]): void => {// 组装数据,添加行业信息const updatedList = val.map(item => {const { belongDivision, belongIndustry, ...other } = item;return {belongDivision,belongIndustry: belongDivision, // 海外事业部值有问题,把belongDivision赋值给belongIndustry(客户中使用的字段是 belongIndustry)custManageIndustryList: [{belongDivision,belongDivisionName: item?.belongDivisionName,// 行业industryLv1: item?.industryLv1,industryLv2: item?.industryLv2,industryLv3: item?.industryLv3,industry: handleTreeReturnData([item.industryLv1, item.industryLv2, item.industryLv3]), // 行业custBelong: item?.channelBelong || '',isMainIndustry: 'N', // 行业:默认否', 不可编辑custCapacityList: [], // 容量},],...other,};});setManageList(updatedList);};/** 校验逻辑 */const validate = async () => {try {console.log('开始全局动态表单校验');// 1、收集所有子组件的校验 Promiseconst validationPromises: Promise<boolean>[] = [];// 2、遍历动态 ref 容器中的所有子组件Object.values(componentRefs.current).forEach(refInstance => {if (refInstance?.validate) {// 调用子组件的 validate 方法,捕获异常并返回 falsevalidationPromises.push(refInstance.validate().catch(error => {console.error('子组件校验失败:', error);return false;}),);}});// 3、无校验项时默认通过if (validationPromises.length === 0) {return true;}// 4、执行所有校验并判断结果const results = await Promise.all(validationPromises);const allValid = results.every(isValid => isValid);if (!allValid) {message.error('请填写完整所有表单信息', 1.5, 'top');}return allValid;} catch (error) {console.error('全局校验异常:', error);return false;}};useImperativeHandle(ref, () => ({getRecordData,setRecordData,validate,}));useEffect(() => {if (detailInfo?.custChannelManageList) {setRecordData(detailInfo.custChannelManageList);}}, [detailInfo]);/** 回调:'事业部'数据变更 */const handleChangeDate = (val: any, index: number, name: string) => {console.log(name, '数据变更回调', val);const updatedList = manageList.map(manageItem => (manageItem.belongDivision === val.belongDivision ? val : manageItem));setManageList(updatedList);};/*** @description 回调:删除* @remark 删除后,只做逻辑删除,数据库里能查到,渠道列表页面查不到。*/const handleDeleteData = (belongDivision: string) => {const updatedList = manageList.filter(item => item.belongDivision !== belongDivision);setManageList(updatedList);};return (<><div className="ltc-c7n-style"><Header detailInfo={detailInfo} />{/* 渠道事业部列表 */}<div>{manageList.map((item, index: number) => {return (<div key={index}>{/* 海外(发达/新兴)  */}{['200001', 'D000001'].includes(item.belongDivision) && (<Overseasref={(el: DivisionRef | null) => {componentRefs.current[getRefKey('overseas', index)] = el;}}detailInfo={item}list={manageList}onSelect={val => handleChangeDate(val, index, '海外(发达/新兴)')}onDelete={(belongDivision: string) => handleDeleteData(belongDivision)}/>)}{/* 通用 */}{item.belongDivision === '100010' && (<Generalref={(el: DivisionRef | null) => {componentRefs.current[getRefKey('general', index)] = el;}}detailInfo={{...item,belongIndustry: item.belongDivision,}}list={manageList}onSelect={val => handleChangeDate(val, index, '通用')}onDelete={(belongDivision: string) => handleDeleteData(belongDivision)}/>)}{/* 电梯 && 非电梯的事业部字段和'电梯事业部'使用相同字段 */}{!['200001', 'D000001', '100010'].includes(item.belongDivision) && (<Elevatorref={(el: DivisionRef | null) => {componentRefs.current[getRefKey('elevator', index)] = el;}}detailInfo={{...item,belongIndustry: item.belongDivision,}}list={manageList}onSelect={val => handleChangeDate(val, index, '电梯 && 非电梯的事业部都归类为电梯')}onDelete={(belongDivision: string) => handleDeleteData(belongDivision)}/>)}</div>);})}</div></div></>);
});ChannelToCustomerModal.displayName = 'ChannelToCustomerModal';
store.ts
import { salesBusinessUnitUrlApi } from '@/api/mcrConfig/salesBusinessUnit';
import { handleTreeResponse } from '@/utils/utils';
import { AxiosRequestConfig } from 'axios';
import DataSet from 'choerodon-ui/dataset';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';export const modelPrompt = 'mcr.channelToCustomer';/*** @description 表单通用配置*/
export const formConfig = {columns: 4,labelLayout: LabelLayout.vertical,
};/*** 销售业务单元*/
export const organizationOptionsDs = (divisionCode?: string) => {return new DataSet({autoQuery: true,parentField: 'parentCode',idField: 'code',childrenField: 'dataList',fields: [{ name: 'code', type: FieldType.string },{ name: 'expand', type: FieldType.boolean },{ name: 'parentCode', type: FieldType.string },],transport: {read: (config: AxiosRequestConfig): AxiosRequestConfig => {if (!divisionCode) return {};return {...config,...salesBusinessUnitUrlApi('GET', {code: divisionCode,}),transformResponse: data => {const dataList = JSON.parse(data);let resultData: any[] = [];if (Array.isArray(dataList)) {const handleData = handleTreeResponse(dataList, 'dataList', {levelField: 'organizationLevel',disableLevels: [1, 2],statusField: 'status',disableStatus: 'FAILURE',});handleData.forEach(item => {if (item.dataList) {resultData = [...item.dataList];}});}return resultData;},};},},});
};
main.less
.channelToCustomer {&_header {width: 100%;display: flex;gap: 16px;&_left {width: 150px;height: 103px;img {width: 100%;height: 100%;}}&_right {flex: 1 1 auto;display: flex;flex-direction: column;justify-content: center;font-size: 14px;color: rgb(34, 34, 34);gap: 8px;&_item {flex: 1;}}}&_baseInfo {margin: 16px 0;&_title {font-size: 18px;font-weight: 700;color: #222222;display: flex;gap: 8px;align-items: center;span {cursor: pointer;img {width: 16px;height: 16px;}}}}
}
components/general/main.tsx
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { Cascader, Form, Select, TextField, useDataSet } from 'choerodon-ui/pro';
import { handleTreeReturnData } from '@/utils/utils';
import { MenuMode } from 'choerodon-ui/lib/cascader/enum';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';
import Title from '@/components/Title';
import { languageConfig } from '@/language/mian';
import styles from './../../main.less';
import { generalConfig } from './store';
import { IndustryInfo } from './../industryInfo/main';interface CurrentData {organization?: string[];[key: string]: any;
}export const General = forwardRef((props: any, ref) => {const { detailInfo, list, onSelect, onDelete } = props;console.log('通用:detailInfo', detailInfo);const industryInfoRef = useRef<any>(null);const [show, setShow] = useState<boolean>(true); // 管理收缩状态const generalInfoDs = useDataSet(() => generalConfig(), []);useImperativeHandle(ref, () => ({validate: async () => {// 1、表单校验const selfValid = await generalInfoDs.current?.validate(true);console.log('1、通用触发:generalInfoDs.current', generalInfoDs.current, '校验结果:', selfValid);// 2、行业信息:校验let industryValid = true;if (industryInfoRef.current) {industryValid = await industryInfoRef.current.validate();console.log('2、行业信息校验结果:', industryValid);}// 合并校验结果const allValid = selfValid && industryValid;console.log('3、通用模块整体校验结果:', allValid);return allValid;},}));useEffect(() => {if (detailInfo) {const { organizationLv1, organizationLv2, organizationLv3, belongArea, belongRegion, belongCity, ...other } = detailInfo || {};const params = {organization: handleTreeReturnData([organizationLv1, organizationLv2, organizationLv3]), // 销售业务单元belongZone: [belongArea, belongRegion, belongCity], // 所属战区...other,};params.id = undefined; // 后端要求,此处需置空generalInfoDs.loadData([params]);}}, [detailInfo, generalInfoDs]);useEffect(() => {const handleDataChange = () => {// 1、获取当前数据const currentData: CurrentData = generalInfoDs.toData()[0] || {};// 2、获取'销售业务单元'const organizationArray = Array.isArray(currentData.organization) ? currentData.organization : [];const [organizationLv1 = '', organizationLv2 = '', organizationLv3 = ''] = organizationArray;// 3、获取'行业'const belongArray = Array.isArray(currentData.belongZone) ? currentData.belongZone : [];const [belongArea = '', belongRegion = '', belongCity = ''] = belongArray;// 4、构建参数const params = {...currentData,// 销售业务单元organizationLv1,organizationLv2,organizationLv3,// 行业belongArea,belongRegion,belongCity,};// 5、触发回调if (params && onSelect) {onSelect(params);}};// 监听 DataSet 的更新事件generalInfoDs.addEventListener('update', handleDataChange);// 组件卸载时移除监听return () => {generalInfoDs.removeEventListener('update', handleDataChange);};}, [generalInfoDs, onSelect]);return (<><div className={styles.channelToCustomer_baseInfo}><Titletitle={<><div className={styles.channelToCustomer_baseInfo_title}>{detailInfo.belongDivisionName}{/* 事情部有多条时:支持删除,至少保留一条 */}{list.length > 1 && (<spanonClick={() => {// TODO: 删除onDelete(detailInfo.belongDivision);}}><img src={require('@/assets/imgs/delete.png')} alt="" /></span>)}</div></>}isExpanded={show}onToggle={() => setShow(!show)}/>{show && (<><Form labelLayout={LabelLayout.vertical} dataSet={generalInfoDs} columns={3}><Cascader name="organization" searchable menuMode={MenuMode.single} />{/* 客户类型:不同'事业部',根据值集里面的标记过滤 */}<Selectname="custType"searchableoptionsFilter={record => {// 1、当前事业部const division = detailInfo.belongDivision;if (!division) return true;// 2、过滤出当前事业部可选的标签return record.get('tag')?.includes(division);}}/><Select name="custCooperationStatus" searchable /><Select name="custLabel" searchable colSpan={3} maxTagCount={6} maxTagTextLength={8} /><Select name="custDuty" searchable /><Select name="saleType" searchable />{/* <TextField name="belongRegionAndArea" disabled /> */}<Cascader name="belongZone" searchable menuMode={MenuMode.single} /></Form><Titletype="subTitle"title={<>{languageConfig('channelToCustomer.title.industryInfo', '行业信息')}</>}isExpanded={show}onToggle={() => setShow(!show)}/><IndustryInforef={industryInfoRef}industryInfo={detailInfo?.custManageIndustryList}onSelect={val => {console.log('行业信息:回调', val);generalInfoDs.current?.set('custManageIndustryList', [val]);}}/></>)}</div></>);
});General.displayName = 'ChannelToCustomerGeneral';
components/general/store.ts
import { languageConfig } from '@/language/mian';
import { renderItemMultipleText } from '@/utils/render';
import { handleAreaOptionDs } from '@/common/commonDs';
import DataSet, { DataSetProps } from 'choerodon-ui/dataset/data-set/DataSet';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';
import { organizationOptionsDs } from '../../store';/** 销售业务单元 */
const orgOptionsCache = new Map();
const getOrganizationOptions = (belongDivision: string) => {if (orgOptionsCache.has(belongDivision)) {return orgOptionsCache.get(belongDivision);}const ds = organizationOptionsDs(belongDivision);orgOptionsCache.set(belongDivision, ds);return ds;
};/** 战区 */
const areaOptionsCache = new Map();
const getAreaOptions = (belongDivision: string) => {if (areaOptionsCache.has(belongDivision)) {return areaOptionsCache.get(belongDivision);}const ds = handleAreaOptionDs(belongDivision);areaOptionsCache.set(belongDivision, ds);return ds;
};export const generalConfig = (): DataSetProps => {return {autoCreate: true,fields: [{name: 'organization',type: FieldType.string,label: languageConfig('channelToCustomer.label.organization', '销售业务单元'),placeholder: languageConfig('channelToCustomer.placeholder.organization', '请选择销售业务单元'),help: languageConfig('channelToCustomer.label.organization.help', '代表客户经理所在的组织,影响业务流程审批走向,请谨慎选择!'),required: true,valueField: 'code',textField: 'organizationName',options: new DataSet({}),dynamicProps: {options: ({ record }) => {const { belongDivision } = record.toData();if (belongDivision) {return getOrganizationOptions(belongDivision);}return new DataSet({});},},},{name: 'custType',type: FieldType.string,label: languageConfig('channelToCustomer.label.custType', '客户类型'),placeholder: languageConfig('channelToCustomer.placeholder.custType', '请选择客户类型'),lookupCode: 'LTC_CUST_TYPE',required: true,},{name: 'custCooperationStatus',type: FieldType.string,label: languageConfig('channelToCustomer.label.custCooperationStatus', '新客户合作状态'),placeholder: languageConfig('channelToCustomer.placeholder.custCooperationStatus', '请选择新客户合作状态'),lookupCode: 'LTC_COLLABORATION_STATUS',},{name: 'custLabel',type: FieldType.string,label: languageConfig('channelToCustomer.label.custLabel', '客户标签'),placeholder: languageConfig('channelToCustomer.placeholder.custLabel', '请选择客户标签'),lookupCode: 'LTC_CUSTOMER_TAGS',multiple: ',',},{name: 'custDuty',type: FieldType.string,label: languageConfig('channelToCustomer.label.custDuty', '客户主责方'),placeholder: languageConfig('channelToCustomer.placeholder.custDuty', '请选择客户主责方'),lookupCode: 'LTC_RESP_PARTY_CUST',required: true,},{name: 'saleType',type: FieldType.string,label: languageConfig('channelToCustomer.label.saleType', '销售类型'),placeholder: languageConfig('channelToCustomer.placeholder.saleType', '请选择销售类型'),lookupCode: 'LTC_SALES_TYPE',required: true,},// {//   name: 'belongRegionAndArea',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.label.custDuty', '战区'),//   transformResponse: (_value, responseObject) => renderItemMultipleText(responseObject, ['belongAreaName', 'belongRegionName', 'belongCityName']),// },{name: 'belongZone',textField: 'regionName',valueField: 'code',label: languageConfig('channelToCustomer.label.belongZone', '所属战区'),placeholder: languageConfig('channelToCustomer.label.placeholder.belongZone', '请选择所属战区'),options: new DataSet({}),dynamicProps: {options: ({ record }) => {const belongDivision = record.get('belongDivision');if (belongDivision) {if (['-', undefined].includes(belongDivision)) return new DataSet({});return getAreaOptions(belongDivision);}return new DataSet({});},},required: true,},],};
};
components/elevator/main.tsx
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { Cascader, Form, Select, TextField, useDataSet } from 'choerodon-ui/pro';
import { handleTreeReturnData } from '@/utils/utils';
import { MenuMode } from 'choerodon-ui/lib/cascader/enum';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';
import { languageConfig } from '@/language/mian';
import Title from '@/components/Title';
import styles from './../../main.less';
import { elevatorConfig } from './store';
import { IndustryInfo } from './../industryInfo/main';interface CurrentData {organization?: string[];[key: string]: any;
}export const Elevator = forwardRef((props: any, ref: any) => {const { detailInfo, list, onSelect, onDelete } = props;// console.log('电梯:detailInfo', detailInfo);const industryInfoRef = useRef<any>(null);const [show, setShow] = useState<boolean>(true); // 管理收缩状态const elevatorInfoDs = useDataSet(() => elevatorConfig(), []);useImperativeHandle(ref, () => ({validate: async () => {// 1、表单校验const selfValid = await elevatorInfoDs.current?.validate(true);console.log('1、电梯触发:generalInfoDs.current', elevatorInfoDs.current, '校验结果:', selfValid);// 2、行业信息:校验let industryValid = true;if (industryInfoRef.current) {industryValid = await industryInfoRef.current.validate();console.log('2、行业信息校验结果:', industryValid);}// 合并校验结果const allValid = selfValid && industryValid;console.log('3、电梯模块整体校验结果:', allValid);return allValid;},}));useEffect(() => {if (detailInfo) {const { organizationLv1, organizationLv2, organizationLv3, belongArea, belongRegion, belongCity, ...other } = detailInfo || {};const params = {organization: handleTreeReturnData([organizationLv1, organizationLv2, organizationLv3]), // 销售业务单元belongZone: [belongArea, belongRegion, belongCity], // 所属战区...other,};params.id = undefined;elevatorInfoDs.loadData([params]);}}, [detailInfo, elevatorInfoDs]);useEffect(() => {const handleDataChange = () => {// 1、获取当前数据const currentData: CurrentData = elevatorInfoDs.toData()[0] || {};// 2、获取'销售业务单元'const organizationArray = Array.isArray(currentData.organization) ? currentData.organization : [];const [organizationLv1 = '', organizationLv2 = '', organizationLv3 = ''] = organizationArray;// 3、获取'行业'const belongArray = Array.isArray(currentData.belongZone) ? currentData.belongZone : [];const [belongArea = '', belongRegion = '', belongCity = ''] = belongArray;// 4、构建参数const params = {...currentData,// 销售业务单元organizationLv1,organizationLv2,organizationLv3,// 行业belongArea,belongRegion,belongCity,};// 5、触发回调if (params && onSelect) {onSelect(params);}};// 监听 DataSet 的更新事件elevatorInfoDs.addEventListener('update', handleDataChange);// 组件卸载时移除监听return () => {elevatorInfoDs.removeEventListener('update', handleDataChange);};}, [elevatorInfoDs, onSelect]);return (<><div className={styles.channelToCustomer_baseInfo}><Titletitle={<><div className={styles.channelToCustomer_baseInfo_title}>{detailInfo.belongDivisionName}{/* 事情部有多条时:支持删除,至少保留一条 */}{list.length > 1 && (<spanonClick={() => {// TODO: 删除onDelete(detailInfo.belongDivision);}}><img src={require('@/assets/imgs/delete.png')} alt="" /></span>)}</div></>}isExpanded={show}onToggle={() => setShow(!show)}/>{show && (<><Form labelLayout={LabelLayout.vertical} dataSet={elevatorInfoDs} columns={3}><Cascader name="organization" searchable menuMode={MenuMode.single} />{/* 客户类型:不同'事业部',根据值集里面的标记过滤 */}<Selectname="custType"searchableoptionsFilter={record => {// 1、当前事业部const division = detailInfo.belongDivision;if (!division) return true;// 2、过滤出当前事业部可选的标签return record.get('tag')?.includes(division);}}/><Select name="custCooperationStatus" searchable /><Select name="custLabel" searchable colSpan={3} maxTagCount={6} maxTagTextLength={8} /><Select name="custDuty" searchable /><Select name="saleType" searchable /><Cascader name="belongZone" searchable menuMode={MenuMode.single} /></Form><Titletype="subTitle"title={<>{languageConfig('channelToCustomer.title.industryInfo', '行业信息')}</>}isExpanded={show}onToggle={() => setShow(!show)}/><IndustryInforef={industryInfoRef}industryInfo={detailInfo?.custManageIndustryList}onSelect={val => {console.log('行业信息:回调', val);elevatorInfoDs.current?.set('custManageIndustryList', [val]);}}/></>)}</div></>);
});Elevator.displayName = 'ChannelToCustomerElevator';
components/elevator/store.ts
import { languageConfig } from '@/language/mian';
import { renderItemMultipleText } from '@/utils/render';
import DataSet, { DataSetProps } from 'choerodon-ui/dataset/data-set/DataSet';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';
import { organizationOptionsDs } from '../../store';
import { handleAreaOptionDs } from '@/common/commonDs';/** 销售业务单元 */
const orgOptionsCache = new Map();
const getOrganizationOptions = (belongDivision: string) => {if (orgOptionsCache.has(belongDivision)) {return orgOptionsCache.get(belongDivision);}const ds = organizationOptionsDs(belongDivision);orgOptionsCache.set(belongDivision, ds);return ds;
};/** 战区 */
const areaOptionsCache = new Map();
const getAreaOptions = (belongDivision: string) => {if (areaOptionsCache.has(belongDivision)) {return areaOptionsCache.get(belongDivision);}const ds = handleAreaOptionDs(belongDivision);areaOptionsCache.set(belongDivision, ds);return ds;
};export const elevatorConfig = (): DataSetProps => {return {autoCreate: true,fields: [{name: 'organization',type: FieldType.string,label: languageConfig('channelToCustomer.label.organization', '销售业务单元'),placeholder: languageConfig('channelToCustomer.placeholder.organization', '请选择销售业务单元'),help: languageConfig('channelToCustomer.label.organization.help', '代表客户经理所在的组织,影响业务流程审批走向,请谨慎选择!'),required: true,valueField: 'code',textField: 'organizationName',options: new DataSet({}),dynamicProps: {options: ({ record }) => {const { belongDivision } = record.toData();if (belongDivision) {return getOrganizationOptions(belongDivision);}return new DataSet({});},},},{name: 'custType',type: FieldType.string,label: languageConfig('channelToCustomer.label.custType', '客户类型'),placeholder: languageConfig('channelToCustomer.placeholder.custType', '请选择客户类型'),lookupCode: 'LTC_CUST_TYPE',required: true,},{name: 'custCooperationStatus',type: FieldType.string,label: languageConfig('channelToCustomer.label.custCooperationStatus', '新客户合作状态'),placeholder: languageConfig('channelToCustomer.placeholder.custCooperationStatus', '请选择新客户合作状态'),lookupCode: 'LTC_COLLABORATION_STATUS',},{name: 'custLabel',type: FieldType.string,label: languageConfig('channelToCustomer.label.custLabel', '客户标签'),placeholder: languageConfig('channelToCustomer.placeholder.custLabel', '请选择客户标签'),lookupCode: 'LTC_CUSTOMER_TAGS',// multiple: true,multiple: ',',},{name: 'custDuty',type: FieldType.string,label: languageConfig('channelToCustomer.label.custDuty', '客户主责方'),placeholder: languageConfig('channelToCustomer.placeholder.custDuty', '请选择客户主责方'),lookupCode: 'LTC_RESP_PARTY_CUST',required: true,},{name: 'saleType',type: FieldType.string,label: languageConfig('channelToCustomer.label.saleType', '销售类型'),placeholder: languageConfig('channelToCustomer.placeholder.saleType', '请选择销售类型'),lookupCode: 'LTC_SALES_TYPE',required: true,},// {//   name: 'belongRegionAndArea',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.label.custDuty', '战区'),//   transformResponse: (_value, responseObject) => renderItemMultipleText(responseObject, ['belongAreaName', 'belongRegionName', 'belongCityName']),// },{name: 'belongZone',textField: 'regionName',valueField: 'code',label: languageConfig('channelToCustomer.label.belongZone', '所属战区'),placeholder: languageConfig('channelToCustomer.label.placeholder.belongZone', '请选择所属战区'),options: new DataSet({}),dynamicProps: {options: ({ record }) => {const belongDivision = record.get('belongDivision');if (belongDivision) {if (['-', undefined].includes(belongDivision)) return new DataSet({});return getAreaOptions(belongDivision);}return new DataSet({});},},required: true,},],};
};
components/overseas/main.tsx
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { Cascader, Form, Select, TextField, useDataSet } from 'choerodon-ui/pro';
import { MenuMode } from 'choerodon-ui/lib/cascader/enum';
import { languageConfig } from '@/language/mian';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';
import { handleTreeReturnData } from '@/utils/utils';
import Title from '@/components/Title';
import styles from './../../main.less';
import { overseasConfig } from './store';
import { IndustryInfo } from './../industryInfo/main';interface CurrentData {organization?: string[];[key: string]: any;
}export const Overseas = forwardRef((props: any, ref: any) => {const { detailInfo, list, onSelect, onDelete } = props;console.log('海外:detailInfo', detailInfo);const industryInfoRef = useRef<any>(null);const [show, setShow] = useState<boolean>(true); // 管理收缩状态const overseasInfoDs = useDataSet(() => overseasConfig(), []);useImperativeHandle(ref, () => ({validate: async () => {// 1、表单校验const selfValid = await overseasInfoDs.current?.validate(true);console.log('1、海外触发:generalInfoDs.current', overseasInfoDs.current, '校验结果:', selfValid);// 2、行业信息:校验let industryValid = true;if (industryInfoRef.current) {industryValid = await industryInfoRef.current.validate();console.log('2、行业信息校验结果:', industryValid);}// 合并校验结果const allValid = selfValid && industryValid;console.log('3、海外模块整体校验结果:', allValid);return allValid;},}));useEffect(() => {if (detailInfo) {const { organizationLv1, organizationLv2, organizationLv3, belongArea, belongRegion, belongCity, ...other } = detailInfo || {};const params = {organization: handleTreeReturnData([organizationLv1, organizationLv2, organizationLv3]), // 销售业务单元belongZone: [belongArea, belongRegion, belongCity], // 所属战区...other,};params.id = undefined;overseasInfoDs.loadData([params]);}}, [detailInfo, overseasInfoDs]);useEffect(() => {const handleDataChange = () => {// 1、获取当前数据const currentData: CurrentData = overseasInfoDs.toData()[0] || {};// 2、获取'销售业务单元'const organizationArray = Array.isArray(currentData.organization) ? currentData.organization : [];const [organizationLv1 = '', organizationLv2 = '', organizationLv3 = ''] = organizationArray;// 3、获取'行业'const belongArray = Array.isArray(currentData.belongZone) ? currentData.belongZone : [];const [belongArea = '', belongRegion = '', belongCity = ''] = belongArray;// 4、构建参数const params = {...currentData,// 销售业务单元organizationLv1,organizationLv2,organizationLv3,// 行业belongArea,belongRegion,belongCity,};// 5、触发回调if (params && onSelect) {onSelect(params);}};// 监听 DataSet 的更新事件overseasInfoDs.addEventListener('update', handleDataChange);// 组件卸载时移除监听return () => {overseasInfoDs.removeEventListener('update', handleDataChange);};}, [overseasInfoDs, onSelect]);return (<><div className={styles.channelToCustomer_baseInfo}><Titletitle={<><div className={styles.channelToCustomer_baseInfo_title}>{detailInfo.belongDivisionName}{/* 事情部有多条时:支持删除,至少保留一条 */}{list.length > 1 && (<spanonClick={() => {// TODO: 删除onDelete(detailInfo.belongDivision);}}><img src={require('@/assets/imgs/delete.png')} alt="" /></span>)}</div></>}isExpanded={show}onToggle={() => setShow(!show)}/>{show && (<><Form labelLayout={LabelLayout.vertical} dataSet={overseasInfoDs} columns={3}><Cascader name="organization" searchable menuMode={MenuMode.single} />{/* 客户类型:不同'事业部',根据值集里面的标记过滤 */}<Selectname="custType"searchableoptionsFilter={record => {// 1、当前事业部const division = detailInfo.belongDivision;if (!division) return true;// 2、过滤出当前事业部可选的标签return record.get('tag')?.includes(division);}}/><Select name="custCooperationStatus" searchable /><Select name="custLabel" searchable colSpan={3} maxTagCount={6} maxTagTextLength={8} /><Select name="custDuty" searchable /><Select name="saleType" searchable /><Cascader name="belongZone" searchable menuMode={MenuMode.single} /></Form><Titletype="subTitle"title={<>{languageConfig('channelToCustomer.title.industryInfo', '行业信息')}</>}isExpanded={show}onToggle={() => setShow(!show)}/><IndustryInforef={industryInfoRef}industryInfo={detailInfo?.custManageIndustryList}onSelect={val => {console.log('海外行业信息:回调', val);overseasInfoDs.current?.set('custManageIndustryList', [val]);}}/></>)}</div></>);
});Overseas.displayName = 'ChannelToCustomerOverseas';
components/overseas/store.ts
import { languageConfig } from '@/language/mian';
import { checkOrganizationCust } from '@/utils/constants';
import { renderItemMultipleText } from '@/utils/render';
import DataSet, { DataSetProps } from 'choerodon-ui/dataset/data-set/DataSet';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';
import { organizationOptionsDs } from '../../store';
import { handleAreaOptionDs } from '@/common/commonDs';/** 销售业务单元 */
const orgOptionsCache = new Map();
const getOrganizationOptions = (belongDivision: string) => {if (orgOptionsCache.has(belongDivision)) {return orgOptionsCache.get(belongDivision);}const ds = organizationOptionsDs(belongDivision);orgOptionsCache.set(belongDivision, ds);return ds;
};/** 战区 */
const areaOptionsCache = new Map();
const getAreaOptions = (belongDivision: string) => {if (areaOptionsCache.has(belongDivision)) {return areaOptionsCache.get(belongDivision);}const ds = handleAreaOptionDs(belongDivision);areaOptionsCache.set(belongDivision, ds);return ds;
};export const overseasConfig = (): DataSetProps => {return {autoCreate: true,fields: [{name: 'organization',type: FieldType.string,label: languageConfig('channelToCustomer.label.organization', '销售业务单元'),placeholder: languageConfig('channelToCustomer.placeholder.organization', '请选择销售业务单元'),help: languageConfig('channelToCustomer.label.organization.help', '代表客户经理所在的组织,影响业务流程审批走向,请谨慎选择!'),required: true,valueField: 'code',textField: 'organizationName',options: new DataSet({}),dynamicProps: {options: ({ record }) => {const { belongDivision } = record.toData();if (belongDivision) {return getOrganizationOptions(belongDivision);}return new DataSet({});},},// dynamicProps: {//   required: ({ record }) => {//     return checkOrganizationCust.includes(record.get('belongDivision'));//   },// },},{name: 'custType',type: FieldType.string,label: languageConfig('channelToCustomer.label.custType', '客户类型'),placeholder: languageConfig('channelToCustomer.placeholder.custType', '请选择客户类型'),lookupCode: 'LTC_CUST_TYPE',required: true,},{name: 'custCooperationStatus',type: FieldType.string,label: languageConfig('channelToCustomer.label.custCooperationStatus', '新客户合作状态'),placeholder: languageConfig('channelToCustomer.placeholder.custCooperationStatus', '请选择新客户合作状态'),lookupCode: 'LTC_COLLABORATION_STATUS',},{name: 'custLabel',type: FieldType.string,label: languageConfig('channelToCustomer.label.custLabel', '客户标签'),placeholder: languageConfig('channelToCustomer.placeholder.custLabel', '请选择客户标签'),lookupCode: 'LTC_CUSTOMER_TAGS',// multiple: true,multiple: ',',},{name: 'custDuty',type: FieldType.string,label: languageConfig('channelToCustomer.label.custDuty', '客户主责方'),placeholder: languageConfig('channelToCustomer.placeholder.custDuty', '请选择客户主责方'),lookupCode: 'LTC_RESP_PARTY_CUST',required: true,},{name: 'saleType',type: FieldType.string,label: languageConfig('channelToCustomer.label.saleType', '销售类型'),placeholder: languageConfig('channelToCustomer.placeholder.saleType', '请选择销售类型'),lookupCode: 'LTC_SALES_TYPE',required: true,},// {//   name: 'belongRegionAndArea',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.label.custDuty', '战区'),//   transformResponse: (_value, responseObject) => renderItemMultipleText(responseObject, ['belongAreaName', 'belongRegionName', 'belongCityName']),// },{name: 'belongZone',textField: 'regionName',valueField: 'code',label: languageConfig('channelToCustomer.label.belongZone', '所属战区'),placeholder: languageConfig('channelToCustomer.label.placeholder.belongZone', '请选择所属战区'),options: new DataSet({}),dynamicProps: {options: ({ record }) => {const belongDivision = record.get('belongDivision');if (belongDivision) {if (['-', undefined].includes(belongDivision)) return new DataSet({});return getAreaOptions(belongDivision);}return new DataSet({});},},required: true,},],};
};
components/industryInfo/main.tsx
import React, { forwardRef, useEffect, useImperativeHandle, useMemo } from 'react';
import { Cascader, Table } from 'choerodon-ui/pro';
import DataSet from 'choerodon-ui/dataset';
import { SelectionMode } from 'choerodon-ui/pro/lib/table/enum';
import { ColumnProps } from 'choerodon-ui/pro/lib/table/Column';
import { MenuMode } from 'choerodon-ui/lib/cascader/enum';
import TableHead from '@/components/TableHead';
import { languageConfig } from '@/language/mian';
import { tableList } from './store';export const IndustryInfo = forwardRef((props: any, ref) => {const { industryInfo, onSelect } = props;// console.log('行业信息:industryInfo', props.industryInfo);// ds Tableconst tableDs = useMemo(() => new DataSet(tableList()), []);const columns: ColumnProps[] = useMemo(() => {return [{name: 'industry',editor: <Cascader searchable menuMode={MenuMode.single} />,header: <TableHead title={languageConfig('channelToCustomer.industryInfo.label.industryName', '行业')} />,},{name: 'custBelong',editor: true,header: <TableHead title={languageConfig('channelToCustomer.industryInfo.label.custBelong', '客户归属')} />,},{name: 'custContactPersonLov',editor: true,header: <TableHead title={languageConfig('channelToCustomer.industryInfo.label.custContactPersonLov', '客户接口人')} />,},{ name: 'isMainIndustry' },];}, []);useImperativeHandle(ref, () => ({validate: async () => {const isValid = await tableDs.current?.validate(true);return isValid;},}));useEffect(() => {const handler = async () => {if (!onSelect || !tableDs.current) return;const currentData = tableDs.current.toData();const industryArray = Array.isArray(currentData.industry) ? currentData.industry : [];const [industryLv1 = '', industryLv2 = '', industryLv3 = ''] = industryArray;const params = {...currentData,industryLv1,industryLv2,industryLv3,};onSelect(params);};tableDs.addEventListener('update', handler);return () => {tableDs.removeEventListener('update', handler);};}, [tableDs, onSelect]);useEffect(() => {if (industryInfo) {tableDs.loadData(industryInfo);}}, [industryInfo, tableDs]);return <Table dataSet={tableDs} columns={columns} selectionMode={SelectionMode.click} pagination={false} style={{ marginBottom: '16px' }} />;
});IndustryInfo.displayName = 'IndustryInfo';
components/industryInfo/store.ts
import { handleIndustryOptionDs } from '@/common/commonDs';
import { languageConfig } from '@/language/mian';
import DataSet from 'choerodon-ui/dataset';
import { FieldIgnore, FieldType } from 'choerodon-ui/dataset/data-set/enum';/** 行业 */
const industryOptionsCache = new Map();
const getIndustryOptions = (belongDivision: string) => {if (industryOptionsCache.has(belongDivision)) {return industryOptionsCache.get(belongDivision);}const ds = handleIndustryOptionDs(belongDivision);industryOptionsCache.set(belongDivision, ds);return ds;
};/** ds table */
export const tableList = () => {return {autoQuery: true,fields: [// {//   name: 'industryName',//   type: FieldType.string,labub//   label: languageConfig('channelToCustomer.industryInfo.label.industryName', '行业'),//   required: true,// },{name: 'industry',type: FieldType.string,valueField: 'code',textField: 'industryName',label: languageConfig('manageInfo.industry', '所属行业'),placeholder: languageConfig('manageInfo.industry.placeholder', '请选择所属行业'),// dynamicProps: {//   options: ({ record }) => {//     if (record.get('belongDivision')) {//       if (['-', undefined].includes(record.get('belongDivision'))) return new DataSet({});//       return handleIndustryOptionDs(record.get('belongDivision'));//     }//     return new DataSet({});//   },// },dynamicProps: {options: ({ record }) => {const { belongDivision } = record.toData();if (belongDivision) {return getIndustryOptions(belongDivision);}return new DataSet({});},},required: true,},{name: 'custBelong',type: FieldType.string,label: languageConfig('channelToCustomer.industryInfo.label.custBelong', '客户归属'),lookupCode: 'LTC_CUSTOMER_OWNERSHIP',placeholder: languageConfig('channelToCustomer.industryInfo.placeholder.custBelong', '请选择客户归属'),required: true,},{name: 'custContactPersonLov',type: FieldType.object,ignore: FieldIgnore.always,label: languageConfig('channelToCustomer.industryInfo.label.custContactPersonLov', '客户接口人'),placeholder: languageConfig('channelToCustomer.industryInfo.placeholder.custContactPersonLov', '请选择客户接口人'),lovCode: 'LTC.HPFM.EMPLOYEE',required: true,},{name: 'custContactPerson',type: FieldType.string,bind: 'custContactPersonLov.userInfo',},{name: 'isMainIndustry',type: FieldType.string,label: languageConfig('channelToCustomer.industryInfo.label.isMainIndustry', '是否主行业'),placeholder: languageConfig('channelToCustomer.industryInfo.placeholder.isMainIndustry', '请选择是否主行业'),lookupCode: 'LTC_YES_OR_NO',defaultValue: 'N',},//// {//   name: 'industryLv1',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.industryInfo.label.industryLv1', '一级行业'),// },// {//   name: 'industryLv2',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.industryInfo.label.industryLv2', '二级行业'),// },// {//   name: 'industryLv3',//   type: FieldType.string,//   label: languageConfig('channelToCustomer.industryInfo.label.industryLv3', '三级行业'),// },],};
};
components/header/main.tsx
import React from 'react';
import bgImg from '@/assets/highSeas/bg.png';
import { languageConfig } from '@/language/mian';
import formatterCollections from 'utils/intl/formatterCollections';
import { commonModelPrompt } from '@/common/language';
import { modelPrompt } from '../../store';
import styles from './../../main.less';interface HeaderProps {detailInfo: any;
}
export const ChannelToCustomerHeader: React.FC<HeaderProps> = props => {const { detailInfo } = props;const fields = [{name: 'custName',style: { fontSize: '20px', fontWeight: '700' },},{name: 'custCode',label: languageConfig('channelToCusotmer.label.custCode', '渠道编号'),style: { fontSize: '12px' },},].map(field => ({...field,value: detailInfo?.[field.name] ?? '-',}));return (<div className={`ltc-c7n-style ${styles.channelToCustomer_header}`}>{/* 左侧 */}<div className={styles.channelToCustomer_header_left}><img src={bgImg} alt="" /></div>{/* 右侧:编辑按钮 */}<div className={styles.channelToCustomer_header_right}>{fields.map(item => {return (<div className={styles.channelDetails_header_left_second_item} key={item.name}>{item.label && <span>{item.label}:</span>}<span style={item.style}>{item.value}</span></div>);})}</div></div>);
};export default formatterCollections({code: [modelPrompt, commonModelPrompt],
})(ChannelToCustomerHeader);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916833.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916833.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916833.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】-《RayS: A Ray Searching Method for Hard-label Adversarial Attack》

RayS&#xff1a;一种用于硬标签对抗攻击的光线搜索方法 Jinghui Chen University of California, Los Angeles jhchencs.ucla.edu Quanquan Gu University of California, Los Angeles qgucs.ucla.edu 原文链接&#xff1a;https://arxiv.org/pdf/2006.12792 摘要 深度神经…

15K的Go开发岗,坐标北京

好久没有分享最新的面经了&#xff0c;今天分享一下北京某公司Go开发岗的面经&#xff0c;薪资是15K左右&#xff0c;看看难度如何&#xff1a; 为什么要用分布式事务 分布式事务的核心作用是解决跨服务、跨数据源操作的数据一致性问题。在单体应用中&#xff0c;数据库本地事务…

Linux 文件管理高级操作:复制、移动与查找的深度探索

目录一、文件复制&#xff1a;从基础到企业级同步的全维度解析1. cp命令&#xff1a;基础工具的进阶密码&#xff08;1&#xff09;文件属性保留&#xff1a;从基础到极致&#xff08;2&#xff09;特殊文件处理&#xff1a;稀疏文件与设备文件&#xff08;3&#xff09;安全操…

Redis内存使用耗尽情况分析

目录 1、内存上限介绍 1.1、产生原因 1.2、Redis的maxmemory限额 1.3、影响的命令与场景 2. 内存用完后的策略 2.1、淘汰策略分类 2.2、淘汰策略介绍 2.3、不同策略对比 3、常见业务示例 3.1、影响 3.2、监控与自动告警 前言 在日常项目中&#xff0c;不知道你思考过…

Ubuntu 系统中配置 SSH 服务教程

一、什么是 SSH&#xff1f;SSH&#xff08;Secure Shell&#xff09;是一种加密的网络协议&#xff0c;用于在不安全的网络中安全地进行远程登录、远程命令执行和文件传输。它是 Telnet、FTP 等传统协议的安全替代品。二、确认系统环境在开始配置之前&#xff0c;请确认你的系…

基于springboot的编程训练系统设计与实现(源码+论文)

一、开发环境 技术/工具描述MYSQL数据库一个真正的多用户、多线程SQL数据库服务器&#xff0c;适用于Web站点或其他应用软件的数据库后端开发。B/S结构基于互联网系统的软件系统开发架构&#xff0c;利用浏览器进行访问&#xff0c;支持多平台使用。Spring Boot框架简化新Spri…

K8s集群两者不同的对外暴露服务的方式

在工作中&#xff0c;我们暴露集群内的服务通常有几种方式&#xff0c;对于普通的http或者https,我们通常使用​Ingress Nginx​ &#xff0c;对于原始的TCP或者UDP端口服务&#xff0c;可能需要选择 ​LoadBalancer​ &#xff0c;它们的核心区别在于工作层级、协议支持和流量…

实习日志111

第一天 加入内网和内网域&#xff0c;设置自己的操作系统 第二天 安装常用软件和平台 Notepad 是一款免费的源代码编辑器&#xff0c;支持多种编程语言&#xff0c;其功能强大且界面友好&#xff0c;适用于 Windows 操作系统。WinMerge 是一款开源的差异比较和合并工具&…

Redis 服务挂掉排查与解决

Redis 是一个高性能的键值对存储系统&#xff0c;广泛应用于缓存、会话存储、消息队列等场景。在使用 Redis 的过程中&#xff0c;偶尔会遇到 Redis 服务挂掉或无法连接的情况。本文将通过常见错误 RedisException in Redis.php line 63 Connection refused 来讲解如何排查并解…

DOM + HTML + HTTP

一、HTML5的新特性 1.语义化标签:其实就是可以让标签有自己的含义 html4之前都是有的,比如:<h1>、<ul>、<li> html5新增了很多语义化标签:<header>、<nav> html5的语义化标签的常用页面布局: 优点: 1.代码结构清晰,方便阅读,有利于团…

HTML 音频/视频

HTML 音频/视频 引言 HTML 音频和视频标签是网页设计中不可或缺的部分,它们为用户提供了一种将多媒体内容嵌入到网页中的方式。本文将详细介绍 HTML 音频/视频标签的用法、属性和注意事项,帮助开发者更好地在网页中嵌入音频和视频。 HTML 音频标签( ) 1. 标签基本用法 …

Apache Ignite Cluster Groups的介绍

以下这段内容是 Apache Ignite 官方文档中关于 Cluster Groups&#xff08;集群组&#xff09; 的介绍。我来用通俗易懂的方式帮你全面理解这个概念。&#x1f310; 什么是 Cluster Group&#xff1f; 简单来说&#xff1a;Cluster Group 就是一个“节点的子集”。想象一下你的…

github上传本地项目过程记录

最近有和别人进行unity项目协作的需求&#xff0c;需要把自己的本地代码上传到github已有的一个仓库里。记录一下上传过程&#xff0c;防止后续还需要用。 文章目录一、把自己的本地代码上传到github已有的一个仓库中二、常用功能一、把自己的本地代码上传到github已有的一个仓…

Spring AI Alibaba

目录 前言&#xff1a; 一、Spring AI 和Spring AI Alibaba 二、Spring AI Alibaba快速入门 1.环境 2.ollama 3.阿里百炼 前言&#xff1a; 2025年真的是AI大爆发的一年&#xff0c;以后无论是什么行业我想都需要AI了&#xff0c;作为一名计算机人&#xff0c;你不学习AI…

【GaussDB】内存资源告急:深度诊断一起“memory temporarily unavailable“故障

【GaussDB】诊断一起内存临时不可用的问题 &#x1f4cb; 背景 在客户测试环境中&#xff08;GaussDB 506.0 SPC0100 集中式&#xff09;&#xff0c;一个重度使用存储过程的系统&#xff0c;频繁出现内存临时不可用的问题(ERROR: memory is temporarily unavailable)。令人困…

FastDFS如何提供HTTP访问电子影像文件

Nginx 作为高性能的 Web 服务器和反向代理服务器&#xff0c;与 FastDFS 结合使用&#xff0c;本文主要介绍用于处理 FastDFS 存储文件的 HTTP 访问请求&#xff0c;方便客户端通过 HTTP 协议直接访问存储在 FastDFS 中的文件&#xff0c;在电子影像系统中&#xff0c;Nginx 可…

水面垃圾识别分割数据集labelme格式2111张8类别

数据集中有部分增强图片&#xff0c;注意为了提供模型泛化识别能力&#xff0c;有很少一部分不是水面垃圾。具体看图片数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件)图片数量(jpg文件个数)&#xff1a;2111标注数量(json文件…

北京-4年功能测试2年空窗-报培训班学测开-第六十二天-模拟未通过,继续准备自我介绍项目介绍面试题中

今日产出&#xff0c;完成昨天模拟面试录音的重听和整理&#xff0c;完成自我介绍梳理&#xff0c;还重写了三个算法题&#xff0c;写了4个sql题。和同学打语音提问今天专注力不强&#xff0c;因为焦虑项目和面试题。关于项目&#xff0c;我理解的&#xff0c;老师以前录屏讲的…

自动化辅助工具教程

该工具支持全部平台使用

里程碑 | 1Panel开源面板GitHub Star数量突破30,000个!

截至2025年7月23日20:00&#xff0c;飞致云旗下开源项目——1Panel开源Linux服务器运维管理面板GitHub Star数超过30,000个&#xff01; 继Halo之后&#xff0c;1Panel成为飞致云旗下第二个GitHub Star数量超过30,000个的开源项目&#xff0c;也是飞致云旗下最快达成30,000个Gi…