feat(系统管理&项目管理): 模板调试
This commit is contained in:
parent
167801743c
commit
112a21e7e1
|
@ -2,15 +2,23 @@ import MSR from '@/api/http/index';
|
||||||
import {
|
import {
|
||||||
CreateFieldUrl,
|
CreateFieldUrl,
|
||||||
CreateOrganizeTemplateUrl,
|
CreateOrganizeTemplateUrl,
|
||||||
|
CreateProjectFieldUrl,
|
||||||
|
CreateProjectTemplateUrl,
|
||||||
DeleteFieldDetailUrl,
|
DeleteFieldDetailUrl,
|
||||||
DeleteOrganizeTemplateUrl,
|
DeleteOrganizeTemplateUrl,
|
||||||
|
DeleteProjectFieldDetailUrl,
|
||||||
|
DeleteProjectTemplateUrl,
|
||||||
EnableOrOffTemplateUrl,
|
EnableOrOffTemplateUrl,
|
||||||
GetDefinedFieldListUrl,
|
GetDefinedFieldListUrl,
|
||||||
|
GetDefinedProjectFieldListUrl,
|
||||||
GetFieldDetailUrl,
|
GetFieldDetailUrl,
|
||||||
|
GetFieldProjectDetailUrl,
|
||||||
|
getOrdTemplateStateUrl,
|
||||||
GetOrganizeTemplateDetailUrl,
|
GetOrganizeTemplateDetailUrl,
|
||||||
GetOrganizeTemplateUrl,
|
GetOrganizeTemplateUrl,
|
||||||
GetProjectTemplateDetailUrl,
|
GetProjectTemplateDetailUrl,
|
||||||
isEnableTemplateUrl,
|
getProjectTemplateStateUrl,
|
||||||
|
GetProjectTemplateUrl,
|
||||||
OrdCreateFlowStatusUrl,
|
OrdCreateFlowStatusUrl,
|
||||||
OrdDeleteFlowStatusUrl,
|
OrdDeleteFlowStatusUrl,
|
||||||
OrdSetStateUrl,
|
OrdSetStateUrl,
|
||||||
|
@ -18,9 +26,17 @@ import {
|
||||||
OrdUpdateFlowStatusUrl,
|
OrdUpdateFlowStatusUrl,
|
||||||
OrdUpdateStateFlowUrl,
|
OrdUpdateStateFlowUrl,
|
||||||
OrdWorkFlowUrl,
|
OrdWorkFlowUrl,
|
||||||
SetOrganizeTemplateUrl,
|
ProjectCreateFlowStatusUrl,
|
||||||
|
ProjectDeleteFlowStatusUrl,
|
||||||
|
ProjectSetStateUrl,
|
||||||
|
ProjectStateSortUrl,
|
||||||
|
ProjectUpdateFlowStatusUrl,
|
||||||
|
ProjectUpdateStateFlowUrl,
|
||||||
|
ProjectWorkFlowUrl,
|
||||||
|
SetProjectTemplateUrl,
|
||||||
UpdateFieldUrl,
|
UpdateFieldUrl,
|
||||||
UpdateOrganizeTemplateUrl,
|
UpdateOrganizeTemplateUrl,
|
||||||
|
UpdateProjectFieldUrl,
|
||||||
UpdateProjectTemplateUrl,
|
UpdateProjectTemplateUrl,
|
||||||
} from '@/api/requrls/setting/template';
|
} from '@/api/requrls/setting/template';
|
||||||
|
|
||||||
|
@ -28,9 +44,7 @@ import { TableQueryParams } from '@/models/common';
|
||||||
import type {
|
import type {
|
||||||
ActionTemplateManage,
|
ActionTemplateManage,
|
||||||
AddOrUpdateField,
|
AddOrUpdateField,
|
||||||
DefinedFieldItem,
|
|
||||||
OrdWorkStatus,
|
OrdWorkStatus,
|
||||||
OrganizeTemplateItem,
|
|
||||||
SeneType,
|
SeneType,
|
||||||
SetStateType,
|
SetStateType,
|
||||||
UpdateWorkFlowSetting,
|
UpdateWorkFlowSetting,
|
||||||
|
@ -38,13 +52,13 @@ import type {
|
||||||
} from '@/models/setting/template';
|
} from '@/models/setting/template';
|
||||||
|
|
||||||
/** *
|
/** *
|
||||||
* 模版
|
* 模版(组织)
|
||||||
*/
|
*/
|
||||||
// 获取模版列表(组织)
|
// 获取模版列表(组织)
|
||||||
export function getOrganizeTemplateList(params: TableQueryParams) {
|
export function getOrganizeTemplateList(params: TableQueryParams) {
|
||||||
return MSR.get({ url: `${GetOrganizeTemplateUrl}/${params.organizationId}/${params.scene}` });
|
return MSR.get({ url: `${GetOrganizeTemplateUrl}/${params.organizationId}/${params.scene}` });
|
||||||
}
|
}
|
||||||
// 获取模版详情
|
// 获取模版详情(组织)
|
||||||
export function getOrganizeTemplateInfo(id: string) {
|
export function getOrganizeTemplateInfo(id: string) {
|
||||||
return MSR.get({ url: `${GetOrganizeTemplateDetailUrl}/${id}` });
|
return MSR.get({ url: `${GetOrganizeTemplateDetailUrl}/${id}` });
|
||||||
}
|
}
|
||||||
|
@ -57,21 +71,32 @@ export function createOrganizeTemplateInfo(data: ActionTemplateManage) {
|
||||||
export function updateOrganizeTemplateInfo(data: ActionTemplateManage) {
|
export function updateOrganizeTemplateInfo(data: ActionTemplateManage) {
|
||||||
return MSR.post({ url: `${UpdateOrganizeTemplateUrl}`, data });
|
return MSR.post({ url: `${UpdateOrganizeTemplateUrl}`, data });
|
||||||
}
|
}
|
||||||
// 是否启用组织XX模板
|
|
||||||
export function isEnableTemplate(organizationId: string) {
|
// 获取模板列表的状态(组织)
|
||||||
return MSR.get<Record<string, boolean>>({ url: `${isEnableTemplateUrl}/${organizationId}` });
|
export function getOrdTemplate(scopedId: string) {
|
||||||
|
return MSR.get<Record<string, boolean>>({ url: `${getOrdTemplateStateUrl}/${scopedId}` });
|
||||||
}
|
}
|
||||||
// 删除模板
|
|
||||||
|
// 获取模板列表的状态(项目)
|
||||||
|
export function getProTemplate(scopedId: string) {
|
||||||
|
return MSR.get<Record<string, boolean>>({ url: `${getProjectTemplateStateUrl}/${scopedId}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除模板(组织)
|
||||||
export function deleteOrdTemplate(id: string) {
|
export function deleteOrdTemplate(id: string) {
|
||||||
return MSR.get({ url: `${DeleteOrganizeTemplateUrl}/${id}` });
|
return MSR.get({ url: `${DeleteOrganizeTemplateUrl}/${id}` });
|
||||||
}
|
}
|
||||||
|
// 关闭组织模板||开启项目模板
|
||||||
|
export function enableOrOffTemplate(organizationId: string, scene: SeneType) {
|
||||||
|
return MSR.get({ url: `${EnableOrOffTemplateUrl}/${organizationId}/${scene}` });
|
||||||
|
}
|
||||||
|
|
||||||
/** *
|
/** *
|
||||||
* 自定义字段(组织)
|
* 自定义字段(组织)
|
||||||
*/
|
*/
|
||||||
// 获取自定义字段列表
|
// 获取自定义字段列表(组织)
|
||||||
export function getFieldList(params: TableQueryParams) {
|
export function getFieldList(params: TableQueryParams) {
|
||||||
return MSR.get({ url: `${GetDefinedFieldListUrl}${params.organizationId}/${params.scene}` });
|
return MSR.get({ url: `${GetDefinedFieldListUrl}${params.scopedId}/${params.scene}` });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建自定义字段(组织)
|
// 创建自定义字段(组织)
|
||||||
|
@ -95,8 +120,8 @@ export function getOrdFieldDetail(id: string) {
|
||||||
// 组织模板-工作流
|
// 组织模板-工作流
|
||||||
|
|
||||||
// 获取组织下边模板工作流
|
// 获取组织下边模板工作流
|
||||||
export function getWorkFlowList(organizationId: string, scene: SeneType) {
|
export function getWorkFlowList(scopedId: string, scene: SeneType) {
|
||||||
return MSR.get<WorkFlowType[]>({ url: `${OrdWorkFlowUrl}/${organizationId}/${scene}` });
|
return MSR.get<WorkFlowType[]>({ url: `${OrdWorkFlowUrl}/${scopedId}/${scene}` });
|
||||||
}
|
}
|
||||||
// 创建工作流状态
|
// 创建工作流状态
|
||||||
export function createWorkFlowStatus(data: OrdWorkStatus) {
|
export function createWorkFlowStatus(data: OrdWorkStatus) {
|
||||||
|
@ -116,11 +141,99 @@ export function setOrdWorkState(data: SetStateType) {
|
||||||
return MSR.post({ url: OrdSetStateUrl, data });
|
return MSR.post({ url: OrdSetStateUrl, data });
|
||||||
}
|
}
|
||||||
// 设置工作流状态排序
|
// 设置工作流状态排序
|
||||||
export function setOrdWorkStateSort(organizationId: string, scene: SeneType, data: string[]) {
|
export function setOrdWorkStateSort(scopedId: string, scene: SeneType, data: string[]) {
|
||||||
return MSR.post({ url: `${OrdStateSortUrl}/${organizationId}/${scene}`, data });
|
return MSR.post({ url: `${OrdStateSortUrl}/${scopedId}/${scene}`, data });
|
||||||
}
|
}
|
||||||
// 更新工作流流转状态
|
// 更新工作流流转状态
|
||||||
export function updateOrdWorkStateFlow(data: UpdateWorkFlowSetting) {
|
export function updateOrdWorkStateFlow(data: UpdateWorkFlowSetting) {
|
||||||
return MSR.post({ url: `${OrdUpdateStateFlowUrl}`, data });
|
return MSR.post({ url: `${OrdUpdateStateFlowUrl}`, data });
|
||||||
}
|
}
|
||||||
export default {};
|
|
||||||
|
/** *
|
||||||
|
* 自定义字段(项目)
|
||||||
|
*/
|
||||||
|
// 获取自定义字段列表(组织)
|
||||||
|
export function getProjectFieldList(params: TableQueryParams) {
|
||||||
|
return MSR.get({ url: `${GetDefinedProjectFieldListUrl}${params.scopedId}/${params.scene}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建自定义字段(组织)
|
||||||
|
export function addOrUpdateProjectField(data: AddOrUpdateField) {
|
||||||
|
if (data.id) {
|
||||||
|
return MSR.post({ url: UpdateProjectFieldUrl, data });
|
||||||
|
}
|
||||||
|
return MSR.post({ url: CreateProjectFieldUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除自定义字段(组织)
|
||||||
|
export function deleteProjectField(id: string) {
|
||||||
|
return MSR.get({ url: DeleteProjectFieldDetailUrl, params: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取自定义字段详情选项(组织)
|
||||||
|
export function getProjectFieldDetail(id: string) {
|
||||||
|
return MSR.get({ url: GetFieldProjectDetailUrl, params: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** *
|
||||||
|
* 模版(项目)
|
||||||
|
*/
|
||||||
|
// 获取模版列表(项目)
|
||||||
|
export function getProjectTemplateList(params: TableQueryParams) {
|
||||||
|
return MSR.get({ url: `${GetProjectTemplateUrl}/${params.projectId}/${params.scene}` });
|
||||||
|
}
|
||||||
|
// 获取模版详情(项目)
|
||||||
|
export function getProjectTemplateInfo(id: string) {
|
||||||
|
return MSR.get({ url: `${GetProjectTemplateDetailUrl}/${id}` });
|
||||||
|
}
|
||||||
|
// 创建模板列表(项目)
|
||||||
|
export function createProjectTemplateInfo(data: ActionTemplateManage) {
|
||||||
|
return MSR.post({ url: `${CreateProjectTemplateUrl}`, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑模板列表(项目)
|
||||||
|
export function updateProjectTemplateInfo(data: ActionTemplateManage) {
|
||||||
|
return MSR.post({ url: `${UpdateProjectTemplateUrl}`, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除模板(项目)
|
||||||
|
export function deleteProjectTemplate(id: string) {
|
||||||
|
return MSR.get({ url: `${DeleteProjectTemplateUrl}/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置默认项目模板
|
||||||
|
export function setDefaultTemplate(projectId: string, id: string) {
|
||||||
|
return MSR.get({ url: `${SetProjectTemplateUrl}/${projectId}/${id}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 项目模板-工作流
|
||||||
|
|
||||||
|
// 获取项目模板工作流
|
||||||
|
export function getProjectWorkFlowList(scopedId: string, scene: SeneType) {
|
||||||
|
return MSR.get<WorkFlowType[]>({ url: `${ProjectWorkFlowUrl}/${scopedId}/${scene}` });
|
||||||
|
}
|
||||||
|
// 创建工作流状态
|
||||||
|
export function createProjectWorkFlowStatus(data: OrdWorkStatus) {
|
||||||
|
return MSR.post<WorkFlowType[]>({ url: ProjectCreateFlowStatusUrl, data });
|
||||||
|
}
|
||||||
|
// 更新工作流状态
|
||||||
|
export function updateProjectWorkFlowStatus(data: OrdWorkStatus) {
|
||||||
|
return MSR.post<WorkFlowType[]>({ url: ProjectUpdateFlowStatusUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除工作流状态
|
||||||
|
export function deleteProjectWorkState(id: string) {
|
||||||
|
return MSR.get({ url: ProjectDeleteFlowStatusUrl, params: id });
|
||||||
|
}
|
||||||
|
// 设置工作流状态初始态 || 结束态
|
||||||
|
export function setProjectWorkState(data: SetStateType) {
|
||||||
|
return MSR.post({ url: ProjectSetStateUrl, data });
|
||||||
|
}
|
||||||
|
// 设置工作流状态排序
|
||||||
|
export function setProjectWorkStateSort(scopedId: string, scene: SeneType, data: string[]) {
|
||||||
|
return MSR.post({ url: `${ProjectStateSortUrl}/${scopedId}/${scene}`, data });
|
||||||
|
}
|
||||||
|
// 更新工作流流转状态
|
||||||
|
export function updateProjectWorkStateFlow(data: UpdateWorkFlowSetting) {
|
||||||
|
return MSR.post({ url: `${ProjectUpdateStateFlowUrl}`, data });
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ export const UpdateProjectTemplateUrl = '/project/template/update';
|
||||||
export const GetProjectTemplateDetailUrl = '/project/template/get';
|
export const GetProjectTemplateDetailUrl = '/project/template/get';
|
||||||
// 删除模版
|
// 删除模版
|
||||||
export const DeleteProjectTemplateUrl = '/project/template/delete';
|
export const DeleteProjectTemplateUrl = '/project/template/delete';
|
||||||
|
// 是否启用项目模板
|
||||||
|
export const getProjectTemplateStateUrl = '/project/template/enable/config';
|
||||||
|
|
||||||
// 组织--- 模板
|
// 组织--- 模板
|
||||||
|
|
||||||
|
@ -29,8 +31,8 @@ export const GetOrganizeTemplateDetailUrl = '/organization/template/get';
|
||||||
export const DeleteOrganizeTemplateUrl = '/organization/template/delete';
|
export const DeleteOrganizeTemplateUrl = '/organization/template/delete';
|
||||||
// 关闭组织模板,开启项目模版
|
// 关闭组织模板,开启项目模版
|
||||||
export const EnableOrOffTemplateUrl = '/organization/template/disable';
|
export const EnableOrOffTemplateUrl = '/organization/template/disable';
|
||||||
// 是否启用组织模板
|
// 获取所有模板状态
|
||||||
export const isEnableTemplateUrl = '/organization/template/enable/config';
|
export const getOrdTemplateStateUrl = '/organization/template/enable/config';
|
||||||
|
|
||||||
// 系统设置-组织-自定义字段
|
// 系统设置-组织-自定义字段
|
||||||
|
|
||||||
|
@ -61,3 +63,33 @@ export const OrdSetStateUrl = '/organization/status/flow/setting/status/definiti
|
||||||
export const OrdStateSortUrl = '/organization/status/flow/setting/status/sort';
|
export const OrdStateSortUrl = '/organization/status/flow/setting/status/sort';
|
||||||
// 更新状态流转
|
// 更新状态流转
|
||||||
export const OrdUpdateStateFlowUrl = '/organization/status/flow/setting/status/flow/update';
|
export const OrdUpdateStateFlowUrl = '/organization/status/flow/setting/status/flow/update';
|
||||||
|
|
||||||
|
// 项目管理-模板-自定义字段
|
||||||
|
|
||||||
|
// 获取自定义字段列表
|
||||||
|
export const GetDefinedProjectFieldListUrl = '/project/custom/field/list/';
|
||||||
|
// 创建自定义字段
|
||||||
|
export const CreateProjectFieldUrl = '/project/custom/field/add';
|
||||||
|
// 更新自定义字段
|
||||||
|
export const UpdateProjectFieldUrl = '/project/custom/field/update';
|
||||||
|
// 获取自定义字段详情
|
||||||
|
export const GetFieldProjectDetailUrl = '/project/custom/field/get';
|
||||||
|
// 删除自定义字段
|
||||||
|
export const DeleteProjectFieldDetailUrl = '/project/custom/field/delete';
|
||||||
|
|
||||||
|
// 项目管理-模板-获取工作流列表
|
||||||
|
export const ProjectWorkFlowUrl = '/project/status/flow/setting/get';
|
||||||
|
// 状态流更新
|
||||||
|
export const ProjectWorkFlowSetting = '/project/status/flow/setting/status/update';
|
||||||
|
// 创建工作流状态
|
||||||
|
export const ProjectCreateFlowStatusUrl = '/project/status/flow/setting/status/add';
|
||||||
|
// 更新工作流状态
|
||||||
|
export const ProjectUpdateFlowStatusUrl = '/project/status/flow/setting/status/update';
|
||||||
|
// 删除工作流状态
|
||||||
|
export const ProjectDeleteFlowStatusUrl = '/project/status/flow/setting/status/delete';
|
||||||
|
// 设置工作流状态为初始态或者标记结束状态
|
||||||
|
export const ProjectSetStateUrl = '/project/status/flow/setting/status/definition/update';
|
||||||
|
// 设置选项排序
|
||||||
|
export const ProjectStateSortUrl = '/project/status/flow/setting/status/sort';
|
||||||
|
// 更新状态流转
|
||||||
|
export const ProjectUpdateStateFlowUrl = '/project/status/flow/setting/status/flow/update';
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<svg width="33" height="30" viewBox="0 0 33 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M14.9333 7.27246C15.5224 7.27246 16 7.63063 16 8.07246L16 22.4725C16 22.9143 15.5224 23.2725 14.9333 23.2725L1.06667 23.2725C0.477563 23.2725 2.69948e-07 22.9143 2.89261e-07 22.4725L9.18705e-07 8.07246C9.38018e-07 7.63063 0.477564 7.27246 1.06667 7.27246L14.9333 7.27246Z" fill="#3370FF"/>
|
||||||
|
<g filter="url(#filter0_i_11927_97606)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9993 0H11.6357C10.029 0 8.72656 1.30245 8.72656 2.90909V26.1818C8.72656 27.7885 10.029 29.0909 11.6357 29.0909H29.0902C30.6968 29.0909 31.9993 27.7885 31.9993 26.1818V2.90909C31.9993 1.30244 30.6968 0 29.0902 0H24.7266V1.90909C24.7266 2.46137 24.2788 2.90909 23.7266 2.90909H16.9993C16.447 2.90909 15.9993 2.46138 15.9993 1.90909V0Z" fill="#F5F8FF"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter1_f_11927_97606)">
|
||||||
|
<path d="M25.2731 5.81836C26.5785 5.81836 27.6367 6.26393 27.6367 6.81357L27.6367 23.7322C27.6367 24.2819 26.5785 24.7275 25.2731 24.7275L11.0913 24.7275C9.78586 24.7275 8.72763 24.2819 8.72763 23.7322L8.72763 6.81357C8.72763 6.26393 9.78586 5.81836 11.0913 5.81836L25.2731 5.81836Z" fill="#3370FF"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter2_d_11927_97606)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.7297 7.02636C16.7297 6.3592 17.2705 5.81836 17.9377 5.81836C18.6048 5.81836 19.1457 6.3592 19.1457 7.02636V10.49C19.1457 10.9533 19.0726 11.3916 18.9265 11.8049C18.784 12.2147 18.5577 12.5746 18.2477 12.8846C17.9412 13.1911 17.6187 13.4067 17.2802 13.5314C16.8098 13.706 16.245 13.7933 15.5858 13.7933C15.2045 13.7933 14.7876 13.7666 14.335 13.7131C13.886 13.6597 13.5101 13.5546 13.2072 13.3978C12.9043 13.2374 12.6264 13.0111 12.3734 12.7189C12.1239 12.4267 11.9529 12.1256 11.8602 11.8156C11.7106 11.3167 11.6357 10.8749 11.6357 10.49V7.02636C11.6357 6.3592 12.1766 5.81836 12.8437 5.81836C13.5109 5.81836 14.0517 6.3592 14.0517 7.02636V10.6023C14.0517 11.0299 14.1693 11.3648 14.4045 11.6071C14.6433 11.8459 14.9729 11.9653 15.3934 11.9653C15.8103 11.9653 16.1363 11.8477 16.3715 11.6125C16.6103 11.3737 16.7297 11.037 16.7297 10.6023V7.02636ZM20.8445 7.03171C20.8445 6.36159 21.3878 5.81836 22.0579 5.81836C22.728 5.81836 23.2712 6.36159 23.2712 7.03171V12.441C23.2712 13.1111 22.728 13.6543 22.0579 13.6543C21.3878 13.6543 20.8445 13.1111 20.8445 12.441V7.03171ZM11.6361 17.4547C11.6361 16.6514 12.2873 16.0002 13.0906 16.0002H17.4543C18.2576 16.0002 18.9088 16.6514 18.9088 17.4547C18.9088 18.258 18.2576 18.9093 17.4543 18.9093H13.0906C12.2873 18.9093 11.6361 18.258 11.6361 17.4547ZM11.6361 21.8183C11.6361 21.015 12.2873 20.3638 13.0906 20.3638H27.6361C28.4394 20.3638 29.0906 21.015 29.0906 21.8183C29.0906 22.6217 28.4394 23.2729 27.6361 23.2729H13.0906C12.2873 23.2729 11.6361 22.6217 11.6361 21.8183Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_i_11927_97606" x="8.72656" y="0" width="23.2725" height="30.0908" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="1"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.2 0 0 0 0 0.439216 0 0 0 0 1 0 0 0 0.1 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_11927_97606"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_f_11927_97606" x="3.72754" y="0.818359" width="28.9092" height="28.9092" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feGaussianBlur stdDeviation="2.5" result="effect1_foregroundBlur_11927_97606"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_d_11927_97606" x="11.6357" y="5.81836" width="17.4551" height="17.5541" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dy="0.1"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.00986111 0 0 0 0 0.0953724 0 0 0 0 0.295833 0 0 0 0.22 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_11927_97606"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_11927_97606" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
|
@ -58,6 +58,7 @@ export interface FormItem {
|
||||||
};
|
};
|
||||||
// 表单布局
|
// 表单布局
|
||||||
wrap?: Record<string, any>;
|
wrap?: Record<string, any>;
|
||||||
|
props?: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FomItemSelect extends FormItemComplexCommonConfig {
|
interface FomItemSelect extends FormItemComplexCommonConfig {
|
||||||
|
|
|
@ -52,6 +52,11 @@
|
||||||
useEditor,
|
useEditor,
|
||||||
} from '@halo-dev/richtext-editor';
|
} from '@halo-dev/richtext-editor';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: string;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits(['update:model-value']);
|
||||||
|
|
||||||
const content = useLocalStorage('content', '');
|
const content = useLocalStorage('content', '');
|
||||||
|
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
|
@ -132,6 +137,22 @@
|
||||||
|
|
||||||
// const locale = useLocalStorage('locale', 'zh-CN');
|
// const locale = useLocalStorage('locale', 'zh-CN');
|
||||||
const locale = computed(() => currentLocale.value as 'zh-CN' | 'en-US');
|
const locale = computed(() => currentLocale.value as 'zh-CN' | 'en-US');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
content.value = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => content.value,
|
||||||
|
() => {
|
||||||
|
emit('update:model-value', `${editor.value?.getHTML()}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -236,6 +236,7 @@
|
||||||
router.replace({
|
router.replace({
|
||||||
path: route.path,
|
path: route.path,
|
||||||
query: {
|
query: {
|
||||||
|
...route.query,
|
||||||
organizationId: appStore.currentOrgId,
|
organizationId: appStore.currentOrgId,
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
},
|
},
|
||||||
|
|
|
@ -165,11 +165,39 @@ export const pathMap: PathMapItem[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'SETTING_ORGANIZATION_TEMPLATE', // 系统设置-组织-模版
|
key: 'SETTING_ORGANIZATION_TEMPLATE', // 系统设置-组织-模版
|
||||||
locale: 'menu.settings.organization.serviceIntegration',
|
locale: 'menu.settings.organization.template',
|
||||||
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[1],
|
level: MENU_LEVEL[1],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING', // 系统设置-模板管理-字段设置
|
||||||
|
locale: 'menu.settings.organization.templateFieldSetting',
|
||||||
|
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT', // 系统设置-模板管理列表
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL', // 系统设置-模板管理-详情
|
||||||
|
locale: 'menu.settings.organization.templateManagementDetail',
|
||||||
|
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[1],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW', // 系统设置-模板管理-工作流
|
||||||
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
|
route: RouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[1],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -202,13 +230,6 @@ export const pathMap: PathMapItem[] = [
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[2],
|
level: MENU_LEVEL[2],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'PROJECT_MANAGEMENT_PERMISSION_TEMPLATE', // 项目管理-项目与权限-菜单管理
|
|
||||||
locale: 'project.permission.templateManager',
|
|
||||||
route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_TEMPLATE,
|
|
||||||
permission: [],
|
|
||||||
level: MENU_LEVEL[2],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_PERMISSION_VERSION', // 项目管理-项目与权限-项目版本
|
key: 'PROJECT_MANAGEMENT_PERMISSION_VERSION', // 项目管理-项目与权限-项目版本
|
||||||
locale: 'project.permission.projectVersion',
|
locale: 'project.permission.projectVersion',
|
||||||
|
@ -232,6 +253,41 @@ export const pathMap: PathMapItem[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'PROJECT_MANAGEMENT_TEMPLATE', // 项目管理-模板管理
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING', // 项目管理-模板管理-字段设置
|
||||||
|
locale: 'menu.settings.organization.templateFieldSetting',
|
||||||
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT', // 项目管理-模板管理列表
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL', // 项目管理-模板管理-详情
|
||||||
|
locale: 'menu.settings.organization.templateManagementDetail',
|
||||||
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW', // 项目管理-模板管理-工作流
|
||||||
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
|
route: RouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
permission: [],
|
||||||
|
level: MENU_LEVEL[2],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'PROJECT_MANAGEMENT_FILE_MANAGEMENT', // 项目管理-文件管理
|
key: 'PROJECT_MANAGEMENT_FILE_MANAGEMENT', // 项目管理-文件管理
|
||||||
locale: 'menu.projectManagement.fileManagement',
|
locale: 'menu.projectManagement.fileManagement',
|
||||||
|
|
|
@ -24,7 +24,11 @@ export enum ProjectManagementRouteEnum {
|
||||||
PROJECT_MANAGEMENT_PERMISSION = 'projectManagementPermission',
|
PROJECT_MANAGEMENT_PERMISSION = 'projectManagementPermission',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_BASIC_INFO = 'projectManagementPermissionBasicInfo',
|
PROJECT_MANAGEMENT_PERMISSION_BASIC_INFO = 'projectManagementPermissionBasicInfo',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT = 'projectManagementPermissionMenuManagement',
|
PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT = 'projectManagementPermissionMenuManagement',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_TEMPLATE = 'projectManagementPermissionTemplate',
|
PROJECT_MANAGEMENT_TEMPLATE = 'projectManagementTemplate',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT = 'projectManagementTemplateManagement',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL = 'projectManagementTemplateManagementDetail',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW = 'projectManagementTemplateManagementWorkFlow',
|
||||||
|
PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING = 'projectManagementTemplateFiledSetting',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_VERSION = 'projectManagementPermissionVersion',
|
PROJECT_MANAGEMENT_PERMISSION_VERSION = 'projectManagementPermissionVersion',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_USER_GROUP = 'projectManagementPermissionUserGroup',
|
PROJECT_MANAGEMENT_PERMISSION_USER_GROUP = 'projectManagementPermissionUserGroup',
|
||||||
PROJECT_MANAGEMENT_PERMISSION_MEMBER = 'projectManagementPermissionMember',
|
PROJECT_MANAGEMENT_PERMISSION_MEMBER = 'projectManagementPermissionMember',
|
||||||
|
|
|
@ -27,6 +27,7 @@ export enum TableKeyEnum {
|
||||||
FILE_MANAGEMENT_CASE = 'fileManagementCase',
|
FILE_MANAGEMENT_CASE = 'fileManagementCase',
|
||||||
FILE_MANAGEMENT_VERSION = 'fileManagementVersion',
|
FILE_MANAGEMENT_VERSION = 'fileManagementVersion',
|
||||||
PROJECT_MANAGEMENT_MENU_FALSE_ALERT = 'projectManagementMenuFalseAlert',
|
PROJECT_MANAGEMENT_MENU_FALSE_ALERT = 'projectManagementMenuFalseAlert',
|
||||||
|
ORGANIZATION_TEMPLATE_DEFECT_TABLE = 'organizationTemplateManagementDefect',
|
||||||
}
|
}
|
||||||
|
|
||||||
// 具有特殊功能的列
|
// 具有特殊功能的列
|
||||||
|
|
|
@ -21,7 +21,7 @@ export enum TemplateIconEnum {
|
||||||
export enum TemplateCardEnum {
|
export enum TemplateCardEnum {
|
||||||
FUNCTIONAL = 'caseTemplate', // 用例模版
|
FUNCTIONAL = 'caseTemplate', // 用例模版
|
||||||
API = 'api_ui_Template', // ui模板
|
API = 'api_ui_Template', // ui模板
|
||||||
UI = 'api_ui_Template', // API模板
|
UI = 'uiTemplate', // API模板
|
||||||
TEST_PLAN = 'testPlanTemplate', // 测试计划模板
|
TEST_PLAN = 'testPlanTemplate', // 测试计划模板
|
||||||
BUG = 'defectTemplate', // 缺陷模板
|
BUG = 'defectTemplate', // 缺陷模板
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,22 @@ import { onBeforeRouteLeave } from 'vue-router';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
|
|
||||||
|
const isSave = ref(false);
|
||||||
|
|
||||||
// 离开页面确认提示
|
// 离开页面确认提示
|
||||||
export default function useLeaveUnSaveTip() {
|
export default function useLeaveUnSaveTip() {
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const setState = (flag: boolean) => {
|
||||||
|
isSave.value = flag;
|
||||||
|
};
|
||||||
onBeforeRouteLeave((to, from, next) => {
|
onBeforeRouteLeave((to, from, next) => {
|
||||||
if (to.path === from.path) {
|
if (to.path === from.path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSave.value) {
|
||||||
openModal({
|
openModal({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: t('common.unSaveLeaveTitle'),
|
title: t('common.unSaveLeaveTitle'),
|
||||||
|
@ -26,5 +33,11 @@ export default function useLeaveUnSaveTip() {
|
||||||
},
|
},
|
||||||
hideCancel: false,
|
hideCancel: false,
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
setState,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,11 +53,12 @@ export default {
|
||||||
'menu.settings.organization.userGroup': 'User Group',
|
'menu.settings.organization.userGroup': 'User Group',
|
||||||
'menu.settings.organization.project': 'Project',
|
'menu.settings.organization.project': 'Project',
|
||||||
'menu.settings.organization.template': 'Template',
|
'menu.settings.organization.template': 'Template',
|
||||||
|
'menu.settings.organization.bugTemplate': 'BUG Template',
|
||||||
'menu.settings.organization.templateFieldSetting': 'fieldSetting',
|
'menu.settings.organization.templateFieldSetting': 'fieldSetting',
|
||||||
'menu.settings.organization.templateManagementList': 'Template list',
|
'menu.settings.organization.templateManagementList': 'Template list',
|
||||||
'menu.settings.organization.templateManagementEdit': 'Update Template',
|
'menu.settings.organization.templateManagementEdit': 'Update Template',
|
||||||
'menu.settings.organization.templateManagementDetail': 'Create Template',
|
'menu.settings.organization.templateManagementDetail': 'Create Template',
|
||||||
'menu.settings.organization.templateManagementWorkFlow': 'WorkFlow',
|
'menu.settings.organization.templateManagementWorkFlow': 'WorkFlow Setting',
|
||||||
'menu.settings.organization.serviceIntegration': 'Service Integration',
|
'menu.settings.organization.serviceIntegration': 'Service Integration',
|
||||||
'menu.settings.organization.log': 'Log',
|
'menu.settings.organization.log': 'Log',
|
||||||
'navbar.action.locale': 'Switch to English',
|
'navbar.action.locale': 'Switch to English',
|
||||||
|
|
|
@ -29,6 +29,7 @@ export default {
|
||||||
'menu.caseManagement': '功能测试',
|
'menu.caseManagement': '功能测试',
|
||||||
'menu.performanceTest': '性能测试',
|
'menu.performanceTest': '性能测试',
|
||||||
'menu.projectManagement': '项目管理',
|
'menu.projectManagement': '项目管理',
|
||||||
|
'menu.projectManagement.templateManager': '模板管理',
|
||||||
'menu.projectManagement.log': '日志',
|
'menu.projectManagement.log': '日志',
|
||||||
'menu.projectManagement.fileManagement': '文件管理',
|
'menu.projectManagement.fileManagement': '文件管理',
|
||||||
'menu.projectManagement.messageManagement': '消息管理',
|
'menu.projectManagement.messageManagement': '消息管理',
|
||||||
|
@ -52,13 +53,14 @@ export default {
|
||||||
'menu.settings.organization.userGroup': '用户组',
|
'menu.settings.organization.userGroup': '用户组',
|
||||||
'menu.settings.organization.project': '项目',
|
'menu.settings.organization.project': '项目',
|
||||||
'menu.settings.organization.serviceIntegration': '服务集成',
|
'menu.settings.organization.serviceIntegration': '服务集成',
|
||||||
'menu.settings.organization.template': '模版',
|
'menu.settings.organization.template': '模板',
|
||||||
|
'menu.settings.organization.bugTemplate': '缺陷模板',
|
||||||
'menu.settings.organization.templateFieldSetting': '字段设置',
|
'menu.settings.organization.templateFieldSetting': '字段设置',
|
||||||
'menu.settings.organization.templateManagementList': '模版列表',
|
'menu.settings.organization.templateManagementList': '模版列表',
|
||||||
'menu.settings.organization.templateManagementDetail': '创建模版',
|
'menu.settings.organization.templateManagementDetail': '创建模版',
|
||||||
'menu.settings.organization.templateManagementCopy': '复制模版',
|
'menu.settings.organization.templateManagementCopy': '复制模版',
|
||||||
'menu.settings.organization.templateManagementEdit': '更新模板',
|
'menu.settings.organization.templateManagementEdit': '更新模板',
|
||||||
'menu.settings.organization.templateManagementWorkFlow': '工作流',
|
'menu.settings.organization.templateManagementWorkFlow': '工作流设置',
|
||||||
'menu.settings.organization.log': '日志',
|
'menu.settings.organization.log': '日志',
|
||||||
'navbar.action.locale': '切换为中文',
|
'navbar.action.locale': '切换为中文',
|
||||||
...sys,
|
...sys,
|
||||||
|
|
|
@ -27,7 +27,7 @@ export interface FieldOptions {
|
||||||
fieldId?: string;
|
fieldId?: string;
|
||||||
value: string | string[] | number | number[];
|
value: string | string[] | number | number[];
|
||||||
text: string;
|
text: string;
|
||||||
internal?: boolean;
|
internal?: boolean; // 是否是内置模版
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义字段
|
// 自定义字段
|
||||||
|
@ -69,6 +69,7 @@ export interface AddOrUpdateField {
|
||||||
scopeId: string; // 组织或项目ID
|
scopeId: string; // 组织或项目ID
|
||||||
options?: FieldOption[];
|
options?: FieldOption[];
|
||||||
enableOptionKey: boolean;
|
enableOptionKey: boolean;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface fieldIconAndNameModal {
|
export interface fieldIconAndNameModal {
|
||||||
|
@ -98,8 +99,8 @@ export interface OrdTemplateManagement {
|
||||||
|
|
||||||
export interface CustomField {
|
export interface CustomField {
|
||||||
fieldId: string;
|
fieldId: string;
|
||||||
required: boolean; // 是否必填
|
required?: boolean; // 是否必填
|
||||||
apiFieldId: string; // api字段名
|
apiFieldId?: string; // api字段名
|
||||||
defaultValue: string | string[] | null | number; // 默认值
|
defaultValue: string | string[] | null | number; // 默认值
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +112,8 @@ export interface ActionTemplateManage {
|
||||||
enableThirdPart?: boolean; // 是否开启api字段名配置
|
enableThirdPart?: boolean; // 是否开启api字段名配置
|
||||||
scene?: SeneType;
|
scene?: SeneType;
|
||||||
customFields?: CustomField[];
|
customFields?: CustomField[];
|
||||||
|
fieldType?: string;
|
||||||
|
systemFields?: Record<string, any>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作流列表字段
|
// 工作流列表字段
|
||||||
|
@ -153,7 +156,7 @@ export interface SetStateType {
|
||||||
|
|
||||||
// 更新流转状态
|
// 更新流转状态
|
||||||
export interface UpdateWorkFlowSetting {
|
export interface UpdateWorkFlowSetting {
|
||||||
fromId: string;
|
fromId: string; // 开始id
|
||||||
toId: string;
|
toId: string; // 结束id
|
||||||
enable: boolean;
|
enable: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,16 +47,6 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 模版管理
|
|
||||||
{
|
|
||||||
path: 'templateManager',
|
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_TEMPLATE,
|
|
||||||
component: () => import('@/views/project-management/projectAndPermission/templateManagement/index.vue'),
|
|
||||||
meta: {
|
|
||||||
locale: 'project.permission.templateManager',
|
|
||||||
roles: ['*'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 项目版本
|
// 项目版本
|
||||||
{
|
{
|
||||||
path: 'projectVersion',
|
path: 'projectVersion',
|
||||||
|
@ -89,6 +79,104 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 項目管理模板
|
||||||
|
{
|
||||||
|
path: 'templateManager',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
component: () => import('@/views/project-management/template/index.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.projectManagement.templateManager',
|
||||||
|
roles: ['*'],
|
||||||
|
isTopMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 模板列表-模板字段设置
|
||||||
|
{
|
||||||
|
path: 'filedSetting',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING,
|
||||||
|
component: () => import('@/views/project-management/template/components/projectFieldSetting.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.settings.organization.templateFieldSetting',
|
||||||
|
roles: ['*'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.projectManagement.templateManager',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING,
|
||||||
|
locale: 'menu.settings.organization.templateFieldSetting',
|
||||||
|
editLocale: 'menu.settings.organization.templateFieldSetting',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 模板列表-模板管理列表
|
||||||
|
{
|
||||||
|
path: 'templateManagement',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
component: () => import('@/views/project-management/template/components/templateManagement.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.settings.organization.templateManagement',
|
||||||
|
roles: ['*'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
editLocale: 'menu.settings.organization.templateManagementList',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 项目-模板-创建模板和模板详情
|
||||||
|
{
|
||||||
|
path: 'templateDetail/:mode?',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
component: () => import('@/views/project-management/template/components/proTemplateDetail.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.settings.organization.templateManagementDetail',
|
||||||
|
roles: ['*'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.template',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
locale: 'menu.settings.organization.templateManagementList',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
locale: 'menu.settings.organization.templateManagementDetail',
|
||||||
|
editLocale: 'menu.settings.organization.templateManagementEdit',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 模板列表-模板管理-工作流
|
||||||
|
{
|
||||||
|
path: 'templateWorkFlow',
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
component: () => import('@/views/project-management/template/components/workFlowTableIndex.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
|
roles: ['*'],
|
||||||
|
breadcrumbs: [
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE,
|
||||||
|
locale: 'menu.settings.organization.bugTemplate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
// 文件管理
|
// 文件管理
|
||||||
{
|
{
|
||||||
path: 'fileManagement',
|
path: 'fileManagement',
|
||||||
|
|
|
@ -192,7 +192,7 @@ const Setting: AppRouteRecordRaw = {
|
||||||
{
|
{
|
||||||
path: 'templateFiledSetting',
|
path: 'templateFiledSetting',
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
|
||||||
component: () => import('@/views/setting/organization/template/components/fieldSetting.vue'),
|
component: () => import('@/views/setting/organization/template/components/ordFieldSetting.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.templateFieldSetting',
|
locale: 'menu.settings.organization.templateFieldSetting',
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
|
@ -259,14 +259,14 @@ const Setting: AppRouteRecordRaw = {
|
||||||
{
|
{
|
||||||
path: 'templateWorkFlow',
|
path: 'templateWorkFlow',
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
component: () => import('@/views/setting/organization/template/components/workflowTable.vue'),
|
component: () => import('@/views/setting/organization/template/components/workFlowTableIndex.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
locale: 'menu.settings.organization.templateManagementWorkFlow',
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,
|
||||||
locale: 'menu.settings.organization.template',
|
locale: 'menu.settings.organization.bugTemplate',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
|
|
@ -73,6 +73,7 @@ const useFormCreateStore = defineStore('form-create', {
|
||||||
'modelValue': item.value,
|
'modelValue': item.value,
|
||||||
'options': currentOptions, // 当前已经存在的options
|
'options': currentOptions, // 当前已经存在的options
|
||||||
'formKey': key, // 对应pinia-form-create里边初始化的KEY
|
'formKey': key, // 对应pinia-form-create里边初始化的KEY
|
||||||
|
'disabled': item?.props?.disabled,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// 如果不存在关联name删除link关联属性
|
// 如果不存在关联name删除link关联属性
|
||||||
|
@ -87,9 +88,7 @@ const useFormCreateStore = defineStore('form-create', {
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
if (result && result.length) {
|
|
||||||
this.setInitdRules(key, result as FormRuleItem[]);
|
this.setInitdRules(key, result as FormRuleItem[]);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 初始化好了的格式给formCreate
|
// 初始化好了的格式给formCreate
|
||||||
setInitdRules(key: FormCreateKeyEnum[keyof FormCreateKeyEnum], result: FormRuleItem[]) {
|
setInitdRules(key: FormCreateKeyEnum[keyof FormCreateKeyEnum], result: FormRuleItem[]) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { isEnableTemplate } from '@/api/modules/setting/template';
|
import { getOrdTemplate, getProTemplate } from '@/api/modules/setting/template';
|
||||||
|
|
||||||
import useAppStore from '../app';
|
import useAppStore from '../app';
|
||||||
|
|
||||||
|
@ -9,40 +9,36 @@ const appStore = useAppStore();
|
||||||
const useTemplateStore = defineStore('template', {
|
const useTemplateStore = defineStore('template', {
|
||||||
persist: true,
|
persist: true,
|
||||||
state: (): {
|
state: (): {
|
||||||
templateStatus: Record<string, boolean>;
|
ordStatus: Record<string, boolean>;
|
||||||
|
projectStatus: Record<string, boolean>;
|
||||||
} => ({
|
} => ({
|
||||||
templateStatus: {
|
ordStatus: {
|
||||||
FUNCTIONAL: true,
|
FUNCTIONAL: false,
|
||||||
API: true,
|
API: false,
|
||||||
UI: true,
|
UI: false,
|
||||||
TEST_PLAN: true,
|
TEST_PLAN: false,
|
||||||
BUG: true,
|
BUG: false,
|
||||||
|
},
|
||||||
|
projectStatus: {
|
||||||
|
FUNCTIONAL: false,
|
||||||
|
API: false,
|
||||||
|
UI: false,
|
||||||
|
TEST_PLAN: false,
|
||||||
|
BUG: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
// 模板列表的状态
|
// 模板列表的状态
|
||||||
async getStatus() {
|
async getStatus() {
|
||||||
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
try {
|
try {
|
||||||
this.templateStatus = await isEnableTemplate(appStore.currentOrgId);
|
this.ordStatus = await getOrdTemplate(currentOrgId.value);
|
||||||
|
this.projectStatus = await getProTemplate(currentProjectId.value);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 获取项目模板状态
|
|
||||||
getProjectTemplateState() {
|
|
||||||
const { FUNCTIONAL, API, UI, TEST_PLAN, BUG } = this.templateStatus;
|
|
||||||
return {
|
|
||||||
FUNCTIONAL: !FUNCTIONAL,
|
|
||||||
API: !API,
|
|
||||||
UI: !UI,
|
|
||||||
TEST_PLAN: !TEST_PLAN,
|
|
||||||
BUG: !BUG,
|
|
||||||
} as Record<string, boolean>;
|
|
||||||
},
|
|
||||||
// 获取组织模板状态
|
|
||||||
getOrdTemplateState() {
|
|
||||||
return this.templateStatus;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,6 @@
|
||||||
level: 2,
|
level: 2,
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT,
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'templateManager',
|
|
||||||
title: 'project.permission.templateManager',
|
|
||||||
level: 2,
|
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_TEMPLATE,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'projectVersion',
|
key: 'projectVersion',
|
||||||
title: 'project.permission.projectVersion',
|
title: 'project.permission.projectVersion',
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
{{ t('organization.member.statusDisable') }}
|
{{ t('organization.member.statusDisable') }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ record }">
|
<template #operation="{ record }">
|
||||||
<MsRemoveButton
|
<MsRemoveButton
|
||||||
position="br"
|
position="br"
|
||||||
:title="t('project.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
:title="t('project.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
} from '@/api/modules/project-management/projectMember';
|
} from '@/api/modules/project-management/projectMember';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const tableStore = useTableStore();
|
||||||
const lastProjectId = computed(() => appStore.getCurrentProjectId);
|
const lastProjectId = computed(() => appStore.getCurrentProjectId);
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
|
@ -131,18 +131,22 @@
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
fixed: 'left',
|
sortIndex: 0,
|
||||||
|
ellipsis: true,
|
||||||
|
showDrag: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'project.member.tableColumnEmail',
|
title: 'project.member.tableColumnEmail',
|
||||||
dataIndex: 'email',
|
dataIndex: 'email',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
|
showDrag: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'project.member.tableColumnPhone',
|
title: 'project.member.tableColumnPhone',
|
||||||
dataIndex: 'phone',
|
dataIndex: 'phone',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -150,6 +154,7 @@
|
||||||
slotName: 'userRole',
|
slotName: 'userRole',
|
||||||
dataIndex: 'userRoleIdNameMap',
|
dataIndex: 'userRoleIdNameMap',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
showDrag: true,
|
||||||
width: 300,
|
width: 300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -161,10 +166,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'project.member.tableColumnActions',
|
title: 'project.member.tableColumnActions',
|
||||||
slotName: 'action',
|
slotName: 'operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
|
dataIndex: 'operation',
|
||||||
width: 100,
|
width: 100,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
showDrag: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -368,6 +375,7 @@
|
||||||
initData();
|
initData();
|
||||||
initOptions();
|
initOptions();
|
||||||
});
|
});
|
||||||
|
tableStore.initColumn(TableKeyEnum.PROJECT_MEMBER, columns, 'drawer');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
<template>
|
|
||||||
<div> 模版管理 </div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -0,0 +1,403 @@
|
||||||
|
<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"
|
||||||
|
show-word-limit
|
||||||
|
class="max-w-[732px]"
|
||||||
|
></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="255"
|
||||||
|
:placeholder="t('system.orgTemplate.resDescription')"
|
||||||
|
:auto-size="{
|
||||||
|
maxRows: 1,
|
||||||
|
}"
|
||||||
|
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')"
|
||||||
|
show-word-limit
|
||||||
|
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:model-value="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,
|
||||||
|
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' ? `${name}_copy` : 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');
|
||||||
|
getClassifyField();
|
||||||
|
} else if (isEdit.value) {
|
||||||
|
title.value = t('menu.settings.organization.templateManagementEdit');
|
||||||
|
getClassifyField();
|
||||||
|
} else {
|
||||||
|
title.value = t('menu.settings.organization.templateManagementDetail');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<template>
|
||||||
|
<MsCard has-breadcrumb simple> <FieldSetting mode="project" /></MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 项目管理-模板-字段设置-首页
|
||||||
|
*/
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue';
|
||||||
|
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
|
|
||||||
|
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
// 更新面包屑
|
||||||
|
const updateBreadcrumbList = () => {
|
||||||
|
const { breadcrumbList } = appStore;
|
||||||
|
const breadTitle = getCardList('project').find((item: any) => item.key === route.query.type);
|
||||||
|
if (breadTitle) {
|
||||||
|
breadcrumbList[0].locale = breadTitle.name;
|
||||||
|
appStore.setBreadcrumbList(breadcrumbList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateBreadcrumbList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,369 @@
|
||||||
|
<template>
|
||||||
|
<MsCard has-breadcrumb simple>
|
||||||
|
<div class="mb-4 flex items-center justify-between">
|
||||||
|
<span v-if="isEnableOrdTemplate" class="font-medium">{{ t('system.orgTemplate.templateList') }}</span>
|
||||||
|
<a-button v-else type="primary" :disabled="false" @click="createTemplate">
|
||||||
|
{{ t('system.orgTemplate.createTemplate') }}
|
||||||
|
</a-button>
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('system.orgTemplate.searchTip')"
|
||||||
|
class="w-[230px]"
|
||||||
|
allow-clear
|
||||||
|
@search="searchFiled"
|
||||||
|
@press-enter="searchFiled"
|
||||||
|
></a-input-search>
|
||||||
|
</div>
|
||||||
|
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
||||||
|
<template #defaultTemplate="{ record }">
|
||||||
|
<a-switch
|
||||||
|
v-model="record.enableDefault"
|
||||||
|
:disabled="record.enableDefault || isEnableOrdTemplate"
|
||||||
|
size="small"
|
||||||
|
@change="(value) => changeDefault(value, record)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #enableThirdPart="{ record }">
|
||||||
|
{{ record.enableThirdPart ? t('system.orgTemplate.yes') : t('system.orgTemplate.no') }}
|
||||||
|
</template>
|
||||||
|
<template #name="{ record }">
|
||||||
|
<span class="ml-2 cursor-pointer text-[rgb(var(--primary-5))]" @click="previewDetail(record)">{{
|
||||||
|
record.name
|
||||||
|
}}</span>
|
||||||
|
<MsTag v-if="record.internal" size="small" class="ml-2">{{ t('system.orgTemplate.isSystem') }}</MsTag>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<div class="flex flex-row flex-nowrap">
|
||||||
|
<MsButton @click="editTemplate(record.id)">{{ t('system.orgTemplate.edit') }}</MsButton>
|
||||||
|
<MsButton class="!mr-0" @click="copyTemplate(record.id)">{{ t('system.orgTemplate.copy') }}</MsButton>
|
||||||
|
<a-divider v-if="!record.internal" direction="vertical" />
|
||||||
|
<MsTableMoreAction
|
||||||
|
v-if="!record.internal"
|
||||||
|
:list="moreActions"
|
||||||
|
@select="(item) => handleMoreActionSelect(item, record)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
|
<MsDrawer
|
||||||
|
v-model:visible="showDetailVisible"
|
||||||
|
:title="titleDetail"
|
||||||
|
:width="1200"
|
||||||
|
:footer="false"
|
||||||
|
unmount-on-close
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<PreviewTemplate
|
||||||
|
:select-field="(selectData as DefinedFieldItem[])"
|
||||||
|
:template-type="route.query.type"
|
||||||
|
:defect-form="defectForm"
|
||||||
|
/>
|
||||||
|
</MsDrawer>
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-项目-模版-模版管理列表
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.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 MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
import PreviewTemplate from '@/views/setting/organization/template/components/viewTemplate.vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
deleteOrdTemplate,
|
||||||
|
getProjectFieldList,
|
||||||
|
getProjectTemplateInfo,
|
||||||
|
getProjectTemplateList,
|
||||||
|
setDefaultTemplate,
|
||||||
|
} from '@/api/modules/setting/template';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useModal from '@/hooks/useModal';
|
||||||
|
import router from '@/router';
|
||||||
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
|
import type { DefinedFieldItem, OrdTemplateManagement } from '@/models/setting/template';
|
||||||
|
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getCardList,
|
||||||
|
getCustomDetailFields,
|
||||||
|
getTotalFieldOptionList,
|
||||||
|
} from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const tableStore = useTableStore();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const templateStore = useTemplateStore();
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const keyword = ref('');
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
|
const sceneType = computed(() => route.query.type);
|
||||||
|
|
||||||
|
const fieldColumns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.columnTemplateName',
|
||||||
|
slotName: 'name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 300,
|
||||||
|
fixed: 'left',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.defaultTemplate',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
slotName: 'defaultTemplate',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.description',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
width: 300,
|
||||||
|
showTooltip: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.columnFieldUpdatedTime',
|
||||||
|
dataIndex: 'updateTime',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const isThirdParty = {
|
||||||
|
title: 'system.orgTemplate.isThirdParty',
|
||||||
|
dataIndex: 'enableThirdPart',
|
||||||
|
slotName: 'enableThirdPart',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
await tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT, fieldColumns, 'drawer');
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getProjectTemplateList, {
|
||||||
|
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
scroll: { x: '1400px' },
|
||||||
|
selectable: false,
|
||||||
|
noDisable: true,
|
||||||
|
size: 'default',
|
||||||
|
showSetting: true,
|
||||||
|
showPagination: false,
|
||||||
|
heightUsed: 380,
|
||||||
|
});
|
||||||
|
const scene = route.query.type;
|
||||||
|
const isEnableOrdTemplate = computed(() => {
|
||||||
|
return !templateStore.projectStatus[scene as string];
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalList = ref<OrdTemplateManagement[]>([]);
|
||||||
|
|
||||||
|
// 查询字段
|
||||||
|
const searchFiled = async () => {
|
||||||
|
try {
|
||||||
|
totalList.value = await getProjectTemplateList({ projectId: currentProjectId.value, scene });
|
||||||
|
const filterData = totalList.value.filter((item: OrdTemplateManagement) => item.name.includes(keyword.value));
|
||||||
|
setProps({ data: filterData });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const moreActions: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 删除模板
|
||||||
|
const handlerDelete = (record: any) => {
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title: t('system.orgTemplate.deleteTemplateTitle', { name: characterLimit(record.name) }),
|
||||||
|
content: t('system.userGroup.beforeDeleteUserGroup'),
|
||||||
|
okText: t('system.userGroup.confirmDelete'),
|
||||||
|
cancelText: t('system.userGroup.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
if (record.id) await deleteOrdTemplate(record.id);
|
||||||
|
Message.success(t('common.deleteSuccess'));
|
||||||
|
loadList();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更多操作
|
||||||
|
const handleMoreActionSelect = (item: ActionsItem, record: any) => {
|
||||||
|
if (item.eventTag === 'delete') {
|
||||||
|
handlerDelete(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
setLoadListParams({ projectId: currentProjectId.value, scene: route.query.type });
|
||||||
|
await loadList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置默认模版
|
||||||
|
const changeDefault = async (value: any, record: OrdTemplateManagement) => {
|
||||||
|
if (value) {
|
||||||
|
try {
|
||||||
|
await setDefaultTemplate(currentProjectId.value, record.id);
|
||||||
|
Message.success(t('system.orgTemplate.setSuccessfully'));
|
||||||
|
fetchData();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建模板
|
||||||
|
const createTemplate = () => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
query: {
|
||||||
|
type: route.query.type,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
mode: 'create',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑模板
|
||||||
|
const editTemplate = (id: string) => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
query: {
|
||||||
|
id,
|
||||||
|
type: route.query.type,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
mode: 'edit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 复制模板
|
||||||
|
const copyTemplate = (id: string) => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_DETAIL,
|
||||||
|
query: {
|
||||||
|
id,
|
||||||
|
type: route.query.type,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
mode: 'copy',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const showDetailVisible = ref<boolean>(false);
|
||||||
|
const selectData = ref<DefinedFieldItem[]>([]);
|
||||||
|
const totalData = ref<DefinedFieldItem[]>([]);
|
||||||
|
|
||||||
|
// 处理自定义字段列表
|
||||||
|
const getFieldOptionList = () => {
|
||||||
|
totalData.value = getTotalFieldOptionList(totalData.value as DefinedFieldItem[]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const initDetailForm = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
};
|
||||||
|
const titleDetail = ref<string>();
|
||||||
|
const defectForm = ref<Record<string, any>>({ ...initDetailForm });
|
||||||
|
// 预览详情
|
||||||
|
const previewDetail = async (record: OrdTemplateManagement) => {
|
||||||
|
showDetailVisible.value = true;
|
||||||
|
titleDetail.value = record.name;
|
||||||
|
try {
|
||||||
|
totalData.value = await getProjectFieldList({ scopedId: currentProjectId.value, scene: route.query.type });
|
||||||
|
getFieldOptionList();
|
||||||
|
const res = await getProjectTemplateInfo(record.id);
|
||||||
|
selectData.value = getCustomDetailFields(totalData.value as DefinedFieldItem[], res.customFields);
|
||||||
|
res.systemFields.forEach((item: any) => {
|
||||||
|
defectForm.value[item.fieldId] = item.defaultValue;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
showDetailVisible.value = false;
|
||||||
|
defectForm.value = { ...initDetailForm };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新面包屑根据不同的模版
|
||||||
|
const updateBreadcrumbList = () => {
|
||||||
|
const { breadcrumbList } = appStore;
|
||||||
|
const breadTitle = getCardList('project').find((item: any) => item.key === route.query.type);
|
||||||
|
if (breadTitle) {
|
||||||
|
breadcrumbList[0].locale = breadTitle.name;
|
||||||
|
appStore.setBreadcrumbList(breadcrumbList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableRef = ref();
|
||||||
|
|
||||||
|
function updateColumns() {
|
||||||
|
const columns =
|
||||||
|
sceneType.value === 'BUG' ? fieldColumns.slice(0, 2).concat(isThirdParty, fieldColumns.slice(2)) : fieldColumns;
|
||||||
|
if (isEnableOrdTemplate.value) {
|
||||||
|
const result = columns.slice(0, fieldColumns.length - 1);
|
||||||
|
tableRef.value.initColumn(result);
|
||||||
|
} else {
|
||||||
|
tableRef.value.initColumn(columns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateBreadcrumbList();
|
||||||
|
fetchData();
|
||||||
|
updateColumns();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.system-flag {
|
||||||
|
background: var(--color-text-n8);
|
||||||
|
@apply ml-2 rounded p-1 text-xs;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<MsCard has-breadcrumb simple>
|
||||||
|
<WorkflowTable mode="project" />
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 项目管理-模版-模版管理-工作流首页
|
||||||
|
*/
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import WorkflowTable from '@/views/setting/organization/template/components/workflowTable.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<MsCard simple>
|
||||||
|
<MsCardList
|
||||||
|
mode="static"
|
||||||
|
:card-min-width="360"
|
||||||
|
class="flex-1"
|
||||||
|
:shadow-limit="50"
|
||||||
|
:list="cardList"
|
||||||
|
:is-proportional="false"
|
||||||
|
:gap="16"
|
||||||
|
padding-bottom-space="16px"
|
||||||
|
>
|
||||||
|
<template #item="{ item, index }">
|
||||||
|
<TemplateItem
|
||||||
|
:card-item="item"
|
||||||
|
:index="index"
|
||||||
|
mode="organization"
|
||||||
|
@field-setting="fieldSetting"
|
||||||
|
@template-management="templateManagement"
|
||||||
|
@workflow-setup="workflowSetup"
|
||||||
|
@update-state="updateState"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</MsCardList>
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 项目设置--模版
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import MsCardList from '@/components/business/ms-card-list/index.vue';
|
||||||
|
import TemplateItem from '@/views/setting/organization/template/components/templateItem.vue';
|
||||||
|
|
||||||
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
|
||||||
|
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
|
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const templateStore = useTemplateStore();
|
||||||
|
// 字段设置
|
||||||
|
const fieldSetting = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_FIELD_SETTING,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 模板管理
|
||||||
|
const templateManagement = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 工作流
|
||||||
|
const workflowSetup = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardList = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
// 更新状态列表
|
||||||
|
const updateState = () => {
|
||||||
|
cardList.value = [...getCardList('project')];
|
||||||
|
};
|
||||||
|
onBeforeMount(() => {
|
||||||
|
templateStore.getStatus();
|
||||||
|
updateState();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
|
@ -43,6 +43,7 @@
|
||||||
>
|
>
|
||||||
<a-option v-for="item of projectOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
<a-option v-for="item of projectOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
<span v-if="(record.selectProjectList || []).length === 0">-</span>
|
||||||
</template>
|
</template>
|
||||||
<template #userRole="{ record }">
|
<template #userRole="{ record }">
|
||||||
<MsTagGroup
|
<MsTagGroup
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
>
|
>
|
||||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
<span v-if="(record.selectUserList || []).length === 0">-</span>
|
||||||
</template>
|
</template>
|
||||||
<template #enable="{ record }">
|
<template #enable="{ record }">
|
||||||
<div v-if="record.enable" class="flex items-center">
|
<div v-if="record.enable" class="flex items-center">
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
height: `calc(100vh - ${collapseHeight} - 230px)`,
|
height: `calc(100vh - ${collapseHeight} - 230px)`,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="list">
|
<div v-if="filterList.length" class="list">
|
||||||
<div v-for="item of filterList" :key="item.id" class="item">
|
<div v-for="item of filterList" :key="item.id" class="item">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<span class="icon float-left mr-2 h-[40px] w-[40px] rounded">
|
<span class="icon float-left mr-2 h-[40px] w-[40px] rounded">
|
||||||
|
@ -94,6 +94,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a-empty class="mt-20">
|
||||||
|
暂无数据
|
||||||
|
<span class="cursor-pointer text-[rgb(var(--primary-5))]" @click="goPluginManagement">跳转至插件管理</span>
|
||||||
|
</a-empty>
|
||||||
</a-scrollbar>
|
</a-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -103,6 +107,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onBeforeMount, ref } from 'vue';
|
import { onBeforeMount, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import ConfigModal from './conifgModal.vue';
|
import ConfigModal from './conifgModal.vue';
|
||||||
|
@ -114,11 +119,13 @@
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import type { ServiceItem, ServiceList } from '@/models/setting/serviceIntegration';
|
import type { ServiceItem, ServiceList } from '@/models/setting/serviceIntegration';
|
||||||
|
import { SettingRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
import Message from '@arco-design/web-vue/es/message';
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const lastOrganizationId = appStore.currentOrgId;
|
const lastOrganizationId = appStore.currentOrgId;
|
||||||
|
@ -211,7 +218,12 @@
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// 跳转到插件管理
|
||||||
|
function goPluginManagement() {
|
||||||
|
router.push({
|
||||||
|
name: SettingRouteEnum.SETTING_SYSTEM_PLUGIN_MANAGEMENT,
|
||||||
|
});
|
||||||
|
}
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
loadList();
|
loadList();
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,7 +49,12 @@
|
||||||
</div>
|
</div>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
</div>
|
</div>
|
||||||
<EditFieldDrawer ref="fieldDrawerRef" v-model:visible="showFieldDrawer" @success="okHandler" />
|
<EditFieldDrawer
|
||||||
|
ref="fieldDrawerRef"
|
||||||
|
v-model:visible="showFieldDrawer"
|
||||||
|
:mode="props.mode"
|
||||||
|
@success="okHandler"
|
||||||
|
/>
|
||||||
<div>
|
<div>
|
||||||
<a-button class="mt-1 px-0" type="text" :disabled="totalData.length > 20" @click="createField">
|
<a-button class="mt-1 px-0" type="text" :disabled="totalData.length > 20" @click="createField">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
@ -92,8 +97,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-模版-模版管理-创建模板-添加字段到模板抽屉
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
@ -111,6 +118,7 @@
|
||||||
const drawerLoading = ref<boolean>(false);
|
const drawerLoading = ref<boolean>(false);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
totalData: DefinedFieldItem[]; // 所有字段
|
totalData: DefinedFieldItem[]; // 所有字段
|
||||||
tableSelectData: DefinedFieldItem[]; // 表格选择字段
|
tableSelectData: DefinedFieldItem[]; // 表格选择字段
|
||||||
|
@ -136,7 +144,7 @@
|
||||||
// 监视回显字段
|
// 监视回显字段
|
||||||
watch(
|
watch(
|
||||||
() => props.tableSelectData,
|
() => props.tableSelectData,
|
||||||
(val) => {
|
() => {
|
||||||
const sysField = props.tableSelectData.filter((item) => item.internal);
|
const sysField = props.tableSelectData.filter((item) => item.internal);
|
||||||
const cusField = props.tableSelectData.filter((item) => !item.internal);
|
const cusField = props.tableSelectData.filter((item) => !item.internal);
|
||||||
selectSystemIds.value = sysField.map((item) => item.id);
|
selectSystemIds.value = sysField.map((item) => item.id);
|
||||||
|
@ -183,10 +191,9 @@
|
||||||
() => totalIds.value,
|
() => totalIds.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
const res = totalList.value.filter((item) => val.indexOf(item.id) > -1);
|
const res = totalList.value.filter((item) => val.indexOf(item.id) > -1);
|
||||||
const result = res.sort((a, b) => {
|
selectedList.value = res.sort((a, b) => {
|
||||||
return val.indexOf(a.id) - val.indexOf(b.id);
|
return val.indexOf(a.id) - val.indexOf(b.id);
|
||||||
});
|
});
|
||||||
selectedList.value = result;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -42,31 +42,42 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织-模板管理-工作流-创建工作流状态
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsDialog from '@/components/pure/ms-dialog/index.vue';
|
import MsDialog from '@/components/pure/ms-dialog/index.vue';
|
||||||
|
|
||||||
import { createWorkFlowStatus, updateWorkFlowStatus } from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
|
|
||||||
import type { OrdWorkStatus } from '@/models/setting/template';
|
import type { OrdWorkStatus } from '@/models/setting/template';
|
||||||
|
|
||||||
|
import { getWorkFlowRequestApi } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
|
}>();
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(e: 'update:visible', visible: boolean): void;
|
(e: 'update:visible', visible: boolean): void;
|
||||||
(e: 'success'): void;
|
(e: 'success'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
|
|
||||||
const initFormValue: OrdWorkStatus = {
|
const initFormValue: OrdWorkStatus = {
|
||||||
scopeId: currentOrgId.value,
|
scopeId: '',
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
scene: route.query.type,
|
scene: route.query.type,
|
||||||
|
@ -87,11 +98,14 @@
|
||||||
|
|
||||||
const isEdit = computed(() => !!form.value.id);
|
const isEdit = computed(() => !!form.value.id);
|
||||||
|
|
||||||
// 添加项目成员
|
const createWorkFlowStatus = getWorkFlowRequestApi(props.mode).create;
|
||||||
|
const updateWorkFlowStatus = getWorkFlowRequestApi(props.mode).update;
|
||||||
const confirmHandler = async (enable: boolean | undefined) => {
|
const confirmHandler = async (enable: boolean | undefined) => {
|
||||||
await formRef.value?.validate().then(async (error) => {
|
await formRef.value?.validate().then(async (error) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
try {
|
try {
|
||||||
|
const scopeId = props.mode === 'organization' ? currentOrgId.value : currentProjectId.value;
|
||||||
|
form.value.scopeId = scopeId;
|
||||||
if (!form.value.id) {
|
if (!form.value.id) {
|
||||||
form.value.allTransferTo = enable as boolean;
|
form.value.allTransferTo = enable as boolean;
|
||||||
await createWorkFlowStatus(form.value);
|
await createWorkFlowStatus(form.value);
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
<template>
|
||||||
|
<a-form ref="viewFormRef" class="rounded-[4px]" :model="viewForm" layout="vertical">
|
||||||
|
<a-form-item
|
||||||
|
field="caseName"
|
||||||
|
:label="t('system.orgTemplate.caseName')"
|
||||||
|
:rules="[{ required: true, message: t('system.orgTemplate.caseNamePlaceholder') }]"
|
||||||
|
required
|
||||||
|
asterisk-position="end"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="viewForm.name"
|
||||||
|
:max-length="255"
|
||||||
|
:placeholder="t('system.orgTemplate.caseNamePlaceholder')"
|
||||||
|
show-word-limit
|
||||||
|
allow-clear
|
||||||
|
:disabled="isDisabled"
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="precondition" :label="t('system.orgTemplate.precondition')" asterisk-position="end">
|
||||||
|
<MsRichText v-model="viewForm.precondition" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="step" :label="t('system.orgTemplate.stepDescription')" class="relative">
|
||||||
|
<div class="absolute left-16 top-0">
|
||||||
|
<a-divider direction="vertical" />
|
||||||
|
<a-dropdown :popup-max-height="false" @select="handleSelectType">
|
||||||
|
<span class="text-[14px] text-[var(--color-text-4)]"
|
||||||
|
>{{ t('system.orgTemplate.changeType') }} <icon-down
|
||||||
|
/></span>
|
||||||
|
<template #content>
|
||||||
|
<a-doption> {{ t('system.orgTemplate.stepDescription') }}</a-doption>
|
||||||
|
<a-doption>{{ t('system.orgTemplate.textDescription') }}</a-doption>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
</div>
|
||||||
|
<!-- 步骤描述 -->
|
||||||
|
<div class="w-full">
|
||||||
|
<MsBaseTable v-bind="propsRes" ref="stepTableRef" v-on="propsEvent">
|
||||||
|
<template #index="{ rowIndex }">
|
||||||
|
{{ rowIndex + 1 }}
|
||||||
|
</template>
|
||||||
|
<template #caseStep="{ record }">
|
||||||
|
<a-input v-if="record.showStep" v-model="record.caseStep" class="w-max-[267px]" />
|
||||||
|
<span v-else-if="record.caseStep && !record.showStep">{{ record.caseStep }}</span>
|
||||||
|
<span v-else-if="!record.caseStep && !record.showStep" class="placeholder text-[var(--color-text-brand)]">{{
|
||||||
|
t('system.orgTemplate.stepTip')
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<template #expectedResult="{ record }">
|
||||||
|
<a-input v-if="record.showExpected" v-model="record.expectedResult" class="w-max-[267px]" />
|
||||||
|
<span v-else-if="record.expectedResult && !record.showExpected">{{ record.caseStep }}</span>
|
||||||
|
<span
|
||||||
|
v-else-if="!record.expectedResult && !record.showExpected"
|
||||||
|
class="placeholder text-[var(--color-text-brand)]"
|
||||||
|
>{{ t('system.orgTemplate.expectationTip') }}</span
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<MsTableMoreAction
|
||||||
|
v-if="!record.internal"
|
||||||
|
:list="moreActions"
|
||||||
|
@select="(item:ActionsItem) => handleMoreActionSelect(item)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
|
</div>
|
||||||
|
<a-button class="mt-2 px-0" type="text" :disabled="isDisabled" @click="addStep">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus class="text-[14px]" />
|
||||||
|
</template>
|
||||||
|
{{ t('system.orgTemplate.addStep') }}
|
||||||
|
</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="remark" label="备注"> <MsRichText v-model="viewForm.remark" /> </a-form-item>
|
||||||
|
<a-form-item field="attachment" label="添加附件">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="mb-1"
|
||||||
|
><a-button type="outline" :disabled="isDisabled">
|
||||||
|
<template #icon> <icon-plus class="text-[14px]" /> </template
|
||||||
|
>{{ t('system.orgTemplate.addAttachment') }}</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="text-[var(--color-text-4)]">{{ t('system.orgTemplate.addAttachmentTip') }}</div>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织-模板管理-用例模板左侧内容
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.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 MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
const isDisabled = ref<boolean>(true);
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const viewForm = ref({
|
||||||
|
name: '',
|
||||||
|
precondition: '',
|
||||||
|
value: '',
|
||||||
|
remark: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSelectType = () => {};
|
||||||
|
|
||||||
|
const moreActions: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.orgTemplate.copy',
|
||||||
|
eventTag: 'copy',
|
||||||
|
disabled: isDisabled.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'system.orgTemplate.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
disabled: isDisabled.value,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const templateFieldColumns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.numberIndex',
|
||||||
|
dataIndex: 'index',
|
||||||
|
slotName: 'index',
|
||||||
|
width: 100,
|
||||||
|
showDrag: false,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.useCaseStep',
|
||||||
|
slotName: 'caseStep',
|
||||||
|
dataIndex: 'caseStep',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.expectedResult',
|
||||||
|
dataIndex: 'expectedResult',
|
||||||
|
slotName: 'expectedResult',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.orgTemplate.operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, setProps } = useTable(undefined, {
|
||||||
|
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_STEP,
|
||||||
|
columns: templateFieldColumns,
|
||||||
|
scroll: { x: '800px' },
|
||||||
|
selectable: false,
|
||||||
|
noDisable: true,
|
||||||
|
size: 'default',
|
||||||
|
showSetting: true,
|
||||||
|
showPagination: false,
|
||||||
|
enableDrag: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const addStep = () => {};
|
||||||
|
const handlerDelete = () => {};
|
||||||
|
|
||||||
|
// 更多操作
|
||||||
|
const handleMoreActionSelect = (item: ActionsItem) => {
|
||||||
|
if (item.eventTag === 'delete') {
|
||||||
|
handlerDelete();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
setProps({ data: [{ id: 1, showStep: false, showExpected: false }] });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,60 @@
|
||||||
|
<template>
|
||||||
|
<a-form ref="viewFormRef" class="rounded-[4px]" :model="viewForm" layout="vertical">
|
||||||
|
<a-form-item
|
||||||
|
field="defectName"
|
||||||
|
:label="t('system.orgTemplate.defectName')"
|
||||||
|
:rules="[{ required: true, message: t('system.orgTemplate.defectNamePlaceholder') }]"
|
||||||
|
required
|
||||||
|
asterisk-position="end"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="viewForm.name"
|
||||||
|
:disabled="true"
|
||||||
|
:max-length="255"
|
||||||
|
:placeholder="t('system.orgTemplate.defectNamePlaceholder')"
|
||||||
|
show-word-limit
|
||||||
|
allow-clear
|
||||||
|
></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="precondition" :label="t('system.orgTemplate.defectContent')" asterisk-position="end">
|
||||||
|
<MsRichText v-model="viewForm.description" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="attachment" label="添加附件">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="mb-1"
|
||||||
|
><a-button type="outline" :disabled="true">
|
||||||
|
<template #icon> <icon-plus class="text-[14px]" /> </template
|
||||||
|
>{{ t('system.orgTemplate.addAttachment') }}</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="text-[var(--color-text-4)]">{{ t('system.orgTemplate.addAttachmentTip') }}</div>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织-模板管理-缺陷模板左侧内容
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const viewForm = ref<Record<string, any>>({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
const props = defineProps<{
|
||||||
|
defectForm: Record<string, any>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
viewForm.value = { ...props.defectForm };
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -58,7 +58,7 @@
|
||||||
:label="t('system.orgTemplate.allowMultiMember')"
|
:label="t('system.orgTemplate.allowMultiMember')"
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
>
|
>
|
||||||
<a-switch v-model="isMultipleSelectMember" size="small" />
|
<a-switch v-model="isMultipleSelectMember" size="small" :disabled="isEdit" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 选项选择器 -->
|
<!-- 选项选择器 -->
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
@ -115,6 +115,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 模板管理-自定义字段-添加自定义字段&编辑自定义字段
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
@ -125,22 +128,22 @@
|
||||||
import MsBatchForm from '@/components/business/ms-batch-form/index.vue';
|
import MsBatchForm from '@/components/business/ms-batch-form/index.vue';
|
||||||
import type { FormItemModel, MsBatchFormInstance } from '@/components/business/ms-batch-form/types';
|
import type { FormItemModel, MsBatchFormInstance } from '@/components/business/ms-batch-form/types';
|
||||||
|
|
||||||
import { addOrUpdateOrdField, getOrdFieldDetail } from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import { getGenerateId } from '@/utils';
|
import { getGenerateId } from '@/utils';
|
||||||
|
|
||||||
import type { AddOrUpdateField, fieldIconAndNameModal } from '@/models/setting/template';
|
import type { AddOrUpdateField, fieldIconAndNameModal } from '@/models/setting/template';
|
||||||
|
|
||||||
import { fieldIconAndName, getFieldType } from './fieldSetting';
|
import { fieldIconAndName, getFieldRequestApi, getFieldType } from './fieldSetting';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
|
||||||
const sceneType = route.query.type;
|
const sceneType = route.query.type;
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
mode: 'organization' | 'project';
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits(['success', 'update:visible']);
|
const emit = defineEmits(['success', 'update:visible']);
|
||||||
|
|
||||||
|
@ -148,11 +151,17 @@
|
||||||
const drawerLoading = ref<boolean>(false);
|
const drawerLoading = ref<boolean>(false);
|
||||||
|
|
||||||
const fieldFormRef = ref<FormInstance>();
|
const fieldFormRef = ref<FormInstance>();
|
||||||
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
|
const scopeId = computed(() => {
|
||||||
|
return props.mode === 'organization' ? currentOrgId.value : currentProjectId.value;
|
||||||
|
});
|
||||||
const initFieldForm: AddOrUpdateField = {
|
const initFieldForm: AddOrUpdateField = {
|
||||||
name: '',
|
name: '',
|
||||||
type: undefined,
|
type: undefined,
|
||||||
remark: '',
|
remark: '',
|
||||||
scopeId: '',
|
scopeId: scopeId.value,
|
||||||
scene: 'FUNCTIONAL',
|
scene: 'FUNCTIONAL',
|
||||||
options: [],
|
options: [],
|
||||||
enableOptionKey: false,
|
enableOptionKey: false,
|
||||||
|
@ -232,6 +241,7 @@
|
||||||
resetForm();
|
resetForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { addOrUpdate, detail } = getFieldRequestApi(props.mode);
|
||||||
// 保存
|
// 保存
|
||||||
const confirmHandler = async (isContinue: boolean) => {
|
const confirmHandler = async (isContinue: boolean) => {
|
||||||
try {
|
try {
|
||||||
|
@ -240,7 +250,7 @@
|
||||||
const formCopy = cloneDeep(fieldForm.value);
|
const formCopy = cloneDeep(fieldForm.value);
|
||||||
|
|
||||||
formCopy.scene = route.query.type;
|
formCopy.scene = route.query.type;
|
||||||
formCopy.scopeId = currentOrgId.value;
|
formCopy.scopeId = scopeId.value;
|
||||||
|
|
||||||
// 如果选择是日期或者数值
|
// 如果选择是日期或者数值
|
||||||
if (selectFormat.value) {
|
if (selectFormat.value) {
|
||||||
|
@ -258,12 +268,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理参数
|
// 处理参数
|
||||||
const { id, name, options, scopeId, scene, type, remark, enableOptionKey } = formCopy;
|
const { id, name, options, scene, type, remark, enableOptionKey } = formCopy;
|
||||||
|
|
||||||
const params: AddOrUpdateField = {
|
const params: AddOrUpdateField = {
|
||||||
name,
|
name,
|
||||||
options,
|
options,
|
||||||
scopeId,
|
scopeId: scopeId.value,
|
||||||
scene,
|
scene,
|
||||||
type,
|
type,
|
||||||
remark,
|
remark,
|
||||||
|
@ -272,7 +282,7 @@
|
||||||
if (id) {
|
if (id) {
|
||||||
params.id = id;
|
params.id = id;
|
||||||
}
|
}
|
||||||
await addOrUpdateOrdField(params);
|
await addOrUpdate(params);
|
||||||
Message.success(isEdit.value ? t('common.updateSuccess') : t('common.addSuccess'));
|
Message.success(isEdit.value ? t('common.updateSuccess') : t('common.addSuccess'));
|
||||||
if (!isContinue) {
|
if (!isContinue) {
|
||||||
handleDrawerCancel();
|
handleDrawerCancel();
|
||||||
|
@ -310,7 +320,7 @@
|
||||||
// 获取字段选项详情
|
// 获取字段选项详情
|
||||||
const getFieldDetail = async (id: string) => {
|
const getFieldDetail = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
const fieldDetail = await getOrdFieldDetail(id);
|
const fieldDetail = await detail(id);
|
||||||
fieldDefaultValues.value = fieldDetail.options.map((item: any) => {
|
fieldDefaultValues.value = fieldDetail.options.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
@ -336,6 +346,7 @@
|
||||||
selectFormat.value = itemType;
|
selectFormat.value = itemType;
|
||||||
return 'DATE';
|
return 'DATE';
|
||||||
default:
|
default:
|
||||||
|
selectFormat.value = itemType;
|
||||||
return itemType;
|
return itemType;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,37 @@
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
||||||
import type { FormItemType } from '@/components/pure/ms-form-create/types';
|
import type { FormItemType } from '@/components/pure/ms-form-create/types';
|
||||||
|
|
||||||
|
import {
|
||||||
|
addOrUpdateOrdField,
|
||||||
|
addOrUpdateProjectField,
|
||||||
|
createProjectWorkFlowStatus,
|
||||||
|
createWorkFlowStatus,
|
||||||
|
deleteOrdField,
|
||||||
|
deleteOrdWorkState,
|
||||||
|
deleteProjectField,
|
||||||
|
deleteProjectWorkState,
|
||||||
|
getFieldList,
|
||||||
|
getOrdFieldDetail,
|
||||||
|
getProjectFieldDetail,
|
||||||
|
getProjectFieldList,
|
||||||
|
getProjectWorkFlowList,
|
||||||
|
getWorkFlowList,
|
||||||
|
setOrdWorkState,
|
||||||
|
setOrdWorkStateSort,
|
||||||
|
setProjectWorkState,
|
||||||
|
setProjectWorkStateSort,
|
||||||
|
updateOrdWorkStateFlow,
|
||||||
|
updateProjectWorkFlowStatus,
|
||||||
|
updateProjectWorkStateFlow,
|
||||||
|
updateWorkFlowStatus,
|
||||||
|
} from '@/api/modules/setting/template';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useTemplateStore from '@/store/modules/setting/template';
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
|
||||||
import type { fieldIconAndNameModal } from '@/models/setting/template';
|
import type { CustomField, DefinedFieldItem, fieldIconAndNameModal } from '@/models/setting/template';
|
||||||
import { TemplateCardEnum, TemplateIconEnum } from '@/enums/templateEnum';
|
import { TemplateCardEnum, TemplateIconEnum } from '@/enums/templateEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -47,49 +73,12 @@ export const getFieldType = (selectFieldType: FormItemType) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const organizationState = computed(() => templateStore.getOrdTemplateState());
|
const organizationState = computed(() => templateStore.ordStatus);
|
||||||
const projectState = computed(() => templateStore.getProjectTemplateState());
|
const projectState = computed(() => templateStore.projectStatus);
|
||||||
// 模板列表Icon
|
|
||||||
export const cardList = [
|
|
||||||
{
|
|
||||||
id: 1001,
|
|
||||||
key: 'FUNCTIONAL',
|
|
||||||
value: TemplateCardEnum.FUNCTIONAL,
|
|
||||||
name: t('system.orgTemplate.caseTemplates'),
|
|
||||||
enable: templateStore.templateStatus.FUNCTIONAL,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1002,
|
|
||||||
key: 'API',
|
|
||||||
value: TemplateCardEnum.API,
|
|
||||||
name: t('system.orgTemplate.APITemplates'),
|
|
||||||
enable: templateStore.templateStatus.API,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1003,
|
|
||||||
key: 'UI',
|
|
||||||
value: TemplateCardEnum.UI,
|
|
||||||
name: t('system.orgTemplate.UITemplates'),
|
|
||||||
enable: templateStore.templateStatus.UI,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1004,
|
|
||||||
key: 'TEST_PLAN',
|
|
||||||
value: TemplateCardEnum.TEST_PLAN,
|
|
||||||
name: t('system.orgTemplate.testPlanTemplates'),
|
|
||||||
enable: templateStore.templateStatus.TEST_PLAN,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1005,
|
|
||||||
key: 'BUG',
|
|
||||||
value: TemplateCardEnum.BUG,
|
|
||||||
name: t('system.orgTemplate.defectTemplates'),
|
|
||||||
enable: templateStore.templateStatus.BUG,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
// 模板列表Icon
|
||||||
export function getCardList(type: string): Record<string, any>[] {
|
export function getCardList(type: string): Record<string, any>[] {
|
||||||
const dataList = [
|
const dataList = ref([
|
||||||
{
|
{
|
||||||
id: 1001,
|
id: 1001,
|
||||||
key: 'FUNCTIONAL',
|
key: 'FUNCTIONAL',
|
||||||
|
@ -120,16 +109,17 @@ export function getCardList(type: string): Record<string, any>[] {
|
||||||
value: TemplateCardEnum.BUG,
|
value: TemplateCardEnum.BUG,
|
||||||
name: t('system.orgTemplate.defectTemplates'),
|
name: t('system.orgTemplate.defectTemplates'),
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
if (type === 'organization') {
|
if (type === 'organization') {
|
||||||
return dataList.map((item) => {
|
return dataList.value.map((item) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
enable: organizationState.value[item.key],
|
enable: organizationState.value[item.key],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return dataList.map((item) => {
|
|
||||||
|
return dataList.value.map((item) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
enable: projectState.value[item.key],
|
enable: projectState.value[item.key],
|
||||||
|
@ -221,4 +211,102 @@ export const getIconType = (iconType: FormItemType) => {
|
||||||
return fieldIconAndName.find((item) => item.key === iconType);
|
return fieldIconAndName.find((item) => item.key === iconType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取接口类型
|
||||||
|
export const getFieldRequestApi = (mode: 'organization' | 'project') => {
|
||||||
|
if (mode === 'organization') {
|
||||||
|
return {
|
||||||
|
list: getFieldList,
|
||||||
|
delete: deleteOrdField,
|
||||||
|
addOrUpdate: addOrUpdateOrdField,
|
||||||
|
detail: getOrdFieldDetail,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
list: getProjectFieldList,
|
||||||
|
delete: deleteProjectField,
|
||||||
|
addOrUpdate: addOrUpdateProjectField,
|
||||||
|
detail: getProjectFieldDetail,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取工作流类型接口
|
||||||
|
export const getWorkFlowRequestApi = (mode: 'organization' | 'project') => {
|
||||||
|
if (mode === 'organization') {
|
||||||
|
return {
|
||||||
|
list: getWorkFlowList,
|
||||||
|
create: createWorkFlowStatus,
|
||||||
|
update: updateWorkFlowStatus,
|
||||||
|
delete: deleteOrdWorkState,
|
||||||
|
changeState: setOrdWorkState,
|
||||||
|
dragChange: setOrdWorkStateSort,
|
||||||
|
updateFlow: updateOrdWorkStateFlow,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
list: getProjectWorkFlowList,
|
||||||
|
create: createProjectWorkFlowStatus,
|
||||||
|
update: updateProjectWorkFlowStatus,
|
||||||
|
delete: deleteProjectWorkState,
|
||||||
|
changeState: setProjectWorkState,
|
||||||
|
dragChange: setProjectWorkStateSort,
|
||||||
|
updateFlow: updateProjectWorkStateFlow,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** **
|
||||||
|
* @description 处理totalData自定义字段列表格式
|
||||||
|
* @param totalData: 自定义字段总列表
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const getTotalFieldOptionList = (totalData: DefinedFieldItem[]) => {
|
||||||
|
return totalData.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,
|
||||||
|
formRules: [
|
||||||
|
{ ...currentFormRules, value: item.value, props: { ...currentFormRules.props, options: selectOptions } },
|
||||||
|
],
|
||||||
|
fApi: null,
|
||||||
|
required: item.internal,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** **
|
||||||
|
* @description 处理自定义字段详情展示格式
|
||||||
|
* @param totalData: 自定义字段总列表
|
||||||
|
* @param customFields: 自定义字段总列表
|
||||||
|
*/
|
||||||
|
export const getCustomDetailFields = (totalData: DefinedFieldItem[], customFields: CustomField[]) => {
|
||||||
|
const customFieldsIds = customFields.map((index: any) => index.fieldId);
|
||||||
|
return totalData.filter((item) => {
|
||||||
|
const currentCustomFieldIndex = customFieldsIds.findIndex((it: any) => it === item.id);
|
||||||
|
if (customFieldsIds.indexOf(item.id) > -1) {
|
||||||
|
const currentForm = item.formRules?.map((it: any) => {
|
||||||
|
it.props.modelValue = customFields[currentCustomFieldIndex].defaultValue;
|
||||||
|
return {
|
||||||
|
...it,
|
||||||
|
value: customFields[currentCustomFieldIndex].defaultValue,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const formItem = item;
|
||||||
|
formItem.formRules = cloneDeep(currentForm);
|
||||||
|
formItem.apiFieldId = customFields[currentCustomFieldIndex].apiFieldId;
|
||||||
|
formItem.required = customFields[currentCustomFieldIndex].required;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<MsCard :has-breadcrumb="true" simple>
|
<div>
|
||||||
<a-alert class="mb-6" :type="isEnable ? 'warning' : 'info'">{{
|
<a-alert class="mb-6" :type="isEnabledTemplate && props.mode === 'organization' ? 'warning' : 'info'">{{
|
||||||
isEnable ? t('system.orgTemplate.enableDescription') : t('system.orgTemplate.fieldLimit')
|
isEnabledTemplate && props.mode === 'organization'
|
||||||
|
? t('system.orgTemplate.enableDescription')
|
||||||
|
: t('system.orgTemplate.fieldLimit')
|
||||||
}}</a-alert>
|
}}</a-alert>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<span v-if="isEnable" class="font-medium">{{ t('system.orgTemplate.fieldList') }}</span>
|
<span v-if="isEnabledTemplate" class="font-medium">{{ t('system.orgTemplate.fieldList') }}</span>
|
||||||
<a-button v-else type="primary" :disabled="isDisabled" @click="fieldHandler">
|
<a-button v-else type="primary" :disabled="isDisabled" @click="fieldHandler">
|
||||||
{{ t('system.orgTemplate.addField') }}
|
{{ t('system.orgTemplate.addField') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -19,12 +21,28 @@
|
||||||
</div>
|
</div>
|
||||||
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<MsIcon v-if="!record.internal" :type="getIconType(record.type)?.iconName || ''" size="16" />
|
<MsIcon
|
||||||
<span class="ml-2">{{ record.name }}</span>
|
v-if="!record.internal"
|
||||||
<span v-if="record.internal" class="system-flag">{{ t('system.orgTemplate.isSystem') }}</span>
|
:type="getIconType(record.type)?.iconName || ''"
|
||||||
|
size="16"
|
||||||
|
:class="{
|
||||||
|
'text-[rgb(var(--primary-5))]': props.mode === 'project',
|
||||||
|
'cursor-pointer': props.mode === 'project',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="ml-2"
|
||||||
|
:class="{
|
||||||
|
'text-[rgb(var(--primary-5))]': props.mode === 'project',
|
||||||
|
'cursor-pointer': props.mode === 'project',
|
||||||
|
}"
|
||||||
|
@click="showDetail(record)"
|
||||||
|
>{{ record.name }}</span
|
||||||
|
>
|
||||||
|
<MsTag v-if="record.internal" size="small" class="ml-2">{{ t('system.orgTemplate.isSystem') }}</MsTag>
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<div class="flex flex-row flex-nowrap">
|
<div class="flex flex-row flex-nowrap items-center">
|
||||||
<MsPopConfirm
|
<MsPopConfirm
|
||||||
type="error"
|
type="error"
|
||||||
:title="t('system.orgTemplate.updateTip', { name: characterLimit(record.name) })"
|
:title="t('system.orgTemplate.updateTip', { name: characterLimit(record.name) })"
|
||||||
|
@ -35,7 +53,7 @@
|
||||||
<MsButton class="!mr-0">{{ t('system.orgTemplate.edit') }}</MsButton></MsPopConfirm
|
<MsButton class="!mr-0">{{ t('system.orgTemplate.edit') }}</MsButton></MsPopConfirm
|
||||||
>
|
>
|
||||||
|
|
||||||
<a-divider v-if="!record.internal" direction="vertical" />
|
<a-divider v-if="!record.internal" class="h-[12px]" direction="vertical" />
|
||||||
<MsTableMoreAction
|
<MsTableMoreAction
|
||||||
v-if="!record.internal"
|
v-if="!record.internal"
|
||||||
:list="moreActions"
|
:list="moreActions"
|
||||||
|
@ -47,29 +65,75 @@
|
||||||
<span>{{ getIconType(record.type)?.label }}</span>
|
<span>{{ getIconType(record.type)?.label }}</span>
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
<EditFieldDrawer ref="fieldDrawerRef" v-model:visible="showDrawer" @success="successHandler" />
|
<EditFieldDrawer ref="fieldDrawerRef" v-model:visible="showDrawer" :mode="props.mode" @success="successHandler" />
|
||||||
</MsCard>
|
<MsDrawer
|
||||||
|
ref="detailDrawerRef"
|
||||||
|
v-model:visible="showDetailVisible"
|
||||||
|
:width="480"
|
||||||
|
:footer="false"
|
||||||
|
:title="t('system.orgTemplate.filedDetail', { name: detailInfo?.name })"
|
||||||
|
>
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.fieldName') }}</span>
|
||||||
|
<span class="content">{{ detailInfo?.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.description') }}</span>
|
||||||
|
<span class="content">{{ detailInfo?.remark || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.fieldType') }}</span>
|
||||||
|
<span class="content">{{ detailInfo?.fieldType || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="detailInfo?.options?.length" class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.optionContent') }}</span>
|
||||||
|
<span class="content flex flex-col">
|
||||||
|
<span v-for="item of detailInfo?.options" :key="item.value" class="flex">
|
||||||
|
<MsTag class="!mr-2 mb-2">{{ item.text }}</MsTag>
|
||||||
|
<MsTag v-if="detailInfo?.enableOptionKey" class="mb-2">{{ item.value }}</MsTag></span
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="detailInfo?.type === 'DATE' || detailInfo?.type === 'DATETIME'" class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.dateFormat') }}</span>
|
||||||
|
<span class="content">
|
||||||
|
{{
|
||||||
|
detailInfo?.type === 'DATE' ? dayjs().format('YYYY/MM/DD') : dayjs().format('YYYY/MM/DD HH:mm:ss')
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div v-if="detailInfo?.type === 'INT' || detailInfo?.type === 'FLOAT'" class="flex">
|
||||||
|
<span class="label">{{ t('system.orgTemplate.numberFormat') }}</span>
|
||||||
|
<span class="content">{{
|
||||||
|
detailInfo?.type === 'INT' ? t('system.orgTemplate.int') : t('system.orgTemplate.float')
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</MsDrawer>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/**
|
/**
|
||||||
* @description 系统管理-组织-模版-字段列表
|
* @description 模版-字段列表
|
||||||
*/
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsPopConfirm from '@/components/pure/ms-popconfirm/index.vue';
|
import MsPopConfirm from '@/components/pure/ms-popconfirm/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import EditFieldDrawer from './editFieldDrawer.vue';
|
import EditFieldDrawer from './editFieldDrawer.vue';
|
||||||
|
|
||||||
import { deleteOrdField, getFieldList } from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
|
@ -79,7 +143,7 @@
|
||||||
import type { AddOrUpdateField, SeneType } from '@/models/setting/template';
|
import type { AddOrUpdateField, SeneType } from '@/models/setting/template';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
import { getCardList, getIconType } from './fieldSetting';
|
import { getFieldRequestApi, getIconType } from './fieldSetting';
|
||||||
|
|
||||||
const templateStore = useTemplateStore();
|
const templateStore = useTemplateStore();
|
||||||
|
|
||||||
|
@ -89,7 +153,12 @@
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
|
}>();
|
||||||
|
|
||||||
const currentOrd = computed(() => appStore.currentOrgId);
|
const currentOrd = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
|
||||||
const fieldColumns: MsTableColumn = [
|
const fieldColumns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
|
@ -97,7 +166,6 @@
|
||||||
slotName: 'name',
|
slotName: 'name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 300,
|
width: 300,
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
|
@ -105,64 +173,67 @@
|
||||||
title: 'system.orgTemplate.columnFieldType',
|
title: 'system.orgTemplate.columnFieldType',
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
slotName: 'fieldType',
|
slotName: 'fieldType',
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.columnFieldDescription',
|
title: 'system.orgTemplate.columnFieldDescription',
|
||||||
dataIndex: 'remark',
|
dataIndex: 'remark',
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.columnFieldUpdatedTime',
|
title: 'system.orgTemplate.columnFieldUpdatedTime',
|
||||||
dataIndex: 'updateTime',
|
dataIndex: 'updateTime',
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.operation',
|
title: 'system.orgTemplate.operation',
|
||||||
slotName: 'operation',
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 200,
|
width: 200,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showDrag: false,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_FIELD_SETTING, fieldColumns, 'drawer');
|
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getFieldList, {
|
const getList = getFieldRequestApi(props.mode).list;
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getList, {
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_FIELD_SETTING,
|
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_FIELD_SETTING,
|
||||||
scroll: { x: '1000px' },
|
scroll: { x: '1000px' },
|
||||||
selectable: false,
|
selectable: false,
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
size: 'default',
|
size: 'default',
|
||||||
showSetting: true,
|
showSetting: false,
|
||||||
showPagination: false,
|
showPagination: false,
|
||||||
heightUsed: 380,
|
heightUsed: 380,
|
||||||
});
|
});
|
||||||
|
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
const totalData = ref([]);
|
const totalData = ref([]);
|
||||||
|
const scene = ref<SeneType>(route.query.type);
|
||||||
|
|
||||||
|
const getParams = () => {
|
||||||
|
scene.value = route.query.type;
|
||||||
|
return {
|
||||||
|
scene: scene.value,
|
||||||
|
scopedId: props.mode === 'organization' ? currentOrd.value : currentProjectId.value,
|
||||||
|
};
|
||||||
|
};
|
||||||
// 查询模板字段
|
// 查询模板字段
|
||||||
const searchFiled = async () => {
|
const searchFiled = async () => {
|
||||||
try {
|
try {
|
||||||
totalData.value = await getFieldList({ organizationId: currentOrd.value, scene: route.query.type });
|
totalData.value = await getList(getParams());
|
||||||
const filterData = totalData.value.filter((item: AddOrUpdateField) => item.name.includes(keyword.value));
|
const filterData = totalData.value.filter((item: AddOrUpdateField) => item.name.includes(keyword.value));
|
||||||
setProps({ data: filterData });
|
setProps({ data: filterData });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const scene = ref<SeneType>(route.query.type);
|
|
||||||
|
|
||||||
// 获取字段列表数据
|
// 获取字段列表数据
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
scene.value = route.query.type;
|
setLoadListParams(getParams());
|
||||||
setLoadListParams({ organizationId: currentOrd.value, scene });
|
|
||||||
await loadList();
|
await loadList();
|
||||||
totalData.value = await getFieldList({ organizationId: currentOrd.value, scene: route.query.type });
|
totalData.value = await getList(getParams());
|
||||||
};
|
};
|
||||||
|
|
||||||
const isDisabled = computed(() => {
|
const isDisabled = computed(() => {
|
||||||
|
@ -170,13 +241,16 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const isEnable = computed(() => {
|
|
||||||
return templateStore.templateStatus[scene.value as string];
|
const isEnabledTemplate = computed(() => {
|
||||||
|
return props.mode === 'organization'
|
||||||
|
? templateStore.projectStatus[scene.value as string]
|
||||||
|
: !templateStore.projectStatus[scene.value as string];
|
||||||
});
|
});
|
||||||
|
|
||||||
// 切换模版是否启用展示操作列
|
// 切换模版是否启用展示操作列
|
||||||
const isEnableOperation = () => {
|
const isEnableOperation = () => {
|
||||||
if (isEnable.value) {
|
if (isEnabledTemplate.value) {
|
||||||
const noOperationColumn = fieldColumns.slice(0, -1);
|
const noOperationColumn = fieldColumns.slice(0, -1);
|
||||||
tableRef.value.initColumn(noOperationColumn);
|
tableRef.value.initColumn(noOperationColumn);
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,6 +266,7 @@
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const deleteApi = getFieldRequestApi(props.mode).delete;
|
||||||
// 删除字段
|
// 删除字段
|
||||||
const handlerDelete = (record: AddOrUpdateField) => {
|
const handlerDelete = (record: AddOrUpdateField) => {
|
||||||
openModal({
|
openModal({
|
||||||
|
@ -205,7 +280,7 @@
|
||||||
},
|
},
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
if (record.id) await deleteOrdField(record.id);
|
if (record.id) await deleteApi(record.id);
|
||||||
Message.success(t('system.orgTemplate.deleteSuccess'));
|
Message.success(t('system.orgTemplate.deleteSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -223,6 +298,25 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showDetailVisible = ref<boolean>(false);
|
||||||
|
const detailInfo = ref<AddOrUpdateField>();
|
||||||
|
|
||||||
|
// 详情
|
||||||
|
const showDetail = (record: AddOrUpdateField) => {
|
||||||
|
if (props.mode === 'organization') return;
|
||||||
|
|
||||||
|
showDetailVisible.value = true;
|
||||||
|
let fieldType;
|
||||||
|
if (record.type === 'MEMBER') {
|
||||||
|
fieldType = getIconType(record.type)?.label;
|
||||||
|
} else if (record.type === 'MULTIPLE_MEMBER') {
|
||||||
|
fieldType = `${getIconType(record.type)?.label}(允许添加多个)`;
|
||||||
|
} else {
|
||||||
|
fieldType = getIconType(record.type)?.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailInfo.value = { ...record, fieldType };
|
||||||
|
};
|
||||||
const showDrawer = ref<boolean>(false);
|
const showDrawer = ref<boolean>(false);
|
||||||
|
|
||||||
const fieldDrawerRef = ref();
|
const fieldDrawerRef = ref();
|
||||||
|
@ -238,26 +332,26 @@
|
||||||
fetchData();
|
fetchData();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新面包屑根据不同的模版
|
|
||||||
const updateBreadcrumbList = () => {
|
|
||||||
const { breadcrumbList } = appStore;
|
|
||||||
const breadTitle = getCardList('organization').find((item) => item.key === route.query.type);
|
|
||||||
if (breadTitle) {
|
|
||||||
breadcrumbList[0].locale = breadTitle.name;
|
|
||||||
appStore.setBreadcrumbList(breadcrumbList);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
updateBreadcrumbList();
|
|
||||||
isEnableOperation();
|
isEnableOperation();
|
||||||
fetchData();
|
fetchData();
|
||||||
});
|
});
|
||||||
|
await tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_FIELD_SETTING, fieldColumns, 'drawer');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.system-flag {
|
.system-flag {
|
||||||
background: var(--color-text-n8);
|
background: var(--color-text-n8);
|
||||||
@apply ml-2 rounded p-1 text-xs;
|
@apply ml-2 inline-block p-1 align-middle text-xs;
|
||||||
|
}
|
||||||
|
.label {
|
||||||
|
margin-top: 16px;
|
||||||
|
width: 30%;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
margin-top: 16px;
|
||||||
|
width: 70%;
|
||||||
|
color: var(--color-text-1);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<template>
|
||||||
|
<MsCard has-breadcrumb simple> <FieldSetting mode="organization" /></MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织-模板管理-字段列表首页
|
||||||
|
*/
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import FieldSetting from '@/views/setting/organization/template/components/fieldSetting.vue';
|
||||||
|
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
|
|
||||||
|
import { getCardList } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
// 更新面包屑根据不同的模版
|
||||||
|
const updateBreadcrumbList = () => {
|
||||||
|
const { breadcrumbList } = appStore;
|
||||||
|
const breadTitle = getCardList('organization').find((item: any) => item.key === route.query.type);
|
||||||
|
if (breadTitle) {
|
||||||
|
breadcrumbList[0].locale = breadTitle.name;
|
||||||
|
appStore.setBreadcrumbList(breadcrumbList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateBreadcrumbList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -20,7 +20,12 @@
|
||||||
<!-- 非预览模式 -->
|
<!-- 非预览模式 -->
|
||||||
<div v-if="isPreview" class="nonPreview">
|
<div v-if="isPreview" class="nonPreview">
|
||||||
<a-form ref="formRef" :model="templateForm" layout="vertical">
|
<a-form ref="formRef" :model="templateForm" layout="vertical">
|
||||||
<a-form-item :label="t('system.orgTemplate.templateName')" field="name" asterisk-position="end" required>
|
<a-form-item
|
||||||
|
:label="t('system.orgTemplate.templateName')"
|
||||||
|
field="name"
|
||||||
|
asterisk-position="end"
|
||||||
|
:rules="[{ required: true, message: t('system.orgTemplate.templateNameRules') }]"
|
||||||
|
>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:model-value="templateForm.name"
|
v-model:model-value="templateForm.name"
|
||||||
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
|
:placeholder="t('system.orgTemplate.templateNamePlaceholder')"
|
||||||
|
@ -40,21 +45,68 @@
|
||||||
class="max-w-[732px]"
|
class="max-w-[732px]"
|
||||||
></a-textarea>
|
></a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="remark" label="" asterisk-position="end"
|
<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-checkbox v-model="templateForm.enableThirdPart">{{ t('system.orgTemplate.thirdParty') }}</a-checkbox>
|
||||||
</a-form-item>
|
</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>
|
</a-form>
|
||||||
<!-- 已有字段表 -->
|
<!-- 已有字段表 -->
|
||||||
<TemplateManagementTable
|
<TemplateManagementTable
|
||||||
|
v-if="fieldType === 'custom'"
|
||||||
ref="templateFieldTableRef"
|
ref="templateFieldTableRef"
|
||||||
v-model:select-data="selectData"
|
v-model:select-data="selectData"
|
||||||
:data="(totalTemplateField as DefinedFieldItem[])"
|
:data="(totalTemplateField as DefinedFieldItem[])"
|
||||||
:enable-third-part="templateForm.enableThirdPart"
|
:enable-third-part="templateForm.enableThirdPart"
|
||||||
|
mode="organization"
|
||||||
@update="updateHandler"
|
@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
|
||||||
|
asterisk-position="end"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="defectForm.name"
|
||||||
|
:max-length="255"
|
||||||
|
:placeholder="t('system.orgTemplate.defectNamePlaceholder')"
|
||||||
|
show-word-limit
|
||||||
|
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">
|
||||||
|
<MsRichText v-model:model-value="defectForm.description" />
|
||||||
|
<MsFormItemSub :text="t('system.orgTemplate.defectContentTip')" :show-fill-icon="false" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
<!-- 预览模式 -->
|
<!-- 预览模式 -->
|
||||||
<PreviewTemplate v-else :select-field="(selectData as DefinedFieldItem[])" />
|
<PreviewTemplate
|
||||||
|
v-else
|
||||||
|
:select-field="(selectData as DefinedFieldItem[])"
|
||||||
|
:template-type="route.query.type"
|
||||||
|
:defect-form="defectForm"
|
||||||
|
/>
|
||||||
</MsCard>
|
</MsCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -64,11 +116,11 @@
|
||||||
*/
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
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 TemplateManagementTable from './templateManagementTable.vue';
|
||||||
import PreviewTemplate from './viewTemplate.vue';
|
import PreviewTemplate from './viewTemplate.vue';
|
||||||
|
|
||||||
|
@ -87,14 +139,16 @@
|
||||||
import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template';
|
import type { ActionTemplateManage, CustomField, DefinedFieldItem } from '@/models/setting/template';
|
||||||
import { SettingRouteEnum } from '@/enums/routeEnum';
|
import { SettingRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
import { getCardList } from './fieldSetting';
|
import { getCardList, getCustomDetailFields, getTotalFieldOptionList } from './fieldSetting';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
// useLeaveUnSaveTip();
|
const { setState } = useLeaveUnSaveTip();
|
||||||
|
|
||||||
|
setState(false);
|
||||||
|
|
||||||
const title = ref('');
|
const title = ref('');
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
@ -107,6 +161,8 @@
|
||||||
enableThirdPart: false,
|
enableThirdPart: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fieldType = ref<string>('custom'); // 缺陷模板字段类型
|
||||||
|
|
||||||
const templateForm = ref<ActionTemplateManage>({ ...initTemplateForm });
|
const templateForm = ref<ActionTemplateManage>({ ...initTemplateForm });
|
||||||
|
|
||||||
const selectData = ref<DefinedFieldItem[]>([]); // 表格已选择字段
|
const selectData = ref<DefinedFieldItem[]>([]); // 表格已选择字段
|
||||||
|
@ -115,15 +171,15 @@
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const totalTemplateField = ref<DefinedFieldItem[]>([]);
|
const totalTemplateField = ref<DefinedFieldItem[]>([]);
|
||||||
const isEdit = computed(() => !!route.query.id);
|
const isEdit = computed(() => !!route.query.id);
|
||||||
const currentOrd = currentOrgId.value;
|
|
||||||
const isEditField = ref<boolean>(false);
|
const isEditField = ref<boolean>(false);
|
||||||
|
const systemFieldData = ref<CustomField[]>([]);
|
||||||
|
|
||||||
// 获取模板详情
|
// 获取模板详情
|
||||||
const getTemplateInfo = async () => {
|
const getTemplateInfo = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await getOrganizeTemplateInfo(route.query.id as string);
|
const res = await getOrganizeTemplateInfo(route.query.id as string);
|
||||||
const { name, customFields } = res;
|
const { name, customFields, systemFields } = res;
|
||||||
templateForm.value = {
|
templateForm.value = {
|
||||||
...res,
|
...res,
|
||||||
name: route.params.mode === 'copy' ? `${name}_copy` : name,
|
name: route.params.mode === 'copy' ? `${name}_copy` : name,
|
||||||
|
@ -131,27 +187,8 @@
|
||||||
if (route.params.mode === 'copy') {
|
if (route.params.mode === 'copy') {
|
||||||
templateForm.value.id = undefined;
|
templateForm.value.id = undefined;
|
||||||
}
|
}
|
||||||
// 处理字段列表
|
selectData.value = getCustomDetailFields(totalTemplateField.value as DefinedFieldItem[], customFields);
|
||||||
const customFieldsIds = customFields.map((index: any) => index.fieldId);
|
systemFieldData.value = systemFields;
|
||||||
const result = totalTemplateField.value.filter((item) => {
|
|
||||||
const currentCustomFieldIndex = customFieldsIds.findIndex((it: any) => it === item.id);
|
|
||||||
if (customFieldsIds.indexOf(item.id) > -1) {
|
|
||||||
const currentForm = item.formRules?.map((it: any) => {
|
|
||||||
it.props.modelValue = customFields[currentCustomFieldIndex].defaultValue;
|
|
||||||
return {
|
|
||||||
...it,
|
|
||||||
value: customFields[currentCustomFieldIndex].defaultValue,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const formItem = item;
|
|
||||||
formItem.formRules = cloneDeep(currentForm);
|
|
||||||
formItem.apiFieldId = customFields[currentCustomFieldIndex].apiFieldId;
|
|
||||||
formItem.required = customFields[currentCustomFieldIndex].required;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
selectData.value = result;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -161,27 +198,7 @@
|
||||||
|
|
||||||
// 处理表单数据格式
|
// 处理表单数据格式
|
||||||
const getFieldOptionList = () => {
|
const getFieldOptionList = () => {
|
||||||
totalTemplateField.value = totalTemplateField.value.map((item: any) => {
|
totalTemplateField.value = getTotalFieldOptionList(totalTemplateField.value as DefinedFieldItem[]);
|
||||||
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,
|
|
||||||
formRules: [
|
|
||||||
{ ...currentFormRules, value: item.value, props: { ...currentFormRules.props, options: selectOptions } },
|
|
||||||
],
|
|
||||||
fApi: null,
|
|
||||||
required: item.internal,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
// 创建默认系统字段
|
// 创建默认系统字段
|
||||||
if (!isEdit.value && !isEditField.value) {
|
if (!isEdit.value && !isEditField.value) {
|
||||||
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
selectData.value = totalTemplateField.value.filter((item) => item.internal);
|
||||||
|
@ -191,9 +208,9 @@
|
||||||
// 获取字段列表数据
|
// 获取字段列表数据
|
||||||
const getClassifyField = async () => {
|
const getClassifyField = async () => {
|
||||||
try {
|
try {
|
||||||
totalTemplateField.value = await getFieldList({ organizationId: currentOrd, scene: route.query.type });
|
totalTemplateField.value = await getFieldList({ scopedId: currentOrgId.value, scene: route.query.type });
|
||||||
getFieldOptionList();
|
getFieldOptionList();
|
||||||
// 编辑字段就需要单独处理过滤
|
// 编辑字段需要单独处理过滤
|
||||||
if (isEditField.value) {
|
if (isEditField.value) {
|
||||||
selectData.value = totalTemplateField.value.filter(
|
selectData.value = totalTemplateField.value.filter(
|
||||||
(item) => selectFiled.value.map((it) => it.id).indexOf(item.id) > -1
|
(item) => selectFiled.value.map((it) => it.id).indexOf(item.id) > -1
|
||||||
|
@ -219,6 +236,8 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const defectForm = ref<Record<string, any>>({}); // 缺陷详情表单
|
||||||
|
|
||||||
// 获取模板参数
|
// 获取模板参数
|
||||||
function getTemplateParams(): ActionTemplateManage {
|
function getTemplateParams(): ActionTemplateManage {
|
||||||
const result = selectData.value.map((item) => {
|
const result = selectData.value.map((item) => {
|
||||||
|
@ -227,13 +246,20 @@
|
||||||
return {
|
return {
|
||||||
fieldId: item.id,
|
fieldId: item.id,
|
||||||
required: item.required,
|
required: item.required,
|
||||||
apiFieldId: item.apiFieldId,
|
apiFieldId: item.apiFieldId || '',
|
||||||
defaultValue: value,
|
defaultValue: value || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 处理缺陷系统详情字段
|
||||||
|
const sysDetailFields = Object.keys(defectForm.value).map((formKey: string) => {
|
||||||
|
return {
|
||||||
|
fieldId: formKey,
|
||||||
|
defaultValue: defectForm.value[formKey],
|
||||||
|
};
|
||||||
|
});
|
||||||
const { name, remark, enableThirdPart, id } = templateForm.value;
|
const { name, remark, enableThirdPart, id } = templateForm.value;
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
@ -243,6 +269,7 @@
|
||||||
customFields: result as CustomField[],
|
customFields: result as CustomField[],
|
||||||
scopeId: currentOrgId.value,
|
scopeId: currentOrgId.value,
|
||||||
scene: route.query.type,
|
scene: route.query.type,
|
||||||
|
systemFields: sysDetailFields,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +296,7 @@
|
||||||
} else {
|
} else {
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
router.push({ name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT, query: route.query });
|
router.push({ name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT, query: route.query });
|
||||||
|
setState(true);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -323,6 +351,19 @@
|
||||||
getClassifyField();
|
getClassifyField();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 缺陷详情表单回显
|
||||||
|
watch(
|
||||||
|
() => systemFieldData.value,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
systemFieldData.value.forEach((item) => {
|
||||||
|
defectForm.value[item.fieldId] = item.defaultValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setBreadText();
|
setBreadText();
|
||||||
getClassifyField();
|
getClassifyField();
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="template-operation">
|
<div class="template-operation">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="font-medium">{{ props.cardItem.name }}</span>
|
<span class="font-medium">{{ props.cardItem.name }}</span>
|
||||||
<span class="enable">{{ t('system.orgTemplate.enabledTemplates') }}</span>
|
<span v-if="!isEnableProject" class="enable">{{ t('system.orgTemplate.enabledTemplates') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex min-w-[300px] flex-nowrap items-center">
|
<div class="flex min-w-[300px] flex-nowrap items-center">
|
||||||
<span class="operation hover:text-[rgb(var(--primary-5))]">
|
<span class="operation hover:text-[rgb(var(--primary-5))]">
|
||||||
|
@ -17,14 +17,14 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="operation hover:text-[rgb(var(--primary-5))]">
|
<span class="operation hover:text-[rgb(var(--primary-5))]">
|
||||||
<span @click="templateManagement">{{ t('system.orgTemplate.TemplateManagement') }}</span>
|
<span @click="templateManagement">{{ t('system.orgTemplate.TemplateManagement') }}</span>
|
||||||
<a-divider v-if="!props.cardItem.enable || props.cardItem.key === 'BUG'" direction="vertical" />
|
<a-divider v-if="isEnableProject || props.cardItem.key === 'BUG'" direction="vertical" />
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.cardItem.key === 'BUG'" class="operation hover:text-[rgb(var(--primary-5))]">
|
<span v-if="props.cardItem.key === 'BUG'" class="operation hover:text-[rgb(var(--primary-5))]">
|
||||||
<span @click="workflowSetup">{{ t('system.orgTemplate.workflowSetup') }}</span>
|
<span @click="workflowSetup">{{ t('system.orgTemplate.workflowSetup') }}</span>
|
||||||
<a-divider v-if="!props.cardItem.enable && props.cardItem.key === 'BUG'" direction="vertical" />
|
<a-divider v-if="isEnableProject && props.cardItem.key === 'BUG'" direction="vertical" />
|
||||||
</span>
|
</span>
|
||||||
<span v-if="!props.cardItem.enable" class="rounded p-[2px] hover:bg-[rgb(var(--primary-9))]">
|
<span v-if="isEnableProject" class="rounded p-[2px] hover:bg-[rgb(var(--primary-9))]">
|
||||||
<MsTableMoreAction :list="moreActions" @select="(item) => handleMoreActionSelect"
|
<MsTableMoreAction :list="moreActions" @select="handleMoreActionSelect"
|
||||||
/></span>
|
/></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,20 +34,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 模版-模版管理小卡片
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
|
||||||
import { isEnableTemplate } from '@/api/modules/setting/template';
|
import { enableOrOffTemplate } from '@/api/modules/setting/template';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useTemplateStore from '@/store/modules/setting/template';
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
|
||||||
import { SettingRouteEnum } from '@/enums/routeEnum';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const templateStore = useTemplateStore();
|
const templateStore = useTemplateStore();
|
||||||
|
@ -56,9 +56,25 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cardItem: Record<string, any>;
|
cardItem: Record<string, any>;
|
||||||
|
mode: 'organization' | 'project';
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const router = useRouter();
|
const emit = defineEmits<{
|
||||||
|
(e: 'fieldSetting', key: string): void;
|
||||||
|
(e: 'templateManagement', key: string): void;
|
||||||
|
(e: 'workflowSetup', key: string): void;
|
||||||
|
(e: 'updateState'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 先判断项目是否是开启
|
||||||
|
const isEnableProject = computed(() => {
|
||||||
|
if (props.mode === 'organization') {
|
||||||
|
return !templateStore.projectStatus[props.cardItem.key];
|
||||||
|
}
|
||||||
|
if (props.mode === 'project') {
|
||||||
|
return templateStore.ordStatus[props.cardItem.key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const moreActions = ref<ActionsItem[]>([
|
const moreActions = ref<ActionsItem[]>([
|
||||||
{
|
{
|
||||||
|
@ -71,47 +87,46 @@
|
||||||
// 启用模板
|
// 启用模板
|
||||||
const enableHandler = async () => {
|
const enableHandler = async () => {
|
||||||
try {
|
try {
|
||||||
await isEnableTemplate(currentOrgId.value);
|
if (props.mode) {
|
||||||
|
await enableOrOffTemplate(currentOrgId.value, props.cardItem.key);
|
||||||
Message.success(t('system.orgTemplate.enabledSuccessfully'));
|
Message.success(t('system.orgTemplate.enabledSuccessfully'));
|
||||||
templateStore.getStatus();
|
await templateStore.getStatus();
|
||||||
|
emit('updateState');
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMoreActionSelect = (item: ActionsItem) => {
|
const handleMoreActionSelect = () => {
|
||||||
if (item.eventTag === 'enable') {
|
|
||||||
enableHandler();
|
enableHandler();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 字段设置
|
// 字段设置
|
||||||
const fieldSetting = () => {
|
const fieldSetting = () => {
|
||||||
router.push({
|
emit('fieldSetting', props.cardItem.key);
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
|
|
||||||
query: {
|
|
||||||
type: props.cardItem.key,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const templateManagement = () => {
|
const templateManagement = () => {
|
||||||
router.push({
|
emit('templateManagement', props.cardItem.key);
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
|
||||||
query: {
|
|
||||||
type: props.cardItem.key,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const workflowSetup = () => {
|
const workflowSetup = () => {
|
||||||
router.push({
|
emit('workflowSetup', props.cardItem.key);
|
||||||
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
|
||||||
query: {
|
|
||||||
type: props.cardItem.key,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const templateCardInfo = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.cardItem,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
debugger;
|
||||||
|
templateCardInfo.value = { ...props.cardItem };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<MsCard has-breadcrumb simple>
|
<MsCard has-breadcrumb simple>
|
||||||
<a-alert v-if="isEnable" class="mb-6" type="warning">{{ t('system.orgTemplate.enableTemplateTip') }}</a-alert>
|
<a-alert v-if="isEnableOrdTemplate" class="mb-6" type="warning">{{
|
||||||
|
t('system.orgTemplate.enableTemplateTip')
|
||||||
|
}}</a-alert>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<span v-if="isEnable" class="font-medium">{{ t('system.orgTemplate.templateList') }}</span>
|
<span v-if="isEnableOrdTemplate" class="font-medium">{{ t('system.orgTemplate.templateList') }}</span>
|
||||||
<a-button v-else type="primary" :disabled="false" @click="createTemplate">
|
<a-button v-else type="primary" :disabled="false" @click="createTemplate">
|
||||||
{{ t('system.orgTemplate.createTemplate') }}
|
{{ t('system.orgTemplate.createTemplate') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -18,13 +20,16 @@
|
||||||
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
<MsBaseTable v-bind="propsRes" ref="tableRef" v-on="propsEvent">
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<span class="ml-2">{{ record.name }}</span>
|
<span class="ml-2">{{ record.name }}</span>
|
||||||
<span v-if="record.internal" class="system-flag">{{ t('system.orgTemplate.isSystem') }}</span>
|
<MsTag v-if="record.internal" size="small" class="ml-2">{{ t('system.orgTemplate.isSystem') }}</MsTag>
|
||||||
|
</template>
|
||||||
|
<template #enableThirdPart="{ record }">
|
||||||
|
{{ record.enableThirdPart ? t('system.orgTemplate.yes') : t('system.orgTemplate.no') }}
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<div class="flex flex-row flex-nowrap">
|
<div class="flex flex-row flex-nowrap">
|
||||||
<MsButton @click="editTemplate(record.id)">{{ t('system.orgTemplate.edit') }}</MsButton>
|
<MsButton @click="editTemplate(record.id)">{{ t('system.orgTemplate.edit') }}</MsButton>
|
||||||
<MsButton class="!mr-0" @click="copyTemplate(record.id)">{{ t('system.orgTemplate.copy') }}</MsButton>
|
<MsButton class="!mr-0" @click="copyTemplate(record.id)">{{ t('system.orgTemplate.copy') }}</MsButton>
|
||||||
<a-divider v-if="!record.internal" direction="vertical" />
|
<a-divider v-if="!record.internal" class="h-[12px]" direction="vertical" />
|
||||||
<MsTableMoreAction
|
<MsTableMoreAction
|
||||||
v-if="!record.internal"
|
v-if="!record.internal"
|
||||||
:list="moreActions"
|
:list="moreActions"
|
||||||
|
@ -51,6 +56,7 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
|
||||||
import { deleteOrdTemplate, getOrganizeTemplateList } from '@/api/modules/setting/template';
|
import { deleteOrdTemplate, getOrganizeTemplateList } from '@/api/modules/setting/template';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
@ -84,12 +90,15 @@
|
||||||
width: 300,
|
width: 300,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.description',
|
title: 'system.orgTemplate.description',
|
||||||
dataIndex: 'remark',
|
dataIndex: 'remark',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
width: 300,
|
||||||
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.columnFieldUpdatedTime',
|
title: 'system.orgTemplate.columnFieldUpdatedTime',
|
||||||
|
@ -100,6 +109,7 @@
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.operation',
|
title: 'system.orgTemplate.operation',
|
||||||
slotName: 'operation',
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 200,
|
width: 200,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
@ -107,10 +117,9 @@
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
await tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT, fieldColumns, 'drawer');
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getOrganizeTemplateList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams, setProps } = useTable(getOrganizeTemplateList, {
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT,
|
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
scroll: { x: '1000px' },
|
scroll: { x: '100%' },
|
||||||
selectable: false,
|
selectable: false,
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
size: 'default',
|
size: 'default',
|
||||||
|
@ -119,9 +128,13 @@
|
||||||
heightUsed: 380,
|
heightUsed: 380,
|
||||||
});
|
});
|
||||||
const scene = route.query.type;
|
const scene = route.query.type;
|
||||||
const isEnable = templateStore.templateStatus[scene as string];
|
|
||||||
|
const isEnableOrdTemplate = computed(() => {
|
||||||
|
return templateStore.projectStatus[scene as string];
|
||||||
|
});
|
||||||
|
|
||||||
const totalList = ref<OrdTemplateManagement[]>([]);
|
const totalList = ref<OrdTemplateManagement[]>([]);
|
||||||
|
|
||||||
// 查询字段
|
// 查询字段
|
||||||
const searchFiled = async () => {
|
const searchFiled = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -140,6 +153,7 @@
|
||||||
eventTag: 'delete',
|
eventTag: 'delete',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// 删除模板
|
// 删除模板
|
||||||
const handlerDelete = (record: any) => {
|
const handlerDelete = (record: any) => {
|
||||||
openModal({
|
openModal({
|
||||||
|
@ -202,6 +216,7 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 复制模板
|
// 复制模板
|
||||||
const copyTemplate = (id: string) => {
|
const copyTemplate = (id: string) => {
|
||||||
router.push({
|
router.push({
|
||||||
|
@ -228,12 +243,24 @@
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
|
||||||
|
const sceneType = computed(() => route.query.type);
|
||||||
|
|
||||||
|
const isThirdParty = {
|
||||||
|
title: 'system.orgTemplate.isThirdParty',
|
||||||
|
dataIndex: 'enableThirdPart',
|
||||||
|
slotName: 'enableThirdPart',
|
||||||
|
showDrag: true,
|
||||||
|
showInTable: true,
|
||||||
|
};
|
||||||
|
|
||||||
function updateColumns() {
|
function updateColumns() {
|
||||||
if (isEnable) {
|
const columns =
|
||||||
const result = fieldColumns.slice(0, fieldColumns.length - 1);
|
sceneType.value === 'BUG' ? fieldColumns.slice(0, 1).concat(isThirdParty, fieldColumns.slice(1)) : fieldColumns;
|
||||||
|
if (isEnableOrdTemplate.value) {
|
||||||
|
const result = columns.slice(0, columns.length - 1);
|
||||||
tableRef.value.initColumn(result);
|
tableRef.value.initColumn(result);
|
||||||
} else {
|
} else {
|
||||||
tableRef.value.initColumn(fieldColumns);
|
tableRef.value.initColumn(columns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +269,7 @@
|
||||||
fetchData();
|
fetchData();
|
||||||
updateColumns();
|
updateColumns();
|
||||||
});
|
});
|
||||||
|
tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT, fieldColumns, 'drawer');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<MsIcon v-if="!record.internal" :type="getIconType(record.type)?.iconName || ''" size="16" />
|
<MsIcon v-if="!record.internal" :type="getIconType(record.type)?.iconName || ''" size="16" />
|
||||||
<span class="ml-2">{{ record.name }}</span>
|
<span class="ml-2">{{ record.name }}</span>
|
||||||
<span v-if="record.internal" class="system-flag">{{ t('system.orgTemplate.isSystem') }}</span>
|
<MsTag v-if="record.internal" size="small" class="ml-2">{{ t('system.orgTemplate.isSystem') }}</MsTag>
|
||||||
</template>
|
</template>
|
||||||
<template #apiFieldId="{ record }">
|
<template #apiFieldId="{ record }">
|
||||||
<a-input
|
<a-input
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
v-model:visible="showDrawer"
|
v-model:visible="showDrawer"
|
||||||
:total-data="(totalData as DefinedFieldItem[])"
|
:total-data="(totalData as DefinedFieldItem[])"
|
||||||
:table-select-data="(selectList as DefinedFieldItem[])"
|
:table-select-data="(selectList as DefinedFieldItem[])"
|
||||||
|
:mode="props.mode"
|
||||||
@confirm="confirmHandler"
|
@confirm="confirmHandler"
|
||||||
@update-data="updateFieldHandler"
|
@update-data="updateFieldHandler"
|
||||||
/>
|
/>
|
||||||
|
@ -46,33 +47,42 @@
|
||||||
</template>
|
</template>
|
||||||
{{ t('system.orgTemplate.createField') }}
|
{{ t('system.orgTemplate.createField') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<EditFieldDrawer ref="fieldDrawerRef" v-model:visible="showFieldDrawer" @success="updateFieldHandler" />
|
<EditFieldDrawer
|
||||||
|
ref="fieldDrawerRef"
|
||||||
|
v-model:visible="showFieldDrawer"
|
||||||
|
:mode="props.mode"
|
||||||
|
@success="updateFieldHandler"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织-模板管理-创建模板-非缺陷模板自定义字段表格
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
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 AddFieldToTemplateDrawer from './addFieldToTemplateDrawer.vue';
|
import AddFieldToTemplateDrawer from './addFieldToTemplateDrawer.vue';
|
||||||
import EditFieldDrawer from './editFieldDrawer.vue';
|
import EditFieldDrawer from './editFieldDrawer.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useTableStore } from '@/store';
|
|
||||||
|
|
||||||
import type { DefinedFieldItem } from '@/models/setting/template';
|
import type { DefinedFieldItem } from '@/models/setting/template';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
import { getIconType } from './fieldSetting';
|
import { getIconType } from './fieldSetting';
|
||||||
|
|
||||||
const tableStore = useTableStore();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
enableThirdPart: boolean; // 是否对接第三方平台
|
enableThirdPart: boolean; // 是否对接第三方平台
|
||||||
data: DefinedFieldItem[]; // 总字段数据
|
data: DefinedFieldItem[]; // 总字段数据
|
||||||
selectData: Record<string, any>[]; // 选择数据
|
selectData: Record<string, any>[]; // 选择数据
|
||||||
|
@ -84,6 +94,8 @@
|
||||||
|
|
||||||
const emit = defineEmits(['update:select-data', 'update']);
|
const emit = defineEmits(['update:select-data', 'update']);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.name',
|
title: 'system.orgTemplate.name',
|
||||||
|
@ -121,6 +133,7 @@
|
||||||
{
|
{
|
||||||
title: 'system.orgTemplate.operation',
|
title: 'system.orgTemplate.operation',
|
||||||
slotName: 'operation',
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 200,
|
width: 200,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
|
@ -141,14 +154,14 @@
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
|
||||||
tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_FIELD, columns, 'drawer');
|
|
||||||
const { propsRes, propsEvent, setProps } = useTable(undefined, {
|
const { propsRes, propsEvent, setProps } = useTable(undefined, {
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_FIELD,
|
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_FIELD,
|
||||||
|
columns,
|
||||||
scroll: { x: '1800px' },
|
scroll: { x: '1800px' },
|
||||||
selectable: false,
|
selectable: false,
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
size: 'default',
|
size: 'default',
|
||||||
showSetting: true,
|
showSetting: false,
|
||||||
showPagination: false,
|
showPagination: false,
|
||||||
enableDrag: true,
|
enableDrag: true,
|
||||||
});
|
});
|
||||||
|
@ -241,7 +254,7 @@
|
||||||
watch(
|
watch(
|
||||||
() => props.enableThirdPart,
|
() => props.enableThirdPart,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val && route.query.type === 'BUG') {
|
||||||
const result = [...columns.slice(0, 1), getApiColumns(), ...columns.slice(1)];
|
const result = [...columns.slice(0, 1), getApiColumns(), ...columns.slice(1)];
|
||||||
tableRef.value.initColumn(result);
|
tableRef.value.initColumn(result);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,220 +1,61 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="wrapper-preview">
|
<div class="wrapper-preview">
|
||||||
<div class="preview-left pr-4">
|
<div class="preview-left pr-4">
|
||||||
<a-form ref="viewFormRef" class="rounded-[4px]" :model="viewForm" layout="vertical">
|
<DefectTemplateLeftContent v-if="props.templateType === 'BUG'" :defect-form="props.defectForm" />
|
||||||
<a-form-item
|
<CaseTemplateLeftContent v-else />
|
||||||
field="caseName"
|
|
||||||
:label="t('system.orgTemplate.caseName')"
|
|
||||||
:rules="[{ required: true, message: t('system.orgTemplate.caseNamePlaceholder') }]"
|
|
||||||
required
|
|
||||||
asterisk-position="end"
|
|
||||||
>
|
|
||||||
<a-input
|
|
||||||
v-model="viewForm.name"
|
|
||||||
:max-length="255"
|
|
||||||
:placeholder="t('system.orgTemplate.caseNamePlaceholder')"
|
|
||||||
show-word-limit
|
|
||||||
allow-clear
|
|
||||||
></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="precondition" :label="t('system.orgTemplate.precondition')" asterisk-position="end">
|
|
||||||
<MsRichText v-model="viewForm.precondition" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="step" :label="t('system.orgTemplate.stepDescription')" class="relative">
|
|
||||||
<div class="absolute left-16 top-0">
|
|
||||||
<a-divider direction="vertical" />
|
|
||||||
<a-dropdown :popup-max-height="false" @select="handleSelectType">
|
|
||||||
<span class="text-[14px] text-[var(--color-text-4)]"
|
|
||||||
>{{ t('system.orgTemplate.changeType') }} <icon-down
|
|
||||||
/></span>
|
|
||||||
<template #content>
|
|
||||||
<a-doption> {{ t('system.orgTemplate.stepDescription') }}</a-doption>
|
|
||||||
<a-doption>{{ t('system.orgTemplate.textDescription') }}</a-doption>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</div>
|
|
||||||
<!-- 步骤描述 -->
|
|
||||||
<div class="w-full">
|
|
||||||
<MsBaseTable v-bind="propsRes" ref="stepTableRef" v-on="propsEvent">
|
|
||||||
<template #index="{ rowIndex }">
|
|
||||||
{{ rowIndex + 1 }}
|
|
||||||
</template>
|
|
||||||
<template #caseStep="{ record }">
|
|
||||||
<a-input v-if="record.showStep" v-model="record.caseStep" class="w-max-[267px]" />
|
|
||||||
<span v-else-if="record.caseStep && !record.showStep">{{ record.caseStep }}</span>
|
|
||||||
<span
|
|
||||||
v-else-if="!record.caseStep && !record.showStep"
|
|
||||||
class="placeholder text-[var(--color-text-brand)]"
|
|
||||||
>{{ t('system.orgTemplate.stepTip') }}</span
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #expectedResult="{ record }">
|
|
||||||
<a-input v-if="record.showExpected" v-model="record.expectedResult" class="w-max-[267px]" />
|
|
||||||
<span v-else-if="record.expectedResult && !record.showExpected">{{ record.caseStep }}</span>
|
|
||||||
<span
|
|
||||||
v-else-if="!record.expectedResult && !record.showExpected"
|
|
||||||
class="placeholder text-[var(--color-text-brand)]"
|
|
||||||
>{{ t('system.orgTemplate.expectationTip') }}</span
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #operation="{ record }">
|
|
||||||
<MsTableMoreAction
|
|
||||||
v-if="!record.internal"
|
|
||||||
:list="moreActions"
|
|
||||||
@select="(item) => handleMoreActionSelect(item)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</MsBaseTable>
|
|
||||||
</div>
|
|
||||||
<a-button class="mt-2 px-0" type="text" @click="addStep">
|
|
||||||
<template #icon>
|
|
||||||
<icon-plus class="text-[14px]" />
|
|
||||||
</template>
|
|
||||||
{{ t('system.orgTemplate.addStep') }}
|
|
||||||
</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="remark" label="备注"> <MsRichText v-model="viewForm.remark" /> </a-form-item>
|
|
||||||
<a-form-item field="attachment" label="添加附件">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="mb-1"
|
|
||||||
><a-button type="outline">
|
|
||||||
<template #icon> <icon-plus class="text-[14px]" /> </template
|
|
||||||
>{{ t('system.orgTemplate.addAttachment') }}</a-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('system.orgTemplate.addAttachmentTip') }}</div>
|
|
||||||
</div>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-right px-4">
|
<div class="preview-right px-4">
|
||||||
<MsFormCreate
|
<MsFormCreate
|
||||||
|
v-if="formRules.length"
|
||||||
ref="formCreateRef"
|
ref="formCreateRef"
|
||||||
:form-rule="formRules"
|
:form-rule="formRules"
|
||||||
:form-create-key="FormCreateKeyEnum.ORGANIZE_TEMPLATE_PREVIEW_TEMPLATE"
|
:form-create-key="FormCreateKeyEnum.ORGANIZE_TEMPLATE_PREVIEW_TEMPLATE"
|
||||||
/>
|
/>
|
||||||
|
<a-empty v-else />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 模板-创建模板&编辑模板-预览模板
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/form-create.vue';
|
import MsFormCreate from '@/components/pure/ms-form-create/form-create.vue';
|
||||||
import type { FormItem } from '@/components/pure/ms-form-create/types';
|
import type { FormItem } from '@/components/pure/ms-form-create/types';
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
import CaseTemplateLeftContent from './caseTemplateLeftContent.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import DefectTemplateLeftContent from './defectTemplateLeftContent.vue';
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import type { DefinedFieldItem, SeneType } from '@/models/setting/template';
|
||||||
import { useTableStore } from '@/store';
|
|
||||||
|
|
||||||
import type { DefinedFieldItem } from '@/models/setting/template';
|
|
||||||
import { FormCreateKeyEnum } from '@/enums/formCreateEnum';
|
import { FormCreateKeyEnum } from '@/enums/formCreateEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const tableStore = useTableStore();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
templateType: SeneType; // 模板场景
|
||||||
selectField: DefinedFieldItem[]; // 选择模板字段
|
selectField: DefinedFieldItem[]; // 选择模板字段
|
||||||
|
defectForm: Record<string, any>; // 缺陷详情
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const templateFieldColumns: MsTableColumn = [
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.numberIndex',
|
|
||||||
dataIndex: 'index',
|
|
||||||
slotName: 'index',
|
|
||||||
width: 100,
|
|
||||||
showDrag: false,
|
|
||||||
showInTable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.useCaseStep',
|
|
||||||
slotName: 'caseStep',
|
|
||||||
dataIndex: 'caseStep',
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.expectedResult',
|
|
||||||
dataIndex: 'expectedResult',
|
|
||||||
slotName: 'expectedResult',
|
|
||||||
showDrag: true,
|
|
||||||
showInTable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'system.orgTemplate.operation',
|
|
||||||
slotName: 'operation',
|
|
||||||
fixed: 'right',
|
|
||||||
width: 200,
|
|
||||||
showInTable: true,
|
|
||||||
showDrag: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const { propsRes, propsEvent, setProps } = useTable(undefined, {
|
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_STEP,
|
|
||||||
scroll: { x: '800px' },
|
|
||||||
selectable: false,
|
|
||||||
noDisable: true,
|
|
||||||
size: 'default',
|
|
||||||
showSetting: true,
|
|
||||||
showPagination: false,
|
|
||||||
enableDrag: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const viewForm = ref({
|
|
||||||
name: '',
|
|
||||||
precondition: '',
|
|
||||||
value: '',
|
|
||||||
remark: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSelectType = () => {};
|
|
||||||
|
|
||||||
const stepTableRef = ref();
|
|
||||||
|
|
||||||
const moreActions: ActionsItem[] = [
|
|
||||||
{
|
|
||||||
label: 'system.orgTemplate.copy',
|
|
||||||
danger: true,
|
|
||||||
eventTag: 'copy',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'system.orgTemplate.delete',
|
|
||||||
danger: true,
|
|
||||||
eventTag: 'delete',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const addStep = () => {};
|
|
||||||
const handlerDelete = () => {};
|
|
||||||
|
|
||||||
// 更多操作
|
|
||||||
const handleMoreActionSelect = (item: ActionsItem) => {
|
|
||||||
if (item.eventTag === 'delete') {
|
|
||||||
handlerDelete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const formRuleField = ref<FormItem[][]>([]);
|
const formRuleField = ref<FormItem[][]>([]);
|
||||||
const formRules = ref<FormItem[]>([]);
|
const formRules = ref<FormItem[]>([]);
|
||||||
const formCreateRef = ref();
|
const formCreateRef = ref();
|
||||||
|
|
||||||
// 处理表单格式
|
// 处理表单格式
|
||||||
const getFormRules = () => {
|
const getFormRules = () => {
|
||||||
|
formRuleField.value = [];
|
||||||
|
formRules.value = [];
|
||||||
if (props.selectField && props.selectField.length) {
|
if (props.selectField && props.selectField.length) {
|
||||||
props.selectField.forEach((item: DefinedFieldItem) => {
|
props.selectField.forEach((item: DefinedFieldItem) => {
|
||||||
const currentFormItem = item.formRules?.map((rule: any) => {
|
const currentFormItem = item.formRules?.map((rule: any) => {
|
||||||
const optionsItem = rule.options.map((opt: any) => {
|
let optionsItem = [];
|
||||||
|
if (rule.options && rule.options.length) {
|
||||||
|
optionsItem = rule.options.map((opt: any) => {
|
||||||
return {
|
return {
|
||||||
text: opt.label,
|
text: opt.label,
|
||||||
value: opt.value,
|
value: opt.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
type: item.type,
|
type: item.type,
|
||||||
name: rule.field,
|
name: rule.field,
|
||||||
|
@ -225,24 +66,28 @@
|
||||||
props: {
|
props: {
|
||||||
modelValue: rule.value,
|
modelValue: rule.value,
|
||||||
options: optionsItem,
|
options: optionsItem,
|
||||||
|
disabled: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
formRuleField.value.push(currentFormItem as FormItem[]);
|
formRuleField.value.push(currentFormItem as FormItem[]);
|
||||||
});
|
});
|
||||||
const result = formRuleField.value.flatMap((item) => item);
|
formRules.value = formRuleField.value.flatMap((item) => item);
|
||||||
formRules.value = result;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
getFormRules();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
formRules.value = [];
|
||||||
|
formRuleField.value = [];
|
||||||
|
});
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getFormRules,
|
getFormRules,
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
setProps({ data: [{ id: 1, showStep: false, showExpected: false }] });
|
|
||||||
getFormRules();
|
|
||||||
});
|
|
||||||
await tableStore.initColumn(TableKeyEnum.ORGANIZATION_TEMPLATE_MANAGEMENT_STEP, templateFieldColumns, 'drawer');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<MsCard has-breadcrumb simple>
|
||||||
|
<WorkflowTable mode="organization" />
|
||||||
|
</MsCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 系统管理-组织=模板-工作流首页
|
||||||
|
*/
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import WorkflowTable from './workflowTable.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -3,10 +3,10 @@
|
||||||
class="wrapper"
|
class="wrapper"
|
||||||
:class="{
|
:class="{
|
||||||
...styleClass.wrapper,
|
...styleClass.wrapper,
|
||||||
_hover_Wrapper: isEnableProjectState || isNotAllowCreate ? false : true,
|
'_hover_Wrapper': isEnableProjectState || isNotAllowCreate ? false : true,
|
||||||
_pointer: !isNotAllowCreate,
|
'_pointer': !isNotAllowCreate,
|
||||||
_not_allowed: isNotAllowCreate,
|
'cursor-not-allowed': isNotAllowCreate,
|
||||||
_disabled_gray_bg: isEnableProjectState,
|
'_disabled_gray_bg': isEnableProjectState,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<!-- 不允许状态流转 -->
|
<!-- 不允许状态流转 -->
|
||||||
|
@ -64,27 +64,27 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/**
|
/**
|
||||||
* @description 系统设置-组织-工作流table小卡片
|
* @description 工作流table小卡片
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { Message, TableColumnData } from '@arco-design/web-vue';
|
import { Message, TableColumnData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
|
||||||
import { updateOrdWorkStateFlow } from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useTemplateStore from '@/store/modules/setting/template';
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
|
||||||
import type { UpdateWorkFlowSetting, WorkFlowType } from '@/models/setting/template';
|
import type { UpdateWorkFlowSetting, WorkFlowType } from '@/models/setting/template';
|
||||||
|
|
||||||
|
import { getWorkFlowRequestApi } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
const templateStore = useTemplateStore();
|
const templateStore = useTemplateStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project';
|
||||||
stateItem: WorkFlowType;
|
stateItem: WorkFlowType;
|
||||||
columnItem: TableColumnData;
|
columnItem: TableColumnData;
|
||||||
cellCoordinates: { rowId: string; columnId: string };
|
cellCoordinates: { rowId: string; columnId: string };
|
||||||
|
@ -134,8 +134,9 @@
|
||||||
|
|
||||||
// 计算是否禁用状态
|
// 计算是否禁用状态
|
||||||
const isEnableProjectState = computed(() => {
|
const isEnableProjectState = computed(() => {
|
||||||
const projectState = templateStore.getProjectTemplateState();
|
return props.mode === 'project'
|
||||||
return projectState[props.stateItem.scene];
|
? !templateStore.projectStatus[props.stateItem.scene]
|
||||||
|
: !templateStore.ordStatus[props.stateItem.scene];
|
||||||
});
|
});
|
||||||
|
|
||||||
const title = computed(() => {
|
const title = computed(() => {
|
||||||
|
@ -227,6 +228,7 @@
|
||||||
|
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const updateOrdWorkStateFlow = getWorkFlowRequestApi(props.mode).updateFlow;
|
||||||
// 创建工作流流转状态
|
// 创建工作流流转状态
|
||||||
async function changeWorkFlow(type: string) {
|
async function changeWorkFlow(type: string) {
|
||||||
try {
|
try {
|
||||||
|
@ -307,9 +309,9 @@
|
||||||
}
|
}
|
||||||
// 容器阴影 hover
|
// 容器阴影 hover
|
||||||
._hover_Wrapper {
|
._hover_Wrapper {
|
||||||
@apply hover:shadow-xl;
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 4px 15px -1px rgba(100 100 102 / 15%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 未创建hover----
|
// 未创建hover----
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<MsCard has-breadcrumb simple>
|
<a-alert v-if="isShowTip" class="mb-6" type="warning">
|
||||||
<a-alert class="mb-6" type="warning">{{ t('system.orgTemplate.workFlowTip') }}</a-alert>
|
<div class="flex items-start justify-between">
|
||||||
|
<span class="w-[80%]">{{ t('system.orgTemplate.workFlowTip') }}</span>
|
||||||
|
<span class="cursor-pointer text-[var(--color-text-2)]" @click="noRemindHandler">{{
|
||||||
|
t('system.orgTemplate.noReminders')
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</a-alert>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="mb-4 flex items-center"
|
<div class="mb-4 flex items-center"
|
||||||
><a-button class="mr-2" type="outline" @click="addStatus">{{ t('system.orgTemplate.addState') }}</a-button>
|
><a-button v-if="!isEnableProjectState" class="mr-2" type="outline" @click="addStatus">{{
|
||||||
|
t('system.orgTemplate.addState')
|
||||||
|
}}</a-button>
|
||||||
|
<span v-else class="mr-2 font-medium text-[var(--color-text-1)]">工作流</span>
|
||||||
<a-popover title="" position="right">
|
<a-popover title="" position="right">
|
||||||
<MsButton class="!mr-1">{{ t('system.orgTemplate.example') }}</MsButton>
|
<MsButton class="!mr-1">{{ t('system.orgTemplate.example') }}</MsButton>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="w-[410px] bg-[var(--color-bg-3)] p-[16px]">
|
<div class="w-[410px] bg-[var(--color-bg-3)] p-1">
|
||||||
<img src="@/assets/images/schematicDrawing.png" alt="" />
|
<img src="@/assets/images/schematicDrawing.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -27,6 +36,7 @@
|
||||||
:bordered="{ cell: true }"
|
:bordered="{ cell: true }"
|
||||||
:hoverable="false"
|
:hoverable="false"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
|
:scroll="{ x: '1400px' }"
|
||||||
:draggable="{ type: 'handle', width: 39 }"
|
:draggable="{ type: 'handle', width: 39 }"
|
||||||
:loading="tableLoading"
|
:loading="tableLoading"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
|
@ -60,7 +70,10 @@
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="action mr-2 flex h-8 w-8 items-center justify-center rounded opacity-0">
|
<div
|
||||||
|
v-if="!isEnableProjectState"
|
||||||
|
class="action mr-2 flex h-8 w-8 items-center justify-center rounded opacity-0"
|
||||||
|
>
|
||||||
<MsTableMoreAction
|
<MsTableMoreAction
|
||||||
:list="getMoreActions(record)"
|
:list="getMoreActions(record)"
|
||||||
@select="(item) => handleMoreActionSelect(item, record)"
|
@select="(item) => handleMoreActionSelect(item, record)"
|
||||||
|
@ -70,6 +83,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="!h-[82px] min-w-[116px] p-[2px]">
|
<div v-else class="!h-[82px] min-w-[116px] p-[2px]">
|
||||||
<WorkflowCard
|
<WorkflowCard
|
||||||
|
:mode="props.mode"
|
||||||
:column-item="column"
|
:column-item="column"
|
||||||
:state-item="record"
|
:state-item="record"
|
||||||
:cell-coordinates="cellCoordinates"
|
:cell-coordinates="cellCoordinates"
|
||||||
|
@ -80,17 +94,27 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table-column>
|
</a-table-column>
|
||||||
<a-table-column :title="t('system.orgTemplate.operation')" :width="360" header-cell-class="splitOperation">
|
<a-table-column
|
||||||
<template #cell="{ record }">
|
:title="t('system.orgTemplate.operation')"
|
||||||
<div class="flex">
|
:width="320"
|
||||||
<MsButton class="!mr-0 ml-4" @click="editWorkStatus(record)">{{ t('common.edit') }}</MsButton>
|
header-cell-class="splitOperation"
|
||||||
<a-divider direction="vertical" />
|
fixed="right"
|
||||||
<a-checkbox v-model="record.currentState" @change="(value) => changeState(value, record)">
|
|
||||||
<MsButton>{{ t('system.orgTemplate.endState') }}</MsButton></a-checkbox
|
|
||||||
>
|
>
|
||||||
<MsButton class="!mr-0 ml-4" @click="detailWorkStatus(record)">{{
|
<template #cell="{ record }">
|
||||||
t('system.orgTemplate.details')
|
<div class="ml-4 flex items-center">
|
||||||
|
<MsButton v-if="!isEnableProjectState" class="!mr-0 ml-4" @click="editWorkStatus(record)">{{
|
||||||
|
t('common.edit')
|
||||||
}}</MsButton>
|
}}</MsButton>
|
||||||
|
<a-divider v-if="!isEnableProjectState" class="h-[12px]" direction="vertical" />
|
||||||
|
<a-checkbox
|
||||||
|
v-if="!isEnableProjectState"
|
||||||
|
v-model="record.currentState"
|
||||||
|
@change="(value) => changeState(value, record)"
|
||||||
|
>
|
||||||
|
<MsButton class="!mr-0">{{ t('system.orgTemplate.endState') }}</MsButton></a-checkbox
|
||||||
|
>
|
||||||
|
<a-divider v-if="!isEnableProjectState" class="h-[12px]" direction="vertical" />
|
||||||
|
<MsButton class="!mr-0" @click="detailWorkStatus(record)">{{ t('system.orgTemplate.details') }}</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table-column>
|
</a-table-column>
|
||||||
|
@ -109,7 +133,12 @@
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</div>
|
</div>
|
||||||
<AddWorkStatusModal ref="addWorkStateRef" v-model:visible="showModel" @success="getWorkFetchList()" />
|
<AddWorkStatusModal
|
||||||
|
ref="addWorkStateRef"
|
||||||
|
v-model:visible="showModel"
|
||||||
|
:mode="props.mode"
|
||||||
|
@success="getWorkFetchList()"
|
||||||
|
/>
|
||||||
<MsDrawer
|
<MsDrawer
|
||||||
ref="detailDrawerRef"
|
ref="detailDrawerRef"
|
||||||
v-model:visible="showDetailVisible"
|
v-model:visible="showDetailVisible"
|
||||||
|
@ -129,44 +158,47 @@
|
||||||
</div>
|
</div>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</div>
|
</div>
|
||||||
</MsCard>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 模板-工作流table
|
||||||
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { Message, TableColumnData, TableData } from '@arco-design/web-vue';
|
import { Message, TableColumnData, TableData } from '@arco-design/web-vue';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import AddWorkStatusModal from './addWorkStatusModal.vue';
|
import AddWorkStatusModal from '@/views/setting/organization/template/components/addWorkStatusModal.vue';
|
||||||
import WorkflowCard from './workflowCard.vue';
|
import WorkflowCard from '@/views/setting/organization/template/components/workflowCard.vue';
|
||||||
|
|
||||||
import {
|
|
||||||
deleteOrdWorkState,
|
|
||||||
getWorkFlowList,
|
|
||||||
setOrdWorkState,
|
|
||||||
setOrdWorkStateSort,
|
|
||||||
} from '@/api/modules/setting/template';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
|
import useVisit from '@/hooks/useVisit';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useTemplateStore from '@/store/modules/setting/template';
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import type { SetStateType, WorkFlowType } from '@/models/setting/template';
|
import type { SetStateType, WorkFlowType } from '@/models/setting/template';
|
||||||
|
|
||||||
|
import { getWorkFlowRequestApi } from '@/views/setting/organization/template/components/fieldSetting';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const templateStore = useTemplateStore();
|
const templateStore = useTemplateStore();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
mode: 'organization' | 'project'; // 组织 || 项目
|
||||||
|
}>();
|
||||||
|
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
@ -180,10 +212,11 @@
|
||||||
|
|
||||||
// 计算是否禁用状态
|
// 计算是否禁用状态
|
||||||
const isEnableProjectState = computed(() => {
|
const isEnableProjectState = computed(() => {
|
||||||
const projectState = templateStore.getProjectTemplateState();
|
return props.mode === 'organization'
|
||||||
return projectState[route.query.type as string];
|
? templateStore.projectStatus[route.query.type as string]
|
||||||
|
: !templateStore.projectStatus[route.query.type as string];
|
||||||
});
|
});
|
||||||
const dataList = ref<any>([]);
|
const dataList = ref<WorkFlowType[]>([]);
|
||||||
|
|
||||||
// 获取的状态流数据
|
// 获取的状态流数据
|
||||||
const workData = ref<WorkFlowType[]>([]);
|
const workData = ref<WorkFlowType[]>([]);
|
||||||
|
@ -212,12 +245,16 @@
|
||||||
|
|
||||||
const tableLoading = ref<boolean>(false);
|
const tableLoading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const scopedId = computed(() => (props.mode === 'organization' ? currentOrgId.value : currentProjectId.value));
|
||||||
|
|
||||||
|
const getWorkList = getWorkFlowRequestApi(props.mode).list;
|
||||||
|
|
||||||
// 获取table列表
|
// 获取table列表
|
||||||
async function getWorkFetchList() {
|
async function getWorkFetchList() {
|
||||||
try {
|
try {
|
||||||
tableLoading.value = true;
|
tableLoading.value = true;
|
||||||
workData.value = await getWorkFlowList(currentOrgId.value, route.query.type);
|
workData.value = await getWorkList(scopedId.value, route.query.type);
|
||||||
workFlowColumns.value = workData.value.map((item, index) => {
|
workFlowColumns.value = workData.value.map((item) => {
|
||||||
const columns = {
|
const columns = {
|
||||||
title: item.name,
|
title: item.name,
|
||||||
dataIndex: item.id,
|
dataIndex: item.id,
|
||||||
|
@ -261,7 +298,7 @@
|
||||||
function addStatus() {
|
function addStatus() {
|
||||||
showModel.value = true;
|
showModel.value = true;
|
||||||
}
|
}
|
||||||
|
const deleteState = getWorkFlowRequestApi(props.mode).delete;
|
||||||
// 删除状态
|
// 删除状态
|
||||||
function deleteHandler(record: WorkFlowType) {
|
function deleteHandler(record: WorkFlowType) {
|
||||||
if (record.statusDefinitions.join().includes('START')) {
|
if (record.statusDefinitions.join().includes('START')) {
|
||||||
|
@ -279,7 +316,7 @@
|
||||||
},
|
},
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
if (record.id) await deleteOrdWorkState(record.id);
|
if (record.id) await deleteState(record.id);
|
||||||
Message.success(t('system.orgTemplate.deleteSuccess'));
|
Message.success(t('system.orgTemplate.deleteSuccess'));
|
||||||
getWorkFetchList();
|
getWorkFetchList();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -290,6 +327,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setInitAndEndState = getWorkFlowRequestApi(props.mode).changeState;
|
||||||
// 设置初始状态|| 设置结束状态
|
// 设置初始状态|| 设置结束状态
|
||||||
async function setState(record: WorkFlowType, type: string) {
|
async function setState(record: WorkFlowType, type: string) {
|
||||||
const params: SetStateType = {
|
const params: SetStateType = {
|
||||||
|
@ -298,7 +336,7 @@
|
||||||
enable: type === 'START' ? true : record.currentState,
|
enable: type === 'START' ? true : record.currentState,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await setOrdWorkState(params);
|
await setInitAndEndState(params);
|
||||||
Message.success(
|
Message.success(
|
||||||
type === 'END' ? t('system.orgTemplate.setEndStateSuccess') : t('system.orgTemplate.setInitStateSuccess')
|
type === 'END' ? t('system.orgTemplate.setEndStateSuccess') : t('system.orgTemplate.setInitStateSuccess')
|
||||||
);
|
);
|
||||||
|
@ -314,15 +352,17 @@
|
||||||
setState(record, 'START');
|
setState(record, 'START');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dragChangeRequest = getWorkFlowRequestApi(props.mode).dragChange;
|
||||||
// 表格拖拽改变回调
|
// 表格拖拽改变回调
|
||||||
async function handleChange(_data: TableData[]) {
|
async function handleChange(_data: TableData[]) {
|
||||||
const originIds = dataList.value.map((item: any) => item.id);
|
const originIds = dataList.value.map((item: any) => item.id);
|
||||||
dataList.value = _data;
|
dataList.value = _data as WorkFlowType[];
|
||||||
const dataIds = _data.map((item: any) => item.id);
|
const dataIds = _data.map((item: any) => item.id);
|
||||||
const isChange = isEqual(originIds, dataIds);
|
const isChange = isEqual(originIds, dataIds);
|
||||||
if (isChange) return {};
|
if (isChange) return false;
|
||||||
try {
|
try {
|
||||||
await setOrdWorkStateSort(currentOrgId.value, route.query.type, dataIds);
|
await dragChangeRequest(scopedId.value, route.query.type, dataIds);
|
||||||
getWorkFetchList();
|
getWorkFetchList();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -364,8 +404,24 @@
|
||||||
detailInfo.value = { ...record };
|
detailInfo.value = { ...record };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const visitedKey = 'notRemindWorkFlowTip';
|
||||||
|
const { addVisited } = useVisit(visitedKey);
|
||||||
|
const { getIsVisited } = useVisit(visitedKey);
|
||||||
|
const isShowTip = ref<boolean>(true);
|
||||||
|
|
||||||
|
// 不再提示
|
||||||
|
const noRemindHandler = () => {
|
||||||
|
isShowTip.value = false;
|
||||||
|
addVisited();
|
||||||
|
};
|
||||||
|
|
||||||
|
const doCheckIsTip = () => {
|
||||||
|
isShowTip.value = !getIsVisited();
|
||||||
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
getWorkFetchList();
|
getWorkFetchList();
|
||||||
|
doCheckIsTip();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,21 @@
|
||||||
:card-min-width="360"
|
:card-min-width="360"
|
||||||
class="flex-1"
|
class="flex-1"
|
||||||
:shadow-limit="50"
|
:shadow-limit="50"
|
||||||
:list="getCardList('organization')"
|
:list="cardList"
|
||||||
:is-proportional="false"
|
:is-proportional="false"
|
||||||
:gap="16"
|
:gap="16"
|
||||||
padding-bottom-space="16px"
|
padding-bottom-space="16px"
|
||||||
>
|
>
|
||||||
<template #item="{ item, index }">
|
<template #item="{ item, index }">
|
||||||
<TemplateItem :card-item="item" :index="index" />
|
<TemplateItem
|
||||||
|
:card-item="item"
|
||||||
|
:index="index"
|
||||||
|
mode="organization"
|
||||||
|
@field-setting="fieldSetting"
|
||||||
|
@template-management="templateManagement"
|
||||||
|
@workflow-setup="workflowSetup"
|
||||||
|
@update-state="updateState"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</MsCardList>
|
</MsCardList>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,7 +39,7 @@
|
||||||
/**
|
/**
|
||||||
* @description 系统设置--组织--模版
|
* @description 系统设置--组织--模版
|
||||||
*/
|
*/
|
||||||
import { onMounted, ref } from 'vue';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import MsCardList from '@/components/business/ms-card-list/index.vue';
|
import MsCardList from '@/components/business/ms-card-list/index.vue';
|
||||||
|
@ -41,16 +49,16 @@
|
||||||
import useVisit from '@/hooks/useVisit';
|
import useVisit from '@/hooks/useVisit';
|
||||||
import useTemplateStore from '@/store/modules/setting/template';
|
import useTemplateStore from '@/store/modules/setting/template';
|
||||||
|
|
||||||
|
import { SettingRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
import { getCardList } from './components/fieldSetting';
|
import { getCardList } from './components/fieldSetting';
|
||||||
|
|
||||||
const templateStore = useTemplateStore();
|
const templateStore = useTemplateStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
const visitedKey = 'notRemind';
|
const visitedKey = 'notRemind';
|
||||||
const { addVisited } = useVisit(visitedKey);
|
const { addVisited } = useVisit(visitedKey);
|
||||||
const { getIsVisited } = useVisit(visitedKey);
|
const { getIsVisited } = useVisit(visitedKey);
|
||||||
|
|
||||||
const isShowTip = ref<boolean>(true);
|
const isShowTip = ref<boolean>(true);
|
||||||
const noRemindHandler = () => {
|
const noRemindHandler = () => {
|
||||||
isShowTip.value = false;
|
isShowTip.value = false;
|
||||||
|
@ -65,8 +73,46 @@
|
||||||
templateStore.getStatus();
|
templateStore.getStatus();
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
// 字段设置
|
||||||
|
const fieldSetting = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_FILED_SETTING,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 模板管理
|
||||||
|
const templateManagement = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 工作流
|
||||||
|
const workflowSetup = (key: string) => {
|
||||||
|
router.push({
|
||||||
|
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE_MANAGEMENT_WORKFLOW,
|
||||||
|
query: {
|
||||||
|
type: key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardList = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
// 更新状态列表
|
||||||
|
const updateState = () => {
|
||||||
|
cardList.value = [...getCardList('organization')];
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
doCheckIsTip();
|
doCheckIsTip();
|
||||||
|
updateState();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default {
|
||||||
'system.orgTemplate.testPlanTemplates': 'TestPlan template',
|
'system.orgTemplate.testPlanTemplates': 'TestPlan template',
|
||||||
'system.orgTemplate.defectTemplates': 'Defect template',
|
'system.orgTemplate.defectTemplates': 'Defect template',
|
||||||
'system.orgTemplate.enabledTemplates': 'enabled',
|
'system.orgTemplate.enabledTemplates': 'enabled',
|
||||||
|
'system.orgTemplate.disabledTemplates': 'disabled',
|
||||||
'system.orgTemplate.fieldSetting': 'Setting',
|
'system.orgTemplate.fieldSetting': 'Setting',
|
||||||
'system.orgTemplate.TemplateManagement': 'Management',
|
'system.orgTemplate.TemplateManagement': 'Management',
|
||||||
'system.orgTemplate.workflowSetup': 'Workflow',
|
'system.orgTemplate.workflowSetup': 'Workflow',
|
||||||
|
@ -86,6 +87,7 @@ export default {
|
||||||
'system.orgTemplate.addStep': 'Add Step',
|
'system.orgTemplate.addStep': 'Add Step',
|
||||||
'system.orgTemplate.caseName': 'Use case name',
|
'system.orgTemplate.caseName': 'Use case name',
|
||||||
'system.orgTemplate.caseNamePlaceholder': 'Please enter a use case name',
|
'system.orgTemplate.caseNamePlaceholder': 'Please enter a use case name',
|
||||||
|
'system.orgTemplate.defectNamePlaceholder': 'Please enter a use defect name',
|
||||||
'system.orgTemplate.precondition': 'precondition',
|
'system.orgTemplate.precondition': 'precondition',
|
||||||
'system.orgTemplate.stepDescription': 'Step description',
|
'system.orgTemplate.stepDescription': 'Step description',
|
||||||
'system.orgTemplate.changeType': 'Change type',
|
'system.orgTemplate.changeType': 'Change type',
|
||||||
|
@ -146,4 +148,20 @@ export default {
|
||||||
'system.orgTemplate.stateTip':
|
'system.orgTemplate.stateTip':
|
||||||
'Open, the existing state will transfer to the state, only in the state of new Settings',
|
'Open, the existing state will transfer to the state, only in the state of new Settings',
|
||||||
'system.orgTemplate.createSuccess': 'Created successfully',
|
'system.orgTemplate.createSuccess': 'Created successfully',
|
||||||
|
'system.orgTemplate.filedDetail': '{name}',
|
||||||
|
'system.orgTemplate.int': 'Int',
|
||||||
|
'system.orgTemplate.float': 'Float',
|
||||||
|
'system.orgTemplate.defaultTemplate': 'Default Template',
|
||||||
|
'system.orgTemplate.setSuccessfully': 'Set successfully',
|
||||||
|
'system.orgTemplate.isThirdParty': 'Third Party',
|
||||||
|
'system.orgTemplate.yes': 'Yes',
|
||||||
|
'system.orgTemplate.no': 'No',
|
||||||
|
'system.orgTemplate.custom': 'custom',
|
||||||
|
'system.orgTemplate.defectName': 'Defect Name',
|
||||||
|
'system.orgTemplate.defectContent': 'Defect Content',
|
||||||
|
'system.orgTemplate.defectNameTip':
|
||||||
|
'You can set a default value for the defect name, which is used uniformly when creating it',
|
||||||
|
'system.orgTemplate.defectContentTip':
|
||||||
|
'You can set the default value for the defect content and use it when creating',
|
||||||
|
'system.orgTemplate.templateNameRules': 'Please enter a template name',
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default {
|
||||||
'system.orgTemplate.testPlanTemplates': '测试计划模版',
|
'system.orgTemplate.testPlanTemplates': '测试计划模版',
|
||||||
'system.orgTemplate.defectTemplates': '缺陷模版',
|
'system.orgTemplate.defectTemplates': '缺陷模版',
|
||||||
'system.orgTemplate.enabledTemplates': '已启用项目模版',
|
'system.orgTemplate.enabledTemplates': '已启用项目模版',
|
||||||
|
'system.orgTemplate.disabledTemplates': '未启用项目模版',
|
||||||
'system.orgTemplate.fieldSetting': '字段设置',
|
'system.orgTemplate.fieldSetting': '字段设置',
|
||||||
'system.orgTemplate.TemplateManagement': '模版管理',
|
'system.orgTemplate.TemplateManagement': '模版管理',
|
||||||
'system.orgTemplate.workflowSetup': '工作流设置',
|
'system.orgTemplate.workflowSetup': '工作流设置',
|
||||||
|
@ -88,6 +89,7 @@ export default {
|
||||||
'system.orgTemplate.addStep': '添加步骤',
|
'system.orgTemplate.addStep': '添加步骤',
|
||||||
'system.orgTemplate.caseName': '用例名称',
|
'system.orgTemplate.caseName': '用例名称',
|
||||||
'system.orgTemplate.caseNamePlaceholder': '请输入用例名称',
|
'system.orgTemplate.caseNamePlaceholder': '请输入用例名称',
|
||||||
|
'system.orgTemplate.defectNamePlaceholder': '请输入缺陷名称',
|
||||||
'system.orgTemplate.precondition': '前置条件',
|
'system.orgTemplate.precondition': '前置条件',
|
||||||
'system.orgTemplate.stepDescription': '步骤描述',
|
'system.orgTemplate.stepDescription': '步骤描述',
|
||||||
'system.orgTemplate.changeType': '更改类型',
|
'system.orgTemplate.changeType': '更改类型',
|
||||||
|
@ -140,4 +142,18 @@ export default {
|
||||||
'system.orgTemplate.details': '详情',
|
'system.orgTemplate.details': '详情',
|
||||||
'system.orgTemplate.stateTip': '开启: 已有的状态会流转到该状态,仅在新建状态时设置',
|
'system.orgTemplate.stateTip': '开启: 已有的状态会流转到该状态,仅在新建状态时设置',
|
||||||
'system.orgTemplate.createSuccess': '创建成功',
|
'system.orgTemplate.createSuccess': '创建成功',
|
||||||
|
'system.orgTemplate.filedDetail': '{name}',
|
||||||
|
'system.orgTemplate.int': '整数',
|
||||||
|
'system.orgTemplate.float': '保留小数',
|
||||||
|
'system.orgTemplate.defaultTemplate': '默认模板',
|
||||||
|
'system.orgTemplate.setSuccessfully': '设置成功',
|
||||||
|
'system.orgTemplate.isThirdParty': '对接第三方',
|
||||||
|
'system.orgTemplate.yes': '是',
|
||||||
|
'system.orgTemplate.no': '否',
|
||||||
|
'system.orgTemplate.custom': '自定义',
|
||||||
|
'system.orgTemplate.defectName': '缺陷名称',
|
||||||
|
'system.orgTemplate.defectContent': '缺陷内容',
|
||||||
|
'system.orgTemplate.defectNameTip': '可为缺陷名称设置默认值,创建时统一使用',
|
||||||
|
'system.orgTemplate.defectContentTip': '可为缺陷内容设置默认值,创建时统一使用',
|
||||||
|
'system.orgTemplate.templateNameRules': '请输入模板名称',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue