基于Vue3手写选课组件(含时区切换,拖拽选择)
环境说明
基于vue3+vite 无关联别的ui框架,组件化
初次使用vue3,技术菜,大佬勿喷
main.ts
"moment": "^2.29.4","moment-timezone": "^0.5.41",
import moment from 'moment';
import momentTz from "moment-timezone";
import 'moment/dist/locale/zh-cn'
moment.locale('zh-cn')app.config.globalProperties.$moment = moment
// or
window.moment = moment
效果图

代码
<script setup lang="ts">
import { ref, onMounted, onBeforeMount, defineComponent } from "vue";withDefaults(defineProps<{msg: String;show: Boolean;}>(),{msg: () => "测试",show: () => true,}
);const weekData:any = ref([{time: "2023-03-06",mmDD: "03/06",week: "周一",},{time: "2023-03-07",mmDD: "03/07",week: "周二",},{time: "2023-03-08",mmDD: "03/08",week: "周三",},{time: "2023-03-09",mmDD: "03/09",week: "周四",},{time: "2023-03-10",mmDD: "03/10",week: "周五",},{time: "2023-03-11",mmDD: "03/11",week: "周六",},{time: "2023-03-12",mmDD: "03/12",week: "周日",},
]);const selectTimes = ref([]);
const drag = ref(false);
const utc = ref("");
const oldUtc = ref("");
const moment = window.momentonBeforeMount(() => {// request databuildWeekTimeInitData();oldUtc.value = Intl.DateTimeFormat().resolvedOptions().timeZone;utc.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
});onMounted(() => {// load charts// 构造数据
});const buildWeekTimeInitData = () => {const start = 0;const end = 48;var times:any = [];var pref = 0;var aft = 0;for (var i = start; i < end; i++) {var pe = pref + "";var be = aft + "";if (pe.length == 1) {pe = "0" + pe;}if (be.length == 1) {be = "0" + be;}var temp = { value: pe + ":" + be };// 模拟不可选// if(i > 30){// temp.notSelect = true// }times.push(temp);aft = aft + 30;if (aft == 60) {pref = pref + 1;aft = 0;}}console.log(times);var index = 0;weekData.value.map((val:any) => {weekData.value[index]["times"] = JSON.parse(JSON.stringify(times));index++;});selectUTC(null);
};const selectTime = async (week: any, time: any, onlyIn: Boolean) => {// console.log(week,time)var key:any = week.time + "_" + time.value;if (selectTimes.value.includes(key)) {selectTimes.value.splice(selectTimes.value.indexOf(key), 1);} else {selectTimes.value.push(key);}
};const mousedownHandler = async (w:any, t:any) => {drag.value = true;setTimeout(() => {mousemoveHandler(w, t);}, 10);
};const mouseClickHandler = async (w:any, t:any) => {await selectTime(w, t,false);
};const mouseupHandler = async () => {drag.value = false;
};const mousemoveHandler = async (w:any, t:any) => {await setTimeout(async () => {if (drag.value) {if (!t.notSelect) {await selectTime(w, t, true);} else {// 无法选中}}}, 50);
};const selectUTC = (v:any) => {if (!v) {v = Intl.DateTimeFormat().resolvedOptions().timeZone;} else {v = v.target.value || Intl.DateTimeFormat().resolvedOptions().timeZone;}utc.value = v;console.log("切换时区", utc.value);var selectedTimes = JSON.parse(JSON.stringify(selectTimes.value));// console.log(selectedTimes)var preSelectedTimes:any = [];selectedTimes.map((val:any) => {preSelectedTimes.push(val.replace("_", " ") + ":00");});// console.log(preSelectedTimes)var afterSelectedTimes:any = [];preSelectedTimes.map((vt:any) => {// var vdate = new Date(v+ ' '+moment().format('z'))var utcUnit = utc.value;console.log("转时区:", utcUnit);console.log(vt);var newYork = convatTime(vt, oldUtc.value, utc.value);var spi = newYork.split(" ");var pft = spi[0] + "_" + spi[1].substring(0, 5);afterSelectedTimes.push(pft);// console.log(vt,newYork)});console.log("最终:", afterSelectedTimes);selectTimes.value = JSON.parse(JSON.stringify(afterSelectedTimes));oldUtc.value = JSON.parse(JSON.stringify(utc.value));
};const convatTime = (vt:any, fromZone:any, toZone:any) => {console.log("将" + vt, "原格式" + fromZone, "最终格式" + toZone);var zoreDate = new Date(vt + " " + moment().tz(fromZone).format("Z"));var newYork = moment.tz(zoreDate, toZone).format("YYYY-MM-DD HH:mm:ss");return newYork;
};
const convatTimeStrap = (vt:any, fromZone:any, toZone:any) => {console.log("将" + vt, "原格式" + fromZone, "最终格式" + toZone);var zoreDate = new Date(vt + " " + moment().tz(fromZone).format("Z"));var newYork = moment.tz(zoreDate, toZone)._d.getTime();return newYork;
};const submit = () => {var utcData = JSON.parse(JSON.stringify(utc.value))var wtimes:any = []var selectedTimes = JSON.parse(JSON.stringify(selectTimes.value));// console.log(selectedTimes)var preSelectedTimes:any = [];selectedTimes.map((val:any) => {preSelectedTimes.push(val.replace("_", " ") + ":00");});preSelectedTimes.map((val:any)=>{var utcV = convatTimeStrap(val,utcData,'UTC')wtimes.push(utcV)})console.log(preSelectedTimes,utcData)console.log('结果:',wtimes)}const changeWeek = (tag:any) => {if(tag == '>'){console.log('向'+tag+'移动')}else if(tag == '<'){console.log('向'+tag+'移动')}
}</script><template><div class="fc-calendar"><div>日历</div><div>{{ selectTimes }}</div><div><select v-model="utc" @change="selectUTC"><option value="Asia/Shanghai">Asia/Shanghai</option><option value="America/New_York">America/New_York</option></select><button @click="submit">提交</button></div><!-- 左右选择 --><div class="fc-calendar-week"><div class="fc-calendar-arror" @click="changeWeek('<')">{{ "<" }}</div><divclass="fc-calendar-week_item"v-for="(week, index) in weekData":key="index"><div>{{ week.week }}</div><div>{{ week.mmDD }}</div></div><div class="fc-calendar-arror" @click="changeWeek('>')">{{ ">" }}</div></div><div class="fc-calendar-tip"><span> * 点击或拖拽即可选择</span></div><divclass="fc-calendar-time"@mouseleave="drag = false"@mouseup="mouseupHandler()"><divclass="fc-calendar-time-col"v-for="(week, index) in weekData":key="index"><divv-for="(t , idx) in week.times":key="idx"class="fc-calendar-time-row"@click="mouseClickHandler(week, t)"@mousedown="mousedownHandler(week, t)"@mouseenter="mousemoveHandler(week, t)"><div v-if="t.notSelect" :class="'not-select'">{{ t.value }}</div><divv-else:class="selectTimes.includes(week.time + '_' + t.value)? 'select': 'unselect'"@click="selectTime(week, t,false)">{{ t.value }}</div></div></div></div></div>
</template><style scoped>
.fc-calendar {width: 62%;border: 1px solid;padding: 4px;
}.fc-calendar-week {display: flex;justify-content: space-around;text-align: center;padding-bottom: 1rem;
}.fc-calendar-week_item {width: 3rem;border-radius: 7px;cursor: pointer;
}.fc-calendar-tip {text-align: center;
}.fc-calendar-time-col {display: inline-flex;justify-content: space-around;align-items: center;flex-direction: column;align-content: space-between;width: 14%;
}.fc-calendar-time-row {display: block;border: 1px solid #939393;line-height: 2.4rem;margin-bottom: 10px;width: 88%;text-align: center;border-radius: 1px;margin: 5px 9px;cursor: pointer;user-select: none;
}
.fc-calendar-time-row-select {display: block;border: 1px solid #939393;line-height: 2.4rem;margin-bottom: 10px;width: 88%;text-align: center;border-radius: 5px;margin: 5px 9px;cursor: pointer;background-color: #0b8049;color: #fff;user-select: none;
}.fc-calendar-time-row:hover {background-color: #0b8049;color: #fff;
}
.select {background-color: #0b8049;color: #fff;
}.unselect {background-color: #fff;color: #000;
}.not-select {background-color: #939393;color: #fff;cursor: not-allowed;
}.fc-calendar-arror {font-size: larger;position: relative;top: 8px;font-weight: 800;font-family: fangsong;cursor: pointer;
}
</style>相关文章:
基于Vue3手写选课组件(含时区切换,拖拽选择)
环境说明 基于vue3vite 无关联别的ui框架,组件化 初次使用vue3,技术菜,大佬勿喷 main.ts "moment": "^2.29.4","moment-timezone": "^0.5.41",import moment from moment; import momentTz from &…...
准备好了吗?加入 GDE 成长计划,成为下一位谷歌开发者专家!
谷歌开发者专家 (Google Developer Experts,GDE),又称谷歌开发者专家项目,是由一群经验丰富的技术专家、具有社交影响力的开发者和思想领袖组成的全球性社区。通过在各项活动演讲以及各个平台上发布优质内容来积极助力开发者、企业和技术社区…...
搭建帮助中心的 8 个最佳工具
网站帮助中心的作用通过向客户表明您了解他们所面临的问题以及如何提供帮助来建立信任;通过回答常见问题来改善客户服务,增强专业的品牌形象;通过减少重复发送给支持人员的电话和电子邮件,节省时间和金钱;增强您在搜索…...
LQB小板焊接V3版本的小板原理图,PCB图,注意事项和步骤
第一部分,这个部分,可以不焊接,直接用买的下载器进行下载代码,外接一个下载器,网上大概是10元左右,以后学习stm32的芯片的时候,这个下载器就是一个串口转换器,也可以使用。。 当然也…...
华为OD机试真题Python实现【翻转单词顺序】真题+解题思路+代码(20222023)
翻转单词顺序 题目 输入一个英文文章片段 翻转指定区间的单词顺序,标点符号和普通字母一样处理 例如输入字符串 I am a developer. 区间[0,3]则输出 developer. a am I 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 使用换行隔…...
微机原理和计算机组成原理复习
1:冯诺依曼机器的主要特点? 1)计算机由运算器、存储器、控制器、输入设备和输出设备五大部分组成; 2)指令和数据存储在存储器中,并可以按地址访问; 3)指令和数据均以二进制表示&…...
mysql5.7.33安装配置教程【保姆级安装教程】
MySQL5.7.33安装教程 1、官方网站下载 点击这里跳转页面下载 1.1、看下你是什么系统,系统是64位还是32位 2、解压到D盘跟路径或者其下面纯英文路径 2.1、可见它没有data、log等文件夹,不需手动添加(下面执行命令自动初始化)!! …...
每天都和时间序列打交道,我总结了这篇文章!
Datawhale干货 作者:戳戳龍,上海交通大学,量化算法工程师前言🔴 平时工作中每天都在和时间序列打交道,对时间序列分析进行研究是有必要的🟡 分享和交流一些自己的在时序处理方面的心得,提供一…...
【Leetcode——重排链表】
文章目录一、重排链表思路1.思路2.总结一、重排链表 对于这道题,有两种思路: 思路1. 1.使用一个线性表,存储链表中的每个节点,然后按照题目的条件,来链接线性表的各个节点即可。 使用左下标和右下标来定位线性表中的…...
HCIP总结(一)
抽象语言---编码---二进制---电信号----处理电信号 (电脑工作流程) OSI参考模型 ----OSI/RM (核心思想:分层) 应用层----提供各种应用服务,将抽象语言转换成编码,提供人机交互的接口 表示层----将编码转换成二进制 …...
华为OD机试真题Python实现【黑板上色】真题+解题思路+代码(20222023)
题目 疫情过后希望小学终于又重新开学了,3 年 2 班开学第一天的任务是将后面的黑板报重新制作, 黑板上已经写上了N个正整数,同学们需要给这每个数分别上一种颜色, 为了让黑板报既美观又有学习意义,老师要求同种颜色的所有数都可以被这个颜色中最小的那个数整除, 现在帮小…...
C++中的利器——模板
前文本文主要是讲解一下C中的利器——模板,相信铁子们在学完这一节后,写代码会更加的得心应手,更加的顺畅。一,泛型编程想要学习模板,我们要先了解为什么需要模板,我们可以看看下面这个程序。int add(int&a…...
k8s控制器
目录 一、控制器简介 二、控制器类型 1、RC和RS 2、Deployment 3、DaemonSet 4、Job 5、CronJob 6、StateFulSet 7、HPA 一、控制器简介 在kubernetes中,按照Pod的创建方式可以将其分为两类: 自主式:kubernetes直接创建出来的Pod,…...
嵌入式学习笔记——认识STM32的 GPIO口
寄存器开发STM32GPIO口前言认识GPIOGPIO是什么GPIO有什么用GPIO怎么用STM32上GPIO的命名以及数量GPIO口的框图(重点)输入框图解析三种输入模式GPIO输入时内部器件及其作用1.保护二极管2.上下拉电阻(可配置)3.施密特触发器4.输入数…...
类和对象(中)
文章目录 继承的概念继承的语法父类成员访问super关键字子类构造方法super和this初始化protected关键字继承方式final关键字继承与组合一、继承的概念 继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类…...
Java——单词接龙
题目链接 leetcode在线oj题——单词接龙 题目描述 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk: 每一对相邻的单词只差一个字母。 对于 1 < i < k 时ÿ…...
HTML DOM 事件监听器
通过JavaScript,我们可以给页面的某些元素添加事件的监听器,当元素触发相应事件的时候监听器就会捕捉到这个事件并执行相应的代码。addEventListener() 方法实例当用户点击按钮时触发监听事件:document.getElementById("myBtn").ad…...
java基本数据类型取值范围
在JAVA中一共有八种基本数据类型,他们分别是 byte、short、int、long、float、double、char、boolean 整型 其中byte、short、int、long都是表示整数的,只不过他们的取值范围不一样 byte的取值范围为-128~127,占用1个字节(-2的…...
maven的安装配置
目录 1. Maven的安装配置 1.1检测jdk的版本 1.2下载maven 1.3配置maven环境变量 2.认识maven的目录结构 2.1 创建一个文件夹作为项目的根目录 1.创建如下结构的目录 2. 在pom.xml文件中写入如下内容(不用记忆) 3.在mian-->java--》下边创建java文件编辑 4.cmd下…...
【转载】System Verilog 上下文context的含义以及设置导入函数的作用域
放丢失,转载一下,原文:https://blog.csdn.net/qq_31348733/article/details/1010546251. 上下文(context)的含义导入函数的上下文是该函数定义所在的位置,比如$unit 、模块、program或者package作用域(scope),这一点跟…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
