卡片式组件封装demo

效果视频:

卡片组件

样式还得细调~,时间有限,主要记录一下逻辑。

html结构:
在这里插入图片描述

目录

  • 父组件
    • 数据处理
      • 数据格式
    • 父组件的全部代码
  • 子组件
    • 数据处理
      • props参数
    • 样式部分
      • 三个圆点
        • 点击三圆点在对应位置显示查看弹框
        • 点击非内容部分隐藏查看弹框
      • 遮罩层
    • 子组件的全部代码

父组件

数据处理

在父页面进行v-for循环,灵活根据状态可赋值数组,再根据数组的长度调用卡片组件。

数据格式

  • ASTATE:状态;整型,0表示进行中,1表示超期
  • DESCRIPTION:描述;字符串类型;
  • STARTTIME:开始时间;字符串类型,格式为年月日T时分秒
  • PLANENDTIME:结束时间;字符串类型,格式为年月日T时分秒

以上字段在子组件中皆有用到

[{"ASTATE": 0,"DESCRIPTION": "大名称大名称\n名称:21名称21名称21\n名称:21名称21名称21\n时间:2024-7-17","STARTTIME": "2024-01-03T01:02:03","PLANENDTIME": "2024-01-04T01:02:03","ID": 2},{"ASTATE": 2,"DESCRIPTION": "大名称大名称\n名称:21名称21名称21\n名称:21名称21名称21\n时间:2024-7-17","STARTTIME": "2024-01-07T01:02:03","PLANENDTIME": "2024-01-08T01:02:03","ID": 4}
]

父组件的全部代码

<!-- 页面名称 -->
<template><div class="homebox-class"><div class="mainbox"><h2>任务管理</h2><!-- 超期 --><h4 v-if="taskOverdueData.length>0" class="overduetitle">超期 {{taskOverdueData.length}}</h4><div class="outtabsbox"><tab-task-com-vue :width="18" :height="16" v-for="(task,index) in taskOverdueData" :taskData="task" :key="'overdue' + index"></tab-task-com-vue></div><!-- 进行中 --><h4 v-if="taskOngoingData.length>0" class="ongoingtitle">进行中 {{taskOngoingData.length}}</h4><div class="outtabsbox"><tab-task-com-vue :width="18" :height="16" v-for="(task,index) in taskOngoingData" :taskData="task" :key="'ongoing' + index"></tab-task-com-vue></div></div></div>
</template><script>
import testdata from './test.json';
import tabTaskComVue from '@/views/hzevt/abnormal/tabTaskCom.vue';
export default {components: { tabTaskComVue },props: {},data() {return {taskOverdueData: [],taskOngoingData: [],};},watch: {},computed: {},created() { },mounted() {console.log('testdata', testdata);for (var i of testdata) {if (i.ASTATE == 0) {this.taskOngoingData.push(i);} else if (i.ASTATE == 2) {this.taskOverdueData.push(i);}}},methods: {},
};
</script>
<style scoped>
.homebox-class {width: 100%;height: 100%;
}
.mainbox {width: 100%;height: 100%;overflow-y: auto;
}
.mainbox h2 {letter-spacing: 2px;font-size: 1.2vw;
}
.mainbox h4 {margin: 2% 0;font-size: 1vw;
}
.overduetitle {color: #f26950;
}
.ongoingtitle {color: #2cc09c;
}.outtabsbox {display: flex;justify-content: flex-start;flex-wrap: wrap;font-weight: bold;
}
</style>

子组件

数据处理

props参数

