chore: show fallback change warning

This commit is contained in:
jialin
2026-02-09 13:26:44 +08:00
parent 83086c46e6
commit e7890dda3d
10 changed files with 113 additions and 33 deletions
+5 -1
View File
@@ -18,6 +18,9 @@ type ModalFooterProps = {
extra?: React.ReactNode;
form?: any;
description?: React.ReactNode;
styles?: {
wrapper?: React.CSSProperties;
};
};
const Wrapper = styled.div`
@@ -38,6 +41,7 @@ const ModalFooter: React.FC<ModalFooterProps> = ({
htmlType = 'button',
style,
showOkBtn = true,
styles,
description,
extra,
showCancelBtn = true,
@@ -45,7 +49,7 @@ const ModalFooter: React.FC<ModalFooterProps> = ({
}) => {
const intl = useIntl();
return (
<Wrapper>
<Wrapper style={{ ...styles?.wrapper }}>
<div>{description}</div>
<Space size={20} style={{ ...style }}>
{showCancelBtn && (
+3 -1
View File
@@ -21,5 +21,7 @@ export default {
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
'routes.form.metadata.uploadIcon': 'Upload Icon',
'routes.form.fallback.warning':
'Changes to fallback route target take effect after one minute.'
};
+3 -1
View File
@@ -21,5 +21,7 @@ export default {
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
'routes.form.metadata.uploadIcon': 'Upload Icon',
'routes.form.fallback.warning':
'Changes to fallback route target take effect after one minute.'
};
+3 -1
View File
@@ -21,5 +21,7 @@ export default {
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
'routes.form.metadata.uploadIcon': 'Upload Icon',
'routes.form.fallback.warning':
'Changes to fallback route target take effect after one minute.'
};
+2 -1
View File
@@ -21,5 +21,6 @@ export default {
'routes.form.metadata.releaseDate': '发布日期',
'routes.form.metadata.languages': '语言',
'routes.form.metadata.icons': '图标',
'routes.form.metadata.uploadIcon': '上传图标'
'routes.form.metadata.uploadIcon': '上传图标',
'routes.form.fallback.warning': 'Fallback 路由目标的更改将在一分钟后生效。'
};
@@ -3,6 +3,7 @@ import TooltipList from '@/components/tooltip-list';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import TransferInner from '@/pages/_components/transfer';
import { RouteItem } from '@/pages/model-routes/config/types';
import { queryUsersList } from '@/pages/users/apis';
import { DownOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
@@ -26,7 +27,7 @@ import {
} from 'react';
import styled from 'styled-components';
import { queryModelAccessUserList } from '../../apis';
import { AccessControlFormData, ListItem } from '../../config/types';
import { AccessControlFormData } from '../../config/types';
type TransferKey = string | number | bigint;
@@ -66,7 +67,7 @@ const Label = styled.div`
interface AccessControlFormProps {
action: PageActionType;
currentData?: ListItem | null;
currentData?: RouteItem | null;
onFinish: (values: AccessControlFormData) => void;
onValuesChange?: (changedValues: any, allValues: any) => void;
}
@@ -1,8 +1,10 @@
import AlertBlockInfo from '@/components/alert-info/block';
import ModalFooter from '@/components/modal-footer';
import { PageActionType } from '@/config/types';
import FormDrawer from '@/pages/_components/form-drawer';
import { useIntl } from '@umijs/max';
import React, { useRef } from 'react';
import { FormData, RouteItem as ListItem } from '../config/types';
import ModelRouteForm from '../forms';
type AddModalProps = {
@@ -21,6 +23,8 @@ const AddProvider: React.FC<AddModalProps> = ({
onOk,
onCancel
}) => {
const intl = useIntl();
const [isChanged, setIsChanged] = React.useState(false);
const form = useRef<any>(null);
const handleSubmit = () => {
@@ -45,12 +49,37 @@ const AddProvider: React.FC<AddModalProps> = ({
onCancel={handleCancel}
onSubmit={handleSubmit}
width={600}
footer={
<div style={{ paddingInline: 24, paddingBottom: 8 }}>
{isChanged && (
<AlertBlockInfo
type="warning"
contentStyle={{ paddingInline: 0 }}
message={intl.formatMessage({
id: 'routes.form.fallback.warning'
})}
></AlertBlockInfo>
)}
<ModalFooter
onOk={handleSubmit}
onCancel={onCancel}
styles={{
wrapper: {
paddingTop: 16
}
}}
></ModalFooter>
</div>
}
>
<ModelRouteForm
ref={form}
action={action}
currentData={currentData}
onFinish={onFinish}
onFallbackChange={(changed: boolean) => {
setIsChanged(changed);
}}
/>
</FormDrawer>
);
@@ -0,0 +1,20 @@
import { PageActionType } from '@/config/types';
import { createContext, useContext } from 'react';
interface FormContextProps {
onFallbackChange?: (changed: boolean) => void;
action?: PageActionType;
currentData?: any;
}
const FormContext = createContext<FormContextProps>({});
export const useFormContext = () => {
const context = useContext(FormContext);
if (!context) {
throw new Error('useFormContext must be used within a FormProvider');
}
return context;
};
export default FormContext;
+28 -24
View File
@@ -14,6 +14,7 @@ import {
useRef,
useState
} from 'react';
import FormContext from '../config/form-context';
import { FormData, RouteItem as ListItem } from '../config/types';
import useEditTargets from '../hooks/use-edit-targets';
import Basic from './basic';
@@ -24,6 +25,7 @@ interface ProviderFormProps {
action: PageActionType;
currentData?: ListItem; // Used when action is EDIT
onFinish: (values: FormData) => Promise<void>;
onFallbackChange?: (changed: boolean) => void;
}
const TABKeysMap = {
@@ -34,7 +36,7 @@ const TABKeysMap = {
};
const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
const { action, currentData, onFinish } = props;
const { action, currentData, onFinish, onFallbackChange } = props;
const intl = useIntl();
const { getScrollElementScrollableHeight } = useWrapperContext();
const [activeKey, setActiveKey] = useState<string[]>([TABKeysMap.BASIC]);
@@ -175,29 +177,31 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
}}
getScrollElementScrollableHeight={getScrollElementScrollableHeight}
>
<Form
form={form}
onFinish={handleOnFinish}
initialValues={{
categories: [],
meta: {}
}}
>
<Basic />
<CollapsePanel
activeKey={activeKey}
accordion={false}
onChange={handleOnCollapseChange}
items={[
{
key: TABKeysMap.TARGETS,
label: intl.formatMessage({ id: 'routes.form.target.title' }),
forceRender: true,
children: <Targets ref={targetsRef}></Targets>
}
]}
></CollapsePanel>
</Form>
<FormContext.Provider value={{ onFallbackChange, action, currentData }}>
<Form
form={form}
onFinish={handleOnFinish}
initialValues={{
categories: [],
meta: {}
}}
>
<Basic />
<CollapsePanel
activeKey={activeKey}
accordion={false}
onChange={handleOnCollapseChange}
items={[
{
key: TABKeysMap.TARGETS,
label: intl.formatMessage({ id: 'routes.form.target.title' }),
forceRender: true,
children: <Targets ref={targetsRef}></Targets>
}
]}
></CollapsePanel>
</Form>
</FormContext.Provider>
</ScrollSpyTabs>
);
});
+16 -1
View File
@@ -1,21 +1,31 @@
import MetadataList from '@/components/metadata-list';
import SealCascader from '@/components/seal-form/seal-cascader';
import SealInput from '@/components/seal-form/seal-input';
import { PageAction } from '@/config';
import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import _ from 'lodash';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState
} from 'react';
import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types';
import useTargetSourceModels from '../hooks/use-target-source-models';
const TargetsForm = forwardRef((props, ref) => {
const { onFallbackChange, action } = useFormContext();
const intl = useIntl();
const { getRuleMessage } = useAppUtils();
const { sourceModels, fetchSourceModels } = useTargetSourceModels();
const [validTriggered, setValidTriggered] = useState<boolean>(false);
const form = Form.useFormInstance<FormData>();
const targets = Form.useWatch('targets', form) || [];
const fallbackCacheRef = useRef<{ value: any[] }>({ value: [] });
const [fallbackValues, setFallbackValues] = useState<{ value: any[] }>({
value: []
});
@@ -29,6 +39,7 @@ const TargetsForm = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
initFallbackValues: (values: { value: any[] }) => {
setFallbackValues(values);
fallbackCacheRef.current = values;
},
initDataList: (
list: {
@@ -105,6 +116,10 @@ const TargetsForm = forwardRef((props, ref) => {
setFallbackValues({
value: value
});
if (action === PageAction.EDIT) {
const isEqual = _.isEqual(fallbackCacheRef.current.value, value);
onFallbackChange?.(!isEqual);
}
};
const handleOnWeightChange = (value: any, index: number) => {