|
|
// 格式化时间
|
|
|
export const formatTime = (date: Date) => {
|
|
|
const year = date.getFullYear()
|
|
|
const month = date.getMonth() + 1
|
|
|
const day = date.getDate()
|
|
|
const hour = date.getHours()
|
|
|
const minute = date.getMinutes()
|
|
|
const second = date.getSeconds()
|
|
|
|
|
|
return (
|
|
|
[year, month, day].map(formatNumber).join('/') +
|
|
|
' ' +
|
|
|
[hour, minute, second].map(formatNumber).join(':')
|
|
|
)
|
|
|
}
|
|
|
|
|
|
const formatNumber = (n: number) => {
|
|
|
const s = n.toString()
|
|
|
return s[1] ? s : '0' + s
|
|
|
}
|
|
|
|
|
|
// 格式化日期为 MM/DD 格式
|
|
|
export const formatDate = (date: Date) => {
|
|
|
const month = date.getMonth() + 1
|
|
|
const day = date.getDate()
|
|
|
return `${formatNumber(month)}/${formatNumber(day)}`
|
|
|
}
|
|
|
|
|
|
// 获取当前周的日期范围
|
|
|
export const getCurrentWeekDates = () => {
|
|
|
const today = new Date()
|
|
|
const currentDay = today.getDay() // 0是周日,1是周一
|
|
|
const monday = new Date(today)
|
|
|
monday.setDate(today.getDate() - (currentDay === 0 ? 6 : currentDay - 1))
|
|
|
|
|
|
const weekDays = []
|
|
|
const weekNames = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
|
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
|
const date = new Date(monday)
|
|
|
date.setDate(monday.getDate() + i)
|
|
|
weekDays.push({
|
|
|
name: weekNames[i],
|
|
|
date: formatDate(date),
|
|
|
fullDate: date
|
|
|
})
|
|
|
}
|
|
|
|
|
|
return weekDays
|
|
|
}
|
|
|
|
|
|
// 学期配置接口
|
|
|
interface SemesterConfig {
|
|
|
startDate: string;
|
|
|
name: string;
|
|
|
totalWeeks: number;
|
|
|
}
|
|
|
|
|
|
// 获取学期配置
|
|
|
export const getSemesterConfig = (): SemesterConfig => {
|
|
|
try {
|
|
|
const config = wx.getStorageSync('semesterConfig');
|
|
|
if (config) {
|
|
|
return JSON.parse(config);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.warn('获取学期配置失败:', error);
|
|
|
}
|
|
|
|
|
|
// 默认配置:智能检测当前学期
|
|
|
return getDefaultSemesterConfig();
|
|
|
}
|
|
|
|
|
|
// 保存学期配置
|
|
|
export const setSemesterConfig = (config: SemesterConfig) => {
|
|
|
try {
|
|
|
wx.setStorageSync('semesterConfig', JSON.stringify(config));
|
|
|
} catch (error) {
|
|
|
console.error('保存学期配置失败:', error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 智能检测默认学期配置
|
|
|
export const getDefaultSemesterConfig = (): SemesterConfig => {
|
|
|
const today = new Date();
|
|
|
const year = today.getFullYear();
|
|
|
const month = today.getMonth() + 1; // 0-11 -> 1-12
|
|
|
|
|
|
if (month >= 2 && month <= 7) {
|
|
|
// 春季学期 (2月-7月)
|
|
|
return {
|
|
|
startDate: `${year}-02-26`, // 一般春季学期2月底开始
|
|
|
name: `${year}年春季学期`,
|
|
|
totalWeeks: 18
|
|
|
};
|
|
|
} else {
|
|
|
// 秋季学期 (8月-次年1月)
|
|
|
const semesterYear = month >= 8 ? year : year - 1;
|
|
|
return {
|
|
|
startDate: `${semesterYear}-09-01`, // 秋季学期9月1日开始(周一)
|
|
|
name: `${semesterYear}年秋季学期`,
|
|
|
totalWeeks: 18
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 获取当前是第几周(基于学期配置)
|
|
|
export const getCurrentWeek = (): number => {
|
|
|
const config = getSemesterConfig();
|
|
|
const semesterStart = new Date(config.startDate);
|
|
|
const today = new Date();
|
|
|
|
|
|
// 确保学期开始日期是周一
|
|
|
const semesterStartDay = semesterStart.getDay();
|
|
|
if (semesterStartDay !== 1) { // 如果不是周一,调整到周一
|
|
|
const daysToMonday = semesterStartDay === 0 ? -6 : 1 - semesterStartDay;
|
|
|
semesterStart.setDate(semesterStart.getDate() + daysToMonday);
|
|
|
}
|
|
|
|
|
|
// 计算今天是学期开始后的第几天
|
|
|
const diffTime = today.getTime() - semesterStart.getTime();
|
|
|
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
|
// 计算周次:第0-6天是第1周,第7-13天是第2周,以此类推
|
|
|
const week = Math.floor(diffDays / 7) + 1;
|
|
|
|
|
|
// 调试信息
|
|
|
console.log('周次计算调试信息:', {
|
|
|
学期开始日期: semesterStart.toDateString(),
|
|
|
今天日期: today.toDateString(),
|
|
|
相差天数: diffDays,
|
|
|
计算周次: week,
|
|
|
最终周次: Math.max(1, Math.min(week, config.totalWeeks))
|
|
|
});
|
|
|
|
|
|
// 确保周次在合理范围内
|
|
|
return Math.max(1, Math.min(week, config.totalWeeks));
|
|
|
}
|
|
|
|
|
|
// 时间字符串转换为分钟数(用于时间比较)
|
|
|
export const timeToMinutes = (timeStr: string): number => {
|
|
|
const [hours, minutes] = timeStr.split(':').map(Number)
|
|
|
return hours * 60 + minutes
|
|
|
}
|
|
|
|
|
|
// 分钟数转换为时间字符串
|
|
|
export const minutesToTime = (minutes: number): string => {
|
|
|
const hours = Math.floor(minutes / 60)
|
|
|
const mins = minutes % 60
|
|
|
return `${formatNumber(hours)}:${formatNumber(mins)}`
|
|
|
}
|
|
|
|
|
|
// 验证时间格式
|
|
|
export const isValidTime = (timeStr: string): boolean => {
|
|
|
const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/
|
|
|
return timeRegex.test(timeStr)
|
|
|
}
|
|
|
|
|
|
// 比较两个时间字符串
|
|
|
export const compareTime = (time1: string, time2: string): number => {
|
|
|
const minutes1 = timeToMinutes(time1)
|
|
|
const minutes2 = timeToMinutes(time2)
|
|
|
return minutes1 - minutes2
|
|
|
}
|
|
|
|
|
|
// 获取星期几的中文名称
|
|
|
export const getWeekDayName = (dayOfWeek: number): string => {
|
|
|
const weekNames = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
|
|
return weekNames[dayOfWeek] || ''
|
|
|
}
|
|
|
|
|
|
// 防抖函数
|
|
|
export const debounce = (func: Function, wait: number) => {
|
|
|
let timeout: number
|
|
|
return function executedFunction(...args: any[]) {
|
|
|
const later = () => {
|
|
|
clearTimeout(timeout)
|
|
|
func(...args)
|
|
|
}
|
|
|
clearTimeout(timeout)
|
|
|
timeout = setTimeout(later, wait)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 节流函数
|
|
|
export const throttle = (func: Function, limit: number) => {
|
|
|
let inThrottle: boolean
|
|
|
return function executedFunction(...args: any[]) {
|
|
|
if (!inThrottle) {
|
|
|
func.apply(this, args)
|
|
|
inThrottle = true
|
|
|
setTimeout(() => inThrottle = false, limit)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 深拷贝
|
|
|
export const deepClone = (obj: any): any => {
|
|
|
if (obj === null || typeof obj !== 'object') return obj
|
|
|
if (obj instanceof Date) return new Date(obj.getTime())
|
|
|
if (obj instanceof Array) return obj.map(item => deepClone(item))
|
|
|
if (typeof obj === 'object') {
|
|
|
const clonedObj: any = {}
|
|
|
for (const key in obj) {
|
|
|
if (obj.hasOwnProperty(key)) {
|
|
|
clonedObj[key] = deepClone(obj[key])
|
|
|
}
|
|
|
}
|
|
|
return clonedObj
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 生成唯一ID
|
|
|
export const generateId = (): string => {
|
|
|
return Date.now().toString(36) + Math.random().toString(36).substr(2)
|
|
|
}
|
|
|
|
|
|
// 存储相关工具函数
|
|
|
export const storage = {
|
|
|
set: (key: string, value: any) => {
|
|
|
try {
|
|
|
wx.setStorageSync(key, value)
|
|
|
} catch (error) {
|
|
|
console.error('存储失败:', error)
|
|
|
}
|
|
|
},
|
|
|
|
|
|
get: (key: string, defaultValue: any = null) => {
|
|
|
try {
|
|
|
return wx.getStorageSync(key) || defaultValue
|
|
|
} catch (error) {
|
|
|
console.error('读取存储失败:', error)
|
|
|
return defaultValue
|
|
|
}
|
|
|
},
|
|
|
|
|
|
remove: (key: string) => {
|
|
|
try {
|
|
|
wx.removeStorageSync(key)
|
|
|
} catch (error) {
|
|
|
console.error('删除存储失败:', error)
|
|
|
}
|
|
|
},
|
|
|
|
|
|
clear: () => {
|
|
|
try {
|
|
|
wx.clearStorageSync()
|
|
|
} catch (error) {
|
|
|
console.error('清空存储失败:', error)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 网络请求工具函数
|
|
|
export const request = {
|
|
|
baseURL: 'http://localhost:8080/api',
|
|
|
|
|
|
get: (url: string, data?: any) => {
|
|
|
return wx.request({
|
|
|
url: `${request.baseURL}${url}`,
|
|
|
method: 'GET',
|
|
|
data,
|
|
|
header: {
|
|
|
'content-type': 'application/json'
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
|
|
|
post: (url: string, data?: any) => {
|
|
|
return wx.request({
|
|
|
url: `${request.baseURL}${url}`,
|
|
|
method: 'POST',
|
|
|
data,
|
|
|
header: {
|
|
|
'content-type': 'application/json'
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
|
|
|
put: (url: string, data?: any) => {
|
|
|
return wx.request({
|
|
|
url: `${request.baseURL}${url}`,
|
|
|
method: 'PUT',
|
|
|
data,
|
|
|
header: {
|
|
|
'content-type': 'application/json'
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
|
|
|
delete: (url: string, data?: any) => {
|
|
|
return wx.request({
|
|
|
url: `${request.baseURL}${url}`,
|
|
|
method: 'DELETE',
|
|
|
data,
|
|
|
header: {
|
|
|
'content-type': 'application/json'
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 显示提示信息
|
|
|
export const showToast = (title: string, icon: 'success' | 'error' | 'loading' | 'none' = 'none') => {
|
|
|
wx.showToast({
|
|
|
title,
|
|
|
icon,
|
|
|
duration: 2000
|
|
|
})
|
|
|
}
|
|
|
|
|
|
// 显示加载中
|
|
|
export const showLoading = (title: string = '加载中...') => {
|
|
|
wx.showLoading({
|
|
|
title,
|
|
|
mask: true
|
|
|
})
|
|
|
}
|
|
|
|
|
|
// 隐藏加载中
|
|
|
export const hideLoading = () => {
|
|
|
wx.hideLoading()
|
|
|
}
|
|
|
|
|
|
// 显示确认对话框
|
|
|
export const showConfirm = (content: string, title: string = '提示'): Promise<boolean> => {
|
|
|
return new Promise((resolve) => {
|
|
|
wx.showModal({
|
|
|
title,
|
|
|
content,
|
|
|
success: (res) => {
|
|
|
resolve(res.confirm)
|
|
|
},
|
|
|
fail: () => {
|
|
|
resolve(false)
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
}
|