Initial commit: X-Server Mobile enterprise tool system

- Frontend: React 18 + TypeScript + Vite + Ant Design Mobile
- Backend: PHP 8.5 + Webman 2.x + MySQL + Redis
- i18n support: Chinese, English, Russian, Spanish, French
- Approval workflow engine
- Docker development environment
- Feishu integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-24 17:57:25 +08:00
commit 8d78e18267
121 changed files with 18563 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
.apps {
min-height: 100vh;
padding: 16px;
padding-bottom: calc(16px + env(safe-area-inset-bottom));
background: #f5f5f5;
}
.header {
margin-bottom: 20px;
padding: 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
color: #fff;
}
.header h1 {
margin: 0 0 4px 0;
font-size: 20px;
font-weight: 600;
}
.header p {
margin: 0;
font-size: 13px;
opacity: 0.9;
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.appCard {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 16px 8px;
background: #fff;
border-radius: 12px;
cursor: pointer;
transition: all 0.2s;
}
.appCard:active {
transform: scale(0.95);
background: #fafafa;
}
.appIcon {
width: 56px;
height: 56px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
}
.appInfo {
text-align: center;
}
.appLabel {
display: block;
font-size: 13px;
color: #262626;
font-weight: 500;
}
.appDesc {
display: block;
font-size: 11px;
color: #8c8c8c;
margin-top: 2px;
}
.safeArea {
height: 16px;
}
+64
View File
@@ -0,0 +1,64 @@
import styles from './apps.module.css'
interface AppItem {
id: string
icon: string
label: string
path: string
color: string
description?: string
}
const apps: AppItem[] = [
{ 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: '/meeting-room', 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 Apps() {
const handleAppClick = (app: AppItem) => {
// TODO: 跳转到应用页面
console.log('点击应用:', app)
}
return (
<div className={styles.apps}>
<div className={styles.header}>
<h1>应用中心</h1>
<p>选择你需要的功能</p>
</div>
<div className={styles.grid}>
{apps.map((app) => (
<div
key={app.id}
className={styles.appCard}
onClick={() => handleAppClick(app)}
>
<div className={styles.appIcon} style={{ backgroundColor: `${app.color}15` }}>
<span style={{ fontSize: 32, color: app.color }}>{app.icon}</span>
</div>
<div className={styles.appInfo}>
<span className={styles.appLabel}>{app.label}</span>
{app.description && (
<span className={styles.appDesc}>{app.description}</span>
)}
</div>
</div>
))}
</div>
{/* 底部安全区域 */}
<div className={styles.safeArea} />
</div>
)
}