style:土地管理新增地图选点功能

This commit is contained in:
李想 2025-03-04 15:49:28 +08:00
parent 871ad7e2a4
commit be24fb0545
5 changed files with 337 additions and 82 deletions

View File

@ -1,13 +1,24 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.png" /> <link rel="icon" type="image/svg+xml" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title> <title></title>
<script>
window._AMapSecurityConfig = {
securityJsCode: 'f09302d3ed65110614bdb26e44717ddf',
};
</script>
<script type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=c843a50db7157faf295c6fa37c48719f&plugin=AMap.PlaceSearch,AMap.Geocoder"></script>
<script src="https://webapi.amap.com/ui/1.1/main.js?v=1.0.11"></script>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
</body> </body>
</html> </html>

View File

@ -1,13 +1,16 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.png" /> <link rel="icon" type="image/svg+xml" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>政务服务</title> <title>政务服务</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
</body> </body>
</html> </html>

View File

@ -132,3 +132,13 @@ export function delLand(id) {
method: 'DELETE', method: 'DELETE',
}); });
} }
/* 导入土地 */
export function importLands(data) {
return request('land-resource/landManage/import', {
method: 'POST',
data,
Headers: {
'Content-Type': 'multipart/form-data',
},
});
}

View File

@ -0,0 +1,104 @@
<template>
<section class="create_land_attrs_content_">
<el-upload
v-if="props.view != 'view'"
class="custom-form__uploader"
action="#"
:show-file-list="false"
accept="image/*"
:limit="20"
:http-request="rowUploadPicture"
>
<el-icon class="custom-form__uploader__icon"><Plus /></el-icon>
</el-upload>
<div v-for="item in attrs_" :key="`attr_${item.id}`" class="attrs_content__item">
<img :src="item.url" :alt="item.name" style="" />
<el-icon v-if="props.view != 'view'" class="clear_btn" @click="handleClearAttr(item.id)"><CircleCloseFilled /></el-icon>
</div>
</section>
</template>
<script setup>
import { ref, watch } from 'vue';
import { CommonUpload } from '@/apis';
const emit = defineEmits(['update:attrs']);
const props = defineProps({
view: {
type: String,
default: 'view',
},
attrs: {
type: Array,
default: () => [],
},
});
const attrs_ = ref([]);
watch(
() => props.attrs,
(val) => {
attrs_.value = val;
},
{ deep: true, immediate: true }
);
function handleClearAttr(id) {
attrs_.value = attrs_.value.filter((item) => item.id !== id);
emit('update:attrs', attrs_.value);
}
async function rowUploadPicture({ file }) {
const formData = new FormData();
formData.append('file', file);
const res = await CommonUpload(formData);
if (res.code === 200) {
attrs_.value.push({
...res.data,
id: 'id_' + Date.now(),
});
emit('update:attrs', attrs_.value);
}
}
</script>
<style lang="scss" scoped>
.create_land_attrs_content_ {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
gap: 20px;
.custom-form__uploader {
box-sizing: border-box;
height: auto;
}
> div {
width: calc(50% - 10px);
aspect-ratio: 1 / 1;
}
.attrs_content__item {
box-sizing: border-box;
position: relative;
padding: 6px;
border: 1px solid #ccc;
border-radius: 4px;
img {
width: 100%;
height: 100%;
border-radius: 2px;
}
.clear_btn {
position: absolute;
right: 0px;
top: 0px;
font-size: 18px;
color: #f15c5c;
opacity: 0;
cursor: pointer;
background-color: #fff;
border-radius: 50%;
}
&:hover {
.clear_btn {
opacity: 1;
}
}
}
}
</style>

View File

