<template>
|
<view class="content">
|
<!-- 搜索栏 -->
|
<view class="search-bar">
|
<input
|
class="search-input"
|
v-model="queryParams.projectName"
|
placeholder="搜索项目名称"
|
confirm-type="search"
|
@confirm="handleQuery"
|
/>
|
<view class="search-actions">
|
<button class="search-btn" @click="handleQuery">搜索</button>
|
<button class="reset-btn" @click="resetQuery">重置</button>
|
</view>
|
</view>
|
|
<!-- 项目列表 -->
|
<view class="list-container">
|
<view v-if="loading && projectInfoList.length === 0" class="loading-box">
|
<uni-icons type="spinner-cycle" size="24" color="#999" class="rotate"></uni-icons>
|
<text>加载中...</text>
|
</view>
|
|
<view v-else-if="projectInfoList.length === 0" class="empty-box">
|
<text>暂无数据</text>
|
</view>
|
|
<view
|
v-for="(item, index) in visibleList"
|
:key="item.id || index"
|
class="project-card"
|
:class="{ 'subtree-item': item._level > 0 }"
|
:style="{ marginLeft: (item._level || 0) * 30 + 'rpx' }"
|
|
>
|
<view class="card-header">
|
<view class="title-wrapper" @click="toggleExpand(item)">
|
<uni-icons
|
v-if="item.children && item.children.length > 0"
|
:type="expandedMap[item.id] ? 'down' : 'right'"
|
size="14"
|
color="#666"
|
></uni-icons>
|
<text class="project-title">{{ item.projectName }}</text>
|
</view>
|
</view>
|
|
<view class="card-body">
|
<view class="info-row">
|
<text class="label">主管部门:</text>
|
<text class="value">{{ item.competentDepartmentName || '-' }}</text>
|
</view>
|
<view class="info-row">
|
<text class="label">业主单位:</text>
|
<text class="value">{{ item.projectOwnerUnitName || '-' }}</text>
|
</view>
|
<view class="info-row-group">
|
<view class="info-item">
|
<text class="label">年份:</text>
|
<text class="value">{{ item.year ? item.year + '年' : '-' }}</text>
|
</view>
|
<view class="info-item">
|
<text class="label">投资额:</text>
|
<text class="value highlight">{{ item.investmentAmount || 0 }} 万</text>
|
</view>
|
</view>
|
<view class="info-row" v-if="item.buildContent">
|
<text class="label">建设内容:</text>
|
<text class="value content-text">{{ item.buildContent }}</text>
|
</view>
|
</view>
|
|
<view class="card-footer">
|
<button
|
v-if="item.processInsId"
|
class="action-btn view-btn"
|
@click="goToDetail(item)"
|
>
|
<uni-icons type="eye" size="16" color="#1E88E5"></uni-icons>
|
<text>查看流程</text>
|
</button>
|
|
<button
|
v-if="isReserve"
|
class="action-btn process-btn"
|
@click="openOpProcess(item)"
|
>
|
<uni-icons type="gear" size="16" color="#26A69A"></uni-icons>
|
<text>办理流程</text>
|
</button>
|
</view>
|
</view>
|
</view>
|
|
<!-- 分页 -->
|
<view class="pagination-box" v-if="total > 0">
|
<text class="total-text">共 {{ total }} 条</text>
|
<view class="pager">
|
<button :disabled="queryParams.currentPage <= 1" @click="changePage(-1)">上一页</button>
|
<text class="page-num">{{ queryParams.currentPage }} / {{ Math.ceil(total / queryParams.pageSize) }}</text>
|
<button :disabled="queryParams.currentPage >= Math.ceil(total / queryParams.pageSize)" @click="changePage(1)">下一页</button>
|
</view>
|
</view>
|
|
<BottomTabBar active="progress" />
|
</view>
|
</template>
|
|
<script>
|
import { getProjectProcess } from '@/api/projectProcess/projectProcess.js'
|
import BottomTabBar from '@/components/BottomTabBar.vue'
|
|
export default {
|
components: { BottomTabBar },
|
data() {
|
return {
|
loading: false,
|
total: 0,
|
projectInfoList: [],
|
expandedMap: {}, // 记录展开状态
|
isReserve: true, // 假设默认为 true,根据业务逻辑调整
|
queryParams: {
|
currentPage: 1,
|
pageSize: 10,
|
projectName: '',
|
projectCode: null,
|
},
|
// 模拟字典数据,实际项目中应从接口或全局获取
|
dict: {
|
type: {
|
sys_project_type: [
|
{ label: '新建', value: '1' },
|
{ label: '扩建', value: '2' },
|
{ label: '改建', value: '3' }
|
],
|
sys_project_status: [
|
{ label: '未开工', value: '0' },
|
{ label: '已开工', value: '1' },
|
{ label: '已完工', value: '2' }
|
]
|
}
|
}
|
}
|
},
|
onLoad() {
|
console.log("执行onload")
|
this.getList()
|
},
|
computed: {
|
/** 过滤出当前应该显示的列表项 */
|
visibleList() {
|
return this.projectInfoList.filter(item => {
|
// 如果没有父节点,说明是根节点,始终显示
|
if (!item._parentId) return true
|
|
// 检查所有祖先节点是否都已展开
|
let parentId = item._parentId
|
while (parentId) {
|
if (!this.expandedMap[parentId]) return false
|
// 找到父节点对象以继续向上查找
|
const parent = this.projectInfoList.find(p => p.id === parentId)
|
parentId = parent ? parent._parentId : null
|
}
|
return true
|
})
|
}
|
},
|
methods: {
|
/** 查询列表 */
|
getList() {
|
this.loading = true
|
getProjectProcess(this.queryParams).then(res => {
|
let records = []
|
let total = 0
|
console.log(res)
|
// 兼容不同返回格式
|
if (res.statusCode === 200) {
|
records = res.data.data || [];
|
total = res.data.total || 0
|
}
|
|
// 处理树形结构(展平显示)
|
this.projectInfoList = this.flattenTree(records)
|
this.total = total
|
|
// 默认展开所有(模拟原 vue2 的 default-expand-all)
|
this.projectInfoList.forEach(item => {
|
if (item.children && item.children.length > 0) {
|
this.$set(this.expandedMap, item.id, true)
|
}
|
})
|
|
this.loading = false
|
}).catch(err => {
|
console.error('获取列表失败:', err)
|
this.loading = false
|
})
|
},
|
|
/** 展平树结构 */
|
flattenTree(list, level = 0, parentId = null) {
|
let result = []
|
list.forEach(item => {
|
item._level = level
|
item._parentId = parentId
|
result.push(item)
|
if (item.children && item.children.length > 0) {
|
result = result.concat(this.flattenTree(item.children, level + 1, item.id))
|
}
|
})
|
return result
|
},
|
|
/** 切换展开状态 */
|
toggleExpand(item) {
|
if (!item.children || item.children.length === 0) return
|
const currentState = !!this.expandedMap[item.id]
|
this.$set(this.expandedMap, item.id, !currentState)
|
},
|
|
/** 搜索按钮操作 */
|
handleQuery() {
|
this.queryParams.currentPage = 1
|
this.getList()
|
},
|
|
/** 重置按钮操作 */
|
resetQuery() {
|
this.queryParams.projectName = ''
|
this.queryParams.currentPage = 1
|
this.getList()
|
},
|
|
/** 翻页 */
|
changePage(delta) {
|
this.queryParams.currentPage += delta
|
this.getList()
|
},
|
|
/** 字典翻译 */
|
getDictLabel(dictType, value) {
|
const options = this.dict.type[dictType] || []
|
const option = options.find(opt => opt.value == value)
|
return option ? option.label : value
|
},
|
|
/** 前往详情页 */
|
goToDetail(item) {
|
uni.navigateTo({
|
|
url: `/subpackage/manager/project-detail?data=${encodeURIComponent(JSON.stringify(item))}`
|
})
|
},
|
|
/** 打开操作流程 */
|
openOpProcess(row) {
|
const params = {
|
projectId: row.id,
|
processDefId: row.processDefId,
|
processInsId: row.processInsId,
|
deployId: row.deployId,
|
processName: row.processName || row.projectName
|
}
|
const query = Object.keys(params)
|
.filter(key => params[key] !== null && params[key] !== undefined)
|
.map(key => `${key}=${encodeURIComponent(params[key])}`)
|
.join('&')
|
|
uni.navigateTo({
|
url: `/subpackage/flowable/process-detail?${query}`
|
})
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.content {
|
width: 100%;
|
min-height: 100vh;
|
background-color: #f5f7fa;
|
padding-bottom: 140rpx;
|
}
|
|
/* 搜索栏样式 */
|
.search-bar {
|
display: flex;
|
align-items: center;
|
background-color: #fff;
|
padding: 24rpx;
|
margin-bottom: 20rpx;
|
position: sticky;
|
top: 0;
|
z-index: 10;
|
}
|
.search-input {
|
flex: 1;
|
height: 80rpx;
|
padding: 0 24rpx;
|
background-color: #f7f7f7;
|
border-radius: 40rpx;
|
font-size: 28rpx;
|
}
|
.search-actions {
|
display: flex;
|
margin-left: 16rpx;
|
gap: 12rpx;
|
}
|
.search-btn, .reset-btn {
|
height: 80rpx;
|
line-height: 80rpx;
|
padding: 0 32rpx;
|
border-radius: 40rpx;
|
font-size: 26rpx;
|
border: none;
|
}
|
.search-btn {
|
background-color: #1E88E5;
|
color: #fff;
|
}
|
.reset-btn {
|
background-color: #e0e0e0;
|
color: #666;
|
}
|
|
/* 列表容器 */
|
.list-container {
|
padding: 0 24rpx;
|
}
|
.loading-box, .empty-box {
|
padding: 100rpx 0;
|
text-align: center;
|
color: #999;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 20rpx;
|
}
|
|
.rotate {
|
animation: rotate 2s linear infinite;
|
}
|
|
@keyframes rotate {
|
from { transform: rotate(0deg); }
|
to { transform: rotate(360deg); }
|
}
|
|
/* 卡片样式 */
|
.project-card {
|
background-color: #fff;
|
border-radius: 16rpx;
|
padding: 24rpx;
|
margin-bottom: 24rpx;
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04);
|
transition: all 0.3s;
|
border: 1rpx solid transparent;
|
}
|
|
/* 子树项样式 */
|
.subtree-item {
|
background-color: #eeeeee; /* 加深背景颜色 */
|
box-shadow: none; /* 去掉阴影,使其看起来更像嵌入的 */
|
border: 1rpx solid #e0e0e0;
|
}
|
|
.subtree-item .project-title {
|
color: #444; /* 背景深了,文字颜色稍微调深一点保证清晰度 */
|
font-size: 30rpx;
|
}
|
|
.subtree-item .value {
|
color: #555;
|
}
|
|
.subtree-item .label {
|
color: #777373;
|
}
|
|
.subtree-item .card-body,
|
.subtree-item .card-footer {
|
border-top-color: #ddd;
|
}
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
margin-bottom: 20rpx;
|
}
|
.title-wrapper {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
gap: 8rpx;
|
cursor: pointer;
|
}
|
.title-wrapper:active {
|
opacity: 0.7;
|
}
|
.project-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
color: #333;
|
line-height: 1.4;
|
}
|
.status-tags {
|
display: flex;
|
gap: 8rpx;
|
margin-left: 16rpx;
|
}
|
.tag {
|
font-size: 22rpx;
|
padding: 4rpx 12rpx;
|
border-radius: 4rpx;
|
}
|
.type-tag {
|
background-color: #E3F2FD;
|
color: #1E88E5;
|
}
|
.status-tag {
|
background-color: #F5F5F5;
|
color: #999;
|
}
|
.status-1 {
|
background-color: #E8F5E9;
|
color: #4CAF50;
|
}
|
.status-2 {
|
background-color: #FFF3E0;
|
color: #FF9800;
|
}
|
|
/* 卡片主体 */
|
.card-body {
|
border-top: 1rpx solid #f0f0f0;
|
padding-top: 20rpx;
|
}
|
.info-row {
|
margin-bottom: 12rpx;
|
display: flex;
|
}
|
.info-row-group {
|
display: flex;
|
margin-bottom: 12rpx;
|
}
|
.info-item {
|
flex: 1;
|
display: flex;
|
}
|
.label {
|
font-size: 26rpx;
|
color: #999;
|
white-space: nowrap;
|
}
|
.value {
|
font-size: 26rpx;
|
color: #333;
|
}
|
.highlight {
|
color: #f44336;
|
font-weight: bold;
|
}
|
.content-text {
|
flex: 1;
|
display: -webkit-box;
|
-webkit-box-orient: vertical;
|
-webkit-line-clamp: 2;
|
overflow: hidden;
|
}
|
|
/* 卡片底部按钮 */
|
.card-footer {
|
border-top: 1rpx solid #f0f0f0;
|
margin-top: 20rpx;
|
padding-top: 20rpx;
|
display: flex;
|
justify-content: flex-end;
|
gap: 20rpx;
|
}
|
.action-btn {
|
display: flex;
|
align-items: center;
|
gap: 8rpx;
|
padding: 0 24rpx;
|
height: 64rpx;
|
line-height: 64rpx;
|
background-color: #fff;
|
border: 1rpx solid #eee;
|
border-radius: 32rpx;
|
font-size: 24rpx;
|
}
|
.view-btn text { color: #1E88E5; }
|
.process-btn text { color: #26A69A; }
|
|
/* 分页 */
|
.pagination-box {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 30rpx 24rpx;
|
color: #666;
|
font-size: 24rpx;
|
}
|
.pager {
|
display: flex;
|
align-items: center;
|
gap: 20rpx;
|
}
|
.pager button {
|
height: 60rpx;
|
line-height: 60rpx;
|
padding: 0 20rpx;
|
font-size: 24rpx;
|
background-color: #fff;
|
border: 1rpx solid #ddd;
|
}
|
.page-num {
|
font-weight: bold;
|
}
|
</style>
|