JavaScript利用el-table實(shí)現(xiàn)繪制熱度表
實(shí)現(xiàn)效果

實(shí)現(xiàn)代碼
<div class="gray w-full h-100 mt-4 table" v-if="props.brandId">
<el-table :data="brandHotList" :header-cell-style="{
'font-weight': 'normal',
'background-color': '#f7f8f9',
}" :cell-style="{ padding: '5px 0' }" :row-style="{ height: 30 }" fit class="showOrder">
<el-table-column align="center" label="排名" width="55">
<template #default="scope">
<span class="index">{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column align="left" label="熱門(mén)車(chē)系">
<template #default="scope">
<el-tooltip effect="dark" :content="scope.row.name || '--'" placement="top">
<div class="lastName">{{ scope.row.name || '--'}}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" label="熱度" min-width="200">
<template #default="scope">
<div class="lastDiv" :style="
scope.row.total >= 0
? 'text-align:left'
: 'text-align:center'
" style="white-space: nowrap">
<span v-if="scope.row.total > 0" :style="`width:${(scope.row.total / brandHotList[0].total) * 83 + 0.5
}%;background:#ff454e`" class="length"></span>
<span class="count">{{ scope.row.total }}</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
<style>
.gray {
background-color: #f7f8f9;
border-radius: 8px;
}
.table {
width: 100%;
overflow: hidden;
padding: 0 20px;
.el-table {
width: 100%;
border: none;
background-color: #f7f8f9;
margin: 0;
padding: 0;
overflow: hidden;
:deep(.el-table__empty-block) {
background-color: #f7f8f9;
margin-top: 105px;
}
:deep(.el-table__body) {
td {
border-bottom: none;
font-size: 14px;
}
}
::before {
height: 0;
}
}
:deep(.index){
font-family: DIN, DIN-Bold;
font-weight: 700;
color: #333333;
}
.length {
display: inline-block;
width: 80%;
height: 12px;
margin-right: 14px;
}
.lastDiv {
display: block !important;
}
.count {
white-space: nowrap;
line-height: 12px;
}
.hot {
display: flex;
align-items: center;
.num {
margin-left: 5px;
text-align: center;
}
}
:deep(.groupName) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
:deep(.el-table__header-wrapper) {
margin-bottom: 12px;
background-color: #f7f8f9;
}
:deep(th .cell) {
font-size: 14px;
font-weight: 400;
color: #333;
}
:deep(.el-table th) {
background-color: #f7f8f9 !important;
}
:deep(.el-table__row) {
background-color: #f7f8f9;
}
}
</style>
補(bǔ)充
除了繪制熱度表,還可以繪制甘特圖哦,下面就是示例代碼
<template>
<div class="hotelApply wl-gantt">
<el-card>
<el-table :data="tableData" border style="width: 100%" :class="dateTypeClass" row-key="id"
:span-method="spanMethod" @cell-click="cellClick" :cell-style="cellStyle">
<el-table-column prop="room" label="房間" align="center" width="140px" fixed="left" :show-overflow-tooltip="true">
</el-table-column>
<el-table-column prop="bedName" label="床位" align="center" width="120px" fixed="left"
:show-overflow-tooltip="true">
</el-table-column>
<!-- mouth and day gantt -->
<template v-if="self_date_type === 'monthAndDay'">
<el-table-column :resizable="false" v-for="month in ganttTitleDate" :label="month.full_date" :key="month.id"
align="center">
<el-table-column class-name="wl-gantt-item" v-for="(day, dindex) in month.children" :resizable="false"
:key="dindex" :label="day.name" width="60" align="center">
<template v-slot="scope">
<div :class="dayGanttType(scope.row, day.full_date)" @click="handleDay(scope.row)"></div>
<div :class="realDayGanttType(scope.row, day.full_date)"></div>
<!-- <div :class="selectedCell(scope.row)"></div> -->
</template>
</el-table-column>
</el-table-column>
</template>
</el-table>
</el-card>
<!-- 右邊抽屜 -->
<el-drawer title="住房信息" :visible.sync="showDrawer" size='40%'>
<div class="drawer_box">
<el-form :model="drawerForm" :inline="true" label-width="100px">
<el-form-item label="入住時(shí)間">
<el-date-picker v-model="drawerForm.beginTime" type="date" placeholder="選擇日期" value-format='yyyy-MM-dd'
disabled>
</el-date-picker>
</el-form-item>
<el-form-item label="退住時(shí)間">
<el-date-picker v-model="drawerForm.endTime" type="date" placeholder="選擇日期" value-format='yyyy-MM-dd'>
</el-date-picker>
</el-form-item>
</el-form>
<div style="text-align:center">
<el-button type="primary" size="mini" @click="drawerConfirm"> 確定</el-button>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
import dayjs from "dayjs" // 導(dǎo)入日期js
const uuidv4 = require("uuid/v4") // 導(dǎo)入uuid生成插件
import isBetween from "dayjs/plugin/isBetween"
import quarterOfYear from "dayjs/plugin/quarterOfYear"
dayjs.extend(quarterOfYear) //獲取季度依賴(lài)
dayjs.extend(isBetween)
export default {
name: "",
data() {
return {
tableData: [
{
id: 1,
room: "公寓101",
bedName: "1號(hào)床",
beginTime: "2021-08-03",
endTime: "2021-08-4",
liveList: [
{ beginTime: "2021-08-03", endTime: "2021-08-4" },
{ beginTime: "2021-08-06", endTime: "2021-08-8" },
],
},
{
id: 2,
room: "公寓101",
bedName: "2號(hào)床",
beginTime: "2021-08-04 00:00:00",
endTime: "2021-08-5 00:00:00",
liveList: [],
},
{
id: 3,
room: "公寓102",
bedName: "1號(hào)床",
beginTime: "2021-08-05 00:00:00",
endTime: "2021-08-7 00:00:00",
liveList: [],
},
{
id: 4,
room: "公寓102",
bedName: "2號(hào)床",
beginTime: "2021-08-01 00:00:00",
endTime: "2021-08-3 00:00:00",
liveList: [],
},
{
id: 5,
room: "公寓103",
bedName: "1號(hào)床",
beginTime: "2021-08-06 00:00:00",
endTime: "2021-08-8 00:00:00",
liveList: [],
},
{
id: 6,
room: "公寓103",
bedName: "2號(hào)床",
beginTime: "2021-08-7 00:00:00",
endTime: "2021-08-9 00:00:00",
liveList: [],
},
],
showDrawer: false, //抽屜
drawerForm: {},
// 甘特圖
self_start_date: "2021-08-01", // 項(xiàng)目開(kāi)始時(shí)間
self_end_date: "2021-09-30", // 項(xiàng)目結(jié)束時(shí)間
self_start_date_day: "", //項(xiàng)目開(kāi)始時(shí)間的日期
self_start_date_month: "", //項(xiàng)目開(kāi)始時(shí)間的月份
self_start_date_year: "", //項(xiàng)目開(kāi)始時(shí)間的年份
self_date_type: "monthAndDay", // 自身日期類(lèi)型
}
},
created() {},
mounted() {
this.initTime() //初始化時(shí)間1
},
computed: {
// 甘特圖標(biāo)題日期分配
ganttTitleDate() {
// 分解開(kāi)始和結(jié)束日期
let start_date_spilt = dayjs(this.self_start_date)
.format("YYYY-M-D")
.split("-")
let end_date_spilt = dayjs(this.self_end_date)
.format("YYYY-M-D")
.split("-")
let start_year = Number(start_date_spilt[0])
let start_mouth = Number(start_date_spilt[1])
let end_year = Number(end_date_spilt[0])
let end_mouth = Number(end_date_spilt[1])
console.log("日期類(lèi)型", this.self_date_type)
if (this.self_date_type === "monthAndDay") {
return this.mouthAndDayTitleDate(
start_year,
start_mouth,
end_year,
end_mouth
)
}
},
// 樹(shù)表配置項(xiàng)
selfProps() {
return {
hasChildren: "hasChildren", // 字段來(lái)指定哪些行是包含子節(jié)點(diǎn)
children: "children", // children字段來(lái)表示有子節(jié)點(diǎn)
name: "name", // 任務(wù)名稱(chēng)字段
id: "id", // id字段
pid: "pid", // pid字段
startDate: "beginTime", // 開(kāi)始時(shí)間字段
endDate: "endTime", // 結(jié)束時(shí)間字段
realStartDate: "recordBeginTime", // 實(shí)際開(kāi)始時(shí)間字段
realEndDate: "recordEndTime", // 實(shí)際結(jié)束時(shí)間字段
identityId: "identityId",
parents: "parents",
pre: "pre", // 前置任務(wù)字段【注意:如果使用recordParents,則pre值應(yīng)是目標(biāo)對(duì)象的identityId字段(可配置)】
// ...this.props
}
},
// 根據(jù)日期類(lèi)型改樣式
dateTypeClass() {
if (this.self_date_type === "monthAndDay") {
return "month-and-day"
}
return ""
},
},
components: {},
methods: {
// =====================表格事件==================
// 單元格點(diǎn)擊
cellClick(row, column, cell, event) {
// console.log(row, column, cell, event);
},
// 單元格樣式
cellStyle({ row, column, rowIndex, columnIndex }) {},
// 預(yù)定者點(diǎn)擊
handleDay(row) {
console.log(row)
this.showDrawer = true
this.drawerForm = Object.assign({}, row)
},
// 模態(tài)框確定
drawerConfirm() {
this.tableData.forEach((item) => {
if (item.id == this.drawerForm.id) {
this.$set(item, "beginTime", this.drawerForm.beginTime)
this.$set(item, "endTime", this.drawerForm.endTime)
}
})
this.showDrawer = false
},
// =====================甘特區(qū)域==================
//維度展示形式
changedateType(val) {
console.log(val)
this.getDataList()
},
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
},
// 初始化時(shí)間
initTime() {
this.self_start_date_year = this.self_start_date.split("-")[0]
this.self_start_date_month = this.self_start_date.split("-")[1]
this.self_start_date_day = this.self_start_date.split("-")[2]
this.self_start_date_day =
this.self_start_date_day > 2
? this.self_start_date_day - 1
: this.self_start_date_day
console.log("開(kāi)始-結(jié)束", this.self_start_date, this.self_end_date)
},
// 設(shè)置dateType
setDataType(type) {
this.self_date_type = type
},
/**
* 當(dāng)前日期gantt狀態(tài)
* row: object 當(dāng)前行信息
* date: string 當(dāng)前格子日期
* unit: string 時(shí)間單位,以天、月、年計(jì)算
*/
dayGanttType(row, date, unit = "days") {
// let start_date = row[this.selfProps.startDate]
// let end_date = row[this.selfProps.endDate]
let start_date = row[this.selfProps.startDate]
let end_date = row[this.selfProps.endDate]
// 若沒(méi)有時(shí)間則不顯示
if (!start_date || !end_date) {
return
}
let between = dayjs(date).isBetween(start_date, end_date, unit)
if (between) {
return "wl-item-on"
}
let start = dayjs(start_date).isSame(date, unit)
let end = dayjs(end_date).isSame(date, unit)
if (start && end) {
return "wl-item-on wl-item-full"
}
if (start) {
return "wl-item-on wl-item-start"
}
if (end) {
return "wl-item-on wl-item-end"
}
},
/**
* 實(shí)際日期gantt狀態(tài)
* row: object 當(dāng)前行信息
* date: string 當(dāng)前格子日期
* unit: string 時(shí)間單位,以天、月、年計(jì)算
*/
realDayGanttType(row, date, unit = "days") {
let start_date = row[this.selfProps.realStartDate]
let end_date = row[this.selfProps.realEndDate]
// 若沒(méi)有實(shí)際時(shí)間則不顯示
if (!start_date || !end_date) {
return
}
let between = dayjs(date).isBetween(start_date, end_date, unit)
if (between) {
return "wl-real-on"
}
let start = dayjs(start_date).isSame(date, unit)
let end = dayjs(end_date).isSame(date, unit)
if (start && end) {
return "wl-real-on wl-real-full"
}
if (start) {
return "wl-real-on wl-real-start"
}
if (end) {
return "wl-real-on wl-real-end"
}
},
// 點(diǎn)擊選中單元格
selectedCell(row) {},
// 以下是表格-日期-gantt生成函數(shù)----------------------------------------生成gantt表格-------------------------------------
/**
* 月-日模式gantt標(biāo)題
* start_year: 起始年
* start_mouth:起始月
* end_year:結(jié)束年
* end_mouth:結(jié)束月
*/
mouthAndDayTitleDate(start_year, start_mouth, end_year, end_mouth) {
// 處理年份
let year_diff = end_year - start_year
// 只存在同年或前后年的情況
if (year_diff === 0) {
// 年間隔為同一年
let isLeap = this.isLeap(start_year) // 是否閏年
let mouths = this.generationMonths(
start_year,
start_mouth,
end_mouth + 1,
isLeap
) // 處理月份
return mouths
}
// 處理開(kāi)始月份
let startIsLeap = this.isLeap(start_year)
let start_mouths = this.generationMonths(
start_year,
start_mouth,
13,
startIsLeap
)
// 處理結(jié)束月份
let endIsLeap = this.isLeap(end_year)
let end_mouths = this.generationMonths(
end_year,
1,
end_mouth + 1,
endIsLeap
)
return start_mouths.concat(end_mouths)
},
/**
* 生成月份函數(shù)
* year: Number 當(dāng)前年份
* start_num: Number 開(kāi)始月分
* end_num:Number 結(jié)束月份
* isLeap: Boolean 是否閏年
* insert_days: Boolean 是否需要插入 日
* week: 是否以周的間隔
*/
generationMonths(
year,
start_num = 1,
end_num = 13,
isLeap = false,
insert_days = true,
week = false
) {
let months = []
if (insert_days) {
// 需 日 的模式
for (let i = start_num; i < end_num; i++) {
// 需要 日 的模式
let days = this.generationDays(year, i, isLeap, week)
months.push({
name: `${i}月`,
date: i,
full_date: `${year}-${i}`,
children: days,
id: uuidv4(),
})
}
return months
}
for (let i = start_num; i < end_num; i++) {
// 無(wú)需要 日 的模式
months.push({
name: `${i}月`,
date: i,
full_date: `${year}-${i}`,
id: uuidv4(),
})
}
return months
},
/**
* 生成日期函數(shù)
* year: Number 當(dāng)前年份
* month: Number 當(dāng)前月份
* isLeap: Boolean 是否閏年
* week: Boolean 是否間隔一周
*/
generationDays(year, month, isLeap = false, week = false) {
let big_month = [1, 3, 5, 7, 8, 10, 12].includes(month)
let small_month = [4, 6, 9, 11].includes(month)
let dates_num = big_month ? 32 : small_month ? 31 : isLeap ? 30 : 29
let days = []
if (week) {
let _day = 1 // 從周日開(kāi)始
let _start_day_inweek = this.timeInWeek(`${year}-${month}-1`)
if (_start_day_inweek !== 0) {
_day = 8 - _start_day_inweek
}
for (let i = _day; i < dates_num; i += 7) {
days.push({
date: i,
name: `${i}日`,
id: uuidv4(),
full_date: `${year}-${month}-${i}`,
})
}
} else {
//第一個(gè)月
if (
year == this.self_start_date_year &&
month == this.self_start_date_month
) {
for (let i = this.self_start_date_day; i < dates_num; i++) {
days.push({
date: i,
name: `${i}日`,
id: uuidv4(),
full_date: `${year}-${month}-${i}`,
})
}
//非第一個(gè)月
} else {
for (let i = 1; i < dates_num; i++) {
days.push({
date: i,
name: `${i}日`,
id: uuidv4(),
full_date: `${year}-${month}-${i}`,
})
}
}
}
return days
},
/**
* 是否閏年函數(shù)
* year: Number 當(dāng)前年份
*/
isLeap(year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
},
// 以下是時(shí)間計(jì)算類(lèi)函數(shù) ------------------------------------------------------時(shí)間計(jì)算---------------------------------------
/**
* 時(shí)間格式化函數(shù)
* date 需要格式化的數(shù)據(jù)
* format 格式化的格式
*/
timeFormat(date, format = "YYYY-MM-DD") {
return date ? dayjs(date).format(format) : this.emptyCellText
},
/**
* 查詢(xún)時(shí)間是周幾
*/
timeInWeek(date) {
return dayjs(date).day()
},
// 合并單元格
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
const key = "room"
const list = this.tableData
let len = list.filter((item) => row[key] === item[key]).length
let firstIndex = -1
for (let i = 0; i < this.tableData.length; i++) {
const element = this.tableData[i]
if (columnIndex === 0 && row[key] === element[key]) {
firstIndex = i
break
}
}
if (rowIndex == firstIndex) {
return {
rowspan: len,
colspan: 1,
}
}
if (rowIndex > firstIndex && rowIndex < firstIndex + len) {
return {
rowspan: 0,
colspan: 0,
}
}
}
},
},
watch: {},
}
</script>
<style lang="scss">
.hotelApply {
padding-top: 10px;
.legend-plan,
.legend-real {
display: inline-block;
width: 40px;
height: 6px;
border-radius: 3px;
background: #00cbed;
}
.legend-real {
background: #fcc300;
}
.selected-cell {
border: 1px solid #00cbed;
}
.drawer_box {
padding: 20px;
}
}
</style>
<style lang="scss">
.el-table >>> th.gutter {
display: table-cell !important;
}
.el-table >>> colgroup.gutter {
display: table-cell !important;
}
// 鼠標(biāo)懸浮去除陰影
.el-table tbody tr:hover > td {
background-color: #fff !important;
}
</style>
<style lang="scss">
$gantt_item: 18px;
$gantt_item_half: 4px;
.wl-gantt {
.wl-gantt-header > th {
text-align: center;
}
.h-full {
height: 100%;
}
.wl-gantt-item {
position: relative;
transition: all 0.3s;
> .cell {
padding: 0;
}
}
.u-full.el-input {
width: 100%;
}
// 計(jì)劃時(shí)間gantt開(kāi)始
.wl-item-on {
position: absolute;
top: 40%;
left: 0;
right: -1px;
margin-top: -$gantt_item_half;
height: $gantt_item;
background: #00cbed;
transition: all 0.4s;
cursor: pointer;
}
.wl-item-start {
left: 10%;
&:after {
position: absolute;
top: 0;
left: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #00cbed;
}
}
.wl-item-end {
right: 10%;
&:after {
position: absolute;
top: 0;
right: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #00cbed;
}
}
.wl-item-full {
left: 5px;
right: 5px;
&:before {
position: absolute;
top: 0;
left: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #00cbed;
}
&:after {
position: absolute;
top: 0;
right: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #00cbed;
}
}
// 計(jì)劃時(shí)間gantt結(jié)束
// 實(shí)際時(shí)間gantt開(kāi)始
.wl-real-on {
position: absolute;
top: 75%;
left: 0;
right: -1px;
margin-top: -$gantt_item_half;
height: $gantt_item;
background: #fcc300; //rgba(250, 167, 146, .6);
transition: all 0.4s;
}
.wl-real-start {
left: 50%;
&:after {
position: absolute;
top: 0;
left: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #fcc300;
}
}
.wl-real-end {
right: 50%;
&:after {
position: absolute;
top: 0;
right: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #fcc300;
}
}
.wl-real-full {
left: 5px;
right: 5px;
&:before {
position: absolute;
top: 0;
left: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #fcc300;
}
&:after {
position: absolute;
top: 0;
right: -5px;
z-index: 1;
content: "";
width: 8px;
height: 18px;
border-radius: 50%;
background: #fcc300;
}
}
// 實(shí)際時(shí)間gantt結(jié)束
// 名稱(chēng)列
.name-col {
position: relative;
&:hover .name-col-edit {
display: inline-block;
}
.name-col-edit {
display: none;
position: absolute;
right: 0;
}
.name-col-icon {
padding: 6px 3px;
cursor: pointer;
font-size: 16px;
}
.task-remove {
color: #f56c6c;
}
.task-add {
color: #409eff;
}
}
}
//季度展示、月度展示、周展示
.year-and-quarter,
.year-and-month,
.year-and-week {
.wl-item-start {
left: 5%;
}
.wl-item-end {
right: 5%;
}
.wl-item-full {
left: 5%;
right: 10%;
}
.wl-real-full {
left: 10%;
right: 5%;
}
}
</style>
效果圖

