refactor: 重构后端目录结构和命名规范
- 将后端目录名从大写改为小写 (Controller->controller 等) - 将命名空间从 App\ 改为 app\ (符合 webman 官方规范) - 移除不必要的 bootstrap 目录 - 完善出差审批业务功能: - 添加删除草稿功能 - 添加审批操作功能(同意/拒绝) - 完善审批详情页,显示审批人和审批记录 - 前端优化: - 调整列表页行高 - 隐藏底部导航栏 - 仪表盘只显示3个快捷入口 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Toast } from 'antd-mobile'
|
||||
import { showLanguageSwitcher } from '@/components/LanguageSwitcher'
|
||||
import styles from './dashboard.module.css'
|
||||
|
||||
@@ -10,40 +11,23 @@ interface QuickAction {
|
||||
label: string
|
||||
path: string
|
||||
color: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
// 从应用页面迁移的完整应用列表
|
||||
const quickActions: QuickAction[] = [
|
||||
{ id: '1', icon: '✈️', label: '出差申请', path: '/business-trip/apply', color: '#1677ff' },
|
||||
{ id: '2', icon: '📝', label: '采购申请', path: '/purchase/apply', color: '#52c41a' },
|
||||
{ id: '3', icon: '🏠', label: '会议室', path: '/meeting-room', color: '#faad14' },
|
||||
{ id: '4', icon: '📅', label: '日程管理', path: '/schedule', color: '#722ed1' },
|
||||
{ id: '5', icon: '💰', label: '报销申请', path: '/expense/apply', color: '#eb2f96' },
|
||||
{ id: '6', icon: '📋', label: '请假申请', path: '/leave/apply', color: '#13c2c2' },
|
||||
]
|
||||
|
||||
interface TodoItem {
|
||||
id: string
|
||||
title: string
|
||||
type: 'approval' | 'notice' | 'task'
|
||||
time: string
|
||||
}
|
||||
|
||||
const mockTodos: TodoItem[] = [
|
||||
{ id: '1', title: '张三的出差申请待审批', type: 'approval', time: '10分钟前' },
|
||||
{ id: '2', title: '本周部门会议', type: 'task', time: '今天 14:00' },
|
||||
]
|
||||
|
||||
interface StatCard {
|
||||
title: string
|
||||
value: number
|
||||
unit: string
|
||||
color: string
|
||||
}
|
||||
|
||||
const mockStats: StatCard[] = [
|
||||
{ title: '待审批', value: 5, unit: '条', color: '#ff4d4f' },
|
||||
{ title: '已审批', value: 12, unit: '条', color: '#52c41a' },
|
||||
{ title: '我发起', value: 8, unit: '条', color: '#1677ff' },
|
||||
{ id: '1', icon: '✈️', label: '出差申请', path: '/business-trip/apply', color: '#1677ff', description: '提交出差申请' },
|
||||
{ id: '2', icon: '📝', label: '采购申请', path: '/purchase/apply', color: '#52c41a', description: '物品采购审批' },
|
||||
{ id: '3', icon: '📦', label: '备货录入', path: '/stock/entry', color: '#faad14', description: '备货信息录入' },
|
||||
{ id: '4', icon: '📅', label: '日程管理', path: '/schedule', color: '#722ed1', description: '个人日程安排' },
|
||||
{ id: '5', icon: '💰', label: '报销申请', path: '/expense/apply', color: '#eb2f96', description: '费用报销审批' },
|
||||
{ id: '6', icon: '📋', label: '请假申请', path: '/leave/apply', color: '#13c2c2', description: '请假审批' },
|
||||
{ id: '7', icon: '🚗', label: '用车申请', path: '/car/apply', color: '#f759ab', description: '公车使用申请' },
|
||||
{ id: '8', icon: '🎁', label: '礼品申请', path: '/gift/apply', color: '#ff7a45', description: '礼品采购申请' },
|
||||
{ id: '9', icon: '📊', label: '数据报表', path: '/reports', color: '#1890ff', description: '业务数据统计' },
|
||||
{ id: '10', icon: '👥', label: '通讯录', path: '/contacts', color: '#096dd9', description: '内部通讯录' },
|
||||
{ id: '11', icon: '📁', label: '文件中心', path: '/files', color: '#595959', description: '文件共享管理' },
|
||||
{ id: '12', icon: '⚙️', label: '系统设置', path: '/settings', color: '#8c8c8c', description: '系统偏好设置' },
|
||||
]
|
||||
|
||||
export default function Dashboard() {
|
||||
@@ -52,7 +36,13 @@ export default function Dashboard() {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const handleQuickAction = (action: QuickAction) => {
|
||||
navigate(action.path)
|
||||
// 允许的应用:出差申请、审批
|
||||
const allowedPaths = ['/business-trip/apply', '/business-trip']
|
||||
if (allowedPaths.includes(action.path)) {
|
||||
navigate(action.path)
|
||||
} else {
|
||||
Toast.show({ content: '功能开发中...', duration: 1500 })
|
||||
}
|
||||
}
|
||||
|
||||
const getCurrentLanguage = () => {
|
||||
@@ -83,59 +73,18 @@ export default function Dashboard() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 数据统计卡片 */}
|
||||
<div className={styles.section}>
|
||||
<h3 className={styles.sectionTitle}>数据概览</h3>
|
||||
<div className={styles.statsGrid}>
|
||||
{mockStats.map((stat) => (
|
||||
<div key={stat.title} className={styles.statCard} style={{ borderTop: `3px solid ${stat.color}` }}>
|
||||
<div className={styles.statValue}>{stat.value}</div>
|
||||
<div className={styles.statTitle}>{stat.title}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 待办事项 */}
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<h3 className={styles.sectionTitle}>待办事项</h3>
|
||||
<span className={styles.more}>查看全部 {'>'}</span>
|
||||
</div>
|
||||
{mockTodos.length > 0 ? (
|
||||
<div className={styles.todoList}>
|
||||
{mockTodos.map((todo) => (
|
||||
<div key={todo.id} className={styles.todoItem} onClick={() => navigate('/approval/pending')}>
|
||||
<div className={styles.todoIcon}>
|
||||
{todo.type === 'approval' && '📋'}
|
||||
{todo.type === 'notice' && '🔔'}
|
||||
{todo.type === 'task' && '✓'}
|
||||
</div>
|
||||
<div className={styles.todoContent}>
|
||||
<div className={styles.todoTitle}>{todo.title}</div>
|
||||
<div className={styles.todoTime}>{todo.time}</div>
|
||||
</div>
|
||||
<div className={styles.todoArrow}>{'>'}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.empty}>暂无待办事项</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 快捷入口 */}
|
||||
<div className={styles.section}>
|
||||
<h3 className={styles.sectionTitle}>快捷入口</h3>
|
||||
<div className={styles.actionGrid}>
|
||||
{quickActions.map((action) => (
|
||||
{quickActions.slice(0, 3).map((action) => (
|
||||
<div
|
||||
key={action.id}
|
||||
className={styles.actionCard}
|
||||
onClick={() => handleQuickAction(action)}
|
||||
>
|
||||
<div className={styles.actionIcon} style={{ backgroundColor: `${action.color}15` }}>
|
||||
<span style={{ fontSize: 28 }}>{action.icon}</span>
|
||||
<span style={{ fontSize: 32 }}>{action.icon}</span>
|
||||
</div>
|
||||
<span className={styles.actionLabel}>{action.label}</span>
|
||||
</div>
|
||||
@@ -143,26 +92,27 @@ export default function Dashboard() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 最新动态 */}
|
||||
{/* 所有应用 */}
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<h3 className={styles.sectionTitle}>最新动态</h3>
|
||||
<span className={styles.more}>更多 {'>'}</span>
|
||||
</div>
|
||||
<div className={styles.activityList}>
|
||||
<div className={styles.activityItem}>
|
||||
<div className={styles.activityDot}></div>
|
||||
<div className={styles.activityContent}>
|
||||
<div>张三 提交了出差申请</div>
|
||||
<div className={styles.activityTime}>10分钟前</div>
|
||||
<h3 className={styles.sectionTitle}>所有应用</h3>
|
||||
<div className={styles.actionGrid}>
|
||||
<div className={styles.actionCard} onClick={() => navigate('/business-trip')}>
|
||||
<div className={styles.actionIcon} style={{ backgroundColor: '#1677ff15' }}>
|
||||
<span style={{ fontSize: 32 }}>✍️</span>
|
||||
</div>
|
||||
<span className={styles.actionLabel}>审批</span>
|
||||
</div>
|
||||
<div className={styles.activityItem}>
|
||||
<div className={styles.activityDot}></div>
|
||||
<div className={styles.activityContent}>
|
||||
<div>李四 审批通过了采购申请</div>
|
||||
<div className={styles.activityTime}>1小时前</div>
|
||||
<div className={styles.actionCard} onClick={() => handleQuickAction(quickActions[8])}>
|
||||
<div className={styles.actionIcon} style={{ backgroundColor: `${quickActions[8].color}15` }}>
|
||||
<span style={{ fontSize: 32 }}>{quickActions[8].icon}</span>
|
||||
</div>
|
||||
<span className={styles.actionLabel}>{quickActions[8].label}</span>
|
||||
</div>
|
||||
<div className={styles.actionCard} onClick={() => handleQuickAction(quickActions[11])}>
|
||||
<div className={styles.actionIcon} style={{ backgroundColor: `${quickActions[11].color}15` }}>
|
||||
<span style={{ fontSize: 32 }}>{quickActions[11].icon}</span>
|
||||
</div>
|
||||
<span className={styles.actionLabel}>{quickActions[11].label}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user