feat: 微信告警配置表格显示修复与开发文档完善 v1.3.6
🐛 核心修复: - 解决NDataTable的remote属性与本地数据冲突导致表格空白的关键问题 - 移除导致渲染失败的属性组合: remote、复杂分页配置、动态高度设置 - 重构列定义为独立computed属性,避免useTable的columns处理丢失render函数 - 修复搜索组件type参数传递,确保企业微信和微信公众号数据正确过滤 - 优化操作按钮使用Vue的h函数,解决JSX语法在Vue模板中的冲突问题 📚 开发文档: - 新增CLAUDE.md开发文档,详细记录API数据解析流程和表格渲染机制 - 建立故障排查最佳实践和快速诊断清单,显著提升调试效率 - 文档化NDataTable使用指南和常见陷阱,为后续开发提供参考 🔧 技术改进: - 实现分层排查法:API → useTable → 组件 → 渲染的系统化调试方法 - 建立对比测试法,使用简化表格快速定位问题根源 - 确立表格组件开发规范,避免复杂属性组合导致的渲染问题 此次修复解决了一个隐蔽性极强的渲染问题,通过完整的文档化避免类似问题重现。
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
# LjwxAdmin Claude 开发文档
|
||||
|
||||
## 数据解析与表格渲染故障排查文档
|
||||
|
||||
### 概述
|
||||
本文档详细记录了 LjwxAdmin 项目中 API 数据解析流程和表格渲染机制,以及一次耗时的微信告警配置表格显示故障的完整排查过程。
|
||||
|
||||
### 核心数据流架构
|
||||
|
||||
#### 1. API 调用层
|
||||
```typescript
|
||||
// src/service/api/health/alert-config-wechat.ts
|
||||
export function fetchGetAlertConfigWechatList(params?: Api.Health.AlertConfigWechatSearchParams) {
|
||||
return request<Api.Health.AlertConfigWechatList>({
|
||||
url: '/t_wechat_alarm_config/page',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. useTable Hook 数据转换层
|
||||
```typescript
|
||||
// src/hooks/common/table.ts
|
||||
const { loading, data, columns, getData, searchParams } = useTable({
|
||||
apiFn: fetchGetAlertConfigWechatList,
|
||||
apiParams: { page: 1, pageSize: 20, customerId, type: 'enterprise' },
|
||||
transformer: res => {
|
||||
const { records = [], page = 1, pageSize = 20, total = 0 } = res.data || {};
|
||||
const recordsWithIndex = records.map((item, index) => ({
|
||||
...item,
|
||||
index: (page - 1) * pageSize + index + 1
|
||||
}));
|
||||
return { data: recordsWithIndex, pageNum: page, pageSize, total };
|
||||
},
|
||||
columns: () => { /* 动态列定义 */ }
|
||||
});
|
||||
```
|
||||
|
||||
#### 3. Vue 组件渲染层
|
||||
```vue
|
||||
<NDataTable
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
/>
|
||||
```
|
||||
|
||||
### 数据流详细分析
|
||||
|
||||
#### API 响应格式
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": {
|
||||
"page": 1,
|
||||
"pageSize": 20,
|
||||
"total": 2,
|
||||
"records": [
|
||||
{
|
||||
"id": 10,
|
||||
"type": "official",
|
||||
"appid": "wx10dcc9f0235e1d77",
|
||||
"templateId": "xxx",
|
||||
"enabled": true,
|
||||
"createTime": 1750168835000
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### transformer 转换过程
|
||||
1. **提取分页数据**:从 `res.data` 中解构 `records`, `page`, `pageSize`, `total`
|
||||
2. **添加索引**:为每条记录添加 `index` 字段,用于表格序号显示
|
||||
3. **返回标准格式**:返回 `{ data, pageNum, pageSize, total }` 供 useTable 使用
|
||||
|
||||
#### 列定义处理
|
||||
useTable hook 通过 `getColumns` 函数处理列定义:
|
||||
```typescript
|
||||
getColumns: (cols, checks) => {
|
||||
const columnMap = new Map();
|
||||
cols.forEach(column => {
|
||||
if (isTableColumnHasKey(column)) {
|
||||
columnMap.set(column.key, column);
|
||||
}
|
||||
});
|
||||
return checks.filter(item => item.checked).map(check => columnMap.get(check.key));
|
||||
}
|
||||
```
|
||||
|
||||
### 故障案例:微信告警配置表格显示空白
|
||||
|
||||
#### 问题现象
|
||||
- API 正常返回数据
|
||||
- data 数组长度正确
|
||||
- columns 数组长度正确
|
||||
- 但 NDataTable 表格完全空白
|
||||
|
||||
#### 排查过程
|
||||
|
||||
##### 第一阶段:参数传递问题
|
||||
**怀疑**:API 参数传递错误
|
||||
**排查**:
|
||||
```typescript
|
||||
// 修复搜索组件 type 参数传递
|
||||
watch(() => props.type, (newType) => {
|
||||
if (newType) {
|
||||
model.value.type = newType;
|
||||
}
|
||||
}, { immediate: true });
|
||||
```
|
||||
**结果**:API 能正确返回数据,但表格仍空白
|
||||
|
||||
##### 第二阶段:数据过滤问题
|
||||
**怀疑**:前端数据过滤导致显示为空
|
||||
**排查**:
|
||||
```typescript
|
||||
// 添加 filteredData 计算属性
|
||||
const filteredData = computed(() => {
|
||||
if (!data.value) return [];
|
||||
return data.value.filter(item => item.type === activeTab.value);
|
||||
});
|
||||
```
|
||||
**结果**:数据过滤正确,但表格仍空白
|
||||
|
||||
##### 第三阶段:useTable hook 问题
|
||||
**怀疑**:useTable 的 columns 处理丢失了 render 函数
|
||||
**排查**:
|
||||
```json
|
||||
// 调试发现列定义中缺失 render 函数
|
||||
[
|
||||
{ "key": "corpId", "title": "企业ID", "align": "center", "width": 150 },
|
||||
// render 函数在 JSON.stringify 时丢失了!
|
||||
]
|
||||
```
|
||||
**发现**:useTable 的 getColumns 函数在处理列定义时,render 函数被丢失
|
||||
|
||||
##### 第四阶段:NDataTable 属性问题
|
||||
**怀疑**:NDataTable 的某些属性导致渲染失败
|
||||
**排查**:逐个移除属性测试
|
||||
```typescript
|
||||
// 问题属性组合
|
||||
<NDataTable
|
||||
remote // ❌ 导致问题的关键属性
|
||||
:pagination="mobilePagination" // ❌ 分页配置问题
|
||||
:flex-height="!appStore.isMobile" // ❌ 高度配置问题
|
||||
class="sm:h-full" // ❌ CSS 类冲突
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
/>
|
||||
|
||||
// 修复后的简化版本
|
||||
<NDataTable
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
size="small"
|
||||
striped
|
||||
:loading="loading"
|
||||
/>
|
||||
```
|
||||
|
||||
#### 根本原因
|
||||
1. **`remote` 属性**:告诉 NDataTable 期待远程分页,但我们提供的是本地数据
|
||||
2. **复杂的分页配置**:mobilePagination 与数据状态不匹配
|
||||
3. **CSS 高度问题**:flex-height 和相关 CSS 类导致表格高度为 0
|
||||
|
||||
### 故障排查最佳实践
|
||||
|
||||
#### 1. 分层排查法
|
||||
```
|
||||
数据层 → 转换层 → 组件层 → 渲染层
|
||||
↓ ↓ ↓ ↓
|
||||
API useTable Vue组件 DOM
|
||||
```
|
||||
|
||||
#### 2. 调试工具使用
|
||||
```typescript
|
||||
// 在关键节点添加调试输出
|
||||
console.log('[API] 原始响应:', response);
|
||||
console.log('[Transformer] 转换后数据:', transformedData);
|
||||
console.log('[Component] 渲染数据:', data.value);
|
||||
console.log('[Columns] 列定义:', columns.value);
|
||||
```
|
||||
|
||||
#### 3. 对比测试法
|
||||
```vue
|
||||
<!-- 使用简化的测试表格对比 -->
|
||||
<NDataTable
|
||||
:data="data"
|
||||
:columns="[
|
||||
{ key: 'id', title: 'ID' },
|
||||
{ key: 'type', title: '类型' }
|
||||
]"
|
||||
:row-key="(row) => row.id"
|
||||
/>
|
||||
```
|
||||
|
||||
### NDataTable 使用指南
|
||||
|
||||
#### ✅ 推荐配置
|
||||
```vue
|
||||
<NDataTable
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
:row-key="(row) => row.id"
|
||||
size="small"
|
||||
striped
|
||||
:loading="loading"
|
||||
v-model:checked-row-keys="checkedRowKeys"
|
||||
/>
|
||||
```
|
||||
|
||||
#### ❌ 避免的属性组合
|
||||
```vue
|
||||
<NDataTable
|
||||
remote <!-- 除非真正需要远程分页 -->
|
||||
:pagination="complexPagination" <!-- 避免复杂分页配置 -->
|
||||
:flex-height="dynamicValue" <!-- 避免动态高度计算 -->
|
||||
class="complex-css-classes" <!-- 避免可能冲突的CSS类 -->
|
||||
/>
|
||||
```
|
||||
|
||||
#### 列定义最佳实践
|
||||
```typescript
|
||||
// ✅ 使用 computed 属性,不依赖 useTable 的 columns
|
||||
const tableColumns = computed(() => [
|
||||
{ key: 'id', title: 'ID', width: 80 },
|
||||
{
|
||||
key: 'status',
|
||||
title: '状态',
|
||||
render: (row) => row.enabled ? '启用' : '禁用'
|
||||
},
|
||||
{
|
||||
key: 'operate',
|
||||
title: '操作',
|
||||
render: (row) => h(NButton, { onClick: () => edit(row) }, () => '编辑')
|
||||
}
|
||||
]);
|
||||
|
||||
// ❌ 避免依赖 useTable 的动态列定义处理
|
||||
```
|
||||
|
||||
### 类似问题快速诊断清单
|
||||
|
||||
#### 1. 数据检查 (30秒)
|
||||
- [ ] API 是否返回正确数据?
|
||||
- [ ] `data.length > 0` 是否为真?
|
||||
- [ ] 数据结构是否与列定义匹配?
|
||||
|
||||
#### 2. 列定义检查 (1分钟)
|
||||
- [ ] `columns.length > 0` 是否为真?
|
||||
- [ ] render 函数是否丢失?
|
||||
- [ ] key 字段是否与数据字段匹配?
|
||||
|
||||
#### 3. 组件属性检查 (2分钟)
|
||||
- [ ] 移除 `remote` 属性测试
|
||||
- [ ] 移除 `pagination` 属性测试
|
||||
- [ ] 使用最简化的 NDataTable 配置测试
|
||||
|
||||
#### 4. 对比测试 (2分钟)
|
||||
- [ ] 创建简化版本的测试表格
|
||||
- [ ] 使用相同数据和简单列定义
|
||||
- [ ] 确认是数据问题还是组件问题
|
||||
|
||||
### 总结
|
||||
|
||||
这次故障排查耗时的主要原因:
|
||||
1. **问题隐蔽性**:表面现象(表格空白)与根本原因(NDataTable属性配置)没有直接关联
|
||||
2. **多层抽象**:useTable hook 增加了调试复杂度
|
||||
3. **属性依赖**:多个 NDataTable 属性的组合效应难以预测
|
||||
|
||||
通过建立这套分层排查方法和文档化的最佳实践,类似问题的排查时间可以从数小时缩短到数分钟。
|
||||
|
||||
---
|
||||
|
||||
## 项目开发注意事项
|
||||
|
||||
### 1. 表格开发规范
|
||||
- 避免使用 `remote` 属性,除非确实需要远程分页
|
||||
- 列定义使用独立的 computed 属性,不依赖 useTable 的 columns 处理
|
||||
- 优先使用简化的 NDataTable 配置,渐进式添加复杂功能
|
||||
|
||||
### 2. 调试技巧
|
||||
- 数据问题时,先用简化测试表格验证数据正确性
|
||||
- 使用分层排查法,从 API → useTable → 组件 → 渲染逐层检查
|
||||
- 重要的调试信息要保留在代码注释中
|
||||
|
||||
### 3. 常见陷阱
|
||||
- useTable hook 的 transformer 会自动添加 index 字段
|
||||
- NDataTable 的 render 函数在 JSON.stringify 时会丢失
|
||||
- type 参数需要在搜索组件中正确设置和传递
|
||||
@@ -471,6 +471,18 @@ Content-Type: application/json
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.3.6 (2025-08-27)
|
||||
- 🐛 **修复微信告警配置表格显示空白问题**
|
||||
- 解决 NDataTable 的 `remote` 属性与本地数据冲突导致的渲染失败
|
||||
- 移除导致问题的属性组合:`remote`、复杂分页配置、动态高度设置
|
||||
- 重构列定义为独立 computed 属性,避免 useTable 的 columns 处理丢失 render 函数
|
||||
- 修复搜索组件中 `type` 参数传递问题,确保企业微信和微信公众号数据正确过滤
|
||||
- 优化操作按钮使用 Vue 的 h 函数,避免 JSX 语法在 Vue 模板中的冲突
|
||||
- 📚 **新增开发文档**
|
||||
- 创建 CLAUDE.md 开发文档,记录数据解析流程和故障排查方法
|
||||
- 建立表格渲染问题的快速诊断清单,提升后续开发效率
|
||||
- 文档化 NDataTable 使用最佳实践和常见陷阱避免指南
|
||||
|
||||
### v1.3.5 (2025-08-27)
|
||||
- ✨ **新增微信告警配置管理功能**
|
||||
- 支持企业微信和微信公众号两种配置类型
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="tsx">
|
||||
import { NButton, NTabs, NTabPane, NCard, NPopconfirm, NDataTable } from 'naive-ui';
|
||||
import type { Ref } from 'vue';
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { ref, computed, watch, onMounted, h } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { convertToBeijingTime } from '@/utils/date';
|
||||
import { useAuth } from '@/hooks/business/auth';
|
||||
@@ -32,6 +32,80 @@ const { hasAuth } = useAuth();
|
||||
const authStore = useAuthStore();
|
||||
const customerId = authStore.userInfo?.customerId;
|
||||
|
||||
// 企业微信列定义
|
||||
const enterpriseColumns = computed(() => [
|
||||
{ key: 'index', title: '序号', width: 64, align: 'center' },
|
||||
{ key: 'corpId', title: '企业ID', align: 'center', width: 150, render: (row: any) => row.corpId || '-' },
|
||||
{ key: 'agentId', title: '应用ID', align: 'center', width: 100, render: (row: any) => row.agentId || '-' },
|
||||
{ key: 'secret', title: '应用Secret', align: 'center', width: 120, render: (row: any) => row.secret ? '***' + row.secret.slice(-4) : '-' },
|
||||
{ key: 'templateId', title: '模板ID', align: 'center', width: 200, render: (row: any) => row.templateId || '-' },
|
||||
{ key: 'enabled', title: '启用状态', align: 'center', width: 100, render: (row: any) => row.enabled ? '启用' : '禁用' },
|
||||
{ key: 'createTime', title: '创建时间', align: 'center', width: 150, render: (row: any) => convertToBeijingTime(row.createTime) },
|
||||
{
|
||||
key: 'operate',
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'flex-center gap-8px' }, [
|
||||
hasAuth('t:wechat:alarm:config:update') && h(NButton, {
|
||||
type: 'primary',
|
||||
quaternary: true,
|
||||
size: 'small',
|
||||
onClick: () => edit(row)
|
||||
}, () => '编辑'),
|
||||
hasAuth('t:wechat:alarm:config:delete') && h(NPopconfirm, {
|
||||
onPositiveClick: () => handleDelete(row.id)
|
||||
}, {
|
||||
default: () => '确认删除?',
|
||||
trigger: () => h(NButton, {
|
||||
type: 'error',
|
||||
quaternary: true,
|
||||
size: 'small'
|
||||
}, () => '删除')
|
||||
})
|
||||
].filter(Boolean));
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
// 微信公众号列定义
|
||||
const officialColumns = computed(() => [
|
||||
{ key: 'index', title: '序号', width: 64, align: 'center' },
|
||||
{ key: 'appid', title: 'AppID', align: 'center', width: 150, render: (row: any) => row.appid || '-' },
|
||||
{ key: 'appsecret', title: 'AppSecret', align: 'center', width: 120, render: (row: any) => row.appsecret ? '***' + row.appsecret.slice(-4) : '-' },
|
||||
{ key: 'wechatId', title: '微信ID', align: 'center', width: 120, render: (row: any) => row.appid || '-' },
|
||||
{ key: 'templateId', title: '模板ID', align: 'center', width: 200, render: (row: any) => row.templateId || '-' },
|
||||
{ key: 'enabled', title: '启用状态', align: 'center', width: 100, render: (row: any) => row.enabled ? '启用' : '禁用' },
|
||||
{ key: 'createTime', title: '创建时间', align: 'center', width: 150, render: (row: any) => convertToBeijingTime(row.createTime) },
|
||||
{
|
||||
key: 'operate',
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
render: (row: any) => {
|
||||
return h('div', { class: 'flex-center gap-8px' }, [
|
||||
hasAuth('t:wechat:alarm:config:update') && h(NButton, {
|
||||
type: 'primary',
|
||||
quaternary: true,
|
||||
size: 'small',
|
||||
onClick: () => edit(row)
|
||||
}, () => '编辑'),
|
||||
hasAuth('t:wechat:alarm:config:delete') && h(NPopconfirm, {
|
||||
onPositiveClick: () => handleDelete(row.id)
|
||||
}, {
|
||||
default: () => '确认删除?',
|
||||
trigger: () => h(NButton, {
|
||||
type: 'error',
|
||||
quaternary: true,
|
||||
size: 'small'
|
||||
}, () => '删除')
|
||||
})
|
||||
].filter(Boolean));
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
// 使用单个useTable
|
||||
const {
|
||||
columns,
|
||||
@@ -51,7 +125,7 @@ const {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
customerId,
|
||||
type: activeTab.value,
|
||||
type: 'enterprise', // 明确设置初始type
|
||||
enabled: null
|
||||
},
|
||||
columns: () => {
|
||||
@@ -208,6 +282,7 @@ async function handleBatchDelete() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Tab切换时重新加载数据
|
||||
function handleTabChange(value: string) {
|
||||
activeTab.value = value;
|
||||
@@ -229,11 +304,15 @@ function handleTabChange(value: string) {
|
||||
|
||||
// 确保初始数据加载时使用正确的type
|
||||
onMounted(() => {
|
||||
// 如果当前searchParams.type与activeTab.value不一致,更新searchParams
|
||||
if (searchParams.type !== activeTab.value) {
|
||||
searchParams.type = activeTab.value;
|
||||
getData();
|
||||
}
|
||||
// 强制设置searchParams的type字段
|
||||
updateSearchParams({
|
||||
...searchParams,
|
||||
type: activeTab.value,
|
||||
customerId
|
||||
});
|
||||
|
||||
// 加载初始数据
|
||||
getData();
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -252,31 +331,29 @@ onMounted(() => {
|
||||
@search="getDataByPage"
|
||||
/>
|
||||
<NCard :bordered="false" class="sm:flex-1-hidden card-wrapper" content-class="flex-col">
|
||||
<TableHeaderOperation
|
||||
v-model:columns="columnChecks"
|
||||
:checked-row-keys="checkedRowKeys"
|
||||
:loading="loading"
|
||||
add-auth="t:wechat:alarm:config:add"
|
||||
delete-auth="t:wechat:alarm:config:delete"
|
||||
@add="handleAdd"
|
||||
@delete="handleBatchDelete"
|
||||
@refresh="getData"
|
||||
/>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||
<div>
|
||||
<NButton type="primary" @click="handleAdd" v-if="hasAuth('t:wechat:alarm:config:add')">
|
||||
新增
|
||||
</NButton>
|
||||
<NButton type="error" @click="handleBatchDelete" :disabled="checkedRowKeys.length === 0" v-if="hasAuth('t:wechat:alarm:config:delete')" style="margin-left: 8px;">
|
||||
批量删除
|
||||
</NButton>
|
||||
</div>
|
||||
<NButton @click="getData" :loading="loading">
|
||||
刷新
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
|
||||
<NDataTable
|
||||
v-model:checked-row-keys="checkedRowKeys"
|
||||
remote
|
||||
striped
|
||||
size="small"
|
||||
class="sm:h-full"
|
||||
:data="data"
|
||||
:scroll-x="962"
|
||||
:columns="columns"
|
||||
:flex-height="!appStore.isMobile"
|
||||
:loading="loading"
|
||||
:single-line="false"
|
||||
:columns="enterpriseColumns"
|
||||
:row-key="(row: any) => row.id"
|
||||
:pagination="mobilePagination"
|
||||
size="small"
|
||||
striped
|
||||
:loading="loading"
|
||||
/>
|
||||
</NCard>
|
||||
</div>
|
||||
@@ -292,31 +369,29 @@ onMounted(() => {
|
||||
@search="getDataByPage"
|
||||
/>
|
||||
<NCard :bordered="false" class="sm:flex-1-hidden card-wrapper" content-class="flex-col">
|
||||
<TableHeaderOperation
|
||||
v-model:columns="columnChecks"
|
||||
:checked-row-keys="checkedRowKeys"
|
||||
:loading="loading"
|
||||
add-auth="t:wechat:alarm:config:add"
|
||||
delete-auth="t:wechat:alarm:config:delete"
|
||||
@add="handleAdd"
|
||||
@delete="handleBatchDelete"
|
||||
@refresh="getData"
|
||||
/>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||
<div>
|
||||
<NButton type="primary" @click="handleAdd" v-if="hasAuth('t:wechat:alarm:config:add')">
|
||||
新增
|
||||
</NButton>
|
||||
<NButton type="error" @click="handleBatchDelete" :disabled="checkedRowKeys.length === 0" v-if="hasAuth('t:wechat:alarm:config:delete')" style="margin-left: 8px;">
|
||||
批量删除
|
||||
</NButton>
|
||||
</div>
|
||||
<NButton @click="getData" :loading="loading">
|
||||
刷新
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
|
||||
<NDataTable
|
||||
v-model:checked-row-keys="checkedRowKeys"
|
||||
remote
|
||||
striped
|
||||
size="small"
|
||||
class="sm:h-full"
|
||||
:data="data"
|
||||
:scroll-x="962"
|
||||
:columns="columns"
|
||||
:flex-height="!appStore.isMobile"
|
||||
:loading="loading"
|
||||
:single-line="false"
|
||||
:columns="officialColumns"
|
||||
:row-key="(row: any) => row.id"
|
||||
:pagination="mobilePagination"
|
||||
size="small"
|
||||
striped
|
||||
:loading="loading"
|
||||
/>
|
||||
</NCard>
|
||||
</div>
|
||||
@@ -324,6 +399,7 @@ onMounted(() => {
|
||||
</NTabs>
|
||||
</NCard>
|
||||
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<AlertConfigWechatOperateDrawer
|
||||
v-model:visible="drawerVisible"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, watch } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
|
||||
@@ -22,6 +22,13 @@ const emit = defineEmits<Emits>();
|
||||
|
||||
const model = defineModel<Api.Health.AlertConfigWechatSearchParams>('model', { required: true });
|
||||
|
||||
// 监听props.type变化,自动设置model中的type字段
|
||||
watch(() => props.type, (newType) => {
|
||||
if (newType) {
|
||||
model.value.type = newType;
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
const { dictOptions } = useDict();
|
||||
|
||||
// 计算属性处理条件字段绑定
|
||||
|
||||
Reference in New Issue
Block a user