feat(新增需求评审功能): 新增需求评审功能。

feat(动态切换对象域下的对象):对象域下的对象可以动态切换。
fix(产品需求、项目需求): 按照会议意见修改诸多细节。
fix(产品对象域的概览界面): 把假数据换成真实的需求统计数据。
This commit is contained in:
dk
2026-05-22 14:05:25 +08:00
parent ab882e085b
commit 13b74cfe97
36 changed files with 3764 additions and 771 deletions

View File

@@ -47,8 +47,6 @@ declare namespace Api {
id: number;
/** dict label */
label: string;
/** sign */
sign?: string | null;
/** dict value */
value: string;
/** dict type code */
@@ -69,8 +67,6 @@ declare namespace Api {
interface FrontendDictData {
/** dict label */
label: string;
/** sign */
sign?: string | null;
/** dict value */
value: string;
/** display order */
@@ -92,7 +88,7 @@ declare namespace Api {
type DictDataSearchParams = CommonType.RecordNullable<Pick<DictData, 'label' | 'dictType' | 'status'>> & PageParams;
/** dict data save params */
type SaveDictDataParams = Pick<DictData, 'label' | 'sign' | 'value' | 'dictType' | 'sort' | 'status'> & {
type SaveDictDataParams = Pick<DictData, 'label' | 'value' | 'dictType' | 'sort' | 'status'> & {
remark?: string | null;
};
}

View File

@@ -256,15 +256,29 @@ declare namespace Api {
// ========== 产品需求相关类型定义 ==========
/** 需求状态编码 */
type RequirementStatusCode =
| 'pending_confirm'
| 'pending_claim'
| 'pending_review'
| 'pending_dispatch'
| 'reviewed'
| 'review_rejected'
| 'implementing'
| 'accepted'
| 'closed'
| 'rejected'
| 'cancelled';
/** 需求状态动作编码 */
type RequirementStatusActionCode =
| 'claim_to_review'
| 'claim_to_dispatch'
| 'pass_review'
| 'reject_review'
| 'dispatch'
| 'cancel'
| 'accept'
| 'close'
| 'reject';
/** 需求来源类型 */
type RequirementSourceType = 'manual' | 'work_order';
@@ -333,8 +347,6 @@ declare namespace Api {
updateTime: string;
/** 子需求列表(树形结构) */
children?: Requirement[];
/** 是否为终态 */
terminal?: boolean;
}
// ========== 需求模块实体 ==========
@@ -371,27 +383,18 @@ declare namespace Api {
initialFlag: boolean;
/** 是否终态 */
terminalFlag: boolean;
/** 是否允许编辑 */
allowEdit: boolean;
}
// ========== 需求生命周期 ==========
interface RequirementLifecycleAction {
actionCode: string;
actionCode: RequirementStatusActionCode;
actionName: string;
toStatusCode: string;
toStatusName: string;
needReason: boolean;
}
interface RequirementLifecycleInfo {
statusCode: RequirementStatusCode;
statusName?: string | null;
lastStatusReason?: string | null;
terminal: boolean;
allowEdit: boolean;
availableActions: RequirementLifecycleAction[];
}
interface RequirementBatchReqVO {
productId: string;
requirementIds: string[];
@@ -407,6 +410,78 @@ declare namespace Api {
hasDispatched: boolean;
}
type ProductRequirementDashboardRecentChangeActionType = 'create' | 'delete' | 'status_terminal';
interface ProductRequirementDashboardSummary {
/** 当前产品下所有未删除需求数,包括根需求和子需求 */
total: number;
/** 待认领、待评审、待指派的需求数 */
todo: number;
/** 待认领需求数 */
pendingClaim: number;
/** 待评审需求数 */
pendingReview: number;
/** 待指派需求数 */
pendingDispatch: number;
/** 已验收或已关闭需求数 */
completed: number;
/** 完成率0-100 */
completionRate: number;
/** P0/P1 且待处理的需求数 */
highPriorityTodo: number;
}
interface ProductRequirementDashboardRecentChange {
id: string;
requirementId?: string | null;
title: string;
actionType: ProductRequirementDashboardRecentChangeActionType;
actionLabel: string;
content: string;
occurredAt: string;
operatorUserId?: string | null;
operatorName?: string | null;
}
interface ProductRequirementDashboard {
summary: ProductRequirementDashboardSummary;
recentChanges: ProductRequirementDashboardRecentChange[];
}
type RequirementReviewConclusion = 0 | 1;
interface RequirementReviewAttendeeItem {
userId: string;
nickname: string;
}
interface RequirementReview {
id: string;
objectType: 'product_requirement';
requirementId: string;
operatorId: string;
conclusion: RequirementReviewConclusion;
reviewContent?: string | null;
requirementEstimatedHours?: number | string | null;
attendees?: RequirementReviewAttendeeItem[];
attachments?: Api.Project.AttachmentItem[] | null;
reviewTime?: string | null;
createTime?: string;
updateTime?: string;
}
interface RequirementReviewSubmitParams {
productId: string;
requirementId: string;
operatorId: string;
conclusion: RequirementReviewConclusion;
reviewContent?: string | null;
requirementEstimatedHours?: number | string | null;
attendees?: RequirementReviewAttendeeItem[];
attachments?: Api.Project.AttachmentItem[] | null;
reviewTime?: string | null;
}
// ========== 请求参数类型 ==========
/** 需求分页查询参数 */

View File

@@ -713,14 +713,28 @@ declare namespace Api {
// ========== 项目需求相关类型定义 ==========
/** 项目需求状态编码 */
type ProjectRequirementStatusCode =
| 'pending_confirm'
| 'pending_claim'
| 'pending_review'
| 'reviewed'
| 'review_rejected'
| 'implementing'
| 'accepted'
| 'closed'
| 'rejected'
| 'cancelled';
/** 项目需求状态动作编码 */
type ProjectRequirementStatusActionCode =
| 'claim_to_review'
| 'claim_to_implement'
| 'pass_review'
| 'reject_review'
| 'start_implement'
| 'accept'
| 'cancel'
| 'close'
| 'reject';
/** 项目需求来源类型 */
type ProjectRequirementSourceType = 'manual' | 'work_order' | 'product_requirement';
@@ -785,8 +799,6 @@ declare namespace Api {
updateTime: string;
/** 子需求列表 */
children?: ProjectRequirement[];
/** 是否终态 */
terminal?: boolean;
}
interface ProjectRequirementModule {
@@ -819,25 +831,18 @@ declare namespace Api {
initialFlag: boolean;
/** 是否终态 */
terminalFlag: boolean;
/** 是否允许编辑 */
allowEdit: boolean;
}
interface ProjectRequirementLifecycleAction {
actionCode: string;
actionCode: ProjectRequirementStatusActionCode;
actionName: string;
toStatusCode: string;
toStatusName: string;
needReason: boolean;
}
interface ProjectRequirementLifecycleInfo {
statusCode: ProjectRequirementStatusCode;
statusName?: string | null;
lastStatusReason?: string | null;
terminal: boolean;
allowEdit: boolean;
availableActions: ProjectRequirementLifecycleAction[];
}
interface ProjectRequirementBatchReqVO {
projectId: string;
requirementIds: string[];
@@ -848,6 +853,40 @@ declare namespace Api {
transitions: ProjectRequirementLifecycleAction[];
}
type ProjectRequirementReviewConclusion = 0 | 1;
interface ProjectRequirementReviewAttendeeItem {
userId: string;
nickname: string;
}
interface ProjectRequirementReview {
id: string;
objectType: 'project_requirement';
requirementId: string;
operatorId: string;
conclusion: ProjectRequirementReviewConclusion;
reviewContent?: string | null;
requirementEstimatedHours?: number | string | null;
attendees?: ProjectRequirementReviewAttendeeItem[];
attachments?: AttachmentItem[] | null;
reviewTime?: string | null;
createTime?: string;
updateTime?: string;
}
interface ProjectRequirementReviewSubmitParams {
projectId: string;
requirementId: string;
operatorId: string;
conclusion: ProjectRequirementReviewConclusion;
reviewContent?: string | null;
requirementEstimatedHours?: number | string | null;
attendees?: ProjectRequirementReviewAttendeeItem[];
attachments?: AttachmentItem[] | null;
reviewTime?: string | null;
}
/** 项目需求分页查询参数 */
type ProjectRequirementSearchParams = CommonType.RecordNullable<
Pick<PageParams, 'pageNo' | 'pageSize'> &

View File

@@ -9,6 +9,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
AppProvider: typeof import('./../components/common/app-provider.vue')['default']
AttendeeUserPicker: typeof import('./../components/custom/attendee-user-picker.vue')['default']
BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
BusinessAttachmentUploader: typeof import('./../components/custom/business-attachment-uploader.vue')['default']
BusinessDateRangePicker: typeof import('./../components/custom/business-date-range-picker.vue')['default']
@@ -100,10 +101,14 @@ declare module 'vue' {
IconCarbonStop: typeof import('~icons/carbon/stop')['default']
'IconCharm:download': typeof import('~icons/charm/download')['default']
'IconEp:arrowDown': typeof import('~icons/ep/arrow-down')['default']
'IconEp:arrowRight': typeof import('~icons/ep/arrow-right')['default']
'IconEp:box': typeof import('~icons/ep/box')['default']
'IconEp:check': typeof import('~icons/ep/check')['default']
'IconEp:files': typeof import('~icons/ep/files')['default']
'IconEp:folder': typeof import('~icons/ep/folder')['default']
'IconEp:infoFilled': typeof import('~icons/ep/info-filled')['default']
'IconEp:plus': typeof import('~icons/ep/plus')['default']
'IconEp:sort': typeof import('~icons/ep/sort')['default']
IconEpRemoveFilled: typeof import('~icons/ep/remove-filled')['default']
IconEpSuccessFilled: typeof import('~icons/ep/success-filled')['default']
'IconF7:circleFill': typeof import('~icons/f7/circle-fill')['default']