index.vue 10.5 KB
<template>
  <view class="main-container">
    <!-- 吸顶区域 -->
    <up-sticky>
      <view class="sticky-wrap">
        <!-- 第一行标签:养护类型 -->
        <up-tabs
            v-model="activeType"
            :list="typeTabs"
            line-width="40rpx"
            active-color="#1989fa"
            inactive-color="#666"
            :scrollable="true"
            class="first-tabs"
            @click="handleTypeChange"
        ></up-tabs>

        <!-- 第二行标签:状态筛选 -->
        <up-tabs
            v-model="activeStatus"
            :list="statusTabs"
            line-width="40rpx"
            active-color="#1989fa"
            inactive-color="#666"
            :scrollable="true"
            class="second-tabs"
            @click="handleStatusChange"
        ></up-tabs>

        <!-- 动态搜索框(道路名称/计划名称) -->
        <up-search
            v-model="searchValue"
            :placeholder="searchPlaceholder"
            bg-color="#f5f5f5"
            shape="round"
            :show-action="true"
            actionText="搜索"
            :animation="true"
            @search="handleSearch"
            @custom="handleSearch"
            :clearabled="false"
            maxlength="50"
            style="margin: 20rpx 20rpx 0"
        ></up-search>
      </view>
    </up-sticky>

    <!-- 内容区域 - 集成z-paging分页 -->
    <z-paging
        ref="pagingRef"
        v-model="currentList"
        @query="fetchData"
        :top="200"
    :bottom="20"
    :page-size="pageSize"
    >
    <!-- 空数据提示 -->
    <template #empty>
      <empty-view/>
    </template>

    <!-- 加载中提示(z-paging内置,可自定义) -->
    <template #loading>
      <view class="loading-tip">
        <up-loading-page text="加载中..."></up-loading-page>
      </view>
    </template>

    <!-- 列表内容 -->
    <view class="content-wrap">
      <!-- 道路类型卡片 -->
      <view v-if="activeType === '道路'" class="card-list">
        <view
            class="card-item"
            v-for="(item, index) in currentList"
            :key="index"
        >
          <view class="card-content">
            <view class="card-text up-line-1">
              <span class="field-name">道路名称:</span>{{ item.roadName || '-' }}
            </view>
            <view class="card-text up-line-1">
              <span class="field-name">所属街道:</span>{{ item.streetName || '-' }}
            </view>
            <!-- 养护级别行增加计划明细按钮 -->
            <view class="card-text up-line-1">
              <span class="field-name">养护级别:</span>{{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}
              <view class="inline-action" @click="goToDetail(item)">
                计划明细
              </view>
            </view>
            <view class="card-text up-line-1">
              <span class="field-name">计划时间:</span>{{ timeFormat(item.beginTime,'yyyy-mm-dd') || '-'}} 至 {{ timeFormat(item.endTime,'yyyy-mm-dd') || '-'}}
            </view>
          </view>
        </view>
      </view>

      <!-- 其他养护类型卡片(补植/浇水等) -->
      <view v-else class="card-list">
        <view
            class="card-item"
            v-for="(item, index) in currentList"
            :key="index"
        >
          <view class="card-content">
            <view class="card-text up-line-1 font-bold">{{ item.planName || '-' }}</view>
            <view class="card-text up-line-1">
              <span class="field-name">计划编码:</span>{{ item.planNo || '-' }}
            </view>
            <view class="card-text up-line-1">
              <span class="field-name">养护周期:</span>{{ item.rate || '-' }} {{ uni.$dict.getDictLabel('cycle_id_type', item.cycleId) }}
            </view>
            <view class="card-text up-line-1">
              <span class="field-name">计划完成次数:</span>{{ item.planNum || 0 }}
            </view>
            <!-- 已完成次数行增加提交记录按钮 -->
            <view class="card-text up-line-1">
              <span class="field-name">完成比较:</span>{{ item.finishPercent || 0 }}%
              <view class="inline-action submit-btn" @click="submitRecord(item)">
                提交记录
              </view>
            </view>
            <view class="card-text up-line-1">
              <span class="field-name">计划有效期:</span> {{timeFormat(item.beginTime,'yy-mm-dd hh:MM:ss')}} 至 {{timeFormat(item.endTime,'yy-mm-dd hh:MM:ss')}}
            </view>
          </view>
        </view>
      </view>
    </view>
    </z-paging>
  </view>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { roadPage, getRoadDetails, planTypePage } from "@/api/maintain-manage/maintain-manage";
import { timeFormat } from '@/uni_modules/uview-plus';

// 初始化响应式数据
const typeTabs = ref([])
const statusTabs = ref([
  { name: '待完成', id: '1' },
  { name: '已失效', id: '3' },
  { name: '已完成', id: '2' }
])

// 核心响应式数据
const activeType = ref('道路')
const activeStatus = ref('1')
const searchValue = ref('')
const pagingRef = ref(null) // z-paging实例

// 分页参数
const pageSize = ref(10)
const currentList = ref([]) // z-paging绑定的列表

// 处理字典数据的方法
const handleDictData = () => {
  // 获取养护类型字典
  const tabList = uni.$dict.getDictSimpleList('maintain_type')
  console.log('原始字典数据:', tabList)

  if (!tabList || tabList.length === 0) {
    console.warn('养护类型字典数据为空,请检查字典配置')
    typeTabs.value = [{ name: '道路', planTypeId: '', id: '道路' }]
    return
  }

  // 1. 过滤掉临时养护(包含"临时养护"的项)
  const filteredList = tabList.filter(item => !item.label.includes('临时养护'))

  // 2. 转换为 {name: 字典原生标签, planTypeId: 字典值, id: 标签名} 格式
  const convertedList = filteredList.map(item => ({
    name: item.label, // 直接使用字典原始名称
    planTypeId: item.value,
    id: item.label // 兼容up-tabs的id字段
  }))

  // 3. 补充道路类型(放在第一位)
  convertedList.unshift({
    name: '道路',
    planTypeId: '',
    id: '道路'
  })

  // 赋值给typeTabs
  typeTabs.value = convertedList
  console.log('处理后的字典数据:', typeTabs.value)
}

// 动态搜索框占位符
const searchPlaceholder = computed(() => {
  return activeType.value === '道路' ? '请输入道路名称' : '请输入计划名称'
})

// 养护类型切换
const handleTypeChange = (item) => {
  console.log('切换养护类型:', item)
  activeType.value = item.name
  searchValue.value = ''
  // 重置分页并刷新
  pagingRef.value?.reload()
}

// 状态筛选切换
const handleStatusChange = (item) => {
  console.log('切换状态:', item)
  activeStatus.value = item.id
  // 重置分页并刷新
  pagingRef.value?.reload()
}

// 搜索处理
const handleSearch = () => {
  console.log('搜索关键词:', searchValue.value)
  // 重置分页并刷新
  pagingRef.value?.reload()
}

// 核心数据请求方法(适配z-paging的query回调)
const fetchData = async (pageNo, pageSize) => {
  try {
    let res = null
    // 道路类型请求
    if (activeType.value === '道路') {
      res = await roadPage({
        roadName: searchValue.value.trim(),
        pageNo,
        pageSize,
        finishState: activeStatus.value
      })
    } else {
      // 其他养护类型请求
      // 找到当前类型对应的planTypeId
      const currentType = typeTabs.value.find(item => item.name === activeType.value)
      res = await planTypePage({
        planTypeId: currentType?.planTypeId || '',
        planName: searchValue.value.trim(),
        pageNo,
        pageSize,
        finishState: activeStatus.value
      })
    }

    // 告诉z-paging数据加载完成
    // res.list为当前页数据,res.total为总条数(如果接口返回)
    pagingRef.value?.complete(res?.list || [], res?.total)
  } catch (error) {
    console.error('请求失败:', error)
    uni.showToast({ title: '网络异常,请重试', icon: 'none' })
    // 加载失败,告诉z-paging
    pagingRef.value?.complete(false)
  }
}

// 跳转到计划明细页面
const goToDetail = (item) => {
  uni.navigateTo({
    url: `/pages-sub/daily/maintain-manage/road-detail-list?roadId=${item.roadId}&finish_state=${item.finishState || ''}`
  })
}

// 提交记录
const submitRecord = (item) => {
  uni.navigateTo({
    url: `/pages/submitRecord/submitRecord?planId=${item.id || ''}&planName=${encodeURIComponent(item.planName || '')}`
  })
  console.log('提交记录:', item)
}

// 页面加载时初始化数据
onLoad(() => {
  // 先处理字典数据
  handleDictData()
  // 初始化分页数据
  pagingRef.value?.reload()
})
</script>

<style scoped lang="scss">
.main-container {
  min-height: 100vh;
  background-color: #f8f8f8;
}

// 吸顶区域样式
.sticky-wrap {
  background-color: #fff;
  padding-bottom: 10rpx;
  border-bottom: 1px solid #eee;

  .first-tabs, .second-tabs {
    margin: 10rpx 0;
  }
}

// 内容区域样式
.content-wrap {
  padding: 20rpx;
  box-sizing: border-box;
}

// 卡片列表样式
.card-list {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
}

// 卡片项样式
.card-item {
  background-color: #fff;
  border-radius: 12rpx;
  padding: 20rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);

  .card-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 12rpx;

    .card-text {
      font-size: 28rpx;
      color: #333;
      line-height: 1.4;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between; // 让文本和按钮两端对齐

      &.font-bold {
        font-weight: 600;
        font-size: 30rpx;
      }

      .field-name {
        color: #999;
        display: inline-block;
        margin-right: 15rpx;
        flex-shrink: 0;
      }
    }
  }
}

// 行内操作按钮样式
.inline-action {
  font-size: 26rpx;
  color: #1989fa;
  padding: 4rpx 12rpx;
  border-radius: 4rpx;
  background-color: #f0f8ff;
  white-space: nowrap;
  float: right;
  &.submit-btn {
    background-color: #1989fa;
    color: #fff;
  }
}

// 空数据提示
.empty-tip {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300rpx;
  font-size: 28rpx;
  color: #999;
}

// 加载中提示
.loading-tip {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300rpx;
}
</style>