981 lines
31 KiB
Vue
981 lines
31 KiB
Vue
<script lang="ts" setup>
|
||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||
import { IconSettings } from '@arco-design/web-vue/es/icon';
|
||
import Handsontable from 'handsontable';
|
||
import 'handsontable/styles/handsontable.min.css';
|
||
import 'handsontable/styles/ht-theme-main.min.css';
|
||
import { useI18n } from 'vue-i18n';
|
||
import dayjs from 'dayjs';
|
||
|
||
defineOptions({
|
||
name: 'MyOrders',
|
||
});
|
||
|
||
const { t } = useI18n();
|
||
|
||
// 当前激活的标签页
|
||
const activeTab = ref('all');
|
||
|
||
// 标签页配置
|
||
const tabs = ref([
|
||
{ key: 'all', labelKey: 'order.myOrders.tabs.all', count: null },
|
||
{ key: 'draft', labelKey: 'order.myOrders.tabs.draft', count: 0 },
|
||
{ key: 'predeclared', labelKey: 'order.myOrders.tabs.predeclared', count: 0 },
|
||
{ key: 'received', labelKey: 'order.myOrders.tabs.received', count: 0 },
|
||
{ key: 'pendingPayment', labelKey: 'order.myOrders.tabs.pendingPayment', count: 0 },
|
||
{ key: 'pendingShip', labelKey: 'order.myOrders.tabs.pendingShip', count: 0 },
|
||
{ key: 'pendingOnline', labelKey: 'order.myOrders.tabs.pendingOnline', count: 0 },
|
||
{ key: 'shipping', labelKey: 'order.myOrders.tabs.shipping', count: 0 },
|
||
{ key: 'deliverySuccess', labelKey: 'order.myOrders.tabs.deliverySuccess', count: 0 },
|
||
{ key: 'deliveryFailed', labelKey: 'order.myOrders.tabs.deliveryFailed', count: 0 },
|
||
{ key: 'problematic', labelKey: 'order.myOrders.tabs.problematic', count: 0 },
|
||
{ key: 'deleted', labelKey: 'order.myOrders.tabs.deleted', count: null },
|
||
{ key: 'claimed', labelKey: 'order.myOrders.tabs.claimed', count: null },
|
||
]);
|
||
|
||
// 分页相关数据
|
||
const currentPage = ref(1);
|
||
const pageSize = ref(20);
|
||
const totalCount = ref(20);
|
||
const jumpPage = ref('');
|
||
|
||
// 生成模拟订单数据
|
||
const generateMockOrders = () => {
|
||
const orders = []
|
||
const countries = ['US', 'GB', 'DE', 'FR', 'CA', 'AU', 'JP', 'KR']
|
||
const cities = ['New York', 'Los Angeles', 'London', 'Paris', 'Berlin', 'Toronto', 'Sydney', 'Tokyo', 'Seoul', 'Shanghai']
|
||
const states = ['California', 'New York', 'Texas', 'Florida', 'Illinois', 'Ontario', 'Quebec', 'NSW', 'Tokyo', 'Seoul']
|
||
const warehouses = ['深圳仓', '东莞仓', '广州仓', '上海仓', '北京仓']
|
||
const shippingMethods = ['美国空运专线(普货)', '美国空运特惠专线898(普货)', 'DHL空运快递', 'EMS国际快递', 'FedEx国际快递']
|
||
const orderStatuses = ['待支付', '草稿', '已预报', '已收货', '待发货', '待上网', '运输中', '派送成功', '派送失败', '问题件', '已删除', '已理赔']
|
||
const statuses = ['pendingPayment', 'draft', 'predeclared', 'received', 'pendingShip', 'pendingOnline', 'shipping', 'deliverySuccess', 'deliveryFailed', 'problematic', 'deleted', 'claimed']
|
||
|
||
for (let i = 1; i <= 20; i++) {
|
||
const country = countries[Math.floor(Math.random() * countries.length)]
|
||
const city = cities[Math.floor(Math.random() * cities.length)]
|
||
const state = states[Math.floor(Math.random() * states.length)]
|
||
const warehouse = warehouses[Math.floor(Math.random() * warehouses.length)]
|
||
const shippingMethod = shippingMethods[Math.floor(Math.random() * shippingMethods.length)]
|
||
const statusIndex = Math.floor(Math.random() * statuses.length)
|
||
const orderStatus = orderStatuses[statusIndex]
|
||
const status = statuses[statusIndex]
|
||
|
||
// 生成时间(随机在过去30天内)
|
||
const daysAgo = Math.floor(Math.random() * 30)
|
||
const createTime = dayjs().subtract(daysAgo, 'day').format('YYYY-MM-DD HH:mm:ss')
|
||
|
||
// 根据订单状态生成相应的时间
|
||
let receiveTime = ''
|
||
let shipTime = ''
|
||
let payTime = ''
|
||
let signTime = ''
|
||
|
||
if (status === 'pendingPayment') {
|
||
// 待支付:只有创建时间
|
||
payTime = ''
|
||
} else if (status === 'draft' || status === 'predeclared') {
|
||
// 草稿或已预报:只有创建时间
|
||
} else if (status === 'received') {
|
||
// 已收货:有创建时间和收货时间
|
||
receiveTime = daysAgo > 2 ? dayjs().subtract(daysAgo - 2, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
} else if (status === 'pendingShip') {
|
||
// 待发货:有创建时间和收货时间
|
||
receiveTime = daysAgo > 2 ? dayjs().subtract(daysAgo - 2, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
} else if (status === 'pendingOnline') {
|
||
// 待上网:有创建时间、收货时间、发货时间
|
||
receiveTime = daysAgo > 3 ? dayjs().subtract(daysAgo - 3, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
shipTime = daysAgo > 2 ? dayjs().subtract(daysAgo - 2, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
} else if (status === 'shipping') {
|
||
// 运输中:有创建时间、收货时间、发货时间
|
||
receiveTime = daysAgo > 3 ? dayjs().subtract(daysAgo - 3, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
shipTime = daysAgo > 1 ? dayjs().subtract(daysAgo - 1, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
} else if (status === 'completed') {
|
||
// 已完成:有所有时间
|
||
receiveTime = daysAgo > 5 ? dayjs().subtract(daysAgo - 5, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
shipTime = daysAgo > 4 ? dayjs().subtract(daysAgo - 4, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
payTime = daysAgo > 3 ? dayjs().subtract(daysAgo - 3, 'day').format('YYYY-MM-DD HH:mm:ss') : createTime
|
||
signTime = daysAgo > 0 ? dayjs().subtract(Math.floor(Math.random() * daysAgo), 'day').format('YYYY-MM-DD HH:mm:ss') : ''
|
||
}
|
||
|
||
orders.push({
|
||
id: i,
|
||
waybillNo: `LP${String(Math.floor(Math.random() * 100000000000000)).padStart(14, '0')}`,
|
||
customerOrderNo: `CUST${String(Math.floor(Math.random() * 100000000000)).padStart(12, '0')}`,
|
||
trackingNo: `TRK${String(Math.floor(Math.random() * 100000000000000)).padStart(15, '0')}`,
|
||
shippingMethod: shippingMethod,
|
||
consigneeCountry: country,
|
||
chargeableWeight: (Math.random() * 10 + 0.1).toFixed(2),
|
||
receivableAmount: (Math.random() * 500 + 50).toFixed(2),
|
||
consignee: `收件人${i}`,
|
||
consigneePhone: `1${Math.floor(Math.random() * 1000000000).toString().padStart(10, '0')}`,
|
||
consigneeAddress: `${city}市${state}区${Math.floor(Math.random() * 999) + 1}号`,
|
||
consigneePostcode: String(Math.floor(Math.random() * 100000)).padStart(5, '0'),
|
||
consigneeState: state,
|
||
consigneeCity: city,
|
||
ioss: Math.random() > 0.5 ? `IOSS${String(Math.floor(Math.random() * 1000000000)).padStart(12, '0')}` : '',
|
||
eori: Math.random() > 0.5 ? `EORI${String(Math.floor(Math.random() * 1000000000)).padStart(12, '0')}` : '',
|
||
orderStatus: orderStatus,
|
||
status: status,
|
||
createTime: createTime,
|
||
receiveTime: receiveTime,
|
||
shipTime: shipTime,
|
||
payTime: payTime,
|
||
signTime: signTime,
|
||
warehouse: warehouse
|
||
})
|
||
}
|
||
return orders
|
||
}
|
||
|
||
// 订单列表数据
|
||
const orderList = ref(generateMockOrders())
|
||
|
||
// 选中的行数
|
||
const selectedRowCount = ref(0)
|
||
|
||
// 标签页切换
|
||
const handleTabChange = (key: string) => {
|
||
activeTab.value = key;
|
||
};
|
||
|
||
// 操作按钮处理
|
||
const handlePay = () => {
|
||
};
|
||
|
||
const handlePreDeclare = () => {
|
||
};
|
||
|
||
const handleIntercept = () => {
|
||
};
|
||
|
||
const handleCancelIntercept = () => {
|
||
};
|
||
|
||
const handleDelete = () => {
|
||
};
|
||
|
||
const handlePrint = () => {
|
||
};
|
||
|
||
const handleExport = () => {
|
||
};
|
||
|
||
const handleModifyOrder = () => {
|
||
};
|
||
|
||
const handleSettings = () => {
|
||
};
|
||
|
||
// 分页处理函数
|
||
const handlePageChange = (page: number) => {
|
||
currentPage.value = page;
|
||
};
|
||
|
||
const handlePageSizeChange = (size: number) => {
|
||
pageSize.value = size;
|
||
currentPage.value = 1;
|
||
};
|
||
|
||
const handleJumpPage = () => {
|
||
const page = Number(jumpPage.value);
|
||
if (page > 0 && page <= Math.ceil(totalCount.value / pageSize.value)) {
|
||
currentPage.value = page;
|
||
} else {
|
||
}
|
||
};
|
||
|
||
// Handsontable 相关
|
||
const hotContainer = ref<HTMLElement | null>(null);
|
||
let hotInstance: Handsontable | null = null;
|
||
|
||
// 初始化 Handsontable
|
||
const initHandsontable = () => {
|
||
if (!hotContainer.value) {
|
||
return;
|
||
}
|
||
|
||
// 如果已有实例,先销毁
|
||
if (hotInstance) {
|
||
hotInstance.destroy();
|
||
hotInstance = null;
|
||
}
|
||
|
||
// 准备表格列配置(23个字段)
|
||
const columns = Array.from({ length: 23 }, (_, i) => ({
|
||
data: i,
|
||
type: 'text',
|
||
readOnly: true
|
||
}));
|
||
|
||
// 准备表格数据
|
||
const data = orderList.value.map((item, index) => [
|
||
index + 1, // 序号
|
||
item.waybillNo || '', // 运单号
|
||
item.customerOrderNo || '', // 客户单号
|
||
item.trackingNo || '', // 跟踪号
|
||
item.shippingMethod || '', // 运输方式
|
||
item.consigneeCountry || '', // 收件人国家
|
||
item.chargeableWeight || '', // 计费重
|
||
item.receivableAmount || '', // 应收费用
|
||
item.consignee || '', // 收件人
|
||
item.consigneePhone || '', // 收件人电话
|
||
item.consigneeAddress || '', // 收件人地址
|
||
item.consigneePostcode || '', // 收件人邮编
|
||
item.consigneeState || '', // 收件人州省
|
||
item.consigneeCity || '', // 收件人城市
|
||
item.ioss || '', // IOSS
|
||
item.eori || '', // EORI
|
||
item.orderStatus || '', // 订单状态
|
||
item.createTime || '', // 创建时间
|
||
item.receiveTime || '', // 收货时间
|
||
item.shipTime || '', // 发货时间
|
||
item.payTime || '', // 支付时间
|
||
item.signTime || '', // 签收时间
|
||
item.warehouse || '' // 仓库
|
||
]);
|
||
|
||
// 计算表格高度:表头高度(约50px) + 数据行数 * 每行高度(约50px,包含padding和border)
|
||
// 确保能显示全部20条数据,最小高度设为1000px
|
||
const headerHeight = 50;
|
||
const rowHeight = 50;
|
||
const minHeight = 1000;
|
||
const calculatedHeight = Math.max(headerHeight + data.length * rowHeight, minHeight);
|
||
|
||
try {
|
||
hotInstance = new Handsontable(hotContainer.value, {
|
||
data: data,
|
||
columns: columns,
|
||
theme: 'ht-theme-main',
|
||
colHeaders: [
|
||
t('order.myOrders.table.serialNo'),
|
||
t('order.myOrders.table.waybillNo'),
|
||
t('order.myOrders.table.customerOrderNo'),
|
||
t('order.myOrders.table.trackingNo'),
|
||
t('order.myOrders.table.shippingMethod'),
|
||
t('order.myOrders.table.consigneeCountry'),
|
||
t('order.myOrders.table.chargeableWeight'),
|
||
t('order.myOrders.table.receivableAmount'),
|
||
t('order.myOrders.table.consignee'),
|
||
t('order.myOrders.table.consigneePhone'),
|
||
t('order.myOrders.table.consigneeAddress'),
|
||
t('order.myOrders.table.consigneePostcode'),
|
||
t('order.myOrders.table.consigneeState'),
|
||
t('order.myOrders.table.consigneeCity'),
|
||
t('order.myOrders.table.ioss'),
|
||
t('order.myOrders.table.eori'),
|
||
t('order.myOrders.table.orderStatus'),
|
||
t('order.myOrders.table.createTime'),
|
||
t('order.myOrders.table.receiveTime'),
|
||
t('order.myOrders.table.shipTime'),
|
||
t('order.myOrders.table.payTime'),
|
||
t('order.myOrders.table.signTime'),
|
||
t('order.myOrders.table.warehouse')
|
||
],
|
||
rowHeaders: false,
|
||
selectionMode: 'multiple',
|
||
width: '100%',
|
||
height: calculatedHeight,
|
||
licenseKey: 'non-commercial-and-evaluation',
|
||
readOnly: true,
|
||
contextMenu: false,
|
||
manualColumnResize: true,
|
||
manualRowResize: true,
|
||
stretchH: 'all',
|
||
className: 'htCenter',
|
||
search: {
|
||
callback: function(queryResult: any, row: number, col: number, value: any) {
|
||
// 搜索回调函数
|
||
}
|
||
},
|
||
filters: true,
|
||
dropdownMenu: true,
|
||
cells: function(row: number, col: number) {
|
||
const cellProperties: any = {};
|
||
|
||
// 所有单元格居中显示
|
||
cellProperties.renderer = function(instance: any, td: any, row: number, col: number, prop: any, value: any) {
|
||
td.style.textAlign = 'center';
|
||
td.style.verticalAlign = 'middle';
|
||
|
||
// 序号列特殊样式
|
||
if (col === 0) {
|
||
td.style.color = '#8c8c8c';
|
||
td.style.fontWeight = '500';
|
||
}
|
||
|
||
// 订单状态列(第16列,索引16)用标签显示
|
||
if (col === 16 && row >= 0 && row < orderList.value.length) {
|
||
const order = orderList.value[row];
|
||
const status = order.orderStatus || '';
|
||
|
||
// 根据状态设置标签颜色
|
||
let tagColor = '#86909c'; // 默认灰色
|
||
let tagBgColor = '#f2f3f5'; // 默认背景色
|
||
let statusKey = '';
|
||
|
||
if (status === '待支付' || status === 'pendingPayment') {
|
||
tagColor = '#ff7d00';
|
||
tagBgColor = '#fff7e6';
|
||
statusKey = 'order.myOrders.status.pendingPayment';
|
||
} else if (status === '草稿' || status === 'draft') {
|
||
tagColor = '#86909c';
|
||
tagBgColor = '#f2f3f5';
|
||
statusKey = 'order.myOrders.status.draft';
|
||
} else if (status === '已预报' || status === 'predeclared') {
|
||
tagColor = '#165dff';
|
||
tagBgColor = '#e8f3ff';
|
||
statusKey = 'order.myOrders.status.predeclared';
|
||
} else if (status === '已收货' || status === 'received') {
|
||
tagColor = '#00b42a';
|
||
tagBgColor = '#e8f8e8';
|
||
statusKey = 'order.myOrders.status.received';
|
||
} else if (status === '待发货' || status === 'pendingShip') {
|
||
tagColor = '#ff7d00';
|
||
tagBgColor = '#fff7e6';
|
||
statusKey = 'order.myOrders.status.pendingShip';
|
||
} else if (status === '待上网' || status === 'pendingOnline') {
|
||
tagColor = '#165dff';
|
||
tagBgColor = '#e8f3ff';
|
||
statusKey = 'order.myOrders.status.pendingOnline';
|
||
} else if (status === '运输中' || status === 'shipping') {
|
||
tagColor = '#165dff';
|
||
tagBgColor = '#e8f3ff';
|
||
statusKey = 'order.myOrders.status.shipping';
|
||
} else if (status === '派送成功' || status === 'deliverySuccess') {
|
||
tagColor = '#00b42a';
|
||
tagBgColor = '#e8f8e8';
|
||
statusKey = 'order.myOrders.status.deliverySuccess';
|
||
} else if (status === '派送失败' || status === 'deliveryFailed') {
|
||
tagColor = '#f53f3f';
|
||
tagBgColor = '#ffece8';
|
||
statusKey = 'order.myOrders.status.deliveryFailed';
|
||
} else if (status === '问题件' || status === 'problematic') {
|
||
tagColor = '#f53f3f';
|
||
tagBgColor = '#ffece8';
|
||
statusKey = 'order.myOrders.status.problematic';
|
||
} else if (status === '已删除' || status === 'deleted') {
|
||
tagColor = '#86909c';
|
||
tagBgColor = '#f2f3f5';
|
||
statusKey = 'order.myOrders.status.deleted';
|
||
} else if (status === '已理赔' || status === 'claimed') {
|
||
tagColor = '#722ed1';
|
||
tagBgColor = '#f7e8ff';
|
||
statusKey = 'order.myOrders.status.claimed';
|
||
}
|
||
|
||
// 创建标签HTML,使用翻译后的状态文本
|
||
const statusText = statusKey ? t(statusKey) : status;
|
||
td.innerHTML = `<span style="display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 12px; color: ${tagColor}; background-color: ${tagBgColor}; white-space: nowrap;">${statusText}</span>`;
|
||
} else {
|
||
// 其他列正常显示
|
||
td.innerHTML = value || '';
|
||
}
|
||
|
||
// 根据订单状态设置行背景颜色
|
||
if (row >= 0 && row < orderList.value.length) {
|
||
const order = orderList.value[row];
|
||
if (order.orderStatus === '问题件' || order.status === 'problematic') {
|
||
td.style.backgroundColor = '#fff1f0'; // 淡红色
|
||
} else if (order.orderStatus === '待支付' || order.status === 'pendingPayment') {
|
||
td.style.backgroundColor = '#fffbe6'; // 淡黄色
|
||
}
|
||
}
|
||
};
|
||
|
||
return cellProperties;
|
||
},
|
||
afterSelectionEnd: function(r: number, c: number, r2: number, c2: number) {
|
||
// 监听选中变化
|
||
if (hotInstance) {
|
||
const selected = hotInstance.getSelected() || [];
|
||
// 计算选中的行数(去重),排除表头行(row === -1)
|
||
const selectedRows = new Set<number>();
|
||
selected.forEach(([rowStart, colStart, rowEnd, colEnd]: number[]) => {
|
||
const startRow = Math.min(rowStart, rowEnd);
|
||
const endRow = Math.max(rowStart, rowEnd);
|
||
for (let i = startRow; i <= endRow; i++) {
|
||
// 排除表头行(row === -1)和无效行
|
||
if (i >= 0 && i < orderList.value.length) {
|
||
selectedRows.add(i);
|
||
}
|
||
}
|
||
});
|
||
selectedRowCount.value = selectedRows.size;
|
||
}
|
||
}
|
||
});
|
||
} catch (error) {
|
||
}
|
||
};
|
||
|
||
// 组件挂载后初始化表格
|
||
onMounted(() => {
|
||
nextTick(() => {
|
||
initHandsontable();
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="my-orders-container">
|
||
<!-- 标签页导航和操作按钮 -->
|
||
<div class="tabs-actions-section">
|
||
<div class="tabs-container">
|
||
<div
|
||
v-for="tab in tabs"
|
||
:key="tab.key"
|
||
:class="['tab-item', { active: activeTab === tab.key }]"
|
||
@click="handleTabChange(tab.key)"
|
||
>
|
||
<span class="tab-label">{{ tab.label || $t(tab.labelKey) }}</span>
|
||
<span v-if="tab.count !== null" class="tab-count">({{ tab.count }})</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="actions-right">
|
||
<a-button class="btn-pay" @click="handlePay">{{ t('order.myOrders.actions.pay') }}</a-button>
|
||
<a-button class="btn-predeclare" @click="handlePreDeclare">{{ t('order.myOrders.actions.predeclare') }}</a-button>
|
||
<a-button class="btn-intercept" @click="handleIntercept">{{ t('order.myOrders.actions.intercept') }}</a-button>
|
||
<a-button class="btn-cancel-intercept" @click="handleCancelIntercept">{{ t('order.myOrders.actions.cancelIntercept') }}</a-button>
|
||
<a-button class="btn-delete" @click="handleDelete">{{ t('order.myOrders.actions.delete') }}</a-button>
|
||
<a-button class="btn-print" @click="handlePrint">{{ t('order.myOrders.actions.print') }}</a-button>
|
||
<a-button class="btn-export" @click="handleExport">{{ t('order.myOrders.actions.export') }}</a-button>
|
||
<a-button class="btn-modify" @click="handleModifyOrder">{{ t('order.myOrders.actions.modifyOrder') }}</a-button>
|
||
<a-button class="btn-settings" @click="handleSettings">
|
||
<icon-settings />
|
||
</a-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 订单表格区域 -->
|
||
<div class="table-section">
|
||
<!-- 表格操作按钮和分页控制 -->
|
||
<div class="table-toolbar">
|
||
<div class="toolbar-left">
|
||
<span class="selected-count">
|
||
{{ t('order.myOrders.selectedCount', { count: selectedRowCount }) }}
|
||
</span>
|
||
</div>
|
||
|
||
<div class="toolbar-right">
|
||
<div class="pagination-controls">
|
||
<span class="total-records">
|
||
{{ $t('order.myOrders.pagination.totalRecords', { count: totalCount }) }}
|
||
</span>
|
||
<a-button
|
||
size="small"
|
||
:disabled="currentPage <= 1"
|
||
@click="handlePageChange(currentPage - 1)"
|
||
>
|
||
<
|
||
</a-button>
|
||
<span class="current-page">{{ currentPage }}</span>
|
||
<a-button
|
||
size="small"
|
||
:disabled="currentPage >= Math.ceil(totalCount / pageSize)"
|
||
@click="handlePageChange(currentPage + 1)"
|
||
>
|
||
>
|
||
</a-button>
|
||
<a-select
|
||
v-model="pageSize"
|
||
size="small"
|
||
class="page-size-select"
|
||
@change="handlePageSizeChange"
|
||
>
|
||
<a-option :value="20">20</a-option>
|
||
<a-option :value="50">50</a-option>
|
||
<a-option :value="100">100</a-option>
|
||
<a-option :value="200">200</a-option>
|
||
</a-select>
|
||
<span class="page-size-text">{{ $t('order.myOrders.pagination.perPage') }}</span>
|
||
<span class="go-to-text">{{ $t('order.myOrders.pagination.goto') }}</span>
|
||
<a-input
|
||
v-model="jumpPage"
|
||
size="small"
|
||
class="jump-input"
|
||
@keyup.enter="handleJumpPage"
|
||
/>
|
||
<span class="page-text">{{ $t('order.myOrders.pagination.page') }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="handsontable-container">
|
||
<div ref="hotContainer" class="handsontable-wrapper"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="less" scoped>
|
||
.my-orders-container {
|
||
padding: 24px;
|
||
background-color: #f5f5f5;
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.page-header {
|
||
margin-bottom: 24px;
|
||
|
||
h2 {
|
||
margin: 0;
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
color: #262626;
|
||
}
|
||
}
|
||
|
||
.tabs-actions-section {
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
padding: 0 24px;
|
||
margin-bottom: 16px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.tabs-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.tab-item {
|
||
padding: 16px 20px;
|
||
cursor: pointer;
|
||
border-bottom: 3px solid transparent;
|
||
transition: all 0.3s;
|
||
position: relative;
|
||
|
||
&:hover {
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
&.active {
|
||
border-bottom-color: #2D8C8C;
|
||
|
||
.tab-label {
|
||
color: #2D8C8C;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.tab-label {
|
||
font-size: 14px;
|
||
color: #262626;
|
||
transition: color 0.3s;
|
||
}
|
||
|
||
.tab-count {
|
||
font-size: 12px;
|
||
color: #8c8c8c;
|
||
margin-left: 4px;
|
||
}
|
||
}
|
||
|
||
.actions-right {
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
padding: 16px 0;
|
||
|
||
.arco-btn {
|
||
border-radius: 20px;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
border: 2px solid;
|
||
position: relative;
|
||
overflow: hidden;
|
||
padding: 8px 16px;
|
||
height: auto;
|
||
|
||
// 支付按钮 - 淡黄色
|
||
&.btn-pay {
|
||
background: #fffbe6;
|
||
border-color: #ffd666;
|
||
color: #d46b08;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #fff7d1;
|
||
border-color: #ffc53d;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #fff1b8;
|
||
border-color: #ffb020;
|
||
}
|
||
}
|
||
|
||
// 预报按钮 - 深青色
|
||
&.btn-predeclare {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 拦截按钮 - 深青色
|
||
&.btn-intercept {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 取消拦截按钮 - 深青色
|
||
&.btn-cancel-intercept {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 删除按钮 - 深青色
|
||
&.btn-delete {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 打印按钮 - 深青色
|
||
&.btn-print {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 导出按钮 - 深青色
|
||
&.btn-export {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 修改订单按钮 - 深青色
|
||
&.btn-modify {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 设置按钮 - 深青色
|
||
&.btn-settings {
|
||
background: #2D8C8C;
|
||
border-color: #2D8C8C;
|
||
color: #ffffff;
|
||
padding: 8px 12px;
|
||
min-width: 36px;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 禁用状态
|
||
&:disabled {
|
||
opacity: 1;
|
||
cursor: not-allowed;
|
||
background: rgba(169, 169, 169, 0.8) !important;
|
||
border-color: rgba(169, 169, 169, 0.8) !important;
|
||
color: #ffffff !important;
|
||
transform: none !important;
|
||
box-shadow: none !important;
|
||
}
|
||
}
|
||
}
|
||
|
||
.table-section {
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
padding: 24px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.table-toolbar {
|
||
margin-bottom: 8px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.toolbar-left {
|
||
flex: 1;
|
||
|
||
.selected-count {
|
||
font-size: 14px;
|
||
color: #4e5969;
|
||
|
||
.count-number {
|
||
color: #f53f3f;
|
||
font-weight: 600;
|
||
margin: 0 2px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.toolbar-right {
|
||
.pagination-controls {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 14px;
|
||
white-space: nowrap;
|
||
flex-wrap: nowrap;
|
||
|
||
.total-records {
|
||
color: #4e5969;
|
||
margin-right: 8px;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.current-page {
|
||
color: #1684fc;
|
||
font-weight: 500;
|
||
min-width: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.page-size-select {
|
||
width: 110px;
|
||
}
|
||
|
||
.go-to-text {
|
||
color: #4e5969;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.jump-input {
|
||
width: 50px;
|
||
}
|
||
|
||
.page-text {
|
||
color: #4e5969;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.arco-btn {
|
||
min-width: 24px;
|
||
height: 24px;
|
||
padding: 0 6px;
|
||
border-radius: 4px;
|
||
|
||
&:disabled {
|
||
opacity: 0.5;
|
||
}
|
||
}
|
||
|
||
.arco-select {
|
||
.arco-select-view {
|
||
height: 24px;
|
||
border-radius: 4px;
|
||
}
|
||
}
|
||
|
||
.arco-input {
|
||
height: 24px;
|
||
border-radius: 4px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.handsontable-container {
|
||
width: 100%;
|
||
border: 0.5px solid #f0f0f0 !important;
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
|
||
.handsontable-wrapper {
|
||
width: 100%;
|
||
|
||
:deep(.handsontable) {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
border: none !important;
|
||
|
||
// 覆盖 Handsontable 默认的 table 边框
|
||
table {
|
||
border: none !important;
|
||
}
|
||
|
||
.ht_master,
|
||
.ht_clone_top,
|
||
.ht_clone_left,
|
||
.ht_clone_corner {
|
||
border: none !important;
|
||
}
|
||
|
||
.wtHolder {
|
||
border: none !important;
|
||
}
|
||
|
||
.htCore {
|
||
border-collapse: separate;
|
||
border-spacing: 0;
|
||
border: none !important;
|
||
|
||
td {
|
||
border-right: 0.5px solid #f0f0f0 !important;
|
||
border-bottom: 0.5px solid #f0f0f0 !important;
|
||
border-top: none !important;
|
||
border-left: none !important;
|
||
padding: 7px 16px;
|
||
font-size: 13px;
|
||
line-height: 1.4;
|
||
color: #262626;
|
||
transition: all 0.2s ease;
|
||
background: #fff;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
|
||
&:hover {
|
||
background-color: #fafafa;
|
||
}
|
||
}
|
||
|
||
tr {
|
||
transition: all 0.2s ease;
|
||
|
||
&:hover {
|
||
td {
|
||
// hover时,如果单元格已经有背景色(状态背景),则稍微加深
|
||
// 否则使用默认hover颜色
|
||
&:not([style*="background-color"]) {
|
||
background-color: #fafafa;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
th {
|
||
background: #f5f5f5 !important; // 表头背景颜色改为淡灰色
|
||
border-right: 0.5px solid #f0f0f0 !important;
|
||
border-bottom: 0.5px solid #f0f0f0 !important;
|
||
border-top: none !important;
|
||
border-left: none !important;
|
||
}
|
||
|
||
// 隐藏筛选图标的边框
|
||
.changeType {
|
||
border: none !important;
|
||
box-shadow: none !important;
|
||
background: transparent !important;
|
||
}
|
||
|
||
// 隐藏筛选图标容器的边框
|
||
.ht_master .ht_clone_top th .changeType,
|
||
.ht_clone_top th .changeType,
|
||
.htCore th .changeType,
|
||
th .changeType {
|
||
border: none !important;
|
||
box-shadow: none !important;
|
||
background: transparent !important;
|
||
}
|
||
}
|
||
|
||
.ht_master .wtHolder {
|
||
overflow: auto;
|
||
}
|
||
|
||
.handsontableInput {
|
||
display: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 响应式设计
|
||
@media (max-width: 768px) {
|
||
.tabs-container {
|
||
overflow-x: auto;
|
||
flex-wrap: nowrap;
|
||
}
|
||
|
||
.actions-right {
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
}
|
||
|
||
.action-btn {
|
||
font-size: 12px;
|
||
padding: 0 8px;
|
||
height: 28px;
|
||
}
|
||
}
|
||
</style> |