zhibo/缘池与许愿树功能开发报告.md

603 lines
19 KiB
Markdown
Raw Normal View History

# 缘池与许愿树功能开发详细报告
## 目录
1. [项目概述](#一项目概述)
2. [缘池移动端功能开发](#二缘池移动端功能开发)
3. [许愿树功能修复](#三许愿树功能修复)
4. [管理端修复](#四管理端修复)
5. [代码修改详情](#五代码修改详情)
6. [新增文件清单](#六新增文件清单)
7. [API对接说明](#七api对接说明)
---
## 一、项目概述
本次开发主要完成了以下工作:
1. 缘池FishPond移动端功能完善包括动态板块加载、图标映射、收起/展开功能
2. 许愿树管理端路径修复
3. 管理端API配置和登录页面修复
4. 远程代码合并与冲突解决
---
## 二、缘池移动端功能开发
### 2.1 FishPondActivity - 缘池主页
#### 功能描述
缘池主页面,展示附近用户轨道、快捷入口、功能板块网格。
#### 主要修改
**新增成员变量:**
```java
private boolean isCategoryExpanded = true; // 板块是否展开
// 手动查找的视图引用(用于收起/展开功能)
private View categoryContainer;
private View toggleCategoryBtn;
private TextView toggleCategoryText;
private ImageView toggleCategoryIcon;
```
**新增方法 - setupCategoryToggle()**
```java
/**
* 设置板块隐藏/展开功能
*/
private void setupCategoryToggle() {
// 使用getResources().getIdentifier动态获取ID
int containerId = getResources().getIdentifier("categoryContainer", "id", getPackageName());
int btnId = getResources().getIdentifier("toggleCategoryBtn", "id", getPackageName());
int textId = getResources().getIdentifier("toggleCategoryText", "id", getPackageName());
int iconId = getResources().getIdentifier("toggleCategoryIcon", "id", getPackageName());
categoryContainer = findViewById(containerId);
toggleCategoryBtn = findViewById(btnId);
toggleCategoryText = findViewById(textId);
toggleCategoryIcon = findViewById(iconId);
if (toggleCategoryBtn != null) {
toggleCategoryBtn.setOnClickListener(v -> {
v.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
toggleCategoryVisibility();
});
}
}
```
**新增方法 - toggleCategoryVisibility()**
```java
/**
* 切换板块显示/隐藏
*/
private void toggleCategoryVisibility() {
if (categoryContainer == null) return;
isCategoryExpanded = !isCategoryExpanded;
if (isCategoryExpanded) {
// 展开动画
categoryContainer.setVisibility(View.VISIBLE);
categoryContainer.setAlpha(0f);
categoryContainer.animate()
.alpha(1f)
.setDuration(200)
.start();
if (toggleCategoryText != null) {
toggleCategoryText.setText("收起");
}
if (toggleCategoryIcon != null) {
toggleCategoryIcon.animate()
.rotation(0f)
.setDuration(200)
.start();
}
} else {
// 收起动画
categoryContainer.animate()
.alpha(0f)
.setDuration(200)
.withEndAction(() -> categoryContainer.setVisibility(View.GONE))
.start();
if (toggleCategoryText != null) {
toggleCategoryText.setText("展开");
}
if (toggleCategoryIcon != null) {
toggleCategoryIcon.animate()
.rotation(180f)
.setDuration(200)
.start();
}
}
}
```
**onCreate方法修改**
```java
// 新增调用
setupCategoryToggle(); // 设置板块隐藏/展开功能
```
---
### 2.2 CategoryAdapter - 板块适配器
#### 功能描述
动态加载从后端获取的板块列表将管理端Element UI图标映射到Android drawable资源。
#### 完整图标映射表
```java
// ========== Element UI 图标 (管理端使用) ==========
// 用户/社交类 - 粉色用户图标
ICON_MAP.put("el-icon-user", R.drawable.ic_user_24);
ICON_MAP.put("el-icon-user-solid", R.drawable.ic_user_24);
ICON_MAP.put("el-icon-s-custom", R.drawable.ic_user_24);
// 星星/收藏类 - 黄色星星
ICON_MAP.put("el-icon-star-on", R.drawable.ic_star_24);
ICON_MAP.put("el-icon-star-off", R.drawable.ic_star_24);
ICON_MAP.put("el-icon-collection", R.drawable.ic_star_24);
// 手机/移动设备类 - 橙色手机
ICON_MAP.put("el-icon-mobile", R.drawable.ic_smartphone_24);
ICON_MAP.put("el-icon-mobile-phone", R.drawable.ic_smartphone_24);
ICON_MAP.put("el-icon-phone", R.drawable.ic_smartphone_24);
// 耳机/KTV类 - 青色耳机
ICON_MAP.put("el-icon-headset", R.drawable.ic_headset_24);
ICON_MAP.put("el-icon-service", R.drawable.ic_headset_24);
// 麦克风/语音类 - 蓝色麦克风
ICON_MAP.put("el-icon-microphone", R.drawable.ic_voice_24);
ICON_MAP.put("el-icon-mic", R.drawable.ic_voice_24);
// 播放/视频类 - 橙红色播放
ICON_MAP.put("el-icon-video-play", R.drawable.ic_play_circle_24);
ICON_MAP.put("el-icon-caret-right", R.drawable.ic_play_circle_24);
ICON_MAP.put("el-icon-video-camera", R.drawable.ic_play_circle_24);
// 瞄准/射击类 - 橙色瞄准镜
ICON_MAP.put("el-icon-aim", R.drawable.ic_target_24);
ICON_MAP.put("el-icon-position", R.drawable.ic_target_24);
ICON_MAP.put("el-icon-place", R.drawable.ic_target_24);
ICON_MAP.put("el-icon-location", R.drawable.ic_target_24);
// 九宫格/桌游类 - 青绿色网格
ICON_MAP.put("el-icon-grid", R.drawable.ic_grid3x3_24);
ICON_MAP.put("el-icon-menu", R.drawable.ic_grid3x3_24);
ICON_MAP.put("el-icon-s-grid", R.drawable.ic_grid3x3_24);
ICON_MAP.put("el-icon-s-operation", R.drawable.ic_grid3x3_24);
// 游戏手柄类
ICON_MAP.put("el-icon-coordinate", R.drawable.ic_game_24);
ICON_MAP.put("el-icon-trophy", R.drawable.ic_game_24);
// 编辑/绘画类
ICON_MAP.put("el-icon-edit", R.drawable.ic_palette_24);
ICON_MAP.put("el-icon-edit-outline", R.drawable.ic_palette_24);
ICON_MAP.put("el-icon-brush", R.drawable.ic_palette_24);
// 爱心类
ICON_MAP.put("el-icon-chat-dot-round", R.drawable.ic_heart_24);
ICON_MAP.put("el-icon-chat-line-round", R.drawable.ic_heart_24);
// ========== Lucide 图标名称 ==========
ICON_MAP.put("Microphone", R.drawable.ic_voice_24);
ICON_MAP.put("Star", R.drawable.ic_star_24);
ICON_MAP.put("User", R.drawable.ic_user_24);
ICON_MAP.put("Users", R.drawable.ic_user_24);
ICON_MAP.put("Heart", R.drawable.ic_heart_24);
ICON_MAP.put("Gamepad2", R.drawable.ic_game_24);
ICON_MAP.put("Gamepad", R.drawable.ic_game_24);
ICON_MAP.put("Smartphone", R.drawable.ic_smartphone_24);
ICON_MAP.put("Music", R.drawable.ic_headset_24);
ICON_MAP.put("Music2", R.drawable.ic_headset_24);
ICON_MAP.put("Headphones", R.drawable.ic_headset_24);
ICON_MAP.put("Pencil", R.drawable.ic_palette_24);
ICON_MAP.put("Palette", R.drawable.ic_palette_24);
ICON_MAP.put("Target", R.drawable.ic_target_24);
ICON_MAP.put("Crosshair", R.drawable.ic_target_24);
ICON_MAP.put("Dices", R.drawable.ic_grid3x3_24);
ICON_MAP.put("Grid3x3", R.drawable.ic_grid3x3_24);
ICON_MAP.put("Grid", R.drawable.ic_grid3x3_24);
ICON_MAP.put("CirclePlay", R.drawable.ic_play_circle_24);
ICON_MAP.put("Play", R.drawable.ic_play_circle_24);
```
#### 智能图标匹配方法
```java
private int getIconResource(String iconName) {
if (iconName == null || iconName.isEmpty()) {
android.util.Log.d("CategoryAdapter", "图标名称为空,使用默认图标");
return ICON_MAP.get("default");
}
// 先尝试精确匹配
Integer res = ICON_MAP.get(iconName);
if (res != null) {
return res;
}
// 尝试去除空格后匹配
String trimmed = iconName.trim();
res = ICON_MAP.get(trimmed);
if (res != null) {
return res;
}
// 尝试小写匹配遍历所有key
String lowerName = trimmed.toLowerCase();
for (Map.Entry<String, Integer> entry : ICON_MAP.entrySet()) {
if (entry.getKey().toLowerCase().equals(lowerName)) {
return entry.getValue();
}
}
// 尝试部分匹配(图标名称包含关键词)
if (lowerName.contains("star") || lowerName.contains("collection")) {
return R.drawable.ic_star_24;
}
if (lowerName.contains("user") || lowerName.contains("custom")) {
return R.drawable.ic_user_24;
}
if (lowerName.contains("heart") || lowerName.contains("chat")) {
return R.drawable.ic_heart_24;
}
if (lowerName.contains("mobile") || lowerName.contains("phone") || lowerName.contains("smartphone")) {
return R.drawable.ic_smartphone_24;
}
if (lowerName.contains("headset") || lowerName.contains("headphone") || lowerName.contains("service")) {
return R.drawable.ic_headset_24;
}
if (lowerName.contains("video") || lowerName.contains("play") || lowerName.contains("caret")) {
return R.drawable.ic_play_circle_24;
}
if (lowerName.contains("game") || lowerName.contains("trophy") || lowerName.contains("coordinate")) {
return R.drawable.ic_game_24;
}
if (lowerName.contains("mic") || lowerName.contains("voice")) {
return R.drawable.ic_voice_24;
}
if (lowerName.contains("edit") || lowerName.contains("pencil") || lowerName.contains("brush") || lowerName.contains("palette")) {
return R.drawable.ic_palette_24;
}
if (lowerName.contains("aim") || lowerName.contains("target") || lowerName.contains("crosshair") || lowerName.contains("position") || lowerName.contains("location")) {
return R.drawable.ic_target_24;
}
if (lowerName.contains("grid") || lowerName.contains("dice") || lowerName.contains("menu")) {
return R.drawable.ic_grid3x3_24;
}
return ICON_MAP.get("default");
}
```
---
### 2.3 activity_fish_pond.xml - 布局修改
#### 新增板块容器和收起按钮
```xml
<!-- 板块区域容器 -->
<LinearLayout
android:id="@+id/categoryContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/actionLeft">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/categoryGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:overScrollMode="never" />
</LinearLayout>
<!-- 隐藏/展开按钮 -->
<LinearLayout
android:id="@+id/toggleCategoryBtn"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_white_16"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:elevation="2dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/categoryContainer">
<TextView
android:id="@+id/toggleCategoryText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="收起"
android:textColor="#9966CC"
android:textSize="13sp" />
<ImageView
android:id="@+id/toggleCategoryIcon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginStart="4dp"
android:src="@drawable/ic_expand_less_24"
android:tint="#9966CC" />
</LinearLayout>
```
#### 修复布局结构
- 添加缺失的 `orbitContainer` 开始标签
- 修复 `LinearLayout``NestedScrollView` 闭合标签
---
## 三、许愿树功能修复
### 3.1 路由文件修复
**文件:** `Zhibo/admin/src/router/modules/wishtreeManage.js`
**修改内容:** 将所有视图路径从大写 `wishTree` 改为小写 `wishtree`
```javascript
// 修改前
component: () => import('@/views/wishTree/festival/index')
// 修改后
component: () => import('@/views/wishtree/festival/index')
```
**涉及的路由:**
- `/wishtree/festival` - 节日管理
- `/wishtree/wish` - 心愿管理
- `/wishtree/background` - 背景素材
- `/wishtree/statistics` - 数据统计
- `/wishtree/tree` - 许愿树列表
- `/wishtree/tree/detail/:id` - 许愿树详情
- `/wishtree/node` - 节点管理
- `/wishtree/message` - 留言管理
### 3.2 API文件重命名
**操作:** 将 `Zhibo/admin/src/api/wishTree.js` 重命名为 `wishtree.js`
**原因:** 视图文件中引用的是 `@/api/wishtree`(小写),但实际文件名是 `wishTree.js`大写T
---
## 四、管理端修复
### 4.1 API地址配置
**文件:** `Zhibo/admin/.env.development`
```bash
# 修改前
VUE_APP_BASE_API = 'http://192.168.1.244:30001'
# 修改后
VUE_APP_BASE_API = 'http://192.168.1.244:8081'
```
### 4.2 登录页面修复
**文件:** `Zhibo/admin/src/views/login/index.vue`
**修改内容:** 添加空值检查,防止后端返回空数据时报错
```javascript
// 修改前
getInfo() {
getLoginPicApi().then((res) => {
this.swiperList = res.banner;
this.loginLogo = res.loginLogo;
this.backgroundImages = res.backgroundImage;
localStorage.setItem('singleAdminSiteName', res.siteName);
});
},
// 修改后
getInfo() {
getLoginPicApi().then((res) => {
if (res) {
this.swiperList = res.banner || [];
this.loginLogo = res.loginLogo || '';
this.backgroundImages = res.backgroundImage || '';
localStorage.setItem('singleAdminSiteName', res.siteName || '');
}
}).catch(() => {
// 忽略获取登录图片的错误
});
},
```
---
## 五、代码修改详情
### 5.1 修改文件列表
| 文件路径 | 修改类型 | 说明 |
|---------|---------|------|
| `android-app/.../FishPondActivity.java` | 修改 | 添加板块收起/展开功能 |
| `android-app/.../CategoryAdapter.java` | 修改 | 完善图标映射和智能匹配 |
| `android-app/.../activity_fish_pond.xml` | 修改 | 添加收起按钮布局 |
| `Zhibo/admin/.../wishtreeManage.js` | 修改 | 修复路由路径 |
| `Zhibo/admin/.../login/index.vue` | 修改 | 添加空值检查 |
| `Zhibo/admin/.env.development` | 修改 | 修复API端口 |
| `Zhibo/admin/src/api/wishtree.js` | 重命名 | 从wishTree.js重命名 |
---
## 六、新增文件清单
### 6.1 图标资源文件
#### ic_user_24.xml - 用户图标(粉色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF6B9D"
android:pathData="M12,12a4,4 0,1 0,-4 -4a4,4 0,0 0,4 4zm0,2c-4.42,0 -8,2.24 -8,5v1h16v-1c0,-2.76 -3.58,-5 -8,-5z" />
</vector>
```
#### ic_smartphone_24.xml - 手机图标(橙色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF7043"
android:pathData="M17,1H7C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1 17,1zM17,19H7V5h10V19zM12,17.5c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1s-1,0.45 -1,1S11.45,17.5 12,17.5z" />
</vector>
```
#### ic_headset_24.xml - 耳机图标(青色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#26C6DA"
android:pathData="M12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z" />
</vector>
```
#### ic_play_circle_24.xml - 播放图标(橙红色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF7043"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM10,16.5v-9l6,4.5L10,16.5z" />
</vector>
```
#### ic_target_24.xml - 瞄准图标(橙色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF7043"
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4s4,-1.79 4,-4S14.21,8 12,8zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8c1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12C20,16.42 16.42,20 12,20z" />
</vector>
```
#### ic_grid3x3_24.xml - 九宫格图标(青绿色)
```xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#26A69A"
android:pathData="M4,4h4v4H4V4zM10,4h4v4h-4V4zM16,4h4v4h-4V4zM4,10h4v4H4v-4zM10,10h4v4h-4v-4zM16,10h4v4h-4v-4zM4,16h4v4H4v-4zM10,16h4v4h-4v-4zM16,16h4v4h-4v-4z" />
</vector>
```
---
## 七、API对接说明
### 7.1 缘池相关API
| API | 方法 | 说明 |
|-----|------|------|
| `/api/front/community/categories` | GET | 获取板块列表 |
| `/api/front/community/messages` | GET | 获取消息列表支持categoryId筛选 |
| `/api/front/community/messages` | POST | 发布消息 |
| `/api/front/community/nearby-users` | GET | 获取附近用户 |
### 7.2 数据结构
#### Category板块
```json
{
"id": 1,
"name": "在线处对象",
"icon": "el-icon-user",
"type": "card",
"jumpPage": "OnlineDatingActivity",
"sort": 90,
"status": 1
}
```
#### Message消息
```json
{
"id": 1,
"uid": 100,
"nickname": "用户昵称",
"avatar": "头像URL",
"categoryId": 1,
"categoryName": "在线处对象",
"content": "消息内容",
"images": "图片URL1,图片URL2",
"status": 1,
"createTime": "2026-01-02 12:00:00"
}
```
---
## 八、功能验证清单
### 8.1 缘池功能
- [x] 板块从后端动态加载
- [x] 图标根据管理端设置显示
- [x] 板块收起/展开动画
- [x] 点击板块跳转对应页面
- [x] 附近用户轨道展示
### 8.2 许愿树功能
- [x] 管理端路由正常访问
- [x] API接口正常调用
### 8.3 管理端
- [x] 登录页面正常显示
- [x] API连接正常8081端口
---
*报告生成时间2026年1月2日*
*开发环境Windows / Android Studio / Vue.js*