diff --git a/frontend/config/vite.config.dev.ts b/frontend/config/vite.config.dev.ts
index 7ead8b015c..db038b0f01 100644
--- a/frontend/config/vite.config.dev.ts
+++ b/frontend/config/vite.config.dev.ts
@@ -46,6 +46,16 @@ export default mergeConfig(
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/front\/test-plan\/report/, ''),
},
+ '/organization': {
+ target: process.env.VITE_DEV_DOMAIN,
+ changeOrigin: true,
+ rewrite: (path: string) => path.replace(/^\/front\/organization/, ''),
+ },
+ '/project': {
+ target: process.env.VITE_DEV_DOMAIN,
+ changeOrigin: true,
+ rewrite: (path: string) => path.replace(/^\/front\/project/, ''),
+ },
'/plugin/image': {
target: process.env.VITE_DEV_DOMAIN,
changeOrigin: true,
diff --git a/frontend/src/api/modules/setting/template.ts b/frontend/src/api/modules/setting/template.ts
index 6e0bfc0b03..a5a6fa4fbf 100644
--- a/frontend/src/api/modules/setting/template.ts
+++ b/frontend/src/api/modules/setting/template.ts
@@ -26,6 +26,7 @@ import {
OrdUpdateFlowStatusUrl,
OrdUpdateStateFlowUrl,
OrdWorkFlowUrl,
+ orgRichUploadImageUrl,
ProjectCreateFlowStatusUrl,
ProjectDeleteFlowStatusUrl,
ProjectSetStateUrl,
@@ -33,6 +34,7 @@ import {
ProjectUpdateFlowStatusUrl,
ProjectUpdateStateFlowUrl,
ProjectWorkFlowUrl,
+ proRichUploadImageUrl,
SetProjectTemplateUrl,
UpdateFieldUrl,
UpdateOrganizeTemplateUrl,
@@ -40,11 +42,10 @@ import {
UpdateProjectTemplateUrl,
} from '@/api/requrls/setting/template';
-import { CommonList, TableQueryParams } from '@/models/common';
+import { TableQueryParams } from '@/models/common';
import type {
ActionTemplateManage,
AddOrUpdateField,
- OrdTemplateManagement,
OrdWorkStatus,
SeneType,
SetStateType,
@@ -178,6 +179,12 @@ export function getProjectFieldDetail(id: string) {
return MSR.get({ url: GetFieldProjectDetailUrl, params: id });
}
+// 富文本编辑器上传图片文件
+export function editorUploadFile(data: { fileList: File[] }, mode: 'organization' | 'project') {
+ const url = mode === 'organization' ? orgRichUploadImageUrl : proRichUploadImageUrl;
+ return MSR.uploadFile({ url }, { fileList: data.fileList }, '', false);
+}
+
/** *
* 模板(项目)
*/
diff --git a/frontend/src/api/requrls/setting/template.ts b/frontend/src/api/requrls/setting/template.ts
index 4bd8764d94..9539132a79 100644
--- a/frontend/src/api/requrls/setting/template.ts
+++ b/frontend/src/api/requrls/setting/template.ts
@@ -93,3 +93,11 @@ export const ProjectSetStateUrl = '/project/status/flow/setting/status/definitio
export const ProjectStateSortUrl = '/project/status/flow/setting/status/sort';
// 更新状态流转
export const ProjectUpdateStateFlowUrl = '/project/status/flow/setting/status/flow/update';
+// 组织模板富文本图片链接
+export const orgRichUploadImageUrl = '/organization/template/upload/temp/img';
+// 项目模板富文本图片链接
+export const proRichUploadImageUrl = '/project/template/upload/temp/img';
+// 组织预览富文本图片
+export const previewOrgImageUrl = '/organization/template/img/preview';
+// 项目预览富文本图片
+export const previewProImageUrl = '/project/template/img/preview';
diff --git a/frontend/src/components/pure/ms-rich-text/MsRichText.vue b/frontend/src/components/pure/ms-rich-text/MsRichText.vue
index ecbbfa393b..2594fadabc 100644
--- a/frontend/src/components/pure/ms-rich-text/MsRichText.vue
+++ b/frontend/src/components/pure/ms-rich-text/MsRichText.vue
@@ -12,6 +12,7 @@
* import rehypeStringify from 'rehype-stringify';
* return unified().use(rehypeParse).use(rehypeFormat).use(rehypeStringify).processSync(content.value);
*/
+ import { useRoute } from 'vue-router';
import { useDebounceFn, useVModel } from '@vueuse/core';
import type { MsFileItem } from '@/components/pure/ms-upload/types';
@@ -20,7 +21,6 @@
import { editorUploadFile } from '@/api/modules/case-management/featureCase';
import { useI18n } from '@/hooks/useI18n';
import useLocale from '@/locale/useLocale';
- import { useAppStore } from '@/store';
import '@halo-dev/richtext-editor/dist/style.css';
import ExtensionImage from './extensions/image/index';
@@ -70,10 +70,8 @@
import type { queueAsPromised } from 'fastq';
import * as fastq from 'fastq';
- const appStore = useAppStore();
const { t } = useI18n();
-
- // image drag and paste upload
+ const route = useRoute();
type Task = {
file: File;
process: (permalink: string, fileId: string) => void;
@@ -122,8 +120,8 @@
}
const uploadFileId = await props.uploadImage(arg.file);
if (uploadFileId) {
- // const permanentUrl = `${PreviewEditorImageUrl}/${appStore.currentProjectId}/${uploadFileId}/${true}`;
- const permanentUrl = `${props.previewUrl}/${appStore.currentProjectId}/${uploadFileId}/${true}`;
+ const infoId = route.query.orgId && route.query.pId ? route.query.pId : route.query.orgId;
+ const permanentUrl = `${props.previewUrl}/${infoId}/${uploadFileId}/${true}`;
arg.process(permanentUrl, uploadFileId);
}
}
diff --git a/frontend/src/models/setting/template.ts b/frontend/src/models/setting/template.ts
index d112ead3e2..ac96bd39a9 100644
--- a/frontend/src/models/setting/template.ts
+++ b/frontend/src/models/setting/template.ts
@@ -120,6 +120,7 @@ export interface ActionTemplateManage {
enablePlatformDefault?: boolean;
internal?: boolean; // 是否为系统模板
platForm?: string;
+ uploadImgFileIds: string[]; // 模板附件
[key: string]: any;
}
diff --git a/frontend/src/views/project-management/template/components/templateManagement.vue b/frontend/src/views/project-management/template/components/templateManagement.vue
index 78928e3b2a..ee9fe1f761 100644
--- a/frontend/src/views/project-management/template/components/templateManagement.vue
+++ b/frontend/src/views/project-management/template/components/templateManagement.vue
@@ -315,6 +315,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
type: route.query.type,
},
params: {
@@ -328,6 +329,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
id,
type: route.query.type,
},
@@ -342,6 +344,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
id,
type: route.query.type,
},
diff --git a/frontend/src/views/project-management/template/index.vue b/frontend/src/views/project-management/template/index.vue
index fa6a78412f..2cacdd5ff3 100644
--- a/frontend/src/views/project-management/template/index.vue
+++ b/frontend/src/views/project-management/template/index.vue
@@ -30,7 +30,7 @@
* @description 项目设置--模板
*/
- import { useRouter } from 'vue-router';
+ import { useRoute, useRouter } from 'vue-router';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsCardList from '@/components/business/ms-card-list/index.vue';
@@ -43,12 +43,14 @@
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
const router = useRouter();
+ const route = useRoute();
const templateStore = useTemplateStore();
// 字段设置
const fieldSetting = (key: string) => {
router.push({
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING,
query: {
+ ...route.query,
type: key,
},
});
@@ -59,6 +61,7 @@
router.push({
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
query: {
+ ...route.query,
type: key,
},
});
@@ -69,6 +72,7 @@
router.push({
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
query: {
+ ...route.query,
type: key,
},
});
diff --git a/frontend/src/views/setting/organization/template/components/addTemplate.vue b/frontend/src/views/setting/organization/template/components/addTemplate.vue
index 8fb1e5b40a..beee2cdc5e 100644
--- a/frontend/src/views/setting/organization/template/components/addTemplate.vue
+++ b/frontend/src/views/setting/organization/template/components/addTemplate.vue
@@ -56,8 +56,18 @@
-
-
+
+
@@ -308,6 +318,7 @@
scopeId: props.mode === 'organization' ? currentOrgId.value : currentProjectId.value,
enableThirdPart: false,
platForm: '',
+ uploadImgFileIds: [],
};
const initBugForm = {
@@ -359,6 +370,9 @@
// 缺陷默认字段
const defaultBugForm = ref
(cloneDeep(defaultTemplateBugDetail));
+ const uploadBugImgFileIds = ref([]);
+ const uploadCaseImgFileIds = ref([]);
+
// 获取系统默认字段
function getSystemFields(form: Record) {
const tempFormField: Record[] = [];
@@ -397,6 +411,8 @@
const systemFields: Record[] =
route.query.type === 'BUG' ? getSystemFields(defaultBugForm.value) : getSystemFields(defaultCaseForm.value);
+ const uploadImgFileIds = route.query.type === 'BUG' ? uploadBugImgFileIds.value : uploadCaseImgFileIds.value;
+
const { name, remark, enableThirdPart, id } = templateForm.value;
return {
id,
@@ -407,6 +423,7 @@
scopeId: props.mode === 'organization' ? currentOrgId.value : currentProjectId.value,
scene: route.query.type,
systemFields,
+ uploadImgFileIds,
};
}
diff --git a/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue b/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue
index 431fa7c9b2..24e1b7906f 100644
--- a/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue
+++ b/frontend/src/views/setting/organization/template/components/caseTemplateLeftContent.vue
@@ -20,7 +20,7 @@
v-model:raw="form.prerequisite"
v-model:filed-ids="prerequisiteFileIds"
:upload-image="handleUploadImage"
- :preview-url="PreviewEditorImageUrl"
+ :preview-url="previewEditorImageUrl"
:editable="!props.isDisabled"
/>
@@ -55,7 +55,7 @@
v-model:raw="form.textDescription"
v-model:filed-ids="textDescriptionFileIds"
:upload-image="handleUploadImage"
- :preview-url="PreviewEditorImageUrl"
+ :preview-url="previewEditorImageUrl"
:editable="!props.isDisabled"
/>
@@ -68,7 +68,7 @@
v-model:raw="form.expectedResult"
v-model:filed-ids="expectedResultFileIds"
:upload-image="handleUploadImage"
- :preview-url="PreviewEditorImageUrl"
+ :preview-url="previewEditorImageUrl"
:editable="!props.isDisabled"
/>
@@ -77,7 +77,7 @@
v-model:raw="form.description"
v-model:filed-ids="descriptionFileIds"
:upload-image="handleUploadImage"
- :preview-url="PreviewEditorImageUrl"
+ :preview-url="previewEditorImageUrl"
:editable="!props.isDisabled"
/>
@@ -95,8 +95,8 @@
import AddAttachment from '@/components/business/ms-add-attachment/index.vue';
import AddStep from '@/views/case-management/caseManagementFeature/components/addStep.vue';
- import { editorUploadFile } from '@/api/modules/case-management/featureCase';
- import { PreviewEditorImageUrl } from '@/api/requrls/case-management/featureCase';
+ import { editorUploadFile } from '@/api/modules/setting/template';
+ import { previewOrgImageUrl, previewProImageUrl } from '@/api/requrls/setting/template';
import { defaultTemplateCaseDetail } from '@/config/template';
import { useI18n } from '@/hooks/useI18n';
import { getGenerateId } from '@/utils';
@@ -107,12 +107,16 @@
const { t } = useI18n();
const props = defineProps<{
+ mode: 'organization' | 'project';
isDisabled?: boolean;
}>();
const form = defineModel('defaultForm', {
default: defaultTemplateCaseDetail,
});
+ const uploadImgFileIds = defineModel('uploadImgFileIds', {
+ default: [],
+ });
const fileList = ref([]);
@@ -177,13 +181,41 @@
}
}
);
- // TODO 上传需要接口
+ // 上传图片
async function handleUploadImage(file: File) {
- const { data } = await editorUploadFile({
- fileList: [file],
- });
+ const { data } = await editorUploadFile(
+ {
+ fileList: [file],
+ },
+ props.mode
+ );
return data;
}
+
+ const previewEditorImageUrl = computed(() =>
+ props.mode === 'organization' ? previewOrgImageUrl : previewProImageUrl
+ );
+
+ const fileIds = computed(() => {
+ return [
+ ...prerequisiteFileIds.value,
+ ...textDescriptionFileIds.value,
+ ...expectedResultFileIds.value,
+ ...descriptionFileIds.value,
+ ];
+ });
+
+ watch(
+ () => fileIds.value,
+ (val) => {
+ if (val) {
+ uploadImgFileIds.value = val;
+ }
+ },
+ {
+ deep: true,
+ }
+ );
diff --git a/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue b/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue
index 118a528620..c0952533c6 100644
--- a/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue
+++ b/frontend/src/views/setting/organization/template/components/defectTemplateLeftContent.vue
@@ -17,7 +17,7 @@
v-model:raw="form.description"
v-model:filed-ids="descriptionFileIds"
:upload-image="handleUploadImage"
- :preview-url="EditorPreviewFileUrl"
+ :preview-url="previewEditorImageUrl"
:editable="!props.isDisabled"
/>
@@ -34,8 +34,8 @@
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import AddAttachment from '@/components/business/ms-add-attachment/index.vue';
- import { editorUploadFile } from '@/api/modules/bug-management';
- import { EditorPreviewFileUrl } from '@/api/requrls/bug-management';
+ import { editorUploadFile } from '@/api/modules/setting/template';
+ import { previewOrgImageUrl, previewProImageUrl } from '@/api/requrls/setting/template';
import { defaultTemplateBugDetail } from '@/config/template';
import { useI18n } from '@/hooks/useI18n';
@@ -44,6 +44,7 @@
const { t } = useI18n();
const props = defineProps<{
+ mode: 'organization' | 'project';
isDisabled?: boolean;
}>();
@@ -53,16 +54,39 @@
default: defaultTemplateBugDetail,
});
+ const uploadImgFileIds = defineModel('uploadImgFileIds', {
+ default: [],
+ });
+
// 富文本附件ID
const descriptionFileIds = ref([]);
- // TODO 上传图片需要接口
+ // 上传图片
async function handleUploadImage(file: File) {
- const { data } = await editorUploadFile({
- fileList: [file],
- });
+ const { data } = await editorUploadFile(
+ {
+ fileList: [file],
+ },
+ props.mode
+ );
return data;
}
+
+ const previewEditorImageUrl = computed(() =>
+ props.mode === 'organization' ? previewOrgImageUrl : previewProImageUrl
+ );
+
+ watch(
+ () => descriptionFileIds.value,
+ (val) => {
+ if (val) {
+ uploadImgFileIds.value = val;
+ }
+ },
+ {
+ deep: true,
+ }
+ );
diff --git a/frontend/src/views/setting/organization/template/components/templateManagement.vue b/frontend/src/views/setting/organization/template/components/templateManagement.vue
index 84c3c1eb36..48900e139e 100644
--- a/frontend/src/views/setting/organization/template/components/templateManagement.vue
+++ b/frontend/src/views/setting/organization/template/components/templateManagement.vue
@@ -238,6 +238,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
type: route.query.type,
},
params: {
@@ -251,6 +252,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
id,
type: route.query.type,
},
@@ -265,6 +267,7 @@
router.push({
name: routeName.value,
query: {
+ ...route.query,
id,
type: route.query.type,
},
diff --git a/frontend/src/views/setting/organization/template/components/viewTemplate.vue b/frontend/src/views/setting/organization/template/components/viewTemplate.vue
index 4dd57e927b..bdaa8f971d 100644
--- a/frontend/src/views/setting/organization/template/components/viewTemplate.vue
+++ b/frontend/src/views/setting/organization/template/components/viewTemplate.vue
@@ -1,8 +1,13 @@
-
-
+
+
diff --git a/frontend/src/views/setting/organization/template/index.vue b/frontend/src/views/setting/organization/template/index.vue
index dde3863520..0ad1f351aa 100644
--- a/frontend/src/views/setting/organization/template/index.vue
+++ b/frontend/src/views/setting/organization/template/index.vue
@@ -39,7 +39,7 @@
/**
* @description 系统设置--组织--模版
*/
- import { useRouter } from 'vue-router';
+ import { useRoute, useRouter } from 'vue-router';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsCardList from '@/components/business/ms-card-list/index.vue';
@@ -56,6 +56,7 @@
const templateStore = useTemplateStore();
const { t } = useI18n();
const router = useRouter();
+ const route = useRoute();
const visitedKey = 'notRemind';
const { addVisited } = useVisit(visitedKey);
const { getIsVisited } = useVisit(visitedKey);
@@ -78,6 +79,7 @@
router.push({
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
query: {
+ ...route.query,
type: key,
},
});
@@ -88,6 +90,7 @@
router.push({
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
query: {
+ ...route.query,
type: key,
},
});
@@ -98,6 +101,7 @@
router.push({
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
query: {
+ ...route.query,
type: key,
},
});