Compare commits

..

No commits in common. "develop-20231228" and "main" have entirely different histories.

22 changed files with 6689 additions and 55515 deletions

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
node_modules
package-lock.json
src/.umi

View File

@ -1,12 +1,3 @@
/*
* @version: V1.0.0
* @Date: 2023-12-28 11:28:34
* @LastEditors: lzq
* @LastEditTime: 2023-12-29 15:41:41
* @company:
* @FilePath: \salpa-web\config\defaultSettings.ts
* @Descripttion:
*/
import { Settings as LayoutSettings } from '@ant-design/pro-layout'; import { Settings as LayoutSettings } from '@ant-design/pro-layout';
const Settings: LayoutSettings & { const Settings: LayoutSettings & {
@ -16,7 +7,7 @@ const Settings: LayoutSettings & {
} = { } = {
navTheme: 'light', navTheme: 'light',
headerTheme: 'light', headerTheme: 'light',
primaryColor: '#2B50C4', primaryColor: '#722ED1',
layout: 'top', layout: 'top',
splitMenus: true, splitMenus: true,
contentWidth: 'Fluid', contentWidth: 'Fluid',

View File

@ -1,12 +1,3 @@
/*
* @version: V1.0.0
* @Date: 2023-12-28 11:28:34
* @LastEditors: lzq
* @LastEditTime: 2023-12-28 13:31:22
* @company:
* @FilePath: \salpa-web\config\proxy.ts
* @Descripttion:
*/
/** /**
* *
* ------------------------------- * -------------------------------
@ -19,7 +10,7 @@ export default {
dev: { dev: {
'/api/': { '/api/': {
// target: 'http://192.168.103.172:8080', // target: 'http://192.168.103.172:8080',
target: 'http://192.168.1.217:9080', target: 'http://192.168.2.58:8080',
changeOrigin: true, changeOrigin: true,
pathRewrite: { '^/api': '' }, pathRewrite: { '^/api': '' },
}, },
@ -28,7 +19,7 @@ export default {
target: 'http://192.168.113.251:8080', target: 'http://192.168.113.251:8080',
changeOrigin: true, changeOrigin: true,
}, }
}, },
test: { test: {
'/api/': { '/api/': {

57256
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,98 +5,77 @@
* *
* */ * */
import type { Settings as LayoutSettings } from '@ant-design/pro-layout'; import RightContent from '@/components/RightContent'
import { PageLoading } from '@ant-design/pro-layout'; import type { Settings as LayoutSettings } from '@ant-design/pro-layout'
import type { RunTimeLayoutConfig } from 'umi'; import { PageLoading } from '@ant-design/pro-layout'
import { history, Link } from 'umi'; import type { RunTimeLayoutConfig } from 'umi'
import { history, Link } from 'umi'
// import Footer from '@/components/Footer'; // import Footer from '@/components/Footer';
import { BookOutlined, LinkOutlined } from '@ant-design/icons'; import { BookOutlined, LinkOutlined } from '@ant-design/icons'
import defaultSettings from '../config/defaultSettings'; import defaultSettings from '../config/defaultSettings'
import iconStyle from '../public/樽海鞘_图案.svg'; import iconStyle from '../public/樽海鞘_图案.svg'
import './modelstyle.css'; import { getRoutersInfo, getUserInfo } from './services/session'
import { getRoutersInfo, getUserInfo } from './services/session'; const isDev = process.env.NODE_ENV === 'development'
import { login } from './services/login'; const loginPath = '/user/login'
import { setSessionToken } from './access';
import { Route } from 'react-router';
const isDev = process.env.NODE_ENV === 'development';
const loginPath = '/user/login';
/** 获取用户信息比较慢的时候会展示一个 loading */ /** 获取用户信息比较慢的时候会展示一个 loading */
export const initialStateConfig = { export const initialStateConfig = {
loading: <PageLoading />, loading: <PageLoading />
};
const fetchUserInfo = async (setInitialState: any) => {
try {
const resp = await getUserInfo()
if (resp === undefined || resp.code !== 200) {
const response = await login({ username: 'admin', password: 'admin123' });
const current = new Date();
const expireTime = current.setTime(current.getTime() + 1000 * 12 * 60 * 60);
setSessionToken(response.token, response.token, expireTime);
const { user, permissions } = await getUserInfo()
await setInitialState((s) => ({
...s,
currentUser: { permissions, user },
}));
let menus = await getRoutersInfo();
if (window.localStorage.getItem('redirectPath')?.indexOf('?') !== -1) {
menus = menus.map((item) => {
return {
...item,
hideInMenu: true,
};
});
}
setInitialState((preInitialState: any) => ({
...preInitialState,
menus,
})).then(() => {
const path = window.localStorage.getItem("redirectPath") || loginPath
history.push(path)
})
} else {
return { ...resp.user, permissions: resp.permissions } as API.CurrentUser
}
} catch (error) {
console.log(error);
history.push(loginPath)
}
return undefined
} }
/** /**
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state * @see https://umijs.org/zh-CN/plugins/plugin-initial-state
* */ * */
export async function getInitialState(): Promise<{ export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>; settings?: Partial<LayoutSettings>
currentUser?: API.CurrentUser; currentUser?: API.CurrentUser
loading?: boolean; loading?: boolean
fetchUserInfo?: (params: any) => Promise<API.CurrentUser | undefined>; fetchUserInfo?: () => Promise<API.CurrentUser | undefined>
}> { }> {
const fetchUserInfo = async () => {
try {
console.log(1111111111111111111111111111111)
const resp = await getUserInfo()
if (resp === undefined || resp.code !== 200) {
history.push(loginPath)
} else {
return { ...resp.user, permissions: resp.permissions } as API.CurrentUser
}
} catch (error) {
history.push(loginPath)
}
return undefined
}
// 如果是登录页面,不执行
if (history.location.pathname !== loginPath) {
console.log(222222222222222222222222222222)
const currentUser = await fetchUserInfo()
return {
settings: defaultSettings,
currentUser,
fetchUserInfo
}
}
return { return {
fetchUserInfo, fetchUserInfo,
settings: defaultSettings, settings: defaultSettings
}; }
} }
// ProLayout 支持的api https://procomponents.ant.design/components/layout // ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => { export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
return { return {
rightContentRender: () => <div />, rightContentRender: () => <RightContent />,
waterMarkProps: { waterMarkProps: {
content: initialState?.currentUser?.userName, content: initialState?.currentUser?.userName
}, },
// footerRender: () => <Footer />, // footerRender: () => <Footer />,
onPageChange: async () => { onPageChange: () => {
if (!initialState?.currentUser?.userId) { const { location } = history
fetchUserInfo?.(setInitialState); // 如果没有登录,重定向到 login
if (!initialState?.currentUser && location.pathname !== loginPath) {
history.push(loginPath)
} }
}, },
pure: !!new URLSearchParams(window.location.search), // 删除自带页面
// pure:true,
links: isDev links: isDev
? [ ? [
<Link key="openapi" to="/umi/plugin/openapi" target="_blank"> <Link key="openapi" to="/umi/plugin/openapi" target="_blank">
@ -106,41 +85,27 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
<Link key="docs" to="/~docs"> <Link key="docs" to="/~docs">
<BookOutlined /> <BookOutlined />
<span></span> <span></span>
</Link>, </Link>
] ]
: [], : [],
menuHeaderRender: false, menuHeaderRender: undefined,
menu: { menu: {
// 每当 initialState?.currentUser?.userid 发生修改时重新执行 request // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
params: { params: {
userId: initialState?.currentUser?.userId, userId: initialState?.currentUser?.userId
}, },
request: async () => { request: async () => {
if (!initialState?.currentUser?.userId) { if (!initialState?.currentUser?.userId) {
let path = window.location.pathname return []
if (window.location.search) {
path += '?hideInMenu=true'
}
window.localStorage.setItem("redirectPath", path)
return [];
} }
// initialState.currentUser 中包含了所有用户信息 // initialState.currentUser 中包含了所有用户信息
const menus = await getRoutersInfo(); const menus = await getRoutersInfo()
// const hideInMenu = urlParams.get('hideInMenu'); // 替换 'hideInMenu' 为你要获取的参数名
// if (hideInMenu) {
// menus = menus.map((item) => {
// return {
// ...item,
// hideInMenu: true,
// };
// });
// }
setInitialState((preInitialState: any) => ({ setInitialState((preInitialState: any) => ({
...preInitialState, ...preInitialState,
menus, menus
})); }))
return menus; return menus
}, }
}, },
// 自定义 403 页面 // 自定义 403 页面
// unAccessible: <div>unAccessible</div>, // unAccessible: <div>unAccessible</div>,
@ -151,9 +116,9 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
{children} {children}
{!props.location?.pathname?.includes('/login')} {!props.location?.pathname?.includes('/login')}
</div> </div>
); )
}, },
...initialState?.settings, ...initialState?.settings,
logo: <img src={iconStyle} />, logo: <img src={iconStyle} />
}; }
}; }

View File

@ -5,119 +5,111 @@
* @Last Modified time: 2022-02-21 11:12:12 * @Last Modified time: 2022-02-21 11:12:12
*/ */
import { CloseOutlined } from '@ant-design/icons';
import { SortableElement } from 'react-sortable-hoc'; import { SortableElement } from 'react-sortable-hoc';
import { useAliveController, useHistory, useModel } from 'umi'; import { CloseOutlined } from '@ant-design/icons';
import { useModel, useHistory, useAliveController } from 'umi'
import styles from './index.less'; import styles from './index.less';
interface ITab { interface ITab {
value: { value: {
hash: string; hash: string
key: string; key: string
title: string; title: string
pathname: string; pathname: string
query: Record<string, any>; query: Record<string, any>
search: string; search: string
state: any; state: any
keepAliveName: string; keepAliveName: string
}; }
// index: number // index: number
tabIndex: number; tabIndex: number
} }
const SortableTab = (props: ITab) => { const SortableTab = (props: ITab) => {
const history = useHistory(); const history = useHistory()
const { value, tabIndex } = props; const { value, tabIndex } = props;
const { active, dispatch, tabWidth, tarnslateX, showTabs, tabsWidth, tabList } = const { active, dispatch, tabWidth, tarnslateX, showTabs, tabsWidth, tabList } = useModel("system");
useModel('system'); const { dropScope } = useAliveController()
const { dropScope } = useAliveController(); const closable = tabList.length > 1
const closable = tabList.length > 1; return (
const urlParams = new URLSearchParams(window.location.search);
const hideInMenu = urlParams.get('hideInMenu'); // 替换 'hideInMenu' 为你要获取的参数名
return !hideInMenu ? (
<div <div
className={`${styles.tabItem} link-tab ${tabIndex === active ? styles.active : ''}`} className={`${styles.tabItem} link-tab ${tabIndex === active ? styles.active : ''}`}
title={value.title} title={value.title}
onClick={() => { onClick={() => {
// translate了 多少个 // translate了 多少个
const tarnsNumber = Math.floor(tarnslateX / tabWidth); const tarnsNumber = Math.floor(tarnslateX / tabWidth)
// 隐藏了多少 // 隐藏了多少
const isBeyondDistance = tarnslateX - tarnsNumber * tabWidth; const isBeyondDistance = tarnslateX - tarnsNumber * tabWidth;
if (tabIndex - tarnsNumber <= 0) { if (tabIndex - tarnsNumber <= 0) {
dispatch({ dispatch({ type: 'CHANGESTATE', payload: { active: tabIndex, tarnslateX: tarnslateX - isBeyondDistance } })
type: 'CHANGESTATE', history.push({ ...value })
payload: { active: tabIndex, tarnslateX: tarnslateX - isBeyondDistance },
});
history.push({ ...value });
return; return;
} }
// 是否在可视区域内 // 是否在可视区域内
if (tabIndex - tarnsNumber + 1 === showTabs) { if ((tabIndex - tarnsNumber + 1) === showTabs) {
// 需要移动的距离计算 // 需要移动的距离计算
const x = (tabIndex + 1) * (tabWidth as number) - (tabsWidth - 100); const x = (tabIndex + 1) * (tabWidth as number) - (tabsWidth - 100)
dispatch({ type: 'CHANGESTATE', payload: { active: tabIndex, tarnslateX: x } }); dispatch({ type: 'CHANGESTATE', payload: { active: tabIndex, tarnslateX: x } })
history.push({ ...value }); history.push({ ...value })
return; return;
} }
dispatch({ type: 'CHANGESTATE', payload: { active: tabIndex } }); dispatch({ type: 'CHANGESTATE', payload: { active: tabIndex } })
history.push({ ...value }); history.push({ ...value })
}}
> }}>
{value.title} {value.title}
{closable && ( {
closable && (
<div <div
className={styles.closeIcon} className={styles.closeIcon}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation()
const currentName = value.keepAliveName; const currentName = value.keepAliveName
// 如果关闭激活中的 KeepAlive Tab需要先离开当前路由 // 如果关闭激活中的 KeepAlive Tab需要先离开当前路由
// 触发 KeepAlive unactivated 后再进行 drop // 触发 KeepAlive unactivated 后再进行 drop
const localTablist = JSON.parse(JSON.stringify(tabList)); const localTablist = JSON.parse(JSON.stringify(tabList))
localTablist.splice(tabIndex, 1); localTablist.splice(tabIndex, 1)
let activeIndex: number = 0; let activeIndex: number = 0;
if (tabIndex < active) { if (tabIndex < active) {
// 我在前面 // 我在前面
activeIndex = active - 1; activeIndex = active - 1;
dropScope(currentName); dropScope(currentName)
} else if (tabIndex === active) { } else if (tabIndex === active) {
// 点击后面当前窗口 // 点击后面当前窗口
if (active > 0) { if (active > 0) {
activeIndex = active - 1; activeIndex = active - 1
const timer = setTimeout(() => { const timer = setTimeout(() => {
clearTimeout(timer); clearTimeout(timer)
history.push(tabList[activeIndex]); history.push(tabList[activeIndex])
}, 10); }, 10)
} else { } else {
activeIndex = 0; activeIndex = 0
const timer = setTimeout(() => { const timer = setTimeout(() => {
clearTimeout(timer); clearTimeout(timer)
history.push(localTablist[activeIndex]); history.push(localTablist[activeIndex])
}, 10); }, 10)
} }
const unlisten = history.listen(() => { const unlisten = history.listen(() => {
unlisten(); unlisten()
const dropTimer = setTimeout(() => { const dropTimer = setTimeout(() => {
clearTimeout(dropTimer); clearTimeout(dropTimer)
dropScope(currentName); dropScope(currentName)
}, 10); }, 10)
}); })
} else { } else {
activeIndex = active; activeIndex = active
dropScope(currentName); dropScope(currentName)
} }
dispatch({ dispatch({ type: "CHANGESTATE", payload: { tabList: localTablist, active: activeIndex, tarnslateX: 0 } })
type: 'CHANGESTATE', }}>
payload: { tabList: localTablist, active: activeIndex, tarnslateX: 0 },
});
}}
>
<CloseOutlined /> <CloseOutlined />
</div> </div>
)} )
}
</div> </div>
) : (
<div />
); );
}; }
export default SortableElement(SortableTab); export default SortableElement(SortableTab);

