400 lines
8.2 KiB
Markdown
400 lines
8.2 KiB
Markdown
# Vuex 错误修复说明
|
||
|
||
## 🔍 问题描述
|
||
|
||
控制台出现多个 Vuex 相关错误:
|
||
|
||
1. `[vuex] unknown action type: getSysTitle`
|
||
2. `[vuex] unknown getter: isServerRun`
|
||
3. `[vuex] unknown getter: infoMsg`
|
||
4. `Unknown custom element: <asyncModal>`
|
||
|
||
## 📝 修复内容
|
||
|
||
### 1. 修复 `getSysTitle` action 错误
|
||
|
||
**问题位置**:`src/components/main/main.vue`
|
||
|
||
**错误原因**:
|
||
- 在 `created` 钩子中调用了 `this.$store.dispatch('getSysTitle')`
|
||
- 缺少模块命名空间前缀 `app/`
|
||
- 且在 `demo-project/src/main.js` 中已经调用过,不需要重复调用
|
||
|
||
**修改前**:
|
||
```javascript
|
||
created() {
|
||
this.init()
|
||
},
|
||
methods: {
|
||
async init() {
|
||
await this.$store.dispatch('getSysTitle') // ❌ 错误
|
||
},
|
||
}
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
created() {
|
||
this.init()
|
||
},
|
||
methods: {
|
||
async init() {
|
||
// 获取系统标题(已在 main.js 中调用,这里不需要重复调用)
|
||
// await this.$store.dispatch('app/getSysTitle')
|
||
},
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- ✅ 移除了重复的 `getSysTitle` 调用
|
||
- ✅ 系统标题在 `demo-project/src/main.js` 的 `mounted` 钩子中统一获取
|
||
- ✅ 避免了重复请求
|
||
|
||
### 2. 修复 `isServerRun` getter 错误
|
||
|
||
**问题位置**:`src/components/main/components/terminal/index.vue`
|
||
|
||
**错误原因**:
|
||
- 使用了不存在的 `isServerRun` getter
|
||
- 这是 Terminal 功能相关的状态,但 store 中没有定义
|
||
|
||
**修改前**:
|
||
```javascript
|
||
computed: {
|
||
...mapGetters({
|
||
isServerRun: 'isServerRun' // ❌ 不存在的 getter
|
||
}),
|
||
iconclass() {
|
||
let curClass = 'terminal-icon ml10 '
|
||
if (this.isServerRun) {
|
||
curClass += ' run'
|
||
}
|
||
return curClass
|
||
}
|
||
},
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
computed: {
|
||
iconclass() {
|
||
let curClass = 'terminal-icon ml10'
|
||
// Terminal 功能暂时禁用
|
||
// if (this.isServerRun) {
|
||
// curClass += ' run'
|
||
// }
|
||
return curClass
|
||
}
|
||
},
|
||
```
|
||
|
||
**说明**:
|
||
- ✅ 移除了对不存在的 `isServerRun` getter 的依赖
|
||
- ✅ Terminal 功能暂时禁用
|
||
- ✅ 如果需要启用,需要在 store 中添加相应的 state 和 getter
|
||
|
||
### 3. 修复 `infoMsg` getter 错误
|
||
|
||
**问题位置**:`src/components/main/components/terminal/terminal.vue`
|
||
|
||
**错误原因**:
|
||
- 使用了不存在的 `infoMsg` getter
|
||
- 调用了不存在的 `clearInfoMsg` mutation 和 `setInteverLog` action
|
||
|
||
**修改前**:
|
||
```javascript
|
||
computed: {
|
||
...mapGetters({
|
||
infoMsg: 'infoMsg' // ❌ 不存在的 getter
|
||
})
|
||
},
|
||
methods: {
|
||
clearLog() {
|
||
this.$store.commit('clearInfoMsg') // ❌ 不存在的 mutation
|
||
},
|
||
reloadLog() {
|
||
this.$store.dispatch('setInteverLog') // ❌ 不存在的 action
|
||
},
|
||
}
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
computed: {
|
||
infoMsg() {
|
||
// Terminal 功能暂时禁用
|
||
return '终端功能暂未启用'
|
||
}
|
||
},
|
||
methods: {
|
||
clearLog() {
|
||
// Terminal 功能暂时禁用
|
||
this.$Message.info('终端功能暂未启用')
|
||
},
|
||
reloadLog() {
|
||
// Terminal 功能暂时禁用
|
||
this.$Message.info('终端功能暂未启用')
|
||
},
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- ✅ 移除了对不存在的 Vuex 状态的依赖
|
||
- ✅ 提供了友好的提示信息
|
||
- ✅ 避免了运行时错误
|
||
|
||
### 4. 修复 `asyncModal` 组件未注册错误
|
||
|
||
**问题位置**:`src/components/main/components/terminal/index.vue`
|
||
|
||
**错误原因**:
|
||
- 模板中使用了 `<asyncModal>` 组件
|
||
- 但没有在 `components` 中注册
|
||
|
||
**修改前**:
|
||
```javascript
|
||
import { mapGetters } from 'vuex'
|
||
import Terminal from './terminal.vue'
|
||
export default {
|
||
components: {
|
||
Terminal // ❌ 缺少 asyncModal
|
||
},
|
||
}
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
import Terminal from './terminal.vue'
|
||
import asyncModal from '@/components/asyncModal'
|
||
export default {
|
||
components: {
|
||
Terminal,
|
||
asyncModal // ✅ 添加 asyncModal 组件
|
||
},
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- ✅ 导入了 `asyncModal` 组件
|
||
- ✅ 在 `components` 中注册
|
||
- ✅ 移除了不需要的 `mapGetters` 导入
|
||
|
||
## 📊 修复总结
|
||
|
||
### 修改的文件
|
||
|
||
1. **`src/components/main/main.vue`**
|
||
- 移除了重复的 `getSysTitle` 调用
|
||
|
||
2. **`src/components/main/components/terminal/index.vue`**
|
||
- 移除了 `isServerRun` getter 的使用
|
||
- 添加了 `asyncModal` 组件注册
|
||
|
||
3. **`src/components/main/components/terminal/terminal.vue`**
|
||
- 移除了 `infoMsg` getter 的使用
|
||
- 修改了 `clearLog` 和 `reloadLog` 方法
|
||
|
||
### 错误修复
|
||
|
||
- ✅ `[vuex] unknown action type: getSysTitle` - 已修复
|
||
- ✅ `[vuex] unknown getter: isServerRun` - 已修复
|
||
- ✅ `[vuex] unknown getter: infoMsg` - 已修复
|
||
- ✅ `Unknown custom element: <asyncModal>` - 已修复
|
||
|
||
## 💡 Terminal 功能说明
|
||
|
||
### 当前状态
|
||
|
||
Terminal 功能已**暂时禁用**,因为:
|
||
- 缺少相关的 Vuex store 配置
|
||
- 缺少后端接口支持
|
||
- 不影响系统核心功能
|
||
|
||
### 如何启用 Terminal 功能
|
||
|
||
如果需要启用 Terminal 功能,需要:
|
||
|
||
**1. 在 Vuex store 中添加 Terminal 模块**
|
||
|
||
创建 `src/store/terminal.js`:
|
||
```javascript
|
||
export default {
|
||
namespaced: true,
|
||
state: {
|
||
isServerRun: false,
|
||
infoMsg: ''
|
||
},
|
||
getters: {
|
||
isServerRun: state => state.isServerRun,
|
||
infoMsg: state => state.infoMsg
|
||
},
|
||
mutations: {
|
||
setServerRun(state, value) {
|
||
state.isServerRun = value
|
||
},
|
||
setInfoMsg(state, msg) {
|
||
state.infoMsg += msg + '\n'
|
||
},
|
||
clearInfoMsg(state) {
|
||
state.infoMsg = ''
|
||
}
|
||
},
|
||
actions: {
|
||
async setInteverLog({ commit }) {
|
||
// 实现日志加载逻辑
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**2. 在 `src/store/index.js` 中注册模块**
|
||
|
||
```javascript
|
||
import terminal from './terminal'
|
||
|
||
export default new Vuex.Store({
|
||
modules: {
|
||
user,
|
||
app,
|
||
terminal // 添加 terminal 模块
|
||
}
|
||
})
|
||
```
|
||
|
||
**3. 更新组件代码**
|
||
|
||
`src/components/main/components/terminal/index.vue`:
|
||
```javascript
|
||
computed: {
|
||
...mapGetters('terminal', {
|
||
isServerRun: 'isServerRun'
|
||
}),
|
||
iconclass() {
|
||
let curClass = 'terminal-icon ml10 '
|
||
if (this.isServerRun) {
|
||
curClass += ' run'
|
||
}
|
||
return curClass
|
||
}
|
||
}
|
||
```
|
||
|
||
`src/components/main/components/terminal/terminal.vue`:
|
||
```javascript
|
||
computed: {
|
||
...mapGetters('terminal', {
|
||
infoMsg: 'infoMsg'
|
||
})
|
||
},
|
||
methods: {
|
||
clearLog() {
|
||
this.$store.commit('terminal/clearInfoMsg')
|
||
},
|
||
reloadLog() {
|
||
this.$store.dispatch('terminal/setInteverLog')
|
||
}
|
||
}
|
||
```
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. 系统标题获取时机
|
||
|
||
系统标题在 `demo-project/src/main.js` 的 `mounted` 钩子中获取:
|
||
|
||
```javascript
|
||
mounted() {
|
||
AdminFramework.uiTool.setRem()
|
||
|
||
// 只在已登录时获取系统标题
|
||
const token = this.$store.state.user.token
|
||
if (token) {
|
||
this.$store.dispatch('app/getSysTitle', {
|
||
defaultTitle: 'Demo 管理系统',
|
||
defaultLogo: ''
|
||
})
|
||
} else {
|
||
document.title = 'Demo 管理系统'
|
||
}
|
||
}
|
||
```
|
||
|
||
**不要在其他地方重复调用**,避免:
|
||
- 重复的 HTTP 请求
|
||
- 不必要的性能开销
|
||
- 可能的竞态条件
|
||
|
||
### 2. Vuex 模块命名空间
|
||
|
||
所有 Vuex 模块都使用了 `namespaced: true`:
|
||
|
||
```javascript
|
||
// ✅ 正确的调用方式
|
||
this.$store.dispatch('app/getSysTitle')
|
||
this.$store.commit('user/setToken', token)
|
||
this.$store.getters['user/userName']
|
||
|
||
// ❌ 错误的调用方式
|
||
this.$store.dispatch('getSysTitle')
|
||
this.$store.commit('setToken', token)
|
||
this.$store.getters['userName']
|
||
```
|
||
|
||
**使用 mapGetters/mapActions 时**:
|
||
```javascript
|
||
// ✅ 正确
|
||
...mapGetters('app', ['sysFormModel'])
|
||
...mapActions('user', ['handleLogin'])
|
||
|
||
// 或者
|
||
...mapGetters({
|
||
sysFormModel: 'app/sysFormModel'
|
||
})
|
||
```
|
||
|
||
### 3. 组件注册
|
||
|
||
使用第三方组件或自定义组件时,必须:
|
||
1. 导入组件
|
||
2. 在 `components` 中注册
|
||
3. 才能在模板中使用
|
||
|
||
```javascript
|
||
// ✅ 正确
|
||
import asyncModal from '@/components/asyncModal'
|
||
export default {
|
||
components: {
|
||
asyncModal
|
||
}
|
||
}
|
||
|
||
// ❌ 错误(直接在模板中使用未注册的组件)
|
||
<template>
|
||
<asyncModal></asyncModal>
|
||
</template>
|
||
```
|
||
|
||
## ✅ 验证清单
|
||
|
||
### 功能验证
|
||
|
||
- ✅ 登录功能正常
|
||
- ✅ 系统标题正确显示
|
||
- ✅ 菜单正确显示
|
||
- ✅ 页面跳转正常
|
||
- ✅ 控制台没有 Vuex 错误
|
||
|
||
### 错误检查
|
||
|
||
- ✅ 没有 `[vuex] unknown action` 错误
|
||
- ✅ 没有 `[vuex] unknown getter` 错误
|
||
- ✅ 没有 `Unknown custom element` 错误
|
||
- ✅ 没有组件注册错误
|
||
|
||
---
|
||
|
||
**所有 Vuex 错误已修复!** 🎉
|
||
|
||
现在系统可以正常运行,Terminal 功能暂时禁用但不影响核心功能。
|
||
|