Compare commits

..

20 Commits
dev ... main

@ -0,0 +1,682 @@
/* 基本重置 */
body, h1, h2, p, a {
margin: 0;
padding: 0;
text-decoration: none;
color: rgb(255, 255, 255);
}
/* 基础字体和背景 */
body {
font-family: 'Arial', sans-serif;
background-color: #f8f8f8;
color: #333;
}
header {
background-color: #d9534f;
color: #fff;
padding: 20px 0;
text-align: center;
}
header h1 {
margin: 0;
}
main {
padding: 20px;
text-align: center;
}
footer {
background-color: #fe5b56;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
bottom: 0;
width: 100%;
}
/* 输入框和按钮样式 */
input[type="text"] {
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
width: calc(100% - 22px); /* 减去padding和border的宽度 */
}
button {
padding: 10px 20px;
background-color: #d9534f;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #c9302c;
}
/* 动画效果 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
header, main, footer {
animation: fadeInDown 1s ease-in-out;
}
/* 响应式设计 */
@media (max-width: 768px) {
/* 针对小屏幕的样式调整 */
}
/* 动态阴影效果 */
@keyframes shadowPulse {
0%, 100% { box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); }
50% { box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); }
}
button:hover {
animation: shadowPulse 1.5s infinite;
}
/* 文字跳动动画*/
h1 {
animation: jump 1.5s ease-in-out infinite;
}
@keyframes jump {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* 输入框和按钮的悬停效果*/
input[type="text"]:hover, button:hover {
border: 1px solid #d9534f;
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
/*按钮点击动画*/
button:active {
transform: scale(0.95);
background-color: #b52b27;
}
/*光晕效果*/
.glow {
animation: glowEffect 1.5s infinite alternate;
}
@keyframes glowEffect {
from {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #d9534f, 0 0 20px #d9534f, 0 0 25px #d9534f, 0 0 30px #d9534f;
}
to {
text-shadow: 0 0 10px #fff, 0 0 20px #d9534f, 0 0 30px #d9534f, 0 0 40px #d9534f, 0 0 50px #d9534f, 0 0 60px #d9534f;
}
}
/* 3D翻转效果*/
.feature {
perspective: 1000px;
}
.feature:hover .feature-inner {
transform: rotateY(360deg);
transition: transform 15s;
}
/*视差滚动效果*/
.parallax-section {
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* 粒子背景*/
.particle-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.particle {
fill: rgba(255, 255, 255, 0.8);
animation: moveParticles 10s infinite linear;
}
@keyframes moveParticles {
0% { transform: translate(0, 0); }
100% { transform: translate(100px, 100px); }
}
/*线条动画*/
.dynamic-line {
stroke-dasharray: 300;
stroke-dashoffset: 300;
animation: dash 3s linear infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 300;
}
to {
stroke-dashoffset: 0;
}
}
/*光晕效果*/
button {
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 300%;
height: 200%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%) rotate(45deg);
transition: all 0.5s;
}
button:hover::before {
width: 100%;
height: 100%;
}
/*闪烁效果*/
@keyframes blinker {
50% { opacity: 0; }
}
.blink-text {
animation: blinker 1s linear infinite;
}
/* 打字机效果*/
.typewriter {
font-family: monospace;
overflow: hidden;
white-space: nowrap;
width: 100%;
animation: typewriter 4s steps(40) 1s infinite;
}
@keyframes typewriter {
0% { width: 0; }
100% { width: 100%; }
}
/* 3D文字效果*/
.three-d-text {
transform: rotateX(45deg) rotateY(45deg);
transform-style: preserve-3d;
perspective: 600px;
}
/*渐变文字效果*/
.gradient-text {
background: -webkit-linear-gradient(45deg, #d9534f, #fe5b56);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/*动态阴影效果*/
.dynamic-shadow {
transition: box-shadow 0.3s ease-in-out;
}
.dynamic-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}
/*光点闪烁效果*/
.sparkle-point {
position: absolute;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.8);
pointer-events: none;
animation: sparkle 2s infinite;
}
@keyframes sparkle {
0% { opacity: 0; transform: scale(0); }
50% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0); }
}
/*动态渲染效果*/
.render-effect {
animation: renderEffect 5s infinite alternate;
}
@keyframes renderEffect {
0%, 100% { filter: grayscale(0); }
50% { filter: grayscale(1); }
}
/* 全屏背景动画*/
body {
background: linear-gradient(-45deg, #000, #7c7c7c, #000);
background-size: 400% 1000%;
animation: gradientBG 15s ease infinite;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/*线条动画*/
.waves {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 90px;
z-index: -1;
}
@keyframes backgroundGradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
body {
animation: backgroundGradient 15s ease infinite;
}
a {
color: #fdfdfd;
}
a:hover {
color: #000000;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
background-color: #d9534f;
color: white;
}
.svg-background {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保SVG在内容的后面 */
}
@keyframes colorShift {
0% { background-color: #d9534f; }
50% { background-color: #fe5b56; }
100% { background-color: #d9534f; }
}
button {
animation: colorShift 3s infinite;
}
.blink {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
input[type="text"]:hover {
background-color: rgba(217, 83, 79, 0.1);
}
.parallax-section {
background-image: url('your-image.jpg');
background-attachment: fixed;
background-size: cover;
height: 100vh;
}
/*字体动态改变*/
h2 {
transition: font-size 0.3s;
}
h2:hover {
font-size: 2em;
}
/*动态内容加载*/
.main-content {
animation: fadeIn 1s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 旋转效果*/
footer {
transition: transform 0.5s;
}
footer:hover {
transform: rotate(5deg);
}
.dynamic-line {
stroke: #d9534f;
stroke-width: 2;
fill: none;
animation: dash 5s linear infinite;
}
@keyframes dash {
0% { stroke-dasharray: 0, 100; }
100% { stroke-dasharray: 100, 0; }
}
button {
perspective: 1000px;
}
button:hover {
transform: rotateX(10deg) rotateY(10deg);
transition: transform 0.3s;
}
/*文字打字效果*/
.typewriter {
overflow: hidden;
white-space: nowrap;
border-right: .15em solid orange;
animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: orange; }
}
/*旋转加载*/
.loading {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/*字体阴影动态*/
h2 {
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
transition: text-shadow 0.3s ease;
}
h2:hover {
text-shadow: 0 0 20px rgba(255, 0, 0, 1);
}
/*彩色阴影*/
button {
box-shadow: 0 4px 20px rgba(217, 83, 79, 0.5);
}
button:hover {
box-shadow: 0 8px 30px rgba(217, 83, 79, 0.8);
}
.particle-background {
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 10%, transparent 10%);
animation: particleAnimation 5s infinite;
}
/*随机粒子背景*/
@keyframes particleAnimation {
0% { background-size: 0%; }
100% { background-size: 100%; }
}
/*光环效果*/
header {
box-shadow: 0 0 20px rgba(217, 83, 79, 0.6);
}
/*悬浮按钮效果*/
button {
transition: transform 0.3s ease;
}
button:hover {
transform: translateY(-5px);
}
/*玻璃效果*/
main {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 20px;
}
/**/
.result-box {
background-color: #ff6e7a; /* 淡红色背景,与按钮颜色呼应 */
border: 1px solid #d9534f; /* 边框颜色与头部和底部颜色一致 */
padding: 20px;
margin-top: 20px;
border-radius: 5px; /* 圆角边框 */
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* 轻微的立体阴影效果 */
animation: fadeInDown 1s ease-in-out; /* 淡入下移动画 */
}
/* 结果文本框样式 */
.result-textarea {
background-color: #f5f5f5; /* 浅灰色背景,更好的对比度 */
border: 1px solid #ddd; /* 边框颜色与输入框一致 */
border-radius: 5px; /* 圆角边框 */
padding: 10px;
width: 100%; /* 宽度与输入框一致 */
box-sizing: border-box; /* 盒模型宽度包含padding和border */
resize: none; /* 禁止调整大小 */
font-family: 'Arial', sans-serif; /* 与页面字体一致 */
color: #333; /* 文本颜色与页面一致 */
line-height: 1.5; /* 行高 */
overflow-y: auto; /* 超出内容显示滚动条 */
}
/* 响应式设计 */
@media (max-width: 768px) {
.result-box {
width: auto; /* 小屏幕上宽度自动调整 */
margin-left: 10px; /* 较小的外边距 */
margin-right: 10px;
}
input[type="text"] {
width: calc(100% - 22px); /* 调整输入框宽度 */
}
}
/* 悬停效果,使结果框在鼠标悬停时有阴影变化 */
.result-box:hover {
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
}
/* 点击效果,使结果框在被点击时有压缩效果 */
.result-box:active {
transform: translateY(2px);
}
/* 显示动画 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 隐藏动画 */
@keyframes fadeOutUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
/* 展开动画 */
@keyframes expand {
from {
height: 0;
}
to {
height: 200px; /* 根据需要调整高度 */
}
}
.result-box {
display: none; /* 初始时隐藏 */
background-color: #f8d7da;
border: 1px solid #d9534f;
padding: 20px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
animation-fill-mode: forwards; /* 保持动画结束状态 */
overflow: hidden; /* 隐藏内容超出部分 */
}
.result-box:active {
animation: ripple 0.5s forwards;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.result-box {
background-size: 200% 200%;
animation: gradientBG 5s ease infinite;
}
@keyframes textBounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.result-textarea:hover {
animation: textBounce 0.5s infinite;
}
@keyframes borderBounce {
0%, 100% { border: 1px solid #d9534f; }
50% { border: 2px solid #ff6e7a; }
}
.result-box:hover {
animation: borderBounce 1s infinite;
}
@keyframes backgroundBlink {
0%, 100% { background-color: #ff6e7a; }
50% { background-color: #d9534f; }
}
.result-box:hover {
animation: backgroundBlink 1s infinite;
}
@keyframes typewriter {
0% { width: 0; }
100% { width: 100%; }
}
.result-textarea {
animation: typewriter 3s steps(30, end) forwards;
}
.result-box {
background-image: linear-gradient(135deg, #ff6e7a, #d9534f);
}
.result-textarea {
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
}
.result-box, .result-textarea {
transition: all 0.3s ease;
}
.result-box:hover {
background-image: linear-gradient(135deg, #ff7e8a, #e95a5f);
}
.result-box:active {
transform: scale(0.98);
}
@keyframes textGlow {
0%, 100% { color: #333; }
50% { color: #555; }
}
.result-textarea {
animation: textGlow 2s infinite;
}
.result-box {
position: relative;
overflow: hidden;
}
.result-box::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.2);
z-index: 1;
opacity: 0;
transition: opacity 0.3s ease;
}
.result-box:hover::before {
animation: ripple 1.5s infinite;
}
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.result-box {
animation: bounce 2s infinite ease-in-out;
}
@keyframes shadowSpread {
0%, 100% { box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); }
50% { box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2); }
}
.result-box:hover {
animation: shadowSpread 2s infinite;
}

@ -0,0 +1,568 @@
/* 基本重置 */
body, h1, h2, p, a {
margin: 0;
padding: 0;
text-decoration: none;
color: rgb(255, 255, 255);
}
/* 基础字体和背景 */
body {
font-family: 'Arial', sans-serif;
background-color: #f8f8f8;
color: #333;
}
header {
background-color: #d9534f;
color: #fff;
padding: 20px 0;
text-align: center;
}
header h1 {
margin: 0;
}
main {
padding: 20px;
text-align: center;
}
footer {
background-color: #fe5b56;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
bottom: 0;
width: 100%;
}
/* 输入框和按钮样式 */
input[type="text"] {
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
width: calc(100% - 22px); /* 减去padding和border的宽度 */
}
button {
padding: 10px 20px;
background-color: #d9534f;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #c9302c;
}
/* 动画效果 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
header, main, footer {
animation: fadeInDown 1s ease-in-out;
}
/* 响应式设计 */
@media (max-width: 768px) {
/* 针对小屏幕的样式调整 */
}
/* 动态阴影效果 */
@keyframes shadowPulse {
0%, 100% { box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); }
50% { box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); }
}
button:hover {
animation: shadowPulse 1.5s infinite;
}
/* 文字跳动动画*/
h1 {
animation: jump 1.5s ease-in-out infinite;
}
@keyframes jump {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* 输入框和按钮的悬停效果*/
input[type="text"]:hover, button:hover {
border: 1px solid #d9534f;
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
/*按钮点击动画*/
button:active {
transform: scale(0.95);
background-color: #b52b27;
}
/*光晕效果*/
.glow {
animation: glowEffect 1.5s infinite alternate;
}
@keyframes glowEffect {
from {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #d9534f, 0 0 20px #d9534f, 0 0 25px #d9534f, 0 0 30px #d9534f;
}
to {
text-shadow: 0 0 10px #fff, 0 0 20px #d9534f, 0 0 30px #d9534f, 0 0 40px #d9534f, 0 0 50px #d9534f, 0 0 60px #d9534f;
}
}
/* 3D翻转效果*/
.feature {
perspective: 1000px;
}
.feature:hover .feature-inner {
transform: rotateY(360deg);
transition: transform 15s;
}
/*视差滚动效果*/
.parallax-section {
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* 粒子背景*/
.particle-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.particle {
fill: rgba(255, 255, 255, 0.8);
animation: moveParticles 10s infinite linear;
}
@keyframes moveParticles {
0% { transform: translate(0, 0); }
100% { transform: translate(100px, 100px); }
}
/*线条动画*/
.dynamic-line {
stroke-dasharray: 300;
stroke-dashoffset: 300;
animation: dash 3s linear infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 300;
}
to {
stroke-dashoffset: 0;
}
}
/*光晕效果*/
button {
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 300%;
height: 200%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%) rotate(45deg);
transition: all 0.5s;
}
button:hover::before {
width: 100%;
height: 100%;
}
/*闪烁效果*/
@keyframes blinker {
50% { opacity: 0; }
}
.blink-text {
animation: blinker 1s linear infinite;
}
/* 打字机效果*/
.typewriter {
font-family: monospace;
overflow: hidden;
white-space: nowrap;
width: 100%;
animation: typewriter 4s steps(40) 1s infinite;
}
@keyframes typewriter {
0% { width: 0; }
100% { width: 100%; }
}
/* 3D文字效果*/
.three-d-text {
transform: rotateX(45deg) rotateY(45deg);
transform-style: preserve-3d;
perspective: 600px;
}
/*渐变文字效果*/
.gradient-text {
background: -webkit-linear-gradient(45deg, #d9534f, #fe5b56);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/*动态阴影效果*/
.dynamic-shadow {
transition: box-shadow 0.3s ease-in-out;
}
.dynamic-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}
/*光点闪烁效果*/
.sparkle-point {
position: absolute;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.8);
pointer-events: none;
animation: sparkle 2s infinite;
}
@keyframes sparkle {
0% { opacity: 0; transform: scale(0); }
50% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0); }
}
/*动态渲染效果*/
.render-effect {
animation: renderEffect 5s infinite alternate;
}
@keyframes renderEffect {
0%, 100% { filter: grayscale(0); }
50% { filter: grayscale(1); }
}
/* 全屏背景动画*/
body {
background: linear-gradient(-45deg, #000, #7c7c7c, #000);
background-size: 400% 1000%;
animation: gradientBG 15s ease infinite;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/*线条动画*/
.waves {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 90px;
z-index: -1;
}
@keyframes backgroundGradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
body {
animation: backgroundGradient 15s ease infinite;
}
a {
color: #fdfdfd;
}
a:hover {
color: #000000;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
background-color: #d9534f;
color: white;
}
.svg-background {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保SVG在内容的后面 */
}
@keyframes colorShift {
0% { background-color: #d9534f; }
50% { background-color: #fe5b56; }
100% { background-color: #d9534f; }
}
button {
animation: colorShift 3s infinite;
}
.blink {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
input[type="text"]:hover {
background-color: rgba(217, 83, 79, 0.1);
}
.parallax-section {
background-image: url('your-image.jpg');
background-attachment: fixed;
background-size: cover;
height: 100vh;
}
/*字体动态改变*/
h2 {
transition: font-size 0.3s;
}
h2:hover {
font-size: 2em;
}
/*动态内容加载*/
.main-content {
animation: fadeIn 1s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 旋转效果*/
footer {
transition: transform 0.5s;
}
footer:hover {
transform: rotate(5deg);
}
.dynamic-line {
stroke: #d9534f;
stroke-width: 2;
fill: none;
animation: dash 5s linear infinite;
}
@keyframes dash {
0% { stroke-dasharray: 0, 100; }
100% { stroke-dasharray: 100, 0; }
}
button {
perspective: 1000px;
}
button:hover {
transform: rotateX(10deg) rotateY(10deg);
transition: transform 0.3s;
}
/*文字打字效果*/
.typewriter {
overflow: hidden;
white-space: nowrap;
border-right: .15em solid orange;
animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: orange; }
}
/*旋转加载*/
.loading {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/*字体阴影动态*/
h2 {
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
transition: text-shadow 0.3s ease;
}
h2:hover {
text-shadow: 0 0 20px rgba(255, 0, 0, 1);
}
/*彩色阴影*/
button {
box-shadow: 0 4px 20px rgba(217, 83, 79, 0.5);
}
button:hover {
box-shadow: 0 8px 30px rgba(217, 83, 79, 0.8);
}
.particle-background {
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 10%, transparent 10%);
animation: particleAnimation 5s infinite;
}
/*随机粒子背景*/
@keyframes particleAnimation {
0% { background-size: 0%; }
100% { background-size: 100%; }
}
/*光环效果*/
header {
box-shadow: 0 0 20px rgba(217, 83, 79, 0.6);
}
/*悬浮按钮效果*/
button {
transition: transform 0.3s ease;
}
button:hover {
transform: translateY(-5px);
}
/*玻璃效果*/
main {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 20px;
}
/* 术语 */
/* 术语结果框样式 */
.result-box {
background-color: #ff6e7a; /* 淡红色背景,与按钮颜色呼应 */
border: 1px solid #d9534f; /* 边框颜色与头部和底部颜色一致 */
padding: 20px;
margin-top: 20px;
border-radius: 5px; /* 圆角边框 */
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* 轻微的立体阴影效果 */
animation: fadeInDown 1s ease-in-out; /* 淡入下移动画 */
}
/* 结果文本框样式 */
.result-textarea {
background-color: #f5f5f5; /* 浅灰色背景,更好的对比度 */
border: 1px solid #ddd; /* 边框颜色与输入框一致 */
border-radius: 5px; /* 圆角边框 */
padding: 10px;
width: 100%; /* 宽度与输入框一致 */
box-sizing: border-box; /* 盒模型宽度包含padding和border */
resize: none; /* 禁止调整大小 */
font-family: 'Arial', sans-serif; /* 与页面字体一致 */
color: #333; /* 文本颜色与页面一致 */
line-height: 1.5; /* 行高 */
overflow-y: auto; /* 超出内容显示滚动条 */
}
/* 响应式设计 */
@media (max-width: 768px) {
.result-box {
width: auto; /* 小屏幕上宽度自动调整 */
margin-left: 10px; /* 较小的外边距 */
margin-right: 10px;
}
input[type="text"] {
width: calc(100% - 22px); /* 调整输入框宽度 */
}
}
/* 悬停效果,使结果框在鼠标悬停时有阴影变化 */
.result-box:hover {
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
}
/* 点击效果,使结果框在被点击时有压缩效果 */
.result-box:active {
transform: translateY(2px);
}
/* 显示动画 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 隐藏动画 */
@keyframes fadeOutUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
/* 展开动画 */
@keyframes expand {
from {
height: 0;
}
to {
height: 200px; /* 根据需要调整高度 */
}
}
.result-box {
display: none; /* 初始时隐藏 */
background-color: #f8d7da;
border: 1px solid #d9534f;
padding: 20px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
animation-fill-mode: forwards; /* 保持动画结束状态 */
overflow: hidden; /* 隐藏内容超出部分 */
}

@ -0,0 +1,568 @@
/* 基本重置 */
body, h1, h2, p, a {
margin: 0;
padding: 0;
text-decoration: none;
color: rgb(255, 255, 255);
}
/* 基础字体和背景 */
body {
font-family: 'Arial', sans-serif;
background-color: #f8f8f8;
color: #333;
}
header {
background-color: #d9534f;
color: #fff;
padding: 20px 0;
text-align: center;
}
header h1 {
margin: 0;
}
main {
padding: 20px;
text-align: center;
}
footer {
background-color: #fe5b56;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
bottom: 0;
width: 100%;
}
/* 输入框和按钮样式 */
input[type="text"] {
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
width: calc(100% - 22px); /* 减去padding和border的宽度 */
}
button {
padding: 10px 20px;
background-color: #d9534f;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #c9302c;
}
/* 动画效果 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
header, main, footer {
animation: fadeInDown 1s ease-in-out;
}
/* 响应式设计 */
@media (max-width: 768px) {
/* 针对小屏幕的样式调整 */
}
/* 动态阴影效果 */
@keyframes shadowPulse {
0%, 100% { box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); }
50% { box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); }
}
button:hover {
animation: shadowPulse 1.5s infinite;
}
/* 文字跳动动画*/
h1 {
animation: jump 1.5s ease-in-out infinite;
}
@keyframes jump {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* 输入框和按钮的悬停效果*/
input[type="text"]:hover, button:hover {
border: 1px solid #d9534f;
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
/*按钮点击动画*/
button:active {
transform: scale(0.95);
background-color: #b52b27;
}
/*光晕效果*/
.glow {
animation: glowEffect 1.5s infinite alternate;
}
@keyframes glowEffect {
from {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #d9534f, 0 0 20px #d9534f, 0 0 25px #d9534f, 0 0 30px #d9534f;
}
to {
text-shadow: 0 0 10px #fff, 0 0 20px #d9534f, 0 0 30px #d9534f, 0 0 40px #d9534f, 0 0 50px #d9534f, 0 0 60px #d9534f;
}
}
/* 3D翻转效果*/
.feature {
perspective: 1000px;
}
.feature:hover .feature-inner {
transform: rotateY(360deg);
transition: transform 15s;
}
/*视差滚动效果*/
.parallax-section {
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* 粒子背景*/
.particle-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.particle {
fill: rgba(255, 255, 255, 0.8);
animation: moveParticles 10s infinite linear;
}
@keyframes moveParticles {
0% { transform: translate(0, 0); }
100% { transform: translate(100px, 100px); }
}
/*线条动画*/
.dynamic-line {
stroke-dasharray: 300;
stroke-dashoffset: 300;
animation: dash 3s linear infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 300;
}
to {
stroke-dashoffset: 0;
}
}
/*光晕效果*/
button {
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 300%;
height: 200%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%) rotate(45deg);
transition: all 0.5s;
}
button:hover::before {
width: 100%;
height: 100%;
}
/*闪烁效果*/
@keyframes blinker {
50% { opacity: 0; }
}
.blink-text {
animation: blinker 1s linear infinite;
}
/* 打字机效果*/
.typewriter {
font-family: monospace;
overflow: hidden;
white-space: nowrap;
width: 100%;
animation: typewriter 4s steps(40) 1s infinite;
}
@keyframes typewriter {
0% { width: 0; }
100% { width: 100%; }
}
/* 3D文字效果*/
.three-d-text {
transform: rotateX(45deg) rotateY(45deg);
transform-style: preserve-3d;
perspective: 600px;
}
/*渐变文字效果*/
.gradient-text {
background: -webkit-linear-gradient(45deg, #d9534f, #fe5b56);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/*动态阴影效果*/
.dynamic-shadow {
transition: box-shadow 0.3s ease-in-out;
}
.dynamic-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}
/*光点闪烁效果*/
.sparkle-point {
position: absolute;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.8);
pointer-events: none;
animation: sparkle 2s infinite;
}
@keyframes sparkle {
0% { opacity: 0; transform: scale(0); }
50% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0); }
}
/*动态渲染效果*/
.render-effect {
animation: renderEffect 5s infinite alternate;
}
@keyframes renderEffect {
0%, 100% { filter: grayscale(0); }
50% { filter: grayscale(1); }
}
/* 全屏背景动画*/
body {
background: linear-gradient(-45deg, #000, #7c7c7c, #000);
background-size: 400% 1000%;
animation: gradientBG 15s ease infinite;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/*线条动画*/
.waves {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 90px;
z-index: -1;
}
@keyframes backgroundGradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
body {
animation: backgroundGradient 15s ease infinite;
}
a {
color: #fdfdfd;
}
a:hover {
color: #000000;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
background-color: #d9534f;
color: white;
}
.svg-background {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保SVG在内容的后面 */
}
@keyframes colorShift {
0% { background-color: #d9534f; }
50% { background-color: #fe5b56; }
100% { background-color: #d9534f; }
}
button {
animation: colorShift 3s infinite;
}
.blink {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
input[type="text"]:hover {
background-color: rgba(217, 83, 79, 0.1);
}
.parallax-section {
background-image: url('your-image.jpg');
background-attachment: fixed;
background-size: cover;
height: 100vh;
}
/*字体动态改变*/
h2 {
transition: font-size 0.3s;
}
h2:hover {
font-size: 2em;
}
/*动态内容加载*/
.main-content {
animation: fadeIn 1s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 旋转效果*/
footer {
transition: transform 0.5s;
}
footer:hover {
transform: rotate(5deg);
}
.dynamic-line {
stroke: #d9534f;
stroke-width: 2;
fill: none;
animation: dash 5s linear infinite;
}
@keyframes dash {
0% { stroke-dasharray: 0, 100; }
100% { stroke-dasharray: 100, 0; }
}
button {
perspective: 1000px;
}
button:hover {
transform: rotateX(10deg) rotateY(10deg);
transition: transform 0.3s;
}
/*文字打字效果*/
.typewriter {
overflow: hidden;
white-space: nowrap;
border-right: .15em solid orange;
animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: orange; }
}
/*旋转加载*/
.loading {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/*字体阴影动态*/
h2 {
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
transition: text-shadow 0.3s ease;
}
h2:hover {
text-shadow: 0 0 20px rgba(255, 0, 0, 1);
}
/*彩色阴影*/
button {
box-shadow: 0 4px 20px rgba(217, 83, 79, 0.5);
}
button:hover {
box-shadow: 0 8px 30px rgba(217, 83, 79, 0.8);
}
.particle-background {
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 10%, transparent 10%);
animation: particleAnimation 5s infinite;
}
/*随机粒子背景*/
@keyframes particleAnimation {
0% { background-size: 0%; }
100% { background-size: 100%; }
}
/*光环效果*/
header {
box-shadow: 0 0 20px rgba(217, 83, 79, 0.6);
}
/*悬浮按钮效果*/
button {
transition: transform 0.3s ease;
}
button:hover {
transform: translateY(-5px);
}
/*玻璃效果*/
main {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 20px;
}
/* 术语 */
/* 术语结果框样式 */
.result-box {
background-color: #ff6e7a; /* 淡红色背景,与按钮颜色呼应 */
border: 1px solid #d9534f; /* 边框颜色与头部和底部颜色一致 */
padding: 20px;
margin-top: 20px;
border-radius: 5px; /* 圆角边框 */
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* 轻微的立体阴影效果 */
animation: fadeInDown 1s ease-in-out; /* 淡入下移动画 */
}
/* 结果文本框样式 */
.result-textarea {
background-color: #f5f5f5; /* 浅灰色背景,更好的对比度 */
border: 1px solid #ddd; /* 边框颜色与输入框一致 */
border-radius: 5px; /* 圆角边框 */
padding: 10px;
width: 100%; /* 宽度与输入框一致 */
box-sizing: border-box; /* 盒模型宽度包含padding和border */
resize: none; /* 禁止调整大小 */
font-family: 'Arial', sans-serif; /* 与页面字体一致 */
color: #333; /* 文本颜色与页面一致 */
line-height: 1.5; /* 行高 */
overflow-y: auto; /* 超出内容显示滚动条 */
}
/* 响应式设计 */
@media (max-width: 768px) {
.result-box {
width: auto; /* 小屏幕上宽度自动调整 */
margin-left: 10px; /* 较小的外边距 */
margin-right: 10px;
}
input[type="text"] {
width: calc(100% - 22px); /* 调整输入框宽度 */
}
}
/* 悬停效果,使结果框在鼠标悬停时有阴影变化 */
.result-box:hover {
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
}
/* 点击效果,使结果框在被点击时有压缩效果 */
.result-box:active {
transform: translateY(2px);
}
/* 显示动画 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 隐藏动画 */
@keyframes fadeOutUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
/* 展开动画 */
@keyframes expand {
from {
height: 0;
}
to {
height: 200px; /* 根据需要调整高度 */
}
}
.result-box {
display: none; /* 初始时隐藏 */
background-color: #f8d7da;
border: 1px solid #d9534f;
padding: 20px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
animation-fill-mode: forwards; /* 保持动画结束状态 */
overflow: hidden; /* 隐藏内容超出部分 */
}

@ -0,0 +1,568 @@
/* 基本重置 */
body, h1, h2, p, a {
margin: 0;
padding: 0;
text-decoration: none;
color: rgb(255, 255, 255);
}
/* 基础字体和背景 */
body {
font-family: 'Arial', sans-serif;
background-color: #f8f8f8;
color: #333;
}
header {
background-color: #d9534f;
color: #fff;
padding: 20px 0;
text-align: center;
}
header h1 {
margin: 0;
}
main {
padding: 20px;
text-align: center;
}
footer {
background-color: #fe5b56;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
bottom: 0;
width: 100%;
}
/* 输入框和按钮样式 */
input[type="text"] {
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 5px;
width: calc(100% - 22px); /* 减去padding和border的宽度 */
}
button {
padding: 10px 20px;
background-color: #d9534f;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #c9302c;
}
/* 动画效果 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
header, main, footer {
animation: fadeInDown 1s ease-in-out;
}
/* 响应式设计 */
@media (max-width: 768px) {
/* 针对小屏幕的样式调整 */
}
/* 动态阴影效果 */
@keyframes shadowPulse {
0%, 100% { box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); }
50% { box-shadow: 0 0 20px rgba(0, 0, 0, 0.8); }
}
button:hover {
animation: shadowPulse 1.5s infinite;
}
/* 文字跳动动画*/
h1 {
animation: jump 1.5s ease-in-out infinite;
}
@keyframes jump {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
/* 输入框和按钮的悬停效果*/
input[type="text"]:hover, button:hover {
border: 1px solid #d9534f;
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
/*按钮点击动画*/
button:active {
transform: scale(0.95);
background-color: #b52b27;
}
/*光晕效果*/
.glow {
animation: glowEffect 1.5s infinite alternate;
}
@keyframes glowEffect {
from {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #d9534f, 0 0 20px #d9534f, 0 0 25px #d9534f, 0 0 30px #d9534f;
}
to {
text-shadow: 0 0 10px #fff, 0 0 20px #d9534f, 0 0 30px #d9534f, 0 0 40px #d9534f, 0 0 50px #d9534f, 0 0 60px #d9534f;
}
}
/* 3D翻转效果*/
.feature {
perspective: 1000px;
}
.feature:hover .feature-inner {
transform: rotateY(360deg);
transition: transform 15s;
}
/*视差滚动效果*/
.parallax-section {
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* 粒子背景*/
.particle-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.particle {
fill: rgba(255, 255, 255, 0.8);
animation: moveParticles 10s infinite linear;
}
@keyframes moveParticles {
0% { transform: translate(0, 0); }
100% { transform: translate(100px, 100px); }
}
/*线条动画*/
.dynamic-line {
stroke-dasharray: 300;
stroke-dashoffset: 300;
animation: dash 3s linear infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 300;
}
to {
stroke-dashoffset: 0;
}
}
/*光晕效果*/
button {
position: relative;
overflow: hidden;
}
button::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 300%;
height: 200%;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%) rotate(45deg);
transition: all 0.5s;
}
button:hover::before {
width: 100%;
height: 100%;
}
/*闪烁效果*/
@keyframes blinker {
50% { opacity: 0; }
}
.blink-text {
animation: blinker 1s linear infinite;
}
/* 打字机效果*/
.typewriter {
font-family: monospace;
overflow: hidden;
white-space: nowrap;
width: 100%;
animation: typewriter 4s steps(40) 1s infinite;
}
@keyframes typewriter {
0% { width: 0; }
100% { width: 100%; }
}
/* 3D文字效果*/
.three-d-text {
transform: rotateX(45deg) rotateY(45deg);
transform-style: preserve-3d;
perspective: 600px;
}
/*渐变文字效果*/
.gradient-text {
background: -webkit-linear-gradient(45deg, #d9534f, #fe5b56);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/*动态阴影效果*/
.dynamic-shadow {
transition: box-shadow 0.3s ease-in-out;
}
.dynamic-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
}
/*光点闪烁效果*/
.sparkle-point {
position: absolute;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.8);
pointer-events: none;
animation: sparkle 2s infinite;
}
@keyframes sparkle {
0% { opacity: 0; transform: scale(0); }
50% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0); }
}
/*动态渲染效果*/
.render-effect {
animation: renderEffect 5s infinite alternate;
}
@keyframes renderEffect {
0%, 100% { filter: grayscale(0); }
50% { filter: grayscale(1); }
}
/* 全屏背景动画*/
body {
background: linear-gradient(-45deg, #000, #7c7c7c, #000);
background-size: 400% 1000%;
animation: gradientBG 15s ease infinite;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/*线条动画*/
.waves {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 90px;
z-index: -1;
}
@keyframes backgroundGradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
body {
animation: backgroundGradient 15s ease infinite;
}
a {
color: #fdfdfd;
}
a:hover {
color: #000000;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
background-color: #d9534f;
color: white;
}
.svg-background {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1; /* 确保SVG在内容的后面 */
}
@keyframes colorShift {
0% { background-color: #d9534f; }
50% { background-color: #fe5b56; }
100% { background-color: #d9534f; }
}
button {
animation: colorShift 3s infinite;
}
.blink {
animation: blink 1s step-start infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
input[type="text"]:hover {
background-color: rgba(217, 83, 79, 0.1);
}
.parallax-section {
background-image: url('your-image.jpg');
background-attachment: fixed;
background-size: cover;
height: 100vh;
}
/*字体动态改变*/
h2 {
transition: font-size 0.3s;
}
h2:hover {
font-size: 2em;
}
/*动态内容加载*/
.main-content {
animation: fadeIn 1s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 旋转效果*/
footer {
transition: transform 0.5s;
}
footer:hover {
transform: rotate(5deg);
}
.dynamic-line {
stroke: #d9534f;
stroke-width: 2;
fill: none;
animation: dash 5s linear infinite;
}
@keyframes dash {
0% { stroke-dasharray: 0, 100; }
100% { stroke-dasharray: 100, 0; }
}
button {
perspective: 1000px;
}
button:hover {
transform: rotateX(10deg) rotateY(10deg);
transition: transform 0.3s;
}
/*文字打字效果*/
.typewriter {
overflow: hidden;
white-space: nowrap;
border-right: .15em solid orange;
animation: typing 3.5s steps(40, end), blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: orange; }
}
/*旋转加载*/
.loading {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/*字体阴影动态*/
h2 {
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
transition: text-shadow 0.3s ease;
}
h2:hover {
text-shadow: 0 0 20px rgba(255, 0, 0, 1);
}
/*彩色阴影*/
button {
box-shadow: 0 4px 20px rgba(217, 83, 79, 0.5);
}
button:hover {
box-shadow: 0 8px 30px rgba(217, 83, 79, 0.8);
}
.particle-background {
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 10%, transparent 10%);
animation: particleAnimation 5s infinite;
}
/*随机粒子背景*/
@keyframes particleAnimation {
0% { background-size: 0%; }
100% { background-size: 100%; }
}
/*光环效果*/
header {
box-shadow: 0 0 20px rgba(217, 83, 79, 0.6);
}
/*悬浮按钮效果*/
button {
transition: transform 0.3s ease;
}
button:hover {
transform: translateY(-5px);
}
/*玻璃效果*/
main {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 20px;
}
/* 术语 */
/* 术语结果框样式 */
.result-box {
background-color: #ff6e7a; /* 淡红色背景,与按钮颜色呼应 */
border: 1px solid #d9534f; /* 边框颜色与头部和底部颜色一致 */
padding: 20px;
margin-top: 20px;
border-radius: 5px; /* 圆角边框 */
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* 轻微的立体阴影效果 */
animation: fadeInDown 1s ease-in-out; /* 淡入下移动画 */
}
/* 结果文本框样式 */
.result-textarea {
background-color: #f5f5f5; /* 浅灰色背景,更好的对比度 */
border: 1px solid #ddd; /* 边框颜色与输入框一致 */
border-radius: 5px; /* 圆角边框 */
padding: 10px;
width: 100%; /* 宽度与输入框一致 */
box-sizing: border-box; /* 盒模型宽度包含padding和border */
resize: none; /* 禁止调整大小 */
font-family: 'Arial', sans-serif; /* 与页面字体一致 */
color: #333; /* 文本颜色与页面一致 */
line-height: 1.5; /* 行高 */
overflow-y: auto; /* 超出内容显示滚动条 */
}
/* 响应式设计 */
@media (max-width: 768px) {
.result-box {
width: auto; /* 小屏幕上宽度自动调整 */
margin-left: 10px; /* 较小的外边距 */
margin-right: 10px;
}
input[type="text"] {
width: calc(100% - 22px); /* 调整输入框宽度 */
}
}
/* 悬停效果,使结果框在鼠标悬停时有阴影变化 */
.result-box:hover {
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
}
/* 点击效果,使结果框在被点击时有压缩效果 */
.result-box:active {
transform: translateY(2px);
}
/* 显示动画 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 隐藏动画 */
@keyframes fadeOutUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
/* 展开动画 */
@keyframes expand {
from {
height: 0;
}
to {
height: 200px; /* 根据需要调整高度 */
}
}
.result-box {
display: none; /* 初始时隐藏 */
background-color: #f8d7da;
border: 1px solid #d9534f;
padding: 20px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
animation-fill-mode: forwards; /* 保持动画结束状态 */
overflow: hidden; /* 隐藏内容超出部分 */
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,24 @@
<template>
<div id="app">
<transition>
<router-view />
</transition>
</div>
</template>
<style>
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
}
#app {
height: 100%;
overflow: hidden;
}
</style>

@ -0,0 +1,837 @@
<template>
<div class="login">
<div class="light-spots"></div>
<div class="ripples"></div>
<div class="flowing-lines"></div>
<div class="login-container">
<el-tabs
v-model="activeName"
class="login-tabs"
stretch
@tab-click="handleClick"
>
<el-tab-pane label="用户登录" name="login">
<el-form
ref="loginForm"
:model="user"
status-icon
:rules="rules"
class="login-form"
>
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="user.username" class="form-input">
<i slot="prefix" class="el-icon-user"></i>
</el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="user.password" class="form-input">
<i slot="prefix" class="el-icon-lock"></i>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')" class="submit-btn">
<span> </span>
</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="用户注册" name="register">
<el-form
ref="registerForm"
:model="user"
status-icon
:rules="rules"
class="login-form"
>
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="user.username" class="form-input">
<i slot="prefix" class="el-icon-user"></i>
</el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="user.password" class="form-input">
<i slot="prefix" class="el-icon-lock"></i>
</el-input>
</el-form-item>
<el-form-item label="确认密码" prop="surePassword">
<el-input type="password" v-model="user.surePassword" class="form-input">
<i slot="prefix" class="el-icon-key"></i>
</el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input type="email" v-model="user.email" class="form-input">
<i slot="prefix" class="el-icon-message"></i>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('registerForm')" class="submit-btn">
<span> </span>
</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane>
<span slot="label"><i class="el-icon-service"></i> 帮助中心</span>
<div class="help-content">
<i class="el-icon-question"></i>
<p>如需帮助请联系客服</p>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import { mapActions } from "vuex"
import { MessageBox } from 'element-ui'
export default {
name: "Login",
data() {
var validateUsername = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入用户名"));
}
callback();
};
var validatePassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
}
callback();
};
var validateSurePassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入确认密码"));
} else if (value !== this.user.password) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
var validateEmail = (rule, value, callback) => {
const emailPattern = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
if (value === "") {
callback(new Error("请输入邮箱"));
} else if (!emailPattern.test(value)) {
callback(new Error("请输入有效的邮箱地址"));
} else {
callback();
}
};
return {
user: {
username: "",
password: "",
surePassword: "",
email:""
},
rules: {
username: [{ validator: validateUsername, trigger: "blur" }],
password: [{ validator: validatePassword, trigger: "blur" }],
email: [{ validator: validateEmail, trigger: "blur" }],
surePassword: [
{ validator: validateSurePassword, trigger: "blur" },
],
},
activeName: "login",
};
},
methods: {
...mapActions("loginModule",["setUserActions"]),
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.activeName === "login") {
this.setUserActions(this.user)
}
if (this.activeName === "register") {
this.$api.register({
username:this.user.username,
password:this.user.password,
email:this.user.email
}).then(res => {
if (res.data.success) {
MessageBox.alert(res.data.msg || '注册成功', '提示', {
confirmButtonText: '确定',
type: 'success'
});
} else {
MessageBox.alert(res.data.msg || '注册失败', '提示', {
confirmButtonText: '确定',
type: 'error'
});
}
}).catch(error => {
MessageBox.alert('请勿重复注册', '错误', {
confirmButtonText: '确定',
type: 'error'
});
});
}
} else {
console.log("error submit!!");
return false;
}
});
},
handleClick(tab, event) {},
},
};
</script>
<style scoped lang="less">
.login {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
//
background: linear-gradient(135deg,
#002FA7 0%, //
#0047AB 50%, //
#1E90FF 100% //
);
position: relative;
overflow: hidden;
//
.light-spots {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
&::before, &::after {
content: '';
position: absolute;
width: 200px;
height: 200px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
animation: spotFloat 10s infinite alternate;
}
&::before {
top: 20%;
left: 20%;
animation-delay: -5s;
}
&::after {
bottom: 20%;
right: 20%;
}
}
//
.ripples {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
&::before, &::after {
content: '';
position: absolute;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(255,255,255,0.2) 0%, transparent 70%);
border-radius: 50%;
animation: rippleEffect 8s infinite;
}
&::after {
animation-delay: -4s;
animation-duration: 10s;
}
}
// 线
.flowing-lines {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
&::before {
content: '';
position: absolute;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
background: linear-gradient(45deg,
transparent 45%,
rgba(255,255,255,0.1) 50%,
transparent 55%
);
animation: flowingLines 5s linear infinite;
}
}
.login-container {
width: 480px;
backdrop-filter: blur(20px);
background: rgba(255, 255, 255, 0.08);
border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
padding: 30px;
position: relative;
z-index: 1;
animation: float 6s ease-in-out infinite;
transition: all 0.4s ease;
border: 1px solid rgba(255, 255, 255, 0.1);
&::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg,
#002FA7, //
);
border-radius: 22px;
z-index: -1;
animation: containerGlow 4s linear infinite;
filter: blur(15px);
opacity: 0.5;
}
&:hover {
transform: translateY(-5px);
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
}
}
.login-tabs {
:deep(.el-tabs__nav-wrap) {
&::after {
display: none;
}
}
:deep(.el-tabs__item) {
color: #ffffff;
font-size: 16px;
transition: all 0.3s;
padding: 0 20px;
&.is-active {
color: #fff;
font-weight: 600;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
&:hover {
color: #fff;
transform: translateY(-2px);
}
}
:deep(.el-tabs__active-bar) {
background: linear-gradient(90deg, #ffffff, rgba(255, 255, 255, 0.6));
height: 3px;
border-radius: 3px;
}
}
.login-form {
margin-top: 30px;
.el-form-item__label {
color: #ffffff !important;
font-weight: 500;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
}
.form-input {
:deep(.el-input__inner) {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 10px;
color: #ffffff;
height: 45px;
padding-left: 45px;
transition: all 0.3s;
font-size: 15px;
&::placeholder {
color: rgba(255, 255, 255, 0.6);
}
&:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
}
&:focus {
border-color: #002FA7;
box-shadow: 0 0 15px rgba(0, 47, 167, 0.5);
animation: borderFlow 2s linear infinite;
}
}
:deep(.el-input__prefix) {
left: 15px;
color: #ffffff;
opacity: 0.8;
animation: iconGlow 2s ease-in-out infinite;
}
}
.submit-btn {
width: 100%;
height: 45px;
background: linear-gradient(45deg, #002FA7, #0047AB);
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
letter-spacing: 2px;
color: #fff;
transition: all 0.3s;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(
circle,
rgba(255, 255, 255, 0.3) 0%,
transparent 50%
);
animation: btnRadialGlow 3s ease-in-out infinite;
}
&:hover {
background: linear-gradient(45deg, #0047AB, #1E90FF);
transform: translateY(-2px);
box-shadow: 0 7px 20px rgba(0, 0, 0, 0.2);
}
&:active {
transform: translateY(1px);
}
&::after {
content: '';
position: absolute;
width: 30px;
height: 100%;
top: 0;
left: -30px;
background: linear-gradient(
to right,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
transform: skewX(-45deg);
animation: btnShine 3s infinite;
}
}
.help-content {
text-align: center;
color: #ffffff;
padding: 30px;
i {
font-size: 40px;
margin-bottom: 15px;
animation: pulse 2s infinite;
}
p {
font-size: 15px;
color: #ffffff;
margin-top: 10px;
}
}
//
.light-beam {
position: absolute;
width: 100%;
height: 100%;
pointer-events: none;
opacity: 0.5;
&::before {
content: '';
position: absolute;
width: 100%;
height: 2px;
background: linear-gradient(90deg,
transparent 0%,
rgba(255, 255, 255, 0.2) 50%,
transparent 100%
);
animation: scanLine 4s linear infinite;
}
}
//
.login-container {
//
&:hover {
.el-input__inner {
transform: translateY(-2px);
transition: transform 0.3s ease;
}
}
}
//
.form-input {
&:focus-within {
&::after {
content: '';
position: absolute;
inset: -2px;
border-radius: inherit;
padding: 2px;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
mask: linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask-composite: exclude;
animation: focusGlow 2s linear infinite;
}
}
}
//
.submit-btn {
&:active {
transform: scale(0.98);
&::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
circle at center,
rgba(255, 255, 255, 0.3),
transparent 70%
);
animation: buttonPress 0.3s ease-out;
}
}
}
}
//
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes borderGlow {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
@keyframes shine {
0% {
transform: translateX(-100%) skewX(-15deg);
opacity: 0;
}
20% { opacity: 0.5; }
100% {
transform: translateX(100%) skewX(-15deg);
opacity: 0;
}
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.8; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes buttonShine {
0% { left: -100%; }
50% { left: 100%; }
100% { left: 100%; }
}
@keyframes particleMove {
0% { transform: translateY(0) rotate(0deg); }
100% { transform: translateY(-100%) rotate(360deg); }
}
//
@keyframes ripple {
0% { transform: scale(1); opacity: 0.4; }
100% { transform: scale(2); opacity: 0; }
}
//
@media screen and (max-width: 576px) {
.login {
.login-container {
width: 90%;
padding: 20px;
}
}
}
//
@keyframes spotFloat {
0% { transform: translate(0, 0) scale(1); }
50% { transform: translate(30px, 20px) scale(1.2); }
100% { transform: translate(-20px, -15px) scale(0.8); }
}
@keyframes rippleEffect {
0% {
transform: scale(0.5);
opacity: 0.5;
}
50% {
transform: scale(2);
opacity: 0.2;
}
100% {
transform: scale(0.5);
opacity: 0.5;
}
}
@keyframes flowingLines {
0% { transform: translateX(-50%) rotate(0deg); }
100% { transform: translateX(50%) rotate(360deg); }
}
@keyframes borderRotate {
0% { filter: hue-rotate(0deg); }
100% { filter: hue-rotate(360deg); }
}
@keyframes inputGlow {
0% { box-shadow: 0 0 5px rgba(255, 255, 255, 0.2); }
100% { box-shadow: 0 0 20px rgba(255, 255, 255, 0.4); }
}
@keyframes btnShine {
0% { left: -30px; }
100% { left: 130%; }
}
//
@keyframes breathe {
0%, 100% { opacity: 0.4; }
50% { opacity: 1; }
}
// 3D
@keyframes float3D {
0% {
transform: perspective(1000px) rotateX(0deg) rotateY(0deg);
}
50% {
transform: perspective(1000px) rotateX(3deg) rotateY(5deg);
}
100% {
transform: perspective(1000px) rotateX(0deg) rotateY(0deg);
}
}
@keyframes borderFlow {
0% {
border-image: linear-gradient(
90deg,
#002FA7 0%,
#0047AB 25%,
#1E90FF 50%,
#0047AB 75%,
#002FA7 100%
) 1;
}
100% {
border-image: linear-gradient(
90deg,
#002FA7 100%,
#0047AB 0%,
#1E90FF 25%,
#0047AB 50%,
#002FA7 75%
) 1;
}
}
@keyframes iconGlow {
0%, 100% {
text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
}
50% {
text-shadow: 0 0 15px rgba(255, 255, 255, 0.8);
}
}
@keyframes containerGlow {
0% {
filter: blur(15px) hue-rotate(0deg);
}
100% {
filter: blur(15px) hue-rotate(360deg);
}
}
//
.el-form-item__label,
.el-tabs__item,
.help-content,
.el-input__inner,
.submit-btn {
color: #ffffff !important;
}
//
.submit-btn {
background: linear-gradient(45deg, #002FA7, #0047AB);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(
circle,
rgba(255, 255, 255, 0.3) 0%,
transparent 50%
);
animation: btnRadialGlow 3s ease-in-out infinite;
}
&:hover {
background: linear-gradient(45deg, #0047AB, #1E90FF);
transform: translateY(-2px);
}
}
@keyframes btnRadialGlow {
0% {
transform: scale(0.5) rotate(0deg);
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
transform: scale(2) rotate(360deg);
opacity: 0;
}
}
.form-input {
:deep(.el-input__inner) {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
background-color: rgba(255, 255, 255, 0.08) !important;
caret-color: #ffffff !important; //
//
&:-webkit-autofill,
&:-webkit-autofill:hover,
&:-webkit-autofill:focus,
&:-webkit-autofill:active {
-webkit-text-fill-color: #ffffff !important;
-webkit-box-shadow: 0 0 0 30px transparent inset !important;
transition: background-color 5000s ease-in-out 0s;
background-color: transparent !important;
}
//
&::placeholder {
color: rgba(255, 255, 255, 0.6) !important;
-webkit-text-fill-color: rgba(255, 255, 255, 0.6) !important;
}
}
}
//
:deep(.el-input__inner),
:deep(.el-input input),
:deep(.el-input textarea) {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
}
//
:deep(.el-form-item__label) {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
}
//
@keyframes scanLine {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(100%);
}
}
@keyframes focusGlow {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
@keyframes buttonPress {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}
</style>
<style lang="less">
.el-input__inner {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
background-color: rgba(255, 255, 255, 0.08) !important;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

@ -0,0 +1,59 @@
<template>
<div>
<bar title="法律助手" left="bars" right="search" color="font-white" />
<carousel />
<navigation />
<ask-home />
<infer-home />
<legal-home />
<background />
</div>
</template>
<script>
import Background from "@/components/background/Background";
import Carousel from "@/components/carousel/Carousel";
import Bar from "@/components/bar/Bar";
import Navigation from "@/components/main/Navigation";
import AskHome from "@/components/main/ask/AskHome";
import InferHome from "@/components/main/infer/InferHome";
import LegalHome from "@/components/main/legal/LegalHome";
import {mapState} from 'vuex'
export default {
name: "Home",
components: {
LegalHome,
InferHome,
Navigation,
Background,
Carousel,
Bar,
AskHome
},
computed: {
...mapState(['currentTab'])
},
watch: {
currentTab() {
let metaThemeColor = document.querySelector("meta[name=theme-color]");
if(this.currentTab === 'Home') {
metaThemeColor.setAttribute("content", "#ffa947");
} else {
setTimeout(() => {
if(this.currentTab === 'Ask') {
metaThemeColor.setAttribute("content", "#12D8FA");
} else if(this.currentTab === 'Infer') {
metaThemeColor.setAttribute("content", "#3ba675");
}
}, 400);
}
}
}
}
</script>
<style>
* {
box-sizing: border-box!important;
}
</style>

@ -0,0 +1,30 @@
<template>
<div class="background">
<background-color :colors="setting.color"/>
</div>
</template>
<script>
import { mapState } from 'vuex'
import BackgroundColor from "@/components/background/BackgroundColor";
export default {
name: "Background",
components: {
BackgroundColor
},
computed: {
...mapState(['setting'])
}
}
</script>
<style scoped>
.background {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
}
</style>

@ -0,0 +1,33 @@
<template>
<div class="background-color"
:style="{ backgroundImage: gradientColor }"
></div>
</template>
<script>
export default {
name: "BackgroundColor",
props: {
colors: {
type: Array
}
},
computed: {
gradientColor () {
const colorBottom = `color-stop(30%, ${this.colors[0]})`;
const colorTop = `to(${this.colors[1]})`;
return `-webkit-gradient(linear, left bottom, left top, ${colorBottom}, ${colorTop})`
}
}
}
</script>
<style scoped>
.background-color {
position: absolute;
width: 100%;
height: 100%;
transition: opacity 0.5s ease;
opacity: 1;
}
</style>

@ -0,0 +1,63 @@
<template>
<div class="bar text-shadow" :class="[`${color}`]">
<span @click="$emit('left')">
<i :class="['fas', `fa-${left}`]"></i>
</span>
<span>{{ title }}</span>
<span @click="$emit('right')">
<i :class="['fas', `fa-${right}`]"></i>
</span>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
},
left: {
type: String,
default: ''
},
right: {
type: String,
default: ''
},
color: {
type: String,
default: 'font-white'
}
}
}
</script>
<style scoped>
.bar {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
height: 54px;
font-size: 18px;
z-index: 1;
padding: 0 15px;
transition-duration: 250ms;
}
span {
padding: 5px 5px;
}
.font-white {
color: #fefefe;
text-shadow: 2px 4px 6px rgba(0, 0, 0, 0.15);
}
.font-dark {
color: #37474f;
text-shadow: 2px 4px 6px rgba(0, 0, 0, 0.3);
}
</style>

@ -0,0 +1,45 @@
<template>
<div class="carousel">
<p class="heading-1">智能</p>
<p class="heading-2">法律助手</p>
<p class="heading-3">Smart Legal Assistant</p>
</div>
</template>
<script>
export default {
props: {
},
};
</script>
<style scoped>
.carousel {
display: flex;
padding: 0 40px;
height: 220px;
justify-content: flex-end;
flex-direction: column;
transition: all 0.5s ease;
color: #fefefe;
text-shadow: 2px 4px 5px rgba(0, 0, 0, 0.2);
}
.heading-1 {
font-size: 48px;
opacity: 95%;
font-weight: 200;
margin: 0;
}
.heading-2 {
font-size: 40px;
opacity: 95%;
font-weight: 300;
margin:0;
}
.heading-3 {
opacity: 90%;
font-size: 25px;
font-weight: 200;
margin: 0;
}
</style>

@ -0,0 +1,28 @@
<template>
<div class="ask-card">
</div>
</template>
<script>
export default {
name: "AskCard"
}
</script>
<style scoped>
.ask-card {
width: 100%;
height: 60px;
background-color: rgba(255, 255, 255, 0.80);
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
border-radius: 30px;
padding-top: 12px;
margin-top: 15px;
display: flex;
flex-direction: row;
justify-content: center;
transition-duration: 2s;
will-change: transform;
}
</style>

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "AskList"
}
</script>
<style scoped>
</style>

@ -0,0 +1,32 @@
<template>
<div class="navigation">
<!--通过tab控制跳往哪个子组件-->
<navigator-button tab="Ask" title="问答咨询" icon="far fa-comment"/>
<navigator-button tab="Infer" title="案情推断" icon="far fa-compass"/>
<navigator-button tab="Legal" title="文书查询" icon="fas fa-search"/>
</div>
</template>
<script>
import NavigatorButton from "@/components/main/NavigatorButton";
export default {
name: "Navigation",
components: {
NavigatorButton,
},
}
</script>
<style scoped>
.navigation {
width: 100%;
display: flex;
align-content: center;
padding: 0 40px;
margin-top: 25px;
justify-content: flex-start;
flex-wrap: wrap;
transition: all 0.5s ease;
color: #fefefe;
}
</style>

@ -0,0 +1,79 @@
<template>
<div class="button" @click="handleClick">
<i :class="[`${icon}`]" class="button-icon"></i>
<span class="button-title">{{ title }}</span>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
props: {
tab: {
type: String,
default: 'Ask'
},
icon: {
type: String,
default: 'comment'
},
title: {
type: String,
default: '问答咨询'
}
},
computed: {
...mapState(['selected', 'unselect', 'onAsk'])
},
methods: {
handleClick () {
const appRect = document.querySelector('#app').getBoundingClientRect();
const elRect = this.$el.getBoundingClientRect();
const rect = {};
const tab = this.tab;
rect.top = elRect.top - appRect.top;
rect.left = elRect.left - appRect.left;
rect.width = elRect.width;
rect.height = elRect.height;
rect.appWidth = appRect.width;
rect.appHeight = appRect.height;
this.$store.commit('selectTab', { rect });
this.$store.commit('setTab', tab)
}
}
}
</script>
<style scoped>
.button {
width: 100%;
height: 60px;
background-color: #f8f8f8;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
border-radius: 30px;
padding-top: 12px;
margin-top: 15px;
display: flex;
flex-direction: row;
justify-content: center;
transition-duration: 2s;
will-change: transform;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
}
.button:hover {
background-color: rgba(255, 255, 255, 0.87);
box-shadow: 5px 10px 10px rgba(0, 0, 0, 0.18);
}
.button-icon {
font-size: 30px;
color: #455a64;
margin-right: 15px;
margin-top: 2px;
margin-left: -25px;
}
.button-title {
font-size: 18px;
margin-top: 5px;
color: #37474f;
}
</style>

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "AskDetail"
}
</script>
<style scoped>
</style>

@ -0,0 +1,226 @@
<template>
<!--todo 问王灿这个动画 -->
<transition name="show" @enter="handleEnter" @leave="handleLeave">
<div id="ask-home" class="ask-home" v-if="selected&&(currentTab=='Ask')">
<bar id="app-bar" class="app-bar" :color="barColor" @left="unselectTab" left="arrow-left"/>
<div class="ask-content">
<div class="ask-heading">
<i class="fas fa-microphone-alt ask-icon"></i>
<search-bar class="search-bar" type="input" v-on:result="handleAskChange" mode="ask" />
<h1 class="ask-title">问答咨询</h1>
</div>
<div id="ask-list" class="ask-list">
<home-card class="home-card" v-for="(ask,index) in asks" :key="index" :theId="index" :title="ask.questionName" :content="ask.answers" />
</div>
<div class="ask-footer">
</div>
</div>
</div>
</transition>
</template>
<script>
import {mapState, mapMutations} from 'vuex'
import Bar from "@/components/bar/Bar";
import SearchBar from "@/components/utils/SearchBar";
import HomeCard from "@/components/utils/HomeCard";
export default {
name: "AskHome",
components: {
HomeCard,
Bar,
SearchBar
},
data: function () {
return {
barColor: 'font-white',
asks: null,
}
},
computed: {
// vuex使
...mapState(['selected', 'unselect', 'currentTab'])
},
watch: {
currentTab() {
if(this.currentTab === "Ask") {
window.addEventListener('scroll', this.handleScroll, true);
} else {
window.removeEventListener('scroll', this.handleScroll, true);
}
}
},
methods: {
...mapMutations(['unselectTab']),
handleEnter(el) {
Object.assign(el.style, {
top: `${this.selected.rect.top}px`,
left: `${this.selected.rect.left}px`,
width: `${this.selected.rect.width}px`,
height: `${this.selected.rect.height}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.selected.rect.appWidth}px`,
height: `${this.selected.rect.appHeight}px`
})
}, 0)
},
handleLeave(el) {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.unselect.rect.appWidth}px`,
height: `${this.unselect.rect.appHeight}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: `${this.unselect.rect.top}px`,
left: `${this.unselect.rect.left}px`,
width: `${this.unselect.rect.width}px`,
height: `${this.unselect.rect.height}px`
})
}, 0)
},
handleScroll () {
const askHome = document.getElementById("ask-home");
if(askHome) {
if(askHome.scrollTop > 275) {
this.barColor = 'font-dark';
} else if(askHome.scrollTop < 275) {
this.barColor = 'font-white';
}
}
},
handleAskChange (asks) {
this.asks = asks;
}
},
}
</script>
<style lang="scss" scoped>
.ask-home {
position: fixed;
border-radius: 0;
color: #444;
background-color: #f8f8f8;
padding: 0 12px;
will-change: top, left, width, height;
overflow: auto;
}
.ask-home::-webkit-scrollbar {
display: none;
}
.app-bar {
width: 100%;
position: fixed;
}
.ask-heading {
width: calc(100% + 60px);
height: 349px;
color: #fff;
background: #1FA2FF;
text-align: center;
text-shadow: 0 5px 8px rgba(0, 0, 0, 0.1);
background: -webkit-linear-gradient(to top, #1FA2FF, #12D8FA);
background: linear-gradient(to top, #1FA2FF, #12D8FA);
margin-top: -54px;
margin-left: -30px;
margin-right: -30px;
padding: 30px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column-reverse;
}
.ask-heading h1 {
font-weight: 400;
}
.search-bar {
margin-top: 10px;
margin-bottom: 20px;
}
.ask-icon {
font-size: 30px;
color: #fafafa;
}
.home-card {
margin-bottom: 12px;
}
.home-card:first-of-type {
margin-top: 20px;
}
.ask-footer {
width: 100%;
height: 60px;
padding-top: 15px;
padding-bottom: 20px;
font-size: 15px;
color: #37474f;
text-align: center;
}
.show-enter-to,
.show-leave {
border-radius: 0;
.ask-home {
padding: 0 20px;
}
.ask-home,
.app-bar,
.ask-content {
opacity: 1;
transform: translate3d(0, 0px, 0);
}
.ask-title {
font-size: 2rem;
}
}
.show-leave-to,
.show-enter {
border-radius: 30px;
.ask-home {
padding: 0;
}
.ask-home,
.app-bar,
.ask-content{
opacity: 0;
transform: translate3d(0, -40px, 0);
}
.ask-title {
font-size: 1.5rem;
}
}
.show-enter-active,
.show-leave-active {
transition: all 0.5s ease;
.ask-home,
.app-bar,
.ask-content,
.ask-title {
transition: all 0.5s ease;
}
}
</style>

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "InferDetail"
}
</script>
<style scoped>
</style>

@ -0,0 +1,224 @@
<template>
<transition name="show" @enter="handleEnter" @leave="handleLeave">
<div class="infer-home" v-if="selected&&(currentTab=='Infer')">
<bar id="app-bar" class="app-bar" :color="barColor" @left="unselectTab" left="arrow-left"/>
<div class="infer-content">
<div class="infer-heading">
<i v-if="loading" class="fas fa-5x fa-spin fa-spinner infer-icon"></i>
<i v-else class="fas fa-microphone-alt infer-icon"></i>
<search-bar class="search-bar" type="area" v-on:result="handleInferResult" mode="infer" v-on:loading="handleLoading" />
<h1 class="infer-title">案情推断</h1><br>
</div>
<div id="infer-list" class="infer-list">
<home-card class="home-card" v-for="(infer, index) in data" :theId="index" :key="index" :title="title(index)" :content="infer" />
</div>
<div class="infer-footer">
</div>
</div>
</div>
</transition>
</template>
<script>
import {mapState, mapMutations} from 'vuex';
import Bar from "@/components/bar/Bar";
import SearchBar from "@/components/utils/SearchBar";
import HomeCard from "@/components/utils/HomeCard";
export default {
name: "InferHome",
components: {
HomeCard,
Bar,
SearchBar
},
data: function () {
return {
barColor: 'font-white',
data: null,
crime: null,
loading: false
}
},
computed: {
...mapState(['selected', 'unselect', 'currentTab']),
},
methods: {
...mapMutations(['unselectTab']),
handleEnter(el) {
Object.assign(el.style, {
top: `${this.selected.rect.top}px`,
left: `${this.selected.rect.left}px`,
width: `${this.selected.rect.width}px`,
height: `${this.selected.rect.height}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.selected.rect.appWidth}px`,
height: `${this.selected.rect.appHeight}px`
})
}, 0)
},
handleLeave(el) {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.unselect.rect.appWidth}px`,
height: `${this.unselect.rect.appHeight}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: `${this.unselect.rect.top}px`,
left: `${this.unselect.rect.left}px`,
width: `${this.unselect.rect.width}px`,
height: `${this.unselect.rect.height}px`
})
}, 0)
},
handleLoading(data) {
this.loading = data;
},
handleInferResult(data) {
delete data.id;
this.crime = data.crimeName;
delete data.crimeName;
this.data = data;
this.loading = false;
},
title(index) {
if(index==='concept') {
return '罪名解释'
} else if(index==='feature') {
return '罪名特征'
} else if(index==='rending') {
return '定罪条件'
} else if(index==='punish') {
return '量刑区间'
} else if(index==='laws') {
return '有关法条'
}
return undefined;
}
}
}
</script>
<style lang="scss" scoped>
.infer-home {
position: fixed;
border-radius: 0;
color: #444;
background-color: #f8f8f8;
padding: 0 12px;
will-change: top, left, width, height;
overflow: auto;
}
.infer-home::-webkit-scrollbar {
display: none;
}
.app-bar {
width: 100%;
position: fixed;
}
.infer-heading {
width: calc(100% + 60px);
height: 450px;
color: #fff;
background: #2c7d59;
text-align: center;
text-shadow: 0 5px 8px rgba(0, 0, 0, 0.1);
background: -webkit-linear-gradient(to top, #2c7d59, #3ba675);
background: linear-gradient(to top, #2c7d59, #3ba675);
margin-top: -54px;
margin-left: -30px;
margin-right: -30px;
padding: 30px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column-reverse;
}
.infer-heading h1 {
font-weight: 400;
}
.search-bar {
margin-top: 15px;
margin-bottom: 45px;
}
.infer-icon {
font-size: 35px;
color: #fafafa;
margin-bottom: 30px;
}
.home-card {
margin-bottom: 12px;
}
.home-card:first-of-type {
margin-top: 20px;
}
.infer-footer {
width: 100%;
height: 60px;
padding-top: 15px;
padding-bottom: 20px;
font-size: 15px;
color: #37474f;
text-align: center;
}
.show-enter-to,
.show-leave {
border-radius: 0;
.infer-home {
padding: 0 20px;
}
.infer-home,
.app-bar,
.infer-heading,
.infer-content {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.show-leave-to,
.show-enter {
border-radius: 30px;
.infer-home {
padding: 0;
}
.infer-home,
.app-bar,
.infer-heading,
.infer-content{
opacity: 0;
transform: translate3d(0, -40px, 0);
}
}
.show-enter-active,
.show-leave-active {
transition: all 0.5s ease;
.infer-home,
.app-bar,
.infer-heading,
.infer-content{
transition: all 0.5s ease;
}
}
</style>

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "LegalDetail"
}
</script>
<style scoped>
</style>

@ -0,0 +1,211 @@
<template>
<transition name="show" @enter="handleEnter" @leave="handleLeave">
<div class="legal-home" v-if="selected&&(currentTab=='Legal')">
<bar id="app-bar" class="app-bar" :color="barColor" @left="unselectTab" left="arrow-left"/>
<div class="legal-content">
<div class="legal-heading">
<search-bar class="search-bar" type="area" v-on:result="handleInferResult" mode="legal" v-on:loading="handleLoading"/>
<h1 class="legal-title">查询相似文书</h1>
</div>
<div id="legal-list" class="legal-list">
<home-card class="home-card" v-for="(theCase,index) in data" :theId="index" :key="index" :title="theCase.title" :content="theCase"/>
</div>
<div class="legal-footer"></div>
</div>
</div>
</transition>
</template>
<script>
import {mapState, mapMutations} from 'vuex'
import Bar from "@/components/bar/Bar";
import HomeCard from "@/components/utils/HomeCard";
import SearchBar from "@/components/utils/SearchBar";
export default {
name: "LegalHome",
components: {
HomeCard,
Bar,
SearchBar
},
data: function () {
return {
barColor: 'font-white',
data: {},
loading: false
}
},
computed: {
...mapState(['selected', 'unselect', 'currentTab'])
},
methods: {
...mapMutations(['unselectTab']),
handleInferResult(data) {
this.data=data;
},
handleLoading(loading) {
this.loading=loading;
},
handleEnter(el) {
Object.assign(el.style, {
top: `${this.selected.rect.top}px`,
left: `${this.selected.rect.left}px`,
width: `${this.selected.rect.width}px`,
height: `${this.selected.rect.height}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.selected.rect.appWidth}px`,
height: `${this.selected.rect.appHeight}px`
})
}, 0)
},
handleLeave(el) {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.unselect.rect.appWidth}px`,
height: `${this.unselect.rect.appHeight}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: `${this.unselect.rect.top}px`,
left: `${this.unselect.rect.left}px`,
width: `${this.unselect.rect.width}px`,
height: `${this.unselect.rect.height}px`
})
}, 0)
}
}
}
</script>
<style lang="scss" scoped>
.legal-home {
position: fixed;
border-radius: 0;
color: #444;
background-color: #f8f8f8;
padding: 0 12px;
will-change: top, left, width, height;
overflow: auto;
}
.legal-home::-webkit-scrollbar {
display: none;
}
.app-bar {
width: 100%;
position: fixed;
}
.upload {
margin: 20px 0;
}
.legal-heading {
width: calc(100% + 60px);
height: 350px;
color: #fff;
background: #6e18e1;
text-align: center;
text-shadow: 0 5px 8px rgba(0, 0, 0, 0.1);
background: -webkit-linear-gradient(to top, #4A00E0, #8E2DE2);
background: linear-gradient(to top, #4A00E0, #8E2DE2);
margin-top: -54px;
margin-left: -30px;
margin-right: -30px;
padding: 30px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column-reverse;
}
.upload-form {
display: flex;
flex-direction: column-reverse;
}
.legal-heading h1 {
font-weight: 400;
}
.search-bar {
margin-top: 15px;
margin-bottom: 45px;
}
.legal-icon {
font-size: 30px;
color: #fafafa;
margin-bottom: 5px;
}
.home-card {
margin-bottom: 12px;
}
.home-card:first-of-type {
margin-top: 20px;
}
.legal-footer {
width: 100%;
height: 60px;
padding-top: 15px;
padding-bottom: 20px;
font-size: 15px;
color: #37474f;
text-align: center;
}
.show-enter-to,
.show-leave {
border-radius: 0;
.legal-home {
padding: 0 20px;
}
.legal-home,
.app-bar,
.legal-heading,
.legal-content {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.show-leave-to,
.show-enter {
border-radius: 30px;
.legal-home {
padding: 0;
}
.legal-home,
.app-bar,
.legal-heading,
.legal-content {
opacity: 0;
transform: translate3d(0, -40px, 0);
}
}
.show-enter-active,
.show-leave-active {
transition: all 0.5s ease;
.legal-home,
.app-bar,
.legal-heading,
.legal-content {
transition: all 0.5s ease;
}
}
</style>

@ -0,0 +1,207 @@
<template>
<transition name="show" @enter="handleEnter" @leave="handleLeave">
<div class="legal-home" v-if="selected&&(currentTab=='Legal')">
<bar id="app-bar" class="app-bar" :color="barColor" @left="unselectTab" left="arrow-left"/>
<div class="legal-content">
<div class="legal-heading">
<form class="upload-form">
<a href="#"><i class="fas fa-upload legal-icon"></i></a>
<Upload class="upload" />
</form>
<h1 class="legal-title">查询相似文书</h1>
</div>
<div id="legal-list" class="legal-list">
<home-card class="home-card" />
</div>
<div class="legal-footer">
</div>
</div>
</div>
</transition>
</template>
<script>
import {mapState, mapMutations} from 'vuex'
import Bar from "@/components/bar/Bar";
import HomeCard from "@/components/utils/HomeCard";
import Upload from "@/components/utils/Upload";
export default {
name: "LegalHome",
components: {
HomeCard,
Bar,
Upload
},
data: function () {
return {
barColor: 'font-white',
}
},
computed: {
...mapState(['selected', 'unselect', 'currentTab'])
},
methods: {
...mapMutations(['unselectTab']),
handleEnter(el) {
Object.assign(el.style, {
top: `${this.selected.rect.top}px`,
left: `${this.selected.rect.left}px`,
width: `${this.selected.rect.width}px`,
height: `${this.selected.rect.height}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.selected.rect.appWidth}px`,
height: `${this.selected.rect.appHeight}px`
})
}, 0)
},
handleLeave(el) {
Object.assign(el.style, {
top: 0,
left: 0,
width: `${this.unselect.rect.appWidth}px`,
height: `${this.unselect.rect.appHeight}px`
});
setTimeout(() => {
Object.assign(el.style, {
top: `${this.unselect.rect.top}px`,
left: `${this.unselect.rect.left}px`,
width: `${this.unselect.rect.width}px`,
height: `${this.unselect.rect.height}px`
})
}, 0)
}
}
}
</script>
<style lang="scss" scoped>
.legal-home {
position: fixed;
border-radius: 0;
color: #444;
background-color: #f8f8f8;
padding: 0 12px;
will-change: top, left, width, height;
overflow: auto;
}
.legal-home::-webkit-scrollbar {
display: none;
}
.app-bar {
width: 100%;
position: fixed;
}
.upload {
margin: 20px 0;
}
.legal-heading {
width: calc(100% + 60px);
height: 350px;
color: #fff;
background: #6e18e1;
text-align: center;
text-shadow: 0 5px 8px rgba(0, 0, 0, 0.1);
background: -webkit-linear-gradient(to top, #4A00E0, #8E2DE2);
background: linear-gradient(to top, #4A00E0, #8E2DE2);
margin-top: -54px;
margin-left: -30px;
margin-right: -30px;
padding: 30px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
display: flex;
flex-direction: column-reverse;
}
.upload-form {
display: flex;
flex-direction: column-reverse;
}
.legal-heading h1 {
font-weight: 400;
}
.search-bar {
margin-top: 15px;
margin-bottom: 45px;
}
.legal-icon {
font-size: 30px;
color: #fafafa;
margin-bottom: 5px;
}
.home-card {
margin-bottom: 12px;
}
.home-card:first-of-type {
margin-top: 20px;
}
.legal-footer {
width: 100%;
height: 60px;
padding-top: 15px;
padding-bottom: 20px;
font-size: 15px;
color: #37474f;
text-align: center;
}
.show-enter-to,
.show-leave {
border-radius: 0;
.legal-home {
padding: 0 20px;
}
.legal-home,
.app-bar,
.legal-heading,
.legal-content {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.show-leave-to,
.show-enter {
border-radius: 30px;
.legal-home {
padding: 0;
}
.legal-home,
.app-bar,
.legal-heading,
.legal-content{
opacity: 0;
transform: translate3d(0, -40px, 0);
}
}
.show-enter-active,
.show-leave-active {
transition: all 0.5s ease;
.legal-home,
.app-bar,
.legal-heading,
.legal-content{
transition: all 0.5s ease;
}
}
</style>

@ -0,0 +1,120 @@
<template>
<div class="home-card" :id="'home-card'+theId" style="position: relative" >
<div class="title-container">
<p class="card-title">{{ title }}</p>
</div>
<div :id="theId" class="content-container">
<p v-for="(text, index) in content" :key="index" class="card-content">{{ text }}</p>
</div>
<div id="unfold-button" @click="handleUnfold"><i v-if="arror" :id="'arror'+theId" :class="{'arror-down':unfold}" class="fa fa-2x fa-angle-down"></i> </div>
</div>
</template>
<script>
export default {
name: "HomeCard",
props: {
title: {
type: String,
default: 'Ops刷新一下试试吧'
},
content: {
type: Array,
},
theId:{
type:Number
}
},
data() {
return {
unfold: false,
arror: true
}
},
watch:{
title(){
}
},
mounted() {
// eslint-disable-next-line no-console
let temp = document.getElementById(this.theId).scrollHeight + 50;
if(temp < 260) {
this.arror = false;
}
},
methods: {
handleUnfold: function () {
if(!this.unfold){
let temp = document.getElementById(this.theId).scrollHeight + 50;
if(temp > 1000) {
document.getElementById("home-card"+this.theId).style.transition = '1000ms';
document.getElementById("arror"+this.theId).style.transitionDuration = '1000ms';
}
let tempString = String(temp);
document.getElementById("home-card"+this.theId).style.maxHeight=tempString + 'px';
} else {
document.getElementById("home-card"+this.theId).style.maxHeight='260px';
}
this.unfold = !this.unfold;
}
}
}
</script>
<style scoped>
#arror {
transition-duration: 500ms;
}
.arror-down {
transform:rotate(180deg);
-ms-transform:rotate(180deg); /* IE 9 */
-moz-transform:rotate(180deg); /* Firefox */
-webkit-transform:rotate(180deg); /* Safari 和 Chrome */
-o-transform:rotate(180deg);
}
#unfold-button {
position: absolute;
bottom: 0;
width: 100%;
display: flex;
justify-content: center;
background: rgba(254, 254, 254, 0.16);
background: -webkit-linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 254, 255, 0.98));
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(254, 255, 255, 0.98));
}
.home-card {
border-radius: 5px;
background-color: #fff;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.06);
max-height: 260px;
transition: 500ms;
overflow: hidden;
padding: 5px 0;
}
.title-container {
padding: 5px 15px;
border: #333 1px;
}
.card-title {
font-size: 16px;
margin-top: 10px;
margin-bottom: 0;
}
.content-container {
padding: 5px 15px 15px 15px;
text-indent: 1em;
}
.card-content {
margin: 5px 0;
font-size: 14px;
}
</style>

@ -0,0 +1,288 @@
<template>
<div class="search-bar">
<label style="display: none" for="search-bar-area"></label>
<label style="display: none" for="search-bar-input"></label>
<div id="search-bar-container">
<!--searchbar是复用组件-->
<!--根据不同的type类型选择显示下拉框还是选择文本域-->
<textarea v-if="type === 'area'" id="search-bar-area" v-model="text"></textarea>
<div v-if="type === 'input'">
<input id="search-bar-input" type="text" v-model="input"/>
<div class="search-bar-pop">
<!--下拉动画-->
<transition-group name="show" v-if="hintShow&&!requestFlag">
<div v-for="(text, index) in hint" :key="index" class="search-bar-hint" @click="fillHint(text)">{{ text }}</div>
</transition-group>
</div>
</div>
<div id="search-icon" :style="{ color: color }">
<a class="search-button" @click="getFullResult">
<i class="fas fa-search"></i>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: "SearchBar",
// html使
props: {
type: {
type: String,
default: 'area'
},
color: {
type: String,
default: '#455a64'
},
mode: {
type: String,
}
},
data() {
return {
oldInput: null,
input: null,
text: null,
hintShow: true,
hint: null,
requestFlag: false
}
},
mounted() {
// , , ,
if(this.type==='input'&&this.mode==='ask') {
this.inputListener();
}
},
methods: {
inputListener:function () {
const that = this;
this.pointer = setInterval(function () {
if(that.requestFlag) {
clearInterval(that.pointer);
}
if((that.input === null)&&(that.oldInput === null)) {
return;
} else if((that.input !== null)&&(that.oldInput === null)) {
that.oldInput = that.input;
} else if(that.input === that.oldInput) {
return;
}
that.oldInput = that.input;
if (that.input==null)
return ;
that.$http.get("http://api.zhuchangwu.com/api-consumer/question/promptSearch", {
params: {
content: that.input
}
}).then((res)=> {
that.hint = res.data.data;
// eslint-disable-next-line no-console
console.log(that.hint);
// eslint-disable-next-line no-console
console.log("send");
//
if (!that.hintShow)
that.hintShow=true;
});
}, 500)
},
fillHint: function (text) {
this.input = text;
// todo
//this.requestFlag = false;
this.hint = null;
this.getFullResult();
},
//
getFullResult: function () {
clearInterval(this.pointer);
if(this.mode==='ask') {
this.hint=null;
this.$http.get("http://api.zhuchangwu.com/api-consumer/question/preciseSearch", {
params: {
title: this.input
}
}).then((res)=> {
// result
this.$emit('result', res.data.data);
//
this.hintShow=false;
this.requestFlag = true;
});
// ,
this.inputListener();
} else if(this.mode==='infer') {
this.$emit('loading', true);
this.axios.post("http://api.zhuchangwu.com/api-consumer/py/intelligenceAnalyze", {
content: this.text
}).then((res)=> {
if (res.data.data===null){
//
this.$emit('result', res.data.data);
}
this.$emit('result', res.data.data);
});
}else if (this.mode==='legal'){
//
this.$emit('loading', true);
this.axios.post("http://api.zhuchangwu.com/api-consumer/checking/describe",{
describe: this.text
}).then((res)=>{
this.$emit('result',res.data.data)
})
}
}
}
}
</script>
<style lang="scss" scoped>
.search-bar {
width: 100%;
height: 40px;
border-radius: 20px;
box-shadow: 5px 10px 10px rgba(0, 0, 0, 0.1);
z-index: 100;
}
#search-bar-area::-webkit-scrollbar {
display: none;
}
#search-bar-area {
box-sizing: border-box;
width: 100%;
height: 40px;
overflow-y: auto;
color: #222;
font-weight: 300;
font-family: "Microsoft YaHei", sans-serif;
background-color: #fff;
box-shadow: inset 0 -5px 5px rgba(0, 0, 0, 0.1);
border-radius: 20px;
padding: 10px 20px 10px 20px;
font-size: 18px;
border: none;
outline: none;
transition-property: height;
transition-duration: 400ms;
resize:none;
}
#search-bar-input {
box-sizing: border-box;
width: 100%;
height: 40px;
overflow-y: auto;
color: #222;
font-weight: 300;
font-family: "Microsoft YaHei", sans-serif;
border-radius: 20px;
padding: 10px 45px 10px 15px;
font-size: 18px;
border: none;
outline: none;
transition-duration: 200ms;
}
#search-bar-area:focus {
height: 300px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.1);
}
#search-bar-container {
position: relative;
}
#search-icon {
position: absolute;
bottom: 0;
right: 0;
height: 40px;
width: 50px;
padding-top: 2px;
padding-bottom: 3px;
padding-right: 5px;
font-size: 24px;
text-shadow: 2px 3px 3px rgba(0, 0, 0, 0.1);
transition-duration: 250ms;
}
.search-button:hover {
color: #37474f;
text-shadow: 2px 1px 1px rgba(0, 0, 0, 0.1);
}
.search-button:active {
color: #263238;
text-shadow: 0 0 6px rgba(0, 0, 0, 0.25);
}
.search-bar-pop {
min-height: 40px;
width: 100%;
position: absolute;
background-color: #fff;
top: 0;
z-index: -1;
border-radius: 20px;
box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.1);
transition-property: height;
transition-duration: 300ms;
padding: 40px 0 0 0;
color: #444;
text-align: left;
display: flex;
flex-direction: column;
overflow: hidden;
}
.search-bar-hint {
height: 35px;
overflow: hidden;
font-size: 14px;
line-height: 30px;
padding: 0 10px 5px 15px;
transition-duration: 100ms;
background-color: #fbfbfb;
}
.search-bar-hint:first-of-type {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.search-bar-hint:hover {
background-color: rgba(31, 162, 255, 0.15);
}
.show-enter-to,
.show-leave {
.search-bar-hint {
opacity: 1;
transform: translate3d(0, 0px, 0);
}
}
.show-leave-to,
.show-enter {
.search-bar-hint {
opacity: 1;
transform: translate3d(0, 20px, 0);
}
}
.show-enter-active,
.show-leave-active {
transition: all 0.2s ease;
.search-bar-hint {
transition: all 0.2s ease;
}
}
</style>

@ -0,0 +1,92 @@
<template>
<div class="upload">
<label class="file" id="fileLabel">
<input type="file" id="file">
<span class="file-custom">123</span>
</label>
</div>
</template>
<script>
export default {
name : "upload",
methods: {
uploadFunc : function (document) {
let input = document.getElementById("file");
let label = document.getElementById("fileLabel");
input.addEventListener( 'change', function( e )
{
let fileName = '';
fileName = e.target.value.split( '\\' ).pop();
label.querySelector( 'span' ).innerHTML = fileName;
});
// Firefox bug fix
input.addEventListener( 'focus', function(){ input.classList.add( 'has-focus' ); });
input.addEventListener( 'blur', function(){ input.classList.remove( 'has-focus' ); });
}
},
mounted() {
this.uploadFunc(document);
}
}
</script>
<style scoped>
.file {
position: relative;
display: inline-block;
cursor: pointer;
height: 40px;
box-sizing: border-box;
}
.file input {
min-width: 14rem;
margin: 0;
filter: alpha(opacity=0);
opacity: 0;
}
.file-custom {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 5;
height: 40px;
padding: .5rem 1rem;
line-height: 1.5;
color: #555;
background-color: #fff;
border: .075rem solid #ddd;
border-radius: .25rem;
box-shadow: inset 0 .2rem .4rem rgba(0,0,0,.05);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: left;
}
.file-custom:before {
position: absolute;
top: -.075rem;
right: -.075rem;
bottom: -.075rem;
z-index: 6;
display: block;
content: "选择文书";
height: 20px;
padding: .5rem 1rem;
line-height: 1.5;
color: #555;
background-color: #eee;
border: .075rem solid #ddd;
border-radius: 0 .25rem .25rem 0;
}
/* Focus */
.file input:focus ~ .file-custom {
box-shadow: 0 0 0 .075rem #fff, 0 0 0 .2rem #0074d9;
}
</style>

@ -0,0 +1,742 @@
<template>
<div class="user-center">
<h3>个人中心</h3>
<!-- 个人信息卡片 -->
<el-card class="user-info-card">
<div class="user-avatar">
<el-avatar :size="100" :src="userInfo.avatar"></el-avatar>
<el-upload
class="avatar-uploader"
action="/api/upload"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
accept=".jpg,.jpeg,.png">
<el-button size="small" type="primary">更换头像</el-button>
</el-upload>
</div>
<div class="user-detail">
<p><span>用户名:</span> {{userInfo.username}}</p>
<p><span>角色:</span> {{userInfo.role}}</p>
<p><span>邮箱:</span> {{userInfo.email}}</p>
<p><span>手机号:</span> {{userInfo.phone}}</p>
<p><span>注册时间:</span> {{userInfo.registerTime}}</p>
<p><span>最后登录:</span> {{userInfo.lastLogin}}</p>
<div class="action-buttons">
<el-button type="primary" size="small" @click="editUserInfo"></el-button>
<el-button type="warning" size="small" @click="changePassword"></el-button>
</div>
</div>
</el-card>
<!-- 数据统计卡片 -->
<div class="data-cards">
<el-row :gutter="20">
<el-col :span="6">
<el-card shadow="hover" @click.native="showOrderList" class="data-card">
<div class="data-item">
<i class="el-icon-s-order"></i>
<div class="data-num">{{statistics.orderCount}}</div>
<div class="data-title">订单总数</div>
<div class="data-trend" v-if="statistics.orderTrend > 0">
<i class="el-icon-top" style="color: #67C23A"></i>
<span>{{statistics.orderTrend}}%</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" @click.native="showFinanceDetails" class="data-card">
<div class="data-item">
<i class="el-icon-money"></i>
<div class="data-num">¥{{statistics.totalAmount}}</div>
<div class="data-title">交易总额</div>
<div class="data-trend" v-if="statistics.amountTrend > 0">
<i class="el-icon-top" style="color: #67C23A"></i>
<span>{{statistics.amountTrend}}%</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" @click.native="showProductList" class="data-card">
<div class="data-item">
<i class="el-icon-goods"></i>
<div class="data-num">{{statistics.productCount}}</div>
<div class="data-title">商品数量</div>
<div class="data-trend" v-if="statistics.productTrend > 0">
<i class="el-icon-top" style="color: #67C23A"></i>
<span>{{statistics.productTrend}}%</span>
</div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover" @click.native="showCustomerList" class="data-card">
<div class="data-item">
<i class="el-icon-user"></i>
<div class="data-num">{{statistics.customerCount}}</div>
<div class="data-title">客户数量</div>
<div class="data-trend" v-if="statistics.customerTrend > 0">
<i class="el-icon-top" style="color: #67C23A"></i>
<span>{{statistics.customerTrend}}%</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
<!-- 图表展示区域 -->
<div class="charts-container">
<el-row :gutter="20">
<el-col :span="12">
<el-card>
<div slot="header" class="chart-header">
<span>销售趋势分析</span>
<div class="chart-controls">
<el-date-picker
v-model="dateRange"
type="daterange"
size="small"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleDateRangeChange">
</el-date-picker>
<el-radio-group v-model="chartTimeRange" size="small" @change="handleTimeRangeChange">
<el-radio-button label="week"></el-radio-button>
<el-radio-button label="month"></el-radio-button>
<el-radio-button label="quarter"></el-radio-button>
<el-radio-button label="year"></el-radio-button>
</el-radio-group>
</div>
</div>
<div id="line" style="height: 400px"></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<div slot="header" class="chart-header">
<span>商品类别分布</span>
<div class="chart-controls">
<el-select v-model="selectedCategory" size="small" placeholder="选择类别" @change="handleCategoryChange">
<el-option
v-for="item in categories"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button size="small" type="primary" icon="el-icon-refresh" @click="refreshChartData"></el-button>
</div>
</div>
<div id="pie" style="height: 400px"></div>
</el-card>
</el-col>
</el-row>
</div>
<!-- 活动日历 -->
<el-card class="calendar-card">
<div slot="header">
<span>活动日历</span>
<el-button style="float: right" type="text" @click="addEvent"></el-button>
</div>
<el-calendar v-model="currentDate">
<template slot="dateCell" slot-scope="{date, data}">
<div class="calendar-cell">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split('-').slice(2).join('') }}
</p>
<div v-if="hasEvent(date)" class="event-dot"></div>
</div>
</template>
</el-calendar>
</el-card>
<!-- 修改密码对话框 -->
<el-dialog title="修改密码" :visible.sync="passwordDialogVisible" width="400px">
<el-form :model="passwordForm" :rules="passwordRules" ref="passwordForm" label-width="100px">
<el-form-item label="原密码" prop="oldPassword">
<el-input v-model="passwordForm.oldPassword" type="password" show-password></el-input>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="passwordForm.newPassword" type="password" show-password></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="passwordForm.confirmPassword" type="password" show-password></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="passwordDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitPasswordChange"></el-button>
</span>
</el-dialog>
<!-- 编辑用户信息对话框 -->
<el-dialog title="编辑个人资料" :visible.sync="userInfoDialogVisible" width="500px">
<el-form :model="editForm" :rules="rules" ref="editForm" label-width="100px">
<el-form-item label="用户名" prop="username">
<el-input v-model="editForm.username"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="editForm.email">
<template slot="append">
<el-button @click="sendVerificationCode"></el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="验证码" prop="verificationCode" v-if="showVerificationCode">
<el-input v-model="editForm.verificationCode" maxlength="6"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="editForm.phone"></el-input>
</el-form-item>
<el-form-item label="地址" prop="address">
<el-cascader
v-model="editForm.address"
:options="addressOptions"
:props="{ expandTrigger: 'hover' }"
@change="handleAddressChange">
</el-cascader>
</el-form-item>
<el-form-item label="详细地址" prop="detailAddress">
<el-input v-model="editForm.detailAddress" type="textarea"></el-input>
</el-form-item>
<el-form-item label="简介" prop="bio">
<el-input type="textarea" v-model="editForm.bio" :rows="4"></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="userInfoDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitUserInfo" :loading="submitLoading">确定</el-button>
</span>
</el-dialog>
<!-- 添加活动对话框 -->
<el-dialog title="添加活动" :visible.sync="eventDialogVisible" width="400px">
<el-form :model="eventForm" :rules="eventRules" ref="eventForm" label-width="80px">
<el-form-item label="活动名称" prop="title">
<el-input v-model="eventForm.title"></el-input>
</el-form-item>
<el-form-item label="活动日期" prop="date">
<el-date-picker v-model="eventForm.date" type="date" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="活动描述" prop="description">
<el-input type="textarea" v-model="eventForm.description"></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="eventDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitEvent"></el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import pdf from "vue-pdf";
import { debounce } from 'lodash';
var loadingTask = pdf.createLoadingTask("./gf.pdf");
export default {
data() {
const validateConfirmPassword = (rule, value, callback) => {
if (value !== this.passwordForm.newPassword) {
callback(new Error('两次输入的密码不一致'));
} else {
callback();
}
};
return {
dialogVisible: false,
src: loadingTask,
currentPage: 1,
numPages: 1,
isFullscreen: false,
userInfoDialogVisible: false,
passwordDialogVisible: false,
eventDialogVisible: false,
tableLoading: false,
chartTimeRange: 'month',
submitLoading: false,
showVerificationCode: false,
dateRange: [],
selectedCategory: '',
currentDate: new Date(),
categories: [
{ value: 'all', label: '全部' },
{ value: 'food', label: '食品' },
{ value: 'clothing', label: '服装' },
{ value: 'electronics', label: '电子' }
],
addressOptions: [], //
events: [], //
eventForm: {
title: '',
date: '',
description: ''
},
eventRules: {
title: [
{ required: true, message: '请输入活动名称', trigger: 'blur' }
],
date: [
{ required: true, message: '请选择活动日期', trigger: 'change' }
],
description: [
{ required: true, message: '请输入活动描述', trigger: 'blur' }
]
},
passwordForm: {
oldPassword: '',
newPassword: '',
confirmPassword: ''
},
passwordRules: {
oldPassword: [
{ required: true, message: '请输入原密码', trigger: 'blur' }
],
newPassword: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{ min: 6, message: '密码长度不能小于6位', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '请确认新密码', trigger: 'blur' },
{ validator: validateConfirmPassword, trigger: 'blur' }
]
},
editForm: {
username: '',
email: '',
phone: '',
address: [],
detailAddress: '',
bio: '',
verificationCode: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
],
address: [
{ required: true, message: '请选择地址', trigger: 'change' }
],
detailAddress: [
{ required: true, message: '请输入详细地址', trigger: 'blur' }
],
bio: [
{ required: true, message: '请输入简介', trigger: 'blur' },
{ min: 10, max: 200, message: '长度在 10 到 200 个字符', trigger: 'blur' }
],
verificationCode: [
{ required: true, message: '请输入验证码', trigger: 'blur' },
{ len: 6, message: '验证码长度应为6位', trigger: 'blur' }
]
},
userInfo: {
username: '管理员',
role: '超级管理员',
avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
email: 'admin@example.com',
phone: '13800138000',
registerTime: '2023-01-01',
lastLogin: '2023-06-20 10:30:00'
},
statistics: {
orderCount: 1580,
orderTrend: 12.5,
totalAmount: '156,789.00',
amountTrend: 8.3,
productCount: 268,
productTrend: 5.2,
customerCount: 1200,
customerTrend: 15.8
},
echartData:{
color:['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399'],
water:[],
categories: ['食品', '服装', '电子', '家居', '其他'],
values: [30, 25, 20, 15, 10],
monthlyData: {
sales: [2300, 2800, 3200, 2900, 3500, 3800, 4200, 4500, 4800, 5200, 5500, 6000],
orders: [180, 220, 260, 240, 280, 300, 340, 360, 400, 420, 460, 500]
}
}
};
},
computed: {
hasEvent() {
return (date) => {
return this.events.some(event => {
return new Date(event.date).toDateString() === new Date(date).toDateString();
});
};
}
},
components: {
pdf,
},
created() {
this.handleSearch = debounce(this.handleSearch, 300);
this.loadAddressOptions();
},
mounted() {
this.src.promise.then((pdf) => {
this.numPages = pdf.numPages;
});
this.initCharts();
this.loadUserData();
},
methods: {
addEvent() {
this.eventDialogVisible = true;
this.$nextTick(() => {
this.$refs.eventForm && this.$refs.eventForm.resetFields();
});
},
submitEvent() {
this.$refs.eventForm.validate(valid => {
if (valid) {
this.events.push({...this.eventForm});
this.$message.success('活动添加成功');
this.eventDialogVisible = false;
}
});
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
})
.catch((_) => {});
},
changePage(page) {
this.currentPage = page;
},
getProgress(e) {
console.log("加载进度:", e);
},
loadPdfHandler() {
console.log("PDF加载完成啦");
this.$message.success('文件加载成功');
},
handleError(err) {
console.error('PDF加载错误:', err);
this.$message.error('文件加载失败');
},
beforeAvatarUpload(file) {
const isImage = file.type.startsWith('image/');
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isImage) {
this.$message.error('上传头像只能是图片格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isImage && isLt2M;
},
handleAvatarSuccess(res) {
if (res.code === 0) {
this.userInfo.avatar = res.data.url;
this.$message.success('头像更新成功');
} else {
this.$message.error(res.message || '头像更新失败');
}
},
changePassword() {
this.passwordDialogVisible = true;
this.$nextTick(() => {
this.$refs.passwordForm && this.$refs.passwordForm.resetFields();
});
},
submitPasswordChange() {
this.$refs.passwordForm.validate(valid => {
if (valid) {
// TODO: API
this.$message.success('密码修改成功,请重新登录');
this.passwordDialogVisible = false;
setTimeout(() => {
this.$router.push('/login');
}, 1500);
}
});
},
editUserInfo() {
this.editForm = {
username: this.userInfo.username,
email: this.userInfo.email || '',
phone: this.userInfo.phone || '',
address: this.userInfo.address || [],
detailAddress: this.userInfo.detailAddress || '',
bio: this.userInfo.bio || ''
};
this.userInfoDialogVisible = true;
},
async sendVerificationCode() {
if (!this.editForm.email) {
return this.$message.warning('请先输入邮箱地址');
}
try {
// TODO: API
this.$message.success('验证码已发送到您的邮箱');
this.showVerificationCode = true;
} catch (error) {
this.$message.error('验证码发送失败');
}
},
submitUserInfo() {
this.$refs.editForm.validate(async valid => {
if (valid) {
this.submitLoading = true;
try {
// TODO: API
await new Promise(resolve => setTimeout(resolve, 1000)); // API
this.$message.success('保存成功');
this.userInfoDialogVisible = false;
this.loadUserData(); //
} catch (error) {
this.$message.error('保存失败');
} finally {
this.submitLoading = false;
}
}
});
},
handleDateRangeChange(val) {
if (val) {
this.refreshChartData();
}
},
handleTimeRangeChange(val) {
this.refreshChartData();
},
handleCategoryChange(val) {
this.refreshChartData();
},
handleAddressChange(val) {
console.log('地址选择:', val);
},
loadAddressOptions() {
// TODO:
},
toggleFullscreen() {
this.isFullscreen = !this.isFullscreen;
},
downloadPdf() {
this.$message.success('开始下载');
},
refreshChartData() {
this.initCharts();
this.$message.success('数据已更新');
},
async loadUserData() {
try {
await new Promise(resolve => setTimeout(resolve, 1000)); // API
} catch (error) {
this.$message.error('加载用户数据失败');
}
},
showOrderList() {
this.$router.push('/orders');
},
showFinanceDetails() {
this.$router.push('/finance');
},
showProductList() {
this.$router.push('/products');
},
showCustomerList() {
this.$router.push('/customers');
},
initCharts() {
//
const lineChart = this.$charts.line("line", {
color: this.echartData.color,
xData: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
yData: this.echartData.monthlyData.sales,
smooth: true,
areaStyle: {
opacity: 0.3
}
});
//
const pieChart = this.$echarts.init(document.getElementById('pie'));
pieChart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 10,
data: this.echartData.categories
},
series: [
{
name: '商品类别',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '30',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: this.echartData.categories.map((category, index) => ({
value: this.echartData.values[index],
name: category
}))
}
]
});
//
const resizeHandler = () => {
lineChart.resize();
pieChart.resize();
};
window.addEventListener('resize', resizeHandler);
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', resizeHandler);
});
}
},
};
</script>
<style scoped>
.user-center {
padding: 20px;
}
.user-info-card {
margin-bottom: 20px;
}
.user-avatar {
text-align: center;
margin-bottom: 20px;
}
.avatar-uploader {
margin-top: 10px;
}
.user-detail {
margin-left: 20px;
}
.user-detail p {
margin: 10px 0;
font-size: 14px;
}
.user-detail span {
font-weight: bold;
margin-right: 10px;
}
.data-cards {
margin-bottom: 20px;
}
.data-item {
text-align: center;
padding: 20px 0;
cursor: pointer;
transition: all 0.3s;
}
.data-item:hover {
transform: translateY(-5px);
}
.data-num {
font-size: 24px;
font-weight: bold;
color: #409EFF;
}
.data-title {
margin-top: 10px;
color: #666;
}
.charts-container {
margin-bottom: 20px;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.calendar-card {
margin-bottom: 20px;
}
.calendar-cell {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.event-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #409EFF;
margin-top: 2px;
}
.is-selected {
color: #409EFF;
font-weight: bold;
}
#line, #pie {
width: 100%;
height: 400px;
}
.dialog-toolbar {
margin-bottom: 10px;
}
.parent {
margin: 20px 0;
}
/* 全屏模式样式 */
.el-dialog.is-fullscreen {
margin: 0 !important;
width: 100% !important;
height: 100% !important;
}
</style>

