Переглянути джерело

项目管理页修改:项目分类,点击转跳

WQQ 3 тижнів тому
батько
коміт
109c37bd7c

+ 55 - 1
RuoYi-Vue3/src/views/front/ProjectManagement.vue

@@ -27,7 +27,7 @@
   <!-- 右侧内容区域 -->
       <section class="right-content">
         <!-- 面包屑导航已移除 -->
-        <component :is="activeComponent" />
+        <component :is="activeComponent" ref="shuiliGongchengRef" />
       </section>
 </main>
 
@@ -44,6 +44,9 @@ import ShuiliGongcheng from './content/ShuiliGongcheng.vue'
 import JidianShebei from './content/JidianShebei.vue'
 import ShuiliSheshi from './content/ShuiliSheshi.vue'
 
+// 创建一个可响应的引用,用于访问ShuiliGongcheng组件的实例
+const shuiliGongchengRef = ref(null)
+
 // 使用markRaw标记组件,避免Vue将其转换为响应式对象
 const ShuiliGongchengRaw = markRaw(ShuiliGongcheng)
 const JidianShebeiRaw = markRaw(JidianShebei)
@@ -60,6 +63,11 @@ const handleOpen = (key, keyPath) => {
     activeMenuName.value = '数字孪生'
     activeComponent.value = ShuiliGongchengRaw
     console.log('Set active component to ShuiliGongcheng')
+    
+    // 当打开数字孪生大类时,显示所有数字孪生项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生')
+    }
   }
 }
 
@@ -75,18 +83,43 @@ const handleMenuSelect = (key) => {
   if (key === '1') {
     activeMenuName.value = '数字孪生'
     activeComponent.value = ShuiliGongchengRaw
+    
+    // 当选择数字孪生大类时,显示所有数字孪生项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生')
+    }
   } else if (key === '1-1') {
     activeMenuName.value = '数字孪生太浦河'
     activeComponent.value = ShuiliGongchengRaw
+    
+    // 当选择数字孪生太浦河子类时,显示对应的项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生太浦河')
+    }
   } else if (key === '1-2') {
     activeMenuName.value = '数字孪生水文站'
     activeComponent.value = ShuiliGongchengRaw
+    
+    // 当选择数字孪生水文站子类时,显示对应的项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生水文站')
+    }
   } else if (key === '1-3') {
     activeMenuName.value = '数字孪生灌区'
     activeComponent.value = ShuiliGongchengRaw
+    
+    // 当选择数字孪生灌区子类时,显示对应的项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生灌区')
+    }
   } else {
     activeMenuName.value = '数字孪生'
     activeComponent.value = ShuiliGongchengRaw
+    
+    // 默认显示所有数字孪生项目
+    if (shuiliGongchengRef.value) {
+      shuiliGongchengRef.value.selectCategory('数字孪生')
+    }
   }
   
   console.log('Active component:', activeComponent.value)
@@ -144,6 +177,27 @@ const handleMenuSelect = (key) => {
   line-height: 1.5;
 }
 
