当前位置: 首页 > news >正文

Bug问题

一、list 页面

import React, { useEffect, useState } from 'react';
import { shallowEqual, useHistory, useSelector } from 'dva';
import { Button, message } from 'choerodon-ui/pro';
import formatterCollections from 'hzero-front/lib/utils/intl/formatterCollections';
import {commonModelPrompt,languageConfig,prdTemCode,
} from '@/language/language';
import { ButtonColor } from 'choerodon-ui/pro/lib/button/enum';
import {getPortalConfig,getPortalSyncConfig,postPortalConfig,
} from '@/api/portalConfig/main';
import { pubPath } from '@/utils/utils';
import { useDefaultPage } from '@ino/ltc-component-paas';
import { DefaultPageMode } from '@ino/ltc-component-paas/lib/component/defaultPage/enum';
import Tabs from '@/components/Tabs/index';
import { TabItem, TableData } from '@/interface/portalConfig/main';
import { queryMapIdpValue } from 'services/api';
import { renderSync } from '@/pages/portalConfig/list/hook';
import { dataSourceTabs, languageTabs } from '@/pages/portalConfig/list';
import {mergeConfigData,portalConfigAddComponentLevelAndSort,
} from '@/utils/portalConfig/main';
import Banner from '../components/Banner/main';
import Resources from '../components/Resources/main';
import FooterBanner from '../components/FooterBanner/main';
import { loadingModel } from './hook';
import '@/assets/styles/c7n.less';
import styles from './main.less';
import { configDefault } from './store';const PortanConfig = () => {const history = useHistory();/** 定义提交成功页面 */const openDefaultSuccess = useDefaultPage({mode: DefaultPageMode.handleSuccess,renderDom: {current: document.getElementsByClassName('hzero-common-layout-content',)[0],},isClose: true,closeWait: 3,onClose: () => {fetchConfig();},});/** 跳转到:没有权限页面 */const openNoPermissions = useDefaultPage({mode: DefaultPageMode.noPermissions,renderDom: {current: document.getElementsByClassName('hzero-common-layout-content',)[0],},isClose: true,closeWait: 3,onClose: () => {fetchConfig();},});/** 系统错误 */const openDefault = useDefaultPage({mode: DefaultPageMode.sysError,renderDom: {current: document.getElementsByClassName('hzero-common-layout-content',)[0],},isClose: true,closeWait: 3,onClose: () => {fetchConfig();},});const [loading, setLoading] = useState(true); // 初始状态设为true,确保开始时显示loadingconst [isDataLoaded, setIsDataLoaded] = useState(false); // 新增状态,用于判断数据是否已加载const [tabKey, setTabKey] = useState<string>('zh_CN'); // 语言模式const [dataSource, setDataSource] = useState<string>('pc'); // 数据源(PC/移动)const [operation, setOperation] = useState<boolean>(false); // 操作模式const [rule, setRule] = useState([]); // 添加规则上限const [configData, setConfigData] = useState<TableData[]>(configDefault); // 配置数据/** 当前tab页 */const activeTabKey = useSelector((state: any) => state?.global?.activeTabKey,shallowEqual,);/** 获取配置 */const fetchConfig = async (sourse?: string) => {setLoading(true);try {const res = await getPortalConfig({language: tabKey,dataSource: sourse ? sourse : dataSource,componentPlate: 'DEVELOPER',});if (res.failed) {message.error(languageConfig('tips.fetchError', '获取配置失败'),1.5,'top',);setIsDataLoaded(false);res?.code === '401' ? openNoPermissions.open() : openDefault.open();return;}// console.log('获取配置', dataSource, res);// console.log('原始数据', configData);// 合并数据const result = mergeConfigData(configDefault, res || []);setConfigData(result);setIsDataLoaded(true);} catch (error) {message.error(languageConfig('tips.fetchError', '获取配置失败'),1.5,'top',);setIsDataLoaded(false);} finally {setLoading(false);}};/** 移动端:一键同步 */const handleSync = async () => {setLoading(true);const res = await getPortalSyncConfig({language: tabKey,componentPlate: 'DEVELOPER',componentSys: 'app',});if (res.failed) {message.error(languageConfig('tips.syncFetchDataError', '同步失败'),1.5,'top',);setIsDataLoaded(false);res?.code === '401' ? openNoPermissions.open() : openDefault.open();} else {setConfigData(res || []);setIsDataLoaded(true);}setLoading(false);};/** tabs 切换 */const handleTabChange = (selectedTab: TabItem) => {// console.log('当前选中的标签数据:', selectedTab);setTabKey(selectedTab.key);setDataSource('pc');setLoading(true); // 切换 tabs 时设置 loading 为 truesetOperation(false); // 切换 tabs 时设置 operation 为 false};/** 数据源: 移动端、PC端切换 */const handleTabTypeChange = () => {setDataSource(dataSource === 'pc' ? 'app' : 'pc');setOperation(false); // 切换 tabs 时设置 operation 为 false};/** 提交 */const handleSubmit = async () => {// 1、componentLevel 和 componentSortconst submitParams = portalConfigAddComponentLevelAndSort(configData);console.log('submitParams', submitParams);// 2、提交数据setLoading(true);const params = {componentSys: dataSource,containerComponentList: submitParams,};const res = await postPortalConfig(tabKey, params);setLoading(false);if (res.failed) {message.warning(res.message, undefined, undefined, 'top');return;}message.success(languageConfig('tips.success', '保存成功'), 1.5, 'top');// 3、跳转到成功页面setOperation(false); // 操作状态关闭openDefaultSuccess.open(); // 跳转到成功页面};/** 回调 */const handleAction = (val: TableData[]) => {// console.log('这里是回调', val);setConfigData(val);};useEffect(() => {if (activeTabKey) {fetchConfig();}}, [activeTabKey, tabKey, dataSource]);// 获取数量上限useEffect(() => {const fetchRule = async () => {const res = await queryMapIdpValue(['INO_TAI_HOME_PAGE_MODULE']);// console.log('rule', res[0]);setRule(res?.[0] || []);};fetchRule();}, []);return (<>{loading && !isDataLoaded && loadingModel()}<divclassName="ltc-c7n-style"style={{overflow: 'auto',height: '100%',}}><div className={styles.portalConfig}><div className={styles.portalConfig_content}>{/* Tabs:切换中英文 */}<div className={styles.portalConfig_content_tabs}><Tabs tabs={languageTabs} onTabChange={handleTabChange} /><divclassName={styles.portalConfig_content_tabs_preview}onClick={() => history.push(`${pubPath}/tal/preview/${tabKey}`)}><imgsrc={require('@/assets/imgs/portalConfig/icon_preview.png')}alt={'icon_preview'}/>{languageConfig('btn.preview', '预览')}</div></div>{/* 配置项:内容 */}<div className={styles.portalConfig_content_config}>{/* tabs: PC/移动端配置 */}<div className={styles.portalConfig_content_config_typeTabs}><Tabstype="card"tabs={dataSourceTabs}activeKey={dataSource}onTabChange={handleTabTypeChange}/>{renderSync(dataSource, operation, () => handleSync())}</div><Banneroperation={operation}configData={configData}ruleData={rule}dataSource={dataSource}onAction={val => handleAction(val)}/>{/* <Resourcesoperation={operation}configData={configData}ruleData={rule}dataSource={dataSource}onAction={val => handleAction(val)}/><FooterBanneroperation={operation}configData={configData}ruleData={rule}dataSource={dataSource}onAction={val => handleAction(val)}/> */}</div></div>{/* 底部:提交按钮 */}<div className={styles.portalConfig_operation}>{operation ? (<><Button color={ButtonColor.primary} onClick={handleSubmit}>{languageConfig('btn.submit', '提交')}</Button><Buttoncolor={ButtonColor.default}onClick={() => {setOperation(!operation);fetchConfig();}}>{languageConfig('btn.cancel', '取消')}</Button></>) : (<Buttoncolor={ButtonColor.primary}onClick={() => setOperation(!operation)}>{languageConfig('btn.edit', '编辑')}</Button>)}</div></div></div></>);
};export default formatterCollections({code: [prdTemCode, commonModelPrompt],
})(PortanConfig);

