705 lines
17 KiB
Vue
Raw Normal View History

2025-02-26 13:36:43 +08:00
<template>
2025-03-27 15:56:05 +08:00
<section class="custom-page">
2025-03-03 16:28:34 +08:00
<avue-crud
ref="crudRef"
v-model:page="pageData"
2025-04-03 17:23:48 +08:00
v-model:search="searchCondition"
2025-03-03 16:28:34 +08:00
class="custon_create_land_"
:data="data"
:option="option"
:before-close="handleCloseFrom"
2025-03-05 17:30:00 +08:00
:table-loading="loading"
2025-04-03 17:23:48 +08:00
@refresh-change="getList()"
@current-change="getList()"
2025-03-03 16:28:34 +08:00
@size-change="handleSizeChange"
2025-04-03 17:23:48 +08:00
@search-reset="
() => {
resetLandType();
getList(1);
}
"
@search-change="
(form, done) => {
getList(1);
done();
}
"
2025-03-03 16:28:34 +08:00
@row-save="handleRowSave"
2025-04-03 17:23:48 +08:00
@row-update="handleRowUpdate"
2025-03-03 16:28:34 +08:00
>
<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>
2025-04-08 11:11:04 +08:00
<template #area-form="{ type }">
<section v-show="type != 'view'" class="area_form_">
<el-input-number v-model="landArea" :precision="2" :step="1" :min="1" controls-position="right"></el-input-number>
<el-select v-model="unitValue">
2025-04-03 17:23:48 +08:00
<el-option v-for="item in unitOptions" :key="'unitOptions_' + item.value" :label="item.label" :value="item.label" />
</el-select>
</section>
2025-04-08 11:11:04 +08:00
<section v-show="type == 'view'">
{{ landArea + unitValue }}
</section>
</template>
2025-03-03 16:28:34 +08:00
<template #propertyCertificateUrl-form="{ type }">
2025-03-17 17:32:59 +08:00
<Attrs v-model:attrs="attrs" :type="type" />
</template>
<template #landCertificateUrl-form="{ type }">
2025-03-17 17:32:59 +08:00
<Attrs v-model:attrs="landOwnerAttrs" :type="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 }">
2025-03-17 17:32:59 +08:00
<Attrs v-model:attrs="landAttrs" :type="type" />
2025-03-03 16:28:34 +08:00
</template>
2025-03-25 08:45:53 +01:00
<template #menu="scope">
<custom-table-operate :actions="option.actions" :data="scope" />
</template>
2025-03-03 16:28:34 +08:00
</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-03-27 15:56:05 +08:00
</section>
2025-02-26 13:36:43 +08:00
</template>
<script setup>
2025-04-03 17:23:48 +08:00
import { ref, reactive, onMounted, watch } from 'vue';
2025-03-03 16:28:34 +08:00
import { CRUD_OPTIONS } from '@/config';
import { useUserStore } from '@/store/modules/user';
2025-04-03 17:23:48 +08:00
import { getLandsList, exportLands, delLand, saveLand, importLands, editLand } from '@/apis/land.js';
2025-04-08 09:27:53 +08:00
import { getRegion } from '@/apis';
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();
2025-04-03 17:23:48 +08:00
const { loadFinish, resetLandType, searchCondition, unitOptions, unitValue, landTreeDic } = 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
2025-04-03 17:23:48 +08:00
watch(
() => loadFinish.value,
() => {
if (loadFinish.value == 2) {
getList();
2025-04-08 09:27:53 +08:00
handleGetRegion();
2025-04-03 17:23:48 +08:00
}
}
);
const params = ref({
zoom: 10,
});
const local_ = ref([102.833669, 24.88149, '昆明市']);
const local = ref(JSON.parse(JSON.stringify(local_.value)));
const landArea = ref(1);
2025-04-03 17:23:48 +08:00
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: [
2025-04-03 17:23:48 +08:00
{
hide: true,
label: '用地分类',
prop: 'landType',
search: true,
type: 'cascader',
dicData: landTreeDic,
clearable: false,
value: [],
addDisplay: false,
display: false,
editDisplay: false,
},
2025-03-03 16:28:34 +08:00
{
2025-05-12 17:46:49 +08:00
label: '地块名称',
2025-03-03 16:28:34 +08:00
prop: 'landName',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
2025-04-03 17:23:48 +08:00
width: 200,
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-04-03 17:23:48 +08:00
width: 300,
2025-02-26 13:36:43 +08:00
},
2025-03-03 16:28:34 +08:00
{
2025-05-12 17:46:49 +08:00
label: '经营主体',
2025-03-03 16:28:34 +08:00
prop: 'owner',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
2025-05-12 17:46:49 +08:00
width: 100,
2025-03-03 16:28:34 +08:00
},
{
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,
2025-04-03 17:23:48 +08:00
width: 300,
2025-03-03 16:28:34 +08:00
},
{
label: '面积',
prop: 'area',
addDisplay: false,
display: false,
editDisplay: false,
render: ({ row }) => {
let s = '';
if (row.area && row.landUnit) {
2025-04-03 17:23:48 +08:00
s = row.area + row.landUnit;
}
return s;
},
2025-03-03 16:28:34 +08:00
},
{
label: '坐标',
prop: 'coordinate',
addDisplay: false,
display: false,
editDisplay: false,
2025-04-03 17:23:48 +08:00
width: 300,
2025-03-03 16:28:34 +08:00
},
{
label: '是否流转土地',
prop: 'landTransfer',
addDisplay: false,
display: false,
editDisplay: false,
2025-04-03 17:23:48 +08:00
width: 140,
2025-03-03 16:28:34 +08:00
},
{
label: '产权编号',
prop: 'landCode',
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '土壤类型',
2025-04-03 17:23:48 +08:00
prop: 'soilTypeName',
2025-03-03 16:28:34 +08:00
addDisplay: false,
editDisplay: false,
},
{
label: '是否上传附件',
prop: 'isUpload',
addDisplay: false,
display: false,
editDisplay: false,
2025-04-03 17:23:48 +08:00
width: 140,
2025-03-03 16:28:34 +08:00
},
],
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',
},
dicHeaders: {
authorization: UserStore.token,
},
2025-04-08 09:27:53 +08:00
dicFormatter: handleGetGrid,
2025-03-03 16:28:34 +08:00
rules: [
{
required: true,
message: '请输入',
trigger: 'blur',
},
],
2025-04-08 11:11:04 +08:00
change: handleChangeGrid,
2025-03-03 16:28:34 +08:00
},
{
2025-04-08 11:11:04 +08:00
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-04-08 09:27:53 +08:00
editDisplay: false,
},
2025-03-03 16:28:34 +08:00
{
label: '位置',
2025-04-08 09:27:53 +08:00
prop: '_villageCode',
type: 'cascader',
props: {
label: 'areaName',
value: 'areaCode',
children: 'areaChildVOS',
},
2025-03-03 16:28:34 +08:00
rules: [
{
required: true,
message: '请选择',
2025-03-03 16:28:34 +08:00
trigger: 'blur',
},
],
2025-04-08 11:11:04 +08:00
viewDisplay: false,
},
{
hide: true,
label: '位置',
prop: 'address',
addDisplay: false,
editDisplay: false,
2025-03-03 16:28:34 +08:00
},
{
label: '是否土地流转',
prop: 'isTransfer',
type: 'select',
viewDisplay: false,
2025-03-03 16:28:34 +08:00
dicData: [
{
label: '是',
value: '0',
},
{
label: '否',
value: '1',
},
],
},
{
2025-04-03 17:23:48 +08:00
label: '是否土地流转',
prop: 'isTransferView',
addDisplay: false,
2025-04-08 09:27:53 +08:00
editDisplay: false,
},
2025-03-03 16:28:34 +08:00
{
label: '面积',
prop: 'area',
},
{
2025-05-12 17:46:49 +08:00
label: '经营主体',
2025-03-03 16:28:34 +08:00
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: 'baseGroup',
column: [
{
2025-05-12 17:46:49 +08:00
label: '经营主体姓名',
2025-03-03 16:28:34 +08:00
prop: 'propertyName',
},
{
2025-05-12 17:46:49 +08:00
label: '经营主体联系电话',
2025-03-03 16:28:34 +08:00
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
],
2025-03-25 08:45:53 +01:00
actions: [
{
name: '查看',
icon: 'view',
event: ({ row }) => handleView(row),
},
2025-04-03 17:23:48 +08:00
{
name: '编辑',
icon: 'edit',
event: ({ row }) => rowEdit(row),
},
2025-03-25 08:45:53 +01:00
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => handleDelete(row.id),
},
],
2025-03-03 16:28:34 +08:00
});
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-04-08 09:27:53 +08:00
const regionData = ref([]);
2025-02-26 13:36:43 +08:00
// #endregion
/* --------------- methods --------------- */
// #region
2025-04-03 17:23:48 +08:00
async function getList(reset = 1) {
reset == 1 && (pageData.value.currentPage = 1);
2025-03-05 17:30:00 +08:00
loading.value = true;
2025-04-03 17:23:48 +08:00
let params = Object.assign(
{},
{
current: pageData.value.currentPage,
size: pageData.value.pageSize,
...searchCondition.value,
}
);
params.landType = searchCondition.value.landType[searchCondition.value.landType.length - 1];
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) => {
2025-04-08 09:27:53 +08:00
v.isTransfer = v.landTransfer || '1';
v.isTransferView = v.landTransfer == '1' ? '否' : '是';
2025-03-05 17:30:00 +08:00
v.coordinateView = v.coordinate;
2025-04-03 17:23:48 +08:00
v.soilTypeName = v.soilType;
v.soilTypeId = v.soilId;
2025-04-25 13:34:18 +08:00
v._villageCode = typeof v.villageCode == 'string' ? [v.villageCode] : v.villageCode;
2025-04-08 09:27:53 +08:00
v.landTypeId = [v.pid, v.landType];
});
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-04-08 09:27:53 +08:00
function handleGetGrid(res) {
2025-04-08 11:11:04 +08:00
return res?.data?.records ?? [];
}
function handleChangeGrid(val) {
val.item && filterArea(val.item.townCode);
}
function filterArea(id) {
option.group[0].column[4].dicData = regionData.value.find((v) => v.areaCode == id)?.areaChildVOS ?? [];
2025-04-08 09:27:53 +08:00
}
async function handleGetRegion() {
let res = await getRegion();
if (res.code == 200) {
2025-04-08 11:11:04 +08:00
regionData.value = res?.data?.[0].areaChildVOS?.[0].areaChildVOS?.[0].areaChildVOS ?? [];
2025-04-08 09:27:53 +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-02-27 17:30:06 +08:00
async function handleExport() {
let res = await exportLands({
2025-04-03 17:23:48 +08:00
landType: searchCondition.value.landType[searchCondition.value.landType.length - 1],
2025-02-27 17:30:06 +08:00
});
if (res) {
let a = document.createElement('a');
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-25 08:45:53 +01:00
function handleDelete(id) {
app
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
delLand(id)
.then((res) => {
if (res.code === 200) {
app.$message.success('删除成功!');
getList();
}
})
.catch((err) => {
app.$message.error(err.msg);
});
})
.catch(() => {});
2025-03-03 16:28:34 +08:00
}
function handleView(obj) {
2025-04-08 09:27:53 +08:00
handleOtherInfo(obj);
2025-03-03 16:28:34 +08:00
rowData.value = obj;
crudRef.value.rowView(obj);
2025-02-27 17:30:06 +08:00
}
function handleCloseFrom(done) {
landOwnerAttrs.value = [];
attrs.value = [];
landAttrs.value = [];
landArea.value = 1;
2025-04-03 17:23:48 +08:00
unitValue.value = unitOptions[0].label || '';
local.value = JSON.parse(JSON.stringify(local_.value));
done();
}
2025-04-03 17:23:48 +08:00
function handleData(val) {
let data = JSON.parse(JSON.stringify(val));
data.isDraftsSave = 0;
2025-04-03 17:23:48 +08:00
data.landType = searchCondition.value.landType[searchCondition.value.landType.length - 1];
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.area = landArea.value;
data.landUnit = unitValue.value;
data.propertyCertificateUrl = urls.join();
data.landCertificateUrl = landOwnerUrls.join();
data.landUrl = landUrls.join();
2025-04-25 13:34:18 +08:00
data.villageCode = data._villageCode[0];
2025-03-14 17:33:44 +08:00
data.landTypeId = data.landTypeId[data.landTypeId.length - 1];
2025-04-03 17:23:48 +08:00
data.soilType = data.soilTypeId;
2025-03-05 17:30:00 +08:00
if (local.value.length != 0) {
data.coordinate = `${local.value[0]}E,${local.value[1]}N`;
}
2025-04-08 09:27:53 +08:00
delete data.address;
delete data.provinceCode;
delete data.cityCode;
delete data.county;
delete data.townCode;
2025-04-03 17:23:48 +08:00
return data;
}
async function handleRowSave(val, done, loading) {
let data = handleData(val);
2025-04-08 09:27:53 +08:00
const res = await saveLand(data);
2025-04-03 17:23:48 +08:00
loading();
2025-04-08 09:27:53 +08:00
if (res.code == 200) {
ElMessage.success('保存成功');
getList();
attrs.value = [];
landOwnerAttrs.value = [];
done();
}
2025-04-03 17:23:48 +08:00
}
async function handleRowUpdate(form, index, done, loading) {
let data = handleData(form);
let res = await editLand(data);
loading();
if (res.code == 200) {
2025-04-03 17:23:48 +08:00
ElMessage.success('编辑成功');
done();
}
}
2025-04-03 17:23:48 +08:00
2025-04-08 09:27:53 +08:00
async function rowEdit(row) {
handleOtherInfo(row);
2025-04-08 11:11:04 +08:00
filterArea(row.townCode);
2025-04-08 09:27:53 +08:00
crudRef.value.rowEdit(row);
2025-04-03 17:23:48 +08:00
}
2025-04-08 09:27:53 +08:00
function handleOtherInfo(obj) {
landArea.value = obj.area;
unitValue.value = obj.landUnit;
2025-04-03 17:23:48 +08:00
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-14 17:33:44 +08:00
// 导入
const onUpload = () => {
importExcelRef?.value && importExcelRef.value.show();
};
const onDownloadExcel = (url) => {
downloadFile(url, `土地模版表.xlsx`);
};
const onUploadExcel = (formData) => {
2025-04-03 17:23:48 +08:00
formData.append('landType', searchCondition.value.landType[searchCondition.value.landType.length - 1]);
2025-03-14 17:33:44 +08:00
importLands(formData)
.then((res) => {
if (res.status === 200) {
app.$message.success('导入成功!');
}
})
.catch((err) => {
app.$message.error('导入失败!');
importExcelRef.value.clear();
})
.finally(() => {
importExcelRef.value.hide();
});
};
2025-04-03 17:23:48 +08:00
2025-02-26 13:36:43 +08:00
// #endregion
</script>
<style lang="scss" scoped>
.area_form_ {
display: grid;
grid-template-columns: 75% 25%;
::v-deep() {
.el-input-number {
width: 100%;
.el-input__wrapper {
border-radius: 4px 0 0 4px;
}
}
.el-select__wrapper {
border-radius: 0 4px 4px 0 !important;
border-left: none;
}
}
}
2025-02-26 13:36:43 +08:00
</style>