@ -0,0 +1,17 @@
import Vue from 'vue'
import App from './App.vue'
import router from "@/router";
import store from "@/store";
import './registerServiceWorker'
import Axios from "axios";
import VueAxios from "vue-axios";
Vue.use(VueAxios, Axios);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');

@ -0,0 +1,32 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}

@ -0,0 +1,19 @@
import Vue from 'vue'
import Router from 'vue-router'
import Home from "@/components/Home";
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BABEL_URL,
routes: [
{
path: '/',
name: 'home',
components: {
default: Home,
}
}
]
})

@ -0,0 +1,58 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
setting: {
color: ['#ff6262', '#ffa947'],
},
settingOption: {
colors: [{
name: '炽焰',
color: ['#ff6262', '#ffa947'],
},{
name: '冰蓝',
color: ['#5b9df9', '#47bfff'],
},{
name: '青草',
color: ['#2c7d59', '#3ba776'],
},{
name: '江户',
color: ['#8E2DE2', '#4A00E0'],
}]
},
askList: [],
onAsk: false,
onInfer: false,
onLegal: false,
currentTab: 'Home',
selected: null,
unselect: null,
cardSelected: null,
cardUnselect: null,
},
mutations: {
selectTab (state, selected) {
state.unselect = null;
state.selected = selected;
},
setTab (state, tab) {
state.currentTab = tab;
},
unselectTab (state) {
state.unselect = state.selected;
state.selected = null;
state.currentTab = 'Home';
},
selectCard (state, selected) {
state.cardUnselect = null;
state.cardSelected = selected;
},
unselectCard (state) {
state.cardUnselect = state.cardSelected;
state.cardSelected = null;
}
}
})
Loading…
Cancel
Save