From 8f9205a6a18473e4a8d673abfa059762300f13cc Mon Sep 17 00:00:00 2001 From: lzm <2316711944@qq.com> Date: Fri, 17 Apr 2026 18:17:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 4 +- README.md | 153 ++++ index.html | 4 +- src/api/tjt/outputSplit/index.ts | 56 ++ src/api/tjt/planning/index.ts | 92 ++ src/api/tjt/planningQuarter/index.ts | 43 + src/api/tjt/profit/index.ts | 33 + src/api/tjt/project/index.ts | 53 ++ src/api/tjt/specialtyRoleSplit/index.ts | 44 + src/locales/zh-CN.ts | 4 +- src/views/tjt/output-split/index.vue | 828 ++++++++++++++++++ src/views/tjt/output/PlanningOutputForm.vue | 600 +++++++++++++ .../tjt/output/QuarterDistributionForm.vue | 356 ++++++++ src/views/tjt/output/index.vue | 616 +++++++++++++ src/views/tjt/profit/index.vue | 399 +++++++++ src/views/tjt/project/PlanningForm.vue | 280 ++++++ src/views/tjt/project/ProjectForm.vue | 257 ++++++ src/views/tjt/project/index.vue | 414 +++++++++ src/views/tjt/shared/planning.ts | 154 ++++ src/views/tjt/staff-assignment/index.vue | 821 +++++++++++++++++ 20 files changed, 5205 insertions(+), 6 deletions(-) create mode 100644 src/api/tjt/outputSplit/index.ts create mode 100644 src/api/tjt/planning/index.ts create mode 100644 src/api/tjt/planningQuarter/index.ts create mode 100644 src/api/tjt/profit/index.ts create mode 100644 src/api/tjt/project/index.ts create mode 100644 src/api/tjt/specialtyRoleSplit/index.ts create mode 100644 src/views/tjt/output-split/index.vue create mode 100644 src/views/tjt/output/PlanningOutputForm.vue create mode 100644 src/views/tjt/output/QuarterDistributionForm.vue create mode 100644 src/views/tjt/output/index.vue create mode 100644 src/views/tjt/profit/index.vue create mode 100644 src/views/tjt/project/PlanningForm.vue create mode 100644 src/views/tjt/project/ProjectForm.vue create mode 100644 src/views/tjt/project/index.vue create mode 100644 src/views/tjt/shared/planning.ts create mode 100644 src/views/tjt/staff-assignment/index.vue diff --git a/.env b/.env index 10be622..87dd35d 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ # 标题 -VITE_APP_TITLE=abcd管理系统 +VITE_APP_TITLE=产值管理系统 # 项目本地运行端口号 VITE_PORT=80 @@ -34,4 +34,4 @@ VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883 # VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ== # 百度地图 -VITE_BAIDU_MAP_KEY = 'efHIw2qmH8RzHPxK0z0rbCgzDVLup9LD' \ No newline at end of file +VITE_BAIDU_MAP_KEY = 'efHIw2qmH8RzHPxK0z0rbCgzDVLup9LD' diff --git a/README.md b/README.md index e69de29..1a0f8d3 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,153 @@ +# tjt_czjs-ui + +`tjt_czjs-ui` 是特建投设计产值统计平台的管理后台前端工程。当前底座基于 `Lyzsys` 前端后台框架,整体属于芋道源码体系上的二次开发版本。 + +这个项目负责后台页面、路由、权限按钮、统一请求封装、表格与表单交互等前端能力。后续特建投页面 1 到页面 3,建议统一落在独立业务域 `tjt` 下。 + +## 技术栈 + +- Vue 3 + +- TypeScript + +- Vite + +- Element Plus + +- Pinia + +- Vue Router + +- Axios + +- Vue I18n + +- UnoCSS + +## 快速开始 + +环境要求: + +- Node.js `>= 16` + +- 推荐使用 `npm` 或 `pnpm` + +安装依赖: + +```bash +npm install +``` + +如果你本地长期使用 `pnpm`,也可以执行: + +```bash +pnpm install +``` + +本地启动: + +```bash +npm run dev +``` + +使用 `dev` 环境变量启动: + +```bash +npm run dev-server +``` + +构建: + +```bash +npm run build:dev +npm run build:test +npm run build:stage +npm run build:prod +``` + +类型检查与代码整理: + +```bash +npm run ts:check +npm run lint:eslint +npm run lint:format +npm run lint:style +``` + +## 配置说明 + +当前请求基地址由 `src/config/axios/config.ts` 中的 `VITE_BASE_URL + VITE_API_URL` 组合而成。 + +本地环境文件位于项目根目录的 `.env*` 文件中。启动前请确认前端请求地址已经指向可用的后端服务。 + +## 关键目录 + +- `src/api` + 业务接口封装目录,建议后续新增 `src/api/tjt/*` + +- `src/views` + 页面目录,建议后续新增 `src/views/tjt/*` + +- `src/config` + 全局配置目录,包含请求封装与主题等配置 + +- `src/router` + 路由配置目录 + +- `src/store` + Pinia 状态管理目录 + +- `src/main.ts` + 应用入口,统一接入 i18n、Pinia、Element Plus、路由与权限控制 + +## 特建投业务建议落位 + +建议按以下方式组织特建投页面: + +- 页面 1 项目概况 + 合同规划:`src/views/tjt/project` + +- 页面 2 单项目产值计算:`src/views/tjt/output` + +- 页面 3 项目盈亏表:`src/views/tjt/profit` + +与之对应的接口建议放在: + +- `src/api/tjt/project` + +- `src/api/tjt/planning` + +- `src/api/tjt/output` + +- `src/api/tjt/profit` + +## 推荐参考代码 + +如果要按现有规范快速开发新页面,建议优先参考: + +- `src/api/demo/project/index.ts` + +- `src/views/demo/project/index.vue` + +- `src/views/demo/project/ProjectForm.vue` + +- `src/config/axios/service.ts` + +- `src/main.ts` + +这套示例已经包含列表分页、搜索筛选、新增编辑删除、批量删除、Excel 导出和权限按钮控制。 + +## 与后端联调 + +后端默认本地 Profile 为 `local`,当前本地端口配置为 `48080`。 + +联调前建议确认接口地址、登录态、租户头和加密配置是否与当前环境一致。 + +## 文档入口 + +特建投业务分析与计划文档: + +- [`../doc/特建投业务分析与计划.md`](../doc/特建投业务分析与计划.md) + +主需求文档: + +- [`../tejiantou_ai_requirements_20260410_v2.md`](../tejiantou_ai_requirements_20260410_v2.md) diff --git a/index.html b/index.html index 14da164..5d9d876 100644 --- a/index.html +++ b/index.html @@ -7,11 +7,11 @@ %VITE_APP_TITLE% diff --git a/src/api/tjt/outputSplit/index.ts b/src/api/tjt/outputSplit/index.ts new file mode 100644 index 0000000..3e4dec6 --- /dev/null +++ b/src/api/tjt/outputSplit/index.ts @@ -0,0 +1,56 @@ +import request from '@/config/axios' + +export interface ProjectOutputSplitVO { + id?: number + projectId?: number + planningId: number + projectName?: string + planningContent?: string + year?: number + assessmentOutputValue?: number + projectManagerName?: string + projectManagerRatio: number + projectManagerAmount?: number + engineeringLeaderName?: string + engineeringLeaderRatio: number + engineeringLeaderAmount?: number + officeRatio: number + officeAmount?: number + archRatio: number + archAmount?: number + decorRatio: number + decorAmount?: number + structRatio: number + structAmount?: number + waterRatio: number + waterAmount?: number + elecRatio: number + elecAmount?: number + hvacRatio: number + hvacAmount?: number + digitalRatio: number + digitalAmount?: number +} + +export type ProjectOutputSplitSaveVO = Pick< + ProjectOutputSplitVO, + | 'planningId' + | 'projectManagerRatio' + | 'engineeringLeaderRatio' + | 'officeRatio' + | 'archRatio' + | 'decorRatio' + | 'structRatio' + | 'waterRatio' + | 'elecRatio' + | 'hvacRatio' + | 'digitalRatio' +> + +export const getProjectOutputSplitByPlanningId = (planningId: number) => { + return request.get({ url: '/tjt/output-split/get-by-planning', params: { planningId } }) +} + +export const saveProjectOutputSplit = (data: ProjectOutputSplitSaveVO) => { + return request.put({ url: '/tjt/output-split/save', data }) +} diff --git a/src/api/tjt/planning/index.ts b/src/api/tjt/planning/index.ts new file mode 100644 index 0000000..03bcf8a --- /dev/null +++ b/src/api/tjt/planning/index.ts @@ -0,0 +1,92 @@ +import request from '@/config/axios' + +export interface ProjectPlanningVO { + id?: number + projectId: number + ownershipType: string + calculationMethod: string + planningContent: string + planningAmount?: number + managementFeeRate?: number + managementFee?: number + implementationTeam?: string + planningStartYear?: number + planningArea?: number + designStage?: string + currentDesignStageRatio?: number + reviewOutsourceFlag?: boolean + reviewOutsourceRatio?: number + totalDistributionAmount?: number + progressRemark?: string + allocatedAmount?: number + pendingAmount?: number + buildingOrUnitCount?: number + drawingSetFactor?: number + scaleFactor?: number + modificationFactor?: number + complexityFactor?: number + internalGuidanceUnitPrice?: number + virtualCalculationMethod?: string + workingDayCount?: number + workingDayUnitPrice?: number + guidanceUnitPrice?: number + guidanceTotalPrice?: number + virtualTotalPrice?: number + calculationRatio?: number + contractUnitPrice?: number + totalAdjustmentFactor?: number + assessmentArea?: number + virtualOutputValue?: number + assessmentOutputValue?: number + createTime?: string +} + +export type ProjectPlanningSaveVO = Omit< + ProjectPlanningVO, + | 'allocatedAmount' + | 'pendingAmount' + | 'managementFee' + | 'contractUnitPrice' + | 'totalAdjustmentFactor' + | 'assessmentArea' + | 'virtualOutputValue' + | 'assessmentOutputValue' + | 'createTime' +> + +export interface ProjectPlanningPageReqVO extends PageParam { + projectId?: number + ownershipType?: string + calculationMethod?: string + planningContent?: string + planningStartYear?: number + createTime?: string[] +} + +export const getProjectPlanningPage = (params: ProjectPlanningPageReqVO) => { + return request.get({ url: '/tjt/planning/page', params }) +} + +export const getProjectPlanning = (id: number) => { + return request.get({ url: '/tjt/planning/get', params: { id } }) +} + +export const getProjectPlanningListByProjectId = (projectId: number) => { + return request.get({ url: '/tjt/planning/list-by-project', params: { projectId } }) +} + +export const createProjectPlanning = (data: ProjectPlanningSaveVO) => { + return request.post({ url: '/tjt/planning/create', data }) +} + +export const updateProjectPlanning = (data: ProjectPlanningSaveVO) => { + return request.put({ url: '/tjt/planning/update', data }) +} + +export const deleteProjectPlanning = (id: number) => { + return request.delete({ url: '/tjt/planning/delete', params: { id } }) +} + +export const deleteProjectPlanningList = (ids: number[]) => { + return request.delete({ url: '/tjt/planning/delete-list', params: { ids: ids.join(',') } }) +} diff --git a/src/api/tjt/planningQuarter/index.ts b/src/api/tjt/planningQuarter/index.ts new file mode 100644 index 0000000..7cdc217 --- /dev/null +++ b/src/api/tjt/planningQuarter/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface ProjectPlanningQuarterVO { + id?: number + planningId: number + distributionYear: number + quarterNo: number + distributionRatio?: number + distributionAmount?: number + createTime?: string +} + +export type ProjectPlanningQuarterSaveVO = Omit< + ProjectPlanningQuarterVO, + 'distributionAmount' | 'createTime' +> + +export const getProjectPlanningQuarter = (id: number) => { + return request.get({ url: '/tjt/planning-quarter/get', params: { id } }) +} + +export const getProjectPlanningQuarterListByPlanningId = (planningId: number) => { + return request.get({ url: '/tjt/planning-quarter/list-by-planning', params: { planningId } }) +} + +export const createProjectPlanningQuarter = (data: ProjectPlanningQuarterSaveVO) => { + return request.post({ url: '/tjt/planning-quarter/create', data }) +} + +export const updateProjectPlanningQuarter = (data: ProjectPlanningQuarterSaveVO) => { + return request.put({ url: '/tjt/planning-quarter/update', data }) +} + +export const deleteProjectPlanningQuarter = (id: number) => { + return request.delete({ url: '/tjt/planning-quarter/delete', params: { id } }) +} + +export const deleteProjectPlanningQuarterList = (ids: number[]) => { + return request.delete({ + url: '/tjt/planning-quarter/delete-list', + params: { ids: ids.join(',') } + }) +} diff --git a/src/api/tjt/profit/index.ts b/src/api/tjt/profit/index.ts new file mode 100644 index 0000000..df9493f --- /dev/null +++ b/src/api/tjt/profit/index.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +export interface ProjectProfitVO { + projectId: number + projectName: string + contractSignedFlag: boolean + contractAmount?: number + finalSettlementAmount?: number + comprehensivePlanningAmount?: number + subcontractPlanningAmount?: number + majorOutputValue?: number + expectedKValue?: number + majorExpectedPerformance?: number + profitLossValue?: number + profitLossRate?: number + projectStartYear?: number + createTime?: string +} + +export interface ProjectProfitPageReqVO extends PageParam { + projectName?: string + contractSignedFlag?: boolean + projectStartYear?: number + createTime?: string[] +} + +export const getProjectProfitPage = (params: ProjectProfitPageReqVO) => { + return request.get({ url: '/tjt/profit/page', params }) +} + +export const getProjectProfit = (projectId: number) => { + return request.get({ url: '/tjt/profit/get', params: { projectId } }) +} diff --git a/src/api/tjt/project/index.ts b/src/api/tjt/project/index.ts new file mode 100644 index 0000000..a50e8e3 --- /dev/null +++ b/src/api/tjt/project/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +export interface ProjectVO { + id?: number + projectName: string + contractSignedFlag: boolean + contractAmount?: number + totalConstructionArea?: number + constructionUnitName?: string + contactName?: string + contactPhone?: string + contractSigningDate?: string + projectManagerName?: string + engineeringPrincipalName?: string + projectType?: string + projectStartYear?: number + finalSettlementAmount?: number + expectedKValue?: number + createTime?: string +} + +export type ProjectSaveVO = Omit + +export interface ProjectPageReqVO extends PageParam { + projectName?: string + contractSignedFlag?: boolean + projectStartYear?: number + createTime?: string[] +} + +export const getProjectPage = (params: ProjectPageReqVO) => { + return request.get({ url: '/tjt/project/page', params }) +} + +export const getProject = (id: number) => { + return request.get({ url: '/tjt/project/get', params: { id } }) +} + +export const createProject = (data: ProjectSaveVO) => { + return request.post({ url: '/tjt/project/create', data }) +} + +export const updateProject = (data: ProjectSaveVO) => { + return request.put({ url: '/tjt/project/update', data }) +} + +export const deleteProject = (id: number) => { + return request.delete({ url: '/tjt/project/delete', params: { id } }) +} + +export const deleteProjectList = (ids: number[]) => { + return request.delete({ url: '/tjt/project/delete-list', params: { ids: ids.join(',') } }) +} diff --git a/src/api/tjt/specialtyRoleSplit/index.ts b/src/api/tjt/specialtyRoleSplit/index.ts new file mode 100644 index 0000000..fe38735 --- /dev/null +++ b/src/api/tjt/specialtyRoleSplit/index.ts @@ -0,0 +1,44 @@ +import request from '@/config/axios' + +export interface SpecialtyRolePersonVO { + personName?: string + personRatio?: number + personAmount?: number +} + +export interface SpecialtyRoleSplitVO { + id?: number + outputSplitId?: number + planningId?: number + projectName?: string + planningContent?: string + specialtyCode: string + specialtyName?: string + specialtyAmount?: number + roleCode: string + roleName?: string + roleRatio: number + roleAmount?: number + persons?: SpecialtyRolePersonVO[] + sortNo?: number +} + +export interface SpecialtyRoleSplitSaveItemVO { + specialtyCode: string + roleCode: string + roleRatio: number + persons: SpecialtyRolePersonVO[] +} + +export interface SpecialtyRoleSplitBatchSaveVO { + planningId: number + items: SpecialtyRoleSplitSaveItemVO[] +} + +export const getSpecialtyRoleSplitListByPlanningId = (planningId: number) => { + return request.get({ url: '/tjt/specialty-role-split/list-by-planning', params: { planningId } }) +} + +export const saveSpecialtyRoleSplitBatch = (data: SpecialtyRoleSplitBatchSaveVO) => { + return request.put({ url: '/tjt/specialty-role-split/save-batch', data }) +} diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index ac9d760..8383a69 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -115,7 +115,7 @@ export default { }, login: { welcome: '欢迎使用本系统', - message: '中后台管理系统', + message: '产值管理系统', tenantname: '租户名称', username: '用户名', password: '密码', @@ -374,7 +374,7 @@ export default { qrSignInFormTitle: '二维码登录', signUpFormTitle: '注册', forgetFormTitle: '重置密码', - signInTitle: '中后台管理系统', + signInTitle: '产值管理系统', signInDesc: '输入您的个人详细信息开始使用!', policy: '我同意xxx隐私政策', scanSign: `扫码后点击"确认",即可完成登录`, diff --git a/src/views/tjt/output-split/index.vue b/src/views/tjt/output-split/index.vue new file mode 100644 index 0000000..10fc5aa --- /dev/null +++ b/src/views/tjt/output-split/index.vue @@ -0,0 +1,828 @@ + + + diff --git a/src/views/tjt/output/PlanningOutputForm.vue b/src/views/tjt/output/PlanningOutputForm.vue new file mode 100644 index 0000000..6d5e561 --- /dev/null +++ b/src/views/tjt/output/PlanningOutputForm.vue @@ -0,0 +1,600 @@ + + + diff --git a/src/views/tjt/output/QuarterDistributionForm.vue b/src/views/tjt/output/QuarterDistributionForm.vue new file mode 100644 index 0000000..02a3a1d --- /dev/null +++ b/src/views/tjt/output/QuarterDistributionForm.vue @@ -0,0 +1,356 @@ + + + diff --git a/src/views/tjt/output/index.vue b/src/views/tjt/output/index.vue new file mode 100644 index 0000000..1ed900f --- /dev/null +++ b/src/views/tjt/output/index.vue @@ -0,0 +1,616 @@ + + + diff --git a/src/views/tjt/profit/index.vue b/src/views/tjt/profit/index.vue new file mode 100644 index 0000000..31942dc --- /dev/null +++ b/src/views/tjt/profit/index.vue @@ -0,0 +1,399 @@ + + + diff --git a/src/views/tjt/project/PlanningForm.vue b/src/views/tjt/project/PlanningForm.vue new file mode 100644 index 0000000..560d973 --- /dev/null +++ b/src/views/tjt/project/PlanningForm.vue @@ -0,0 +1,280 @@ + + + diff --git a/src/views/tjt/project/ProjectForm.vue b/src/views/tjt/project/ProjectForm.vue new file mode 100644 index 0000000..c1022c4 --- /dev/null +++ b/src/views/tjt/project/ProjectForm.vue @@ -0,0 +1,257 @@ + + + diff --git a/src/views/tjt/project/index.vue b/src/views/tjt/project/index.vue new file mode 100644 index 0000000..8bf15f4 --- /dev/null +++ b/src/views/tjt/project/index.vue @@ -0,0 +1,414 @@ + + + diff --git a/src/views/tjt/shared/planning.ts b/src/views/tjt/shared/planning.ts new file mode 100644 index 0000000..cb70f6c --- /dev/null +++ b/src/views/tjt/shared/planning.ts @@ -0,0 +1,154 @@ +export const OWNERSHIP_TYPE_OPTIONS = [ + { label: '专业所', value: '专业所' }, + { label: '综合所', value: '综合所' }, + { label: '专业分包', value: '专业分包' } +] + +export const CALCULATION_METHOD_OPTIONS = [ + { label: '指导价法', value: '指导价法' }, + { label: '合同价法', value: '合同价法' }, + { label: '虚拟产值法', value: '虚拟产值法' } +] + +export const VIRTUAL_CALCULATION_METHOD_OPTIONS = [ + { label: '指导单价法', value: '指导单价法' }, + { label: '虚拟总价法', value: '虚拟总价法' }, + { label: '工日法', value: '工日法' } +] + +export const DESIGN_STAGE_OPTIONS = [ + { label: '方案', value: '方案' }, + { label: '施工图', value: '施工图' }, + { label: '方案+施工图', value: '方案+施工图' } +] + +export const CONTRACT_SIGN_OPTIONS = [ + { label: '已签订', value: true }, + { label: '未签订', value: false } +] + +export const PROJECT_TYPE_OPTIONS = [ + { label: '建筑工程', value: '建筑工程' }, + { label: '精装工程', value: '精装工程' }, + { label: '综合工程', value: '综合工程' } +] + +export const QUARTER_OPTIONS = [ + { label: '一季度', value: 1 }, + { label: '二季度', value: 2 }, + { label: '三季度', value: 3 }, + { label: '四季度', value: 4 } +] + +export const OUTPUT_SPLIT_SPECIALTY_OPTIONS = [ + { 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 = [ + { label: '专业负责人', value: 'director' }, + { label: '校对', value: 'check' }, + { label: '审核', value: 'review' }, + { label: '审定', value: 'approve' }, + { label: '设计', value: 'design' } +] + +const OWNERSHIP_TYPE_MAJOR = '专业所' +const OWNERSHIP_TYPE_COMPREHENSIVE = '综合所' +const OWNERSHIP_TYPE_SUBCONTRACT = '专业分包' +const CALCULATION_METHOD_GUIDANCE_PRICE = '指导价法' +const CALCULATION_METHOD_CONTRACT_PRICE = '合同价法' +const CALCULATION_METHOD_VIRTUAL_OUTPUT = '虚拟产值法' +const VIRTUAL_METHOD_GUIDANCE_PRICE = '指导单价法' +const VIRTUAL_METHOD_VIRTUAL_TOTAL_PRICE = '虚拟总价法' +const VIRTUAL_METHOD_WORKING_DAY = '工日法' + +export const isMajorOwnership = (value?: string) => value === OWNERSHIP_TYPE_MAJOR +export const isComprehensiveOwnership = (value?: string) => value === OWNERSHIP_TYPE_COMPREHENSIVE +export const isSubcontractOwnership = (value?: string) => value === OWNERSHIP_TYPE_SUBCONTRACT + +export const isGuidancePriceMethod = (value?: string) => value === CALCULATION_METHOD_GUIDANCE_PRICE +export const isContractPriceMethod = (value?: string) => value === CALCULATION_METHOD_CONTRACT_PRICE +export const isVirtualOutputMethod = (value?: string) => value === CALCULATION_METHOD_VIRTUAL_OUTPUT + +export const isVirtualGuidanceMethod = (value?: string) => value === VIRTUAL_METHOD_GUIDANCE_PRICE +export const isVirtualTotalPriceMethod = (value?: string) => value === VIRTUAL_METHOD_VIRTUAL_TOTAL_PRICE +export const isWorkingDayMethod = (value?: string) => value === VIRTUAL_METHOD_WORKING_DAY + +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)}%` +} diff --git a/src/views/tjt/staff-assignment/index.vue b/src/views/tjt/staff-assignment/index.vue new file mode 100644 index 0000000..0ffd1d5 --- /dev/null +++ b/src/views/tjt/staff-assignment/index.vue @@ -0,0 +1,821 @@ + + + + +