+
-
+
-
+
-
+
@@ -99,198 +114,205 @@
diff --git a/admin/src/router/index.js b/admin/src/router/index.js
index 3b82e732..0a00bee4 100644
--- a/admin/src/router/index.js
+++ b/admin/src/router/index.js
@@ -1,108 +1,120 @@
-import { createRouter, createWebHistory } from 'vue-router'
-import { useUserStore } from '@/stores/user'
+import { createRouter, createWebHistory } from "vue-router";
+import { useUserStore } from "@/stores/user";
const routes = [
{
- path: '/login',
- name: 'Login',
- component: () => import('@/views/login/index.vue'),
- meta: { title: '登录', public: true }
+ path: "/login",
+ name: "Login",
+ component: () => import("@/views/login/index.vue"),
+ meta: { title: "登录", public: true },
},
{
- path: '/',
- component: () => import('@/layouts/MainLayout.vue'),
- redirect: '/dashboard',
+ path: "/",
+ component: () => import("@/layouts/MainLayout.vue"),
+ redirect: "/dashboard",
children: [
{
- path: 'dashboard',
- name: 'Dashboard',
- component: () => import('@/views/dashboard/index.vue'),
- meta: { title: '首页', icon: 'HomeFilled' }
+ path: "dashboard",
+ name: "Dashboard",
+ component: () => import("@/views/dashboard/index.vue"),
+ meta: { title: "首页", icon: "HomeFilled" },
},
{
- path: 'users',
- name: 'Users',
- component: () => import('@/views/user/index.vue'),
- meta: { title: '用户管理', icon: 'User', superAdmin: true }
+ path: "users",
+ name: "Users",
+ component: () => import("@/views/user/index.vue"),
+ meta: { title: "用户管理", icon: "User", superAdmin: true },
},
{
- path: 'stores',
- name: 'Stores',
- component: () => import('@/views/store/index.vue'),
- meta: { title: '门店管理', icon: 'OfficeBuilding', superAdmin: true }
+ path: "stores",
+ name: "Stores",
+ component: () => import("@/views/store/index.vue"),
+ meta: { title: "门店管理", icon: "OfficeBuilding", superAdmin: true },
},
{
- path: 'ladder',
- name: 'Ladder',
- component: () => import('@/views/ladder/index.vue'),
- meta: { title: '天梯用户', icon: 'TrendCharts' }
+ path: "ladder",
+ name: "Ladder",
+ component: () => import("@/views/ladder/index.vue"),
+ meta: { title: "天梯用户", icon: "TrendCharts" },
},
{
- path: 'matches',
- name: 'Matches',
- component: () => import('@/views/match/index.vue'),
- meta: { title: '比赛管理', icon: 'Trophy' }
+ path: "matches",
+ name: "Matches",
+ component: () => import("@/views/match/index.vue"),
+ meta: { title: "比赛管理", icon: "Trophy" },
},
{
- path: 'matches/:id',
- name: 'MatchDetail',
- component: () => import('@/views/match/detail.vue'),
- meta: { title: '比赛详情', hidden: true }
+ path: "matches/:id",
+ name: "MatchDetail",
+ component: () => import("@/views/match/detail.vue"),
+ meta: { title: "比赛详情", hidden: true },
},
{
- path: 'points/actions',
- name: 'PointActions',
- component: () => import('@/views/points/actions.vue'),
- meta: { title: '积分行为', icon: 'StarFilled' }
+ path: "points/actions",
+ name: "PointActions",
+ component: () => import("@/views/points/actions.vue"),
+ meta: { title: "积分行为", icon: "StarFilled" },
},
{
- path: 'points/products',
- name: 'PointProducts',
- component: () => import('@/views/points/products.vue'),
- meta: { title: '积分商品', icon: 'GoodsFilled' }
+ path: "points/products",
+ name: "PointProducts",
+ component: () => import("@/views/points/products.vue"),
+ meta: { title: "积分商品", icon: "GoodsFilled" },
},
{
- path: 'points/orders',
- name: 'PointOrders',
- component: () => import('@/views/points/orders.vue'),
- meta: { title: '兑换订单', icon: 'List' }
+ path: "points/orders",
+ name: "PointOrders",
+ component: () => import("@/views/points/orders.vue"),
+ meta: { title: "兑换订单", icon: "List" },
},
{
- path: 'system/users',
- name: 'SystemUsers',
- component: () => import('@/views/system/users.vue'),
- meta: { title: '系统用户', icon: 'UserFilled', superAdmin: true }
- }
- ]
- }
-]
+ path: "system/users",
+ name: "SystemUsers",
+ component: () => import("@/views/system/users.vue"),
+ meta: { title: "系统用户", icon: "UserFilled", superAdmin: true },
+ },
+ ],
+ },
+ {
+ path: "/display/ranking",
+ name: "RankingBoard",
+ component: () => import("@/views/display/RankingBoard.vue"),
+ meta: { title: "天梯排行大屏", public: true },
+ },
+ {
+ path: "/display/ranking-orange",
+ name: "RankingBoardOrange",
+ component: () => import("@/views/display/RankingBoardOrange.vue"),
+ meta: { title: "天梯排行大屏(橙色)", public: true },
+ },
+];
const router = createRouter({
history: createWebHistory(),
- routes
-})
+ routes,
+});
router.beforeEach((to, from, next) => {
- document.title = `${to.meta.title || ''} - 羽毛球俱乐部管理系统`
-
- if (to.meta.public) {
- next()
- return
- }
-
- const userStore = useUserStore()
- if (!userStore.token) {
- next('/login')
- return
- }
-
- // 超管权限检查
- if (to.meta.superAdmin && userStore.userInfo?.role !== 'super_admin') {
- next('/dashboard')
- return
- }
-
- next()
-})
+ document.title = `${to.meta.title || ""} - 英飒俱乐部管理系统`;
-export default router
+ if (to.meta.public) {
+ next();
+ return;
+ }
+
+ const userStore = useUserStore();
+ if (!userStore.token) {
+ next("/login");
+ return;
+ }
+
+ // 超管权限检查
+ if (to.meta.superAdmin && userStore.userInfo?.role !== "super_admin") {
+ next("/dashboard");
+ return;
+ }
+
+ next();
+});
+
+export default router;
diff --git a/admin/src/views/dashboard/index.vue b/admin/src/views/dashboard/index.vue
index d8379ee8..efe9f89f 100644
--- a/admin/src/views/dashboard/index.vue
+++ b/admin/src/views/dashboard/index.vue
@@ -51,6 +51,14 @@
扫码核销
+
+
+ 天梯大屏(蓝)
+
+
+
+ 天梯大屏(橙)
+
@@ -263,7 +271,7 @@
+
+
diff --git a/admin/src/views/display/RankingBoardOrange.vue b/admin/src/views/display/RankingBoardOrange.vue
new file mode 100644
index 00000000..5fe7e20a
--- /dev/null
+++ b/admin/src/views/display/RankingBoardOrange.vue
@@ -0,0 +1,858 @@
+
+
+
+
+
+
+
+
+
{{ currentTime }}
+
+ 🏆
+
英飒俱乐部 · 荣耀天梯
+ PREMIUM
+
+
+
+
+ 切换经典风格
+
+
+
场馆:
+
{{ currentStore?.name || "未选择" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
HALL OF FAME
+
+
+
+
NO.2
+
+
+ {{ rankingList[1].realName?.[0] || "?" }}
+
+
🥈
+
+
+
{{ rankingList[1].realName }}
+
{{ rankingList[1].powerScore }}
+
+ {{ rankingList[1].levelName }}
+ {{
+ Math.round(
+ (rankingList[1].matchCount * rankingList[1].winRate) /
+ 100,
+ )
+ }}胜
+
+
+
+
+
+
+
CHAMPION
+
+
+ {{ rankingList[0].realName?.[0] || "?" }}
+
+
👑
+
+
+
{{ rankingList[0].realName }}
+
{{ rankingList[0].powerScore }}
+
+ {{ rankingList[0].levelName }}
+ {{
+ Math.round(
+ (rankingList[0].matchCount * rankingList[0].winRate) /
+ 100,
+ )
+ }}胜
+
+
+
+
+
+
+
+
NO.3
+
+
+ {{ rankingList[2].realName?.[0] || "?" }}
+
+
🥉
+
+
+
{{ rankingList[2].realName }}
+
{{ rankingList[2].powerScore }}
+
+ {{ rankingList[2].levelName }}
+ {{
+ Math.round(
+ (rankingList[2].matchCount * rankingList[2].winRate) /
+ 100,
+ )
+ }}胜
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/admin/src/views/login/index.vue b/admin/src/views/login/index.vue
index 848a2605..c77d243c 100644
--- a/admin/src/views/login/index.vue
+++ b/admin/src/views/login/index.vue
@@ -5,57 +5,53 @@
-
+
-
-
+ @submit.prevent="handleLogin">
-
+ size="large" />
-
+
-
+ @keyup.enter="handleLogin" />
-
+
-
- {{ loading ? '登录中...' : '登 录' }}
+ @click="handleLogin">
+ {{ loading ? "登录中..." : "登 录" }}
-
+
@@ -64,158 +60,170 @@
diff --git a/miniprogram/app.json b/miniprogram/app.json
index 642dbea2..65545ac9 100644
--- a/miniprogram/app.json
+++ b/miniprogram/app.json
@@ -14,7 +14,7 @@
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#FF6B35",
- "navigationBarTitleText": "羽动俱乐部",
+ "navigationBarTitleText": "英飒俱乐部",
"navigationBarTextStyle": "white"
},
"tabBar": {
diff --git a/miniprogram/app.wxss b/miniprogram/app.wxss
index ec412e25..d6b91009 100644
--- a/miniprogram/app.wxss
+++ b/miniprogram/app.wxss
@@ -1,57 +1,68 @@
/* ==========================================
- 影沙俱乐部 - 全局样式
+ 英飒俱乐部 - 全局样式
设计理念:浅色高级感 · 橙色点缀 · 流畅动画
========================================== */
page {
/* 主色调:活力橙系 */
- --primary: #FF6B35;
- --primary-dark: #E85A28;
- --primary-light: #FF8C5A;
- --primary-soft: #FFF0EB;
- --primary-gradient: linear-gradient(135deg, #FF6B35 0%, #FF8C5A 50%, #FFBA08 100%);
- --primary-gradient-soft: linear-gradient(135deg, rgba(255,107,53,0.1) 0%, rgba(255,186,8,0.05) 100%);
-
+ --primary: #ff6b35;
+ --primary-dark: #e85a28;
+ --primary-light: #ff8c5a;
+ --primary-soft: #fff0eb;
+ --primary-gradient: linear-gradient(
+ 135deg,
+ #ff6b35 0%,
+ #ff8c5a 50%,
+ #ffba08 100%
+ );
+ --primary-gradient-soft: linear-gradient(
+ 135deg,
+ rgba(255, 107, 53, 0.1) 0%,
+ rgba(255, 186, 8, 0.05) 100%
+ );
+
/* 强调色 */
- --accent: #00C9A7;
- --accent-light: #E6FBF7;
+ --accent: #00c9a7;
+ --accent-light: #e6fbf7;
--accent-soft: rgba(0, 201, 167, 0.1);
-
+
/* 浅色背景系 */
- --bg-page: #F7F8FA;
- --bg-white: #FFFFFF;
- --bg-card: #FFFFFF;
- --bg-card-hover: #FAFBFC;
- --bg-soft: #F2F3F5;
- --bg-warm: #FFFBF8;
-
+ --bg-page: #f7f8fa;
+ --bg-white: #ffffff;
+ --bg-card: #ffffff;
+ --bg-card-hover: #fafbfc;
+ --bg-soft: #f2f3f5;
+ --bg-warm: #fffbf8;
+
/* 文字颜色 */
- --text-primary: #1A1A1A;
- --text-secondary: #5C5C5C;
- --text-muted: #8C8C8C;
- --text-hint: #BFBFBF;
- --text-white: #FFFFFF;
-
+ --text-primary: #1a1a1a;
+ --text-secondary: #5c5c5c;
+ --text-muted: #8c8c8c;
+ --text-hint: #bfbfbf;
+ --text-white: #ffffff;
+
/* 边框 */
- --border-light: #EBEDF0;
- --border-soft: #F0F1F2;
+ --border-light: #ebedf0;
+ --border-soft: #f0f1f2;
--border-primary: rgba(255, 107, 53, 0.2);
-
+
/* 阴影 */
--shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
--shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
--shadow-lg: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
--shadow-primary: 0 8rpx 24rpx rgba(255, 107, 53, 0.25);
--shadow-card: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
-
+
/* 圆角 */
--radius-sm: 12rpx;
--radius-md: 16rpx;
--radius-lg: 24rpx;
--radius-xl: 32rpx;
--radius-full: 100rpx;
-
- font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', sans-serif;
+
+ font-family:
+ -apple-system, BlinkMacSystemFont, "SF Pro Display", "PingFang SC",
+ "Helvetica Neue", sans-serif;
font-size: 28rpx;
color: var(--text-primary);
background: var(--bg-page);
@@ -68,11 +79,26 @@ page {
background: var(--bg-page);
}
-.flex { display: flex; }
-.flex-center { display: flex; align-items: center; justify-content: center; }
-.flex-between { display: flex; align-items: center; justify-content: space-between; }
-.flex-column { display: flex; flex-direction: column; }
-.flex-1 { flex: 1; }
+.flex {
+ display: flex;
+}
+.flex-center {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.flex-between {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.flex-column {
+ display: flex;
+ flex-direction: column;
+}
+.flex-1 {
+ flex: 1;
+}
/* ==========================================
卡片组件 - 高级感设计
@@ -96,11 +122,13 @@ page {
.card-highlight {
background: var(--bg-white);
border: 1rpx solid var(--border-primary);
- box-shadow: var(--shadow-card), 0 0 0 1rpx rgba(255, 107, 53, 0.05);
+ box-shadow:
+ var(--shadow-card),
+ 0 0 0 1rpx rgba(255, 107, 53, 0.05);
}
.card-highlight::before {
- content: '';
+ content: "";
position: absolute;
top: 0;
left: 0;
@@ -133,19 +161,29 @@ page {
}
.btn-primary::after {
- content: '';
+ content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
- background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
+ background: linear-gradient(
+ 90deg,
+ transparent,
+ rgba(255, 255, 255, 0.3),
+ transparent
+ );
animation: btn-shimmer 2.5s ease-in-out infinite;
}
@keyframes btn-shimmer {
- 0% { left: -100%; }
- 50%, 100% { left: 100%; }
+ 0% {
+ left: -100%;
+ }
+ 50%,
+ 100% {
+ left: 100%;
+ }
}
.btn-secondary {
@@ -188,28 +226,28 @@ page {
}
.level-tag.lv1 {
- background: linear-gradient(135deg, #E8F5E9, #C8E6C9);
- color: #2E7D32;
+ background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
+ color: #2e7d32;
}
.level-tag.lv2 {
- background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
- color: #1565C0;
+ background: linear-gradient(135deg, #e3f2fd, #bbdefb);
+ color: #1565c0;
}
.level-tag.lv3 {
- background: linear-gradient(135deg, #FFF3E0, #FFE0B2);
- color: #E65100;
+ background: linear-gradient(135deg, #fff3e0, #ffe0b2);
+ color: #e65100;
}
.level-tag.lv4 {
- background: linear-gradient(135deg, #FCE4EC, #F8BBD9);
- color: #C2185B;
+ background: linear-gradient(135deg, #fce4ec, #f8bbd9);
+ color: #c2185b;
}
.level-tag.lv5 {
- background: linear-gradient(135deg, #F3E5F5, #E1BEE7);
- color: #7B1FA2;
+ background: linear-gradient(135deg, #f3e5f5, #e1bee7);
+ color: #7b1fa2;
}
/* ==========================================
@@ -228,20 +266,20 @@ page {
}
.rank-badge.top1 {
- background: linear-gradient(135deg, #FFD700 0%, #FFAA00 100%);
- color: #8B4513;
+ background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
+ color: #8b4513;
box-shadow: 0 4rpx 16rpx rgba(255, 170, 0, 0.4);
}
.rank-badge.top2 {
- background: linear-gradient(135deg, #E8E8E8 0%, #C0C0C0 100%);
- color: #4A4A4A;
+ background: linear-gradient(135deg, #e8e8e8 0%, #c0c0c0 100%);
+ color: #4a4a4a;
box-shadow: 0 4rpx 12rpx rgba(192, 192, 192, 0.4);
}
.rank-badge.top3 {
- background: linear-gradient(135deg, #DEB887 0%, #CD853F 100%);
- color: #5C4033;
+ background: linear-gradient(135deg, #deb887 0%, #cd853f 100%);
+ color: #5c4033;
box-shadow: 0 4rpx 12rpx rgba(205, 133, 63, 0.4);
}
@@ -355,13 +393,13 @@ page {
}
.tag-warning {
- background: #FFF8E6;
- color: #FA8C16;
+ background: #fff8e6;
+ color: #fa8c16;
}
.tag-danger {
- background: #FFF1F0;
- color: #FF4D4F;
+ background: #fff1f0;
+ color: #ff4d4f;
}
/* ==========================================
@@ -377,7 +415,7 @@ page {
}
.power-change.negative {
- color: #FF4D4F;
+ color: #ff4d4f;
}
/* ==========================================
@@ -474,7 +512,8 @@ page {
/* 脉冲效果 */
@keyframes pulse {
- 0%, 100% {
+ 0%,
+ 100% {
transform: scale(1);
opacity: 1;
}
@@ -486,7 +525,8 @@ page {
/* 呼吸发光 */
@keyframes breathe {
- 0%, 100% {
+ 0%,
+ 100% {
box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.25);
}
50% {
@@ -496,28 +536,50 @@ page {
/* 渐变流动 */
@keyframes gradientFlow {
- 0% { background-position: 0% 50%; }
- 50% { background-position: 100% 50%; }
- 100% { background-position: 0% 50%; }
+ 0% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+ 100% {
+ background-position: 0% 50%;
+ }
}
/* 旋转 */
@keyframes spin {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
}
/* 摇摆 */
@keyframes swing {
- 0%, 100% { transform: rotate(0deg); }
- 25% { transform: rotate(3deg); }
- 75% { transform: rotate(-3deg); }
+ 0%,
+ 100% {
+ transform: rotate(0deg);
+ }
+ 25% {
+ transform: rotate(3deg);
+ }
+ 75% {
+ transform: rotate(-3deg);
+ }
}
/* 闪烁 */
@keyframes blink {
- 0%, 100% { opacity: 1; }
- 50% { opacity: 0.6; }
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.6;
+ }
}
/* 波纹扩散 */
@@ -566,11 +628,21 @@ page {
}
/* 延迟类 */
-.delay-1 { animation-delay: 0.1s; }
-.delay-2 { animation-delay: 0.2s; }
-.delay-3 { animation-delay: 0.3s; }
-.delay-4 { animation-delay: 0.4s; }
-.delay-5 { animation-delay: 0.5s; }
+.delay-1 {
+ animation-delay: 0.1s;
+}
+.delay-2 {
+ animation-delay: 0.2s;
+}
+.delay-3 {
+ animation-delay: 0.3s;
+}
+.delay-4 {
+ animation-delay: 0.4s;
+}
+.delay-5 {
+ animation-delay: 0.5s;
+}
/* ==========================================
页面过渡效果
@@ -580,16 +652,36 @@ page {
}
/* 列表项依次入场 */
-.stagger-item:nth-child(1) { animation-delay: 0s; }
-.stagger-item:nth-child(2) { animation-delay: 0.05s; }
-.stagger-item:nth-child(3) { animation-delay: 0.1s; }
-.stagger-item:nth-child(4) { animation-delay: 0.15s; }
-.stagger-item:nth-child(5) { animation-delay: 0.2s; }
-.stagger-item:nth-child(6) { animation-delay: 0.25s; }
-.stagger-item:nth-child(7) { animation-delay: 0.3s; }
-.stagger-item:nth-child(8) { animation-delay: 0.35s; }
-.stagger-item:nth-child(9) { animation-delay: 0.4s; }
-.stagger-item:nth-child(10) { animation-delay: 0.45s; }
+.stagger-item:nth-child(1) {
+ animation-delay: 0s;
+}
+.stagger-item:nth-child(2) {
+ animation-delay: 0.05s;
+}
+.stagger-item:nth-child(3) {
+ animation-delay: 0.1s;
+}
+.stagger-item:nth-child(4) {
+ animation-delay: 0.15s;
+}
+.stagger-item:nth-child(5) {
+ animation-delay: 0.2s;
+}
+.stagger-item:nth-child(6) {
+ animation-delay: 0.25s;
+}
+.stagger-item:nth-child(7) {
+ animation-delay: 0.3s;
+}
+.stagger-item:nth-child(8) {
+ animation-delay: 0.35s;
+}
+.stagger-item:nth-child(9) {
+ animation-delay: 0.4s;
+}
+.stagger-item:nth-child(10) {
+ animation-delay: 0.45s;
+}
/* ==========================================
装饰元素
diff --git a/miniprogram/env-template.txt b/miniprogram/env-template.txt
index 64a0fbd9..56837b09 100644
--- a/miniprogram/env-template.txt
+++ b/miniprogram/env-template.txt
@@ -1,5 +1,5 @@
================================================================================
- 影沙俱乐部小程序配置说明
+ 英飒俱乐部小程序配置说明
================================================================================
【配置文件位置】
diff --git a/miniprogram/pages/user/index.wxml b/miniprogram/pages/user/index.wxml
index 1bdef35d..7a2e425b 100644
--- a/miniprogram/pages/user/index.wxml
+++ b/miniprogram/pages/user/index.wxml
@@ -1,10 +1,9 @@
-
+
-
@@ -17,7 +16,6 @@
✏️
-
{{userInfo.nickname || '新用户'}}
@@ -38,7 +36,6 @@
-
@@ -58,7 +55,6 @@
出示给对方扫码挑战
-
@@ -66,31 +62,23 @@
-
开启你的运动之旅
- 授权手机号,加入影沙俱乐部
+ 授权手机号,加入英飒俱乐部
-
-
-
-
@@ -98,7 +86,6 @@
{{ladderUser.realName}}
-
战力值
@@ -108,24 +95,26 @@
-
{{ladderUser.winCount || 0}}
胜场
- {{(ladderUser.matchCount || 0) - (ladderUser.winCount || 0)}}
+
+ {{(ladderUser.matchCount || 0) - (ladderUser.winCount || 0)}}
+
负场
- {{(ladderUser.matchCount > 0 && ladderUser.winCount !== null && ladderUser.winCount !== undefined) ? Math.round((Number(ladderUser.winCount) || 0) / Number(ladderUser.matchCount) * 100) : 0}}%
+
+ {{(ladderUser.matchCount > 0 && ladderUser.winCount !== null && ladderUser.winCount !== undefined) ? Math.round((Number(ladderUser.winCount) || 0) / Number(ladderUser.matchCount) * 100) : 0}}%
+
胜率
-
🏸
@@ -134,7 +123,6 @@
请联系门店工作人员,开启你的天梯之旅
-
-
-
-
-
@@ -176,7 +160,6 @@
我的会员码
×
-
@@ -185,13 +168,7 @@
生成中...
-
+
@@ -200,12 +177,10 @@
-
会员码
{{userInfo.memberCode}}
-
📱
@@ -214,7 +189,6 @@
-
@@ -222,47 +196,34 @@
{{isEditMode ? '修改资料' : '完善个人资料'}}
×
-
💡
完善资料后,好友可以更容易找到你
-
头像
-
+
📷
点击更换头像
-
昵称
-
+
-
-
+
\ No newline at end of file
diff --git a/miniprogram/project.config.json b/miniprogram/project.config.json
index 5bfff837..b81740b1 100644
--- a/miniprogram/project.config.json
+++ b/miniprogram/project.config.json
@@ -1,5 +1,5 @@
{
- "description": "羽毛球俱乐部小程序",
+ "description": "英飒俱乐部小程序",
"packOptions": {
"ignore": [],
"include": []
@@ -56,4 +56,4 @@
"tabSize": 2
},
"simulatorPluginLibVersion": {}
-}
\ No newline at end of file
+}
diff --git a/miniprogram/utils/util.js b/miniprogram/utils/util.js
index a817f824..e33e13a0 100644
--- a/miniprogram/utils/util.js
+++ b/miniprogram/utils/util.js
@@ -1,73 +1,74 @@
// 格式化日期
-const formatDate = (date, format = 'YYYY-MM-DD HH:mm') => {
- if (!date) return ''
- const d = new Date(date)
- const year = d.getFullYear()
- const month = String(d.getMonth() + 1).padStart(2, '0')
- const day = String(d.getDate()).padStart(2, '0')
- const hour = String(d.getHours()).padStart(2, '0')
- const minute = String(d.getMinutes()).padStart(2, '0')
- const second = String(d.getSeconds()).padStart(2, '0')
+const formatDate = (date, format = "YYYY-MM-DD HH:mm") => {
+ if (!date) return "";
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = String(d.getMonth() + 1).padStart(2, "0");
+ const day = String(d.getDate()).padStart(2, "0");
+ const hour = String(d.getHours()).padStart(2, "0");
+ const minute = String(d.getMinutes()).padStart(2, "0");
+ const second = String(d.getSeconds()).padStart(2, "0");
return format
- .replace('YYYY', year)
- .replace('MM', month)
- .replace('DD', day)
- .replace('HH', hour)
- .replace('mm', minute)
- .replace('ss', second)
-}
+ .replace("YYYY", year)
+ .replace("MM", month)
+ .replace("DD", day)
+ .replace("HH", hour)
+ .replace("mm", minute)
+ .replace("ss", second);
+};
// 等级名称
const levelNames = {
- 1: '新锐',
- 2: '精锐',
- 3: '高手',
- 4: '大师',
- 5: '宗师'
-}
+ 1: "新锐",
+ 2: "精锐",
+ 3: "高手",
+ 4: "大师",
+ 5: "宗师",
+};
-const getLevelName = (level) => levelNames[level] || '未知'
+const getLevelName = (level) => levelNames[level] || "未知";
// 等级描述
const levelDescs = {
- 1: '掌握基础动作,能进行多拍回合。',
- 2: '技术较全面,具备初步的战术意识。',
- 3: '技术稳定,战术意图清晰,比赛经验丰富。',
- 4: '在俱乐部内属顶尖战力,具备较强掌控力。',
- 5: '技术全面,战术素养高,是俱乐部标杆。'
-}
+ 1: "掌握基础动作,能进行多拍回合。",
+ 2: "技术较全面,具备初步的战术意识。",
+ 3: "技术稳定,战术意图清晰,比赛经验丰富。",
+ 4: "在英飒俱乐部内属顶尖战力,具备较强掌控力。",
+ 5: "技术全面,战术素养高,是英飒俱乐部标杆。",
+};
-const getLevelDesc = (level) => levelDescs[level] || ''
+const getLevelDesc = (level) => levelDescs[level] || "";
// 比赛状态
const matchStatusTexts = {
- 0: '待开始',
- 1: '进行中',
- 2: '已结束',
- 3: '已取消'
-}
+ 0: "待开始",
+ 1: "进行中",
+ 2: "已结束",
+ 3: "已取消",
+};
-const getMatchStatusText = (status) => matchStatusTexts[status] || '未知'
+const getMatchStatusText = (status) => matchStatusTexts[status] || "未知";
// 订单状态
const orderStatusTexts = {
- 0: '待核销',
- 1: '已完成',
- 2: '已取消'
-}
+ 0: "待核销",
+ 1: "已完成",
+ 2: "已取消",
+};
-const getOrderStatusText = (status) => orderStatusTexts[status] || '未知'
+const getOrderStatusText = (status) => orderStatusTexts[status] || "未知";
// 生成随机字符串
const randomString = (len = 16) => {
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
- let result = ''
+ const chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ let result = "";
for (let i = 0; i < len; i++) {
- result += chars.charAt(Math.floor(Math.random() * chars.length))
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
}
- return result
-}
+ return result;
+};
module.exports = {
formatDate,
@@ -75,5 +76,5 @@ module.exports = {
getLevelDesc,
getMatchStatusText,
getOrderStatusText,
- randomString
-}
+ randomString,
+};
diff --git a/server/env-template.txt b/server/env-template.txt
index 3ce30f24..2d10a2b0 100644
--- a/server/env-template.txt
+++ b/server/env-template.txt
@@ -1,5 +1,5 @@
# ==========================================
-# 影杀俱乐部管理系统 - 环境配置模板
+# 英飒俱乐部管理系统 - 环境配置模板
# ==========================================
# 使用说明:
# 1. 复制此文件为 .env
diff --git a/server/package.json b/server/package.json
index c08e1dd9..4ea006d7 100644
--- a/server/package.json
+++ b/server/package.json
@@ -1,7 +1,7 @@
{
"name": "yingsha-server",
"version": "1.0.0",
- "description": "羽毛球俱乐部管理系统后端服务",
+ "description": "英飒俱乐部管理系统后端服务",
"main": "src/app.js",
"scripts": {
"start": "node src/app.js",
diff --git a/server/src/config/constants.js b/server/src/config/constants.js
index 4aba423f..a661e81d 100644
--- a/server/src/config/constants.js
+++ b/server/src/config/constants.js
@@ -1,88 +1,88 @@
// 用户等级
const LADDER_LEVELS = {
- LV1_ROOKIE: 1, // 新锐
- LV2_ELITE: 2, // 精锐
- LV3_EXPERT: 3, // 高手
- LV4_MASTER: 4, // 大师
- LV5_GRANDMASTER: 5 // 宗师
+ LV1_ROOKIE: 1, // 新锐
+ LV2_ELITE: 2, // 精锐
+ LV3_EXPERT: 3, // 高手
+ LV4_MASTER: 4, // 大师
+ LV5_GRANDMASTER: 5, // 宗师
};
const LADDER_LEVEL_NAMES = {
- 1: '新锐',
- 2: '精锐',
- 3: '高手',
- 4: '大师',
- 5: '宗师'
+ 1: "新锐",
+ 2: "精锐",
+ 3: "高手",
+ 4: "大师",
+ 5: "宗师",
};
const LADDER_LEVEL_DESC = {
- 1: '掌握基础动作,能进行多拍回合。',
- 2: '技术较全面,具备初步的战术意识。',
- 3: '技术稳定,战术意图清晰,比赛经验丰富。',
- 4: '在俱乐部内属顶尖战力,具备较强掌控力。',
- 5: '技术全面,战术素养高,是俱乐部标杆。'
+ 1: "掌握基础动作,能进行多拍回合。",
+ 2: "技术较全面,具备初步的战术意识。",
+ 3: "技术稳定,战术意图清晰,比赛经验丰富。",
+ 4: "在英飒俱乐部内属顶尖战力,具备较强掌控力。",
+ 5: "技术全面,战术素养高,是英飒俱乐部标杆。",
};
// 比赛类型
const MATCH_TYPES = {
- CHALLENGE: 1, // 挑战赛
- RANKING: 2 // 排位赛
+ CHALLENGE: 1, // 挑战赛
+ RANKING: 2, // 排位赛
};
// 比赛状态
const MATCH_STATUS = {
- PENDING: 0, // 待开始
- ONGOING: 1, // 进行中
- FINISHED: 2, // 已结束
- CANCELLED: 3 // 已取消
+ PENDING: 0, // 待开始
+ ONGOING: 1, // 进行中
+ FINISHED: 2, // 已结束
+ CANCELLED: 3, // 已取消
};
// 排位赛阶段
const RANKING_STAGE = {
- SIGNUP: 0, // 报名中
- ROUND_ROBIN: 1, // 循环赛
- ELIMINATION: 2, // 淘汰赛
- FINISHED: 3 // 已结束
+ SIGNUP: 0, // 报名中
+ ROUND_ROBIN: 1, // 循环赛
+ ELIMINATION: 2, // 淘汰赛
+ FINISHED: 3, // 已结束
};
// 比赛确认状态
const CONFIRM_STATUS = {
- PENDING: 0, // 待确认
- CONFIRMED: 1, // 已确认
- DISPUTED: 2 // 有争议
+ PENDING: 0, // 待确认
+ CONFIRMED: 1, // 已确认
+ DISPUTED: 2, // 有争议
};
// 积分订单状态
const ORDER_STATUS = {
- PENDING: 0, // 待核销
- COMPLETED: 1, // 已完成
- CANCELLED: 2 // 已取消
+ PENDING: 0, // 待核销
+ COMPLETED: 1, // 已完成
+ CANCELLED: 2, // 已取消
};
// 战力值计算参数
const POWER_CALC = {
- BASE_WIN: 15, // 基础胜场分
- BASE_LOSE: -5, // 基础负场分
+ BASE_WIN: 15, // 基础胜场分
+ BASE_LOSE: -5, // 基础负场分
UNDERDOG_THRESHOLD: 100, // 以下克上分差阈值
- UNDERDOG_RATE: 0.1, // 以下克上奖励比例
- MAX_CHANGE: 50, // 单场最大变动
- NEWBIE_PROTECTION: 5, // 新手保护场次
- NEWBIE_LOSE_RATE: 0.5, // 新手输分减半
+ UNDERDOG_RATE: 0.1, // 以下克上奖励比例
+ MAX_CHANGE: 50, // 单场最大变动
+ NEWBIE_PROTECTION: 5, // 新手保护场次
+ NEWBIE_LOSE_RATE: 0.5, // 新手输分减半
MIN_MONTHLY_MATCHES: 3, // 每月最低参赛场次
- CHALLENGE_COOLDOWN: 30 // 挑战赛同人冷却天数
+ CHALLENGE_COOLDOWN: 30, // 挑战赛同人冷却天数
};
// 比赛权重
const MATCH_WEIGHTS = {
- DAILY: 1.0, // 日常畅打
- CHALLENGE: 1.5, // 挑战赛
- MONTHLY: 1.5, // 月度排位赛
- SEASONAL: 2.0 // 季度/年度总决赛
+ DAILY: 1.0, // 日常畅打
+ CHALLENGE: 1.5, // 挑战赛
+ MONTHLY: 1.5, // 月度排位赛
+ SEASONAL: 2.0, // 季度/年度总决赛
};
// 积分计算
const POINTS_CALC = {
- CONSUME_RATE: 0.1 // 每10元1分
+ CONSUME_RATE: 0.1, // 每10元1分
};
module.exports = {
@@ -96,5 +96,5 @@ module.exports = {
ORDER_STATUS,
POWER_CALC,
MATCH_WEIGHTS,
- POINTS_CALC
+ POINTS_CALC,
};
diff --git a/server/src/controllers/ladderController.js b/server/src/controllers/ladderController.js
index e7ed90c0..56ebf2ca 100644
--- a/server/src/controllers/ladderController.js
+++ b/server/src/controllers/ladderController.js
@@ -8,7 +8,7 @@ class LadderController {
// 获取天梯排名
async getRanking(req, res) {
try {
- const { store_id, gender, level, page = 1, pageSize = 50 } = req.query;
+ const { store_id, gender, level, page = 1, pageSize = 50, is_display } = req.query;
const { limit, offset } = getPagination(page, pageSize);
if (!store_id) {
@@ -17,10 +17,14 @@ class LadderController {
const where = {
store_id,
- status: 1,
- monthly_match_count: { [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES }
+ status: 1
};
+ // 如果不是大屏显示,则需要满足每月最低参赛场次限制
+ if (!is_display) {
+ where.monthly_match_count = { [Op.gte]: POWER_CALC.MIN_MONTHLY_MATCHES };
+ }
+
if (gender) {
where.gender = gender;
}