Skip to content

Commit 11f01b3

Browse files
authored
refactor: improve memory handling and app status display (#149)
- Update dev IP configuration - Replace grayscale with opacity for stopped apps - Convert memory units from MB to bytes for better precision - Add memory tooltip formatter in compose config - Enhance AppCard v-model implementation - Improve code formatting and component structure
1 parent ff4a5dc commit 11f01b3

File tree

9 files changed

+677
-163
lines changed

9 files changed

+677
-163
lines changed

.env.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# .env.dev
22
NODE_ENV=dev
33
#VUE_APP_DEV_IP=demo.casaos.io
4-
VUE_APP_DEV_IP=10.0.0.77
4+
VUE_APP_DEV_IP=10.0.0.111
55
# VUE_APP_DEV_IP=10.147.20.1
66
# VUE_APP_DEV_IP=192.168.2.15
77
# VUE_APP_DEV_IP=192.168.2.219

AppCard-Optimization-Summary.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# AppCard 组件优化总结
2+
3+
## 优化内容
4+
5+
### 1. 标准化 Vue 2 Model 实现
6+
- 添加了 `model` 选项,将 `item` 设置为 v-model 的绑定属性
7+
- 移除了 Vue 3 风格的 `modelValue` prop 和 `update:modelValue` 事件
8+
- 使用标准的 `update:item` 事件实现双向绑定
9+
10+
### 2. Props 验证和优化
11+
-`item` prop 添加了验证器,确保包含必需的属性 (`name`, `status`, `app_type`)
12+
-`appIds` prop 添加了默认值,提高组件的健壮性
13+
14+
### 3. 数据更新管理
15+
添加了专用的数据更新方法:
16+
- `updateItem(updates)`: 通用的数据更新方法,带错误处理
17+
- `updateItemStatus(status)`: 专门用于更新状态的方法
18+
- `resetItem(initialData)`: 重置 item 数据的辅助方法
19+
- `getCurrentItem()`: 获取当前 item 数据的调试方法
20+
21+
### 4. 计算属性优化
22+
新增了多个有用的计算属性:
23+
- `canBeControlled`: 判断应用是否可以被控制
24+
- `showActionButton`: 判断是否显示操作按钮
25+
- `isSystemApp`: 判断是否为系统应用
26+
- `statusColorClass`: 状态颜色类名
27+
- `itemDisplayTitle`: 显示标题(带国际化)
28+
29+
### 5. 生命周期管理
30+
- 添加了 `created` 钩子进行数据验证
31+
- 添加了 `beforeDestroy` 钩子进行清理工作
32+
- 改进了定时器管理,防止内存泄漏
33+
34+
### 6. 错误处理
35+
-`updateItem` 方法中添加了错误处理
36+
-`created` 钩子中添加了数据验证
37+
- 添加了更多的调试信息和警告
38+
39+
### 7. 代码可读性提升
40+
- 使用计算属性替代模板中的复杂表达式
41+
- 标记了 `dotClass` 方法为已弃用,推荐使用新的计算属性
42+
- 优化了模板中的条件判断
43+
44+
## 使用方式变更
45+
46+
### 之前
47+
```vue
48+
<AppCard
49+
:model-value="appItem"
50+
@update:modelValue="appItem = $event"
51+
:app-ids="appIds"
52+
/>
53+
```
54+
55+
### 现在
56+
```vue
57+
<AppCard
58+
v-model="appItem"
59+
:app-ids="appIds"
60+
/>
61+
```
62+
63+
## 向后兼容性
64+
- 保留了原有的所有事件和方法
65+
- 保留了 `dotClass` 方法但标记为已弃用
66+
- 所有原有功能都可以正常工作
67+
68+
## 性能优化
69+
- 使用计算属性缓存复杂计算
70+
- 减少模板中的重复计算
71+
- 更好的内存管理和清理
72+
73+
## 代码质量
74+
- 添加了完整的 JSDoc 注释
75+
- 改进了错误处理和边界情况
76+
- 增强了类型检查和验证
77+
78+
这些优化使得 AppCard 组件更符合 Vue 2 的最佳实践,同时提高了代码的可维护性、可读性和健壮性。

AppCard-PropValidation-Fix.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# AppCard Prop 验证错误修复总结
2+
3+
## 问题描述
4+
出现了 "Invalid prop: custom validator check failed for prop 'item'" 错误,说明 AppCard 组件的 item prop 验证失败。
5+
6+
## 根本原因分析
7+
8+
### 1. 验证器过于严格
9+
原始验证器要求 `item` 对象必须包含 `['name', 'status', 'app_type']` 三个属性:
10+
```javascript
11+
validator(value) {
12+
const requiredProps = ['name', 'status', 'app_type'];
13+
return requiredProps.every(prop => value && value.hasOwnProperty(prop));
14+
}
15+
```
16+
17+
### 2. 组件接口不匹配
18+
AppSection.vue 在手动编辑后又使用了混合的绑定方式:
19+
- 使用了 `v-model="appList[index]"`
20+
- 但同时还有 `@update:model-value` 事件监听器
21+
- oldAppList 部分甚至绑定了错误的数组 `v-model="appList[index]"`
22+
23+
## 修复方案
24+
25+
### 1. 放宽 Props 验证器
26+
修改验证器使其更加宽容,提供更好的调试信息:
27+
28+
```javascript
29+
validator(value) {
30+
// 基础类型检查
31+
if (!value || typeof value !== 'object') {
32+
console.warn('[AppCard] item prop must be an object, received:', typeof value, value);
33+
return false;
34+
}
35+
36+
// 只要求必须有 name 属性
37+
if (!value.hasOwnProperty('name')) {
38+
console.warn('[AppCard] item prop must have "name" property, received:', Object.keys(value));
39+
return false;
40+
}
41+
42+
// 其他属性只是推荐,不强制要求
43+
const recommendedProps = ['status', 'app_type'];
44+
const missingProps = recommendedProps.filter(prop => !value.hasOwnProperty(prop));
45+
if (missingProps.length > 0) {
46+
console.warn('[AppCard] item prop missing recommended properties:', missingProps);
47+
}
48+
49+
return true;
50+
}
51+
```
52+
53+
### 2. 统一组件接口
54+
AppSection.vue 现在使用标准的 Vue 2 v-model:
55+
56+
```vue
57+
<!-- 修复前 -->
58+
<app-card
59+
v-model="appList[index]"
60+
@update:model-value="updateAppItem(index, $event)"
61+
/>
62+
63+
<!-- 修复后 -->
64+
<app-card
65+
v-model="appList[index]"
66+
/>
67+
```
68+
69+
### 3. 修复数组绑定错误
70+
oldAppList 部分的绑定已修复:
71+
72+
```vue
73+
<!-- 修复前(错误的数组绑定) -->
74+
<app-card v-model="appList[index]" />
75+
76+
<!-- 修复后 -->
77+
<app-card v-model="oldAppList[index]" />
78+
```
79+
80+
## Vue 2 v-model 工作原理
81+
82+
现在 AppCard 组件使用标准的 Vue 2 model:
83+
```javascript
84+
model: {
85+
prop: 'item',
86+
event: 'update:item'
87+
}
88+
```
89+
90+
这意味着:
91+
- `v-model="someData"` 等价于 `:item="someData"` + `@update:item="someData = $event"`
92+
- Vue 自动处理双向绑定,无需手动事件处理器
93+
- 数组元素的更新也会被正确响应
94+
95+
## 清理工作
96+
- 标记了 `updateAppItem``updateOldAppItem` 方法为已弃用
97+
- 这些方法现在不再需要,但保留用于向后兼容
98+
- 添加了调试日志以便追踪是否有代码还在使用它们
99+
100+
## 验证结果
101+
- ✅ 编译错误已解决
102+
- ✅ Props 验证通过
103+
- ✅ v-model 双向绑定正常工作
104+
- ✅ 数组更新响应正常
105+
106+
这次修复确保了:
107+
1. 更宽容的 props 验证,提供更好的错误诊断
108+
2. 标准化的 Vue 2 v-model 使用
109+
3. 正确的数组绑定
110+
4. 更简洁的代码结构

V-Model-Fix-Summary.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# V-Model 错误修复总结
2+
3+
## 问题描述
4+
在 Vue 2 中,不能在 v-for 循环中直接对迭代变量使用 v-model,因为这会尝试修改一个函数局部变量,无法更新原始数组。
5+
6+
## 错误代码
7+
```vue
8+
<div v-for="(item, index) in appList" :key="item.name">
9+
<app-card v-model="item" /> <!-- ❌ 错误:无法修改原数组 -->
10+
</div>
11+
```
12+
13+
## 修复方案
14+
15+
### 1. 更新 AppSection.vue 模板
16+
将直接的 v-model 绑定改为显式的 prop 和事件:
17+
18+
**修复前:**
19+
```vue
20+
<app-card v-model="item" />
21+
```
22+
23+
**修复后:**
24+
```vue
25+
<app-card
26+
:item="item"
27+
@update:item="updateAppItem(index, $event)"
28+
/>
29+
```
30+
31+
### 2. 添加数组更新方法
32+
在 AppSection.vue 的 methods 中添加专门的更新方法:
33+
34+
```javascript
35+
/**
36+
* @description: Update app item in appList array
37+
* @param {Number} index
38+
* @param {Object} newValue
39+
* @return {*} void
40+
*/
41+
updateAppItem(index, newValue) {
42+
this.$set(this.appList, index, newValue);
43+
}
44+
```
45+
46+
### 3. 统一处理方式
47+
同时更新了 oldAppList 的处理方式,保持一致性:
48+
49+
```vue
50+
<!-- 统一使用新的绑定方式 -->
51+
<app-card
52+
:item="item"
53+
@update:item="updateOldAppItem(index, $event)"
54+
/>
55+
```
56+
57+
## 技术要点
58+
59+
### Vue.set 的使用
60+
使用 `this.$set()` 确保 Vue 2 的响应式系统能正确检测到数组变化:
61+
```javascript
62+
this.$set(this.appList, index, newValue);
63+
```
64+
65+
### 为什么不能直接修改
66+
在 v-for 中,`item` 是一个临时变量引用,直接修改它不会影响原数组:
67+
```javascript
68+
// 这样做无效
69+
item.status = 'new-status'; // ❌ 只修改了局部引用
70+
71+
// 正确做法是通过索引更新原数组
72+
this.appList[index] = newItem; // ✅ 修改原数组
73+
```
74+
75+
## 修复范围
76+
- ✅ appList 循环中的 app-card 组件
77+
- ✅ oldAppList 循环中的 app-card 组件
78+
- ✅ 添加对应的更新方法
79+
- ✅ 确保响应式更新正常工作
80+
81+
## 验证
82+
- 编译错误已解决
83+
- 组件功能保持不变
84+
- 响应式更新正常工作
85+
- 代码更加符合 Vue 2 最佳实践
86+
87+
这个修复确保了数据能够正确地从子组件传播回父组件,并更新到原始数组中,同时保持了 Vue 的响应式特性。

src/assets/scss/common/_card.scss

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,9 @@
4646
position: relative;
4747

4848
&.stop img {
49-
filter: grayscale(100%);
49+
opacity: 0.5;
5050
}
5151

52-
//&.stop::after {
53-
// position: absolute;
54-
// content: "";
55-
// width: 0.75rem;
56-
// height: 0.75rem;
57-
// background-color: #ff1616;
58-
// border-radius: 50%;
59-
// right: -0.375rem;
60-
// top: -0.375rem;
61-
//}
62-
6352
img {
6453
border-radius: 8px;
6554
margin: 0 auto;
@@ -73,20 +62,9 @@
7362
justify-content: center;
7463

7564
&.stop img {
76-
filter: grayscale(100%);
65+
opacity: 0.5;
7766
}
7867

79-
//&.stop::after {
80-
// position: absolute;
81-
// content: "";
82-
// width: 0.75rem;
83-
// height: 0.75rem;
84-
// background-color: #ff1616;
85-
// border-radius: 50%;
86-
// right: -0.375rem;
87-
// top: -0.375rem;
88-
//}
89-
9068
img {
9169
border-radius: 8px;
9270
margin: 0 auto;

0 commit comments

Comments
 (0)