动态更新面包屑导航
This commit is contained in:
123
README.md
Normal file
123
README.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# 动态面包屑导航实现说明
|
||||||
|
|
||||||
|
## 功能介绍
|
||||||
|
|
||||||
|
本项目实现了动态修改页面面包屑名称的功能,特别适用于新增和修改页面共用一个组件的场景。通过 dva 状态管理,可以在具体页面中动态设置面包屑导航的最后一级显示文本。
|
||||||
|
|
||||||
|
## 实现原理
|
||||||
|
|
||||||
|
1. 通过 `breadcrumb` 模型管理面包屑状态
|
||||||
|
2. 使用 `connect` 将 `breadcrumb` 状态连接到布局组件
|
||||||
|
3. 在页面组件中根据不同条件(如是否有 id 参数)来动态设置面包屑名称
|
||||||
|
|
||||||
|
## 代码结构
|
||||||
|
|
||||||
|
- `src/models/breadcrumb.ts` - 面包屑状态模型
|
||||||
|
- `src/layouts/BasicLayout.tsx` - 支持动态面包屑的布局组件
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 实际项目中的使用方式 (supplierAnnualTemplateManageAdd.tsx)
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useIntl, connect } from 'umi';
|
||||||
|
import type { Dispatch } from 'umi';
|
||||||
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
|
|
||||||
|
// 组件 props 接口定义
|
||||||
|
interface PageProps extends ConnectProps {
|
||||||
|
breadcrumb: BreadcrumbState; // dva model状态
|
||||||
|
dispatch: Dispatch; // dva dispatch方法
|
||||||
|
}
|
||||||
|
|
||||||
|
const YourPage: React.FC<PageProps> = ({ dispatch }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
// 设置面包屑名称
|
||||||
|
useEffect(() => {
|
||||||
|
if (location.state?.editData?.id && dispatch) {
|
||||||
|
// 编辑模式,设置编辑相关的面包屑
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "yourNamespace.add.edit" }),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 新增模式,设置新增相关的面包屑
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "yourNamespace.add.title" }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件卸载时重置面包屑
|
||||||
|
return () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [dispatch, intl, location]);
|
||||||
|
|
||||||
|
// 页面其他内容...
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* 页面内容... */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将dva model中的状态映射到组件props
|
||||||
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
||||||
|
breadcrumb,
|
||||||
|
}))(YourPage);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关键实现点
|
||||||
|
|
||||||
|
1. 在页面组件中通过 connect 连接到 dva 状态:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// 将dva model中的状态映射到组件props
|
||||||
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
||||||
|
breadcrumb,
|
||||||
|
}))(YourPage);
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 在 useEffect 中动态设置面包屑名称:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
useEffect(() => {
|
||||||
|
// 根据条件设置不同的面包屑名称
|
||||||
|
if (location.state?.editData?.id) {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "yourNamespace.add.edit" }),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "yourNamespace.add.title" }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件卸载时重置面包屑
|
||||||
|
return () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [dispatch, intl, location]);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **payload 必须是字符串**:传递给 `updateBreadcrumbName` action 的 payload 必须是字符串类型,不能是对象或 React 组件
|
||||||
|
- 正确:`payload: intl.formatMessage({ id: "menu.edit" })`
|
||||||
|
- 错误:`payload: { breadcrumbName: <FormattedMessage id="menu.edit" /> }`
|
||||||
|
|
||||||
|
2. **重置面包屑**:确保在组件卸载时调用 `resetBreadcrumb` 以重置面包屑状态
|
||||||
|
|
||||||
|
3. **国际化处理**:使用 `intl.formatMessage()` 方法处理国际化文本,不要在 payload 中直接使用 FormattedMessage 组件
|
||||||
|
|
||||||
|
4. **依赖项管理**:确保 useEffect 的依赖项包含 `dispatch`, `intl` 和用于条件判断的变量(如 `location`)
|
@ -2,11 +2,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProLayout, { PageContainer } from '@ant-design/pro-layout';
|
import ProLayout, { PageContainer } from '@ant-design/pro-layout';
|
||||||
import { Link, useLocation, useIntl, useHistory } from 'umi';
|
import { Link, useLocation, useIntl, useHistory } from 'umi';
|
||||||
|
import { connect } from 'dva';
|
||||||
import defaultSettings from '../../config/defaultSettings';
|
import defaultSettings from '../../config/defaultSettings';
|
||||||
import routes from '../../config/router.config'; // 引入你的自定义路由结构
|
import routes from '../../config/router.config'; // 引入你的自定义路由结构
|
||||||
import { ConfigProvider, Breadcrumb } from 'antd';
|
import { ConfigProvider, Breadcrumb } from 'antd';
|
||||||
import HeaderComponent from './Header';
|
import HeaderComponent from './Header';
|
||||||
import IconFont from '@/components/IconFont/IconFont';
|
import IconFont from '@/components/IconFont/IconFont';
|
||||||
|
import { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
|
|
||||||
|
|
||||||
const MenuRender = (item: any, isSubMenu: boolean) => {
|
const MenuRender = (item: any, isSubMenu: boolean) => {
|
||||||
@ -32,22 +34,29 @@ const MenuRender = (item: any, isSubMenu: boolean) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const BreadcrumbRender = (breadcrumb: any, intl: any, history: any) => {
|
const BreadcrumbRender = (routeBreadcrumb: any, intl: any, history: any, dynamicBreadcrumbName: string | null) => {
|
||||||
const breadcrumbRoutes = breadcrumb?.routes;
|
const breadcrumbRoutes = routeBreadcrumb?.routes;
|
||||||
return (
|
return (
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<Breadcrumb.Item
|
<Breadcrumb.Item
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.push('/');
|
history.push('/');
|
||||||
}}
|
}}
|
||||||
style={{ cursor: 'pointer' }}
|
|
||||||
>
|
>
|
||||||
{intl.formatMessage({ id: 'menu.首页' })}
|
<span style={{ cursor: 'pointer' }}>
|
||||||
|
{intl.formatMessage({ id: 'menu.首页' })}
|
||||||
|
</span>
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
{breadcrumbRoutes?.map((item: any) => {
|
{breadcrumbRoutes?.map((item: any, index: number) => {
|
||||||
|
// 判断是否是最后一个面包屑项且存在动态名称
|
||||||
|
const isLastItem = index === (breadcrumbRoutes.length - 1);
|
||||||
|
const displayName = (isLastItem && dynamicBreadcrumbName)
|
||||||
|
? dynamicBreadcrumbName
|
||||||
|
: intl.formatMessage({ id: `menu.${item.breadcrumbName}` || '' });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Breadcrumb.Item key={item.path}>
|
<Breadcrumb.Item key={item.path}>
|
||||||
{intl.formatMessage({ id: `menu.${item.breadcrumbName}` || '' })}
|
{displayName}
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -55,7 +64,13 @@ const BreadcrumbRender = (breadcrumb: any, intl: any, history: any) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const BasicLayout: React.FC = (props) => {
|
interface BasicLayoutProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
breadcrumb: BreadcrumbState;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
|
||||||
|
const { children, breadcrumb } = props;
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@ -81,14 +96,18 @@ const BasicLayout: React.FC = (props) => {
|
|||||||
ghost={true}
|
ghost={true}
|
||||||
header={{
|
header={{
|
||||||
title: false,
|
title: false,
|
||||||
breadcrumbRender: ({ breadcrumb }) => BreadcrumbRender(breadcrumb, intl, history),
|
breadcrumbRender: ({ breadcrumb: routeBreadcrumb }) =>
|
||||||
|
BreadcrumbRender(routeBreadcrumb, intl, history, breadcrumb.breadcrumbName),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{children}
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</ProLayout>
|
</ProLayout>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BasicLayout;
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
||||||
|
breadcrumb
|
||||||
|
}))(BasicLayout);
|
||||||
|
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
// import Header from './Header';
|
|
||||||
import { Layout, Breadcrumb } from 'antd';
|
|
||||||
import { useLocation, useIntl, Link, connect } from 'umi';
|
|
||||||
|
|
||||||
import type { ConnectProps, Dispatch } from 'umi';
|
|
||||||
const { Header, Sider, Content } = Layout;
|
|
||||||
//导入logo图片
|
|
||||||
import HeaderComponent from './Header';
|
|
||||||
import SiderMenu from './SiderMenu';
|
|
||||||
import './layout.less';
|
|
||||||
import type { BreadcrumbModelState } from '@/models/breadcrumb';
|
|
||||||
|
|
||||||
interface LayoutIndexProps extends ConnectProps {
|
|
||||||
breadcrumb: BreadcrumbModelState;
|
|
||||||
dispatch: Dispatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LayoutIndex: React.FC<LayoutIndexProps> = (props) => {
|
|
||||||
const { children, breadcrumb, dispatch } = props;
|
|
||||||
const location = useLocation();
|
|
||||||
const intl = useIntl();
|
|
||||||
// 当路由变化时更新面包屑
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(location)
|
|
||||||
dispatch({
|
|
||||||
type: 'breadcrumb/updateBreadcrumbs',
|
|
||||||
payload: { pathname: location.pathname, intl },
|
|
||||||
});
|
|
||||||
}, [location.pathname, intl, dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Layout>
|
|
||||||
<Header className="header">
|
|
||||||
<HeaderComponent />
|
|
||||||
</Header>
|
|
||||||
<Layout>
|
|
||||||
<Sider width={200} theme="light">
|
|
||||||
<SiderMenu />
|
|
||||||
</Sider>
|
|
||||||
<Layout className="layout-content">
|
|
||||||
<Breadcrumb style={{ margin: '10px 0' }}>
|
|
||||||
{breadcrumb.breadcrumbs.map((breadcrumbItem, index) => (
|
|
||||||
<Breadcrumb.Item key={breadcrumbItem.path}>
|
|
||||||
{index < breadcrumb.breadcrumbs.length - 1 ? (
|
|
||||||
<Link to={breadcrumbItem.path}>{breadcrumbItem.breadcrumbName}</Link>
|
|
||||||
) : (
|
|
||||||
breadcrumbItem.breadcrumbName
|
|
||||||
)}
|
|
||||||
</Breadcrumb.Item>
|
|
||||||
))}
|
|
||||||
</Breadcrumb>
|
|
||||||
<Content>{children}</Content>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbModelState }) => ({
|
|
||||||
breadcrumb,
|
|
||||||
}))(LayoutIndex);
|
|
@ -1,127 +0,0 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Menu, Tooltip } from 'antd';
|
|
||||||
import { useIntl, Link, useHistory } from 'umi';
|
|
||||||
import IconFont from '@/components/IconFont/IconFont';
|
|
||||||
import routerConfig from '../../config/router.config';
|
|
||||||
|
|
||||||
// 路由接口定义
|
|
||||||
interface IRouteItem {
|
|
||||||
path: string;
|
|
||||||
component?: string;
|
|
||||||
name?: string;
|
|
||||||
meta?: {
|
|
||||||
title?: string;
|
|
||||||
hide?: boolean;
|
|
||||||
icon?: string;
|
|
||||||
};
|
|
||||||
routes?: IRouteItem[];
|
|
||||||
children?: IRouteItem[];
|
|
||||||
redirect?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMenuItem {
|
|
||||||
label: string;
|
|
||||||
key: string;
|
|
||||||
path: string;
|
|
||||||
icon: string;
|
|
||||||
children?: IMenuItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取路由配置转换为菜单项
|
|
||||||
const generateMenuItems = (): IMenuItem[] => {
|
|
||||||
// 找到主布局下的路由
|
|
||||||
const mainLayoutRoute = routerConfig.find((route: IRouteItem) => route.path === '/');
|
|
||||||
if (!mainLayoutRoute || !mainLayoutRoute.routes) return [];
|
|
||||||
|
|
||||||
// 递归处理路由,生成菜单项
|
|
||||||
const processRoutes = (routes: IRouteItem[], parentPath: string = ''): IMenuItem[] => {
|
|
||||||
return routes
|
|
||||||
.filter((route) => !route.redirect && route.name && !route.meta?.hide)
|
|
||||||
.map((route) => {
|
|
||||||
// 构建完整路径
|
|
||||||
const routePath = route.path.startsWith('/')
|
|
||||||
? route.path
|
|
||||||
: `${parentPath}/${route.path}`.replace(/\/+/g, '/');
|
|
||||||
|
|
||||||
// 创建菜单项
|
|
||||||
const menuItem: IMenuItem = {
|
|
||||||
label: route.meta?.title ? `menu.${route.meta.title}` : `menu.${route.name || ''}`,
|
|
||||||
key: route.path || '',
|
|
||||||
path: routePath,
|
|
||||||
icon: route.meta?.icon || 'icon-liebiaomoshi',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 如果有子路由,递归处理
|
|
||||||
if (route.routes && route.routes.length > 0) {
|
|
||||||
const children = processRoutes(route.routes, routePath);
|
|
||||||
if (children.length > 0) {
|
|
||||||
menuItem.children = children;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有children,递归处理
|
|
||||||
if (route.children && route.children.length > 0) {
|
|
||||||
const children = processRoutes(route.children, routePath);
|
|
||||||
if (children.length > 0) {
|
|
||||||
menuItem.children = children;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return menuItem;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return processRoutes(mainLayoutRoute.routes);
|
|
||||||
};
|
|
||||||
|
|
||||||
const items: IMenuItem[] = generateMenuItems();
|
|
||||||
|
|
||||||
const SiderMenu: React.FC = (props: any) => {
|
|
||||||
//当前激活菜单
|
|
||||||
const [current, setCurrent] = useState('index');
|
|
||||||
const intl = useIntl();
|
|
||||||
const history = useHistory();
|
|
||||||
useEffect(() => {
|
|
||||||
// 获取当前激活菜单
|
|
||||||
const path = history.location.pathname;
|
|
||||||
setCurrent(path);
|
|
||||||
// if (path.split('/').length > 1) {
|
|
||||||
// setCurrent(path.split('/')[path.split('/').length - 1]);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
}, [history.location.pathname]);
|
|
||||||
|
|
||||||
// 递归渲染菜单项
|
|
||||||
const renderMenuItems = (menuItems: IMenuItem[]) => {
|
|
||||||
return menuItems.map((item: IMenuItem) =>
|
|
||||||
item.children && item.children.length > 0 ? (
|
|
||||||
<Menu.SubMenu
|
|
||||||
key={item.path}
|
|
||||||
title={
|
|
||||||
<Tooltip title={intl.formatMessage({ id: item.label })} placement="right">
|
|
||||||
<>{intl.formatMessage({ id: item.label })}</>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
icon={<IconFont type={item.icon} />}
|
|
||||||
>
|
|
||||||
{renderMenuItems(item.children)}
|
|
||||||
</Menu.SubMenu>
|
|
||||||
) : (
|
|
||||||
<Menu.Item key={item.path} icon={<IconFont type={item.icon} />}>
|
|
||||||
<Tooltip title={intl.formatMessage({ id: item.label })} placement="right">
|
|
||||||
<Link to={item.path}>{intl.formatMessage({ id: item.label })}</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</Menu.Item>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="header-menu">
|
|
||||||
<Menu selectedKeys={[current]} mode="inline">
|
|
||||||
{renderMenuItems(items)}
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default SiderMenu;
|
|
@ -1,136 +1,60 @@
|
|||||||
import { Effect, Reducer } from 'umi';
|
|
||||||
|
|
||||||
export interface BreadcrumbItem {
|
type Effect = (action: { payload: any }, effects: { call: any; put: any; select: any }) => Generator<any, void, unknown>;
|
||||||
path: string;
|
type Reducer<S> = (state: S, action: { payload: any }) => S;
|
||||||
breadcrumbName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BreadcrumbModelState {
|
export interface BreadcrumbState {
|
||||||
breadcrumbs: BreadcrumbItem[];
|
breadcrumbName: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BreadcrumbModelType {
|
export interface BreadcrumbModelType {
|
||||||
namespace: 'breadcrumb';
|
namespace: 'breadcrumb';
|
||||||
state: BreadcrumbModelState;
|
state: BreadcrumbState;
|
||||||
effects: {
|
effects: {
|
||||||
updateBreadcrumbs: Effect;
|
updateBreadcrumbName: Effect;
|
||||||
|
resetBreadcrumb: Effect;
|
||||||
};
|
};
|
||||||
reducers: {
|
reducers: {
|
||||||
saveBreadcrumbs: Reducer<BreadcrumbModelState>;
|
setBreadcrumbName: Reducer<BreadcrumbState>;
|
||||||
|
resetState: Reducer<BreadcrumbState>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成面包屑数据
|
|
||||||
* @param pathname 当前路径
|
|
||||||
* @param intl 国际化对象
|
|
||||||
*/
|
|
||||||
const generateBreadcrumbs = (pathname: string, intl: any): BreadcrumbItem[] => {
|
|
||||||
// 如果是首页,直接返回首页
|
|
||||||
if (pathname === '/' || pathname === '/index') {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
breadcrumbName: intl.formatMessage({ id: 'menu.首页' }, { defaultMessage: '首页' }),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建面包屑数据
|
|
||||||
const breadcrumbs = [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
breadcrumbName: intl.formatMessage({ id: 'menu.首页' }, { defaultMessage: '首页' }),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// 按照斜杠分割路径
|
|
||||||
const pathSegments = pathname.split('/').filter(segment => segment);
|
|
||||||
let currentPath = '';
|
|
||||||
|
|
||||||
// 构建每一级的路径和对应的面包屑名称
|
|
||||||
for (let i = 0; i < pathSegments.length; i++) {
|
|
||||||
const segment = pathSegments[i];
|
|
||||||
currentPath += `/${segment}`;
|
|
||||||
|
|
||||||
// 尝试使用多语言配置
|
|
||||||
// 先尝试完整路径的多语言配置
|
|
||||||
let menuKey = `menu.${pathSegments.slice(0, i + 1).join('/')}`;
|
|
||||||
let menuName = intl.formatMessage({ id: menuKey }, { defaultMessage: '' });
|
|
||||||
|
|
||||||
// 如果完整路径没有对应的多语言,则尝试使用当前段的多语言
|
|
||||||
if (!menuName) {
|
|
||||||
menuKey = `menu.${segment}`;
|
|
||||||
menuName = intl.formatMessage({ id: menuKey }, { defaultMessage: '' });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果仍然没有找到多语言配置,尝试使用特定页面的多语言配置
|
|
||||||
if (!menuName) {
|
|
||||||
// 处理特殊情况,如数据统计下的子页面
|
|
||||||
if (pathSegments[0] === 'dataStatistics') {
|
|
||||||
switch (segment) {
|
|
||||||
case 'supplierEvaluateStatistics':
|
|
||||||
menuName = intl.formatMessage({ id: 'menu.供应商评价情况统计' }, { defaultMessage: '供应商评价情况统计' });
|
|
||||||
break;
|
|
||||||
case 'supplierAnnualStatistics':
|
|
||||||
menuName = intl.formatMessage({ id: 'menu.供应商年审情况统计' }, { defaultMessage: '供应商年审情况统计' });
|
|
||||||
break;
|
|
||||||
case 'supplierQualificationWarningStatistics':
|
|
||||||
menuName = intl.formatMessage({ id: 'menu.供应商资质预警统计' }, { defaultMessage: '供应商资质预警统计' });
|
|
||||||
break;
|
|
||||||
case 'supplierExitStatistics':
|
|
||||||
menuName = intl.formatMessage({ id: 'menu.供应商清退情况统计' }, { defaultMessage: '供应商清退情况统计' });
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
menuName = segment;
|
|
||||||
}
|
|
||||||
} else if (pathSegments[0] === 'supplierEvaluate') {
|
|
||||||
// 处理供应商评价模块
|
|
||||||
menuName = intl.formatMessage({ id: `menu.${segment}` }, { defaultMessage: segment });
|
|
||||||
} else if (pathSegments[0] === 'supplierAnnual') {
|
|
||||||
// 处理供应商年审模块
|
|
||||||
menuName = intl.formatMessage({ id: `menu.${segment}` }, { defaultMessage: segment });
|
|
||||||
} else {
|
|
||||||
menuName = segment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
breadcrumbs.push({
|
|
||||||
path: currentPath,
|
|
||||||
breadcrumbName: menuName || segment,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return breadcrumbs;
|
|
||||||
};
|
|
||||||
|
|
||||||
const BreadcrumbModel: BreadcrumbModelType = {
|
const BreadcrumbModel: BreadcrumbModelType = {
|
||||||
namespace: 'breadcrumb',
|
namespace: 'breadcrumb',
|
||||||
|
|
||||||
state: {
|
state: {
|
||||||
breadcrumbs: [],
|
breadcrumbName: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
effects: {
|
effects: {
|
||||||
*updateBreadcrumbs({ payload }, { put }) {
|
*updateBreadcrumbName({ payload }, { put }) {
|
||||||
const { pathname, intl } = payload;
|
|
||||||
console.log(pathname)
|
|
||||||
const breadcrumbs = generateBreadcrumbs(pathname, intl);
|
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveBreadcrumbs',
|
type: 'setBreadcrumbName',
|
||||||
payload: breadcrumbs,
|
payload,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
*resetBreadcrumb(_, { put }) {
|
||||||
|
yield put({
|
||||||
|
type: 'resetState',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
reducers: {
|
reducers: {
|
||||||
saveBreadcrumbs(state, { payload }) {
|
setBreadcrumbName(state: BreadcrumbState, { payload }: { payload: string }) {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
breadcrumbs: payload,
|
breadcrumbName: payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
resetState() {
|
||||||
|
return {
|
||||||
|
breadcrumbName: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BreadcrumbModel;
|
export default BreadcrumbModel;
|
@ -1,5 +1,8 @@
|
|||||||
import globalModal from './globalModal';
|
import globalModal from './globalModal';
|
||||||
|
import breadcrumb from './breadcrumb';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
globalModal,
|
globalModal,
|
||||||
|
breadcrumb,
|
||||||
// ... 其他 models
|
// ... 其他 models
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@ import SupplierSelectStep from './components/SupplierSelectStep';
|
|||||||
import EvaluatorSelectStep from './components/EvaluatorSelectStep';
|
import EvaluatorSelectStep from './components/EvaluatorSelectStep';
|
||||||
import styles from './supplierAnnualTaskManageAdd.less';
|
import styles from './supplierAnnualTaskManageAdd.less';
|
||||||
import type { SupplierTaskModelState } from '@/models/supplierAnnualTaskManage';
|
import type { SupplierTaskModelState } from '@/models/supplierAnnualTaskManage';
|
||||||
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
|
|
||||||
const { Step } = Steps;
|
const { Step } = Steps;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ interface PageProps extends ConnectProps {
|
|||||||
* 供应商任务管理添加/编辑组件
|
* 供应商任务管理添加/编辑组件
|
||||||
* 使用步骤式表单引导用户完成添加或编辑任务的流程
|
* 使用步骤式表单引导用户完成添加或编辑任务的流程
|
||||||
*/
|
*/
|
||||||
const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierAnnualTaskManage, dispatch }) => {
|
const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierAnnualTaskManage, dispatch, breadcrumb }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
// 获取dva model中的状态
|
// 获取dva model中的状态
|
||||||
const { currentStep, loading, detailLoading } = supplierAnnualTaskManage;
|
const { currentStep, loading, detailLoading } = supplierAnnualTaskManage;
|
||||||
@ -85,14 +86,23 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierAnnualTaskManage,
|
|||||||
* 组件卸载时重置状态
|
* 组件卸载时重置状态
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (isEditMode && dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: 'supplierAnnualTaskManage.edit.title' }),
|
||||||
|
});
|
||||||
|
}
|
||||||
return () => {
|
return () => {
|
||||||
if (dispatch) {
|
if (dispatch) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'supplierAnnualTaskManage/resetState',
|
type: 'supplierAnnualTaskManage/resetState',
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [dispatch]);
|
}, [dispatch, isEditMode]);
|
||||||
|
|
||||||
// 步骤配置,定义每个步骤的标题、描述和内容组件
|
// 步骤配置,定义每个步骤的标题、描述和内容组件
|
||||||
const steps = [
|
const steps = [
|
||||||
@ -274,7 +284,8 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierAnnualTaskManage,
|
|||||||
|
|
||||||
// 将dva model中的状态映射到组件props
|
// 将dva model中的状态映射到组件props
|
||||||
export default connect(
|
export default connect(
|
||||||
({ supplierAnnualTaskManage }: { supplierAnnualTaskManage: SupplierTaskModelState }) => ({
|
({ supplierAnnualTaskManage, breadcrumb }: { supplierAnnualTaskManage: SupplierTaskModelState, breadcrumb: BreadcrumbState }) => ({
|
||||||
supplierAnnualTaskManage,
|
supplierAnnualTaskManage,
|
||||||
|
breadcrumb,
|
||||||
}),
|
}),
|
||||||
)(SupplierTaskManageAdd);
|
)(SupplierTaskManageAdd);
|
||||||
|
@ -17,23 +17,17 @@ import {
|
|||||||
Popconfirm,
|
Popconfirm,
|
||||||
Modal,
|
Modal,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { history, useLocation, useIntl } from 'umi';
|
import { history, useLocation, useIntl, connect, FormattedMessage } from 'umi';
|
||||||
import {
|
import type { ConnectProps, Dispatch } from 'umi';
|
||||||
ArrowLeftOutlined,
|
import { ArrowLeftOutlined, SaveOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||||
SaveOutlined,
|
|
||||||
PlusOutlined,
|
|
||||||
DeleteOutlined,
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
import CategorySelector from '@/components/CategorySelector';
|
import CategorySelector from '@/components/CategorySelector';
|
||||||
import {
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
AnnualTemplateStatus,
|
import { AnnualTemplateStatus, AnnualTemplateStatusText } from '@/dicts/supplierAnnualDict';
|
||||||
AnnualTemplateStatusText,
|
|
||||||
} from '@/dicts/supplierAnnualDict';
|
|
||||||
import {
|
import {
|
||||||
addAnnualTemplate,
|
addAnnualTemplate,
|
||||||
updateAnnualTemplate,
|
updateAnnualTemplate,
|
||||||
getAnnualTemplateDetail,
|
getAnnualTemplateDetail,
|
||||||
getAllAnnualTemplates
|
getAllAnnualTemplates,
|
||||||
} from '@/servers/api/supplierAnnual';
|
} from '@/servers/api/supplierAnnual';
|
||||||
import styles from './supplierAnnualTemplateManage.less';
|
import styles from './supplierAnnualTemplateManage.less';
|
||||||
|
|
||||||
@ -53,33 +47,30 @@ const CategoryLimitationType = {
|
|||||||
UNIVERSAL: '0', // 不限
|
UNIVERSAL: '0', // 不限
|
||||||
LIMITED: '1', // 限制
|
LIMITED: '1', // 限制
|
||||||
};
|
};
|
||||||
|
|
||||||
// 品类限制类型文本
|
|
||||||
const CategoryLimitationTypeText = {
|
|
||||||
[CategoryLimitationType.UNIVERSAL]: '不限',
|
|
||||||
[CategoryLimitationType.LIMITED]: '限制',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 是否星号项常量
|
// 是否星号项常量
|
||||||
const StarOptions = {
|
const StarOptions = {
|
||||||
YES: '1',
|
YES: '1',
|
||||||
NO: '0',
|
NO: '0',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 是否星号项文本
|
interface PageProps extends ConnectProps {
|
||||||
const StarOptionsText = {
|
breadcrumb: BreadcrumbState; // dva model状态
|
||||||
[StarOptions.YES]: '是',
|
dispatch: Dispatch; // dva dispatch方法
|
||||||
[StarOptions.NO]: '否',
|
}
|
||||||
};
|
const SupplierAnnualTemplateManageAdd: React.FC<PageProps> = ({ breadcrumb, dispatch }) => {
|
||||||
|
|
||||||
const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [isEdit, setIsEdit] = useState<boolean>(false);
|
const [isEdit, setIsEdit] = useState<boolean>(false);
|
||||||
const [templateDetail, setTemplateDetail] = useState<supplierAnnualTemplateManage.TemplateDetailData | null>(null);
|
const [templateDetail, setTemplateDetail] =
|
||||||
const [templateList, setTemplateList] = useState<supplierAnnualTemplateManage.TemplateRecord[]>([]);
|
useState<supplierAnnualTemplateManage.TemplateDetailData | null>(null);
|
||||||
const [indicatorList, setIndicatorList] = useState<supplierAnnualTemplateManage.IndicatorItem[]>([]);
|
const [templateList, setTemplateList] = useState<supplierAnnualTemplateManage.TemplateRecord[]>(
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const [indicatorList, setIndicatorList] = useState<supplierAnnualTemplateManage.IndicatorItem[]>(
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
// 获取路由传递的数据
|
// 获取路由传递的数据
|
||||||
const location = useLocation<LocationState>();
|
const location = useLocation<LocationState>();
|
||||||
@ -90,9 +81,22 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const res = await getAllAnnualTemplates();
|
const res = await getAllAnnualTemplates();
|
||||||
if (res.success && res.data) {
|
if (res.success && res.data) {
|
||||||
setTemplateList(res.data);
|
// 如果是修改,需要过滤掉自己
|
||||||
|
if (location.state?.editData) {
|
||||||
|
setTemplateList(
|
||||||
|
res.data.filter(
|
||||||
|
(template: supplierAnnualTemplateManage.TemplateRecord) =>
|
||||||
|
template.id !== location.state.editData?.id,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setTemplateList(res.data);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message || intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.getListFailed' }));
|
message.error(
|
||||||
|
res.message ||
|
||||||
|
intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.getListFailed' }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -124,7 +128,10 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
setIndicatorList(res.data.indicatorList);
|
setIndicatorList(res.data.indicatorList);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message || intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }));
|
message.error(
|
||||||
|
res.message ||
|
||||||
|
intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -133,7 +140,21 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (location.state?.editData?.id && dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "supplierAnnualTemplateManage.add.edit" }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件卸载时重置面包屑
|
||||||
|
return () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [dispatch, intl, location]);
|
||||||
// 初始化编辑数据
|
// 初始化编辑数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 获取所有模板列表
|
// 获取所有模板列表
|
||||||
@ -176,20 +197,27 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res && res.success) {
|
if (res && res.success) {
|
||||||
message.success(isEdit
|
message.success(
|
||||||
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitSuccess' })
|
isEdit
|
||||||
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveSuccess' }));
|
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitSuccess' })
|
||||||
|
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveSuccess' }),
|
||||||
|
);
|
||||||
history.goBack();
|
history.goBack();
|
||||||
} else {
|
} else {
|
||||||
message.error(res?.message || (isEdit
|
message.error(
|
||||||
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitFailed' })
|
res?.message ||
|
||||||
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveFailed' })));
|
(isEdit
|
||||||
|
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitFailed' })
|
||||||
|
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveFailed' })),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('提交失败:', error);
|
console.error('提交失败:', error);
|
||||||
message.error(isEdit
|
message.error(
|
||||||
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitFailed' })
|
isEdit
|
||||||
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveFailed' }));
|
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.submitFailed' })
|
||||||
|
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.saveFailed' }),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@ -199,17 +227,21 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
const handleSubmit = async (values: any) => {
|
const handleSubmit = async (values: any) => {
|
||||||
// 检查指标列表
|
// 检查指标列表
|
||||||
if (!indicatorList || indicatorList.length === 0) {
|
if (!indicatorList || indicatorList.length === 0) {
|
||||||
message.error(intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.atLeastOneIndicator' }));
|
message.error(
|
||||||
|
intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.atLeastOneIndicator' }),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查指标名称不能为空
|
// 检查指标名称不能为空
|
||||||
const emptyNameIndex = indicatorList.findIndex(item => !item.itemName);
|
const emptyNameIndex = indicatorList.findIndex((item) => !item.itemName);
|
||||||
if (emptyNameIndex !== -1) {
|
if (emptyNameIndex !== -1) {
|
||||||
message.error(intl.formatMessage(
|
message.error(
|
||||||
{ id: 'supplierAnnualTemplateManage.add.indicatorNameRequired' },
|
intl.formatMessage(
|
||||||
{ index: emptyNameIndex + 1 }
|
{ id: 'supplierAnnualTemplateManage.add.indicatorNameRequired' },
|
||||||
));
|
{ index: emptyNameIndex + 1 },
|
||||||
|
),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +267,7 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
cancelText: intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' }),
|
cancelText: intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' }),
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
await submitFormData(submitData);
|
await submitFormData(submitData);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -255,20 +287,27 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
|
|
||||||
// 复制指标列表
|
// 复制指标列表
|
||||||
if (res.data.indicatorList && res.data.indicatorList.length > 0) {
|
if (res.data.indicatorList && res.data.indicatorList.length > 0) {
|
||||||
const copiedList = JSON.parse(JSON.stringify(res.data.indicatorList)).map((item: any) => {
|
const copiedList = JSON.parse(JSON.stringify(res.data.indicatorList)).map(
|
||||||
// 删除id,防止ID冲突
|
(item: any) => {
|
||||||
delete item.id;
|
// 删除id,防止ID冲突
|
||||||
return item;
|
delete item.id;
|
||||||
});
|
return item;
|
||||||
|
},
|
||||||
|
);
|
||||||
setIndicatorList(copiedList);
|
setIndicatorList(copiedList);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error(res.message || intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }));
|
message.error(
|
||||||
|
res.message ||
|
||||||
|
intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取模板详情失败:', error);
|
console.error('获取模板详情失败:', error);
|
||||||
message.error(intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }));
|
message.error(
|
||||||
|
intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.getDetailFailed' }),
|
||||||
|
);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +359,9 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
<Input
|
<Input
|
||||||
value={text}
|
value={text}
|
||||||
onChange={(e) => handleIndicatorChange(index, 'itemName', e.target.value)}
|
onChange={(e) => handleIndicatorChange(index, 'itemName', e.target.value)}
|
||||||
placeholder={`${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseInput' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.checkItem' })}`}
|
placeholder={`${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseInput',
|
||||||
|
})}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.checkItem' })}`}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -335,8 +376,12 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
onChange={(value) => handleIndicatorChange(index, 'isStar', value)}
|
onChange={(value) => handleIndicatorChange(index, 'isStar', value)}
|
||||||
className={styles.starSelector}
|
className={styles.starSelector}
|
||||||
>
|
>
|
||||||
<Option value={StarOptions.YES}>{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.yes' })}</Option>
|
<Option value={StarOptions.YES}>
|
||||||
<Option value={StarOptions.NO}>{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.no' })}</Option>
|
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.yes' })}
|
||||||
|
</Option>
|
||||||
|
<Option value={StarOptions.NO}>
|
||||||
|
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.no' })}
|
||||||
|
</Option>
|
||||||
</Select>
|
</Select>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -355,12 +400,19 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.modal.deleteConfirmContent' })}
|
title={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.modal.deleteConfirmContent',
|
||||||
|
})}
|
||||||
onConfirm={() => handleDeleteIndicator(index)}
|
onConfirm={() => handleDeleteIndicator(index)}
|
||||||
okText={intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.confirm' })}
|
okText={intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.confirm' })}
|
||||||
cancelText={intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' })}
|
cancelText={intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' })}
|
||||||
>
|
>
|
||||||
<Button type="link" danger icon={<DeleteOutlined />} title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.deleteIndicator' })} />
|
<Button
|
||||||
|
type="link"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.deleteIndicator' })}
|
||||||
|
/>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
@ -369,143 +421,223 @@ const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="common-container">
|
<div className="common-container">
|
||||||
<div className={styles.pageHeader}>
|
<div className={styles.pageHeader}>
|
||||||
<Title level={4} style={{ margin: 0 }}>
|
<Title level={4} style={{ margin: 0 }}>
|
||||||
{isEdit
|
{isEdit
|
||||||
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.edit' })
|
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.edit' })
|
||||||
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.title' })
|
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.title' })}
|
||||||
}
|
</Title>
|
||||||
</Title>
|
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.back' })}
|
||||||
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.back' })}
|
</Button>
|
||||||
</Button>
|
</div>
|
||||||
|
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
onFinish={handleSubmit}
|
||||||
|
initialValues={{
|
||||||
|
categoryLimitation: CategoryLimitationType.UNIVERSAL,
|
||||||
|
status: AnnualTemplateStatus.DRAFT,
|
||||||
|
}}
|
||||||
|
labelCol={{ span: 7 }}
|
||||||
|
wrapperCol={{ span: 17 }}
|
||||||
|
>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
<Card
|
||||||
|
title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.basicInfo' })}
|
||||||
|
bordered={false}
|
||||||
|
className={styles.innerCard}
|
||||||
|
>
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col span={8}>
|
||||||
|
<Form.Item
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.list.templateName',
|
||||||
|
})}
|
||||||
|
name="templateName"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseInput',
|
||||||
|
})}${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.list.templateName',
|
||||||
|
})}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder={`${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseInput',
|
||||||
|
})}${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.list.templateName',
|
||||||
|
})}`}
|
||||||
|
maxLength={50}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Form.Item
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.categoryLimitation',
|
||||||
|
})}
|
||||||
|
name="categoryLimitation"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseSelect',
|
||||||
|
})}${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.categoryLimitation',
|
||||||
|
})}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={CategoryLimitationType.UNIVERSAL}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.categoryLimitationUniversal',
|
||||||
|
})}
|
||||||
|
</Radio>
|
||||||
|
<Radio value={CategoryLimitationType.LIMITED}>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.categoryLimitationLimited',
|
||||||
|
})}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Form.Item
|
||||||
|
noStyle
|
||||||
|
shouldUpdate={(prevValues, currentValues) =>
|
||||||
|
prevValues.categoryLimitation !== currentValues.categoryLimitation
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{({ getFieldValue }) => {
|
||||||
|
const categoryLimitation = getFieldValue('categoryLimitation');
|
||||||
|
return categoryLimitation === CategoryLimitationType.LIMITED ? (
|
||||||
|
<Form.Item
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.selectCategory',
|
||||||
|
})}
|
||||||
|
name="categoryId"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseSelect',
|
||||||
|
})}${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.list.category',
|
||||||
|
})}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<CategorySelector multiple={false} />
|
||||||
|
</Form.Item>
|
||||||
|
) : null;
|
||||||
|
}}
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col span={8}>
|
||||||
|
<Form.Item
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.selectTemplate',
|
||||||
|
})}
|
||||||
|
name="copyTemplateId"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseSelect',
|
||||||
|
})}
|
||||||
|
loading={templateList.length === 0}
|
||||||
|
onSelect={handleTemplateSelect}
|
||||||
|
>
|
||||||
|
{templateList.map((template) =>
|
||||||
|
template.id ? (
|
||||||
|
<Option key={template.id} value={template.id}>
|
||||||
|
{template.templateName}
|
||||||
|
</Option>
|
||||||
|
) : null,
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Form.Item
|
||||||
|
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.status' })}
|
||||||
|
name="status"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.common.pleaseSelect',
|
||||||
|
})}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.status' })}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value={AnnualTemplateStatus.DRAFT}>
|
||||||
|
{AnnualTemplateStatusText[AnnualTemplateStatus.DRAFT]}
|
||||||
|
</Radio>
|
||||||
|
<Radio value={AnnualTemplateStatus.ENABLED}>
|
||||||
|
{AnnualTemplateStatusText[AnnualTemplateStatus.ENABLED]}
|
||||||
|
</Radio>
|
||||||
|
<Radio value={AnnualTemplateStatus.DISABLED}>
|
||||||
|
{AnnualTemplateStatusText[AnnualTemplateStatus.DISABLED]}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Card
|
||||||
|
title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.indicatorInfo' })}
|
||||||
|
bordered={false}
|
||||||
|
className={styles.innerCard}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
dataSource={indicatorList}
|
||||||
|
bordered
|
||||||
|
rowKey="orderBy"
|
||||||
|
size="middle"
|
||||||
|
pagination={false}
|
||||||
|
locale={{
|
||||||
|
emptyText: intl.formatMessage({
|
||||||
|
id: 'supplierAnnualTemplateManage.add.noIndicatorData',
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
className={styles.indicatorTable}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Spin>
|
||||||
|
|
||||||
|
<div className={styles.formActions}>
|
||||||
|
<Space>
|
||||||
|
<Button onClick={handleBack}>
|
||||||
|
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' })}
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" htmlType="submit" loading={loading} icon={<SaveOutlined />}>
|
||||||
|
{isEdit
|
||||||
|
? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.update' })
|
||||||
|
: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.save' })}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
|
</Form>
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
onFinish={handleSubmit}
|
|
||||||
initialValues={{
|
|
||||||
categoryLimitation: CategoryLimitationType.UNIVERSAL,
|
|
||||||
status: AnnualTemplateStatus.DRAFT,
|
|
||||||
}}
|
|
||||||
labelCol={{ span: 7 }}
|
|
||||||
wrapperCol={{ span: 17 }}
|
|
||||||
>
|
|
||||||
<Spin spinning={loading}>
|
|
||||||
<Card title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.basicInfo' })} bordered={false} className={styles.innerCard}>
|
|
||||||
<Row gutter={24}>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item
|
|
||||||
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.templateName' })}
|
|
||||||
name="templateName"
|
|
||||||
rules={[{ required: true, message: `${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseInput' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.templateName' })}` }]}
|
|
||||||
>
|
|
||||||
<Input placeholder={`${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseInput' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.templateName' })}`} maxLength={50} />
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item
|
|
||||||
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.categoryLimitation' })}
|
|
||||||
name="categoryLimitation"
|
|
||||||
rules={[{ required: true, message: `${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseSelect' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.categoryLimitation' })}` }]}
|
|
||||||
>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={CategoryLimitationType.UNIVERSAL}>
|
|
||||||
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.categoryLimitationUniversal' })}
|
|
||||||
</Radio>
|
|
||||||
<Radio value={CategoryLimitationType.LIMITED}>
|
|
||||||
{intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.categoryLimitationLimited' })}
|
|
||||||
</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item
|
|
||||||
noStyle
|
|
||||||
shouldUpdate={(prevValues, currentValues) =>
|
|
||||||
prevValues.categoryLimitation !== currentValues.categoryLimitation
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{({ getFieldValue }) => {
|
|
||||||
const categoryLimitation = getFieldValue('categoryLimitation');
|
|
||||||
return categoryLimitation === CategoryLimitationType.LIMITED ? (
|
|
||||||
<Form.Item
|
|
||||||
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.selectCategory' })}
|
|
||||||
name="categoryId"
|
|
||||||
rules={[{ required: true, message: `${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseSelect' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.category' })}` }]}
|
|
||||||
>
|
|
||||||
<CategorySelector multiple={false} />
|
|
||||||
</Form.Item>
|
|
||||||
) : null;
|
|
||||||
}}
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
<Row gutter={24}>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item
|
|
||||||
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.selectTemplate' })}
|
|
||||||
name="copyTemplateId"
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
placeholder={intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseSelect' })}
|
|
||||||
loading={templateList.length === 0}
|
|
||||||
onSelect={handleTemplateSelect}
|
|
||||||
>
|
|
||||||
{templateList.map(template => (
|
|
||||||
template.id ? (
|
|
||||||
<Option key={template.id} value={template.id}>
|
|
||||||
{template.templateName}
|
|
||||||
</Option>
|
|
||||||
) : null
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Form.Item
|
|
||||||
label={intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.status' })}
|
|
||||||
name="status"
|
|
||||||
rules={[{ required: true, message: `${intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.pleaseSelect' })}${intl.formatMessage({ id: 'supplierAnnualTemplateManage.list.status' })}` }]}
|
|
||||||
>
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value={AnnualTemplateStatus.DRAFT}>{AnnualTemplateStatusText[AnnualTemplateStatus.DRAFT]}</Radio>
|
|
||||||
<Radio value={AnnualTemplateStatus.ENABLED}>{AnnualTemplateStatusText[AnnualTemplateStatus.ENABLED]}</Radio>
|
|
||||||
<Radio value={AnnualTemplateStatus.DISABLED}>{AnnualTemplateStatusText[AnnualTemplateStatus.DISABLED]}</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<Card title={intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.indicatorInfo' })} bordered={false} className={styles.innerCard}>
|
|
||||||
<Table
|
|
||||||
columns={columns}
|
|
||||||
dataSource={indicatorList}
|
|
||||||
bordered
|
|
||||||
rowKey="orderBy"
|
|
||||||
size="middle"
|
|
||||||
pagination={false}
|
|
||||||
locale={{ emptyText: intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.noIndicatorData' }) }}
|
|
||||||
className={styles.indicatorTable}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Spin>
|
|
||||||
|
|
||||||
<div className={styles.formActions}>
|
|
||||||
<Space>
|
|
||||||
<Button onClick={handleBack}>{intl.formatMessage({ id: 'supplierAnnualTemplateManage.common.cancel' })}</Button>
|
|
||||||
<Button type="primary" htmlType="submit" loading={loading} icon={<SaveOutlined />}>
|
|
||||||
{isEdit ? intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.update' }) : intl.formatMessage({ id: 'supplierAnnualTemplateManage.add.save' })}
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SupplierAnnualTemplateManageAdd;
|
// export default SupplierAnnualTemplateManageAdd;
|
||||||
|
// 将dva model中的状态映射到组件props
|
||||||
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
||||||
|
breadcrumb,
|
||||||
|
}))(SupplierAnnualTemplateManageAdd);
|
||||||
|
@ -10,6 +10,7 @@ import DivisionStep from './components/DivisionStep';
|
|||||||
import styles from './supplierTaskManageAdd.less';
|
import styles from './supplierTaskManageAdd.less';
|
||||||
import { TaskNotifyLowerUnits } from '@/dicts/supplierTaskDict';
|
import { TaskNotifyLowerUnits } from '@/dicts/supplierTaskDict';
|
||||||
import type { SupplierTaskModelState } from '@/models/supplierTaskManage';
|
import type { SupplierTaskModelState } from '@/models/supplierTaskManage';
|
||||||
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
|
|
||||||
const { Step } = Steps;
|
const { Step } = Steps;
|
||||||
|
|
||||||
@ -40,7 +41,11 @@ interface PageProps extends ConnectProps {
|
|||||||
* 供应商任务管理添加/编辑组件
|
* 供应商任务管理添加/编辑组件
|
||||||
* 使用步骤式表单引导用户完成添加或编辑任务的流程
|
* 使用步骤式表单引导用户完成添加或编辑任务的流程
|
||||||
*/
|
*/
|
||||||
const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispatch }) => {
|
const SupplierTaskManageAdd: React.FC<PageProps> = ({
|
||||||
|
supplierTaskManage,
|
||||||
|
dispatch,
|
||||||
|
breadcrumb,
|
||||||
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
// 获取dva model中的状态
|
// 获取dva model中的状态
|
||||||
const { currentStep, loading, detailLoading } = supplierTaskManage;
|
const { currentStep, loading, detailLoading } = supplierTaskManage;
|
||||||
@ -70,6 +75,11 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispat
|
|||||||
type: 'supplierTaskManage/saveMode',
|
type: 'supplierTaskManage/saveMode',
|
||||||
payload: 'edit',
|
payload: 'edit',
|
||||||
});
|
});
|
||||||
|
// 更新面包屑
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: 'supplierTaskManage.title.edit' }),
|
||||||
|
});
|
||||||
// 编辑模式,获取任务详情
|
// 编辑模式,获取任务详情
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'supplierTaskManage/fetchTaskDetail',
|
type: 'supplierTaskManage/fetchTaskDetail',
|
||||||
@ -106,6 +116,9 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispat
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: 'supplierTaskManage/resetState',
|
type: 'supplierTaskManage/resetState',
|
||||||
});
|
});
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
@ -124,7 +137,9 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispat
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'supplierTaskManage.step.selectEvaluator.title' }),
|
title: intl.formatMessage({ id: 'supplierTaskManage.step.selectEvaluator.title' }),
|
||||||
description: intl.formatMessage({ id: 'supplierTaskManage.step.selectEvaluator.description' }),
|
description: intl.formatMessage({
|
||||||
|
id: 'supplierTaskManage.step.selectEvaluator.description',
|
||||||
|
}),
|
||||||
content: <EvaluatorSelectStep ref={evaluatorFormRef} />,
|
content: <EvaluatorSelectStep ref={evaluatorFormRef} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -177,7 +192,9 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispat
|
|||||||
if (typeof errorInfo === 'string') {
|
if (typeof errorInfo === 'string') {
|
||||||
message.error(errorInfo);
|
message.error(errorInfo);
|
||||||
} else if (errorInfo && errorInfo.errorFields) {
|
} else if (errorInfo && errorInfo.errorFields) {
|
||||||
message.error(intl.formatMessage({ id: 'supplierTaskManage.message.formValidationFailed' }));
|
message.error(
|
||||||
|
intl.formatMessage({ id: 'supplierTaskManage.message.formValidationFailed' }),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -357,7 +374,14 @@ const SupplierTaskManageAdd: React.FC<PageProps> = ({ supplierTaskManage, dispat
|
|||||||
|
|
||||||
// 将dva model中的状态映射到组件props
|
// 将dva model中的状态映射到组件props
|
||||||
export default connect(
|
export default connect(
|
||||||
({ supplierTaskManage }: { supplierTaskManage: SupplierTaskModelState }) => ({
|
({
|
||||||
supplierTaskManage,
|
supplierTaskManage,
|
||||||
|
breadcrumb,
|
||||||
|
}: {
|
||||||
|
supplierTaskManage: SupplierTaskModelState;
|
||||||
|
breadcrumb: BreadcrumbState;
|
||||||
|
}) => ({
|
||||||
|
supplierTaskManage,
|
||||||
|
breadcrumb,
|
||||||
}),
|
}),
|
||||||
)(SupplierTaskManageAdd);
|
)(SupplierTaskManageAdd);
|
||||||
|
@ -16,7 +16,9 @@ import {
|
|||||||
Spin,
|
Spin,
|
||||||
Modal,
|
Modal,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { history, useLocation, useIntl } from 'umi';
|
import { history, useLocation, useIntl, connect } from 'umi';
|
||||||
|
import type { Dispatch,ConnectProps } from 'umi';
|
||||||
|
import type { BreadcrumbState } from '@/models/breadcrumb';
|
||||||
import { ArrowLeftOutlined, SaveOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
import { ArrowLeftOutlined, SaveOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
import EvaluateTemplateTable from '@/components/EvaluateTemplateTable';
|
import EvaluateTemplateTable from '@/components/EvaluateTemplateTable';
|
||||||
import CategorySelector from '@/components/CategorySelector';
|
import CategorySelector from '@/components/CategorySelector';
|
||||||
@ -50,6 +52,11 @@ interface FormValues {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PageProps extends ConnectProps {
|
||||||
|
breadcrumb: BreadcrumbState; // dva model状态
|
||||||
|
dispatch: Dispatch; // dva dispatch方法
|
||||||
|
}
|
||||||
|
|
||||||
interface LocationState {
|
interface LocationState {
|
||||||
isEdit?: boolean;
|
isEdit?: boolean;
|
||||||
editData?: SupplierTemplateManage.TemplateItem;
|
editData?: SupplierTemplateManage.TemplateItem;
|
||||||
@ -57,7 +64,7 @@ interface LocationState {
|
|||||||
|
|
||||||
const { Title } = Typography;
|
const { Title } = Typography;
|
||||||
|
|
||||||
const SupplierTemplateManageAdd: React.FC = () => {
|
const SupplierTemplateManageAdd: React.FC<PageProps> = ({ breadcrumb, dispatch }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm<FormValues>();
|
const [form] = Form.useForm<FormValues>();
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
@ -79,7 +86,12 @@ const SupplierTemplateManageAdd: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const res = await getAllTemplates();
|
const res = await getAllTemplates();
|
||||||
if (res.success && res.data) {
|
if (res.success && res.data) {
|
||||||
setTemplateList(res.data);
|
// 如果是修改,需要过滤掉自己
|
||||||
|
if (location.state?.editData) {
|
||||||
|
setTemplateList(res.data.filter((template: SupplierTemplateManage.TemplateItem) => template.id !== location.state.editData?.id));
|
||||||
|
} else {
|
||||||
|
setTemplateList(res.data);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
message.error(intl.formatMessage({ id: 'supplierTemplateManage.message.getTemplateListFailed' }) || res.message);
|
message.error(intl.formatMessage({ id: 'supplierTemplateManage.message.getTemplateListFailed' }) || res.message);
|
||||||
}
|
}
|
||||||
@ -122,6 +134,19 @@ const SupplierTemplateManageAdd: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (location.state?.editData?.id && dispatch) {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/updateBreadcrumbName',
|
||||||
|
payload: intl.formatMessage({ id: "supplierTemplateManage.edit.title" }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'breadcrumb/resetBreadcrumb',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [dispatch, intl, location]);
|
||||||
// 初始化编辑数据
|
// 初始化编辑数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 获取所有模板列表
|
// 获取所有模板列表
|
||||||
@ -450,4 +475,9 @@ const SupplierTemplateManageAdd: React.FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SupplierTemplateManageAdd;
|
|
||||||
|
// export default SupplierTemplateManageAdd;
|
||||||
|
// 将dva model中的状态映射到组件props
|
||||||
|
export default connect(({ breadcrumb }: { breadcrumb: BreadcrumbState }) => ({
|
||||||
|
breadcrumb,
|
||||||
|
}))(SupplierTemplateManageAdd);
|
||||||
|
Reference in New Issue
Block a user