feat(项目管理): 公共脚本页面&富文本内容回显调整
This commit is contained in:
parent
d086de31a6
commit
e073d53d6e
|
@ -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<ModulesTreeType[]>({ url: `${AddDependOnRelationUrl}`, data });
|
||||
}
|
||||
// 取消依赖关系
|
||||
export function cancelPreOrPostCase(id: string) {
|
||||
return MSR.get({ url: `${cancelPreAndPostCaseUrl}/${id}` });
|
||||
}
|
||||
export default {};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="w-full items-center">
|
||||
<a-input v-if="!isActive" class="w-full" @click="isActive = true"></a-input>
|
||||
<div v-else class="flex flex-col justify-between">
|
||||
<MsRichText v-model="currentContent" class="w-full" />
|
||||
<MsRichText v-model:raw="currentContent" class="w-full" />
|
||||
<div class="mt-4 flex flex-row justify-end gap-[12px]">
|
||||
<a-button @click="cancelClick">{{ t('common.cancel') }}</a-button>
|
||||
<a-button type="primary" :disabled="!currentContent" @click="publish">{{ t('common.publish') }}</a-button>
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
:sub-title-tip="props.subTitleTip"
|
||||
:loading="props.loading"
|
||||
:visible="currentVisible"
|
||||
:ok-text="props.okText"
|
||||
@confirm="handleOk"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<MsButton @click="showPopover">{{ t('common.remove') }}</MsButton>
|
||||
<MsButton @click="showPopover">{{ t(props.removeText) }}</MsButton>
|
||||
</MsPopconfirm>
|
||||
</template>
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<any>;
|
||||
}>(),
|
||||
{
|
||||
raw: '',
|
||||
uploadImage: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
const editor = shallowRef<Editor>();
|
||||
|
||||
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();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
const item = props.items[index];
|
||||
|
||||
if (item) {
|
||||
props.command({ id: `${item.name}(${item.email})` } as any);
|
||||
props.command({ id: item.id, label: `${item.name}` } as any);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@
|
|||
function selectItem(index: any) {
|
||||
const item = props.items[index];
|
||||
if (item) {
|
||||
props.command({ id: `${item.name}(${item.email})` } as any);
|
||||
props.command({ id: item.id, label: `${item.name}` } as any);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import useAppStore from '@/store/modules/app';
|
|||
|
||||
import type { UserListItem } from '@/models/setting/user';
|
||||
|
||||
import { VueRenderer } from '@halo-dev/richtext-editor';
|
||||
import { Extension, VueRenderer } from '@halo-dev/richtext-editor';
|
||||
import Suggestion from '@tiptap/suggestion';
|
||||
import type { Instance } from 'tippy.js';
|
||||
import tippy from 'tippy.js';
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ export enum ProjectManagementRouteEnum {
|
|||
PROJECT_MANAGEMENT = 'projectManagement',
|
||||
PROJECT_MANAGEMENT_FILE_MANAGEMENT = 'projectManagementFileManageMent',
|
||||
PROJECT_MANAGEMENT_MESSAGE_MANAGEMENT = 'projectManagementMessageManagement',
|
||||
PROJECT_MANAGEMENT_COMMON_SCRIPT = 'projectManagementCommonScript',
|
||||
PROJECT_MANAGEMENT_MESSAGE_MANAGEMENT_EDIT = 'projectManagementMessageManagementEdit',
|
||||
PROJECT_MANAGEMENT_LOG = 'projectManagementLog',
|
||||
PROJECT_MANAGEMENT_PERMISSION = 'projectManagementPermission',
|
||||
|
|
|
@ -23,6 +23,7 @@ export enum TableKeyEnum {
|
|||
ORGANIZATION_TEMPLATE_MANAGEMENT_STEP = 'organizationTemplateManagementStep',
|
||||
ORGANIZATION_PROJECT = 'organizationProject',
|
||||
ORGANIZATION_PROJECT_USER_DRAWER = 'organizationProjectUserDrawer',
|
||||
ORGANIZATION_PROJECT_COMMON_SCRIPT = 'projectManagementCommonScript',
|
||||
FILE_MANAGEMENT_FILE = 'fileManagementFile',
|
||||
FILE_MANAGEMENT_CASE = 'fileManagementCase',
|
||||
FILE_MANAGEMENT_CASE_RECYCLE = 'fileManagementCaseRecycle',
|
||||
|
|
|
@ -30,6 +30,7 @@ export default {
|
|||
'menu.projectManagement': 'Project',
|
||||
'menu.projectManagement.fileManagement': 'File Management',
|
||||
'menu.projectManagement.messageManagement': 'Message Management',
|
||||
'menu.projectManagement.commonScript': 'Common Script',
|
||||
'menu.projectManagement.messageManagementEdit': 'Update Template',
|
||||
'menu.caseManagement.featureCase': 'Feature Case',
|
||||
'menu.caseManagement.featureCaseRecycle': 'Recycle',
|
||||
|
|
|
@ -33,6 +33,7 @@ export default {
|
|||
'menu.projectManagement.log': '日志',
|
||||
'menu.projectManagement.fileManagement': '文件管理',
|
||||
'menu.projectManagement.messageManagement': '消息管理',
|
||||
'menu.projectManagement.commonScript': '公共脚本',
|
||||
'menu.projectManagement.messageManagementEdit': '更新模板',
|
||||
'menu.caseManagement.featureCase': '功能用例',
|
||||
'menu.caseManagement.featureCaseRecycle': '回收站',
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export interface CommonScriptMenu {
|
||||
title: string;
|
||||
value: string;
|
||||
command?: string;
|
||||
}
|
|
@ -220,6 +220,17 @@ const ProjectManagement: AppRouteRecordRaw = {
|
|||
],
|
||||
},
|
||||
},
|
||||
// 公共脚本
|
||||
{
|
||||
path: 'commonScript',
|
||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_COMMON_SCRIPT,
|
||||
component: () => import('@/views/project-management/commonScript/index.vue'),
|
||||
meta: {
|
||||
locale: 'menu.projectManagement.commonScript',
|
||||
roles: ['*'],
|
||||
isTopMenu: true,
|
||||
},
|
||||
},
|
||||
// 项目日志
|
||||
{
|
||||
path: 'log',
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div class="mt-[8]" :class="{ 'max-h-[260px]': contentEditAble }">
|
||||
<MsRichText
|
||||
v-if="form.content"
|
||||
v-model:model-value="form.content"
|
||||
v-model:raw="form.content"
|
||||
:disabled="!contentEditAble"
|
||||
:placeholder="t('bugManagement.edit.contentPlaceholder')"
|
||||
/>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<a-input v-model="form.title" :max-length="255" show-word-limit />
|
||||
</a-form-item>
|
||||
<a-form-item field="description" :label="t('bugManagement.edit.content')">
|
||||
<MsRichText v-model="form.description" />
|
||||
<MsRichText v-model:raw="form.description" />
|
||||
</a-form-item>
|
||||
<a-form-item field="attachment" :label="t('bugManagement.edit.file')">
|
||||
<div class="flex flex-col">
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="precondition" :label="t('system.orgTemplate.precondition')" asterisk-position="end">
|
||||
<MsRichText v-model:model-value="form.prerequisite" />
|
||||
<MsRichText v-model:raw="form.prerequisite" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="step"
|
||||
|
@ -48,17 +48,17 @@
|
|||
<AddStep v-model:step-list="stepData" :is-disabled="false" />
|
||||
</div>
|
||||
<!-- 文本描述 -->
|
||||
<MsRichText v-else v-model:modelValue="form.textDescription" />
|
||||
<MsRichText v-else v-model:raw="form.textDescription" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="form.caseEditType === 'TEXT'"
|
||||
field="remark"
|
||||
:label="t('caseManagement.featureCase.expectedResult')"
|
||||
>
|
||||
<MsRichText v-model:modelValue="form.expectedResult" />
|
||||
<MsRichText v-model:raw="form.expectedResult" />
|
||||
</a-form-item>
|
||||
<a-form-item field="remark" :label="t('caseManagement.featureCase.remark')">
|
||||
<MsRichText v-model:modelValue="form.description" />
|
||||
<MsRichText v-model:raw="form.description" />
|
||||
</a-form-item>
|
||||
<AddAttachment @change="handleChange" @link-file="associatedFile" @upload="beforeUpload" />
|
||||
</a-form>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<a-input v-model="form.title" :max-length="255" show-word-limit />
|
||||
</a-form-item>
|
||||
<a-form-item :label="t('bugManagement.edit.content')">
|
||||
<MsRichText v-model="form.description" />
|
||||
<MsRichText v-model:raw="form.description" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</MsDrawer>
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
(e: 'success', val: string[]): void;
|
||||
(e: 'success'): void;
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
|
@ -273,6 +273,7 @@
|
|||
},
|
||||
showSetting: false,
|
||||
selectable: true,
|
||||
heightUsed: 300,
|
||||
showSelectAll: true,
|
||||
},
|
||||
(record) => {
|
||||
|
@ -332,21 +333,16 @@
|
|||
moduleLoading.value = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param 获取回收站模块
|
||||
*/
|
||||
|
||||
// 回收站模块树count参数
|
||||
const emitTableParams: CaseModuleQueryParams = {
|
||||
keyword: keyword.value,
|
||||
moduleIds: [],
|
||||
projectId: currentProjectId.value,
|
||||
current: propsRes.value.msPagination?.current,
|
||||
pageSize: propsRes.value.msPagination?.pageSize,
|
||||
};
|
||||
|
||||
async function getModulesCount() {
|
||||
try {
|
||||
const emitTableParams: CaseModuleQueryParams = {
|
||||
keyword: keyword.value,
|
||||
moduleIds: [],
|
||||
projectId: currentProjectId.value,
|
||||
current: propsRes.value.msPagination?.current,
|
||||
pageSize: propsRes.value.msPagination?.pageSize,
|
||||
};
|
||||
modulesCount.value = await getCaseModulesCounts(emitTableParams);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
@ -401,6 +397,7 @@
|
|||
};
|
||||
await addPrepositionRelation(params);
|
||||
Message.success(t('common.addSuccess'));
|
||||
emit('success');
|
||||
innerVisible.value = false;
|
||||
resetSelector();
|
||||
} catch (error) {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<a-button v-if="showType === 'preposition'" class="mr-3" type="primary" @click="addCase('preposition')">
|
||||
<a-button v-if="showType === 'preposition'" class="mr-3" type="primary" @click="addCase">
|
||||
{{ t('caseManagement.featureCase.addPresetCase') }}
|
||||
</a-button>
|
||||
<a-button v-else type="primary" @click="addCase('postPosition')">
|
||||
<a-button v-else type="primary" @click="addCase">
|
||||
{{ t('caseManagement.featureCase.addPostCase') }}
|
||||
</a-button>
|
||||
</div>
|
||||
|
@ -28,33 +28,50 @@
|
|||
</div>
|
||||
<ms-base-table ref="tableRef" v-bind="propsRes" v-on="propsEvent">
|
||||
<template #operation="{ record }">
|
||||
<MsButton @click="cancelDependency(record)">{{ t('caseManagement.featureCase.cancelDependency') }}</MsButton>
|
||||
<MsRemoveButton
|
||||
position="br"
|
||||
ok-text="common.confirm"
|
||||
remove-text="caseManagement.featureCase.cancelDependency"
|
||||
:title="t('caseManagement.featureCase.cancelDependencyTip', { name: characterLimit(record.name) })"
|
||||
:sub-title-tip="t('caseManagement.featureCase.cancelDependencyContent')"
|
||||
:loading="cancelLoading"
|
||||
@ok="cancelDependency(record)"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="(keyword || '').trim() === ''" #empty>
|
||||
<div class="flex items-center justify-center">
|
||||
{{ t('caseManagement.caseReview.tableNoData') }}
|
||||
<MsButton class="ml-[8px]" @click="addCase('preposition')">
|
||||
<MsButton class="ml-[8px]" @click="addCase">
|
||||
{{ t('caseManagement.featureCase.addPresetCase') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
</ms-base-table>
|
||||
<PreAndPostCaseDrawer ref="drawerRef" v-model:visible="showDrawer" :show-type="showType" :case-id="props.caseId" />
|
||||
<PreAndPostCaseDrawer
|
||||
ref="drawerRef"
|
||||
v-model:visible="showDrawer"
|
||||
:show-type="showType"
|
||||
:case-id="props.caseId"
|
||||
@success="successHandler"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
||||
import PreAndPostCaseDrawer from './preAndPostCaseDrawer.vue';
|
||||
|
||||
import { getDependOnCase } from '@/api/modules/case-management/featureCase';
|
||||
import { cancelPreOrPostCase, getDependOnCase } from '@/api/modules/case-management/featureCase';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useAppStore } from '@/store';
|
||||
import { characterLimit } from '@/utils';
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
|
@ -88,8 +105,8 @@
|
|||
},
|
||||
{
|
||||
title: 'caseManagement.featureCase.tableColumnVersion',
|
||||
slotName: 'defectState',
|
||||
dataIndex: 'defectState',
|
||||
slotName: 'versionName',
|
||||
dataIndex: 'versionName',
|
||||
showInTable: true,
|
||||
showTooltip: true,
|
||||
width: 300,
|
||||
|
@ -97,8 +114,8 @@
|
|||
},
|
||||
{
|
||||
title: 'caseManagement.featureCase.tableColumnCreateUser',
|
||||
slotName: 'createUser',
|
||||
dataIndex: 'createUser',
|
||||
slotName: 'userName',
|
||||
dataIndex: 'userName',
|
||||
showInTable: true,
|
||||
showTooltip: true,
|
||||
width: 300,
|
||||
|
@ -124,8 +141,20 @@
|
|||
enableDrag: true,
|
||||
});
|
||||
|
||||
const cancelLoading = ref<boolean>(false);
|
||||
// 取消依赖
|
||||
function cancelDependency(record: any) {}
|
||||
async function cancelDependency(record: any) {
|
||||
cancelLoading.value = true;
|
||||
try {
|
||||
await cancelPreOrPostCase(record.id);
|
||||
Message.success(t('caseManagement.featureCase.cancelFollowSuccess'));
|
||||
loadList();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
cancelLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getParams() {
|
||||
setLoadListParams({
|
||||
|
@ -139,11 +168,15 @@
|
|||
const showDrawer = ref<boolean>(false);
|
||||
const drawerRef = ref();
|
||||
// 添加前后置用例
|
||||
function addCase(type: string) {
|
||||
function addCase() {
|
||||
showDrawer.value = true;
|
||||
drawerRef.value.initModules();
|
||||
}
|
||||
|
||||
function successHandler() {
|
||||
loadList();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => showType.value,
|
||||
() => {
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
}}</a-button
|
||||
></span
|
||||
>
|
||||
<MsRichText v-if="isEditPreposition" v-model:model-value="detailForm.prerequisite" class="mt-2" />
|
||||
<div v-else class="text-[var(--color-text-3)]" v-html="detailForm?.prerequisite || '-'"></div>
|
||||
<MsRichText v-if="isEditPreposition" v-model:raw="detailForm.prerequisite" class="mt-2" />
|
||||
<div v-else v-dompurify-html="detailForm?.prerequisite || '-'" class="text-[var(--color-text-3)]"></div>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="step"
|
||||
|
@ -50,7 +50,7 @@
|
|||
<!-- 文本描述 -->
|
||||
<MsRichText
|
||||
v-if="detailForm.caseEditType === 'TEXT' && isEditPreposition"
|
||||
v-model:modelValue="detailForm.textDescription"
|
||||
v-model:raw="detailForm.textDescription"
|
||||
/>
|
||||
<div v-if="detailForm.caseEditType === 'TEXT' && !isEditPreposition">{{
|
||||
detailForm.textDescription || '-'
|
||||
|
@ -63,13 +63,13 @@
|
|||
>
|
||||
<MsRichText
|
||||
v-if="detailForm.caseEditType === 'TEXT' && isEditPreposition"
|
||||
v-model:modelValue="detailForm.expectedResult"
|
||||
v-model:raw="detailForm.expectedResult"
|
||||
/>
|
||||
<div v-else class="text-[var(--color-text-3)]" v-html="detailForm.description || '-'"></div>
|
||||
</a-form-item>
|
||||
<a-form-item field="remark" :label="t('caseManagement.featureCase.remark')">
|
||||
<MsRichText v-if="isEditPreposition" v-model:modelValue="detailForm.description" />
|
||||
<div v-else class="text-[var(--color-text-3)]" v-html="detailForm.description || '-'"></div>
|
||||
<MsRichText v-if="isEditPreposition" v-model:raw="detailForm.description" />
|
||||
<div v-else v-dompurify-html="detailForm.description || '-'" class="text-[var(--color-text-3)]"></div>
|
||||
</a-form-item>
|
||||
<div v-if="isEditPreposition" class="flex justify-end">
|
||||
<a-button type="secondary" @click="handleCancel">{{ t('common.cancel') }}</a-button>
|
||||
|
|
|
@ -244,4 +244,6 @@ export default {
|
|||
'caseManagement.featureCase.fileIsUpdated': 'File is updated',
|
||||
'caseManagement.featureCase.selectTransferDirectory': 'Please select the transfer directory',
|
||||
'caseManagement.featureCase.quicklyCreateDefectSuccess': 'Quick bug creation success',
|
||||
'caseManagement.featureCase.cancelDependencyTip': 'Confirm cancel dependencies?',
|
||||
'caseManagement.featureCase.cancelDependencyContent': 'Cancel after impact test plan related statistics',
|
||||
};
|
||||
|
|
|
@ -239,4 +239,6 @@ export default {
|
|||
'caseManagement.featureCase.fileIsUpdated': '当前文件已更新',
|
||||
'caseManagement.featureCase.selectTransferDirectory': '请选择转存目录',
|
||||
'caseManagement.featureCase.quicklyCreateDefectSuccess': '快速创建缺陷成功',
|
||||
'caseManagement.featureCase.cancelDependencyTip': '确认取消依赖关系吗?',
|
||||
'caseManagement.featureCase.cancelDependencyContent': '取消后,影响测试计划相关统计',
|
||||
};
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<template>
|
||||
<MsDrawer
|
||||
v-model:visible="showScriptDrawer"
|
||||
:title="t('ms.case.associate.title')"
|
||||
:width="768"
|
||||
:footer="false"
|
||||
unmount-on-close
|
||||
>
|
||||
<a-form ref="formRef" :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
field="name"
|
||||
:label="t('project.commonScript.publicScriptName')"
|
||||
:rules="[{ required: true, message: t('project.commonScript.publicScriptNameNotEmpty') }]"
|
||||
>
|
||||
<a-input
|
||||
v-model="form.name"
|
||||
:max-length="255"
|
||||
show-word-limit
|
||||
:placeholder="t('project.commonScript.pleaseEnterScriptName')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="enable" :label="t('project.commonScript.scriptEnabled')">
|
||||
<a-select class="max-w-[396px]" :placeholder="t('project.commonScript.scriptEnabled')">
|
||||
<a-option>{{ t('project.commonScript.draft') }}</a-option>
|
||||
<a-option>{{ t('project.commonScript.testsPass') }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="description" :label="t('system.organization.description')">
|
||||
<a-textarea
|
||||
v-model="form.description"
|
||||
:placeholder="t('system.organization.descriptionPlaceholder')"
|
||||
allow-clear
|
||||
:auto-size="{ minRows: 1 }"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="tags" :label="t('system.organization.description')">
|
||||
<a-input-tag :placeholder="t('project.commonScript.enterContentAddTags')" allow-clear />
|
||||
</a-form-item>
|
||||
<a-form-item field="inputParameters" :label="t('project.commonScript.inputParams')">
|
||||
<ms-base-table v-bind="propsRes" ref="tableRef" no-disable v-on="propsEvent"> </ms-base-table>
|
||||
</a-form-item>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<a-radio-group v-model:model-value="scriptType" type="button" size="small">
|
||||
<a-radio value="commonScript">{{ t('project.commonScript.commonScript') }}</a-radio>
|
||||
<a-radio value="executionResult">{{ t('project.commonScript.executionResult') }}</a-radio>
|
||||
</a-radio-group>
|
||||
<a-button type="outline">{{ t('project.commonScript.scriptTest') }}</a-button>
|
||||
</div>
|
||||
<ScriptDefined v-if="scriptType === 'commonScript'" />
|
||||
<div v-else>
|
||||
<MsCodeEditor
|
||||
v-model:model-value="executionResultValue"
|
||||
title=""
|
||||
width="100%"
|
||||
height="calc(100vh - 155px)"
|
||||
theme="MS-text"
|
||||
:read-only="false"
|
||||
:show-full-screen="false"
|
||||
:show-theme-change="false"
|
||||
/>
|
||||
</div>
|
||||
</a-form>
|
||||
</MsDrawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import ScriptDefined from './scriptDefined.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:visible']);
|
||||
|
||||
const showScriptDrawer = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:visible', val);
|
||||
},
|
||||
});
|
||||
|
||||
const initForm = {
|
||||
name: '',
|
||||
description: '',
|
||||
};
|
||||
|
||||
const form = ref({ ...initForm });
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: '参数名称',
|
||||
slotName: 'name',
|
||||
dataIndex: 'name',
|
||||
showTooltip: true,
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
title: '是否必填',
|
||||
slotName: 'required',
|
||||
dataIndex: 'required',
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
title: '参数值',
|
||||
dataIndex: 'tags',
|
||||
slotName: 'tags',
|
||||
showTooltip: true,
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
slotName: 'desc',
|
||||
dataIndex: 'desc',
|
||||
showTooltip: true,
|
||||
},
|
||||
];
|
||||
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
|
||||
() =>
|
||||
Promise.resolve({
|
||||
list: [],
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 2,
|
||||
}),
|
||||
{
|
||||
columns,
|
||||
tableKey: TableKeyEnum.FILE_MANAGEMENT_FILE,
|
||||
showSetting: false,
|
||||
scroll: { x: '100%' },
|
||||
heightUsed: 300,
|
||||
},
|
||||
(item) => {
|
||||
return {
|
||||
...item,
|
||||
tags: item.tags?.map((e: string) => ({ id: e, name: e })) || [],
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const scriptType = ref<'commonScript' | 'executionResult'>('commonScript');
|
||||
|
||||
const executionResultValue = ref('');
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -0,0 +1,111 @@
|
|||
<template>
|
||||
<div class="w-full bg-[var(--color-bg-3)] p-4 pb-0">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<MsTag class="!mr-2" theme="outline">
|
||||
<template #icon><icon-undo class="mr-1 text-[16px] text-[var(--color-text-4)]" /> </template>
|
||||
{{ t('project.commonScript.undo') }}</MsTag
|
||||
>
|
||||
<MsTag theme="outline">
|
||||
<template #icon>
|
||||
<icon-eraser class="mr-1 text-[16px] text-[var(--color-text-4)]" />
|
||||
</template>
|
||||
|
||||
{{ t('project.commonScript.clear') }}</MsTag
|
||||
>
|
||||
</div>
|
||||
<MsTag theme="outline">{{ t('project.commonScript.formatting') }}</MsTag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-[calc(100vh-120px)] bg-[var(--color-bg-3)]">
|
||||
<div class="leftCodeEditor w-[70%]">
|
||||
<MsCodeEditor
|
||||
v-model:model-value="commonScriptValue"
|
||||
title=""
|
||||
width="100%"
|
||||
height="calc(100vh - 155px)"
|
||||
theme="MS-text"
|
||||
:read-only="false"
|
||||
:show-full-screen="false"
|
||||
:show-theme-change="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="rightCodeEditor mt-[24px] h-[calc(100vh-155px)] w-[calc(30%-12px)] bg-white">
|
||||
<div class="flex items-center justify-between p-3">
|
||||
<div class="flex items-center">
|
||||
<span v-if="expanded" class="collapsebtn mr-1 flex items-center justify-center" @click="expandedHandler">
|
||||
<icon-right class="text-[12px] text-[var(--color-text-4)]" />
|
||||
</span>
|
||||
<span v-else class="expand mr-1 flex items-center justify-center" @click="expandedHandler">
|
||||
<icon-down class="text-[12px] text-[rgb(var(--primary-6))]" />
|
||||
</span>
|
||||
<div class="font-medium">{{ t('project.commonScript.codeSnippet') }}</div>
|
||||
</div>
|
||||
|
||||
<a-select v-model="language" class="max-w-[50%]" :placeholder="t('project.commonScript.pleaseSelected')">
|
||||
<a-option v-for="item of languages" :key="item.value">{{ item.text }}</a-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<div v-if="!expanded" class="p-[12px] pt-0">
|
||||
<div v-for="item of SCRIPT_MENU" :key="item.value" class="menuItem px-1 text-[12px]" @click="handleClick(item)">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
|
||||
|
||||
import { SCRIPT_MENU } from '../utils';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const expanded = ref<boolean>(true);
|
||||
const language = ref('beanshell');
|
||||
const commonScriptValue = ref('');
|
||||
|
||||
const languages = [
|
||||
{ text: 'beanshell', value: 'beanshell' },
|
||||
{ text: 'python', value: 'python' },
|
||||
{ text: 'groovy', value: 'groovy' },
|
||||
{ text: 'javascript', value: 'javascript' },
|
||||
];
|
||||
|
||||
function expandedHandler() {
|
||||
expanded.value = !expanded.value;
|
||||
}
|
||||
|
||||
function handleClick(menu: CommonScriptMenu) {}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.collapsebtn {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-text-n8) !important;
|
||||
@apply cursor-pointer bg-white;
|
||||
}
|
||||
.expand {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: rgb(var(--primary-1));
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
.menuItem {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
color: rgb(var(--primary-5));
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,226 @@
|
|||
<template>
|
||||
<MsCard simple>
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<a-button type="outline" @click="addCommonScript"> {{ t('project.commonScript.addPublicScript') }} </a-button>
|
||||
<a-input-search
|
||||
v-model:model-value="keyword"
|
||||
:placeholder="t('project.commonScript.searchByNameAndId')"
|
||||
allow-clear
|
||||
class="mx-[8px] w-[240px]"
|
||||
/>
|
||||
</div>
|
||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||
<template #name="{ record }">
|
||||
<div class="flex items-center">
|
||||
<div class="one-line-text max-w-[200px] text-[rgb(var(--primary-5))]">{{ record.name }}</div>
|
||||
<a-popover :title="t('project.commonScript.publicScriptName')" position="right">
|
||||
<a-button type="text" class="ml-2 px-0">{{ t('project.commonScript.preview') }}</a-button>
|
||||
<template #content>
|
||||
<div class="w-[436px] bg-[var(--color-bg-3)] px-2 pb-2">
|
||||
<MsCodeEditor
|
||||
v-model:model-value="record.name"
|
||||
:show-theme-change="false"
|
||||
title=""
|
||||
width="100%"
|
||||
height="376px"
|
||||
theme="MS-text"
|
||||
:read-only="false"
|
||||
:show-full-screen="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</a-popover>
|
||||
</div>
|
||||
</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>
|
||||
</template>
|
||||
<template #operation="{ record }">
|
||||
<MsButton status="primary">
|
||||
{{ t('common.edit') }}
|
||||
</MsButton>
|
||||
<MsTableMoreAction
|
||||
v-if="!record.internal"
|
||||
:list="actions"
|
||||
@select="(item:ActionsItem) => handleMoreActionSelect(item,record)"
|
||||
/></template>
|
||||
</ms-base-table>
|
||||
<template v-if="(keyword || '').trim() === ''" #empty>
|
||||
<div class="flex items-center justify-center">
|
||||
{{ t('caseManagement.caseReview.tableNoData') }}
|
||||
<MsButton class="ml-[8px]"> {{ t('project.commonScript.addPublicScript') }} </MsButton>
|
||||
</div>
|
||||
</template>
|
||||
<AddScriptDrawer v-model:visible="showScriptDrawer" />
|
||||
</MsCard>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
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 MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
import AddScriptDrawer from './components/addScriptDrawer.vue';
|
||||
|
||||
import { getDependOnCase } from '@/api/modules/case-management/featureCase';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import { useAppStore, useTableStore } from '@/store';
|
||||
import { characterLimit } from '@/utils';
|
||||
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
|
||||
const tableStore = useTableStore();
|
||||
|
||||
const { openModal } = useModal();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const keyword = ref<string>('');
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: 'project.commonScript.name',
|
||||
dataIndex: 'name',
|
||||
slotName: 'name',
|
||||
width: 300,
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.description',
|
||||
slotName: 'description',
|
||||
dataIndex: 'description',
|
||||
width: 200,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.enable',
|
||||
dataIndex: 'enable',
|
||||
slotName: 'enable',
|
||||
showInTable: true,
|
||||
width: 150,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.tags',
|
||||
dataIndex: 'tags',
|
||||
slotName: 'tags',
|
||||
showInTable: true,
|
||||
isTag: true,
|
||||
width: 150,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.createUser',
|
||||
slotName: 'createUser',
|
||||
dataIndex: 'createUser',
|
||||
showInTable: true,
|
||||
width: 200,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.createTime',
|
||||
slotName: 'createTime',
|
||||
dataIndex: 'createTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
showInTable: true,
|
||||
width: 300,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'system.resourcePool.tableColumnUpdateTime',
|
||||
dataIndex: 'updateTime',
|
||||
width: 180,
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'project.commonScript.tableColumnActions',
|
||||
slotName: 'operation',
|
||||
dataIndex: 'operation',
|
||||
fixed: 'right',
|
||||
width: 140,
|
||||
showInTable: true,
|
||||
showDrag: false,
|
||||
},
|
||||
];
|
||||
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setProps } = useTable(getDependOnCase, {
|
||||
scroll: { x: '100%' },
|
||||
tableKey: TableKeyEnum.ORGANIZATION_PROJECT_COMMON_SCRIPT,
|
||||
selectable: true,
|
||||
heightUsed: 340,
|
||||
showSetting: true,
|
||||
enableDrag: true,
|
||||
});
|
||||
|
||||
const actions: ActionsItem[] = [
|
||||
{
|
||||
label: t('common.delete'),
|
||||
danger: true,
|
||||
eventTag: 'delete',
|
||||
},
|
||||
];
|
||||
|
||||
function deleteScript(record: Record<string, any>) {
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('project.commonScript.deleteTitleTip', { name: characterLimit(record.name) }),
|
||||
content: t('project.commonScript.deleteTitleContent'),
|
||||
okText: t('common.confirmDelete'),
|
||||
cancelText: t('common.cancel'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
}
|
||||
|
||||
function handleMoreActionSelect(item: ActionsItem, record: Record<string, any>) {
|
||||
if (item.eventTag === 'delete') {
|
||||
deleteScript(record);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// setLoadListParams({});
|
||||
// loadList();
|
||||
setProps({
|
||||
data: [
|
||||
// {
|
||||
// name: '哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈',
|
||||
// description: 'description',
|
||||
// enable: true,
|
||||
// tags: [{ id: '1001', name: 'A' }],
|
||||
// },
|
||||
],
|
||||
});
|
||||
});
|
||||
tableStore.initColumn(TableKeyEnum.ORGANIZATION_PROJECT_COMMON_SCRIPT, columns, 'drawer');
|
||||
|
||||
const showScriptDrawer = ref<boolean>(false);
|
||||
|
||||
function addCommonScript() {
|
||||
showScriptDrawer.value = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -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',
|
||||
},
|
||||
};
|
|
@ -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: '终止测试',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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 {};
|
|
@ -101,7 +101,7 @@
|
|||
asterisk-position="end"
|
||||
class="max-w-[732px]"
|
||||
>
|
||||
<MsRichText v-model:model-value="defectForm.description" />
|
||||
<MsRichText v-model:raw="defectForm.description" />
|
||||
<MsFormItemSub :text="t('system.orgTemplate.defectContentTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="precondition" :label="t('system.orgTemplate.precondition')" asterisk-position="end">
|
||||
<MsRichText v-model="viewForm.precondition" />
|
||||
<MsRichText v-model:raw="viewForm.precondition" />
|
||||
</a-form-item>
|
||||
<a-form-item field="step" :label="t('system.orgTemplate.stepDescription')" class="relative">
|
||||
<div class="absolute left-16 top-0">
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item field="precondition" :label="t('system.orgTemplate.defectContent')" asterisk-position="end">
|
||||
<MsRichText v-model="viewForm.description" />
|
||||
<MsRichText v-model:raw="viewForm.description" />
|
||||
</a-form-item>
|
||||
<a-form-item field="attachment" label="添加附件">
|
||||
<div class="flex flex-col">
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
asterisk-position="end"
|
||||
class="max-w-[732px]"
|
||||
>
|
||||
<MsRichText v-model:model-value="defectForm.description" />
|
||||
<MsRichText v-model:raw="defectForm.description" />
|
||||
<MsFormItemSub :text="t('system.orgTemplate.defectContentTip')" :show-fill-icon="false" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
|
|
@ -281,7 +281,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
<style scoped lang="less">
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
min-width: 112px;
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
<a-tooltip>
|
||||
<template #content>
|
||||
<div class="text-sm">{{ t('system.plugin.statusEnableTip') }}</div>
|
||||
<div class="text-sm">{{ t('system.plugin.statusDisableTip') }}</div>
|
||||
</template>
|
||||
<div class="mx-1 flex h-[32px] items-center">
|
||||
<span class="mr-1">{{ t('system.plugin.pluginStatus') }}</span>
|
||||
|
|
Loading…
Reference in New Issue