
<template>
<view class="page-container">
<view class="table-container">
<view class="scroll-area">
<view class="table-content">
<view class="table-row header-row">
<view class="table-cell" v-for="(col, index) in columns" :key="'h' + index" :style="{ width: col.width }">
{{ col.label }}
</view>
</view>
<view class="table-row" v-for="(item, rowIndex) in tableData" :key="'r' + rowIndex">
<view class="table-cell" v-for="(col, index) in columns" :key="'c' + rowIndex + index" :style="{ width: col.width }">
<template v-if="col.field === 'status'">
<view class="status-tag" :class="item[col.field] === '在职' ? 'active' : ''">
{{ item[col.field] }}
</view>
</template>
<template v-else>{{ item[col.field] }}</template>
</view>
</view>
</view>
</view>
<view class="fixed-columns">
<view class="table-row header-row">
<view class="table-cell" v-for="(col, index) in fixedColumns" :key="'fh' + index" :style="{ width: col.width }">
{{ col.label }}
</view>
</view>
<view class="table-row" v-for="(item, rowIndex) in tableData" :key="'fr' + rowIndex">
<view class="table-cell" v-for="(col, index) in fixedColumns" :key="'fc' + rowIndex + index" :style="{ width: col.width }">
{{ item[col.field] }}
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
const cellHeight = 56;
const fixedCount = 2;
const columns = ref([
{ label: 'ID', field: 'id', width: '80px' },
{ label: '姓名', field: 'name', width: '120px' },
{ label: '年龄', field: 'age', width: '80px' },
{ label: '邮箱', field: 'email', width: '200px' },
{ label: '地址', field: 'address', width: '300px' },
{ label: '电话', field: 'phone', width: '150px' },
{ label: '职位', field: 'position', width: '180px' },
{ label: '入职日期', field: 'hireDate', width: '150px' },
{ label: '状态', field: 'status', width: '100px' },
]);
const fixedColumns = computed(() => columns.value.slice(0, fixedCount));
const tableData = ref([
{
id: 1,
name: '张三',
age: 28,
email: 'zhangsan@example.com',
address: '北京市朝阳区建国路88号',
phone: '13800138000',
position: '前端开发工程师',
hireDate: '2020-03-15',
status: '在职',
},
{
id: 2,
name: '李四',
age: 32,
email: 'lisi@example.com',
address: '上海市浦东新区张江高科技园区',
phone: '13900139000',
position: '后端开发工程师',
hireDate: '2019-07-22',
status: '在职',
},
{
id: 3,
name: '王五',
age: 25,
email: 'wangwu@example.com',
address: '广州市天河区珠江新城',
phone: '13700137000',
position: 'UI设计师',
hireDate: '2021-01-10',
status: '离职',
},
{
id: 4,
name: '赵六',
age: 35,
email: 'zhaoliu@example.com',
address: '深圳市南山区科技园',
phone: '13600136000',
position: '产品经理',
hireDate: '2018-05-30',
status: '在职',
},
{
id: 5,
name: '孙七',
age: 29,
email: 'sunqi@example.com',
address: '杭州市西湖区西溪路',
phone: '13500135000',
position: '测试工程师',
hireDate: '2020-09-05',
status: '在职',
},
{
id: 6,
name: '周八',
age: 31,
email: 'zhouba@example.com',
address: '成都市高新区天府大道,这是一个比较长的地址用于测试单元格内容换行',
phone: '13400134000',
position: '数据分析师',
hireDate: '2019-11-18',
status: '在职',
},
]);
</script>
<style scoped>
.page-container {
padding: 16px;
background-color: #f5f7fa;
min-height: 100vh;
}
.page-title {
font-size: 20px;
font-weight: bold;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.table-container {
position: relative;
width: 100%;
max-height: 500px;
border: 1px solid #e5e7eb;
border-radius: 4px;
overflow: hidden;
background-color: #fff;
}
.scroll-area {
width: 100%;
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.table-content {
width: 1360px;
}
.table-row {
display: flex;
}
.header-row {
background-color: #f9fafb;
border-bottom: 1px solid #e5e7eb;
}
.table-cell {
width: 100px;
height: v-bind(cellHeight + 'px');
padding: 0 16px;
display: flex;
align-items: center;
border-right: 1px solid #e5e7eb;
border-bottom: 1px solid #e5e7eb;
font-size: 14px;
color: #333;
word-break: break-all;
box-sizing: border-box;
line-height: 1.5;
}
.table-row .table-cell:last-child {
border-right: none;
}
.header-row .table-cell {
font-weight: 500;
color: #666;
}
.table-row:not(.header-row):nth-child(even) .table-cell {
background-color: #fcfcfc;
}
.fixed-columns {
position: absolute;
top: 0;
left: 0;
height: 100%;
z-index: 10;
background-color: #fff;
border-right: 1px solid #e5e7eb;
pointer-events: none;
}
.fixed-columns .table-cell {
pointer-events: auto;
}
.status-tag {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
background-color: #fff2e8;
color: #ff7d00;
}
.status-tag.active {
background-color: #e6f7ed;
color: #00875a;
}
</style>