@ -12,17 +12,21 @@
class="custon_create_land_" class="custon_create_land_"
:data="data" :data="data"
:option="option" :option="option"
:before-close="handleCloseFrom"
@current-change="handlePageChange" @current-change="handlePageChange"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@search-reset="handleResetSearch" @search-reset="handleResetSearch"
@search-change="handleSearch" @search-change="handleSearch"
@row-save="handleRowSave" @row-save="handleRowSave"
> >
<!-- <template #menu-form> <template #landTransfer="{ row }">
<CreateLand :row-data="rowData" :land-type="0" /> {{ row.landTransfer == '1' ? '是' : '否' }}
</template> --> </template>
<template #isUpload="{ row }">
{{ row.isUpload != '1' ? '是' : '否' }}
</template>
<template #menu-left> <template #menu-left>
<el-button type="success" icon="upload">导入</el-button> <el-button type="success" icon="upload" @click="handleImport">导入</el-button>
<el-button type="success" icon="download" @click="handleExport">导出</el-button> <el-button type="success" icon="download" @click="handleExport">导出</el-button>
</template> </template>
<template #menu="{ row }"> <template #menu="{ row }">
@ -33,25 +37,17 @@
</template> </template>
</el-popconfirm> </el-popconfirm>
</template> </template>
<template #propertyCertificateUrl-form="{ type }"> <template #propertyCertificateUrl-form="{ type }">
<section class="create_land_attrs_content_"> <Attrs v-model:attrs="attrs" :view="type" />
<el-upload </template>
v-if="type !== 'view'" <template #landCertificateUrl-form="{ type }">
class="custom-form__uploader" <Attrs v-model:attrs="landOwnerAttrs" :view="type" />
action="#" </template>
:show-file-list="false" <template #coordinate-form>
accept="image/*" <avue-input-map v-model="local" :params="params" placeholder="请选择位置"></avue-input-map>
:limit="20" </template>
:http-request="rowUploadPicture" <template #landUrl-form="{ type }">
> <Attrs v-model:attrs="landAttrs" :view="type" />
<el-icon class="custom-form__uploader__icon"><Plus /></el-icon>
</el-upload>
<div v-for="item in attrs" :key="`attr_${item.id}`" class="attrs_content__item">
<img :src="item.url" :alt="item.name" style="" />
<el-icon class="clear_btn" @click="handleClearAttr(item.id)"><CircleCloseFilled /></el-icon>
</div>
</section>
</template> </template>
</avue-crud> </avue-crud>
</CustomCard> </CustomCard>
@ -62,24 +58,27 @@ import { ref, reactive, onMounted } from 'vue';
import CustomCard from '@/components/CustomCard'; import CustomCard from '@/components/CustomCard';
import { CRUD_OPTIONS } from '@/config'; import { CRUD_OPTIONS } from '@/config';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import { getLandsList, exportLands, delLand, saveLand } from '@/apis/land.js'; import { getLandsList, exportLands, delLand, saveLand, importLands } from '@/apis/land.js';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import useLandHook from './useLandHook'; import useLandHook from './useLandHook';
import { CommonUpload } from '@/apis'; import { CommonUpload } from '@/apis';
import { get } from 'lodash'; import Attrs from './common/Attrs.vue';
import { add } from 'lodash';
const { landType, landsType, landClassificationType, handleIficationType } = useLandHook(); const { landType, landsType, landClassificationType, handleIficationType } = useLandHook();
const { VITE_APP_BASE_API } = import.meta.env; const { VITE_APP_BASE_API } = import.meta.env;
const UserStore = useUserStore(); const UserStore = useUserStore();
const landClassificationType_ = ref('');
onMounted(() => { onMounted(() => {
getList(); getList();
}); });
const params = ref({
zoom: 10,
});
const local_ = ref([102.833669, 24.88149, '昆明市']);
const local = ref(JSON.parse(JSON.stringify(local_.value)));
/* --------------- data --------------- */ /* --------------- data --------------- */
// #region // #region
const crudRef = ref(); const crudRef = ref();
const pageData = reactive({ const pageData = reactive({
currentPage: 1, currentPage: 1,
@ -223,6 +222,7 @@ const option = reactive({
prop: 'landClassificationType', prop: 'landClassificationType',
type: 'select', type: 'select',
dicData: landClassificationType, dicData: landClassificationType,
viewDisplay: false,
rules: [ rules: [
{ {
required: true, required: true,
@ -231,13 +231,30 @@ const option = reactive({
}, },
], ],
}, },
{
label: '用地分类',
prop: 'landClassificationTypeView',
addDisplay: false,
},
{ {
label: '位置', label: '位置',
prop: 'villageCode', 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),
rules: [ rules: [
{ {
required: true, required: true,
message: '请输入', message: '请选择',
trigger: 'blur', trigger: 'blur',
}, },
], ],
@ -246,6 +263,7 @@ const option = reactive({
label: '是否土地流转', label: '是否土地流转',
prop: 'isTransfer', prop: 'isTransfer',
type: 'select', type: 'select',
viewDisplay: false,
dicData: [ dicData: [
{ {
label: '是', label: '是',
@ -257,6 +275,11 @@ const option = reactive({
}, },
], ],
}, },
{
label: '是否土地流转1',
prop: 'isTransferView',
addDisplay: false,
},
{ {
label: '面积', label: '面积',
prop: 'area', prop: 'area',
@ -293,6 +316,48 @@ const option = reactive({
}, },
], ],
}, },
{
label: '土地使用权信息',
prop: 'baseGroup',
column: [
{
label: '联系人',
prop: 'landUseName',
},
{
label: '联系电话',
prop: 'landUsePhone',
},
{
label: '用地性质',
prop: 'nature',
},
{
label: '证书',
prop: 'landCertificateUrl',
},
],
},
{
label: '土地使用权信息',
prop: 'baseGroup',
column: [
{
label: '地理位置',
prop: 'coordinate',
viewDisplay: false,
},
{
label: '地理位置',
prop: 'coordinateView',
addDisplay: false,
},
{
label: '图片',
prop: 'landUrl',
},
],
},
], ],
}); });
const searchData = reactive({ const searchData = reactive({
@ -301,6 +366,8 @@ const searchData = reactive({
owner: '', owner: '',
}); });
const attrs = ref([]); const attrs = ref([]);
const landOwnerAttrs = ref([]);
const landAttrs = ref([]);
const rowData = ref([]); const rowData = ref([]);
// #endregion // #endregion
@ -315,14 +382,18 @@ async function getList() {
...searchData, ...searchData,
}; };
let res = await getLandsList(params); let res = await getLandsList(params);
console.log('res ---------', res);
if (res.code == 200) { if (res.code == 200) {
data.value = res.data.records; data.value = res.data.records;
data.value.forEach((v) => {
v.isTransfer = v.landTransfer || 1;
v.isTransferView = v.landTransfer == 1 ? '否' : '是';
v.landClassificationTypeView = handleIficationType(v.handleIficationType);
v.coordinateView = v.coordinate;
});
pageData.total = res.data.total; pageData.total = res.data.total;
} }
} }
function handlePageChange(val) { function handlePageChange(val) {
console.log('page', val);
pageData.currentPage = val; pageData.currentPage = val;
getList(); getList();
} }
@ -346,29 +417,32 @@ async function handleResetSearch() {
pageData.total = 0; pageData.total = 0;
await getList(); await getList();
} }
async function handleRowSave(val, done, loading) { const attrNames = reactive(landsType.map((v) => v.label));
let data = JSON.parse(JSON.stringify(val)); function handleImport() {
data.isDraftsSave = 0; let inp = document.createElement('input');
data.landType = 0; inp.type = 'file';
let urls = []; inp.onchange = fileUp;
if (data.propertyCertificateUrl.length) { document.body.appendChild(inp);
data.propertyCertificateUrl.forEach((item) => urls.push(item.url)); inp.click();
document.body.removeChild(inp);
} }
data.propertyCertificateUrl = urls.join(); async function fileUp(e) {
const res = await saveLand(data); let formData = new FormData();
formData.append('file', e.target.files[0]);
formData.append('landType', landType.value);
const res = await importLands(formData);
if (res.code == 200) { if (res.code == 200) {
ElMessage.success('保存成功'); ElMessage.success('导入成功');
getList(); getList();
done();
} }
} }
async function handleExport() { async function handleExport() {
let res = await exportLands({ let res = await exportLands({
landType: 1, landType: landType.value,
}); });
if (res) { if (res) {
let a = document.createElement('a'); let a = document.createElement('a');
// a.download = attrNames.value[Number(searchCondition.landType)] + '.xlsx'; a.download = attrNames.value[Number(landType.value)] + '.xlsx';
a.download = 'test.xlsx'; a.download = 'test.xlsx';
let blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); let blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
let link = window.URL.createObjectURL(blob); let link = window.URL.createObjectURL(blob);
@ -379,20 +453,6 @@ async function handleExport() {
window.URL.revokeObjectURL(link); window.URL.revokeObjectURL(link);
} }
} }
const rowUploadPicture = async ({ file }) => {
const formData = new FormData();
formData.append('file', file);
const res = await CommonUpload(formData);
if (res.code === 200) {
attrs.value.push({
...res.data,
id: 'id_' + Date.now(),
});
}
};
function handleClearAttr(id) {
attrs.value = attrs.value.filter((item) => item.id !== id);
}
async function handleDelete(id) { async function handleDelete(id) {
let res = await delLand(id); let res = await delLand(id);
if (res.code == 200) { if (res.code == 200) {
@ -401,9 +461,76 @@ async function handleDelete(id) {
} }
function handleView(obj) { function handleView(obj) {
rowData.value = obj; rowData.value = obj;
console.log('row', rowData.value); if (obj.propertyCertificateUrl) {
attrs.value = obj.propertyCertificateUrl.split(',').map((v, i) => {
return {
name: `产权附件_${i}`,
url: v,
id: 'id_' + Date.now(),
};
});
}
if (obj.landCertificateUrl) {
landOwnerAttrs.value = obj.landCertificateUrl.split(',').map((v, i) => {
return {
name: `使用信息附件_${i}`,
url: v,
id: 'id_' + Date.now(),
};
});
if (obj.landUrl) {
landAttrs.value = obj.landUrl.split(',').map((v, i) => {
return {
name: `位置附件_${i}`,
url: v,
id: 'id_' + Date.now(),
};
});
}
}
crudRef.value.rowView(obj); crudRef.value.rowView(obj);
} }
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] || '';
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();
}
}
// #endregion // #endregion
</script> </script>