二、Banner

import React, { useMemo, useState } from 'react';
import {languageConfig,PICTURE_FORMAT,PICTURE_MAX_SIZE,
} from '@/language/language';
import Title from '@/components/Title';
import { ModuleCreateProps, TableData } from '@/interface/portalConfig/main';
import {portalConfigFetchMaxLimit,portanConfigUpdateModuleData,replaceConfigData,
} from '@/utils/portalConfig/main';
import styles from '../../list/main.less';
import { renderRuleLimit, renderTitle } from '../../list/hook';
import { findZoneSize } from '../../list/store';
import Create from './create/main';
import View from './create/view';const Banner = (props: ModuleCreateProps) => {const { operation, configData, ruleData, dataSource, onAction } = props;const [show, setShow] = useState<boolean>(true); // 管理收缩状态/** 获取配置数据 */const bannerList = useMemo(() => {// 1、找到这个组件数据const bannerModule = configData.find(item => item.componentModule === 'developer.bannerConfig',);if (!bannerModule?.childrenList) return [];// 2、获取组件下'配置项'数据const bannerChild = bannerModule.childrenList.find(child => child.componentModule === 'developer.bannerConfig.banner',);return bannerChild?.childrenList || [];}, [configData]);/** 回调:用于接收子页面传递过来的数据 */const handleChildDataUpdate = (newData: TableData[]) => {// console.log('bannerl回调', newData);// console.log('configData', configData);// 1、给模块添加'提示'标头const resultData = newData?.map((item, index) => ({...item,componentName: `${languageConfig('developer.banner.label.bannerImage','banner图片',)}${index + 1}`,}));// 2、更新:从父组件'configData'中获取的本模块数据const bannerModule = configData.find(item => item.componentModule === 'developer.bannerConfig',);const updatedTableData = portanConfigUpdateModuleData(bannerModule,resultData,'developer.bannerConfig.banner',);// console.log('更新后的 tableData:', updatedTableData);// 2、合并:更新过后的'本模块'和父组件中配置数据进行合并const result = replaceConfigData(configData, updatedTableData);onAction(result);};return (<div className={styles.portalConfig_banner}><Titletitle={languageConfig('developer.banner.label.bannerConfig','banner配置',)}desc={<div><imgsrc={require('@/assets/imgs/portalConfig/demo_banner.png')}alt={'banner示例'}/></div>}isExpanded={show}onToggle={() => setShow(!show)}/>{show && (<div className={styles.portalConfig_card}>{/* 左侧:标题、规则限制 */}<div className={styles.portalConfig_card_left}>{renderTitle(languageConfig('developer.banner.label.bannerImage','banner图片',),)}{renderRuleLimit(ruleData, 'developer.bannerConfig.banner')}</div>{/* 右侧 */}<div className={styles.portalConfig_card_right}>{operation ? (<Createlist={bannerList}maxNum={portalConfigFetchMaxLimit(ruleData,'developer.bannerConfig.banner',)}tips={<>{PICTURE_FORMAT}<br />{findZoneSize('developer.bannerConfig', dataSource)}<br />{PICTURE_MAX_SIZE}<br /></>}onSelect={handleChildDataUpdate}/>) : (<View detail={bannerList} />)}</div></div>)}</div>);
};export default Banner;

