From e073d53d6ef88c118be2c52cf24c3c077c8e459a Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Mon, 8 Jan 2024 15:18:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=A1=B9=E7=9B=AE=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E8=84=9A=E6=9C=AC=E9=A1=B5=E9=9D=A2&?= =?UTF-8?q?=E5=AF=8C=E6=96=87=E6=9C=AC=E5=86=85=E5=AE=B9=E5=9B=9E=E6=98=BE?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/case-management/featureCase.ts | 5 + .../requrls/case-management/featureCase.ts | 2 + .../components/business/ms-comment/input.vue | 2 +- .../ms-remove-button/MsRemoveButton.vue | 20 +- .../pure/ms-rich-text/MsRichText.vue | 67 ++++-- .../extensions/mention/MentionList.vue | 4 +- .../extensions/mention/suggestion.ts | 3 +- frontend/src/enums/routeEnum.ts | 1 + frontend/src/enums/tableEnum.ts | 1 + frontend/src/locale/en-US/index.ts | 1 + frontend/src/locale/zh-CN/index.ts | 1 + .../models/projectManagement/commonScript.ts | 5 + .../routes/modules/projectManagement.ts | 11 + .../components/bugDetailTab.vue | 2 +- frontend/src/views/bug-management/edit.vue | 2 +- .../components/caseTemplateDetail.vue | 8 +- .../tabContent/tabBug/addDefectDrawer.vue | 2 +- .../tabDependency/preAndPostCaseDrawer.vue | 23 +- .../tabDependency/tabDependency.vue | 57 ++++- .../components/tabContent/tabDetail.vue | 12 +- .../caseManagementFeature/locale/en-US.ts | 2 + .../caseManagementFeature/locale/zh-CN.ts | 2 + .../components/addScriptDrawer.vue | 160 +++++++++++++ .../commonScript/components/scriptDefined.vue | 111 +++++++++ .../project-management/commonScript/index.vue | 226 ++++++++++++++++++ .../commonScript/locale/en-US.ts | 46 ++++ .../commonScript/locale/zh-CN.ts | 47 ++++ .../project-management/commonScript/utils.ts | 55 +++++ .../template/components/proTemplateDetail.vue | 2 +- .../components/caseTemplateLeftContent.vue | 2 +- .../components/defectTemplateLeftContent.vue | 2 +- .../template/components/templateDetail.vue | 2 +- .../template/components/workflowCard.vue | 2 +- .../pluginManager/components/uploadModel.vue | 1 - 34 files changed, 816 insertions(+), 73 deletions(-) create mode 100644 frontend/src/models/projectManagement/commonScript.ts create mode 100644 frontend/src/views/project-management/commonScript/components/addScriptDrawer.vue create mode 100644 frontend/src/views/project-management/commonScript/components/scriptDefined.vue create mode 100644 frontend/src/views/project-management/commonScript/index.vue create mode 100644 frontend/src/views/project-management/commonScript/locale/en-US.ts create mode 100644 frontend/src/views/project-management/commonScript/locale/zh-CN.ts create mode 100644 frontend/src/views/project-management/commonScript/utils.ts diff --git a/frontend/src/api/modules/case-management/featureCase.ts b/frontend/src/api/modules/case-management/featureCase.ts index 40581b168e..2a94fab6ec 100644 --- a/frontend/src/api/modules/case-management/featureCase.ts +++ b/frontend/src/api/modules/case-management/featureCase.ts @@ -9,6 +9,7 @@ import { BatchEditCaseUrl, BatchMoveCaseUrl, CancelAssociationDemandUrl, + cancelPreAndPostCaseUrl, checkFileIsUpdateUrl, CreateCaseModuleTreeUrl, CreateCaseUrl, @@ -309,4 +310,8 @@ export function getPrepositionRelation(data: TableQueryParams) { export function addPrepositionRelation(data: TableQueryParams) { return MSR.post({ url: `${AddDependOnRelationUrl}`, data }); } +// 取消依赖关系 +export function cancelPreOrPostCase(id: string) { + return MSR.get({ url: `${cancelPreAndPostCaseUrl}/${id}` }); +} export default {}; diff --git a/frontend/src/api/requrls/case-management/featureCase.ts b/frontend/src/api/requrls/case-management/featureCase.ts index 5afd8acba4..428a2a7d76 100644 --- a/frontend/src/api/requrls/case-management/featureCase.ts +++ b/frontend/src/api/requrls/case-management/featureCase.ts @@ -114,3 +114,5 @@ export const GetDependOnPageUrl = '/functional/case/relationship/page'; export const GetDependOnRelationUrl = '/functional/case/relationship/relate/page'; // 添加前后置关系 export const AddDependOnRelationUrl = '/functional/case/relationship/add'; +// 取消关联前后置关系 +export const cancelPreAndPostCaseUrl = '/functional/case/relationship/delete'; diff --git a/frontend/src/components/business/ms-comment/input.vue b/frontend/src/components/business/ms-comment/input.vue index c25baccb3c..1a960a530f 100644 --- a/frontend/src/components/business/ms-comment/input.vue +++ b/frontend/src/components/business/ms-comment/input.vue @@ -10,7 +10,7 @@
- +
{{ t('common.cancel') }} {{ t('common.publish') }} diff --git a/frontend/src/components/business/ms-remove-button/MsRemoveButton.vue b/frontend/src/components/business/ms-remove-button/MsRemoveButton.vue index 601ff531fa..81813f53ce 100644 --- a/frontend/src/components/business/ms-remove-button/MsRemoveButton.vue +++ b/frontend/src/components/business/ms-remove-button/MsRemoveButton.vue @@ -5,10 +5,11 @@ :sub-title-tip="props.subTitleTip" :loading="props.loading" :visible="currentVisible" + :ok-text="props.okText" @confirm="handleOk" @cancel="handleCancel" > - {{ t('common.remove') }} + {{ t(props.removeText) }} @@ -20,11 +21,18 @@ import { useI18n } from '@/hooks/useI18n'; - const props = defineProps<{ - title: string; - subTitleTip: string; - loading?: boolean; - }>(); + const props = withDefaults( + defineProps<{ + title: string; + subTitleTip: string; + loading?: boolean; + removeText?: string; + okText?: string; + }>(), + { + removeText: 'common.remove', + } + ); const emit = defineEmits<{ (e: 'ok'): void; diff --git a/frontend/src/components/pure/ms-rich-text/MsRichText.vue b/frontend/src/components/pure/ms-rich-text/MsRichText.vue index 4660acd012..1f28dc77a5 100644 --- a/frontend/src/components/pure/ms-rich-text/MsRichText.vue +++ b/frontend/src/components/pure/ms-rich-text/MsRichText.vue @@ -2,7 +2,7 @@ /** * * @name: MsRichText.vue - * @param {string} modelValue v-model绑定的值 + * @param {string} raw v-model绑定的值 * @return {string} 返回编辑器内容 * @description: 富文本编辑器 * @example: @@ -12,11 +12,14 @@ * import rehypeStringify from 'rehype-stringify'; * return unified().use(rehypeParse).use(rehypeFormat).use(rehypeStringify).processSync(content.value); */ + import { useDebounceFn, useLocalStorage } from '@vueuse/core'; + import useLocale from '@/locale/useLocale'; import '@halo-dev/richtext-editor/dist/style.css'; import suggestion from './extensions/mention/suggestion'; import { + Editor, ExtensionAudio, ExtensionBlockquote, ExtensionBold, @@ -57,19 +60,36 @@ ExtensionVideo, lowlight, RichTextEditor, - useEditor, } from '@halo-dev/richtext-editor'; import Mention from '@tiptap/extension-mention'; - const props = defineProps<{ - modelValue: string; + const props = withDefaults( + defineProps<{ + raw?: string; + uploadImage?: (file: File) => Promise; + }>(), + { + raw: '', + uploadImage: undefined, + } + ); + + const editor = shallowRef(); + + const emit = defineEmits<{ + (event: 'update:raw', value: string): void; + (event: 'update', value: string): void; }>(); - const emit = defineEmits(['update:model-value']); - const content = ref(''); + // debounce OnUpdate + const debounceOnUpdate = useDebounceFn(() => { + const html = `${editor.value?.getHTML()}`; + emit('update:raw', html); + emit('update', html); + }, 250); - const editor = useEditor({ - content: content.value, + editor.value = new Editor({ + content: props.raw, extensions: [ ExtensionBlockquote, ExtensionBold, @@ -92,6 +112,8 @@ ExtensionStrike, ExtensionText, ExtensionImage.configure({ + inline: true, + allowBase64: false, HTMLAttributes: { loading: 'lazy', }, @@ -132,31 +154,38 @@ HTMLAttributes: { class: 'mention', }, + // TODO第一版本先按照初始化评论的人 不加userMap + renderLabel({ options, node }) { + return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`; + // return `${options.suggestion.char}${userMap[node.attrs.id]}`; + }, suggestion, }), ], + autofocus: 'start', onUpdate: () => { - content.value = `${editor.value?.getHTML()}`; + debounceOnUpdate(); }, }); const { currentLocale } = useLocale(); const locale = computed(() => currentLocale.value as 'zh-CN' | 'en-US'); + watch( - () => props.modelValue, - (val) => { - if (val) { - content.value = val; + () => props.raw, + () => { + if (props.raw !== editor.value?.getHTML()) { + editor.value?.commands.setContent(props.raw); } + }, + { + immediate: true, } ); - watch( - () => content.value, - () => { - emit('update:model-value', `${editor.value?.getHTML()}`); - } - ); + onBeforeUnmount(() => { + editor.value?.destroy(); + }); + + diff --git a/frontend/src/views/project-management/commonScript/components/scriptDefined.vue b/frontend/src/views/project-management/commonScript/components/scriptDefined.vue new file mode 100644 index 0000000000..f8af6ceeee --- /dev/null +++ b/frontend/src/views/project-management/commonScript/components/scriptDefined.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/frontend/src/views/project-management/commonScript/index.vue b/frontend/src/views/project-management/commonScript/index.vue new file mode 100644 index 0000000000..99289e564f --- /dev/null +++ b/frontend/src/views/project-management/commonScript/index.vue @@ -0,0 +1,226 @@ + + + + + diff --git a/frontend/src/views/project-management/commonScript/locale/en-US.ts b/frontend/src/views/project-management/commonScript/locale/en-US.ts new file mode 100644 index 0000000000..2f5da3ab2d --- /dev/null +++ b/frontend/src/views/project-management/commonScript/locale/en-US.ts @@ -0,0 +1,46 @@ +export default { + 'project.commonScript.searchByNameAndId': 'Search by name', + 'project.commonScript.addPublicScript': 'Add public Script', + 'project.commonScript.name': 'Name', + 'project.commonScript.description': 'Description', + 'project.commonScript.enable': 'Enable', + 'project.commonScript.createUser': 'CreateUser', + 'project.commonScript.createTime': 'CreateTime', + 'project.commonScript.updateTime': 'UpdateTime', + 'project.commonScript.tableColumnActions': 'Operation', + 'project.commonScript.tags': 'tags', + 'project.commonScript.deleteTitleTip': 'Confirm delete {name} script?', + 'project.commonScript.deleteTitleContent': + 'After deletion, the script may cause test cases that refer to it to fail, so be careful!', + 'project.commonScript.preview': 'Preview', + 'project.commonScript.testsPass': 'Pass the test', + 'project.commonScript.draft': 'draft', + 'project.commonScript.publicScriptName': 'Common script name', + 'project.commonScript.publicScriptNameNotEmpty': 'The public script name cannot be empty', + 'project.commonScript.pleaseEnterScriptName': 'Please enter a script name', + 'project.commonScript.scriptEnabled': 'Script state', + 'project.commonScript.enterContentAddTags': 'Enter the content to add the label directly', + 'project.commonScript.inputParams': 'In parameter', + 'project.commonScript.commonScript': 'Common script', + 'project.commonScript.executionResult': 'Execution result', + 'project.commonScript.scriptTest': 'test', + 'project.commonScript.codeSnippet': 'Code snippet', + 'project.commonScript.pleaseSelected': 'Please select', + 'project.commonScript.formatting': 'formatting', + 'project.commonScript.undo': 'cancel', + 'project.commonScript.clear': 'clear', + 'code_segment': { + importApiTest: 'Import from API definition', + newApiTest: 'New API test[JSON]', + }, + 'processor': { + codeTemplateGetVariable: 'Get Variable', + codeTemplateSetVariable: 'Set Variable', + codeTemplateGetResponseHeader: 'Get Response Header', + codeTemplateGetResponseCode: 'Get Response Code', + codeTemplateGetResponseResult: 'Get Response Result', + paramEnvironmentSetGlobalVariable: 'Set run environment param', + insertPublicScript: 'Insert the public script', + terminationTest: 'Termination test', + }, +}; diff --git a/frontend/src/views/project-management/commonScript/locale/zh-CN.ts b/frontend/src/views/project-management/commonScript/locale/zh-CN.ts new file mode 100644 index 0000000000..02ef2ca116 --- /dev/null +++ b/frontend/src/views/project-management/commonScript/locale/zh-CN.ts @@ -0,0 +1,47 @@ +export default { + 'project.commonScript.searchByNameAndId': '通过名称搜索', + 'project.commonScript.addPublicScript': '添加公共脚本', + 'project.commonScript.name': '名称', + 'project.commonScript.description': '描述', + 'project.commonScript.enable': '状态', + 'project.commonScript.createUser': '创建人', + 'project.commonScript.createTime': '创建时间', + 'project.commonScript.updateTime': '更新时间', + 'project.commonScript.tableColumnActions': '操作', + 'project.commonScript.tags': '标签', + 'project.commonScript.deleteTitleTip': '确认删除 {name} 脚本吗?', + 'project.commonScript.deleteTitleContent': '删除后,脚本可能会导致引用该脚本的测试用例执行失败,请谨慎操作!', + 'project.commonScript.preview': '预览', + 'project.commonScript.testsPass': '测试通过', + 'project.commonScript.draft': '草稿', + 'project.commonScript.publicScriptName': '公共脚本名称', + 'project.commonScript.publicScriptNameNotEmpty': '公共脚本名称', + 'project.commonScript.pleaseEnterScriptName': '请输入脚本名称', + 'project.commonScript.scriptEnabled': '脚本状态', + 'project.commonScript.enterContentAddTags': '输入内容后回车可直接添加标签', + 'project.commonScript.inputParams': '入参', + 'project.commonScript.commonScript': '公共脚本', + 'project.commonScript.executionResult': '执行结果', + 'project.commonScript.scriptTest': '测试', + 'project.commonScript.codeSnippet': '代码片段', + 'project.commonScript.pleaseSelected': '请选择', + 'project.commonScript.formatting': '格式化', + 'project.commonScript.undo': '撤销', + 'project.commonScript.clear': '清空', + 'project': { + code_segment: { + importApiTest: '从API定义导入', + newApiTest: '新API测试(JSON)', + }, + processor: { + codeTemplateGetVariable: '获取变量', + codeTemplateSetVariable: '设置变量', + codeTemplateGetResponseHeader: '获取响应头', + codeTemplateGetResponseCode: '获取响应码', + codeTemplateGetResponseResult: '获取响应结果', + paramEnvironmentSetGlobalVariable: '设置环境参数', + insertPublicScript: '插入公共脚本', + terminationTest: '终止测试', + }, + }, +}; diff --git a/frontend/src/views/project-management/commonScript/utils.ts b/frontend/src/views/project-management/commonScript/utils.ts new file mode 100644 index 0000000000..867c07a201 --- /dev/null +++ b/frontend/src/views/project-management/commonScript/utils.ts @@ -0,0 +1,55 @@ +import { useI18n } from '@/hooks/useI18n'; + +import type { CommonScriptMenu } from '@/models/projectManagement/commonScript'; + +const { t } = useI18n(); + +export const SCRIPT_MENU: CommonScriptMenu[] = [ + { + title: t('project.code_segment.importApiTest'), + value: 'api_definition', + command: 'api_definition', + }, + { + title: t('project.code_segment.newApiTest'), + value: 'new_api_request', + command: 'new_api_request', + }, + { + title: t('project.processor.codeTemplateGetVariable'), + value: 'vars.get("variable_name")', + }, + { + title: t('project.processor.codeTemplateSetVariable'), + value: 'vars.put("variable_name", "variable_value")', + }, + { + title: t('project.processor.codeTemplateGetResponseHeader'), + value: 'prev.getResponseHeaders()', + }, + { + title: t('project.processor.codeTemplateGetResponseCode'), + value: 'prev.getResponseCode()', + }, + { + title: t('project.processor.codeTemplateGetResponseResult'), + value: 'prev.getResponseDataAsString()', + }, + { + title: t('project.processor.paramEnvironmentSetGlobalVariable'), + value: `vars.put(\${__metersphere_env_id}+"key","value"); + vars.put("key","value")`, + }, + { + title: t('project.processor.insertPublicScript'), + value: 'custom_function', + command: 'custom_function', + }, + { + title: t('project.processor.terminationTest'), + value: 'terminal_function', + command: 'terminal_function', + }, +]; + +export default {}; diff --git a/frontend/src/views/project-management/template/components/proTemplateDetail.vue b/frontend/src/views/project-management/template/components/proTemplateDetail.vue index 794a65b7b6..5c8051c91c 100644 --- a/frontend/src/views/project-management/template/components/proTemplateDetail.vue +++ b/frontend/src/views/project-management/template/components/proTemplateDetail.vue @@ -101,7 +101,7 @@ asterisk-position="end" class="max-w-[732px]" > - + diff --git a/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue b/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue index 265451e8d8..78cc2e3ffe 100644 --- a/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue +++ b/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue @@ -17,7 +17,7 @@ > - +
diff --git a/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue b/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue index 4adecf467d..6c3e3a9a6c 100644 --- a/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue +++ b/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue @@ -17,7 +17,7 @@ > - +
diff --git a/frontend/src/views/setting/organization/template/components/templateDetail.vue b/frontend/src/views/setting/organization/template/components/templateDetail.vue index f5c7b5a8f2..1a6a6bbbd1 100644 --- a/frontend/src/views/setting/organization/template/components/templateDetail.vue +++ b/frontend/src/views/setting/organization/template/components/templateDetail.vue @@ -101,7 +101,7 @@ asterisk-position="end" class="max-w-[732px]" > - + diff --git a/frontend/src/views/setting/organization/template/components/workflowCard.vue b/frontend/src/views/setting/organization/template/components/workflowCard.vue index 5fe9abbf4f..54c5c0fa76 100644 --- a/frontend/src/views/setting/organization/template/components/workflowCard.vue +++ b/frontend/src/views/setting/organization/template/components/workflowCard.vue @@ -281,7 +281,7 @@ } -