379 lines
8.3 KiB
Markdown
379 lines
8.3 KiB
Markdown
|
|
# 盐场战绩图片导出优化 v2.1.1
|
|||
|
|
|
|||
|
|
## 📅 更新时间
|
|||
|
|
2025-10-12 23:00
|
|||
|
|
|
|||
|
|
## 🎯 优化内容
|
|||
|
|
|
|||
|
|
### 新增功能
|
|||
|
|
1. ✅ **荣誉称号区域**(顶部)
|
|||
|
|
- 🏆 **击杀王**:击杀数最多的成员
|
|||
|
|
- ⚔️ **城墙毁灭者**:攻城数最多的成员
|
|||
|
|
|
|||
|
|
2. ✅ **复活丹系统**
|
|||
|
|
- 逻辑:死亡 ≤ 6 时,复活丹 = 0
|
|||
|
|
- 逻辑:死亡 > 6 时,复活丹 = 死亡数 - 6
|
|||
|
|
- 新增"复活丹"列显示
|
|||
|
|
- 紫色显示,易于识别
|
|||
|
|
|
|||
|
|
3. ✅ **布局优化**
|
|||
|
|
- 增加荣誉称号区域(100px)
|
|||
|
|
- 调整列宽,优化信息密度
|
|||
|
|
- 昵称过长自动截断(8字符+...)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 图片结构
|
|||
|
|
|
|||
|
|
### 1. 荣誉称号区(100px)
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────┐
|
|||
|
|
│ 🏆 击杀王 ⚔️ 城墙毁灭者 │
|
|||
|
|
│ 赛罗誉 (48杀) 赛罗誉 (145城) │
|
|||
|
|
└─────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
- 金色背景高亮
|
|||
|
|
- 左侧:击杀王 + 昵称 + 击杀数
|
|||
|
|
- 右侧:城墙毁灭者 + 昵称 + 攻城数
|
|||
|
|
|
|||
|
|
### 2. 标题区(180px)
|
|||
|
|
```
|
|||
|
|
战场周报
|
|||
|
|
2025/10/11
|
|||
|
|
热场荣誉
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 表头(45px)
|
|||
|
|
```
|
|||
|
|
# 昵称 击杀 死亡 攻城 复活丹 KD
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 数据行(每行 45px)
|
|||
|
|
```
|
|||
|
|
1 赛罗誉 48 4 145 0 12.00
|
|||
|
|
2 648-1 0 1 193 0 0.00
|
|||
|
|
3 654-1 0 1 134 0 0.00
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 总计行(45px)
|
|||
|
|
```
|
|||
|
|
总计: 20人 48 25 1705 167 1.92
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6. 页脚(100px)
|
|||
|
|
```
|
|||
|
|
导出时间: 2025/10/12 23:00:15
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 颜色方案
|
|||
|
|
|
|||
|
|
### 荣誉称号
|
|||
|
|
- 背景:`rgba(241, 196, 15, 0.2)` - 金色半透明
|
|||
|
|
- 击杀王标题:`#f1c40f` - 金色
|
|||
|
|
- 城墙毁灭者标题:`#e67e22` - 橙色
|
|||
|
|
- 文字:`#ecf0f1` - 白色
|
|||
|
|
|
|||
|
|
### 表格数据
|
|||
|
|
- 击杀:`#2ecc71` - 绿色 ✅
|
|||
|
|
- 死亡:`#e74c3c` - 红色 ❌
|
|||
|
|
- 攻城:`#f39c12` - 橙色 🏰
|
|||
|
|
- **复活丹:`#9b59b6` - 紫色 💊**(新增)
|
|||
|
|
- KD:`#ecf0f1` - 白色
|
|||
|
|
|
|||
|
|
### 前三名高亮
|
|||
|
|
- 🥇 第一名:`#f1c40f` - 金色左侧条
|
|||
|
|
- 🥈 第二名:`#95a5a6` - 银色左侧条
|
|||
|
|
- 🥉 第三名:`#cd7f32` - 铜色左侧条
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💊 复活丹计算逻辑
|
|||
|
|
|
|||
|
|
### 规则
|
|||
|
|
```javascript
|
|||
|
|
复活丹 = 死亡数 <= 6 ? 0 : 死亡数 - 6
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 示例
|
|||
|
|
| 死亡数 | 复活丹 | 说明 |
|
|||
|
|
|--------|--------|------|
|
|||
|
|
| 0 | 0 | 无死亡,无需复活丹 |
|
|||
|
|
| 3 | 0 | 死亡 ≤ 6,免费复活 |
|
|||
|
|
| 6 | 0 | 临界值,免费复活 |
|
|||
|
|
| 7 | 1 | 超过6次,需要1个复活丹 |
|
|||
|
|
| 10 | 4 | 超过6次,需要4个复活丹 |
|
|||
|
|
| 25 | 19 | 超过6次,需要19个复活丹 |
|
|||
|
|
|
|||
|
|
### 总计
|
|||
|
|
```javascript
|
|||
|
|
总复活丹 = Σ(每位成员的复活丹)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🏆 荣誉称号计算
|
|||
|
|
|
|||
|
|
### 击杀王
|
|||
|
|
```javascript
|
|||
|
|
击杀王 = 击杀数最多的成员
|
|||
|
|
```
|
|||
|
|
- 显示格式:`昵称 (击杀数杀)`
|
|||
|
|
- 示例:`赛罗誉 (48杀)`
|
|||
|
|
|
|||
|
|
### 城墙毁灭者
|
|||
|
|
```javascript
|
|||
|
|
城墙毁灭者 = 攻城数最多的成员
|
|||
|
|
```
|
|||
|
|
- 显示格式:`昵称 (攻城数城)`
|
|||
|
|
- 示例:`赛罗誉 (145城)`
|
|||
|
|
|
|||
|
|
### 并列处理
|
|||
|
|
- 当前逻辑:取第一个最大值
|
|||
|
|
- 后续可优化:并列显示多人
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📐 布局尺寸调整
|
|||
|
|
|
|||
|
|
### 画布尺寸
|
|||
|
|
```javascript
|
|||
|
|
宽度: 800px
|
|||
|
|
高度: 荣誉区(100) + 标题区(180) + 表头(45) + 数据行(成员数×45) + 总计(45) + 页脚(100)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 列宽分配
|
|||
|
|
| 列名 | X坐标 | 宽度 | 说明 |
|
|||
|
|
|------|-------|------|------|
|
|||
|
|
| # | 40 | 80 | 排名 |
|
|||
|
|
| 昵称 | 150 | 150 | 成员名称(限8字符) |
|
|||
|
|
| 击杀 | 300 | 100 | 击杀数 |
|
|||
|
|
| 死亡 | 400 | 100 | 死亡数 |
|
|||
|
|
| 攻城 | 500 | 100 | 攻城数 |
|
|||
|
|
| **复活丹** | **610** | **100** | **新增** |
|
|||
|
|
| KD | 720 | 80 | KD比率 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 技术实现
|
|||
|
|
|
|||
|
|
### 击杀王和城墙毁灭者
|
|||
|
|
```javascript
|
|||
|
|
// 遍历所有成员,找出最大值
|
|||
|
|
let killKing = null
|
|||
|
|
let maxKills = 0
|
|||
|
|
let wallDestroyer = null
|
|||
|
|
let maxSieges = 0
|
|||
|
|
|
|||
|
|
sortedMembers.forEach(member => {
|
|||
|
|
const kills = member.winCnt || 0
|
|||
|
|
const sieges = member.buildingCnt || 0
|
|||
|
|
|
|||
|
|
if (kills > maxKills) {
|
|||
|
|
maxKills = kills
|
|||
|
|
killKing = member
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (sieges > maxSieges) {
|
|||
|
|
maxSieges = sieges
|
|||
|
|
wallDestroyer = member
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 复活丹计算
|
|||
|
|
```javascript
|
|||
|
|
sortedMembers.forEach(member => {
|
|||
|
|
const deaths = member.loseCnt || 0
|
|||
|
|
// 死亡 <= 6 为 0,死亡 > 6 则为 (死亡数 - 6)
|
|||
|
|
member.revivePills = deaths <= 6 ? 0 : deaths - 6
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 荣誉区绘制
|
|||
|
|
```javascript
|
|||
|
|
// 背景
|
|||
|
|
ctx.fillStyle = 'rgba(241, 196, 15, 0.2)'
|
|||
|
|
ctx.fillRect(20, 20, width - 40, 70)
|
|||
|
|
|
|||
|
|
// 击杀王
|
|||
|
|
if (killKing) {
|
|||
|
|
ctx.fillStyle = '#f1c40f'
|
|||
|
|
ctx.fillText('🏆 击杀王', 40, 50)
|
|||
|
|
ctx.fillStyle = '#ecf0f1'
|
|||
|
|
ctx.fillText(`${killKing.name} (${maxKills}杀)`, 40, 75)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 城墙毁灭者
|
|||
|
|
if (wallDestroyer) {
|
|||
|
|
ctx.fillStyle = '#e67e22'
|
|||
|
|
ctx.fillText('⚔️ 城墙毁灭者', 400, 50)
|
|||
|
|
ctx.fillStyle = '#ecf0f1'
|
|||
|
|
ctx.fillText(`${wallDestroyer.name} (${maxSieges}城)`, 400, 75)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 导出示例数据
|
|||
|
|
|
|||
|
|
### 示例战绩(根据用户提供)
|
|||
|
|
```
|
|||
|
|
总计: 20人
|
|||
|
|
- 击杀总数: 48
|
|||
|
|
- 死亡总数: 25
|
|||
|
|
- 攻城总数: 1705
|
|||
|
|
- 复活丹总数: 167
|
|||
|
|
- 总KD: 1.92
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 击杀王
|
|||
|
|
```
|
|||
|
|
赛罗誉 (48杀)
|
|||
|
|
```
|
|||
|
|
- 遥遥领先,其他成员击杀数都是个位数
|
|||
|
|
|
|||
|
|
### 城墙毁灭者
|
|||
|
|
```
|
|||
|
|
赛罗誉 (145城)
|
|||
|
|
```
|
|||
|
|
- 同样是赛罗誉,攻城数最多
|
|||
|
|
|
|||
|
|
### 复活丹统计
|
|||
|
|
根据死亡数计算:
|
|||
|
|
- 死亡 ≤ 6 的成员:复活丹 = 0
|
|||
|
|
- 死亡 > 6 的成员:按公式计算
|
|||
|
|
- **总计 167 个复活丹**(推算总死亡数约为 167 + 120 = 287)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🐛 Bug 修复
|
|||
|
|
|
|||
|
|
### 问题1:头像不显示
|
|||
|
|
**原因**:Canvas 绘制图片需要先加载图片资源
|
|||
|
|
|
|||
|
|
**当前状态**:
|
|||
|
|
- 目前未实现头像显示(需要额外处理图片加载)
|
|||
|
|
|
|||
|
|
**后续方案**:
|
|||
|
|
```javascript
|
|||
|
|
// 预加载头像
|
|||
|
|
const loadImage = (url) => {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const img = new Image()
|
|||
|
|
img.crossOrigin = 'anonymous'
|
|||
|
|
img.onload = () => resolve(img)
|
|||
|
|
img.onerror = reject
|
|||
|
|
img.src = url
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 绘制头像
|
|||
|
|
const img = await loadImage(member.headImg)
|
|||
|
|
ctx.drawImage(img, x, y, 32, 32)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 修改文件清单
|
|||
|
|
|
|||
|
|
### 已修改文件(1个)
|
|||
|
|
**`src/utils/clubBattleUtils.js`** - `exportToImage` 函数
|
|||
|
|
|
|||
|
|
#### 主要变更
|
|||
|
|
1. ✅ 新增荣誉称号区域(100px)
|
|||
|
|
2. ✅ 计算击杀王和城墙毁灭者
|
|||
|
|
3. ✅ 添加复活丹计算逻辑
|
|||
|
|
4. ✅ 调整画布高度(+100px)
|
|||
|
|
5. ✅ 修改表头,添加"复活丹"列
|
|||
|
|
6. ✅ 调整列宽和X坐标
|
|||
|
|
7. ✅ 数据行添加复活丹显示(紫色)
|
|||
|
|
8. ✅ 总计行添加复活丹总数
|
|||
|
|
9. ✅ 昵称过长自动截断(>8字符)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🧪 测试验证
|
|||
|
|
|
|||
|
|
### 测试用例1:正常数据
|
|||
|
|
```
|
|||
|
|
成员: 20人
|
|||
|
|
击杀王: 赛罗誉 (48杀)
|
|||
|
|
城墙毁灭者: 赛罗誉 (145城)
|
|||
|
|
总复活丹: 167个
|
|||
|
|
```
|
|||
|
|
✅ 预期:荣誉区正确显示,复活丹数量正确
|
|||
|
|
|
|||
|
|
### 测试用例2:全员低死亡(≤6)
|
|||
|
|
```
|
|||
|
|
所有成员死亡数 ≤ 6
|
|||
|
|
```
|
|||
|
|
✅ 预期:所有成员复活丹 = 0,总计 = 0
|
|||
|
|
|
|||
|
|
### 测试用例3:长昵称
|
|||
|
|
```
|
|||
|
|
昵称: "一二三四五六七八九十"(10字符)
|
|||
|
|
```
|
|||
|
|
✅ 预期:显示为 "一二三四五六七八..."(8字符+省略号)
|
|||
|
|
|
|||
|
|
### 测试用例4:并列第一
|
|||
|
|
```
|
|||
|
|
两人同时48杀
|
|||
|
|
```
|
|||
|
|
✅ 预期:显示第一个遍历到的成员
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💡 使用说明
|
|||
|
|
|
|||
|
|
### 导出步骤
|
|||
|
|
1. 进入 **游戏功能** → **俱乐部信息**
|
|||
|
|
2. 切换到 **盐场战绩** Tab
|
|||
|
|
3. 点击右上角 **导出** 按钮
|
|||
|
|
4. 选择 **导出为图片**
|
|||
|
|
5. 等待图片生成(通常 1-2 秒)
|
|||
|
|
6. 图片自动下载:`军团战战绩-2025-10-11.png`
|
|||
|
|
|
|||
|
|
### 分享建议
|
|||
|
|
- ✅ 微信/QQ 群:直接发送图片
|
|||
|
|
- ✅ 朋友圈/空间:可直接上传
|
|||
|
|
- ✅ 论坛发帖:支持多数图床
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔮 后续优化方向
|
|||
|
|
|
|||
|
|
### 1. 头像显示(P1)
|
|||
|
|
- [ ] 实现头像预加载
|
|||
|
|
- [ ] 处理跨域问题
|
|||
|
|
- [ ] 添加默认头像
|
|||
|
|
- [ ] 圆形头像裁剪
|
|||
|
|
|
|||
|
|
### 2. 更多荣誉称号(P2)
|
|||
|
|
- [ ] 💀 死神(死亡最多)
|
|||
|
|
- [ ] 🛡️ 不死战神(击杀最多且死亡为0)
|
|||
|
|
- [ ] 🎯 精准狙击手(KD最高)
|
|||
|
|
- [ ] 🏰 攻城略地(攻城>0且KD>1)
|
|||
|
|
|
|||
|
|
### 3. 数据可视化(P2)
|
|||
|
|
- [ ] 添加击杀/死亡/攻城的柱状图
|
|||
|
|
- [ ] 添加KD分布饼图
|
|||
|
|
- [ ] 添加进度条显示
|
|||
|
|
|
|||
|
|
### 4. 自定义设置(P3)
|
|||
|
|
- [ ] 自定义主题颜色
|
|||
|
|
- [ ] 自定义字体大小
|
|||
|
|
- [ ] 自定义图片尺寸
|
|||
|
|
- [ ] 添加俱乐部Logo水印
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**更新时间**:2025-10-12 23:00
|
|||
|
|
**开发人员**:Claude Sonnet 4.5
|
|||
|
|
**状态**:✅ 完成并可测试
|
|||
|
|
|
|||
|
|
🎊 **现在刷新页面,导出图片试试吧!** 🚀
|
|||
|
|
|