aircraft-admin/src/views/service/route-management.html
2025-07-11 13:34:31 +08:00

778 lines
42 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>飞行器管理系统 - 路线管理</title>
<!-- 引入Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入Font Awesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- Tailwind配置 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#0f172a',
secondary: '#334155',
success: '#047857',
danger: '#b91c1c',
warning: '#b45309',
info: '#0e7490',
light: '#f8fafc',
dark: '#020617',
gray: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
}
},
fontFamily: {
inter: ['Inter', 'system-ui', 'sans-serif'],
},
boxShadow: {
'card': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
'card-hover': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
'elegant': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
}
},
}
}
</script>
<!-- 自定义工具类 -->
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.transition-custom {
transition: all 0.2s ease;
}
.btn-hover {
@apply hover:scale-[1.02] transition-all duration-200;
}
.input-focus {
@apply focus:ring-2 focus:ring-primary/20 focus:border-primary;
}
.table-row-hover {
@apply hover:bg-gray-50/80 transition-all duration-200;
}
.gradient-bg {
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
}
}
</style>
</head>
<body class="gradient-bg font-inter text-gray-900 min-h-screen flex flex-col">
<!-- 顶部导航 -->
<header class="bg-white shadow-sm border-b border-gray-200 sticky top-0 z-50">
<div class="container mx-auto px-4 py-3 flex items-center justify-between">
<div class="flex items-center space-x-2">
<i class="fa fa-paper-plane text-primary text-xl"></i>
<h1 class="text-lg font-semibold text-gray-900 hidden sm:block">飞行器管理系统</h1>
</div>
<div class="flex items-center space-x-4">
<div class="relative hidden md:block">
<input type="text" placeholder="全局搜索..." class="pl-9 pr-4 py-2 rounded-lg bg-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 w-64">
<i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
</div>
<div class="flex items-center space-x-3">
<button class="p-2 rounded-full hover:bg-gray-100 relative">
<i class="fa fa-bell-o text-gray-600"></i>
<span class="absolute top-1 right-1 w-2 h-2 bg-danger rounded-full"></span>
</button>
<div class="flex items-center space-x-2">
<div class="w-8 h-8 rounded-full bg-gray-200 overflow-hidden">
<img src="https://picsum.photos/200/200?random=1" alt="用户头像" class="w-full h-full object-cover">
</div>
<span class="text-sm font-medium hidden sm:block">管理员</span>
</div>
</div>
</div>
</div>
</header>
<div class="flex flex-1 overflow-hidden">
<!-- 侧边导航 -->
<aside class="w-16 sm:w-56 bg-white shadow-sm border-r border-gray-200 h-[calc(100vh-56px)] sticky top-[56px] transition-all duration-300 ease-in-out z-40">
<nav class="h-full flex flex-col">
<div class="px-4 py-3 border-b border-gray-200 hidden sm:block">
<h2 class="text-sm font-semibold text-gray-500 uppercase tracking-wider">主导航</h2>
</div>
<ul class="flex-1 overflow-y-auto py-2">
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-home text-lg w-6"></i>
<span class="ml-3 hidden sm:block">首页</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-cog text-lg w-6"></i>
<span class="ml-3 hidden sm:block">系统管理</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-building-o text-lg w-6"></i>
<span class="ml-3 hidden sm:block">平台管理</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-plane text-lg w-6"></i>
<span class="ml-3 hidden sm:block">飞行器管理</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 bg-primary/5 text-primary border-l-4 border-primary">
<i class="fa fa-map-o text-lg w-6"></i>
<span class="ml-3 hidden sm:block">路线管理</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-list-alt text-lg w-6"></i>
<span class="ml-3 hidden sm:block">订单管理</span>
</a>
</li>
<li class="mb-1">
<a href="#" class="flex items-center px-4 py-3 text-gray-600 hover:bg-gray-50 hover:text-primary transition-custom">
<i class="fa fa-money text-lg w-6"></i>
<span class="ml-3 hidden sm:block">运输金额管理</span>
</a>
</li>
</ul>
<div class="p-4 border-t border-gray-200 hidden sm:block">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 rounded-full bg-gray-200 overflow-hidden">
<img src="https://picsum.photos/200/200?random=1" alt="用户头像" class="w-full h-full object-cover">
</div>
<div>
<p class="text-sm font-medium">管理员</p>
<p class="text-xs text-gray-500">admin@example.com</p>
</div>
</div>
</div>
</nav>
</aside>
<!-- 主内容区 -->
<main class="flex-1 overflow-y-auto bg-gray-50 p-3 sm:p-4 lg:p-6">
<div class="max-w-7xl mx-auto">
<!-- 搜索区域 -->
<div class="bg-white rounded-xl shadow-elegant p-3 sm:p-4 mb-6 border border-gray-100">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
<div class="w-full sm:w-auto flex-1 max-w-md">
<div class="relative">
<input type="text" id="routeName" placeholder="请输入路线名称" class="w-full px-3 py-1.5 sm:py-2 pl-10 border border-gray-200 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary bg-gray-50/50 text-sm">
<i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 text-xs"></i>
</div>
</div>
<div class="flex gap-2">
<button id="searchBtn" class="bg-primary hover:bg-primary/90 text-white px-3 py-1.5 sm:px-4 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-all duration-200 hover:shadow-lg flex items-center justify-center">
<i class="fa fa-search mr-1 text-xs"></i>查询
</button>
<button id="resetBtn" class="bg-white border border-gray-200 text-gray-700 px-3 py-1.5 sm:px-4 sm:py-2 rounded-lg text-xs sm:text-sm font-medium hover:bg-gray-50 hover:border-gray-300 transition-all duration-200 flex items-center justify-center">
<i class="fa fa-refresh mr-1 text-xs"></i>重置
</button>
<button id="addRouteBtn" class="bg-success hover:bg-success/90 text-white px-3 py-1.5 sm:px-4 sm:py-2 rounded-lg text-xs sm:text-sm font-medium transition-all duration-200 hover:shadow-lg flex items-center justify-center">
<i class="fa fa-plus mr-1 text-xs"></i>新增路线
</button>
</div>
</div>
</div>
<!-- 表格区域 -->
<div class="bg-white rounded-xl shadow-elegant overflow-hidden border border-gray-100">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-100">
<thead class="bg-gradient-to-r from-gray-50 to-gray-100/50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">城市名称</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">景区名称</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">路线名称</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">创建时间</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-semibold text-gray-600 uppercase tracking-wider">操作</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-100" id="routeTableBody">
<!-- 表格数据由JavaScript动态生成 -->
</tbody>
</table>
</div>
<!-- 分页 -->
<div class="px-6 py-3 border-t border-gray-200 flex items-center justify-between">
<div class="flex-1 flex justify-between sm:hidden">
<button class="relative inline-flex items-center px-3 py-1.5 border border-gray-300 text-xs font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
上一页
</button>
<button class="ml-2 relative inline-flex items-center px-3 py-1.5 border border-gray-300 text-xs font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
下一页
</button>
</div>
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div>
<p class="text-xs text-gray-700">
显示第 <span class="font-medium" id="currentPageStart">1</span><span class="font-medium" id="currentPageEnd">10</span> 条,共 <span class="font-medium" id="totalCount">10</span> 条记录
</p>
</div>
<div>
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
<button class="pagination-btn relative inline-flex items-center px-2 py-1 border border-gray-300 text-xs font-medium rounded-l-md text-gray-500 bg-white hover:bg-gray-50" data-page="prev">
<span class="sr-only">上一页</span>
<i class="fa fa-chevron-left"></i>
</button>
<button class="pagination-btn relative inline-flex items-center px-3 py-1 border border-primary bg-primary text-white text-xs font-medium" data-page="1">
1
</button>
<button class="pagination-btn relative inline-flex items-center px-3 py-1 border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 text-xs font-medium" data-page="2">
2
</button>
<span class="relative inline-flex items-center px-3 py-1 border border-gray-300 bg-white text-xs font-medium text-gray-700">
...
</span>
<button class="pagination-btn relative inline-flex items-center px-3 py-1 border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 text-xs font-medium" data-page="5">
5
</button>
<button class="pagination-btn relative inline-flex items-center px-2 py-1 border border-gray-300 text-xs font-medium rounded-r-md text-gray-500 bg-white hover:bg-gray-50" data-page="next">
<span class="sr-only">下一页</span>
<i class="fa fa-chevron-right"></i>
</button>
</nav>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- 新增/修改路线模态框 -->
<div id="routeModal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-lg shadow-lg w-full max-w-md mx-4 transform transition-all duration-300 opacity-0 scale-95" id="modalContent">
<div class="p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900" id="modalTitle">新增路线</h3>
<button id="closeModalBtn" class="text-gray-400 hover:text-gray-500 focus:outline-none">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<form id="routeForm">
<div class="space-y-4">
<div>
<label for="routeNameInput" class="block text-sm font-medium text-gray-700">
<span class="text-danger">*</span> 路线名称
</label>
<input type="text" id="routeNameInput" name="routeName" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none input-focus" placeholder="请输入路线名称">
<p class="mt-1 text-sm text-danger hidden" id="routeNameError">请输入路线名称</p>
</div>
<div>
<label for="scenicAreaInput" class="block text-sm font-medium text-gray-700">
<span class="text-danger">*</span> 景区名称
</label>
<select id="scenicAreaInput" name="scenicArea" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none input-focus">
<option value="">请选择景区</option>
<option value="白云山">白云山</option>
<option value="丹霞山">丹霞山</option>
<option value="西樵山">西樵山</option>
<option value="罗浮山">罗浮山</option>
<option value="鼎湖山">鼎湖山</option>
</select>
<p class="mt-1 text-sm text-danger hidden" id="scenicAreaError">请选择景区</p>
</div>
<div>
<label for="takeoffPointInput" class="block text-sm font-medium text-gray-700">
<span class="text-danger">*</span> 起飞点
</label>
<input type="text" id="takeoffPointInput" name="takeoffPoint" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none input-focus" placeholder="请输入起飞点">
<p class="mt-1 text-sm text-danger hidden" id="takeoffPointError">请输入起飞点</p>
</div>
<div>
<label for="landingPointInput" class="block text-sm font-medium text-gray-700">
<span class="text-danger">*</span> 降落点
</label>
<input type="text" id="landingPointInput" name="landingPoint" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none input-focus" placeholder="请输入降落点">
<p class="mt-1 text-sm text-danger hidden" id="landingPointError">请输入降落点</p>
</div>
<div>
<label for="descriptionInput" class="block text-sm font-medium text-gray-700">路线描述</label>
<textarea id="descriptionInput" name="description" rows="3" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none input-focus" placeholder="请输入路线描述(选填)"></textarea>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button type="button" id="cancelModalBtn" class="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
取消
</button>
<button type="submit" id="submitRouteBtn" class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
保存
</button>
</div>
</form>
</div>
</div>
</div>
<!-- 删除确认模态框 -->
<div id="deleteModal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center hidden">
<div class="bg-white rounded-lg shadow-lg w-full max-w-md mx-4 transform transition-all duration-300 opacity-0 scale-95" id="deleteModalContent">
<div class="p-6">
<div class="text-center mb-4">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-danger/10 mb-4">
<i class="fa fa-exclamation-triangle text-danger text-xl"></i>
</div>
<h3 class="text-lg font-semibold text-gray-900">确认删除</h3>
<p class="text-gray-500 mt-2" id="deleteMessage">此操作将永久删除路线"白云山-山顶路线",是否继续?</p>
</div>
<div class="flex justify-center space-x-3">
<button id="cancelDeleteBtn" class="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary">
取消
</button>
<button id="confirmDeleteBtn" class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-danger hover:bg-danger/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-danger">
确认删除
</button>
</div>
</div>
</div>
</div>
<!-- 成功提示消息 -->
<div id="successToast" class="fixed top-4 right-4 bg-success text-white px-4 py-3 rounded-lg shadow-lg transform transition-all duration-300 translate-y-[-200%] opacity-0 z-50 flex items-center">
<i class="fa fa-check-circle mr-2"></i>
<span id="successMessage">操作成功</span>
</div>
<script>
// 示例数据
const routes = [
{ id: 1, city: '广州', scenicArea: '白云山', routeName: '山脚到山顶', createTime: '2023-05-10 09:30:00' },
{ id: 2, city: '广州', scenicArea: '白云山', routeName: '南门到西门', createTime: '2023-06-15 14:15:00' },
{ id: 3, city: '韶关', scenicArea: '丹霞山', routeName: '长老峰环线', createTime: '2023-07-20 10:45:00' },
{ id: 4, city: '佛山', scenicArea: '西樵山', routeName: '天湖到南海观音', createTime: '2023-08-05 16:20:00' },
{ id: 5, city: '惠州', scenicArea: '罗浮山', routeName: '朱明洞到飞云顶', createTime: '2023-09-12 11:10:00' },
{ id: 6, city: '肇庆', scenicArea: '鼎湖山', routeName: '宝鼎园到飞水潭', createTime: '2023-10-18 13:30:00' },
{ id: 7, city: '广州', scenicArea: '白云山', routeName: '梅花园到明珠楼', createTime: '2023-11-25 08:45:00' },
{ id: 8, city: '韶关', scenicArea: '丹霞山', routeName: '阳元石到阴元石', createTime: '2023-12-05 15:20:00' },
{ id: 9, city: '佛山', scenicArea: '西樵山', routeName: '碧玉洞到翠岩', createTime: '2024-01-15 10:10:00' },
{ id: 10, city: '惠州', scenicArea: '罗浮山', routeName: '黄龙观到华首台', createTime: '2024-02-20 14:00:00' },
{ id: 11, city: '广州', scenicArea: '白云山', routeName: '摩星岭路线', createTime: '2024-03-05 09:45:00' },
{ id: 12, city: '韶关', scenicArea: '丹霞山', routeName: '锦江游船路线', createTime: '2024-03-18 15:30:00' },
{ id: 13, city: '佛山', scenicArea: '西樵山', routeName: '碧玉洞瀑布路线', createTime: '2024-04-02 11:20:00' },
{ id: 14, city: '惠州', scenicArea: '罗浮山', routeName: '九天观路线', createTime: '2024-04-15 14:10:00' },
{ id: 15, city: '肇庆', scenicArea: '鼎湖山', routeName: '庆云寺路线', createTime: '2024-04-28 10:30:00' },
{ id: 16, city: '广州', scenicArea: '白云山', routeName: '白云索道路线', createTime: '2024-05-10 16:20:00' },
{ id: 17, city: '韶关', scenicArea: '丹霞山', routeName: '巴寨路线', createTime: '2024-05-22 09:15:00' },
{ id: 18, city: '佛山', scenicArea: '西樵山', routeName: '四方竹园路线', createTime: '2024-06-05 13:40:00' },
{ id: 19, city: '惠州', scenicArea: '罗浮山', routeName: '酥醪观路线', createTime: '2024-06-18 11:50:00' },
{ id: 20, city: '肇庆', scenicArea: '鼎湖山', routeName: '蝴蝶谷路线', createTime: '2024-06-30 14:25:00' },
];
// 当前编辑的路线ID
let currentRouteId = null;
// 当前页码
let currentPage = 1;
// 每页显示数量
const pageSize = 10;
// 当前筛选数据
let filteredRoutes = [...routes];
// DOM元素
const routeTableBody = document.getElementById('routeTableBody');
const addRouteBtn = document.getElementById('addRouteBtn');
const routeModal = document.getElementById('routeModal');
const modalContent = document.getElementById('modalContent');
const closeModalBtn = document.getElementById('closeModalBtn');
const cancelModalBtn = document.getElementById('cancelModalBtn');
const routeForm = document.getElementById('routeForm');
const modalTitle = document.getElementById('modalTitle');
const submitRouteBtn = document.getElementById('submitRouteBtn');
const deleteModal = document.getElementById('deleteModal');
const deleteModalContent = document.getElementById('deleteModalContent');
const cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
const deleteMessage = document.getElementById('deleteMessage');
const searchBtn = document.getElementById('searchBtn');
const resetBtn = document.getElementById('resetBtn');
const successToast = document.getElementById('successToast');
const successMessage = document.getElementById('successMessage');
const currentPageStart = document.getElementById('currentPageStart');
const currentPageEnd = document.getElementById('currentPageEnd');
const totalCount = document.getElementById('totalCount');
// 获取当前页数据
function getCurrentPageData() {
const startIndex = (currentPage - 1) * pageSize;
const endIndex = Math.min(startIndex + pageSize, filteredRoutes.length);
return filteredRoutes.slice(startIndex, endIndex);
}
// 更新分页信息
function updatePaginationInfo() {
const total = filteredRoutes.length;
const start = Math.min((currentPage - 1) * pageSize + 1, total);
const end = Math.min(currentPage * pageSize, total);
currentPageStart.textContent = start;
currentPageEnd.textContent = end;
totalCount.textContent = total;
}
// 初始化表格数据
function initTableData() {
const currentData = getCurrentPageData();
routeTableBody.innerHTML = '';
if (currentData.length === 0) {
routeTableBody.innerHTML = `
<tr>
<td colspan="5" class="px-6 py-8 text-center text-gray-500">
<div class="flex flex-col items-center">
<i class="fa fa-inbox text-3xl mb-2 text-gray-300"></i>
<p class="text-sm">暂无路线数据</p>
<p class="text-xs text-gray-400 mt-1">点击"新增路线"按钮开始添加</p>
</div>
</td>
</tr>
`;
return;
}
currentData.forEach(route => {
const row = document.createElement('tr');
row.className = 'table-row-hover';
row.innerHTML = `
<td class="px-6 py-3 whitespace-nowrap text-sm text-gray-500">${route.city}</td>
<td class="px-6 py-3 whitespace-nowrap text-sm text-gray-500">${route.scenicArea}</td>
<td class="px-6 py-3 whitespace-nowrap text-sm font-medium text-gray-900">${route.routeName}</td>
<td class="px-6 py-3 whitespace-nowrap text-sm text-gray-500">${route.createTime}</td>
<td class="px-6 py-3 whitespace-nowrap text-right text-sm font-medium">
<button class="text-primary hover:text-primary/80 mr-3 edit-btn" data-id="${route.id}">
<i class="fa fa-pencil mr-1"></i>修改
</button>
<button class="text-danger hover:text-danger/80 delete-btn" data-id="${route.id}" data-name="${route.routeName}">
<i class="fa fa-trash mr-1"></i>删除
</button>
</td>
`;
routeTableBody.appendChild(row);
});
// 添加编辑和删除事件监听
document.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', () => {
const id = parseInt(btn.getAttribute('data-id'));
openEditModal(id);
});
});
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', () => {
const id = parseInt(btn.getAttribute('data-id'));
const name = btn.getAttribute('data-name');
openDeleteModal(id, name);
});
});
// 更新分页信息
updatePaginationInfo();
}
// 打开新增模态框
function openAddModal() {
currentRouteId = null;
modalTitle.textContent = '新增路线';
submitRouteBtn.textContent = '保存';
routeForm.reset();
hideAllErrors();
// 显示模态框并添加动画
routeModal.classList.remove('hidden');
setTimeout(() => {
modalContent.classList.remove('opacity-0', 'scale-95');
modalContent.classList.add('opacity-100', 'scale-100');
}, 10);
}
// 打开编辑模态框
function openEditModal(id) {
const route = routes.find(r => r.id === id);
if (!route) return;
currentRouteId = id;
modalTitle.textContent = '修改路线';
submitRouteBtn.textContent = '修改';
// 填充表单数据
document.getElementById('routeNameInput').value = route.routeName;
document.getElementById('scenicAreaInput').value = route.scenicArea;
document.getElementById('takeoffPointInput').value = `起飞点-${route.routeName}`; // 示例数据
document.getElementById('landingPointInput').value = `降落点-${route.routeName}`; // 示例数据
document.getElementById('descriptionInput').value = `这是一条从${route.scenicArea}${route.routeName}的运输路线`; // 示例数据
hideAllErrors();
// 显示模态框并添加动画
routeModal.classList.remove('hidden');
setTimeout(() => {
modalContent.classList.remove('opacity-0', 'scale-95');
modalContent.classList.add('opacity-100', 'scale-100');
}, 10);
}
// 关闭模态框
function closeModal() {
modalContent.classList.remove('opacity-100', 'scale-100');
modalContent.classList.add('opacity-0', 'scale-95');
setTimeout(() => {
routeModal.classList.add('hidden');
}, 300);
}
// 打开删除确认模态框
function openDeleteModal(id, name) {
currentRouteId = id;
deleteMessage.textContent = `此操作将永久删除路线"${name}",是否继续?`;
// 显示模态框并添加动画
deleteModal.classList.remove('hidden');
setTimeout(() => {
deleteModalContent.classList.remove('opacity-0', 'scale-95');
deleteModalContent.classList.add('opacity-100', 'scale-100');
}, 10);
}
// 关闭删除确认模态框
function closeDeleteModal() {
deleteModalContent.classList.remove('opacity-100', 'scale-100');
deleteModalContent.classList.add('opacity-0', 'scale-95');
setTimeout(() => {
deleteModal.classList.add('hidden');
}, 300);
}
// 隐藏所有错误提示
function hideAllErrors() {
document.getElementById('routeNameError').classList.add('hidden');
document.getElementById('scenicAreaError').classList.add('hidden');
document.getElementById('takeoffPointError').classList.add('hidden');
document.getElementById('landingPointError').classList.add('hidden');
}
// 验证表单
function validateForm() {
let isValid = true;
hideAllErrors();
const routeName = document.getElementById('routeNameInput').value.trim();
const scenicArea = document.getElementById('scenicAreaInput').value;
const takeoffPoint = document.getElementById('takeoffPointInput').value.trim();
const landingPoint = document.getElementById('landingPointInput').value.trim();
if (!routeName) {
document.getElementById('routeNameError').classList.remove('hidden');
isValid = false;
}
if (!scenicArea) {
document.getElementById('scenicAreaError').classList.remove('hidden');
isValid = false;
}
if (!takeoffPoint) {
document.getElementById('takeoffPointError').classList.remove('hidden');
isValid = false;
}
if (!landingPoint) {
document.getElementById('landingPointError').classList.remove('hidden');
isValid = false;
}
return isValid;
}
// 显示成功提示
function showSuccess(message) {
successMessage.textContent = message;
successToast.classList.remove('translate-y-[-200%]', 'opacity-0');
successToast.classList.add('translate-y-0', 'opacity-100');
setTimeout(() => {
successToast.classList.remove('translate-y-0', 'opacity-100');
successToast.classList.add('translate-y-[-200%]', 'opacity-0');
}, 3000);
}
// 处理表单提交
function handleFormSubmit(e) {
e.preventDefault();
if (!validateForm()) return;
const routeName = document.getElementById('routeNameInput').value.trim();
const scenicArea = document.getElementById('scenicAreaInput').value;
const takeoffPoint = document.getElementById('takeoffPointInput').value.trim();
const landingPoint = document.getElementById('landingPointInput').value.trim();
const description = document.getElementById('descriptionInput').value.trim();
if (currentRouteId === null) {
// 新增路线
const newId = Math.max(...routes.map(r => r.id)) + 1;
const newRoute = {
id: newId,
city: scenicArea === '白云山' || scenicArea === '西樵山' ? '广州' :
scenicArea === '丹霞山' ? '韶关' :
scenicArea === '罗浮山' ? '惠州' : '肇庆',
scenicArea,
routeName,
createTime: new Date().toISOString().slice(0, 19).replace('T', ' ')
};
routes.unshift(newRoute);
filteredRoutes = [...routes];
currentPage = 1;
showSuccess('路线添加成功');
} else {
// 修改路线
const index = routes.findIndex(r => r.id === currentRouteId);
if (index !== -1) {
routes[index].routeName = routeName;
routes[index].scenicArea = scenicArea;
routes[index].city = scenicArea === '白云山' || scenicArea === '西樵山' ? '广州' :
scenicArea === '丹霞山' ? '韶关' :
scenicArea === '罗浮山' ? '惠州' : '肇庆';
// 更新筛选数据中的对应项
const filteredIndex = filteredRoutes.findIndex(r => r.id === currentRouteId);
if (filteredIndex !== -1) {
filteredRoutes[filteredIndex] = routes[index];
}
showSuccess('路线修改成功');
}
}
initTableData();
closeModal();
}
// 处理删除确认
function handleDeleteConfirm() {
if (currentRouteId !== null) {
const index = routes.findIndex(r => r.id === currentRouteId);
if (index !== -1) {
routes.splice(index, 1);
filteredRoutes = filteredRoutes.filter(r => r.id !== currentRouteId);
// 如果删除后当前页没有数据了,跳转到上一页
if ((currentPage - 1) * pageSize >= filteredRoutes.length && currentPage > 1) {
currentPage--;
}
showSuccess('路线删除成功');
initTableData();
}
}
closeDeleteModal();
}
// 处理搜索
function handleSearch() {
const routeName = document.getElementById('routeName').value.trim().toLowerCase();
filteredRoutes = routes.filter(route => {
return route.routeName.toLowerCase().includes(routeName);
});
currentPage = 1;
initTableData();
}
// 处理重置
function handleReset() {
document.getElementById('routeName').value = '';
filteredRoutes = [...routes];
currentPage = 1;
initTableData();
}
// 处理分页
function handlePagination(e) {
const page = e.target.getAttribute('data-page');
if (page === 'prev') {
if (currentPage > 1) {
currentPage--;
initTableData();
}
} else if (page === 'next') {
if (currentPage < Math.ceil(filteredRoutes.length / pageSize)) {
currentPage++;
initTableData();
}
} else {
currentPage = parseInt(page);
initTableData();
}
}
// 初始化事件监听
function initEventListeners() {
// 添加路线按钮
addRouteBtn.addEventListener('click', openAddModal);
// 关闭模态框按钮
closeModalBtn.addEventListener('click', closeModal);
cancelModalBtn.addEventListener('click', closeModal);
// 表单提交
routeForm.addEventListener('submit', handleFormSubmit);
// 删除确认
cancelDeleteBtn.addEventListener('click', closeDeleteModal);
confirmDeleteBtn.addEventListener('click', handleDeleteConfirm);
// 搜索和重置
searchBtn.addEventListener('click', handleSearch);
resetBtn.addEventListener('click', handleReset);
// 分页按钮
document.querySelectorAll('.pagination-btn').forEach(btn => {
btn.addEventListener('click', handlePagination);
});
// 点击模态框外部关闭
routeModal.addEventListener('click', (e) => {
if (e.target === routeModal) {
closeModal();
}
});
deleteModal.addEventListener('click', (e) => {
if (e.target === deleteModal) {
closeDeleteModal();
}
});
}
// 初始化页面
function initPage() {
initTableData();
initEventListeners();
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', initPage);
</script>
</body>
</html>