export type Option = { label: string value: T } export const OWNERSHIP_TYPE = { major: '专业所', comprehensive: '综合所', subcontract: '专业分包' } as const export const CALCULATION_METHOD = { guidancePrice: '指导价法', contractPrice: '合同价法', virtualOutput: '虚拟产值法' } as const export const VIRTUAL_CALCULATION_METHOD = { guidancePrice: '指导单价法', guidanceTotalPrice: '指导总价法', workingDay: '工日法' } as const export const DESIGN_STAGE = { scheme: '方案', constructionDrawing: '施工图', schemeAndConstructionDrawing: '方案+施工图' } as const export const DESIGN_PART = { realEstate: '地上部分', underground: '地下部分' } as const export const PROJECT_TYPE = { building: '建筑工程', decoration: '精装工程', comprehensive: '综合工程', special: '专项设计', bim: 'BIM设计', other: '其他' } as const export const PROJECT_CATEGORY = { residential: '住宅', publicBuilding: '公建', industry: '工业', landscape: '园林景观', other: '其他' } as const export const PROJECT_STATUS = { inProgress: '进行中', completed: '完成', paused: '暂停', terminated: '中止' } as const export const EMPLOYEE_GENDER = { male: '男', female: '女' } as const export const EMPLOYEE_STATUS = { active: '在职', resigned: '离职', suspended: '停职' } as const const normalizeValue = (value: string | undefined, validValues: string[]) => value && validValues.includes(value) ? value : undefined const findLabel = (options: Array>, value?: T | string) => options.find((item) => String(item.value) === String(value))?.label export const normalizeOwnershipType = (value?: string) => normalizeValue(value, Object.values(OWNERSHIP_TYPE)) export const normalizeCalculationMethod = (value?: string) => normalizeValue(value, Object.values(CALCULATION_METHOD)) export const normalizeVirtualCalculationMethod = (value?: string) => normalizeValue(value, Object.values(VIRTUAL_CALCULATION_METHOD)) export const normalizeDesignStage = (value?: string) => normalizeValue(value, Object.values(DESIGN_STAGE)) export const normalizeDesignPart = (value?: string) => normalizeValue(value, Object.values(DESIGN_PART)) export const normalizeProjectType = (value?: string) => normalizeValue(value, Object.values(PROJECT_TYPE)) export const normalizeProjectCategory = (value?: string) => normalizeValue(value, Object.values(PROJECT_CATEGORY)) export const normalizeProjectStatus = (value?: string) => normalizeValue(value, Object.values(PROJECT_STATUS)) export const OWNERSHIP_TYPE_OPTIONS: Option[] = [ { label: OWNERSHIP_TYPE.major, value: OWNERSHIP_TYPE.major }, { label: OWNERSHIP_TYPE.comprehensive, value: OWNERSHIP_TYPE.comprehensive }, { label: OWNERSHIP_TYPE.subcontract, value: OWNERSHIP_TYPE.subcontract } ] export const CALCULATION_METHOD_OPTIONS: Option[] = [ { label: CALCULATION_METHOD.guidancePrice, value: CALCULATION_METHOD.guidancePrice }, { label: CALCULATION_METHOD.contractPrice, value: CALCULATION_METHOD.contractPrice }, { label: CALCULATION_METHOD.virtualOutput, value: CALCULATION_METHOD.virtualOutput } ] export const VIRTUAL_CALCULATION_METHOD_OPTIONS: Option[] = [ { label: VIRTUAL_CALCULATION_METHOD.guidancePrice, value: VIRTUAL_CALCULATION_METHOD.guidancePrice }, { label: VIRTUAL_CALCULATION_METHOD.guidanceTotalPrice, value: VIRTUAL_CALCULATION_METHOD.guidanceTotalPrice }, { label: VIRTUAL_CALCULATION_METHOD.workingDay, value: VIRTUAL_CALCULATION_METHOD.workingDay } ] export const DESIGN_STAGE_OPTIONS: Option[] = [ { label: DESIGN_STAGE.scheme, value: DESIGN_STAGE.scheme }, { label: DESIGN_STAGE.constructionDrawing, value: DESIGN_STAGE.constructionDrawing }, { label: DESIGN_STAGE.schemeAndConstructionDrawing, value: DESIGN_STAGE.schemeAndConstructionDrawing } ] export const DESIGN_PART_OPTIONS: Option[] = [ { label: DESIGN_PART.realEstate, value: DESIGN_PART.realEstate }, { label: DESIGN_PART.underground, value: DESIGN_PART.underground } ] export const CONTRACT_SIGN_OPTIONS: Option[] = [ { label: '已签约', value: true }, { label: '未签约', value: false } ] export const PROJECT_TYPE_OPTIONS: Option[] = [ { label: PROJECT_TYPE.building, value: PROJECT_TYPE.building }, { label: PROJECT_TYPE.decoration, value: PROJECT_TYPE.decoration }, { label: PROJECT_TYPE.comprehensive, value: PROJECT_TYPE.comprehensive }, { label: PROJECT_TYPE.special, value: PROJECT_TYPE.special }, { label: PROJECT_TYPE.bim, value: PROJECT_TYPE.bim }, { label: PROJECT_TYPE.other, value: PROJECT_TYPE.other } ] export const PROJECT_CATEGORY_OPTIONS: Option[] = [ { label: PROJECT_CATEGORY.residential, value: PROJECT_CATEGORY.residential }, { label: PROJECT_CATEGORY.publicBuilding, value: PROJECT_CATEGORY.publicBuilding }, { label: PROJECT_CATEGORY.industry, value: PROJECT_CATEGORY.industry }, { label: PROJECT_CATEGORY.landscape, value: PROJECT_CATEGORY.landscape }, { label: PROJECT_CATEGORY.other, value: PROJECT_CATEGORY.other } ] export const PROJECT_STATUS_OPTIONS: Option[] = [ { label: PROJECT_STATUS.inProgress, value: PROJECT_STATUS.inProgress }, { label: PROJECT_STATUS.completed, value: PROJECT_STATUS.completed }, { label: PROJECT_STATUS.paused, value: PROJECT_STATUS.paused }, { label: PROJECT_STATUS.terminated, value: PROJECT_STATUS.terminated } ] export const EMPLOYEE_GENDER_OPTIONS: Option[] = [ { label: EMPLOYEE_GENDER.male, value: EMPLOYEE_GENDER.male }, { label: EMPLOYEE_GENDER.female, value: EMPLOYEE_GENDER.female } ] export const EMPLOYEE_STATUS_OPTIONS: Option[] = [ { label: EMPLOYEE_STATUS.active, value: EMPLOYEE_STATUS.active }, { label: EMPLOYEE_STATUS.resigned, value: EMPLOYEE_STATUS.resigned }, { label: EMPLOYEE_STATUS.suspended, value: EMPLOYEE_STATUS.suspended } ] export const EMPLOYEE_JOB_TITLE = { junior: '初级', intermediate: '中级', viceSenior: '副高级', senior: '正高级' } as const export const EMPLOYEE_JOB_TITLE_OPTIONS: Option[] = [ { label: EMPLOYEE_JOB_TITLE.junior, value: EMPLOYEE_JOB_TITLE.junior }, { label: EMPLOYEE_JOB_TITLE.intermediate, value: EMPLOYEE_JOB_TITLE.intermediate }, { label: EMPLOYEE_JOB_TITLE.viceSenior, value: EMPLOYEE_JOB_TITLE.viceSenior }, { label: EMPLOYEE_JOB_TITLE.senior, value: EMPLOYEE_JOB_TITLE.senior } ] export const DEFAULT_INNOVATION_OUTPUT_RATE = 0.01 export const DEFAULT_WORKING_DAY_UNIT_PRICE = 1000 export const QUARTER_OPTIONS: Option[] = [ { label: '一季度', value: 1 }, { label: '二季度', value: 2 }, { label: '三季度', value: 3 }, { label: '四季度', value: 4 } ] export const OUTPUT_SPLIT_SPECIALTY_OPTIONS: Option[] = [ { label: '建筑', value: 'arch' }, { label: '装饰', value: 'decor' }, { label: '结构', value: 'struct' }, { label: '给排水', value: 'water' }, { label: '电气', value: 'elec' }, { label: '暖通', value: 'hvac' }, { label: '数字化设计', value: 'digital' } ] export const SPECIALTY_ROLE_OPTIONS: Option[] = [ { label: '专业负责人', value: 'director' }, { label: '校对', value: 'check' }, { label: '审核', value: 'review' }, { label: '审定', value: 'approve' }, { label: '设计', value: 'design' } ] export const isMajorOwnership = (value?: string) => normalizeOwnershipType(value) === OWNERSHIP_TYPE.major export const isComprehensiveOwnership = (value?: string) => normalizeOwnershipType(value) === OWNERSHIP_TYPE.comprehensive export const isSubcontractOwnership = (value?: string) => normalizeOwnershipType(value) === OWNERSHIP_TYPE.subcontract export const isGuidancePriceMethod = (value?: string) => normalizeCalculationMethod(value) === CALCULATION_METHOD.guidancePrice export const isContractPriceMethod = (value?: string) => normalizeCalculationMethod(value) === CALCULATION_METHOD.contractPrice export const isVirtualOutputMethod = (value?: string) => normalizeCalculationMethod(value) === CALCULATION_METHOD.virtualOutput export const isVirtualGuidanceMethod = (value?: string) => normalizeVirtualCalculationMethod(value) === VIRTUAL_CALCULATION_METHOD.guidancePrice export const isVirtualGuidanceTotalPriceMethod = (value?: string) => normalizeVirtualCalculationMethod(value) === VIRTUAL_CALCULATION_METHOD.guidanceTotalPrice export const isWorkingDayMethod = (value?: string) => normalizeVirtualCalculationMethod(value) === VIRTUAL_CALCULATION_METHOD.workingDay export const getOwnershipTypeLabel = (value?: string) => findLabel(OWNERSHIP_TYPE_OPTIONS, normalizeOwnershipType(value)) || '-' export const getCalculationMethodLabel = (value?: string) => findLabel(CALCULATION_METHOD_OPTIONS, normalizeCalculationMethod(value)) || '-' export const getProjectTypeLabel = (value?: string) => findLabel(PROJECT_TYPE_OPTIONS, normalizeProjectType(value)) || '-' export const getProjectCategoryLabel = (value?: string) => findLabel(PROJECT_CATEGORY_OPTIONS, normalizeProjectCategory(value)) || '-' export const getProjectStatusLabel = (value?: string) => findLabel(PROJECT_STATUS_OPTIONS, normalizeProjectStatus(value)) || '-' export const getDesignStageLabel = (value?: string) => findLabel(DESIGN_STAGE_OPTIONS, normalizeDesignStage(value)) || '-' export const getDesignPartLabel = (value?: string) => findLabel(DESIGN_PART_OPTIONS, normalizeDesignPart(value)) || '-' export const getVirtualCalculationMethodLabel = (value?: string) => findLabel(VIRTUAL_CALCULATION_METHOD_OPTIONS, normalizeVirtualCalculationMethod(value)) || '-' export const getCalculationRatioLabel = (ownershipType?: string) => { if (isComprehensiveOwnership(ownershipType)) { return '协作比例' } if (isSubcontractOwnership(ownershipType)) { return '分包比例' } return '比例' } export const getReviewOutsourceDefaultPercent = ( ownershipType?: string, reviewOutsourceFlag?: boolean ) => { if (!reviewOutsourceFlag) { return 0 } if (isMajorOwnership(ownershipType)) { return 6 } return 25 } export const getCalculationRatioDefaultPercent = (ownershipType?: string) => { if (isComprehensiveOwnership(ownershipType)) { return 8 } if (isSubcontractOwnership(ownershipType)) { return 4 } return undefined } export const toPercentValue = (value?: number | string | null, digits = 2) => { if (value === undefined || value === null || value === '') { return undefined } const numericValue = Number(value) if (Number.isNaN(numericValue)) { return undefined } return Number((numericValue * 100).toFixed(digits)) } export const fromPercentValue = (value?: number | string | null, digits = 4) => { if (value === undefined || value === null || value === '') { return undefined } const numericValue = Number(value) if (Number.isNaN(numericValue)) { return undefined } return Number((numericValue / 100).toFixed(digits)) } export const formatAmountText = (value?: number | string | null) => { if (value === undefined || value === null || value === '') { return '0.00' } const numericValue = Number(value) if (Number.isNaN(numericValue)) { return '0.00' } return numericValue.toFixed(2) } export const formatAreaText = (value?: number | string | null) => `${formatAmountText(value)} ㎡` export const formatPercentText = (value?: number | string | null, digits = 2) => { const percentValue = toPercentValue(value, digits) return `${(percentValue ?? 0).toFixed(digits)}%` }