宽高单位为百分比。

 props: {width: {//卡片的宽度type: Number,required: true},height: {//卡片的高度type: Number,required: true},taskData: {//父组件传过来对应的item对象type: Object,required: true},},

样式部分

三个圆点

圆点的实现是采用三个div并添加border-radius: 50%的样式。
dots: [1, 2, 3],表示有三个圆点。

<div class="dotbox" @click="showTooltip($event)"><div class="dot" v-for="(dot, index) in dots" :key="index"></div><div v-if="showPopup" @click="toCheckBtn" class="popup" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">查看</div>
</div>
点击三圆点在对应位置显示查看弹框
  1. 获取目标元素的位置信息:
    getBoundingClientRect() 是一个 DOM API 方法,返回一个 DOMRect 对象,提供了目标元素的大小和其相对于视口的位置信息。

  2. 计算鼠标相对于目标元素的偏移量:
    event.clientXevent.clientY 分别是鼠标指针相对于整个文档的坐标位置。
    dotboxRect.leftdotboxRect.top 分别是目标元素的左上角相对于视口的坐标位置。

  3. 设置popup弹框元素的位置信息:

  4. 显示popup弹框元素:

showTooltip(event) {const dotboxRect = event.currentTarget.getBoundingClientRect();const offsetX = event.clientX - dotboxRect.left;const offsetY = event.clientY - dotboxRect.top;//设置popup弹框元素的位置信息this.popupTop = offsetY + 'px';this.popupLeft = offsetX + 'px';this.showPopup = true;//显示popup弹框元素
},
点击非内容部分隐藏查看弹框

内容部分:

<div class="contentbox" ref="contentRef"></div>
  1. mounted添加监听事件
    ①. 获取点击目标信息:
    ②. 判断点击位置
handleClickOutside(event) {const clickedInsideContentbox = this.$refs.contentRef.contains(event.target);//获取点击目标信息if (!clickedInsideContentbox) {//判断点击位置this.showPopup = false;}
},

遮罩层

根据showPopup动态控制遮罩层的显示和隐藏

<div v-if="showPopup" class="popup-overlay" @click="togglePopup()"></div>

子组件的全部代码

<!-- 首页使用到的tab框组件 -->
<template><div :style="{ width: `${width}%`, height: `${height}%` }" class="tabsbox"><!-- 遮罩层 --><div v-if="showPopup" class="popup-overlay" @click="togglePopup()"></div><div class="tabstitle overduetitle" v-if="taskData.ASTATE==2">超期</div><div class="tabstitle ongoingtitle" v-if="taskData.ASTATE==0">进行中</div><div class="contentbox" ref="contentRef"><div class="contenttitlebox"><div class="content-title" :class="taskData.ASTATE === 0?'state-0':'state-2'">生产异常流程</div><div class="dotbox" @click="showTooltip($event)"><div class="dot" v-for="(dot, index) in dots" :key="index"></div><div v-if="showPopup" @click="toCheckBtn" class="popup" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">查看</div></div></div><pre class="content-descbox">{{taskData.DESCRIPTION}}</pre><div class="tabsbottombox"><div class="timebox"><img src="@/views/system/index/components/d2-page-cover/image/time1.png" alt=""><div v-if="taskData.STARTTIME.includes('T')">{{taskData.STARTTIME.replace("T", " ").slice(0, 16)}}</div><div v-else>{{taskData.STARTTIME}}</div></div><div class="timebox" style="justify-content: flex-end;"><img src="@/views/system/index/components/d2-page-cover/image/time2.png" alt=""><div v-if="taskData.PLANENDTIME.includes('T')">{{taskData.PLANENDTIME.replace("T", " ").slice(0, 16)}}</div><div v-else>{{taskData.PLANENDTIME.replace("T", " ").slice(0, 16)}}</div></div></div></div></div>
</template><script>
export default {components: {},props: {width: {type: Number,required: true},height: {type: Number,required: true},taskData: {type: Object,required: true},},data() {return {dots: [1, 2, 3],showPopup: false,popupTop: 0,popupLeft: 0,};},watch: {},computed: {},created() { },beforeDestroy() {// 在组件销毁前,移除全局点击事件监听器document.removeEventListener('click', this.handleClickOutside);},mounted() {document.addEventListener('click', this.handleClickOutside);},methods: {showTooltip(event) {const dotboxRect = event.currentTarget.getBoundingClientRect();const offsetX = event.clientX - dotboxRect.left;const offsetY = event.clientY - dotboxRect.top;this.popupTop = offsetY + 'px';this.popupLeft = offsetX + 'px';this.showPopup = true;},togglePopup() {// 点击tabsbox时切换popup状态this.showPopup = false;},// 全局点击事件处理函数,用于关闭弹窗handleClickOutside(event) {const clickedInsideContentbox = this.$refs.contentRef.contains(event.target);if (!clickedInsideContentbox) {this.showPopup = false;}},closePopup() {this.showPopup = false;},// 查看详情toCheckBtn() {//你的操作逻辑},},watch: {},
};
</script>
<style scoped>
.tabsbox {opacity: 0.6;border-radius: 15px;background: rgba(255, 255, 255, 1);border: 1px solid rgba(138, 127, 127, 0.3);box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);margin: 0 3% 3% 1%;padding: 1%;position: relative;
}
.overduetitle {color: #f26950;
}
.ongoingtitle {color: #2cc09c;
}
.tabstitle {font-size: 0.8vw;height: 15%;border-bottom: 1px solid #e6e8ed;
}
.contentbox {height: 85%;
}
.content-title {font-size: 1vw;height: 10%;padding: 2%;font-weight: bold;position: relative; /* 让元素变为相对定位,以便使用 top 属性 */
}
.content-title::before {content: ""; /* 伪元素用于创建边框 */position: absolute; /* 绝对定位在元素内部 */top: 15px; /* 距离顶部偏移量,根据需要调整 */left: -2px; /* 边框从左侧开始 */height: 100%; /* 高度为元素高度减去偏移量 */
}
/* ASTATE 为 0 时的伪类元素样式 */
.content-title.state-0::before {border-left: 3px solid #2cc09c;
}/* ASTATE 为 2 时的伪类元素样式 */
.content-title.state-2::before {border-left: 3px solid #f26950;
}
.content-descbox {height: 66%;margin: 0 3% 3%;color: #4f545a;font-family: none;font-size: 0.7vw;display: flex;align-items: center;
}
.tabsbottombox {height: 14%;display: flex;
}
.timebox {height: 100%;width: 100%;display: flex;align-items: center;
}
.timebox img {width: 18px;height: 18px;
}
.timebox div {font-size: 0.7vw;margin-left: 4px;
}.contenttitlebox {display: flex;flex-direction: row;flex-wrap: nowrap;justify-content: space-between;
}
.dotbox {display: flex;flex-direction: column;align-items: center;justify-content: center;position: relative;
}
.dotbox:hover {cursor: pointer;
}
.dot {width: 0.2vw;height: 0.3vh;background-color: #787b83;border-radius: 50%;margin: 1.5px;cursor: pointer;
}
.popup {position: absolute;background-color: #fff;padding: 5px 0;z-index: 1000;width: 55px;right: 10px;top: 10px;text-align: center;border-radius: 0.3rem;color: #8e8f95;font-size: 0.8vw;border: 1px solid #ededed;box-sizing: border-box;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.popup:hover {background: #409eff;color: #fff;box-shadow: 0 2px 12px 0 rgb(0 0 0 / 40%);
}
.popup-overlay {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: rgba(0, 0, 0, 0.5); /* 遮罩层颜色 */z-index: 1; /* 确保遮罩层在popup之下 */border-radius: 15px;
}.tabsbox {/* 默认背景样式 */background-color: #fff;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3248469.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

第四章 自定义序列类

目录 5.1 序列类型的分类 容器序列 扁平序列 可变序列 不可变序列 5.2 序列的abc继承关系 5.3 序列的、和extend的区别 操作符 操作符 extend方法 5.4 实现可切片的对象 5.5 bisect管理可排序序列 深入解释 5.6 什么时候我们不该用列表 深入解释 5.7 列表推导式…

第十章 多线程、多进程和线程池编程

目录 11.1 多线程编程 什么是多线程&#xff1f; 创建和启动线程 线程同步 11.2 多进程编程 什么是多进程&#xff1f; 创建和启动进程 进程间通信 11.3 线程池和进程池 什么是线程池和进程池&#xff1f; 使用线程池 使用进程池 11.4 选择多线程还是多进程 适用…

vue3 vxe-grid修改currentPage,查询数据的时候,从第一页开始查询

1、当我们设置好VxeGrid.Options进行数据查询的时候,下面是可能的设置&#xff1a; const gridOptions reactive<BasicTableProps>({id: UserTable,showHeaderOverflow: false,showOverflow: true,keepSource: true,columns: userColumns,size: small,pagerConfig: {cur…

【常见开源库的二次开发】基于openssl的加密与解密——单向散列函数(四)

目录&#xff1a; 目录&#xff1a; 一、什么是单项散列函数&#xff1f; 1.1 如何验证文件是否被修改过 1.2 单项散列函数&#xff1a; 二、单向hash抗碰撞 2.1 弱抗碰撞&#xff08;Weak Collision Resistance&#xff09; 2.2 强抗碰撞&#xff08;Strong Collision Resista…

[GXYCTF2019]Ping Ping Ping1

打开靶机 结合题目名称&#xff0c;考虑是命令注入&#xff0c;试试ls 结果应该就在flag.php。尝试构造命令注入载荷。 cat flag.php 可以看到过滤了空格,用 $IFS$1替换空格 还过滤了flag&#xff0c;我们用字符拼接的方式看能否绕过,ag;cat$IFS$1fla$a.php。注意这里用分号间隔…

【光伏发电功率预测】方法综述学习笔记2《光伏发电功率超短期预测方法综述》

本文参考《光伏发电功率超短期预测方法综述》&#xff1a;https://d.wanfangdata.com.cn/periodical/ChlQZXJpb2RpY2FsQ0hJTmV3UzIwMjQwNzA0Eg5nZHlqczIwMjMwNzAyNBoIeHp4NW40YmU%3D 文章目录 摘要&#xff1a;引言1. 光伏发电功率的影响因素分析1.1传递过程中的影响因素1.1.1…

DDei在线设计器-数据格式说明

数据格式说明 DDei的所有设计数据都以文件为单位保存在一个JSON对象中。JSON对象包含了全量的页签、舞台、图层、控件的位置以及属性信息。开发人员可以存储这个JSON到服务端数据库中&#xff0c;从而轻易的实现保存功能&#xff1b;也解析这个JSON&#xff0c;将其转换成自己业…

对红酒品质进行数据分析(python)

http://t.csdnimg.cn/UWg2S 数据来源于这篇博客&#xff0c;直接下载好csv文件。 这篇内容均在VScode的jupyter notebook上完成&#xff0c;操作可以看我的另一篇博客&#xff1a;http://t.csdnimg.cn/69sDJ 一、准备工作 1. 导入数据库 #功能是可以内嵌绘图&#xff0c;并…

用了6年git,不知道cherry-pick是啥意思

背景 可能是测试开发角色原因&#xff0c;平时很少有代码冲突或多人协同的编码场景。今天有个协同项目&#xff0c;需要提交自己的代码到其它业务的代码库中&#xff0c;这个代码库是分支开发分支上线模式&#xff0c;同时会有多个同事提交代码&#xff0c;然后模块负责的同学…

常用优秀内网穿透工具(实测详细版)

文章目录 1、前言2、安装Nginx3、配置Nginx4、启动Nginx服务4.1、配置登录页面 5、内网穿透5.1、cpolar5.1.1、cpolar软件安装5.1.2、cpolar穿透 5.2、Ngrok5.2.1、Ngrok安装5.2.2、随机域名5.2.3、固定域名5.2.4、前后端服务端口 5.3、NatApp5.4、Frp5.4.1、下载Frp5.4.2、暴露…

【数学建模】——【线性规划】及其在资源优化中的应用

目录 线性规划问题的两类主要应用&#xff1a; 线性规划的数学模型的三要素&#xff1a; 线性规划的一般步骤&#xff1a; 例1&#xff1a; 人数选择 例2 &#xff1a;任务分配问题 例3: 饮食问题 线性规划模型 线性规划的模型一般可表示为 线性规划的模型标准型&…

vue2.0结合使用 el-scrollbar 和 v-for实现一个横向滚动的元素列表,并且能够自动滚动到指定元素(开箱即用)

效果图&#xff1a; 代码&#xff1a; <div class"gas-mode-item-body"><el-scrollbar style"width: 300px;height: 100%;" wrap-style"overflow-y:hidden" ref"scrollbarRef"><div style"display: flex&quo…

Python Linux环境(Centos8)安装minicoda3+jupyterlab

文章目录 安装miniconda安装python环境启动 最近服务器检查&#xff0c;我下面的服务器有漏洞&#xff0c;不得已重装了&#xff0c;正好记录下怎么从零到python写代码。 安装miniconda miniconda是anconda的精简版&#xff0c;就是管理python环境的得力助手。 # 创建一个名…

7.18 学习笔记 解决分页越界问题 及分页查询

1.解决分页越界 1.1出现的问题 于是我索性把分页去掉想是不是就可以了&#xff0c;结果发现还不行 1.2解决方法 就当我找了一两个小时抓耳挠腮时&#xff0c;万幸在csdn上找到了相关的帖子&#xff0c;在此感谢一下那位大佬。 原因是我的实体类中没有构造方法&#xff0c;那…

软考系规百天备考攻略:基础阶段的三轮强化

早在今年4-5月份的时候&#xff0c;我就曾经讲过系统规划与管理师的备考建议&#xff0c;也就是先从教程学起&#xff0c;先读教程&#xff0c;而且我也说过&#xff0c;不要迷信任何培训班或者培训视频&#xff0c;任何培训班或者培训视频都不能取代你认真读至少一遍教程&…

BIOMOD2 物种分布模拟教程

原文链接&#xff1a;BIOMOD2 物种分布模拟教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247609373&idx5&sn492e7597314a5f9e358c35e4780b275f&chksmfa826dfacdf5e4ecf8ac06bdeba5469b31650bdbefbc8fb88b79c0f332714c453a4cc058d29f&token155…

Calibration相机内参数标定

1.环境依赖 本算法采用张正友相机标定法进行实现&#xff0c;内部对其进行了封装。 环境依赖为 ubuntu20.04 opencv4.2.0 yaml-cpp yaml-cpp安装方式&#xff1a; &#xff08;1&#xff09;git clone https://github.com/jbeder/yaml-cpp.git #将yaml-cpp下载至本地 &a…

15- 微分方程

对三角函数不敏感

模块化沙箱:解锁数据防泄密的终极密码

在这个数字化时代&#xff0c;数据已经成为企业最宝贵的资产之一。然而&#xff0c;数据泄露的威胁如同暗夜中的幽灵&#xff0c;随时可能侵袭企业的信息安全防线。面对日益复杂的内外部风险&#xff0c;企业亟需一种既高效又灵活的安全解决方案&#xff0c;来保护其核心数据不…

专业PDF编辑工具:Acrobat Pro DC 2024.002.20933绿色版,提升你的工作效率!

软件介绍 Adobe Acrobat Pro DC 2024绿色便携版是一款功能强大的PDF编辑和转换软件&#xff0c;由Adobe公司推出。它是Acrobat XI系列的后续产品&#xff0c;提供了全新的用户界面和增强功能。用户可以借助这款软件将纸质文件转换为可编辑的电子文件&#xff0c;便于传输、签署…