fix(projects): 1、修复管俊提的工时填报完毕后,提示的404报错;2、调整执行协办人可以编辑协办人列表的操作;

This commit is contained in:
2026-07-14 11:24:49 +08:00
parent 503ea1e255
commit 27c136c906
4 changed files with 27 additions and 13 deletions

View File

@@ -29,7 +29,10 @@ function isTaskMutationActor(task: Api.Project.ProjectTask, identity: TaskMutati
);
}
function isExecutionMutationActor(execution: Api.Project.ProjectExecution, identity: TaskMutationIdentity): boolean {
export function isExecutionMutationActor(
execution: Api.Project.ProjectExecution,
identity: TaskMutationIdentity
): boolean {
const { currentUserId, projectManagerUserId } = identity;
if (!currentUserId) return false;

View File

@@ -12,7 +12,6 @@ export interface CascadeTriggerPayload {
export interface UseTaskCompletionCascadeOptions {
projectId: ComputedRef<string>;
executionId: ComputedRef<string>;
/** 由调用方提供:打开 StatusActionDialog 的钩子composable 不持有 dialog 实例 */
openStatusActionDialog: (task: ProjectTask, action: TaskAction, fromCascade: boolean) => void;
/** 从 task 的 availableActions 里找出"完成"动作;找不到返回 null */
@@ -74,7 +73,7 @@ export function useTaskCompletionCascade(options: UseTaskCompletionCascadeOption
return;
}
const siblings = await loadSiblings(completedTask.parentTaskId);
const siblings = await loadSiblings(completedTask.parentTaskId, completedTask.executionId);
if (siblings === null) {
window.$message?.warning('父任务级联检查失败');
return;
@@ -84,7 +83,7 @@ export function useTaskCompletionCascade(options: UseTaskCompletionCascadeOption
return;
}
const parent = await fetchTaskDetail(completedTask.parentTaskId);
const parent = await fetchTaskDetail(completedTask.parentTaskId, completedTask.executionId);
if (!parent) {
window.$message?.warning('父任务级联检查失败');
return;
@@ -122,7 +121,8 @@ export function useTaskCompletionCascade(options: UseTaskCompletionCascadeOption
}
try {
const result = await fetchGetProjectTaskWorklogPage(options.projectId.value, options.executionId.value, task.id, {
// 跨执行视角下 workspace 没有执行上下文,级联链路一律取任务自身的 executionId
const result = await fetchGetProjectTaskWorklogPage(options.projectId.value, task.executionId, task.id, {
pageNo: 1,
pageSize: -1
});
@@ -153,10 +153,10 @@ export function useTaskCompletionCascade(options: UseTaskCompletionCascadeOption
}
}
/** 拉父级下所有子任务;接口失败返回 null与"空列表"区分,由调用方降级处理) */
async function loadSiblings(parentTaskId: string): Promise<ProjectTask[] | null> {
/** 拉父级下所有子任务;接口失败返回 null与"空列表"区分,由调用方降级处理)。父子任务同执行executionId 取被完成任务自身的值 */
async function loadSiblings(parentTaskId: string, executionId: string): Promise<ProjectTask[] | null> {
try {
const result = await fetchGetProjectTaskPage(options.projectId.value, options.executionId.value, {
const result = await fetchGetProjectTaskPage(options.projectId.value, executionId, {
pageNo: 1,
pageSize: -1,
parentTaskId
@@ -171,9 +171,9 @@ export function useTaskCompletionCascade(options: UseTaskCompletionCascadeOption
}
/** 拉父任务详情;失败返回 null */
async function fetchTaskDetail(taskId: string): Promise<ProjectTask | null> {
async function fetchTaskDetail(taskId: string, executionId: string): Promise<ProjectTask | null> {
try {
const result = await fetchGetProjectTask(options.projectId.value, options.executionId.value, taskId);
const result = await fetchGetProjectTask(options.projectId.value, executionId, taskId);
if (result.error || !result.data) {
return null;
}

View File

@@ -6,6 +6,7 @@ import {
canDeleteTaskByIdentity,
canEditExecutionByIdentity,
canEditTaskByIdentity,
isExecutionMutationActor,
isMutable
} from './task-permission-rules';
@@ -54,13 +55,24 @@ export function useTaskPermissions() {
});
}
/** 协办人弹窗内的写操作(设为负责人 / 失效 / 新增协办人)与编辑同一身份口径:执行负责人或项目负责人 */
function canChangeExecutionOwner(execution: Api.Project.ProjectExecution): boolean {
return isMutable(execution) && hasPermission('project:execution:owner');
return (
isMutable(execution) &&
isExecutionMutationActor(execution, {
currentUserId: currentUserId.value,
projectManagerUserId: currentProjectManagerUserId.value
})
);
}
function canManageExecutionAssignee(execution: Api.Project.ProjectExecution): boolean {
return (
isMutable(execution) && (hasPermission('project:execution:assignee') || currentUserId.value === execution.ownerId)
isMutable(execution) &&
isExecutionMutationActor(execution, {
currentUserId: currentUserId.value,
projectManagerUserId: currentProjectManagerUserId.value
})
);
}

View File

@@ -539,7 +539,6 @@ async function handleOperateSubmit(payload: Api.Project.SaveProjectTaskParams) {
const cascade = useTaskCompletionCascade({
projectId: computed(() => props.projectId),
executionId,
openStatusActionDialog: async (task, action, fromCascade) => {
currentTask.value = task;
currentStatusAction.value = action;