You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
11 KiB
419 lines
11 KiB
<template>
|
|
<el-container>
|
|
<!-- 导航栏 -->
|
|
<el-header>
|
|
<Header />
|
|
</el-header>
|
|
|
|
<el-main>
|
|
<div class="container">
|
|
<!-- 标题、输入框和按钮 -->
|
|
<!-- <div class="bg"></div> -->
|
|
<div class="top-section">
|
|
<h1 class="title">运单查询</h1>
|
|
<div class="input-group">
|
|
<el-input
|
|
v-model="form.trackingNumber"
|
|
placeholder="请输入快递单号"
|
|
clearable
|
|
style="width: 300px; margin-right: 20px;"
|
|
@input="validateTrackingNumber"
|
|
@keyup.enter="searchPackage"
|
|
></el-input>
|
|
<el-button @click="searchPackage" type="primary" :loading="loading">查询</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 选项卡 -->
|
|
<el-tabs v-model="activeTab" type="card" style="margin-top: 20px;" @tab-click="handleTabClick">
|
|
<el-tab-pane label="我寄的" name="sent">
|
|
<el-table v-if="sentPackages.length" :data="sentPackages" style="margin-top: 20px;">
|
|
<el-table-column label="快递单号" prop="trackingNumber"></el-table-column>
|
|
<el-table-column label="包裹名称" prop="packageName"></el-table-column>
|
|
<el-table-column label="寄件人" prop="sender"></el-table-column>
|
|
<el-table-column label="寄件人地址" prop="senderaddress"></el-table-column>
|
|
<el-table-column label="收件人" prop="receiver"></el-table-column>
|
|
<el-table-column label="收件人地址" prop="receiveraddress"></el-table-column>
|
|
<el-table-column label="状态" prop="status">
|
|
<template #default="scope">
|
|
<span :class="getStatusClass(scope.row.status)">{{ scope.row.status }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="最新位置" prop="latestLocation"></el-table-column>
|
|
</el-table>
|
|
<p v-else>暂无数据</p>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="我收的" name="received">
|
|
<el-table v-if="receivedPackages.length" :data="receivedPackages" style="margin-top: 20px;">
|
|
<el-table-column label="快递单号" prop="trackingNumber"></el-table-column>
|
|
<el-table-column label="包裹名称" prop="packageName"></el-table-column>
|
|
<el-table-column label="寄件人地址" prop="senderaddress"></el-table-column>
|
|
<el-table-column label="寄件人" prop="sender"></el-table-column>
|
|
<el-table-column label="收件人地址" prop="receiveraddress"></el-table-column>
|
|
<el-table-column label="收件人" prop="receiver"></el-table-column>
|
|
<el-table-column label="状态" prop="status">
|
|
<template #default="scope">
|
|
<span :class="getStatusClass(scope.row.status)">{{ scope.row.status }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="最新位置" prop="latestLocation"></el-table-column>
|
|
</el-table>
|
|
<p v-else>暂无数据</p>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
</el-main>
|
|
|
|
<el-footer>
|
|
<Footer />
|
|
</el-footer>
|
|
</el-container>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { ElMessage, ElMessageBox, ElInput, ElButton, ElTable, ElTableColumn } from 'element-plus'
|
|
|
|
// 定义包裹数据的类型
|
|
interface Package {
|
|
trackingNumber: string;
|
|
packageName: string;
|
|
sender: string;
|
|
senderaddress: string;
|
|
receiver: string;
|
|
receiveraddress: string;
|
|
status: string;
|
|
latestLocation: string;
|
|
}
|
|
|
|
// 模拟数据
|
|
const mockData: Package[] = [
|
|
{
|
|
trackingNumber: '123',
|
|
packageName: '书籍',
|
|
sender: '张帅齐',
|
|
senderaddress: '北京市海淀区',
|
|
receiver: '李四',
|
|
receiveraddress: '上海市浦东新区',
|
|
status: '未签收',
|
|
latestLocation: '北京市海淀区',
|
|
},
|
|
{
|
|
trackingNumber: '456',
|
|
packageName: '衣物',
|
|
sender: '林涛',
|
|
senderaddress: '上海市浦东新区',
|
|
receiver: '李四',
|
|
receiveraddress: '北京市海淀区',
|
|
status: '正在运输',
|
|
latestLocation: '上海市浦东新区',
|
|
},
|
|
{
|
|
trackingNumber: '789',
|
|
packageName: '电子产品',
|
|
sender: '陈子润',
|
|
senderaddress: '北京市海淀区',
|
|
receiver: '李四',
|
|
receiveraddress: '北京市海淀区',
|
|
status: '已签收',
|
|
latestLocation: '北京市海淀区',
|
|
},
|
|
{
|
|
trackingNumber: '011',
|
|
packageName: '书籍',
|
|
sender: '张帅齐',
|
|
senderaddress: '北京市海淀区',
|
|
receiver: '李四',
|
|
receiveraddress: '北京市海淀区',
|
|
status: '已签收',
|
|
latestLocation: '北京市海淀区',
|
|
},
|
|
{
|
|
trackingNumber: '012',
|
|
packageName: '书籍',
|
|
sender: '孙贺贺',
|
|
senderaddress: '北京市海淀区',
|
|
receiver: '李四',
|
|
receiveraddress: '北京市海淀区',
|
|
status: '已签收',
|
|
latestLocation: '北京市海淀区',
|
|
},
|
|
{
|
|
trackingNumber: '013',
|
|
packageName: '书籍',
|
|
sender: '梁佳琪',
|
|
senderaddress: '北京市海淀区',
|
|
receiver: '李四',
|
|
receiveraddress: '北京市海淀区',
|
|
status: '未签收',
|
|
latestLocation: '北京市海淀区',
|
|
}
|
|
]
|
|
|
|
const form = ref({
|
|
trackingNumber: ''
|
|
})
|
|
|
|
const activeTab = ref('sent')
|
|
|
|
const sentPackages = ref<Package[]>([]) // 初始为空数组
|
|
const receivedPackages = ref<Package[]>([]) // 初始为空数组
|
|
|
|
const error = ref('')
|
|
const loading = ref(false)
|
|
|
|
// 验证快递单号
|
|
const validateTrackingNumber = () => {
|
|
if (form.value.trackingNumber && !/^\d+$/.test(form.value.trackingNumber)) {
|
|
error.value = '快递单号只能包含数字'
|
|
} else {
|
|
error.value = ''
|
|
}
|
|
}
|
|
|
|
// 处理选项卡点击事件
|
|
const handleTabClick = (tab: any) => {
|
|
// 清空当前的包裹数据
|
|
sentPackages.value = [];
|
|
receivedPackages.value = [];
|
|
|
|
if (tab.paneName === 'sent') {
|
|
sentPackages.value = mockData.filter(item => ['123', '456', '789'].includes(item.trackingNumber));
|
|
activeTab.value = 'sent'; // 确保 activeTab 更新
|
|
} else if (tab.paneName === 'received') {
|
|
receivedPackages.value = mockData.filter(item => ['011', '012', '013'].includes(item.trackingNumber));
|
|
activeTab.value = 'received'; // 确保 activeTab 更新
|
|
}
|
|
}
|
|
|
|
// 初始化加载“我寄的”运单数据
|
|
const initSentPackages = () => {
|
|
sentPackages.value = mockData.filter(item => ['123', '456', '789'].includes(item.trackingNumber));
|
|
}
|
|
|
|
// 在组件初始化时调用
|
|
onMounted(() => {
|
|
initSentPackages();
|
|
})
|
|
|
|
// 查询包裹的函数
|
|
const searchPackage = async () => {
|
|
if (!form.value.trackingNumber) {
|
|
ElMessage.error('请输入快递单号')
|
|
return
|
|
}
|
|
|
|
if (error.value) {
|
|
ElMessageBox.alert(error.value, '错误', {
|
|
confirmButtonText: '确定',
|
|
type: 'error',
|
|
})
|
|
return
|
|
}
|
|
|
|
loading.value = true
|
|
try {
|
|
const result = mockData.find(item => item.trackingNumber === form.value.trackingNumber)
|
|
if (result) {
|
|
ElMessage.success('查询成功')
|
|
// 自动跳转到对应的选项卡
|
|
if (['123', '456', '789'].includes(result.trackingNumber)) {
|
|
activeTab.value = 'sent'
|
|
sentPackages.value = [result] // 只显示查询到的包裹
|
|
receivedPackages.value = [] // 清空收到的包裹
|
|
} else if (['011', '012', '013'].includes(result.trackingNumber)) {
|
|
activeTab.value = 'received'
|
|
receivedPackages.value = [result] // 只显示查询到的包裹
|
|
sentPackages.value = [] // 清空寄出的包裹
|
|
}
|
|
} else {
|
|
ElMessageBox.alert('未找到该快递单号的信息,请确认单号是否正确。', '错误', {
|
|
confirmButtonText: '确定',
|
|
type: 'error',
|
|
})
|
|
}
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 获取状态的颜色类
|
|
const getStatusClass = (status: string) => {
|
|
switch (status) {
|
|
case '已签收':
|
|
return 'status-success';
|
|
case '正在运输':
|
|
return 'status-warning';
|
|
default:
|
|
return 'status-fail';
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 将容器设置为 flex 布局,居中对齐 */
|
|
.container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: flex-start; /* 从顶部开始排列 */
|
|
padding: 20px;
|
|
/* background: #f5f5f5; */
|
|
}
|
|
|
|
/* 标题样式 */
|
|
.title {
|
|
font-size: 32px;
|
|
font-weight: bold;
|
|
color: #0093dd;
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
margin-top: 0px; /* 为标题留出导航栏的空间 */
|
|
}
|
|
|
|
/* 顶部区域样式 */
|
|
.top-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
max-width: 600px;
|
|
}
|
|
|
|
/* 输入框和按钮容器 */
|
|
.input-group {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.input-group .el-input {
|
|
margin-right: 20px;
|
|
width: 300px;
|
|
}
|
|
|
|
.el-button {
|
|
padding: 10px 20px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
/* 表格样式 */
|
|
.el-table {
|
|
width: 100%;
|
|
max-width: 1000px; /* 增加表格的最大宽度 */
|
|
margin-top: 20px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.el-table th,
|
|
.el-table td {
|
|
text-align: center;
|
|
padding: 12px 0;
|
|
}
|
|
|
|
.el-table th {
|
|
background: #f0f0f0;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.el-table tr:nth-child(even) {
|
|
background: #f9f9f9;
|
|
}
|
|
|
|
.el-table tr:hover {
|
|
background: #e0e0e0;
|
|
}
|
|
|
|
/* 状态颜色样式 */
|
|
.status-success {
|
|
color: green;
|
|
}
|
|
|
|
.status-fail {
|
|
color: rgb(255, 0, 0);
|
|
}
|
|
|
|
.status-warning {
|
|
color: orange;
|
|
}
|
|
|
|
/* 选项卡样式 */
|
|
.el-tabs {
|
|
width: 100%;
|
|
max-width: 1000px; /* 增加选项卡的最大宽度 */
|
|
margin-top: 20px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.el-tabs__header {
|
|
margin: 0;
|
|
padding: 0 20px;
|
|
background: #f0f0f0;
|
|
border-bottom: 1px solid #ddd;
|
|
}
|
|
|
|
.el-tabs__nav-wrap::after {
|
|
display: none;
|
|
}
|
|
|
|
.el-tabs__item {
|
|
padding: 0 20px;
|
|
height: 40px;
|
|
line-height: 40px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
transition: background 0.3s, color 0.3s, border-bottom 0.3s;
|
|
border-bottom: 2px solid transparent; /* 默认情况下没有下划线 */
|
|
}
|
|
|
|
.el-tabs__item.is-active {
|
|
background: #fff;
|
|
color: #409eff;
|
|
border-bottom: 2px solid red !important; /* 激活状态下有红色下划线 */
|
|
}
|
|
|
|
.el-tabs__item:hover {
|
|
background: #e0e0e0;
|
|
color: #409eff;
|
|
border-bottom: 2px solid #f60d0d !important; /* 悬停时有下划线 */
|
|
}
|
|
|
|
/* Element UI 容器样式 */
|
|
.el-header {
|
|
padding: 0;
|
|
height: 100;
|
|
}
|
|
|
|
.el-main {
|
|
margin-top: 80px;
|
|
padding: 20px 0;
|
|
overflow: hidden;
|
|
height: calc(100vh - 200px); /* 调整高度以适应屏幕 */
|
|
}
|
|
|
|
.el-footer {
|
|
margin-top: 0px;
|
|
padding: 20px 0;
|
|
/* background: #333; */
|
|
color: #fff;
|
|
text-align: center;
|
|
}
|
|
.bg{
|
|
background-image: url('./assets/check-bg.jpg'); /* 替换为你的图片路径 */
|
|
background-size: cover; /* 覆盖整个元素 */
|
|
background-position: center; /* 背景图居中 */
|
|
background-repeat: no-repeat; /* 不重复背景图 */
|
|
width: 100%; /* 宽度填满整个容器 */
|
|
height: 100%; /* 高度填满整个容器 */
|
|
position: absolute; /* 绝对定位 */
|
|
top: 0;
|
|
left: 0;
|
|
z-index: -1; /* 确保背景图在内容下方 */
|
|
}
|
|
</style> |