refactor(系统设置): 重构系统设置模板&项目模板
This commit is contained in:
parent
f21064cb3e
commit
53226e689e
|
@ -28,7 +28,10 @@ export function getCommonScriptPage(data: TableQueryParams) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加公共脚本
|
// 添加公共脚本
|
||||||
export function addCommonScriptReq(data: AddOrUpdateCommonScript) {
|
export function addOrUpdateCommonScriptReq(data: AddOrUpdateCommonScript) {
|
||||||
|
if (data.id) {
|
||||||
|
return MSR.post({ url: UpdateCommonScriptUrl, data });
|
||||||
|
}
|
||||||
return MSR.post({ url: AddCommonScriptUrl, data });
|
return MSR.post({ url: AddCommonScriptUrl, data });
|
||||||
}
|
}
|
||||||
// 更新公共脚本
|
// 更新公共脚本
|
||||||
|
|
|
@ -58,6 +58,15 @@
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
|
<AddScriptDrawer
|
||||||
|
v-model:visible="showScriptDrawer"
|
||||||
|
v-model:params="paramsList"
|
||||||
|
:confirm-loading="confirmLoading"
|
||||||
|
:script-id="isEditId"
|
||||||
|
ok-text="project.commonScript.apply"
|
||||||
|
:enable-radio-selected="radioSelected"
|
||||||
|
@save="saveHandler"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -71,14 +80,20 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
|
||||||
import { getInsertCommonScriptPage } from '@/api/modules/project-management/commonScript';
|
import { addOrUpdateCommonScriptReq, getInsertCommonScriptPage } from '@/api/modules/project-management/commonScript';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import type { AddOrUpdateCommonScript, ParamsRequestType } from '@/models/projectManagement/commonScript';
|
||||||
|
|
||||||
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
const AddScriptDrawer = defineAsyncComponent(
|
||||||
|
() => import('@/components/business/ms-common-script/ms-addScriptDrawer.vue')
|
||||||
|
);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -93,7 +108,7 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits(['update:visible', 'update:checkedId', 'save', 'addScript']);
|
const emit = defineEmits(['update:visible', 'update:checkedId', 'save']);
|
||||||
const insertScriptDrawer = computed({
|
const insertScriptDrawer = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.visible;
|
return props.visible;
|
||||||
|
@ -229,9 +244,41 @@
|
||||||
function handleDrawerCancel() {
|
function handleDrawerCancel() {
|
||||||
insertScriptDrawer.value = false;
|
insertScriptDrawer.value = false;
|
||||||
}
|
}
|
||||||
|
const showScriptDrawer = ref<boolean>(false);
|
||||||
function addCommonScript() {
|
function addCommonScript() {
|
||||||
emit('addScript');
|
showScriptDrawer.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramsList = ref<ParamsRequestType[]>([]);
|
||||||
|
const confirmLoading = ref<boolean>(false);
|
||||||
|
const isEditId = ref<string>('');
|
||||||
|
const radioSelected = ref<boolean>(false);
|
||||||
|
|
||||||
|
// 保存自定义代码片段应用
|
||||||
|
async function saveHandler(form: AddOrUpdateCommonScript) {
|
||||||
|
try {
|
||||||
|
confirmLoading.value = true;
|
||||||
|
const { status } = form;
|
||||||
|
const paramTableList = paramsList.value.slice(0, -1);
|
||||||
|
const paramsObj: AddOrUpdateCommonScript = {
|
||||||
|
...form,
|
||||||
|
status: status || 'DRAFT',
|
||||||
|
projectId: currentProjectId.value,
|
||||||
|
params: JSON.stringify(paramTableList),
|
||||||
|
};
|
||||||
|
await addOrUpdateCommonScriptReq(paramsObj);
|
||||||
|
showScriptDrawer.value = false;
|
||||||
|
initData();
|
||||||
|
Message.success(
|
||||||
|
form.status === 'DRAFT'
|
||||||
|
? t('project.commonScript.saveDraftSuccessfully')
|
||||||
|
: t('project.commonScript.appliedSuccessfully')
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
confirmLoading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<MsDrawer
|
<MsDrawer
|
||||||
v-model:visible="showScriptDrawer"
|
v-model:visible="showScriptDrawer"
|
||||||
:title="t('project.commonScript.addPublicScript')"
|
:title="form.id ? t('project.commonScript.editPublicScript') : t('project.commonScript.addPublicScript')"
|
||||||
:width="768"
|
:width="768"
|
||||||
:footer="true"
|
:footer="true"
|
||||||
unmount-on-close
|
unmount-on-close
|
||||||
|
@ -43,6 +43,7 @@
|
||||||
:scroll="{ x: '100%' }"
|
:scroll="{ x: '100%' }"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:height-used="heightUsed"
|
:height-used="heightUsed"
|
||||||
|
:selectable="false"
|
||||||
@change="handleParamTableChange"
|
@change="handleParamTableChange"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -218,12 +219,23 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// watchEffect(() => {
|
||||||
|
// editScriptId.value = props.scriptId;
|
||||||
|
// if (editScriptId.value) {
|
||||||
|
// getDetail();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => showScriptDrawer.value,
|
() => showScriptDrawer.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
form.value = { ...initForm };
|
form.value = { ...initForm };
|
||||||
innerParams.value = [];
|
innerParams.value = [];
|
||||||
|
editScriptId.value = props.scriptId;
|
||||||
|
if (editScriptId.value) {
|
||||||
|
getDetail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -311,6 +323,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// onBeforeUnmount(() => {
|
||||||
|
// editScriptId.value = '';
|
||||||
|
// });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
v-model:visible="showInsertDrawer"
|
v-model:visible="showInsertDrawer"
|
||||||
:script-language="innerLanguagesType"
|
:script-language="innerLanguagesType"
|
||||||
:enable-radio-selected="props.enableRadioSelected"
|
:enable-radio-selected="props.enableRadioSelected"
|
||||||
@add-script="insertCommonScript"
|
|
||||||
@save="saveHandler"
|
@save="saveHandler"
|
||||||
/>
|
/>
|
||||||
<FormApiImportDrawer
|
<FormApiImportDrawer
|
||||||
|
@ -168,6 +167,7 @@ ${item.script}
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
codeEditorRef.value?.insertContent(scriptStr);
|
codeEditorRef.value?.insertContent(scriptStr);
|
||||||
|
showInsertDrawer.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ export const TEXTAREA = {
|
||||||
props: {
|
props: {
|
||||||
'placeholder': t('formCreate.PleaseEnter'),
|
'placeholder': t('formCreate.PleaseEnter'),
|
||||||
'max-length': 1000,
|
'max-length': 1000,
|
||||||
'auto-size': '{ minRows: 1 }',
|
'auto-size': { minRows: 1 },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const JIRAKEY = {
|
export const JIRAKEY = {
|
||||||
|
|
|
@ -73,7 +73,8 @@
|
||||||
emits('reload');
|
emits('reload');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleChange() {
|
function handleChange(value: any) {
|
||||||
|
formApi.value?.validateField(value);
|
||||||
emits('change');
|
emits('change');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -480,7 +480,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
locale: 'menu.projectManagement.templateManager',
|
locale: 'menu.projectManagement.templateManager',
|
||||||
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL', // 模板管理-用例模板
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL', // 模板管理-用例模板
|
||||||
|
@ -490,7 +490,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'FUNCTIONAL',
|
type: 'FUNCTIONAL',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL_FIELD', // 模板管理-用例模板-用例模板字段管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL_FIELD', // 模板管理-用例模板-用例模板字段管理
|
||||||
|
@ -500,7 +500,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'FUNCTIONAL',
|
type: 'FUNCTIONAL',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL_TEMPLATE', // 模板管理-用例模板-用例模板管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_FUNCTIONAL_TEMPLATE', // 模板管理-用例模板-用例模板管理
|
||||||
|
@ -510,7 +510,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'FUNCTIONAL',
|
type: 'FUNCTIONAL',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -522,7 +522,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'API',
|
type: 'API',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_API_FIELD', // 模板管理-接口模板-接口模板字段管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_API_FIELD', // 模板管理-接口模板-接口模板字段管理
|
||||||
|
@ -532,7 +532,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'API',
|
type: 'API',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_API_TEMPLATE', // 模板管理-接口模板-接口模板管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_API_TEMPLATE', // 模板管理-接口模板-接口模板管理
|
||||||
|
@ -542,7 +542,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'API',
|
type: 'API',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -554,7 +554,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'BUG',
|
type: 'BUG',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_FIELD', // 模板管理-缺陷模板管理-字段管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_FIELD', // 模板管理-缺陷模板管理-字段管理
|
||||||
|
@ -564,7 +564,7 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'BUG',
|
type: 'BUG',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_TEMPLATE', // 模板管理-缺陷模板-缺陷模板管理
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_TEMPLATE', // 模板管理-缺陷模板-缺陷模板管理
|
||||||
|
@ -574,14 +574,14 @@ export const pathMap: PathMapItem[] = [
|
||||||
routeQuery: {
|
routeQuery: {
|
||||||
type: 'BUG',
|
type: 'BUG',
|
||||||
},
|
},
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_WORKFLOW', // 模板管理-缺陷模板-缺陷工作流
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_BUG_WORKFLOW', // 模板管理-缺陷模板-缺陷工作流
|
||||||
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,7 @@ export enum ApiTestRouteEnum {
|
||||||
API_TEST = 'apiTest',
|
API_TEST = 'apiTest',
|
||||||
API_TEST_DEBUG = 'apiTestDebug',
|
API_TEST_DEBUG = 'apiTestDebug',
|
||||||
API_TEST_MANAGEMENT = 'apiTestManagement',
|
API_TEST_MANAGEMENT = 'apiTestManagement',
|
||||||
|
API_TEST_REPORT = 'apiTestReport',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BugManagementRouteEnum {
|
export enum BugManagementRouteEnum {
|
||||||
|
@ -41,7 +42,9 @@ export enum ProjectManagementRouteEnum {
|
||||||
PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT = 'projectManagementPermissionMenuManagement',
|
PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT = 'projectManagementPermissionMenuManagement',
|
||||||
PROJECT_MANAGEMENT_TEMPLATE = 'projectManagementTemplate',
|
PROJECT_MANAGEMENT_TEMPLATE = 'projectManagementTemplate',
|
||||||
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT = 'projectManagementTemplateManagement',
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT = 'projectManagementTemplateManagement',
|
||||||
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL = 'projectManagementTemplateManagementDetail',
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_CASE_DETAIL = 'projectManagementTemplateManagementCaseDetail',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_API_DETAIL = 'projectManagementTemplateManagementCaseDetail',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_BUG_DETAIL = 'projectManagementTemplateManagementBugDetail',
|
||||||
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW = 'projectManagementTemplateManagementWorkFlow',
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW = 'projectManagementTemplateManagementWorkFlow',
|
||||||
PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING = 'projectManagementTemplateFiledSetting',
|
PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING = 'projectManagementTemplateFiledSetting',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_VERSION = 'projectManagementPermissionVersion',
|
PROJECT_MANAGEMENT_PERMISSION_VERSION = 'projectManagementPermissionVersion',
|
||||||
|
@ -84,7 +87,9 @@ export enum SettingRouteEnum {
|
||||||
SETTING_ORGANIZATION_TEMPLATE = 'settingOrganizationTemplate',
|
SETTING_ORGANIZATION_TEMPLATE = 'settingOrganizationTemplate',
|
||||||
SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING = 'settingOrganizationTemplateFiledSetting',
|
SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING = 'settingOrganizationTemplateFiledSetting',
|
||||||
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT = 'settingOrganizationTemplateManagement',
|
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT = 'settingOrganizationTemplateManagement',
|
||||||
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL = 'settingOrganizationTemplateManagementDetail',
|
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_CASE_DETAIL = 'settingOrganizationTemplateManagementCaseDetail',
|
||||||
|
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_API_DETAIL = 'settingOrganizationTemplateManagementApiDetail',
|
||||||
|
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_BUG_DETAIL = 'settingOrganizationTemplateManagementBugDetail',
|
||||||
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW = 'settingOrganizationTemplateWorkFlow',
|
SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW = 'settingOrganizationTemplateWorkFlow',
|
||||||
SETTING_ORGANIZATION_SERVICE = 'settingOrganizationService',
|
SETTING_ORGANIZATION_SERVICE = 'settingOrganizationService',
|
||||||
SETTING_ORGANIZATION_LOG = 'settingOrganizationLog',
|
SETTING_ORGANIZATION_LOG = 'settingOrganizationLog',
|
||||||
|
|
|
@ -116,6 +116,8 @@ export interface ActionTemplateManage {
|
||||||
fieldType?: string;
|
fieldType?: string;
|
||||||
systemFields?: Record<string, any>[];
|
systemFields?: Record<string, any>[];
|
||||||
internal?: boolean; // 是否为系统模板
|
internal?: boolean; // 是否为系统模板
|
||||||
|
platForm?: string;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作流列表字段
|
// 工作流列表字段
|
||||||
|
|
|
@ -177,11 +177,11 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
},
|
},
|
||||||
// 项目-模板-创建模板和模板详情
|
// 项目-模板-创建模板和模板详情
|
||||||
{
|
{
|
||||||
path: 'templateDetail/:mode?',
|
path: 'templateCaseDetail/:mode?',
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_CASE_DETAIL,
|
||||||
component: () => import('@/views/project-management/template/components/proTemplateDetail.vue'),
|
component: () => import('@/views/project-management/template/components/detail.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.templateManagementDetail',
|
locale: 'system.orgTemplate.createCaseTemplate',
|
||||||
roles: ['PROJECT_TEMPLATE:READ+UPDATE', 'PROJECT_TEMPLATE:READ+ADD'],
|
roles: ['PROJECT_TEMPLATE:READ+UPDATE', 'PROJECT_TEMPLATE:READ+ADD'],
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
|
@ -194,9 +194,65 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
query: ['type'],
|
query: ['type'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_CASE_DETAIL,
|
||||||
locale: 'menu.settings.organization.templateManagementDetail',
|
locale: 'system.orgTemplate.createCaseTemplate',
|
||||||
editLocale: 'menu.settings.organization.templateManagementEdit',
|
editLocale: 'system.orgTemplate.updateCaseTemplate',
|
||||||
|
editTag: 'id',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 项目-模板-接口模板
|
||||||
|
{
|
||||||
|
path: 'templateApiDetail/:mode?',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_API_DETAIL,
|
||||||
|
component: () => import('@/views/project-management/template/components/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'system.orgTemplate.createApiTemplate',
|
||||||
|
roles: ['PROJECT_TEMPLATE:READ+UPDATE', 'PROJECT_TEMPLATE:READ+ADD'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_API_DETAIL,
|
||||||
|
locale: 'system.orgTemplate.createApiTemplate',
|
||||||
|
editLocale: 'system.orgTemplate.updateApiTemplate',
|
||||||
|
editTag: 'id',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 项目-模板-缺陷模板
|
||||||
|
{
|
||||||
|
path: 'templateBugDetail/:mode?',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_BUG_DETAIL,
|
||||||
|
component: () => import('@/views/project-management/template/components/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'system.orgTemplate.createDefectTemplate',
|
||||||
|
roles: ['PROJECT_TEMPLATE:READ+UPDATE', 'PROJECT_TEMPLATE:READ+ADD'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_BUG_DETAIL,
|
||||||
|
locale: 'system.orgTemplate.createDefectTemplate',
|
||||||
|
editLocale: 'system.orgTemplate.updateDefectTemplate',
|
||||||
editTag: 'id',
|
editTag: 'id',
|
||||||
query: ['type'],
|
query: ['type'],
|
||||||
},
|
},
|
||||||
|
|
|
@ -285,13 +285,14 @@ const Setting: AppRouteRecordRaw = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 模板列表-模板管理-创建&编辑模板
|
// 模板列表-创建&编辑模板
|
||||||
|
// 用例模板
|
||||||
{
|
{
|
||||||
path: 'templateManagementDetail/:mode?',
|
path: 'templateManagementCaseDetail/:mode?',
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_CASE_DETAIL,
|
||||||
component: () => import('@/views/setting/organization/template/components/templateDetail.vue'),
|
component: () => import('@/views/setting/organization/template/components/detail.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.templateManagementDetail',
|
locale: 'system.orgTemplate.createCaseTemplate',
|
||||||
roles: ['ORGANIZATION_TEMPLATE:READ+UPDATE', 'ORGANIZATION_TEMPLATE:READ+ADD'],
|
roles: ['ORGANIZATION_TEMPLATE:READ+UPDATE', 'ORGANIZATION_TEMPLATE:READ+ADD'],
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
|
@ -305,9 +306,65 @@ const Setting: AppRouteRecordRaw = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
locale: 'menu.settings.organization.templateManagementDetail',
|
locale: 'system.orgTemplate.createCaseTemplate',
|
||||||
editTag: 'id',
|
editTag: 'id',
|
||||||
editLocale: 'menu.settings.organization.templateManagementEdit',
|
editLocale: 'system.orgTemplate.updateCaseTemplate',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 接口模板
|
||||||
|
{
|
||||||
|
path: 'templateManagementApiDetail/:mode?',
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_API_DETAIL,
|
||||||
|
component: () => import('@/views/setting/organization/template/components/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'system.orgTemplate.createApiTemplate',
|
||||||
|
roles: ['ORGANIZATION_TEMPLATE:READ+UPDATE', 'ORGANIZATION_TEMPLATE:READ+ADD'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'system.orgTemplate.createApiTemplate',
|
||||||
|
editTag: 'id',
|
||||||
|
editLocale: 'system.orgTemplate.updateApiTemplate',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 缺陷模板
|
||||||
|
{
|
||||||
|
path: 'templateManagementBugDetail/:mode?',
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_BUG_DETAIL,
|
||||||
|
component: () => import('@/views/setting/organization/template/components/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'system.orgTemplate.createDefectTemplate',
|
||||||
|
roles: ['ORGANIZATION_TEMPLATE:READ+UPDATE', 'ORGANIZATION_TEMPLATE:READ+ADD'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
query: ['type'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'system.orgTemplate.createDefectTemplate',
|
||||||
|
editTag: 'id',
|
||||||
|
editLocale: 'system.orgTemplate.updateDefectTemplate',
|
||||||
query: ['type'],
|
query: ['type'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
import { createCaseRequest, updateCaseRequest } from '@/api/modules/case-management/featureCase';
|
import { createCaseRequest, updateCaseRequest } from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
|
||||||
import useVisit from '@/hooks/useVisit';
|
import useVisit from '@/hooks/useVisit';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||||
|
@ -48,10 +49,13 @@
|
||||||
|
|
||||||
import Message from '@arco-design/web-vue/es/message';
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
|
const { setState } = useLeaveUnSaveTip();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
setState(false);
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
|
|
||||||
const visitedKey = 'doNotNextTipCreateCase';
|
const visitedKey = 'doNotNextTipCreateCase';
|
||||||
|
@ -83,6 +87,7 @@
|
||||||
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE,
|
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE,
|
||||||
query: { organizationId: route.query.organizationId, projectId: route.query.projectId },
|
query: { organizationId: route.query.organizationId, projectId: route.query.projectId },
|
||||||
});
|
});
|
||||||
|
setState(true);
|
||||||
// 创建用例
|
// 创建用例
|
||||||
} else {
|
} else {
|
||||||
// 创建并关联
|
// 创建并关联
|
||||||
|
@ -119,6 +124,7 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
setState(true);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
|
@ -229,15 +229,6 @@
|
||||||
import { CommentParams } from '@/components/business/ms-comment/types';
|
import { CommentParams } from '@/components/business/ms-comment/types';
|
||||||
import MsDetailDrawer from '@/components/business/ms-detail-drawer/index.vue';
|
import MsDetailDrawer from '@/components/business/ms-detail-drawer/index.vue';
|
||||||
import SettingDrawer from './tabContent/settingDrawer.vue';
|
import SettingDrawer from './tabContent/settingDrawer.vue';
|
||||||
import TabDefect from './tabContent/tabBug/tabDefect.vue';
|
|
||||||
import TabCaseTable from './tabContent/tabCase/tabCaseTable.vue';
|
|
||||||
import TabCaseReview from './tabContent/tabCaseReview.vue';
|
|
||||||
import TabChangeHistory from './tabContent/tabChangeHistory.vue';
|
|
||||||
import TabComment from './tabContent/tabComment/tabCommentIndex.vue';
|
|
||||||
import TabDemand from './tabContent/tabDemand/demand.vue';
|
|
||||||
import TabDependency from './tabContent/tabDependency/tabDependency.vue';
|
|
||||||
import TabDetail from './tabContent/tabDetail.vue';
|
|
||||||
import TabTestPlan from './tabContent/tabTestPlan.vue';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createCommentList,
|
createCommentList,
|
||||||
|
@ -261,6 +252,16 @@
|
||||||
import { getCaseLevels } from './utils';
|
import { getCaseLevels } from './utils';
|
||||||
import { LabelValue } from '@arco-design/web-vue/es/tree-select/interface';
|
import { LabelValue } from '@arco-design/web-vue/es/tree-select/interface';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
|
// 异步加载组件
|
||||||
|
const TabDefect = defineAsyncComponent(() => import('./tabContent/tabBug/tabDefect.vue'));
|
||||||
|
const TabCaseTable = defineAsyncComponent(() => import('./tabContent/tabCase/tabCaseTable.vue'));
|
||||||
|
const TabCaseReview = defineAsyncComponent(() => import('./tabContent/tabCaseReview.vue'));
|
||||||
|
const TabChangeHistory = defineAsyncComponent(() => import('./tabContent/tabChangeHistory.vue'));
|
||||||
|
const TabComment = defineAsyncComponent(() => import('./tabContent/tabComment/tabCommentIndex.vue'));
|
||||||
|
const TabDemand = defineAsyncComponent(() => import('./tabContent/tabDemand/demand.vue'));
|
||||||
|
const TabDependency = defineAsyncComponent(() => import('./tabContent/tabDependency/tabDependency.vue'));
|
||||||
|
const TabDetail = defineAsyncComponent(() => import('./tabContent/tabDetail.vue'));
|
||||||
|
const TabTestPlan = defineAsyncComponent(() => import('./tabContent/tabTestPlan.vue'));
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const detailDrawerRef = ref<InstanceType<typeof MsDetailDrawer>>();
|
const detailDrawerRef = ref<InstanceType<typeof MsDetailDrawer>>();
|
||||||
|
|
|
@ -465,21 +465,18 @@
|
||||||
'slotName': 'num',
|
'slotName': 'num',
|
||||||
'dataIndex': 'num',
|
'dataIndex': 'num',
|
||||||
'width': 200,
|
'width': 200,
|
||||||
'showInTable': true,
|
|
||||||
'sortable': {
|
'sortable': {
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
'filter-icon-align-left': true,
|
'filter-icon-align-left': true,
|
||||||
'showTooltip': true,
|
'showTooltip': true,
|
||||||
'ellipsis': true,
|
|
||||||
'showDrag': false,
|
'showDrag': false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.tableColumnName',
|
title: 'caseManagement.featureCase.tableColumnName',
|
||||||
slotName: 'name',
|
slotName: 'name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
showInTable: true,
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
width: 300,
|
width: 300,
|
||||||
editType: hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,
|
editType: hasAnyPermission(['FUNCTIONAL_CASE:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,
|
||||||
|
@ -487,7 +484,6 @@
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
ellipsis: true,
|
|
||||||
showDrag: false,
|
showDrag: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -791,7 +787,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const initDefaultFields = ref<CustomAttributes[]>([]);
|
const initDefaultFields = ref<CustomAttributes[]>([]);
|
||||||
let fullColumns: MsTableColumn = []; // 全量列表
|
// let fullColumns: MsTableColumn = []; // 全量列表
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setKeyword, setAdvanceFilter } = useTable(
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector, setKeyword, setAdvanceFilter } = useTable(
|
||||||
getCaseList,
|
getCaseList,
|
||||||
|
@ -1183,6 +1179,7 @@
|
||||||
// 处理自定义字段列
|
// 处理自定义字段列
|
||||||
let customFieldsColumns: Record<string, any>[] = [];
|
let customFieldsColumns: Record<string, any>[] = [];
|
||||||
const tableRef = ref<InstanceType<typeof MsBaseTable> | null>(null);
|
const tableRef = ref<InstanceType<typeof MsBaseTable> | null>(null);
|
||||||
|
const fullColumns = ref<MsTableColumn>([]);
|
||||||
|
|
||||||
// 处理自定义字段展示
|
// 处理自定义字段展示
|
||||||
async function getDefaultFields() {
|
async function getDefaultFields() {
|
||||||
|
@ -1204,12 +1201,12 @@
|
||||||
|
|
||||||
caseLevelFields.value = result.customFields.find((item: any) => item.internal && item.fieldName === '用例等级');
|
caseLevelFields.value = result.customFields.find((item: any) => item.internal && item.fieldName === '用例等级');
|
||||||
caseFilters.value = caseLevelFields.value.options.map((item: any) => item.value);
|
caseFilters.value = caseLevelFields.value.options.map((item: any) => item.value);
|
||||||
fullColumns = [
|
fullColumns.value = [
|
||||||
...columns.slice(0, columns.length - 1),
|
...columns.slice(0, columns.length - 1),
|
||||||
...customFieldsColumns,
|
...customFieldsColumns,
|
||||||
...columns.slice(columns.length - 1, columns.length),
|
...columns.slice(columns.length - 1, columns.length),
|
||||||
];
|
];
|
||||||
await tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_TABLE, fullColumns, 'drawer');
|
await tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_TABLE, fullColumns.value, 'drawer');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是用例等级
|
// 如果是用例等级
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
/> -->
|
/> -->
|
||||||
<MsButton @click="saveAsHandler(record)">{{ t('caseManagement.featureCase.saveAsVersion') }}</MsButton>
|
<MsButton @click="saveAsHandler(record)">{{ t('caseManagement.featureCase.saveAsVersion') }}</MsButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="showModal"
|
v-model:visible="showModal"
|
||||||
|
@ -129,15 +128,15 @@
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: 'caseManagement.featureCase.tableColumnActions',
|
// title: 'caseManagement.featureCase.tableColumnActions',
|
||||||
slotName: 'operation',
|
// slotName: 'operation',
|
||||||
dataIndex: 'operation',
|
// dataIndex: 'operation',
|
||||||
fixed: 'right',
|
// fixed: 'right',
|
||||||
width: 140,
|
// width: 140,
|
||||||
showInTable: true,
|
// showInTable: true,
|
||||||
showDrag: false,
|
// showDrag: false,
|
||||||
},
|
// },
|
||||||
];
|
];
|
||||||
|
|
||||||
const typeOptions = [
|
const typeOptions = [
|
||||||
|
@ -159,9 +158,9 @@
|
||||||
columns,
|
columns,
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_CHANGE_HISTORY,
|
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_CHANGE_HISTORY,
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
selectable: true,
|
selectable: false,
|
||||||
heightUsed: 340,
|
heightUsed: 340,
|
||||||
enableDrag: true,
|
enableDrag: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
|
@ -240,8 +239,8 @@
|
||||||
setLoadListParams({
|
setLoadListParams({
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
sourceId: props.caseId,
|
sourceId: props.caseId,
|
||||||
type:['IMPORT','ADD','UPDATE'],
|
type: ['IMPORT', 'ADD', 'UPDATE'],
|
||||||
module: ['CASE_MANAGEMENT_CASE_CREATE','CASE_MANAGEMENT_CASE_UPDATE'],
|
module: ['CASE_MANAGEMENT_CASE_CREATE', 'CASE_MANAGEMENT_CASE_UPDATE'],
|
||||||
});
|
});
|
||||||
await loadList();
|
await loadList();
|
||||||
featureCaseStore.getCaseCounts(props.caseId);
|
featureCaseStore.getCaseCounts(props.caseId);
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.name',
|
title: 'caseManagement.featureCase.demandName',
|
||||||
slotName: 'demandName',
|
slotName: 'demandName',
|
||||||
dataIndex: 'demandName',
|
dataIndex: 'demandName',
|
||||||
width: 300,
|
width: 300,
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
import ScriptDetailDrawer from './components/scriptDetailDrawer.vue';
|
import ScriptDetailDrawer from './components/scriptDetailDrawer.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
addCommonScriptReq,
|
addOrUpdateCommonScriptReq,
|
||||||
deleteCommonScript,
|
deleteCommonScript,
|
||||||
getCommonScriptPage,
|
getCommonScriptPage,
|
||||||
} from '@/api/modules/project-management/commonScript';
|
} from '@/api/modules/project-management/commonScript';
|
||||||
|
@ -279,13 +279,14 @@
|
||||||
try {
|
try {
|
||||||
confirmLoading.value = true;
|
confirmLoading.value = true;
|
||||||
const { status } = form;
|
const { status } = form;
|
||||||
|
const paramTableList = paramsList.value.slice(0, -1);
|
||||||
const paramsObj: AddOrUpdateCommonScript = {
|
const paramsObj: AddOrUpdateCommonScript = {
|
||||||
...form,
|
...form,
|
||||||
status: status || 'DRAFT',
|
status: status || 'DRAFT',
|
||||||
projectId: currentProjectId.value,
|
projectId: currentProjectId.value,
|
||||||
params: JSON.stringify(paramsList.value),
|
params: JSON.stringify(paramTableList),
|
||||||
};
|
};
|
||||||
await addCommonScriptReq(paramsObj);
|
await addOrUpdateCommonScriptReq(paramsObj);
|
||||||
showScriptDrawer.value = false;
|
showScriptDrawer.value = false;
|
||||||
initData();
|
initData();
|
||||||
Message.success(
|
Message.success(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
'project.commonScript.searchByNameAndId': 'Search by name',
|
'project.commonScript.searchByNameAndId': 'Search by name',
|
||||||
'project.commonScript.addPublicScript': 'Add public Script',
|
'project.commonScript.addPublicScript': 'Add public Script',
|
||||||
|
'project.commonScript.editPublicScript': 'Edit public Script',
|
||||||
'project.commonScript.name': 'Name',
|
'project.commonScript.name': 'Name',
|
||||||
'project.commonScript.description': 'Description',
|
'project.commonScript.description': 'Description',
|
||||||
'project.commonScript.enable': 'Enable',
|
'project.commonScript.enable': 'Enable',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
'project.commonScript.searchByNameAndId': '通过名称搜索',
|
'project.commonScript.searchByNameAndId': '通过名称搜索',
|
||||||
'project.commonScript.addPublicScript': '添加公共脚本',
|
'project.commonScript.addPublicScript': '添加公共脚本',
|
||||||
|
'project.commonScript.editPublicScript': '编辑公共脚本',
|
||||||
'project.commonScript.name': '名称',
|
'project.commonScript.name': '名称',
|
||||||
'project.commonScript.description': '描述',
|
'project.commonScript.description': '描述',
|
||||||
'project.commonScript.enable': '状态',
|
'project.commonScript.enable': '状态',
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<template>
|
||||||
|
<AddTemplate mode="project" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import AddTemplate from '@/views/setting/organization/template/components/addTemplate.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -1,408 +0,0 @@
|
||||||
<template>
|
|
||||||
<MsCard
|
|
||||||
:loading="loading"
|
|
||||||
:title="title"
|
|
||||||
:is-edit="isEdit && route.params.mode !== 'copy'"
|
|
||||||
has-breadcrumb
|
|
||||||
@save="saveHandler"
|
|
||||||
@save-and-continue="saveHandler(true)"
|
|
||||||
>
|
|
||||||
<template #headerRight>
|
|
||||||
<div class="rightBtn">
|
|
||||||
<a-button v-show="isPreview" type="outline" class="text-[var(--color-text-1)]" @click="togglePreview">{{
|
|
||||||
t('system.orgTemplate.templatePreview')
|
|
||||||
}}</a-button>
|
|
||||||
<a-button v-show="!isPreview" type="outline" class="text-[var(--color-text-1)]" @click="togglePreview">{{
|
|
||||||
t('system.orgTemplate.exitPreview')
|
|
||||||
}}</a-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<!-- 非预览模式 -->
|
|
||||||
<div v-if="isPreview" class="nonPreview">
|
|
||||||
<a-form ref="formRef" :model="templateForm" layout="vertical">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('system.orgTemplate.templateName')"
|
|
||||||
field="name"
|
|
||||||
asterisk-position="end"
|
|
||||||
:rules="[{ required: true, message: t('system.orgTemplate.templateNameRules') }]"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:model-value="templateForm.name"
|
|
||||||
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
|
|
||||||
:max-length="255"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
:disabled="templateForm?.internal"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="remark" :label="t('system.orgTemplate.description')" asterisk-position="end">
|
|
||||||
<a-textarea
|
|
||||||
v-model="templateForm.remark"
|
|
||||||
:max-length="1000"
|
|
||||||
:placeholder="t('system.orgTemplate.resDescription')"
|
|
||||||
:auto-size="{ minRows: 1 }"
|
|
||||||
style="resize: vertical"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
></a-textarea>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="route.query.type === 'BUG'" field="remark" label="" asterisk-position="end"
|
|
||||||
><a-checkbox v-model="templateForm.enableThirdPart">{{ t('system.orgTemplate.thirdParty') }}</a-checkbox>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="route.query.type === 'BUG'"
|
|
||||||
field="fieldType"
|
|
||||||
:label="t('system.orgTemplate.columnFieldType')"
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-radio-group v-model="fieldType" type="button">
|
|
||||||
<a-radio value="custom">{{ t('system.orgTemplate.custom') }}</a-radio>
|
|
||||||
<a-radio value="detail">{{ t('system.orgTemplate.details') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<!-- 已有字段表 -->
|
|
||||||
<TemplateManagementTable
|
|
||||||
v-if="fieldType === 'custom'"
|
|
||||||
ref="templateFieldTableRef"
|
|
||||||
v-model:select-data="selectData"
|
|
||||||
:data="(totalTemplateField as DefinedFieldItem[])"
|
|
||||||
:enable-third-part="templateForm.enableThirdPart"
|
|
||||||
mode="project"
|
|
||||||
@update="updateHandler"
|
|
||||||
/>
|
|
||||||
<!-- 缺陷详情表 -->
|
|
||||||
<a-form
|
|
||||||
v-if="fieldType === 'detail'"
|
|
||||||
ref="defectFormRef"
|
|
||||||
class="rounded-[4px]"
|
|
||||||
:model="defectForm"
|
|
||||||
layout="vertical"
|
|
||||||
>
|
|
||||||
<a-form-item
|
|
||||||
class="max-w-[732px]"
|
|
||||||
field="name"
|
|
||||||
:label="t('system.orgTemplate.defectName')"
|
|
||||||
:rules="[{ required: true, message: t('system.orgTemplate.defectNamePlaceholder') }]"
|
|
||||||
required
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model="defectForm.name"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('system.orgTemplate.defectNamePlaceholder')"
|
|
||||||
allow-clear
|
|
||||||
></a-input>
|
|
||||||
<MsFormItemSub :text="t('system.orgTemplate.defectNameTip')" :show-fill-icon="false" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
field="precondition"
|
|
||||||
:label="t('system.orgTemplate.defectContent')"
|
|
||||||
asterisk-position="end"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
>
|
|
||||||
<MsRichText v-model:raw="defectForm.description" />
|
|
||||||
<MsFormItemSub :text="t('system.orgTemplate.defectContentTip')" :show-fill-icon="false" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
<!-- 预览模式 -->
|
|
||||||
<PreviewTemplate
|
|
||||||
v-else
|
|
||||||
:select-field="(selectData as DefinedFieldItem[])"
|
|
||||||
:template-type="route.query.type"
|
|
||||||
:defect-form="defectForm"
|
|
||||||
/>
|
|
||||||
</MsCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
/**
|
|
||||||
* @description 系统管理-项目-模板-模板管理-创建&编辑
|
|
||||||
*/
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
|
||||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
|
||||||
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
|
||||||
import TemplateManagementTable from '@/views/setting/organization/template/components/templateManagementTable.vue';
|
|
||||||
import PreviewTemplate from '@/views/setting/organization/template/components/viewTemplate.vue';
|
|
||||||
|
|
||||||
import {
|
|
||||||
createProjectTemplateInfo,
|
|
||||||
getProjectFieldList,
|
|
||||||
getProjectTemplateInfo,
|
|
||||||
updateProjectTemplateInfo,
|
|
||||||
} from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
|
|
||||||
import { useAppStore } from '@/store';
|
|
||||||
import { sleep } from '@/utils';
|
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
|
||||||
|
|
||||||
import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template';
|
|
||||||
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getCardList,
|
|
||||||
getCustomDetailFields,
|
|
||||||
getTemplateName,
|
|
||||||
getTotalFieldOptionList,
|
|
||||||
} from '@/views/setting/organization/template/components/fieldSetting';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
|
||||||
|
|
||||||
const { setState } = useLeaveUnSaveTip();
|
|
||||||
|
|
||||||
setState(false);
|
|
||||||
|
|
||||||
const title = ref('');
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
const initTemplateForm: ActionTemplateManage = {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
remark: '',
|
|
||||||
scopeId: currentProjectId.value,
|
|
||||||
enableThirdPart: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const fieldType = ref<string>('custom'); // 缺陷模板字段类型
|
|
||||||
|
|
||||||
const templateForm = ref<ActionTemplateManage>({ ...initTemplateForm });
|
|
||||||
|
|
||||||
const selectData = ref<DefinedFieldItem[]>([]); // 表格已选择字段
|
|
||||||
const selectFiled = ref<DefinedFieldItem[]>([]);
|
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
|
||||||
const totalTemplateField = ref<DefinedFieldItem[]>([]);
|
|
||||||
const isEdit = computed(() => !!route.query.id);
|
|
||||||
const isEditField = ref<boolean>(false);
|
|
||||||
const systemFieldData = ref<CustomField[]>([]);
|
|
||||||
|
|
||||||
// 获取模板详情
|
|
||||||
const getTemplateInfo = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const res = await getProjectTemplateInfo(route.query.id as string);
|
|
||||||
const { name, customFields, systemFields } = res;
|
|
||||||
templateForm.value = {
|
|
||||||
...res,
|
|
||||||
name: route.params.mode === 'copy' ? `copy_${name}` : name,
|
|
||||||
};
|
|
||||||
if (route.params.mode === 'copy') {
|
|
||||||
templateForm.value.id = undefined;
|
|
||||||
}
|
|
||||||
selectData.value = getCustomDetailFields(totalTemplateField.value as DefinedFieldItem[], customFields);
|
|
||||||
systemFieldData.value = systemFields;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理表单数据格式
|
|
||||||
const getFieldOptionList = () => {
|
|
||||||
totalTemplateField.value = getTotalFieldOptionList(totalTemplateField.value as DefinedFieldItem[]);
|
|
||||||
// 创建默认系统字段
|
|
||||||
if (!isEdit.value && !isEditField.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取字段列表数据
|
|
||||||
const getClassifyField = async () => {
|
|
||||||
try {
|
|
||||||
totalTemplateField.value = await getProjectFieldList({
|
|
||||||
scopedId: currentProjectId.value,
|
|
||||||
scene: route.query.type,
|
|
||||||
});
|
|
||||||
getFieldOptionList();
|
|
||||||
// 编辑字段就需要单独处理过滤
|
|
||||||
if (isEditField.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter(
|
|
||||||
(item) => selectFiled.value.map((it) => it.id).indexOf(item.id) > -1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (isEdit.value) {
|
|
||||||
getTemplateInfo();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watchEffect(async () => {
|
|
||||||
if (isEdit.value && route.params.mode === 'copy') {
|
|
||||||
title.value = t('system.orgTemplate.copyTemplate', {
|
|
||||||
type: getTemplateName('organization', route.query.type as string),
|
|
||||||
});
|
|
||||||
getClassifyField();
|
|
||||||
} else if (isEdit.value) {
|
|
||||||
title.value = t('system.orgTemplate.editTemplateType', {
|
|
||||||
type: getTemplateName('organization', route.query.type as string),
|
|
||||||
});
|
|
||||||
getClassifyField();
|
|
||||||
} else {
|
|
||||||
title.value = t('system.orgTemplate.createTemplateType', {
|
|
||||||
type: getTemplateName('organization', route.query.type as string),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const initDefectForm = {
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
};
|
|
||||||
// 缺陷详情字段
|
|
||||||
const defectForm = ref<Record<string, any>>({ ...initDefectForm });
|
|
||||||
|
|
||||||
// 获取模板参数
|
|
||||||
function getTemplateParams(): ActionTemplateManage {
|
|
||||||
const result = selectData.value.map((item) => {
|
|
||||||
if (item.formRules?.length) {
|
|
||||||
const { value } = item.formRules[0];
|
|
||||||
return {
|
|
||||||
fieldId: item.id,
|
|
||||||
required: item.required,
|
|
||||||
apiFieldId: item.apiFieldId,
|
|
||||||
defaultValue: value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理缺陷系统详情字段
|
|
||||||
const sysDetailFields = Object.keys(defectForm.value).map((formKey: string) => {
|
|
||||||
return {
|
|
||||||
fieldId: formKey,
|
|
||||||
defaultValue: defectForm.value[formKey],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const { name, remark, enableThirdPart, id } = templateForm.value;
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
remark,
|
|
||||||
enableThirdPart,
|
|
||||||
customFields: result as CustomField[],
|
|
||||||
scopeId: currentProjectId.value,
|
|
||||||
scene: route.query.type,
|
|
||||||
systemFields: sysDetailFields,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetForm() {
|
|
||||||
templateForm.value = { ...initTemplateForm };
|
|
||||||
}
|
|
||||||
|
|
||||||
const isContinueFlag = ref(false);
|
|
||||||
|
|
||||||
// 保存回调
|
|
||||||
async function save() {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const params = getTemplateParams();
|
|
||||||
if (isEdit.value && route.params.mode !== 'copy') {
|
|
||||||
await updateProjectTemplateInfo(params);
|
|
||||||
Message.success(t('system.orgTemplate.updateSuccess'));
|
|
||||||
} else {
|
|
||||||
await createProjectTemplateInfo(params);
|
|
||||||
Message.success(t('system.orgTemplate.addSuccess'));
|
|
||||||
}
|
|
||||||
if (isContinueFlag.value) {
|
|
||||||
resetForm();
|
|
||||||
} else {
|
|
||||||
await sleep(300);
|
|
||||||
router.push({ name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT, query: route.query });
|
|
||||||
setState(true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存
|
|
||||||
function saveHandler(isContinue = false) {
|
|
||||||
isContinueFlag.value = isContinue;
|
|
||||||
formRef.value?.validate().then((res) => {
|
|
||||||
if (!res) {
|
|
||||||
return save();
|
|
||||||
}
|
|
||||||
return scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否预览模式
|
|
||||||
const isPreview = ref<boolean>(true); // 默认非预览模式
|
|
||||||
function togglePreview() {
|
|
||||||
isPreview.value = !isPreview.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算当前级别title
|
|
||||||
const breadTitle = computed(() => {
|
|
||||||
const firstBreadTitle = getCardList('organization').find((item: any) => item.key === route.query.type)?.name;
|
|
||||||
const ThirdBreadTitle = title.value;
|
|
||||||
return {
|
|
||||||
firstBreadTitle,
|
|
||||||
ThirdBreadTitle,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// 更新面包屑标题
|
|
||||||
const setBreadText = () => {
|
|
||||||
const { breadcrumbList } = appStore;
|
|
||||||
const { firstBreadTitle, ThirdBreadTitle } = breadTitle.value;
|
|
||||||
if (firstBreadTitle) {
|
|
||||||
breadcrumbList[0].locale = firstBreadTitle;
|
|
||||||
if (appStore.breadcrumbList.length > 2) {
|
|
||||||
breadcrumbList[2].locale = ThirdBreadTitle;
|
|
||||||
}
|
|
||||||
appStore.setBreadcrumbList(breadcrumbList);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 字段表编辑更新表
|
|
||||||
const updateHandler = (flag: boolean) => {
|
|
||||||
isEditField.value = flag;
|
|
||||||
selectFiled.value = selectData.value;
|
|
||||||
getClassifyField();
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => systemFieldData.value,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
defectForm.value = { ...initDefectForm };
|
|
||||||
systemFieldData.value.forEach((item) => {
|
|
||||||
defectForm.value[item.fieldId] = item.defaultValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// setBreadText();
|
|
||||||
getClassifyField();
|
|
||||||
if (!isEdit.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.rightBtn {
|
|
||||||
:deep(.arco-btn-outline) {
|
|
||||||
border-color: var(--color-text-input-border) !important;
|
|
||||||
color: var(--color-text-1) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -301,11 +301,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const routeName = ref<string>('');
|
||||||
// 创建模板
|
// 创建模板
|
||||||
const createTemplate = () => {
|
const createTemplate = () => {
|
||||||
router.push({
|
router.push({
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
},
|
},
|
||||||
|
@ -318,7 +318,7 @@
|
||||||
// 编辑模板
|
// 编辑模板
|
||||||
const editTemplate = (id: string) => {
|
const editTemplate = (id: string) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
id,
|
id,
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
|
@ -332,7 +332,7 @@
|
||||||
// 复制模板
|
// 复制模板
|
||||||
const copyTemplate = (id: string) => {
|
const copyTemplate = (id: string) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
id,
|
id,
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
|
@ -413,6 +413,13 @@
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
updateColumns();
|
updateColumns();
|
||||||
|
if (route.query.type === 'FUNCTIONAL') {
|
||||||
|
routeName.value = ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_CASE_DETAIL;
|
||||||
|
} else if (route.query.type === 'API') {
|
||||||
|
routeName.value = ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_API_DETAIL;
|
||||||
|
} else {
|
||||||
|
routeName.value = ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_API_DETAIL;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,713 @@
|
||||||
|
<template>
|
||||||
|
<MsCard
|
||||||
|
:loading="loading"
|
||||||
|
:title="title"
|
||||||
|
:is-edit="isEdit && route.params.mode !== 'copy'"
|
||||||
|
has-breadcrumb
|
||||||
|
:hide-back="true"
|
||||||
|
@save="saveHandler"
|
||||||
|
@save-and-continue="saveHandler(true)"
|
||||||
|
>
|
||||||
|
<template #headerLeft>
|
||||||
|
<a-alert v-if="templateForm.enableThirdPart && route.query.type === 'BUG'" class="mb-[16px] w-full">
|
||||||
|
{{ t('system.orgTemplate.enableApiAlert') }}
|
||||||
|
</a-alert>
|
||||||
|
<a-form ref="formRef" class="mt-1 max-w-[710px]" :model="templateForm">
|
||||||
|
<a-form-item
|
||||||
|
v-if="!templateForm?.internal"
|
||||||
|
field="name"
|
||||||
|
asterisk-position="end"
|
||||||
|
:hide-label="true"
|
||||||
|
hide-asterisk
|
||||||
|
:rules="[{ required: true, message: t('system.orgTemplate.templateNameRules') }]"
|
||||||
|
content-class="contentClass"
|
||||||
|
class="mb-0 max-w-[710px]"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:model-value="templateForm.name"
|
||||||
|
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
|
||||||
|
:max-length="255"
|
||||||
|
class="max-w-[732px]"
|
||||||
|
:disabled="templateForm?.internal"
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<span v-else class="font-medium text-[var(--color-text-1)] underline">{{ templateForm.name }}</span>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
<template #headerRight>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<!-- <a-select
|
||||||
|
v-if="templateForm.enableThirdPart && route.query.type === 'BUG'"
|
||||||
|
v-model="templateForm.platForm"
|
||||||
|
class="!my-0 w-[240px]"
|
||||||
|
:placeholder="t('system.orgTemplate.selectThirdPlatType')"
|
||||||
|
>
|
||||||
|
<a-option v-for="item of platFormList" :key="item.value" :value="item.value">{{ item.label }}</a-option>
|
||||||
|
</a-select> -->
|
||||||
|
<a-checkbox v-if="route.query.type === 'BUG'" v-model="templateForm.enableThirdPart" class="mx-2">{{
|
||||||
|
t('system.orgTemplate.thirdParty')
|
||||||
|
}}</a-checkbox>
|
||||||
|
<MsTag size="large" class="cursor-pointer" theme="outline" @click="brash">
|
||||||
|
<MsIcon class="text-[var(color-text-4)]" :size="16" type="icon-icon_reset_outlined" />
|
||||||
|
</MsTag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="wrapper-preview">
|
||||||
|
<div class="preview-left pr-4">
|
||||||
|
<DefectTemplateLeftContent v-if="route.query.type === 'BUG'" :defect-form="defectForm" />
|
||||||
|
<CaseTemplateLeftContent v-else />
|
||||||
|
</div>
|
||||||
|
<div class="preview-right px-4">
|
||||||
|
<!-- 自定义字段开始 -->
|
||||||
|
<VueDraggable v-model="selectData" handle=".form" ghost-class="ghost" @change="changeDrag">
|
||||||
|
<div v-for="(formItem, index) of selectData" :key="formItem.id" class="customWrapper">
|
||||||
|
<div class="action">
|
||||||
|
<span class="required">
|
||||||
|
<a-checkbox
|
||||||
|
v-model="formItem.required"
|
||||||
|
class="mr-1"
|
||||||
|
@change="(value) => changeState(value, formItem)"
|
||||||
|
>{{ t('ms.assertion.mustInclude') }}</a-checkbox
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<div class="actionList">
|
||||||
|
<a-tooltip :content="t('system.orgTemplate.toTop')">
|
||||||
|
<MsIcon
|
||||||
|
type="icon-icon_up_outlined"
|
||||||
|
size="16"
|
||||||
|
:class="getColor(index, 'top')"
|
||||||
|
@click="moveField(formItem as DefinedFieldItem, 'top')"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-divider direction="vertical" class="!m-0 !mx-2" />
|
||||||
|
<a-tooltip :content="t('system.orgTemplate.toBottom')">
|
||||||
|
<MsIcon
|
||||||
|
:class="getColor(index, 'bottom')"
|
||||||
|
type="icon-icon_down_outlined"
|
||||||
|
size="16"
|
||||||
|
@click="moveField(formItem as DefinedFieldItem, 'bottom')"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-divider v-if="!formItem.internal" direction="vertical" class="!m-0 !mx-2" />
|
||||||
|
<a-tooltip :content="t('common.edit')">
|
||||||
|
<MsIcon
|
||||||
|
v-if="!formItem.internal"
|
||||||
|
type="icon-icon_edit_outlined"
|
||||||
|
size="16"
|
||||||
|
@click="editField(formItem as DefinedFieldItem)"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-divider v-if="!formItem.internal" direction="vertical" class="!m-0 !mx-2" />
|
||||||
|
<a-tooltip :content="t('common.delete')">
|
||||||
|
<MsIcon
|
||||||
|
v-if="!formItem.internal"
|
||||||
|
type="icon-icon_delete-trash_outlined"
|
||||||
|
size="16"
|
||||||
|
@click="deleteSelectedField(formItem as DefinedFieldItem)"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="form"
|
||||||
|
:class="{
|
||||||
|
'hover:border-[var(--color-text-n8)]': activeIndex !== index,
|
||||||
|
'activeStyle': activeIndex === index,
|
||||||
|
}"
|
||||||
|
@click="activeHandler(index)"
|
||||||
|
>
|
||||||
|
<!-- 表单 -->
|
||||||
|
<MsFormCreate
|
||||||
|
v-model:api="formItem.api"
|
||||||
|
v-model:rule="formItem.formRules"
|
||||||
|
:option="configOptions"
|
||||||
|
@click="activeHandler(index)"
|
||||||
|
/>
|
||||||
|
<a-form
|
||||||
|
v-if="templateForm.enableThirdPart && route.query.type === 'BUG'"
|
||||||
|
:ref="(el: refItem) => setStepRefMap(el, formItem as DefinedFieldItem)"
|
||||||
|
:model="formItem"
|
||||||
|
>
|
||||||
|
<a-form-item
|
||||||
|
row-class="apiFieldIdClass"
|
||||||
|
hide-asterisk
|
||||||
|
hide-label
|
||||||
|
field="apiFieldId"
|
||||||
|
:rules="[{ required: true, message: t('system.orgTemplate.apiFieldNotEmpty') }]"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model:model-value="formItem.apiFieldId"
|
||||||
|
:placeholder="t('system.orgTemplate.pleaseEnterAPITip')"
|
||||||
|
class="mt-1"
|
||||||
|
:max-length="255"
|
||||||
|
/></a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VueDraggable>
|
||||||
|
<!-- 自定义字段结束 -->
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-button class="mr-1 mt-1 px-0" type="text" @click="associatedField">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus class="text-[14px]" />
|
||||||
|
</template>
|
||||||
|
{{ t('system.orgTemplate.associatedField') }}
|
||||||
|
</a-button>
|
||||||
|
<a-tooltip :content="t('system.orgTemplate.associatedHasField')" placement="top" effect="dark">
|
||||||
|
<IconQuestionCircle
|
||||||
|
class="mr-8 mt-1 h-[16px] w-[16px] text-[--color-text-4] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
|
<a-button class="mr-1 mt-1 px-0" type="text" :disabled="totalTemplateField.length >= 20" @click="createField">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus class="text-[14px]" />
|
||||||
|
</template>
|
||||||
|
{{ t('system.orgTemplate.addField') }}
|
||||||
|
</a-button>
|
||||||
|
<a-tooltip :content="t('system.orgTemplate.addFieldDesc')" placement="top" effect="dark">
|
||||||
|
<IconQuestionCircle
|
||||||
|
class="mt-1 h-[16px] w-[16px] text-[--color-text-4] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 添加字段到模板抽屉 -->
|
||||||
|
<AddFieldToTemplateDrawer
|
||||||
|
ref="fieldSelectRef"
|
||||||
|
v-model:visible="showDrawer"
|
||||||
|
:total-data="(totalTemplateField as DefinedFieldItem[])"
|
||||||
|
:table-select-data="(selectData as DefinedFieldItem[])"
|
||||||
|
:mode="props.mode"
|
||||||
|
@confirm="confirmHandler"
|
||||||
|
/>
|
||||||
|
<EditFieldDrawer
|
||||||
|
ref="fieldDrawerRef"
|
||||||
|
v-model:visible="showFieldDrawer"
|
||||||
|
:mode="props.mode"
|
||||||
|
@success="updateFieldHandler"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 模板-创建模板&编辑模板-预览模板
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import { VueDraggable } from 'vue-draggable-plus';
|
||||||
|
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
||||||
|
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
import AddFieldToTemplateDrawer from './addFieldToTemplateDrawer.vue';
|
||||||
|
import CaseTemplateLeftContent from './caseTemplateLeftContent.vue';
|
||||||
|
import DefectTemplateLeftContent from './defectTemplateLeftContent.vue';
|
||||||
|
import EditFieldDrawer from './editFieldDrawer.vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOrganizeTemplateInfo,
|
||||||
|
createProjectTemplateInfo,
|
||||||
|
getFieldList,
|
||||||
|
getOrganizeTemplateInfo,
|
||||||
|
getProjectFieldList,
|
||||||
|
getProjectTemplateInfo,
|
||||||
|
updateOrganizeTemplateInfo,
|
||||||
|
updateProjectTemplateInfo,
|
||||||
|
} from '@/api/modules/setting/template';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
|
import { sleep } from '@/utils';
|
||||||
|
import { scrollIntoView } from '@/utils/dom';
|
||||||
|
|
||||||
|
import type { ActionTemplateManage, CustomField, DefinedFieldItem, SeneType } from '@/models/setting/template';
|
||||||
|
import { ProjectManagementRouteEnum, SettingRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
|
import { getTemplateName, getTotalFieldOptionList } from './fieldSetting';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
|
}>();
|
||||||
|
|
||||||
|
type refItem = Element | ComponentPublicInstance | null;
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
|
const { setState } = useLeaveUnSaveTip();
|
||||||
|
|
||||||
|
setState(false);
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const title = ref('');
|
||||||
|
const initTemplateForm: ActionTemplateManage = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
remark: '',
|
||||||
|
scopeId: props.mode === 'organization' ? currentOrgId.value : currentProjectId.value,
|
||||||
|
enableThirdPart: false,
|
||||||
|
platForm: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const initBugForm = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const defectForm = ref({ ...initBugForm });
|
||||||
|
|
||||||
|
const isEdit = computed(() => !!route.query.id);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const templateForm = ref<ActionTemplateManage>({ ...initTemplateForm });
|
||||||
|
const isContinueFlag = ref(false);
|
||||||
|
|
||||||
|
const platFormList = ref<{ value: string; label: string }[]>([
|
||||||
|
{
|
||||||
|
value: 'zental',
|
||||||
|
label: '禅道',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'JIRA',
|
||||||
|
label: 'JIRA',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const templateApiMaps: Record<string, any> = {
|
||||||
|
organization: {
|
||||||
|
fieldList: getFieldList,
|
||||||
|
create: createOrganizeTemplateInfo,
|
||||||
|
update: updateOrganizeTemplateInfo,
|
||||||
|
detail: getOrganizeTemplateInfo,
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
fieldList: getProjectFieldList,
|
||||||
|
create: createProjectTemplateInfo,
|
||||||
|
update: updateProjectTemplateInfo,
|
||||||
|
detail: getProjectTemplateInfo,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const totalTemplateField = ref<DefinedFieldItem[]>([]);
|
||||||
|
const selectData = ref<DefinedFieldItem[]>([]);
|
||||||
|
|
||||||
|
// 获取模板参数
|
||||||
|
function getTemplateParams(): ActionTemplateManage {
|
||||||
|
const result = selectData.value.map((item) => {
|
||||||
|
if (item.formRules?.length) {
|
||||||
|
const { value } = item.formRules[0];
|
||||||
|
return {
|
||||||
|
fieldId: item.id,
|
||||||
|
required: item.required,
|
||||||
|
apiFieldId: item.apiFieldId || '',
|
||||||
|
defaultValue: value || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
const { name, remark, enableThirdPart, id } = templateForm.value;
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
remark,
|
||||||
|
enableThirdPart,
|
||||||
|
customFields: result as CustomField[],
|
||||||
|
scopeId: props.mode === 'organization' ? currentOrgId.value : currentProjectId.value,
|
||||||
|
scene: route.query.type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetForm() {
|
||||||
|
templateForm.value = { ...initTemplateForm };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存回调
|
||||||
|
async function save() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const params = getTemplateParams();
|
||||||
|
if (isEdit.value && route.params.mode !== 'copy') {
|
||||||
|
await templateApiMaps[props.mode].update(params);
|
||||||
|
Message.success(t('system.orgTemplate.updateSuccess'));
|
||||||
|
} else {
|
||||||
|
await templateApiMaps[props.mode].create(params);
|
||||||
|
Message.success(t('system.orgTemplate.addSuccess'));
|
||||||
|
}
|
||||||
|
if (isContinueFlag.value) {
|
||||||
|
resetForm();
|
||||||
|
} else {
|
||||||
|
await sleep(300);
|
||||||
|
if (props.mode === 'organization') {
|
||||||
|
router.push({ name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT, query: route.query });
|
||||||
|
} else {
|
||||||
|
router.push({ name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT, query: route.query });
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(true);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const refStepMap: Record<string, any> = {};
|
||||||
|
function setStepRefMap(el: refItem, formItem: DefinedFieldItem) {
|
||||||
|
if (el) {
|
||||||
|
refStepMap[`${formItem.id}`] = el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 保存
|
||||||
|
function saveHandler(isContinue = false) {
|
||||||
|
isContinueFlag.value = isContinue;
|
||||||
|
formRef.value?.validate().then((res) => {
|
||||||
|
if (!res) {
|
||||||
|
const allValidatePromises = Object.keys(refStepMap).map((key) => {
|
||||||
|
return refStepMap[key].validate();
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(allValidatePromises).then((results) => {
|
||||||
|
const allValid = results.every((result) => !result);
|
||||||
|
if (allValid) {
|
||||||
|
return save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理表单数据格式
|
||||||
|
const getFieldOptionList = () => {
|
||||||
|
totalTemplateField.value = getTotalFieldOptionList(totalTemplateField.value as DefinedFieldItem[]);
|
||||||
|
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取字段列表数据
|
||||||
|
const getClassifyField = async () => {
|
||||||
|
try {
|
||||||
|
totalTemplateField.value = await templateApiMaps[props.mode].fieldList({
|
||||||
|
scopedId: props.mode === 'organization' ? currentOrgId.value : currentProjectId.value,
|
||||||
|
scene: route.query.type,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect(async () => {
|
||||||
|
if (isEdit.value && route.params.mode === 'copy') {
|
||||||
|
title.value = t('system.orgTemplate.copyTemplate');
|
||||||
|
} else if (isEdit.value) {
|
||||||
|
title.value = t('system.orgTemplate.editTemplateType', {
|
||||||
|
type: getTemplateName('organization', route.query.type as string),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
title.value = t('system.orgTemplate.createTemplateType', {
|
||||||
|
type: getTemplateName('organization', route.query.type as string),
|
||||||
|
});
|
||||||
|
templateForm.value.name = title.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const showFieldDrawer = ref<boolean>(false);
|
||||||
|
function createField() {
|
||||||
|
showFieldDrawer.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const showDrawer = ref<boolean>(false);
|
||||||
|
function associatedField() {
|
||||||
|
showDrawer.value = true;
|
||||||
|
}
|
||||||
|
const selectFiled = ref<DefinedFieldItem[]>([]);
|
||||||
|
const selectedIds = ref<string[]>();
|
||||||
|
|
||||||
|
// 编辑更新已选择字段
|
||||||
|
const isEditField = ref<boolean>(false);
|
||||||
|
|
||||||
|
// 添加字段或编辑字段
|
||||||
|
const updateFieldHandler = async (editFlag: boolean, fieldId: string) => {
|
||||||
|
selectFiled.value = selectData.value;
|
||||||
|
isEditField.value = editFlag;
|
||||||
|
await getClassifyField();
|
||||||
|
totalTemplateField.value = getTotalFieldOptionList(totalTemplateField.value as DefinedFieldItem[]);
|
||||||
|
// 编辑字段
|
||||||
|
if (isEditField.value) {
|
||||||
|
const index = selectData.value.findIndex((e: any) => e.id === fieldId);
|
||||||
|
const newUpdateData = totalTemplateField.value.find((item: any) => item.id === fieldId);
|
||||||
|
if (index > -1 && newUpdateData) {
|
||||||
|
selectData.value.splice(index, 1);
|
||||||
|
selectData.value.splice(index, 0, newUpdateData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 新增字段
|
||||||
|
if (!isEditField.value && fieldId) {
|
||||||
|
const newUpdateData = totalTemplateField.value.find((item: any) => item.id === fieldId);
|
||||||
|
if (newUpdateData) {
|
||||||
|
selectData.value.push(newUpdateData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除已选择字段
|
||||||
|
const deleteSelectedField = (record: DefinedFieldItem) => {
|
||||||
|
selectData.value = selectData.value.filter((item) => item.id !== record.id);
|
||||||
|
};
|
||||||
|
const fieldDrawerRef = ref();
|
||||||
|
// 编辑字段
|
||||||
|
const editField = (record: DefinedFieldItem) => {
|
||||||
|
showFieldDrawer.value = true;
|
||||||
|
fieldDrawerRef.value.editHandler(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确定处理字段表单数据
|
||||||
|
const confirmHandler = (dataList: DefinedFieldItem[]) => {
|
||||||
|
const selectFieldIds = selectData.value.map((e) => e.id);
|
||||||
|
const newData = dataList.filter((item) => !selectFieldIds.includes(item.id));
|
||||||
|
selectData.value = [...selectData.value, ...newData];
|
||||||
|
};
|
||||||
|
|
||||||
|
function changeState(value: boolean | (string | number | boolean)[], formItem) {
|
||||||
|
formItem.required = value;
|
||||||
|
formItem.formRules[0].effect.required = value;
|
||||||
|
}
|
||||||
|
const systemFieldData = ref<CustomField[]>([]);
|
||||||
|
|
||||||
|
function getSelectData(customFields: DefinedFieldItem[]) {
|
||||||
|
return customFields.map((item: any) => {
|
||||||
|
const currentFormRules = FieldTypeFormRules[item.type];
|
||||||
|
let selectOptions: any = [];
|
||||||
|
if (item.options && item.options.length) {
|
||||||
|
selectOptions = item.options.map((optionItem: any) => {
|
||||||
|
return {
|
||||||
|
label: optionItem.text,
|
||||||
|
value: optionItem.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
currentFormRules.options = selectOptions;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
id: item.fieldId,
|
||||||
|
formRules: [
|
||||||
|
{
|
||||||
|
...currentFormRules,
|
||||||
|
title: item.fieldName,
|
||||||
|
effect: {
|
||||||
|
required: item.required,
|
||||||
|
},
|
||||||
|
value: item.defaultValue,
|
||||||
|
props: { ...currentFormRules.props, options: selectOptions, modelValue: item.defaultValue },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fApi: null,
|
||||||
|
required: item.required,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 获取模板详情
|
||||||
|
const getTemplateInfo = async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await templateApiMaps[props.mode].detail(route.query.id as string);
|
||||||
|
const { name, customFields, systemFields } = res;
|
||||||
|
templateForm.value = {
|
||||||
|
...res,
|
||||||
|
name: route.params.mode === 'copy' ? `copy_${name}` : name,
|
||||||
|
};
|
||||||
|
if (route.params.mode === 'copy') {
|
||||||
|
templateForm.value.id = undefined;
|
||||||
|
}
|
||||||
|
selectData.value = getSelectData(customFields);
|
||||||
|
systemFieldData.value = systemFields;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function moveField(formItem: DefinedFieldItem, type: string) {
|
||||||
|
const moveIndex = selectData.value.findIndex((item: any) => item.id === formItem.id);
|
||||||
|
if (type === 'top') {
|
||||||
|
if (moveIndex === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectData.value.splice(moveIndex, 1);
|
||||||
|
selectData.value.splice(moveIndex - 1, 0, formItem);
|
||||||
|
} else {
|
||||||
|
if (moveIndex === selectData.value.length - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectData.value.splice(moveIndex, 1);
|
||||||
|
selectData.value.splice(moveIndex + 1, 0, formItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColor(index: number, type: string) {
|
||||||
|
if (type === 'top' && index === 0) {
|
||||||
|
return ['text-[rgb(var(--primary-3))]'];
|
||||||
|
}
|
||||||
|
if (type === 'bottom' && index === selectData.value.length - 1) {
|
||||||
|
return ['text-[rgb(var(--primary-3))]'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getClassifyField();
|
||||||
|
getFieldOptionList();
|
||||||
|
if (isEdit.value) {
|
||||||
|
getTemplateInfo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeIndex = ref(-1);
|
||||||
|
async function brash() {
|
||||||
|
activeIndex.value = -1;
|
||||||
|
await getClassifyField();
|
||||||
|
getFieldOptionList();
|
||||||
|
if (isEdit.value) {
|
||||||
|
getTemplateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeHandler(index: number) {
|
||||||
|
activeIndex.value = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeDrag() {
|
||||||
|
activeIndex.value = -1;
|
||||||
|
}
|
||||||
|
const configOptions = ref({
|
||||||
|
resetBtn: false,
|
||||||
|
submitBtn: false,
|
||||||
|
on: false,
|
||||||
|
form: {
|
||||||
|
layout: 'vertical',
|
||||||
|
labelAlign: 'left',
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
gutter: 0,
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
'asterisk-position': 'end',
|
||||||
|
'validate-trigger': ['change'],
|
||||||
|
'row-class': 'selfClass',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.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;
|
||||||
|
right: 16px;
|
||||||
|
z-index: 99999999 !important;
|
||||||
|
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%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
:deep(.contentClass > .arco-input-wrapper) {
|
||||||
|
border-color: transparent;
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-text-input-border);
|
||||||
|
}
|
||||||
|
&:hover > .arco-input {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
& > .arco-input {
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--color-text-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.contentClass > .arco-input-focus) {
|
||||||
|
border-color: rgb(var(--primary-5));
|
||||||
|
& > .arco-input {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ghost {
|
||||||
|
border: 1px solid rgba(var(--primary-5));
|
||||||
|
background-color: var(--color-text-n9);
|
||||||
|
}
|
||||||
|
:deep(.apiFieldIdClass) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<template>
|
||||||
|
<AddTemplate mode="organization" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import AddTemplate from './addTemplate.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -252,6 +252,7 @@
|
||||||
// 保存
|
// 保存
|
||||||
const confirmHandler = async (isContinue = false) => {
|
const confirmHandler = async (isContinue = false) => {
|
||||||
try {
|
try {
|
||||||
|
drawerLoading.value = true;
|
||||||
const formCopy = cloneDeep(fieldForm.value);
|
const formCopy = cloneDeep(fieldForm.value);
|
||||||
|
|
||||||
formCopy.scene = route.query.type;
|
formCopy.scene = route.query.type;
|
||||||
|
@ -287,13 +288,13 @@
|
||||||
if (id) {
|
if (id) {
|
||||||
params.id = id;
|
params.id = id;
|
||||||
}
|
}
|
||||||
await addOrUpdate(params);
|
const res = await addOrUpdate(params);
|
||||||
Message.success(isEdit.value ? t('common.updateSuccess') : t('common.newSuccess'));
|
Message.success(isEdit.value ? t('common.updateSuccess') : t('common.newSuccess'));
|
||||||
if (!isContinue) {
|
if (!isContinue) {
|
||||||
handleDrawerCancel();
|
handleDrawerCancel();
|
||||||
}
|
}
|
||||||
resetForm();
|
resetForm();
|
||||||
emit('success', isEdit.value);
|
emit('success', isEdit.value, res.id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -302,15 +303,16 @@
|
||||||
};
|
};
|
||||||
const fieldDefaultValues = ref<FormItemModel[]>([]);
|
const fieldDefaultValues = ref<FormItemModel[]>([]);
|
||||||
function userFormFiledValidate(cb: () => Promise<any>) {
|
function userFormFiledValidate(cb: () => Promise<any>) {
|
||||||
fieldFormRef.value?.validate((errors: undefined | Record<string, ValidatedError>) => {
|
fieldFormRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||||
if (errors) {
|
if (errors) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (showOptionsSelect.value) {
|
||||||
batchFormRef.value?.formValidate(async (list: any) => {
|
batchFormRef.value?.formValidate(async (list: any) => {
|
||||||
try {
|
try {
|
||||||
drawerLoading.value = true;
|
drawerLoading.value = true;
|
||||||
fieldDefaultValues.value = [...list];
|
fieldDefaultValues.value = [...list];
|
||||||
if (showOptionsSelect) {
|
if (showOptionsSelect.value) {
|
||||||
fieldForm.value.options = (batchFormRef.value?.getFormResult() || []).map((item: any) => {
|
fieldForm.value.options = (batchFormRef.value?.getFormResult() || []).map((item: any) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
@ -326,6 +328,9 @@
|
||||||
drawerLoading.value = false;
|
drawerLoading.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await cb();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,21 +347,6 @@
|
||||||
|
|
||||||
// 字段类型列表选项
|
// 字段类型列表选项
|
||||||
const fieldOptions = ref<fieldIconAndNameModal[]>([]);
|
const fieldOptions = ref<fieldIconAndNameModal[]>([]);
|
||||||
|
|
||||||
// 获取字段选项详情
|
|
||||||
const getFieldDetail = async (id: string) => {
|
|
||||||
try {
|
|
||||||
const fieldDetail = await detail(id);
|
|
||||||
fieldDefaultValues.value = fieldDetail.options.map((item: any) => {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理特殊情况编辑回显
|
// 处理特殊情况编辑回显
|
||||||
const getSpecialHandler = (itemType: FormItemType): FormItemType => {
|
const getSpecialHandler = (itemType: FormItemType): FormItemType => {
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
|
@ -377,16 +367,30 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取字段选项详情
|
||||||
|
const getFieldDetail = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const fieldDetail = await detail(id);
|
||||||
|
fieldForm.value = {
|
||||||
|
...fieldDetail,
|
||||||
|
type: getSpecialHandler(fieldDetail.type),
|
||||||
|
};
|
||||||
|
fieldDefaultValues.value = fieldDetail.options.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 编辑
|
// 编辑
|
||||||
const editHandler = (item: AddOrUpdateField) => {
|
const editHandler = (item: AddOrUpdateField) => {
|
||||||
showDrawer.value = true;
|
showDrawer.value = true;
|
||||||
isMultipleSelectMember.value = item.type === 'MULTIPLE_MEMBER';
|
isMultipleSelectMember.value = item.type === 'MULTIPLE_MEMBER';
|
||||||
if (item.id) {
|
if (item.id) {
|
||||||
getFieldDetail(item.id);
|
getFieldDetail(item.id);
|
||||||
fieldForm.value = {
|
|
||||||
...item,
|
|
||||||
type: getSpecialHandler(item.type),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -281,11 +281,15 @@ export const getTotalFieldOptionList = (totalData: DefinedFieldItem[]) => {
|
||||||
formRules: [
|
formRules: [
|
||||||
{
|
{
|
||||||
...currentFormRules,
|
...currentFormRules,
|
||||||
|
title: item.name,
|
||||||
|
effect: {
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
props: { ...currentFormRules.props, options: selectOptions },
|
props: { ...currentFormRules.props, options: selectOptions },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
fApi: null,
|
fApi: null,
|
||||||
required: item.internal,
|
required: false,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -305,6 +309,9 @@ export const getCustomDetailFields = (totalData: DefinedFieldItem[], customField
|
||||||
return {
|
return {
|
||||||
...it,
|
...it,
|
||||||
value: customFields[currentCustomFieldIndex].defaultValue,
|
value: customFields[currentCustomFieldIndex].defaultValue,
|
||||||
|
effect: {
|
||||||
|
required: item.required,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const formItem = item;
|
const formItem = item;
|
||||||
|
|
|
@ -1,368 +0,0 @@
|
||||||
<template>
|
|
||||||
<MsCard
|
|
||||||
:loading="loading"
|
|
||||||
:title="title"
|
|
||||||
:is-edit="isEdit && route.params.mode !== 'copy'"
|
|
||||||
has-breadcrumb
|
|
||||||
@save="saveHandler"
|
|
||||||
@save-and-continue="saveHandler(true)"
|
|
||||||
>
|
|
||||||
<template #headerRight>
|
|
||||||
<div class="rightBtn">
|
|
||||||
<a-button v-show="isPreview" type="outline" class="text-[var(--color-text-1)]" @click="togglePreview">{{
|
|
||||||
t('system.orgTemplate.templatePreview')
|
|
||||||
}}</a-button>
|
|
||||||
<a-button v-show="!isPreview" type="outline" class="text-[var(--color-text-1)]" @click="togglePreview">{{
|
|
||||||
t('system.orgTemplate.exitPreview')
|
|
||||||
}}</a-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<!-- 非预览模式 -->
|
|
||||||
<div v-if="isPreview" class="nonPreview">
|
|
||||||
<a-form ref="formRef" :model="templateForm" layout="vertical">
|
|
||||||
<a-form-item
|
|
||||||
:label="t('system.orgTemplate.templateName')"
|
|
||||||
field="name"
|
|
||||||
asterisk-position="end"
|
|
||||||
:rules="[{ required: true, message: t('system.orgTemplate.templateNameRules') }]"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model:model-value="templateForm.name"
|
|
||||||
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
|
|
||||||
:max-length="255"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
:disabled="templateForm?.internal"
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="remark" :label="t('system.orgTemplate.description')" asterisk-position="end">
|
|
||||||
<a-textarea
|
|
||||||
v-model="templateForm.remark"
|
|
||||||
:max-length="1000"
|
|
||||||
:placeholder="t('system.orgTemplate.resDescription')"
|
|
||||||
:auto-size="{ minRows: 1 }"
|
|
||||||
style="resize: vertical"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
></a-textarea>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="route.query.type === 'BUG'" field="remark" label="" asterisk-position="end"
|
|
||||||
><a-checkbox v-model="templateForm.enableThirdPart">{{ t('system.orgTemplate.thirdParty') }}</a-checkbox>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
v-if="route.query.type === 'BUG'"
|
|
||||||
field="fieldType"
|
|
||||||
:label="t('system.orgTemplate.columnFieldType')"
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-radio-group v-model="fieldType" type="button">
|
|
||||||
<a-radio value="custom">{{ t('system.orgTemplate.custom') }}</a-radio>
|
|
||||||
<a-radio value="detail">{{ t('system.orgTemplate.details') }}</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<!-- 已有字段表 -->
|
|
||||||
<TemplateManagementTable
|
|
||||||
v-if="fieldType === 'custom'"
|
|
||||||
ref="templateFieldTableRef"
|
|
||||||
v-model:select-data="selectData"
|
|
||||||
:data="(totalTemplateField as DefinedFieldItem[])"
|
|
||||||
:enable-third-part="templateForm.enableThirdPart"
|
|
||||||
mode="organization"
|
|
||||||
@update="updateHandler"
|
|
||||||
/>
|
|
||||||
<!-- 缺陷详情表 -->
|
|
||||||
<a-form
|
|
||||||
v-if="fieldType === 'detail'"
|
|
||||||
ref="defectFormRef"
|
|
||||||
class="rounded-[4px]"
|
|
||||||
:model="defectForm"
|
|
||||||
layout="vertical"
|
|
||||||
>
|
|
||||||
<a-form-item
|
|
||||||
field="name"
|
|
||||||
:label="t('system.orgTemplate.defectName')"
|
|
||||||
:rules="[{ required: true, message: t('system.orgTemplate.defectNamePlaceholder') }]"
|
|
||||||
required
|
|
||||||
class="max-w-[732px]"
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model="defectForm.name"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('system.orgTemplate.defectNamePlaceholder')"
|
|
||||||
allow-clear
|
|
||||||
></a-input>
|
|
||||||
<MsFormItemSub :text="t('system.orgTemplate.defectNameTip')" :show-fill-icon="false" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
field="precondition"
|
|
||||||
:label="t('system.orgTemplate.defectContent')"
|
|
||||||
asterisk-position="end"
|
|
||||||
class="max-w-[732px]"
|
|
||||||
>
|
|
||||||
<MsRichText v-model:raw="defectForm.description" />
|
|
||||||
<MsFormItemSub :text="t('system.orgTemplate.defectContentTip')" :show-fill-icon="false" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
<!-- 预览模式 -->
|
|
||||||
<PreviewTemplate
|
|
||||||
v-else
|
|
||||||
:select-field="(selectData as DefinedFieldItem[])"
|
|
||||||
:template-type="route.query.type"
|
|
||||||
:defect-form="defectForm"
|
|
||||||
/>
|
|
||||||
</MsCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
/**
|
|
||||||
* @description 系统管理-组织-模板-模板管理-创建&编辑
|
|
||||||
*/
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
|
||||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
|
||||||
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
|
||||||
import TemplateManagementTable from './templateManagementTable.vue';
|
|
||||||
import PreviewTemplate from './viewTemplate.vue';
|
|
||||||
|
|
||||||
import {
|
|
||||||
createOrganizeTemplateInfo,
|
|
||||||
getFieldList,
|
|
||||||
getOrganizeTemplateInfo,
|
|
||||||
updateOrganizeTemplateInfo,
|
|
||||||
} from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import useLeaveUnSaveTip from '@/hooks/useLeaveUnSaveTip';
|
|
||||||
import { useAppStore } from '@/store';
|
|
||||||
import { sleep } from '@/utils';
|
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
|
||||||
|
|
||||||
import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template';
|
|
||||||
import { SettingRouteEnum } from '@/enums/routeEnum';
|
|
||||||
|
|
||||||
import { getCardList, getCustomDetailFields, getTemplateName, getTotalFieldOptionList } from './fieldSetting';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
|
||||||
const { setState } = useLeaveUnSaveTip();
|
|
||||||
|
|
||||||
setState(false);
|
|
||||||
|
|
||||||
const title = ref('');
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
const initTemplateForm: ActionTemplateManage = {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
remark: '',
|
|
||||||
scopeId: currentOrgId.value,
|
|
||||||
enableThirdPart: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const fieldType = ref<string>('custom'); // 缺陷模板字段类型
|
|
||||||
|
|
||||||
const templateForm = ref<ActionTemplateManage>({ ...initTemplateForm });
|
|
||||||
|
|
||||||
const selectData = ref<DefinedFieldItem[]>([]); // 表格已选择字段
|
|
||||||
const selectFiled = ref<DefinedFieldItem[]>([]);
|
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
|
||||||
const totalTemplateField = ref<DefinedFieldItem[]>([]);
|
|
||||||
const isEdit = computed(() => !!route.query.id);
|
|
||||||
const isEditField = ref<boolean>(false);
|
|
||||||
const systemFieldData = ref<CustomField[]>([]);
|
|
||||||
|
|
||||||
// 获取模板详情
|
|
||||||
const getTemplateInfo = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const res = await getOrganizeTemplateInfo(route.query.id as string);
|
|
||||||
const { name, customFields, systemFields } = res;
|
|
||||||
templateForm.value = {
|
|
||||||
...res,
|
|
||||||
name: route.params.mode === 'copy' ? `copy_${name}` : name,
|
|
||||||
};
|
|
||||||
if (route.params.mode === 'copy') {
|
|
||||||
templateForm.value.id = undefined;
|
|
||||||
}
|
|
||||||
selectData.value = getCustomDetailFields(totalTemplateField.value as DefinedFieldItem[], customFields);
|
|
||||||
systemFieldData.value = systemFields;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理表单数据格式
|
|
||||||
const getFieldOptionList = () => {
|
|
||||||
totalTemplateField.value = getTotalFieldOptionList(totalTemplateField.value as DefinedFieldItem[]);
|
|
||||||
// 创建默认系统字段
|
|
||||||
if (!isEdit.value && !isEditField.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取字段列表数据
|
|
||||||
const getClassifyField = async () => {
|
|
||||||
try {
|
|
||||||
totalTemplateField.value = await getFieldList({ scopedId: currentOrgId.value, scene: route.query.type });
|
|
||||||
getFieldOptionList();
|
|
||||||
// 编辑字段需要单独处理过滤
|
|
||||||
if (isEditField.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter(
|
|
||||||
(item) => selectFiled.value.map((it) => it.id).indexOf(item.id) > -1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (isEdit.value) {
|
|
||||||
getTemplateInfo();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watchEffect(async () => {
|
|
||||||
if (isEdit.value && route.params.mode === 'copy') {
|
|
||||||
title.value = t('system.orgTemplate.copyTemplate');
|
|
||||||
getClassifyField();
|
|
||||||
} else if (isEdit.value) {
|
|
||||||
title.value = t('system.orgTemplate.editTemplateType', {
|
|
||||||
type: getTemplateName('organization', route.query.type as string),
|
|
||||||
});
|
|
||||||
getClassifyField();
|
|
||||||
} else {
|
|
||||||
title.value = t('system.orgTemplate.createTemplateType', {
|
|
||||||
type: getTemplateName('organization', route.query.type as string),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const defectForm = ref<Record<string, any>>({}); // 缺陷详情表单
|
|
||||||
|
|
||||||
// 获取模板参数
|
|
||||||
function getTemplateParams(): ActionTemplateManage {
|
|
||||||
const result = selectData.value.map((item) => {
|
|
||||||
if (item.formRules?.length) {
|
|
||||||
const { value } = item.formRules[0];
|
|
||||||
return {
|
|
||||||
fieldId: item.id,
|
|
||||||
required: item.required,
|
|
||||||
apiFieldId: item.apiFieldId || '',
|
|
||||||
defaultValue: value || '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理缺陷系统详情字段
|
|
||||||
const sysDetailFields = Object.keys(defectForm.value).map((formKey: string) => {
|
|
||||||
return {
|
|
||||||
fieldId: formKey,
|
|
||||||
defaultValue: defectForm.value[formKey],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const { name, remark, enableThirdPart, id } = templateForm.value;
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
remark,
|
|
||||||
enableThirdPart,
|
|
||||||
customFields: result as CustomField[],
|
|
||||||
scopeId: currentOrgId.value,
|
|
||||||
scene: route.query.type,
|
|
||||||
systemFields: sysDetailFields,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetForm() {
|
|
||||||
templateForm.value = { ...initTemplateForm };
|
|
||||||
}
|
|
||||||
|
|
||||||
const isContinueFlag = ref(false);
|
|
||||||
|
|
||||||
// 保存回调
|
|
||||||
async function save() {
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const params = getTemplateParams();
|
|
||||||
if (isEdit.value && route.params.mode !== 'copy') {
|
|
||||||
await updateOrganizeTemplateInfo(params);
|
|
||||||
Message.success(t('system.orgTemplate.updateSuccess'));
|
|
||||||
} else {
|
|
||||||
await createOrganizeTemplateInfo(params);
|
|
||||||
Message.success(t('system.orgTemplate.addSuccess'));
|
|
||||||
}
|
|
||||||
if (isContinueFlag.value) {
|
|
||||||
resetForm();
|
|
||||||
} else {
|
|
||||||
await sleep(300);
|
|
||||||
router.push({ name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT, query: route.query });
|
|
||||||
setState(true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存
|
|
||||||
function saveHandler(isContinue = false) {
|
|
||||||
isContinueFlag.value = isContinue;
|
|
||||||
formRef.value?.validate().then((res) => {
|
|
||||||
if (!res) {
|
|
||||||
return save();
|
|
||||||
}
|
|
||||||
return scrollIntoView(document.querySelector('.arco-form-item-message'), { block: 'center' });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否预览模式
|
|
||||||
const isPreview = ref<boolean>(true); // 默认非预览模式
|
|
||||||
function togglePreview() {
|
|
||||||
isPreview.value = !isPreview.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字段表编辑更新表
|
|
||||||
const updateHandler = (flag: boolean) => {
|
|
||||||
isEditField.value = flag;
|
|
||||||
selectFiled.value = selectData.value;
|
|
||||||
getClassifyField();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 缺陷详情表单回显
|
|
||||||
watch(
|
|
||||||
() => systemFieldData.value,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
systemFieldData.value.forEach((item) => {
|
|
||||||
defectForm.value[item.fieldId] = item.defaultValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getClassifyField();
|
|
||||||
if (!isEdit.value) {
|
|
||||||
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.rightBtn {
|
|
||||||
:deep(.arco-btn-outline) {
|
|
||||||
border-color: var(--color-text-input-border) !important;
|
|
||||||
color: var(--color-text-1) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -230,10 +230,12 @@
|
||||||
await loadList();
|
await loadList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const routeName = ref<string>('');
|
||||||
|
|
||||||
// 创建模板
|
// 创建模板
|
||||||
const createTemplate = () => {
|
const createTemplate = () => {
|
||||||
router.push({
|
router.push({
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
},
|
},
|
||||||
|
@ -246,7 +248,7 @@
|
||||||
// 编辑模板
|
// 编辑模板
|
||||||
const editTemplate = (id: string) => {
|
const editTemplate = (id: string) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
id,
|
id,
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
|
@ -260,7 +262,7 @@
|
||||||
// 复制模板
|
// 复制模板
|
||||||
const copyTemplate = (id: string) => {
|
const copyTemplate = (id: string) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL,
|
name: routeName.value,
|
||||||
query: {
|
query: {
|
||||||
id,
|
id,
|
||||||
type: route.query.type,
|
type: route.query.type,
|
||||||
|
@ -307,6 +309,13 @@
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
updateColumns();
|
updateColumns();
|
||||||
|
if (route.query.type === 'FUNCTIONAL') {
|
||||||
|
routeName.value = SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_CASE_DETAIL;
|
||||||
|
} else if (route.query.type === 'API') {
|
||||||
|
routeName.value = SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_API_DETAIL;
|
||||||
|
} else {
|
||||||
|
routeName.value = SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_BUG_DETAIL;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,296 +0,0 @@
|
||||||
<template>
|
|
||||||
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
|
||||||
<template #name="{ record }">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<MsIcon v-if="!record.internal" :type="getIconType(record.type)?.iconName || ''" size="16" />
|
|
||||||
<span class="ml-2">{{ record.name }}</span>
|
|
||||||
<MsTag v-if="record.internal" size="small" class="ml-2">{{ t('system.orgTemplate.isSystem') }}</MsTag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #apiFieldId="{ record }">
|
|
||||||
<a-input
|
|
||||||
v-model="record.apiFieldId"
|
|
||||||
:max-length="255"
|
|
||||||
class="min-w-[200px] max-w-[300px]"
|
|
||||||
:placeholder="t('system.orgTemplate.apiInputPlaceholder')"
|
|
||||||
allow-clear
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #defaultValue="{ record }">
|
|
||||||
<div class="form-create-wrapper w-full">
|
|
||||||
<MsFormCreate v-model:api="record.fApi" :rule="record.formRules" :option="configOptions" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #required="{ record }">
|
|
||||||
<a-checkbox v-model="record.required"></a-checkbox>
|
|
||||||
</template>
|
|
||||||
<template #operation="{ record }">
|
|
||||||
<div class="flex flex-row flex-nowrap">
|
|
||||||
<MsButton class="!mr-0" @click="editField(record)">{{ t('system.orgTemplate.edit') }}</MsButton>
|
|
||||||
<a-divider v-if="!record.internal" direction="vertical" />
|
|
||||||
<MsButton v-if="!record.internal" class="!mr-0" @click="deleteSelectedField(record)">{{
|
|
||||||
t('system.orgTemplate.delete')
|
|
||||||
}}</MsButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</MsBaseTable>
|
|
||||||
<!-- 添加字段到模板抽屉 -->
|
|
||||||
<AddFieldToTemplateDrawer
|
|
||||||
ref="fieldSelectRef"
|
|
||||||
v-model:visible="showDrawer"
|
|
||||||
:total-data="(totalData as DefinedFieldItem[])"
|
|
||||||
:table-select-data="(selectList as DefinedFieldItem[])"
|
|
||||||
:mode="props.mode"
|
|
||||||
@confirm="confirmHandler"
|
|
||||||
@update-data="updateFieldHandler"
|
|
||||||
/>
|
|
||||||
<a-button class="mt-3 px-0" type="text" @click="addField">
|
|
||||||
<template #icon>
|
|
||||||
<icon-plus class="text-[14px]" />
|
|
||||||
</template>
|
|
||||||
{{ t('system.orgTemplate.createField') }}
|
|
||||||
</a-button>
|
|
||||||
<EditFieldDrawer
|
|
||||||
ref="fieldDrawerRef"
|
|
||||||
v-model:visible="showFieldDrawer"
|
|
||||||
:mode="props.mode"
|
|
||||||
@success="updateFieldHandler"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
/**
|
|
||||||
* @description 系统管理-组织-模板管理-创建模板-非缺陷模板自定义字段表格
|
|
||||||
*/
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
|
||||||
import AddFieldToTemplateDrawer from './addFieldToTemplateDrawer.vue';
|
|
||||||
import EditFieldDrawer from './editFieldDrawer.vue';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
|
|
||||||
import type { DefinedFieldItem } from '@/models/setting/template';
|
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
|
||||||
|
|
||||||
import { getIconType } from './fieldSetting';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
mode: 'organization' | 'project';
|
|
||||||
enableThirdPart: boolean; // 是否对接第三方平台
|
|
||||||
data: DefinedFieldItem[]; // 总字段数据
|
|
||||||
selectData: Record<string, any>[]; // 选择数据
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
enableThirdPart: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:select-data', 'update']);
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.name',
|
|
||||||
slotName: 'name',
|
|
||||||
dataIndex: 'name',
|
|
||||||
width: 300,
|
|
||||||
fixed: 'left',
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
showTooltip: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.defaultValue',
|
|
||||||
dataIndex: 'defaultValue',
|
|
||||||
slotName: 'defaultValue',
|
|
||||||
width: 300,
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.required',
|
|
||||||
dataIndex: 'required',
|
|
||||||
slotName: 'required',
|
|
||||||
width: 180,
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.description',
|
|
||||||
dataIndex: 'remark',
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
showTooltip: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.operation',
|
|
||||||
slotName: 'operation',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
fixed: 'right',
|
|
||||||
width: 200,
|
|
||||||
showInTable: true,
|
|
||||||
showDrag: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function getApiColumns() {
|
|
||||||
return {
|
|
||||||
title: 'system.orgTemplate.apiFieldId',
|
|
||||||
dataIndex: 'apiFieldId',
|
|
||||||
slotName: 'apiFieldId',
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
width: 300,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableRef = ref();
|
|
||||||
|
|
||||||
const { propsRes, propsEvent, setProps } = useTable(undefined, {
|
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_FIELD,
|
|
||||||
columns,
|
|
||||||
scroll: { x: '1800px' },
|
|
||||||
selectable: false,
|
|
||||||
noDisable: true,
|
|
||||||
size: 'default',
|
|
||||||
showSetting: false,
|
|
||||||
showPagination: false,
|
|
||||||
enableDrag: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const configOptions = ref({
|
|
||||||
resetBtn: false,
|
|
||||||
submitBtn: false,
|
|
||||||
on: false,
|
|
||||||
form: {
|
|
||||||
layout: 'vertical',
|
|
||||||
labelAlign: 'left',
|
|
||||||
},
|
|
||||||
row: {
|
|
||||||
gutter: 0,
|
|
||||||
},
|
|
||||||
wrap: {
|
|
||||||
'asterisk-position': 'end',
|
|
||||||
'validate-trigger': ['change'],
|
|
||||||
'hide-label': true,
|
|
||||||
'hide-asterisk': true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const showDrawer = ref<boolean>(false);
|
|
||||||
const totalData = ref<DefinedFieldItem[]>([]);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
totalData.value = props.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectList = ref<DefinedFieldItem[]>([]);
|
|
||||||
|
|
||||||
// 确定处理字段表单数据
|
|
||||||
const confirmHandler = (dataList: DefinedFieldItem[]) => {
|
|
||||||
selectList.value = dataList;
|
|
||||||
};
|
|
||||||
|
|
||||||
const showFieldDrawer = ref<boolean>(false);
|
|
||||||
const fieldDrawerRef = ref();
|
|
||||||
|
|
||||||
// 编辑字段
|
|
||||||
const editField = (record: DefinedFieldItem) => {
|
|
||||||
showFieldDrawer.value = true;
|
|
||||||
fieldDrawerRef.value.editHandler(record);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加字段
|
|
||||||
const addField = async () => {
|
|
||||||
showDrawer.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 编辑更新已选择字段
|
|
||||||
const updateFieldHandler = async (isEdit: boolean) => {
|
|
||||||
emit('update', isEdit);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除已选择字段
|
|
||||||
const deleteSelectedField = (record: DefinedFieldItem) => {
|
|
||||||
selectList.value = selectList.value.filter((item) => item.id !== record.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => selectList.value,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
emit('update:select-data', val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.selectData,
|
|
||||||
(val) => {
|
|
||||||
if (val) {
|
|
||||||
selectList.value = val as DefinedFieldItem[];
|
|
||||||
setProps({ data: val });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.data,
|
|
||||||
(val) => {
|
|
||||||
totalData.value = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 是否开启三方API
|
|
||||||
watch(
|
|
||||||
() => props.enableThirdPart,
|
|
||||||
(val) => {
|
|
||||||
if (val && route.query.type === 'BUG') {
|
|
||||||
const result = [...columns.slice(0, 1), getApiColumns(), ...columns.slice(1)];
|
|
||||||
tableRef.value.initColumn(result);
|
|
||||||
} else {
|
|
||||||
tableRef.value.initColumn(columns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 获取拖拽数据
|
|
||||||
const dragTableData = computed(() => {
|
|
||||||
return propsRes.value.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => dragTableData.value,
|
|
||||||
(val) => {
|
|
||||||
selectList.value = dragTableData.value as DefinedFieldItem[];
|
|
||||||
emit('update:select-data', val);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.form-create-wrapper {
|
|
||||||
:deep(.arco-form-item) {
|
|
||||||
margin-bottom: 0 !important;
|
|
||||||
}
|
|
||||||
:deep(.arco-picker) {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.system-flag {
|
|
||||||
background: var(--color-text-n8);
|
|
||||||
@apply ml-2 rounded p-1 text-xs;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -189,4 +189,16 @@ export default {
|
||||||
'system.orgTemplate.caseTemplateManagement': 'Use case template management',
|
'system.orgTemplate.caseTemplateManagement': 'Use case template management',
|
||||||
'system.orgTemplate.apiTemplateManagement': 'Interface template management',
|
'system.orgTemplate.apiTemplateManagement': 'Interface template management',
|
||||||
'system.orgTemplate.bugTemplateManagement': 'Defect template management',
|
'system.orgTemplate.bugTemplateManagement': 'Defect template management',
|
||||||
|
'system.orgTemplate.templateTypeName': ' {type}name',
|
||||||
|
'system.orgTemplate.createCaseTemplate': 'Create a use case template',
|
||||||
|
'system.orgTemplate.updateCaseTemplate': 'Update the use case template',
|
||||||
|
'system.orgTemplate.createApiTemplate': 'Creating Api Template',
|
||||||
|
'system.orgTemplate.updateApiTemplate': 'Update Api Template',
|
||||||
|
'system.orgTemplate.createDefectTemplate': 'Create defect templates',
|
||||||
|
'system.orgTemplate.updateDefectTemplate': 'Update defect templates',
|
||||||
|
'system.orgTemplate.enableApiAlert':
|
||||||
|
'After connecting to the third-party platform, you need to fill in the field API for the custom field. When using the template, the API field is not displayed',
|
||||||
|
'system.orgTemplate.pleaseEnterAPITip': 'Please enter the field API',
|
||||||
|
'system.orgTemplate.apiFieldNotEmpty': 'The field API cannot be empty',
|
||||||
|
'system.orgTemplate.selectThirdPlatType': 'Please select the third party platform',
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,4 +180,15 @@ export default {
|
||||||
'system.orgTemplate.caseTemplateManagement': '用例模板管理',
|
'system.orgTemplate.caseTemplateManagement': '用例模板管理',
|
||||||
'system.orgTemplate.apiTemplateManagement': '接口模板管理',
|
'system.orgTemplate.apiTemplateManagement': '接口模板管理',
|
||||||
'system.orgTemplate.bugTemplateManagement': '缺陷模板管理',
|
'system.orgTemplate.bugTemplateManagement': '缺陷模板管理',
|
||||||
|
'system.orgTemplate.templateTypeName': ' {type}名称',
|
||||||
|
'system.orgTemplate.createCaseTemplate': '创建用例模板',
|
||||||
|
'system.orgTemplate.updateCaseTemplate': '更新用例模板',
|
||||||
|
'system.orgTemplate.createApiTemplate': '创建接口模板',
|
||||||
|
'system.orgTemplate.updateApiTemplate': '更新接口模板',
|
||||||
|
'system.orgTemplate.createDefectTemplate': '创建缺陷模板',
|
||||||
|
'system.orgTemplate.updateDefectTemplate': '更新缺陷模板',
|
||||||
|
'system.orgTemplate.enableApiAlert': '对接第三方平台后,自定义字段需要填写字段 API,使用模版时,不显示 API 字段',
|
||||||
|
'system.orgTemplate.pleaseEnterAPITip': '请输入字段API',
|
||||||
|
'system.orgTemplate.apiFieldNotEmpty': '字段 API 不能为空',
|
||||||
|
'system.orgTemplate.selectThirdPlatType': '请选择三方平台',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue