一、注意
二、实现效果
三、问题
1.el-date-picker绑定的要是一个字符串,报错: dateStr.match is not a function ;不能直接new Date().getFullYear() 得到一个Number,得String();
2.el-input-number 默认会把null转为0,解决:没值写成undefined
3.el-dialog组件
1.初始化(不一定非要父子组件传参visible)(但是我感觉容易不销毁)
<el-dialog :visible.sync="visible" width="50%">
</el-dialog>
init(){
this.visible = true
}
父组件中:
<dialog-item ref='dialog' v-if='dialogVisible'>
</ dialog-item>
this.$refs.dialogVisible.init()
2.嵌套el-dialog 里面的dialog用 append-to-body 成为全屏弹框
3.常用dialog封装
子组件:
<!-- 辨识危险源 弹框 -->
<template>
<div v-if="visible">
<el-dialog
title="辨识危险源"
:visible.sync="visible"
width="50%"
destroy-on-close
:before-close="handleClose"
@close="$emit('closeDialog')"
>
<div class="add-dialog-content">
</div>
<span slot="footer" class="dialog-footer">
<div class="btn cancel-button" @click="$emit('closeDialog')">取 消</div>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
dialogVisible: {
type: Boolean,
required: true,
},
},
components: { },
data() {
//这里存放数据
return {
visible: false,
};
},
//监听属性 类似于data概念
computed: {},
//监控data中的数据变化
watch: {
dialogVisible: {
handler(v) {
this.visible = v;
},
},
//方法集合
methods: {
handleClose(done) {
this.$emit("closeDialog");
done();
},
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {},
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
},
beforeCreate() {}, //生命周期 - 创建之前
beforeMount() {}, //生命周期 - 挂载之前
beforeUpdate() {}, //生命周期 - 更新之前
updated() {}, //生命周期 - 更新之后
beforeDestroy() {}, //生命周期 - 销毁之前
destroyed() {}, //生命周期 - 销毁完成
activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style scoped lang="scss">
::v-deep .el-dialog {}
</style>
父组件:
<add-dialog
v-if="dialogVisible && riskLevelList"
ref="addDialog"
:dialogVisible="dialogVisible"
:riskLevelList="riskLevelList"
@closeDialog="closeDialog"
/>
closeLevelDialog(isChange, riskLevelId) {
this.riskLevelList = null;
this.levelDialogVisible = false;
},
4.el-input .stop失效
vue element上面 .stop失效(vue好像也不能用原生),则再el-input外再套一层div\span元素,@click.stop 即可<span v-else @click.stop>
<el-input
:id="Math.random()"
v-model="scope.row.titleName"
@blur.stop="rowUpdate(scope)"
></el-input>
</span>
5.日期范围
1.限制日期选择范围
https://www.cnblogs.com/wuqilang/p/15654978.html
限制区间30天:
pickerMinDate: '',
pickerOptions: {
onPick: ({ maxDate, minDate }) => {
this.pickerMinDate = minDate.getTime()
if (maxDate) this.pickerMinDate = ''
},
disabledDate: (time) => {
if (this.pickerMinDate !== '') {
const one = 30 * 24 * 3600 * 1000
const minTime = this.pickerMinDate - one
const maxTime = this.pickerMinDate + one
return time.getTime() < minTime || time.getTime() > maxTime
}
}
}
使用 eg:
//数据中心-能耗小时统计
let pickerMinDate = "";
export const tableOption = (list) => {
return {
border: true, //边框
stripe: false, //表格条纹
card: false, //卡片表格
index: true, //序号
indexLabel: "序号", //序号名称
selection: false, //是否多选
searchShow: true, //页面初次加载是否显示搜索框
searchMenuPosition: "center", //搜索操作按钮的位置
searchMenuSpan: 6, //搜索操作按钮的位置
searchSlot: true, //自定义列搜索
menu: false, //是否显示操作菜单栏
menuWidth: 100,
// header: false,
// size:'mini', //控件大小 medium/small/mini
align: "center", //列的对其方式
refreshBtn: true, //刷新按钮
header: true,
addBtn: false, //添加按钮
editBtn: false, //修改按钮
viewBtn: false, //查看按钮
delBtn: false, //删除按钮
columnBtn: true, //表格右侧操作列显隐的按钮
cellBtn: false, //是否行编辑按钮
printBtn: false, //即可开启打印功能
excelBtn: false, //导出exce按钮
dateBtn: false, //日期范围搜索功能
searchShowBtn: false, //搜索显隐按钮
searchLabelWidth: 80,
labelWidth: 130,
props: {
label: "label",
value: "value",
},
column: [
{
label: "统计日期",
prop: "statisticsDateArray",
type: "input",
searchType: "daterange",
format: "yyyy-MM-dd",
valueFormat: "yyyy-MM-dd",
popperClass: "time-picker",
search: true,
startPlaceholder: "开始日期",
endPlaceholder: "结束日期",
rules: [
{ required: true, message: "统计日期不能为空", trigger: "blur" },
],
hide: true,
clearable: false,
type: "date",
pickerOptions: {
onPick: ({ maxDate, minDate }) => {
pickerMinDate = minDate.getTime();
if (maxDate) pickerMinDate = "";
},
disabledDate: (time) => {
if (pickerMinDate !== "") {
// 只能选择62天
const one = 62 * 24 * 3600 * 1000;
const minTime = pickerMinDate - one;
const maxTime = pickerMinDate + one;
return time.getTime() < minTime || time.getTime() > maxTime;
}
},
},
// searchSlot: true,
},
],
};
};
限制区间30天,不能大于今日:
pickerMinDate: '',
pickerOptions: {
onPick: ({ maxDate, minDate }) => {
this.pickerMinDate = minDate.getTime()
if (maxDate) this.pickerMinDate = ''
},
disabledDate: (time) => {
if (this.pickerMinDate !== '') {
const one = 30 * 24 * 3600 * 1000
let minTime = this.pickerMinDate - one
let maxTime = this.pickerMinDate + one
if (maxTime > new Date()) maxTime = new Date() // 限制不能选择今天之后的日期
return time.getTime() < minTime || time.getTime() > maxTime
}
return time.getTime() > Date.now()
}
}
限制区间30天,不能小于今日:
pickerMinDate: '',
pickerOptions: {
onPick: ({ maxDate, minDate }) => {
this.pickerMinDate = minDate.getTime()
if (maxDate) this.pickerMinDate = ''
},
disabledDate: (time) => {
if (this.pickerMinDate !== '') {
const one = 30 * 24 * 3600 * 1000
let minTime = this.pickerMinDate - one
let maxTime = this.pickerMinDate + one
if (minTime < new Date()) minTime = new Date() // 限制不能选择今天之前的日期
return time.getTime() < minTime || time.getTime() > maxTime
}
return time.getTime() < Date.now() - 8.64e7 // 加上 - 8.64e7 就可以选择今天
}
}
选择今天及之前的日期:
pickerOptions: {
disabledDate: (time) => {
return time.getTime() > Date.now()
}
}
选择今天之前的日期:
pickerOptions: {
disabledDate: (time) => {
return time.getTime() > Date.now() - 8.64e7
}
}
6.el-tree手动设置高亮
el-tree设置高亮节点:
<el-tree
ref="riskPointIdTreeRef"
default-expand-all
:data="riskPointIdTree"
v-model="form.riskPointId"
placeholder="请选择关联风险点"
node-key="riskPointId"
@node-click="handleNodeClick"
></el-tree>
this.$nextTick(() => {
this.$refs.riskPointIdTreeRef.setCurrentNode(
this.riskPointIdList.find(
(v) => v.riskPointId == this.form.riskPointId
)
);
});
7.el-table
1.滚动条 || fixed固定列导致的表格错位
公共样式中:
// 解决overflow-y拖拽表格滚动条,错位问题
.no-last-td-avue .el-table__header-wrapper {
padding-right: 10px !important; // 滚动条宽度
}
// .no-last-td-avue .el-table__fixed-header-wrapper {
// padding-right: 10px !important;
// }
// 解决左右 对不齐 的情况 (表格有fixed固定列)
// el-table 左右有列固定时,fixed为left和right时,行未对齐解决办法
// * 产生原因: el-table底部有滚动条,固定列底部没有滚动条
// * 解决办法: 在el-table的表格中设置padding-bottom的内边距跟滚动条等高
.no-last-td-avue .el-table__fixed {
height: calc(100% - 10px) !important;
}
.no-last-td-avue .el-table__fixed-body-wrapper {
height: calc(100% - 83px) !important; // 83px:他的top值,即表头的高
}
// 下面的会导致横向滚动条在fixed列拉不住 (没有横向滚动条可用)
// .no-last-td-avue .el-table__fixed-body-wrapper .el-table__body {
// padding-bottom: 10px; // 6px为横向滚动条高度
// }
2.el-table 自动滚动 vue3 + el-table css设置
<el-table ref="scrollTableOne" :data="data.tableData" height="100%" style="width: 100%">
<el-table-column prop="date" label="时间" align="left" header-align="center" width="100" />
<el-table-column prop="name" label="设备名称" show-overflow-tooltip align="left" header-align="left" />
<el-table-column prop="status" label="状态" align="left" header-align="left" width="70">
<template #default="scope">
<span :style="{ color: scope.row.status == 1 ? '#F96168' : '#00FF84' }">{{ scope.row.status == 1 ? '待修' : '维修中' }}</span>
</template>
</el-table-column>
</el-table>
const data = ref({
// 设备工单
tableDataOld: [
{
date: '2024-8-12',
name: '全悬浮自动洗涤脱水机',
status: '1'
},
{
date: '2024-8-13',
name: '全自动快速烘干机',
status: '1'
},
{
date: '2024-8-14',
name: '宽幅烫平机',
status: '2'
},
{
date: '2024-8-14',
name: '空压机',
status: '2'
},
{
date: '2024-8-14',
name: '20KG全自动洗脱机',
status: '2'
},
{
date: '2024-8-16',
name: '空压机',
status: '2'
}
],
tableData: [],
})
const tableNode = ref(null);
const scrollBarNode = ref(null);
let scrollTableOne = ref('');
let tableTimer = null;
const computedTableRowHeight = () => {
tableNode.value = scrollTableOne.value.$refs.bodyWrapper.getElementsByClassName('el-scrollbar__wrap')[0];
scrollTable(tableNode, tableNode.value.getBoundingClientRect().height || tableNode.value.offsetHeight);
scrollBarNode.value = document.getElementsByClassName('md-bot-left')[0].getElementsByClassName('el-scrollbar__wrap')[0];
scrollTable(scrollBarNode, scrollBarNode.value.getBoundingClientRect().height || scrollBarNode.value.offsetHeight);
};
const scrollTable = (tableNode, height) => {
const tableScroll = ref(true);
tableNode.value.addEventListener('mouseover', () => {
tableScroll.value = false;
});
tableNode.value.addEventListener('mouseout', () => {
tableScroll.value = true;
});
setInterval(() => {
if (tableScroll.value) {
tableNode.value.scrollTop++;
// 这个方法,多添加了好几倍数据才能保证页面高度小于数据高度,会导致手动滚动一看,有好多数据,别用!就直接让他滚完然后直接回最上面拉倒!
// if (
// parseInt(tableNode.value.scrollHeight / 2) === tableNode.value.scrollTop ||
// parseInt(tableNode.value.scrollHeight / 2) < tableNode.value.scrollTop
// ) {
// tableNode.value.scrollTop = 0;
// }
// console.log(tableNode.value.scrollHeight, tableNode.value.scrollTop, tableNode.value.scrollTop + height + 1);
if (tableNode.value.scrollHeight <= tableNode.value.scrollTop + height + 1) {
tableNode.value.scrollTop = 0;
}
}
}, 60);
};
onMounted(() => {
data.value.tableData = data.value.tableDataOld;
data.value.middleBottomLeftData = data.value.middleBottomLeftDataOld;
// data.value.tableData =
// data.value.tableDataOld.length < 7
// ? [...data.value.tableDataOld, ...data.value.tableDataOld, ...data.value.tableDataOld]
// : [...data.value.tableDataOld, ...data.value.tableDataOld];
// data.value.middleBottomLeftData =
// data.value.middleBottomLeftDataOld.length < 3
// ? [...data.value.middleBottomLeftDataOld, ...data.value.middleBottomLeftDataOld, ...data.value.middleBottomLeftDataOld]
// : [...data.value.middleBottomLeftDataOld, ...data.value.middleBottomLeftDataOld];
tableTimer = setTimeout(() => {
computedTableRowHeight();
});
});
onUnmounted(() => {
clearTimeout(tableTimer);
tableTimer = null;
});
.el-table {
background: rgba(10, 16, 29, 0.4) !important;
.el-table__header-wrapper tr,
.el-table__header-wrapper th,
.el-table__fixed-header-wrapper th {
// 表头高度
height: 0.182292rem /* 35/192 */ !important;
background-color: rgba(10, 16, 29, 0.4) !important;
color: #e1e1e1;
}
/* 设置行背景色 */
.el-table__body tr.el-table__row {
background-color: rgba(185, 223, 250, 0.1);
}
// border 颜色
td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border-bottom: 5px solid rgba(10, 16, 29, 0.4);
}
// 行高度
.el-table__row,
.el-table__row td,
th {
padding: 0 !important;
}
thead th {
font-weight: 400 !important;
font-size: 0.078125rem /* 15/192 */;
}
// 行背景色
.el-table__body-wrapper tr {
background-color: rgba(185, 223, 250, 0.1);
color: #fff;
&:hover {
background-color: rgba(10, 16, 29, 0.1) !important;
}
}
.el-table--enable-row-hover,
.el-table__body tr:hover > td.el-table__cell {
background-color: rgba(10, 16, 29, 0.1) !important;
}
.el-table__cell {
font-size: 0.067708rem /* 13/192 */;
white-space: nowrap;
}
}
3.el-scrollbar自动滚动,同el-table类似(也改为上面的不添加数据滚完,直接回最上面)
<el-scrollbar height="400px" ref="scrollbarRef">
<div class="scrollbar-item" v-for="(v, index) in data.middleBottomLeftData" :key="index">
<p class="time"><span class="yuan"></span> {{ v.time }}</p>
<div class="context flex column he">
<p class="event">
<img src="~@/assets/images/screen/gantan.png" alt="" />
事件:
{{ v.event }}
</p>
<p class="status"> 状态:{{ v.status }} 上报时间:{{ v.reportTime }}</p>
</div>
</div>
</el-scrollbar>
middleBottomLeftDataOld: [
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理1!', status: '待处理', reportTime: '2024/08/29 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理2!', status: '待处理', reportTime: '2024/08/28 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理3!', status: '待处理', reportTime: '2024/08/27 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理4!', status: '待处理', reportTime: '2024/08/26 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理5!', status: '待处理', reportTime: '2024/08/25 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理6!', status: '待处理', reportTime: '2024/08/24 22:12:00' },
{ time: '08月23日 22:12:20', event: '南区正门马路车辆占道违停,请立即处理7!', status: '待处理', reportTime: '2024/08/23 22:12:00' }
],
middleBottomLeftData: [],
let tableTimer = null;
const computedTableRowHeight = () => {
// tableNode.value = scrollTableOne.value.$refs.bodyWrapper.getElementsByClassName('el-scrollbar__wrap')[0];
// scrollTable(tableNode);
scrollBarNode.value = document.getElementsByClassName('md-bot-left')[0].getElementsByClassName('el-scrollbar__wrap')[0];
scrollTable(scrollBarNode);
};
const scrollTable = (tableNode) => {
const tableScroll = ref(true);
tableNode.value.addEventListener('mouseover', () => {
tableScroll.value = false;
});
tableNode.value.addEventListener('mouseout', () => {
tableScroll.value = true;
});
setInterval(() => {
if (tableScroll.value) {
tableNode.value.scrollTop++;
if (
parseInt(tableNode.value.scrollHeight / 2) === tableNode.value.scrollTop ||
parseInt(tableNode.value.scrollHeight / 2) < tableNode.value.scrollTop
) {
tableNode.value.scrollTop = 0;
}
}
}, 30);
};
onMounted(() => {
data.value.tableData = [...data.value.tableDataOld, ...data.value.tableDataOld];
data.value.middleBottomLeftData = [...data.value.middleBottomLeftDataOld, ...data.value.middleBottomLeftDataOld];
tableTimer = setTimeout(() => {
computedTableRowHeight();
});
data.value.commodationData = [
{
name: '房间入住数',
value: 321,
color: '#00ff84',
all: 363,
imgSrc: '../../assets/images/screen/commodationRoom.png'
},
{
name: '床位入住数',
value: 636,
color: '#ef9c00',
all: 726,
imgSrc: '../../assets/images/screen/commodationBed.png'
},
{
name: '入住总人数',
value: 76,
color: '#81c5c8',
imgSrc: '../../assets/images/screen/commodationPersonnel.png'
}
];
});
onUnmounted(() => {
clearTimeout(tableTimer);
this.tableTimer = null;
});
4.el-table横向滚动条设置
//el-table横向滚动条高度
.el-scrollbar__bar.is-horizontal{
height: 9px !important;
}
.el-scrollbar__bar.is-horizontal .el-scrollbar__thumb {
// opacity: 1; // 默认滚动条自带透明度
height: 9px !important; // 横向滑块的宽度
border-radius: 5px; // 圆角度数
// background-color: var(--el-color-primary-light-4); // 滑块背景色
// box-shadow: 0 0 6px rgba(0, 0, 0, 0.15); // 滑块阴影
}
8.v-loading指令不能用在组件上啥的
报错:Runtime directive used on component with non-el
9.element-plus(vue3)-$DialogForm日期英文
main.js引入
// element中文
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
app.use(ElementPlus,{locale:zhCn })
10.element日期框定位错误原因:原来的位置放不下那个弹框了
11.el-select
1.select自己拼了一个数据字典中的desc
解决:手动把数据desc置空,或者让后端改数据,数据字典中不要desc字段
12.el-tree-自定义模板和回显值
spaceName:单个值,spaceNameFull:拼起来的值
{
label: '空间',
prop: 'spaceId',
type: 'tree',
search: true,
props: {
label: 'spaceNameFull',
value: 'spaceId'
},
dicUrl: `/park/space/list`,
dicFormatter: (data) => {
return handleTree(data, 'spaceId', 'parentId');
},
typeformat(item, label, value) {
return item.spaceName;
},
defaultExpandAll: true,
filterable: true,
showAllLevels: true,
rules: [
{
required: true,
message: '空间不能为空',
trigger: 'blur'
}
],
width: 160
},