+/* 选中状态的样式 */
+.el-menu-vertical-demo .el-menu-item.is-active,
+.el-menu-vertical-demo .el-sub-menu.is-active > .el-sub-menu__title {
+  color: #409eff !important;
+  font-weight: 600 !important;
+}
+
+/* 大类选中时的样式增强 */
+.el-menu-vertical-demo .el-sub-menu.is-active > .el-sub-menu__title {
+  background-color: rgba(64, 158, 255, 0.1) !important;
+  border-left: 3px solid #409eff !important;
+}
+
+/* 确保大类在打开时也保持选中状态 */
+.el-menu-vertical-demo .el-sub-menu.is-opened > .el-sub-menu__title {
+  color: #409eff !important;
+  font-weight: 600 !important;
+  background-color: rgba(64, 158, 255, 0.1) !important;
+  border-left: 3px solid #409eff !important;
+}
+
 .menu-title-text {
   font-size: 1rem !important;
   font-weight: 600;

+ 185 - 159
RuoYi-Vue3/src/views/front/content/ShuiliGongcheng.vue

@@ -1,97 +1,80 @@
 <template>
   <div class="shuili-gongcheng-content">
-    <!-- 模型表格 -->
+    <!-- 项目表格容器 -->
     <div class="project-table-container">
-      <!-- 上传项目按钮 -->
-      <div style="display: flex; justify-content: flex-end; margin-bottom: 20px;">
-        <el-button type="primary" @click="openUploadDialog">
-          <el-icon><Upload /></el-icon> 上传项目
-        </el-button>
-      </div>
-      <!-- 项目卡片网格 -->
-      <div class="project-grid">
-        <div v-for="project in projectData" :key="project.id" class="project-card">
-          <!-- 项目图片 -->
-          <div class="project-image">
-            <img :src="getProjectImage(project.name)" :alt="project.name" class="project-image-src" />
-          </div>
-          <!-- 项目名称 -->
-          <div class="project-name">{{ project.name }}</div>
-          <!-- 项目分类标签 -->
-          <div class="project-category">
-            <el-tag :type="getCategoryTagType(project.category)">
-              {{ project.category }}
-            </el-tag>
-          </div>
-          <!-- 项目信息 -->
-          <div class="project-info">
-            <div class="info-item">
-              <span class="info-label">类型:</span>
-              <span class="info-value">{{ getTypeDisplayName(project.type) }}</span>
-            </div>
-            <div class="info-item">
-              <span class="info-label">提交单位:</span>
-              <span class="info-value">{{ project.uploadUnit }}</span>
+      <!-- 项目内容区 -->
+      <div class="content-area">
+        <!-- 上传项目按钮 -->
+        <div style="display: flex; justify-content: flex-end; margin-bottom: 20px;">
+          <el-button type="primary" @click="openUploadDialog">
+            <el-icon><Upload /></el-icon> 上传项目
+          </el-button>
+        </div>
+        <!-- 项目卡片网格 -->
+        <div class="project-grid">
+          <div v-for="project in projectData" :key="project.id" class="project-card" @click="viewProject(project)">
+            <!-- 项目图片 -->
+            <div class="project-image">
+              <img :src="getProjectImage(project.name)" :alt="project.name" class="project-image-element" />
             </div>
-            <div class="info-item">
-              <span class="info-label">创建时间:</span>
-              <span class="info-value">{{ project.createTime }}</span>
+            <div class="project-content">
+              <!-- 项目名称 -->
+              <h3>{{ project.name }}</h3>
+              <!-- 项目描述 -->
+              <p>{{ project.description }}</p>
+              <!-- 项目标签 -->
+              <div class="project-tags">
+                <span v-for="tag in project.tags" :key="tag" class="tag">{{ tag }}</span>
+              </div>
             </div>
           </div>
-          <!-- 操作按钮 -->
-          <div class="project-actions">
-            <el-button size="small" type="primary" @click="viewProject(project)">
-              <el-icon><View /></el-icon> 查看
-            </el-button>
-          </div>
         </div>
-      </div>
-      
-      <!-- 分页组件 -->
-      <div class="pagination-container">
-        <el-pagination
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 50, 100]"
-          :small="false"
-          :disabled="false"
-          :background="true"
-          layout="total, sizes, prev, pager, next, jumper"
-          :total="total"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        >
-          <template #total>
-            共 {{ total }} 条
-          </template>
-          <template #sizes>
-            <el-select v-model="pageSize" style="width: 110px;" placeholder="请选择">
-              <el-option
-                v-for="item in [10, 20, 50, 100]"
-                :key="item"
-                :label="item + '条/页'"
-                :value="item"
+        <!-- 分页组件 -->
+        <div class="pagination-container">
+          <el-pagination
+            v-model:current-page="currentPage"
+            v-model:page-size="pageSize"
+            :page-sizes="[10, 20, 50, 100]"
+            :small="false"
+            :disabled="false"
+            :background="true"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          >
+            <template #total>
+              共 {{ total }} 条
+            </template>
+            <template #sizes>
+              <el-select v-model="pageSize" style="width: 110px;" placeholder="请选择">
+                <el-option
+                  v-for="item in [10, 20, 50, 100]"
+                  :key="item"
+                  :label="item + '条/页'"
+                  :value="item"
+                />
+              </el-select>
+            </template>
+            <template #prev>
+              上一页
+            </template>
+            <template #next>
+              下一页
+            </template>
+            <template #jumper>
+              前往
+              <el-input-number
+                v-model="currentPage"
+                :min="1"
+                :max="Math.ceil(total / pageSize)"
+                controls-position="right"
+                style="width: 60px; margin: 0 8px;"
               />