三、create

import React, { useCallback } from 'react';
import {Button,Form,Icon,useDataSet,message,Attachment,TextField,
} from 'choerodon-ui/pro';
import { onBeforeUpload } from '@/utils/utils';
import { languageConfig } from '@/language/language';
import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum';
import { FuncType } from 'choerodon-ui/pro/lib/button/enum';
import { Record } from 'choerodon-ui/dataset';
import '@/assets/styles/c7n.less';
import styles from '../../../list/main.less';
import { tableFields } from './store';interface CreateProps {list: any[];maxNum: string | number; // 添加最大限制tips: React.ReactNode; // 提示文案onSelect: (val: any) => void; // 回调
}const BannerCreate = (props: CreateProps) => {const { list = [], maxNum, tips = '', onSelect } = props;// dsconst dataDs = useDataSet(() => {return {autoCreate: true,fields: tableFields(),data: list.map(item => new Record(item)),events: {update: () => {onSelect?.(dataDs.toData());},},};}, [list, onSelect]);/** 上传状态变化的处理 */const onUploadSuccess = (index, file) => {// console.log('上传状态变化的处理:info', index, file);if (file.fileUrl) {// 图片url添加dataDs?.get(index)?.set('componentPicture', file.fileUrl);}};/** 新增 */const handleAdd = async () => {// 1、限制上限,如里maxNumber 为'-' 表示不限制上限if (maxNum !== '-' && dataDs.length >= Number(maxNum)) {message.error(`${languageConfig('uploadBanner.label.menuMaxNumPleaseDeleteRetry','banner图片超出最大限制,请删除后重试:',)}${languageConfig('uploadBanner.label.maxLength','最多支持',)}${maxNum}${languageConfig('uploadBanner.label.unit', '条')}`,1.5,'top',);return;}// 3、创建新记录const newRecordData = {componentModule: 'developer.bannerConfig.banner.item',};// console.log('newRecordData', newRecordData);dataDs.push(new Record(newRecordData, dataDs));// console.log('karla', dataDs.toData());onSelect?.(dataDs.toData());};/** 删除 */const handleDelete = useCallback(async (index: number) => {try {await dataDs.delete(dataDs.get(index), false);// 手动触发 onSelect,确保父组件收到更新if (typeof onSelect === 'function') {onSelect(dataDs.toData());}} catch (error) {console.error('Delete failed:', error);message.error('删除记录时发生错误,请重试');}},[dataDs, onSelect],);return (<div className="ltc-c7n-style">{/* Add */}<div className={styles.portalConfig_card_right_add} onClick={handleAdd}><Icon type="add" />{languageConfig('developer.banner.label.bannerImageAdd','添加banner图片',)}</div>{/* Form */}{dataDs.map((item: any, index: number) => {return (<div key={item} className={styles.portalConfig_card_right_item}>{/* 标识 */}<div className={styles.portalConfig_card_right_item_label}>{languageConfig('developer.banner.label.bannerImage','banner图片',)}{index + 1}</div><Formcolumns={1}labelLayout={LabelLayout.none}record={dataDs.get(index)}style={{ flex: 1 }}><Form.Item><divstyle={{display: 'flex',gap: '16px',background: '#F5F5F5',}}>{/* 图片 */}<div className={styles.portalConfig_upload}><Attachmentname="remark"labelLayout={'float'}listType="picture-card"max={1}beforeUpload={onBeforeUpload}onUploadSuccess={file => onUploadSuccess(index, file)}onRemove={() => {dataDs.get(index)?.set('componentPicture', '');dataDs.get(index)?.set('remark', '');}}/></div>{/* Tips */}<div className={styles.portalConfig_tips}>{tips}</div>{/* 删除:大于1条时显示  */}<divstyle={{marginTop: '40px',}}>{dataDs.toData()?.length > 1 && (<ButtonfuncType={FuncType.link}onClick={() => {handleDelete(index);}}className={styles.uploadConfig_card_right_delete}>{languageConfig('btn.remove', '移除')}</Button>)}</div></div></Form.Item><Form.Item><divstyle={{display: 'flex',gap: '8px',}}>{/* 网页链接 */}<div><TextFieldname="componentLink"clearButtonstyle={{ width: '652px' }}/></div></div></Form.Item></Form></div>);})}</div>);
};export default BannerCreate;

