482 lines
14 KiB
Vue
482 lines
14 KiB
Vue
<template>
|
|
<section class="custom-page">
|
|
<avue-crud ref="crudRef" v-model:page="pageData" :data="data" :option="option" :table-loading="loading">
|
|
<template #search>
|
|
<div class="custom-search">
|
|
<AreaCascader v-model:region-code="query.regionCode" v-model:grid-id="query.gridId" :width="500" />
|
|
<!-- <url-select
|
|
v-model="query.landType"
|
|
placeholder="土地类型"
|
|
url="/land-resource/landManage/page"
|
|
style="margin-left: 8px; width: 200px"
|
|
label-key="landName"
|
|
value-key="landType"
|
|
:clearable="true"
|
|
/> -->
|
|
<el-select v-model="query.landType" placeholder="选择土地类型" clearable style="width: 200px; margin-left: 8px">
|
|
<el-option v-for="item in landTypeOptions" :key="item.id" :label="item.landType" :value="item.id" />
|
|
</el-select>
|
|
<el-input v-model="query.keyword" placeholder="关键词搜索" style="margin-left: 8px; width: 200px" @keyup.enter="handleSearch" />
|
|
<el-button type="primary" @click="handleSearch"> 搜索 </el-button>
|
|
<el-button @click="resetSearch"> 重置 </el-button>
|
|
</div>
|
|
</template>
|
|
<template #menu-left>
|
|
<el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
|
|
</template>
|
|
<template #menu="scope">
|
|
<custom-table-operate :actions="option.actions" :data="scope" />
|
|
</template>
|
|
</avue-crud>
|
|
|
|
<!-- 新增弹窗 -->
|
|
<el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true">
|
|
<el-tabs v-model="activeTab" class="tabs-wrapper">
|
|
<el-tab-pane label="土地基本信息" name="basic">
|
|
<p class="form-title">编辑基本信息</p>
|
|
<el-form ref="basicFormRef" :model="formDataBasic" :disabled="isReadonly" label-width="120px">
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<el-form-item label="地块名称" prop="landName">
|
|
<el-input v-model="formDataBasic.landName" placeholder="请输入地块名称" />
|
|
</el-form-item>
|
|
<el-form-item label="土地类型" prop="landType">
|
|
<el-select v-model="formDataBasic.landType" placeholder="选择土地类型" clearable>
|
|
<el-option v-for="item in landTypeOptions" :key="item.id" :label="item.landType" :value="item.id" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="具体位置" prop="address">
|
|
<el-input v-model="formDataBasic.address" placeholder="请输入具体位置" />
|
|
</el-form-item>
|
|
<el-form-item label="土壤类型" prop="soilTypeId">
|
|
<url-select
|
|
v-model="formDataBasic.soilTypeId"
|
|
placeholder="选择土壤类型"
|
|
url="/land-resource/baseInfo/soilTypePage"
|
|
:params="{ current: 1, size: 100 }"
|
|
label-key="soilType"
|
|
value-key="id"
|
|
:clearable="true"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="土地照片" prop="landUrl">
|
|
<FileUploader v-model="formDataBasic.landUrl" :limit="1" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="面积(亩)" prop="area">
|
|
<el-input-number v-model="formDataBasic.area" :min="0" :precision="2" :step="0.1" controls-position="right" style="width: 100%" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="" label-width="0" prop="gridId">
|
|
<AreaCascader v-model:region-code="formDataBasic.regionCode" v-model:grid-id="formDataBasic.gridId" label="" :split-rows="true" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="土地范围" prop="scope">
|
|
<el-input v-model="formDataBasic.scope" placeholder="请输入土地范围" />
|
|
<!-- <Attrs v-model:attrs="formDataBasic.scope" type="add" accept="image/*" /> -->
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="土地产权信息" name="property">
|
|
<p class="form-title">编辑产权信息</p>
|
|
<el-form ref="propertyFormRef" style="width: 60%" :model="formDataProperty" :disabled="isReadonly" label-width="120px">
|
|
<el-row :gutter="20">
|
|
<el-form-item label="地块名称">
|
|
<el-input v-model="formDataProperty.landName" disabled />
|
|
</el-form-item>
|
|
<el-form-item label="产权人姓名" prop="propertyName">
|
|
<el-input v-model="formDataProperty.propertyName" placeholder="请输入产权人姓名" />
|
|
</el-form-item>
|
|
<el-form-item label="联系方式" prop="propertyPhone">
|
|
<el-input v-model="formDataProperty.propertyPhone" placeholder="请输入产权人联系方式" />
|
|
</el-form-item>
|
|
<el-form-item label="产权编号" prop="landCode">
|
|
<el-input v-model="formDataProperty.landCode" placeholder="请输入产权编号" />
|
|
</el-form-item>
|
|
<el-form-item label="产权证书" prop="propertyCertificateUrl">
|
|
<FileUploader v-model="formDataProperty.propertyCertificateUrl" :limit="1" />
|
|
</el-form-item>
|
|
</el-row>
|
|
</el-form>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
|
|
<template #footer>
|
|
<span class="dialog-footer">
|
|
<el-button @click="visible = false">取消</el-button>
|
|
|
|
<!-- 土地基本信息 tab -->
|
|
<template v-if="activeTab === 'basic'">
|
|
<el-button type="primary" @click="submitBasicInfo">暂存</el-button>
|
|
<el-button @click="activeTab = 'property'">下一步</el-button>
|
|
</template>
|
|
|
|
<!-- 土地产权信息 tab -->
|
|
<template v-else>
|
|
<el-button @click="activeTab = 'basic'">上一步</el-button>
|
|
<el-button v-if="formDataProperty.landId" type="primary" @click="submitPropertyInfo">提交</el-button>
|
|
<el-button v-else type="primary" @click="submitAll">保存</el-button>
|
|
</template>
|
|
</span>
|
|
</template>
|
|
</el-dialog>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, onMounted, computed, nextTick } from 'vue';
|
|
import { CRUD_OPTIONS } from '@/config';
|
|
import { getLandList, createLand, saveBaseInfo, saveProperty, editLand, deleteLand } from '@/apis/landResourceManagement/landManagement';
|
|
import { CommonUpload } from '@/apis/index';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import request from '@/utils/axios';
|
|
|
|
// ==============================
|
|
// 状态管理
|
|
// ==============================
|
|
const loading = ref(false);
|
|
const crudRef = ref();
|
|
const visible = ref(false);
|
|
const isReadonly = ref(false);
|
|
const activeTab = ref('basic');
|
|
const dialogTitle = ref('新增');
|
|
|
|
// 表单引用
|
|
const basicFormRef = ref(null);
|
|
const propertyFormRef = ref(null);
|
|
|
|
// 分页数据
|
|
const pageData = ref({
|
|
currentPage: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
});
|
|
|
|
// 查询参数
|
|
const query = ref({
|
|
landType: null,
|
|
current: 1,
|
|
size: 10,
|
|
regionCode: null,
|
|
keyword: '',
|
|
gridId: null,
|
|
});
|
|
|
|
// 表格数据
|
|
const data = ref([]);
|
|
const landTypeOptions = ref([]);
|
|
|
|
// 表单数据
|
|
const formDataBasic = ref({
|
|
landName: '',
|
|
regionCode: '',
|
|
gridId: '',
|
|
area: 0,
|
|
landType: '',
|
|
address: '',
|
|
soilTypeId: '',
|
|
landUrl: '',
|
|
scope: '',
|
|
});
|
|
|
|
const formDataProperty = ref({
|
|
id: '',
|
|
landName: '',
|
|
propertyName: '',
|
|
propertyPhone: '',
|
|
landCode: '',
|
|
propertyCertificateUrl: '',
|
|
});
|
|
|
|
// ==============================
|
|
// CRUD 配置
|
|
// ==============================
|
|
const option = reactive({
|
|
...CRUD_OPTIONS,
|
|
addBtn: false,
|
|
searchBtn: false,
|
|
emptyBtn: false,
|
|
column: [
|
|
{ label: '地块名称', prop: 'landName' },
|
|
{ label: '所属网格', prop: 'gridName' },
|
|
{ label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` },
|
|
{ label: '土地类型', prop: 'landTypeName' },
|
|
{ label: '所属行政区域', prop: 'fullRegionName' },
|
|
{ label: '具体位置', prop: 'address' },
|
|
{ label: '产权人姓名', prop: 'propertyName' },
|
|
{ label: '产权人联系方式', prop: 'propertyPhone' },
|
|
{ label: '产权编号', prop: 'landCode' },
|
|
{ label: '信息录入时间', prop: 'createTime' },
|
|
{ label: '信息更新时间', prop: 'updateTime' },
|
|
],
|
|
actions: [
|
|
// {
|
|
// name: '查看',
|
|
// icon: 'view',
|
|
// event: ({ row }) => handleView(row),
|
|
// },
|
|
// {
|
|
// name: '编辑',
|
|
// icon: 'edit',
|
|
// event: ({ row }) => handleEdit(row),
|
|
// },
|
|
{
|
|
type: 'danger',
|
|
name: '删除',
|
|
icon: 'delete',
|
|
event: ({ row }) => handleDelete(row.id),
|
|
},
|
|
],
|
|
});
|
|
|
|
// ==============================
|
|
// 方法 - 数据获取
|
|
// ==============================
|
|
const getData = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const res = await getLandList(query.value);
|
|
const { current, size, total, records } = res.data;
|
|
data.value = records;
|
|
pageData.value = {
|
|
currentPage: current || 1,
|
|
pageSize: size || 10,
|
|
total: total,
|
|
};
|
|
} catch (error) {
|
|
console.error('获取数据失败', error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const fetchLandTypeData = async () => {
|
|
try {
|
|
const response = await request.get('/land-resource/baseInfo/landTree', { params: { status: '1' } });
|
|
if (response.code === 200) {
|
|
landTypeOptions.value = extractLeafNodes(response.data);
|
|
}
|
|
} catch (error) {
|
|
console.error('获取土地类型数据失败', error);
|
|
}
|
|
};
|
|
|
|
// ==============================
|
|
// 方法 - 表单操作
|
|
// ==============================
|
|
const handleAdd = () => {
|
|
// 重置表单
|
|
formDataBasic.value = {
|
|
landName: '',
|
|
gridId: '',
|
|
area: 0,
|
|
landType: '',
|
|
address: '',
|
|
soilTypeId: '',
|
|
landUrl: '',
|
|
scope: '',
|
|
};
|
|
|
|
formDataProperty.value = {
|
|
id: '',
|
|
landName: '',
|
|
propertyName: '',
|
|
propertyPhone: '',
|
|
landCode: '',
|
|
propertyCertificateUrl: '',
|
|
};
|
|
|
|
visible.value = true;
|
|
activeTab.value = 'basic';
|
|
|
|
// 重置表单验证
|
|
nextTick(() => {
|
|
if (basicFormRef.value) {
|
|
basicFormRef.value.resetFields();
|
|
}
|
|
if (propertyFormRef.value) {
|
|
propertyFormRef.value.resetFields();
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleView = (row) => {
|
|
isReadonly.value = true;
|
|
dialogTitle.value = '土地资源详情';
|
|
visible.value = true;
|
|
};
|
|
|
|
const handleEdit = (row) => {
|
|
dialogTitle.value = '编辑';
|
|
isReadonly.value = false;
|
|
visible.value = true;
|
|
};
|
|
|
|
const handleDelete = (id) => {
|
|
// 删除逻辑
|
|
deleteLand(id).then(() => {
|
|
getData();
|
|
});
|
|
};
|
|
|
|
const handleSearch = () => {
|
|
query.value.current = 1;
|
|
getData();
|
|
};
|
|
|
|
const resetSearch = () => {
|
|
query.value = {
|
|
landType: null,
|
|
current: 1,
|
|
size: 10,
|
|
regionCode: null,
|
|
keyword: '',
|
|
gridId: null,
|
|
};
|
|
getData();
|
|
};
|
|
|
|
// ==============================
|
|
// 方法 - 表单提交
|
|
// ==============================
|
|
const submitBasicInfo = async () => {
|
|
try {
|
|
await basicFormRef.value.validate();
|
|
const res = await saveBaseInfo(formDataBasic.value);
|
|
if (res.code === 200) {
|
|
formDataProperty.value.id = res.data.id;
|
|
formDataProperty.value.landName = formDataBasic.value.landName;
|
|
ElMessage.success('基本信息已暂存');
|
|
}
|
|
} catch (error) {
|
|
console.error('暂存失败', error);
|
|
}
|
|
};
|
|
|
|
const submitPropertyInfo = async () => {
|
|
try {
|
|
await propertyFormRef.value.validate();
|
|
if (!formDataProperty.value.id) {
|
|
ElMessage.error('请先保存基本信息');
|
|
return;
|
|
}
|
|
const res = await saveProperty(formDataProperty.value);
|
|
if (res.code === 200) {
|
|
ElMessage.success('产权信息提交成功');
|
|
visible.value = false;
|
|
getData();
|
|
}
|
|
} catch (error) {
|
|
console.error('产权信息提交失败', error);
|
|
}
|
|
};
|
|
|
|
const submitAll = async () => {
|
|
try {
|
|
await basicFormRef.value.validate();
|
|
await propertyFormRef.value.validate();
|
|
|
|
const combinedData = {
|
|
...formDataProperty.value,
|
|
...formDataBasic.value,
|
|
};
|
|
const baseRes = await createLand(combinedData);
|
|
if (baseRes.code === 200) {
|
|
ElMessage.success('全部信息保存成功');
|
|
visible.value = false;
|
|
getData();
|
|
} else {
|
|
ElMessage.error('信息保存失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('保存失败', error);
|
|
}
|
|
};
|
|
|
|
// ==============================
|
|
// 工具函数
|
|
// ==============================
|
|
const extractLeafNodes = (nodes) => {
|
|
let result = [];
|
|
for (const node of nodes) {
|
|
if (node.children && node.children.length > 0) {
|
|
result = result.concat(extractLeafNodes(node.children));
|
|
} else if (node.status === '1') {
|
|
result.push(node);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
// ==============================
|
|
// 生命周期
|
|
// ==============================
|
|
onMounted(() => {
|
|
getData();
|
|
fetchLandTypeData();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
// :deep(.el-dialog__body) {
|
|
// padding: 20px;
|
|
// height: calc(100vh - 300px);
|
|
// overflow-y: auto;
|
|
// }
|
|
.custom-page {
|
|
padding: 20px;
|
|
height: calc(100vh - 150px);
|
|
overflow-y: auto;
|
|
// background-color: #409eff;
|
|
|
|
.custom-search {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 16px;
|
|
|
|
.el-button {
|
|
margin-left: 12px;
|
|
}
|
|
}
|
|
}
|
|
.tabs-wrapper {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
// background-color: #7daaaa;
|
|
|
|
:deep(.el-tabs__item) {
|
|
font-size: 16px;
|
|
color: #555555;
|
|
font-weight: 500;
|
|
// border: 1 solid #f000;
|
|
}
|
|
:deep(.el-tabs__content) {
|
|
padding: 20px;
|
|
// background-color: #f5f5f5;
|
|
border-radius: 4px;
|
|
height: calc(100vh - 300px);
|
|
overflow-y: auto;
|
|
}
|
|
:deep(.el-tab-pane) {
|
|
margin: 0 auto;
|
|
width: 80%;
|
|
}
|
|
}
|
|
|
|
.form-title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
margin: 30px 0;
|
|
color: #333333;
|
|
}
|
|
|
|
.dialog-footer {
|
|
display: block;
|
|
text-align: center;
|
|
}
|
|
</style>
|