已知问题汇总.md 9.4 KB

已知问题汇总

最后更新: 2026-02-09 目的: 记录项目中的已知问题和解决方案,避免后续开发中重复踩坑

🔴 高优先级问题

1. 版本冲突

问题描述

项目中同时存在同一库的不同版本,可能导致兼容性问题。

具体案例

Photo Sphere Viewer:

// package.json
"photo-sphere-viewer": "^4.8.1",
"@photo-sphere-viewer/core": "^5.7.3",

影响:

  • VR 全景功能可能不稳定
  • 包体积增大
  • API 不一致

解决方案:

// 统一使用 5.x 版本
// 1. 移除旧版本
npm uninstall photo-sphere-viewer

// 2. 更新导入语句
// 之前: import { Viewer } from 'photo-sphere-viewer';
// 之后: import { Viewer } from '@photo-sphere-viewer/core';

日期管理库:

// package.json
"dayjs": "^1.11.3",
"moment": "^2.29.3",

影响:

  • 包体积增大
  • API 不一致

解决方案:

// 统一使用 dayjs(更轻量)
// 1. 移除 moment
npm uninstall moment

// 2. 替换所有 moment 调用为 dayjs
// moment(date).format('YYYY-MM-DD')
// → dayjs(date).format('YYYY-MM-DD')

2. Keep-Alive 缓存问题

问题描述

keepPages 空数组会导致所有页面都被缓存。

具体案例

// src/store/index.js:25
keepPages: ['default'], // 很坑爹,空值全部都缓存

影响:

  • 如果 keepPages[],所有页面都会被缓存
  • 页面状态不会重置
  • 可能导致内存泄漏

解决方案:

// ✅ 正确:至少包含 'default' 作为占位符
keepPages: ['default']

// ❌ 错误:空数组
keepPages: []  // 会导致所有页面都被缓存

使用方法:

// 添加需要缓存的页面
const keepThisPage = () => {
  const keepPages = [...mainStore.keepPages];
  if (!keepPages.includes('PageName')) {
    keepPages.push('PageName');
  }
  mainStore.keepPages = keepPages;
};

3. 路由 Hash 模式

问题描述

项目使用 Hash 模式,所有路由必须包含 #/index.html 前缀。

具体案例

// src/router/index.js
history: createWebHashHistory('/index.html')

影响:

  • URL 格式: http://localhost:8006/index.html#/index.html/views/page
  • 如果忘记前缀,路由无法匹配

解决方案:

// ✅ 正确:使用完整路径
router.push('/index.html/views/page')

// ❌ 错误:缺少前缀
router.push('/views/page')

// ✅ 推荐:使用路由名称
router.push({ name: 'PageName' })

🟡 中优先级问题

4. jQuery 依赖

问题描述

项目仍使用 jQuery,与 Vue 3 冲突。

具体案例

// src/components/VRViewer/index.vue:23
import $ from 'jquery';

// 使用 jQuery 操作 DOM
$('.psv-zoom-button').css('display', '');

影响:

  • 不符合 Vue 3 理念
  • 性能较差
  • 不利于维护

解决方案:

// ❌ 错误:使用 jQuery
import $ from 'jquery';
$('.psv-zoom-button').css('display', '');

// ✅ 正确:使用 Vue 原生 API
import { ref, onMounted } from 'vue';

const zoomButton = ref(null);

onMounted(() => {
  if (zoomButton.value) {
    zoomButton.value.style.display = '';
  }
});

迁移优先级:

  1. 新代码避免使用 jQuery
  2. 逐步重构现有 jQuery 代码
  3. 最终完全移除 jQuery 依赖

5. 全局样式注入

问题描述

Less 配置中全局注入 base.less,所有组件都会包含全局样式。

具体案例

// vite.config.js:107
additionalData: `@import "${path.resolve(__dirname, 'src/assets/styles/base.less')}";`

影响:

  • 所有 .vue 文件中的 <style lang="less"> 都会包含全局样式
  • 可能导致样式冲突
  • 编译时间增加

解决方案:

/* ✅ 推荐:仅在需要时导入 */
@import './base.less';

/* ❌ 不推荐:重复导入 */
/* base.less 已经全局注入,无需重复导入 */

6. SVG 渲染性能

问题描述

复杂 SVG 可能导致渲染卡顿。

具体案例

<!-- src/components/Floor/index.vue -->
<div v-html="level.svg"></div>

影响:

  • 楼层平面图 SVG 可能很复杂
  • 渲染时间长
  • 可能导致页面卡顿

解决方案:

// 1. 简化 SVG 路径
// 2. 使用懒加载
const loadFloorSVG = async (level) => {
  const { data } = await mapAPI({ id: locationId, level });
  return data.svg;
};