View File

@ -5,246 +5,238 @@
* @Last Modified time: 2022-02-21 11:12:12 * @Last Modified time: 2022-02-21 11:12:12
*/ */
import { DownOutlined, MoreOutlined } from '@ant-design/icons';
import { Divider, Dropdown, Menu } from 'antd';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { SortableContainer } from 'react-sortable-hoc'; import { SortableContainer } from 'react-sortable-hoc';
import { history, useAliveController, useModel } from 'umi'; import { Dropdown, Menu, Divider } from 'antd';
import SortableTab from './components/SortableTab'; import { DownOutlined, MoreOutlined } from '@ant-design/icons';
import { useModel, history, useAliveController } from 'umi'
import SortableTab from './components/SortableTab'
import styles from './index.less'; import styles from './index.less';
const SortableList = SortableContainer(() => { const SortableList = SortableContainer(() => {
const tabsRef = useRef<any>(); const tabsRef = useRef<any>()
const { tabList, tarnslateX } = useModel('system'); const { tabList, tarnslateX } = useModel("system");
return ( return (
<div className={`${styles.tabList}`} ref={tabsRef} > <div className={`${styles.tabList}`} ref={tabsRef} >
{/* <div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}> */} {/* <div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}> */}
<div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}> <div className={styles.linkTabs} style={{ transform: `translateX(-${tarnslateX}px)` }}>
{tabList.map((value, index: number) => ( {
tabList.map((value, index: number) => (
<SortableTab key={`item-${index}`} index={index} value={value} tabIndex={index} /> <SortableTab key={`item-${index}`} index={index} value={value} tabIndex={index} />
))} ))
}
</div> </div>
</div > </div >
); );
}); });
const KeepAliveTabs = () => { const KeepAliveTabs = () => {
const { initialState } = useModel<any>('@@initialState'); const { initialState } = useModel<any>("@@initialState");
const { collapsed } = initialState; const { collapsed } = initialState;
const { tabList, dispatch, active, showTabs, tabsWidth, tabWidth, tarnslateX } = const { tabList, dispatch, active, showTabs, tabsWidth, tabWidth, tarnslateX } = useModel("system");
useModel('system');
const { dropScope, clear } = useAliveController(); const { dropScope, clear } = useAliveController();
const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { const onSortEnd = ({ oldIndex, newIndex }: { oldIndex: number, newIndex: number }) => {
const dataSource = JSON.parse(JSON.stringify(tabList)); const dataSource = JSON.parse(JSON.stringify(tabList))
const activeItem = dataSource[active as number]; const activeItem = dataSource[active as number]
dataSource.splice(newIndex, 0, dataSource.splice(oldIndex, 1)[0]); dataSource.splice(newIndex, 0, dataSource.splice(oldIndex, 1)[0]);
const movedActiveIndex = dataSource.findIndex((item: string) => item === activeItem); const movedActiveIndex = dataSource.findIndex((item: string) => item === activeItem)
dispatch({ type: 'CHANGESTATE', payload: { tabList: dataSource, active: movedActiveIndex } }); dispatch({ type: "CHANGESTATE", payload: { tabList: dataSource, active: movedActiveIndex } })
}; }
// 当前的索引值active showTabs一排能展示多少个 // 当前的索引值active showTabs一排能展示多少个
// 计算应该在菜单展示的菜单有哪些 // 计算应该在菜单展示的菜单有哪些
const arr: any[] = []; const arr: any[] = []
if (tabList.length > showTabs) { if (tabList.length > showTabs) {
// 前面隐藏的元素 // 前面隐藏的元素
const beforeTab = Math.floor(tarnslateX / tabWidth); const beforeTab = Math.floor(tarnslateX / tabWidth);
// 后面隐藏的元素 // 后面隐藏的元素
const afterTab = Math.floor(tarnslateX / tabWidth) + showTabs; const afterTab = Math.floor(tarnslateX / tabWidth) + showTabs
tabList.forEach((item, index) => { tabList.forEach((item, index) => {
if (index < beforeTab) { if (index < beforeTab) {
arr.push(item); arr.push(item)
} }
if (index >= afterTab) { if (index >= afterTab) {
arr.push(item); arr.push(item)
} }
}); })
} }
const menuMore = ( const menuMore = (
<Menu <Menu onClick={(e) => {
onClick={(e) => {
// 判断点击多余tab的展示移动距离是多少 // 判断点击多余tab的展示移动距离是多少
// 计算超出了多少 // 计算超出了多少
// tabsWidth tabWidth showTabs 100是右边操作的距离目前写死 // tabsWidth tabWidth showTabs 100是右边操作的距离目前写死
const isBeyondDistance = const isBeyondDistance = ((showTabs as number) * (tabWidth as number)) - (tabsWidth as number) + 100;
(showTabs as number) * (tabWidth as number) - (tabsWidth as number) + 100;
// TODO 找到当前点击的索引值 // TODO 找到当前点击的索引值
const curClickIndex = tabList?.findIndex((item) => item.pathname === e.key) as number; const curClickIndex = tabList?.findIndex(item => item.pathname === e.key) as number;
// 能展示多少个 // 能展示多少个
const totalShowIndex = (showTabs as number) - 1; const totalShowIndex = (showTabs as number) - 1;
if (curClickIndex > totalShowIndex) { if (curClickIndex > totalShowIndex) {
// 计算移动的距离 // 计算移动的距离
const x = (curClickIndex - totalShowIndex) * (tabWidth as number) + isBeyondDistance; const x = (curClickIndex - totalShowIndex) * (tabWidth as number) + isBeyondDistance
dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: x, active: curClickIndex } }); dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: x, active: curClickIndex } })
} else { } else {
dispatch({ dispatch({ type: 'CHANGESTATE', payload: { tarnslateX: tabWidth * curClickIndex, active: curClickIndex } })
type: 'CHANGESTATE', }
payload: { tarnslateX: tabWidth * curClickIndex, active: curClickIndex }, history.push({ ...tabList[curClickIndex] })
}); }}>
{
arr.map(item => {
return <Menu.Item key={item.pathname}> {item.title}</Menu.Item>
})
} }
history.push({ ...tabList[curClickIndex] });
}}
>
{arr.map((item) => {
return <Menu.Item key={item.pathname}> {item.title}</Menu.Item>;
})}
</Menu> </Menu>
); );
const menu = ( const menu = (
<Menu <Menu onClick={(e) => {
onClick={(e) => {
let activeIndex: number = 0; let activeIndex: number = 0;
const localTablist = JSON.parse(JSON.stringify(tabList)); const localTablist = JSON.parse(JSON.stringify(tabList))
switch (e.key) { switch (e.key) {
case 'closeCurrent': { case "closeCurrent": {
const currentName = localTablist[active].keepAliveName; const currentName = localTablist[active].keepAliveName
if (active > 0) { if (active > 0) {
activeIndex = active - 1; activeIndex = active - 1
const timer = setTimeout(() => { const timer = setTimeout(() => {
clearTimeout(timer); clearTimeout(timer)
history.push(tabList[activeIndex]); history.push(tabList[activeIndex])
}, 10); }, 10)
} else { } else {
activeIndex = 0; activeIndex = 0
const timer = setTimeout(() => { const timer = setTimeout(() => {
clearTimeout(timer); clearTimeout(timer)
history.push(localTablist[activeIndex]); history.push(localTablist[activeIndex])
}, 10); }, 10)
} }
const unlisten = history.listen(() => { const unlisten = history.listen(() => {
unlisten(); unlisten()
const dropTimer = setTimeout(() => { const dropTimer = setTimeout(() => {
clearTimeout(dropTimer); clearTimeout(dropTimer)
dropScope(currentName); dropScope(currentName)
}, 10); }, 10)
}); })
localTablist.splice(active, 1); localTablist.splice(active, 1)
dispatch({ dispatch({ type: "CHANGESTATE", payload: { tabList: localTablist, active: activeIndex, tarnslateX: 0 } })
type: 'CHANGESTATE',
payload: { tabList: localTablist, active: activeIndex, tarnslateX: 0 },
});
break; break;
} }
case 'closeOther': { case "closeOther": {
const needDelete = localTablist.filter((item: any, index: number) => index !== active); const needDelete = localTablist.filter((item: any, index: number) => index !== active);
const needUpdate = localTablist.filter((item: any, index: number) => index === active); const needUpdate = localTablist.filter((item: any, index: number) => index === active);
needDelete.forEach((item: any) => dropScope(item.keepAliveName)); needDelete.forEach((item: any) => dropScope(item.keepAliveName));
dispatch({ dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, active: 0, tarnslateX: 0 } })
type: 'CHANGESTATE',
payload: { tabList: needUpdate, active: 0, tarnslateX: 0 },
});
break; break;
} }
case 'closeAll': { case "closeAll": {
const unlisten = history.listen(() => { const unlisten = history.listen(() => {
unlisten(); unlisten()
const dropTimer = setTimeout(() => { const dropTimer = setTimeout(() => {
clearTimeout(dropTimer); clearTimeout(dropTimer)
clear(); clear()
}, 10); }, 10)
}); })
const timer = setTimeout(() => { const timer = setTimeout(() => {
clearTimeout(timer); clearTimeout(timer)
history.push('/'); history.push("/")
}, 10); }, 10)
dispatch({ type: 'CHANGESTATE', payload: { tabList: [], active: 0, tarnslateX: 0 } }); dispatch({ type: "CHANGESTATE", payload: { tabList: [], active: 0, tarnslateX: 0 } })
break; break;
} }
case 'closeLeft': { case "closeLeft": {
const needDelete = localTablist.filter((item: any, index: number) => index < active); const needDelete = localTablist.filter((item: any, index: number) => index < active);
const needUpdate = localTablist.filter((item: any, index: number) => index >= active); const needUpdate = localTablist.filter((item: any, index: number) => index >= active);
needDelete.forEach((item: any) => dropScope(item.keepAliveName)); needDelete.forEach((item: any) => dropScope(item.keepAliveName));
dispatch({ dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, active: 0, tarnslateX: 0 } })
type: 'CHANGESTATE',
payload: { tabList: needUpdate, active: 0, tarnslateX: 0 },
});
break; break;
} }
case 'closeRight': { case "closeRight": {
const needDelete = localTablist.filter((item: any, index: number) => index > active); const needDelete = localTablist.filter((item: any, index: number) => index > active);
const needUpdate = localTablist.filter((item: any, index: number) => index <= active); const needUpdate = localTablist.filter((item: any, index: number) => index <= active);
needDelete.forEach((item: any) => dropScope(item.keepAliveName)); needDelete.forEach((item: any) => dropScope(item.keepAliveName));
dispatch({ type: 'CHANGESTATE', payload: { tabList: needUpdate, tarnslateX: 0 } }); dispatch({ type: "CHANGESTATE", payload: { tabList: needUpdate, tarnslateX: 0 } })
break; break;
} }
} }
}}
> }}>
<Menu.Item key="closeCurrent"></Menu.Item> <Menu.Item key="closeCurrent"></Menu.Item>
<Menu.Item key="closeOther"></Menu.Item> <Menu.Item key="closeOther"></Menu.Item>
<Menu.Item key="closeAll"></Menu.Item> <Menu.Item key="closeAll"></Menu.Item>
<Menu.Item key="closeLeft" disabled={active === 0}> <Menu.Item key="closeLeft" disabled={active === 0}></Menu.Item>
<Menu.Item key="closeRight" disabled={active === tabList.length - 1}></Menu.Item>
</Menu.Item>
<Menu.Item key="closeRight" disabled={active === tabList.length - 1}>
</Menu.Item>
</Menu> </Menu>
); );
useEffect(() => { useEffect(() => {
window.onresize = () => { window.onresize = () => {
const width = document.getElementById('contentContainer') const width = document.getElementById("contentContainer") ? document.getElementById("contentContainer")!.getBoundingClientRect()!.width : 0;
? document.getElementById('contentContainer')!.getBoundingClientRect()!.width dispatch({ type: "CHANGESTATE", payload: { tabsWidth: width, tarnslateX: 0 } })
: 0; }
dispatch({ type: 'CHANGESTATE', payload: { tabsWidth: width, tarnslateX: 0 } });
};
const timer = setTimeout(() => { const timer = setTimeout(() => {
const width = document.getElementById('contentContainer') const width = document.getElementById("contentContainer") ? document.getElementById("contentContainer")!.getBoundingClientRect()!.width : 0;
? document.getElementById('contentContainer')!.getBoundingClientRect()!.width dispatch({ type: "CHANGESTATE", payload: { tabsWidth: width } })
: 0;
dispatch({ type: 'CHANGESTATE', payload: { tabsWidth: width } });
}, 100); }, 100);
return () => { return () => {
clearTimeout(timer); clearTimeout(timer)
}; }
}, [collapsed]); }, [collapsed])
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
// 需要重新计算拿到当前tab的宽度 // 需要重新计算拿到当前tab的宽度
const itemWidth = document.getElementsByClassName('link-tab')[0] const itemWidth = document.getElementsByClassName("link-tab")[0] ? document.getElementsByClassName("link-tab")[0]!.getBoundingClientRect().width : 120;
? document.getElementsByClassName('link-tab')[0]!.getBoundingClientRect().width
: 120;
//计算一排能展示多少个tab 需要减去操作占用的空间100 //计算一排能展示多少个tab 需要减去操作占用的空间100
const isShowTabs = Math.ceil(((tabsWidth as number) - 100) / itemWidth); const isShowTabs = Math.ceil((tabsWidth as number - 100) / itemWidth);
if (itemWidth > 0 && tabWidth > 0) { if (itemWidth > 0 && tabWidth > 0) {
dispatch({ type: 'CHANGESTATE', payload: { showTabs: isShowTabs, tabWidth: itemWidth } }); dispatch({ type: "CHANGESTATE", payload: { showTabs: isShowTabs, tabWidth: itemWidth } })
} }
}, 100); }, 100);
return () => { return () => {
clearTimeout(timer); clearTimeout(timer)
}; }
}, [tabsWidth]); }, [tabsWidth])
return ( return (
// <div className={styles.tabs} style={{ width: initialState?.collapsed ? "calc(100vw - 41px)" : "calc(100vw - 249px)" }}> // <div className={styles.tabs} style={{ width: initialState?.collapsed ? "calc(100vw - 41px)" : "calc(100vw - 249px)" }}>
<div className={!!new URLSearchParams(window.location.search) ? 'hideContent' : styles.tabs} id="contentContainer"> <div className={styles.tabs} id="contentContainer">
{tabList.length > 0 && <SortableList onSortEnd={onSortEnd} axis={'x'} distance={1} />} {tabList.length > 0 && <SortableList onSortEnd={onSortEnd} axis={'x'} distance={1} />}
<div className={`${styles.tabLeftMenu} ${tabList.length >= showTabs && styles.boxShadow}`}> <div className={`${styles.tabLeftMenu} ${tabList.length >= showTabs && styles.boxShadow}`}>
{tabList.length > showTabs && ( {
tabList.length > showTabs && (
<> <>
<Dropdown overlay={menuMore} className={styles.tabMore}> <Dropdown overlay={menuMore} className={styles.tabMore}>
<a className="ant-dropdown-link" onClick={(e) => e.preventDefault()}> <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
<MoreOutlined /> <MoreOutlined />
</a> </a>
</Dropdown> </Dropdown>
<Divider type="vertical" /> <Divider type='vertical' />
</> </>
)} )
{tabList.length > 1 && ( }
{
tabList.length > 1 && (
<Dropdown overlay={menu} className={styles.menuRight}> <Dropdown overlay={menu} className={styles.menuRight}>
<a className="ant-dropdown-link" onClick={(e) => e.preventDefault()}> <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
<DownOutlined /> <DownOutlined />
</a> </a>
</Dropdown> </Dropdown>
)} )
}
</div> </div>
</div> </div>
); );
}; }
export default KeepAliveTabs; export default KeepAliveTabs;

