This commit is contained in:
Mr.j 2025-08-14 17:12:59 +08:00
commit 08ce05d9f4
4 changed files with 155 additions and 90 deletions

View File

@ -906,12 +906,61 @@ export const systemRoutes: RouteRecordRaw[] = [
}, },
], ],
}, },
// start
{
path: '/construction-operation-platform',
name: 'ConstructionOperationPlatform',
component: Layout,
redirect: '/construction-operation-platform/implementation-workflow/field-construction',
meta: { title: '我的工作台', icon: 'tool', hidden: false, sort: 5 },
children: [
// {
// path: '/construction-operation-platform/implementation-workflow',
// name: 'ImplementationWorkflow',
// component: () => import('@/components/ParentView/index.vue'),
// redirect: '/construction-operation-platform/implementation-workflow/field-construction',
// meta: { title: '项目实施工作流程', icon: 'fork', hidden: false },
// children: [
{
path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/attachment',
name: 'AttachmentManagement',
component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/index.vue'),
meta: { title: '附件管理', icon: 'attachment', hidden: false },
},
{
path: '/construction-operation-platform/implementation-workflow/data-processing/model-config',
name: 'ModelConfig',
component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/model-config/index.vue'),
meta: { title: '模型配置', icon: 'robot', hidden: false },
},
{
path: '/construction-operation-platform/implementation-workflow/field-construction',
name: 'FieldConstruction',
component: () => import('@/components/ParentView/index.vue'),
redirect: '/construction-operation-platform/implementation-workflow/field-construction/project-list',
meta: { title: '我的项目', icon: 'construction', hidden: false },
children: [
{
path: '/project-management/projects/list',
name: 'ProjectList',
component: () => import('@/views/project-management/projects/list/index.vue'),
meta: {
title: '项目列表',
icon: 'unordered-list',
hidden: false,
},
},
{
path: '/construction-operation-platform/implementation-workflow/field-construction/technology',
name: 'FieldConstructionTechnology',
component: () => import('@/views/project-operation-platform/implementation-workflow/field-construction/project-list/index.vue'),
meta: { title: '我的施工', icon: 'tool', hidden: false },
},
// start
// 数据管理 // 数据管理
{ {
path: '/data-management', path: '/data-management',
name: 'DataManagement', name: 'DataManagement',
component: Layout,
redirect: '/data-management/project-management/project-template', redirect: '/data-management/project-management/project-template',
meta: { title: '数据管理', icon: 'database', hidden: false, sort: 4 }, meta: { title: '数据管理', icon: 'database', hidden: false, sort: 4 },
children: [ children: [
@ -1027,55 +1076,6 @@ export const systemRoutes: RouteRecordRaw[] = [
], ],
}, },
// end // end
{
path: '/construction-operation-platform',
name: 'ConstructionOperationPlatform',
component: Layout,
redirect: '/construction-operation-platform/implementation-workflow/field-construction',
meta: { title: '我的工作台', icon: 'tool', hidden: false, sort: 5 },
children: [
// {
// path: '/construction-operation-platform/implementation-workflow',
// name: 'ImplementationWorkflow',
// component: () => import('@/components/ParentView/index.vue'),
// redirect: '/construction-operation-platform/implementation-workflow/field-construction',
// meta: { title: '项目实施工作流程', icon: 'fork', hidden: false },
// children: [
{
path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/attachment',
name: 'AttachmentManagement',
component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/index.vue'),
meta: { title: '附件管理', icon: 'attachment', hidden: false },
},
{
path: '/construction-operation-platform/implementation-workflow/data-processing/model-config',
name: 'ModelConfig',
component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/model-config/index.vue'),
meta: { title: '模型配置', icon: 'robot', hidden: false },
},
{
path: '/construction-operation-platform/implementation-workflow/field-construction',
name: 'FieldConstruction',
component: () => import('@/components/ParentView/index.vue'),
redirect: '/construction-operation-platform/implementation-workflow/field-construction/project-list',
meta: { title: '我的项目', icon: 'construction', hidden: false },
children: [
{
path: '/project-management/projects/list',
name: 'ProjectList',
component: () => import('@/views/project-management/projects/list/index.vue'),
meta: {
title: '项目列表',
icon: 'unordered-list',
hidden: false,
},
},
{
path: '/construction-operation-platform/implementation-workflow/field-construction/technology',
name: 'FieldConstructionTechnology',
component: () => import('@/views/project-operation-platform/implementation-workflow/field-construction/project-list/index.vue'),
meta: { title: '我的施工', icon: 'tool', hidden: false },
},
{ {
path: '/construction-operation-platform/implementation-workflow/project-delivery', path: '/construction-operation-platform/implementation-workflow/project-delivery',
name: 'ProjectDelivery', name: 'ProjectDelivery',

View File

@ -70,6 +70,6 @@ declare global {
// for type re-export // for type re-export
declare global { declare global {
// @ts-ignore // @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue') import('vue')
} }

View File

@ -3,22 +3,22 @@ import { computed } from 'vue'
import WindTurbine from './icons/WindTurbine.vue' import WindTurbine from './icons/WindTurbine.vue'
interface Turbine { interface Turbine {
id: number id: number
turbineNo: string turbineNo: string
status: 0 | 1 | 2 // 0 1 2 status: 0 | 1 | 2 // 0 1 2
lat?: number lat?: number
lng?: number lng?: number
} }
const props = defineProps<{ modelValue: Turbine }>() const props = defineProps<{ modelValue: Turbine }>()
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:modelValue', v: Turbine): void (e: 'update:modelValue', v: Turbine): void
(e: 'map'): void (e: 'map'): void
}>() }>()
const turbine = computed({ const turbine = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: v => emit('update:modelValue', v) set: (v) => emit('update:modelValue', v),
}) })
/* 状态文字 & 颜色 */ /* 状态文字 & 颜色 */
@ -27,34 +27,36 @@ const statusColorMap = { 0: '#FF7D00', 1: '#165DFF', 2: '#00B42A' }
/* 点击循环切换 */ /* 点击循环切换 */
function toggleStatus() { function toggleStatus() {
const next = ((turbine.value.status + 1) % 3) as 0 | 1 | 2 const next = ((turbine.value.status + 1) % 3) as 0 | 1 | 2
turbine.value = { ...turbine.value, status: next } turbine.value = { ...turbine.value, status: next }
} }
function updateNo(val: string) { function updateNo(val: string) {
turbine.value = { ...turbine.value, turbineNo: val } turbine.value = { ...turbine.value, turbineNo: val }
} }
</script> </script>
<template> <template>
<div class="turbine-card"> <div class="turbine-card">
<!-- 可点击的状态标签 --> <!-- 可点击的状态标签 -->
<div class="status-tag" :style="{ backgroundColor: statusColorMap[turbine.status] }" @click="toggleStatus"> <div class="status-tag" :style="{ backgroundColor: statusColorMap[turbine.status] }" @click="toggleStatus">
{{ statusTextMap[turbine.status] }} {{ statusTextMap[turbine.status] }}
</div>
<!-- 风机图标 -->
<WindTurbine />
<!-- 机组编号输入框 -->
<a-input :model-value="turbine.turbineNo" @update:model-value="updateNo" size="small" class="turbine-input"
placeholder="编号" />
<!-- 地图选点按钮 -->
<a-button size="mini" @click="$emit('map')">
<template #icon><icon-location /></template>
</a-button>
</div> </div>
<!-- 风机图标 -->
<WindTurbine />
<!-- 机组编号输入框 -->
<a-input
:model-value="turbine.turbineNo" size="small" class="turbine-input" placeholder="编号"
@update:model-value="updateNo"
/>
<!-- 地图选点按钮 -->
<a-button size="mini" @click="$emit('map')">
<template #icon><icon-location /></template>
</a-button>
</div>
</template> </template>
<style scoped> <style scoped>
@ -85,4 +87,4 @@ function updateNo(val: string) {
margin-top: 8px; margin-top: 8px;
text-align: center; text-align: center;
} }
</style> </style>

View File

@ -347,6 +347,53 @@
</a-upload> </a-upload>
</div> </div>
</a-modal> </a-modal>
<!-- 详情弹窗 -->
<a-modal
v-model:visible="detailVisible"
title="项目详情"
width="900px"
:footer="false"
:mask-closable="false"
>
<a-spin :loading="detailLoading">
<a-descriptions :column="2" bordered :label-style="{ width: '140px', fontWeight: 'bold' }">
<a-descriptions-item label="项目名称" :span="2">{{ detailData.projectName || '-' }}</a-descriptions-item>
<a-descriptions-item label="项目编号">{{ detailData.projectCode || '-' }}</a-descriptions-item>
<a-descriptions-item label="状态">
<a-tag v-if="detailData.status !== undefined" :color="getStatusColor(detailData.status)">
{{ PROJECT_STATUS_MAP[detailData.status] || detailData.statusLabel || '-' }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item label="项目类型">{{ detailData.projectCategory || '-' }}</a-descriptions-item>
<a-descriptions-item label="业主">{{ detailData.inspectionUnit || '-' }}</a-descriptions-item>
<a-descriptions-item label="业主联系人">{{ detailData.inspectionContact || '-' }}</a-descriptions-item>
<a-descriptions-item label="业主电话">{{ detailData.inspectionPhone || '-' }}</a-descriptions-item>
<a-descriptions-item label="委托单位">{{ detailData.client || '-' }}</a-descriptions-item>
<a-descriptions-item label="委托联系人">{{ detailData.clientContact || '-' }}</a-descriptions-item>
<a-descriptions-item label="委托电话">{{ detailData.clientPhone || '-' }}</a-descriptions-item>
<a-descriptions-item label="风场名称">{{ detailData.farmName || '-' }}</a-descriptions-item>
<a-descriptions-item label="风场地址">{{ detailData.farmAddress || '-' }}</a-descriptions-item>
<a-descriptions-item label="项目经理">{{ detailData.projectManagerName || '-' }}</a-descriptions-item>
<a-descriptions-item label="项目规模">{{ detailData.scale || detailData.projectScale || '-' }}</a-descriptions-item>
<a-descriptions-item label="风机型号">{{ detailData.turbineModel || '-' }}</a-descriptions-item>
<a-descriptions-item label="开始时间">{{ detailData.startDate || '-' }}</a-descriptions-item>
<a-descriptions-item label="结束时间">{{ detailData.endDate || '-' }}</a-descriptions-item>
<a-descriptions-item label="项目简介" :span="2">
<a-typography-paragraph :ellipsis="{ rows: 3, expandable: true, collapseText: '收起', expandText: '展开' }">
{{ detailData.projectIntro || '-' }}
</a-typography-paragraph>
</a-descriptions-item>
</a-descriptions>
</a-spin>
</a-modal>
</GiPageLayout> </GiPageLayout>
</template> </template>
@ -412,6 +459,12 @@ const dataList = ref<T.ProjectResp[]>([])
const userLoading = ref(false) const userLoading = ref(false)
const userOptions = ref<{ label: string, value: string }[]>([]) const userOptions = ref<{ label: string, value: string }[]>([])
//
const detailVisible = ref(false)
const detailLoading = ref(false)
const detailData = ref<any>({})
const searchForm = reactive<Partial<ProjectPageQuery>>({ const searchForm = reactive<Partial<ProjectPageQuery>>({
projectName: '', projectName: '',
status: undefined, status: undefined,
@ -979,19 +1032,29 @@ const deleteItem = async (record: T.ProjectResp) => {
} }
} }
const viewDetail = (record: T.ProjectResp) => { const viewDetail = async (record: T.ProjectResp) => {
const projectId = record.id || record.projectId const projectId = record.id || record.projectId
if (!projectId) { if (!projectId) {
Message.error('项目ID不存在') Message.error('项目ID不存在')
return return
} }
detailVisible.value = true
router.push({ detailLoading.value = true
name: 'ProjectDetail', try {
params: { // /project/detail/{projectId}
id: projectId.toString(), const res = await getProjectDetail(projectId)
}, const data = (res as any).data || res || {}
}) // status
if (typeof data.status === 'number' && !data.statusLabel) {
data.statusLabel = PROJECT_STATUS_MAP[data.status]
}
detailData.value = data
} catch (e) {
console.error('获取项目详情失败:', e)
Message.error('获取项目详情失败')
} finally {
detailLoading.value = false
}
} }
const openImportModal = () => { const openImportModal = () => {