From 0e936b8e2087439b4237c59f2f43daa6fcb2fd3a Mon Sep 17 00:00:00 2001
From: zhangyibo95 <690096405@qq.com>
Date: Sat, 9 May 2026 10:04:15 +0800
Subject: [PATCH] =?UTF-8?q?update:=E6=8E=92=E4=BD=8D=E8=B5=9B=E7=95=8C?=
=?UTF-8?q?=E9=9D=A2=E3=80=81=E6=8E=92=E8=A1=8C=E6=A6=9C=E7=95=8C=E9=9D=A2?=
=?UTF-8?q?=E6=94=B9=E7=89=88=EF=BC=8C=E6=96=B0=E5=A2=9Eagents=E6=8F=8F?=
=?UTF-8?q?=E8=BF=B0=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
AGENTS.md | 269 +++++++++++
src/apis.js | 60 +++
src/components/AppBackground.vue | 8 +-
src/pages/index.vue | 28 +-
src/pages/rank-list.vue | 509 +++++++++++++++++----
src/pages/ranking.vue | 710 ++++++++++++++++++++----------
src/static/battle-choose.png | Bin 7946 -> 0 bytes
src/static/battle10.png | Bin 6274 -> 0 bytes
src/static/battle1v1.png | Bin 5711 -> 0 bytes
src/static/battle2v2.png | Bin 4217 -> 0 bytes
src/static/battle3v3.png | Bin 3603 -> 0 bytes
src/static/battle5.png | Bin 6477 -> 0 bytes
src/static/rank/battle-choose.png | Bin 0 -> 9000 bytes
src/static/rank/battle10.png | Bin 0 -> 6696 bytes
src/static/rank/battle1v1.png | Bin 0 -> 5581 bytes
src/static/rank/battle2v2.png | Bin 0 -> 3762 bytes
src/static/rank/battle3v3.png | Bin 0 -> 3403 bytes
src/static/rank/battle5.png | Bin 0 -> 6051 bytes
src/static/rank/bubble-tip.png | Bin 0 -> 1502 bytes
src/static/rank/rank-bg.png | Bin 0 -> 96121 bytes
src/static/rank/star.png | Bin 0 -> 4916 bytes
src/static/rank/triangle.png | Bin 0 -> 208 bytes
22 files changed, 1249 insertions(+), 335 deletions(-)
create mode 100644 AGENTS.md
delete mode 100644 src/static/battle-choose.png
delete mode 100644 src/static/battle10.png
delete mode 100644 src/static/battle1v1.png
delete mode 100644 src/static/battle2v2.png
delete mode 100644 src/static/battle3v3.png
delete mode 100644 src/static/battle5.png
create mode 100644 src/static/rank/battle-choose.png
create mode 100644 src/static/rank/battle10.png
create mode 100644 src/static/rank/battle1v1.png
create mode 100644 src/static/rank/battle2v2.png
create mode 100644 src/static/rank/battle3v3.png
create mode 100644 src/static/rank/battle5.png
create mode 100644 src/static/rank/bubble-tip.png
create mode 100644 src/static/rank/rank-bg.png
create mode 100644 src/static/rank/star.png
create mode 100644 src/static/rank/triangle.png
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..b03bab1
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,269 @@
+# AI Agent 企业级行为策略(Ultimate Edition)
+
+## 核心目标
+
+AI 应:
+
+* 像高级工程师一样思考
+* 保持智能
+* 保持上下文理解能力
+* 保持组件联动能力
+* 同时避免无意义 token 消耗
+
+目标不是限制 AI。
+
+目标是:
+
+* 智能
+* 克制
+* 稳定
+* 高效
+
+---
+
+# AI 工作模式
+
+默认采用:
+
+Think First
+Explore Second
+Modify Last
+
+即:
+
+1. 先理解需求
+2. 再推理可能相关文件
+3. 再最小化读取
+4. 最后修改代码
+
+禁止:
+
+* 无脑全项目扫描
+* 不经思考直接 grep
+* 无限递归读取
+
+---
+
+# 智能按需扫描(核心规则)
+
+允许 AI 自动:
+
+* 分析当前任务
+* 分析 import
+* 分析组件依赖
+* 分析 store 依赖
+* 分析 api 依赖
+* 分析 types 依赖
+* 分析 utils 依赖
+
+允许:
+
+* 自动读取直接依赖文件
+* 自动修复 import
+* 自动修复类型引用
+* 自动分析运行链路
+
+但必须:
+
+* 最小化扫描范围
+* 最小化 token 消耗
+* 禁止无限递归探索
+
+---
+
+# 扫描深度限制
+
+默认最大依赖深度:
+
+2 层
+
+例如:
+
+index.vue
+-> ProductCard.vue
+-> product.ts
+
+允许读取:
+
+* ProductCard.vue
+* product.ts
+
+禁止继续无限扫描。
+
+如果任务复杂:
+
+必须先输出分析计划,
+等待确认后再扩大扫描范围。
+
+---
+
+# AI 自由发挥边界
+
+允许:
+
+* 合理重构
+* 合理组件化
+* 合理优化结构
+* 合理优化样式
+* 合理优化复用
+* 合理修复低级问题
+* 合理修复 import
+* 合理修复类型错误
+
+禁止:
+
+* 为了炫技重构项目
+* 无意义抽象
+* 过度设计
+* 无意义拆分
+* 无意义新增依赖
+* 自动升级依赖
+
+---
+
+# Token 经济策略
+
+Token 应优先用于:
+
+* 推理
+* 架构理解
+* 业务逻辑
+* UI 结构优化
+* 类型安全
+* 组件联动
+
+禁止浪费在:
+
+* 全项目 grep
+* 重复读取
+* 重复输出
+* 重复解释
+* 输出完整项目
+* 输出未修改代码
+
+---
+
+# 页面生成规则(Figma / uni-app)
+
+允许:
+
+* 自动组件化
+* 自动布局优化
+* 自动结构优化
+* 自动提取公共组件
+
+优先:
+
+* flex 布局
+* 可维护性
+* uni-app 最佳实践
+* 低嵌套结构
+* 高复用结构
+
+禁止:
+
+* div 套 div
+* 全 absolute 页面
+* 垃圾 HTML
+* 无意义嵌套
+* 内联 style 泛滥
+
+---
+
+# uni-app 规则
+
+必须:
+
+* 使用 view/text/image
+* px 转 rpx
+* 使用 script setup
+* scoped scss
+* 兼容:
+
+ * H5
+ * 微信小程序
+ * App
+
+---
+
+# 大任务策略
+
+复杂任务:
+
+必须:
+
+1. 先分析
+2. 先规划
+3. 先输出方案
+4. 等待确认
+
+再:
+
+5. 编码
+
+禁止直接进入大规模代码生成。
+
+---
+
+# 修改策略
+
+优先:
+
+* diff 修改
+* 小范围 patch
+* 保持现有架构
+* 保持现有组件体系
+* 保持现有 API 结构
+
+允许:
+
+* 小范围智能优化
+
+禁止:
+
+* 全项目重构
+* 无关文件修改
+
+---
+
+# 高级工程师行为模式
+
+AI 应像高级工程师:
+
+* 先思考
+* 再探索
+* 再修改
+
+而不是:
+
+* 无脑扫描器
+* Token 消耗机器
+* 低级代码生成器
+
+AI 应主动:
+
+* 控制扫描范围
+* 控制输出长度
+* 控制修改范围
+* 控制复杂度
+
+同时保持:
+
+* 智能
+* 联动能力
+* 架构理解能力
+
+---
+
+# 默认输出规则
+
+默认:
+
+* 仅输出修改部分
+* 不重复未修改代码
+* 少解释
+* 优先 patch
+* 优先 diff
+
+除非用户明确要求:
+否则不要输出完整项目。
diff --git a/src/apis.js b/src/apis.js
index 1907015..b8836ee 100644
--- a/src/apis.js
+++ b/src/apis.js
@@ -496,3 +496,63 @@ export const kickPlayerAPI = (number, userId) => {
userId,
});
};
+
+// 获取赛季列表
+export const getSeasonList = () => {
+ return request("GET", "/index/season/list");
+};
+
+// 获取赛季统计
+export const getSeasonStats = (seasonId) => {
+ const data = {};
+ if (seasonId !== undefined && seasonId !== null) data.seasonId = seasonId;
+ return request("GET", "/index/season/stats", data);
+};
+
+//获取积分榜
+export const getScoreRankList = (seasonId, page, perPage) => {
+ return request("GET", "/index/score/rank/list", {
+ seasonId,
+ page,
+ perPage
+ });
+};
+
+// 获取10环排行榜
+export const getTenRingRankList = (seasonId, page, perPage) => {
+ return request("GET", "/index/tenRing/rank/list", {
+ seasonId,
+ page,
+ perPage
+ });
+};
+
+// 获取MVP排行榜
+export const getMvpRankList = (seasonId, page, perPage) => {
+ return request("GET", "/index/mvp/rank/list", {
+ seasonId,
+ page,
+ perPage
+ });
+};
+
+// 获取我的积分排名
+export const getMyScoreRank = (seasonId) => {
+ const data = {};
+ if (seasonId !== undefined && seasonId !== null) data.seasonId = seasonId;
+ return request("GET", "/index/myScoreRank", data);
+};
+
+// 获取我的MVP排名
+export const getMyMvpRank = (seasonId) => {
+ const data = {};
+ if (seasonId !== undefined && seasonId !== null) data.seasonId = seasonId;
+ return request("GET", "/index/myMvpRank", data);
+};
+
+// 获取我的10环排名
+export const getMyTenRingRank = (seasonId) => {
+ const data = {};
+ if (seasonId !== undefined && seasonId !== null) data.seasonId = seasonId;
+ return request("GET", "/index/myTenRingRank", data);
+};
diff --git a/src/components/AppBackground.vue b/src/components/AppBackground.vue
index ae678c3..22407d0 100644
--- a/src/components/AppBackground.vue
+++ b/src/components/AppBackground.vue
@@ -51,6 +51,12 @@ const props = defineProps({
src="https://static.shelingxingqiu.com/attachment/2026-01-05/dfgf3b5kp459tfyn0f.png"
mode="widthFix"
/>
+
@@ -67,7 +73,7 @@ const props = defineProps({
.bg-image {
width: 100%;
- height: 100%;
+ /* height: 100%; */
}
.bg-overlay {
diff --git a/src/pages/index.vue b/src/pages/index.vue
index c670356..72944f5 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -13,7 +13,7 @@ import {
getDeviceBatteryAPI,
getHomeData,
getMyDevicesAPI,
- getRankListAPI,
+ getScoreRankList,
silentLoginAPI,
} from "@/apis";
import {topThreeColors} from "@/constants";
@@ -26,15 +26,23 @@ const {
updateConfig,
updateUser,
updateDevice,
- updateRank,
getLvlName,
getLvlNameByScore,
updateOnline,
} = store;
-const {user, device, rankData, online, game} = storeToRefs(store);
+const {user, device, online, game} = storeToRefs(store);
const showModal = ref(false);
const showGuide = ref(false);
+const scoreRankList = ref([]);
+
+// 提取积分榜接口返回的榜单数组,兼容数组和对象两种返回格式。
+const getScoreRankData = (result) => {
+ if (Array.isArray(result)) return result;
+ if (Array.isArray(result?.list)) return result.list;
+ if (Array.isArray(result?.items)) return result.items;
+ return [];
+};
const toPage = async (path) => {
if (!user.value.id) {
@@ -84,15 +92,15 @@ onShow(async () => {
}
}
- const promises = [getRankListAPI()];
+ const promises = [getScoreRankList(undefined, 1, 10)];
if (token || user.value.id) {
promises.push(getHomeData());
}
const [rankList, homeData] = await Promise.all(promises);
- console.log("排行数据", rankList);
- updateRank(rankList);
+ console.log("积分榜数据", rankList);
+ scoreRankList.value = getScoreRankData(rankList).slice(0, 10);
if (homeData) {
console.log("首页数据:", homeData);
@@ -216,7 +224,7 @@ onShareTimeline(() => {
class="player-avatar"
:style="{
zIndex: 8 - i,
- borderColor: rankData.rank[i - 1]
+ borderColor: scoreRankList[i - 1]
? topThreeColors[i - 1] || '#000'
: '#000',
}"
@@ -227,15 +235,15 @@ onShareTimeline(() => {
{{ i }}
- {{ rankData.rank.length }}
+ {{ scoreRankList.length }}
diff --git a/src/pages/rank-list.vue b/src/pages/rank-list.vue
index 286c9a5..552feab 100644
--- a/src/pages/rank-list.vue
+++ b/src/pages/rank-list.vue
@@ -1,58 +1,333 @@
@@ -75,18 +350,32 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
+
-
+
+
- {{ rankType }}
+ {{ rankType.title }}
- {{ index + 1 }}
+
+ {{ getDisplayRank(item, index) }}
+
{{ item.name }}
- {{ getLvlName(item.rankLvl) }},{{ item.TotalGames }}场
+ {{ formatLevelText(item) }}
-
+
{{ item.totalScore }} 分
-
-
- {{ item.mvpCount }} 次
-
-
- {{ item.TenRings }} 次
+ >
+ {{ getRankValue(item) }}
+
+ {{ getRankUnit() }}
-
- 筹备中...
+
+ 加载中...
+
+
+ 暂无数据
+
+
+ 加载中...
+ 没有更多了
-
+
- {{ myData.rank }}
-
+ {{ getDisplayMyRank(currentMyData) }}
+
- {{ user.nickName }}
- {{ user.lvlName }},{{ myData.TotalGames }}场
+ {{ currentMyData.name || user.nickName }}
+ {{ formatLevelText(currentMyData) }}
-
+
{{ myData.totalScore || 0 }}分
-
- {{ myData.mvpCount || 0 }}次
-
- {{ myData.TenRings || 0 }}次
+ >
+ {{ getRankValue(currentMyData) }}
+
+ {{ getRankUnit() }}
+
@@ -214,9 +498,16 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
.container {
width: 100%;
}
+
+.content-start-anchor {
+ width: 100%;
+ height: 0;
+}
+
.header-bg {
width: 100%;
}
+
.header {
width: 100%;
height: 50px;
@@ -227,6 +518,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
z-index: 10;
overflow: hidden;
}
+
.header-back {
width: 22px;
height: 22px;
@@ -234,6 +526,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
margin-top: 5px;
position: relative;
}
+
.header > image:first-child {
width: 100vw;
height: 100vh;
@@ -242,25 +535,40 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
left: 0;
transition: all 0.5s ease;
}
+
.header > text {
color: #fff;
font-weight: bold;
transition: all 0.5s ease;
position: relative;
}
+
.rank-tabs {
width: calc(100% - 20px);
display: flex;
justify-content: space-around;
- padding: 0 10px;
- margin-top: -15px;
+ padding: 20rpx 10px;
}
+
.rank-tabs > view {
width: 25%;
padding: 10px;
text-align: center;
border-radius: 20px;
}
+
+.rank-tabs-placeholder {
+ width: 100%;
+}
+
+.rank-tabs-anchor-fixed {
+ position: fixed;
+ left: 0;
+ z-index: 11;
+ background: #000000;
+ backdrop-filter: blur(8px);
+}
+
.rank-list {
display: flex;
flex-direction: column;
@@ -268,11 +576,12 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
width: calc(100% - 20px);
color: #fff9;
font-size: 12px;
- margin: 10px;
+ margin: 0 10px 10px 10px;
border: 1px solid rgb(255 217 71 / 0.2);
border-radius: 10px;
background-color: #313131;
}
+
.rank-list > view {
display: flex;
align-items: center;
@@ -281,20 +590,25 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
overflow: hidden;
position: relative;
}
+
.rank-list-header {
width: calc(100% - 20px) !important;
padding: 10px;
}
+
.rank-list-header > text:nth-child(2) {
width: 14%;
}
+
.rank-list-header > text:last-child {
width: 30%;
text-align: right;
}
+
.rank-list-item {
padding: 10px 0;
}
+
.player-bg {
position: absolute;
width: 100%;
@@ -302,12 +616,14 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
top: 0;
left: 0;
}
+
.player-crown {
position: relative;
width: 27px;
height: 27px;
margin: 0 15px;
}
+
.view-crown {
width: 27px;
height: 27px;
@@ -319,6 +635,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
background-color: #676767;
position: relative;
}
+
.rank-item-content {
display: flex;
flex-direction: column;
@@ -328,17 +645,20 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
position: relative;
padding-left: 10px;
}
+
.rank-item-content > text:first-child {
color: #fff;
font-size: 14px;
margin-bottom: 3px;
width: 120px;
}
+
.rank-list-item > text:last-child {
margin-right: 10px;
width: 56px;
text-align: right;
}
+
.my-rank-data {
width: calc(100% - 30px);
padding: 15px;
@@ -352,12 +672,14 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
overflow: hidden;
border-radius: 10px;
}
+
.my-rank-data > image:first-child {
position: absolute;
width: 100%;
left: 0;
top: -5px;
}
+
.my-rank-data > text:nth-child(2) {
background-color: #c1a434;
position: relative;
@@ -369,20 +691,24 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
min-width: 15px;
text-align: center;
}
+
.my-rank-data > text:last-child {
position: relative;
margin-right: 10px;
width: 65px;
text-align: right;
}
+
.my-rank-data > .rank-item-content > text:first-child {
color: #fed847;
}
+
.my-rank-data > .rank-item-integral {
color: #fff9;
font-size: 12px;
margin-right: 0 !important;
}
+
.no-data {
width: 100%;
height: 400px;
@@ -392,4 +718,11 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
color: #fff9;
font-size: 14px;
}
+
+.list-tip {
+ justify-content: center !important;
+ color: #fff9;
+ font-size: 12px;
+ min-height: 60rpx;
+}
diff --git a/src/pages/ranking.vue b/src/pages/ranking.vue
index 8bd2ea9..c78d6ad 100644
--- a/src/pages/ranking.vue
+++ b/src/pages/ranking.vue
@@ -1,46 +1,103 @@
-
+
+
+
+
+
+
+
+ toMatchPage(1, 2)"
+ />
+ toMatchPage(2, 4)"
+ />
+ toMatchPage(3, 6)"
+ />
+ toMatchPage(4, 5)"
+ />
+ toMatchPage(5, 10)"
+ />
+
+
(showSeasonList = false)">
- {{ user.nickName }}
+ {{ seasonStats.nickName || user.nickName }}
{
{{ seasonName }}
@@ -151,10 +335,16 @@ onShow(async () => {
() => onChangeSeason(item.seasonId, item.seasonName)
"
>
- {{ item.seasonName }}
+
+ {{ item.seasonName }}
+
@@ -164,177 +354,120 @@ onShow(async () => {
段位
- {{
- getLvlName(rankData.user.rankLvl) || "-"
- }}
+
+ {{ seasonStats.rankName || getLvlName(seasonStats.rankLvl) || "-" }}
+
赛季平均环数
- {{
- rankData.user.avg_ring ? rankData.user.avg_ring + "环" : "-"
- }}
+
+ {{ formatTopStatValue(seasonStats.avgRing, "环") }}
+
赛季胜率
- {{
- rankData.user.avg_win
- ? Number((rankData.user.avg_win * 100).toFixed(2)) + "%"
- : "-"
- }}
+
+ {{ formatTopStatValue(seasonStats.winRate, "%") }}
+
-
- 积分:{{ Math.max(0, rankData.user.scores) }}
+
+ 积分:{{ seasonStats.score }}
-
-
- toMatchPage(1, 2)"
- />
- toMatchPage(2, 4)"
- />
- toMatchPage(3, 6)"
- />
- toMatchPage(4, 5)"
- />
- toMatchPage(5, 10)"
- />
-
-
- {{
- `【1 V 1】${currentSeasonData["1v1"].totalGames}场 胜率 ${currentSeasonData["1v1"].winRate}%`
- }}
-
-
+
+ {{ currentSeasonData["1v1"].modeName || "1V1" }}
+ {{ formatSeasonText(currentSeasonData["1v1"], "winRate", "胜率") }}
+
+
-
- {{
- `【2 V 2】${currentSeasonData["2v2"].totalGames}场 胜率 ${currentSeasonData["2v2"].winRate}%`
- }}
-
-
+
+ {{ currentSeasonData["2v2"].modeName || "2V2" }}
+ {{ formatSeasonText(currentSeasonData["2v2"], "winRate", "胜率") }}
+
+
-
- {{
- `【3 V 3】${currentSeasonData["3v3"].totalGames}场 胜率 ${currentSeasonData["3v3"].winRate}%`
- }}
-
-
+
+ {{ currentSeasonData["3v3"].modeName || "3V3" }}
+ {{ formatSeasonText(currentSeasonData["3v3"], "winRate", "胜率") }}
+
+
-
- {{
- `【5人大乱斗】${currentSeasonData["5m"].totalGames}场 得分率 ${currentSeasonData["5m"].winRate}%`
- }}
-
-
+
+ {{ currentSeasonData["5m"].modeName || "5V5" }}
+ {{ formatSeasonText(currentSeasonData["5m"], "scoreRate", "得分率") }}
+
+
-
- {{
- `【10人大乱斗】${currentSeasonData["10m"].totalGames}场 得分率 ${currentSeasonData["10m"].winRate}%`
- }}
-
-
+
+ {{ currentSeasonData["10m"].modeName || "10人大乱斗" }}
+ {{ formatSeasonText(currentSeasonData["10m"], "scoreRate", "得分率") }}
+
+
- 查看我的比赛记录
+
+ 查看我的比赛记录
+
+
{{ rankType }}
+
-
-
-
+
+
+
{{ index + 1 }}
{
/>
{{ item.name }}
-
- {{ getLvlName(item.rankLvl) }},{{ item.TotalGames }}场
-
+ {{ formatRankSubTitle(item) }}
-
- {{ item.totalScore }}分
-
-
- {{ item.mvpCount }}次
-
-
- {{ item.TenRings }}次
-
+ {{ item.totalScore || 0 }}分
-
- 筹备中...
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ {{ item.name }}
+ {{ formatRankSubTitle(item) }}
+
+ {{ item.mvpCount || 0 }}次
- 点击查看更多
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ {{ item.name }}
+ {{ formatRankSubTitle(item) }}
+
+ {{ item.tenRings ?? item.TenRings ?? 0 }}次
+
+
+
+ 加载中...
+
+
+ 暂无数据
+
+ 点击查看更多
@@ -369,34 +542,34 @@ onShow(async () => {