View File

@ -27,11 +27,6 @@ body {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.hideContent{
display: none;
}
ul, ul,
ol { ol {
list-style: none; list-style: none;
@ -61,28 +56,29 @@ ol {
} }
} }
// .ant-layout{
// background: #fff;
// }
// .ant-layout-header{
// //display: none;
// }
// #contentContainer{ .ant-layout{
// //display: none; background: #fff;
// } }
// .ant-pro-right-content{ .ant-layout-header{
//display: none; //display: none;
// } }
// .ant-modal-mask{
// background-color: rgba(255, 0, 0, 0); #contentContainer{
// }
// .chiner-modal{
// background-color: rgba(255, 0, 0, 0);
// }
// .ant-pro-top-nav-header-logo{
//display: none; //display: none;
// } }
// .ant-pro-top-nav-header-main-left{ .ant-pro-right-content{
// min-width: 0px; display: none;
// } }
.ant-modal-mask{
background-color: rgba(255, 0, 0, 0);
}
.chiner-modal{
background-color: rgba(255, 0, 0, 0);
}
.ant-pro-top-nav-header-logo{
display: none;
}
.ant-pro-top-nav-header-main-left{
min-width: 0px;
}

View File

@ -1,149 +0,0 @@
body .ant-layout{
background: #fff;
}
/*ant-btn*/
body .ant-btn:focus,
body .ant-btn:hover {
color: #2B50C4;
border-color: #2B50C4;
background: #fff;
}
body .ant-btn:active {
color:#042281;
border-color:#042281;
background:#fff
}
body .ant-btn-primary {
color: #fff;
border-color: #233A82;
background: #233A82;
}
body .ant-btn-primary:focus,
body .ant-btn-primary:hover {
color: #fff;
border-color: #2B50C4;
background: #2B50C4;
}
body .ant-btn-primary:active {
color: #fff;
border-color: #042281;
background: #042281;
}
html {
--antd-wave-shadow-color:#233A82 !important;
}
body .ant-input:hover {
border-color: #233A82;
}
body .ant-input-affix-wrapper-focused,
body .ant-input-affix-wrapper:focus {
border-color:#233A82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper-focused,
body .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper:focus {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-affix-wrapper-status-warning:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper-focused,
body .ant-input-affix-wrapper-status-warning:not(.ant-input-affix-wrapper-disabled):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper:focus {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-search-rtl>.ant-input-group>.ant-input-affix-wrapper-focused,
body .ant-input-search-rtl>.ant-input-group>.ant-input-affix-wrapper:hover {
border-right-color:#233A82;
}
body .ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover {
border-color: #233A82;
}
body .ant-select:not(.ant-select-disabled):hover .ant-select-selector {
border-color: #233A82;
}
body .ant-select-status-error.ant-select:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer).ant-select-focused .ant-select-selector,
body .ant-select-status-error.ant-select:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer).ant-select-open .ant-select-selector {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-select-status-warning.ant-select:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer).ant-select-focused .ant-select-selector,
body .ant-select-status-warning.ant-select:not(.ant-select-disabled):not(.ant-select-customize-input):not(.ant-pagination-size-changer).ant-select-open .ant-select-selector {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
border-color:#233A82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-group-addon .ant-select-focused .ant-select-selector,
body .ant-input-group-addon .ant-select-open .ant-select-selector {
color:#233A82;
}
body .namediv:hover {
color: #233A82;
}
body .ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
color: #1d2129;
background: #e9ecf4;
}
body .ant-select-item-option-selected:hover{
background: #e9ecf4;
}
body .ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state {
color: #233a82;
}
body .ant-input-status-warning:not(.ant-input-disabled):not(.ant-input-borderless).ant-input-focused,
body .ant-input-status-warning:not(.ant-input-disabled):not(.ant-input-borderless).ant-input:focus {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-affix-wrapper-focused,
body .ant-input-affix-wrapper:focus {
border-color:#233a82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-focused,
body .ant-input:focus {
border-color:#233a82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-pagination-options-quick-jumper input-focused,
body .ant-pagination-options-quick-jumper input:focus {
border-color:#233a82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-pagination-simple .ant-pagination-simple-pager input:focus {
border-color:#233a82;
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .ant-input-status-error:not(.ant-input-disabled):not(.ant-input-borderless).ant-input-focused,
body .ant-input-status-error:not(.ant-input-disabled):not(.ant-input-borderless).ant-input:focus {
box-shadow:0 0 0 2px rgba(35, 58, 130, .2);
}
body .spandes:hover{
color:#233a82;
}
body .cardstyle:hover .deletestyle:hover {
color: #233a82;
}
body .ant-pagination-item-active {
border-color: #233a82;
}
body .ant-pagination-item:hover a {
color: #233a82;
}
body .ant-pagination-item:hover {
border-color: #233a82;
}
body .ant-pagination-next:hover .ant-pagination-item-link,
body .ant-pagination-prev:hover .ant-pagination-item-link {
color: #233a82;
border-color: #233a82;
}

View File

@ -84,7 +84,7 @@ const Login: React.FC = () => {
// 如果失败去设置用户错误信息 // 如果失败去设置用户错误信息
setUserLoginState({status: 'error', type: 'account', massage: response.msg}); setUserLoginState({status: 'error', type: 'account', massage: response.msg});
message.error(response.msg); message.error(response.msg);
// getCaptchaCode(); getCaptchaCode();
} }
} catch (error) { } catch (error) {
clearSessionToken(); clearSessionToken();
@ -93,13 +93,13 @@ const Login: React.FC = () => {
defaultMessage: '登录失败,请重试!', defaultMessage: '登录失败,请重试!',
}); });
message.error(defaultLoginFailureMessage); message.error(defaultLoginFailureMessage);
// getCaptchaCode(); getCaptchaCode();
} }
}; };
const { status, type: loginType, massage } = userLoginState; const { status, type: loginType, massage } = userLoginState;
useEffect(() => { useEffect(() => {
// getCaptchaCode(); getCaptchaCode();
}, []); }, []);
return ( return (

View File

@ -1,22 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="keywords" <meta
content="antd,umi,umijs,ant design,Scaffolding, layout, Ant Design, project, Pro, admin, console, homepage, out-of-the-box, middle and back office, solution, component library" /> name="keywords"
<meta name="description" content=" content="antd,umi,umijs,ant design,Scaffolding, layout, Ant Design, project, Pro, admin, console, homepage, out-of-the-box, middle and back office, solution, component library"
An out-of-box UI solution for enterprise applications as a React boilerplate." /> />
<meta name="description" content=" <meta
Out-of-the-box mid-stage front-end/design solution." /> name="description"
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> content="
An out-of-box UI solution for enterprise applications as a React boilerplate."
/>
<meta
name="description"
content="
Out-of-the-box mid-stage front-end/design solution."
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
<title>Salpa</title> <title>Salpa</title>
<link rel="icon" href="<%= context.config.publicPath +'樽海鞘_图案.svg'%>" type="image/x-icon" /> <link rel="icon" href="<%= context.config.publicPath +'樽海鞘_图案.svg'%>" type="image/x-icon" />
<script src="https://cdn.jsdelivr.net/npm/xlsx@latest/dist/xlsx.full.min.js"></script>
</head> </head>
<body> <body>
<noscript> <noscript>
<div class="noscript-container"> <div class="noscript-container">
@ -38,12 +45,10 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
#root { #root {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% auto; background-size: 100% auto;
} }
.noscript-container { .noscript-container {
display: flex; display: flex;
align-content: center; align-content: center;
@ -53,19 +58,16 @@
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode',
Geneva, Verdana, sans-serif; Geneva, Verdana, sans-serif;
} }
.noscript-enableJS { .noscript-enableJS {
padding-right: 3px; padding-right: 3px;
padding-left: 3px; padding-left: 3px;
} }
.page-loading-warp { .page-loading-warp {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 98px; padding: 98px;
} }
.ant-spin { .ant-spin {
position: absolute; position: absolute;
display: none; display: none;
@ -167,8 +169,7 @@
height: 14px; height: 14px;
} }
@media all and (-ms-high-contrast: none), @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
(-ms-high-contrast: active) {
.ant-spin-blur { .ant-spin-blur {
background: #fff; background: #fff;
opacity: 0.5; opacity: 0.5;
@ -201,27 +202,34 @@
} }
} }
</style> </style>
<!-- <div style=" <div
style="
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100%; height: 100%;
min-height: 420px; min-height: 420px;
"> "
>
<h1>Salpa</h1> <h1>Salpa</h1>
<div class="page-loading-warp"> <div class="page-loading-warp">
<div class="ant-spin ant-spin-lg ant-spin-spinning"> <div class="ant-spin ant-spin-lg ant-spin-spinning">
<span class="ant-spin-dot ant-spin-dot-spin"><i class="ant-spin-dot-item"></i><i <span class="ant-spin-dot ant-spin-dot-spin"
class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i></span> ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
></span>
</div> </div>
</div> </div>
<div style="display: flex; align-items: center; justify-content: center"> <div style="display: flex; align-items: center; justify-content: center">
<img src="<%= context.config.publicPath +'樽海鞘_图案.svg'%>" width="32" style="margin-right: 8px" /> <img
src="<%= context.config.publicPath +'樽海鞘_图案.svg'%>"
width="32"
style="margin-right: 8px"
/>
Salpa Salpa
</div> </div>
</div> --> </div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,6 +1,8 @@
// import { getUserConfig } from '../../lib/middle'; // import { getUserConfig } from '../../lib/middle';
import { openLoading, closeLoading, STATUS } from '../common';
import allLangData from '../../lang'; import allLangData from '../../lang';
import { openLoading } from '../common'; import { setMemoryCache } from '../../lib/cache';
import { CONFIG } from '../../lib/variable';
export const SAVE_USER_CONFIG_SUCCESS = 'SAVE_USER_CONFIG_SUCCESS'; // 保存成功 export const SAVE_USER_CONFIG_SUCCESS = 'SAVE_USER_CONFIG_SUCCESS'; // 保存成功
export const SAVE_USER_CONFIG_FAIL = 'SAVE_USER_CONFIG_FAIL'; // 保存失败 export const SAVE_USER_CONFIG_FAIL = 'SAVE_USER_CONFIG_FAIL'; // 保存失败
@ -51,15 +53,12 @@ export const saveUserConfigSome = (data) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const configData = getState()?.config?.data || []; const configData = getState()?.config?.data || [];
const config = {...configData[0], ...data}; const config = {...configData[0], ...data};
saveUserConfigData( saveUserConfigData(configData.map((d, index) => {
configData.map((d, index) => {
if (index === 0) { if (index === 0) {
return config; return config;
} }
return d; return d;
}), }), allLangData[config.lang].updateConfig)(dispatch);
allLangData[config.lang].updateConfig,
)(dispatch);
}; };
}; };
@ -88,31 +87,26 @@ export const removeHistory = (h) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const configData = getState()?.config?.data || []; const configData = getState()?.config?.data || [];
const config = configData[0]; const config = configData[0];
saveUserConfigData( saveUserConfigData(configData.map((d, index) => {
configData.map((d, index) => {
if (index === 0) { if (index === 0) {
return { return {
...d, ...d,
projectHistories: (d.projectHistories || []).filter((p) => p.path !== h.path), projectHistories: (d.projectHistories || []).filter(p => (p.path !== h.path)),
}; }
} }
return d; return d;
}), }), allLangData[config.lang].updateConfig)(dispatch);
allLangData[config.lang].updateConfig, }
)(dispatch);
};
}; };
export const addHistory = (data, cb) => { export const addHistory = (data, cb) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const configData = getState()?.config?.data || []; const configData = getState()?.config?.data || [];
const config = configData[0]; const config = configData[0];
saveUserConfigData( saveUserConfigData(configData.map((d, index) => {
configData.map((d, index) => {
if (index === 0) { if (index === 0) {
const tempProjectHistories = [...(d.projectHistories || [])].filter( const tempProjectHistories = [...(d.projectHistories || [])]
(h) => h.path !== data.path, .filter(h => h.path !== data.path); // 移除当前的项目信息
); // 移除当前的项目信息
tempProjectHistories.unshift(data); tempProjectHistories.unshift(data);
return { return {
...d, ...d,
@ -120,19 +114,15 @@ export const addHistory = (data, cb) => {
}; };
} }
return d; return d;
}), }), allLangData[config.lang].updateConfig, cb)(dispatch);
allLangData[config.lang].updateConfig, }
cb,
)(dispatch);
};
}; };
export const updateHistory = (oldData, newData) => { export const updateHistory = (oldData, newData) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const configData = getState()?.config?.data || []; const configData = getState()?.config?.data || [];
const config = configData[0]; const config = configData[0];
saveUserConfigData( saveUserConfigData(configData.map((d, index) => {
configData.map((d, index) => {
if (index === 0) { if (index === 0) {
return { return {
...d, ...d,
@ -150,8 +140,6 @@ export const updateHistory = (oldData, newData) => {
}; };
} }
return d; return d;
}), }), allLangData[config.lang].updateConfig)(dispatch);
allLangData[config.lang].updateConfig, }
)(dispatch);
};
}; };