store.js

import { languageConfig } from '@/language/language';
import { bucketInfo } from '@/utils/utils';
import { FieldType } from 'choerodon-ui/dataset/data-set/enum';/** ds table */
export const tableFields = () => {return [{name: 'remark',type: FieldType.string,// bucketName: 'inovance-tai-pub-test',// bucketDirectory: '/portalConfig',// storageCode: 'INOTAL',bucketName: bucketInfo.bucketName,bucketDirectory: bucketInfo.bucketDirectory,storageCode: bucketInfo.storageCode,defaultValue: '',},{name: 'componentLink',type: FieldType.string,label: languageConfig('portalConfig.menu.label.link', '网页链接'),placeholder: languageConfig('portalConfig.menu.placeholder.pleaseInputLink','请输入网页链接',),defaultValue: '',},{name: 'componentModule',type: FieldType.string,defaultValue: 'developer.bannerConfig.banner.item',},];
};

相关文章:

  • qt ui 转python
  • 导航路径优化(一)——平滑
  • PX4 | 无人机关闭磁力计罗盘飞行(yaw estimate error报错解决方法)
  • Vue事件总线
  • windows命令行面板升级Git版本
  • 面试总结一
  • 【HarmonyOS 5】 社交行业详解以及 开发案例
  • Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(七):消息框交互功能添加
  • 第二章支线八 ·CSS终式:Tailwind与原子风暴
  • 一个基于Java的简单抢单功能实现示例,模拟多线程环境下的并发抢单场景
  • c#基础010(程序结构)
  • JavaSec-XSS
  • Mysql 身份认证绕过漏洞 CVE-2012-2122
  • OpenResty 安装指南
  • DNS攻击类型有哪些?如何应对DNS攻击威胁?
  • 12.MySQL视图特性
  • 高敏感应用如何保护自身不被逆向?iOS 安全加固策略与工具组合实战(含 Ipa Guard 等)
  • 无法下载CUDA,下载界面链接打开异常
  • Linux网络——socket网络通信udp
  • 13.4 AI颠覆语言学习:预录制视频+GPT-4评估如何实现60%成本降低与40%留存飙升
  • 创建商务站点的主要工作/色盲眼中的世界
  • 如何做自己的电影网站/云优化软件
  • 蓬莱市住房和规划建设管理局网站/怎么投放广告
  • 上海专业做网站服务商/网络营销方案范文
  • 外贸网站建设哪家比较好/百度手机极速版
  • 十堰微网站建设/百度指数大数据