feat: 前端UI/UX全面优化 - CSS变量系统/交互动画/按下反馈/弹窗动画/输入框聚焦增强
This commit is contained in:
5
public/assets/home/default-avatar.svg
Normal file
5
public/assets/home/default-avatar.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none">
|
||||
<circle cx="50" cy="50" r="50" fill="#E5E7EB"/>
|
||||
<circle cx="50" cy="38" r="16" fill="#9CA3AF"/>
|
||||
<path d="M20 85c0-16.569 13.431-30 30-30s30 13.431 30 30" fill="#9CA3AF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 259 B |
53
src/App.vue
53
src/App.vue
@@ -64,7 +64,11 @@ onMounted(async () => {
|
||||
</header>
|
||||
|
||||
<main class="main-content">
|
||||
<router-view />
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="page-fade" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</main>
|
||||
|
||||
<!-- 底部导航栏 -->
|
||||
@@ -493,16 +497,63 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面切换过渡动画 */
|
||||
.page-fade-enter-active {
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
|
||||
.page-fade-leave-active {
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.page-fade-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
.page-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* 平滑滚动 */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* 自定义滚动条 */
|
||||
::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
/* 选择高亮颜色 */
|
||||
::selection {
|
||||
background: rgba(229, 62, 62, 0.2);
|
||||
color: #e53e3e;
|
||||
}
|
||||
|
||||
/* 全局 Element Plus 输入框聚焦增强 */
|
||||
.el-input__wrapper.is-focus {
|
||||
box-shadow: 0 0 0 1px var(--color-primary, #e53e3e) inset !important;
|
||||
}
|
||||
|
||||
/* 全局骨架屏动画优化 */
|
||||
.el-skeleton.is-animated .el-skeleton__item {
|
||||
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 37%, #f0f0f0 63%) !important;
|
||||
background-size: 400% 100% !important;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,53 +1,51 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
/* 精彩猪手 - 设计变量系统 */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
/* 品牌色 */
|
||||
--color-primary: #e53e3e;
|
||||
--color-primary-light: #ff6b6b;
|
||||
--color-primary-dark: #c53030;
|
||||
--color-primary-bg: rgba(229, 62, 62, 0.08);
|
||||
--color-primary-shadow: rgba(229, 62, 62, 0.25);
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
/* 功能色 */
|
||||
--color-success: #48bb78;
|
||||
--color-warning: #ed8936;
|
||||
--color-danger: #f56565;
|
||||
--color-info: #4299e1;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
/* 中性色 */
|
||||
--color-text-primary: #1a202c;
|
||||
--color-text-secondary: #4a5568;
|
||||
--color-text-tertiary: #a0aec0;
|
||||
--color-text-placeholder: #cbd5e0;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
/* 背景色 */
|
||||
--color-bg-page: #f0f2f5;
|
||||
--color-bg-card: #ffffff;
|
||||
--color-bg-input: #f7fafc;
|
||||
--color-bg-hover: #edf2f7;
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
/* 边框色 */
|
||||
--color-border: #e2e8f0;
|
||||
--color-border-light: #edf2f7;
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
/* 圆角 */
|
||||
--radius-sm: 8px;
|
||||
--radius-md: 12px;
|
||||
--radius-lg: 16px;
|
||||
--radius-xl: 20px;
|
||||
--radius-full: 9999px;
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
/* 阴影 */
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
--shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.12);
|
||||
--shadow-xl: 0 12px 40px rgba(0, 0, 0, 0.16);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
/* 过渡 */
|
||||
--transition-fast: 0.15s ease;
|
||||
--transition-base: 0.25s ease;
|
||||
--transition-slow: 0.4s ease;
|
||||
}
|
||||
|
||||
*,
|
||||
@@ -55,28 +53,18 @@
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
color: var(--color-text-primary);
|
||||
background: var(--color-bg-page);
|
||||
line-height: 1.6;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 15px;
|
||||
|
||||
@@ -53,19 +53,22 @@ export default {
|
||||
/* 底部导航栏 */
|
||||
.bottom-nav {
|
||||
height: 70px;
|
||||
background: white;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
|
||||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.06);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
max-width: 850px;
|
||||
width: 100%;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
@@ -74,37 +77,44 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
color: #8a8a8a;
|
||||
transition: all 0.3s ease;
|
||||
padding: 4px 8px;
|
||||
color: #999;
|
||||
transition: color 0.2s ease, transform 0.15s ease;
|
||||
padding: 6px 12px;
|
||||
min-width: 60px;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
border-radius: var(--radius-sm, 8px);
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
color: #ff6b35;
|
||||
background: rgba(255, 107, 53, 0.05);
|
||||
color: var(--color-primary, #e53e3e);
|
||||
}
|
||||
|
||||
.nav-item:hover .nav-icon-img {
|
||||
transform: scale(1.05);
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
.nav-item:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
color: #ff6b35;
|
||||
background: rgba(255, 107, 53, 0.1);
|
||||
color: var(--color-primary, #e53e3e);
|
||||
}
|
||||
|
||||
.nav-item.active .nav-icon {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.nav-item.active .nav-text {
|
||||
color: #ff6b35;
|
||||
color: var(--color-primary, #e53e3e);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
margin-bottom: 4px;
|
||||
transition: all 0.3s ease;
|
||||
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -116,14 +126,14 @@ export default {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
object-fit: contain;
|
||||
transition: all 0.3s ease;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-text {
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
transition: color 0.2s ease;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@@ -135,7 +145,7 @@ export default {
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 3px 6px;
|
||||
padding: 4px 8px;
|
||||
min-width: 55px;
|
||||
}
|
||||
|
||||
@@ -162,7 +172,7 @@ export default {
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 2px 4px;
|
||||
padding: 3px 6px;
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
msg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="greetings">
|
||||
<h1 class="green">{{ msg }}</h1>
|
||||
<h3>
|
||||
You’ve successfully created a project with
|
||||
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 2.6rem;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,94 +0,0 @@
|
||||
<script setup>
|
||||
import WelcomeItem from './WelcomeItem.vue'
|
||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
||||
import ToolingIcon from './icons/IconTooling.vue'
|
||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
||||
import CommunityIcon from './icons/IconCommunity.vue'
|
||||
import SupportIcon from './icons/IconSupport.vue'
|
||||
|
||||
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<DocumentationIcon />
|
||||
</template>
|
||||
<template #heading>Documentation</template>
|
||||
|
||||
Vue’s
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
||||
provides you with all information you need to get started.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<ToolingIcon />
|
||||
</template>
|
||||
<template #heading>Tooling</template>
|
||||
|
||||
This project is served and bundled with
|
||||
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
||||
recommended IDE setup is
|
||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
|
||||
+
|
||||
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener">Vue - Official</a>. If
|
||||
you need to test your components and web pages, check out
|
||||
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
|
||||
and
|
||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
|
||||
/
|
||||
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
|
||||
|
||||
<br />
|
||||
|
||||
More instructions are available in
|
||||
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
|
||||
>.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<EcosystemIcon />
|
||||
</template>
|
||||
<template #heading>Ecosystem</template>
|
||||
|
||||
Get official tools and libraries for your project:
|
||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
||||
you need more resources, we suggest paying
|
||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
||||
a visit.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<CommunityIcon />
|
||||
</template>
|
||||
<template #heading>Community</template>
|
||||
|
||||
Got stuck? Ask your question on
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
|
||||
(our official Discord server), or
|
||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
||||
>StackOverflow</a
|
||||
>. You should also follow the official
|
||||
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
|
||||
Bluesky account or the
|
||||
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
||||
X account for latest news in the Vue world.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<SupportIcon />
|
||||
</template>
|
||||
<template #heading>Support Vue</template>
|
||||
|
||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
||||
us by
|
||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
||||
</WelcomeItem>
|
||||
</template>
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<i>
|
||||
<slot name="icon"></slot>
|
||||
</i>
|
||||
<div class="details">
|
||||
<h3>
|
||||
<slot name="heading"></slot>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--color-heading);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
i {
|
||||
top: calc(50% - 25px);
|
||||
left: -26px;
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 8px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.item:before {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:after {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:first-of-type:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item:last-of-type:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -25,7 +25,7 @@ export const userStore = reactive({
|
||||
avatar: userData.userAvatar || userData.avatar || null,
|
||||
userType: userData.userType || 'trial',
|
||||
isVip: userData.isVip,
|
||||
expireDate: userData.vipExpire || userData.expireDate || '2025-06-30',
|
||||
expireDate: userData.vipExpire || userData.expireDate || null,
|
||||
registeredAt: userData.createTime || userData.registeredAt || new Date().toISOString(),
|
||||
status: userData.status !== undefined ? userData.status : 0, // 添加status字段,默认为0 (正常)
|
||||
stats: {
|
||||
|
||||
75
src/utils/format.js
Normal file
75
src/utils/format.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 通用格式化工具函数
|
||||
*/
|
||||
|
||||
/**
|
||||
* 格式化时间为短格式:YY-MM-DD HH:mm
|
||||
* @param {string|number|Date} timestamp
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatTime(timestamp) {
|
||||
if (!timestamp) return ''
|
||||
const date = new Date(timestamp)
|
||||
const year = String(date.getFullYear()).slice(-2)
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间为完整格式:YYYY-MM-DD HH:mm
|
||||
* @param {string|number|Date} timestamp
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatFullTime(timestamp) {
|
||||
if (!timestamp) return ''
|
||||
const date = new Date(timestamp)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期时间为本地化格式:YYYY-MM-DD HH:mm:ss
|
||||
* @param {string|number|Date} dateStr
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDateTime(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
const date = new Date(dateStr)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期为短格式:YYYY-MM-DD
|
||||
* @param {string|number|Date} dateStr
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
const date = new Date(dateStr)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字为两位,不足补零
|
||||
* @param {number|string} num
|
||||
* @returns {string}
|
||||
*/
|
||||
export function padNumber(num) {
|
||||
return String(num).padStart(2, '0')
|
||||
}
|
||||
@@ -156,13 +156,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElCard } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DataAnalysis',
|
||||
components: {
|
||||
ElCard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentLotteryType: 'ssq', // 默认选中双色球
|
||||
@@ -232,7 +227,7 @@ export default {
|
||||
<style scoped>
|
||||
.data-analysis-container {
|
||||
padding: 20px 20px 0px 20px;
|
||||
background-color: #f0f2f5;
|
||||
background-color: var(--color-bg-page, #f0f2f5);
|
||||
min-height: calc(100vh - 140px);
|
||||
}
|
||||
|
||||
@@ -293,6 +288,11 @@ export default {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.lottery-option:active {
|
||||
transform: scale(0.95);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.lottery-option-image {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
@@ -371,7 +371,13 @@ export default {
|
||||
}
|
||||
|
||||
.analysis-option:hover {
|
||||
transform: scale(1.05);
|
||||
transform: scale(1.03);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.analysis-option:active {
|
||||
transform: scale(0.98);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
/* 第一个卡片的图标在左侧 */
|
||||
@@ -478,6 +484,16 @@ export default {
|
||||
}
|
||||
|
||||
/* 开发中提示框 */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from { opacity: 0; transform: scale(0.9); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
.tip-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -490,16 +506,18 @@ export default {
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
padding: 20px;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.tip-content {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
border-radius: var(--radius-lg, 16px);
|
||||
padding: 32px 24px;
|
||||
text-align: center;
|
||||
max-width: 300px;
|
||||
width: 100%;
|
||||
box-shadow: 0 16px 48px rgba(0,0,0,0.2);
|
||||
box-shadow: var(--shadow-xl, 0 16px 48px rgba(0,0,0,0.2));
|
||||
animation: scaleIn 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
@@ -539,7 +557,7 @@ export default {
|
||||
}
|
||||
|
||||
.tip-button:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.96);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
|
||||
@@ -220,35 +220,8 @@
|
||||
<script>
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { userStore } from '../store/user.js'
|
||||
import {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon
|
||||
} from 'element-plus'
|
||||
import {
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'ExcelImportManagement',
|
||||
components: {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 权限验证
|
||||
@@ -467,7 +440,7 @@ export default {
|
||||
<style scoped>
|
||||
.excel-import-management {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,36 +142,9 @@
|
||||
<script>
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { userStore } from '../store/user.js'
|
||||
import {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElResult,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElPagination
|
||||
} from 'element-plus'
|
||||
import { ShoppingBag, Refresh } from '@element-plus/icons-vue'
|
||||
|
||||
import { formatDateTime } from '../utils/format.js'
|
||||
export default {
|
||||
name: 'ExchangeRecords',
|
||||
components: {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElResult,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElPagination,
|
||||
ShoppingBag,
|
||||
Refresh
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -291,20 +264,8 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 格式化日期
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '-'
|
||||
|
||||
const date = new Date(dateStr)
|
||||
const formatted = date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
})
|
||||
return formatted.replace(/\//g, '-')
|
||||
return formatDateTime(dateStr)
|
||||
},
|
||||
|
||||
// 跳转到个人中心
|
||||
@@ -622,6 +583,11 @@ export default {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.record-card-modern:active {
|
||||
transform: scale(0.98);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 记录头部 */
|
||||
|
||||
@@ -148,22 +148,8 @@ import { userStore } from '../store/user'
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElCard, ElInput, ElButton, ElCheckbox, ElAlert } from 'element-plus'
|
||||
import { User, Lock, Iphone, Key } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
components: {
|
||||
ElCard,
|
||||
ElInput,
|
||||
ElButton,
|
||||
ElCheckbox,
|
||||
ElAlert,
|
||||
User,
|
||||
Lock,
|
||||
Iphone,
|
||||
Key
|
||||
},
|
||||
setup() {
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
@@ -438,10 +424,22 @@ export default {
|
||||
/* 登录页面容器 */
|
||||
.login-page-container {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f0f2f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 20px 20px 8px 20px;
|
||||
}
|
||||
|
||||
/* 表单入场动画 */
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
background: linear-gradient(135deg, #ff6b6b, #ee5a52);
|
||||
@@ -450,8 +448,9 @@ export default {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 12px;
|
||||
border-radius: var(--radius-md, 12px);
|
||||
box-shadow: 0 4px 20px rgba(238, 90, 82, 0.3);
|
||||
animation: slideUp 0.5s ease;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
@@ -464,7 +463,7 @@ export default {
|
||||
margin: 0 auto 4px;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
text-shadow: 0 2px 8px rgba(0,0,0,0.5), 0 0 20px rgba(0,0,0,0.3);
|
||||
text-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
||||
letter-spacing: 1px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
@@ -475,7 +474,7 @@ export default {
|
||||
margin: 0;
|
||||
color: white;
|
||||
opacity: 0.95;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.4);
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.2);
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
font-weight: 400;
|
||||
@@ -492,9 +491,10 @@ export default {
|
||||
padding: 0;
|
||||
background: white;
|
||||
margin: 0 0 20px 0;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||
border-radius: var(--radius-lg, 16px);
|
||||
box-shadow: var(--shadow-lg, 0 8px 30px rgba(0, 0, 0, 0.12));
|
||||
overflow: hidden;
|
||||
animation: slideUp 0.5s ease 0.1s both;
|
||||
}
|
||||
|
||||
/* 登录方式切换标签 */
|
||||
@@ -502,6 +502,7 @@ export default {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: #fafafa;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-tab {
|
||||
@@ -509,19 +510,36 @@ export default {
|
||||
text-align: center;
|
||||
padding: 18px 0;
|
||||
font-size: 15px;
|
||||
color: #888;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
transition: color 0.25s ease, background 0.25s ease;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.login-tab::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 2.5px;
|
||||
background: var(--color-primary, #e53e3e);
|
||||
border-radius: 2px;
|
||||
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.login-tab.active {
|
||||
color: #e53e3e;
|
||||
color: var(--color-primary, #e53e3e);
|
||||
background: white;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-tab.active::after {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.login-tab:hover:not(.active) {
|
||||
color: #666;
|
||||
@@ -537,26 +555,25 @@ export default {
|
||||
|
||||
/* 表单组 */
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 2px solid #e9ecef;
|
||||
border: 2px solid var(--color-border, #e9ecef);
|
||||
border-radius: 6px;
|
||||
background: #f8f9fa;
|
||||
transition: all 0.3s ease;
|
||||
background: var(--color-bg-input, #f8f9fa);
|
||||
transition: all var(--transition-base, 0.25s ease);
|
||||
min-height: 56px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.input-wrapper:focus-within {
|
||||
border-color: #e9ecef;
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
background: white;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--color-primary-bg, rgba(229, 62, 62, 0.08));
|
||||
}
|
||||
|
||||
input:focus {
|
||||
@@ -565,12 +582,12 @@ input:focus {
|
||||
}
|
||||
|
||||
.input-wrapper.error {
|
||||
border-color: #dc3545;
|
||||
border-color: var(--color-danger, #dc3545);
|
||||
background: #fff5f5;
|
||||
}
|
||||
|
||||
.input-wrapper.success {
|
||||
border-color: #4caf50;
|
||||
border-color: var(--color-success, #4caf50);
|
||||
background: #f8fff8;
|
||||
}
|
||||
|
||||
@@ -597,9 +614,10 @@ input:focus {
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
background: transparent;
|
||||
color: #212529;
|
||||
color: var(--color-text-primary, #212529);
|
||||
box-shadow: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
@@ -633,11 +651,11 @@ input:-webkit-autofill:active {
|
||||
|
||||
/* 内联发送验证码按钮样式 */
|
||||
.send-code-btn-inline {
|
||||
background: linear-gradient(135deg, #e53e3e, #ff6b6b);
|
||||
background: linear-gradient(135deg, var(--color-primary, #e53e3e), var(--color-primary-light, #ff6b6b));
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
border-radius: var(--radius-md, 12px);
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
transition: all var(--transition-base, 0.25s ease);
|
||||
min-width: 120px;
|
||||
flex-shrink: 0;
|
||||
height: auto;
|
||||
@@ -647,36 +665,37 @@ input:-webkit-autofill:active {
|
||||
}
|
||||
|
||||
.send-code-btn-inline:hover:not(.is-disabled) {
|
||||
background: linear-gradient(135deg, #d43030, #ff5a5a);
|
||||
background: linear-gradient(135deg, var(--color-primary-dark, #d43030), #ff5a5a);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(229, 62, 62, 0.3);
|
||||
box-shadow: 0 4px 15px var(--color-primary-shadow, rgba(229, 62, 62, 0.3));
|
||||
}
|
||||
|
||||
.send-code-btn-inline:active:not(.is-disabled) {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.98);
|
||||
}
|
||||
|
||||
.send-code-btn-inline.is-disabled {
|
||||
background: #cccccc !important;
|
||||
border-color: #cccccc !important;
|
||||
color: #888 !important;
|
||||
background: #d9d9d9 !important;
|
||||
border-color: #d9d9d9 !important;
|
||||
color: #999 !important;
|
||||
transform: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 提示文本 */
|
||||
.error-text {
|
||||
color: #ff4444;
|
||||
color: var(--color-danger, #f56565);
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
margin-left: 8px;
|
||||
margin-top: 6px;
|
||||
margin-left: 4px;
|
||||
animation: slideUp 0.2s ease;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #888888;
|
||||
color: var(--color-text-tertiary, #a0aec0);
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
margin-left: 8px;
|
||||
margin-top: 6px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* 隐藏浏览器自带的密码控件 */
|
||||
@@ -692,7 +711,7 @@ input::-webkit-credentials-auto-fill-button {
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: #9ca3af;
|
||||
color: var(--color-text-placeholder, #cbd5e0);
|
||||
}
|
||||
|
||||
.password-toggle {
|
||||
@@ -739,24 +758,25 @@ input::-webkit-credentials-auto-fill-button {
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
color: transparent;
|
||||
transition: all 0.3s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.checkbox-wrapper input:checked + .checkmark {
|
||||
background: #e53e3e;
|
||||
border-color: #e53e3e;
|
||||
background: var(--color-primary, #e53e3e);
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 忘记密码链接 */
|
||||
.forgot-password-link {
|
||||
color: #e53e3e;
|
||||
color: var(--color-primary, #e53e3e);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
transition: color var(--transition-fast, 0.15s ease);
|
||||
}
|
||||
|
||||
.forgot-password-link:hover {
|
||||
color: var(--color-primary-dark, #c53030);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -768,22 +788,23 @@ input::-webkit-credentials-auto-fill-button {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
height: 52px;
|
||||
background: linear-gradient(135deg, #e53e3e, #ff6b6b);
|
||||
background: linear-gradient(135deg, var(--color-primary, #e53e3e), var(--color-primary-light, #ff6b6b));
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(229, 62, 62, 0.25);
|
||||
transition: all 0.3s ease;
|
||||
border-radius: var(--radius-md, 12px);
|
||||
box-shadow: 0 4px 20px var(--color-primary-shadow, rgba(229, 62, 62, 0.25));
|
||||
transition: all var(--transition-base, 0.25s ease);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.login-btn:hover:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 30px rgba(229, 62, 62, 0.35);
|
||||
background: linear-gradient(135deg, #d43030, #ff5a5a);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(229, 62, 62, 0.4);
|
||||
background: linear-gradient(135deg, var(--color-primary-dark, #d43030), #ff5a5a);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.login-btn:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.98);
|
||||
box-shadow: 0 2px 10px rgba(229, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
@@ -791,65 +812,71 @@ input::-webkit-credentials-auto-fill-button {
|
||||
:deep(.el-input__wrapper) {
|
||||
padding: 6px 16px;
|
||||
box-shadow: none !important;
|
||||
background-color: #f8f9fa;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
background-color: var(--color-bg-input, #f7fafc);
|
||||
border: 2px solid var(--color-border, #e2e8f0);
|
||||
border-radius: var(--radius-md, 12px);
|
||||
transition: all var(--transition-base, 0.25s ease);
|
||||
}
|
||||
|
||||
|
||||
:deep(.el-input__wrapper.is-focus) {
|
||||
background-color: #fff;
|
||||
border-color: #e53e3e;
|
||||
box-shadow: 0 0 0 4px rgba(229, 62, 62, 0.1);
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
box-shadow: 0 0 0 3px var(--color-primary-bg, rgba(229, 62, 62, 0.08)) !important;
|
||||
}
|
||||
|
||||
|
||||
:deep(.el-input__prefix) {
|
||||
margin-right: 12px;
|
||||
color: #999;
|
||||
color: var(--color-text-tertiary, #a0aec0);
|
||||
transition: color var(--transition-base, 0.25s ease);
|
||||
}
|
||||
|
||||
:deep(.el-input.is-focus .el-input__prefix) {
|
||||
color: var(--color-primary, #e53e3e);
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
height: 44px;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
color: var(--color-text-primary, #1a202c);
|
||||
}
|
||||
|
||||
:deep(.el-checkbox__label) {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
color: var(--color-text-secondary, #4a5568);
|
||||
}
|
||||
|
||||
:deep(.el-checkbox__inner) {
|
||||
border-color: #ddd;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
||||
background-color: #e53e3e;
|
||||
border-color: #e53e3e;
|
||||
background-color: var(--color-primary, #e53e3e);
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
}
|
||||
|
||||
|
||||
:deep(.el-button.is-disabled) {
|
||||
background: #cccccc;
|
||||
border-color: #cccccc;
|
||||
background: #d9d9d9;
|
||||
border-color: #d9d9d9;
|
||||
}
|
||||
|
||||
/* 注册链接 */
|
||||
.register-link {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
color: var(--color-text-secondary, #4a5568);
|
||||
}
|
||||
|
||||
.register-link .link {
|
||||
color: #e53e3e;
|
||||
color: var(--color-primary, #e53e3e);
|
||||
text-decoration: none;
|
||||
margin-left: 5px;
|
||||
font-weight: 500;
|
||||
transition: color var(--transition-fast, 0.15s ease);
|
||||
}
|
||||
|
||||
.register-link .link:hover {
|
||||
color: var(--color-primary-dark, #c53030);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -862,7 +889,6 @@ input::-webkit-credentials-auto-fill-button {
|
||||
.login-form {
|
||||
padding: 22px 20px 18px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
@@ -919,6 +945,4 @@ input::-webkit-credentials-auto-fill-button {
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面端样式 - 这部分已在上面定义,这里移除重复定义 */
|
||||
</style>
|
||||
@@ -163,7 +163,7 @@ export default {
|
||||
<style scoped>
|
||||
.lottery-info-page {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
overflow-x: hidden;
|
||||
padding-top: 16px; /* 顶部添加一些间距,因为没有banner */
|
||||
}
|
||||
|
||||
@@ -181,9 +181,10 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { formatTime, formatFullTime } from '../utils/format.js'
|
||||
|
||||
export default {
|
||||
name: 'LotterySelection',
|
||||
name: 'LotteryPremium',
|
||||
data() {
|
||||
return {
|
||||
showTip: false,
|
||||
@@ -262,26 +263,8 @@ export default {
|
||||
this.noticeTimer = null
|
||||
}
|
||||
},
|
||||
// 格式化时间
|
||||
formatTime(timestamp) {
|
||||
const date = new Date(timestamp)
|
||||
const year = String(date.getFullYear()).slice(-2)
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
},
|
||||
// 格式化完整时间
|
||||
formatFullTime(timestamp) {
|
||||
const date = new Date(timestamp)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
},
|
||||
formatTime,
|
||||
formatFullTime,
|
||||
// 显示公告列表
|
||||
async showAnnouncementList() {
|
||||
try {
|
||||
@@ -308,7 +291,7 @@ export default {
|
||||
<style scoped>
|
||||
.home-page {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@@ -524,11 +507,16 @@ export default {
|
||||
}
|
||||
|
||||
.lottery-card.available:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
|
||||
border-color: #ff6b35;
|
||||
}
|
||||
|
||||
.lottery-card:active {
|
||||
transform: scale(0.97);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.lottery-card.disabled {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { formatTime, formatFullTime } from '../utils/format.js'
|
||||
|
||||
export default {
|
||||
name: 'LotterySelection',
|
||||
@@ -264,26 +265,8 @@ export default {
|
||||
this.noticeTimer = null
|
||||
}
|
||||
},
|
||||
// 格式化时间
|
||||
formatTime(timestamp) {
|
||||
const date = new Date(timestamp)
|
||||
const year = String(date.getFullYear()).slice(-2)
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
},
|
||||
// 格式化完整时间
|
||||
formatFullTime(timestamp) {
|
||||
const date = new Date(timestamp)
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
},
|
||||
formatTime,
|
||||
formatFullTime,
|
||||
// 显示公告列表
|
||||
async showAnnouncementList() {
|
||||
try {
|
||||
@@ -318,7 +301,7 @@ export default {
|
||||
<style scoped>
|
||||
.home-page {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@@ -504,7 +487,7 @@ export default {
|
||||
}
|
||||
|
||||
.premium-btn:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.95);
|
||||
}
|
||||
|
||||
.lottery-grid {
|
||||
@@ -532,11 +515,16 @@ export default {
|
||||
}
|
||||
|
||||
.lottery-card.available:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
|
||||
border-color: #ff6b35;
|
||||
}
|
||||
|
||||
.lottery-card:active {
|
||||
transform: scale(0.97);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.lottery-card.disabled {
|
||||
opacity: 0.85;
|
||||
}
|
||||
@@ -709,6 +697,16 @@ export default {
|
||||
border: 1px solid rgba(255, 255, 255, 0.3) !important;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from { opacity: 0; transform: scale(0.9); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
.tip-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -721,16 +719,18 @@ export default {
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
padding: 20px;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.tip-content {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
border-radius: var(--radius-lg, 16px);
|
||||
padding: 32px 24px;
|
||||
text-align: center;
|
||||
max-width: 300px;
|
||||
width: 100%;
|
||||
box-shadow: 0 16px 48px rgba(0,0,0,0.2);
|
||||
box-shadow: var(--shadow-xl, 0 16px 48px rgba(0,0,0,0.2));
|
||||
animation: scaleIn 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
@@ -770,7 +770,7 @@ export default {
|
||||
}
|
||||
|
||||
.tip-button:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.96);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@@ -1128,17 +1128,19 @@ export default {
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
padding: 20px;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.announcement-modal-content {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
border-radius: var(--radius-lg, 16px);
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: var(--shadow-xl, 0 16px 48px rgba(0, 0, 0, 0.2));
|
||||
animation: scaleIn 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.announcement-modal-header {
|
||||
|
||||
@@ -220,41 +220,8 @@
|
||||
<script>
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { userStore } from '../store/user.js'
|
||||
import {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElPagination,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElSelect,
|
||||
ElOption
|
||||
} from 'element-plus'
|
||||
import { Tickets } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'PredictRecords',
|
||||
components: {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElPagination,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
Tickets
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -825,6 +792,11 @@ export default {
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.record-card-modern:active {
|
||||
transform: scale(0.98);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.record-header {
|
||||
padding: 14px 16px 0 16px;
|
||||
display: flex;
|
||||
|
||||
@@ -458,37 +458,11 @@
|
||||
import { userStore } from '../store/user'
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import QRCode from 'qrcode'
|
||||
import { ElIcon, ElTable, ElTableColumn, ElMessage } from 'element-plus'
|
||||
import CustomSelect from '../components/CustomSelect.vue'
|
||||
import {
|
||||
View,
|
||||
TrendCharts,
|
||||
Star,
|
||||
Download,
|
||||
Comment,
|
||||
Reading,
|
||||
Collection,
|
||||
Tickets,
|
||||
ShoppingBag,
|
||||
Warning
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'Profile',
|
||||
components: {
|
||||
ElIcon,
|
||||
View,
|
||||
TrendCharts,
|
||||
Star,
|
||||
Download,
|
||||
Comment,
|
||||
Reading,
|
||||
Collection,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
Tickets,
|
||||
ShoppingBag,
|
||||
Warning,
|
||||
CustomSelect
|
||||
},
|
||||
data() {
|
||||
@@ -596,7 +570,7 @@ export default {
|
||||
const date = new Date(this.userStore.user.expireDate)
|
||||
return date.toISOString().split('T')[0] // 只取日期部分 YYYY-MM-DD
|
||||
}
|
||||
return '2025-06-30'
|
||||
return '暂无'
|
||||
},
|
||||
|
||||
// 检查会员是否已过期
|
||||
@@ -1055,8 +1029,8 @@ export default {
|
||||
/* 用户中心容器 */
|
||||
.profile-container {
|
||||
min-height: calc(100vh - 85px);
|
||||
background: #f5f5f5;
|
||||
padding: 0 0 0px 0;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1070,16 +1044,22 @@ export default {
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
@keyframes cardEntry {
|
||||
from { opacity: 0; transform: translateY(30px) scale(0.96); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
border-radius: var(--radius-xl, 20px);
|
||||
padding: 50px 30px;
|
||||
text-align: center;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: var(--shadow-xl, 0 12px 40px rgba(0, 0, 0, 0.12));
|
||||
max-width: 380px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: cardEntry 0.5s ease;
|
||||
}
|
||||
|
||||
.login-icon {
|
||||
@@ -1338,13 +1318,19 @@ export default {
|
||||
padding: 18px 10px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: background-color 0.2s ease, transform 0.15s ease;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.action-item:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.action-item:active {
|
||||
transform: scale(0.95);
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.action-item:not(:last-child)::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -1426,7 +1412,7 @@ export default {
|
||||
}
|
||||
|
||||
.benefit-item:active {
|
||||
transform: translateY(-1px);
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -1537,6 +1523,10 @@ export default {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.function-list-item:active {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.function-list-item:first-child {
|
||||
border-radius: 15px 15px 0 0;
|
||||
}
|
||||
@@ -1719,9 +1709,10 @@ export default {
|
||||
}
|
||||
|
||||
.modern-input:focus {
|
||||
border-color: #ddd;
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
background: white;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--color-primary-bg, rgba(229, 62, 62, 0.08));
|
||||
}
|
||||
|
||||
.input-focus-border {
|
||||
@@ -1826,7 +1817,7 @@ export default {
|
||||
}
|
||||
|
||||
.primary-btn:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.97);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
|
||||
@@ -150,22 +150,8 @@ import { userStore } from '../store/user'
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElCard, ElInput, ElButton, ElCheckbox } from 'element-plus'
|
||||
import { User, Lock, Iphone, Key, Avatar } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'Register',
|
||||
components: {
|
||||
ElCard,
|
||||
ElInput,
|
||||
ElButton,
|
||||
ElCheckbox,
|
||||
User,
|
||||
Lock,
|
||||
Iphone,
|
||||
Key,
|
||||
Avatar
|
||||
},
|
||||
setup() {
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
@@ -451,10 +437,7 @@ export default {
|
||||
const formData = {
|
||||
username: this.formData.username,
|
||||
nickname: this.formData.nickname,
|
||||
password: this.formData.password,
|
||||
confirmPassword: this.formData.confirmPassword,
|
||||
phone: this.formData.phone,
|
||||
code: this.formData.code,
|
||||
agreeTerms: this.formData.agreeTerms
|
||||
};
|
||||
sessionStorage.setItem('register_form_data', JSON.stringify(formData));
|
||||
@@ -534,7 +517,7 @@ export default {
|
||||
/* 注册页面容器 */
|
||||
.register-page-container {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f0f2f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 20px 20px 8px 20px;
|
||||
}
|
||||
|
||||
@@ -609,28 +592,27 @@ export default {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 2px solid #e9ecef;
|
||||
border: 2px solid var(--color-border, #e9ecef);
|
||||
border-radius: 6px;
|
||||
background: #f8f9fa;
|
||||
transition: all 0.3s ease;
|
||||
background: var(--color-bg-input, #f8f9fa);
|
||||
transition: all var(--transition-base, 0.25s ease);
|
||||
min-height: 56px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.input-wrapper:focus-within {
|
||||
border-color: #e9ecef;
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
background: white;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--color-primary-bg, rgba(229, 62, 62, 0.08));
|
||||
}
|
||||
|
||||
.input-wrapper.error {
|
||||
border-color: #dc3545;
|
||||
border-color: var(--color-danger, #dc3545);
|
||||
background: #fff5f5;
|
||||
}
|
||||
|
||||
.input-wrapper.success {
|
||||
border-color: #4caf50;
|
||||
border-color: var(--color-success, #4caf50);
|
||||
background: #f8fff8;
|
||||
}
|
||||
|
||||
@@ -668,6 +650,7 @@ export default {
|
||||
color: #212529;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
@@ -860,7 +843,7 @@ input::-webkit-credentials-auto-fill-button {
|
||||
}
|
||||
|
||||
.register-btn:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.98);
|
||||
box-shadow: 0 2px 10px rgba(229, 62, 62, 0.3);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,18 +112,8 @@
|
||||
import { lotteryApi } from '../api/index.js'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElInput, ElButton } from 'element-plus'
|
||||
import { Lock, Iphone, Key } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'ResetPassword',
|
||||
components: {
|
||||
ElInput,
|
||||
ElButton,
|
||||
Lock,
|
||||
Iphone,
|
||||
Key
|
||||
},
|
||||
setup() {
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
@@ -353,7 +343,7 @@ export default {
|
||||
/* 页面容器 */
|
||||
.reset-password-page-container {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f0f2f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 20px 20px 8px 20px;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,14 +91,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ElPageHeader, ElCard } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'UserAgreement',
|
||||
components: {
|
||||
ElPageHeader,
|
||||
ElCard
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.go(-1)
|
||||
|
||||
@@ -120,18 +120,11 @@
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { User, Lock, Key, Document } from '@element-plus/icons-vue'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
|
||||
export default {
|
||||
name: 'AdminLogin',
|
||||
components: {
|
||||
User,
|
||||
Lock,
|
||||
Key,
|
||||
Document
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
const loginFormRef = ref()
|
||||
|
||||
@@ -270,32 +270,10 @@
|
||||
<script>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Bell,
|
||||
CircleCheck,
|
||||
Edit,
|
||||
Close,
|
||||
Search,
|
||||
Refresh,
|
||||
Plus,
|
||||
View,
|
||||
Delete
|
||||
} from '@element-plus/icons-vue'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
|
||||
export default {
|
||||
name: 'AnnouncementManagement',
|
||||
components: {
|
||||
Bell,
|
||||
CircleCheck,
|
||||
Edit,
|
||||
Close,
|
||||
Search,
|
||||
Refresh,
|
||||
Plus,
|
||||
View,
|
||||
Delete
|
||||
},
|
||||
setup() {
|
||||
const loading = ref(false)
|
||||
const submitting = ref(false)
|
||||
|
||||
@@ -224,21 +224,6 @@
|
||||
|
||||
<script>
|
||||
import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import {
|
||||
User,
|
||||
Key,
|
||||
Ticket,
|
||||
TrendCharts,
|
||||
Operation,
|
||||
Document,
|
||||
Setting,
|
||||
InfoFilled,
|
||||
Clock,
|
||||
ArrowRight,
|
||||
View,
|
||||
Sunny,
|
||||
DataLine
|
||||
} from '@element-plus/icons-vue'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -246,21 +231,6 @@ import * as echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'AdminDashboard',
|
||||
components: {
|
||||
User,
|
||||
Key,
|
||||
Ticket,
|
||||
TrendCharts,
|
||||
Operation,
|
||||
Document,
|
||||
Setting,
|
||||
InfoFilled,
|
||||
Clock,
|
||||
ArrowRight,
|
||||
View,
|
||||
Sunny,
|
||||
DataLine
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
|
||||
|
||||
@@ -218,35 +218,8 @@
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import dltLotteryApi from '../../api/dlt/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon
|
||||
} from 'element-plus'
|
||||
import {
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'AdminDltExcelImportManagement',
|
||||
components: {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 权限验证
|
||||
@@ -461,7 +434,7 @@ export default {
|
||||
<style scoped>
|
||||
.excel-import-management {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
|
||||
@@ -217,35 +217,8 @@
|
||||
<script>
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon
|
||||
} from 'element-plus'
|
||||
import {
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'AdminExcelImportManagement',
|
||||
components: {
|
||||
ElCard,
|
||||
ElRow,
|
||||
ElCol,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
Document,
|
||||
Warning,
|
||||
Plus,
|
||||
InfoFilled,
|
||||
FolderOpened
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 权限验证
|
||||
@@ -472,7 +445,7 @@ export default {
|
||||
<style scoped>
|
||||
.excel-import-management {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,23 +141,11 @@
|
||||
<script>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
Clock,
|
||||
Refresh,
|
||||
Search,
|
||||
Filter
|
||||
} from '@element-plus/icons-vue'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
|
||||
export default {
|
||||
name: 'OperationHistory',
|
||||
components: {
|
||||
Clock,
|
||||
Refresh,
|
||||
Search,
|
||||
Filter
|
||||
},
|
||||
setup() {
|
||||
// 筛选表单
|
||||
const filterForm = reactive({
|
||||
|
||||
@@ -423,28 +423,12 @@
|
||||
<script>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Search,
|
||||
Refresh,
|
||||
Plus,
|
||||
Download,
|
||||
Edit,
|
||||
Delete
|
||||
} from '@element-plus/icons-vue'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default {
|
||||
name: 'UserList',
|
||||
components: {
|
||||
Search,
|
||||
Refresh,
|
||||
Plus,
|
||||
Download,
|
||||
Edit,
|
||||
Delete
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter()
|
||||
// 权限检查
|
||||
|
||||
@@ -374,33 +374,11 @@
|
||||
<script>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Key,
|
||||
Check,
|
||||
User,
|
||||
Plus,
|
||||
Search,
|
||||
List,
|
||||
Refresh,
|
||||
Download,
|
||||
CopyDocument
|
||||
} from '@element-plus/icons-vue'
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
|
||||
export default {
|
||||
name: 'VipCodeManagement',
|
||||
components: {
|
||||
Key,
|
||||
Check,
|
||||
User,
|
||||
Plus,
|
||||
Search,
|
||||
List,
|
||||
Refresh,
|
||||
Download,
|
||||
CopyDocument
|
||||
},
|
||||
setup() {
|
||||
// 统计数据
|
||||
const stats = reactive({
|
||||
|
||||
@@ -157,47 +157,17 @@
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
DataBoard,
|
||||
User,
|
||||
Key,
|
||||
Document,
|
||||
Fold,
|
||||
Expand,
|
||||
ArrowDown,
|
||||
Refresh,
|
||||
Setting,
|
||||
SwitchButton,
|
||||
Clock,
|
||||
Bell,
|
||||
Aim,
|
||||
Trophy
|
||||
} from '@element-plus/icons-vue'
|
||||
import { userStore } from '../../../store/user.js'
|
||||
import { lotteryApi } from '../../../api/index.js'
|
||||
|
||||
export default {
|
||||
name: 'AdminLayout',
|
||||
components: {
|
||||
DataBoard,
|
||||
User,
|
||||
Key,
|
||||
Document,
|
||||
Fold,
|
||||
Expand,
|
||||
ArrowDown,
|
||||
Bell,
|
||||
Refresh,
|
||||
Setting,
|
||||
SwitchButton,
|
||||
Clock
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const isCollapse = ref(false)
|
||||
const userName = ref('管理员')
|
||||
const userAvatar = ref('https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png')
|
||||
const userAvatar = ref('/assets/home/default-avatar.svg')
|
||||
const userRole = ref('')
|
||||
|
||||
// 当前激活的菜单项
|
||||
|
||||
@@ -93,28 +93,8 @@
|
||||
|
||||
<script>
|
||||
import { dltLotteryApi } from '../../api/dlt/index.js'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElEmpty
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'DltTableAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElEmpty
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
drawsData: [],
|
||||
|
||||
@@ -136,14 +136,10 @@
|
||||
<script>
|
||||
import dltLotteryApi from '../../api/dlt/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption, ElMessage } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DltHitAnalysis',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -1176,44 +1176,12 @@ import { lotteryApi } from '../../api'
|
||||
import { dltLotteryApi } from '../../api/dlt'
|
||||
import { userStore } from '../../store/user'
|
||||
import AlgorithmProcessModal from '../../components/AlgorithmProcessModal.vue'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ElMessage
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled, Trophy } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DltHome',
|
||||
components: {
|
||||
AlgorithmProcessModal,
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ArrowLeft,
|
||||
InfoFilled,
|
||||
Trophy
|
||||
AlgorithmProcessModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -2233,7 +2201,7 @@ export default {
|
||||
/* 基础样式参考双色球界面但使用绿色主题 */
|
||||
.home-container {
|
||||
padding: 20px 20px 8px 20px;
|
||||
background-color: #f0f2f5;
|
||||
background-color: var(--color-bg-page, #f0f2f5);
|
||||
min-height: calc(100vh - 70px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -2561,12 +2529,18 @@ export default {
|
||||
}
|
||||
|
||||
.position-item:hover {
|
||||
transform: translateY(-1px);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.position-item:active {
|
||||
transform: scale(0.97);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.position-item.selected {
|
||||
border-color: #4CAF50;
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
background: rgba(76, 175, 80, 0.08);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.2);
|
||||
}
|
||||
|
||||
@@ -273,33 +273,8 @@
|
||||
|
||||
<script>
|
||||
import { dltLotteryApi } from '@/api/dlt'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'DltLineAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
InfoFilled
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
analysisType: '', // 'front-front', 'back-back', 'front-back', 'back-front'
|
||||
|
||||
@@ -586,7 +586,7 @@ export default {
|
||||
<style scoped>
|
||||
.dlt-lottery-page {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,41 +218,8 @@
|
||||
<script>
|
||||
import { dltLotteryApi } from '../../api/dlt/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElPagination,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElSelect,
|
||||
ElOption
|
||||
} from 'element-plus'
|
||||
import { Tickets } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'DltPredictRecords',
|
||||
components: {
|
||||
ElPageHeader,
|
||||
ElCard,
|
||||
ElButton,
|
||||
ElIcon,
|
||||
ElEmpty,
|
||||
ElTag,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElPagination,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
Tickets
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -80,14 +80,10 @@
|
||||
<script>
|
||||
import dltLotteryApi from '../../api/dlt/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption, ElMessage } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DltPrizeStatistics',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -272,43 +272,8 @@
|
||||
|
||||
<script>
|
||||
import { dltLotteryApi } from '@/api/dlt'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElTag,
|
||||
ElStatistic,
|
||||
ElTooltip,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElTable,
|
||||
ElTableColumn
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'DltSurfaceAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElTag,
|
||||
ElStatistic,
|
||||
ElTooltip,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
InfoFilled
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
analysisType: '', // 'front-front', 'front-back', 'back-back', 'back-front'
|
||||
|
||||
@@ -149,46 +149,8 @@
|
||||
|
||||
<script>
|
||||
import { dltLotteryApi } from '@/api/dlt'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElPagination,
|
||||
ElEmpty,
|
||||
ElIcon
|
||||
} from 'element-plus'
|
||||
import {
|
||||
ArrowLeft,
|
||||
Document,
|
||||
Sort,
|
||||
Histogram,
|
||||
Menu
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'DltTrendAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElPagination,
|
||||
ElEmpty,
|
||||
ElIcon,
|
||||
Document,
|
||||
Sort,
|
||||
Histogram,
|
||||
Menu
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -102,14 +102,10 @@
|
||||
<script>
|
||||
import dltLotteryApi from '../../api/dlt/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption, ElMessage } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DltUsageStats',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -976,44 +976,12 @@
|
||||
import { dltLotteryApi } from '../../api/dlt'
|
||||
import { userStore } from '../../store/user'
|
||||
import AlgorithmProcessModal from '../../components/AlgorithmProcessModal.vue'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ElMessage
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled, Trophy } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'DltHome',
|
||||
components: {
|
||||
AlgorithmProcessModal,
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ArrowLeft,
|
||||
InfoFilled,
|
||||
Trophy
|
||||
AlgorithmProcessModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -836,56 +836,10 @@
|
||||
import { lotteryApi } from '../../api'
|
||||
import { userStore } from '../../store/user'
|
||||
import AlgorithmProcessModal from '../../components/AlgorithmProcessModal.vue'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElTable,
|
||||
ElTableColumn
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, Warning, Check, InfoFilled, Trophy, QuestionFilled, Bell, Promotion } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: {
|
||||
AlgorithmProcessModal,
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ArrowLeft,
|
||||
Warning,
|
||||
Check,
|
||||
InfoFilled,
|
||||
QuestionFilled,
|
||||
Bell,
|
||||
Promotion,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
Trophy
|
||||
AlgorithmProcessModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -123,14 +123,10 @@
|
||||
<script>
|
||||
import api, { lotteryApi } from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption, ElMessage } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'HitAnalysis',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -1106,52 +1106,10 @@
|
||||
import { lotteryApi } from '../../api'
|
||||
import { userStore } from '../../store/user'
|
||||
import AlgorithmProcessModal from '../../components/AlgorithmProcessModal.vue'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ElSelect,
|
||||
ElOption
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, Warning, Check, InfoFilled, Trophy, QuestionFilled, Bell, Promotion } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: {
|
||||
AlgorithmProcessModal,
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSteps,
|
||||
ElStep,
|
||||
ElInput,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElDialog,
|
||||
ElAlert,
|
||||
ElCheckbox,
|
||||
ElDivider,
|
||||
ElSkeleton,
|
||||
ElTag,
|
||||
ArrowLeft,
|
||||
Warning,
|
||||
Check,
|
||||
InfoFilled,
|
||||
QuestionFilled,
|
||||
Bell,
|
||||
Promotion,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
Trophy
|
||||
AlgorithmProcessModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -2186,6 +2144,14 @@ export default {
|
||||
box-shadow: 0 6px 16px rgba(229, 62, 62, 0.4);
|
||||
}
|
||||
|
||||
.custom-btn-primary:active {
|
||||
transform: translateY(0) scale(0.97);
|
||||
}
|
||||
|
||||
.custom-btn-default:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
/* 消息弹窗特殊样式 */
|
||||
.custom-message-dialog {
|
||||
width: 400px;
|
||||
@@ -2282,7 +2248,7 @@ export default {
|
||||
/* 页面容器 */
|
||||
.home-container {
|
||||
padding: 20px 20px 8px 20px;
|
||||
background-color: #f0f2f5;
|
||||
background-color: var(--color-bg-page, #f0f2f5);
|
||||
min-height: calc(100vh - 70px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -2457,14 +2423,20 @@ export default {
|
||||
}
|
||||
|
||||
.position-item:hover {
|
||||
transform: translateY(-1px);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.position-item:active {
|
||||
transform: scale(0.97);
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
|
||||
.position-item.selected {
|
||||
border-color: #e53e3e;
|
||||
background: rgba(229, 62, 62, 0.1);
|
||||
border-color: var(--color-primary, #e53e3e);
|
||||
background: var(--color-primary-bg, rgba(229, 62, 62, 0.08));
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(229, 62, 62, 0.2);
|
||||
box-shadow: 0 4px 12px var(--color-primary-shadow, rgba(229, 62, 62, 0.2));
|
||||
}
|
||||
|
||||
.position-title {
|
||||
@@ -3138,7 +3110,7 @@ export default {
|
||||
}
|
||||
|
||||
.login-confirm-btn:active {
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(0.96);
|
||||
}
|
||||
|
||||
.single-btn {
|
||||
|
||||
@@ -263,33 +263,8 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '@/api'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'LineAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
InfoFilled
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
analysisType: '', // 'red-red', 'blue-blue', 'red-blue', 'blue-red'
|
||||
|
||||
@@ -577,7 +577,7 @@ export default {
|
||||
<style scoped>
|
||||
.ssq-lottery-page {
|
||||
min-height: calc(100vh - 70px);
|
||||
background: #f5f5f5;
|
||||
background: var(--color-bg-page, #f0f2f5);
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,14 +80,8 @@
|
||||
<script>
|
||||
import api from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'PrizeStatistics',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -93,28 +93,8 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '../../api/index.js'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElEmpty
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SsqTableAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElEmpty
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
drawsData: [],
|
||||
|
||||
@@ -251,43 +251,8 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '@/api'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElTag,
|
||||
ElStatistic,
|
||||
ElTooltip,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElTable,
|
||||
ElTableColumn
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft, InfoFilled } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'SurfaceAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElAvatar,
|
||||
ElDivider,
|
||||
ElAlert,
|
||||
ElResult,
|
||||
ElTag,
|
||||
ElStatistic,
|
||||
ElTooltip,
|
||||
ElIcon,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
InfoFilled
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
analysisType: '', // 'red-red', 'red-blue', 'blue-red'
|
||||
|
||||
@@ -149,46 +149,8 @@
|
||||
|
||||
<script>
|
||||
import { lotteryApi } from '@/api'
|
||||
import {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElPagination,
|
||||
ElEmpty,
|
||||
ElIcon
|
||||
} from 'element-plus'
|
||||
import {
|
||||
ArrowLeft,
|
||||
Document,
|
||||
Sort,
|
||||
Histogram,
|
||||
Menu
|
||||
} from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'TrendAnalysis',
|
||||
components: {
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
ElSkeleton,
|
||||
ElAlert,
|
||||
ElTable,
|
||||
ElTableColumn,
|
||||
ElPagination,
|
||||
ElEmpty,
|
||||
ElIcon,
|
||||
Document,
|
||||
Sort,
|
||||
Histogram,
|
||||
Menu
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -102,14 +102,8 @@
|
||||
<script>
|
||||
import api from '../../api/index.js'
|
||||
import { userStore } from '../../store/user.js'
|
||||
import { ElSelect, ElOption } from 'element-plus'
|
||||
|
||||
export default {
|
||||
name: 'UsageStats',
|
||||
components: {
|
||||
ElSelect,
|
||||
ElOption
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
Reference in New Issue
Block a user