From ff960d17241894274bba702d7d86d6dc91e4646f Mon Sep 17 00:00:00 2001
From: lihanqi <13868246742@163.com>
Date: Sat, 14 Feb 2026 11:56:57 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=89=8D=E7=AB=AFUI/UX=E5=85=A8?=
=?UTF-8?q?=E9=9D=A2=E4=BC=98=E5=8C=96=20-=20CSS=E5=8F=98=E9=87=8F?=
=?UTF-8?q?=E7=B3=BB=E7=BB=9F/=E4=BA=A4=E4=BA=92=E5=8A=A8=E7=94=BB/?=
=?UTF-8?q?=E6=8C=89=E4=B8=8B=E5=8F=8D=E9=A6=88/=E5=BC=B9=E7=AA=97?=
=?UTF-8?q?=E5=8A=A8=E7=94=BB/=E8=BE=93=E5=85=A5=E6=A1=86=E8=81=9A?=
=?UTF-8?q?=E7=84=A6=E5=A2=9E=E5=BC=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/assets/home/default-avatar.svg | 5 +
src/App.vue | 53 +++++-
src/assets/base.css | 96 ++++------
src/components/BottomNavigation.vue | 46 +++--
src/components/HelloWorld.vue | 44 -----
src/components/TheWelcome.vue | 94 ---------
src/components/WelcomeItem.vue | 87 ---------
src/components/icons/IconCommunity.vue | 7 -
src/components/icons/IconDocumentation.vue | 7 -
src/components/icons/IconEcosystem.vue | 7 -
src/components/icons/IconSupport.vue | 7 -
src/components/icons/IconTooling.vue | 19 --
src/store/user.js | 2 +-
src/utils/format.js | 75 ++++++++
src/views/DataAnalysis.vue | 38 +++-
src/views/ExcelImportManagement.vue | 29 +--
src/views/ExchangeRecords.vue | 48 +----
src/views/Login.vue | 190 +++++++++++--------
src/views/LotteryInfo.vue | 2 +-
src/views/LotteryPremium.vue | 36 ++--
src/views/LotterySelection.vue | 60 +++---
src/views/PredictRecords.vue | 38 +---
src/views/Profile.vue | 61 +++---
src/views/Register.vue | 37 +---
src/views/ResetPassword.vue | 12 +-
src/views/UserAgreement.vue | 6 -
src/views/admin/AdminLogin.vue | 7 -
src/views/admin/AnnouncementManagement.vue | 22 ---
src/views/admin/Dashboard.vue | 30 ---
src/views/admin/DltExcelImportManagement.vue | 29 +--
src/views/admin/ExcelImportManagement.vue | 29 +--
src/views/admin/OperationHistory.vue | 12 --
src/views/admin/UserList.vue | 16 --
src/views/admin/VipCodeManagement.vue | 22 ---
src/views/admin/layout/AdminLayout.vue | 32 +---
src/views/dlt/DltTableAnalysis.vue | 20 --
src/views/dlt/HitAnalysis.vue | 6 +-
src/views/dlt/Home.vue | 48 ++---
src/views/dlt/LineAnalysis.vue | 25 ---
src/views/dlt/Lottery.vue | 2 +-
src/views/dlt/PredictRecords.vue | 33 ----
src/views/dlt/PrizeStatistics.vue | 6 +-
src/views/dlt/SurfaceAnalysis.vue | 35 ----
src/views/dlt/TrendAnalysis.vue | 38 ----
src/views/dlt/UsageStats.vue | 6 +-
src/views/jt/DltHome.vue | 36 +---
src/views/jt/SsqHome.vue | 48 +----
src/views/ssq/HitAnalysis.vue | 6 +-
src/views/ssq/Home.vue | 70 ++-----
src/views/ssq/LineAnalysis.vue | 25 ---
src/views/ssq/Lottery.vue | 2 +-
src/views/ssq/PrizeStatistics.vue | 6 -
src/views/ssq/SsqTableAnalysis.vue | 20 --
src/views/ssq/SurfaceAnalysis.vue | 35 ----
src/views/ssq/TrendAnalysis.vue | 38 ----
src/views/ssq/UsageStats.vue | 6 -
56 files changed, 476 insertions(+), 1340 deletions(-)
create mode 100644 public/assets/home/default-avatar.svg
delete mode 100644 src/components/HelloWorld.vue
delete mode 100644 src/components/TheWelcome.vue
delete mode 100644 src/components/WelcomeItem.vue
delete mode 100644 src/components/icons/IconCommunity.vue
delete mode 100644 src/components/icons/IconDocumentation.vue
delete mode 100644 src/components/icons/IconEcosystem.vue
delete mode 100644 src/components/icons/IconSupport.vue
delete mode 100644 src/components/icons/IconTooling.vue
create mode 100644 src/utils/format.js
diff --git a/public/assets/home/default-avatar.svg b/public/assets/home/default-avatar.svg
new file mode 100644
index 0000000..efb95f3
--- /dev/null
+++ b/public/assets/home/default-avatar.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/App.vue b/src/App.vue
index 19d3bed..4fbd2d5 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -64,7 +64,11 @@ onMounted(async () => {
-
+
+
+
+
+
@@ -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;
+}
+
diff --git a/src/assets/base.css b/src/assets/base.css
index 8816868..2c0e930 100644
--- a/src/assets/base.css
+++ b/src/assets/base.css
@@ -1,53 +1,51 @@
-/* color palette from */
+/* 精彩猪手 - 设计变量系统 */
: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;
diff --git a/src/components/BottomNavigation.vue b/src/components/BottomNavigation.vue
index bac2300..fee7d85 100644
--- a/src/components/BottomNavigation.vue
+++ b/src/components/BottomNavigation.vue
@@ -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;
}
diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue
deleted file mode 100644
index eff59f1..0000000
--- a/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
{{ msg }}
-
- You’ve successfully created a project with
- Vite +
- Vue 3 .
-
-
-
-
-
diff --git a/src/components/TheWelcome.vue b/src/components/TheWelcome.vue
deleted file mode 100644
index fe48afc..0000000
--- a/src/components/TheWelcome.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-
- Documentation
-
- Vue’s
- official documentation
- provides you with all information you need to get started.
-
-
-
-
-
-
- Tooling
-
- This project is served and bundled with
- Vite . The
- recommended IDE setup is
- VSCode
- +
- Vue - Official . If
- you need to test your components and web pages, check out
- Vitest
- and
- Cypress
- /
- Playwright .
-
-
-
- More instructions are available in
- README.md .
-
-
-
-
-
-
- Ecosystem
-
- Get official tools and libraries for your project:
- Pinia ,
- Vue Router ,
- Vue Test Utils , and
- Vue Dev Tools . If
- you need more resources, we suggest paying
- Awesome Vue
- a visit.
-
-
-
-
-
-
- Community
-
- Got stuck? Ask your question on
- Vue Land
- (our official Discord server), or
- StackOverflow . You should also follow the official
- @vuejs.org
- Bluesky account or the
- @vuejs
- X account for latest news in the Vue world.
-
-
-
-
-
-
- Support Vue
-
- As an independent project, Vue relies on community backing for its sustainability. You can help
- us by
- becoming a sponsor .
-
-
diff --git a/src/components/WelcomeItem.vue b/src/components/WelcomeItem.vue
deleted file mode 100644
index 6d7086a..0000000
--- a/src/components/WelcomeItem.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
diff --git a/src/components/icons/IconCommunity.vue b/src/components/icons/IconCommunity.vue
deleted file mode 100644
index 2dc8b05..0000000
--- a/src/components/icons/IconCommunity.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/icons/IconDocumentation.vue b/src/components/icons/IconDocumentation.vue
deleted file mode 100644
index 6d4791c..0000000
--- a/src/components/icons/IconDocumentation.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/icons/IconEcosystem.vue b/src/components/icons/IconEcosystem.vue
deleted file mode 100644
index c3a4f07..0000000
--- a/src/components/icons/IconEcosystem.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/icons/IconSupport.vue b/src/components/icons/IconSupport.vue
deleted file mode 100644
index 7452834..0000000
--- a/src/components/icons/IconSupport.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/icons/IconTooling.vue b/src/components/icons/IconTooling.vue
deleted file mode 100644
index 660598d..0000000
--- a/src/components/icons/IconTooling.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
diff --git a/src/store/user.js b/src/store/user.js
index b7260fd..d6e55ce 100644
--- a/src/store/user.js
+++ b/src/store/user.js
@@ -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: {
diff --git a/src/utils/format.js b/src/utils/format.js
new file mode 100644
index 0000000..0f0e4db
--- /dev/null
+++ b/src/utils/format.js
@@ -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')
+}
diff --git a/src/views/DataAnalysis.vue b/src/views/DataAnalysis.vue
index d1153b3..7c7ec7a 100644
--- a/src/views/DataAnalysis.vue
+++ b/src/views/DataAnalysis.vue
@@ -156,13 +156,8 @@