diff --git a/oms_web/oms_web_new/src/components/ConfirmDialog/ConfirmDialog.jsx b/oms_web/oms_web_new/src/components/ConfirmDialog/ConfirmDialog.jsx deleted file mode 100644 index d7095b01..00000000 --- a/oms_web/oms_web_new/src/components/ConfirmDialog/ConfirmDialog.jsx +++ /dev/null @@ -1,138 +0,0 @@ -import { Modal } from 'antd' -import { ExclamationCircleOutlined, DeleteOutlined } from '@ant-design/icons' - -/** - * 标准确认对话框组件 - * @param {Object} options - 对话框配置 - * @param {string} options.title - 标题 - * @param {string|ReactNode} options.content - 内容 - * @param {string} options.okText - 确认按钮文字 - * @param {string} options.cancelText - 取消按钮文字 - * @param {string} options.type - 类型: 'warning', 'danger', 'info' - * @param {Function} options.onOk - 确认回调 - * @param {Function} options.onCancel - 取消回调 - */ -const ConfirmDialog = { - /** - * 显示删除确认对话框(单个项目) - */ - delete: ({ title = '确认删除', itemName, itemInfo, onOk, onCancel }) => { - Modal.confirm({ - title, - content: ( -
-

您确定要删除以下项目吗?

-
-

{itemName}

- {itemInfo && ( -

{itemInfo}

- )} -
-

- 此操作不可恢复,请谨慎操作! -

-
- ), - okText: '确认删除', - cancelText: '取消', - okType: 'danger', - centered: true, - icon: , - onOk, - onCancel, - }) - }, - - /** - * 显示批量删除确认对话框 - */ - batchDelete: ({ count, items, onOk, onCancel }) => { - Modal.confirm({ - title: '批量删除确认', - content: ( -
-

您确定要删除选中的 {count} 个项目吗?

-
- {items.map((item, index) => ( -
- {item.name} - {item.info && ( - - ({item.info}) - - )} -
- ))} -
-

- 此操作不可恢复,请谨慎操作! -

-
- ), - okText: '确认删除', - cancelText: '取消', - okType: 'danger', - centered: true, - icon: , - onOk, - onCancel, - }) - }, - - /** - * 显示警告确认对话框 - */ - warning: ({ title, content, okText = '确定', cancelText = '取消', onOk, onCancel }) => { - Modal.confirm({ - title, - content, - okText, - cancelText, - centered: true, - icon: , - onOk, - onCancel, - }) - }, - - /** - * 显示通用确认对话框 - */ - confirm: ({ - title, - content, - okText = '确定', - cancelText = '取消', - okType = 'primary', - onOk, - onCancel, - }) => { - Modal.confirm({ - title, - content, - okText, - cancelText, - okType, - centered: true, - onOk, - onCancel, - }) - }, -} - -export default ConfirmDialog diff --git a/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.css b/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.css deleted file mode 100644 index 32bf54d7..00000000 --- a/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.css +++ /dev/null @@ -1,120 +0,0 @@ -/* 详情抽屉容器 */ -.detail-drawer-content { - height: 100%; - display: flex; - flex-direction: column; -} - -/* 顶部信息区域 - 固定不滚动 */ -.detail-drawer-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 16px 24px; - background: #fafafa; - border-bottom: 1px solid #f0f0f0; - flex-shrink: 0; -} - -.detail-drawer-header-left { - display: flex; - align-items: center; - gap: 16px; -} - -.detail-drawer-close-button { - font-size: 18px; - color: #666; -} - -.detail-drawer-close-button:hover { - color: #1677ff; -} - -.detail-drawer-header-info { - display: flex; - align-items: center; - gap: 12px; -} - -.detail-drawer-title-icon { - font-size: 18px; - color: #1677ff; -} - -.detail-drawer-title { - margin: 0; - font-size: 18px; - font-weight: 600; - color: rgba(0, 0, 0, 0.88); -} - -.detail-drawer-badge { - display: flex; - align-items: center; -} - -.detail-drawer-header-right { - flex: 1; - display: flex; - justify-content: flex-end; -} - -/* 可滚动内容区域 */ -.detail-drawer-scrollable-content { - flex: 1; - overflow-y: auto; - overflow-x: hidden; -} - -/* 标签页区域 */ -.detail-drawer-tabs { - background: #ffffff; - padding-top: 16px; - padding-left: 12px; - min-height: 400px; -} - -.detail-drawer-tabs :global(.ant-tabs) { - height: 100%; -} - -.detail-drawer-tabs :global(.ant-tabs-content-holder) { - overflow: visible; -} - -.detail-drawer-tabs :global(.ant-tabs-nav) { - padding: 0; - margin: 0 24px; - margin-bottom: 0; - background: transparent; -} - -.detail-drawer-tabs :global(.ant-tabs-nav::before) { - border-bottom: 1px solid #f0f0f0; -} - -.detail-drawer-tabs :global(.ant-tabs-tab) { - padding: 12px 0; - margin: 0 32px 0 0; - font-size: 14px; - font-weight: 500; -} - -.detail-drawer-tabs :global(.ant-tabs-tab:first-child) { - margin-left: 0; -} - -.detail-drawer-tabs :global(.ant-tabs-tab-active .ant-tabs-tab-btn) { - color: #d946ef; -} - -.detail-drawer-tabs :global(.ant-tabs-ink-bar) { - background: #d946ef; - height: 3px; -} - -.detail-drawer-tab-content { - padding: 24px; - background: #ffffff; -} diff --git a/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.jsx b/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.jsx deleted file mode 100644 index 2ef0eab3..00000000 --- a/oms_web/oms_web_new/src/components/DetailDrawer/DetailDrawer.jsx +++ /dev/null @@ -1,97 +0,0 @@ -import { Drawer, Button, Space, Tabs } from 'antd' -import { CloseOutlined } from '@ant-design/icons' -import './DetailDrawer.css' - -/** - * 详情抽屉组件 - * @param {Object} props - * @param {boolean} props.visible - 是否显示抽屉 - * @param {Function} props.onClose - 关闭回调 - * @param {Object} props.title - 标题配置 - * @param {string} props.title.text - 标题文本 - * @param {ReactNode} props.title.badge - 状态徽标(可选) - * @param {ReactNode} props.title.icon - 图标(可选) - * @param {Array} props.headerActions - 顶部操作按钮 - * @param {number} props.width - 抽屉宽度 - * @param {ReactNode} props.children - 主要内容 - * @param {Array} props.tabs - 标签页配置(可选) - */ -function DetailDrawer({ - visible, - onClose, - title, - headerActions = [], - width = 1080, - children, - tabs, -}) { - return ( - -
- {/* 顶部标题栏 - 固定不滚动 */} -
-
-
-
- - {headerActions.map((action) => ( - - ))} - -
-
- - {/* 可滚动内容区域 */} -
- {children} - - {/* 可选的标签页区域 */} - {tabs && tabs.length > 0 && ( -
- ({ - key: tab.key, - label: tab.label, - children:
{tab.content}
, - }))} - /> -
- )} -
-
-
- ) -} - -export default DetailDrawer diff --git a/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.css b/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.css deleted file mode 100644 index 0593f3c6..00000000 --- a/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.css +++ /dev/null @@ -1,94 +0,0 @@ -/* 信息面板 */ -.info-panel { - padding: 6px 8px; - background: #ffffff; -} - -/* 信息区域容器 */ -.info-panel > :global(.ant-row) { - padding: 32px; - background: #ffffff; - border-bottom: 1px solid #f0f0f0; -} - -.info-panel-item { - display: flex; - flex-direction: column; - gap: 5px; - padding: 10px 0; - border-bottom: 1px solid #f0f0f0; - transition: all 0.2s ease; - position: relative; -} - -.info-panel-item:last-child { - border-bottom: none; -} - -/* 添加底部装饰条 */ -.info-panel-item::before { - content: ''; - position: absolute; - left: 3px; - bottom: -1px; - width: 0; - height: 3px; - background: linear-gradient(90deg, #1677ff 0%, #4096ff 100%); - border-radius: 2px; - transition: width 0.3s ease; -} - -.info-panel-item:hover { - background: linear-gradient(90deg, #f0f7ff 0%, transparent 100%); - padding-left: 10px; - padding-right: 16px; - margin-left: -12px; - margin-right: -16px; - border-radius: 8px; - border-bottom-color: transparent; -} - -.info-panel-item:hover::before { - width: 60px; -} - -.info-panel-label { - color: rgba(0, 0, 0, 0.45); - font-size: 13px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 1px; - margin-bottom: 4px; -} - -.info-panel-value { - color: rgba(0, 0, 0, 0.88); - font-size: 15px; - font-weight: 500; - word-break: break-all; - line-height: 1.6; -} - -/* 操作按钮区 */ -.info-panel-actions { - padding: 24px 32px; - background: linear-gradient(to bottom, #fafafa 0%, #f5f5f5 100%); - border-top: 2px solid #e8e8e8; - position: relative; -} - -/* 操作区域顶部装饰线 */ -.info-panel-actions::before { - content: ''; - position: absolute; - top: -2px; - left: 0; - right: 0; - height: 2px; - background: linear-gradient(90deg, #1677ff 0%, transparent 50%, #1677ff 100%); - opacity: 0.3; -} - - - - diff --git a/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.jsx b/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.jsx deleted file mode 100644 index c60f2c99..00000000 --- a/oms_web/oms_web_new/src/components/InfoPanel/InfoPanel.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Row, Col, Space, Button } from 'antd' -import './InfoPanel.css' - -/** - * 信息展示面板组件 - * @param {Object} props - * @param {Object} props.data - 数据源 - * @param {Array} props.fields - 字段配置数组 - * @param {Array} props.actions - 操作按钮配置(可选) - * @param {Array} props.gutter - Grid间距配置 - */ -function InfoPanel({ data, fields = [], actions = [], gutter = [24, 16] }) { - if (!data) { - return null - } - - return ( -
- - {fields.map((field) => { - const value = data[field.key] - const displayValue = field.render ? field.render(value, data) : value - - return ( - -
-
{field.label}
-
{displayValue}
-
- - ) - })} -
- - {/* 可选的操作按钮区 */} - {actions && actions.length > 0 && ( -
- - {actions.map((action) => ( - - ))} - -
- )} -
- ) -} - -export default InfoPanel diff --git a/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.css b/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.css deleted file mode 100644 index b1b6fb6e..00000000 --- a/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.css +++ /dev/null @@ -1,49 +0,0 @@ -.list-action-bar { - position: sticky; - top: 0; - z-index: 10; - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 16px; - padding: 16px; - background: #ffffff; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); -} - -.list-action-bar-left, -.list-action-bar-right { - display: flex; - gap: 12px; - align-items: center; -} - -/* 搜索和筛选组合 */ -.list-action-bar-right :global(.ant-space-compact) { - display: flex; -} - -.list-action-bar-right :global(.ant-space-compact .ant-input-search) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.list-action-bar-right :global(.ant-space-compact > .ant-btn) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -/* 响应式 */ -@media (max-width: 768px) { - .list-action-bar { - flex-direction: column; - gap: 12px; - align-items: stretch; - } - - .list-action-bar-left, - .list-action-bar-right { - flex-wrap: wrap; - } -} diff --git a/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.jsx b/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.jsx deleted file mode 100644 index 97c8043f..00000000 --- a/oms_web/oms_web_new/src/components/ListActionBar/ListActionBar.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import { Button, Input, Space, Popover } from 'antd' -import { ReloadOutlined, FilterOutlined } from '@ant-design/icons' -import './ListActionBar.css' - -const { Search } = Input - -/** - * 列表操作栏组件 - * @param {Object} props - * @param {Array} props.actions - 左侧操作按钮配置数组 - * @param {Object} props.search - 搜索配置 - * @param {Object} props.filter - 高级筛选配置(可选) - * @param {boolean} props.showRefresh - 是否显示刷新按钮 - * @param {Function} props.onRefresh - 刷新回调 - */ -function ListActionBar({ - actions = [], - search, - filter, - showRefresh = false, - onRefresh, -}) { - return ( -
- {/* 左侧操作按钮区 */} -
- {actions.map((action) => ( - - ))} -
- - {/* 右侧搜索筛选区 */} -
- - search?.onChange?.(e.target.value)} - value={search?.value} - /> - {filter && ( - - - {filter.title || '高级筛选'} -
- } - trigger="click" - open={filter.visible} - onOpenChange={filter.onVisibleChange} - placement="bottomRight" - overlayClassName="filter-popover" - > - - - )} - - {showRefresh && ( - - )} -
- - ) -} - -export default ListActionBar diff --git a/oms_web/oms_web_new/src/components/ListTable/ListTable.css b/oms_web/oms_web_new/src/components/ListTable/ListTable.css deleted file mode 100644 index 7d967095..00000000 --- a/oms_web/oms_web_new/src/components/ListTable/ListTable.css +++ /dev/null @@ -1,43 +0,0 @@ -/* 列表表格容器 */ -.list-table-container { - background: #ffffff; - border-radius: 8px; - padding: 16px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); -} - -/* 表格行样式 */ -.list-table-container :global(.ant-table-row) { - cursor: pointer; - transition: all 0.3s; -} - -.list-table-container :global(.ant-table-row:hover) { - background: #f5f5f5; -} - -.list-table-container :global(.ant-table-row.row-selected) { - background: #e6f4ff; -} - -/* 操作列样式 - 重新设计 */ -.list-table-container :global(.ant-table-thead > tr > th:last-child) { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; - color: #ffffff !important; - font-weight: 600; - border-left: 2px solid #e8e8e8; -} - -.list-table-container :global(.ant-table-tbody > tr > td:last-child) { - background: #f8f9ff !important; - border-left: 2px solid #e8e8e8; - box-shadow: -2px 0 4px rgba(0, 0, 0, 0.02); -} - -.list-table-container :global(.ant-table-tbody > tr:hover > td:last-child) { - background: #eef0ff !important; -} - -.list-table-container :global(.ant-table-tbody > tr.row-selected > td:last-child) { - background: #e1e6ff !important; -} diff --git a/oms_web/oms_web_new/src/components/ListTable/ListTable.jsx b/oms_web/oms_web_new/src/components/ListTable/ListTable.jsx deleted file mode 100644 index 49bc09fa..00000000 --- a/oms_web/oms_web_new/src/components/ListTable/ListTable.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Table } from 'antd' -import './ListTable.css' - -/** - * 列表表格组件 - * @param {Object} props - * @param {Array} props.columns - 表格列配置 - * @param {Array} props.dataSource - 数据源 - * @param {string} props.rowKey - 行唯一标识字段 - * @param {Array} props.selectedRowKeys - 选中的行 - * @param {Function} props.onSelectionChange - 选择变化回调 - * @param {Object} props.pagination - 分页配置 - * @param {Object} props.scroll - 表格滚动配置 - * @param {Function} props.onRowClick - 行点击回调 - * @param {Object} props.selectedRow - 当前选中的行 - * @param {boolean} props.loading - 加载状态 - * @param {string} props.className - 自定义类名 - */ -function ListTable({ - columns, - dataSource, - rowKey = 'id', - selectedRowKeys = [], - onSelectionChange, - pagination = { - pageSize: 10, - showSizeChanger: true, - showQuickJumper: true, - showTotal: (total) => `共 ${total} 条`, - }, - scroll = { x: 1200 }, - onRowClick, - selectedRow, - loading = false, - className = '', -}) { - // 行选择配置 - const rowSelection = { - selectedRowKeys, - onChange: (newSelectedRowKeys) => { - onSelectionChange?.(newSelectedRowKeys) - }, - } - - return ( -
- ({ - onClick: () => onRowClick?.(record), - className: selectedRow?.[rowKey] === record[rowKey] ? 'row-selected' : '', - })} - /> - - ) -} - -export default ListTable diff --git a/oms_web/oms_web_new/src/components/MainLayout/AppHeader.css b/oms_web/oms_web_new/src/components/MainLayout/AppHeader.css deleted file mode 100644 index 9b18ee4c..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/AppHeader.css +++ /dev/null @@ -1,129 +0,0 @@ -.app-header { - background: #fff; - padding: 0 24px; - display: flex; - align-items: center; - justify-content: space-between; - box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); - height: 64px; - border-bottom: 1px solid #f0f0f0; -} - -/* 左侧区域 */ -.header-left { - display: flex; - align-items: center; - gap: 16px; -} - -/* Logo 区域 */ -.header-logo { - display: flex; - align-items: center; - justify-content: center; - width: 168px; - transition: width 0.2s; -} - -.logo-small { - width: 40px; - height: 40px; - border-radius: 8px; - transition: all 0.2s; -} - -.logo-full { - height: 32px; - width: auto; - transition: all 0.2s; -} - -.trigger { - font-size: 18px; - cursor: pointer; - transition: color 0.3s; - padding: 8px; - border-radius: 4px; - color: rgba(0, 0, 0, 0.65); - display: flex; - align-items: center; -} - -.trigger:hover { - color: #b8178d; - background: rgba(184, 23, 141, 0.06); -} - -/* 右侧区域 */ -.header-right { - display: flex; - align-items: center; - gap: 16px; -} - -.header-search { - border-radius: 16px; -} - -.header-actions { - display: flex; - align-items: center; -} - -.header-icon { - font-size: 16px; - color: rgba(0, 0, 0, 0.65); - cursor: pointer; - transition: all 0.3s; - padding: 8px; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; -} - -.header-icon:hover { - color: #b8178d; - background: rgba(184, 23, 141, 0.06); -} - -.header-link { - font-size: 14px; - color: rgba(0, 0, 0, 0.65); - cursor: pointer; - transition: all 0.3s; - padding: 6px 12px; - border-radius: 4px; - display: flex; - align-items: center; - gap: 4px; -} - -.header-link:hover { - color: #b8178d; - background: rgba(184, 23, 141, 0.06); -} - -.user-info { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: all 0.3s; -} - -.user-info:hover { - background: rgba(184, 23, 141, 0.06); -} - -.username { - font-size: 14px; - color: rgba(0, 0, 0, 0.88); - font-weight: 500; -} - -.ml-1 { - margin-left: 4px; -} diff --git a/oms_web/oms_web_new/src/components/MainLayout/AppHeader.jsx b/oms_web/oms_web_new/src/components/MainLayout/AppHeader.jsx deleted file mode 100644 index 90bb7f2c..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/AppHeader.jsx +++ /dev/null @@ -1,128 +0,0 @@ -import { Layout, Input, Badge, Avatar, Dropdown, Space } from 'antd' -import { useNavigate } from 'react-router-dom' -import { - MenuFoldOutlined, - MenuUnfoldOutlined, - SearchOutlined, - BellOutlined, - QuestionCircleOutlined, - FileTextOutlined, - CustomerServiceOutlined, - UserOutlined, -} from '@ant-design/icons' -import headerMenuData from '../../constants/headerMenuData.json' -import logoFull from '../../assets/logo-full.png' -import './AppHeader.css' - -const { Header } = Layout - -// 图标映射 -const iconMap = { - QuestionCircleOutlined: , - FileTextOutlined: , - CustomerServiceOutlined: , -} - -function AppHeader({ collapsed, onToggle }) { - const navigate = useNavigate() - - // 用户下拉菜单 - const userMenuItems = [ - { - key: 'profile', - label: '个人中心', - }, - { - key: 'settings', - label: '账户设置', - }, - { - type: 'divider', - }, - { - key: 'logout', - label: '退出登录', - }, - ] - - const handleUserMenuClick = ({ key }) => { - if (key === 'logout') { - console.log('退出登录') - } - } - - const handleHeaderMenuClick = (key) => { - console.log('Header menu clicked:', key) - // 如果点击的是设计文档,跳转到文档页面 - if (key === 'docs') { - navigate('/design') - } - } - - return ( -
- {/* 左侧:Logo + 折叠按钮 */} -
- {/* Logo 区域 */} -
- NEX Console -
- - {/* 折叠按钮 */} -
- {collapsed ? : } -
-
- - {/* 右侧:搜索 + 功能按钮 + 用户信息 */} -
- {/* 搜索框 */} - } - style={{ width: 200 }} - /> - - {/* 功能图标 */} - - {/* 动态渲染 header 菜单 */} - {headerMenuData.map((item) => ( -
handleHeaderMenuClick(item.key)} - > - {iconMap[item.icon]} - {item.label} -
- ))} - - {/* 消息中心 */} - -
- -
-
- - {/* 用户下拉菜单 */} - -
- } /> - Admin -
-
-
-
-
- ) -} - -export default AppHeader diff --git a/oms_web/oms_web_new/src/components/MainLayout/AppSider.css b/oms_web/oms_web_new/src/components/MainLayout/AppSider.css deleted file mode 100644 index f4a98aa8..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/AppSider.css +++ /dev/null @@ -1,96 +0,0 @@ -.app-sider { - height: 100%; - overflow: auto; - background: #fafafa; - border-right: 1px solid #f0f0f0; - transition: all 0.2s; -} - -.app-sider::-webkit-scrollbar { - width: 6px; -} - -.app-sider::-webkit-scrollbar-thumb { - background: rgba(0, 0, 0, 0.1); - border-radius: 3px; -} - -.app-sider::-webkit-scrollbar-thumb:hover { - background: rgba(0, 0, 0, 0.2); -} - -/* 菜单样式 */ -.sider-menu { - border-right: none; - padding-top: 8px; - background: #fafafa; -} - -/* 收起状态下的图标放大 */ -:global(.ant-layout-sider-collapsed) .sider-menu :global(.ant-menu-item) { - padding: 0 !important; - display: flex; - align-items: center; - justify-content: center; - height: 56px; - margin: 8px 0; -} - -/* 收起状态下的 SubMenu 样式 */ -:global(.ant-layout-sider-collapsed) .sider-menu :global(.ant-menu-submenu) { - padding: 0 !important; -} - -:global(.ant-layout-sider-collapsed) .sider-menu :global(.ant-menu-submenu-title) { - padding: 0 !important; - display: flex; - align-items: center; - justify-content: center; - height: 56px; - margin: 8px 0; -} - -:global(.ant-layout-sider-collapsed) .sider-menu :global(.anticon) { - font-size: 24px; - margin: 0; -} - -/* 收起状态下的 Tooltip */ -:global(.ant-layout-sider-collapsed) .sider-menu :global(.ant-menu-item-icon) { - font-size: 24px; -} - -:global(.ant-layout-sider-collapsed) .sider-menu :global(.ant-menu-submenu-title) :global(.anticon) { - font-size: 24px; - margin: 0; -} - -/* 菜单项徽章 */ -.menu-item-with-badge { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; -} - -.menu-badge { - font-size: 10px; - height: 18px; - line-height: 18px; - border-radius: 9px; - padding: 0 6px; - margin-left: 8px; -} - -.badge-hot :global(.ant-badge-count) { - background: #ff4d4f; -} - -.badge-new :global(.ant-badge-count) { - background: #52c41a; -} - -/* 收起状态下隐藏徽章 */ -:global(.ant-layout-sider-collapsed) .menu-badge { - display: none; -} diff --git a/oms_web/oms_web_new/src/components/MainLayout/AppSider.jsx b/oms_web/oms_web_new/src/components/MainLayout/AppSider.jsx deleted file mode 100644 index 6e33b606..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/AppSider.jsx +++ /dev/null @@ -1,172 +0,0 @@ -import { useState, useEffect } from 'react' -import { Layout, Menu, Badge, Tooltip } from 'antd' -import { useNavigate, useLocation } from 'react-router-dom' -import { - DashboardOutlined, - GlobalOutlined, - CloudServerOutlined, - UserOutlined, - AppstoreOutlined, - SettingOutlined, -} from '@ant-design/icons' -import menuData from '../../constants/menuData.json' -import './AppSider.css' - -const { Sider } = Layout -const { SubMenu } = Menu - -// 图标映射 -const iconMap = { - DashboardOutlined: DashboardOutlined, - GlobalOutlined: GlobalOutlined, - CloudServerOutlined: CloudServerOutlined, - UserOutlined: UserOutlined, - AppstoreOutlined: AppstoreOutlined, - SettingOutlined: SettingOutlined, -} - -function AppSider({ collapsed, onToggle }) { - const navigate = useNavigate() - const location = useLocation() - const [openKeys, setOpenKeys] = useState([]) - - // 根据当前路径获取应该打开的父菜单 - const getDefaultOpenKeys = () => { - const path = location.pathname - for (const item of menuData) { - if (item.children) { - const hasChild = item.children.some((c) => c.path === path) - if (hasChild) { - return [item.key] - } - } - } - return [] - } - - // 监听路径变化和收拢状态,自动打开父菜单 - useEffect(() => { - if (!collapsed) { - const defaultKeys = getDefaultOpenKeys() - setOpenKeys(defaultKeys) - } - }, [location.pathname, collapsed]) - - const handleMenuClick = ({ key }) => { - // 查找对应的路径 - for (const item of menuData) { - if (item.key === key && item.path) { - navigate(item.path) - return - } - if (item.children) { - const child = item.children.find((c) => c.key === key) - if (child) { - navigate(child.path) - return - } - } - } - } - - const handleOpenChange = (keys) => { - setOpenKeys(keys) - } - - // 获取当前选中的菜单项 - const getSelectedKey = () => { - const path = location.pathname - for (const item of menuData) { - if (item.path === path) return item.key - if (item.children) { - const child = item.children.find((c) => c.path === path) - if (child) return child.key - } - } - return 'overview' - } - - // 渲染菜单项 - const renderMenuItems = () => { - return menuData.map((item) => { - const IconComponent = iconMap[item.icon] - const icon = IconComponent ? : null - - // 如果有子菜单 - if (item.children) { - // 在收拢状态下,用 Tooltip 包装 SubMenu 的图标 - const subMenuIcon = collapsed ? ( - - {icon} - - ) : ( - icon - ) - - return ( - - {item.children.map((child) => ( - - {child.badge ? ( - - {child.label} - - - ) : ( - child.label - )} - - ))} - - ) - } - - // 普通菜单项 - 也用 Tooltip 包装 - const menuIcon = collapsed ? ( - - {icon} - - ) : ( - icon - ) - - return ( - - {item.label} - - ) - }) - } - - return ( - - {/* 菜单 */} - - {renderMenuItems()} - - - ) -} - -export default AppSider diff --git a/oms_web/oms_web_new/src/components/MainLayout/MainLayout.css b/oms_web/oms_web_new/src/components/MainLayout/MainLayout.css deleted file mode 100644 index 386f3ff6..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/MainLayout.css +++ /dev/null @@ -1,24 +0,0 @@ -.main-layout { - min-height: 100vh; - display: flex; - flex-direction: column; - background: #fafafa; -} - -.main-content-wrapper { - display: flex; - flex: 1; - height: calc(100vh - 64px); - background: #fafafa; -} - -.main-content { - background: #f5f5f5; - overflow-y: auto; - flex: 1; -} - -.content-wrapper { - padding: 24px; - min-height: 100%; -} diff --git a/oms_web/oms_web_new/src/components/MainLayout/MainLayout.jsx b/oms_web/oms_web_new/src/components/MainLayout/MainLayout.jsx deleted file mode 100644 index 2c4ea0b2..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/MainLayout.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useState } from 'react' -import { Layout } from 'antd' -import AppSider from './AppSider' -import AppHeader from './AppHeader' -import './MainLayout.css' - -const { Content } = Layout - -function MainLayout({ children }) { - const [collapsed, setCollapsed] = useState(false) - - const toggleCollapsed = () => { - setCollapsed(!collapsed) - } - - return ( - - - - - -
- {children} -
-
-
-
- ) -} - -export default MainLayout diff --git a/oms_web/oms_web_new/src/components/MainLayout/index.js b/oms_web/oms_web_new/src/components/MainLayout/index.js deleted file mode 100644 index 12555fdd..00000000 --- a/oms_web/oms_web_new/src/components/MainLayout/index.js +++ /dev/null @@ -1,4 +0,0 @@ -export { default } from './MainLayout' -export { default as MainLayout } from './MainLayout' -export { default as AppSider } from './AppSider' -export { default as AppHeader } from './AppHeader' diff --git a/oms_web/oms_web_new/src/components/PageHeader/PageHeader.css b/oms_web/oms_web_new/src/components/PageHeader/PageHeader.css deleted file mode 100644 index 6ba9202e..00000000 --- a/oms_web/oms_web_new/src/components/PageHeader/PageHeader.css +++ /dev/null @@ -1,109 +0,0 @@ -.page-header-standard { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border-radius: 12px; - padding: 24px 28px; - margin-bottom: 24px; - display: flex; - justify-content: space-between; - align-items: center; - box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15); - position: relative; - overflow: hidden; -} - -.page-header-standard::before { - content: ''; - position: absolute; - top: -50%; - right: -10%; - width: 300px; - height: 300px; - background: rgba(255, 255, 255, 0.1); - border-radius: 50%; -} - -.page-header-main { - display: flex; - align-items: center; - gap: 16px; - position: relative; - z-index: 1; -} - -.back-button { - width: 36px; - height: 36px; - border-radius: 8px; - background: rgba(255, 255, 255, 0.2); - border: 1px solid rgba(255, 255, 255, 0.3); - color: #ffffff; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s; - font-size: 16px; -} - -.back-button:hover { - background: rgba(255, 255, 255, 0.3); - transform: translateX(-2px); -} - -.page-header-content { - display: flex; - align-items: center; - gap: 16px; -} - -.page-header-icon { - width: 48px; - height: 48px; - border-radius: 12px; - background: rgba(255, 255, 255, 0.2); - backdrop-filter: blur(10px); - display: flex; - align-items: center; - justify-content: center; - font-size: 24px; - color: #ffffff; - border: 1px solid rgba(255, 255, 255, 0.3); -} - -.page-header-text { - display: flex; - flex-direction: column; - gap: 4px; -} - -.page-header-title { - font-size: 22px; - font-weight: 600; - color: #ffffff; - margin: 0; - letter-spacing: 0.3px; -} - -.page-header-description { - font-size: 14px; - color: rgba(255, 255, 255, 0.9); - margin: 0; - line-height: 1.5; -} - -.page-header-extra { - position: relative; - z-index: 1; -} - -@media (max-width: 768px) { - .page-header-standard { - flex-direction: column; - align-items: flex-start; - gap: 16px; - } - - .page-header-extra { - width: 100%; - } -} diff --git a/oms_web/oms_web_new/src/components/PageHeader/PageHeader.jsx b/oms_web/oms_web_new/src/components/PageHeader/PageHeader.jsx deleted file mode 100644 index b934376d..00000000 --- a/oms_web/oms_web_new/src/components/PageHeader/PageHeader.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ArrowLeftOutlined } from '@ant-design/icons' -import './PageHeader.css' - -function PageHeader({ - title, - description, - icon, - showBack = false, - onBack, - extra -}) { - return ( -
-
- {showBack && ( - - )} -
- {icon &&
{icon}
} -
-

{title}

- {description && ( -

{description}

- )} -
-
-
- {extra &&
{extra}
} -
- ) -} - -export default PageHeader diff --git a/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.css b/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.css deleted file mode 100644 index 9913e326..00000000 --- a/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.css +++ /dev/null @@ -1,165 +0,0 @@ -.page-title-bar { - background: linear-gradient(135deg, #e0e7ff 0%, #f3e8ff 100%); - border-radius: 12px; - padding: 16px 24px; - margin-bottom: 16px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); - position: relative; - overflow: hidden; - border: 1px solid rgba(139, 92, 246, 0.1); -} - -.page-title-bar::before { - content: ''; - position: absolute; - top: -50%; - right: -5%; - width: 200px; - height: 200px; - background: rgba(139, 92, 246, 0.05); - border-radius: 50%; -} - -.title-bar-content { - position: relative; - z-index: 1; - display: flex; - justify-content: space-between; - align-items: center; -} - -.title-bar-left { - flex: 1; -} - -.title-row { - display: flex; - align-items: center; - gap: 16px; -} - -.title-group { - display: flex; - align-items: center; - gap: 12px; -} - -.page-title { - font-size: 20px; - font-weight: 600; - color: #1e293b; - margin: 0; - letter-spacing: 0.3px; -} - -.title-badge { - background: rgba(139, 92, 246, 0.15); - color: #7c3aed; - padding: 2px 10px; - border-radius: 10px; - font-size: 12px; - font-weight: 500; -} - -.page-description { - font-size: 13px; - color: #64748b; - margin: 0; - white-space: nowrap; -} - -.title-bar-right { - display: flex; - align-items: center; - gap: 12px; -} - -.title-actions { - display: flex; - gap: 10px; -} - -.title-actions button { - padding: 8px 16px; - border-radius: 6px; - font-size: 13px; - font-weight: 500; - cursor: pointer; - transition: all 0.3s; - border: none; - outline: none; -} - -.title-actions button.primary { - background: #7c3aed; - color: #ffffff; -} - -.title-actions button.primary:hover { - background: #6d28d9; - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(124, 58, 237, 0.25); -} - -.title-actions button.secondary { - background: rgba(139, 92, 246, 0.1); - color: #7c3aed; - border: 1px solid rgba(139, 92, 246, 0.2); -} - -.title-actions button.secondary:hover { - background: rgba(139, 92, 246, 0.15); - transform: translateY(-1px); -} - -.toggle-button { - width: 32px; - height: 32px; - border-radius: 6px; - background: rgba(139, 92, 246, 0.1); - border: 1px solid rgba(139, 92, 246, 0.2); - color: #7c3aed; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s; - font-size: 14px; -} - -.toggle-button:hover { - background: rgba(139, 92, 246, 0.2); - transform: translateY(-1px); -} - -/* 响应式适配 */ -@media (max-width: 768px) { - .title-bar-content { - flex-direction: column; - align-items: flex-start; - gap: 12px; - } - - .title-row { - flex-direction: column; - align-items: flex-start; - gap: 4px; - } - - .page-description { - white-space: normal; - } - - .title-bar-right { - width: 100%; - justify-content: space-between; - } - - .title-actions { - flex: 1; - } - - .title-actions button { - flex: 1; - } -} diff --git a/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.jsx b/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.jsx deleted file mode 100644 index 870b861c..00000000 --- a/oms_web/oms_web_new/src/components/PageTitleBar/PageTitleBar.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useState } from 'react' -import { UpOutlined, DownOutlined } from '@ant-design/icons' -import './PageTitleBar.css' - -function PageTitleBar({ - title, - badge, - description, - actions, - showToggle = false, - onToggle, - defaultExpanded = true, -}) { - const [expanded, setExpanded] = useState(defaultExpanded) - - const handleToggle = () => { - const newExpanded = !expanded - setExpanded(newExpanded) - if (onToggle) { - onToggle(newExpanded) - } - } - - return ( -
-
-
-
-
-

{title}

- {badge && {badge}} -
- {description &&

{description}

} -
-
-
- {actions &&
{actions}
} - {showToggle && ( - - )} -
-
-
- ) -} - -export default PageTitleBar diff --git a/oms_web/oms_web_new/src/components/Toast/Toast.jsx b/oms_web/oms_web_new/src/components/Toast/Toast.jsx deleted file mode 100644 index 94862e33..00000000 --- a/oms_web/oms_web_new/src/components/Toast/Toast.jsx +++ /dev/null @@ -1,114 +0,0 @@ -import { notification } from 'antd' -import { - CheckCircleOutlined, - CloseCircleOutlined, - ExclamationCircleOutlined, - InfoCircleOutlined, -} from '@ant-design/icons' - -// 配置全局通知位置和样式 -notification.config({ - placement: 'topRight', - top: 24, - duration: 3, - maxCount: 3, -}) - -/** - * 标准通知反馈组件 - * 从右上角滑出,默认3秒后消失 - */ -const Toast = { - /** - * 成功通知 - * @param {string} message - 消息内容 - * @param {string} description - 详细描述(可选) - * @param {number} duration - 显示时长(秒),默认3秒 - */ - success: (message, description = '', duration = 3) => { - notification.success({ - message, - description, - duration, - icon: , - style: { - borderRadius: '8px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', - }, - }) - }, - - /** - * 错误通知 - * @param {string} message - 消息内容 - * @param {string} description - 详细描述(可选) - * @param {number} duration - 显示时长(秒),默认3秒 - */ - error: (message, description = '', duration = 3) => { - notification.error({ - message, - description, - duration, - icon: , - style: { - borderRadius: '8px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', - }, - }) - }, - - /** - * 警告通知 - * @param {string} message - 消息内容 - * @param {string} description - 详细描述(可选) - * @param {number} duration - 显示时长(秒),默认3秒 - */ - warning: (message, description = '', duration = 3) => { - notification.warning({ - message, - description, - duration, - icon: , - style: { - borderRadius: '8px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', - }, - }) - }, - - /** - * 信息通知 - * @param {string} message - 消息内容 - * @param {string} description - 详细描述(可选) - * @param {number} duration - 显示时长(秒),默认3秒 - */ - info: (message, description = '', duration = 3) => { - notification.info({ - message, - description, - duration, - icon: , - style: { - borderRadius: '8px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', - }, - }) - }, - - /** - * 自定义通知 - * @param {Object} config - 完整的通知配置对象 - */ - custom: (config) => { - notification.open({ - ...config, - style: { - borderRadius: '8px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)', - ...config.style, - }, - }) - }, -} - -export default Toast diff --git a/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.css b/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.css deleted file mode 100644 index fd6341ce..00000000 --- a/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.css +++ /dev/null @@ -1,58 +0,0 @@ -/* 树形筛选面板 */ -.tree-filter-panel { - width: 320px; - max-height: 500px; - overflow-y: auto; -} - -/* 已选择的筛选条件 */ -.tree-filter-selected { - min-height: 40px; - padding: 12px; - background: #f5f7fa; - border-radius: 6px; - border: 1px dashed #d9d9d9; -} - -.tree-filter-tag { - display: flex; - align-items: center; - gap: 8px; -} - -.tree-filter-label { - font-size: 13px; - color: rgba(0, 0, 0, 0.65); - font-weight: 500; -} - -.tree-filter-placeholder { - display: flex; - align-items: center; - justify-content: center; - min-height: 24px; -} - -.tree-filter-placeholder span { - color: #8c8c8c; - font-size: 13px; -} - -/* 树形选择器容器 */ -.tree-filter-container { - max-height: 280px; - overflow-y: auto; -} - -.tree-filter-header { - font-size: 14px; - font-weight: 500; - margin-bottom: 12px; - color: rgba(0, 0, 0, 0.85); -} - -/* 操作按钮 */ -.tree-filter-actions { - display: flex; - justify-content: flex-end; -} diff --git a/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.jsx b/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.jsx deleted file mode 100644 index 2723c226..00000000 --- a/oms_web/oms_web_new/src/components/TreeFilterPanel/TreeFilterPanel.jsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Tree, Tag, Divider, Button, Space } from 'antd' -import { useState, useEffect } from 'react' -import './TreeFilterPanel.css' - -/** - * 树形筛选面板组件 - * @param {Object} props - * @param {Array} props.treeData - 树形数据 - * @param {string} props.selectedKey - 当前选中的节点ID - * @param {string} props.tempSelectedKey - 临时选中的节点ID(确认前) - * @param {string} props.treeTitle - 树标题 - * @param {Function} props.onSelect - 选择变化回调 - * @param {Function} props.onConfirm - 确认筛选 - * @param {Function} props.onClear - 清除筛选 - * @param {string} props.placeholder - 占位提示文本 - */ -function TreeFilterPanel({ - treeData, - selectedKey, - tempSelectedKey, - treeTitle = '分组筛选', - onSelect, - onConfirm, - onClear, - placeholder = '请选择分组进行筛选', -}) { - // 获取所有节点的key用于默认展开 - const getAllKeys = (nodes) => { - let keys = [] - const traverse = (node) => { - keys.push(node.key) - if (node.children) { - node.children.forEach(traverse) - } - } - nodes.forEach(traverse) - return keys - } - - const [expandedKeys, setExpandedKeys] = useState([]) - - // 初始化时展开所有节点 - useEffect(() => { - if (treeData && treeData.length > 0) { - setExpandedKeys(getAllKeys(treeData)) - } - }, [treeData]) - - // 查找节点名称 - const findNodeName = (nodes, id) => { - for (const node of nodes) { - if (node.key === id) return node.title - if (node.children) { - const found = findNodeName(node.children, id) - if (found) return found - } - } - return '' - } - - const handleTreeSelect = (selectedKeys) => { - const key = selectedKeys[0] || null - onSelect?.(key) - } - - const handleExpand = (keys) => { - setExpandedKeys(keys) - } - - return ( -
- {/* 已选择的筛选条件 */} -
- {tempSelectedKey ? ( -
- 已选择分组: - onSelect?.(null)}> - {findNodeName(treeData, tempSelectedKey)} - -
- ) : ( -
- {placeholder} -
- )} -
- - - - {/* 树形选择器 */} -
-
{treeTitle}
- -
- - - - {/* 操作按钮 */} -
- - - - -
-
- ) -} - -export default TreeFilterPanel diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/vue/VueStockController.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/vue/VueStockController.java new file mode 100644 index 00000000..bfc7a00c --- /dev/null +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/vue/VueStockController.java @@ -0,0 +1,91 @@ +package com.ruoyi.sip.controller.vue; + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.sip.domain.OmsStockInfo; +import com.ruoyi.sip.service.IOmsStockInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + +/** + * @Author ch + * @Desc 备货信息(OmsStockInfo)表Vue控制器 + * @Date 2025-10-16 09:43:37 + */ +@RestController +@RequestMapping("/stock/vue") +public class VueStockController extends BaseController { + + @Autowired + private IOmsStockInfoService omsStockInfoService; + + /** + * 查询备货信息列表 + */ + @GetMapping("/list") + public TableDataInfo list(OmsStockInfo omsStockInfo) { + startPage(); + List list = omsStockInfoService.queryAll(omsStockInfo); + return getDataTable(list); + } + + /** + * 获取备货信息详细信息 + */ + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Integer id) { + return AjaxResult.success(omsStockInfoService.queryById(id)); + } + + /** + * 新增备货信息 + */ + @PostMapping + public AjaxResult add(@RequestBody OmsStockInfo omsStockInfo) { + return toAjax(omsStockInfoService.insert(omsStockInfo)); + } + + /** + * 修改备货信息 + */ + @PutMapping + @Log(title = "备货管理", businessType = BusinessType.UPDATE) + public AjaxResult edit(@RequestBody OmsStockInfo omsStockInfo) { + return toAjax(omsStockInfoService.update(omsStockInfo)); + } + + /** + * 删除备货信息 + */ + @DeleteMapping("/{ids}") + @Log(title = "备货管理", businessType = BusinessType.DELETE) + public AjaxResult remove(@PathVariable String ids) { + return toAjax(omsStockInfoService.batchRemove(ids.split(","))); + } + + /** + * 导出备货信息 + */ + @PostMapping("/export") + @Log(title = "备货管理", businessType = BusinessType.EXPORT) + public void export(OmsStockInfo omsStockInfo, HttpServletResponse response) throws IOException { + // This is a placeholder for actual Excel export logic. + // In a real project, this would typically involve using a utility class like ExcelUtil + // to write the list of OmsStockInfo objects to an Excel file and send it as a response. + List list = omsStockInfoService.queryAll(omsStockInfo); + // Example: + // ExcelUtil util = new ExcelUtil(OmsStockInfo.class); + // util.exportExcel(response, list, "StockData"); + System.out.println("Export functionality called for OmsStockInfo with " + list.size() + " items."); + // A minimal response to avoid client timeout/error if no actual file is written. + response.setContentType("text/plain"); + response.getWriter().write("Export command received. Check server logs for details."); + } +}