View File

@ -1,109 +1,94 @@
/* eslint-disable no-const-assign */ /* eslint-disable no-const-assign */
/* eslint-disable no-undef */ /* eslint-disable no-undef */
import _ from 'lodash/object'; import _ from 'lodash/object'
import moment from 'moment'; import moment from 'moment'
import version from '../../../../../package.json'; import { openLoading, closeLoading, STATUS, optReset } from '../common'
import { setMemoryCache } from '../../lib/cache'; import { reduceProject, transformationData } from '../../lib/datasource_util'
import { transformationData } from '../../lib/datasource_util'; import { setMemoryCache } from '../../lib/cache'
import * as template from '../../lib/template'; import * as template from '../../lib/template'
import { closeLoading, openLoading, optReset, STATUS } from '../common'; import { compareVersion } from '../../lib/update'
import version from '../../../../../package.json'
// import {emptyProject} from '../../lib/template/empty'; // import {emptyProject} from '../../lib/template/empty';
import allLangData from '../../lang'; import { removeHistory, addHistory, updateHistory } from '../config'
import { projectSuffix } from '../../profile'
import allLangData from '../../lang'
import { import {
basename, basename, saveVersion, deleteFile, ensureDirectoryExistence, openFileOrDirPath, renameVersion, dirSplicing, fileExists, saveJsonPromiseAs, updateAllVersion, saveJsonPromise, getBackupAllFile, writeLog, deleteVersion, openProjectFilePath, readJsonPromise, getAllVersionProject
deleteFile, } from '../../lib/middle'
deleteVersion,
dirSplicing,
ensureDirectoryExistence,
fileExists,
getAllVersionProject,
getBackupAllFile,
openFileOrDirPath,
openProjectFilePath,
readJsonPromise,
renameVersion,
saveJsonPromise,
saveJsonPromiseAs,
saveVersion,
updateAllVersion,
writeLog,
} from '../../lib/middle';
import { projectSuffix } from '../../profile';
import { addHistory, removeHistory, updateHistory } from '../config';
/* /*
* 核心的action 负责整个项目的保存和删除 * 核心的action 负责整个项目的保存和删除
* */ * */
/* /*
* action 类型 * action 类型
*/ */
export const SAVE_PROJECT_SUCCESS = 'SAVE_PROJECT_SUCCESS'; // 保存成功 export const SAVE_PROJECT_SUCCESS = 'SAVE_PROJECT_SUCCESS' // 保存成功
export const SAVE_PROJECT_FAIL = 'SAVE_PROJECT_FAIL'; // 保存失败 export const SAVE_PROJECT_FAIL = 'SAVE_PROJECT_FAIL' // 保存失败
export const READ_PROJECT_SUCCESS = 'READ_PROJECT_SUCCESS'; // 读取成功 export const READ_PROJECT_SUCCESS = 'READ_PROJECT_SUCCESS' // 读取成功
export const READ_PROJECT_FAIL = 'READ_PROJECT_FAIL'; // 读取失败 export const READ_PROJECT_FAIL = 'READ_PROJECT_FAIL' // 读取失败
export const CREATE_PROJECT_SUCCESS = 'CREATE_PROJECT_SUCCESS'; // 创建成功 export const CREATE_PROJECT_SUCCESS = 'CREATE_PROJECT_SUCCESS' // 创建成功
export const CREATE_PROJECT_ERROR = 'CREATE_PROJECT_ERROR'; // 创建失败 export const CREATE_PROJECT_ERROR = 'CREATE_PROJECT_ERROR' // 创建失败
export const SAVE_VERSION_SUCCESS = 'SAVE_VERSION_SUCCESS'; // 保存版本信息成功 export const SAVE_VERSION_SUCCESS = 'SAVE_VERSION_SUCCESS' // 保存版本信息成功
export const SAVE_VERSION_FAIL = 'SAVE_VERSION_FAIL'; // 保存版本信息失败 export const SAVE_VERSION_FAIL = 'SAVE_VERSION_FAIL' // 保存版本信息失败
export const SAVE_ALL_VERSION_SUCCESS = 'SAVE_ALL_VERSION_SUCCESS'; export const SAVE_ALL_VERSION_SUCCESS = 'SAVE_ALL_VERSION_SUCCESS'
export const SAVE_ALL_VERSION_FAIL = 'SAVE_ALL_VERSION_FAIL'; export const SAVE_ALL_VERSION_FAIL = 'SAVE_ALL_VERSION_FAIL'
export const REMOVE_VERSION_SUCCESS = 'REMOVE_VERSION_SUCCESS'; // 版本信息删除成功 export const REMOVE_VERSION_SUCCESS = 'REMOVE_VERSION_SUCCESS' // 版本信息删除成功
export const REMOVE_ALL_VERSION_SUCCESS = 'REMOVE_ALL_VERSION_SUCCESS'; // 所有版本信息删除成功 export const REMOVE_ALL_VERSION_SUCCESS = 'REMOVE_ALL_VERSION_SUCCESS' // 所有版本信息删除成功
export const UPDATE_PROJECT = 'UPDATE_PROJECT'; // 更新项目 export const UPDATE_PROJECT = 'UPDATE_PROJECT' // 更新项目
export const CLOSE_PROJECT = 'CLOSE_PROJECT'; // 关闭项目 export const CLOSE_PROJECT = 'CLOSE_PROJECT' // 关闭项目
export const UPDATE_PROJECT_INFO = 'UPDATE_PROJECT_INFO'; // 更新项目信息 export const UPDATE_PROJECT_INFO = 'UPDATE_PROJECT_INFO' // 更新项目信息
export const updateProjectInfo = (info) => { export const updateProjectInfo = (info) => {
return { return {
type: UPDATE_PROJECT_INFO, type: UPDATE_PROJECT_INFO,
data: info, data: info,
}; }
}; }
export const updateProject = (data) => { export const updateProject = (data) => {
return { return {
type: UPDATE_PROJECT, type: UPDATE_PROJECT,
data, data,
}; }
}; }
const saveAllVersionSuccess = (data) => { const saveAllVersionSuccess = (data) => {
return { return {
type: SAVE_ALL_VERSION_SUCCESS, type: SAVE_ALL_VERSION_SUCCESS,
data, data,
}; }
}; }
const saveAllVersionFail = (err) => { const saveAllVersionFail = (err) => {
return { return {
type: SAVE_ALL_VERSION_FAIL, type: SAVE_ALL_VERSION_FAIL,
data: err, data: err,
}; }
}; }
const removeVersionSuccess = (versionInfo) => { const removeVersionSuccess = (versionInfo) => {
return { return {
type: REMOVE_VERSION_SUCCESS, type: REMOVE_VERSION_SUCCESS,
data: versionInfo, data: versionInfo,
}; }
}; }
const saveVersionSuccess = (data, oldData) => { const saveVersionSuccess = (data, oldData) => {
return { return {
type: SAVE_VERSION_SUCCESS, type: SAVE_VERSION_SUCCESS,
data: { data, oldData }, data: { data, oldData },
}; }
}; }
const saveVersionFail = (err) => { const saveVersionFail = (err) => {
return { return {
type: SAVE_VERSION_FAIL, type: SAVE_VERSION_FAIL,
data: err, data: err,
}; }
}; }
const createProjectSuccess = (data, path) => { const createProjectSuccess = (data, path) => {
return { return {
type: CREATE_PROJECT_SUCCESS, type: CREATE_PROJECT_SUCCESS,
@ -112,82 +97,82 @@ const createProjectSuccess = (data, path) => {
data, data,
versionsData: [], versionsData: [],
}, },
}; }
}; }
const createProjectError = (error) => { const createProjectError = (error) => {
return { return {
type: CREATE_PROJECT_ERROR, type: CREATE_PROJECT_ERROR,
data: error, data: error,
}; }
}; }
const saveProjectFail = (err) => { const saveProjectFail = (err) => {
return { return {
type: SAVE_PROJECT_FAIL, type: SAVE_PROJECT_FAIL,
data: err, data: err,
}; }
}; }
const saveProjectSuccess = (data) => { const saveProjectSuccess = (data) => {
return { return {
type: SAVE_PROJECT_SUCCESS, type: SAVE_PROJECT_SUCCESS,
data, data,
}; }
}; }
let isSaving = false; let isSaving = false
export const saveProject = (data, saveAs, callback) => { export const saveProject = (data, saveAs, callback) => {
if (!isSaving) { if (!isSaving) {
// 此处为异步操作 // 此处为异步操作
const time = moment().format('YYYY-M-D HH:mm:ss'); const time = moment().format('YYYY-M-D HH:mm:ss')
const tempData = { const tempData = {
...data, ...data,
createdTime: saveAs ? time : data.createdTime || time, createdTime: saveAs ? time : data.createdTime || time,
updatedTime: time, updatedTime: time,
version, version,
}; }
return (dispatch, getState) => { return (dispatch, getState) => {
const info = getState()?.core?.info; const info = getState()?.core?.info
const getName = (p) => { const getName = (p) => {
const name = basename(p, '.json'); const name = basename(p, '.json')
return name.split('.')[0]; return name.split('.')[0]
}; }
if (saveAs) { if (saveAs) {
const projectModelInfo = { const projectModelInfo = {
projectName: data.name, projectName: data.name,
jsonFile: typeof data === 'string' ? data : JSON.stringify(data, null, 2), jsonFile: typeof data === 'string' ? data : JSON.stringify(data, null, 2)
}; }
// 保存操作 // 保存操作
if (data) { if (data) {
saveJsonPromiseAs(projectModelInfo).then(() => { saveJsonPromiseAs(projectModelInfo).then(() => {
getBackupAllFile(getState(), () => { getBackupAllFile(getState(), () => {
setMemoryCache('data', tempData); setMemoryCache('data', tempData)
callback && callback(); callback && callback()
dispatch(saveProjectSuccess(tempData)); dispatch(saveProjectSuccess(tempData))
}); })
}); })
} else { } else {
callback && callback(err); callback && callback(err)
dispatch(saveProjectFail(err)); dispatch(saveProjectFail(err))
} }
} else { } else {
saveJsonPromise(info, tempData) saveJsonPromise(info, tempData)
.then(() => { .then(() => {
getBackupAllFile(getState(), () => { getBackupAllFile(getState(), () => {
isSaving = false; isSaving = false
setMemoryCache('data', tempData); setMemoryCache('data', tempData)
callback && callback(); callback && callback()
dispatch(saveProjectSuccess(tempData)); dispatch(saveProjectSuccess(tempData))
}); })
}) })
.catch((err) => { .catch((err) => {
isSaving = false; isSaving = false
callback && callback(err); callback && callback(err)
dispatch(saveProjectFail(err)); dispatch(saveProjectFail(err))
}); })
}
} }
};
} }
// return () => {}; // return () => {};
}; }
const readProjectSuccess = (data, versionsData, path, isDemoProject) => { const readProjectSuccess = (data, versionsData, path, isDemoProject) => {
return { return {
type: READ_PROJECT_SUCCESS, type: READ_PROJECT_SUCCESS,
@ -197,314 +182,276 @@ const readProjectSuccess = (data, versionsData, path, isDemoProject) => {
data, data,
versionsData, versionsData,
}, },
}; }
}; }
export const autoSaveProject = (data) => { export const autoSaveProject = (data) => {
// 此处为异步操作 // 此处为异步操作
const time = moment().format('YYYY-M-D HH:mm:ss'); const time = moment().format('YYYY-M-D HH:mm:ss')
const tempData = { const tempData = {
...data, ...data,
updatedTime: time, updatedTime: time,
version, version,
}; }
return (dispatch, getState) => { return (dispatch, getState) => {
const info = getState()?.core?.info; const info = getState()?.core?.info
getBackupAllFile(getState(), () => { getBackupAllFile(getState(), () => {
saveJsonPromise(info, tempData).catch((err) => { saveJsonPromise(info, tempData)
writeLog(err); .catch((err) => {
}); writeLog(err)
}); })
}; })
}; }
}
export const removeVersionData = (title, versionInfo) => { export const removeVersionData = (title, versionInfo) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const { data, info } = getState()?.core || {}; const { data, info } = getState()?.core || {}
dispatch(openLoading(title)); dispatch(openLoading(title))
deleteVersion(versionInfo, data, info); deleteVersion(versionInfo, data, info)
dispatch(removeVersionSuccess(versionInfo)); dispatch(removeVersionSuccess(versionInfo))
dispatch(closeLoading(STATUS[1], null)); dispatch(closeLoading(STATUS[1], null))
}; }
}; }
export const updateAllVersionData = (versionDataCallBack, title, dataSource) => { export const updateAllVersionData = (versionDataCallBack, title, dataSource) => {
return (dispatch, getState) => { return (dispatch, getState) => {
const { data, info, versionsData } = getState()?.core || {}; const { data, info, versionsData } = getState()?.core || {}
if (info) { if (info) {
dispatch(openLoading(title)); dispatch(openLoading(title))
const finalData = versionDataCallBack(versionsData); const finalData = versionDataCallBack(versionsData)
dispatch(autoSaveProject(dataSource)); dispatch(autoSaveProject(dataSource))
updateAllVersion(finalData, info, data) updateAllVersion(finalData, info, data).then(() => {
.then(() => { dispatch(saveAllVersionSuccess(finalData))
dispatch(saveAllVersionSuccess(finalData)); dispatch(closeLoading(STATUS[1], null))
dispatch(closeLoading(STATUS[1], null)); }).catch((err) => {
dispatch(saveAllVersionFail(err))
dispatch(closeLoading(STATUS[2], err))
}) })
.catch((err) => {
dispatch(saveAllVersionFail(err));
dispatch(closeLoading(STATUS[2], err));
});
} }
}; }
}; }
export const saveVersionData = (versionData, oldVersion, dataSource, title) => { export const saveVersionData = (versionData, oldVersion, dataSource, title) => {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(openLoading(title)); dispatch(openLoading(title))
const info = getState()?.core?.info; const info = getState()?.core?.info
return new Promise((res, rej) => { return new Promise((res, rej) => {
saveVersion(versionData, oldVersion, info, dataSource) saveVersion(versionData, oldVersion, info, dataSource).then(() => {
.then(() => { dispatch(saveVersionSuccess(versionData, oldVersion))
dispatch(saveVersionSuccess(versionData, oldVersion)); dispatch(closeLoading(STATUS[1], null))
dispatch(closeLoading(STATUS[1], null)); res(versionData)
res(versionData); }).catch((err) => {
dispatch(saveVersionFail(err))
rej(err)
}) })
.catch((err) => { })
dispatch(saveVersionFail(err)); }
rej(err); }
});
});
};
};
export const renameProject = (newData, oldData, title, dataInfo) => { export const renameProject = (newData, oldData, title, dataInfo) => {
// 判断项目名和项目目录是否已经修改 该方法无只需触发loading操作的action // 判断项目名和项目目录是否已经修改 该方法无只需触发loading操作的action
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(openLoading(title)); dispatch(openLoading(title))
// 1.需要调整项目文件 先新建 再删除 // 1.需要调整项目文件 先新建 再删除
const oldFilePath = dirSplicing(dataInfo.path, ''); const oldFilePath = dirSplicing(dataInfo.path, '')
const newFilePath = dirSplicing(newData.path, `${newData.name}.${projectSuffix}.json`); const newFilePath = dirSplicing(newData.path, `${newData.name}.${projectSuffix}.json`)
const config = getState()?.config?.data[0]; const config = getState()?.config?.data[0]
if (fileExists(newFilePath) && oldFilePath !== newFilePath) { if (fileExists(newFilePath) && (oldFilePath !== newFilePath)) {
dispatch(closeLoading(STATUS[2], allLangData[config.lang].createProjectExists)); dispatch(closeLoading(STATUS[2], allLangData[config.lang].createProjectExists))
} else { } else {
saveJsonPromise( saveJsonPromise(newFilePath, _.omit({
newFilePath,
_.omit(
{
...oldData, ...oldData,
...newData, ...newData,
updatedTime: moment().format('YYYY-M-D HH:mm:ss'), updatedTime: moment().format('YYYY-M-D HH:mm:ss'),
}, }, ['path'])).then(() => {
['path'],
),
)
.then(() => {
if (oldFilePath !== newFilePath) { if (oldFilePath !== newFilePath) {
// 删除 // 删除
deleteFile(oldFilePath); deleteFile(oldFilePath)
// 更新版本文件 // 更新版本文件
renameVersion(oldFilePath, newFilePath, oldData, newData); renameVersion(oldFilePath, newFilePath, oldData, newData)
} }
// 2.需要更新用户配置文件 // 2.需要更新用户配置文件
updateHistory( updateHistory({
{
...oldData, ...oldData,
path: oldFilePath, path: oldFilePath,
}, }, {
{
describe: newData.describe || '', describe: newData.describe || '',
name: newData.name || '', name: newData.name || '',
avatar: newData.avatar || '', avatar: newData.avatar || '',
path: newFilePath, path: newFilePath,
}, })(dispatch, getState)
)(dispatch, getState); }).catch((err) => {
dispatch(closeLoading(STATUS[2], err))
}) })
.catch((err) => {
dispatch(closeLoading(STATUS[2], err));
});
} }
}; }
}; }
export const removeProject = (data, title) => { export const removeProject = (data, title) => {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(openLoading(title)); dispatch(openLoading(title))
// 删除项目 // 删除项目
deleteFile(data.path); deleteFile(data.path)
// 更新历史记录 // 更新历史记录
removeHistory(data)(dispatch, getState); removeHistory(data)(dispatch, getState)
}; }
}; }
export const createProject = (data, path, title, type) => { export const createProject = (data, path, title, type) => {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(openLoading(title)); dispatch(openLoading(title))
// 如果传递的路径则直接保存 反之则需要选取路径 // 如果传递的路径则直接保存 反之则需要选取路径
new Promise((res, rej) => { new Promise((res, rej) => {
if (!path) { if (!path) {
openFileOrDirPath([], ['openDirectory']) openFileOrDirPath([], ['openDirectory']).then((dir) => {
.then((dir) => { res(dir)
res(dir); }).catch(rej)
})
.catch(rej);
} else { } else {
// 校验目录是否存在 如果不存在则需要创建 // 校验目录是否存在 如果不存在则需要创建
ensureDirectoryExistence(path); ensureDirectoryExistence(path)
res(path); res(path)
} }
}) }).then((projectDir) => {
.then((projectDir) => {
// 拼接路径和项目名 // 拼接路径和项目名
const realFilePath = dirSplicing(projectDir, `${data.name}.${projectSuffix}.json`); const realFilePath = dirSplicing(projectDir, `${data.name}.${projectSuffix}.json`)
const config = getState()?.config?.data[0]; const config = getState()?.config?.data[0]
if (fileExists(realFilePath)) { if (fileExists(realFilePath)) {
throw new Error(allLangData[config.lang].createProjectExists); throw new Error(allLangData[config.lang].createProjectExists)
} else { } else {
const time = moment().format('YYYY-M-D HH:mm:ss'); const time = moment().format('YYYY-M-D HH:mm:ss')
const newData = { const newData = {
// ...emptyProject, // ...emptyProject,
...data, ...data,
version, version,
createdTime: time, createdTime: time,
updatedTime: time, updatedTime: time,
}; }
saveJsonPromise(realFilePath, newData) saveJsonPromise(realFilePath, newData).then(() => {
.then(() => { addHistory({
addHistory(
{
describe: newData.describe || '', describe: newData.describe || '',
name: newData.name || '', name: newData.name || '',
avatar: newData.avatar || '', avatar: newData.avatar || '',
path: realFilePath, path: realFilePath,
}, }, (err) => {
(err) => {
if (!err) { if (!err) {
dispatch(createProjectSuccess(newData, realFilePath)); dispatch(createProjectSuccess(newData, realFilePath))
dispatch(closeLoading(STATUS[1], null, '', type)); dispatch(closeLoading(STATUS[1], null, '', type))
} else { } else {
// dispatch(createProjectError(err)); // dispatch(createProjectError(err));
dispatch(closeLoading(STATUS[2], err)); dispatch(closeLoading(STATUS[2], err))
} }
}, })(dispatch, getState)
)(dispatch, getState); }).catch((err) => {
}) dispatch(createProjectError(err))
.catch((err) => {
dispatch(createProjectError(err));
// dispatch(closeLoading(STATUS[2], err)); // dispatch(closeLoading(STATUS[2], err));
});
}
}) })
.catch((err) => { }
dispatch(closeLoading(STATUS[2], err)); }).catch((err) => {
dispatch(closeLoading(STATUS[2], err))
// dispatch(createProjectError(err)); // dispatch(createProjectError(err));
}); })
}; }
}; }
/* /*
* action 创建函数 * action 创建函数
*/ */
export const openDemoProject = (h, t, title, type) => { export const openDemoProject = (h, t, title, type) => {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(openLoading(title)); dispatch(openLoading(title))
let tempH = h; let tempH = h
let isDemoProject = t || getState().core.isDemoProject; let isDemoProject = t || getState().core.isDemoProject
if (!tempH) { if (!tempH) {
tempH = template[isDemoProject]; tempH = template[isDemoProject]
} }
const data = const data =
// compareVersion('3.5.0', tempH.version.split('.')) // compareVersion('3.5.0', tempH.version.split('.'))
// ? reduceProject(tempH, 'defKey') : // ? reduceProject(tempH, 'defKey') :
tempH; tempH
setMemoryCache('data', data); setMemoryCache('data', data)
dispatch(readProjectSuccess(data, [], '', isDemoProject)); dispatch(readProjectSuccess(data, [], '', isDemoProject))
dispatch(closeLoading(STATUS[1], null, '', type)); dispatch(closeLoading(STATUS[1], null, '', type))
};
};
export const updateDataSource = (data) => {
return (dispatch, getState) => {
let isDemoProject = getState().core.isDemoProject;
dispatch(readProjectSuccess(data, [], '', isDemoProject));
} }
} }
export const close = () => { export const close = () => {
return { return {
type: CLOSE_PROJECT, type: CLOSE_PROJECT,
}; }
}; }
export const closeProject = (type) => { export const closeProject = (type) => {
return (dispatch) => { return (dispatch) => {
dispatch(optReset(type)); dispatch(optReset(type))
dispatch(close()); dispatch(close())
}; }
}; }
export const readProject = (path, title, getState, type, isDemoProject) => { export const readProject = (path, title, getState, type, isDemoProject) => {
return (dispatch) => { return (dispatch) => {
dispatch(openLoading(title)); // 开启全局loading dispatch(openLoading(title)) // 开启全局loading
// 判断项目文件是否为只读权限 // 判断项目文件是否为只读权限
readJsonPromise(path) readJsonPromise(path)
.then((data) => { .then((data) => {
if (!data.version) { if (!data.version) {
// 无效的项目 // 无效的项目
const config = getState()?.config?.data[0]; const config = getState()?.config?.data[0]
const err = new Error(allLangData[config.lang].invalidProjectData); const err = new Error(allLangData[config.lang].invalidProjectData)
dispatch(readProjectFail(err)); dispatch(readProjectFail(err))
dispatch(closeLoading(STATUS[2], err)); dispatch(closeLoading(STATUS[2], err))
} else if (!isDemoProject) { } else if (!isDemoProject) {
const newData = transformationData(data); const newData = transformationData(data)
// 将打开的项目记录存储到用户信息中 // 将打开的项目记录存储到用户信息中
addHistory( addHistory({
{
describe: newData.describe || '', describe: newData.describe || '',
name: newData.name || '', name: newData.name || '',
avatar: newData.avatar || '', avatar: newData.avatar || '',
path, path,
}, }, (err) => {
(err) => {
if (!err) { if (!err) {
setMemoryCache('data', newData); setMemoryCache('data', newData)
getAllVersionProject(path, newData) getAllVersionProject(path, newData).then((versionData) => {
.then((versionData) => { dispatch(readProjectSuccess(newData, versionData, path))
dispatch(readProjectSuccess(newData, versionData, path)); }).catch(() => {
setMemoryCache('data', newData)
dispatch(readProjectSuccess(newData, versionData, path))
}).finally(() => {
dispatch(closeLoading(STATUS[1], null, '', type))
}) })
.catch(() => {
setMemoryCache('data', newData);
dispatch(readProjectSuccess(newData, versionData, path));
})
.finally(() => {
dispatch(closeLoading(STATUS[1], null, '', type));
});
} else { } else {
dispatch(readProjectFail(err)); dispatch(readProjectFail(err))
dispatch(closeLoading(STATUS[2], err)); dispatch(closeLoading(STATUS[2], err))
} }
}, })(dispatch, getState)
)(dispatch, getState);
} else { } else {
const newData = transformationData(data); const newData = transformationData(data)
setMemoryCache('data', newData); setMemoryCache('data', newData)
dispatch(readProjectSuccess(newData, [], path, isDemoProject)); dispatch(readProjectSuccess(newData, [], path, isDemoProject))
dispatch(closeLoading(STATUS[1], null, '', type)); dispatch(closeLoading(STATUS[1], null, '', type))
} }
}) })
.catch((err) => { .catch((err) => {
dispatch(readProjectFail(err)); dispatch(readProjectFail(err))
dispatch(closeLoading(STATUS[2], err)); dispatch(closeLoading(STATUS[2], err))
}); })
}; }
}; }
const readProjectFail = (err) => { const readProjectFail = (err) => {
return { return {
type: READ_PROJECT_FAIL, type: READ_PROJECT_FAIL,
data: err, data: err,
}; }
}; }
// 打开项目 // 打开项目
export const openProject = (title, type, path, suffix, isDemoProject) => { export const openProject = (title, type, path, suffix, isDemoProject) => {
// 从系统中选择项目 无需传递路径 // 从系统中选择项目 无需传递路径
return (dispatch, getState) => { return (dispatch, getState) => {
if (path) { if (path) {
readProject(path, title, getState, type)(dispatch); readProject(path, title, getState, type)(dispatch)
} else { } else {
const config = getState()?.config?.data[0]; const config = getState()?.config?.data[0]
openProjectFilePath(allLangData[config.lang].invalidProjectFile, suffix) openProjectFilePath(allLangData[config.lang].invalidProjectFile, suffix).then((filePath) => {
.then((filePath) => { readProject(filePath, title, getState, type, isDemoProject)(dispatch)
readProject(filePath, title, getState, type, isDemoProject)(dispatch); }).catch((err) => {
dispatch(readProjectFail(err))
}) })
.catch((err) => {
dispatch(readProjectFail(err));
});
} }
}; }
}; }