到此這篇關(guān)于JavaScript利用el-table實(shí)現(xiàn)繪制熱度表的文章就介紹到這了,更多相關(guān)JavaScript el-table熱度表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用es6 new.target來(lái)對(duì)模擬抽象類(lèi)的方法
這篇文章主要介紹了利用es6 new.target來(lái)對(duì)模擬抽象類(lèi)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
JavaScript實(shí)現(xiàn)五子棋游戲的方法詳解
這篇文章主要介紹了JavaScript實(shí)現(xiàn)五子棋游戲的方法,結(jié)合實(shí)例形式詳細(xì)分析了javascript實(shí)現(xiàn)五子棋游戲的具體步驟、原理與相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
在mpvue框架中使用Vant WeappUI組件庫(kù)的注意事項(xiàng)【推進(jìn)】
這篇文章主要介紹了在mpvue框架中使用Vant WeappUI組件庫(kù)的注意事項(xiàng),本文給大家提到了引入組件庫(kù)的兩種方法,需要的朋友可以參考下2019-06-06
JS如何對(duì)Iframe內(nèi)外頁(yè)面進(jìn)行操作總結(jié)
iframe標(biāo)簽是一個(gè)內(nèi)聯(lián)框架,即用來(lái)在當(dāng)前HTML頁(yè)面中嵌入另一個(gè)文檔的,且所有主流瀏覽器都支持iframe標(biāo)簽,這篇文章主要給大家介紹了關(guān)于JS如何對(duì)Iframe內(nèi)外頁(yè)面進(jìn)行操作的相關(guān)資料,需要的朋友可以參考下2021-10-10
JS新標(biāo)簽頁(yè)打開(kāi)的方法大全(讓你的網(wǎng)站訪(fǎng)問(wèn)更加便捷)
在開(kāi)發(fā)Web應(yīng)用中我們常常需要在當(dāng)前頁(yè)面打開(kāi)一個(gè)鏈接,但又不希望離開(kāi)當(dāng)前頁(yè)面,這篇文章主要給大家介紹了關(guān)于JS新標(biāo)簽頁(yè)打開(kāi)的方法大全,通過(guò)這些方法可以讓你的網(wǎng)站訪(fǎng)問(wèn)更加便捷,需要的朋友可以參考下2023-10-10

