- 新增 .editorconfig 文件统一代码风格配置 - 新增 .env 环境变量配置文件 - 添加开发和生产环境的环境变量配置 - 配置 ESLint 忽略规则文件 - 设置代码检查配置文件 .eslintrc.js - 添加 Git 忽略文件规则 - 创建 Prettier 格式化忽略规则 - 添加隐私政策和服务协议HTML文件 - 实现访问密钥编辑组件基础结构
90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
// 动画工具类
|
|
export class AnimationUtils {
|
|
// 页面加载动画
|
|
static pageEnterAnimation() {
|
|
const elements = document.querySelectorAll('.animate-on-load');
|
|
elements.forEach((el, index) => {
|
|
(el as HTMLElement).style.animationDelay = `${index * 0.1}s`;
|
|
el.classList.add('animate-fade-in-up');
|
|
});
|
|
}
|
|
|
|
// 表单项动画
|
|
static formItemAnimation(element: HTMLElement, delay: number = 0) {
|
|
setTimeout(() => {
|
|
element.classList.add('animate-slide-in-left');
|
|
}, delay);
|
|
}
|
|
|
|
// 按钮点击波纹效果
|
|
static rippleEffect(event: MouseEvent) {
|
|
const button = event.currentTarget as HTMLElement;
|
|
const ripple = document.createElement('span');
|
|
const rect = button.getBoundingClientRect();
|
|
const size = Math.max(rect.width, rect.height);
|
|
const x = event.clientX - rect.left - size / 2;
|
|
const y = event.clientY - rect.top - size / 2;
|
|
|
|
ripple.style.width = ripple.style.height = size + 'px';
|
|
ripple.style.left = x + 'px';
|
|
ripple.style.top = y + 'px';
|
|
ripple.classList.add('ripple');
|
|
|
|
button.appendChild(ripple);
|
|
|
|
setTimeout(() => {
|
|
ripple.remove();
|
|
}, 600);
|
|
}
|
|
|
|
// 输入框聚焦动画
|
|
static inputFocusAnimation(element: HTMLElement) {
|
|
const parent = element.closest('.ant-form-item');
|
|
if (parent) {
|
|
parent.classList.add('input-focused');
|
|
}
|
|
}
|
|
|
|
// 输入框失焦动画
|
|
static inputBlurAnimation(element: HTMLElement) {
|
|
const parent = element.closest('.ant-form-item');
|
|
if (parent && !(element as HTMLInputElement).value) {
|
|
parent.classList.remove('input-focused');
|
|
}
|
|
}
|
|
|
|
// 错误提示动画
|
|
static errorShakeAnimation(element: HTMLElement) {
|
|
element.classList.add('animate-shake');
|
|
setTimeout(() => {
|
|
element.classList.remove('animate-shake');
|
|
}, 500);
|
|
}
|
|
|
|
// 成功提示动画
|
|
static successPulseAnimation(element: HTMLElement) {
|
|
element.classList.add('animate-pulse-success');
|
|
setTimeout(() => {
|
|
element.classList.remove('animate-pulse-success');
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
// Vue 3 组合式 API 动画钩子
|
|
export function useAnimations() {
|
|
const onEnter = (el: Element, done: () => void) => {
|
|
el.classList.add('animate-fade-in');
|
|
setTimeout(done, 300);
|
|
};
|
|
|
|
const onLeave = (el: Element, done: () => void) => {
|
|
el.classList.add('animate-fade-out');
|
|
setTimeout(done, 300);
|
|
};
|
|
|
|
return {
|
|
onEnter,
|
|
onLeave
|
|
};
|
|
}
|