12451 b553c4e519 feat: API 统一 + 设备详情补全 + H5 导航优化
- API 路由统一: 移除 /api/h5/,统一 /api/pms/ 入口
- 二进制改名: api-server -> pms-api(与服务名一致)
- nginx: 合并 /api/ + /pms/api/ 为 /api/pms/
- 新增 docs/API.md 接口文档
- 后端: CabinetDetail 增加 rssi/pow_fail/address/soc 等字段
- Redis 管道批量读取仓体实时数据(SOC/电压/电流/功率)
- DB: 所有 TIMESTAMP 列改为 DATETIME(修复类型不匹配)
- 用户管理: 新增创建时间/修改时间列,状态改用 Switch
- 角色管理/用户管理: 操作按钮改为图标
- PC 设备详情: 基本信息补全 RSSI/ICCID/电源/地址
- PC 卡片: 通道统计改用 Lucide 图标,颜色统一
- PC 二维码: canvas 渲染,含编号文字,支持右键下载
- H5: 按 uni-app 规范修正导航(navigateTo 替代 reLaunch)
- H5: 详情页加返回导航条
- H5: 扫码支持摄像头(jsQR)+ ?id= 参数
- H5: 底部 tabBar 在所有页面常显
- H5: 首页统计改为 6 项(设备/通道/空闲/充电/充满/故障)
- H5: 下拉刷新 / 上拉加载
- 产品首页: 添加业务联系
- 文档: 清理过时文件,补充缺失规范章节
2026-07-04 04:03:02 +08:00

4.4 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
Avoid Component Naming Conflicts Between Global and Local HIGH Naming conflicts cause unexpected component rendering and hard-to-debug issues gotcha
vue3
component-registration
naming-conflicts
global-local
debugging

Avoid Component Naming Conflicts Between Global and Local

Impact: HIGH - When a global component and a local component have the same name (or resolve to the same name due to casing differences), unexpected behavior occurs. The precedence rules can be confusing, and the wrong component may render silently without any error. This is particularly problematic when using third-party component libraries.

Task Checklist

  • Use unique, prefixed names for global components (e.g., BaseButton, AppHeader)
  • Check for naming conflicts when adding global components
  • Explicitly alias local components if there's potential conflict
  • When overriding third-party components, document and test thoroughly

Incorrect:

// main.js
import { createApp } from 'vue'
import Button from './components/Button.vue'

const app = createApp(App)
app.component('Button', Button) // Global Button
<!-- SomeComponent.vue -->
<script setup>
// This local Button might conflict with global Button
import Button from './local/Button.vue'
</script>

<template>
  <!-- Which Button renders? Behavior may be unexpected -->
  <Button>Click me</Button>
</template>
<!-- Another confusing scenario -->
<script setup>
// Registering with camelCase
import MyButton from './MyButton.vue'
</script>

<template>
  <!-- Using kebab-case - might match a global 'my-button' instead -->
  <my-button>Click</my-button>
</template>

Correct:

// main.js - use prefixes for global components
import { createApp } from 'vue'
import BaseButton from './components/BaseButton.vue'
import BaseIcon from './components/BaseIcon.vue'

const app = createApp(App)
app.component('BaseButton', BaseButton)
app.component('BaseIcon', BaseIcon)
<!-- SomeComponent.vue -->
<script setup>
// Local components have distinct names
import SubmitButton from './local/SubmitButton.vue'
</script>

<template>
  <!-- No ambiguity - each name is unique -->
  <BaseButton>Generic button</BaseButton>
  <SubmitButton>Submit form</SubmitButton>
</template>

Explicit Aliasing for Clarity

When you intentionally want to override or have similar names, use explicit aliasing:

<script setup>
// Explicit alias to avoid confusion
import { default as LocalButton } from './Button.vue'
</script>

<template>
  <LocalButton>Local version</LocalButton>
</template>
<!-- Options API with explicit component name -->
<script>
import ThirdPartyModal from 'some-library'
import CustomModal from './CustomModal.vue'

export default {
  components: {
    // Explicit names prevent ambiguity
    LibraryModal: ThirdPartyModal,
    CustomModal
  }
}
</script>

Resolution Order

Understanding Vue's component resolution order helps debug issues:

  1. Local registration takes precedence over global
  2. Exact case match takes precedence over case-insensitive match
  3. Self-referencing component name (file name) has lowest priority
<!-- If all exist: GlobalButton, local Button, and file is Button.vue -->
<script setup>
import Button from './Button.vue' // Local registration
</script>

<template>
  <!-- Resolves to locally imported Button, not global -->
  <Button />
</template>

Third-Party Library Conflicts

<script setup>
// Be explicit when using components from multiple libraries
import { Button as AntButton } from 'ant-design-vue'
import { Button as ElButton } from 'element-plus'
</script>

<template>
  <AntButton>Ant Design</AntButton>
  <ElButton>Element Plus</ElButton>
</template>

Naming Convention Strategy

Component Type Naming Pattern Example
Base/Global Base* or App* prefix BaseButton, AppHeader
Domain-specific Domain prefix UserCard, ProductList
Page components *Page or *View suffix HomePage, UserView
Layout components *Layout suffix DefaultLayout, AdminLayout

Reference