This commit is contained in:
lzc 2025-03-12 09:50:18 +08:00
commit a564d61c22
17 changed files with 924 additions and 211 deletions

View File

@ -50,13 +50,6 @@ export function delPlanCrop(params) {
// });
// }
export function savePlanStage(data) {
return request('land-resource/baseInfo/stageTypeSave', {
method: 'POST',
data,
});
}
// export function upPlanStage(data = {}) {
// return request('land-resource/baseInfo/planTypeEdit', {
// method: 'PUT',
@ -79,3 +72,38 @@ export function savePlanStage(data) {
// }
// #endregion
// #region
export function savePlanStage(data) {
return request('land-resource/baseInfo/stageTypeSave', {
method: 'POST',
data,
});
}
/* ------ ------ */
/* 获取土壤类型列表 */
export function getSoilType(params) {
return request('land-resource/baseInfo/soilTypePage', {
method: 'GET',
params,
});
}
/* 创建土壤类型 */
export function saveSoilType(data) {
return request('land-resource/baseInfo/soilTypeSave', {
method: 'POST',
data,
});
}
/* 编辑土壤类型 */
export function updateSoilType(data) {
return request('land-resource/baseInfo/soilTypeSave', {
method: 'PUT',
data,
});
}
// #endregion

View File

@ -0,0 +1,3 @@
import * as redBlack from './redAndBlank';
export { redBlack };

View File

@ -0,0 +1 @@
import request from '@/utils/request';

View File

@ -3,17 +3,16 @@
* @Author: zenghua.wang
* @Date: 2023-06-20 11:48:41
* @LastEditors: zenghua.wang
* @LastEditTime: 2025-03-06 16:11:29
* @LastEditTime: 2025-03-11 16:51:49
*/
import { createRouter, createWebHistory } from 'vue-router';
import Layout from '@/layouts/index.vue';
import resourceRouter from './modules/resource';
import traceRouter from './modules/trace';
import landsRoutes from './modules/lands';
import dictRoutes from './modules/dict';
import productOperateMainRoutes from './modules/productOperateMain';
import inputSuppliesRoutes from './modules/inputSupplies';
import plantingAndBreedingRouter from './modules/plantingAndBreeding';
export const constantRoutes = [
{
@ -45,10 +44,9 @@ export const constantRoutes = [
},
...resourceRouter,
...traceRouter,
// ...landsRoutes,
// ...dictRoutes,
...productOperateMainRoutes,
...inputSuppliesRoutes,
...plantingAndBreedingRouter,
];
/**

View File

@ -0,0 +1,25 @@
import Layout from '@/layouts/index.vue';
export default [
{
path: '/sub-government-affairs-service/plantingAndBreeding',
name: 'plantingAndBreeding',
component: Layout,
redirect: '/sub-government-affairs-service/breeding-base-information',
meta: { title: '种养植综合管理', icon: 'Document' },
children: [
{
path: '/sub-government-affairs-service/environment-monitor',
name: 'environment-monitor',
component: () => import('@/views/plantingAndBreeding/environment/index.vue'),
meta: { title: '环境监测信息', icon: 'Document' },
},
// {
// path: '/sub-government-affairs-service/breeding-base-information',
// name: 'breeding-base-information',
// component: () => import('@/views/plantingAndBreeding/base/index.vue'),
// meta: { title: '种养殖基地信息', icon: 'Document' },
// },
],
},
];

View File

@ -4,7 +4,7 @@
ref="crudRef"
v-model:page="pageData"
v-model:search="condition"
:table-loading="loading"
:table-loading="_loading"
:data="data"
:option="option"
@search-change="handleSearch"
@ -12,24 +12,24 @@
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
@row-save="handleSave"
@row-update="handleUpdete"
@row-update="handleUpdate"
>
<template #menu="{ index, row }">
<el-dropdown popper-class="custom-table-operate">
<el-icon class="custom-table-operate__more"><More /></el-icon>
<el-dropdown>
<el-icon style="padding: 14px 0"><More /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<template v-for="item in actions" :key="item.name">
<el-dropdown-item @click="item.event(row, index)">
<el-button :type="item.type ?? 'primary'" :icon="item.icon" :size="item.size" :disabled="item.disabled" text>
{{ item.name == '查看' ? (row.status == 1 ? '启用' : '禁用') : item.name }}
{{ item.name == '查看' ? (row.status == '1' ? '禁用' : '启用') : item.name }}
</el-button>
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown></template
>
</el-dropdown>
</template>
</avue-crud>
</CustomCard>
</template>
@ -41,7 +41,7 @@ import useSoilTypeHook from './useSoilTypeHook';
const {
crudRef,
condition,
loading,
_loading,
data,
pageData,
option,
@ -51,7 +51,7 @@ const {
handleSearch,
handleSearchReset,
handleSave,
handleUpdete,
handleUpdate,
} = useSoilTypeHook();
/* --------------- data --------------- */

View File

@ -1,31 +1,17 @@
import { ref, onMounted } from 'vue';
import { ref, onMounted, nextTick } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import { getSoilType, saveSoilType, updateSoilType } from '@/apis/baseInfo';
import { ElMessage } from 'element-plus';
export default function useSoilTypeHook() {
onMounted(getList);
const crudRef = ref();
const condition = ref({
soilType: '',
soilType: null,
});
const data = ref([
{
code: 'a123456',
soilType: '黑土地',
status: 0,
},
{
code: 'b258369',
soilType: '黄土地',
status: 1,
},
{
code: 'c987654',
soilType: '盐碱土地',
status: 0,
},
]);
const loading = ref(false);
const data = ref([]);
const _loading = ref(false);
const pageData = ref({
currentPage: 1,
pageSize: 10,
@ -40,7 +26,7 @@ export default function useSoilTypeHook() {
column: [
{
label: '编号',
prop: 'code',
prop: 'id',
display: false,
addDisplay: false,
},
@ -69,7 +55,7 @@ export default function useSoilTypeHook() {
display: false,
addDisplay: false,
render: ({ row }) => {
return row.status === 0 ? '启用' : '禁用';
return row.status === '1' ? '启用' : '禁用';
},
},
],
@ -92,34 +78,31 @@ export default function useSoilTypeHook() {
event: handleDel,
},
]);
function getList() {
async function getList() {
let params = {
current: pageData.value.currentPage,
pageSize: pageData.value.pageSize,
size: pageData.value.pageSize,
...condition.value,
};
console.log('get --- ', params);
console.table(data.value);
let res = await getSoilType(params);
if (res.code == 200) {
data.value = res.data.records;
pageData.value.total = res.data.total;
}
function handleStatusChange(row, index) {
console.log('handleStatusChange --- ', row);
data.value[index].status = data.value[index].status === 0 ? 1 : 0;
console.table(data.value);
}
async function handleStatusChange(row, index) {
await editSoilType(row, index);
}
function handleCurrentChange(val) {
console.log('handleCurrentChange --- ', val);
pageData.value.currentPage = val;
getList();
}
function handleSizeChange(val) {
console.log('handleSizeChange --- ', val);
pageData.value.currentPage = 1;
pageData.value.pageSize = val;
getList();
}
function handleSearch(val, done) {
console.log('handleSearch --- ', val);
console.log('ccc', condition.value);
resetPage();
done();
}
@ -127,22 +110,43 @@ export default function useSoilTypeHook() {
resetPage();
}
function handleEdit(row, index) {
console.log('handleEdit --- ', row);
console.log('index --- ', index);
crudRef.value.rowEdit(row);
crudRef.value.rowEdit(row, index);
}
function handleDel(row) {
console.log('handleDel --- ', row);
}
function handleSave(form, _loading, done) {
console.log('save --- ', form);
_loading();
async function handleSave(form, loading, done) {
let res = await saveSoilType(form);
if (res.code == 200) {
ElMessage({
type: 'success',
message: '添加成功',
});
}
loading();
getList();
}
function handleUpdate(form, _loading, done) {
console.log('update --- ', form);
_loading();
getList();
async function handleUpdate(row, index, done, loading) {
await editSoilType(row, index);
loading();
done();
}
async function editSoilType(row, index) {
let res = await updateSoilType({
id: row.id,
soilType: row.soilType,
status: row.status === '0' ? '1' : '0',
});
if (res.code == 200) {
ElMessage({
type: 'success',
message: '修改成功',
});
nextTick(() => {
data.value[index].soilType = row.soilType;
data.value[index].status = row.status === '0' ? '1' : '0';
});
}
}
function resetPage() {
pageData.value.currentPage = 1;
@ -152,7 +156,7 @@ export default function useSoilTypeHook() {
return {
crudRef,
condition,
loading,
_loading,
data,
pageData,
option,

View File

@ -64,12 +64,5 @@ watch(
}
}
}
::v-deep() {
.is-active {
.el-radio-button__inner {
background-color: rgb(255, 45, 45) !important;
}
}
}
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<el-radio-group v-model="val" class="radio_group" style="margin-bottom: 30px" @change="emit('update:value', val)">
<el-radio-button v-for="item in options" :key="'radio_' + item.value" :value="item.value" color="red">
{{ item.label }}
</el-radio-button>
</el-radio-group>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
const props = defineProps({
value: {
type: String,
default: '1',
},
});
const emit = defineEmits(['update:value']);
/* --------------- data --------------- */
// #region
const val = ref('1');
watch(
() => props.value,
() => (val.value = props.value),
{
deep: true,
immediate: true,
}
);
const options = reactive([
{
value: '1',
label: '红榜',
},
{
value: '2',
label: '黑榜',
},
]);
// #endregion
/* --------------- methods --------------- */
// #region
// #endregion
</script>
<style lang="scss" scoped>
.radio_group {
justify-content: center;
width: 100%;
font-size: 18px;
> label {
width: 12%;
::v-deep() {
.el-radio-button__inner {
width: 100%;
}
}
}
::v-deep() {
.el-radio-button__inner {
font-size: 18px;
font-weight: bold;
font-family: '黑体';
}
.is-active {
.el-radio-button__inner {
background-color: unset !important;
}
}
&:nth-child(1) {
.el-radio-button__inner {
background-color: red !important;
color: #fff;
border-color: red !important;
}
}
&:nth-child(2) {
.el-radio-button__inner {
color: rgba(28, 111, 255, 0.77) !important;
border-color: #c5c5c5 !important;
}
}
}
}
</style>

View File

@ -1,45 +1,62 @@
<template>
<section class="rank_content" :style="{ '--theme': props.type == 1 ? 'red' : 'black' }">
<!-- <h2>{{ props.type == '1' ? '红' : '黑' }}</h2> -->
<TypeRadio v-model:value="radio" :options="options" />
<section>{{ radio }}</section>
<div v-for="(item, i) in props.data" :key="`rank_${props.type}_${i}`" class="rank_item">
<div class="name">{{ item.name }}</div>
<div></div>
<div></div>
<div></div>
<section class="rank_content" :style="{ '--theme': radio == '1' ? 'red' : 'black' }">
<RankType v-model:value="radio" />
<div class="rank_item rank_header">
<div class="index_">排名</div>
<div>企业名称</div>
<div>上榜理由</div>
<div>企业类型</div>
</div>
<div v-for="(item, i) in radio == '1' ? props.data.red : props.data.black" :key="`rank_${props.type}_${i}`" class="rank_item">
<div class="index_">{{ i + 1 }}</div>
<div>{{ item.name }}</div>
<div>{{ item.reason }}</div>
<div>{{ item.type }}</div>
</div>
</section>
</template>
<script setup>
import { reactive, ref } from 'vue';
import TypeRadio from '../../common/TypeRadio.vue';
import RankType from './RankType.vue';
const props = defineProps({
type: {
type: String,
default: '1',
},
data: {
type: Array,
default: () => [],
type: Object,
default: () => {
return {
red: [
{
name: '企业1',
reason: '企业1',
type: '生产商',
},
{
name: '企业2',
reason: '好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好',
type: '生产商',
},
{
name: '企业3',
reason: '2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222',
type: '生产商',
},
],
black: [
{
name: '企业222',
reason: '不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好',
type: '经销商',
},
],
};
},
},
});
/* --------------- data --------------- */
// #region
const radio = ref('1');
const options = reactive([
{
value: '1',
label: '红榜',
},
{
value: '2',
label: '黑榜',
},
]);
// #endregion
/* --------------- methods --------------- */
@ -49,8 +66,12 @@ const options = reactive([
</script>
<style lang="scss" scoped>
div,
section {
box-sizing: border-box;
}
.rank_content {
border: 1px solid skyblue;
font-size: 16px;
border-radius: 2px;
h2 {
padding: 4px 0;
@ -59,22 +80,33 @@ const options = reactive([
text-align: center;
color: var(--theme);
}
.rank_header {
> div {
background-color: var(--theme);
color: #fff;
}
}
> .rank_item {
display: grid;
grid-template-columns: repeat(4, 1fr);
border-top: 1px solid skyblue;
grid-template-columns: calc(13% + 1px) 39% 24% 24%;
border-top: 1px solid #c6c6c6;
> div {
padding: 6px 12px;
border-right: 1px solid skyblue;
border-right: 1px solid #c6c6c6;
text-align: center;
word-break: break-all;
}
:last-child {
border-right: none;
:first-child {
border-left: 1px solid #c6c6c6;
}
.name {
font-size: 18px;
color: var(--theme);
font-weight: bold;
.index_ {
color: #fff;
background-color: var(--theme);
}
}
.rank_item:last-child {
border-bottom: 1px solid #c6c6c6;
}
}
</style>

View File

@ -1,8 +1,8 @@
<template>
<CustomCard>
<section class="rank_container">
<RankCard type="1" :data="redData" />
<RankCard type="2" :data="blackData" />
<RankCard />
<RankCard />
</section>
</CustomCard>
</template>
@ -72,7 +72,7 @@ const blackData = ref(JSON.parse(JSON.stringify(redData.value)));
padding: 40px 0;
display: grid;
justify-content: center;
grid-template-columns: calc(30%) calc(30%);
grid-template-columns: calc(40%) calc(40%);
gap: 40px;
}
</style>

View File

@ -12,10 +12,10 @@
>
<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">
<div v-for="item in attrs_" :key="`attr_${item.uid}`" class="attrs_content__item">
<video v-if="isMP4(item.url)" :src="item.url" controls />
<img v-else :src="item.url" :alt="item.name" />
<el-icon v-if="props.type != 'view'" class="clear_btn" @click="handleClearAttr(item.id)"><CircleCloseFilled /></el-icon>
<el-icon v-if="props.type != 'view'" class="clear_btn" @click="handleClearAttr(item.uid)"><CircleCloseFilled /></el-icon>
</div>
</section>
</template>
@ -54,8 +54,8 @@ watch(
},
{ deep: true, immediate: true }
);
function handleClearAttr(id) {
attrs_.value = attrs_.value.filter((item) => item.id !== id);
function handleClearAttr(uid) {
attrs_.value = attrs_.value.filter((item) => item.uid !== uid);
emit('update:attrs', attrs_.value);
}
async function rowUploadPicture({ file }) {
@ -65,7 +65,7 @@ async function rowUploadPicture({ file }) {
if (res.code === 200) {
attrs_.value.push({
...res.data,
id: 'id_' + Date.now(),
uid: 'id_' + Date.now(),
});
emit('update:attrs', attrs_.value);
}

View File

@ -1,22 +1,21 @@
<template>
<el-upload
ref="upload"
class="upload-demo"
:limit="props.limit"
:auto-upload="false"
:file-list="fileList"
:on-change="fileChange"
:before-remove="handleDelFile"
>
<el-upload ref="upload" :file-list="fileList" class="upload-demo" :limit="props.limit" :auto-upload="false" :on-change="fileChange">
<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>
<template #file="{ file }">
<section class="file_line">
<span class="name_">{{ file.name }}</span>
<el-icon v-if="props.type == 'view'" @click="handleDown(file)"><Download /></el-icon>
<el-icon v-else @click="handleDelFile(file)"><Close /></el-icon>
</section>
</template>
</el-upload>
</template>
<script setup>
import { ref, watch } from 'vue';
import { ref, watch, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import { CommonUpload } from '@/apis';
@ -38,11 +37,15 @@ const props = defineProps({
type: Number,
default: 20,
},
type: {
type: String,
default: 'view',
},
});
/* --------------- data --------------- */
// #region
const upload = ref();
const fileList = ref([]);
watch(
() => props.attrs,
@ -80,7 +83,10 @@ function delAttr(uid, list = []) {
let i = list.findIndex((v) => v.uid == uid);
if (i < 0) return;
else list.splice(i, 1);
nextTick(() => {
fileList.value = JSON.parse(JSON.stringify(list));
emit('update:attrs', fileList.value);
});
}
async function rowUploadPicture({ raw, name, uid }) {
@ -97,8 +103,33 @@ async function rowUploadPicture({ raw, name, uid }) {
emit('update:attrs', fileList.value);
}
}
async function handleDown(file) {
let res = await fetch(file.url);
let blob = await res.blob();
let link = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.download = file.name;
a.href = link;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
// #endregion
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.file_line {
padding: 0 12px;
display: flex;
justify-content: space-between;
align-items: center;
.name_ {
flex: 1;
margin-right: 24px;
}
.el-icon {
font-size: 16px;
cursor: pointer;
}
}
</style>

View File

@ -7,23 +7,28 @@
:option="option"
:data="data"
:table-loading="_loading"
:before-open="handleOpenFrom"
:before-close="handleCloseFrom"
@current-change="handlePageChange"
@size-change="handleSizeChange"
@search-change="handleSearch"
@search-reset="handleResetSearch"
@row-save="handleRowSave"
@row-update="handleExamine"
@cell-click="handleCellClick"
>
<template #menu="{ row }">
<el-button type="primary" @click="handleInfo(row)">登记处理</el-button>
<el-button v-if="row.status == '0'" type="primary" @click="handleInfo(row)">登记处理</el-button>
</template>
<template #sceneProof-form>
<template #status="{ row }"> {{ row.status == '0' ? '未' : '已' }}处理 </template>
<template #sceneProof-form="{ row, type }">
<section class="proof_content_">
<span>照片视频</span>
<Attrs v-model:attrs="examineForm.proof" type="add" :limit="5" :file-num="5" accept="image/*,video/*" />
<span v-if="type == 'add'">照片视频</span>
<Attrs v-model:attrs="examineForm.proof" :type="type" :limit="5" :file-num="5" accept="image/*,video/*" />
</section>
</template>
<template #attrs_-form>
<FileUpload v-model:attrs="examineForm.attrs" :format="['rar', 'zip', 'doc', 'docx', 'pdf']" />
<template #attrs_-form="{ row, type }">
<FileUpload v-model:attrs="examineForm.attrs" :format="['rar', 'zip', 'doc', 'docx', 'pdf']" :type="type" />
</template>
</avue-crud>
</CustomCard>
@ -31,7 +36,7 @@
</template>
<script setup>
import { ref, reactive, h, onMounted } from 'vue';
import { ref, reactive, h, onMounted, watch } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import CustomCard from '@/components/CustomCard.vue';
import { useUserStore } from '@/store/modules/user';
@ -40,20 +45,19 @@ import FileUpload from './common/FileUpload.vue';
import { getLandIllegal, createLandIllegal, registerLandIllegal, illegalInfo } from '@/apis/land';
import { ElMessage, ElMessageBox } from 'element-plus';
import Attrs from '../../common/Attrs.vue';
import { add } from 'lodash';
const { VITE_APP_BASE_API } = import.meta.env;
const UserStore = useUserStore();
onMounted(() => {
getList();
});
onMounted(getList);
/* --------------- data --------------- */
// #region
const crudRef = ref();
const searchData = ref({
caseId: '',
caseResult: '',
status: '',
});
const page = ref({
currentPage: 1,
@ -63,11 +67,52 @@ const page = ref({
const _loading = ref(false);
const data = ref([]);
const landsArr = ref([]);
const resultData = ref([
{
label: '正常营业,无违规行为',
value: 1,
},
{
label: '简易程序,当场行政处罚',
value: 2,
},
{
label: '普通程序,当场处罚立案审批',
value: 3,
},
{
label: '移送程序,案件移送',
value: 4,
},
{
label: '特殊程序,案件终止',
value: 5,
},
]);
const documentData = ref([
{
label: '协助调查函',
value: 1,
},
{
label: '抽样取样凭证',
value: 2,
},
{
label: '检测报告',
value: 3,
},
{
label: '其他文书',
value: 4,
},
]);
const option = ref({
...CRUD_OPTIONS,
refreshBtn: false,
rowKey: 'caseId',
editTitle: '案件登记处理',
selection: false,
column: [
{
label: '案件编号',
@ -179,16 +224,21 @@ const option = ref({
},
{
label: '案件进度',
prop: 'caseResult',
prop: 'status',
display: false,
search: true,
type: 'select',
dicData: [
{ label: '未处理', value: 0 },
{ label: '已处理', value: 1 },
],
addDisplay: true,
editDisplay: false,
viewDisplay: false,
},
{
label: '案件结果',
prop: 'caseResult',
prop: 'status',
display: false,
addDisplay: true,
editDisplay: false,
@ -232,9 +282,9 @@ const option = ref({
},
{
label: '关联地块',
prop: 'land',
prop: 'relatedLandname',
render: ({ row }) => {
return h('span', {}, row.land);
return h('span', {}, row.relatedLandname);
},
},
{
@ -281,6 +331,13 @@ const option = ref({
span: 24,
display: true,
editDisplay: true,
rules: [
{
required: true,
message: '请输入',
trigger: 'blur',
},
],
},
{
label: '现场取证',
@ -292,33 +349,34 @@ const option = ref({
{
label: '执法文书',
prop: 'lawDocument',
labelSuffix: '件',
span: 24,
display: true,
type: 'radio',
editDisplay: true,
dicData: [
viewDisplay: false,
addDisplay: false,
dicData: documentData.value,
rules: [
{
label: '协助调查函',
value: 1,
},
{
label: '抽样取样凭证',
value: 2,
},
{
label: '检测报告',
value: 3,
},
{
label: '其他文书',
value: 4,
required: true,
message: '请选择',
trigger: 'blur',
},
],
},
{
label: '执法文书',
prop: 'lawDocument',
span: 24,
addDisplay: false,
editDisplay: false,
viewDisplay: true,
render: ({ row }) => {
return h('span', {}, documentData.value.find((item) => item.value == row.lawDocument)?.label);
},
},
{
label: '',
prop: 'attrs_',
span: 24,
},
],
},
@ -331,32 +389,27 @@ const option = ref({
label: '案件处理结果',
prop: 'caseResult',
type: 'radio',
value: 1,
dicData: [
dicData: resultData.value,
span: 24,
addDisplay: false,
viewDisplay: false,
rules: [
{
label: '正常营业,无违规行为',
value: 1,
},
{
label: '简易程序,当场行政处罚',
value: 2,
},
{
label: '普通程序,当场处罚立案审批',
value: 3,
},
{
label: '移送程序,案件移送',
value: 4,
},
{
label: '特殊程序,案件终止',
value: 5,
required: true,
message: '请选择',
trigger: 'blur',
},
],
},
{
label: '案件处理结果',
prop: 'caseResult',
span: 24,
display: true,
editDisplay: true,
addDisplay: false,
editDisplay: false,
render: ({ row }) => {
return h('span', {}, resultData.value.find((item) => item.value == row.caseResult)?.label);
},
},
],
},
@ -370,6 +423,16 @@ const examineForm = reactive({
proof: [],
attrs: [],
});
watch(
() => examineForm,
() => {
console.log('examineForm', examineForm.attrs);
},
{
deep: true,
immediate: true,
}
);
// #endregion
/* --------------- methods --------------- */
@ -377,21 +440,21 @@ const examineForm = reactive({
// #region
async function getList() {
_loading.value = true;
let params = {
current: page.value.currentPage,
size: page.value.pageSize,
...searchData.value,
};
console.log('params -- ', params);
let res = await getLandIllegal(params);
console.log('res -- ', res);
_loading.value = false;
if (res.code == 200) {
data.value = res.data.records;
page.value.total = res.data.total;
}
}
function handlePageChange(val) {
console.log('page', val);
page.value.currentPage = val;
getList();
}
@ -407,13 +470,16 @@ function handleInfo(row) {
crudRef.value.rowEdit(row);
// crudRef.value.rowView(row);
}
function handleSearch(form, done) {
console.log('search', form);
let t = setTimeout(() => {
clearTimeout(t);
async function handleSearch(form, done) {
page.value.currentPage = 1;
await getList();
done();
}, 1000);
}
async function handleResetSearch() {
page.value.currentPage = 1;
await getList();
}
async function handleRowSave(val, done, loading) {
let data = {
caseId: val.caseId,
@ -438,11 +504,9 @@ async function handleRowSave(val, done, loading) {
confirmButtonText: '是,现在添加',
cancelButtonText: '否,后续添加',
type: 'success',
})
.then(() => {
// getDetails('c-1');
})
.catch(() => {});
}).then(() => {
getDetails(val.caseId);
});
}
loading();
}
@ -460,18 +524,60 @@ async function handleExamine(val, done, loading) {
if (examineForm.attrs.length > 0) {
data.lawFile = examineForm.attrs.map((v) => `${v.name}&${v.url}`).join();
}
console.log('val', data);
let res = await registerLandIllegal(data);
console.log('res --', res);
loading();
if (res.code == 200) {
ElMessage.success('提交成功');
getList();
}
}
async function getDetails(id) {
async function getDetails(id, type = 'add') {
examineForm.caseId = id;
let res = await illegalInfo(id);
if (res.code == 200) {
console.log('detaile', res);
if (res.data.evidenceFile) {
examineForm.proof = res.data.evidenceFile.split(',').map((v, i) => {
return {
url: v,
uid: `id_${i}_${Date.now()}`,
};
});
}
if (res.data.lawFile) {
examineForm.attrs = res.data.lawFile.split(',').map((v, i) => {
let [name, url] = v.split('&');
return {
name,
url,
uid: `id_${i}_${Date.now()}`,
status: 'success',
};
});
}
type == 'add' ? crudRef.value.rowEdit(res.data) : crudRef.value.rowView(res.data);
}
}
const cellClick = ref(['caseId', 'caseName']);
function handleCellClick(row, column) {
if (cellClick.value.includes(column.columnKey)) {
getDetails(row.caseId, 'view');
}
}
function handleOpenFrom(done, type) {
console.log('form open', type);
let lab = type == 'view' ? '执法文书附件' : '';
if (type == 'view') {
option.value.group.find((v) => v.prop == 'caseHandle').column.find((v) => v.prop == 'attrs_').label = lab;
}
done();
}
function handleCloseFrom(done) {
console.log('form close');
examineForm.caseId = '';
examineForm.proof = [];
examineForm.attrs = [];
done();
}
// #endregion
</script>

View File

@ -11,9 +11,9 @@
>
<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">
<div v-for="item in attrs_" :key="`attr_${item.uid}`" 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>
<el-icon v-if="props.view != 'view'" class="clear_btn" @click="handleClearAttr(item.uid)"><CircleCloseFilled /></el-icon>
</div>
</section>
</template>
@ -44,8 +44,8 @@ watch(
},
{ deep: true, immediate: true }
);
function handleClearAttr(id) {
attrs_.value = attrs_.value.filter((item) => item.id !== id);
function handleClearAttr(uid) {
attrs_.value = attrs_.value.filter((item) => item.uid !== uid);
emit('update:attrs', attrs_.value);
}
async function rowUploadPicture({ file }) {
@ -55,7 +55,7 @@ async function rowUploadPicture({ file }) {
if (res.code === 200) {
attrs_.value.push({
...res.data,
id: 'id_' + Date.now(),
uid: 'id_' + Date.now(),
});
emit('update:attrs', attrs_.value);
}

View File

@ -469,7 +469,7 @@ function handleView(obj) {
return {
name: `产权附件_${i}`,
url: v,
id: 'id_' + Date.now(),
uid: 'id_' + Date.now(),
};
});
}
@ -478,7 +478,7 @@ function handleView(obj) {
return {
name: `使用信息附件_${i}`,
url: v,
id: 'id_' + Date.now(),
uid: 'id_' + Date.now(),
};
});
if (obj.landUrl) {
@ -486,7 +486,7 @@ function handleView(obj) {
return {
name: `位置附件_${i}`,
url: v,
id: 'id_' + Date.now(),
uid: 'id_' + Date.now(),
};
});
}

View File

@ -0,0 +1,406 @@
<template>
<div class="custom-page">
<el-row :gutter="20">
<el-col :span="4">
<custom-table-tree title="土地分类" :data="landTypeData" @node-click="onNodeClick" />
</el-col>
<el-col :span="20">
<avue-crud
ref="crudRef"
v-model="state.form"
v-model:search="state.query"
v-model:page="state.pageData"
:table-loading="state.loading"
:data="state.data"
:option="state.options"
@refresh-change="refreshChange"
@search-reset="searchChange"
@search-change="searchChange"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@row-del="rowDel"
@row-save="rowSave"
@row-update="rowUpdate"
>
<!-- <template #menu-left>
<el-button type="primary" icon="Plus" @click="onAdd">新增</el-button>
<el-button type="success" icon="download" @click="onExport">导出</el-button>
</template> -->
<template #menu="scope">
<custom-table-operate :actions="state.options.actions" :data="scope" />
</template>
</avue-crud>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { useApp } from '@/hooks';
import { useUserStore } from '@/store/modules/user';
import { CRUD_OPTIONS } from '@/config';
import { mockData, sleep } from '@/utils';
const { VITE_APP_BASE_API } = import.meta.env;
const app = useApp();
const UserStore = useUserStore();
const crudRef = ref(null);
const landTypeData = ref([
{
label: '农用地',
id: '0',
children: [
{ label: '耕地', id: '01', children: [], pId: '0' },
{ label: '园地', children: [], id: '02', pId: '0' },
],
},
{
label: '建设用地',
id: '1',
children: [{ label: '城乡建设用地', children: [], id: '11', pId: '10' }],
},
{
label: '住宅用地',
id: '2',
children: [],
},
]);
const state = reactive({
loading: false,
query: {
current: 1,
size: 10,
},
form: {},
// selection: [],
options: {
...CRUD_OPTIONS,
addBtnText: '阀值设置',
selection: false,
column: [
{
label: '地块名称',
prop: 'p1',
search: true,
width: 200,
rules: {
required: true,
message: '请输入',
trigger: 'blur',
},
},
{
label: '地点',
prop: 'p2',
width: 200,
// type: 'cascader',
// hide: true,
// addDisplay: true,
// editDisplay: true,
// viewDisplay: false,
// 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 ?? [],
rules: {
required: true,
message: '请选择',
trigger: 'blur',
},
},
{
label: '土壤环境报告',
children: [
{
label: '酸碱度(PH值)',
prop: 'p3',
width: 150,
},
{
label: '土壤质地',
prop: 'p4',
width: 150,
},
{
label: '养分含量',
prop: 'p5',
width: 150,
},
{
label: '重金属含量',
prop: 'p6',
width: 150,
overHidden: true,
},
],
},
{
label: '水环境报告',
children: [
{
label: '水温',
prop: 'p7',
},
{
label: '浑浊度',
prop: 'p8',
},
{
label: '酸碱度',
prop: 'p9',
},
{
label: '盐分含量',
prop: 'p10',
width: 150,
},
{
label: '重金属和有害物质',
prop: 'p11',
width: 150,
overHidden: true,
},
],
},
{
label: '大气环境报告',
children: [
{
label: '温度',
prop: 'p12',
},
{
label: '湿度',
prop: 'p13',
},
{
label: '风速',
prop: 'p14',
},
{
label: '风向',
prop: 'p15',
},
{
label: '光照强度',
prop: 'p16',
width: 150,
},
{
label: '降雨量',
prop: 'p17',
},
{
label: '有害气体',
prop: 'p18',
width: 150,
},
],
},
{
label: '创建时间',
prop: 'createTime',
width: 200,
search: true,
display: false,
},
{
label: '更新时间',
prop: 'updateTime',
width: 200,
display: false,
},
],
actions: [
{
name: '查看',
icon: 'view',
event: ({ row }) => rowView(row),
},
{
name: '编辑',
icon: 'edit',
event: ({ row }) => rowEdit(row),
},
{
type: 'success',
name: ({ row }) => {
return row.status === 1 ? '禁用' : '启用';
},
icon: ({ row }) => {
return row.status === 1 ? 'turnOff' : 'open';
},
event: ({ row }) => rowStatus(row),
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => rowDel(row),
},
],
},
pageData: {
total: 0,
currentPage: 1,
pageSize: 10,
},
data: [],
currentRow: {},
});
const loadData = async () => {
//state.loading = true;
// GetEntityList(state.query)
// .then((res) => {
// if (res.code === 200) {
// const { current, size, total, records } = res.data;
// state.data = records;
// state.pageData = {
// currentPage: current || 1,
// pageSize: size || 10,
// total: total,
// };
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// state.data = [];
// })
// .finally(() => {
// state.loading = false;
// });
state.loading = true;
await sleep(500);
state.data = mockData(
{
p1: '202501号地',
p2: '耿马县/耿马镇',
p3: '酸性',
p4: '正常',
p5: '正常',
p7: '正常',
p6: '正常',
p8: '正常',
p9: '正常',
p10: '正常',
p11: '铜含量接近阀值',
p12: '正常',
p13: '正常',
p14: '正常',
p15: '东南风',
p16: '正常',
p17: '偏低',
p18: '正常',
status: 1,
createTime: '2025-01-01',
updateTime: '2025-01-15',
},
10
);
state.loading = false;
};
loadData();
const onNodeClick = (data) => {
console.log('onNodeClick', data);
};
//
const currentChange = (current) => {
state.query.current = current;
loadData();
};
//
const sizeChange = (size) => {
state.query.size = size;
loadData();
};
//
const searchChange = (params, done) => {
if (done) done();
state.query = params;
state.query.current = 1;
loadData();
};
//
const refreshChange = () => {
loadData();
app.$message.success('刷新成功');
};
//
const selectionChange = (rows) => {
state.selection = rows;
};
//
const rowView = (row) => {
crudRef.value && crudRef.value.rowView(row);
};
//
const rowStatus = (row) => {
console.info('操作状态');
};
//
const onAdd = () => {
crudRef.value && crudRef.value.rowAdd();
};
const rowSave = (row, done, loading) => {
// AddEntity(row)
// .then((res) => {
// if (res.code === 200) {
// app.$message.success('');
// done();
// loadData();
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// })
// .finally(() => {
// loading();
// });
};
//
const rowEdit = (row) => {
crudRef.value && crudRef.value.rowEdit(row);
};
const rowUpdate = (row, index, done, loading) => {
// UpdateEntity(row)
// .then((res) => {
// if (res.code === 200) {
// app.$message.success('');
// done();
// loadData();
// }
// })
// .catch((err) => {
// app.$message.error(err.msg);
// })
// .finally(() => {
// loading();
// });
};
//
const rowDel = (row) => {};
</script>