feat(公共组件): 增加评论人ids
This commit is contained in:
parent
a3e8453536
commit
b3822a3607
|
@ -795,7 +795,6 @@
|
||||||
|
|
||||||
/*** 徽标 ****/
|
/*** 徽标 ****/
|
||||||
.arco-badge-number {
|
.arco-badge-number {
|
||||||
width: 30px !important;
|
|
||||||
height: 16px !important;
|
height: 16px !important;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -74,6 +74,8 @@ export default defineComponent({
|
||||||
currentItem.parentId = item.parentId || '';
|
currentItem.parentId = item.parentId || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const noticeUserIds = ref<string[]>([]);
|
||||||
|
|
||||||
const renderInput = (item: CommentItem) => {
|
const renderInput = (item: CommentItem) => {
|
||||||
return (
|
return (
|
||||||
<CommentInput
|
<CommentInput
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="w-full items-center">
|
<div class="w-full items-center">
|
||||||
<a-input v-if="!isActive" class="w-full" @click="isActive = true"></a-input>
|
<a-input v-if="!isActive" class="w-full" @click="isActive = true"></a-input>
|
||||||
<div v-else class="flex flex-col justify-between">
|
<div v-else class="flex flex-col justify-between">
|
||||||
<MsRichText v-model:raw="currentContent" class="w-full" />
|
<MsRichText v-model:raw="currentContent" v-model:commentIds="commentIds" class="w-full" />
|
||||||
<div class="mt-4 flex flex-row justify-end gap-[12px]">
|
<div class="mt-4 flex flex-row justify-end gap-[12px]">
|
||||||
<a-button @click="cancelClick">{{ t('common.cancel') }}</a-button>
|
<a-button @click="cancelClick">{{ t('common.cancel') }}</a-button>
|
||||||
<a-button type="primary" :disabled="!currentContent" @click="publish">{{ t('common.publish') }}</a-button>
|
<a-button type="primary" :disabled="!currentContent" @click="publish">{{ t('common.publish') }}</a-button>
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useVModel } from '@vueuse/core';
|
||||||
|
|
||||||
import MsAvatar from '@/components/pure/ms-avatar/index.vue';
|
import MsAvatar from '@/components/pure/ms-avatar/index.vue';
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
isShowAvatar: boolean; // 是否显示评论人头像
|
isShowAvatar: boolean; // 是否显示评论人头像
|
||||||
isUseBottom: boolean; // 是否被用于底部
|
isUseBottom: boolean; // 是否被用于底部
|
||||||
defaultValue?: string; // 默认值
|
defaultValue?: string; // 默认值
|
||||||
|
noticeUserIds?: string[]; // 评论人id列表
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const currentContent = ref(props.defaultValue || '');
|
const currentContent = ref(props.defaultValue || '');
|
||||||
|
@ -48,6 +50,7 @@
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const isActive = ref(false);
|
const isActive = ref(false);
|
||||||
|
const commentIds = useVModel(props, 'noticeUserIds', emit);
|
||||||
|
|
||||||
const publish = () => {
|
const publish = () => {
|
||||||
emit('publish', currentContent.value);
|
emit('publish', currentContent.value);
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
popupContainer: 'body',
|
popupContainer: 'body',
|
||||||
disabledWidthDrag: false,
|
disabledWidthDrag: false,
|
||||||
okPermission: () => [], // 确认按钮权限
|
okPermission: () => [], // 确认按钮权限
|
||||||
|
closable: true,
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['update:visible', 'confirm', 'cancel', 'continue']);
|
const emit = defineEmits(['update:visible', 'confirm', 'cancel', 'continue']);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<FormCreate v-model:api="formApi" :rule="formRules" :option="option"></FormCreate>
|
<FormCreate v-model:api="formApi" :rule="formRules" :option="props.option"></FormCreate>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
|
@ -94,6 +94,7 @@
|
||||||
uploadImage?: (file: File) => Promise<any>;
|
uploadImage?: (file: File) => Promise<any>;
|
||||||
maxHeight?: string;
|
maxHeight?: string;
|
||||||
filedIds?: string[];
|
filedIds?: string[];
|
||||||
|
commentIds?: string[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
raw: '',
|
raw: '',
|
||||||
|
@ -107,9 +108,11 @@
|
||||||
(event: 'update:raw', value: string): void;
|
(event: 'update:raw', value: string): void;
|
||||||
(event: 'update:filedIds', value: string[]): void;
|
(event: 'update:filedIds', value: string[]): void;
|
||||||
(event: 'update', value: string): void;
|
(event: 'update', value: string): void;
|
||||||
|
(event: 'update:commentIds', value: string): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const imagesNodes = useVModel(props, 'filedIds', emit);
|
const imagesNodesIds = useVModel(props, 'filedIds', emit);
|
||||||
|
const commentNodeIds = useVModel(props, 'commentIds', emit);
|
||||||
|
|
||||||
async function asyncWorker(arg: Task): Promise<void> {
|
async function asyncWorker(arg: Task): Promise<void> {
|
||||||
if (!props.uploadImage) {
|
if (!props.uploadImage) {
|
||||||
|
@ -142,6 +145,7 @@
|
||||||
|
|
||||||
const attachmentSelectorModal = ref(false);
|
const attachmentSelectorModal = ref(false);
|
||||||
const selectedimagesNode = ref<string>();
|
const selectedimagesNode = ref<string>();
|
||||||
|
const selectedCommentNode = ref<string>();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const debounceOnUpdate = useDebounceFn(() => {
|
const debounceOnUpdate = useDebounceFn(() => {
|
||||||
|
@ -194,7 +198,7 @@
|
||||||
images.push(node.attrs.fileId);
|
images.push(node.attrs.fileId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
imagesNodes.value = images;
|
imagesNodesIds.value = images;
|
||||||
if (!selectedimagesNode.value) {
|
if (!selectedimagesNode.value) {
|
||||||
// eslint-disable-next-line prefer-destructuring
|
// eslint-disable-next-line prefer-destructuring
|
||||||
selectedimagesNode.value = images[0];
|
selectedimagesNode.value = images[0];
|
||||||
|
@ -206,6 +210,32 @@
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
Extension.create({
|
||||||
|
addProseMirrorPlugins() {
|
||||||
|
return [
|
||||||
|
new Plugin({
|
||||||
|
key: new PluginKey(Mention.name),
|
||||||
|
props: {
|
||||||
|
decorations: (state) => {
|
||||||
|
const commentUsers: string[] = [];
|
||||||
|
const { doc } = state;
|
||||||
|
doc.descendants((node) => {
|
||||||
|
if (node.type.name === 'mention') {
|
||||||
|
commentUsers.push(node.attrs.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
commentNodeIds.value = commentUsers;
|
||||||
|
if (!selectedCommentNode.value) {
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
|
selectedCommentNode.value = commentUsers[0];
|
||||||
|
}
|
||||||
|
return DecorationSet.empty;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
}),
|
||||||
ExtensionTaskList,
|
ExtensionTaskList,
|
||||||
ExtensionLink.configure({
|
ExtensionLink.configure({
|
||||||
autolink: false,
|
autolink: false,
|
||||||
|
|
|
@ -37,6 +37,7 @@ export default {
|
||||||
'menu.caseManagement.featureCaseRecycle': 'Recycle',
|
'menu.caseManagement.featureCaseRecycle': 'Recycle',
|
||||||
'menu.caseManagement.featureCaseList': 'Case list',
|
'menu.caseManagement.featureCaseList': 'Case list',
|
||||||
'menu.caseManagement.featureCaseDetail': 'Create Case',
|
'menu.caseManagement.featureCaseDetail': 'Create Case',
|
||||||
|
'menu.caseManagement.featureCaseEdit': 'Edit Case',
|
||||||
'menu.caseManagement.featureCaseCreateSuccess': 'Create Success',
|
'menu.caseManagement.featureCaseCreateSuccess': 'Create Success',
|
||||||
'menu.caseManagement.caseManagementReview': 'Feature Case Review',
|
'menu.caseManagement.caseManagementReview': 'Feature Case Review',
|
||||||
'menu.caseManagement.caseManagementReviewCreate': 'Create Review',
|
'menu.caseManagement.caseManagementReviewCreate': 'Create Review',
|
||||||
|
|
|
@ -41,6 +41,7 @@ export default {
|
||||||
'menu.caseManagement.featureCaseRecycle': '回收站',
|
'menu.caseManagement.featureCaseRecycle': '回收站',
|
||||||
'menu.caseManagement.featureCaseList': '用例列表',
|
'menu.caseManagement.featureCaseList': '用例列表',
|
||||||
'menu.caseManagement.featureCaseDetail': '创建用例',
|
'menu.caseManagement.featureCaseDetail': '创建用例',
|
||||||
|
'menu.caseManagement.featureCaseEdit': '编辑用例',
|
||||||
'menu.caseManagement.featureCaseCreateSuccess': '创建用例成功',
|
'menu.caseManagement.featureCaseCreateSuccess': '创建用例成功',
|
||||||
'menu.caseManagement.caseManagementReview': '用例评审',
|
'menu.caseManagement.caseManagementReview': '用例评审',
|
||||||
'menu.caseManagement.caseManagementReviewCreate': '创建评审',
|
'menu.caseManagement.caseManagementReviewCreate': '创建评审',
|
||||||
|
|
|
@ -224,6 +224,7 @@ export interface TabItemType {
|
||||||
key: string;
|
key: string;
|
||||||
title: string;
|
title: string;
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 需求
|
// 需求
|
||||||
|
|
|
@ -42,8 +42,9 @@ const CaseManagement: AppRouteRecordRaw = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_DETAIL,
|
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_DETAIL,
|
||||||
editTag: 'id',
|
|
||||||
locale: 'menu.caseManagement.featureCaseDetail',
|
locale: 'menu.caseManagement.featureCaseDetail',
|
||||||
|
editTag: 'id',
|
||||||
|
editLocale: 'menu.caseManagement.featureCaseEdit',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -146,6 +146,7 @@
|
||||||
:content="commentContent"
|
:content="commentContent"
|
||||||
is-show-avatar
|
is-show-avatar
|
||||||
is-use-bottom
|
is-use-bottom
|
||||||
|
:notice-user-ids="noticeUserIds"
|
||||||
@publish="publishHandler"
|
@publish="publishHandler"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -205,6 +206,7 @@
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const commentContent = ref('');
|
const commentContent = ref('');
|
||||||
const commentRef = ref();
|
const commentRef = ref();
|
||||||
|
const noticeUserIds = ref<string[]>([]); // 通知人ids
|
||||||
|
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
:pagination="props.pagination"
|
:pagination="props.pagination"
|
||||||
:table-data="props.tableData"
|
:table-data="props.tableData"
|
||||||
:page-change="props.pageChange"
|
:page-change="props.pageChange"
|
||||||
|
:mask-closable="true"
|
||||||
@loaded="loadedCase"
|
@loaded="loadedCase"
|
||||||
>
|
>
|
||||||
<template #titleLeft>
|
<template #titleLeft>
|
||||||
|
@ -184,6 +185,7 @@
|
||||||
</div>
|
</div>
|
||||||
<inputComment
|
<inputComment
|
||||||
v-model:content="content"
|
v-model:content="content"
|
||||||
|
v-model:notice-user-ids="noticeUserIds"
|
||||||
v-permission="['FUNCTIONAL_CASE:READ+COMMENT']"
|
v-permission="['FUNCTIONAL_CASE:READ+COMMENT']"
|
||||||
:is-active="isActive"
|
:is-active="isActive"
|
||||||
is-show-avatar
|
is-show-avatar
|
||||||
|
@ -483,8 +485,9 @@
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
(val) => {
|
(val) => {
|
||||||
showDrawerVisible.value = val;
|
|
||||||
if (val) {
|
if (val) {
|
||||||
|
showDrawerVisible.value = val;
|
||||||
|
activeTab.value = 'detail';
|
||||||
settingDrawerRef.value.getTabModule();
|
settingDrawerRef.value.getTabModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,21 +511,17 @@
|
||||||
const content = ref('');
|
const content = ref('');
|
||||||
const commentRef = ref();
|
const commentRef = ref();
|
||||||
const isActive = ref<boolean>(false);
|
const isActive = ref<boolean>(false);
|
||||||
|
|
||||||
|
const noticeUserIds = ref<string[]>([]);
|
||||||
async function publishHandler(currentContent: string) {
|
async function publishHandler(currentContent: string) {
|
||||||
const regex = /data-id="([^"]*)"/g;
|
|
||||||
const matchesNotifier = currentContent.match(regex);
|
|
||||||
let notifiers = '';
|
|
||||||
if (matchesNotifier?.length) {
|
|
||||||
notifiers = matchesNotifier.map((match) => match.replace('data-id="', '').replace('"', '')).join(';');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const params: CommentParams = {
|
const params: CommentParams = {
|
||||||
caseId: detailInfo.value.id,
|
caseId: detailInfo.value.id,
|
||||||
notifier: notifiers,
|
notifier: noticeUserIds.value.join(';'),
|
||||||
replyUser: '',
|
replyUser: '',
|
||||||
parentId: '',
|
parentId: '',
|
||||||
content: currentContent,
|
content: currentContent,
|
||||||
event: notifiers ? 'AT' : 'COMMENT', // 任务事件(仅评论: ’COMMENT‘; 评论并@: ’AT‘; 回复评论/回复并@: ’REPLAY‘;)
|
event: noticeUserIds.value.join(';') ? 'AT' : 'COMMENT', // 任务事件(仅评论: ’COMMENT‘; 评论并@: ’AT‘; 回复评论/回复并@: ’REPLAY‘;)
|
||||||
};
|
};
|
||||||
await createCommentList(params);
|
await createCommentList(params);
|
||||||
commentRef.value.getAllCommentList();
|
commentRef.value.getAllCommentList();
|
||||||
|
|
|
@ -82,11 +82,13 @@
|
||||||
key: 'requirement',
|
key: 'requirement',
|
||||||
title: 'caseManagement.featureCase.requirement',
|
title: 'caseManagement.featureCase.requirement',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'bug',
|
key: 'bug',
|
||||||
title: 'caseManagement.featureCase.bug',
|
title: 'caseManagement.featureCase.bug',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// testPlan: [
|
// testPlan: [
|
||||||
|
@ -108,31 +110,37 @@
|
||||||
key: 'changeHistory',
|
key: 'changeHistory',
|
||||||
title: 'caseManagement.featureCase.changeHistory',
|
title: 'caseManagement.featureCase.changeHistory',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabDefaultSettingList = ref<TabItemType[]>([
|
const tabDefaultSettingList = ref<TabItemType[]>([
|
||||||
{
|
{
|
||||||
key: 'case',
|
key: 'case',
|
||||||
title: 'caseManagement.featureCase.case',
|
title: 'caseManagement.featureCase.case',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'dependency',
|
key: 'dependency',
|
||||||
title: 'caseManagement.featureCase.dependency',
|
title: 'caseManagement.featureCase.dependency',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'caseReview',
|
key: 'caseReview',
|
||||||
title: 'caseManagement.featureCase.caseReview',
|
title: 'caseManagement.featureCase.caseReview',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'comments',
|
key: 'comments',
|
||||||
title: 'caseManagement.featureCase.comments',
|
title: 'caseManagement.featureCase.comments',
|
||||||
enable: true,
|
enable: true,
|
||||||
|
total: 0,
|
||||||
},
|
},
|
||||||
// TOTO Xpack 不上
|
// TOTO Xpack 不上
|
||||||
// ...getTabList(),
|
// ...getTabList(),
|
||||||
|
|
Loading…
Reference in New Issue