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.1 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
v-model Breaking Changes from Vue 2 to Vue 3 HIGH Vue 3 changed v-model prop/event names and removed .sync modifier - migration required migration
vue3
vue2
v-model
migration
breaking-changes
sync

v-model Breaking Changes from Vue 2 to Vue 3

Impact: HIGH - Vue 3 fundamentally changed how v-model works on custom components. Code using the Vue 2 pattern will silently fail - the component won't receive the prop value and changes won't propagate to the parent.

Task Checklist

  • Change prop name from value to modelValue
  • Change event name from input to update:modelValue
  • Replace .sync modifier with v-model:propName
  • Remove model component option (use defineModel or named v-model)
  • Update any v-bind.sync to v-model with named argument

Key Breaking Changes

Feature Vue 2 Vue 3
Default prop value modelValue
Default event input update:modelValue
Custom name model: { prop, event } v-model:customName
Sync modifier v-bind:prop.sync v-model:prop
Multiple models Not supported Fully supported

Vue 2 Pattern (No longer works in Vue 3):

<!-- Vue 2 Child Component -->
<script>
export default {
  props: ['value'],  // WRONG in Vue 3
  methods: {
    update(val) {
      this.$emit('input', val)  // WRONG in Vue 3
    }
  }
}
</script>

<template>
  <input :value="value" @input="update($event.target.value)">
</template>

Vue 3 Pattern (Options API):

<!-- Vue 3 Child Component -->
<script>
export default {
  props: ['modelValue'],  // Changed from 'value'
  emits: ['update:modelValue'],  // Declare emits
  methods: {
    update(val) {
      this.$emit('update:modelValue', val)  // Changed from 'input'
    }
  }
}
</script>

<template>
  <input :value="modelValue" @input="update($event.target.value)">
</template>

Vue 3 Pattern (Composition API with defineModel):

<!-- Vue 3 Child Component - Recommended -->
<script setup>
const model = defineModel()  // Handles prop and emit automatically
</script>

<template>
  <input v-model="model">
</template>

Migrating the .sync Modifier

Vue 2's .sync modifier is removed. Use named v-model instead.

Vue 2:

<!-- Parent -->
<MyComponent :title.sync="pageTitle" />

<!-- Child -->
<script>
export default {
  props: ['title'],
  methods: {
    updateTitle(val) {
      this.$emit('update:title', val)  // .sync pattern
    }
  }
}
</script>

Vue 3:

<!-- Parent -->
<MyComponent v-model:title="pageTitle" />

<!-- Child with defineModel -->
<script setup>
const title = defineModel('title')
</script>

<template>
  <input v-model="title">
</template>

<!-- Child with manual props/emits -->
<script setup>
const props = defineProps(['title'])
const emit = defineEmits(['update:title'])
</script>

<template>
  <input
    :value="props.title"
    @input="emit('update:title', $event.target.value)"
  >
</template>

Migrating Custom model Option

Vue 2's model component option is removed.

Vue 2:

<script>
export default {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: ['checked']
}
</script>

Vue 3:

<!-- Use named v-model argument instead -->
<!-- Parent -->
<MyCheckbox v-model:checked="isChecked" />

<!-- Child -->
<script setup>
const checked = defineModel('checked')
</script>

Multiple v-model Bindings (New in Vue 3)

Vue 3 allows multiple v-model directives on a single component:

<!-- Parent -->
<UserForm
  v-model:firstName="first"
  v-model:lastName="last"
  v-model:email="email"
/>

<!-- Child -->
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
const email = defineModel('email')
</script>

<template>
  <input v-model="firstName" placeholder="First Name">
  <input v-model="lastName" placeholder="Last Name">
  <input v-model="email" type="email" placeholder="Email">
</template>

Reference