|
|
@@ -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 {
|