集群问题处理

This commit is contained in:
geht
2026-06-09 18:26:31 +08:00
parent 5b8bd2797a
commit de48bd2324
19 changed files with 626 additions and 17 deletions

View File

@@ -12,6 +12,7 @@ enum Api {
deleteThirdAccount = '/sys/thirdApp/deleteThirdAccount',
deleteThirdAppConfig = '/sys/thirdApp/deleteThirdAppConfig',
testKingdeeConnect = '/sys/thirdApp/testKingdeeConnect',
getDingTalkStreamNodeInfo = '/xslmes/dingtalk/stream/nodeInfo',
}
/**
@@ -86,4 +87,11 @@ export const deleteThirdAppConfig = (params, handleSuccess) => {
*/
export const testKingdeeConnect = (params) => {
return defHttp.get({ url: Api.testKingdeeConnect, params }, { isTransformResponse: false });
};
/**
* 获取本机钉钉 Stream 节点信息主机名、IP、是否接收
*/
export const getDingTalkStreamNodeInfo = () => {
return defHttp.get({ url: Api.getDingTalkStreamNodeInfo });
};

View File

@@ -77,7 +77,57 @@ export const thirdAppFormSchema: FormSchema[] = [
},
helpMessage: '开启后,此应用的 AppKey/AppSecret 将用于接收钉钉 Stream 事件推送(审批结果等)。同一企业只需开启一个',
defaultValue: 0,
},{
},
{
label: '限制接收节点',
field: 'streamReceiverEnabled',
component: 'Switch',
ifShow: ({ values }) => values.thirdType === 'dingtalk' && values.streamEnabled === 1,
componentProps: {
checkedChildren: '已限制',
checkedValue: 1,
unCheckedChildren: '不限制',
unCheckedValue: 0,
},
helpMessage: '开启后,仅下方白名单内的服务器会建立 Stream 连接并处理审批回调(推荐用 IP',
defaultValue: 0,
},
{
label: '允许接收的IP',
field: 'streamDesignatedIps',
component: 'InputTextArea',
ifShow: ({ values }) =>
values.thirdType === 'dingtalk' && values.streamEnabled === 1 && values.streamReceiverEnabled === 1,
componentProps: {
rows: 2,
placeholder: '多个 IP 用逗号分隔,例如 192.168.1.74(可参考页面展示的本机 IP',
},
},
{
label: '允许接收的主机名',
field: 'streamDesignatedHosts',
component: 'Input',
ifShow: ({ values }) =>
values.thirdType === 'dingtalk' && values.streamEnabled === 1 && values.streamReceiverEnabled === 1,
componentProps: {
placeholder: '可选,多个用逗号分隔(不如 IP 稳定)',
},
},
{
label: '集群Redis选主',
field: 'streamClusterMode',
component: 'Switch',
ifShow: ({ values }) => values.thirdType === 'dingtalk' && values.streamEnabled === 1,
componentProps: {
checkedChildren: '开启',
checkedValue: 1,
unCheckedChildren: '关闭',
unCheckedValue: 0,
},
helpMessage: '多实例共用同一 AppKey 时务必开启,避免多台服务器同时建连抢消息',
defaultValue: 1,
},
{
label: '租户id',
field: 'tenantId',
component: 'Input',

View File

@@ -1,5 +1,13 @@
<template>
<BasicModal @register="registerModal" :width="800" :title="title" @ok="handleSubmit">
<BasicModal @register="registerModal" :width="860" :title="title" @ok="handleSubmit">
<a-alert
v-if="showStreamNodeHint"
type="info"
show-icon
style="margin-bottom: 12px"
:message="streamNodeHintTitle"
:description="streamNodeHintDesc"
/>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
@@ -9,12 +17,15 @@
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useForm, BasicForm } from '/@/components/Form';
import { thirdAppFormSchema } from './ThirdApp.data';
import { getThirdConfigByTenantId, saveOrUpdateThirdConfig } from './ThirdApp.api';
import { getThirdConfigByTenantId, saveOrUpdateThirdConfig, getDingTalkStreamNodeInfo } from './ThirdApp.api';
export default defineComponent({
name: 'ThirdAppConfigModal',
components: { BasicModal, BasicForm },
setup(props, { emit }) {
const title = ref<string>('钉钉配置');
const showStreamNodeHint = ref(false);
const streamNodeHintTitle = ref('本机 Stream 节点信息');
const streamNodeHintDesc = ref('');
//表单配置
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
schemas: thirdAppFormSchema,
@@ -25,8 +36,23 @@
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: true });
showStreamNodeHint.value = false;
streamNodeHintDesc.value = '';
if (data.thirdType == 'dingtalk') {
title.value = '钉钉配置';
try {
const nodeInfo = await getDingTalkStreamNodeInfo();
if (nodeInfo) {
showStreamNodeHint.value = true;
const ips = Array.isArray(nodeInfo.localIps) ? nodeInfo.localIps.join(', ') : '';
const receiverText = nodeInfo.thisNodeReceiver ? '是(本机将接收回调)' : '否(本机不接收回调)';
streamNodeHintDesc.value =
`主机名:${nodeInfo.hostName || '-'}\n本机IP${ips || '-'}\n当前是否接收${receiverText}\n` +
`提示:开启「限制接收节点」后,请将本机局域网 IP 填入「允许接收的IP」`;
}
} catch (e) {
// 接口不可用时忽略
}
} else if (data.thirdType == 'kingdee') {
title.value = '金蝶配置';
} else {
@@ -60,6 +86,9 @@
return {
title,
showStreamNodeHint,
streamNodeHintTitle,
streamNodeHintDesc,
registerForm,
registerModal,
handleSubmit,

View File

@@ -53,6 +53,49 @@
</a-tag>
</div>
</div>
<template v-if="appConfigData.streamEnabled === 1">
<div class="flex-flow">
<div class="base-title">接收限制</div>
<div class="base-message" style="display:flex;align-items:center;min-height:50px;">
<a-tag :color="appConfigData.streamReceiverEnabled === 1 ? 'orange' : 'default'">
{{ appConfigData.streamReceiverEnabled === 1 ? '仅白名单节点' : '不限制节点' }}
</a-tag>
</div>
</div>
<div class="flex-flow" v-if="appConfigData.streamReceiverEnabled === 1">
<div class="base-title">允许IP</div>
<div class="base-message" style="min-height:50px;line-height:1.6;padding-top:12px;">
{{ appConfigData.streamDesignatedIps || '(未配置,所有节点均可接收)' }}
</div>
</div>
<div class="flex-flow">
<div class="base-title">集群选主</div>
<div class="base-message" style="display:flex;align-items:center;height:50px;">
<a-tag :color="appConfigData.streamClusterMode === 1 ? 'blue' : 'default'">
{{
appConfigData.streamClusterMode === 1
? 'Redis选主已开启'
: appConfigData.streamClusterMode === 0
? '单节点直连'
: '沿用YAML默认'
}}
</a-tag>
</div>
</div>
<div class="flex-flow" v-if="streamNodeInfo.hostName">
<div class="base-title">本机信息</div>
<div class="base-message stream-node-info">
<div>主机名{{ streamNodeInfo.hostName }}</div>
<div>本机IP{{ (streamNodeInfo.localIps || []).join(', ') }}</div>
<div>
本机是否接收
<a-tag :color="streamNodeInfo.thisNodeReceiver ? 'green' : 'default'" style="margin-left:4px">
{{ streamNodeInfo.thisNodeReceiver ? '是' : '否' }}
</a-tag>
</div>
</div>
</div>
</template>
<div style="margin-top: 20px; width: 100%; text-align: right">
<a-button @click="dingEditClick">编辑</a-button>
<a-button v-if="appConfigData.id" @click="cancelBindClick" danger style="margin-left: 10px">取消绑定</a-button>
@@ -85,7 +128,12 @@
<script lang="ts">
import { defineComponent, h, inject, onMounted, reactive, ref, watch } from 'vue';
import { getThirdConfigByTenantId, syncDingTalkDepartUserToLocal, deleteThirdAppConfig } from './ThirdApp.api';
import {
getThirdConfigByTenantId,
syncDingTalkDepartUserToLocal,
deleteThirdAppConfig,
getDingTalkStreamNodeInfo,
} from './ThirdApp.api';
import { useModal } from '/@/components/Modal';
import ThirdAppConfigModal from './ThirdAppConfigModal.vue';
import { Modal } from 'ant-design-vue';
@@ -109,6 +157,7 @@
clientId: '',
clientSecret: '',
});
const streamNodeInfo = ref<any>({});
//企业微信钉钉配置modal
const [registerAppConfigModal, { openModal }] = useModal();
@@ -132,7 +181,12 @@
if (values) {
appConfigData.value = values;
} else {
appConfigData.value = "";
appConfigData.value = '';
}
try {
streamNodeInfo.value = (await getDingTalkStreamNodeInfo()) || {};
} catch (e) {
streamNodeInfo.value = {};
}
}
@@ -252,6 +306,7 @@
return {
appConfigData,
streamNodeInfo,
collapseActiveKey,
registerAppConfigModal,
dingEditClick,
@@ -331,4 +386,10 @@
top: 2px
}
:deep(.ant-collapse-borderless >.ant-collapse-item:last-child) {border-bottom-width:1px;}
.stream-node-info {
line-height: 1.8;
padding-top: 10px;
font-size: 13px;
color: @text-color-secondary;
}
</style>