finstep-template-cli 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/cli.js +117 -0
- package/package.json +39 -0
- package/template/.env.development +3 -0
- package/template/.env.production +3 -0
- package/template/.env.staging +3 -0
- package/template/.env.test +3 -0
- package/template/.eslintrc.cjs +21 -0
- package/template/README.md +69 -0
- package/template/auto-imports.d.ts +47 -0
- package/template/eslint.config.js +26 -0
- package/template/index.html +16 -0
- package/template/package.json +46 -0
- package/template/postcss.config.js +5 -0
- package/template/public/logo.svg +85 -0
- package/template/public/vite.svg +1 -0
- package/template/src/App.css +42 -0
- package/template/src/App.tsx +25 -0
- package/template/src/api/home/index.ts +56 -0
- package/template/src/api/home/typings.d.ts +8 -0
- package/template/src/assets/logo.svg +85 -0
- package/template/src/assets/react.svg +1 -0
- package/template/src/components/admin-layout.tsx +211 -0
- package/template/src/components/f-b-footer.tsx +46 -0
- package/template/src/components/f-b-header.tsx +894 -0
- package/template/src/components/global-loading.tsx +143 -0
- package/template/src/components/hero-section.tsx +371 -0
- package/template/src/components/products-preview.tsx +175 -0
- package/template/src/components/stats-section.tsx +85 -0
- package/template/src/components/trusted-by.tsx +53 -0
- package/template/src/hooks/useGlobalLoading.ts +57 -0
- package/template/src/index.css +341 -0
- package/template/src/main.tsx +30 -0
- package/template/src/pages/admin/index.tsx +361 -0
- package/template/src/pages/admin/pages/applications/index.tsx +558 -0
- package/template/src/pages/home/index.tsx +129 -0
- package/template/src/router/index.tsx +9 -0
- package/template/src/router/routes.tsx +30 -0
- package/template/src/stores/loading.store.ts +46 -0
- package/template/src/stores/root.store.ts +22 -0
- package/template/src/stores/store-context.tsx +43 -0
- package/template/src/stores/user.store.ts +46 -0
- package/template/src/utils/index.ts +14 -0
- package/template/src/utils/request.ts +116 -0
- package/template/src/utils/tokenManager.ts +168 -0
- package/template/src/vite-env.d.ts +1 -0
- package/template/tailwind.config.js +19 -0
- package/template/tsconfig.app.json +29 -0
- package/template/tsconfig.json +7 -0
- package/template/tsconfig.node.json +26 -0
- package/template/vite.config.ts +36 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { motion } from 'framer-motion';
|
4
|
+
import { useState, useEffect } from 'react';
|
5
|
+
|
6
|
+
function CountUp({ end, duration = 2000 }: { end: number; duration?: number }) {
|
7
|
+
const [count, setCount] = useState(0);
|
8
|
+
|
9
|
+
useEffect(() => {
|
10
|
+
let startTime: number;
|
11
|
+
const animate = (timestamp: number) => {
|
12
|
+
if (!startTime) startTime = timestamp;
|
13
|
+
const progress = timestamp - startTime;
|
14
|
+
const percentage = Math.min(progress / duration, 1);
|
15
|
+
|
16
|
+
setCount(Math.floor(end * percentage));
|
17
|
+
|
18
|
+
if (percentage < 1) {
|
19
|
+
requestAnimationFrame(animate);
|
20
|
+
}
|
21
|
+
};
|
22
|
+
|
23
|
+
requestAnimationFrame(animate);
|
24
|
+
}, [end, duration]);
|
25
|
+
|
26
|
+
return <span>{count}</span>;
|
27
|
+
}
|
28
|
+
|
29
|
+
export default function StatsSection() {
|
30
|
+
return (
|
31
|
+
<section className="bg-slate-950 py-20">
|
32
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
33
|
+
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
|
34
|
+
<motion.div
|
35
|
+
initial={{ opacity: 0, y: 30 }}
|
36
|
+
whileInView={{ opacity: 1, y: 0 }}
|
37
|
+
transition={{ duration: 0.6 }}
|
38
|
+
className="text-center"
|
39
|
+
>
|
40
|
+
<div className="text-4xl font-bold text-white mb-2">
|
41
|
+
<CountUp end={500} />+
|
42
|
+
</div>
|
43
|
+
<div className="text-slate-400">合作企业</div>
|
44
|
+
</motion.div>
|
45
|
+
|
46
|
+
<motion.div
|
47
|
+
initial={{ opacity: 0, y: 30 }}
|
48
|
+
whileInView={{ opacity: 1, y: 0 }}
|
49
|
+
transition={{ duration: 0.6, delay: 0.1 }}
|
50
|
+
className="text-center"
|
51
|
+
>
|
52
|
+
<div className="text-4xl font-bold text-white mb-2">
|
53
|
+
<CountUp end={50} />+
|
54
|
+
</div>
|
55
|
+
<div className="text-slate-400">AI产品</div>
|
56
|
+
</motion.div>
|
57
|
+
|
58
|
+
<motion.div
|
59
|
+
initial={{ opacity: 0, y: 30 }}
|
60
|
+
whileInView={{ opacity: 1, y: 0 }}
|
61
|
+
transition={{ duration: 0.6, delay: 0.2 }}
|
62
|
+
className="text-center"
|
63
|
+
>
|
64
|
+
<div className="text-4xl font-bold text-white mb-2">
|
65
|
+
<CountUp end={99} />.9%
|
66
|
+
</div>
|
67
|
+
<div className="text-slate-400">准确率</div>
|
68
|
+
</motion.div>
|
69
|
+
|
70
|
+
<motion.div
|
71
|
+
initial={{ opacity: 0, y: 30 }}
|
72
|
+
whileInView={{ opacity: 1, y: 0 }}
|
73
|
+
transition={{ duration: 0.6, delay: 0.3 }}
|
74
|
+
className="text-center"
|
75
|
+
>
|
76
|
+
<div className="text-4xl font-bold text-white mb-2">
|
77
|
+
<CountUp end={24} />/7
|
78
|
+
</div>
|
79
|
+
<div className="text-slate-400">技术支持</div>
|
80
|
+
</motion.div>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
</section>
|
84
|
+
);
|
85
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
// AI生成的代码 - 合作伙伴展示组件
|
2
|
+
|
3
|
+
import { motion } from "framer-motion";
|
4
|
+
|
5
|
+
export default function TrustedBy() {
|
6
|
+
const companies = [
|
7
|
+
{ name: "国泰海通", logo: "ri-money-dollar-circle-line" },
|
8
|
+
{ name: "华锐技术", logo: "ri-shield-line" },
|
9
|
+
{ name: "国金证券", logo: "ri-money-dollar-circle-line" },
|
10
|
+
{ name: "东吴证券", logo: "ri-money-dollar-circle-line" },
|
11
|
+
{ name: "上海银行", logo: "ri-bank-line" },
|
12
|
+
];
|
13
|
+
|
14
|
+
return (
|
15
|
+
<section className="bg-slate-950 py-16">
|
16
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
17
|
+
<motion.div
|
18
|
+
initial={{ opacity: 0, y: 20 }}
|
19
|
+
whileInView={{ opacity: 1, y: 0 }}
|
20
|
+
transition={{ duration: 0.8 }}
|
21
|
+
className="text-center"
|
22
|
+
>
|
23
|
+
<p className="text-slate-400 text-sm font-medium mb-8 uppercase tracking-wider">
|
24
|
+
全球 500+ 金融机构的信赖选择
|
25
|
+
</p>
|
26
|
+
|
27
|
+
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8 items-center">
|
28
|
+
{companies.map((company, index) => (
|
29
|
+
<motion.div
|
30
|
+
key={company.name}
|
31
|
+
initial={{ opacity: 0, y: 20 }}
|
32
|
+
whileInView={{ opacity: 1, y: 0 }}
|
33
|
+
transition={{ duration: 0.6, delay: index * 0.1 }}
|
34
|
+
className="flex flex-col items-center group cursor-pointer"
|
35
|
+
>
|
36
|
+
<div className="w-16 h-16 bg-slate-800/50 border border-slate-700 rounded-xl flex items-center justify-center mb-3 group-hover:border-slate-600 group-hover:bg-slate-800 transition-all duration-200">
|
37
|
+
<div className="w-8 h-8 flex items-center justify-center">
|
38
|
+
<i
|
39
|
+
className={`${company.logo} text-slate-400 group-hover:text-slate-300 text-2xl`}
|
40
|
+
></i>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
<span className="text-slate-500 text-sm font-medium group-hover:text-slate-400 transition-colors">
|
44
|
+
{company.name}
|
45
|
+
</span>
|
46
|
+
</motion.div>
|
47
|
+
))}
|
48
|
+
</div>
|
49
|
+
</motion.div>
|
50
|
+
</div>
|
51
|
+
</section>
|
52
|
+
);
|
53
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
// AI生成的代码 - 全局Loading自定义Hook
|
2
|
+
import { useStore } from "@/stores/store-context";
|
3
|
+
import { useCallback } from "react";
|
4
|
+
|
5
|
+
export const useGlobalLoading = () => {
|
6
|
+
const { loadingStore } = useStore();
|
7
|
+
|
8
|
+
// AI生成的代码 - 显示loading的方法
|
9
|
+
const showLoading = useCallback(
|
10
|
+
(text?: string) => {
|
11
|
+
loadingStore.showLoading(text);
|
12
|
+
},
|
13
|
+
[loadingStore]
|
14
|
+
);
|
15
|
+
|
16
|
+
// AI生成的代码 - 隐藏loading的方法
|
17
|
+
const hideLoading = useCallback(() => {
|
18
|
+
loadingStore.hideLoading();
|
19
|
+
}, [loadingStore]);
|
20
|
+
|
21
|
+
// AI生成的代码 - 强制隐藏loading的方法
|
22
|
+
const forceHideLoading = useCallback(() => {
|
23
|
+
loadingStore.forceHideLoading();
|
24
|
+
}, [loadingStore]);
|
25
|
+
|
26
|
+
// AI生成的代码 - 设置loading文本的方法
|
27
|
+
const setLoadingText = useCallback(
|
28
|
+
(text: string) => {
|
29
|
+
loadingStore.setLoadingText(text);
|
30
|
+
},
|
31
|
+
[loadingStore]
|
32
|
+
);
|
33
|
+
|
34
|
+
// AI生成的代码 - 包装异步函数的方法
|
35
|
+
const withLoading = useCallback(
|
36
|
+
async <T>(asyncFn: () => Promise<T>, loadingText?: string): Promise<T> => {
|
37
|
+
showLoading(loadingText);
|
38
|
+
try {
|
39
|
+
const result = await asyncFn();
|
40
|
+
return result;
|
41
|
+
} finally {
|
42
|
+
hideLoading();
|
43
|
+
}
|
44
|
+
},
|
45
|
+
[showLoading, hideLoading]
|
46
|
+
);
|
47
|
+
|
48
|
+
return {
|
49
|
+
isLoading: loadingStore.isLoading,
|
50
|
+
loadingText: loadingStore.loadingText,
|
51
|
+
showLoading,
|
52
|
+
hideLoading,
|
53
|
+
forceHideLoading,
|
54
|
+
setLoadingText,
|
55
|
+
withLoading,
|
56
|
+
};
|
57
|
+
};
|
@@ -0,0 +1,341 @@
|
|
1
|
+
/* AI生成的代码 - 全局样式文件 */
|
2
|
+
@import url('https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.5.0/remixicon.min.css');
|
3
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Pacifico&display=swap');
|
4
|
+
@import "tailwindcss";
|
5
|
+
|
6
|
+
:root {
|
7
|
+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
8
|
+
line-height: 1.5;
|
9
|
+
font-weight: 400;
|
10
|
+
font-synthesis: none;
|
11
|
+
text-rendering: optimizeLegibility;
|
12
|
+
-webkit-font-smoothing: antialiased;
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
14
|
+
}
|
15
|
+
|
16
|
+
* {
|
17
|
+
box-sizing: border-box;
|
18
|
+
}
|
19
|
+
|
20
|
+
body {
|
21
|
+
margin: 0;
|
22
|
+
padding: 0;
|
23
|
+
min-height: 100vh;
|
24
|
+
background-color: #0f172a;
|
25
|
+
color: #ffffff;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* 自定义滚动条样式 */
|
29
|
+
::-webkit-scrollbar {
|
30
|
+
width: 8px;
|
31
|
+
}
|
32
|
+
|
33
|
+
::-webkit-scrollbar-track {
|
34
|
+
background: #1e293b;
|
35
|
+
}
|
36
|
+
|
37
|
+
::-webkit-scrollbar-thumb {
|
38
|
+
background: #475569;
|
39
|
+
border-radius: 4px;
|
40
|
+
}
|
41
|
+
|
42
|
+
::-webkit-scrollbar-thumb:hover {
|
43
|
+
background: #64748b;
|
44
|
+
}
|
45
|
+
|
46
|
+
/* AI生成的代码 - 优化后的HeroSection动画关键帧,移除filter属性以提升性能 */
|
47
|
+
@keyframes energyOrb1 {
|
48
|
+
0%, 100% {
|
49
|
+
transform: translateY(0px) translateX(0px) scale(1);
|
50
|
+
opacity: 0.3;
|
51
|
+
}
|
52
|
+
25% {
|
53
|
+
transform: translateY(-30px) translateX(20px) scale(1.1);
|
54
|
+
opacity: 0.5;
|
55
|
+
}
|
56
|
+
50% {
|
57
|
+
transform: translateY(-15px) translateX(35px) scale(0.9);
|
58
|
+
opacity: 0.4;
|
59
|
+
}
|
60
|
+
75% {
|
61
|
+
transform: translateY(-45px) translateX(15px) scale(1.05);
|
62
|
+
opacity: 0.6;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
@keyframes energyOrb2 {
|
67
|
+
0%, 100% {
|
68
|
+
transform: translateY(0px) translateX(0px) rotate(0deg) scale(1);
|
69
|
+
opacity: 0.25;
|
70
|
+
}
|
71
|
+
33% {
|
72
|
+
transform: translateY(-35px) translateX(-20px) rotate(90deg) scale(1.2);
|
73
|
+
opacity: 0.4;
|
74
|
+
}
|
75
|
+
66% {
|
76
|
+
transform: translateY(-20px) translateX(-40px) rotate(180deg) scale(0.85);
|
77
|
+
opacity: 0.35;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
@keyframes energyOrb3 {
|
82
|
+
0%, 100% {
|
83
|
+
transform: translateY(0px) translateX(0px) scale(1) rotate(0deg);
|
84
|
+
opacity: 0.2;
|
85
|
+
}
|
86
|
+
50% {
|
87
|
+
transform: translateY(-50px) translateX(-25px) scale(1.3) rotate(120deg);
|
88
|
+
opacity: 0.45;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
@keyframes floatSmall {
|
93
|
+
0% {
|
94
|
+
transform: translateY(100vh) translateX(0px) scale(0);
|
95
|
+
opacity: 0;
|
96
|
+
}
|
97
|
+
10% {
|
98
|
+
opacity: 1;
|
99
|
+
scale: 1;
|
100
|
+
}
|
101
|
+
90% {
|
102
|
+
opacity: 1;
|
103
|
+
}
|
104
|
+
100% {
|
105
|
+
transform: translateY(-100px) translateX(20px) scale(0);
|
106
|
+
opacity: 0;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
/* AI生成的代码 - 覆盖 Ant Design 下拉菜单背景色 */
|
111
|
+
.ant-dropdown-menu.ant-dropdown-menu-root.ant-dropdown-menu-vertical.ant-dropdown-menu-light {
|
112
|
+
background: unset !important;
|
113
|
+
}
|
114
|
+
|
115
|
+
/* 兼容性样式 - 处理可能的 CSS-in-JS 类名 */
|
116
|
+
.ant-dropdown-menu[class*="css-dev-only-do-not-override"] {
|
117
|
+
background: unset !important;
|
118
|
+
}
|
119
|
+
|
120
|
+
/* AI生成的代码 - 全局提示组件样式 */
|
121
|
+
|
122
|
+
/* 全局消息容器样式 */
|
123
|
+
.ant-message {
|
124
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
125
|
+
z-index: 999999 !important;
|
126
|
+
position: fixed;
|
127
|
+
left: 50%;
|
128
|
+
transform: translateX(-50%);
|
129
|
+
width: auto;
|
130
|
+
top: 30px !important;
|
131
|
+
}
|
132
|
+
|
133
|
+
/* 消息项基础样式 */
|
134
|
+
.ant-message .ant-message-notice {
|
135
|
+
padding: 0;
|
136
|
+
margin-bottom: 12px;
|
137
|
+
}
|
138
|
+
|
139
|
+
.ant-message .ant-message-notice-content {
|
140
|
+
padding: 16px 24px !important;
|
141
|
+
border-radius: 16px !important;
|
142
|
+
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3) !important;
|
143
|
+
backdrop-filter: blur(20px) !important;
|
144
|
+
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
145
|
+
font-size: 14px !important;
|
146
|
+
font-weight: 500 !important;
|
147
|
+
display: flex !important;
|
148
|
+
align-items: center !important;
|
149
|
+
gap: 12px !important;
|
150
|
+
min-width: 320px !important;
|
151
|
+
animation: slideDown 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) !important;
|
152
|
+
background: rgba(30, 41, 59, 0.95) !important;
|
153
|
+
color: #ffffff !important;
|
154
|
+
}
|
155
|
+
|
156
|
+
/* 成功消息样式 */
|
157
|
+
.ant-message-success .anticon {
|
158
|
+
color: #10b981;
|
159
|
+
font-size: 18px;
|
160
|
+
background: rgba(16, 185, 129, 0.15);
|
161
|
+
border-radius: 50%;
|
162
|
+
padding: 4px;
|
163
|
+
width: 26px;
|
164
|
+
height: 26px;
|
165
|
+
display: flex;
|
166
|
+
align-items: center;
|
167
|
+
justify-content: center;
|
168
|
+
}
|
169
|
+
|
170
|
+
/* 错误消息样式 */
|
171
|
+
.ant-message-error .anticon {
|
172
|
+
color: #ef4444;
|
173
|
+
font-size: 18px;
|
174
|
+
background: rgba(239, 68, 68, 0.15);
|
175
|
+
border-radius: 50%;
|
176
|
+
padding: 4px;
|
177
|
+
width: 26px;
|
178
|
+
height: 26px;
|
179
|
+
display: flex;
|
180
|
+
align-items: center;
|
181
|
+
justify-content: center;
|
182
|
+
}
|
183
|
+
|
184
|
+
/* 警告消息样式 */
|
185
|
+
.ant-message-warning .anticon {
|
186
|
+
color: #f59e0b;
|
187
|
+
font-size: 18px;
|
188
|
+
background: rgba(245, 158, 11, 0.15);
|
189
|
+
border-radius: 50%;
|
190
|
+
padding: 4px;
|
191
|
+
width: 26px;
|
192
|
+
height: 26px;
|
193
|
+
display: flex;
|
194
|
+
align-items: center;
|
195
|
+
justify-content: center;
|
196
|
+
}
|
197
|
+
|
198
|
+
/* 信息消息样式 */
|
199
|
+
.ant-message-info .anticon {
|
200
|
+
color: #3b82f6;
|
201
|
+
font-size: 18px;
|
202
|
+
background: rgba(59, 130, 246, 0.15);
|
203
|
+
border-radius: 50%;
|
204
|
+
padding: 4px;
|
205
|
+
width: 26px;
|
206
|
+
height: 26px;
|
207
|
+
display: flex;
|
208
|
+
align-items: center;
|
209
|
+
justify-content: center;
|
210
|
+
}
|
211
|
+
|
212
|
+
/* 加载消息样式 */
|
213
|
+
.ant-message-loading .anticon {
|
214
|
+
color: #6b7280;
|
215
|
+
font-size: 18px;
|
216
|
+
background: rgba(107, 114, 128, 0.15);
|
217
|
+
border-radius: 50%;
|
218
|
+
padding: 4px;
|
219
|
+
width: 26px;
|
220
|
+
height: 26px;
|
221
|
+
display: flex;
|
222
|
+
align-items: center;
|
223
|
+
justify-content: center;
|
224
|
+
}
|
225
|
+
|
226
|
+
/* 加载动画 */
|
227
|
+
.finstep-message-loading .anticon-loading {
|
228
|
+
animation: spin 1s linear infinite;
|
229
|
+
}
|
230
|
+
|
231
|
+
/* 悬停效果 */
|
232
|
+
.ant-message .ant-message-notice-content:hover {
|
233
|
+
transform: translateY(-3px) scale(1.02);
|
234
|
+
box-shadow: 0 12px 40px 0 rgba(0, 0, 0, 0.4);
|
235
|
+
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
236
|
+
border-color: rgba(255, 255, 255, 0.2);
|
237
|
+
}
|
238
|
+
|
239
|
+
/* 关闭按钮样式 */
|
240
|
+
.ant-message .ant-message-notice .ant-message-notice-close {
|
241
|
+
color: rgba(255, 255, 255, 0.8);
|
242
|
+
font-size: 12px;
|
243
|
+
right: 8px;
|
244
|
+
top: 50%;
|
245
|
+
transform: translateY(-50%);
|
246
|
+
transition: color 0.2s ease;
|
247
|
+
}
|
248
|
+
|
249
|
+
.ant-message .ant-message-notice .ant-message-notice-close:hover {
|
250
|
+
color: #ffffff;
|
251
|
+
}
|
252
|
+
|
253
|
+
/* 响应式设计 */
|
254
|
+
@media (max-width: 768px) {
|
255
|
+
.ant-message .ant-message-notice-content {
|
256
|
+
min-width: 280px;
|
257
|
+
max-width: calc(100vw - 32px);
|
258
|
+
padding: 14px 20px;
|
259
|
+
font-size: 13px;
|
260
|
+
border-radius: 14px;
|
261
|
+
gap: 10px;
|
262
|
+
}
|
263
|
+
|
264
|
+
.ant-message {
|
265
|
+
left: 50% !important;
|
266
|
+
right: auto !important;
|
267
|
+
transform: translateX(-50%) !important;
|
268
|
+
width: auto !important;
|
269
|
+
margin: 0 16px !important;
|
270
|
+
}
|
271
|
+
|
272
|
+
.ant-message-success .anticon,
|
273
|
+
.ant-message-error .anticon,
|
274
|
+
.ant-message-warning .anticon,
|
275
|
+
.ant-message-info .anticon,
|
276
|
+
.ant-message-loading .anticon {
|
277
|
+
width: 24px;
|
278
|
+
height: 24px;
|
279
|
+
font-size: 16px;
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
/* 动画定义 */
|
284
|
+
@keyframes slideDown {
|
285
|
+
0% {
|
286
|
+
opacity: 0;
|
287
|
+
transform: translateY(-30px) scale(0.9);
|
288
|
+
filter: blur(4px);
|
289
|
+
}
|
290
|
+
50% {
|
291
|
+
opacity: 0.8;
|
292
|
+
transform: translateY(-5px) scale(1.02);
|
293
|
+
filter: blur(1px);
|
294
|
+
}
|
295
|
+
100% {
|
296
|
+
opacity: 1;
|
297
|
+
transform: translateY(0) scale(1);
|
298
|
+
filter: blur(0);
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
@keyframes spin {
|
303
|
+
0% {
|
304
|
+
transform: rotate(0deg);
|
305
|
+
}
|
306
|
+
100% {
|
307
|
+
transform: rotate(360deg);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
/* 暗色主题适配 */
|
312
|
+
@media (prefers-color-scheme: dark) {
|
313
|
+
.ant-message .ant-message-notice-content {
|
314
|
+
border-color: rgba(255, 255, 255, 0.15);
|
315
|
+
backdrop-filter: blur(15px);
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
/* 高对比度模式适配 */
|
320
|
+
@media (prefers-contrast: high) {
|
321
|
+
.ant-message .ant-message-notice-content {
|
322
|
+
border-width: 2px;
|
323
|
+
font-weight: 600;
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
/* 减少动画模式适配 */
|
328
|
+
@media (prefers-reduced-motion: reduce) {
|
329
|
+
.ant-message .ant-message-notice-content {
|
330
|
+
animation: none;
|
331
|
+
}
|
332
|
+
|
333
|
+
.ant-message .ant-message-notice-content:hover {
|
334
|
+
transform: none;
|
335
|
+
transition: none;
|
336
|
+
}
|
337
|
+
|
338
|
+
.ant-message-loading .anticon-loading {
|
339
|
+
animation: none;
|
340
|
+
}
|
341
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// AI生成的代码 - 应用入口文件
|
2
|
+
import { createRoot } from "react-dom/client";
|
3
|
+
import { ConfigProvider, theme } from "antd";
|
4
|
+
import zhCN from "antd/locale/zh_CN";
|
5
|
+
// AI生成的代码 - 修正导入路径,导入全局状态管理的Provider组件
|
6
|
+
import { StoreProvider } from "@/stores/store-context";
|
7
|
+
import "./index.css";
|
8
|
+
// AI生成的代码 - 导入组件库样式
|
9
|
+
// import "finstep-b-components/dist/index.css";
|
10
|
+
import App from "./App.tsx";
|
11
|
+
|
12
|
+
// Antd主题配置
|
13
|
+
const customTheme = {
|
14
|
+
token: {
|
15
|
+
colorPrimary: "#3b82f6",
|
16
|
+
colorBgBase: "#0f172a",
|
17
|
+
colorTextBase: "#ffffff",
|
18
|
+
colorBgContainer: "#1e293b",
|
19
|
+
colorBorder: "#334155",
|
20
|
+
},
|
21
|
+
algorithm: theme.darkAlgorithm,
|
22
|
+
};
|
23
|
+
|
24
|
+
createRoot(document.getElementById("root")!).render(
|
25
|
+
<StoreProvider>
|
26
|
+
<ConfigProvider theme={customTheme} locale={zhCN}>
|
27
|
+
<App />
|
28
|
+
</ConfigProvider>
|
29
|
+
</StoreProvider>
|
30
|
+
);
|