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

This commit is contained in:
xinxin.wu 2024-03-15 13:21:43 +08:00 committed by Craftsman
parent 51c199264c
commit 868a1a38cb
19 changed files with 286 additions and 150 deletions

View File

@ -40,10 +40,11 @@ import {
UpdateProjectTemplateUrl,
} from '@/api/requrls/setting/template';
import { TableQueryParams } from '@/models/common';
import { CommonList, TableQueryParams } from '@/models/common';
import type {
ActionTemplateManage,
AddOrUpdateField,
OrdTemplateManagement,
OrdWorkStatus,
SeneType,
SetStateType,
@ -56,7 +57,9 @@ import type {
*/
// 获取模板列表(组织)
export function getOrganizeTemplateList(params: TableQueryParams) {
return MSR.get({ url: `${GetOrganizeTemplateUrl}/${params.organizationId}/${params.scene}` });
return MSR.get({
url: `${GetOrganizeTemplateUrl}/${params.organizationId}/${params.scene}`,
});
}
// 获取模板详情(组织)
export function getOrganizeTemplateInfo(id: string) {
@ -180,7 +183,9 @@ export function getProjectFieldDetail(id: string) {
*/
// 获取模板列表(项目)
export function getProjectTemplateList(params: TableQueryParams) {
return MSR.get({ url: `${GetProjectTemplateUrl}/${params.projectId}/${params.scene}` });
return MSR.get({
url: `${GetProjectTemplateUrl}/${params.projectId}/${params.scene}`,
});
}
// 获取模板详情(项目)
export function getProjectTemplateInfo(id: string) {

View File

@ -19,6 +19,11 @@ export default defineComponent({
type: Boolean as PropType<boolean>,
default: false,
},
uploadImage: {
type: Function,
// eslint-disable-next-line @typescript-eslint/no-empty-function
default: (file: File) => Promise<any>,
},
},
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
@ -26,7 +31,7 @@ export default defineComponent({
delete: (value: string) => true, // 删除评论
},
setup(props, { emit }) {
const { commentList, disabled } = toRefs(props);
const { commentList, disabled, uploadImage } = toRefs(props);
const currentItem = reactive<{ id: string; commentType: CommentType; commentStatus: string }>({
id: '',
commentType: 'ADD',
@ -123,6 +128,7 @@ export default defineComponent({
onUpdate:noticeUserIds={(ids: string[]) => {
noticeUserIds.value = ids;
}}
uploadImage={uploadImage.value}
onCancel={() => resetCurrentItem()}
{...item}
/>

View File

@ -18,6 +18,7 @@
<MsRichText
v-model:raw="currentContent"
v-model:commentIds="commentIds"
:upload-image="props.uploadImage"
class="w-full"
placeholder="ms.comment.enterPlaceHolderTip"
/>
@ -46,6 +47,7 @@
const props = defineProps<{
isShowAvatar: boolean; //
isUseBottom: boolean; //
uploadImage?: (file: File) => Promise<any>;
}>();
const currentContent = defineModel<string>('defaultValue', { default: '' });

View File

@ -52,6 +52,12 @@
</a-popover>
</div>
</template>
<template #status="{ record }">
<MsTag v-if="record.status === 'PASSED'" type="success" theme="light">{{
t('project.commonScript.testsPass')
}}</MsTag>
<MsTag v-else>{{ t('project.commonScript.draft') }}</MsTag>
</template>
<template #enable="{ record }">
<MsTag v-if="record.enable" type="success" theme="light">{{ t('project.commonScript.testsPass') }}</MsTag>
<MsTag v-else>{{ t('project.commonScript.draft') }}</MsTag>
@ -136,8 +142,8 @@
},
{
title: 'project.commonScript.enable',
dataIndex: 'enable',
slotName: 'enable',
dataIndex: 'status',
slotName: 'status',
showInTable: true,
width: 150,
showDrag: true,

View File

@ -171,6 +171,7 @@
function handleParamTableChange(resultArr: any[], isInit?: boolean) {
innerParams.value = [...resultArr];
form.value.params = JSON.stringify([...resultArr]);
if (!isInit) {
emit('change');
}

View File

@ -13,7 +13,7 @@
{{ null }}
</template>
<template #content>
<img class="h-[247px] w-[398px]" :src="previewIcon" />
<img class="h-full w-full" :src="previewIcon" />
</template>
<span class="cursor-pointer text-[rgb(var(--primary-5))]">{{ t('project.menu.preview') }}</span>
</a-popover>

View File

@ -164,7 +164,8 @@ const Image = TiptapImage.extend<ExtensionOptions & ImageOptions>({
),
title: t('editor.extensions.image.open_link'),
action: () => {
window.open(editor.getAttributes(Image.name).src, '_blank');
const newWindow = window.open('');
newWindow?.document.write(`<img src="${editor.getAttributes(Image.name).src}">`);
},
},
},

View File

@ -116,6 +116,7 @@ export interface ActionTemplateManage {
customFields?: CustomField[];
fieldType?: string;
systemFields?: Record<string, any>[];
enablePlatformDefault?: boolean;
internal?: boolean; // 是否为系统模板
platForm?: string;
[key: string]: any;

View File

@ -14,6 +14,7 @@
:page-change="props.pageChange"
show-full-screen
unmount-on-close
:mask="false"
@loaded="loadedBug"
>
<template #titleRight="{ loading }">
@ -78,7 +79,7 @@
</MsButton>
</div>
</template>
<template #default>
<template #default="{ loading }">
<div ref="wrapperRef" class="h-full bg-white">
<MsSplitBox
ref="wrapperRef"
@ -124,15 +125,20 @@
</template>
<template #second>
<div class="rightWrapper p-[24px]">
<div class="mb-4 font-medium">
<strong>
{{ t('bugManagement.detail.basicInfo') }}
</strong>
</div>
<!-- 自定义字段开始 -->
<div style="display: inline-block; width: 100%; word-wrap: break-word">
<div class="inline-block w-full break-words">
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
<a-space direction="vertical" class="w-[100%]" size="large">
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
</a-space>
</a-skeleton>
<div v-if="!loading" class="mb-4 font-medium">
<strong>
{{ t('bugManagement.detail.basicInfo') }}
</strong>
</div>
<MsFormCreate
v-if="formRules.length"
v-if="!loading"
ref="formCreateRef"
v-model:form-item="formItem"
v-model:api="fApi"
@ -141,34 +147,37 @@
:option="options"
@change="handelFormCreateChange"
/>
</div>
<!-- 自定义字段结束 -->
<div v-if="!isPlatformDefaultTemplate" class="baseItem">
<a-form
:model="{}"
:label-col-props="{
span: 9,
}"
:wrapper-col-props="{
span: 15,
}"
label-align="left"
content-class="tags-class"
<!-- 自定义字段结束 -->
<div
v-if="!isPlatformDefaultTemplate && hasAnyPermission(['PROJECT_BUG:READ+UPDATE']) && !loading"
class="baseItem"
>
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
<MsTagsInput
v-model:model-value="tags"
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
/>
</a-form-item>
</a-form>
<a-form
:model="{}"
:label-col-props="{
span: 9,
}"
:wrapper-col-props="{
span: 15,
}"
label-align="left"
content-class="tags-class"
>
<a-form-item field="tags" :label="t('system.orgTemplate.tags')">
<MsTagsInput
v-model:model-value="tags"
:disabled="!hasAnyPermission(['PROJECT_BUG:READ+UPDATE'])"
/>
</a-form-item>
</a-form>
<!-- <span class="label"> {{ t('bugManagement.detail.tag') }}</span>-->
<!-- <span style="width: 200px">-->
<!-- <MsTag v-for="item of tags" :key="item"> {{ item }} </MsTag>-->
<!-- </span>-->
<!-- <span class="label"> {{ t('bugManagement.detail.tag') }}</span>-->
<!-- <span style="width: 200px">-->
<!-- <MsTag v-for="item of tags" :key="item"> {{ item }} </MsTag>-->
<!-- </span>-->
</div>
</div>
<!-- 内置基础信息结束 -->
</div>
</template>
@ -178,6 +187,7 @@
v-if="activeTab === 'comment'"
:content="commentContent"
is-show-avatar
:upload-image="handleUploadImage"
is-use-bottom
:notice-user-ids="noticeUserIds"
@publish="publishHandler"
@ -211,6 +221,7 @@
import {
createOrUpdateComment,
deleteSingleBug,
editorUploadFile,
followBug,
getBugDetail,
getTemplateById,
@ -218,9 +229,11 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useAppStore } from '@/store';
import useUserStore from '@/store/modules/user';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { CustomFieldItem } from '@/models/bug-management';
import { BugEditCustomField, BugEditFormObject, BugTemplateRequest } from '@/models/bug-management';
import { SelectValue } from '@/models/projectManagement/menuManagement';
import { RouteEnum } from '@/enums/routeEnum';
@ -245,7 +258,6 @@
pagination: MsPaginationI; //
pageChange: (page: number) => Promise<void>; //
}>();
const caseCount = ref(0);
const appStore = useAppStore();
const commentContent = ref('');
@ -258,35 +270,44 @@
const showDrawerVisible = defineModel<boolean>('visible', { default: false });
const bugDetailTabRef = ref();
const isPlatformDefaultTemplate = ref(false);
const rowLength = ref<number>(0);
const activeTab = ref<string>('detail');
const detailInfo = ref<Record<string, any>>({ match: [] }); // loadBug
const tags = ref([]);
const platformSystemFields = ref<BugEditCustomField[]>([]); //
const userStore = useUserStore();
//
const getFormRules = (arr: BugEditCustomField[], valueObj: BugEditFormObject) => {
formRules.value = [];
const memberType = ['MEMBER', 'MULTIPLE_MEMBER'];
if (Array.isArray(arr) && arr.length) {
formRules.value = arr.map((item: any) => {
let initValue = valueObj[item.fieldId];
const initOptions = item.options ? item.options : JSON.parse(item.platformOptionJson);
if (memberType.includes(item.type)) {
if (item.defaultValue === 'CREATE_USER' || item.defaultValue.includes('CREATE_USER')) {
initValue = item.type === 'MEMBER' ? userStore.id : [userStore.id];
}
}
return {
type: item.type,
name: item.fieldId,
label: item.fieldName,
value: valueObj[item.fieldId],
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
value: initValue,
options: initOptions,
required: item.required as boolean,
platformPlaceHolder: item.platformPlaceHolder,
props: {
modelValue: valueObj[item.fieldId],
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
modelValue: initValue,
options: initOptions,
disabled: !hasAnyPermission(['PROJECT_BUG:READ+UPDATE']),
},
};
});
}
};
const currentCustomFields = ref<CustomFieldItem[]>([]);
const templateChange = async (v: SelectValue, valueObj: BugEditFormObject, request: BugTemplateRequest) => {
if (v) {
@ -313,25 +334,50 @@
};
async function loadedBug(detail: BugEditFormObject) {
detailInfo.value = { ...detail };
const { templateId } = detail;
const { templateId } = detailInfo.value;
//
isPlatformDefaultTemplate.value = detail.platformDefault;
// TAG
tags.value = detail.tags || [];
caseCount.value = detail.linkCaseCount;
const tmpObj = { status: detail.status };
if (detail.customFields && Array.isArray(detail.customFields)) {
caseCount.value = detailInfo.value.linkCaseCount;
const tmpObj = { status: detailInfo.value.status };
//
const customFieldsRes = await getTemplateById({
projectId: appStore.currentProjectId,
id: templateId,
fromStatusId: detail.status,
platformBugKey: detail.platformBugId,
});
currentCustomFields.value = customFieldsRes.customFields || [];
if (detailInfo.value.customFields && Array.isArray(detailInfo.value.customFields)) {
const MULTIPLE_TYPE = ['MULTIPLE_SELECT', 'MULTIPLE_INPUT', 'CHECKBOX', 'MULTIPLE_MEMBER'];
const SINGRADIO_TYPE = ['RADIO', 'SELECT', 'MEMBER'];
detail.customFields.forEach((item) => {
if (item.type === 'MULTIPLE_SELECT' || item.type === 'MULTIPLE_INPUT' || item.type === 'CHECKBOX') {
tmpObj[item.id] = JSON.parse(item.value);
} else if (item.type === 'INT') {
if (MULTIPLE_TYPE.includes(item.type)) {
const multipleOptions =
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || [];
//
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
if (item.type !== 'MULTIPLE_INPUT') {
const currentDefaultValue = optionsIds.filter((e: any) => JSON.parse(item.value).includes(e));
tmpObj[item.id] = currentDefaultValue;
} else {
tmpObj[item.id] = JSON.parse(item.value);
}
} else if (item.type === 'INT' || item.type === 'FLOAT') {
tmpObj[item.id] = Number(item.value);
} else if (item.type === 'CASCADER') {
const arr = JSON.parse(item.value);
if (arr && arr instanceof Array && arr.length > 0) {
tmpObj[item.id] = arr[arr.length - 1];
}
} else if (SINGRADIO_TYPE.includes(item.type)) {
const multipleOptions =
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || [];
//
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || '';
tmpObj[item.id] = currentDefaultValue;
} else {
tmpObj[item.id] = item.value;
}
@ -534,6 +580,13 @@
console.log(error);
}
}
async function handleUploadImage(file: File) {
const { data } = await editorUploadFile({
fileList: [file],
});
return data;
}
watch(
() => showDrawerVisible.value,
(val) => {
@ -542,11 +595,6 @@
}
}
);
watchEffect(() => {
if (props.detailIndex) {
activeTab.value = 'detail';
}
});
</script>
<style scoped lang="less">

View File

@ -151,7 +151,7 @@
<div class="min-w-[250px] overflow-auto">
<a-skeleton v-if="isLoading" :loading="isLoading" :animation="true">
<a-space direction="vertical" class="w-full" size="large">
<a-skeleton-line :rows="rowLength" :line-height="30" :line-spacing="30" />
<a-skeleton-line :rows="12" :line-height="30" :line-spacing="30" />
</a-space>
</a-skeleton>
<a-form v-else :model="form" layout="vertical">
@ -239,10 +239,12 @@
import useVisit from '@/hooks/useVisit';
import router from '@/router';
import { useAppStore } from '@/store';
import useUserStore from '@/store/modules/user';
import { downloadByteFile } from '@/utils';
import { scrollIntoView } from '@/utils/dom';
import { findParents, Option } from '@/utils/recursion';
import type { CustomFieldItem } from '@/models/bug-management';
import {
BugEditCustomField,
BugEditCustomFieldItem,
@ -304,7 +306,7 @@
const associatedDrawer = ref(false);
const loading = ref(false);
const acceptType = ref('none'); // -
const userStore = useUserStore();
const isEdit = computed(() => !!route.query.id && route.params.mode === 'edit');
const bugId = computed(() => route.query.id || '');
const isEditOrCopy = computed(() => !!bugId.value);
@ -364,25 +366,34 @@
//
const getFormRules = (arr: BugEditCustomField[]) => {
formRules.value = [];
const memberType = ['MEMBER', 'MULTIPLE_MEMBER'];
if (Array.isArray(arr) && arr.length) {
formRules.value = arr.map((item: any) => {
let initValue = item.defaultValue;
const initOptions = item.options;
if (memberType.includes(item.type)) {
if (item.defaultValue === 'CREATE_USER' || item.defaultValue.includes('CREATE_USER')) {
initValue = item.type === 'MEMBER' ? userStore.id : [userStore.id];
}
}
return {
type: item.type,
name: item.fieldId,
label: item.fieldName,
value: item.defaultValue,
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
value: initValue,
options: initOptions,
required: item.required as boolean,
platformPlaceHolder: item.platformPlaceHolder,
props: {
modelValue: item.defaultValue,
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
modelValue: initValue,
options: initOptions,
},
};
});
}
};
const currentCustomFields = ref<CustomFieldItem[]>([]);
const templateChange = async (v: SelectValue, request?: BugTemplateRequest) => {
if (v) {
try {
@ -392,6 +403,7 @@
param = { ...param, ...request };
}
const res = await getTemplateById(param);
currentCustomFields.value = res.customFields || [];
await getFormRules(res.customFields);
isLoading.value = false;
isPlatformDefaultTemplate.value = res.platformDefault;
@ -674,19 +686,39 @@
tmpObj = { status: res.status };
}
if (customFields && Array.isArray(customFields)) {
const MULTIPLE_TYPE = ['MULTIPLE_SELECT', 'MULTIPLE_INPUT', 'CHECKBOX', 'MULTIPLE_MEMBER'];
const SINGRADIO_TYPE = ['RADIO', 'SELECT', 'MEMBER'];
customFields.forEach((item) => {
if (item.id === 'status' && isCopy.value) {
// ,
tmpObj[item.id] = '';
} else if (item.type === 'MULTIPLE_SELECT' || item.type === 'MULTIPLE_INPUT' || item.type === 'CHECKBOX') {
tmpObj[item.id] = JSON.parse(item.value);
} else if (item.type === 'INT') {
//
} else if (MULTIPLE_TYPE.includes(item.type)) {
const multipleOptions =
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || [];
//
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
if (item.type !== 'MULTIPLE_INPUT') {
const currentDefaultValue = optionsIds.filter((e: any) => JSON.parse(item.value).includes(e));
tmpObj[item.id] = currentDefaultValue;
} else {
tmpObj[item.id] = JSON.parse(item.value);
}
} else if (item.type === 'INT' || item.type === 'FLOAT') {
tmpObj[item.id] = Number(item.value);
} else if (item.type === 'CASCADER') {
const arr = JSON.parse(item.value);
if (arr && arr instanceof Array && arr.length > 0) {
tmpObj[item.id] = arr[arr.length - 1];
}
//
} else if (SINGRADIO_TYPE.includes(item.type)) {
const multipleOptions =
currentCustomFields.value.find((filed: any) => item.id === filed.fieldId)?.options || [];
//
const optionsIds = (multipleOptions || []).map((e: any) => e.value);
const currentDefaultValue = optionsIds.find((e: any) => item.value === e) || '';
tmpObj[item.id] = currentDefaultValue;
} else {
tmpObj[item.id] = item.value;
}

View File

@ -226,8 +226,7 @@
import useTable from '@/components/pure/ms-table/useTable';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import BatchEditModal from './components/batchEditModal.vue';
import BugDetailDrawer from './components/bug-detail-drawer.vue';
// import BugDetailDrawer from './components/bug-detail-drawer.vue';
import TableFilter from '@/views/case-management/caseManagementFeature/components/tableFilter.vue';
import {
@ -264,6 +263,8 @@
const MsExportDrawer = defineAsyncComponent(() => import('@/components/pure/ms-export-drawer/index.vue'));
const DeleteModal = defineAsyncComponent(() => import('./components/deleteModal.vue'));
const MsBaseTable = defineAsyncComponent(() => import('@/components/pure/ms-table/base-table.vue'));
const BatchEditModal = defineAsyncComponent(() => import('./components/batchEditModal.vue'));
const BugDetailDrawer = defineAsyncComponent(() => import('./components/bug-detail-drawer.vue'));
const tableStore = useTableStore();
const appStore = useAppStore();

View File

@ -87,7 +87,7 @@
</MsButton>
</div>
</template>
<template #default>
<template #default="{ loading }">
<div
ref="wrapperRef"
class="wrapperRef bg-white"
@ -158,54 +158,61 @@
</template>
<template #second>
<div class="rightWrapper h-full p-[24px]">
<div class="mb-4 font-medium">{{ t('caseManagement.featureCase.basicInfo') }}</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnModule') }}</span>
<span class="w-[calc(100%-36%)]">
<a-tree-select
v-model="detailInfo.moduleId"
:data="caseTree"
class="w-full"
:allow-search="true"
:field-names="{
title: 'name',
key: 'id',
children: 'children',
}"
:tree-props="{
virtualListProps: {
height: 200,
},
}"
@change="handleChangeModule"
></a-tree-select>
</span>
</div>
<!-- 自定义字段开始 -->
<MsFormCreate
v-if="formRules.length"
ref="formCreateRef"
v-model:api="fApi"
v-model:form-item="formItem"
:form-rule="formRules"
class="w-full"
:option="options"
@change="changeHandler"
/>
<!-- 自定义字段结束 -->
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnCreateUser') }}</span>
<span class="value">{{ detailInfo?.createUserName }}</span>
</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnCreateTime') }}</span>
<span class="value">{{ dayjs(detailInfo?.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnTag') }}</span>
<span class="value">
<MsTag v-for="item of detailInfo.tags" :key="item"> {{ item }} </MsTag>
</span>
<a-skeleton v-if="loading" class="w-full" :loading="loading" :animation="true">
<a-space direction="vertical" class="w-[100%]" size="large">
<a-skeleton-line :rows="14" :line-height="30" :line-spacing="30" />
</a-space>
</a-skeleton>
<div v-else>
<div class="mb-4 font-medium">{{ t('caseManagement.featureCase.basicInfo') }}</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnModule') }}</span>
<span class="w-[calc(100%-36%)]">
<a-tree-select
v-model="detailInfo.moduleId"
:data="caseTree"
class="w-full"
:allow-search="true"
:field-names="{
title: 'name',
key: 'id',
children: 'children',
}"
:tree-props="{
virtualListProps: {
height: 200,
},
}"
@change="handleChangeModule"
></a-tree-select>
</span>
</div>
<!-- 自定义字段开始 -->
<MsFormCreate
v-if="formRules.length"
ref="formCreateRef"
v-model:api="fApi"
v-model:form-item="formItem"
:form-rule="formRules"
class="w-full"
:option="options"
@change="changeHandler"
/>
<!-- 自定义字段结束 -->
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnCreateUser') }}</span>
<span class="value">{{ detailInfo?.createUserName }}</span>
</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnCreateTime') }}</span>
<span class="value">{{ dayjs(detailInfo?.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div>
<div class="baseItem">
<span class="label"> {{ t('caseManagement.featureCase.tableColumnTag') }}</span>
<span class="value">
<MsTag v-for="item of detailInfo.tags" :key="item"> {{ item }} </MsTag>
</span>
</div>
</div>
</div>
</template>
@ -217,6 +224,7 @@
:is-active="isActive"
is-show-avatar
is-use-bottom
:upload-image="handleUploadImage"
@publish="publishHandler"
@cancel="cancelPublish"
/>
@ -248,6 +256,7 @@
import {
createCommentList,
deleteCaseRequest,
editorUploadFile,
followerCaseRequest,
getCaseDetail,
getCaseModuleTree,
@ -622,6 +631,13 @@
onMounted(() => {
settingDrawerRef.value.getTabModule();
});
async function handleUploadImage(file: File) {
const { data } = await editorUploadFile({
fileList: [file],
});
return data;
}
</script>
<style scoped lang="less">

View File

@ -695,7 +695,6 @@
const filterConfigList = ref<FilterFormItem[]>([]);
const searchCustomFields = ref<FilterFormItem[]>([]);
const scrollWidth = ref<number>(3400);
const memberOptions = ref<{ label: string; value: string }[]>([]);
const updateUserFilters = ref<string[]>([]);
const createUserFilters = ref<string[]>([]);

View File

@ -10,9 +10,15 @@
</div>
</div>
<div>
<div id="magnifier"></div>
<!-- 用例评论 -->
<div v-show="activeComment === 'caseComment'">
<MsComment :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdateOrAdd" />
<MsComment
:upload-image="handleUploadImage"
:comment-list="commentList"
@delete="handleDelete"
@update-or-add="handleUpdateOrAdd"
/>
<MsEmpty v-if="commentList.length === 0" />
</div>
@ -74,6 +80,7 @@
import {
addOrUpdateCommentList,
deleteCommentList,
editorUploadFile,
getCommentList,
getReviewCommentList,
} from '@/api/modules/case-management/featureCase';
@ -211,6 +218,13 @@
// }
// );
async function handleUploadImage(file: File) {
const { data } = await editorUploadFile({
fileList: [file],
});
return data;
}
onMounted(() => {
getAllCommentList();
});
@ -220,4 +234,14 @@
});
</script>
<style scoped></style>
<style scoped lang="less">
#magnifier {
position: absolute;
display: none;
width: 200px;
height: 200px;
border: 1px solid red;
background-size: contain;
pointer-events: none;
}
</style>

View File

@ -157,8 +157,8 @@
},
{
title: 'project.commonScript.createUser',
slotName: 'createUser',
dataIndex: 'createUser',
slotName: 'createUserName',
dataIndex: 'createUserName',
showInTable: true,
width: 200,
showDrag: true,
@ -278,7 +278,8 @@
async function saveHandler(form: AddOrUpdateCommonScript) {
try {
confirmLoading.value = true;
const { status } = form;
const { status, params } = form;
paramsList.value = JSON.parse(params);
const paramTableList = paramsList.value.slice(0, -1);
const paramsObj: AddOrUpdateCommonScript = {
...form,

View File

@ -53,7 +53,9 @@
</template>
<template #name="{ record }">
<div class="flex items-center">
<span v-if="record.enablePlatformDefault" class="one-line-text ml-2">{{ record.name }}</span>
<span
v-else
class="one-line-text ml-2 cursor-pointer text-[rgb(var(--primary-5))]"
@click="previewDetail(record.id)"
>{{ record.name }}</span
@ -237,7 +239,9 @@
const searchFiled = async () => {
try {
totalList.value = await getProjectTemplateList({ projectId: currentProjectId.value, scene });
const filterData = totalList.value.filter((item: OrdTemplateManagement) => item.name.includes(keyword.value));
const filterData: OrdTemplateManagement[] = totalList.value.filter((item: OrdTemplateManagement) =>
item.name.includes(keyword.value)
);
setProps({ data: filterData });
} catch (error) {
console.log(error);

View File

@ -676,35 +676,29 @@
.wrapper-preview {
display: flex;
height: 100%;
.preview-left {
width: 100%;
border-right: 1px solid var(--color-text-n8);
}
.preview-right {
padding-top: 8px;
width: 428px;
min-width: 428px;
.customWrapper {
position: relative;
margin-bottom: 4px;
border: 1px solid transparent;
border-radius: 6px;
@apply flex flex-col justify-between;
.form {
padding: 8px;
border: 1px solid transparent;
border-radius: 6px;
}
.form.activeStyle {
border-color: rgb(var(--primary-5));
background: var(--color-text-n9);
}
.action {
position: absolute;
top: -12px;
@ -713,29 +707,24 @@
background: white;
opacity: 0;
@apply flex items-center justify-end;
.actionList {
padding: 4px;
border-radius: 4px;
@apply flex items-center justify-center;
}
.required > .arco-checkbox {
padding: 2px 4px;
border-radius: 4px;
box-shadow: 0 4px 10px -1px rgba(100 100 102/ 15%);
}
}
&:hover {
border: 1px solid var(--color-text-n8);
background: var(--color-text-n9);
}
&:hover > .action {
opacity: 1;
}
&:hover > .action > .actionList {
color: rgb(var(--primary-5));
box-shadow: 0 4px 10px -1px rgba(100 100 102/ 15%);
@ -743,19 +732,16 @@
}
}
}
.hoverStyle {
.customWrapper:hover > .form {
border-color: var(--color-text-n8) !important;
}
}
.activeStyle {
.customWrapper:hover .form {
border-color: rgb(var(--primary-5));
}
}
:deep(.selfClass) {
margin-bottom: 0;
}
@ -787,7 +773,6 @@
border: 1px solid rgba(var(--primary-5));
background-color: var(--color-text-n9);
}
:deep(.apiFieldIdClass) {
margin-bottom: 0;
}

View File

@ -185,9 +185,13 @@
//
const showDateOrNumber = computed(() => {
if (getFieldType(fieldForm.value.type)[0]) {
selectFormat.value = getFieldType(fieldForm.value.type)[0]?.value;
if (fieldForm.value.type) return getFieldType(fieldForm.value.type);
// if (getFieldType(fieldForm.value.type)[0]) {
// selectFormat.value = getFieldType(fieldForm.value.type)[0]?.value;
// if (fieldForm.value.type) return getFieldType(fieldForm.value.type);
// }
selectFormat.value = getFieldType(fieldForm.value.type)[0]?.value;
if (fieldForm.value.type) {
return getFieldType(fieldForm.value.type);
}
});

View File

@ -75,16 +75,16 @@
@confirm="handleOk(record)"
>
<MsButton
v-if="!record.internal && hasAnyPermission(props.updatePermission)"
v-if="!record.templateRequired && hasAnyPermission(props.updatePermission)"
:disabled="record.internal"
class="!mr-0"
>{{ t('system.orgTemplate.edit') }}</MsButton
></MsPopConfirm
>
<a-divider v-if="!record.internal" class="h-[12px]" direction="vertical" />
<a-divider v-if="!record.templateRequired" class="h-[12px]" direction="vertical" />
<MsTableMoreAction
v-if="!record.internal"
v-if="!record.templateRequired"
v-permission="props.deletePermission"
:list="moreActions"
@select="(item) => handleMoreActionSelect(item, record)"