-            </el-select>
-          </template>
-          <template #prev>
-            上一页
-          </template>
-          <template #next>
-            下一页
-          </template>
-          <template #jumper>
-            前往
-            <el-input-number
-              v-model="currentPage"
-              :min="1"
-              :max="Math.ceil(total / pageSize)"
-              controls-position="right"
-              style="width: 60px; margin: 0 8px;"
-            />
-            页
-          </template>
-        </el-pagination>
+              页
+            </template>
+          </el-pagination>
+        </div>
       </div>
     </div>
 
@@ -112,6 +95,13 @@
             <el-option label="泵站" value="PUMPING_STATION" />
           </el-select>
           </el-form-item>
+          <el-form-item label="项目分类">
+            <el-select v-model="formData.category" placeholder="请选择项目分类" style="width: 100%;" :popper-append-to-body="false" :popper-options="{ boundariesElement: 'body' }">
+            <el-option label="数字孪生太浦河" value="数字孪生太浦河" />
+            <el-option label="数字孪生水文站" value="数字孪生水文站" />
+            <el-option label="数字孪生灌区" value="数字孪生灌区" />
+          </el-select>
+          </el-form-item>
           <el-form-item label="经纬度">
             <el-input v-model="formData.location" placeholder="请输入经纬度" style="width: 100%;" />
           </el-form-item>
@@ -168,22 +158,41 @@
 import { ref, onMounted, computed } from 'vue'
 import { Setting, House, Menu, DataBoard, Upload, View } from '@element-plus/icons-vue'
 import { ElMessage, ElMessageBox, ElInputNumber } from 'element-plus'
+import { useRouter } from 'vue-router'
 // 导入项目的axios service实例
 import request from '@/utils/request'
 // 导入用户store,用于获取当前登录用户信息
 import useUserStore from '@/store/modules/user'
 
+const router = useRouter()
+
 const projectData = ref([])
+const allProjectData = ref([]) // 保存所有项目数据,用于筛选
 const uploadDialogVisible = ref(false)
 const uploadKey = ref(0)
 const currentPage = ref(1)
 const pageSize = ref(10)
 const total = ref(0)
 
