index.vue 7.46 KB
<template>
  <view class="container">
    <!-- 归属单位选择 -->
    <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom style="padding: 0 15px">
      <up-form-item
          label="归属单位"
          prop="companyId"
          @click="showActionSheet = true"
          class="form-item-custom"
      >
        <up-input
            v-model="formData.companyId"
            placeholder="请选择归属单位"
            disabled
            disabled-color="#ffffff"
            border="none"
            bg-color="transparent"
        />
        <template #right>
          <up-icon name="arrow-right" size="16"></up-icon>
        </template>
      </up-form-item>
    </up-form>

    <!-- 弹窗式 Search 搜索组件 -->
    <view class="search-wrap">
      <up-search
          v-model="searchValue"
          placeholder="请输入道路名称搜索"
          @search="handleSearch"
          bg-color="#f5f5f5"
          :clearabled="false"
          :show-action="true"
          actionText="搜索"
          :animation="true"
          @custom="handleSearch"
      />
    </view>

    <!-- ✅ 核心:uview-plus up-row+up-col 实现左右布局【无u-scroll-list,无任何多余组件】 -->
    <up-row type="flex" class="cate-layout" align="flex-start">
      <!-- 左侧:班组列表 (uview栅格列 + 原生滚动) -->
      <up-col span="3" class="cate-left">
          <view
              class="left-item"
              :class="{ active: currentIndex === index }"
              v-for="(item, index) in cateTabList"
              :key="item.deptId"
              @click="cateTabChange(index)"
          >
            {{ item.deptName }}
          </view>

      </up-col>

      <!-- 右侧:道路列表 (uview栅格列 + 原生滚动) -->
      <up-col span="9" class="cate-right">
        <scroll-view scroll-y class="right-scroll">
          <!-- 暂无数据 -->
<!--          <empty-view v-if="!hasValidRoadId" style="margin-top: 100px"></empty-view>-->
          <up-empty v-if="!hasValidRoadId" marginTop="100" mode="list"></up-empty>
          <!-- 道路数据列表 -->
          <view v-else class="road-list-wrap">
            <view
                v-for="item in roads"
                class="card-wrap cad-box-shadow"
                :key="item.roadId"
                @click="toNewPage(item.roadId, item.treeCount)"
            >
              <p class="fs-flex__between">
                <span class="up-line-1" style="color: #333;font-size: 14px">{{ item.roadName }}</span>
                <span class="treeCount" style="font-size: 14px">{{ item.treeCount }}棵</span>
              </p>
              <p class="up-line-1 fs-my8" style="color: #333;font-size: 14px">已录入行道树:{{ item.recordedCount }}棵</p>
              <p class="up-line-1 fs-my8" style="color: #999;font-size: 12px">起点:{{ item.startRemark }}</p>
              <p class="up-line-1" style="color: #999;font-size: 12px">终点:{{ item.endRemark }}</p>
            </view>
          </view>
        </scroll-view>
      </up-col>
    </up-row>

    <!-- ActionSheet 底部弹出选择菜单 -->
    <up-action-sheet
        :show="showActionSheet"
        :actions="belongCompanyData"
        title="请选择归属单位"
        @select="actionSheetSelect"
        @close="showActionSheet = false"
    ></up-action-sheet>

  </view>
</template>

<script setup>
import { ref, reactive, watch } from 'vue'
import { onShow } from '@dcloudio/uni-app';
import { getCompanyList } from "@/api/common";
import { deptListReq } from '@/api/tree-archive/tree-archive'


const formRef = ref(null)
const showActionSheet = ref(false)
const currentIndex = ref(0)
const hasValidRoadId = ref(false)
const searchValue = ref('') // 搜索关键词 独立绑定

// 表单数据
const formData = reactive({
  companyId: '',
})

// 接口数据变量
const companyId = ref('')
const belongCompanyData = ref([])  // 归属单位下拉数据
const depts = ref([])              // 归属班组列表
const roads = ref([])              // 当前选中班组的道路列表
const cateTabList = ref([])        // 左侧tab数据源

