Initial commit: Car Maintenance Management System
Author: Yang Lu School: Liaoning Institute of Science and Technology Major: Computer Science and Technology Class: BZ246 Tech Stack: - Backend: Spring Boot 2.7.18 + JPA + MySQL - Frontend: HTML5 + CSS3 + JavaScript Features: - User Management (Admin/Staff/Customer roles) - Vehicle Archive Management - Service Order Management - Parts Inventory Management - Online Appointment Service - Data Statistics and Analysis Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
270
frontend/staff/dashboard.html
Normal file
270
frontend/staff/dashboard.html
Normal file
@@ -0,0 +1,270 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>工作人员仪表板 - 车管家4S店车辆维保管理系统</title>
|
||||
<link rel="stylesheet" href="../css/common.css">
|
||||
<link rel="stylesheet" href="../css/dashboard.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="dashboard-container">
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h2>车管家系统</h2>
|
||||
<p>工作人员控制台</p>
|
||||
</div>
|
||||
<div class="sidebar-menu">
|
||||
<div class="menu-item active" onclick="showSection('overview')">
|
||||
<span class="menu-icon">📊</span>
|
||||
<span>工作概览</span>
|
||||
</div>
|
||||
<div class="menu-item" onclick="showSection('myorders')">
|
||||
<span class="menu-icon">📋</span>
|
||||
<span>我的工单</span>
|
||||
</div>
|
||||
<div class="menu-item" onclick="showSection('vehicles')">
|
||||
<span class="menu-icon">🚗</span>
|
||||
<span>车辆查询</span>
|
||||
</div>
|
||||
<div class="menu-item" onclick="showSection('parts')">
|
||||
<span class="menu-icon">🔧</span>
|
||||
<span>配件查询</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<div class="top-nav">
|
||||
<div class="top-nav-left">
|
||||
<h1>工作人员仪表板</h1>
|
||||
</div>
|
||||
<div class="top-nav-right">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar" id="userAvatar">S</div>
|
||||
<span class="user-name" id="userName">工作人员</span>
|
||||
</div>
|
||||
<button class="btn-logout" onclick="utils.logout()">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="overview-section" class="section">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon blue">📋</div>
|
||||
<div class="stat-info">
|
||||
<h3 id="myOrdersCount">0</h3>
|
||||
<p>我的工单</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon orange">⏳</div>
|
||||
<div class="stat-info">
|
||||
<h3 id="inProgressCount">0</h3>
|
||||
<p>进行中</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon green">✅</div>
|
||||
<div class="stat-info">
|
||||
<h3 id="completedCount">0</h3>
|
||||
<p>已完成</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card">
|
||||
<div class="content-header">
|
||||
<h2>待处理工单</h2>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>工单编号</th>
|
||||
<th>服务类型</th>
|
||||
<th>车牌号</th>
|
||||
<th>状态</th>
|
||||
<th>预约时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="pendingOrdersBody">
|
||||
<tr><td colspan="6" class="empty-state">暂无待处理工单</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="myorders-section" class="section" style="display: none;">
|
||||
<div class="content-card">
|
||||
<div class="content-header">
|
||||
<h2>我的工单列表</h2>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>工单编号</th>
|
||||
<th>服务类型</th>
|
||||
<th>车牌号</th>
|
||||
<th>客户姓名</th>
|
||||
<th>状态</th>
|
||||
<th>创建时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="myOrdersBody">
|
||||
<tr><td colspan="7" class="empty-state">加载中...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="vehicles-section" class="section" style="display: none;">
|
||||
<div class="toolbar">
|
||||
<div class="search-box">
|
||||
<input type="text" id="searchVehicle" placeholder="输入车牌号查询...">
|
||||
<button onclick="searchVehicle()">🔍</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-card">
|
||||
<div class="content-body">
|
||||
<div id="vehicleResult"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="parts-section" class="section" style="display: none;">
|
||||
<div class="toolbar">
|
||||
<div class="search-box">
|
||||
<input type="text" id="searchPart" placeholder="搜索配件...">
|
||||
<button onclick="searchParts()">🔍</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-card">
|
||||
<div class="content-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>配件编号</th>
|
||||
<th>配件名称</th>
|
||||
<th>类别</th>
|
||||
<th>库存数量</th>
|
||||
<th>单价</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="partsBody">
|
||||
<tr><td colspan="5" class="empty-state">请输入关键词搜索配件</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../js/config.js"></script>
|
||||
<script src="../js/api.js"></script>
|
||||
<script>
|
||||
if (!utils.checkAuth() || !utils.hasRole('staff')) {
|
||||
window.location.href = '../login.html';
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const user = utils.getCurrentUser();
|
||||
if (user) {
|
||||
document.getElementById('userName').textContent = user.realName;
|
||||
document.getElementById('userAvatar').textContent = user.realName.charAt(0);
|
||||
loadStaffData(user.userId);
|
||||
}
|
||||
});
|
||||
|
||||
function showSection(name) {
|
||||
document.querySelectorAll('.section').forEach(s => s.style.display = 'none');
|
||||
document.querySelectorAll('.menu-item').forEach(m => m.classList.remove('active'));
|
||||
event.currentTarget.classList.add('active');
|
||||
document.getElementById(name + '-section').style.display = 'block';
|
||||
}
|
||||
|
||||
async function loadStaffData(staffId) {
|
||||
try {
|
||||
const response = await api.get(API_ENDPOINTS.ORDERS);
|
||||
if (response.code === 200 && response.data) {
|
||||
const myOrders = response.data.filter(o => o.staffId === staffId);
|
||||
const inProgress = myOrders.filter(o => o.status === 'in_progress');
|
||||
const completed = myOrders.filter(o => o.status === 'completed');
|
||||
|
||||
document.getElementById('myOrdersCount').textContent = myOrders.length;
|
||||
document.getElementById('inProgressCount').textContent = inProgress.length;
|
||||
document.getElementById('completedCount').textContent = completed.length;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function searchVehicle() {
|
||||
const plate = document.getElementById('searchVehicle').value.trim();
|
||||
if (!plate) {
|
||||
utils.showError('请输入车牌号');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await api.get(API_ENDPOINTS.VEHICLE_BY_PLATE(plate));
|
||||
if (response.code === 200 && response.data) {
|
||||
const v = response.data;
|
||||
document.getElementById('vehicleResult').innerHTML = `
|
||||
<div class="card">
|
||||
<h3>车辆信息</h3>
|
||||
<p><strong>车牌号:</strong> ${v.licensePlate}</p>
|
||||
<p><strong>品牌型号:</strong> ${v.brand} ${v.model}</p>
|
||||
<p><strong>颜色:</strong> ${v.color || '-'}</p>
|
||||
<p><strong>车架号:</strong> ${v.vin || '-'}</p>
|
||||
<p><strong>里程数:</strong> ${v.mileage || 0} 公里</p>
|
||||
<p><strong>状态:</strong> ${utils.getStatusBadge(v.status)}</p>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
document.getElementById('vehicleResult').innerHTML = '<p class="empty-state">未找到该车辆</p>';
|
||||
}
|
||||
} catch (error) {
|
||||
utils.showError('查询失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function searchParts() {
|
||||
try {
|
||||
const response = await api.get(API_ENDPOINTS.PARTS);
|
||||
if (response.code === 200 && response.data) {
|
||||
const tbody = document.getElementById('partsBody');
|
||||
const keyword = document.getElementById('searchPart').value.toLowerCase();
|
||||
const filtered = response.data.filter(p =>
|
||||
p.partName.toLowerCase().includes(keyword) ||
|
||||
p.partNo.toLowerCase().includes(keyword)
|
||||
);
|
||||
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="empty-state">未找到配件</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = filtered.map(p => `
|
||||
<tr>
|
||||
<td>${p.partNo}</td>
|
||||
<td>${p.partName}</td>
|
||||
<td>${p.category || '-'}</td>
|
||||
<td>${p.stockQuantity} ${p.unit}</td>
|
||||
<td>¥${p.unitPrice}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
}
|
||||
} catch (error) {
|
||||
utils.showError('搜索失败');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user