+// 分类筛选相关
+const selectedCategory = ref('all') // 选中的分类,默认显示全部项目
+const categoryOptions = ref([
+  {
+    value: '数字孪生',
+    label: '数字孪生',
+    children: [
+      { value: '数字孪生太浦河', label: '数字孪生太浦河' },
+      { value: '数字孪生水文站', label: '数字孪生水文站' },
+      { value: '数字孪生灌区', label: '数字孪生灌区' }
+    ]
+  }
+])
+
 const formData = ref({
   name: '',
   type: '',
   location: '',
+  category: '',
   format: '',
   status: '正常',
   uploadUnit: '',
@@ -311,7 +320,9 @@ const mockProjectData = ref([
     format: 'GLTF',
     status: '正常',
     createTime: '2024-06-15',
-    category: '数字孪生太浦河'
+    category: '数字孪生太浦河',
+    description: '基于数字孪生技术的太浦河流域综合管理平台,实现河流监测、模拟预测与智能调度',
+    tags: ['数字孪生', 'GIS', '大数据']
   },
   {
     id: '2',
@@ -322,7 +333,9 @@ const mockProjectData = ref([
     format: 'GLB',
     status: '正常',
     createTime: '2024-06-20',
-    category: '数字孪生太浦河'
+    category: '数字孪生太浦河',
+    description: '基于数字孪生技术的太浦闸智能监控系统,实现闸门运行状态实时监测与调度控制',
+    tags: ['数字孪生', '水利工程', '智能监控']
   },
   {
     id: '3',
@@ -333,7 +346,9 @@ const mockProjectData = ref([
     format: 'FBX',
     status: '正常',
     createTime: '2024-03-10',
-    category: '数字孪生水文站'
+    category: '数字孪生水文站',
+    description: '实现水文监测站点的数字化映射,提供实时数据可视化与智能分析功能',
+    tags: ['数字孪生', '物联网', 'AI']
   },
   {
     id: '4',
@@ -344,7 +359,9 @@ const mockProjectData = ref([
     format: 'OBJ',
     status: '正常',
     createTime: '2024-03-15',
-    category: '数字孪生水文站'
+    category: '数字孪生水文站',
+    description: '全流域水文数据采集与传输系统,支持多源数据融合与标准化管理',
+    tags: ['数据采集', '传感器', '通信']
   },
   {
     id: '5',
@@ -355,14 +372,51 @@ const mockProjectData = ref([
     format: 'STL',
     status: '正常',
     createTime: '2024-04-20',
-    category: '数字孪生灌区'
+    category: '数字孪生灌区',
+    description: '基于数字孪生技术的灌区水资源优化配置系统,实现精准灌溉与水资源高效利用',
+    tags: ['数字孪生', '灌溉', '水资源']
   }
 ])
 
+// 左侧分类列表点击处理函数
+const selectCategory = (category) => {
+  selectedCategory.value = category;
+  
+  // 根据选择的分类筛选项目
+  if (category === 'all') {
+    // 显示所有项目
+    projectData.value = allProjectData.value;
+  } else if (category === '数字孪生') {
+    // 显示所有数字孪生项目
+    projectData.value = allProjectData.value.filter(project => 
+      project.category && project.category.includes('数字孪生')
+    );
+  } else if (category === '数字孪生太浦河') {
+    // 显示数字孪生太浦河和数字孪生太浦闸
+    projectData.value = allProjectData.value.filter(project => 
+      project.category === '数字孪生太浦河'
+    );
+  } else if (category === '数字孪生水文站') {
+    // 显示贡湖实验站和太师桥水文站
+    projectData.value = allProjectData.value.filter(project => 
+      project.category === '数字孪生水文站'
+    );
+  } else if (category === '数字孪生灌区') {
+    // 显示铜山源灌区
+    projectData.value = allProjectData.value.filter(project => 
+      project.category === '数字孪生灌区'
+    );
+  }
+  
+  total.value = projectData.value.length;
+  currentPage.value = 1; // 重置到第一页
+}
+
 // 组件挂载时获取数据
 onMounted(() => {
   // 先使用模拟数据,后续可替换为真实API调用
-  projectData.value = mockProjectData.value
+  allProjectData.value = mockProjectData.value // 保存所有项目数据
+  projectData.value = allProjectData.value // 初始显示所有项目
   total.value = mockProjectData.value.length
   // fetchProjects()
 })
@@ -378,6 +432,7 @@ const openUploadDialog = () => {
     name: '',
     type: '',
     location: '',
+    category: '',
     uploadUnit: userStore.dept.deptName || '未知单位', // 自动填充当前登录用户的部门名称
     format: '',
     status: 'NORMAL',  // 改为英文默认值
@@ -438,9 +493,11 @@ const submitForm = async () => {
   }
 }
 
-// 查看项目
-const viewProject = (row) => {
-  ElMessage.info(`查看项目: ${row.name}`)
+// 查看项目 - 跳转到项目详情页
+const viewProject = (project) => {
+  // 将项目ID转换为小写并替换空格和中文,以便符合路由规范
+  const projectId = project.name.toLowerCase().replace(/\s+/g, '-').replace(/[\u4e00-\u9fa5]/g, '').replace(/[^a-z0-9-]/g, '')
+  router.push(`/project-cases/${projectId}`)
 }
 
 // 删除项目
@@ -518,8 +575,10 @@ const handleCurrentChange = (val) => {
   fetchProjects()
 }
 
-
-
+// 暴露方法给父组件
+defineExpose({
+  selectCategory
+})
 
 </script>
 
@@ -540,6 +599,8 @@ const handleCurrentChange = (val) => {
   padding: 20px;
 }
 
+
+
 .el-table {
   --el-table-header-text-color: #303133;
   --el-table-row-hover-bg-color: #f5f7fa;
@@ -583,9 +644,8 @@ const handleCurrentChange = (val) => {
   border-radius: 16px;
   box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
   transition: all 0.3s ease;
-  display: flex;
-  flex-direction: column;
   overflow: hidden;
+  cursor: pointer;
 }
 
 .project-card:hover {
@@ -598,91 +658,57 @@ const handleCurrentChange = (val) => {
   width: 100%;
   height: 200px;
   overflow: hidden;
-  background: #f5f7fa;
+  background: #f0f5ff;
 }
 
-.project-image-src {
+.project-image-element {
   width: 100%;
   height: 100%;
   object-fit: cover;
   transition: transform 0.3s ease;
 }
 
-.project-card:hover .project-image-src {
-  transform: scale(1.05);
+.project-card:hover .project-image-element {
+  transform: scale(1.1);
+}
+
+/* 项目内容样式 */
+.project-content {
+  padding: 2rem;
 }
 
-/* 项目名称样式 */
-.project-name {
+.project-content h3 {
   font-size: 1.25rem;
-  font-weight: 600;
   color: #2c3e50;
-  margin: 1.5rem 1.5rem 1rem;
-  text-align: center;
+  margin-bottom: 1rem;
+  font-weight: 600;
   line-height: 1.4;
 }
 
-/* 项目分类标签样式 */
-.project-category {
-  text-align: center;
-  margin-bottom: 1.5rem;
-}
-
-.project-category :deep(.el-tag) {
+.project-content p {
   font-size: 0.875rem;
-  padding: 0.25rem 1rem;
-  border-radius: 20px;
-  font-weight: 500;
-}
-
-/* 项目信息样式 */
-.project-info {
-  padding: 0 1.5rem 2rem;
-  margin-bottom: 0;
-  flex-grow: 1;
-}
-
-/* 信息项样式 */
-.info-item {
-  display: flex;
-  justify-content: space-between;
-  margin-bottom: 10px;
-  font-size: 1rem;
-  line-height: 1.6;
-}
-
-/* 信息标签样式 */
-.info-label {
-  font-weight: 500;
   color: #7f8c8d;
+  margin-bottom: 1.5rem;
+  line-height: 1.6;
 }
 
-/* 信息值样式 */
-.info-value {
-  color: #2c3e50;
-  font-weight: 500;
-  text-align: right;
-}
-
-/* 操作按钮样式 */
-.project-actions {
+/* 项目标签样式 */
+.project-tags {
   display: flex;
-  gap: 1rem;
-  justify-content: center;
-  padding: 0 1.5rem 1.5rem;
+  gap: 0.5rem;
+  flex-wrap: wrap;
 }
 
-/* 按钮样式调整 */
-.project-actions :deep(.el-button) {
-  padding: 0.5rem 1.5rem;
-  font-weight: 500;
+.tag {
+  background: #f0f5ff;
+  color: #326ee2;
+  padding: 0.25rem 0.75rem;
   border-radius: 20px;
+  font-size: 0.75rem;
+  font-weight: 500;
 }
 
-/* 图标样式 */
-.project-actions :deep(.el-icon) {
-  margin-right: 0.25rem;
-}
+
 
 /* 分页组件样式 */
 .el-pagination {