vue3+ts,tag样式使用的是colorUi 的tag 和 bg 样式 ,然后改了单位,合并通过table 的 span-method 实现
1、实现效果
2、代码
<template>
<div class="app-container">
<el-card shadow="never" class="table-container">
<el-table ref="dataTableRef" class="table-card-container" :border="false" :span-method="spanMethod" :data="state.data" size="large">
<el-table-column align="center" label="学员" prop="student" fixed />
<el-table-column align="center" label="身份" prop="role" fixed />
<el-table-column align="center" label="培养月数" prop="studyMonth" width="100" fixed />
<el-table-column align="center" label="轮转月数" prop="roteMonth" width="100" fixed />
<el-table-column align="center">
<template #header>
<div class="table-head">
<div class="header-item">
<div class="centered-content">
{{ `${state.command}年` }}
<el-dropdown @command="handleCommand">
<i-ep-arrow-down class="action-more" />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="year in state.years" :key="year" :command="year"> {{ year }}年 </el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
</template>
<template v-for="(month, index) in 12" :key="index">
<el-table-column :label="`${month}月`" :prop="`departments[${month - 1}]`" align="center">
<template #default="{ row: { departments } }">
<span round class="cu-tag light round" :class="colors[departments[month - 1]]" style="width: 100%">
{{ departments[month - 1] }}
</span>
</template>
</el-table-column>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script setup lang="ts">
interface RoteObj {
student: string;
role: string;
studyMonth: string;
roteMonth: string;
year: string;
departments: [];
}
const state = reactive({
command: 2023,
years: [2023, 2024, 2025],
data: [
{
student: '张三',
role: '专硕',
studyMonth: '1',
roteMonth: '1',
year: '2023',
departments: ['骨科', '麻醉科', '超声科', '超声科', '儿科', '重症医学科', '重症医学科', '消化内科', '消化内科', '急诊科', '急诊科', '急诊科'],
},
{
student: '李四',
role: '专硕',
studyMonth: '1',
roteMonth: '1',
year: '2023',
departments: ['骨科', '麻醉科', '麻醉科', '骨科', '骨科', '急诊科', '儿科', '消化内科', '重症医学科', '重症医学科', '急诊科', '急诊科'],
},
{
student: '王五',
role: '专硕',
studyMonth: '1',
roteMonth: '1',
year: '2023',
departments: ['重症医学科', '重症医学科', '儿科', '儿科', '骨科', '骨科', '重症医学科', '消化内科', '消化内科', '急诊科', '超声科', '超声科'],
},
{
student: '赵六',
role: '专硕',
studyMonth: '1',
roteMonth: '1',
year: '2023',
departments: ['骨科', '骨科', '骨科', '超声科', '重症医学科', '重症医学科', '重症医学科', '消化内科', '消化内科', '急诊科', '急诊科', '急诊科'],
},
],
});
const colors = {
骨科: 'bg-red',
麻醉科: 'bg-orange',
超声科: 'bg-yellow',
重症医学科: 'bg-olive',
消化内科: 'bg-green',
急诊科: 'bg-cyan',
儿科: 'bg-blue',
};
const spanMethod = ({ row, column, rowIndex, columnIndex }: { row: RoteObj; column: any; rowIndex: number; columnIndex: number }) => {
// console.log(row, column, rowIndex, columnIndex);
// 科室表格开始列下标
if (columnIndex > 3) {
const k = columnIndex - 4;
const { departments } = row;
const department = departments[k];
if (k > 0 && department == departments[k - 1]) return [0, 0];
else if (k < 11) {
const span = [0, 0];
for (let i = k; i < departments.length; i++) {
if (departments[i] == department) {
span[1] += 1;
} else break;
}
if (span[1] > 0) {
span[0] = 1;
return span;
}
}
}
};
/**
* 选择菜单
* @param command
*/
const handleCommand = (command: number) => {
state.command = command;
};
</script>
<style lang="scss" scoped>
.table-container {
:deep(.cell) {
padding: 0 !important;
}
:deep(td) {
border-right: 0 !important;
padding-right: 1px;
}
}
/* ==================
徽章
==================== */
.cu-tag {
font-size: 14px;
vertical-align: middle;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0px 8px;
height: 24px;
font-family:
Helvetica Neue,
Helvetica,
sans-serif;
white-space: nowrap;
}
.cu-tag:not([class*='bg']):not([class*='line']) {
background-color: #f1f1f1;
}
.cu-tag[class*='line-']::after {
content: ' ';
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border: 1px solid currentColor;
transform: scale(0.5);
transform-origin: 0 0;
box-sizing: border-box;
border-radius: inherit;
z-index: 1;
pointer-events: none;
}
.cu-tag.radius[class*='line']::after {
border-radius: 6px;
}
.cu-tag.round {
border-radius: 500px;
}
.cu-tag[class*='line-']::after {
border-radius: 0;
}
.cu-tag + .cu-tag {
margin-left: 5px;
}
.cu-tag.sm {
font-size: 10px;
padding: 0px 6px;
height: 16px;
}
.cu-capsule {
display: inline-flex;
vertical-align: middle;
}
.cu-capsule + .cu-capsule {
margin-left: 5px;
}
.cu-capsule .cu-tag {
margin: 0;
}
.cu-capsule .cu-tag[class*='line-']:last-child::after {
border-left: 0px solid transparent;
}
.cu-capsule .cu-tag[class*='line-']:first-child::after {
border-right: 0px solid transparent;
}
.cu-capsule.radius .cu-tag:first-child {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.cu-capsule.radius .cu-tag:last-child::after,
.cu-capsule.radius .cu-tag[class*='line-'] {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
.cu-capsule.round .cu-tag:first-child {
border-top-left-radius: 100px;
border-bottom-left-radius: 100px;
text-indent: 2px;
}
.cu-capsule.round .cu-tag:last-child::after,
.cu-capsule.round .cu-tag:last-child {
border-top-right-radius: 100px;
border-bottom-right-radius: 100px;
text-indent: -2px;
}
.cu-tag.badge {
border-radius: 100px;
position: absolute;
top: -5px;
right: -5px;
font-size: 10px;
padding: 0px 5px;
height: 14px;
color: #ffffff;
}
.cu-tag.badge:not([class*='bg-']) {
background-color: #dd514c;
}
.cu-tag:empty:not([class*='cuIcon-']) {
padding: 0px;
width: 8px;
height: 8px;
top: -2px;
right: -2px;
}
.cu-tag[class*='cuIcon-'] {
width: 16px;
height: 16px;
top: -2px;
right: -2px;
}
/* ==================
背景
==================== */
.line-red::after,
.lines-red::after {
border-color: #e54d42;
}
.line-orange::after,
.lines-orange::after {
border-color: #f37b1d;
}
.line-yellow::after,
.lines-yellow::after {
border-color: #fbbd08;
}
.line-olive::after,
.lines-olive::after {
border-color: #8dc63f;
}
.line-green::after,
.lines-green::after {
border-color: #39b54a;
}
.line-cyan::after,
.lines-cyan::after {
border-color: #1cbbb4;
}
.line-blue::after,
.lines-blue::after {
border-color: #0081ff;
}
.line-purple::after,
.lines-purple::after {
border-color: #6739b6;
}
.line-mauve::after,
.lines-mauve::after {
border-color: #9c26b0;
}
.line-pink::after,
.lines-pink::after {
border-color: #e03997;
}
.line-brown::after,
.lines-brown::after {
border-color: #a5673f;
}
.line-grey::after,
.lines-grey::after {
border-color: #8799a3;
}
.line-gray::after,
.lines-gray::after {
border-color: #aaaaaa;
}
.line-black::after,
.lines-black::after {
border-color: #333333;
}
.line-white::after,
.lines-white::after {
border-color: #ffffff;
}
.bg-red {
background-color: #e54d42;
color: #ffffff;
}
.bg-orange {
background-color: #f37b1d;
color: #ffffff;
}
.bg-yellow {
background-color: #fbbd08;
color: #333333;
}
.bg-olive {
background-color: #8dc63f;
color: #ffffff;
}
.bg-green {
background-color: #39b54a;
color: #ffffff;
}
.bg-cyan {
background-color: #1cbbb4;
color: #ffffff;
}
.bg-blue {
background-color: #0081ff;
color: #ffffff;
}
.bg-purple {
background-color: #6739b6;
color: #ffffff;
}
.bg-mauve {
background-color: #9c26b0;
color: #ffffff;
}
.bg-pink {
background-color: #e03997;
color: #ffffff;
}
.bg-brown {
background-color: #a5673f;
color: #ffffff;
}
.bg-grey {
background-color: #8799a3;
color: #ffffff;
}
.bg-gray {
background-color: #f0f0f0;
color: #333333;
}
.bg-black {
background-color: #333333;
color: #ffffff;
}
.bg-white {
background-color: #ffffff;
color: #666666;
}
.bg-shadeTop {
background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
color: #ffffff;
}
.bg-shadeBottom {
background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
color: #ffffff;
}
.bg-red.light {
color: #e54d42;
background-color: #fadbd9;
}
.bg-orange.light {
color: #f37b1d;
background-color: #fde6d2;
}
.bg-yellow.light {
color: #fbbd08;
background-color: #fef2ced2;
}
.bg-olive.light {
color: #8dc63f;
background-color: #e8f4d9;
}
.bg-green.light {
color: #39b54a;
background-color: #d7f0dbff;
}
.bg-cyan.light {
color: #1cbbb4;
background-color: #d2f1f0;
}
.bg-blue.light {
color: #0081ff;
background-color: #cce6ff;
}
.bg-purple.light {
color: #6739b6;
background-color: #e1d7f0;
}
.bg-mauve.light {
color: #9c26b0;
background-color: #ebd4ef;
}
.bg-pink.light {
color: #e03997;
background-color: #f9d7ea;
}
.bg-brown.light {
color: #a5673f;
background-color: #ede1d9;
}
.bg-grey.light {
color: #8799a3;
background-color: #e7ebed;
}
.bg-gradual-red {
background-image: linear-gradient(45deg, #f43f3b, #ec008c);
color: #ffffff;
}
.bg-gradual-orange {
background-image: linear-gradient(45deg, #ff9700, #ed1c24);
color: #ffffff;
}
.bg-gradual-green {
background-image: linear-gradient(45deg, #39b54a, #8dc63f);
color: #ffffff;
}
.bg-gradual-purple {
background-image: linear-gradient(45deg, #9000ff, #5e00ff);
color: #ffffff;
}
.bg-gradual-pink {
background-image: linear-gradient(45deg, #ec008c, #6739b6);
color: #ffffff;
}
.bg-gradual-blue {
background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
color: #ffffff;
}
</style>