View File

@ -1,12 +1,3 @@
/*
* @version: V1.0.0
* @Date: 2023-12-28 11:28:35
* @LastEditors: lzq
* @LastEditTime: 2024-01-03 11:32:11
* @company: 睿展数据
* @FilePath: \salpa-web\src\pages\pdManer\components\groupicon\index.js
* @Descripttion:
*/
import React, {useRef, useState, useEffect, useMemo } from 'react'; import React, {useRef, useState, useEffect, useMemo } from 'react';
import { v4 as uuidv4 } from "uuid" import { v4 as uuidv4 } from "uuid"
import GroupIconGroup from './GroupIconGroup'; import GroupIconGroup from './GroupIconGroup';
@ -31,7 +22,7 @@ const GroupIcon = React.memo(({ prefix, title, onClick, icon, dropMenu, dropType
} }
}; };
const dropClick = (m, e) => { const dropClick = (m, e) => {
onClick && onClick(e, m.key, m?.dataSource); onClick && onClick(e, m.key);
e.stopPropagation(); e.stopPropagation();
}; };
const onIconClick = (e) => { const onIconClick = (e) => {

View File

@ -1,3 +1,4 @@
export default { export default {
system: { system: {
title: 'PDManer', title: 'PDManer',
@ -37,8 +38,6 @@ export default {
exportConfig: '导出系统设置', exportConfig: '导出系统设置',
importConfig: '导入系统设置', importConfig: '导入系统设置',
importDDL: '导入DDL', importDDL: '导入DDL',
standardDataImport:'标准数据导入',
standardDataExport:'标准数据导出',
exportImg: '导出当前画布为图片', exportImg: '导出当前画布为图片',
exportImgLoading: '正在导出当前画布为图片...', exportImgLoading: '正在导出当前画布为图片...',
exportSql: '导出DDL', exportSql: '导出DDL',
@ -50,7 +49,7 @@ export default {
exportPath: '导出文件位于:"{path}"', exportPath: '导出文件位于:"{path}"',
setting: '设置', setting: '设置',
dbConnect: '数据库', dbConnect: '数据库',
dbConnectTest: '数据库连接', dbConnectTest:"数据库连接",
search: '数据表/视图/数据字典', search: '数据表/视图/数据字典',
create: '新建', create: '新建',
open: '打开', open: '打开',
@ -154,8 +153,7 @@ export default {
emptyField: '<空字段>', emptyField: '<空字段>',
entityUniqueKeyError: '数据表中包含重复字段,请修改,重复字段有[{entities}]', entityUniqueKeyError: '数据表中包含重复字段,请修改,重复字段有[{entities}]',
entityUniqueDefKeyError: '数据表或视图已经存在,请修改,重复数据表或视图有[{entities}]', entityUniqueDefKeyError: '数据表或视图已经存在,请修改,重复数据表或视图有[{entities}]',
entityHideInGraphSizeError: entityHideInGraphSizeError: '逻辑图显示字段请选择能够代表本表业务含义的典型属性字段,限制为[{size}]个,超限数据表有[{entities}],如需修改,请通过:"设置->系统参数->逻辑图最大展示字段数"进行修改',
'逻辑图显示字段请选择能够代表本表业务含义的典型属性字段,限制为[{size}]个,超限数据表有[{entities}],如需修改,请通过:"设置->系统参数->逻辑图最大展示字段数"进行修改',
modify: '前往修改', modify: '前往修改',
formValidateMessage: '带星号为必输项,不能为空!', formValidateMessage: '带星号为必输项,不能为空!',
defKeyValidateMessage: '{name}代码不能为空', defKeyValidateMessage: '{name}代码不能为空',
@ -424,23 +422,6 @@ export default {
search: '搜索数据表', search: '搜索数据表',
selectEntityEmpty: '请选择数据表', selectEntityEmpty: '请选择数据表',
}, },
tableExportHeaders: {
defKey: '字段代码',
defName: '显示名称',
primaryKey: '主键',
notNull: '不为空',
autoIncrement: '自增',
domain: '数据域',
hideInGraph: '显示与逻辑图',
type: '数据类型',
len: '长度',
scale: '小数位数',
comment: '说明',
refDict: '数据字典',
defaultValue: '默认值',
uiHint: 'UI建议',
extProps: '拓展属性',
},
tableHeaders: { tableHeaders: {
defName: '显示名称', defName: '显示名称',
defKey: '字段代码', defKey: '字段代码',
@ -691,8 +672,7 @@ export default {
success: '配置成功', success: '配置成功',
error: '配置失败', error: '配置失败',
placeholder: '不填将自动从系统的环境变量中读取', placeholder: '不填将自动从系统的环境变量中读取',
notFoundJDK: notFoundJDK: '未检测到JDK请先安装JDK(如果已经安装,请检查环境变量是否配置正确或者前往系统【设置】-> 【系统参数】->【JAVA_HOME】指定JDK路径)',
'未检测到JDK请先安装JDK(如果已经安装,请检查环境变量是否配置正确或者前往系统【设置】-> 【系统参数】->【JAVA_HOME】指定JDK路径)',
outOfMemoryError: 'JVM所需内存不足请前往[设置=>系统参数=>JVM参数]调整', outOfMemoryError: 'JVM所需内存不足请前往[设置=>系统参数=>JVM参数]调整',
}, },
DictSQLTemplate: '数据字典SQL模板', DictSQLTemplate: '数据字典SQL模板',
@ -753,8 +733,7 @@ export default {
delete: '删除', delete: '删除',
copy: '复制', copy: '复制',
demoDbConnect: { demoDbConnect: {
mysql: mysql: 'jdbc:mysql://IP地址:端口号/数据库名?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=UTC',
'jdbc:mysql://IP地址:端口号/数据库名?characterEncoding=UTF-8&useSSL=false&useUnicode=true&serverTimezone=UTC',
oracle: 'jdbc:oracle:thin:@IP地址:端口号/数据库名', oracle: 'jdbc:oracle:thin:@IP地址:端口号/数据库名',
sqlserver: 'jdbc:sqlserver://IP地址:端口号;DatabaseName=数据库名', sqlserver: 'jdbc:sqlserver://IP地址:端口号;DatabaseName=数据库名',
sqlserverTitle: '官方驱动默认支持java8如果您是其他版本的JDK请自定义驱动', sqlserverTitle: '官方驱动默认支持java8如果您是其他版本的JDK请自定义驱动',
@ -763,10 +742,8 @@ export default {
dm: 'jdbc:dm://IP地址:端口号/数据库名', dm: 'jdbc:dm://IP地址:端口号/数据库名',
guassdb: 'jdbc:postgresql://IP地址:端口号/数据库名', guassdb: 'jdbc:postgresql://IP地址:端口号/数据库名',
kingbase: 'jdbc:kingbase8://IP地址:端口号/数据库名', kingbase: 'jdbc:kingbase8://IP地址:端口号/数据库名',
maxcompute: maxcompute: 'jdbc:odps:http://IP地址:端口号/api?project=项目名&accessId=ACCESS_ID&accessKey=ACCESS_KEY',
'jdbc:odps:http://IP地址:端口号/api?project=项目名&accessId=ACCESS_ID&accessKey=ACCESS_KEY', sqlite: 'jdbc:sqlite:/path/db-file-name (MAC以及Linux) jdbc:sqlite://path/db-file-name (Windows)',
sqlite:
'jdbc:sqlite:/path/db-file-name (MAC以及Linux) jdbc:sqlite://path/db-file-name (Windows)',
}, },
configExample: '配置示例:', configExample: '配置示例:',
connectSuccess: '连接成功', connectSuccess: '连接成功',
@ -792,12 +769,10 @@ export default {
parseDb: '正在解析数据库,请稍后。。。(请勿关闭当前弹窗!)', parseDb: '正在解析数据库,请稍后。。。(请勿关闭当前弹窗!)',
parseDbError: '数据库解析失败', parseDbError: '数据库解析失败',
selectEntity: '选择数据表', selectEntity: '选择数据表',
dealResult: dealResult: '解析结果:共解析出[{data}]张数据表,当前模型中已经存在的有[{exists}]张表,请勾选需要添加到模型中的数据表!',
'解析结果:共解析出[{data}]张数据表,当前模型中已经存在的有[{exists}]张表,请勾选需要添加到模型中的数据表!',
}, },
importDb: { importDb: {
dealResult: dealResult: '解析结果:共解析出[{data}]张数据表,当前模型中已经存在的有[{exists}]张表,请勾选需要添加到模型中的数据表!',
'解析结果:共解析出[{data}]张数据表,当前模型中已经存在的有[{exists}]张表,请勾选需要添加到模型中的数据表!',
}, },
group: { group: {
base: '基本信息', base: '基本信息',
@ -878,4 +853,4 @@ export default {
viewList: '视图', viewList: '视图',
current: '数据库类型:', current: '数据库类型:',
}, },
}; }

View File

@ -1,192 +1,103 @@
import { executeSql } from '@/services/api.ts'; import React, { useState, forwardRef, useImperativeHandle, useRef, useEffect } from 'react'
import { Divider, Upload, message } from 'antd'; import { FormatMessage, GroupIcon, Icon, SearchSuggest, Slider, NumberInput, Modal } from '../../components'
import numeral from 'numeral'; import { SketchPicker } from 'react-color'
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'; import numeral from 'numeral'
import { validateNeedSave } from '../../lib/datasource_util'
import { Divider, message } from 'antd'
import { executeSql } from '@/services/api.ts'
import { getAllDataSQLByFilter } from '../../lib/json2code_util'
import './style/index.less'
const GroupIconGroup = GroupIcon.GroupIconGroup
import { SketchPicker } from 'react-color'; export default React.memo(forwardRef(({ currentPrefix, close, iconClick, colorChange, openModal, templateType,
import _ from 'lodash/object' activeTab, resize, sliderChange, dataSource,
import { jumpPosition, jumpDetail }, ref) => {
FormatMessage, const dbConn = dataSource?.dbConn || []
GroupIcon, const properties = dbConn[0]?.properties
Icon, const [isCellSelected, setIsCellSelected] = useState(false)
Modal, const [scaleNumber, setScaleNumber] = useState(1)
NumberInput,
SearchSuggest,
Slider,
} from '../../components';
import { validateNeedSave } from '../../lib/datasource_util';
import { getAllDataSQLByFilter } from '../../lib/json2code_util';
import './style/index.less';
const GroupIconGroup = GroupIcon.GroupIconGroup;
export default React.memo(
forwardRef(
(
{
currentPrefix,
close,
iconClick,
colorChange,
openModal,
templateType,
activeTab,
resize,
sliderChange,
dataSource,
getDataSource,
restProps,
jumpPosition,
jumpDetail,
},
ref,
) => {
const dbConn = dataSource?.dbConn || [];
const properties = dbConn[0]?.properties;
const [isCellSelected, setIsCellSelected] = useState(false);
const [scaleNumber, setScaleNumber] = useState(1);
const [colorState, setColor] = useState({ const [colorState, setColor] = useState({
fontColor: 'rgba(0, 0, 0, 0.65)', fontColor: 'rgba(0, 0, 0, 0.65)',
fillColor: '#ACDAFC', fillColor: '#ACDAFC',
}); })
const [fileList, setFileList] = useState([]); useImperativeHandle(ref, () => {
useImperativeHandle(
ref,
() => {
return { return {
setScaleNumber, setScaleNumber,
setIsCellSelected, setIsCellSelected,
}; }
}, }, [])
[],
);
const _colorChange = (key, value) => { const _colorChange = (key, value) => {
setColor((pre) => { setColor((pre) => {
return { return {
...pre, ...pre,
[key]: value.hex, [key]: value.hex,
}; }
}); })
colorChange && colorChange(key, value); colorChange && colorChange(key, value)
}; }
const _close = () => { const _close = () => {
if (validateNeedSave(dataSource)) { if (validateNeedSave(dataSource)) {
Modal.confirm({ Modal.confirm({
title: FormatMessage.string({ id: 'closeConfirmTitle' }), title: FormatMessage.string({ id: 'closeConfirmTitle' }),
message: FormatMessage.string({ id: 'closeConfirm' }), message: FormatMessage.string({ id: 'closeConfirm' }),
onOk: () => { onOk: () => {
close(); close()
}, },
});
} else {
close();
}
};
const handleExportDataBase = () => {
const { entities, domains } = dataSource;
const workBook = window.XLSX.utils.book_new();
for (let index = 0; index < entities.length; index++) {
const data = entities[index];
const headers = data.headers
.filter((item) => item.refKey !== 'isStandard')
.map((item) => FormatMessage.string({ id: `tableExportHeaders.${item.refKey}` }));
const keyList = data.headers
.filter((item) => item.refKey !== 'isStandard')
.map((item) => item.refKey);
const tableColumnData = data.fields
.map((item) => {
// 判断为哪个数据域字典
const {
len,
defName: domain,
scale,
uiHint,
} = domains.find((domain) => domain.id === item.domain);
// 数据字典处理
const obj = { ...item, len, domain, scale, uiHint };
if (item.defKey.indexOf('time') === -1) {
obj.type = 'VARCHAR';
} else {
obj.type = 'DATETIME';
}
return obj;
}) })
.map((item) => {
return keyList.map((key) =>
typeof item[key] === 'boolean' ? (item[key] ? '是' : '否') : item[key],
);
});
tableColumnData.unshift(headers);
const workSheet = window.XLSX.utils.aoa_to_sheet(tableColumnData);
if (!workSheet['!cols']) workSheet['!cols'] = [];
for (let i = 0; i <= 21; i += 1) {
if (i === 0 || i === 1) {
workSheet['!cols'][i] = { wpx: 260 };
} else { } else {
workSheet['!cols'][i] = { wpx: 150 }; close()
} }
} }
window.XLSX.utils.book_append_sheet(workBook, workSheet, data.defName); const defaultTemplate = ['createTable', 'createIndex', 'content']
} const templateRef = useRef(defaultTemplate)
const dataTypeSupports = _.get(dataSource, 'profile.dataTypeSupports', [])
window.XLSX.writeFile(workBook, '数据表.xlsx'); const defaultDb = _.get(dataSource, 'profile.default.db', dataTypeSupports[0]?.id)
};
const defaultTemplate = ['createTable', 'createIndex', 'content'];
const templateRef = useRef(defaultTemplate);
const dataTypeSupports = _.get(dataSource, 'profile.dataTypeSupports', []);
const defaultDb = _.get(dataSource, 'profile.default.db', dataTypeSupports[0]?.id);
const [codeData, setCodeData] = useState(() => { const [codeData, setCodeData] = useState(() => {
return getAllDataSQLByFilter( return getAllDataSQLByFilter(dataSource,
dataSource, templateType === 'dict' ? 'dictSQLTemplate' : defaultDb, templateRef.current)
templateType === 'dict' ? 'dictSQLTemplate' : defaultDb, })
templateRef.current,
);
});
const backGroup = async () => { const backGroup = async () => {
if (!properties) { if (!properties) {
Modal.error({ Modal.error({
title: FormatMessage.string({ id: 'dbConnect.connectError' }), title: FormatMessage.string({ id: 'dbConnect.connectError' }),
message: '请连接数据库', message: '请连接数据库',
}); })
} else { } else {
const data = { const data = {
driverName: properties.driver_class_name, driverName: properties.driver_class_name,
url: properties.url, url: properties.url,
username: properties.username, username: properties.username,
password: properties.password, password: properties.password,
sql: codeData, sql: codeData
}; }
const res = await executeSql(data); const res = await executeSql(data)
if (res.code == 200) { if (res.code == 200) {
Modal.success({ Modal.success({
title: FormatMessage.string({ id: 'dbConnect.connectSuccess' }), title: FormatMessage.string({ id: 'dbConnect.connectSuccess' }),
message: `${res.msg}`, message: `${res.msg}`,
}); })
} else { } else {
Modal.error({ Modal.error({
bodyStyle: { width: '50%' }, bodyStyle: { width: '50%' },
contentStyle: { width: '100%', height: '100%' }, contentStyle: { width: '100%', height: '100%' },
title: FormatMessage.string({ id: 'dbConnect.connectError' }), title: FormatMessage.string({ id: 'dbConnect.connectError' }),
message: `${res.msg}`, message: `${res.msg}`
}); })
} }
} }
};
const [issee, setIssee] = useState(false); }
const [isfill, setIsfill] = useState(false); const [issee, setIssee] = useState(false)
const [isfill, setIsfill] = useState(false)
const fill = () => { const fill = () => {
setIsfill(!isfill); setIsfill(!isfill)
setIssee(false); setIssee(false)
}; }
const see = () => { const see = () => {
setIsfill(false); setIsfill(false)
setIssee(!issee); setIssee(!issee)
}; }
return ( return (
<div className={`${currentPrefix}-head`}> <div className={`${currentPrefix}-head`}>
@ -201,7 +112,7 @@ export default React.memo(
</div> </div>
</div> </div>
</div> </div>
<Divider className="divider" /> <Divider className='divider' />
<div className={`${currentPrefix}-iconstyle`}> <div className={`${currentPrefix}-iconstyle`}>
<GroupIconGroup> <GroupIconGroup>
<GroupIcon <GroupIcon
@ -211,6 +122,7 @@ export default React.memo(
groupKey="save" groupKey="save"
icon="icon-bianzu2" icon="icon-bianzu2"
onClick={iconClick} onClick={iconClick}
/> />
<GroupIcon <GroupIcon
className={`${currentPrefix}-icongroup`} className={`${currentPrefix}-icongroup`}
@ -283,21 +195,11 @@ export default React.memo(
//onMouseDown={e => iconClick(e, 'polygon')} //onMouseDown={e => iconClick(e, 'polygon')}
/> />
<div className="fontColor1"> <div className='fontColor1'>
<Icon <Icon type="icon-zitiyanse" onClick={see}
type="icon-zitiyanse" disable={activeTab?.type !== 'diagram' || !isCellSelected} title="字体颜色" />
onClick={see}
disable={activeTab?.type !== 'diagram' || !isCellSelected}
title="字体颜色"
/>
{/* display: issee ? 'block' : 'none' */} {/* display: issee ? 'block' : 'none' */}
<div <div style={{ display: activeTab?.type == 'diagram' && issee && isCellSelected ? 'block' : 'none' }} className='fontColor2' >
style={{
display:
activeTab?.type == 'diagram' && issee && isCellSelected ? 'block' : 'none',
}}
className="fontColor2"
>
<SketchPicker <SketchPicker
disableAlpha disableAlpha
presetColors={[ presetColors={[
@ -323,20 +225,9 @@ export default React.memo(
/> />
</div> </div>
</div> </div>
<div className="fontColor1"> <div className='fontColor1'>
<Icon <Icon type="icon-tianchongyanse" onClick={fill} disable={activeTab?.type !== 'diagram' || !isCellSelected} title="填充颜色" />
type="icon-tianchongyanse" <div style={{ display: activeTab?.type == 'diagram' && isfill && isCellSelected ? 'block' : 'none' }} className='fontColor2' >
onClick={fill}
disable={activeTab?.type !== 'diagram' || !isCellSelected}
title="填充颜色"
/>
<div
style={{
display:
activeTab?.type == 'diagram' && isfill && isCellSelected ? 'block' : 'none',
}}
className="fontColor2"
>
<SketchPicker <SketchPicker
disableAlpha disableAlpha
presetColors={[ presetColors={[
@ -474,14 +365,32 @@ export default React.memo(
</> </>
} }
/> />
<GroupIcon {/* <GroupIcon
className={`${currentPrefix}-icongroup`} className={`${currentPrefix}-icongroup`}
hoverTitle={FormatMessage.string({ id: 'toolbar.import' })} hoverTitle={FormatMessage.string({ id: 'toolbar.import' })}
onClick={iconClick} onClick={iconClick}
icon={<Icon type="icon-daoru" />} icon={<Icon type="icon-daoru" />}
dropMenu={[ dropMenu={[
{ key: 'chiner', name: FormatMessage.string({ id: 'toolbar.importCHNR' }) },
{
key: 'powerdesigner',
name: FormatMessage.string({ id: 'toolbar.importPowerDesigner' }),
},
{ key: 'db', name: FormatMessage.string({ id: 'toolbar.importDb' }) },
{ key: 'importDDL', name: FormatMessage.string({ id: 'toolbar.importDDL' }) }, { key: 'importDDL', name: FormatMessage.string({ id: 'toolbar.importDDL' }) },
{ key: 'standardDataImport', name: FormatMessage.string({ id: 'toolbar.standardDataImport' }), dataSource }, {
style: { borderTop: '1px solid #DFE3EB' },
key: 'domains',
name: FormatMessage.string({ id: 'toolbar.importDomains' }),
},
{
key: 'appCodes',
name: FormatMessage.string({ id: 'toolbar.importAppCodes' }),
},
{
key: 'importConfig',
name: FormatMessage.string({ id: 'toolbar.importConfig' }),
},
]} ]}
/> />
<GroupIcon <GroupIcon
@ -490,11 +399,29 @@ export default React.memo(
hoverTitle={FormatMessage.string({ id: 'toolbar.export' })} hoverTitle={FormatMessage.string({ id: 'toolbar.export' })}
icon={<Icon type="icon-daochu" />} icon={<Icon type="icon-daochu" />}
dropMenu={[ dropMenu={[
{ key: 'word', name: FormatMessage.string({ id: 'toolbar.exportWord' }) },
{ key: 'sql', name: FormatMessage.string({ id: 'toolbar.exportSql' }) }, { key: 'sql', name: FormatMessage.string({ id: 'toolbar.exportSql' }) },
{ key: 'standardDataExport', name: FormatMessage.string({ id: 'toolbar.standardDataExport' }), dataSource }, { key: 'dict', name: FormatMessage.string({ id: 'toolbar.exportDict' }) },
{
key: 'img',
name: FormatMessage.string({ id: 'toolbar.exportImg' }),
disable: activeTab?.type !== 'diagram',
},
{
style: { borderTop: '1px solid #DFE3EB' },
key: 'exportDomains',
name: FormatMessage.string({ id: 'toolbar.exportDomains' }),
},
{
key: 'exportAppCodes',
name: FormatMessage.string({ id: 'toolbar.exportAppCodes' }),
},
{
key: 'exportConfig',
name: FormatMessage.string({ id: 'toolbar.exportConfig' }),
},
]} ]}
/> /> */}
{/* <GroupIcon {/* <GroupIcon
className={`${currentPrefix}-icongroup`} className={`${currentPrefix}-icongroup`}
hoverTitle={FormatMessage.string({ id: 'toolbar.setting' })} hoverTitle={FormatMessage.string({ id: 'toolbar.setting' })}
@ -514,7 +441,6 @@ export default React.memo(
onClick={backGroup} onClick={backGroup}
/> />
</GroupIconGroup> </GroupIconGroup>
<div className={`${currentPrefix}-head-search`}> <div className={`${currentPrefix}-head-search`}>
<SearchSuggest <SearchSuggest
jumpPosition={jumpPosition} jumpPosition={jumpPosition}
@ -525,7 +451,5 @@ export default React.memo(
</div> </div>
</div> </div>
</div> </div>
); )
}, }))
),
);

File diff suppressed because it is too large Load Diff

View File

@ -1,507 +0,0 @@
[
{
"id": "57fa5152-07c0-4216-a384-67729c987e38",
"env": {
"base": {
"nameSpace": "",
"codeRoot": ""
}
},
"defKey": "sys_user",
"defName": "用户表",
"comment": "",
"properties": {
"partitioned by": "(date string)",
"row format delimited": "",
"fields terminated by ','": "",
"collection items terminated by '-'": "",
"map keys terminated by ':'": "",
"store as textfile;": ""
},
"nameTemplate": "{defKey}[{defName}]",
"headers": [
{
"refKey": "hideInGraph",
"hideInGraph": true
},
{
"refKey": "defKey",
"hideInGraph": false
},
{
"refKey": "defName",
"hideInGraph": false
},
{
"refKey": "primaryKey",
"hideInGraph": false
},
{
"refKey": "notNull",
"hideInGraph": true
},
{
"refKey": "autoIncrement",
"hideInGraph": true
},
{
"refKey": "domain",
"hideInGraph": true
},
{
"refKey": "type",
"hideInGraph": false
},
{
"refKey": "len",
"hideInGraph": false
},
{
"refKey": "scale",
"hideInGraph": false
},
{
"refKey": "comment",
"hideInGraph": true
},
{
"refKey": "refDict",
"hideInGraph": true
},
{
"refKey": "defaultValue",
"hideInGraph": true
},
{
"refKey": "isStandard",
"hideInGraph": false
},
{
"refKey": "uiHint",
"hideInGraph": true
},
{
"refKey": "extProps",
"hideInGraph": true
}
],
"fields": [
{
"defKey": "tenant_id",
"defName": "租户号",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"refDict": "",
"uiHint": "",
"id": "fd1196b9-bc37-4275-b38b-a658f82252e8"
},
{
"defKey": "revision",
"defName": "乐观锁",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "653db02c-54e3-4f3f-bff4-af294cb7cac3"
},
{
"defKey": "created_by",
"defName": "创建人",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "5e0f02b1-632b-44c8-ba86-4cfb49fd0d40"
},
{
"defKey": "created_time",
"defName": "创建时间",
"comment": "",
"domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "02de6461-ca9b-4c33-b304-b51ff055be5d"
},
{
"defKey": "updated_by",
"defName": "更新人",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "a9c8cd25-5ee1-4eb2-9f65-4a0ebf8a670a"
},
{
"defKey": "updated_time",
"defName": "更新时间",
"comment": "",
"domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "a034d653-7590-44bd-aa3d-e174f1610f0e"
},
{
"defKey": "user_id",
"defName": "用户ID",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": true,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "16120F75-6AA7-4483-868D-F07F511BB081",
"id": "acc5f059-e2f9-4898-8f3e-67da1b131aab"
},
{
"defKey": "user_name",
"defName": "用户名称",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"id": "fb905579-49a8-4ba1-8779-739c07e550ae"
}
],
"correlations": [],
"indexes": []
},
{
"id": "3cb84272-2063-4c42-b3bf-e9f16583333",
"env": {
"base": {
"nameSpace": "",
"codeRoot": ""
}
},
"defKey": "sys_dept",
"defName": "部门表",
"comment": "",
"properties": {
"partitioned by": "(date string)",
"row format delimited": "",
"fields terminated by ','": "",
"collection items terminated by '-'": "",
"map keys terminated by ':'": "",
"store as textfile;": ""
},
"nameTemplate": "{defKey}[{defName}]",
"headers": [
{
"refKey": "hideInGraph",
"hideInGraph": true
},
{
"refKey": "defKey",
"hideInGraph": false
},
{
"refKey": "defName",
"hideInGraph": false
},
{
"refKey": "primaryKey",
"hideInGraph": false
},
{
"refKey": "notNull",
"hideInGraph": true
},
{
"refKey": "autoIncrement",
"hideInGraph": true
},
{
"refKey": "domain",
"hideInGraph": true
},
{
"refKey": "type",
"hideInGraph": false
},
{
"refKey": "len",
"hideInGraph": false
},
{
"refKey": "scale",
"hideInGraph": false
},
{
"refKey": "comment",
"hideInGraph": true
},
{
"refKey": "refDict",
"hideInGraph": true
},
{
"refKey": "defaultValue",
"hideInGraph": true
},
{
"refKey": "isStandard",
"hideInGraph": false
},
{
"refKey": "uiHint",
"hideInGraph": true
},
{
"refKey": "extProps",
"hideInGraph": true
}
],
"fields": [
{
"defKey": "tenant_id",
"defName": "租户号",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"refDict": "",
"uiHint": "",
"id": "22de7bde-fdc0-4469-ad9f-97a555549bef"
},
{
"defKey": "revision",
"defName": "乐观锁",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "2e48ad92-7f86-44d5-aa51-326878ab39ba"
},
{
"defKey": "created_by",
"defName": "创建人",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "aef05e82-3fdd-48d1-b863-95df9d8025a1"
},
{
"defKey": "created_time",
"defName": "创建时间",
"comment": "",
"domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "e043ad8c-80a1-4ac8-938d-2e220c508fd1"
},
{
"defKey": "updated_by",
"defName": "更新人",
"comment": "",
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "56f2afaa-00be-405c-af90-58ffc10f1bec"
},
{
"defKey": "updated_time",
"defName": "更新时间",
"comment": "",
"domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": true,
"refDict": "",
"uiHint": "",
"id": "f471d0b0-450c-436f-b300-0e26fd1c5189"
},
{
"defKey": "dept_id",
"defName": "部门ID",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": true,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "16120F75-6AA7-4483-868D-F07F511BB081",
"id": "0cdd83a0-fa06-4139-9547-0fb8165fde0b"
},
{
"defKey": "pid",
"defName": "上级部门",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"id": "8fb08930-0abf-4410-aa35-a9891c6a81a7"
},
{
"defKey": "sub_count",
"defName": "子部门数目",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
"id": "6b784bad-1a7f-4989-a9db-a9225e6e947b"
},
{
"defKey": "name",
"defName": "名称",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "9092C4E0-1A54-4859-ABBB-5B62DBC27573",
"id": "210abffa-a4f8-4ce9-8459-29c4948fb2b1"
},
{
"defKey": "dept_sort",
"defName": "排序",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
"id": "90ed2b15-35d7-4fc5-82cd-aa7e257cf917"
}
],
"correlations": [],
"indexes": []
}
]

View File

@ -51,20 +51,7 @@ export default ({ openTemplate }) => {
const [eidtLoading, setEidtLoading] = useState(false) const [eidtLoading, setEidtLoading] = useState(false)
const [searchLoading, setSearchLoading] = useState(false) const [searchLoading, setSearchLoading] = useState(false)
React.useEffect(() => { React.useEffect(() => {
const params = new URLSearchParams(window.location.search);
const projectId = params.get('projectId');
if (projectId) {
setSpinCard(true)
getModelId(projectId).then((res) => {
if (res.code == 200) {
setSpinCard(false)
const manerDataKey = JSON.parse(res.data.jsonFile)
openTemplate(manerDataKey, res.data.projectName)
}
})
} else {
goin(current, pagesize) goin(current, pagesize)
}
user() user()
}, []) }, [])
// 用户列表 // 用户列表
@ -299,7 +286,6 @@ export default ({ openTemplate }) => {
<Form.Item> <Form.Item>
<Button <Button
block block
type='primary'
className="ProCard" className="ProCard"
style={{ width: '200px' }} style={{ width: '200px' }}
onClick={createshowModal} onClick={createshowModal}

View File

@ -31,7 +31,3 @@
display: flex; display: flex;
justify-content: end; justify-content: end;
} }
.primary-button{
color: @primary-color;
}

View File

@ -14,7 +14,6 @@ import {
saveProject, saveProject,
saveVersionData, saveVersionData,
updateAllVersionData, updateAllVersionData,
updateDataSource,
updateProject, updateProject,
} from '../../actions/core'; } from '../../actions/core';
import { ConfigContent } from '../../lib/context'; import { ConfigContent } from '../../lib/context';
@ -25,7 +24,7 @@ import './style/index.less';
const Welcome = React.memo(({ prefix, getUserData, config, ...restProps }) => { const Welcome = React.memo(({ prefix, getUserData, config, ...restProps }) => {
const currentPrefix = getPrefix(prefix); const currentPrefix = getPrefix(prefix);
return ( return (
<div className={!!new URLSearchParams(window.location.search) ? '' : `${currentPrefix}-welcome`}> <div className={`${currentPrefix}-welcome`} >
{ {
<ConfigContent.Provider value={config}> <ConfigContent.Provider value={config}>
<Home config={config} {...restProps} /> <Home config={config} {...restProps} />
@ -49,9 +48,6 @@ const mapDispatchToProps = (dispatch) => {
getUserData: (title) => { getUserData: (title) => {
dispatch(getUserConfigData(title)); dispatch(getUserConfigData(title));
}, },
updateData: (data) => {
dispatch(saveUserConfigSome(data));
},
saveUserData: (data) => { saveUserData: (data) => {
dispatch(saveUserConfigSome(data)); dispatch(saveUserConfigSome(data));
}, },
@ -107,10 +103,6 @@ const mapDispatchToProps = (dispatch) => {
updateAllVersion: (versionData, title, dataSource) => { updateAllVersion: (versionData, title, dataSource) => {
return dispatch(updateAllVersionData(versionData, title, dataSource)); return dispatch(updateAllVersionData(versionData, title, dataSource));
}, },
updateDataSource: (dataSource) => {
console.log(dataSource);
return dispatch(updateDataSource(dataSource));
},
}; };
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Welcome); export default connect(mapStateToProps, mapDispatchToProps)(Welcome);

View File

@ -1,5 +1,5 @@
import { createIcon } from '@/utils/IconUtil'; import { createIcon } from '@/utils/IconUtil';
import request from '@/utils/request'; import request from '@/utils/request'
import type { MenuDataItem } from '@umijs/route-utils'; import type { MenuDataItem } from '@umijs/route-utils';
/** 获取当前的用户 GET /api/getUserInfo */ /** 获取当前的用户 GET /api/getUserInfo */
@ -18,6 +18,7 @@ export async function logout(options?: Record<string, any>) {
}); });
} }
export async function getRouters(): Promise<API.GetRoutersResult> { export async function getRouters(): Promise<API.GetRoutersResult> {
return request('/api/getRouters'); return request('/api/getRouters');
} }
@ -43,11 +44,9 @@ export async function getRoutersInfo(): Promise<MenuDataItem[]> {
}); });
} }
export function getMatchMenuItem( export function getMatchMenuItem(path: string, menuData: MenuDataItem[]|undefined): MenuDataItem[] {
path: string, if(!menuData)
menuData: MenuDataItem[] | undefined, return [];
): MenuDataItem[] {
if (!menuData) return [];
let items: MenuDataItem[] = []; let items: MenuDataItem[] = [];
menuData.forEach((item) => { menuData.forEach((item) => {
if (item.path) { if (item.path) {