Vue-App桌面程序列表

Vue-App桌面程序列表

    • 文章说明
    • 讲解视频
    • 核心代码
    • 效果展示
    • 项目链接

文章说明

采用Vue实现PC端的桌面程序列表,采用HBuilderX将程序转化为5+App,实现移动端的适配;支持桌面打开新应用,底部导航展示当前应用列表,可切换或关闭应用

讲解视频

Vue-App桌面程序列表-系统运行演示视频

核心代码

桌面组件核心代码

<template><div class="desktop-container"><div><div v-for="item in data.appList" :key="item.id" class="single-app" @click="openApp(item)"><i :class="'icon-' + item.ico" :style="{ 'color' : item.color}" class="iconfont"></i><div>{{ item.name }}</div></div></div><div v-show="data.openApp.id" class="open-app"><div class="content"><iframe :src="data.openApp.path" style="height: 100%; width: 100%; border: none"></iframe></div></div></div>
</template><script setup>
import {onBeforeMount, reactive} from "vue";
import {appList, BottomNavMessageType} from "@/util/constant";const data = reactive({appList: [],openApp: {id: null,path: null,},
});let bottomNavChannel;onBeforeMount(() => {bottomNavChannel = new BroadcastChannel("bottomNav");data.appList = appList;bottomNavChannel.onmessage = event => {const transferData = event.data;if (transferData.type === BottomNavMessageType.activeOrMinimize) {data.openApp.id = transferData.content.id;data.openApp.path = transferData.content.path;} else if (transferData.type === BottomNavMessageType.toHome) {data.openApp.id = null;data.openApp.path = null;}};
});let clickTime = 0;
const interval = 500;function openApp(item) {if (new Date() - clickTime > interval) {clickTime = new Date();return;}data.openApp.id = item.id;data.openApp.path = item.path;bottomNavChannel.postMessage({type: BottomNavMessageType.openApp,content: {id: item.id,ico: item.ico,color: item.color,name: item.name,path: item.path,}});bottomNavChannel.postMessage({type: BottomNavMessageType.topApp,content: {id: item.id,}});
}
</script><style lang="scss" scoped>
.desktop-container {width: 100%;height: calc(100% - 3rem);background-image: url(../img/desktop.jpg);background-position: center center;background-repeat: no-repeat;background-attachment: fixed;background-size: cover;position: relative;overflow: hidden;padding: 0.5rem;.single-app {display: inline-flex;width: 5rem;height: 5rem;user-select: none;position: relative;&:hover {background-color: #94b5cd;cursor: default;}i::before {font-size: 3rem;position: absolute;left: 50%;top: 35%;transform: translateX(-50%) translateY(-50%);}div {width: 100%;padding: 0 0.5rem;text-align: center;font-size: 0.9rem;color: white;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;position: absolute;left: 50%;top: 80%;transform: translateX(-50%) translateY(-50%);}}.open-app {width: 100%;height: 100%;position: absolute;left: 0;top: 0;margin: 0;padding: 0;border: 0.1rem solid #b1b1b1;.content {position: relative;background-color: #ffffff;width: 100%;height: 100%;}}
}
</style>

底部导航组件核心代码

<template><div class="bottom-menu-container"><div class="open-app-list"><div v-for="item in data.openAppList" :key="item.id":class="data.openAppIdArray[data.openAppIdArray.length - 1] === item.id ? 'single-openApp-active' : ''"class="single-openApp"@click="activeOrMinimize(item)" @contextmenu.prevent="showCloseMenu(item)"><i :class="'icon-' + item.ico" :style="{ 'color' : item.color}" class="iconfont"></i><div v-if="data.openAppIdArray[data.openAppIdArray.length - 1] === item.id" class="open"></div><div v-if="data.openAppIdArray[data.openAppIdArray.length - 1] !== item.id" class="other"></div><div v-if="item.showClose" class="close" @click.stop="closeApp(item)">关闭应用</div></div></div></div>
</template><script setup>
import {onBeforeMount, reactive} from "vue";
import {BottomNavMessageType} from "@/util/constant";
import {message} from "@/util/util";const data = reactive({openAppList: [],openAppIdArray: [],
});let bottomNavChannel;onBeforeMount(() => {listenBottomNavChannel();document.addEventListener("click", () => {for (let i = 0; i < data.openAppList.length; i++) {data.openAppList[i].showClose = false;}});
});function listenBottomNavChannel() {bottomNavChannel = new BroadcastChannel("bottomNav");bottomNavChannel.onmessage = event => {const transferData = event.data;if (transferData.type === BottomNavMessageType.openApp) {let isOpen = false;for (let i = 0; i < data.openAppList.length; i++) {if (transferData.content.id === data.openAppList[i].id) {isOpen = true;break;}}if (!isOpen) {if (data.openAppList.length === 5) {message("warning", "最多打开5个应用");return;}data.openAppList.push(transferData.content);}} else if (transferData.type === BottomNavMessageType.topApp) {data.openAppIdArray = data.openAppIdArray.filter(id => id !== transferData.content.id);data.openAppIdArray.push(transferData.content.id);openCurrentApp();}};
}function openCurrentApp() {if (data.openAppIdArray.length > 0) {const topId = data.openAppIdArray[data.openAppIdArray.length - 1];for (let i = 0; i < data.openAppList.length; i++) {if (topId === data.openAppList[i].id) {bottomNavChannel.postMessage({type: BottomNavMessageType.activeOrMinimize,content: {id: data.openAppList[i].id,path: data.openAppList[i].path}});break;}}} else {bottomNavChannel.postMessage({type: BottomNavMessageType.toHome});}
}function activeOrMinimize(item) {if (item.id === data.openAppIdArray[data.openAppIdArray.length - 1]) {data.openAppIdArray = data.openAppIdArray.filter(id => id !== item.id);openCurrentApp();} else {data.openAppIdArray = data.openAppIdArray.filter(id => id !== item.id);data.openAppIdArray.push(item.id);openCurrentApp();}
}function showCloseMenu(item) {for (let i = 0; i < data.openAppList.length; i++) {data.openAppList[i].showClose = false;}item.showClose = true;
}function closeApp(item) {data.openAppIdArray = data.openAppIdArray.filter(id => id !== item.id);data.openAppList = data.openAppList.filter(app => app.id !== item.id);openCurrentApp();
}
</script><style lang="scss" scoped>
.bottom-menu-container {width: 100%;height: 3rem;background-color: #d4e0f7;border-top: 0.1rem solid #afb5c3;user-select: none;.open-app-list {margin: 0 auto;width: 20rem;height: 100%;display: flex;align-items: center;justify-content: center;.single-openApp {height: 2.5rem;width: 2.5rem;border-radius: 0.2rem;margin: 0 0.25rem;position: relative;&:hover {background-color: #ebf3fe;cursor: default;}.iconfont::before {font-size: 1.5rem;position: absolute;top: 45%;left: 50%;transform: translateX(-50%) translateY(-50%);}.open {position: absolute;bottom: 0;width: 1rem;height: 0.2rem;background-color: #0078d4;border-radius: 0.2rem;left: 50%;transform: translateX(-50%);}.other {position: absolute;bottom: 0;width: 0.4rem;height: 0.2rem;background-color: #777b85;border-radius: 0.2rem;left: 50%;transform: translateX(-50%);}.close {position: absolute;top: -2.5rem;left: 50%;width: 5rem;height: 2rem;line-height: 2rem;font-size: 0.8rem;text-align: center;transform: translateX(-50%);background-color: #d5dff1;color: black;z-index: 999;border: 0.1rem solid #c8c8c8;border-radius: 0.5rem;&:hover {background-color: #eeeeee;}}}.single-openApp-active {background-color: #ebf3fe;cursor: default;}}
}
</style>

配置的app程序列表

export const BottomNavMessageType = {openApp: "openApp",topApp: "topApp",activeOrMinimize: "activeOrMinimize",toHome: "toHome",
}export const appList = [{id: 1,name: "页面1",ico: "market",color: "#1cd67c",path: "http://47.99.202.161:5000/index1.html",},{id: 2,name: "页面2",ico: "img",color: "#4c35d3",path: "http://47.99.202.161:5000/index2.html",},{id: 3,name: "页面3",ico: "calculator",color: "#1d2088",path: "http://47.99.202.161:5000/index3.html",},
];

采用媒介查询来控制rem字体大小

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>Vue-App桌面程序列表</title><style>@media screen and (min-width: 200px) {html {font-size: 16px;}}@media screen and (min-width: 400px) {html {font-size: 18px;}}@media screen and (min-width: 600px) {html {font-size: 20px;}}@media screen and (min-width: 1000px) {html {font-size: 22px;}}@media screen and (min-width: 1500px) {html {font-size: 24px;}}</style></head><body><div id="app"></div></body>
</html>

效果展示

PC端展示效果
在这里插入图片描述

App端展示效果
在这里插入图片描述

项目链接

Vue-App桌面程序列表

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php质量工具系列之PHPCPD

PHPCPD 用于检测重复代码&#xff0c;直观的说就是复制粘贴再稍微改改 该工具作者已经 停止维护 安装 composer global require --dev sebastian/phpcpd执行 phpcpd --log-pmd phpcpd_result.xml ./app参数介绍 --log-pmd 将结果保存在phpcpd_result.xml 中 ./app 是phpcpd扫…

Linux系统之部署Blog-Index导航页

Linux系统之部署Blog-Index导航页 一、Blog-Index介绍1.1 Blog-Index简介1.2 Blog-Index特点1.3 Blog-Index使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍2.3 Yarn介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本3.3 检查系统是否安装yarn 四…

VS-qt中运行程序时报错:fatal error RC1015:cannot open include file ‘afxres.h‘

开发环境&#xff1a;VS2015 qt5.12.10 点击运行时报错如下&#xff1a; 搜索了下afxres.h文件&#xff0c;发现位置如下&#xff1a; 看样子是VS中少安装了部分模块导致的&#xff0c;&#xff0c;看了同事的电脑&#xff0c;该文件应该是在以下目录中的&#xff1a; 所…

如何在Python中向Word文档添加段落

如何在Python中向Word文档添加段落 添加段落代码解析添加前与添加后 在这篇博客文章中&#xff0c;我们使用Python向Word文档添加段落。 添加段落 from docx import Document# 打开一个现有的Word文档 doc Document(rC:\Users\Administrator\Desktop\Word文档\example.docx)…

生成式人工智能如何运作?

一、简述 生成式人工智能是一种可用于创建内容&#xff08;包括对话、故事、图像、视频和音乐&#xff09;的人工智能。人工智能技术试图在图像识别、自然语言处理&#xff08;NLP&#xff09;和翻译等非传统计算任务中模仿人类智能。生成式人工智能是人工智能的发展方向。您可…

Ubuntu22.04下源码编译安装pythonocc-7.8

Ubuntu22.04下源码编译安装pythonocc-7.8 本文介绍Ubuntu下手动编译安装pythonocc&#xff0c;及安装过程遇到的各种坑 基本依赖安装 sudo apt-get update sudo apt-get install -y wget libglu1-mesa-dev libgl1-mesa-dev libxmu-dev libxi-dev build-essential cmake libf…

如何提高网站收录?

GSI服务就是专门干这个的&#xff0c;这个服务用的是光算科技自己研发的GPC爬虫池系统。这个系统通过建立一个庞大的站群和复杂的链接结构&#xff0c;来吸引谷歌的爬虫。这样一来&#xff0c;你的网站就能更频繁地被谷歌的爬虫访问&#xff0c;从而提高被收录的机会。 说到效…

【机器学习】【深度学习】优化器(Optimizer)

一、概述 什么是优化器&#xff1f; 优化器(Optimizer)是深度学习中的一个核心的概念&#xff0c;用于更新神经网络的权重&#xff0c;以减少或最小化损失函数(loss function)的值。损失函数衡量了模型的预测值与真实值之间的差异&#xff0c;而优化器的目标是通过调整网络参…

CPU内部结构窥探·「3」

加法器的工作原理&#xff1a;从简单的逻辑到现代计算 我们在cpu内部结构窥探「1」中提到CPU内部ALU的核心部件就是运算器&#xff0c;今天就以加法器为例&#xff0c;来讲解我们ALU中算数逻辑运算的过程。 1.认识数字电路中的各种门电路 2. 什么是加法器&#xff1f; 加法器…

Web UI自动化测试_Selenium+Python

一、概述&#xff1a; 1.1 Selenium是什么 Selenium 是一个基于浏览器的自动化工具&#xff0c;可以跨平台、跨浏览器使用。 Selenium 主要包括三部分&#xff1a; 1、Selenium IDE&#xff1a; Firefox 浏览器的一个插件&#xff08;扩展&#xff09;&#xff0c;它可以进行…

如何检测UV胶的均匀性?

如何检测UV胶的均匀性&#xff1f; 检测UV胶的均匀性可以通过以下几种方法来实现&#xff1a; 肉眼目视检查&#xff1a; 这是最简单直接的方法。将UV胶涂在表面上&#xff0c;使用裸眼观察胶层的表面。特别注意是否存在气泡、颜色不均匀、裂纹或其他明显的不均匀性。如凹凸不…

异步复位和同步释放

文章目录 前言一、为什么需要复位呢&#xff1f;二、同步复位1. 同步复位定义2. 同步复位的实现3. 同步复位的优点和缺点同步复位优点同步复位缺点 三、异步复位1. 异步复位定义2. 异步复位的实现3. 异步复位的优点和缺点异步复位优点异步复位缺点 四、异步复位同步释放1. reco…

Html/HTML5常用标签的学习

课程目标 项目实战&#xff0c;肯定就需要静态网页。朝着做项目方式去学习静态网页。 01、编写第一个html工程结构化 cssjsimages/imgindex.html 归档存储和结构清晰就可以。 02、HTML标签分类 认知&#xff1a;标签为什么要分类&#xff0c;原因因为&#xff1a;分门别类…

关于怎么用Cubemx生成的USBHID设备实现读取一体的鼠标键盘设备(改进版)

主要最近做了一个要用STM32实现读取鼠标键盘一体的那种USB设备&#xff0c;STM32的界面上要和电脑一样的能通过这个USB接口实现鼠标移动&#xff0c;键盘的按键。然后我就很自然的去参考了正点原子的例程&#xff0c;可是找了一圈&#xff0c;发现正点原子好像用的库函数&#…

【计算机网络】对应用层协议中HTTPS协议的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

Oracle的优化器

sql优化第一步&#xff1a;搞懂Oracle中的SQL的执行过程 从图中我们可以看出SQL语句在Oracle中经历了以下的几个步骤&#xff1a; 语法检查&#xff1a;检查SQL拼写是否正确&#xff0c;如果不正确&#xff0c;Oracle会报语法错误。 语义检查&#xff1a;检查SQL中的访问对象…

【C++】用红黑树封装map、set

用红黑树封装map、set 1. 红黑树1.1 模板参数的控制1.1.1 Value1.1.2 KeyOfValue 1.2 正向迭代器1.2.1 构造函数1.2.2 begin()end()1.2.3 operator()1.2.4 operator--()1.2.5 operator*()1.2.6 operator->()1.2.7 operator()1.2.8 operator!()1.2.9 总代码 1.3 反向迭代器1.…

规则引擎-Easy rule

规则引擎-Easy rule 最近有几个项目中都出现了根据XX条件执行XX方法的业务&#xff0c;在动手之前脑中总会下意识的发现如果按照常规的去写代码&#xff0c;无论使用何种设计模式&#xff0c;都会出现不同程度上的代码冗余或大量if-else判断。 甚至说判断XX条件的代码和执行X…

2024中国大学计算机科学与技术专业排名(非常详细)零基础入门到精通,收藏这一篇就够了

今天 6 月 8 号&#xff0c;高考第二天&#xff0c;随着大部分地区的高考结束&#xff0c;接下来就是焦急的等待分数的公布&#xff0c;然后学生们就迎来人生中的一个重要时刻——选择大学和专业。 在众多专业中&#xff0c;计算机科学与技术一直是备受瞩目的热门选择&#xf…