front/src/views/order/myOrders/index.vue
2026-01-24 11:55:01 +08:00

981 lines
31 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.

<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)"
>
&lt;
</a-button>
<span class="current-page">{{ currentPage }}</span>
<a-button
size="small"
:disabled="currentPage >= Math.ceil(totalCount / pageSize)"
@click="handlePageChange(currentPage + 1)"
>
&gt;
</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>