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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentProject?.projectName || '专业所规划列表' }}
+
+
刷新
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.assessmentOutputValue) }}
+
+
+
+
+
+
+
+
+
+
+
{{ currentPlanning.planningContent }}
+
+ 年度:{{ formData.year || '-' }},考核产值:{{ formatAmountText(formData.assessmentOutputValue) }} 元
+
+
+
+
+
+ 编辑比例
+
+
+
+ 刷新结果
+
+
+
+
+
+ {{ formData.projectName || '-' }}
+ {{ formData.planningContent || '-' }}
+ {{ formData.projectManagerName || '-' }}
+ {{ formData.engineeringLeaderName || '-' }}
+
+
+ 项目层结果
+
+
+
+
+ {{ scope.row.percentText }}
+
+
+
+
+ {{ formatAmountText(scope.row.amount) }}
+
+
+
+
+ 专业层结果
+
+
+
+
+ {{ scope.row.percentText }}
+
+
+
+
+ {{ formatAmountText(scope.row.amount) }}
+
+
+
+
+ 年度分配信息
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+ {{ formatAmountText(item.amount) }}
+
+
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.quarterAmounts[Number(quarter.value)]) }}
+
+
+
+
+ {{ formatAmountText(scope.row.yearTotal) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.contractSignedFlag ? '已签约' : '未签约' }}
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.contractAmount) }}
+
+
+
+
+ {{ formatAreaText(scope.row.totalConstructionArea) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentProject?.projectName || '合约规划列表' }}
+
+
刷新
+
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.planningAmount) }}
+
+
+
+
+ {{ formatPercentText(scope.row.totalDistributionAmount) }}
+
+
+
+
+ {{ formatAmountText(scope.row.assessmentOutputValue) }}
+
+
+
+
+
+
+
+
+
+
+
{{ currentPlanning.planningContent }}
+
+ {{ currentPlanning.ownershipType }} / {{ currentPlanning.calculationMethod }}
+
+
+
+
+
+ 编辑测算参数
+
+
+
+ 编辑季度分配
+
+
+
+ 刷新结果
+
+
+
+
+
+
+ {{ formatAmountText(currentPlanning.planningAmount) }}
+
+
+ {{ formatPercentText(currentPlanning.managementFeeRate) }}
+
+
+ {{ formatAmountText(currentPlanning.managementFee) }}
+
+
+ {{ currentPlanning.implementationTeam || '-' }}
+
+
+ {{ currentPlanning.planningStartYear || '-' }}
+
+
+ {{ formatAreaText(currentPlanning.planningArea) }}
+
+
+ {{ formatAmountText(currentPlanning.contractUnitPrice) }}
+
+
+ {{ currentPlanning.designStage || '-' }}
+
+
+ {{ formatPercentText(currentPlanning.currentDesignStageRatio) }}
+
+
+ {{ currentPlanning.reviewOutsourceFlag ? '是' : '否' }}
+
+
+ {{ formatPercentText(currentPlanning.reviewOutsourceRatio) }}
+
+
+ {{ formatPercentText(currentPlanning.calculationRatio) }}
+
+
+ {{ currentPlanning.buildingOrUnitCount }}
+
+
+ {{ formatFactorText(currentPlanning.drawingSetFactor, 2) }}
+
+
+ {{ formatFactorText(currentPlanning.scaleFactor, 2) }}
+
+
+ {{ formatFactorText(currentPlanning.modificationFactor, 2) }}
+
+
+ {{ formatPercentText(currentPlanning.complexityFactor) }}
+
+
+ {{ formatAmountText(currentPlanning.internalGuidanceUnitPrice) }}
+
+
+ {{ currentPlanning.virtualCalculationMethod }}
+
+
+ {{ formatAmountText(currentPlanning.guidanceUnitPrice) }}
+
+
+ {{ formatAmountText(currentPlanning.guidanceTotalPrice) }}
+
+
+ {{ formatAmountText(currentPlanning.virtualTotalPrice) }}
+
+
+ {{ formatAmountText(currentPlanning.workingDayCount) }}
+
+
+ {{ formatAmountText(currentPlanning.workingDayUnitPrice) }}
+
+
+
+
+
+ {{ formatFactorText(currentPlanning.totalAdjustmentFactor) }}
+
+
+ {{ formatAreaText(currentPlanning.assessmentArea) }}
+
+
+ {{ formatAmountText(currentPlanning.virtualOutputValue) }}
+
+
+ {{ formatAmountText(currentPlanning.assessmentOutputValue) }}
+
+
+
+
+
+
+
+
季度分配
+
+ 总分配、已分配、待分配和提取进度备注属于合约规划的总体分配控制;季度分配表只展示年度、季度和分配比例明细。
+
+
+
+ 编辑季度分配
+
+
+
+
+
+
+
总分配
+
+ {{ formatPercentText(currentPlanning.totalDistributionAmount) }}
+
+
+
+
+
+
已分配
+
+ {{ formatPercentText(currentPlanning.allocatedAmount) }}
+
+
+
+
+
+
待分配
+
+ {{ formatPercentText(currentPlanning.pendingAmount) }}
+
+
+
+
+
+
提取进度备注
+
+ {{ currentPlanning.progressRemark || '-' }}
+
+
+
+
+
+
+
+
+
+
+
+ 分配比例:{{ formatQuarterRatio(scope.row, quarter.value) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.contractSignedFlag ? '已签订' : '未签订' }}
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.contractAmount) }}
+
+
+
+
+ {{ formatAmountText(scope.row.finalSettlementAmount) }}
+
+
+
+
+ {{ formatAmountText(scope.row.comprehensivePlanningAmount) }}
+
+
+
+
+ {{ formatAmountText(scope.row.subcontractPlanningAmount) }}
+
+
+
+
+ {{ formatAmountText(scope.row.majorOutputValue) }}
+
+
+
+
+ {{ formatPercentText(scope.row.expectedKValue) }}
+
+
+
+
+ {{ formatAmountText(scope.row.majorExpectedPerformance) }}
+
+
+
+
+
+ {{ formatAmountText(scope.row.profitLossValue) }}
+
+
+
+
+
+
+ {{ formatPercentText(scope.row.profitLossRate) }}
+
+
+
+
+
+
+
+
+
+
+
{{ currentProfit.projectName }}
+
+
+
+
+ 编辑盈亏参数
+
+
+
+ 刷新详情
+
+
+
+
+
+
+ {{ formatAmountText(currentProfit.contractAmount) }}
+
+
+ {{ formatAmountText(currentProfit.finalSettlementAmount) }}
+
+
+ {{ currentProfit.projectStartYear || '-' }}
+
+
+ {{ formatAmountText(currentProfit.comprehensivePlanningAmount) }}
+
+
+ {{ formatAmountText(currentProfit.subcontractPlanningAmount) }}
+
+
+ {{ formatAmountText(currentProfit.majorOutputValue) }}
+
+
+ {{ formatPercentText(currentProfit.expectedKValue) }}
+
+
+ {{ formatAmountText(currentProfit.majorExpectedPerformance) }}
+
+
+
+ {{ formatAmountText(currentProfit.profitLossValue) }}
+
+
+
+
+ {{ formatPercentText(currentProfit.profitLossRate) }}
+
+
+
+ {{ currentProfit.createTime || '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+ 新增项目
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.contractSignedFlag ? '已签订' : '未签订' }}
+
+
+
+
+
+ {{ formatAmountText(scope.row.contractAmount) }}
+
+
+
+
+ {{ formatAreaText(scope.row.totalConstructionArea) }}
+
+
+
+
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
{{ currentProject.projectName }}
+
+ 建设单位:{{ currentProject.constructionUnitName || '-' }},
+ 项目经理:{{ currentProject.projectManagerName || '-' }},
+ 工程负责人:{{ currentProject.engineeringPrincipalName || '-' }}
+
+
+
+
+
+ 新增合约规划
+
+
+
+ 刷新规划
+
+
+
+
+
+
+
+
+ {{ currentProject.projectName }}
+
+
+ {{ currentProject.projectType || '-' }}
+
+
+ {{ currentProject.contractSigningDate || '-' }}
+
+
+ {{ currentProject.contactName || '-' }}
+
+
+ {{ currentProject.contactPhone || '-' }}
+
+
+ {{ formatAmountText(currentProject.contractAmount) }}
+
+
+ {{ formatAreaText(currentProject.totalConstructionArea) }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.planningAmount) }}
+
+
+
+
+ {{ formatPercentText(scope.row.managementFeeRate) }}
+
+
+
+
+ {{ formatAmountText(scope.row.managementFee) }}
+
+
+
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentProject?.projectName || '专业所规划列表' }}
+
+
刷新
+
+
+
+
+
+
+ {{ formatAmountText(scope.row.assessmentOutputValue) }}
+
+
+
+
+
+
+
+
+
+
+
{{ currentPlanning.planningContent }}
+
+
+
+
+ 编辑人员分配
+
+
+
+ 刷新结果
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+ {{ item.value }}
+
+
+
+
+
+
+
+
+
+ {{ formatPercentText(scope.row.roleRatio) }}
+
+
+
+
+ {{ formatAmountText(scope.row.roleAmount) }}
+
+
+
+
+ {{ formatPercentText(getPersonTotalRatio(scope.row)) }}
+
+
+
+
+
+
+ {{ person.personName || '-' }}
+ {{ formatPercentText(person.personRatio) }}
+ {{ formatAmountText(person.personAmount) }} 元
+
+
+ 暂无人员
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+