fix(缺陷管理): 修复同步缺陷相关缺陷

--bug=1036798 --user=宋昌昌 【缺陷管理】集成jira-jira上缺陷删除附件-同步到ms-ms依旧显示了附件 https://www.tapd.cn/55049933/s/1476721
--bug=1036955 --user=宋昌昌 【缺陷管理】集成zentao-zentao缺陷删除附件-同步带ms附件未删除 https://www.tapd.cn/55049933/s/1476722
--bug=1036339 --user=宋昌昌 【项目管理】项目与权限-应用管理-缺陷管理-同步缺陷-修改同步频率不生效 https://www.tapd.cn/55049933/s/1476723
--bug=1036808 --user=宋昌昌 【项目管理】消息通知-同步缺陷执行完成通知-执行完成同步后未发送通知(所有类型消息都没发送) https://www.tapd.cn/55049933/s/1476724
--bug=1036963 --user=宋昌昌 【缺陷管理】三方全量同步成功后没有找到相应缺陷 https://www.tapd.cn/55049933/s/1476609
This commit is contained in:
song-cc-rock 2024-03-15 21:18:14 +08:00 committed by Craftsman
parent adcab0961c
commit ab88a007d3
10 changed files with 54 additions and 24 deletions

View File

@ -15,8 +15,8 @@ public class BugSyncExtraService {
@Resource @Resource
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;
private static final String SYNC_THIRD_PARTY_ISSUES_KEY = "ISSUE:SYNC"; private static final String SYNC_THIRD_PARTY_ISSUES_KEY = "MS:BUG:SYNC";
private static final String SYNC_THIRD_PARTY_ISSUES_ERROR_KEY = "ISSUE:SYNC:ERROR"; private static final String SYNC_THIRD_PARTY_ISSUES_ERROR_KEY = "MS:BUG:SYNC:ERROR";
/** /**
* 设置手动同步缺陷唯一Key * 设置手动同步缺陷唯一Key

View File

@ -35,7 +35,7 @@ public class BugSyncNoticeService {
paramMap.put("total", total); paramMap.put("total", total);
paramMap.put("projectId", projectId); paramMap.put("projectId", projectId);
NoticeModel noticeModel = NoticeModel.builder().operator(currentUser) NoticeModel noticeModel = NoticeModel.builder().operator(currentUser)
.context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.SYNC_COMPLETED).build(); .context(template).subject(subject).paramMap(paramMap).event(NoticeConstants.Event.EXECUTE_COMPLETED).build();
noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel); noticeSendService.send(NoticeConstants.TaskType.BUG_SYNC_TASK, noticeModel);
} }
} }

View File

@ -207,9 +207,6 @@ public interface NoticeConstants {
@Schema(description = "message.close") @Schema(description = "message.close")
String CLOSE = "CLOSE"; String CLOSE = "CLOSE";
@Schema(description = "message.close")
String SYNC_COMPLETED = "SYNC_COMPLETED";
} }
interface RelatedUser { interface RelatedUser {

View File

@ -251,6 +251,8 @@ public abstract class AbstractNoticeSender implements NoticeSender {
realReceivers.add(receiver); realReceivers.add(receiver);
} }
} }
} else {
realReceivers = receivers;
} }
return realReceivers; return realReceivers;
} }

View File

@ -332,6 +332,12 @@
} }
} }
}; };
const getOptionFromTemplate = (field: CustomFieldItem | undefined) => {
if (field) {
return field.options ? field.options : JSON.parse(field.platformOptionJson);
}
return [];
};
async function loadedBug(detail: BugEditFormObject) { async function loadedBug(detail: BugEditFormObject) {
detailInfo.value = { ...detail }; detailInfo.value = { ...detail };
const { templateId } = detailInfo.value; const { templateId } = detailInfo.value;
@ -354,8 +360,9 @@
const SINGRADIO_TYPE = ['RADIO', 'SELECT', 'MEMBER']; const SINGRADIO_TYPE = ['RADIO', 'SELECT', 'MEMBER'];
detail.customFields.forEach((item) => { detail.customFields.forEach((item) => {
if (MULTIPLE_TYPE.includes(item.type)) { if (MULTIPLE_TYPE.includes(item.type)) {
const multipleOptions = const multipleOptions = getOptionFromTemplate(
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || []; currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)
);
// //
const optionsIds = (multipleOptions || []).map((e: any) => e.value); const optionsIds = (multipleOptions || []).map((e: any) => e.value);
if (item.type !== 'MULTIPLE_INPUT') { if (item.type !== 'MULTIPLE_INPUT') {
@ -372,8 +379,9 @@
tmpObj[item.id] = arr[arr.length - 1]; tmpObj[item.id] = arr[arr.length - 1];
} }
} else if (SINGRADIO_TYPE.includes(item.type)) { } else if (SINGRADIO_TYPE.includes(item.type)) {
const multipleOptions = const multipleOptions = getOptionFromTemplate(
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || []; currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)
);
// //
const optionsIds = (multipleOptions || []).map((e: any) => e.value); const optionsIds = (multipleOptions || []).map((e: any) => e.value);
const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || ''; const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || '';

View File

@ -371,7 +371,7 @@
if (Array.isArray(arr) && arr.length) { if (Array.isArray(arr) && arr.length) {
formRules.value = arr.map((item: any) => { formRules.value = arr.map((item: any) => {
let initValue = item.defaultValue; let initValue = item.defaultValue;
const initOptions = item.options; const initOptions = item.options ? item.options : JSON.parse(item.platformOptionJson);
if (memberType.includes(item.type)) { if (memberType.includes(item.type)) {
if (item.defaultValue === 'CREATE_USER' || item.defaultValue.includes('CREATE_USER')) { if (item.defaultValue === 'CREATE_USER' || item.defaultValue.includes('CREATE_USER')) {
initValue = item.type === 'MEMBER' ? userStore.id : [userStore.id]; initValue = item.type === 'MEMBER' ? userStore.id : [userStore.id];
@ -645,6 +645,14 @@
}); });
scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' }); scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' });
}; };
const getOptionFromTemplate = (field: CustomFieldItem | undefined) => {
if (field) {
return field.options ? field.options : JSON.parse(field.platformOptionJson);
}
return [];
};
// //
const getDetailInfo = async () => { const getDetailInfo = async () => {
loading.value = true; loading.value = true;
@ -694,8 +702,9 @@
tmpObj[item.id] = ''; tmpObj[item.id] = '';
// //
} else if (MULTIPLE_TYPE.includes(item.type)) { } else if (MULTIPLE_TYPE.includes(item.type)) {
const multipleOptions = const multipleOptions = getOptionFromTemplate(
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || []; currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)
);
// //
const optionsIds = (multipleOptions || []).map((e: any) => e.value); const optionsIds = (multipleOptions || []).map((e: any) => e.value);
if (item.type !== 'MULTIPLE_INPUT') { if (item.type !== 'MULTIPLE_INPUT') {
@ -717,8 +726,9 @@
} }
// //
} else if (SINGRADIO_TYPE.includes(item.type)) { } else if (SINGRADIO_TYPE.includes(item.type)) {
const multipleOptions = const multipleOptions = getOptionFromTemplate(
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || []; currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)
);
// //
const optionsIds = (multipleOptions || []).map((e: any) => e.value); const optionsIds = (multipleOptions || []).map((e: any) => e.value);
const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || ''; const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || '';

View File

@ -164,7 +164,7 @@
class="flex flex-row items-center gap-[8px] rounded-[4px] border-[1px] border-[rgb(var(--primary-5))] bg-[rgb(var(--primary-1))] px-[16px] py-[12px]" class="flex flex-row items-center gap-[8px] rounded-[4px] border-[1px] border-[rgb(var(--primary-5))] bg-[rgb(var(--primary-1))] px-[16px] py-[12px]"
> >
<icon-exclamation-circle-fill class="text-[rgb(var(--primary-5))]" /> <icon-exclamation-circle-fill class="text-[rgb(var(--primary-5))]" />
<div>{{ t('bugManagement.bugAutoSync', { name: '每天00:00:00' }) }}</div> <div>{{ t('bugManagement.bugAutoSync') }}</div>
</div> </div>
<div class="mb-[8px] mt-[16px]">{{ t('bugManagement.createTime') }}</div> <div class="mb-[8px] mt-[16px]">{{ t('bugManagement.createTime') }}</div>
<div class="flex flex-row gap-[8px]"> <div class="flex flex-row gap-[8px]">
@ -306,6 +306,7 @@
// //
const isComplete = ref(false); const isComplete = ref(false);
const isShowCompleteMsg = ref(false);
// //
const customFields = ref<BugEditCustomField[]>([]); const customFields = ref<BugEditCustomField[]>([]);
// //
@ -603,12 +604,17 @@
}; };
/** 同步缺陷 */ /** 同步缺陷 */
const { pause, resume } = useIntervalFn(() => { const { pause, resume } = useIntervalFn(() => {
isShowCompleteMsg.value = true;
checkSyncStatus(); checkSyncStatus();
}, 1000); }, 1000);
// //
pause(); pause();
watchEffect(() => { watchEffect(() => {
if (isComplete.value) { if (isComplete.value) {
if (isShowCompleteMsg.value) {
Message.success(t('bugManagement.syncSuccess'));
fetchData();
}
// //
pause(); pause();
} }
@ -622,7 +628,9 @@
try { try {
// //
await syncBugOpenSource(appStore.currentProjectId); await syncBugOpenSource(appStore.currentProjectId);
Message.warning(t('bugManagement.synchronizing'));
isComplete.value = false; isComplete.value = false;
isShowCompleteMsg.value = true;
// //
resume(); resume();
} catch (error) { } catch (error) {
@ -635,11 +643,12 @@
try { try {
await syncBugEnterprise({ await syncBugEnterprise({
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
pre: syncObject.operator === 'lt', pre: syncObject.operator === 'le',
createTime: syncObject.time, createTime: syncObject.time,
}); });
Message.success(t('bugManagement.syncSuccess')); Message.warning(t('bugManagement.synchronizing'));
isComplete.value = false; isComplete.value = false;
isShowCompleteMsg.value = true;
// //
resume(); resume();
} catch (error) { } catch (error) {

View File

@ -19,10 +19,11 @@ export default {
addBug: 'Create Bug', addBug: 'Create Bug',
editBug: 'Edit Bug', editBug: 'Edit Bug',
sync: 'Sync', sync: 'Sync',
synchronizing: 'Synchronizing',
syncSuccess: 'Synchronous success', syncSuccess: 'Synchronous success',
syncBugTipRowOne: 'Sync third plant bug', syncBugTipRowOne: 'Sync third plant bug',
syncBugTipRowTwo: 'Create bug and sync bug', syncBugTipRowTwo: 'Create bug and sync bug',
bugAutoSync: 'System {name} auto sync', bugAutoSync: 'System will auto sync by the project application setting frequency',
syncTime: 'Sync time', syncTime: 'Sync time',
deleteLabel: 'Bug witch created by MeterSphere will in recycle bin and third plant bug will be deleted', deleteLabel: 'Bug witch created by MeterSphere will in recycle bin and third plant bug will be deleted',
nameIsIncorrect: 'Bug name error', nameIsIncorrect: 'Bug name error',

View File

@ -19,10 +19,11 @@ export default {
createTime: '创建时间', createTime: '创建时间',
updateTime: '更新时间', updateTime: '更新时间',
sync: '同步', sync: '同步',
synchronizing: '正在同步中',
syncSuccess: '同步成功', syncSuccess: '同步成功',
syncBugTipRowOne: '将第三方的缺陷同步到缺陷管理中,', syncBugTipRowOne: '将第三方的缺陷同步到缺陷管理中,',
syncBugTipRowTwo: '新增缺陷和更新已有的缺陷?', syncBugTipRowTwo: '新增缺陷和更新已有的缺陷?',
bugAutoSync: '系统 {name} 自动同步', bugAutoSync: '系统将按照项目应用设置频率自动同步',
syncTime: '同步时间', syncTime: '同步时间',
deleteLabel: '删除后MeterSphere 创建的缺陷进入回收站;第三方平台同步的缺陷将不做回收', deleteLabel: '删除后MeterSphere 创建的缺陷进入回收站;第三方平台同步的缺陷将不做回收',
nameIsIncorrect: '缺陷名称不正确', nameIsIncorrect: '缺陷名称不正确',

View File

@ -15,7 +15,7 @@
@confirm="handleConfirm" @confirm="handleConfirm"
> >
<a-form ref="formRef" class="rounded-[4px]" :model="form" layout="vertical"> <a-form ref="formRef" class="rounded-[4px]" :model="form" layout="vertical">
<a-form-item field="platformKey" :label="t('project.menu.platformLabel')"> <a-form-item field="PLATFORM_KEY" :label="t('project.menu.platformLabel')">
<a-select <a-select
v-model="form.PLATFORM_KEY" v-model="form.PLATFORM_KEY"
allow-clear allow-clear
@ -250,11 +250,13 @@
await initPlatformOption(); await initPlatformOption();
const res = await getBugSyncInfo(currentProjectId.value); const res = await getBugSyncInfo(currentProjectId.value);
if (res && res.platform_key) { if (res && res.platform_key) {
form.SYNC_ENABLE = res.sync_enable;
form.PLATFORM_KEY = res.platform_key;
formCreateValue.value = JSON.parse(res.bug_platform_config); formCreateValue.value = JSON.parse(res.bug_platform_config);
// keychange // keychange
await handlePlatformChange(res.platform_key); await handlePlatformChange(res.platform_key);
form.SYNC_ENABLE = res.sync_enable;
form.PLATFORM_KEY = res.platform_key;
form.MECHANISM = res.mechanism;
form.CRON_EXPRESSION = res.cron_expression;
} }
} catch (e) { } catch (e) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console