初步完成进度管理和人员组织
This commit is contained in:
parent
a3f30bf2d0
commit
ee5534d052
|
@ -0,0 +1,54 @@
|
|||
import type * as T from './type'
|
||||
import http from '@/utils/http'
|
||||
|
||||
const BASE_URL = '/project/personnel-organization'
|
||||
|
||||
/** @desc 获取项目列表 */
|
||||
export function getProjectList(query?: T.ProjectQuery) {
|
||||
return http.get<PageRes<T.ProjectResp[]>>('/project/list', query)
|
||||
}
|
||||
|
||||
/** @desc 获取项目人员组织信息 */
|
||||
export function getPersonnelOrganization(projectId: string | number) {
|
||||
return http.get<T.PersonnelOrganizationResp>(`${BASE_URL}/${projectId}`)
|
||||
}
|
||||
|
||||
/** @desc 获取工种列表 */
|
||||
export function getWorkTypeList() {
|
||||
return http.get<T.WorkTypeResp[]>('/work-type/list')
|
||||
}
|
||||
|
||||
/** @desc 获取施工人员列表 */
|
||||
export function getConstructorList(query: T.ConstructorQuery) {
|
||||
return http.get<PageRes<T.ConstructorResp[]>>('/constructor/list', query)
|
||||
}
|
||||
|
||||
/** @desc 获取施工人员技能证书 */
|
||||
export function getConstructorCertifications(constructorId: string | number) {
|
||||
return http.get<T.CertificationResp[]>(`/constructor/${constructorId}/certifications`)
|
||||
}
|
||||
|
||||
/** @desc 分配施工人员到项目 */
|
||||
export function assignConstructorToProject(data: T.AssignConstructorReq) {
|
||||
return http.post(`${BASE_URL}/assign`, data)
|
||||
}
|
||||
|
||||
/** @desc 移除项目施工人员 */
|
||||
export function removeConstructorFromProject(data: T.RemoveConstructorReq) {
|
||||
return http.delete(`${BASE_URL}/remove`, data)
|
||||
}
|
||||
|
||||
/** @desc 更新施工人员分配信息 */
|
||||
export function updateConstructorAssignment(data: T.UpdateAssignmentReq) {
|
||||
return http.put(`${BASE_URL}/update`, data)
|
||||
}
|
||||
|
||||
/** @desc 获取项目人员统计 */
|
||||
export function getPersonnelStats(projectId: string | number) {
|
||||
return http.get<T.PersonnelStatsResp>(`${BASE_URL}/${projectId}/stats`)
|
||||
}
|
||||
|
||||
/** @desc 导出项目人员组织 */
|
||||
export function exportPersonnelOrganization(projectId: string | number) {
|
||||
return http.download(`${BASE_URL}/${projectId}/export`)
|
||||
}
|
|
@ -327,7 +327,137 @@ export interface UpdateRequirementStatusForm {
|
|||
status: 'pending' | 'recruiting' | 'completed'
|
||||
}
|
||||
|
||||
// ==================== 人员组织相关类型 ====================
|
||||
|
||||
/** 工种响应 */
|
||||
export interface WorkTypeResp {
|
||||
id: string | number
|
||||
name: string
|
||||
code: string
|
||||
description?: string
|
||||
requiredCertifications?: string[]
|
||||
sort?: number
|
||||
}
|
||||
|
||||
/** 施工人员响应 */
|
||||
export interface ConstructorResp {
|
||||
id: string | number
|
||||
name: string
|
||||
phone: string
|
||||
email?: string
|
||||
avatar?: string
|
||||
workTypes: string[] // 工种列表
|
||||
certifications: CertificationResp[]
|
||||
experience: number // 工作经验(年)
|
||||
status: 'ACTIVE' | 'INACTIVE' | 'BUSY'
|
||||
rating: number // 评分
|
||||
joinDate: string
|
||||
remark?: string
|
||||
}
|
||||
|
||||
/** 证书响应 */
|
||||
export interface CertificationResp {
|
||||
id: string | number
|
||||
name: string
|
||||
type: string
|
||||
code: string
|
||||
issueDate: string
|
||||
expiryDate: string
|
||||
issuingAuthority: string
|
||||
status: 'VALID' | 'EXPIRED' | 'EXPIRING_SOON'
|
||||
imageUrl?: string
|
||||
}
|
||||
|
||||
/** 施工人员查询参数 */
|
||||
export interface ConstructorQuery extends PageQuery {
|
||||
name?: string
|
||||
workType?: string
|
||||
status?: string
|
||||
hasCertification?: boolean
|
||||
experienceMin?: number
|
||||
experienceMax?: number
|
||||
}
|
||||
|
||||
/** 人员组织响应 */
|
||||
export interface PersonnelOrganizationResp {
|
||||
projectId: string | number
|
||||
projectName: string
|
||||
workTypeAssignments: WorkTypeAssignmentResp[]
|
||||
totalPersonnel: number
|
||||
assignedPersonnel: number
|
||||
availablePersonnel: number
|
||||
}
|
||||
|
||||
/** 工种分配响应 */
|
||||
export interface WorkTypeAssignmentResp {
|
||||
workTypeId: string | number
|
||||
workTypeName: string
|
||||
workTypeCode: string
|
||||
requiredCount: number
|
||||
assignedCount: number
|
||||
constructors: ConstructorAssignmentResp[]
|
||||
}
|
||||
|
||||
/** 施工人员分配响应 */
|
||||
export interface ConstructorAssignmentResp {
|
||||
constructorId: string | number
|
||||
constructorName: string
|
||||
phone: string
|
||||
avatar?: string
|
||||
workTypes: string[]
|
||||
certifications: CertificationResp[]
|
||||
experience: number
|
||||
rating: number
|
||||
assignmentDate: string
|
||||
status: 'ASSIGNED' | 'WORKING' | 'COMPLETED'
|
||||
remark?: string
|
||||
}
|
||||
|
||||
/** 分配施工人员请求 */
|
||||
export interface AssignConstructorReq {
|
||||
projectId: string | number
|
||||
workTypeId: string | number
|
||||
constructorIds: (string | number)[]
|
||||
assignmentDate?: string
|
||||
remark?: string
|
||||
}
|
||||
|
||||
/** 移除施工人员请求 */
|
||||
export interface RemoveConstructorReq {
|
||||
projectId: string | number
|
||||
constructorIds: (string | number)[]
|
||||
reason?: string
|
||||
}
|
||||
|
||||
/** 更新分配信息请求 */
|
||||
export interface UpdateAssignmentReq {
|
||||
projectId: string | number
|
||||
constructorId: string | number
|
||||
workTypeId?: string | number
|
||||
status?: string
|
||||
remark?: string
|
||||
}
|
||||
|
||||
/** 人员统计响应 */
|
||||
export interface PersonnelStatsResp {
|
||||
totalPersonnel: number
|
||||
assignedPersonnel: number
|
||||
availablePersonnel: number
|
||||
workTypeStats: {
|
||||
workTypeName: string
|
||||
requiredCount: number
|
||||
assignedCount: number
|
||||
shortageCount: number
|
||||
}[]
|
||||
certificationStats: {
|
||||
certificationType: string
|
||||
count: number
|
||||
}[]
|
||||
experienceStats: {
|
||||
range: string
|
||||
count: number
|
||||
}[]
|
||||
}
|
||||
|
||||
/** 分页查询基础参数 */
|
||||
export interface PageQuery {
|
||||
|
|
|
@ -804,6 +804,16 @@ export const systemRoutes: RouteRecordRaw[] = [
|
|||
hidden: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/project-management/projects/personnel-organization',
|
||||
name: 'PersonnelOrganization',
|
||||
component: () => import('@/views/project-management/projects/personnel-organization/index.vue'),
|
||||
meta: {
|
||||
title: '人员组织',
|
||||
icon: 'user-group',
|
||||
hidden: false,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: '/project-management/projects/device',
|
||||
|
|
|
@ -7,7 +7,70 @@ export {}
|
|||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ApprovalAssistant: typeof import('./../components/ApprovalAssistant/index.vue')['default']
|
||||
ApprovalMessageItem: typeof import('./../components/NotificationCenter/ApprovalMessageItem.vue')['default']
|
||||
Avatar: typeof import('./../components/Avatar/index.vue')['default']
|
||||
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
|
||||
CellCopy: typeof import('./../components/CellCopy/index.vue')['default']
|
||||
Chart: typeof import('./../components/Chart/index.vue')['default']
|
||||
CircularProgress: typeof import('./../components/CircularProgress/index.vue')['default']
|
||||
ColumnSetting: typeof import('./../components/GiTable/src/components/ColumnSetting.vue')['default']
|
||||
CronForm: typeof import('./../components/GenCron/CronForm/index.vue')['default']
|
||||
CronModal: typeof import('./../components/GenCron/CronModal/index.vue')['default']
|
||||
DateRangePicker: typeof import('./../components/DateRangePicker/index.vue')['default']
|
||||
DayForm: typeof import('./../components/GenCron/CronForm/component/day-form.vue')['default']
|
||||
FilePreview: typeof import('./../components/FilePreview/index.vue')['default']
|
||||
GiCellAvatar: typeof import('./../components/GiCell/GiCellAvatar.vue')['default']
|
||||
GiCellGender: typeof import('./../components/GiCell/GiCellGender.vue')['default']
|
||||
GiCellStatus: typeof import('./../components/GiCell/GiCellStatus.vue')['default']
|
||||
GiCellTag: typeof import('./../components/GiCell/GiCellTag.vue')['default']
|
||||
GiCellTags: typeof import('./../components/GiCell/GiCellTags.vue')['default']
|
||||
GiCodeView: typeof import('./../components/GiCodeView/index.vue')['default']
|
||||
GiDot: typeof import('./../components/GiDot/index.tsx')['default']
|
||||
GiEditTable: typeof import('./../components/GiEditTable/GiEditTable.vue')['default']
|
||||
GiFooter: typeof import('./../components/GiFooter/index.vue')['default']
|
||||
GiForm: typeof import('./../components/GiForm/src/GiForm.vue')['default']
|
||||
GiIconBox: typeof import('./../components/GiIconBox/index.vue')['default']
|
||||
GiIconSelector: typeof import('./../components/GiIconSelector/index.vue')['default']
|
||||
GiIframe: typeof import('./../components/GiIframe/index.vue')['default']
|
||||
GiOption: typeof import('./../components/GiOption/index.vue')['default']
|
||||
GiOptionItem: typeof import('./../components/GiOptionItem/index.vue')['default']
|
||||
GiPageLayout: typeof import('./../components/GiPageLayout/index.vue')['default']
|
||||
GiSpace: typeof import('./../components/GiSpace/index.vue')['default']
|
||||
GiSplitButton: typeof import('./../components/GiSplitButton/index.vue')['default']
|
||||
GiSplitPane: typeof import('./../components/GiSplitPane/index.vue')['default']
|
||||
GiSplitPaneFlexibleBox: typeof import('./../components/GiSplitPane/components/GiSplitPaneFlexibleBox.vue')['default']
|
||||
GiSvgIcon: typeof import('./../components/GiSvgIcon/index.vue')['default']
|
||||
GiTable: typeof import('./../components/GiTable/src/GiTable.vue')['default']
|
||||
GiTag: typeof import('./../components/GiTag/index.tsx')['default']
|
||||
GiThemeBtn: typeof import('./../components/GiThemeBtn/index.vue')['default']
|
||||
HourForm: typeof import('./../components/GenCron/CronForm/component/hour-form.vue')['default']
|
||||
Icon403: typeof import('./../components/icons/Icon403.vue')['default']
|
||||
Icon404: typeof import('./../components/icons/Icon404.vue')['default']
|
||||
Icon500: typeof import('./../components/icons/Icon500.vue')['default']
|
||||
IconBorders: typeof import('./../components/icons/IconBorders.vue')['default']
|
||||
IconTableSize: typeof import('./../components/icons/IconTableSize.vue')['default']
|
||||
IconTreeAdd: typeof import('./../components/icons/IconTreeAdd.vue')['default']
|
||||
IconTreeReduce: typeof import('./../components/icons/IconTreeReduce.vue')['default']
|
||||
ImageImport: typeof import('./../components/ImageImport/index.vue')['default']
|
||||
ImageImportWizard: typeof import('./../components/ImageImportWizard/index.vue')['default']
|
||||
IndustrialImageList: typeof import('./../components/IndustrialImageList/index.vue')['default']
|
||||
JsonPretty: typeof import('./../components/JsonPretty/index.vue')['default']
|
||||
MinuteForm: typeof import('./../components/GenCron/CronForm/component/minute-form.vue')['default']
|
||||
MonthForm: typeof import('./../components/GenCron/CronForm/component/month-form.vue')['default']
|
||||
NotificationCenter: typeof import('./../components/NotificationCenter/index.vue')['default']
|
||||
ParentView: typeof import('./../components/ParentView/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SecondForm: typeof import('./../components/GenCron/CronForm/component/second-form.vue')['default']
|
||||
SplitPanel: typeof import('./../components/SplitPanel/index.vue')['default']
|
||||
TextCopy: typeof import('./../components/TextCopy/index.vue')['default']
|
||||
TurbineGrid: typeof import('./../components/TurbineGrid/index.vue')['default']
|
||||
UserSelect: typeof import('./../components/UserSelect/index.vue')['default']
|
||||
Verify: typeof import('./../components/Verify/index.vue')['default']
|
||||
VerifyPoints: typeof import('./../components/Verify/Verify/VerifyPoints.vue')['default']
|
||||
VerifySlide: typeof import('./../components/Verify/Verify/VerifySlide.vue')['default']
|
||||
WeekForm: typeof import('./../components/GenCron/CronForm/component/week-form.vue')['default']
|
||||
YearForm: typeof import('./../components/GenCron/CronForm/component/year-form.vue')['default']
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue