Files
qhmes/jeecgboot-vue3/src/views/xslmesMcs/mcsSyncConfig/components/CollectModal.vue

202 lines
9.0 KiB
Vue
Raw Normal View History

<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="采集操作" :width="560" @ok="handleOk">
<a-spin :spinning="loading">
<a-form :labelCol="{ span: 7 }" :wrapperCol="{ span: 16 }">
<a-form-item label="采集配置">
<span>{{ configName || '-' }}</span>
<span v-if="sourceTable" style="color: #999"> 源表{{ sourceTable }}</span>
</a-form-item>
<a-form-item label="是否采集">
<a-switch v-model:checked="enabled" checkedChildren="采集中" unCheckedChildren="已停止" />
</a-form-item>
<a-form-item label="采集间隔">
<a-input-number v-model:value="intervalSeconds" :min="1" :precision="0" addonAfter="秒" style="width: 100%" />
</a-form-item>
<a-form-item label="采集模式">
<a-radio-group v-model:value="syncMode" button-style="solid">
<a-radio-button value="FULL">全量匹配</a-radio-button>
<a-radio-button value="TIME">时间匹配</a-radio-button>
<a-radio-button value="INCR">增量匹配</a-radio-button>
</a-radio-group>
<div style="color: #999; font-size: 12px; margin-top: 4px">{{ modeHint }}</div>
</a-form-item>
<template v-if="syncMode === 'TIME'">
<a-form-item label="时间列" required>
<a-select v-model:value="incrColumn" :options="sourceColumnOptions" showSearch allowClear placeholder="选择源表的时间列(如 WriteTime)" />
</a-form-item>
<a-form-item label="时间范围">
<a-radio-group v-model:value="timeWindow">
<a-radio value="TODAY">当天</a-radio>
<a-radio value="LAST7">最近七天</a-radio>
</a-radio-group>
</a-form-item>
</template>
<template v-else-if="syncMode === 'INCR'">
<a-form-item label="标记列" required>
<a-select v-model:value="incrColumn" :options="sourceColumnOptions" showSearch allowClear placeholder="选择源表用于标记是否已采集的列" />
<div style="color: #999; font-size: 12px">需在字段映射中勾选匹配键( GUID)作为回写主键并开启中间库写入开关</div>
</a-form-item>
<a-form-item label="采集条件" required>
<a-radio-group v-model:value="flagCondition" button-style="solid">
<a-radio-button value="IS_NULL">为空</a-radio-button>
<a-radio-button value="EQ_EMPTY">等于</a-radio-button>
<a-radio-button value="NE_EMPTY">不等于</a-radio-button>
</a-radio-group>
<!-- update-begin---author:GHT ---date:20260617 forMES上辅机等于/不等于支持自定义匹配值----------- -->
<a-input
v-if="flagCondition === 'EQ_EMPTY' || flagCondition === 'NE_EMPTY'"
v-model:value="flagMatchValue"
:placeholder="`填写要${flagCondition === 'EQ_EMPTY' ? '等于' : '不等于'}的值(留空表示空字符串“”)`"
allowClear
style="width: 100%; margin-top: 6px"
/>
<!-- update-end---author:GHT ---date:20260617 forMES上辅机等于/不等于支持自定义匹配值----------- -->
<div style="color: #999; font-size: 12px">仅采集标记列满足此条件的行</div>
</a-form-item>
<a-form-item label="回写值">
<a-input v-model:value="flagWriteValue" placeholder="采集完成后写回标记列的值,默认 1" allowClear style="width: 100%" />
<div style="color: #999; font-size: 12px">采集完成后把标记列回写成该值使这些行不再满足上面的采集条件默认1</div>
</a-form-item>
<a-form-item label="每轮最大行数">
<a-input-number v-model:value="batchLimit" :min="100" :step="500" :precision="0" addonAfter="行" style="width: 100%" />
<div style="color: #999; font-size: 12px">每个采集周期最多取这么多行分批吃完历史未采集数据</div>
</a-form-item>
</template>
<a-form-item v-if="lastSyncResult" label="最近采集">
<span style="color: #999">{{ lastSyncResult }}</span>
</a-form-item>
</a-form>
</a-spin>
</BasicModal>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { queryById, getByBizType, saveCollect, getSourceColumns } from '../mcsSyncConfig.api';
const emit = defineEmits(['register', 'success']);
const { createMessage } = useMessage();
const loading = ref(false);
const configId = ref('');
const configName = ref('');
const sourceTable = ref('');
const enabled = ref(false);
const intervalSeconds = ref(1);
const syncMode = ref('FULL');
const incrColumn = ref<string | undefined>(undefined);
const timeWindow = ref('TODAY');
const batchLimit = ref(2000);
const flagCondition = ref('IS_NULL');
const flagMatchValue = ref('');
const flagWriteValue = ref('1');
const lastWatermark = ref('');
const lastSyncResult = ref('');
const sourceColumnOptions = ref<any[]>([]);
const modeHint = computed(() => {
if (syncMode.value === 'TIME') return '只采集时间列在所选范围内的数据,再按匹配键更新/新增。适合中大型表只关注近期数据。';
if (syncMode.value === 'INCR') return '标记位回写只采集“标记列”为空的行采完回写“1”下轮不再重复。适合带 GUID 主键、无可靠递增列的流水表。';
return '全表读取并按匹配键更新/新增。适合数据量小、以更新为主的表。';
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false });
loading.value = true;
try {
reset();
const cfg: any = data?.id ? await queryById(data.id) : await getByBizType(data?.bizType || 'MIX_ACT');
if (!cfg || !cfg.id) {
createMessage.warning('未找到采集配置,请先在「采集配置」中新增');
return;
}
configId.value = cfg.id;
configName.value = cfg.configName || cfg.bizName || cfg.sourceTable;
sourceTable.value = cfg.sourceTable || '';
enabled.value = cfg.running === true || cfg.status === '1';
intervalSeconds.value = cfg.intervalSeconds || 1;
syncMode.value = cfg.syncMode || 'FULL';
incrColumn.value = cfg.incrColumn || undefined;
timeWindow.value = cfg.timeWindow || 'TODAY';
batchLimit.value = cfg.batchLimit || 2000;
flagCondition.value = cfg.flagCondition || 'IS_NULL';
flagMatchValue.value = cfg.flagMatchValue ?? '';
flagWriteValue.value = cfg.flagWriteValue ?? '1';
lastWatermark.value = cfg.lastWatermark || '';
lastSyncResult.value = cfg.lastSyncResult || '';
// 载入源表列供时间列/增量列选择(中间库未连接时静默忽略)
if (sourceTable.value) {
try {
const cols: any = await getSourceColumns(sourceTable.value);
sourceColumnOptions.value = (cols || []).map((c: any) => ({
label: c.columnName + (c.columnComment ? ` - ${c.columnComment}` : '') + (c.dataType ? ` (${c.dataType})` : ''),
value: c.columnName,
}));
} catch (e) {
sourceColumnOptions.value = [];
}
}
} finally {
loading.value = false;
}
});
function reset() {
configId.value = '';
configName.value = '';
sourceTable.value = '';
enabled.value = false;
intervalSeconds.value = 1;
syncMode.value = 'FULL';
incrColumn.value = undefined;
timeWindow.value = 'TODAY';
batchLimit.value = 2000;
flagCondition.value = 'IS_NULL';
flagMatchValue.value = '';
flagWriteValue.value = '1';
lastWatermark.value = '';
lastSyncResult.value = '';
sourceColumnOptions.value = [];
}
async function handleOk() {
if (!configId.value) {
closeModal();
return;
}
if (!intervalSeconds.value || intervalSeconds.value < 1) {
createMessage.warning('采集间隔不能小于1秒');
return;
}
if ((syncMode.value === 'TIME' || syncMode.value === 'INCR') && !incrColumn.value) {
createMessage.warning(syncMode.value === 'TIME' ? '请选择时间列' : '请选择标记列');
return;
}
setModalProps({ confirmLoading: true });
try {
await saveCollect({
id: configId.value,
status: enabled.value ? '1' : '0',
intervalSeconds: intervalSeconds.value,
syncMode: syncMode.value,
incrColumn: incrColumn.value,
timeWindow: timeWindow.value,
batchLimit: batchLimit.value,
flagCondition: flagCondition.value,
flagMatchValue: flagMatchValue.value,
flagWriteValue: flagWriteValue.value,
});
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>