Files
td_official/src/views/project/landTransfer/BusinessLedger/landTransferLedger/index.vue
2025-09-09 09:42:28 +08:00

1381 lines
52 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="p-2 detailbox">
<div class="box1">
<div>
<div>
<span>设计面积</span>
<span>{{ detailInfo.areaSum }} </span>
</div>
<el-icon :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
<div>
<div>
<span>已流转面积</span>
<span>{{ detailInfo.transferAreaSum }} </span>
</div>
<el-icon :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
<div>
<div>
<span>租金</span>
<span>{{ detailInfo.rentSum / 1000 }} 万元</span>
</div>
<el-icon :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
</div>
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="never">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="110px">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="queryParams.transferStatus" placeholder="请选择流转台账状态" clearable>
<el-option label="待流转" :value="0"></el-option>
<el-option label="已流转" :value="1"></el-option>
<el-option label="不流转" :value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="queryParams.responsiblePerson" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['land:landTransferLedger:add']">新增</el-button>
</el-col>
<el-col :span="6"></el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="landTransferLedgerList" @selection-change="handleSelectionChange">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="进场道路" align="center" prop="roadName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="预计完成时间" align="center" prop="expectedFinishDate" width="180"> </el-table-column>
<el-table-column label="流转状态" align="center" prop="type" />
<el-table-column label="已流转面积(亩)" align="center" prop="transferArea" width="180" />
<el-table-column label="不流转面积(亩)" align="center" prop="noTrans" width="180" />
<el-table-column label="未流转面积(亩)" align="center" prop="noTransferAea" width="180" />
<el-table-column label="流转比例(%)" align="center" width="180">
<template #default="scope">
{{ scope.row.transferArea && scope.row.designArea ? ((scope.row.transferArea / scope.row.designArea) * 100).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="土地租金(元)" align="center" prop="landRentAll" width="180" />
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensationAll" width="180" />
<el-table-column label="总金额(元)" align="center" prop="totalAmountAll" width="150" />
<el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope">
<!-- 查看子项按钮 -->
<el-tooltip content="查看子项" placement="top">
<el-button link type="primary" @click="handleViewSons(scope.row)" v-hasPermi="['land:landTransferLedger:childrenList']">
查看子项
</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landTransferLedger:remove']">删除</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 子项列表弹窗 -->
<el-dialog draggable title="子项列表" v-model="sonDialog.visible" width="1300px" append-to-body>
<el-card shadow="never">
<!-- 子项列表统计展示区域 -->
<div class="summary-box">
<div class="summary-item design-area">
<div class="summary-content">
<span class="summary-label">设计面积</span>
<span class="summary-value">{{ sonSummaryInfo.parentDesignArea }} </span>
</div>
<el-icon class="summary-icon" :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
<div class="summary-item transfer-area">
<div class="summary-content">
<span class="summary-label">已流转面积()</span>
<span class="summary-value">{{ sonSummaryInfo.totalTransferArea }} </span>
</div>
<el-icon class="summary-icon" :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
<div class="summary-item non-transfer-area">
<div class="summary-content">
<span class="summary-label">不流转面积()</span>
<span class="summary-value">{{ sonSummaryInfo.totalNonTransferArea }} </span>
</div>
<el-icon class="summary-icon" :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
<div class="summary-item remaining-area">
<div class="summary-content">
<span class="summary-label">未流转面积()</span>
<span class="summary-value">{{ sonSummaryInfo.remainingArea }} </span>
</div>
<el-icon class="summary-icon" :size="50" color="#3176ff">
<Postcard />
</el-icon>
</div>
</div>
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAddSon" v-hasPermi="['land:landTransferLedger:childrenAdd']">
新增子项
</el-button>
</el-col>
</el-row>
</template>
<!-- 已流转子项 -->
<div v-if="sonTransferLedgerList1.length > 0">
<h4 style="margin-bottom: 10px; color: #3176ff">已流转</h4>
<el-table v-loading="sonLoading" :data="sonTransferLedgerList1" @selection-change="handleSonSelectionChange">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
<el-table-column label="已流转面积(亩)" align="center" prop="areaValue" width="180" />
<el-table-column label="流转比例(%)" align="center" prop="transferRatio" width="180" />
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180" />
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180" />
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150" />
<el-table-column label="状态说明" align="center" prop="statusDescription" />
<el-table-column label="问题总结" align="center" prop="issueSummary" />
<el-table-column label="下一步策略" align="center" prop="nextStrategy" width="180" />
</el-table>
</div>
<!-- 不流转子项 -->
<div v-if="sonTransferLedgerList2.length > 0">
<h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff6b6b">不流转</h4>
<el-table v-loading="sonLoading" :data="sonTransferLedgerList2" @selection-change="handleSonSelectionChange">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
<el-table-column label="不流转面积(亩)" align="center" prop="areaValue" width="180" />
<el-table-column label="不签合同面积(亩)" align="center" prop="noContractArea" width="180" />
<el-table-column label="不测量面积(亩)" align="center" prop="noSurveyArea" width="180" />
<el-table-column label="不签合同原因" align="center" prop="noContractReason" width="180" />
<el-table-column label="不流转原因" align="center" prop="nonTransferReason" width="180" />
</el-table>
</div>
<!-- 未流转子项 -->
<div v-if="sonTransferLedgerList0.length > 0">
<h4 style="margin-top: 20px; margin-bottom: 10px; color: #ffc107">未流转子项</h4>
<el-table v-loading="sonLoading" :data="sonTransferLedgerList0" @selection-change="handleSonSelectionChange">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="土地类型" align="center" prop="landTypeName" />
<el-table-column label="地块" align="center" prop="landName" />
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
</el-table>
</div>
<!-- 无数据提示 -->
<div v-if="sonLandTransferLedgerList.length === 0 && !sonLoading" class="text-center py-10">
<el-empty description="暂无子项数据" />
</div>
</el-card>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleCloseSonDialog">关闭</el-button>
</div>
</template>
</el-dialog>
<!-- 新增子项对话框 -->
<el-dialog draggable :title="sonFormDialog.title" v-model="sonFormDialog.visible" width="600px" append-to-body>
<el-form ref="sonLandTransferLedgerFormRef" :model="sonForm" :rules="sonRules" label-width="120px">
<el-row>
<el-col :span="24">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="sonForm.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange" :disabled="true">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<!-- 当enterRoadList有数据时才显示进场道路选择框 -->
<el-col :span="24" v-if="enterRoadList.length > 0">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="sonForm.enterRoadId" clearable placeholder="请选择进场道路" :disabled="true">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="sonForm.landType" placeholder="请选择土地类型" clearable :disabled="true">
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="sonForm.transferStatus" placeholder="请选择流转台账状态" clearable @change="calcSonTransferRatio">
<el-option
v-for="dict in land_transfer_status.filter((item) => item.value !== '0')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input type="number" v-model="sonForm.designArea" placeholder="请输入设计面积" @input="calcSonTransferRatio" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="sonForm.responsiblePerson" placeholder="请输入责任人" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus != '2'">
<el-form-item label="预计完成日期" prop="expectedFinishDate">
<el-date-picker
clearable
v-model="sonForm.expectedFinishDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择预计完成时间"
:disabled="true"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="已流转面积(亩)" prop="areaValue">
<el-input v-model="sonForm.areaValue" type="number" placeholder="请输入已流转面积" @input="calcSonTransferRatio" />
<div style="color: #ff4d4f; font-size: 12px; margin-top: 4px">
{{ sonForm.areaValue && sonForm.transferStatus == '1' ? `提示:当前剩余${sonSummaryInfo.remainingArea}` : '' }}
</div>
</el-form-item>
</el-col>
<!-- 流转比例改为禁用输入自动计算展示 -->
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="流转比例(%)" prop="transferRatio">
<el-input v-model="sonForm.transferRatio" type="text" :disabled="true" placeholder="自动计算中..." />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="土地租金(元)" prop="landRent">
<el-input type="number" v-model="sonForm.landRent" placeholder="请输入土地租金" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="青苗赔偿(元)" prop="seedlingCompensation">
<el-input v-model="sonForm.seedlingCompensation" type="number" placeholder="请输入青苗赔偿" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="总金额(元)" prop="totalAmount">
<el-input type="number" v-model="sonForm.totalAmount" placeholder="请输入总金额" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
<el-form-item label="不流转面积(亩)" prop="areaValue">
<el-input v-model="sonForm.areaValue" type="number" placeholder="请输入不流转面积" />
<div style="color: #ff4d4f; font-size: 12px; margin-top: 4px">
{{ sonForm.areaValue && sonForm.transferStatus == '2' ? `提示:当前剩余 ${sonSummaryInfo.remainingArea}` : '' }}
</div>
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
<el-form-item label="不签合同面积(亩)" prop="noContractArea">
<el-input v-model="sonForm.noContractArea" type="number" placeholder="请输入不签合同面积" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
<el-form-item label="不测量面积(亩)" prop="noSurveyArea">
<el-input v-model="sonForm.noSurveyArea" type="number" placeholder="请输入不测量面积" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
<el-form-item label="不签合同原因" prop="noContractReason">
<el-input v-model="sonForm.noContractReason" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
<el-form-item label="不流转原因" prop="nonTransferReason">
<el-input v-model="sonForm.nonTransferReason" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="状态说明" prop="statusDescription">
<el-input v-model="sonForm.statusDescription" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="问题总结" prop="issueSummary">
<el-input v-model="sonForm.issueSummary" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="sonForm.transferStatus == '1'">
<el-form-item label="下一步策略" prop="nextStrategy">
<el-input v-model="sonForm.nextStrategy" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button v-hasPermi="['land:landTransferLedger:addSon']" :loading="sonButtonLoading" type="primary" @click="submitSonForm"
> </el-button
>
<el-button @click="cancelSonForm"> </el-button>
</div>
</template>
</el-dialog>
<!-- 新增主项对话框 -->
<el-dialog draggable :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body>
<el-form ref="landTransferLedgerFormRef" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="24">
<el-form-item label="对应地块" prop="landBlockId">
<el-select v-model="form.landBlockId" clearable placeholder="请选择对应地块" @change="handleLandBlockChange">
<el-option v-for="item in landBlockList" :key="item.id" :label="item.landName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<!-- 当enterRoadList有数据时才显示进场道路选择框 -->
<el-col :span="24" v-if="enterRoadList.length > 0">
<el-form-item label="进场道路" prop="enterRoadId">
<el-select v-model="form.enterRoadId" clearable placeholder="请选择进场道路">
<el-option v-for="item in enterRoadList" :key="item.id" :label="item.roadName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="土地类型" prop="landType">
<el-select v-model="form.landType" placeholder="请选择土地类型" clearable>
<el-option v-for="dict in land_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="流转台账状态" prop="transferStatus">
<el-select v-model="form.transferStatus" placeholder="请选择流转台账状态" clearable @change="calcTransferRatio">
<el-option
v-for="dict in land_transfer_status.filter((item) => item.value === '0')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设计面积(亩)" prop="designArea">
<el-input type="number" v-model="form.designArea" placeholder="请输入设计面积" @input="calcTransferRatio" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="责任人" prop="responsiblePerson">
<el-input v-model="form.responsiblePerson" placeholder="请输入责任人" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus != '2'">
<el-form-item label="预计完成日期" prop="expectedFinishDate">
<el-date-picker clearable v-model="form.expectedFinishDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择预计完成时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="已流转面积(亩)" prop="transferAea">
<el-input v-model="form.transferAea" type="number" placeholder="请输入已流转面积" @input="calcTransferRatio" />
</el-form-item>
</el-col>
<!-- 流转比例改为禁用输入自动计算展示 -->
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="流转比例(%)" prop="transferRatio">
<el-input v-model="form.transferRatio" type="text" :disabled="true" placeholder="自动计算中..." />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="土地租金(元)" prop="landRent">
<el-input type="number" v-model="form.landRent" placeholder="请输入土地租金" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="青苗赔偿(元)" prop="seedlingCompensation">
<el-input v-model="form.seedlingCompensation" type="number" placeholder="请输入青苗赔偿" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="总金额(元)" prop="totalAmount">
<el-input type="number" v-model="form.totalAmount" placeholder="请输入总金额" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '2'">
<el-form-item label="不签合同面积(亩)" prop="noContractArea">
<el-input v-model="form.noContractArea" type="number" placeholder="请输入不签合同面积" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '2'">
<el-form-item label="不测量面积(亩)" prop="noSurveyArea">
<el-input v-model="form.noSurveyArea" type="number" placeholder="请输入不测量面积" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '2'">
<el-form-item label="不签合同原因" prop="noContractReason">
<el-input v-model="form.noContractReason" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '2'">
<el-form-item label="不流转原因" prop="nonTransferReason">
<el-input v-model="form.nonTransferReason" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="状态说明" prop="statusDescription">
<el-input v-model="form.statusDescription" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="问题总结" prop="issueSummary">
<el-input v-model="form.issueSummary" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.transferStatus == '1'">
<el-form-item label="下一步策略" prop="nextStrategy">
<el-input v-model="form.nextStrategy" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button v-hasPermi="['land:landTransferLedger:add']" :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="LandTransferLedger" lang="ts">
import {
listLandTransferLedger,
getLandTransferLedger,
delLandTransferLedger,
addLandTransferLedger,
landTransferLedgerCount,
listallCountValue,
// 新增子项相关接口
listSonLandTransferLedger,
addSonLandTransferLedger
} from '@/api/system/landTransfer/landTransferLedger';
import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
import { LandTransferLedgerVO, LandTransferLedgerQuery, LandTransferLedgerForm } from '@/api/system/landTransfer/landTransferLedger/types';
import { useUserStoreHook } from '@/store/modules/user';
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
import { getCurrentInstance, ComponentInternalInstance, watch, onUnmounted, onMounted } from 'vue';
import { ElFormInstance } from 'element-plus';
import { area } from '@turf/turf';
// 类型定义补充
interface DialogOption {
visible: boolean;
title: string;
}
interface PageData<T, Q> {
form: T;
queryParams: Q;
rules: Record<string, any[]>;
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const landTransferLedgerList = ref<LandTransferLedgerVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const landBlockList = ref([]);
const queryFormRef = ref<ElFormInstance>();
const landTransferLedgerFormRef = ref<ElFormInstance>();
const enterRoadList = ref([]);
// 字典数据
const { land_type, land_transfer_status } = toRefs<any>(proxy?.useDict('land_type', 'land_transfer_status'));
// 主项弹窗配置
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
// 子项相关状态
const sonDialog = reactive<DialogOption>({
visible: false,
title: '子项列表'
});
const sonFormDialog = reactive<DialogOption>({
visible: false,
title: '新增子项'
});
const sonLandTransferLedgerList = ref<LandTransferLedgerVO[]>([]);
const sonLoading = ref(false);
const sonTotal = ref(0);
const sonIds = ref<Array<string | number>>([]);
const sonButtonLoading = ref(false);
const sonLandTransferLedgerFormRef = ref<ElFormInstance>();
// 当前父项ID用于子项操作
const currentParentId = ref<number | string | undefined>(undefined);
// 子项查询参数
const sonQueryParams = reactive<LandTransferLedgerQuery>({
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
parentId: undefined,
params: {},
listType: 2 // 标识为子项列表
});
// 表单初始数据
const initFormData: LandTransferLedgerForm = {
id: undefined,
parentId: undefined,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
noContractArea: undefined,
noContractReason: undefined,
noSurveyArea: undefined,
nonTransferReason: undefined
};
// 核心数据响应式对象
const data = reactive<PageData<LandTransferLedgerForm, LandTransferLedgerQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
landType: undefined,
landBlockId: undefined,
enterRoadId: undefined,
designArea: undefined,
responsiblePerson: undefined,
expectedFinishDate: undefined,
transferAea: undefined,
transferRatio: undefined,
landRent: undefined,
seedlingCompensation: undefined,
totalAmount: undefined,
transferStatus: undefined,
statusDescription: undefined,
issueSummary: undefined,
nextStrategy: undefined,
params: {},
listType: 1 // 标识为主项列表
},
rules: {
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
landBlockId: [{ required: true, message: '请选择对应地块', trigger: 'change' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }],
transferStatus: [{ required: true, message: '请选择流转台账状态', trigger: 'change' }],
designArea: [{ required: true, message: '请输入设计面积', trigger: 'blur' }],
responsiblePerson: [{ required: true, message: '请输责任人', trigger: 'blur' }],
expectedFinishDate: [{ required: true, message: '请选择预计完成时间', trigger: 'change' }],
transferRatio: [
{
required: true,
message: '流转比例不能为空',
trigger: ['blur', 'change'],
validator: (rule, value, callback) => {
if (data.form.transferStatus !== '1') {
callback();
return;
}
if (value === undefined || value === null || value === '') {
callback(new Error('流转比例不能为空'));
} else {
callback();
}
}
},
{
validator: (rule, value, callback) => {
if (value < 0 || value > 100) {
callback(new Error('流转比例必须在 0-100 之间'));
} else {
callback();
}
},
trigger: 'blur'
}
]
}
});
// 子项表单数据
const sonForm = reactive<LandTransferLedgerForm>({ ...initFormData });
// 子项表单验证规则(与主项相同)
// 根据transferStatus分类的子项列表
const sonTransferLedgerList0 = computed(() => sonLandTransferLedgerList.value.filter((item) => item.transferStatus === '0'));
const sonTransferLedgerList1 = computed(() => sonLandTransferLedgerList.value.filter((item) => item.transferStatus === '1'));
const sonTransferLedgerList2 = computed(() => sonLandTransferLedgerList.value.filter((item) => item.transferStatus === '2'));
// 当前父项完整数据
const currentParentItem = ref<LandTransferLedgerVO | null>(null);
// 子项列表统计信息
const sonSummaryInfo = computed(() => {
// 1. 计算子项已流转面积总和使用areaValue字段当transferStatus为1时
const totalTransferArea = sonTransferLedgerList1.value.reduce((sum, item) => {
return sum + (parseFloat(item.areaValue || '0') || 0);
}, 0);
// 2. 计算子项不流转面积总和使用areaValue字段当transferStatus为2时
const totalNonTransferArea = sonTransferLedgerList2.value.reduce((sum, item) => {
return sum + (parseFloat(item.areaValue || '0') || 0);
}, 0);
// 3. 获取父项设计面积
const parentDesignArea = parseFloat(currentParentItem.value?.designArea || '0') || 0;
// 4. 计算未流转面积
const remainingArea = Math.max(0, parentDesignArea - totalTransferArea - totalNonTransferArea);
return {
parentDesignArea,
totalTransferArea,
totalNonTransferArea,
remainingArea
};
});
// 最近选择的父项数据,用于新增弹窗预填充
const lastSelectedParent = ref<LandTransferLedgerVO | null>(null);
const sonRules = {
projectId: [{ required: true, message: '项目ID不能为空', trigger: 'blur' }],
parentId: [{ required: true, message: '父级ID不能为空', trigger: 'blur' }],
landType: [{ required: true, message: '土地类型不能为空', trigger: 'change' }],
landRent: [{ required: true, message: '土地租金不能为空', trigger: 'blur' }],
seedlingCompensation: [{ required: true, message: '青苗赔偿不能为空', trigger: 'blur' }],
totalAmount: [{ required: true, message: '总金额不能为空', trigger: 'blur' }],
statusDescription: [{ required: true, message: '状态说明不能为空', trigger: 'blur' }],
issueSummary: [{ required: true, message: '问题总结不能为空', trigger: 'blur' }],
nextStrategy: [{ required: true, message: '下一步策略不能为空', trigger: 'blur' }],
noContractArea: [{ required: true, message: '不签约面积不能为空', trigger: 'blur' }],
noSurveyArea: [{ required: true, message: '不测量面积不能为空', trigger: 'blur' }],
noContractReason: [{ required: true, message: '不签约原因不能为空', trigger: 'blur' }],
nonTransferReason: [{ required: true, message: '不流转原因不能为空', trigger: 'blur' }],
transferRatio: [
{
required: true,
message: '流转比例不能为空',
trigger: ['blur', 'change'],
validator: (rule, value, callback) => {
if (sonForm.transferStatus !== '1') {
callback();
return;
}
if (value === undefined || value === null || value === '') {
callback(new Error('流转比例不能为空'));
} else {
callback();
}
}
},
{
validator: (rule, value, callback) => {
if (value < 0 || value > 100) {
callback(new Error('流转比例必须在 0-100 之间'));
} else {
callback();
}
},
trigger: 'blur'
}
]
};
const detailInfo = ref({
areaSum: 0,
rentSum: 0,
transferAreaSum: 0
});
const { queryParams, form, rules } = toRefs(data);
/**
* 自动计算流转比例:(已流转面积 / 设计面积) × 100保留2位小数最大100%
*/
const calcTransferRatio = () => {
// 仅已流转状态下计算
if (form.value.transferStatus !== '1') {
form.value.transferRatio = undefined;
return;
}
// 转换为数字(避免字符串计算)
const designArea = Number(form.value.designArea) || 0;
const areaValue = Number(form.value.areaValue) || 0;
// 边界处理设计面积为0时避免报错
if (designArea === 0) {
form.value.transferRatio = 0;
return;
}
// 核心计算限制最大100%保留2位小数
const ratio = Math.min((areaValue / designArea) * 100, 100);
form.value.transferRatio = Number(ratio.toFixed(2));
};
/**
* 子项自动计算流转比例
*/
const calcSonTransferRatio = () => {
// 仅已流转状态下计算
if (sonForm.transferStatus !== '1') {
sonForm.transferRatio = undefined;
return;
}
// 转换为数字(避免字符串计算)
const designArea = Number(sonForm.designArea) || 0;
const areaValue = Number(sonForm.areaValue) || 0;
// 边界处理设计面积为0时避免报错
if (designArea === 0) {
sonForm.transferRatio = 0;
return;
}
// 核心计算限制最大100%保留2位小数
const ratio = Math.min((areaValue / designArea) * 100, 100);
sonForm.transferRatio = Number(ratio.toFixed(2));
};
/** 查询项目土地流转台账列表(主项) */
const getList = async () => {
loading.value = true;
try {
const res = await listLandTransferLedger(queryParams.value);
console.log('主项接口返回数据:', res);
console.log('主项数据赋值前:', landTransferLedgerList.value);
landTransferLedgerList.value = res.rows || [];
total.value = res.total || 0;
console.log('主项数据赋值后:', landTransferLedgerList.value);
} finally {
loading.value = false;
}
};
/** 查询子项列表 */
const getSonList = async () => {
sonLoading.value = true;
try {
const res = await listSonLandTransferLedger(sonQueryParams);
console.log('子项接口返回数据:', res); // 查看res是否有rows且rows非空
console.log('子项数据赋值前:', sonLandTransferLedgerList.value);
// 处理接口返回的数据,添加缺失的显示属性
const processedData = (res.data || []).map((item) => ({
...item,
// 添加显示所需的属性
landTypeName: getLandTypeName(item.landType),
landName: getLandBlockName(item.landBlockId),
transferStatusName: getTransferStatusName(item.transferStatus)
}));
sonLandTransferLedgerList.value = processedData;
sonTotal.value = res.total || 0;
console.log('子项数据赋值后:', sonLandTransferLedgerList.value); // 确认数组有数据
} finally {
sonLoading.value = false;
}
};
/** 根据土地类型值获取名称 */
const getLandTypeName = (value) => {
if (!value) return '';
const landTypeItem = land_type?.value?.find((item) => item.value === value);
return landTypeItem?.label || '';
};
/** 根据地块ID获取地块名称 */
const getLandBlockName = (id) => {
if (!id) return '';
const landBlockItem = landBlockList.value?.find((item) => item.id === id);
return landBlockItem?.landName || '';
};
/** 根据流转状态值获取名称 */
const getTransferStatusName = (value) => {
if (!value) return '';
const statusItem = land_transfer_status?.value?.find((item) => item.value === value);
return statusItem?.label || '';
};
/** 获取地块统计信息 - 调用listallCountValue接口 */
const getLandBlockList = async () => {
try {
// 获取当前选中的项目ID
const projectId = currentProject.value?.id;
if (!projectId) {
console.error('项目ID不存在无法获取统计信息');
return;
}
// 调用listallCountValue接口传入projectId参数
const res = await listallCountValue(projectId);
// 映射返回的数据到detailInfo对象确保与模板中使用的字段一致
detailInfo.value = {
areaSum: res.data.areaSum,
rentSum: res.data.rentSum,
transferAreaSum: res.data.transferAreaSum
};
} catch (error) {
console.error('获取地块统计信息失败:', error);
}
};
/** 取消按钮(主项) */
const cancel = () => {
dialog.visible = false;
resetForm();
};
/** 取消按钮(子项) */
const cancelSonForm = () => {
sonFormDialog.visible = false;
getLandBlockList(); // 关闭子项时刷新顶部实时信息
resetSonForm();
getList(); // 关闭子项弹窗时刷新父级列表
};
/** 关闭子项列表弹窗 */
const handleCloseSonDialog = () => {
sonDialog.visible = false;
getList(); // 关闭子项列表时刷新父级列表
getLandBlockList(); // 关闭子项时刷新顶部实时信息
};
/** 表单重置(主项) */
const resetForm = () => {
form.value = { ...initFormData, projectId: currentProject.value?.id };
landTransferLedgerFormRef.value?.resetFields();
};
/** 表单重置(子项) */
const resetSonForm = () => {
// 不要重新赋值整个对象,而是修改其属性
Object.assign(sonForm, {
...initFormData,
projectId: currentProject.value?.id,
parentId: currentParentId.value
});
sonLandTransferLedgerFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据(主项) */
const handleSelectionChange = (selection: LandTransferLedgerVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length !== 1;
multiple.value = selection.length === 0;
};
/** 多选框选中数据(子项) */
const handleSonSelectionChange = (selection: LandTransferLedgerVO[]) => {
sonIds.value = selection.map((item) => item.id);
};
/** 新增主项按钮操作 */
const handleAdd = () => {
resetForm();
form.value.transferStatus = '0'; // 默认待流转
enterRoadList.value = [];
dialog.title = '添加项目土地流转台账';
dialog.visible = true;
};
/** 查看子项按钮操作(打开子项弹窗时) */
const handleViewSons = async (row: LandTransferLedgerVO) => {
if (!row?.id) return;
// 1. 确认父项ID已赋值
currentParentId.value = row.id;
console.log('当前父项ID', currentParentId.value); // 确认非空
// 2. 保存当前父项的完整数据,用于计算统计信息
currentParentItem.value = row;
// 2. 确认项目ID已赋值从用户store获取
const projectId = currentProject.value?.id;
console.log('当前项目ID', projectId); // 确认非空
// 3. 设置子项查询参数必须包含parentId和projectId
sonQueryParams.parentId = currentParentId.value;
sonQueryParams.projectId = projectId;
sonQueryParams.pageNum = 1; // 重置为第1页避免分页导致数据不显示
// 4. 重新加载子项列表
await getSonList();
sonDialog.visible = true;
};
/** 新增子项按钮操作 - 从父项继承数据 */
const handleAddSon = async () => {
if (!currentParentId.value) {
proxy?.$modal.msgWarning('请先选择父项记录');
return;
}
// 1. 查找当前父项的完整数据
const parentItem = landTransferLedgerList.value.find((item) => item.id === currentParentId.value);
if (!parentItem) {
proxy?.$modal.msgWarning('未找到父项数据');
return;
}
// 2. 重置表单并继承父项数据
resetSonForm();
// 3. 核心:从父项继承基础数据(根据实际业务调整需要继承的字段)
Object.assign(sonForm, {
// 必传的关联字段
parentId: currentParentId.value,
projectId: currentProject.value?.id,
// 继承父项的核心字段(示例,需根据实际接口字段调整)
landBlockId: parentItem.landBlockId, // 继承“对应地块”
landType: parentItem.landType, // 继承“土地类型”
enterRoadId: parentItem.enterRoadId, // 继承“进场道路”
designArea: parentItem.designArea, // 继承“设计面积”
responsiblePerson: parentItem.responsiblePerson, // 继承“责任人”
expectedFinishDate: parentItem.expectedFinishDate, // 继承“预计完成时间”
// 子项默认值(可覆盖父项或设置新值)
transferStatus: '1', // 默认为“已流转”
areaValue: 0,
transferRatio: 0
});
// 4. 继承后同步加载关联数据(如进场道路列表)
await getListRoad();
// 5. 打开弹窗
sonFormDialog.title = '添加子项(继承父项数据)';
sonFormDialog.visible = true;
};
/** 按流转状态新增子项按钮操作 */
const handleAddSonByStatus = (status: string) => {
handleAddSon();
// 设置指定的流转状态
sonForm.transferStatus = status;
};
/** 提交主项表单 */
const submitForm = () => {
landTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
buttonLoading.value = true;
try {
// 只保留新增功能,移除修改功能
await addLandTransferLedger(form.value);
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
await getLandBlockList(); // 刷新统计信息
} catch (error) {
proxy?.$modal.msgError('操作失败,请重试');
console.error('提交表单失败:', error);
} finally {
buttonLoading.value = false;
}
});
};
/** 提交子项表单 */
const submitSonForm = () => {
sonLandTransferLedgerFormRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
// 面积校验:已流转面积和不流转面积总和不能超过设计面积
try {
// 1. 获取当前父项的设计面积
const parentDesignArea = parseFloat(currentParentItem.value?.designArea || '0');
if (parentDesignArea <= 0) {
proxy?.$modal.msgWarning('父项设计面积未设置或无效');
return;
}
// 2. 获取当前子项的面积
const currentArea = parseFloat(sonForm.areaValue || '0');
if (currentArea <= 0) {
proxy?.$modal.msgWarning('请输入有效的面积值');
return;
}
// 3. 计算当前所有子项的面积总和(排除当前正在编辑的记录)
let totalExistingArea = 0;
if (sonLandTransferLedgerList.value && sonLandTransferLedgerList.value.length > 0) {
totalExistingArea = sonLandTransferLedgerList.value.reduce((sum, item) => {
return sum + (parseFloat(item.areaValue || '0') || 0);
}, 0);
}
// 4. 计算总面积(现有面积 + 当前子项面积)
const totalArea = totalExistingArea + currentArea;
// 5. 校验总面积是否超过设计面积
if (totalArea > parentDesignArea) {
proxy?.$modal.msgError(`面积总和 ${totalArea} 亩超过了设计面积 ${parentDesignArea} 亩,请调整面积值`);
return;
}
} catch (error) {
console.error('面积校验失败:', error);
proxy?.$modal.msgError('面积校验失败,请重试');
return;
}
sonButtonLoading.value = true;
try {
await addSonLandTransferLedger(sonForm);
proxy?.$modal.msgSuccess('子项添加成功');
sonFormDialog.visible = false;
await getSonList(); // 刷新子项列表
} catch (error) {
proxy?.$modal.msgError('操作失败,请重试');
console.error('提交子项表单失败:', error);
} finally {
sonButtonLoading.value = false;
}
});
};
/** 删除主项按钮操作 */
const handleDelete = async (row?: LandTransferLedgerVO) => {
const _ids = row?.id || ids.value;
if (!_ids.length) return;
try {
await proxy?.$modal.confirm(`是否确认删除项目土地流转台账编号为"${_ids}"的数据项?`);
await delLandTransferLedger(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
await getLandBlockList(); // 刷新统计信息
} catch (error) {
console.error('删除数据失败:', error);
if (error !== 'cancel') {
// 排除用户取消确认的情况
proxy?.$modal.msgError('删除失败,请重试');
}
} finally {
loading.value = false;
}
};
/** 选择地块后加载对应道路 */
const handleLandBlockChange = async () => {
await getListRoad();
};
/** 查询地块列表 */
const getListLand = async () => {
try {
const res = await listLandBlock({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id
});
landBlockList.value = res.rows;
} catch (error) {
console.error('获取地块列表失败:', error);
}
};
/** 查询进场道路列表(按地块筛选) */
const getListRoad = async () => {
try {
// 优先使用子项表单的地块ID否则使用主项表单的
const landBlockId = sonForm.landBlockId || form.value.landBlockId;
const res = await listEnterRoad({
pageNum: 1,
pageSize: 10000,
projectId: currentProject.value?.id,
landBlockId
});
enterRoadList.value = res.rows;
} catch (error) {
console.error('获取进场道路列表失败:', error);
}
};
// 监听项目切换时,重置主项查询参数
const listeningProject = watch(
() => currentProject.value?.id,
async (newId) => {
if (newId) {
queryParams.value.projectId = newId; // 确保项目ID赋值
queryParams.value.pageNum = 1; // 重置页码
await Promise.all([getLandBlockList(), getListLand(), getList()]);
}
},
{ immediate: true }
);
/** 组件卸载时清理监听 */
onUnmounted(() => {
listeningProject();
});
/** 组件挂载时初始化数据 */
onMounted(() => {
Promise.all([getLandBlockList(), getListLand(), getList()]);
});
</script>
<style lang="scss">
.detailbox {
width: 100%;
.box1 {
width: 100%;
display: flex;
justify-content: center;
margin: 20px 0;
> div {
width: 300px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 15px;
border: 1px solid #e7e7e7;
margin: 0 20px;
border-radius: 6px;
> div {
display: flex;
flex-direction: column;
> span:first-child {
font-size: 16px;
margin-bottom: 10px;
}
> span:last-child {
font-size: 24px;
/* font-weight: bold; */
}
}
}
}
}
// 子项列表统计展示区域美化样式
.summary-box {
width: 100%;
display: flex;
justify-content: space-between;
margin: 20px 0;
padding: 15px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
// 响应式布局
@media (max-width: 768px) {
flex-wrap: wrap;
> .summary-item {
width: calc(50% - 10px) !important;
margin-bottom: 15px;
}
}
}
.summary-item {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 15px;
background: white;
margin: 0 8px;
border-radius: 10px;
border: 1px solid #e1e5e9;
transition: all 0.3s ease;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(49, 118, 255, 0.15);
border-color: #3176ff;
}
}
.summary-content {
display: flex;
flex-direction: column;
}
.summary-label {
font-size: 14px;
color: #666;
margin-bottom: 8px;
font-weight: 500;
}
.summary-value {
font-size: 24px;
color: #333;
font-weight: bold;
transition: color 0.3s ease;
}
// 不同类型数据的特殊样式
.design-area .summary-value {
color: #3176ff;
}
.transfer-area .summary-value {
color: #52c41a;
}
.non-transfer-area .summary-value {
color: #ff6b6b;
}
.remaining-area .summary-value {
color: #fa8c16;
}
.summary-icon {
transition: transform 0.3s ease;
}
.summary-item:hover .summary-icon {
transform: scale(1.1);
}
// 调整弹窗表单样式,适应竖向排列
.el-dialog__body {
max-height: 70vh;
overflow-y: auto;
padding: 20px;
}
.el-form-item {
margin-bottom: 15px;
}
</style>