feat:土地违法处理页面重构

This commit is contained in:
李想 2025-03-05 17:30:00 +08:00
parent 2c93b36eb4
commit 10f866f394
5 changed files with 374 additions and 51 deletions

View File

@ -6,14 +6,14 @@
<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> <script>
window._AMapSecurityConfig = { window._AMapSecurityConfig = {
securityJsCode: 'f09302d3ed65110614bdb26e44717ddf', securityJsCode: 'f09302d3ed65110614bdb26e44717ddf',
}; };
</script> </script>
<script type="text/javascript" <script type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=c843a50db7157faf295c6fa37c48719f&plugin=AMap.PlaceSearch,AMap.Geocoder"></script> 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> --> <script src="https://webapi.amap.com/ui/1.1/main.js?v=1.0.11"></script>
</head> </head>
<body> <body>

View File

@ -0,0 +1,86 @@
<template>
<el-upload
ref="upload"
class="upload-demo"
:limit="props.limit"
:auto-upload="false"
:file-list="fileList"
:on-change="fileChange"
:before-remove="handleDelFile"
>
<el-button type="primary" :disabled="fileList.length == 5">点击上传</el-button>
<template #tip>
<div v-if="props.format.length" class="el-upload__tip">只能上传{{ props.format.join() }} 文件且不超过20MB</div>
</template>
</el-upload>
</template>
<script setup>
import { ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
const emit = defineEmits(['update:list']);
const props = defineProps({
list: {
type: Array,
default: () => [],
},
limit: {
type: Number,
default: 5,
},
format: {
type: Array,
default: () => [],
},
size: {
type: Number,
default: 20,
},
});
/* --------------- data --------------- */
// #region
const fileList = ref([]);
watch(
() => props.list,
(val) => {
fileList.value = val;
},
{ deep: true, immediate: true }
);
// #endregion
/* --------------- methods --------------- */
// #region
function fileChange(file, list) {
let formatReg = true;
if (props.format.length > 0) {
formatReg = props.format.includes(file.name.slice(file.name.lastIndexOf('.') + 1));
}
const fileSize = file.size / 1024 / 1024 < props.size;
if (!formatReg) {
ElMessage.error(`上传文件格式不正确,仅支持${props.format.join('/ ')}格式`);
delAttr(file.uid, list);
}
if (!fileSize) {
ElMessage.error(`上传文件大小不能超过${props.size}MB`);
delAttr(file.uid, list);
}
fileList.value = list;
}
function handleDelFile(file) {
delAttr(file.uid, fileList.value);
}
function delAttr(id, list = []) {
if (!id || !list) return false;
let i = list.findIndex((v) => v.uid == id);
if (i < 0) return;
else list.splice(i, 1);
}
// #endregion
</script>
<style lang="scss" scoped></style>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog v-model="_visible" title="案件登记处理" append-to="#app" @close="handleClose"> <el-dialog v-model="_visible" :width="800" title="案件登记处理" append-to="#app" @close="handleClose">
<h3>案件信息&gt;</h3> <h3>案件信息&gt;</h3>
<section class="case_info"> <section class="case_info">
<div v-for="item in info" :key="`${item.key}_box`" :style="{ '--w': item.line ? '100%' : 'calc(50% - 12px)' }"> <div v-for="item in info" :key="`${item.key}_box`" :style="{ '--w': item.line ? '100%' : 'calc(50% - 12px)' }">
@ -7,12 +7,12 @@
<div class="text">{{ item.value }}</div> <div class="text">{{ item.value }}</div>
</div> </div>
</section> </section>
<el-form :model="form"> <el-form :model="form" label-width="140px">
<h3>案件处理&gt;</h3> <h3>案件处理&gt;</h3>
<el-form-item label="案情记录:" prop="record"> <el-form-item label="案情记录:" prop="record">
<el-input v-model="form.record" type="textarea" placeholder="请输入"></el-input> <el-input v-model="form.record" type="textarea" placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="现场取证:(照片、视频)"></el-form-item> <el-form-item label="现场取证:(照片、视频)" label-width="200px"></el-form-item>
<el-form-item label="执法文书:"> <el-form-item label="执法文书:">
<section> <section>
<el-radio-group v-model="form.document"> <el-radio-group v-model="form.document">
@ -21,11 +21,18 @@
<el-radio :value="2" label="检测报告"></el-radio> <el-radio :value="2" label="检测报告"></el-radio>
<el-radio :value="3" label="其他文书"></el-radio> <el-radio :value="3" label="其他文书"></el-radio>
</el-radio-group> </el-radio-group>
<FileUpload v-model:list="form.proof" />
</section> </section>
</el-form-item> </el-form-item>
<h3>案件结果&gt;</h3> <h3>案件结果&gt;</h3>
<el-form-item label="案件处理结果:"> <el-form-item label="案件处理结果:" class="result_content">
<!-- <el-radio-group ></el-radio-group> --> <el-radio-group v-model="form.result">
<el-radio :value="0" label="正常营业,无违规行为"></el-radio>
<el-radio :value="1" label="简易程序,当场行政处罚"></el-radio>
<el-radio :value="2" label="普通程序,当场处罚立案审批"></el-radio>
<el-radio :value="3" label="移送程序,案件移送"></el-radio>
<el-radio :value="4" label="特殊程序,案件终止"></el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-dialog> </el-dialog>
@ -33,6 +40,7 @@
<script setup> <script setup>
import { ref, reactive, watch } from 'vue'; import { ref, reactive, watch } from 'vue';
import FileUpload from './FileUpload.vue';
const emit = defineEmits(['update:visible']); const emit = defineEmits(['update:visible']);
const props = defineProps({ const props = defineProps({
@ -102,9 +110,9 @@ const info = reactive([
const form = reactive({ const form = reactive({
record: '', record: '',
proof: [], proof: [],
document: 0, document: 1,
attrs: [], attrs: [],
result: 0, result: 1,
}); });
// #endregion // #endregion
@ -138,4 +146,12 @@ function handleClose() {
} }
} }
} }
::v-deep() {
.result_content {
.el-radio-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
}
}
</style> </style>

View File

@ -1,6 +1,7 @@
<template> <template>
<CustomCard> <CustomCard>
<avue-crud <avue-crud
ref="crudRef"
v-model:page="page" v-model:page="page"
v-model:search="searchData" v-model:search="searchData"
:option="option" :option="option"
@ -10,29 +11,41 @@
@size-change="handleSizeChange" @size-change="handleSizeChange"
@search-change="handleSearch" @search-change="handleSearch"
@row-save="handleRowSave" @row-save="handleRowSave"
@row-update="handleExamine"
> >
<template #menu="{ row }"> <template #menu="{ row }">
<el-button type="primary" @click="handleInfo(row)">登记处理</el-button> <el-button type="primary" @click="handleInfo(row)">登记处理</el-button>
</template> </template>
<template #sceneProof-form>
<section>
<span>照片视频</span>
</section>
</template>
<template #attrs_-form>
<FileUpload v-model:list="examineForm.attrs" :format="['rar', 'zip', 'doc', 'docx', 'pdf']" />
</template>
</avue-crud> </avue-crud>
</CustomCard> </CustomCard>
<Register v-model:visible="caseInfo.visible" /> <Register v-model:visible="caseInfo.visible" />
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, reactive, h } from 'vue';
import { CRUD_OPTIONS } from '@/config'; import { CRUD_OPTIONS } from '@/config';
import CustomCard from '@/components/CustomCard.vue'; import CustomCard from '@/components/CustomCard.vue';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import Register from './common/Register.vue'; import Register from './common/Register.vue';
import FileUpload from './common/FileUpload.vue';
import { add } from 'lodash';
const { VITE_APP_BASE_API } = import.meta.env; const { VITE_APP_BASE_API } = import.meta.env;
const UserStore = useUserStore(); const UserStore = useUserStore();
/* --------------- data --------------- */ /* --------------- data --------------- */
// #region // #region
const crudRef = ref();
const searchData = ref({ const searchData = ref({
code: '', caseNum: '',
process: '', process: '',
}); });
const page = ref({ const page = ref({
@ -43,8 +56,8 @@ const page = ref({
const _loading = ref(false); const _loading = ref(false);
const data = ref([ const data = ref([
{ {
id: '1', id_: '1',
code: '111111111', caseNum: '111111111',
name: '张三', name: '张三',
unit: '123333333333333333333333333333', unit: '123333333333333333333333333333',
owner: '张三', owner: '张三',
@ -52,8 +65,8 @@ const data = ref([
date: '2020-02-02', date: '2020-02-02',
}, },
{ {
id: '2', id_: '2',
code: '222222222', caseNum: '222222222',
name: '张三', name: '张三',
unit: '123333333333333333333333333333', unit: '123333333333333333333333333333',
owner: '张三', owner: '张三',
@ -61,8 +74,8 @@ const data = ref([
date: '2020-02-02', date: '2020-02-02',
}, },
{ {
id: '3', id_: '3',
code: '333333333333', caseNum: '333333333333',
name: '张三', name: '张三',
unit: '123333333333333333333333333333', unit: '123333333333333333333333333333',
owner: '张三', owner: '张三',
@ -73,19 +86,27 @@ const data = ref([
const option = ref({ const option = ref({
...CRUD_OPTIONS, ...CRUD_OPTIONS,
refreshBtn: false, refreshBtn: false,
editTitle: '案件登记处理',
rowKey: 'id_',
column: [ column: [
{ {
label: '案件编号', label: '案件编号',
prop: 'code', prop: 'caseNum',
search: true, search: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '案件名称', label: '案件名称',
prop: 'name', prop: 'name',
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '关联单位', label: '关联单位',
prop: 'unit', prop: 'unit',
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '关联土地·', label: '关联土地·',
@ -107,25 +128,31 @@ const option = ref({
authorization: UserStore.token, authorization: UserStore.token,
}, },
dicFormatter: (res) => res?.data?.records ?? [], dicFormatter: (res) => res?.data?.records ?? [],
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '联系电话', label: '联系电话',
prop: 'phone', prop: 'phone',
viewDisplay: true,
// addDisplay: true,
hide: true, hide: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '法定代表人', label: '法定代表人',
prop: 'onwer', prop: 'onwer',
addDisplay: true, addDisplay: true,
hide: true, hide: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '统一社会信用代码', label: '统一社会信用代码',
prop: 'code', prop: 'code',
addDisplay: true, addDisplay: true,
hide: true, hide: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '违法情况', label: '违法情况',
@ -135,12 +162,16 @@ const option = ref({
hide: true, hide: true,
width: '100%', width: '100%',
span: 24, span: 24,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '负责人', label: '负责人',
prop: 'owner', prop: 'owner',
display: false, display: false,
addDisplay: true, addDisplay: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '案件进度', label: '案件进度',
@ -148,12 +179,16 @@ const option = ref({
display: false, display: false,
search: true, search: true,
addDisplay: true, addDisplay: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '案件结果', label: '案件结果',
prop: 'result', prop: 'result',
display: false, display: false,
addDisplay: true, addDisplay: true,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '处理时间', label: '处理时间',
@ -161,12 +196,178 @@ const option = ref({
display: false, display: false,
addDisplay: false, addDisplay: false,
editDisplay: true, editDisplay: true,
viewDisplay: false,
},
],
group: [
{
label: '案件信息>',
prop: 'caseInfo',
addDisplay: false,
column: [
{
label: '案件名称',
prop: 'name',
render: ({ row }) => {
return h('span', {}, row.name);
},
},
{
label: '案件编号',
prop: 'caseNum',
render: ({ row }) => {
return h('span', {}, row.caseNum);
},
},
{
label: '关联单位',
prop: 'unit',
render: ({ row }) => {
return h('span', {}, row.unit);
},
},
{
label: '关联地块',
prop: 'land',
render: ({ row }) => {
return h('span', {}, row.land);
},
},
{
label: '法定代表人',
prop: 'onwer',
render: ({ row }) => {
return h('span', {}, row.onwer);
},
},
{
label: '联系电话',
prop: 'phone',
render: ({ row }) => {
return h('span', {}, row.phone);
},
},
{
label: '统一社会信用代码',
prop: 'code',
span: 24,
render: ({ row }) => {
return h('span', {}, row.code);
},
},
{
label: '违法情况',
prop: 'result',
span: 24,
render: ({ row }) => {
return h('span', {}, row.result);
},
},
],
},
{
label: '案件处理>',
prop: 'caseHandle',
addDisplay: false,
column: [
{
label: '案情记录',
prop: 'caseRecords',
type: 'textarea',
span: 24,
display: true,
editDisplay: true,
},
{
label: '现场取证',
prop: 'sceneProof',
span: 24,
display: true,
editDisplay: true,
},
{
label: '执法文书',
prop: 'document',
labelSuffix: '件',
span: 24,
display: true,
type: 'radio',
editDisplay: true,
dicData: [
{
label: '协助调查函',
value: 0,
},
{
label: '抽样取样凭证',
value: 1,
},
{
label: '检测报告',
value: 2,
},
{
label: '其他文书',
value: 3,
},
],
},
{
label: '',
prop: 'attrs_',
},
],
},
{
label: '处理结果>',
prop: 'caseResult_',
addDisplay: false,
column: [
{
label: '案件处理结果',
prop: 'caseResult',
type: 'radio',
value: 0,
dicData: [
{
label: '正常营业,无违规行为',
value: 0,
},
{
label: '简易程序,当场行政处罚',
value: 1,
},
{
label: '普通程序,当场处罚立案审批',
value: 2,
},
{
label: '移送程序,案件移送',
value: 3,
},
{
label: '特殊程序,案件终止',
value: 4,
},
],
span: 24,
display: true,
editDisplay: true,
},
],
}, },
], ],
}); });
const caseInfo = ref({ const caseInfo = ref({
visible: false, visible: false,
}); });
const examineForm = reactive({
record: '',
proof: [],
document: 1,
attrs: [],
result: 1,
});
// #endregion // #endregion
/* --------------- methods --------------- */ /* --------------- methods --------------- */
@ -182,7 +383,9 @@ function handleSizeChange(val) {
} }
function handleInfo(row) { function handleInfo(row) {
console.log('row', row); console.log('row', row);
caseInfo.value.visible = true; // caseInfo.value.visible = true;
crudRef.value.rowEdit(row);
// crudRef.value.rowView(row);
} }
function handleSearch(form, done) { function handleSearch(form, done) {
console.log('search', form); console.log('search', form);
@ -201,7 +404,22 @@ function handleRowSave(val, done, loading) {
done(); done();
}, 1000); }, 1000);
} }
function handleExamine(val, done, loading) {
console.log('val', val);
console.log('done', done);
console.log('loading', loading);
loading();
}
// #endregion // #endregion
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
::v-deep() {
.attrs_ {
.el-form-item__label {
opacity: 0;
}
}
}
</style>

View File

@ -13,6 +13,7 @@
:data="data" :data="data"
:option="option" :option="option"
:before-close="handleCloseFrom" :before-close="handleCloseFrom"
:table-loading="loading"
@current-change="handlePageChange" @current-change="handlePageChange"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@search-reset="handleResetSearch" @search-reset="handleResetSearch"
@ -43,9 +44,9 @@
<template #landCertificateUrl-form="{ type }"> <template #landCertificateUrl-form="{ type }">
<Attrs v-model:attrs="landOwnerAttrs" :view="type" /> <Attrs v-model:attrs="landOwnerAttrs" :view="type" />
</template> </template>
<!-- <template #coordinate-form> <template #coordinate-form>
<avue-input-map v-model="local" :params="params" placeholder="请选择位置"></avue-input-map> <avue-input-map v-model="local" :params="params" placeholder="请选择位置"></avue-input-map>
</template> --> </template>
<template #landUrl-form="{ type }"> <template #landUrl-form="{ type }">
<Attrs v-model:attrs="landAttrs" :view="type" /> <Attrs v-model:attrs="landAttrs" :view="type" />
</template> </template>
@ -61,9 +62,7 @@ import { useUserStore } from '@/store/modules/user';
import { getLandsList, exportLands, delLand, saveLand, importLands } 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 Attrs from './common/Attrs.vue'; 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;
@ -79,8 +78,9 @@ const local_ = ref([102.833669, 24.88149, '昆明市']);
const local = ref(JSON.parse(JSON.stringify(local_.value))); const local = ref(JSON.parse(JSON.stringify(local_.value)));
/* --------------- data --------------- */ /* --------------- data --------------- */
// #region // #region
const loading = ref(false);
const crudRef = ref(); const crudRef = ref();
const pageData = reactive({ const pageData = ref({
currentPage: 1, currentPage: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
@ -88,8 +88,8 @@ const pageData = reactive({
const data = ref([]); const data = ref([]);
const option = reactive({ const option = reactive({
...CRUD_OPTIONS, ...CRUD_OPTIONS,
selection: false,
menuWidth: 120, menuWidth: 120,
selection: false,
column: [ column: [
{ {
label: '地块名', label: '地块名',
@ -342,16 +342,16 @@ const option = reactive({
label: '土地使用权信息', label: '土地使用权信息',
prop: 'baseGroup', prop: 'baseGroup',
column: [ column: [
// { {
// label: '', label: '地理位置',
// prop: 'coordinate', prop: 'coordinate',
// viewDisplay: false, viewDisplay: false,
// }, },
// { {
// label: '', label: '地理位置',
// prop: 'coordinateView', prop: 'coordinateView',
// addDisplay: false, addDisplay: false,
// }, },
{ {
label: '图片', label: '图片',
prop: 'landUrl', prop: 'landUrl',
@ -375,30 +375,33 @@ const rowData = ref([]);
// #region // #region
async function getList() { async function getList() {
loading.value = true;
const params = { const params = {
current: pageData.currentPage, current: pageData.value.currentPage,
size: pageData.pageSize, size: pageData.value.pageSize,
landType: landType.value, landType: landType.value,
...searchData, ...searchData,
}; };
let res = await getLandsList(params); let res = await getLandsList(params);
loading.value = false;
if (res.code == 200) { if (res.code == 200) {
data.value = res.data.records; const { total, records } = res.data;
data.value = records;
data.value.forEach((v) => { data.value.forEach((v) => {
v.isTransfer = v.landTransfer || 1; v.isTransfer = v.landTransfer || 1;
v.isTransferView = v.landTransfer == 1 ? '否' : '是'; v.isTransferView = v.landTransfer == 1 ? '否' : '是';
v.landClassificationTypeView = handleIficationType(v.handleIficationType); v.landClassificationTypeView = handleIficationType(v.handleIficationType);
// v.coordinateView = v.coordinate; v.coordinateView = v.coordinate;
}); });
pageData.total = res.data.total; pageData.value.total = total;
} }
} }
function handlePageChange(val) { function handlePageChange(val) {
pageData.currentPage = val; pageData.value.currentPage = val;
getList(); getList();
} }
function handleSizeChange(val) { function handleSizeChange(val) {
pageData.pageSize = val; pageData.value.pageSize = val;
getList(); getList();
} }
async function handleSearch(form, done) { async function handleSearch(form, done) {
@ -412,9 +415,9 @@ async function handleResetSearch() {
for (let key in searchData) { for (let key in searchData) {
searchData[key] = ''; searchData[key] = '';
} }
pageData.currentPage = 1; pageData.value.currentPage = 1;
pageData.pageSize = 10; pageData.value.pageSize = 10;
pageData.total = 0; pageData.value.total = 0;
await getList(); await getList();
} }
const attrNames = reactive(landsType.map((v) => v.label)); const attrNames = reactive(landsType.map((v) => v.label));
@ -518,9 +521,9 @@ async function handleRowSave(val, done, loading) {
data.landCertificateUrl = landOwnerUrls.join(); data.landCertificateUrl = landOwnerUrls.join();
data.landUrl = landUrls.join(); data.landUrl = landUrls.join();
data.villageCode = data.villageCode[data.villageCode.length - 1] || ''; data.villageCode = data.villageCode[data.villageCode.length - 1] || '';
// if (local.value.length != 0) { if (local.value.length != 0) {
// data.coordinate = `${local.value[0]}E,${local.value[1]}N`; data.coordinate = `${local.value[0]}E,${local.value[1]}N`;
// } }
const res = await saveLand(data); const res = await saveLand(data);
loading(); loading();
if (res.code == 200) { if (res.code == 200) {