feat:移植工程

This commit is contained in:
2025-06-10 16:20:21 +08:00
commit 829df0b1d1
356 changed files with 43395 additions and 0 deletions

170
src/utils/blog/blogUtil.ts Normal file
View File

@@ -0,0 +1,170 @@
import { ElMessage } from 'element-plus'
import { IBasicBlog, IBlog } from '@/types/blog.ts'
import dayjs from 'dayjs'
/**
* 粒子特效
*/
export const particlesOptions = {
background: {
color: {}
},
fpsLimit: 60,
interactivity: {
events: {
// 点击时事件
onClick: {
enable: false,
mode: 'push' // 可用的click模式有: "push", "remove", "repulse", "bubble"。
},
// 悬浮时事件
onHover: {
enable: true,
mode: 'grab' // 可用的hover模式有: "grab", "repulse", "bubble"。
},
resize: true
},
modes: {
bubble: {
distance: 400,
duration: 2,
opacity: 0.8,
size: 40
},
push: {
quantity: 4
},
repulse: {
distance: 200,
duration: 0.4
}
}
},
particles: {
color: {
value: '#000000'
},
links: {
color: '#000000', // '#dedede'。线条颜色。
distance: 150, // 线条长度
enable: true, // 是否有线条
opacity: 0.5, // 线条透明度。
width: 1 // 线条宽度。
},
collisions: {
enable: false
},
move: {
direction: 'none',
enable: true,
outMode: 'bounce',
random: false,
speed: 4, // 粒子运动速度。
straight: false
},
number: {
density: {
enable: true,
area: 800
},
value: 50 // 粒子数量。
},
opacity: {
value: 0.1 // 粒子透明度。
},
shape: {
type: 'edge' // 可用的粒子外观类型有:"circle","edge","triangle", "polygon","star"
},
size: {
random: true,
value: 5
}
},
detectRetina: true
}
/**
* 创建鼠标点击爱心特效
* @param leftPosition 左侧位置
* @param topPosition 右侧位置
*/
export const createHeartDiv = (leftPosition: number, topPosition: number) => {
const heart = document.createElement('div')
document.body.appendChild(heart)
heart.classList.add('heart')
heart.style.left = `${leftPosition}px`
heart.style.top = `${topPosition}px`
heart.style.animation = 'move 1s normal forwards'
setTimeout(() => {
document.body.removeChild(heart)
}, 1000)
heart.style.backgroundColor = `rgb(${Math.random() * 255},${Math.random() * 255},${Math.random() * 255})`
}
/**
* 校验博客上传图片
* @param files 文件
*/
export const validateBlogImage = (files: File[]): boolean => {
if (files.length > 1) {
ElMessage.error('请上传1张图片')
return false
}
const uploadFile = files[0]
const fileTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff']
if (fileTypeList.indexOf(uploadFile.type.toLowerCase()) !== -1) {
ElMessage.error('请上传图片文件')
return false
}
const maxFileSize = 5 * 1024 * 1024
if (uploadFile.size > maxFileSize) {
ElMessage.error('请上传5M以内的图片')
return false
}
return true
}
export const formatBlogWordCount = (count: number): string => {
if (count < 10000) return count.toString()
const units = ['万', '亿', '兆']
let unitIndex = -1
while (count >= 10000 && unitIndex < units.length - 1) {
count /= 10000
unitIndex++
}
// 保留一位小数
const formattedNum = Math.round(count * 10) / 10
return `${formattedNum}${units[unitIndex]}`
}
export const getBlogRunTotalTime = (startDateStr: string):string => {
const startDate = dayjs(startDateStr)
const endDate = dayjs() // 当前时间
// 计算完整时间间隔(年、月、日)
const years = endDate.diff(startDate, 'year')
const months = endDate.diff(startDate.add(years, 'year'), 'month')
const days = endDate.diff(startDate.add(years, 'year').add(months, 'month'), 'day')
return `${years}${months}${days}`
}
export const getBasicBlog = (blog: IBlog): IBasicBlog => {
return {
category: blog.category,
isGreat: blog.isGreat,
readDuration: blog.readDuration,
topValue: blog.topValue,
wordCount: blog.wordCount,
visitCount: blog.visitCount,
createTime: blog.createTime,
updateTime: blog.updateTime
}
}