615 lines
15 KiB
Vue
Raw Normal View History

2025-02-26 13:36:43 +08:00
<template>
2025-02-28 16:45:42 +08:00
<CustomCard>
2025-03-03 16:28:34 +08:00
<el-radio-group v-model="landType" class="lands_types" style="margin-bottom: 30px" @change="getList()">
2025-02-26 13:36:43 +08:00
<el-radio-button v-for="item in landsType" :key="'landsType_' + item.value" :value="item.value">
{{ item.label }}
</el-radio-button>
</el-radio-group>
2025-03-03 16:28:34 +08:00
<avue-crud
ref="crudRef"
v-model:page="pageData"
v-model:search="searchData"
class="custon_create_land_"
:data="data"
:option="option"
:before-close="handleCloseFrom"
2025-03-05 17:30:00 +08:00
:table-loading="loading"
2025-03-03 16:28:34 +08:00
@current-change="handlePageChange"
@size-change="handleSizeChange"
@search-reset="handleResetSearch"
@search-change="handleSearch"
@row-save="handleRowSave"
>
<template #landTransfer="{ row }">
{{ row.landTransfer == '1' ? '是' : '否' }}
</template>
<template #isUpload="{ row }">
{{ row.isUpload != '1' ? '是' : '否' }}
</template>
2025-03-03 16:28:34 +08:00
<template #menu-left>
<el-button type="success" icon="download" @click="handleExport">导出</el-button>
2025-03-14 17:33:44 +08:00
<el-button type="success" icon="upload" @click="onUpload">导入</el-button>
2025-03-03 16:28:34 +08:00
</template>
<template #menu="{ row }">
<el-button type="info" link @click="handleView(row)">查看</el-button>
<el-popconfirm title="确定删除该土地?" @confirm="() => handleDelete(row.id)">
<template #reference>
<el-button type="danger" link>删除</el-button>
</template>
</el-popconfirm>
</template>
<template #propertyCertificateUrl-form="{ type }">
<Attrs v-model:attrs="attrs" :view="type" />
</template>
<template #landCertificateUrl-form="{ type }">
<Attrs v-model:attrs="landOwnerAttrs" :view="type" />
</template>
2025-03-05 17:30:00 +08:00
<template #coordinate-form>
<avue-input-map v-model="local" :params="params" placeholder="请选择位置"></avue-input-map>
2025-03-05 17:30:00 +08:00
</template>
<template #landUrl-form="{ type }">
<Attrs v-model:attrs="landAttrs" :view="type" />
2025-03-03 16:28:34 +08:00
</template>
</avue-crud>
2025-03-14 17:33:44 +08:00
<custom-import-excel
ref="importExcelRef"
:template-url="getAssetsFile('template/土地模版表.xlsx')"
@on-download="onDownloadExcel"
@on-confirm="onUploadExcel"
/>
2025-02-28 16:45:42 +08:00
</CustomCard>
2025-02-26 13:36:43 +08:00
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
2025-03-03 16:28:34 +08:00
import CustomCard from '@/components/CustomCard';
import { CRUD_OPTIONS } from '@/config';
import { useUserStore } from '@/store/modules/user';
import { getLandsList, exportLands, delLand, saveLand, importLands } from '@/apis/land.js';
2025-03-14 17:33:44 +08:00
import { getLandTypeTree } from '@/apis/baseInfo';
2025-03-03 16:28:34 +08:00
import { ElMessage } from 'element-plus';
import useLandHook from './useLandHook';
import Attrs from './common/Attrs.vue';
2025-03-14 17:33:44 +08:00
import { getAssetsFile, downloadFile } from '@/utils';
import { useApp } from '@/hooks';
2025-03-14 17:33:44 +08:00
const app = useApp();
const { landType, landsType } = useLandHook();
2025-03-03 16:28:34 +08:00
const { VITE_APP_BASE_API } = import.meta.env;
const UserStore = useUserStore();
2025-02-26 13:36:43 +08:00
onMounted(() => {
getList();
2025-03-14 17:33:44 +08:00
getLandTree();
2025-02-26 13:36:43 +08:00
});
const params = ref({
zoom: 10,
});
const local_ = ref([102.833669, 24.88149, '昆明市']);
const local = ref(JSON.parse(JSON.stringify(local_.value)));
2025-03-14 17:33:44 +08:00
const landTreeDic = ref([]);
2025-02-26 13:36:43 +08:00
/* --------------- data --------------- */
// #region
2025-03-05 17:30:00 +08:00
const loading = ref(false);
2025-03-03 16:28:34 +08:00
const crudRef = ref();
2025-03-05 17:30:00 +08:00
const pageData = ref({
2025-03-03 16:28:34 +08:00
currentPage: 1,
pageSize: 10,
2025-02-26 13:36:43 +08:00
total: 0,
});
2025-03-03 16:28:34 +08:00
const data = ref([]);
const option = reactive({
...CRUD_OPTIONS,
menuWidth: 120,
2025-03-05 17:30:00 +08:00
selection: false,
2025-03-03 16:28:34 +08:00
column: [
{
label: '地块名',
prop: 'landName',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
2025-02-26 13:36:43 +08:00
},
2025-03-03 16:28:34 +08:00
{
label: '地址',
prop: 'address',
addDisplay: false,
display: false,
editDisplay: false,
2025-02-26 13:36:43 +08:00
},
2025-03-03 16:28:34 +08:00
{
label: '产权人',
prop: 'owner',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '所属网格',
prop: 'gridName',
// type: 'select',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '农用地分类',
prop: 'landClassificationType',
select: 'select',
2025-03-14 17:33:44 +08:00
dicData: landTreeDic,
2025-03-03 16:28:34 +08:00
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '面积',
prop: 'area',
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '坐标',
prop: 'coordinate',
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '是否流转土地',
prop: 'landTransfer',
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '产权编号',
prop: 'landCode',
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '土壤类型',
prop: 'soilType',
addDisplay: false,
display: false,
editDisplay: false,
2025-03-14 17:33:44 +08:00
render: ({ row }) => {
return row.soilType;
},
2025-03-03 16:28:34 +08:00
},
{
label: '是否上传附件',
prop: 'isUpload',
addDisplay: false,
display: false,
editDisplay: false,
},
],
group: [
{
label: '用户信息',
prop: 'baseGroup',
column: [
{
label: '土地名称',
prop: 'landName',
rules: [
{
required: true,
message: '请输入',
trigger: 'blur',
},
],
},
{
label: '所属网格',
prop: 'gridId',
type: 'select',
dicUrl: `${VITE_APP_BASE_API}/land-resource/gridManage/page`,
dicQuery: {
current: 1,
size: 9999,
},
props: {
value: 'id',
label: 'gridName',
},
dicMethod: 'get',
dicHeaders: {
authorization: UserStore.token,
},
dicFormatter: (res) => res?.data?.records ?? [],
rules: [
{
required: true,
message: '请输入',
trigger: 'blur',
},
],
},
{
label: '用地分类',
2025-03-14 17:33:44 +08:00
prop: 'landTypeId',
type: 'cascader',
dicData: landTreeDic,
viewDisplay: false,
2025-03-03 16:28:34 +08:00
rules: [
{
required: true,
message: '请输入',
trigger: 'blur',
},
],
},
{
label: '用地分类',
2025-03-14 17:33:44 +08:00
prop: 'landClassificationType',
addDisplay: false,
},
2025-03-03 16:28:34 +08:00
{
label: '位置',
prop: 'villageCode',
type: 'cascader',
props: {
label: 'areaName',
value: 'areaCode',
children: 'areaChildVOS',
},
dicUrl: `${VITE_APP_BASE_API}/system/area/region?areaCode=530000`,
dicHeaders: {
authorization: UserStore.token,
},
dicFormatter: (res) => res.data ?? [],
// change: (o) => setCityChange(o),
2025-03-03 16:28:34 +08:00
rules: [
{
required: true,
message: '请选择',
2025-03-03 16:28:34 +08:00
trigger: 'blur',
},
],
},
{
label: '是否土地流转',
prop: 'isTransfer',
type: 'select',
viewDisplay: false,
2025-03-03 16:28:34 +08:00
dicData: [
{
label: '是',
value: '0',
},
{
label: '否',
value: '1',
},
],
},
{
label: '是否土地流转1',
prop: 'isTransferView',
addDisplay: false,
},
2025-03-03 16:28:34 +08:00
{
label: '面积',
prop: 'area',
},
{
label: '产权人',
prop: 'owner',
},
2025-03-14 17:33:44 +08:00
{
label: '土壤类型',
prop: 'soilTypeId',
type: 'select',
viewDisplay: false,
dicUrl: `${VITE_APP_BASE_API}/land-resource/baseInfo/soilTypePage`,
dicQuery: {
current: 1,
size: 9999,
},
dicHeaders: {
authorization: UserStore.token,
},
dicFormatter: (res) => res.data.records ?? [],
props: {
value: 'id',
label: 'soilType',
},
},
2025-03-03 16:28:34 +08:00
{
label: '土壤类型',
prop: 'soilType',
2025-03-14 17:33:44 +08:00
addDisplay: false,
2025-03-03 16:28:34 +08:00
},
],
},
{
label: '土地产权信息',
prop: 'baseGroup',
column: [
{
label: '产权人姓名',
prop: 'propertyName',
},
{
label: '产权人联系电话',
prop: 'propertyPhone',
},
{
label: '产权编号',
prop: 'landCode',
},
{
label: '产权证书',
prop: 'propertyCertificateUrl',
},
],
},
{
label: '土地使用权信息',
prop: 'baseGroup',
column: [
{
label: '联系人',
prop: 'landUseName',
},
{
label: '联系电话',
prop: 'landUsePhone',
},
{
label: '用地性质',
prop: 'nature',
},
{
label: '证书',
prop: 'landCertificateUrl',
},
],
},
{
label: '土地使用权信息',
prop: 'baseGroup',
column: [
2025-03-05 17:30:00 +08:00
{
label: '地理位置',
prop: 'coordinate',
viewDisplay: false,
},
{
label: '地理位置',
prop: 'coordinateView',
addDisplay: false,
},
{
label: '图片',
prop: 'landUrl',
},
],
},
2025-03-03 16:28:34 +08:00
],
});
const searchData = reactive({
landName: '',
gridName: '',
owner: '',
});
const attrs = ref([]);
const landOwnerAttrs = ref([]);
const landAttrs = ref([]);
2025-03-03 16:28:34 +08:00
const rowData = ref([]);
2025-03-14 17:33:44 +08:00
const importExcelRef = ref();
2025-02-26 13:36:43 +08:00
// #endregion
/* --------------- methods --------------- */
// #region
async function getList() {
2025-03-05 17:30:00 +08:00
loading.value = true;
2025-02-26 13:36:43 +08:00
const params = {
2025-03-05 17:30:00 +08:00
current: pageData.value.currentPage,
size: pageData.value.pageSize,
2025-03-03 16:28:34 +08:00
landType: landType.value,
...searchData,
2025-02-26 13:36:43 +08:00
};
let res = await getLandsList(params);
2025-03-05 17:30:00 +08:00
loading.value = false;
2025-02-27 11:34:43 +08:00
if (res.code == 200) {
2025-03-05 17:30:00 +08:00
const { total, records } = res.data;
data.value = records;
data.value.forEach((v) => {
v.isTransfer = v.landTransfer || 1;
v.isTransferView = v.landTransfer == 1 ? '否' : '是';
2025-03-05 17:30:00 +08:00
v.coordinateView = v.coordinate;
});
2025-03-05 17:30:00 +08:00
pageData.value.total = total;
2025-02-27 11:34:43 +08:00
}
2025-02-26 13:36:43 +08:00
}
2025-03-03 16:28:34 +08:00
function handlePageChange(val) {
2025-03-05 17:30:00 +08:00
pageData.value.currentPage = val;
2025-03-03 16:28:34 +08:00
getList();
2025-02-26 13:36:43 +08:00
}
2025-03-03 16:28:34 +08:00
function handleSizeChange(val) {
2025-03-05 17:30:00 +08:00
pageData.value.pageSize = val;
2025-03-03 16:28:34 +08:00
getList();
2025-02-27 15:01:39 +08:00
}
2025-03-03 16:28:34 +08:00
async function handleSearch(form, done) {
for (let key in form) {
searchData[key] = form[key];
}
await getList();
done();
}
async function handleResetSearch() {
for (let key in searchData) {
searchData[key] = '';
}
2025-03-05 17:30:00 +08:00
pageData.value.currentPage = 1;
pageData.value.pageSize = 10;
pageData.value.total = 0;
2025-03-03 16:28:34 +08:00
await getList();
}
const attrNames = reactive(landsType.map((v) => v.label));
2025-02-27 17:30:06 +08:00
async function handleExport() {
let res = await exportLands({
landType: landType.value,
2025-02-27 17:30:06 +08:00
});
if (res) {
let a = document.createElement('a');
a.download = attrNames.value[Number(landType.value)] + '.xlsx';
2025-03-03 16:28:34 +08:00
a.download = 'test.xlsx';
2025-02-27 17:30:06 +08:00
let blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
let link = window.URL.createObjectURL(blob);
a.href = link;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(link);
}
2025-02-28 16:45:42 +08:00
}
2025-03-03 16:28:34 +08:00
async function handleDelete(id) {
let res = await delLand(id);
if (res.code == 200) {
getList();
}
}
function handleView(obj) {
rowData.value = obj;
if (obj.propertyCertificateUrl) {
attrs.value = obj.propertyCertificateUrl.split(',').map((v, i) => {
return {
name: `产权附件_${i}`,
url: v,
uid: 'id_' + Date.now(),
};
});
}
if (obj.landCertificateUrl) {
landOwnerAttrs.value = obj.landCertificateUrl.split(',').map((v, i) => {
return {
name: `使用信息附件_${i}`,
url: v,
uid: 'id_' + Date.now(),
};
});
if (obj.landUrl) {
landAttrs.value = obj.landUrl.split(',').map((v, i) => {
return {
name: `位置附件_${i}`,
url: v,
uid: 'id_' + Date.now(),
};
});
}
}
2025-03-03 16:28:34 +08:00
crudRef.value.rowView(obj);
2025-02-27 17:30:06 +08:00
}
function handleCloseFrom(done) {
landOwnerAttrs.value = [];
attrs.value = [];
landAttrs.value = [];
local.value = JSON.parse(JSON.stringify(local_.value));
done();
}
async function handleRowSave(val, done, loading) {
let data = JSON.parse(JSON.stringify(val));
data.isDraftsSave = 0;
data.landType = landType.value;
let urls = [];
let landOwnerUrls = [];
let landUrls = [];
if (attrs.value.length) {
attrs.value.forEach((item) => urls.push(item.url));
}
if (landOwnerAttrs.value.length) {
landOwnerAttrs.value.forEach((item) => landOwnerUrls.push(item.url));
}
if (landAttrs.value.length) {
landAttrs.value.forEach((item) => landUrls.push(item.url));
}
data.propertyCertificateUrl = urls.join();
data.landCertificateUrl = landOwnerUrls.join();
data.landUrl = landUrls.join();
data.villageCode = data.villageCode[data.villageCode.length - 1] || '';
2025-03-14 17:33:44 +08:00
data.landTypeId = data.landTypeId[data.landTypeId.length - 1];
2025-03-05 17:30:00 +08:00
if (local.value.length != 0) {
data.coordinate = `${local.value[0]}E,${local.value[1]}N`;
}
const res = await saveLand(data);
loading();
if (res.code == 200) {
ElMessage.success('保存成功');
getList();
attrs.value = [];
landOwnerAttrs.value = [];
done();
}
}
2025-03-14 17:33:44 +08:00
// 导入
const onUpload = () => {
importExcelRef?.value && importExcelRef.value.show();
};
const onDownloadExcel = (url) => {
downloadFile(url, `土地模版表.xlsx`);
};
const onUploadExcel = (formData) => {
formData.append('landType', landType.value);
importLands(formData)
.then((res) => {
if (res.status === 200) {
app.$message.success('导入成功!');
}
})
.catch((err) => {
app.$message.error('导入失败!');
importExcelRef.value.clear();
})
.finally(() => {
importExcelRef.value.hide();
});
};
async function getLandTree() {
let res = await getLandTypeTree();
if (res.code == 200) {
landTreeDic.value = newTree(res.data, 0);
console.log('landTreeDic', landTreeDic.value);
}
}
function newTree(arr, i) {
arr.forEach((v) => {
if (i == 0) {
v.value = v.id;
v.label = v.prentLandType;
v.disabled = !v.children || !v.children.length;
} else {
v.value = v.id;
v.label = v.childLandCategory;
}
if (v.children) v.children = newTree(v.children, i + 1);
});
return arr;
}
2025-02-26 13:36:43 +08:00
// #endregion
</script>
<style lang="scss" scoped>
.lands_types {
justify-content: center;
2025-02-26 17:03:50 +08:00
width: 100%;
2025-02-26 13:36:43 +08:00
> label {
width: 12%;
::v-deep() {
.el-radio-button__inner {
width: 100%;
}
}
}
}
</style>