// 3. 使用 will-change 优化
.floor-svg {
  will-change: transform;
}

7. XSS 风险

问题描述

使用 v-html 渲染 SVG 可能存在 XSS 风险。

具体案例

<div v-html="level.svg"></div>

风险:

  • 如果 SVG 来自用户输入或不可信来源
  • 可能包含恶意脚本

解决方案:

// 安装 DOMPurify
npm install dompurify

// 清理 SVG
import DOMPurify from 'dompurify';

const cleanSVG = DOMPurify.sanitize(svgString);

🟢 低优先级问题

8. 代码重复

问题描述

多个页面中存在重复的代码模式。

具体案例

信息窗口组件:

  • InfoWindowLite.vue
  • InfoWindowWarn.vue
  • InfoWindowYard.vue
  • InfoPopupLite.vue
  • InfoPopupWarn.vue

影响:

  • 维护成本高
  • 代码重复

解决方案:

// ✅ 推荐:合并为一个组件,使用 props 控制样式
<InfoWindow
  :variant="'lite' | 'warn' | 'yard'"
  :title="title"
  :description="description"
/>

// ❌ 不推荐:维护多个相似组件
<InfoWindowLite :title="title" />
<InfoWindowWarn :title="title" />
<InfoWindowYard :title="title" />

9. 缺少类型定义

问题描述

项目使用 TypeScript,但缺少完整的类型定义。

具体案例

// src/auto-imports.d.ts(自动生成)
// 但很多组件和函数缺少类型定义

影响:

  • IDE 提示不完整
  • 容易出现类型错误
  • 不利于重构

解决方案:

// 为组件添加类型定义
// src/components/Floor/index.vue

interface FloorData {
  svg: string;
  pin: PinData[];
}

interface PinData {
  category: string;
  space: string;
  icon: string;
  style: Record<string, string>;
  info?: InfoData;
}

10. 测试覆盖不足

问题描述

项目缺少完整的测试覆盖。

具体案例

// src/test/mocha/test.js(仅有一个测试文件)

影响:

  • 重构时容易引入 Bug
  • 难以保证代码质量

解决方案:

// 补充单元测试
// tests/components/Floor.spec.js
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import Floor from '@/components/Floor/index.vue';

describe('Floor', () => {
  it('should render floor list', () => {
    const wrapper = mount(Floor, {
      props: {
        levelList: [...],
      },
    });

    expect(wrapper.findAll('.level').length).toBe(4);
  });
});

⚠️ 注意事项

1. 环境变量

问题: 环境变量必须以 VITE_ 开头

// ✅ 正确
VITE_PORT=8006
VITE_PROXY_TARGET=http://api.example.com

// ❌ 错误
PORT=8006
PROXY_TARGET=http://api.example.com

2. 路径别名

问题: 使用路径别名时必须使用绝对路径

// ✅ 正确
import Floor from '@components/Floor/index.vue';

// ❌ 错误
import Floor from '../../components/Floor/index.vue';

3. 组件命名

问题: 组件文件名必须使用 PascalCase

// ✅ 正确
audioList.vue
InfoWindowLite.vue
VRViewer/index.vue

// ❌ 错误
audio-list.vue
infoWindowLite.vue
vr-viewer/index.vue

4. API 响应检查

问题: 所有 API 调用必须检查 res.code === 1

// ✅ 正确
const { data } = await mapAPI(params);
if (res.code === 1 && res.data) {
  // 处理数据
}

// ❌ 错误
const { data } = await mapAPI(params);
if (data) {
  // res.code 未检查,可能处理错误数据
}

5. 异步错误处理

问题: 所有 async 函数必须有 try-catch

// ✅ 正确
const fetchData = async () => {
  try {
    const { data } = await mapAPI(params);
    return data;
  } catch (err) {
    console.error('请求失败:', err);
    return null;
  }
};

// ❌ 错误
const fetchData = async () => {
  const { data } = await mapAPI(params);
  return data;
  // 错误未处理,可能导致应用崩溃
};

📝 待解决问题

1. 多页面应用配置未清理

问题: src/packages/ 目录存在但未使用

影响:

  • 代码混乱
  • 构建时间增加

建议: 归档或删除未使用的多页面应用代码

2. 文件历史目录

问题: .history/ 目录存在

影响:

  • Git 仓库混乱
  • 磁盘空间浪费

建议: 添加到 .gitignore

3. 控制台调试代码

问题: 项目中可能存在 console.logdebugger

影响:

  • 生产环境性能
  • 可能泄露敏感信息

建议: 使用 ESLint 检测并移除调试代码

4. 图片优化

问题: 图片未压缩和优化

影响:

  • 加载速度慢
  • 流量消耗大

建议:

  • 使用 WebP 格式
  • 压缩图片
  • 使用 CDN 优化

参考文档