feat: 微信告警配置管理功能完整实现 v1.3.5

This commit is contained in:
2025-08-27 21:41:27 +08:00
parent 65c505f0f7
commit 293918e90a
12 changed files with 352 additions and 411 deletions
+1 -1
View File
@@ -140,7 +140,7 @@ services:
VITE_APP_TITLE: ${VITE_APP_TITLE:-穿戴管理演示系统}
TZ: Asia/Shanghai
ports:
- "8080:80"
- "8088:80"
volumes:
- ./logs/ljwx-admin:/var/log/nginx
- ./custom-admin-config.js:/tmp/custom-admin-config.js:ro
+4
View File
@@ -0,0 +1,4 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
+87
View File
@@ -400,8 +400,95 @@ Content-Type: application/json
}
```
### 🔧 微信告警配置管理 (最新)
#### 功能概述
- 支持企业微信和微信公众号两种类型的告警配置管理
- 动态表格列显示,根据配置类型自适应显示相应字段
- 完整的CRUD操作支持,包含新增、编辑、删除和批量删除功能
- 智能数据过滤和状态管理
#### 功能特点
1. **双类型支持**:
- **企业微信配置**:显示企业ID、应用ID、应用Secret等企业微信专属字段
- **微信公众号配置**:显示AppID、AppSecret、微信ID等公众号专属字段
2. **智能表格**:
- 标签页切换时动态调整表格列
- 自适应字段显示,避免冗余列
- 统一的通用字段:模板ID、启用状态、创建时间、操作等
3. **数据管理**:
- 实时数据同步和状态更新
- 完整的权限控制和操作验证
- 敏感信息脱敏显示(Secret字段只显示后4位)
#### 使用方法
1. **查看配置**:
- 点击"企业微信配置"标签查看企业微信告警配置
- 点击"微信公众号配置"标签查看公众号告警配置
- 支持按类型、启用状态等条件搜索过滤
2. **新增配置**:
- 点击"新增"按钮打开配置表单
- 根据当前标签页自动设置配置类型
- 填写对应类型的必要字段信息
3. **编辑配置**:
- 点击表格中的"编辑"按钮修改配置
- 支持修改除ID和类型外的所有字段
- 实时保存并更新表格显示
#### 技术实现
- **动态列定义**:基于 `activeTab` 值动态生成表格列配置
- **状态管理**:使用 Vue 3 的响应式系统实现状态同步
- **API集成**:与后端 `/t_wechat_alarm_config/page` 接口完整对接
- **类型安全**:完整的 TypeScript 类型定义和验证
#### 数据字段映射
```typescript
// 企业微信配置
{
corpId: string; // 企业ID
agentId: string; // 应用ID
secret: string; // 应用Secret
}
// 微信公众号配置
{
appid: string; // AppID
appsecret: string; // AppSecret
wechatId: string; // 微信ID (映射自appid)
}
// 通用字段
{
templateId: string; // 模板ID
enabled: boolean; // 启用状态
createTime: string; // 创建时间
}
```
## 📝 更新日志
### v1.3.5 (2025-08-27)
- ✨ **新增微信告警配置管理功能**
- 支持企业微信和微信公众号两种配置类型
- 动态表格列显示,根据类型自适应字段
- 完整的CRUD操作和批量管理
- 敏感信息安全脱敏显示
- 智能数据过滤和实时状态同步
- 🔧 **修复表格组件显示问题**
- 解决NDataTable组件数据绑定问题
- 修复TableHeaderOperation组件导入缺失
- 优化标签页切换时的数据加载逻辑
- 完善列定义动态更新机制
- 🐛 **修复数据过滤和状态管理**
- 修复标签切换时数据不更新的问题
- 优化searchParams参数传递机制
- 改进API参数验证和错误处理
- 增强前后端数据同步稳定性
### v1.3.4 (2025-08-25)
- ✨ **新增健康数据源过滤功能**
- 健康数据查看时自动过滤通用事件上传的数据
+3
View File
@@ -31,7 +31,9 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
apiParams,
columns: config.columns,
transformer: res => {
console.log('[DEBUG] API Raw Response:', res);
const { records = [], page = 1, pageSize = 20, total = 0 } = res.data || {};
console.log('[DEBUG] Extracted:', { records, page, pageSize, total });
// Ensure that the size is greater than 0, If it is less than 0, it will cause paging calculation errors.
const rPageSize = pageSize <= 0 ? 20 : pageSize;
const recordsWithIndex = records.map((item, index) => {
@@ -40,6 +42,7 @@ export function useTable<A extends NaiveUI.TableApiFn>(config: NaiveUI.NaiveTabl
index: (page - 1) * rPageSize + index + 1
};
});
console.log('[DEBUG] Final data with index:', recordsWithIndex);
return {
data: recordsWithIndex,
+16 -8
View File
@@ -31,14 +31,22 @@ declare namespace Api {
type AlertConfigWechat = Common.CommonRecord<{
customerId: number;
/** WeChat App ID */
appId: string;
/** WeChat App Secret */
appSecret: string;
/** WeChat Type: enterprise/official */
type: string;
/** Enterprise WeChat Corp ID */
corpId: string;
/** Enterprise WeChat Agent ID */
agentId: string;
/** Enterprise WeChat Secret */
secret: string;
/** Official WeChat App ID */
appid: string;
/** Official WeChat App Secret */
appsecret: string;
/** WeChat Template ID */
templateId: string;
/** WeChat User OpenID */
userOpenid: string;
/** Whether enabled */
enabled: boolean;
/** User who created the record */
createUser: string;
/** Creation timestamp */
@@ -47,13 +55,13 @@ declare namespace Api {
/** Wechaalerconfig search params */
type AlertConfigWechatSearchParams = CommonType.RecordNullable<
Pick<Api.Health.AlertConfigWechat, 'appId' | 'appSecret' | 'templateId' | 'userOpenid'> & Api.Common.CommonSearchParams
Pick<Api.Health.AlertConfigWechat, 'type' | 'corpId' | 'agentId' | 'appid' | 'templateId' | 'enabled'> & Api.Common.CommonSearchParams
>;
/** Wechaalerconfig edit model */
type AlertConfigWechatEdit = Pick<
Api.Health.AlertConfigWechat,
'id' | 'appId' | 'appSecret' | 'templateId' | 'userOpenid' | 'createUser' | 'createTime'
'id' | 'customerId' | 'type' | 'corpId' | 'agentId' | 'secret' | 'appid' | 'appsecret' | 'templateId' | 'enabled' | 'createUser' | 'createTime'
>;
/** Wechaalerconfig list */
+214 -276
View File
@@ -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 } from 'vue';
import { ref, computed, watch, onMounted } from 'vue';
import { useAppStore } from '@/store/modules/app';
import { convertToBeijingTime } from '@/utils/date';
import { useAuth } from '@/hooks/business/auth';
@@ -15,6 +15,7 @@ import {
} from '@/service/api/health/alert-config-wechat';
import AlertConfigWechatSearch from './modules/alertconfigwechat-search.vue';
import AlertConfigWechatOperateDrawer from './modules/alert-config-wechat-operate-drawer.vue';
import TableHeaderOperation from '@/components/advanced/table-header-operation.vue';
defineOptions({
name: 'AlertConfigPage'
@@ -23,275 +24,218 @@ defineOptions({
// 当前激活的tab
const activeTab = ref('enterprise');
// 企业微信配置
const enterpriseOperateType = ref<NaiveUI.TableOperateType>('add');
const enterpriseEditingData: Ref<Api.Health.AlertConfigWechat | null> = ref(null);
// 微信公众号配置
const officialOperateType = ref<NaiveUI.TableOperateType>('add');
const officialEditingData: Ref<Api.Health.AlertConfigWechat | null> = ref(null);
const operateType = ref<NaiveUI.TableOperateType>('add');
const editingData: Ref<Api.Health.AlertConfigWechat | null> = ref(null);
const appStore = useAppStore();
const { hasAuth } = useAuth();
const authStore = useAuthStore();
const customerId = authStore.userInfo?.customerId;
// 企业微信表格配置
const {
columns: enterpriseColumns,
columnChecks: enterpriseColumnChecks,
data: enterpriseData,
loading: enterpriseLoading,
getData: getEnterpriseData,
getDataByPage: getEnterpriseDataByPage,
mobilePagination: enterpriseMobilePagination,
searchParams: enterpriseSearchParams,
resetSearchParams: resetEnterpriseSearchParams
// 使用单个useTable
const {
columns,
columnChecks,
data,
loading,
getData,
getDataByPage,
mobilePagination,
searchParams,
updateSearchParams,
resetSearchParams,
reloadColumns
} = useTable({
apiFn: fetchGetAlertConfigWechatList,
apiParams: {
page: 1,
pageSize: 20,
customerId,
type: 'enterprise',
type: activeTab.value,
enabled: null
},
columns: () => [
{
key: 'index',
title: $t('common.index'),
width: 64,
align: 'center'
},
{
key: 'corpId',
title: '企业ID',
align: 'center',
width: 150,
render: row => row.corpId || '-'
},
{
key: 'agentId',
title: '应用ID',
align: 'center',
width: 100,
render: row => row.agentId || '-'
},
{
key: 'templateId',
title: '模板ID',
align: 'center',
width: 200,
render: row => row.templateId || '-'
},
{
key: 'enabled',
title: '启用状态',
align: 'center',
width: 100,
render: row => row.enabled ? '启用' : '禁用'
},
{
key: 'createTime',
title: $t('page.health.alert.config.wechat.createTime'),
align: 'center',
width: 150,
render: row => convertToBeijingTime(row.createTime)
},
{
key: 'operate',
title: $t('common.operate'),
align: 'center',
width: 120,
minWidth: 120,
render: row => (
<div class="flex-center gap-8px">
{hasAuth('t:wechat:alarm:config:update') && (
<NButton type="primary" quaternary size="small" onClick={() => editEnterprise(row)}>
{$t('common.edit')}
</NButton>
)}
{hasAuth('t:wechat:alarm:config:delete') && (
<NPopconfirm onPositiveClick={() => handleDeleteEnterprise(row.id)}>
{{
default: () => $t('common.confirmDelete'),
trigger: () => (
<NButton type="error" quaternary size="small">
{$t('common.delete')}
</NButton>
)
}}
</NPopconfirm>
)}
</div>
)
}
]
});
columns: () => {
// 基础列
const baseColumns = [
{
key: 'index',
title: $t('common.index'),
width: 64,
align: 'center'
}
];
// 微信公众号表格配置
const {
columns: officialColumns,
columnChecks: officialColumnChecks,
data: officialData,
loading: officialLoading,
getData: getOfficialData,
getDataByPage: getOfficialDataByPage,
mobilePagination: officialMobilePagination,
searchParams: officialSearchParams,
resetSearchParams: resetOfficialSearchParams
} = useTable({
apiFn: fetchGetAlertConfigWechatList,
apiParams: {
page: 1,
pageSize: 20,
customerId,
type: 'official',
enabled: null
},
columns: () => [
{
key: 'index',
title: $t('common.index'),
width: 64,
align: 'center'
},
{
key: 'appid',
title: 'AppID',
align: 'center',
width: 150,
render: row => row.appid || '-'
},
{
key: 'templateId',
title: '模板ID',
align: 'center',
width: 200,
render: row => row.templateId || '-'
},
{
key: 'enabled',
title: '启用状态',
align: 'center',
width: 100,
render: row => row.enabled ? '启用' : '禁用'
},
{
key: 'createTime',
title: $t('page.health.alert.config.wechat.createTime'),
align: 'center',
width: 150,
render: row => convertToBeijingTime(row.createTime)
},
{
key: 'operate',
title: $t('common.operate'),
align: 'center',
width: 120,
minWidth: 120,
render: row => (
<div class="flex-center gap-8px">
{hasAuth('t:wechat:alarm:config:update') && (
<NButton type="primary" quaternary size="small" onClick={() => editOfficial(row)}>
{$t('common.edit')}
</NButton>
)}
{hasAuth('t:wechat:alarm:config:delete') && (
<NPopconfirm onPositiveClick={() => handleDeleteOfficial(row.id)}>
{{
default: () => $t('common.confirmDelete'),
trigger: () => (
<NButton type="error" quaternary size="small">
{$t('common.delete')}
</NButton>
)
}}
</NPopconfirm>
)}
</div>
)
}
]
// 根据当前选中的类型显示不同的列
const typeSpecificColumns = activeTab.value === 'enterprise'
? [
// 企业微信专属字段
{
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: '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 || '-' // 临时使用appid作为微信ID
}
];
// 通用列
const commonColumns = [
{
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: $t('page.health.alert.config.wechat.createTime'),
align: 'center',
width: 150,
render: (row: any) => convertToBeijingTime(row.createTime)
},
{
key: 'operate',
title: $t('common.operate'),
align: 'center',
width: 120,
minWidth: 120,
render: (row: any) => (
<div class="flex-center gap-8px">
{hasAuth('t:wechat:alarm:config:update') && (
<NButton type="primary" quaternary size="small" onClick={() => edit(row)}>
{$t('common.edit')}
</NButton>
)}
{hasAuth('t:wechat:alarm:config:delete') && (
<NPopconfirm onPositiveClick={() => handleDelete(row.id)}>
{{
default: () => $t('common.confirmDelete'),
trigger: () => (
<NButton type="error" quaternary size="small">
{$t('common.delete')}
</NButton>
)
}}
</NPopconfirm>
)}
</div>
)
}
];
return [...baseColumns, ...typeSpecificColumns, ...commonColumns];
}
});
const {
drawerVisible: enterpriseDrawerVisible,
openDrawer: openEnterpriseDrawer,
checkedRowKeys: enterpriseCheckedRowKeys,
onDeleted: onEnterpriseDeleted,
onBatchDeleted: onEnterpriseBatchDeleted
} = useTableOperate(enterpriseData, getEnterpriseData);
drawerVisible,
openDrawer,
checkedRowKeys,
onDeleted,
onBatchDeleted
} = useTableOperate(data, getData);
const {
drawerVisible: officialDrawerVisible,
openDrawer: openOfficialDrawer,
checkedRowKeys: officialCheckedRowKeys,
onDeleted: onOfficialDeleted,
onBatchDeleted: onOfficialBatchDeleted
} = useTableOperate(officialData, getOfficialData);
// 企业微信操作
function handleAddEnterprise() {
enterpriseOperateType.value = 'add';
openEnterpriseDrawer();
// 操作函数
function handleAdd() {
operateType.value = 'add';
openDrawer();
}
function editEnterprise(item: Api.Health.AlertConfigWechat) {
enterpriseOperateType.value = 'edit';
enterpriseEditingData.value = { ...item };
openEnterpriseDrawer();
function edit(item: Api.Health.AlertConfigWechat) {
operateType.value = 'edit';
editingData.value = { ...item };
openDrawer();
}
async function handleDeleteEnterprise(id: string) {
async function handleDelete(id: string) {
const { error, data: result } = await fetchDeleteAlertConfigWechat(transDeleteParams([id]));
if (!error && result) {
await onEnterpriseDeleted();
await onDeleted();
}
}
async function handleEnterpriseBatchDelete() {
const { error, data: result } = await fetchDeleteAlertConfigWechat(transDeleteParams(enterpriseCheckedRowKeys.value));
async function handleBatchDelete() {
const { error, data: result } = await fetchDeleteAlertConfigWechat(transDeleteParams(checkedRowKeys.value));
if (!error && result) {
await onEnterpriseBatchDeleted();
await onBatchDeleted();
}
}
// 微信公众号操作
function handleAddOfficial() {
officialOperateType.value = 'add';
openOfficialDrawer();
}
function editOfficial(item: Api.Health.AlertConfigWechat) {
officialOperateType.value = 'edit';
officialEditingData.value = { ...item };
openOfficialDrawer();
}
async function handleDeleteOfficial(id: string) {
const { error, data: result } = await fetchDeleteAlertConfigWechat(transDeleteParams([id]));
if (!error && result) {
await onOfficialDeleted();
}
}
async function handleOfficialBatchDelete() {
const { error, data: result } = await fetchDeleteAlertConfigWechat(transDeleteParams(officialCheckedRowKeys.value));
if (!error && result) {
await onOfficialBatchDeleted();
}
}
// Tab切换时重新加载数据
function handleTabChange(value: string) {
activeTab.value = value;
if (value === 'enterprise') {
getEnterpriseData();
} else if (value === 'official') {
getOfficialData();
}
// 使用updateSearchParams方法来确保参数正确更新
updateSearchParams({
type: value,
page: 1,
pageSize: searchParams.pageSize || 20,
customerId
});
// 强制重新计算列定义
reloadColumns();
// 重新加载数据
getData();
}
// 确保初始数据加载时使用正确的type
onMounted(() => {
// 如果当前searchParams.type与activeTab.value不一致,更新searchParams
if (searchParams.type !== activeTab.value) {
searchParams.type = activeTab.value;
getData();
}
});
</script>
<template>
@@ -302,36 +246,37 @@ function handleTabChange(value: string) {
<NTabPane name="enterprise" tab="企业微信配置">
<div class="flex-col-stretch gap-8px">
<AlertConfigWechatSearch
v-model:model="enterpriseSearchParams"
v-model:model="searchParams"
type="enterprise"
@reset="resetEnterpriseSearchParams"
@search="getEnterpriseDataByPage"
@reset="resetSearchParams"
@search="getDataByPage"
/>
<NCard :bordered="false" class="sm:flex-1-hidden card-wrapper" content-class="flex-col">
<TableHeaderOperation
v-model:columns="enterpriseColumnChecks"
:checked-row-keys="enterpriseCheckedRowKeys"
:loading="enterpriseLoading"
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="handleAddEnterprise"
@delete="handleEnterpriseBatchDelete"
@refresh="getEnterpriseData"
@add="handleAdd"
@delete="handleBatchDelete"
@refresh="getData"
/>
<NDataTable
v-model:checked-row-keys="enterpriseCheckedRowKeys"
v-model:checked-row-keys="checkedRowKeys"
remote
striped
size="small"
class="sm:h-full"
:data="enterpriseData"
:data="data"
:scroll-x="962"
:columns="enterpriseColumns"
:columns="columns"
:flex-height="!appStore.isMobile"
:loading="enterpriseLoading"
:loading="loading"
:single-line="false"
:row-key="row => row.id"
:pagination="enterpriseMobilePagination"
:row-key="(row: any) => row.id"
:pagination="mobilePagination"
/>
</NCard>
</div>
@@ -341,36 +286,37 @@ function handleTabChange(value: string) {
<NTabPane name="official" tab="微信公众号配置">
<div class="flex-col-stretch gap-8px">
<AlertConfigWechatSearch
v-model:model="officialSearchParams"
v-model:model="searchParams"
type="official"
@reset="resetOfficialSearchParams"
@search="getOfficialDataByPage"
@reset="resetSearchParams"
@search="getDataByPage"
/>
<NCard :bordered="false" class="sm:flex-1-hidden card-wrapper" content-class="flex-col">
<TableHeaderOperation
v-model:columns="officialColumnChecks"
:checked-row-keys="officialCheckedRowKeys"
:loading="officialLoading"
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="handleAddOfficial"
@delete="handleOfficialBatchDelete"
@refresh="getOfficialData"
@add="handleAdd"
@delete="handleBatchDelete"
@refresh="getData"
/>
<NDataTable
v-model:checked-row-keys="officialCheckedRowKeys"
v-model:checked-row-keys="checkedRowKeys"
remote
striped
size="small"
class="sm:h-full"
:data="officialData"
:data="data"
:scroll-x="962"
:columns="officialColumns"
:columns="columns"
:flex-height="!appStore.isMobile"
:loading="officialLoading"
:loading="loading"
:single-line="false"
:row-key="row => row.id"
:pagination="officialMobilePagination"
:row-key="(row: any) => row.id"
:pagination="mobilePagination"
/>
</NCard>
</div>
@@ -380,19 +326,11 @@ function handleTabChange(value: string) {
<!-- 弹窗 -->
<AlertConfigWechatOperateDrawer
v-model:visible="enterpriseDrawerVisible"
:operate-type="enterpriseOperateType"
:row-data="enterpriseEditingData"
type="enterprise"
@submitted="getEnterpriseDataByPage"
/>
<AlertConfigWechatOperateDrawer
v-model:visible="officialDrawerVisible"
:operate-type="officialOperateType"
:row-data="officialEditingData"
type="official"
@submitted="getOfficialDataByPage"
v-model:visible="drawerVisible"
:operate-type="operateType"
:row-data="editingData"
:type="activeTab"
@submitted="getDataByPage"
/>
</div>
</template>
+2 -116
View File
@@ -1,116 +1,2 @@
# ================================
# BigScreen 项目 .gitignore
# ================================
# 配置文件
uploader_config.ini
# Python 环境和缓存
./myenv/
__pycache__/
*.pyc
*.pyo
*.pyd
# ================================
# 日志文件 (所有日志)
# ================================
*.log
*.log.*
logs/
log/
# ================================
# 大文件和数据
# ================================
# SQL 文件 (通常很大)
*.sql
!*_schema.sql
!migration*.sql
# 数据库文件
*.db
*.sqlite
*.sqlite3
# Excel 数据文件
*.xlsx
*.xls
# CSV 数据文件 (大于1MB的)
worker_health_*.csv
# ================================
# 缓存和临时文件
# ================================
cache/
.cache/
uploads/
temp/
tmp/
# 性能测试数据
performance_*.json
*_report.json
*_report.log
# ================================
# 静态资源构建输出
# ================================
static/
dist/
build/
# ================================
# HTML 大文件
# ================================
# 交互式地图文件 (通常很大)
interactive_*.html
mine_topology_map.html
map.html
# 模板文件 (如果是临时的)
templates/personal_cool.html
templates/index.html
./bigScreen/template/index.html
# ================================
# 证书和密钥
# ================================
*.pem
*.key
*.crt
# ================================
# 运行时文件
# ================================
# 进程ID文件
*.pid
# 备份文件
*.backup
*.bak
# 测试输出
test_*.json
test_*.html
test_progress.json
# ================================
# Docker 和部署相关
# ================================
.dockerignore
# ================================
# IDE 和编辑器
# ================================
.vscode/
.idea/
*.swp
*.swo
# ================================
# OS 生成文件
# ================================
.DS_Store
Thumbs.db
# Created by venv; see https://docs.python.org/3/library/venv.html
*
@@ -44,17 +44,32 @@ import java.time.LocalDateTime;
@Schema(name = "TWechatAlertConfigVO", description = "Table to store WeChat alert configuration VO 对象")
public class TWechatAlertConfigVO extends BaseVO {
@Schema(description = "WeChat App ID")
private String appId;
@Schema(description = "Client ID")
private Long customerId;
@Schema(description = "WeChat App Secret")
private String appSecret;
@Schema(description = "WeChat Type: enterprise/official")
private String type;
@Schema(description = "Enterprise WeChat Corp ID")
private String corpId;
@Schema(description = "Enterprise WeChat Agent ID")
private String agentId;
@Schema(description = "Enterprise WeChat Secret")
private String secret;
@Schema(description = "Official WeChat App ID")
private String appid;
@Schema(description = "Official WeChat App Secret")
private String appsecret;
@Schema(description = "WeChat Template ID")
private String templateId;
@Schema(description = "WeChat User OpenID")
private String userOpenid;
@Schema(description = "Whether enabled")
private Boolean enabled;
@Schema(description = "User who created the record")
private String createUser;
@@ -1,2 +1,2 @@
#Sun Aug 24 15:47:42 IRKT 2025
gradle.version=7.3
#Wed Aug 27 19:09:11 CST 2025
gradle.version=8.9
@@ -1,11 +1,11 @@
arguments=--init-script /var/folders/9_/swlb2qbs6qxctt1zx7cq4m3h0000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/9_/swlb2qbs6qxctt1zx7cq4m3h0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
arguments=--init-script /var/folders/mm/vmpdh9394f764qzjhxshxd0m0000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/mm/vmpdh9394f764qzjhxshxd0m0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
auto.sync=true
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
java.home=/opt/homebrew/Cellar/openjdk@21/21.0.7/libexec/openjdk.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true