From b028f2a7bd0db8fe005b356ca0fb3d37474ac297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=BE=B7=E8=B6=85?= <13143889+he-dechao@user.noreply.gitee.com> Date: Wed, 23 Jul 2025 22:46:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.production | 4 +- public/static/images/wind-turbine-icon.svg | 20 + src/apis/attendance-record/index.ts | 13 + src/apis/attendance-record/type.ts | 15 + src/apis/performance-setting/index.ts | 40 ++ src/apis/performance-setting/type.ts | 39 ++ src/components/TurbineGrid/index.vue | 234 ++++++++ src/router/route.ts | 4 +- src/types/auto-imports.d.ts | 3 +- src/types/components.d.ts | 1 + .../default/error/components/ErrorPage.vue | 10 +- src/views/hr/attendance-record/index.vue | 73 +++ src/views/login/components/account/index.vue | 13 +- src/views/performance/my.vue | 34 +- .../setting/components/DimensionDrawer.vue | 58 ++ .../setting/components/RuleDrawer.vue | 86 +++ .../setting/components/RuleList.vue | 64 +++ src/views/performance/setting/index.vue | 67 +++ src/views/project/TurbineCard.vue | 88 +++ src/views/project/TurbineGrid.vue | 41 ++ src/views/project/detail/index.vue | 125 ++--- src/views/project/icons/WindTurbine.vue | 358 +++++++++++++ src/views/project/index.vue | 502 ++++++++---------- 23 files changed, 1510 insertions(+), 382 deletions(-) create mode 100644 public/static/images/wind-turbine-icon.svg create mode 100644 src/apis/attendance-record/index.ts create mode 100644 src/apis/attendance-record/type.ts create mode 100644 src/apis/performance-setting/index.ts create mode 100644 src/apis/performance-setting/type.ts create mode 100644 src/components/TurbineGrid/index.vue create mode 100644 src/views/hr/attendance-record/index.vue create mode 100644 src/views/performance/setting/components/DimensionDrawer.vue create mode 100644 src/views/performance/setting/components/RuleDrawer.vue create mode 100644 src/views/performance/setting/components/RuleList.vue create mode 100644 src/views/performance/setting/index.vue create mode 100644 src/views/project/TurbineCard.vue create mode 100644 src/views/project/TurbineGrid.vue create mode 100644 src/views/project/icons/WindTurbine.vue diff --git a/.env.production b/.env.production index debf235..8700360 100644 --- a/.env.production +++ b/.env.production @@ -4,8 +4,8 @@ VITE_BUILD_MOCK = false # 接口地址 -VITE_API_BASE_URL = 'https://api.continew.top' -VITE_API_WS_URL = 'wss://api.continew.top' +VITE_API_BASE_URL = 'http://pms.dtyx.net:9158/' +VITE_API_WS_URL = 'ws://localhost:8000' # 地址前缀 VITE_BASE = '/' diff --git a/public/static/images/wind-turbine-icon.svg b/public/static/images/wind-turbine-icon.svg new file mode 100644 index 0000000..e4841c4 --- /dev/null +++ b/public/static/images/wind-turbine-icon.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/apis/attendance-record/index.ts b/src/apis/attendance-record/index.ts new file mode 100644 index 0000000..39c5276 --- /dev/null +++ b/src/apis/attendance-record/index.ts @@ -0,0 +1,13 @@ +import http from '@/utils/http' +import type { AttendanceRecordReq, AttendanceRecordResp } from './type' + +const BASE_URL = '/attendance-record' + +/** 新增考勤记录 */ +export function addAttendanceRecord(data: AttendanceRecordReq) { + return http.post(BASE_URL, data, { + headers: { + 'Content-Type': 'application/json' + } + }) +} \ No newline at end of file diff --git a/src/apis/attendance-record/type.ts b/src/apis/attendance-record/type.ts new file mode 100644 index 0000000..d00853c --- /dev/null +++ b/src/apis/attendance-record/type.ts @@ -0,0 +1,15 @@ +/** 新增考勤记录请求体 */ +export interface AttendanceRecordReq { + recordImage?: string + recordPosition?: string + recordPositionLabel?: string + } + + /** 新增考勤记录响应体 */ + export interface AttendanceRecordResp { + code: number + data: object + msg: string + status: number + success: boolean + } \ No newline at end of file diff --git a/src/apis/performance-setting/index.ts b/src/apis/performance-setting/index.ts new file mode 100644 index 0000000..531e171 --- /dev/null +++ b/src/apis/performance-setting/index.ts @@ -0,0 +1,40 @@ +import http from '@/utils/http' +import type { PerformanceDimension, PerformanceRule, DimensionQuery, RuleQuery } from './type' + +/** 维度相关 */ +export function getDimensionList(params?: DimensionQuery) { + return http.get('/performance-dimension/list', params) +} +export function getDimensionDetail(id: string) { + return http.get(`/performance-dimension/${id}`) +} +export function addDimension(data: Partial) { + return http.post('/performance-dimension', data) +} +export function updateDimension(id: string, data: Partial) { + return http.put(`/performance-dimension/${id}`, data) +} +export function deleteDimension(id: string) { + return http.del(`/performance-dimension/${id}`) +} + +/** 细则相关 */ +export function getRuleList(params?: RuleQuery) { + return http.get('/performance-rule/list', params) +} +export function getRuleDetail(id: string) { + return http.get(`/performance-rule/${id}`) +} +export function addRule(data: Partial) { + return http.post('/performance-rule', data) +} +export function updateRule(id: string, data: Partial) { + return http.put(`/performance-rule/${id}`, data) +} +export function deleteRule(id: string) { + return http.del(`/performance-rule/${id}`) +} +// 我的绩效 +export function getMyEvaluation() { + return http.get('/performance-evaluation/my') + } \ No newline at end of file diff --git a/src/apis/performance-setting/type.ts b/src/apis/performance-setting/type.ts new file mode 100644 index 0000000..c0ad66a --- /dev/null +++ b/src/apis/performance-setting/type.ts @@ -0,0 +1,39 @@ +/** 绩效维度 */ +export interface PerformanceDimension { + dimensionId: string + dimensionName: string + description?: string + deptName: string + status: 0 | 1 + createBy?: string + createTime?: string + updateBy?: string + updateTime?: string + } + + /** 绩效细则 */ + export interface PerformanceRule { + ruleId: string + ruleName: string + description?: string + dimensionName: string + bonus?: string + score?: number + weight?: number + status: 0 | 1 + createBy?: string + createTime?: string + updateBy?: string + updateTime?: string + } + + /** 查询参数 */ + export interface DimensionQuery { + dimensionName?: string + status?: 0 | 1 + } + export interface RuleQuery { + dimensionName?: string + ruleName?: string + status?: 0 | 1 + } \ No newline at end of file diff --git a/src/components/TurbineGrid/index.vue b/src/components/TurbineGrid/index.vue new file mode 100644 index 0000000..feabd72 --- /dev/null +++ b/src/components/TurbineGrid/index.vue @@ -0,0 +1,234 @@ + + + + + + {{ getStatusText(turbine.status) }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 添加机组 + + + + + + + diff --git a/src/router/route.ts b/src/router/route.ts index dcec581..f1a454d 100644 --- a/src/router/route.ts +++ b/src/router/route.ts @@ -73,7 +73,7 @@ export const systemRoutes: RouteRecordRaw[] = [ { path: '/organization/hr/performance/dimention', name: 'Dimention', - component: () => import('@/views/performance/dimension.vue'), + component: () => import('@/views/performance/setting/index.vue'), meta: { title: '绩效维度', icon: 'performance', hidden: false }, }, @@ -1144,7 +1144,7 @@ export const systemRoutes: RouteRecordRaw[] = [ { path: '/', - redirect: '/project-management/contract/revenue-contract3', + redirect: '/project-management/project-template/project-aproval', meta: { hidden: true }, }, { diff --git a/src/types/auto-imports.d.ts b/src/types/auto-imports.d.ts index 6a35f3a..369aad4 100644 --- a/src/types/auto-imports.d.ts +++ b/src/types/auto-imports.d.ts @@ -57,6 +57,7 @@ declare global { const useCssVars: typeof import('vue')['useCssVars'] const useId: typeof import('vue')['useId'] const useLink: typeof import('vue-router')['useLink'] + const useModel: typeof import('vue')['useModel'] const useRoute: typeof import('vue-router')['useRoute'] const useRouter: typeof import('vue-router')['useRouter'] const useSlots: typeof import('vue')['useSlots'] @@ -69,6 +70,6 @@ declare global { // for type re-export declare global { // @ts-ignore - export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' import('vue') } diff --git a/src/types/components.d.ts b/src/types/components.d.ts index 92efec9..19a4246 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -61,6 +61,7 @@ declare module 'vue' { 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'] diff --git a/src/views/default/error/components/ErrorPage.vue b/src/views/default/error/components/ErrorPage.vue index a4dea79..8c8dfa3 100644 --- a/src/views/default/error/components/ErrorPage.vue +++ b/src/views/default/error/components/ErrorPage.vue @@ -38,7 +38,7 @@ const IconMap: Record = { const router = useRouter() // 返回首页 const back = () => { - router.replace({ path: '/project-management/bidding/tender-documents' }) + router.replace({ path: '/asset-management/intellectual-property' }) } @@ -58,6 +58,7 @@ const back = () => { flex-direction: column; align-items: center; } + &__img { width: 100%; position: relative; @@ -66,14 +67,17 @@ const back = () => { justify-content: center; align-items: center; } + &__icon { max-width: 90%; height: 50vh; } + &__tip { display: flex; flex-direction: column; align-items: center; + &--a { margin-bottom: 20px; font-size: 32px; @@ -85,6 +89,7 @@ const back = () => { animation-duration: 0.5s; animation-fill-mode: forwards; } + &--b { margin-bottom: 10px; font-size: 20px; @@ -97,6 +102,7 @@ const back = () => { animation-delay: 0.1s; animation-fill-mode: forwards; } + &--c { padding: 0 30px; margin-bottom: 20px; @@ -112,11 +118,13 @@ const back = () => { } } } + @keyframes slideUp { 0% { opacity: 0; transform: translateY(60px); } + 100% { opacity: 1; transform: translateY(0); diff --git a/src/views/hr/attendance-record/index.vue b/src/views/hr/attendance-record/index.vue new file mode 100644 index 0000000..30bcb99 --- /dev/null +++ b/src/views/hr/attendance-record/index.vue @@ -0,0 +1,73 @@ + + + + 新增考勤记录 + + + + + + + + + + + + + + 提交 + + + + {{ resultMsg }} + + + + + diff --git a/src/views/login/components/account/index.vue b/src/views/login/components/account/index.vue index 561b0c9..53f7ba5 100644 --- a/src/views/login/components/account/index.vue +++ b/src/views/login/components/account/index.vue @@ -1,13 +1,6 @@ - + @@ -108,7 +101,7 @@ const handleLogin = async () => { const { rememberMe } = loginConfig.value loginConfig.value.account = rememberMe ? form.account : '' await router.push({ - path: (redirect as string) || '/project-management/projects/initiation', + path: (redirect as string) || '/asset-management/intellectual-property', query: { ...othersQuery, }, diff --git a/src/views/performance/my.vue b/src/views/performance/my.vue index fdb21fa..ce9318d 100644 --- a/src/views/performance/my.vue +++ b/src/views/performance/my.vue @@ -1,6 +1,6 @@ - + 查看详情 @@ -8,41 +8,43 @@ - + + 维度:{{ selected.dimensionName }} + 周期:{{ selected.periodName }} + 评分:{{ selected.score }} + 奖金:{{ selected.bonus }} + 评价:{{ selected.comment }} + + \ No newline at end of file diff --git a/src/views/performance/setting/components/DimensionDrawer.vue b/src/views/performance/setting/components/DimensionDrawer.vue new file mode 100644 index 0000000..a02ff20 --- /dev/null +++ b/src/views/performance/setting/components/DimensionDrawer.vue @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/performance/setting/components/RuleDrawer.vue b/src/views/performance/setting/components/RuleDrawer.vue new file mode 100644 index 0000000..fbdee29 --- /dev/null +++ b/src/views/performance/setting/components/RuleDrawer.vue @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/performance/setting/components/RuleList.vue b/src/views/performance/setting/components/RuleList.vue new file mode 100644 index 0000000..e3d2c67 --- /dev/null +++ b/src/views/performance/setting/components/RuleList.vue @@ -0,0 +1,64 @@ + + + 新增细则 + + + + {{ record.status === 0 ? '启用' : '禁用' }} + + + + + 编辑 + 删除 + + + + + + + + \ No newline at end of file diff --git a/src/views/performance/setting/index.vue b/src/views/performance/setting/index.vue new file mode 100644 index 0000000..8a8464b --- /dev/null +++ b/src/views/performance/setting/index.vue @@ -0,0 +1,67 @@ + + + + 新增维度 + + + + + {{ record.status === 0 ? '启用' : '禁用' }} + + + + + 编辑 + 删除 + 管理细则 + + + + + + + + + + + + + diff --git a/src/views/project/TurbineCard.vue b/src/views/project/TurbineCard.vue new file mode 100644 index 0000000..70764b9 --- /dev/null +++ b/src/views/project/TurbineCard.vue @@ -0,0 +1,88 @@ + + + + + + + {{ statusTextMap[turbine.status] }} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/views/project/TurbineGrid.vue b/src/views/project/TurbineGrid.vue new file mode 100644 index 0000000..88d4b31 --- /dev/null +++ b/src/views/project/TurbineGrid.vue @@ -0,0 +1,41 @@ + + + + + + updateTurbine(i, v)" @map="$emit('map', t)" /> + + + + \ No newline at end of file diff --git a/src/views/project/detail/index.vue b/src/views/project/detail/index.vue index f5e0435..ed7aa2d 100644 --- a/src/views/project/detail/index.vue +++ b/src/views/project/detail/index.vue @@ -7,7 +7,9 @@ {{ projectTitle }} - {{ projectData.status }} + {{ + projectData.status + }} @@ -24,17 +26,18 @@ - + - + 项目收支情况 - + 利润 - {{ finance.profit.toFixed(2) }} + {{ finance.profit.toFixed(2) }} + 收入 @@ -45,11 +48,11 @@ {{ finance.expense.toFixed(2) }} - + - + @@ -66,7 +69,7 @@ - + @@ -75,38 +78,34 @@ {{ column.title }} {{ column.tasks.length }} - + - + {{ task.taskName }} {{ task.description || '暂无描述' }} - {{ user.substring(0, 1) }} - +{{ task.participants.length - 3 }} + {{ + user.substring(0, 1) }} + +{{ task.participants.length - 3 + }} - - - - 添加任务 - + + + + 添加任务 + @@ -114,15 +113,11 @@ - + - + @@ -136,13 +131,9 @@ - - + + @@ -172,13 +163,10 @@ - - + + @@ -186,18 +174,14 @@ - + - + 任务进度 - + @@ -289,7 +273,7 @@ const contractInfos = computed(() => [ const taskDetailInfos = computed(() => { if (!currentTask.value) return [] - + return [ { label: '任务名称', value: currentTask.value.taskName }, { label: '任务编号', value: currentTask.value.taskCode }, @@ -350,19 +334,19 @@ const fetchProjectData = async () => { const fetchTaskData = async () => { try { - const res = await listTask({ + const res = await listTask({ projectId: projectId.value, page: 1, size: 100 }) - + // 重置任务列表 taskColumns.value.forEach(column => { column.tasks = [] }) - + const tasks = res.data?.list || [] - + // 分配任务到对应的列 tasks.forEach((task: any) => { const column = taskColumns.value.find(col => col.status === task.status) @@ -494,10 +478,10 @@ const submitProgressUpdate = async () => { try { await updateTaskProgress({ progress: updateProgress.value }, currentTask.value.id) Message.success('更新进度成功') - + // 更新本地数据 currentTask.value.progress = updateProgress.value - + // 刷新任务列表 await fetchTaskData() } catch (error) { @@ -516,33 +500,41 @@ onMounted(() => { .finance-card { text-align: center; } + .finance-title { color: #7f7f7f; font-size: 14px; } + .finance-amount { font-size: 24px; font-weight: bold; } + .text-danger { color: #f53f3f; } + .text-success { color: #00b42a; } + .text-warning { color: #ff7d00; } + .task-container { overflow-x: auto; min-height: 600px; } + .task-column { background-color: #f5f5f5; border-radius: 4px; height: 100%; min-height: 600px; } + .task-column-header { padding: 12px; border-radius: 4px 4px 0 0; @@ -551,9 +543,11 @@ onMounted(() => { align-items: center; font-weight: bold; } + .task-list { padding: 8px; } + .task-card { background-color: white; border-radius: 4px; @@ -563,16 +557,20 @@ onMounted(() => { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); transition: box-shadow 0.3s; } + .task-card:hover { box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2); } + .task-card-title { font-weight: bold; } + .task-card-members { display: flex; gap: 4px; } + .add-task-placeholder { display: flex; align-items: center; @@ -584,26 +582,31 @@ onMounted(() => { cursor: pointer; gap: 8px; } + .add-task-placeholder:hover { background-color: #d9d9d9; } + .upload-button-content { display: flex; flex-direction: column; align-items: center; color: #7f7f7f; } + .card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; } + .card-title { font-size: 16px; font-weight: bold; } + .general-card { margin-bottom: 16px; } - \ No newline at end of file + diff --git a/src/views/project/icons/WindTurbine.vue b/src/views/project/icons/WindTurbine.vue new file mode 100644 index 0000000..f1f0d5c --- /dev/null +++ b/src/views/project/icons/WindTurbine.vue @@ -0,0 +1,358 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/project/index.vue b/src/views/project/index.vue index a5a3f5a..6a9319b 100644 --- a/src/views/project/index.vue +++ b/src/views/project/index.vue @@ -12,20 +12,12 @@ --> - + - + + @@ -71,12 +63,7 @@ 详情 修改 - + 删除 @@ -84,22 +71,10 @@ - - + + 基本信息 @@ -109,19 +84,61 @@ - - - - {{ user.label }} - - + + + + + { Message.info(`待开发`) }"> + + 地图选点 + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ option.label }} @@ -130,166 +147,57 @@ - - + + - + - + - + - - - - - - - - - - - 委托方信息 - - - - - - - - - - - - - - - - - - - - - 检查方信息 - - - - - - - - - - - - - - - - - - - - - - - 风场信息 - - - - - - - - - - - - - - - - + - - - 项目团队 + + + 风场信息可视化 - - - - - {{ user.label }} - - - - - - - - - {{ user.label }} - - - - - - - - - - - - {{ user.label }} - - - - - - - - - {{ user.label }} - - + + + + + + 地图 + - + 批量导入文件 拖动文件到此处,或点击下方按钮上传 - + 选择文件 @@ -311,7 +219,7 @@ import type { ColumnItem } from '@/components/GiForm' import type { TableColumnData } from '@arco-design/web-vue' import type { ProjectResp, ProjectPageQuery } from '@/apis/project/type' import * as T from '@/apis/project/type' - +import TurbineGrid from './TurbineGrid.vue' defineOptions({ name: 'ProjectManagement' }) // 项目状态常量定义 (API返回数字类型) @@ -324,7 +232,7 @@ const PROJECT_STATUS = { // 项目状态映射 const PROJECT_STATUS_MAP = { 0: '待施工', - 1: '施工中', + 1: '施工中', 2: '已完成' } as const @@ -379,11 +287,11 @@ const queryFormColumns: ColumnItem[] = reactive([ }, { type: 'input', - label: '风场名称', - field: 'fieldName', // 保持使用fieldName,因为API类型定义中使用的是这个字段名 + label: '业主', + field: 'inspectionUnit', span: { xs: 24, sm: 8, xxl: 8 }, props: { - placeholder: '请输入风场名称', + placeholder: '请输入业主名称', }, }, { @@ -419,7 +327,8 @@ const form = reactive({ constructionTeamLeaderId: '', // 施工组长id constructorIds: '', // 施工人员id qualityOfficerId: '', // 质量员id - auditorId: '' // 安全员id + auditorId: '', // 安全员id + turbineList: [] as { id: number; turbineNo: string; lat?: number; lng?: number; status: 0 | 1 | 2 }[], }) const pagination = reactive({ @@ -430,7 +339,9 @@ const pagination = reactive({ showJumper: true, showPageSize: true }) - +const openMapModal = (item: any) => { + Message.info(`地图选点功能待开发,当前机组编号:${item.turbineNo}`) +} const tableColumns = ref([ { title: '序号', @@ -439,91 +350,91 @@ const tableColumns = ref([ render: ({ rowIndex }) => rowIndex + 1 + (pagination.current - 1) * pagination.pageSize, fixed: !isMobile() ? 'left' : undefined, }, - { - title: '项目编号', - dataIndex: 'projectCode', - width: 120, - ellipsis: true, + { + title: '项目编号', + dataIndex: 'projectCode', + width: 120, + ellipsis: true, tooltip: true, fixed: !isMobile() ? 'left' : undefined, }, - { - title: '项目名称', - dataIndex: 'projectName', - minWidth: 140, - ellipsis: true, + { + title: '项目名称', + dataIndex: 'projectName', + minWidth: 140, + ellipsis: true, tooltip: true, fixed: !isMobile() ? 'left' : undefined, }, - { - title: '风场名称/风场地址', - slotName: 'fieldInfo', - minWidth: 180, - ellipsis: true, - tooltip: true + { + title: '地点', + slotName: 'fieldInfo', + minWidth: 180, + ellipsis: true, + tooltip: true }, - { - title: '状态', - dataIndex: 'status', - slotName: 'status', - align: 'center', - width: 100 + { + title: '状态', + dataIndex: 'status', + slotName: 'status', + align: 'center', + width: 100 }, - { - title: '委托单位', - dataIndex: 'commissionUnit', - minWidth: 140, - ellipsis: true, - tooltip: true + { + title: '委托单位', + dataIndex: 'commissionUnit', + minWidth: 140, + ellipsis: true, + tooltip: true }, - { - title: '委托单位联系人/电话', - slotName: 'commissionInfo', - minWidth: 160, - ellipsis: true, - tooltip: true + { + title: '委托单位联系人/电话', + slotName: 'commissionInfo', + minWidth: 160, + ellipsis: true, + tooltip: true }, - { - title: '检查单位', - dataIndex: 'inspectionUnit', - minWidth: 140, - ellipsis: true, - tooltip: true + { + title: '业主', + dataIndex: 'inspectionUnit', + minWidth: 140, + ellipsis: true, + tooltip: true }, - { - title: '检查单位联系人/电话', - slotName: 'inspectionInfo', - minWidth: 160, - ellipsis: true, - tooltip: true + { + title: '业主联系人/电话', + slotName: 'inspectionInfo', + minWidth: 160, + ellipsis: true, + tooltip: true }, - { - title: '项目规模', - dataIndex: 'projectScale', - width: 100, - ellipsis: true, - tooltip: true + { + title: '项目规模', + dataIndex: 'projectScale', + width: 100, + ellipsis: true, + tooltip: true }, - { - title: '机组型号', - dataIndex: 'orgNumber', - width: 100, - ellipsis: true, - tooltip: true + { + title: '机组型号', + dataIndex: 'orgNumber', + width: 100, + ellipsis: true, + tooltip: true }, - { - title: '项目经理/施工人员', - slotName: 'projectManager', - minWidth: 160, - ellipsis: true, - tooltip: true + { + title: '项目经理/施工人员', + slotName: 'projectManager', + minWidth: 160, + ellipsis: true, + tooltip: true }, - { - title: '项目周期', - slotName: 'projectPeriod', - minWidth: 180, - ellipsis: true, - tooltip: true + { + title: '项目周期', + slotName: 'projectPeriod', + minWidth: 180, + ellipsis: true, + tooltip: true }, { title: '操作', @@ -533,7 +444,20 @@ const tableColumns = ref([ fixed: !isMobile() ? 'right' : undefined, }, ]) - +watch(() => form.scale, (newVal) => { + const count = Number(newVal) + if (count > 0 && count <= 999) { + form.turbineList = Array.from({ length: count }, (_, i) => ({ + id: i + 1, + turbineNo: `${String(i + 1).padStart(3, '0')}`, + lat: undefined, + lng: undefined, + status: form.status, + })) + } else { + form.turbineList = [] + } +}, { immediate: true }) const modalTitle = computed(() => isEdit.value ? '编辑项目' : '新增项目') const getStatusColor = (status: number) => { @@ -557,37 +481,37 @@ const fetchData = async () => { page: pagination.current, size: pagination.pageSize } - + const res = await listProject(params) - + if (res.success && res.data) { // API直接返回数组数据 const projects = Array.isArray(res.data) ? res.data : [] - + // 数据映射和兼容性处理 dataList.value = projects.map((item: any) => { const mappedItem: T.ProjectResp = { - ...item, - // 添加别名字段以保持兼容性 - id: item.projectId, - fieldName: item.farmName, - fieldLocation: item.farmAddress, - commissionUnit: item.client, - commissionContact: item.clientContact, - commissionPhone: item.clientPhone, - orgNumber: item.turbineModel, - projectManager: item.projectManagerName, + ...item, + // 添加别名字段以保持兼容性 + id: item.projectId, + fieldName: item.farmName, + fieldLocation: item.farmAddress, + commissionUnit: item.client, + commissionContact: item.clientContact, + commissionPhone: item.clientPhone, + orgNumber: item.turbineModel, + projectManager: item.projectManagerName, projectScale: item.scale, - // 处理项目周期 + // 处理项目周期 projectPeriod: item.startDate && item.endDate ? [item.startDate, item.endDate] : [] }; return mappedItem; }) - + // 由于API没有返回total,使用当前数据长度 // 如果是完整数据,可以用数据长度;如果有分页,需要从其他地方获取total pagination.total = projects.length - + // 如果返回的数据少于每页大小,说明已经是最后一页 if (projects.length < pagination.pageSize) { pagination.total = (pagination.current - 1) * pagination.pageSize + projects.length @@ -619,7 +543,7 @@ const reset = () => { fieldName: '', // 保持使用fieldName,因为API类型定义中使用的是这个字段名 status: undefined, }) - + // 重置分页并重新搜索 pagination.current = 1 search() @@ -661,7 +585,7 @@ const resetForm = () => { qualityOfficerId: '', // 质量员id auditorId: '' // 安全员id }) - + isEdit.value = false currentId.value = null } @@ -674,13 +598,13 @@ const openAddModal = () => { const openEditModal = (record: T.ProjectResp) => { isEdit.value = true currentId.value = record.id || record.projectId || null - + // 重置表单 Object.keys(form).forEach(key => { // @ts-ignore form[key] = '' }) - + // 填充表单数据 Object.keys(form).forEach(key => { if (key in record && record[key as keyof T.ProjectResp] !== undefined) { @@ -688,7 +612,7 @@ const openEditModal = (record: T.ProjectResp) => { form[key] = record[key as keyof T.ProjectResp] } }) - + // 处理特殊字段映射 if (record.farmName) form.farmName = record.farmName if (record.farmAddress) form.farmAddress = record.farmAddress @@ -697,11 +621,11 @@ const openEditModal = (record: T.ProjectResp) => { if (record.clientPhone) form.clientPhone = record.clientPhone if (record.turbineModel) form.turbineModel = record.turbineModel if (record.scale) form.scale = record.scale - + // 处理日期字段 if (record.startDate) form.startDate = record.startDate if (record.endDate) form.endDate = record.endDate - + addModalVisible.value = true } @@ -716,12 +640,12 @@ const submitLoading = ref(false) const handleSubmit = async () => { console.log('表单提交开始', form) submitLoading.value = true - + try { // 表单验证 console.log('开始验证表单', formRef.value) await formRef.value.validate() - + // 准备提交的数据 const submitData = { ...form, @@ -735,7 +659,7 @@ const handleSubmit = async () => { } console.log('提交数据:', submitData) - + let res if (isEdit.value && currentId.value) { // 编辑模式 @@ -748,16 +672,16 @@ const handleSubmit = async () => { res = await addProject(submitData) Message.success('添加成功') } - + console.log('API响应结果:', res) - + // 检查操作是否成功 if (res && res.success === false) { Message.error(res.msg || '操作失败') submitLoading.value = false return } - + addModalVisible.value = false fetchData() } catch (error: any) { @@ -787,16 +711,16 @@ const deleteItem = async (record: T.ProjectResp) => { Message.error('项目ID不存在') return } - + try { const res = await deleteProject(projectId) - + // 检查删除操作是否成功 if (res && res.success === false) { Message.error(res.msg || '删除失败') return } - + Message.success('删除成功') fetchData() } catch (error) { @@ -811,7 +735,7 @@ const viewDetail = (record: T.ProjectResp) => { Message.error('项目ID不存在') return } - + router.push({ name: 'ProjectDetail', params: { @@ -839,24 +763,24 @@ const handleImport = async () => { Message.warning('请选择文件') return false } - + try { const fileItem = fileList.value[0] as any const file = fileItem?.file || fileItem - + if (!file) { Message.warning('请选择有效的文件') return false } - + // 调用导入API const res = await importProject(file) - + if (res && res.success === false) { Message.error(res.msg || '导入失败') return false } - + Message.success('导入成功') handleCancelImport() fetchData() // 重新获取数据 @@ -875,7 +799,7 @@ const exportData = async () => { status: searchForm.status, fieldName: searchForm.fieldName, // 保持使用fieldName,因为API类型定义中使用的是这个字段名 } - + await exportProject(params) Message.success('导出成功') } catch (error) { @@ -922,11 +846,11 @@ onMounted(() => { .arco-form-item { margin-bottom: 16px; } - + .arco-divider { margin: 16px 0; font-weight: 500; color: var(--color-text-2); } } - \ No newline at end of file +