614 lines
13 KiB
Vue
614 lines
13 KiB
Vue
<template>
|
||
<div class="admin-disassembly-orders">
|
||
<!-- 统计卡片 -->
|
||
<div class="disassembly-stats">
|
||
<div class="stat-card">
|
||
<div class="stat-icon total">
|
||
<el-icon><Document /></el-icon>
|
||
</div>
|
||
<div class="stat-info">
|
||
<div class="stat-number">{{ disassemblyStats.total }}</div>
|
||
<div class="stat-label">{{ t('admin.disassemblyOrders.stats.total') }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div class="stat-icon pending">
|
||
<el-icon><Clock /></el-icon>
|
||
</div>
|
||
<div class="stat-info">
|
||
<div class="stat-number">{{ disassemblyStats.pending }}</div>
|
||
<div class="stat-label">{{ t('admin.disassemblyOrders.stats.pending') }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div class="stat-icon processing">
|
||
<el-icon><Loading /></el-icon>
|
||
</div>
|
||
<div class="stat-info">
|
||
<div class="stat-number">{{ disassemblyStats.processing }}</div>
|
||
<div class="stat-label">{{ t('admin.disassemblyOrders.stats.processing') }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 筛选搜索区域 -->
|
||
<div class="disassembly-filters">
|
||
<div class="filter-group">
|
||
<el-select
|
||
v-model="selectedStatus"
|
||
:placeholder="$t('admin.disassemblyOrders.filters.status')"
|
||
clearable
|
||
>
|
||
<el-option
|
||
:label="$t('admin.disassemblyOrders.filters.allStatus')"
|
||
value=""
|
||
/>
|
||
<el-option
|
||
:label="$t('admin.disassemblyOrders.detail.statusOptions.pending')"
|
||
value="pending"
|
||
/>
|
||
<el-option
|
||
:label="$t('admin.disassemblyOrders.detail.statusOptions.processing')"
|
||
value="processing"
|
||
/>
|
||
</el-select>
|
||
</div>
|
||
|
||
<div class="search-group">
|
||
<el-input
|
||
v-model="searchQuery"
|
||
:placeholder="$t('admin.disassemblyOrders.filters.searchPlaceholder')"
|
||
prefix-icon="Search"
|
||
clearable
|
||
/>
|
||
</div>
|
||
|
||
<div class="filter-actions">
|
||
<el-button
|
||
type="primary"
|
||
@click="fetchOrders"
|
||
>
|
||
<el-icon><Search /></el-icon>
|
||
{{ $t('admin.disassemblyOrders.filters.filter') }}
|
||
</el-button>
|
||
<el-button
|
||
@click="resetFilters"
|
||
>
|
||
<el-icon><Refresh /></el-icon>
|
||
{{ $t('admin.disassemblyOrders.filters.refresh') }}
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 订单列表区域 -->
|
||
<div class="disassembly-table">
|
||
<el-table
|
||
:data="paginatedOrders"
|
||
stripe
|
||
style="width: 100%"
|
||
v-loading="loading"
|
||
>
|
||
<el-table-column
|
||
prop="id"
|
||
:label="$t('admin.disassemblyOrders.list.id')"
|
||
width="80"
|
||
/>
|
||
|
||
<el-table-column
|
||
prop="orderNumber"
|
||
:label="$t('admin.disassemblyOrders.list.orderNumber')"
|
||
width="150"
|
||
/>
|
||
|
||
<el-table-column
|
||
prop="creatorName"
|
||
:label="$t('admin.disassemblyOrders.list.creatorName')"
|
||
width="120"
|
||
/>
|
||
|
||
<el-table-column
|
||
prop="status"
|
||
:label="$t('admin.disassemblyOrders.list.status')"
|
||
width="100"
|
||
>
|
||
<template #default="scope">
|
||
<el-tag :type="getStatusType(scope.row.status)">
|
||
{{ getStatusText(scope.row.status) }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column
|
||
prop="createTime"
|
||
:label="$t('admin.disassemblyOrders.list.createTime')"
|
||
width="160"
|
||
>
|
||
<template #default="scope">
|
||
{{ formatDate(scope.row.createTime) }}
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column
|
||
:label="$t('admin.disassemblyOrders.list.actions')"
|
||
width="200"
|
||
fixed="right"
|
||
>
|
||
<template #default="scope">
|
||
<div class="actions-container">
|
||
<el-button
|
||
type="primary"
|
||
size="small"
|
||
:icon="Tools"
|
||
@click="handleDisassemble(scope.row)"
|
||
>
|
||
{{ $t('admin.disassemblyOrders.list.disassembly') }}
|
||
</el-button>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
<div class="pagination-container">
|
||
<el-pagination
|
||
v-model:current-page="currentPage"
|
||
v-model:page-size="pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
:total="filteredOrdersList.length"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { useI18n } from 'vue-i18n'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { Refresh, Search, Document, Clock, Loading, Check, Van, Tools } from '@element-plus/icons-vue'
|
||
|
||
const { t } = useI18n()
|
||
const router = useRouter()
|
||
|
||
// 响应式数据
|
||
const loading = ref(false)
|
||
const currentPage = ref(1)
|
||
const pageSize = ref(10)
|
||
const total = ref(0)
|
||
const ordersList = ref([])
|
||
const selectedStatus = ref('')
|
||
const searchQuery = ref('')
|
||
|
||
// 统计数据
|
||
const disassemblyStats = ref({
|
||
total: 0,
|
||
pending: 0,
|
||
processing: 0
|
||
})
|
||
|
||
// 模拟数据
|
||
const mockOrders = [
|
||
{
|
||
id: 1,
|
||
orderNumber: 'ORD202311001',
|
||
creatorName: '张三',
|
||
status: 'pending',
|
||
createTime: '2023-11-20 10:30:00'
|
||
},
|
||
{
|
||
id: 2,
|
||
orderNumber: 'ORD202311002',
|
||
creatorName: '李四',
|
||
status: 'processing',
|
||
createTime: '2023-11-20 09:15:00'
|
||
},
|
||
{
|
||
id: 3,
|
||
orderNumber: 'ORD202311003',
|
||
creatorName: '王五',
|
||
status: 'pending',
|
||
createTime: '2023-11-19 16:45:00'
|
||
},
|
||
{
|
||
id: 4,
|
||
orderNumber: 'ORD202311004',
|
||
creatorName: '赵六',
|
||
status: 'processing',
|
||
createTime: '2023-11-19 14:20:00'
|
||
},
|
||
{
|
||
id: 5,
|
||
orderNumber: 'ORD202311005',
|
||
creatorName: '钱七',
|
||
status: 'pending',
|
||
createTime: '2023-11-18 11:10:00'
|
||
}
|
||
]
|
||
|
||
// 计算属性 - 筛选后的订单列表
|
||
const filteredOrdersList = computed(() => {
|
||
let filtered = [...ordersList.value]
|
||
|
||
// 按状态筛选
|
||
if (selectedStatus.value) {
|
||
filtered = filtered.filter(order => order.status === selectedStatus.value)
|
||
}
|
||
|
||
// 按搜索关键词筛选
|
||
if (searchQuery.value) {
|
||
const query = searchQuery.value.toLowerCase()
|
||
filtered = filtered.filter(order =>
|
||
order.orderNumber.toLowerCase().includes(query) ||
|
||
order.creatorName.toLowerCase().includes(query)
|
||
)
|
||
}
|
||
|
||
return filtered
|
||
})
|
||
|
||
// 格式化日期
|
||
const formatDate = (dateString) => {
|
||
const date = new Date(dateString)
|
||
return date.toLocaleString()
|
||
}
|
||
|
||
// 获取订单列表
|
||
const fetchOrders = () => {
|
||
loading.value = true
|
||
|
||
// 模拟API请求
|
||
setTimeout(() => {
|
||
// 这里应该是API调用,现在使用模拟数据
|
||
ordersList.value = mockOrders
|
||
total.value = mockOrders.length
|
||
|
||
// 计算统计数据
|
||
const stats = {
|
||
total: mockOrders.length,
|
||
pending: mockOrders.filter(order => order.status === 'pending').length,
|
||
processing: mockOrders.filter(order => order.status === 'processing').length
|
||
}
|
||
disassemblyStats.value = stats
|
||
|
||
loading.value = false
|
||
}, 500)
|
||
}
|
||
|
||
// 刷新订单列表
|
||
const refreshOrders = () => {
|
||
fetchOrders()
|
||
ElMessage.success(t('admin.disassemblyOrders.messages.refreshSuccess'))
|
||
}
|
||
|
||
// 重置筛选条件
|
||
const resetFilters = () => {
|
||
selectedStatus.value = ''
|
||
searchQuery.value = ''
|
||
fetchOrders()
|
||
}
|
||
|
||
// 计算属性 - 分页后的订单列表
|
||
const paginatedOrders = computed(() => {
|
||
const start = (currentPage.value - 1) * pageSize.value
|
||
const end = start + pageSize.value
|
||
return filteredOrdersList.value.slice(start, end)
|
||
})
|
||
|
||
// 获取状态文本
|
||
const getStatusText = (status) => {
|
||
const statusMap = {
|
||
'pending': t('admin.disassemblyOrders.detail.statusOptions.pending'),
|
||
'processing': t('admin.disassemblyOrders.detail.statusOptions.processing')
|
||
}
|
||
return statusMap[status] || status
|
||
}
|
||
|
||
// 获取拆解类型文本
|
||
const getDisassemblyTypeText = (type) => {
|
||
const typeMap = {
|
||
'full': t('admin.disassemblyOrders.detail.typeOptions.full'),
|
||
'partial': t('admin.disassemblyOrders.detail.typeOptions.partial'),
|
||
'custom': t('admin.disassemblyOrders.detail.typeOptions.custom')
|
||
}
|
||
return typeMap[type] || type
|
||
}
|
||
|
||
// 获取拆解类型标签类型
|
||
const getDisassemblyTypeTag = (type) => {
|
||
const typeMap = {
|
||
'full': 'success',
|
||
'partial': 'warning',
|
||
'custom': 'info'
|
||
}
|
||
return typeMap[type] || 'info'
|
||
}
|
||
|
||
// 处理拆件操作
|
||
const handleDisassemble = (order) => {
|
||
// 跳转到拆件页面
|
||
router.push({
|
||
name: 'AdminDisassemblyDetail',
|
||
params: { id: order.id }
|
||
})
|
||
}
|
||
|
||
// 获取状态标签类型
|
||
const getStatusType = (status) => {
|
||
const statusMap = {
|
||
pending: 'warning',
|
||
processing: 'primary'
|
||
}
|
||
return statusMap[status] || 'info'
|
||
}
|
||
|
||
// 分页相关
|
||
const handleSizeChange = (val) => {
|
||
pageSize.value = val
|
||
fetchOrders()
|
||
}
|
||
|
||
const handleCurrentChange = (val) => {
|
||
currentPage.value = val
|
||
fetchOrders()
|
||
}
|
||
|
||
// 组件挂载时获取数据
|
||
onMounted(() => {
|
||
fetchOrders()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 拆件订单管理页面样式 */
|
||
.admin-disassembly-orders {
|
||
padding: 24px;
|
||
max-height: 100vh;
|
||
}
|
||
|
||
/* 统计卡片样式 */
|
||
.disassembly-stats {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin-bottom: 20px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.stat-card {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
padding: 20px;
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||
display: flex;
|
||
align-items: center;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.stat-card:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.stat-icon {
|
||
width: 48px;
|
||
height: 48px;
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 15px;
|
||
font-size: 24px;
|
||
color: white;
|
||
}
|
||
|
||
.stat-icon.total {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
}
|
||
|
||
.stat-icon.pending {
|
||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||
}
|
||
|
||
.stat-icon.processing {
|
||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||
}
|
||
|
||
.stat-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.stat-number {
|
||
font-size: 32px;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
line-height: 1;
|
||
}
|
||
|
||
.stat-label {
|
||
color: #6b7280;
|
||
font-size: 14px;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
/* 筛选搜索区域 */
|
||
.disassembly-filters {
|
||
padding: 20px;
|
||
border-radius: 12px;
|
||
margin-bottom: 24px;
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: flex-end;
|
||
justify-content: flex-end;
|
||
overflow-x: auto;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.filter-group {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: flex-end;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.search-group {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
max-width: 300px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.filter-actions {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* 表格样式 */
|
||
.disassembly-table {
|
||
background: white;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
border: 1px solid #e5e7eb;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
/* 表格样式优化 */
|
||
.disassembly-table :deep(.el-table) {
|
||
width: 100% !important;
|
||
table-layout: auto;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__header) {
|
||
width: 100% !important;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__body) {
|
||
width: 100% !important;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__cell) {
|
||
padding: 8px 12px;
|
||
white-space: nowrap;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__row) {
|
||
height: 66px;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__header-wrapper) {
|
||
background-color: #f8fafc;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__header th) {
|
||
background-color: #f8fafc;
|
||
color: #374151;
|
||
font-weight: 600;
|
||
border-bottom: 2px solid #e5e7eb;
|
||
white-space: nowrap !important;
|
||
text-align: center;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table__header th .cell) {
|
||
white-space: nowrap !important;
|
||
word-break: keep-all;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
/* 操作按钮容器 */
|
||
.actions-container {
|
||
display: flex;
|
||
gap: 6px;
|
||
flex-wrap: nowrap;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.actions-container .el-button {
|
||
flex-shrink: 0;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 分页样式 */
|
||
.pagination-container {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding: 16px 0;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.admin-disassembly-orders {
|
||
padding: 16px;
|
||
}
|
||
|
||
.disassembly-stats {
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
}
|
||
|
||
.stat-card {
|
||
min-width: auto;
|
||
}
|
||
|
||
.disassembly-filters {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 12px;
|
||
}
|
||
|
||
.filter-group {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
|
||
.search-group {
|
||
min-width: auto;
|
||
max-width: none;
|
||
}
|
||
|
||
.filter-actions {
|
||
justify-content: center;
|
||
}
|
||
|
||
.actions-container {
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
}
|
||
|
||
/* 移动端表格优化 */
|
||
.disassembly-table {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.disassembly-table :deep(.el-table) {
|
||
min-width: 800px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 769px) and (max-width: 1024px) {
|
||
.disassembly-stats {
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.stat-card {
|
||
min-width: calc(50% - 10px);
|
||
}
|
||
|
||
.disassembly-filters {
|
||
flex-wrap: wrap;
|
||
}
|
||
}
|
||
</style> |