// 生命周期
onShow( async() => {
  const res = await getCompanyList()
  belongCompanyData.value = res
  if (belongCompanyData.value.length > 0) {
    formData.companyId = belongCompanyData.value[0].name
    companyId.value = belongCompanyData.value[0].id.toString()
    deptListQuery()
  }
})

// 监听 CateTab 选中下标 数据联动
watch(currentIndex, () => {
  if(depts.value.length > 0) {
    roads.value = depts.value[currentIndex.value].roads
    checkRoadDataValid()
  }
})

// 搜索事件 - 点击搜索按钮/回车触发
const handleSearch = () => {
  deptListQuery()
}

// 跳转道路档案记录页
const toNewPage = (roadId, treeCount) => {
  uni.navigateTo({
    url: `/pages-sub/data/tree-archive/treeRecord?roadId=${roadId}&count=${treeCount}`
  })
}

// 查询班组+道路数据 & 格式化CateTab的数据源
const deptListQuery = async () => {
  const params = {
    companyId: companyId.value,
    roadName: searchValue.value
  }
  currentIndex.value=0
  const res = await deptListReq(params)
  if (res.length ==0) {
    depts.value = []
    roads.value = []
    cateTabList.value = []
    hasValidRoadId.value = false
  } else {
    depts.value = res[0].depts
    cateTabList.value = depts.value
    roads.value = depts.value[0].roads
    checkRoadDataValid()
  }
}

// 左侧班组切换事件
const cateTabChange = (index) => {
  currentIndex.value = index
  roads.value = depts.value[index].roads
  checkRoadDataValid()
}

// ActionSheet 选择归属单位的确认事件
const actionSheetSelect = (val) => {
  formData.companyId = val.name
  companyId.value = val.id.toString()
  showActionSheet.value = false // 关闭弹窗
  deptListQuery() // 重新查询数据
}

// 校验是否有有效道路数据
const checkRoadDataValid = () => {
  hasValidRoadId.value = roads.value && roads.value.length > 0 && roads.value.some(item => {
    return item.roadId !== null && item.roadId !== undefined && item.roadId
  })
}
</script>

<style scoped lang="scss">
// 页面容器 满高布局
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
  box-sizing: border-box;
}

// 搜索框外层容器 间距不变
.search-wrap {
  padding: 10rpx 15rpx;
}

.cate-layout {
  flex: 1;
  width: 100%;
  height: calc(100vh - 44px);

}


.cate-left {
  height: 100%;
  padding: 0;
  background: #f8f8f8;
  box-sizing: border-box;
  .left-scroll {
    width: 100%;
    height: 100%;
  }
  // 左侧列表项
  .left-item {
    padding: 24rpx 12rpx;
    font-size: 28rpx;

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    box-sizing: border-box;
  }
  // 选中项高亮 主题色和你一致 #5f5fe2
  .left-item.active {
    background: #ffffff;
    color: #5f5fe2;
    font-weight: 500;
    border-left: 4rpx solid #5f5fe2;
  }
}

.cate-right {
  height: 100%;
  padding: 0 10rpx;
  box-sizing: border-box;
  background: #ffffff;
  .right-scroll {
    width: 100%;
    height: 100%;
  }
}

// 道路列表容器
.road-list-wrap {
  //padding-bottom: 30rpx;
}

// 道路卡片样式 完全复用你的原版
.card-wrap {
  box-shadow:0 0 3px rgba(0, 0, 0, 0.2);
  padding: 20rpx;
  border-radius: 14rpx;
  background: #fff;
  margin:10px 6px;
}

// 公共样式 完全不变
.treeCount {
  color: #5f5fe2;
  min-width: 70px;
  text-align: right;
}
.fs-flex__between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.fs-my8 { margin: 8rpx 0; }
</style>