<template>
|
<div class="business-trip-table">
|
<div class="table-header">
|
<div class="header-actions">
|
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAddTrip">
|
新增出差
|
</el-button>
|
<el-button size="small" icon="el-icon-download" @click="exportData">
|
导出数据
|
</el-button>
|
</div>
|
|
<div class="header-filters">
|
<el-input
|
v-model="filters.employeeName"
|
placeholder="搜索员工姓名"
|
prefix-icon="el-icon-search"
|
style="width: 200px"
|
clearable
|
/>
|
<el-select v-model="filters.status" placeholder="状态筛选" clearable>
|
<el-option label="进行中" value="进行中" />
|
<el-option label="已完成" value="已完成" />
|
</el-select>
|
</div>
|
</div>
|
|
<el-table
|
:data="filteredData"
|
border
|
v-loading="loading"
|
style="width: 100%"
|
>
|
<el-table-column prop="tripNumber" label="出差单号" width="140" />
|
<el-table-column prop="employeeName" label="员工姓名" />
|
<el-table-column prop="startCity" label="出发城市" />
|
<el-table-column prop="endCity" label="目的城市" />
|
<el-table-column prop="startDate" label="开始日期" sortable />
|
<el-table-column prop="endDate" label="结束日期" sortable />
|
<el-table-column prop="duration" label="出差天数" >
|
<template #default="scope">
|
<el-tag size="small">{{ calculateDuration(scope.row) }}天</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="distance" label="里程(km)" sortable />
|
<el-table-column prop="status" label="状态" >
|
<template #default="scope">
|
<el-tag
|
:type="scope.row.status === '已完成' ? 'success' : 'primary'"
|
effect="light"
|
>
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="180" fixed="right">
|
<template #default="scope">
|
<el-button
|
size="mini"
|
type="text"
|
@click="handleViewDetail(scope.row)"
|
icon="el-icon-view"
|
>
|
详情
|
</el-button>
|
<el-button
|
size="mini"
|
type="text"
|
@click="handleEdit(scope.row)"
|
icon="el-icon-edit"
|
>
|
编辑
|
</el-button>
|
<el-button
|
size="mini"
|
type="text"
|
@click="handleDelete(scope.row)"
|
icon="el-icon-delete"
|
style="color: #f56c6c;"
|
>
|
删除
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<div class="pagination-container">
|
<el-pagination
|
:current-page="currentPage"
|
:page-size="pageSize"
|
:total="total"
|
layout="total, sizes, prev, pager, next, jumper"
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
/>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: 'BusinessTripTable',
|
props: {
|
data: {
|
type: Array,
|
default: () => []
|
},
|
loading: {
|
type: Boolean,
|
default: false
|
}
|
},
|
data() {
|
return {
|
currentPage: 1,
|
pageSize: 10,
|
filters: {
|
employeeName: '',
|
status: ''
|
}
|
}
|
},
|
computed: {
|
filteredData() {
|
let data = this.data.filter(item => {
|
const nameMatch = !this.filters.employeeName ||
|
item.employeeName.includes(this.filters.employeeName)
|
const statusMatch = !this.filters.status ||
|
item.status === this.filters.status
|
return nameMatch && statusMatch
|
})
|
|
const start = (this.currentPage - 1) * this.pageSize
|
const end = start + this.pageSize
|
return data.slice(start, end)
|
},
|
total() {
|
return this.data.filter(item => {
|
const nameMatch = !this.filters.employeeName ||
|
item.employeeName.includes(this.filters.employeeName)
|
const statusMatch = !this.filters.status ||
|
item.status === this.filters.status
|
return nameMatch && statusMatch
|
}).length
|
}
|
},
|
methods: {
|
calculateDuration(row) {
|
const start = new Date(row.startDate)
|
const end = new Date(row.endDate)
|
const duration = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1
|
return duration
|
},
|
|
handleViewDetail(row) {
|
this.$emit('view-detail', row)
|
},
|
|
handleAddTrip() {
|
this.$message.info('打开新增出差对话框')
|
},
|
|
handleEdit(row) {
|
this.$message.info(`编辑出差记录: ${row.tripNumber}`)
|
},
|
|
handleDelete(row) {
|
this.$confirm('确定要删除这条出差记录吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
this.$message.success('删除成功')
|
}).catch(() => {})
|
},
|
|
exportData() {
|
this.$message.success('导出功能开发中')
|
},
|
|
handleSizeChange(size) {
|
this.pageSize = size
|
this.currentPage = 1
|
},
|
|
handleCurrentChange(page) {
|
this.currentPage = page
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.business-trip-table {
|
padding: 20px;
|
}
|
|
.table-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 16px;
|
flex-wrap: wrap;
|
gap: 16px;
|
}
|
|
.header-actions {
|
display: flex;
|
gap: 10px;
|
}
|
|
.header-filters {
|
display: flex;
|
gap: 10px;
|
align-items: center;
|
}
|
|
.pagination-container {
|
margin-top: 20px;
|
display: flex;
|
justify-content: flex-end;
|
}
|
|
@media (max-width: 768px) {
|
.table-header {
|
flex-direction: column;
|
align-items: stretch;
|
}
|
|
.header-actions {
|
justify-content: space-between;
|
}
|
}
|
</style>
|