deotalandAi/apps/FrontendDesigner/src/views/admin/AdminDisassemblyOrders.vue

614 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>