react中暴露事件useImperativeHandle

注:本頁面模塊主要是使用?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…