用 Vue 3.5 TypeScript 做了一个日期选择器(改进版)

上一篇 已经实现了一个日期选择器,只不过是模态窗的形式,这个版本改为文本框弹出,点击空白处可关闭日历

代码也增加了不少

<template><div><!-- 添加文本框 --><div class="date-picker-input-wrapper"><inputtype="text"v-model="selectedDateText"@click="showCalendar = true"readonlyplaceholder="请选择日期"class="date-picker-input"ref="inputRef"/><span class="clear-date-button" @click="clearDate" v-if="selectedDateText"><svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg></span></div><!-- 日期选择器 --><div class="e-calendar" v-show="showCalendar" ref="calendarRef"><div class="e-date-year"><transition name="fadeY"><div:key="selectDate.year"class="e-date-year-select"@click="openYearList":class="{ active: showYear }">{{ selectDate.year }}</div></transition></div><div class="e-date-monthday"><transition name="fadeY"><div:key="selectDate.day"class="e-date-monthday-select":class="{ active: !showYear }"@click="openCalendarList"><span>{{ keepDoubleDigit(selectDate.month) }}-{{ keepDoubleDigit(selectDate.day) }}</span>&nbsp;<span style="cursor: pointer;" @click="openMonthList">{{ showDate.monthStr }}</span></div></transition></div><div class="e-calendar-container" v-show="!showYear && !showMonth"><div class="e-calendar-toolbar"><div class="e-calendar-svg" @click="prevMonth"><svg viewBox="0 0 24 24" class="e-calendar-svg-icon"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path></svg><transition name="e_calendar_svg_btn"><div class="e-calendar-svg-cover" v-if="prevMonthClick"></div></transition></div><div class="e-calendar-toolbar-title"><transition :name="fadeXType"><div:key="showDate.monthStr"class="e-calendar-toolbar-title-content"><strong>{{ showDate.year }}</strong>&nbsp;<span style="cursor: pointer;" @click="openMonthList">{{ showDate.monthStr }}</span></div></transition></div><div class="e-calendar-svg" @click="nextMonth"><svg viewBox="0 0 24 24" class="e-calendar-svg-icon"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></svg><transition name="e_calendar_svg_btn"><div class="e-calendar-svg-cover" v-if="nextMonthClick"></div></transition></div></div><div class="e-calendar-week"><span class="e-calendar-week-day">一</span><span class="e-calendar-week-day">二</span><span class="e-calendar-week-day">三</span><span class="e-calendar-week-day">四</span><span class="e-calendar-week-day">五</span><span class="e-calendar-week-day">六</span><span class="e-calendar-week-day">日</span></div><div class="e-calendar-monthday"><transition :name="fadeXType"><div:key="showDate.monthStr"class="e-calendar-monthday-wrapper"><divv-for="(row, index) in rows":key="index"class="e-calendar-monthday-row"><spanv-for="(day, dayIndex) in row":key="dayIndex"class="e-calendar-monthday-row-day"@click="selectDay(day)"@mouseenter="handleDayMouseEnter(dayIndex, index)"@mouseleave="handleDayMouseLeave(dayIndex, index)":class="{active: day.selected,disabled: day.disabled,pointer: day.value!== '',hover: isDayHovered(dayIndex, index)}"><spanv-text="day.value"class="e-calendar-monthday-row-day-value"></span><transition name="e_calendar_day"><spanclass="e-calendar-monthday-row-day-cover"v-if="day.selected"></span></transition></span></div></div></transition></div></div><ul class="e-calendar-year" v-show="showYear" ref="yearList"><liv-for="(item, index) in yearList":key="index":class="{active: item === selectDate.year,hover: isYearHovered(index)}"@click="selectYear(item)"@mouseenter="handleYearMouseEnter(index)"@mouseleave="handleYearMouseLeave()">{{ item }}</li></ul><ul class="e-calendar-year" v-show="showMonth" ref="monthList"><liv-for="(item, index) in monthList":key="index":class="{active: item === selectDate.month,hover: isMonthHovered(index)}"@click="selectMonth(item)"@mouseenter="handleMonthMouseEnter(index)"@mouseleave="handleMonthMouseLeave()">{{ item }}</li></ul></div></div>
</template><script lang="ts">
import { defineComponent, ref, computed, onBeforeMount, onMounted, onUnmounted } from 'vue';// 阿拉伯数字 转 汉字数字的基本库
const weekJson = {1: '星期一',2: '星期二',3: '星期三',4: '星期四',5: '星期五',6: '星期六',7: '星期日',
};
const monthJson = {1: '一月',2: '二月',3: '三月',4: '四月',5: '五月',6: '六月',7: '七月',8: '八月',9: '九月',10: '十月',11: '十一月',12: '十二月',
};export default defineComponent({props: {// 打开date picker的初始值,必传,格式是(2017-08-11)date: {type: String,required: true,},// 日期最小值minDate: String,// 日期最大值maxDate: String,},setup(props, { emit }) {// 定义响应式数据let selectDate = ref({year: 0,month: 0,day: 0,week: 0,date: '',weekStr: '',monthStr: '',});let showDate = ref({year: 0,month: 0,day: 0,week: 0,date: '',monthStr: '',weekStr: '',});let copyMinDate = ref({year: 0,month: 0,day: 0,});let copyMaxDate = ref({year: 0,month: 0,day: 0,});const fadeXType = ref('fadeX_Prev');const nextMonthClick = ref(false);const prevMonthClick = ref(false);const showYear = ref(false);const showMonth = ref(false);const yearListRef = ref<HTMLUListElement | null>(null);const monthListRef = ref<HTMLUListElement | null>(null);const showCalendar = ref(false); // 控制日期选择器的显示和隐藏const selectedDateText = ref(''); // 文本框显示的日期const calendarRef = ref<HTMLDivElement | null>(null); // 日期组件的引用const inputRef = ref<HTMLInputElement | null>(null); // 新增文本框引用const hoveredYearIndex = ref(-1);const hoveredMonthIndex = ref(-1);const hoveredDayIndex = ref({ row: -1, col: -1 });const yearList = computed(() => {const result: number[] = [];for (let i = copyMinDate.value.year; i <= copyMaxDate.value.year; i += 1) {result.push(i);}return result;});const monthList = computed(() => {const result: number[] = [];for (let i = 1; i <= 12; i += 1) {result.push(i);}return result;});const rows = computed(() => {const { year, month } = showDate.value;const months = new Date(year, month, 0).getDate();const result: {value: number | string;selected?: boolean;disabled?: boolean;}[][] = [];let row: {value: number | string;selected?: boolean;disabled?: boolean;}[] = [];let weekValue: number;// 按照星期分组for (let i = 1; i <= months; i += 1) {// 根据日期获取星期,并让开头是1,而非0weekValue = new Date(year, month - 1, i).getDay() + 1;// 判断月第一天在星期几,并填充前面的空白区域if (i === 1 && weekValue!== 1) {addRowEmptyValue(row, weekValue);addRowDayValue(row, i);} else {addRowDayValue(row, i);// 判断月最后一天在星期几,并填充后面的空白区域if (i === months && weekValue!== 7) {addRowEmptyValue(row, (7 - weekValue) + 1);}}// 按照一周分组if (weekValue % 7 === 0 || i === months) {result.push(row);row = [];}}showDate.value.monthStr = monthJson[showDate.value.month as keyof typeof monthJson];return result;});// 初始化日期选择器const initDatePicker = () => {const splitResult = splitDate(props.date, true);showDate.value = {...splitResult,date: `${splitResult.year}-${keepDoubleDigit(splitResult.month)}-${keepDoubleDigit(splitResult.day)}`,week: splitResult.week || 0,monthStr: splitResult.monthStr || '',weekStr: splitResult.weekStr || '',};copyMinDate.value = { ...splitDate(props.minDate || '1970-01-01') };copyMaxDate.value = { ...splitDate(props.maxDate || '2099-12-31') };selectDate.value = { ...showDate.value };selectedDateText.value = showDate.value.date;};onBeforeMount(() => {initDatePicker();});// 拆分日期const splitDate = (date: string, addStr = false) => {let result: {year: number;month: number;day: number;week?: number;monthStr?: string;weekStr?: string;} = {year: 0,month: 0,day: 0,};const splitValue = date.split('-');try {if (!splitValue || splitValue.length < 3) {throw new Error('时间格式不正确');}result = {year: Number(splitValue[0]),month: Number(splitValue[1]),day: Number(splitValue[2]),};if (addStr) {result.week = new Date(result.year, result.month - 1, result.day).getDay() + 1;result.monthStr = monthJson[result.month as keyof typeof monthJson];result.weekStr = weekJson[result.week as 1 | 2 | 3 | 4 | 5 | 6 | 7];}} catch (error) {console.error(error);}return result;};// 添加空值const addRowEmptyValue = (row: {value: number | string;selected?: boolean;disabled?: boolean;}[],count: number) => {for (let w = 1; w < count; w += 1) {row.push({value: '',});}};// 添加日期值const addRowDayValue = (row: {value: number | string;selected?: boolean;disabled?: boolean;}[],i: number) => {const value = { value: i };const { day, month, year } = selectDate.value;const showDateValue = showDate.value;// 判断已经选择的if (year === showDateValue.year && month === showDateValue.month && day === i) {// 为对象添加 selected 属性const newValue = { ...value, selected: true };row.push(newValue);}// 当日期在最小值之外,禁止点击if (isMinLimitMonth() && i < copyMinDate.value.day) {// 修复:添加 disabled 属性const newValue = { ...value, disabled: true };row.push(newValue);}// 当日期在最大值之外,禁止点击if (isMaxLimitMonth() && i > copyMaxDate.value.day) {// 修复:添加 disabled 属性const newValue = { ...value, disabled: true };row.push(newValue);}row.push(value);};// 切换到上一个月const prevMonth = () => {if (prevMonthClick.value) {return;}prevMonthClick.value = true;setTimeout(() => {prevMonthClick.value = false;}, 500);fadeXType.value = 'fadeX_Prev';// 如何当前月份已经小于等于minMonth 就不让其在执行if (isMinLimitMonth()) {return;}const { year, month } = showDate.value;// 判断当前月份,如果已经等于1(1就是一月,而不是二月)if (month <= 1) {showDate.value.year = year - 1;showDate.value.month = 12;} else {showDate.value.month -= 1;}};// 切换到下一个月const nextMonth = () => {if (nextMonthClick.value) {return;}nextMonthClick.value = true;setTimeout(() => {nextMonthClick.value = false;}, 500);fadeXType.value = 'fadeX_Next';// 如何当前月份已经大于等于maxMonth 就不让其在执行if (isMaxLimitMonth()) {return;}const { year, month } = showDate.value;// 判断当前月份,如果已经等于12(12就是十二月)if (month >= 12) {showDate.value.year = year + 1;showDate.value.month = 1;} else {showDate.value.month += 1;}};// 重置选择日期let resetSelectDate = (dayValue: number) => {selectDate.value = { ...showDate.value };selectDate.value.day = dayValue;selectDate.value.week = new Date(showDate.value.year, showDate.value.month - 1, dayValue).getDay() + 1;selectDate.value.weekStr = weekJson[selectDate.value.week as keyof typeof weekJson];selectedDateText.value = `${selectDate.value.year}-${keepDoubleDigit(selectDate.value.month)}-${keepDoubleDigit(selectDate.value.day)}`;showCalendar.value = false; // 选择日期后隐藏日期选择器};// 选择日期const selectDay = (days: { value: number | string; disabled?: boolean }) => {if (days.disabled || days.value === '') {return;}resetSelectDate(Number(days.value));const { year, month, day, week, weekStr, monthStr } = selectDate.value;emit('confirm', {date: `${year}-${keepDoubleDigit(month)}-${keepDoubleDigit(day)}`,year,month,week,monthStr,weekStr,day,});};// 选择月份const selectMonth = (value: number) => {showYear.value = false;showMonth.value = false;showDate.value.month = value;let type: 'copyMinDate' | 'copyMaxDate' | undefined;// 当月份在最小值之外,日期换成最小值日期 或者 当月份在最大值之外,日期换成最大值日期if (isMinLimitMonth()) {type = 'copyMinDate';} else if (isMaxLimitMonth()) {type = 'copyMaxDate';}if (type) {showDate.value.day = type === 'copyMinDate'? copyMinDate.value.day : copyMaxDate.value.day;resetSelectDate(showDate.value.day);return;}let dayValue = selectDate.value.day;// 判断日是最大值,防止另一个月没有这个日期const daysInMonth = new Date(showDate.value.year, showDate.value.month + 1, 0).getDate();if (selectDate.value.day > daysInMonth) {dayValue = daysInMonth;}resetSelectDate(dayValue);};// 选择年份const selectYear = (value: number) => {showYear.value = false;showMonth.value = false;showDate.value.year = value;let type: 'copyMinDate' | 'copyMaxDate' | undefined;// 当日期在最小值之外,月份换成最小值月份 或者 当日期在最大值之外,月份换成最大值月份if (isMinLimitMonth()) {type = 'copyMinDate';} else if (isMaxLimitMonth()) {type = 'copyMaxDate';}if (type) {showDate.value.month = copyMinDate.value.month;showDate.value.day = copyMinDate.value.day;resetSelectDate(showDate.value.day);return;}let dayValue = selectDate.value.day;// 判断日是最大值,防止另一个月没有这个日期if (selectDate.value.day > 28) {const months = new Date(showDate.value.year, showDate.value.month, 0).getDate();// 当前月份没有这么多天,就把当前月份最大值赋值给daydayValue = months < dayValue? months : dayValue;}resetSelectDate(dayValue);};// 判断是否为最小月份限制const isMinLimitMonth = () => {return showDate.value.year <= copyMinDate.value.year && showDate.value.month <= copyMinDate.value.month;};// 判断是否为最大月份限制const isMaxLimitMonth = () => {return showDate.value.year >= copyMaxDate.value.year && showDate.value.month >= copyMaxDate.value.month;};// 打开年份列表const openYearList = () => {if (showYear.value) {showYear.value = false;showMonth.value = false;return;}const index = yearList.value.indexOf(selectDate.value.year);showYear.value = true;showMonth.value = false;setTimeout(() => {if (yearListRef.value) {yearListRef.value.scrollTop = (index - 3) * 40;}});};// 打开月份列表const openMonthList = () => {if (showMonth.value) {showYear.value = false;showMonth.value = false;return;}const index = monthList.value.indexOf(selectDate.value.month);showMonth.value = true;showYear.value = false;setTimeout(() => {if (monthListRef.value) {monthListRef.value.scrollTop = (index - 3) * 20;}});};const openCalendarList = () => {showYear.value = false;};// 定义函数,接收一个 number 类型的参数,返回一个 string 类型的值const keepDoubleDigit = (number: number): string => {// 判断传入的数字是否大于 9return number > 9? String(number) : `0${number}`;};// 清除日期的方法const clearDate = () => {selectedDateText.value = '';showCalendar.value = false;};// 点击文本框和日期组件以外的区域,隐藏日期组件const handleClickOutside = (event: MouseEvent) => {if (calendarRef.value &&inputRef.value &&!calendarRef.value.contains(event.target as Node) &&!inputRef.value.contains(event.target as Node)) {showCalendar.value = false;}};const isYearHovered = (index: number) => hoveredYearIndex.value === index;const isMonthHovered = (index: number) => hoveredMonthIndex.value === index;const isDayHovered = (col: number, row: number) =>hoveredDayIndex.value.row === row && hoveredDayIndex.value.col === col;const handleYearMouseEnter = (index: number) => {hoveredYearIndex.value = index;};const handleYearMouseLeave = () => {hoveredYearIndex.value = -1;};const handleMonthMouseEnter = (index: number) => {hoveredMonthIndex.value = index;};const handleMonthMouseLeave = () => {hoveredMonthIndex.value = -1;};const handleDayMouseEnter = (col: number, row: number) => {hoveredDayIndex.value = { row, col };};const handleDayMouseLeave = () => {hoveredDayIndex.value = { row: -1, col: -1 };};onMounted(() => {document.addEventListener('click', handleClickOutside);});onUnmounted(() => {document.removeEventListener('click', handleClickOutside);});return {selectDate,showDate,copyMinDate,copyMaxDate,fadeXType,nextMonthClick,prevMonthClick,keepDoubleDigit,showYear,yearList,rows,yearListRef,prevMonth,nextMonth,selectDay,selectYear,openYearList,openMonthList,monthList,monthListRef,showMonth,selectMonth,openCalendarList,showCalendar,selectedDateText,clearDate,calendarRef,inputRef,isYearHovered,isMonthHovered,isDayHovered,handleYearMouseEnter,handleYearMouseLeave,handleMonthMouseEnter,handleMonthMouseLeave,handleDayMouseEnter,handleDayMouseLeave};},
});
</script><style lang="scss" scoped>
.e-calendar {background-color: #ffffff;width: 310px;border: 1px solid #ccc;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}.date-picker-input-wrapper {position: relative;display: inline-block;
}.date-picker-input {width: 200px;padding: 10px 15px;border: 1px solid #ccc;border-radius: 4px;font-size: 14px;color: #333;box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);transition: border-color 0.3s ease;
}.date-picker-input:focus {outline: none;border-color: #00bcd4;box-shadow: 0 0 5px rgba(0, 188, 212, 0.5);
}.clear-date-button {position: absolute;right: 10px;top: 50%;transform: translateY(-50%);cursor: pointer;width: 20px;height: 20px;display: flex;align-items: center;justify-content: center;
}.clear-date-button svg {fill: #999;width: 16px;height: 16px;
}.clear-date-button:hover svg {fill: #333;
}.e-date-year {font-size: 18px;padding-bottom: 4px;position: relative;width: 66px;height: 25px;overflow: hidden;cursor: pointer;
}.e-date-year-select {position: absolute;opacity: 0.7;font-size: 20px;
}.e-date-year-select.active {opacity: 1;
}.e-date-monthday {font-size: 26px;position: relative;width: 100%;height: 36px;overflow: hidden;
}.e-date-monthday-select {position: absolute;opacity: 0.7;
}.e-date-monthday-select.active {opacity: 1;
}.e-calendar-toolbar {margin: 5px 10px 5px 10px;height: 40px;display: flex;justify-content: space-between;align-items: center;
}.e-calendar-toolbar-title {position: relative;width: 100px;height: 22px;text-align: center;
}.e-calendar-toolbar-title-content {position: absolute;width: 100%;font-size: 16px;
}.e-calendar-svg {padding: 8px;position: relative;height: 40px;width: 40px;display: flex;justify-content: center;align-items: center;
}.e-calendar-svg-icon {display: block;fill: currentColor;height: 24px;width: 24px;user-select: none;position: relative;z-index: 2;
}.e-calendar-svg-cover {position: absolute;left: 0;top: 0;z-index: 1;width: 100%;height: 100%;background-color: #e0e0e0;border-radius: 50%;opacity: 0;display: inline-block;
}.e-calendar-week {width: 100%;font-size: 12px;color: rgba(0, 0, 0, 0.87);opacity: 0.5;display: flex;justify-content: center;align-items: center;height: 16px;
}.e-calendar-week-day {flex: 1;text-align: center;
}.e-calendar-monthday {padding-top: 10px;font-size: 14px;position: relative;width: 100%;min-height: 210px;overflow: hidden;
}.e-calendar-monthday-wrapper {position: absolute;width: 100%;height: 100%;
}.e-calendar-monthday-row {display: flex;justify-content: center;align-items: center;
}.e-calendar-monthday-row-day {display: flex;justify-content: center;align-items: center;flex: 1;position: relative;height: 35px;
}.e-calendar-monthday-row-day.pointer {cursor: pointer;
}.e-calendar-monthday-row-day.active {color: #ffffff;
}.e-calendar-monthday-row-day.disabled {opacity: 0.4;cursor: not-allowed;
}.e-calendar-monthday-row-day-value {position: relative;z-index: 1;
}.e-calendar-monthday-row-day-cover {width: 25px;height: 25px;background-color: #00bcd4;position: absolute;left: 10px;top: 5px;transform: translate3d(0, 0, 0);z-index: 0;border-radius: 50%;opacity: 1;display: block;
}.e-calendar-monthday-row-day.hover {background-color: #e0e0e0; /* 鼠标悬停时的背景颜色,可按需调整 */
}.e-calendar-year {height: 276px;overflow: auto;
}.e-calendar-year li {padding: 10px;text-align: center;font-size: 16px;cursor: pointer;
}.e-calendar-year li.active {color: #00bcd4;font-size: 20px;font-weight: bold;
}.e-calendar-year li.hover {background-color: #e0e0e0; /* 这里设置鼠标悬停时的背景颜色,可按需调整 */
}.fadeX_Prev-enter-active,
.fadeX_Prev-leave-active,
.fadeX_Next-enter-active,
.fadeX_Next-leave-active,
.fadeY-enter-active,
.fadeY-leave-active {transition: all 0.5s;
}.fadeX_Prev-enter {transform: translateX(-100px);opacity: 0;
}.fadeX_Prev-leave-active {transform: translateX(100px);opacity: 0;
}.fadeX_Next-enter {transform: translateX(100px);opacity: 0;
}.fadeX_Next-leave-active {transform: translateX(-100px);opacity: 0;
}.fadeY-enter {transform: translateY(30px);opacity: 0;
}.fadeY-leave-active {transform: translateY(-30px);opacity: 0;
}.e_calendar_svg_btn-enter-active,
.e_calendar_svg_btn-leave-active {transition: all 1s;
}.e_calendar_svg_btn-enter {opacity: 1;
}.e_calendar_day-enter-active {transition: all 0.2s;
}.e_calendar_svg_btn-leave-active,
.e_calendar_day-enter {opacity: 0;
}.e_calendar_day-enter {width: 0;height: 0;transform: translate3d(12px, 12px, 0);
}
</style>

 调用的地方变化不大

<template><DatePicker:date="selectedDate":minDate="minDate":maxDate="maxDate"@confirm="onDateConfirm"@cancel="hideDatePicker"/>
</template><script setup lang="ts"> 
import { ref } from 'vue'; 
import DatePicker from './components/gantt/DatePicker.vue';  
import dayjs from 'dayjs'; // 存储当前选择的日期,初始值为空 
let selectedDate = ref(dayjs().format('YYYY-MM-DD')); 
// 日期的最小值 
const minDate = ref('2000-01-01'); 
// 日期的最大值 
const maxDate = ref('2030-12-31'); // 处理日期选择确认事件 
const onDateConfirm = (dateInfo: { date: string; }) => { selectedDate.value  = dateInfo.date;  console.log('选择的日期信息:', dateInfo);
}; 
const hideDatePicker = () => { // 可以根据需求添加隐藏逻辑,这里暂时不做处理
}; 
</script> 

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

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

相关文章

【09】单片机编程核心技巧:变量赋值,从定义到存储的底层逻辑

【09】单片机编程核心技巧&#xff1a;变量赋值&#xff0c;从定义到存储的底层逻辑 &#x1f31f; 核心概念 单片机变量的定义与赋值是程序设计的基础&#xff0c;其本质是通过 RAM&#xff08;随机存储器&#xff09; 和 ROM&#xff08;只读存储器&#xff09; 的协作实现…

【爬虫】开篇词

一、网络爬虫概述 二、网络爬虫的应用场景 三、爬虫的痛点 四、需要掌握哪些技术&#xff1f; 在这个信息爆炸的时代&#xff0c;如何高效地获取和处理海量数据成为一项核心技能。无论是数据分析、商业情报、学术研究&#xff0c;还是人工智能训练&#xff0c;网络爬虫&…

文字转语音chat-tts-ui

去年已经使用过chattts了&#xff0c;但是昨晚想用的时候却记怎么打开了&#xff0c;找了一下以前的笔记 MacOS 下源码部署chat-tts-ui 配置好 python3.9-3.11 环境,安装git &#xff0c;执行命令 brew install libsndfile git python3.10 继续执行 brew install ffmpeg ​ …

基于SpringBoot+Vue的瑜伽课体验课预约系统【附源码】

基于SpringBootVue的瑜伽课体验课预约系统 一、系统技术说明二、运行说明三、系统的演示四、系统的核心代码演示 一、系统技术说明 框架&#xff1a;SpringbootVue 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软…

sparkTTS window 安装

SparkTTS 的简介 Spark-TTS是一种基于SpardAudio团队提出的 BiCodec 构建的新系统&#xff0c;BiCodec 是一种单流语音编解码器&#xff0c;可将语音策略性地分解为两种互补的标记类型&#xff1a;用于语言内容的低比特率语义标记和用于说话者特定属性的固定长度全局标记。这种…

从零开始:使用 Python 实现机器学习的基础与实践

文章大纲&#xff1a; 引言 机器学习的定义与应用场景。Python 在机器学习领域的优势。本文目标&#xff1a;通过 Python 实现一个简单的机器学习项目。 环境准备 安装 Python 和必要的库&#xff08;如 NumPy、Pandas、Scikit-learn&#xff09;。使用 Jupyter Notebook 或 V…

ApoorvCTF Rust语言逆向实战

上周参加了国外的比赛&#xff0c;名称叫&#xff1a;ApoorvCTF 看一下老外的比赛跟我们有什么不同&#xff0c;然后我根据国内比赛对比发现&#xff0c;他们考点还是很有意思的&#xff0c;反正都是逆向&#xff0c;哈哈哈 Rusty Vault 题目描述&#xff1a; In the heart…

Git和GitHub基础教学

文章目录 1. 前言2. 历史3. 下载安装Git3.1 下载Git3.2 安装Git3.3 验证安装是否成功 4. 配置Git5. Git基础使用5.1 通过Git Bash使用5.1.1 创建一个新的仓库。5.1.1.1 克隆别人的仓库5.1.1.2 自己创建一个本地仓库 5.1.2 管理存档 5.2 通过Visual Studio Code使用 6. Git完成远…

MySQL中like模糊查询如何优化?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL中like模糊查询如何优化?】面试题。希望对大家有帮助&#xff1b; MySQL中like模糊查询如何优化? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中&#xff0c;LIKE 模糊查询虽然非常常见&#xff0c;…

⭐LeetCode(数学分类) 2. 两数相加——暴力与优化⭐

⭐LeetCode(数学分类) 2. 两数相加——暴力与优化⭐ 提示&#xff1a; 每个链表中的节点数在范围 [1, 100] 内 0 < Node.val < 9 题目数据保证列表表示的数字不含前导零 题解&#xff1a; 暴力与优化&#xff0c;暴力即转换为十进制解题&#xff0c;优化即直接在链表上进…

①Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网

Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网https://item.taobao.com/item.htm?ftt&id784749793551 MODBUS TCP 通信单元 MODBUS TCP 转 RS485 MS-A1-50X1 系列概述 MS-A1-50X1 系列概述 MS-A1-50X1系列作为MODBUS TCP通信的服务器进行动作。可通…

基于PyTorch的深度学习——机器学习3

激活函数在神经网络中作用有很多&#xff0c;主要作用是给神经网络提供非线性建模能力。如果没有激活函数&#xff0c;那么再多层的神经网络也只能处理线性可分问题。 在搭建神经网络时&#xff0c;如何选择激活函数&#xff1f;如果搭建的神经网络层数不多&#xff0c;选择si…

力扣:找到一个数字的 K 美丽值(C++)

一个整数 num 的 k 美丽值定义为 num 中符合以下条件的 子字符串 数目&#xff1a; 子字符串长度为 k 。子字符串能整除 num 。 给你整数 num 和 k &#xff0c;请你返回 num 的 k 美丽值。 注意&#xff1a; 允许有 前缀 0 。0 不能整除任何值。 一个 子字符串 是一个字符串里…

C/C++蓝桥杯算法真题打卡(Day3)

一、P8598 [蓝桥杯 2013 省 AB] 错误票据 - 洛谷 算法代码&#xff1a; #include<bits/stdc.h> using namespace std;int main() {int N;cin >> N; // 读取数据行数unordered_map<int, int> idCount; // 用于统计每个ID出现的次数vector<int> ids; …

<建模软件安装教程1>Blender4.2系列

Blender4.2安装教程 0注意&#xff1a;Windows环境下安装 第一步&#xff0c;百度网盘提取安装包。百度网盘链接&#xff1a;通过网盘分享的文件&#xff1a;blender.zip 链接: https://pan.baidu.com/s/1OG0jMMtN0qWDSQ6z_rE-9w 提取码: 0309 --来自百度网盘超级会员v3的分…

C语言八股---预处理,编译,汇编与链接篇

前言 从多个.c文件到达一个可执行文件的四步:   预处理–>编译–>汇编–>链接 预处理 预处理过程就是预处理器处理这些预处理指令(要不然编译器完全不认识),最终会生成 main.i的文件 主要做的事情有如下几点: 展开头文件展开宏条件编译删除注释添加行号等信息保留…

用Deepseek写一个 HTML 和 JavaScript 实现一个简单的飞机游戏

大家好&#xff01;今天我将分享如何使用 HTML 和 JavaScript 编写一个简单的飞机游戏。这个游戏的核心功能包括&#xff1a;控制飞机移动、发射子弹、敌机生成、碰撞检测和得分统计。代码简洁易懂&#xff0c;适合初学者学习和实践。 游戏功能概述 玩家控制&#xff1a;使用键…

面向高质量视频生成的扩散模型方法-算法、架构与实现【附核心代码】

目录 算法原理 架构 代码示例 算法原理 正向扩散过程&#xff1a;从真实的视频数据开始&#xff0c;逐步向其中添加噪声&#xff0c;随着时间步 t 的增加&#xff0c;噪声添加得越来越多&#xff0c;最终将原始视频数据变成纯噪声。数学上&#xff0c;t 时刻的视频数据与 t…

水下机器人推进器PID参数整定与MATLAB仿真

水下机器人推进器PID参数整定与MATLAB仿真 1. PID控制原理 目标:通过调节比例(P)、积分(I)、微分(D)参数,使推进器输出力快速稳定跟踪期望值。传递函数(示例):推进器动力学模型可简化为: [ G(s) = \frac{K}{\tau s + 1} \cdot e^{-Ts} ] 其中:K为增益,τ为时间常…

游戏引擎学习第149天

今日回顾与计划 在今天的直播中&#xff0c;我们将继续进行游戏的开发工作&#xff0c;目标是完成资产文件&#xff08;pack file&#xff09;的测试版本。目前&#xff0c;游戏的资源&#xff08;如位图和声音文件&#xff09;是直接从磁盘加载的&#xff0c;而我们正在将其转…