refactor(sub-government-affairs-service): 重构新增网格 #4
@ -0,0 +1,43 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
// 新增(POST)
|
||||
export function createGrid(data = {}) {
|
||||
return request('/land-resource/gridManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
// 删除(DELETE)
|
||||
export function deleteGrid(id) {
|
||||
return request(`/land-resource/gridManage/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
// 修改(PUT)
|
||||
export function updateGrid(data = {}) {
|
||||
return request('//land-resource/gridManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
// 查询列表(GET)
|
||||
export function fetchGridList(params) {
|
||||
return request('/land-resource/gridManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
// 获取详情(GET)
|
||||
export function getGridDetail(id) {
|
||||
return request(`/land-resource/gridManage/${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
// 导出(GET + Blob)
|
||||
export function exportGrid(params = {}) {
|
||||
return request('/land-resource/gridManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
@ -1,40 +1,27 @@
|
||||
<template>
|
||||
<div class="area-cascader-container" :style="{ width: width + 'px' }">
|
||||
<div class="area-cascader-container" :style="containerStyle">
|
||||
<!-- 一行显示模式 -->
|
||||
<template v-if="!splitRows">
|
||||
<div v-if="label" class="area-cascader-label">{{ label }}</div>
|
||||
<div style="display: flex; gap: 8px; flex: 1">
|
||||
<el-cascader
|
||||
v-model="selectedAreaCode"
|
||||
:options="areaOptions"
|
||||
:props="cascaderProps"
|
||||
:placeholder="areaPlaceholder"
|
||||
style="flex: 1"
|
||||
clearable
|
||||
/>
|
||||
<div class="controls">
|
||||
<el-cascader v-model="regionModel" :options="areaOptions" :props="cascaderProps" :placeholder="areaPlaceholder" style="flex: 1" clearable />
|
||||
<span v-if="showSeparator" class="area-cascader-separator">{{ separator }}</span>
|
||||
<el-select v-model="selectedGridId" :placeholder="gridPlaceholder" style="flex: 1" clearable :disabled="!selectedAreaCode">
|
||||
<el-option v-for="item in gridOptions" :key="item.gridName" :label="item.gridName" :value="item.id" />
|
||||
<el-select v-model="gridModel" :placeholder="gridPlaceholder" style="flex: 1" :disabled="!regionModel" clearable>
|
||||
<el-option v-for="item in gridOptions" :key="item.id" :label="item.gridName" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 两行显示模式 -->
|
||||
<template v-else>
|
||||
<div class="area-item">
|
||||
<div class="area-cascader-label">所属行政区域</div>
|
||||
<el-cascader
|
||||
v-model="selectedAreaCode"
|
||||
:options="areaOptions"
|
||||
:props="cascaderProps"
|
||||
:placeholder="areaPlaceholder"
|
||||
style="flex: 1"
|
||||
clearable
|
||||
/>
|
||||
<el-cascader v-model="regionModel" :options="areaOptions" :props="cascaderProps" :placeholder="areaPlaceholder" clearable />
|
||||
</div>
|
||||
<div class="area-item">
|
||||
<div class="area-cascader-label">网格</div>
|
||||
<el-select v-model="selectedGridId" :placeholder="gridPlaceholder" style="flex: 1" clearable :disabled="!selectedAreaCode">
|
||||
<el-option v-for="item in gridOptions" :key="item.gridName" :label="item.gridName" :value="item.id" />
|
||||
<el-select v-model="gridModel" :placeholder="gridPlaceholder" :disabled="!regionModel" clearable>
|
||||
<el-option v-for="item in gridOptions" :key="item.id" :label="item.gridName" :value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
@ -42,152 +29,49 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, onMounted, computed } from 'vue';
|
||||
import { ElCascader, ElSelect, ElOption } from 'element-plus';
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import request from '@/utils/axios';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const props = defineProps({
|
||||
regionCode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
gridId: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: '行政区域-网格:',
|
||||
},
|
||||
areaPlaceholder: {
|
||||
type: String,
|
||||
default: '请选择区域',
|
||||
},
|
||||
gridPlaceholder: {
|
||||
type: String,
|
||||
default: '请选择网格',
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 500,
|
||||
},
|
||||
showSeparator: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
separator: {
|
||||
type: String,
|
||||
default: '-',
|
||||
},
|
||||
splitRows: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
regionCode: { type: String, default: '' },
|
||||
gridId: { type: [String, Number], default: '' },
|
||||
label: { type: String, default: '行政区域-网格:' },
|
||||
areaPlaceholder: { type: String, default: '请选择区域' },
|
||||
gridPlaceholder: { type: String, default: '请选择网格' },
|
||||
width: { type: [Number, String], default: 500 },
|
||||
showSeparator: { type: Boolean, default: false },
|
||||
separator: { type: String, default: '-' },
|
||||
splitRows: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:regionCode', 'update:gridId']);
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const areaOptions = ref([]);
|
||||
const gridOptions = ref([]);
|
||||
|
||||
// 本地绑定值
|
||||
const selectedAreaCode = ref(props.regionCode);
|
||||
const selectedGridId = ref(props.gridId);
|
||||
|
||||
// 获取行政区域数据
|
||||
const fetchAreaData = async () => {
|
||||
try {
|
||||
// 使用 request 发起请求,将查询参数放在 params 中
|
||||
const res = await request.get('/system/area/region', {
|
||||
params: {
|
||||
areaCode: '530000',
|
||||
// computed 双向绑定 regionModel & gridModel
|
||||
const regionModel = computed({
|
||||
get() {
|
||||
return props.regionCode;
|
||||
},
|
||||
});
|
||||
areaOptions.value = res.data ?? [];
|
||||
} catch (err) {
|
||||
console.error('区域数据加载失败', err);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取网格列表
|
||||
const fetchGridList = async (regionCode) => {
|
||||
if (!regionCode) return;
|
||||
try {
|
||||
// 使用 request 发起请求,将查询参数放在 params 中
|
||||
const res = await request.get('/land-resource/gridManage/page', {
|
||||
params: {
|
||||
regionCode: regionCode,
|
||||
},
|
||||
});
|
||||
gridOptions.value = res.data?.records ?? [];
|
||||
} catch (err) {
|
||||
console.error('网格数据加载失败', err);
|
||||
}
|
||||
};
|
||||
const selectedAreaLabel = computed(() => {
|
||||
const findLabel = (options, code) => {
|
||||
for (const item of options) {
|
||||
if (item.areaCode === code) return item.areaName;
|
||||
if (item.areaChildVOS?.length) {
|
||||
const res = findLabel(item.areaChildVOS, code);
|
||||
if (res) return res;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
return findLabel(areaOptions.value, selectedAreaCode.value);
|
||||
});
|
||||
|
||||
const selectedGridLabel = computed(() => {
|
||||
const item = gridOptions.value.find((g) => g.id === selectedGridId.value);
|
||||
return item?.gridName || '';
|
||||
});
|
||||
|
||||
// 外部更新时同步内部
|
||||
watch(
|
||||
() => props.regionCode,
|
||||
(val) => {
|
||||
selectedAreaCode.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.gridId,
|
||||
(val) => {
|
||||
selectedGridId.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
// 内部更新时同步外部
|
||||
watch(selectedAreaCode, (val) => {
|
||||
set(val) {
|
||||
emit('update:regionCode', val);
|
||||
selectedGridId.value = ''; // 重置 gridId
|
||||
// reset grid when region changes
|
||||
emit('update:gridId', '');
|
||||
gridOptions.value = [];
|
||||
fetchGridList(val);
|
||||
},
|
||||
});
|
||||
|
||||
watch(selectedGridId, (val) => {
|
||||
const gridModel = computed({
|
||||
get() {
|
||||
return props.gridId;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:gridId', val);
|
||||
},
|
||||
});
|
||||
|
||||
// 更新外部 v-model:value
|
||||
// const updateValue = () => {
|
||||
// console.log('update:value更新外部值', selectedAreaCode.value, selectedGridName.value, selectedGridId.value);
|
||||
// emit('update:value', {
|
||||
// regionCode: selectedAreaCode.value,
|
||||
// gridName: selectedGridName.value,
|
||||
// gridId: selectedGridId.value,
|
||||
// });
|
||||
// };
|
||||
|
||||
onMounted(() => {
|
||||
fetchAreaData();
|
||||
});
|
||||
|
||||
// 自定义字段映射
|
||||
const cascaderProps = computed(() => ({
|
||||
label: 'areaName',
|
||||
value: 'areaCode',
|
||||
@ -195,37 +79,61 @@ const cascaderProps = computed(() => ({
|
||||
emitPath: false,
|
||||
expandTrigger: 'hover',
|
||||
}));
|
||||
|
||||
async function fetchAreaData() {
|
||||
try {
|
||||
const res = await request.get('/system/area/region', { params: { areaCode: '530000' } });
|
||||
areaOptions.value = res.data || [];
|
||||
} catch (err) {
|
||||
console.error('区域数据加载失败', err);
|
||||
}
|
||||
}
|
||||
async function fetchGridList(regionCode) {
|
||||
if (!regionCode) return;
|
||||
try {
|
||||
const res = await request.get('/land-resource/gridManage/page', { params: { regionCode } });
|
||||
gridOptions.value = res.data?.records || [];
|
||||
} catch (err) {
|
||||
console.error('网格数据加载失败', err);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(fetchAreaData);
|
||||
|
||||
// 样式计算
|
||||
const containerStyle = computed(() => ({
|
||||
width: typeof props.width === 'number' ? `${props.width}px` : props.width,
|
||||
display: 'flex',
|
||||
gap: '18px',
|
||||
flexDirection: props.splitRows ? 'column' : 'row',
|
||||
}));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.area-cascader-container {
|
||||
display: flex;
|
||||
gap: 18px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* 分行显示时垂直排列 */
|
||||
flex-direction: v-bind('splitRows ? "column" : "row"');
|
||||
}
|
||||
|
||||
.area-cascader-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
text-align: right;
|
||||
line-height: 32px;
|
||||
box-sizing: border-box;
|
||||
width: 120px;
|
||||
padding-right: v-bind('splitRows ? "12px" : "0"');
|
||||
}
|
||||
|
||||
.area-cascader-separator {
|
||||
align-self: center;
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
.area-item {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
align-items: center;
|
||||
}
|
||||
.area-cascader-separator {
|
||||
align-self: center;
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
}
|
||||
</style>
|
||||
|
@ -24,7 +24,7 @@ const props = defineProps({
|
||||
default: false,
|
||||
},
|
||||
modelValue: {
|
||||
type: Array,
|
||||
type: [Array, String],
|
||||
default: () => [],
|
||||
},
|
||||
label: {
|
||||
@ -39,6 +39,10 @@ const props = defineProps({
|
||||
type: [Number, String],
|
||||
default: 500,
|
||||
},
|
||||
emitPath: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
@ -46,14 +50,35 @@ const emit = defineEmits(['update:modelValue']);
|
||||
const userStore = useUserStore();
|
||||
|
||||
const areaOptions = ref([]);
|
||||
const selectedAreaPath = ref([...props.modelValue]);
|
||||
|
||||
// 检查计算属性有没有循环依赖用
|
||||
// const selectedAreaPath = props.emitPath ? ref([].concat(props.modelValue)) : ref(props.modelValue);
|
||||
|
||||
const selectedAreaPath = computed({
|
||||
get() {
|
||||
// 初始回显 & 外部变更都走这里
|
||||
if (props.emitPath) {
|
||||
return Array.isArray(props.modelValue) ? props.modelValue : [];
|
||||
} else {
|
||||
return typeof props.modelValue === 'string' ? props.modelValue : '';
|
||||
}
|
||||
},
|
||||
set(val) {
|
||||
// 组件内部选中时走这里
|
||||
if (props.emitPath) {
|
||||
emit('update:modelValue', Array.isArray(val) ? val : []);
|
||||
} else {
|
||||
emit('update:modelValue', typeof val === 'string' ? val : '');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// 自定义字段映射
|
||||
const cascaderProps = computed(() => ({
|
||||
label: 'areaName',
|
||||
value: 'areaCode',
|
||||
children: 'areaChildVOS',
|
||||
emitPath: true,
|
||||
emitPath: props.emitPath,
|
||||
expandTrigger: 'hover',
|
||||
}));
|
||||
|
||||
@ -70,7 +95,7 @@ const fetchAreaData = async () => {
|
||||
console.error('加载行政区域失败', err);
|
||||
}
|
||||
};
|
||||
|
||||
// !!!禁止使用外部更新,会造成循环依赖
|
||||
// // 外部更新 => 内部同步
|
||||
// watch(
|
||||
// () => props.modelValue,
|
||||
@ -80,9 +105,19 @@ const fetchAreaData = async () => {
|
||||
// );
|
||||
|
||||
// 内部更新 => 外部同步
|
||||
watch(selectedAreaPath, (val) => {
|
||||
emit('update:modelValue', val);
|
||||
});
|
||||
watch(
|
||||
selectedAreaPath,
|
||||
(val) => {
|
||||
if (props.emitPath) {
|
||||
// 期望数组模式,确保输出数组
|
||||
emit('update:modelValue', Array.isArray(val) ? val : []);
|
||||
} else {
|
||||
// 期望字符串模式,确保输出字符串
|
||||
emit('update:modelValue', typeof val === 'string' ? val : '');
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
fetchAreaData();
|
||||
|
@ -12,6 +12,7 @@
|
||||
:auto-upload="true"
|
||||
:disabled="readonly"
|
||||
:accept="accept"
|
||||
@preview="handlePreview"
|
||||
>
|
||||
<el-icon v-if="fileList.length < limit"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
@ -24,78 +25,74 @@ import { ref, computed } from 'vue';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { CommonUpload } from '@/apis/index';
|
||||
|
||||
// 1. props & emit
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
ossUrl: {
|
||||
type: String,
|
||||
default: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/',
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: 'image/*',
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
modelValue: { type: [Array, String], default: () => [] },
|
||||
ossUrl: { type: String, default: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/' },
|
||||
limit: { type: Number, default: 5 },
|
||||
accept: { type: String, default: 'image/*' },
|
||||
readonly: { type: Boolean, default: false },
|
||||
});
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
// 构造 el-upload 所需 file-list
|
||||
const fileList = computed(() => {
|
||||
return props.modelValue.map((path, idx) => ({
|
||||
name: `image_${idx}`,
|
||||
url: props.ossUrl + path,
|
||||
uid: `${idx}`,
|
||||
}));
|
||||
// 2. 中间层 computed:统一成数组,写时根据 limit 决定发出数组还是字符串
|
||||
const selectedFiles = computed({
|
||||
get() {
|
||||
// 回显:如果父传字符串且 limit===1,就把它当成长度 1 数组
|
||||
if (props.limit === 1 && typeof props.modelValue === 'string' && props.modelValue) {
|
||||
return [props.modelValue];
|
||||
}
|
||||
// 其他情况,确保数组
|
||||
return Array.isArray(props.modelValue) ? props.modelValue : [];
|
||||
},
|
||||
set(val) {
|
||||
// 内部操作后:如果单文件场景,传字符串;多文件场景,传数组
|
||||
if (props.limit === 1) {
|
||||
emit('update:modelValue', val.length ? val[0] : '');
|
||||
} else {
|
||||
emit('update:modelValue', val);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// 预览
|
||||
// 3. fileList & previewList 都基于 selectedFiles
|
||||
const fileList = computed(() =>
|
||||
selectedFiles.value.map((path, idx) => ({
|
||||
name: `file_${idx}`,
|
||||
url: props.ossUrl + path,
|
||||
uid: `${idx}`,
|
||||
}))
|
||||
);
|
||||
const previewShow = ref(false);
|
||||
const previewList = computed(() => fileList.value.map((item) => item.url));
|
||||
const previewIndex = ref(0);
|
||||
const previewList = computed(() => fileList.value.map((f) => f.url));
|
||||
|
||||
// 上传请求内部实现
|
||||
// 4. 上传 & 移除
|
||||
const customUploadRequest = async ({ file, onSuccess, onError }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
try {
|
||||
const res = await CommonUpload(formData);
|
||||
// 假设后端返回 { code:200, data: { url: 'relative/path.jpg' } }
|
||||
onSuccess(res, file);
|
||||
} catch (err) {
|
||||
onError(err);
|
||||
}
|
||||
};
|
||||
|
||||
// 上传成功回调,推入 modelValue
|
||||
function handleUploadSuccess(res) {
|
||||
const relative = res.data?.url;
|
||||
if (relative) {
|
||||
const newArr = [...props.modelValue, relative];
|
||||
emit('update:modelValue', newArr);
|
||||
if (!relative) return;
|
||||
// 推入中间层
|
||||
selectedFiles.value = [...selectedFiles.value, relative];
|
||||
}
|
||||
}
|
||||
|
||||
// 删除图片
|
||||
function handleRemove(file) {
|
||||
const fullUrl = file.url;
|
||||
const relative = fullUrl.replace(props.ossUrl, '');
|
||||
const newArr = props.modelValue.filter((path) => path !== relative);
|
||||
emit('update:modelValue', newArr);
|
||||
const rel = file.url.replace(props.ossUrl, '');
|
||||
selectedFiles.value = selectedFiles.value.filter((p) => p !== rel);
|
||||
}
|
||||
|
||||
// 点击预览
|
||||
// 5. 预览
|
||||
function handlePreview(file) {
|
||||
const idx = fileList.value.findIndex((item) => item.uid === file.uid);
|
||||
if (idx !== -1) {
|
||||
if (idx >= 0) {
|
||||
previewIndex.value = idx;
|
||||
previewShow.value = true;
|
||||
}
|
||||
|
@ -95,16 +95,7 @@
|
||||
<el-input v-model="formDataProperty.landCode" placeholder="请输入产权编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产权证书" prop="propertyCertificateUrl">
|
||||
<el-upload
|
||||
:http-request="customUploadRequest"
|
||||
:on-success="(res, file) => handleUploadSuccess(res, file, 'property')"
|
||||
multiple
|
||||
:show-file-list="true"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">点击上传</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
<FileUploader v-model="formDataProperty.propertyCertificateUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
@ -147,7 +138,7 @@
|
||||
<el-input v-model="viewEditFormData.address" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属网格" prop="gridId">
|
||||
<AreaCascader v-model:grid-id="viewEditFormData.gridId" :width="500" label="" />
|
||||
<AreaCascader v-model="viewEditFormData.regionCode" v-model:grid-id="viewEditFormData.gridId" :width="500" label="" />
|
||||
</el-form-item>
|
||||
<el-form-item label="土壤类型" prop="soilTypeId">
|
||||
<url-select
|
||||
@ -160,20 +151,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="土地照片" prop="landUrl">
|
||||
<template v-if="viewEditFormData.landUrl">
|
||||
<img :src="`${ossUrl}${viewEditFormData.landUrl}`" alt="土地照片" class="preview-image" />
|
||||
</template>
|
||||
<el-upload
|
||||
v-if="!isView"
|
||||
:http-request="customUploadRequest"
|
||||
:on-success="(res, file) => handleUploadSuccess(res, file, 'viewEditBasic')"
|
||||
multiple
|
||||
:show-file-list="true"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">点击上传</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
<FileUploader v-model="viewEditFormData.landUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="土地范围" prop="scope">
|
||||
<el-input v-model="viewEditFormData.scope" />
|
||||
@ -190,20 +168,7 @@
|
||||
<el-input v-model="viewEditFormData.landCode" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产权证书" prop="propertyCertificateUrl">
|
||||
<template v-if="viewEditFormData.propertyCertificateUrl">
|
||||
<img :src="`${ossUrl}${viewEditFormData.propertyCertificateUrl}`" alt="产权证书" class="preview-image" />
|
||||
</template>
|
||||
<el-upload
|
||||
v-if="!isView"
|
||||
:http-request="customUploadRequest"
|
||||
:on-success="(res, file) => handleUploadSuccess(res, file, 'viewEditProperty')"
|
||||
multiple
|
||||
:show-file-list="true"
|
||||
>
|
||||
<template #trigger>
|
||||
<el-button type="primary">点击上传</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
<FileUploader v-model="viewEditFormData.propertyCertificateUrl" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<!-- <FileUploader v-model="localForm.cooperativePhoto" :limit="1" /> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
@ -45,7 +46,7 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="营业执照">
|
||||
<el-upload
|
||||
<!-- <el-upload
|
||||
action="#"
|
||||
:http-request="customUploadRequest"
|
||||
:on-success="(res, file) => handleUploadSuccess(res, file, 'businessLicence')"
|
||||
@ -56,7 +57,8 @@
|
||||
:on-remove="() => handleRemove('businessLicence')"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-upload> -->
|
||||
<FileUploader v-model="localForm.businessLicence" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -2,391 +2,260 @@
|
||||
<div class="custom-page">
|
||||
<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-save="rowSave"
|
||||
@row-update="rowUpdate"
|
||||
@row-del="rowDel"
|
||||
v-model:page="pageData"
|
||||
:data="crudData"
|
||||
:option="crudOptions"
|
||||
:table-loading="loading"
|
||||
@refresh-change="handleRefresh"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
>
|
||||
<template #search="{ size }">
|
||||
<AreaCascader v-model:value="state.query" placeholder="选择行政区域与网格" :width="400" />
|
||||
</template>
|
||||
|
||||
<template #menu-left>
|
||||
<el-button type="success" icon="download" @click="onExport">导出</el-button>
|
||||
</template>
|
||||
|
||||
<template #menu="scope">
|
||||
<custom-table-operate :actions="state.options.actions" :data="scope" />
|
||||
</template>
|
||||
|
||||
<template #detail="scope">
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="基本信息">
|
||||
<avue-detail :option="baseDetailOption" :data="scope.row"></avue-detail>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="网格地图">
|
||||
<div v-if="scope.row.mapUrl" style="height: 400px">
|
||||
<img :src="scope.row.mapUrl" style="max-width: 100%; max-height: 100%" />
|
||||
<template #search>
|
||||
<div class="custom-search">
|
||||
<AreaCascader v-model:region-code="searchForm.regionCode" v-model:grid-id="searchForm.id" :width="600" />
|
||||
<el-button type="primary" @click="handleSearch"> 搜索 </el-button>
|
||||
<el-button @click="resetSearch"> 重置 </el-button>
|
||||
</div>
|
||||
<el-empty v-else description="暂无地图数据"></el-empty>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="其他信息">
|
||||
<avue-detail :option="otherDetailOption" :data="scope.row"></avue-detail>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<template #menu-left>
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新增网格</el-button>
|
||||
<!-- <el-button type="success" icon="download" @click="handleExport">导出</el-button> -->
|
||||
</template>
|
||||
<template #menu="scope">
|
||||
<custom-table-operate :actions="crudOptions.actions" :data="scope" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true">
|
||||
<el-form ref="form" :model="formData" :rules="rules" :disabled="isReadonly" label-width="100px" class="form-item">
|
||||
<p class="form-title">填写网格信息</p>
|
||||
<el-form-item label="网格名称" prop="gridName">
|
||||
<el-input v-model="formData.gridName" placeholder="请输入网格名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属行政区域" prop="gridAreaCode">
|
||||
<AreaSelect v-model="formData.gridAreaCode" :label="null" :emit-path="false" />
|
||||
</el-form-item>
|
||||
<el-form-item label="网格化地图" prop="scopeImg">
|
||||
<FileUploader v-model="formData.scopeImg" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="note">
|
||||
<el-input v-model="formData.note" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button v-if="!isReadonly" type="primary" @click="handleSubmit()"> 保存 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useApp } from '@/hooks';
|
||||
import { CRUD_OPTIONS } from '@/config';
|
||||
import { isEmpty, downloadFile } from '@/utils';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { compact } from 'lodash';
|
||||
import { GetEntityList, AddEntity, UpdateEntity, DeleteEntity, ExportEntity } from '@/apis/resource/grid';
|
||||
|
||||
const { VITE_APP_BASE_API } = import.meta.env;
|
||||
const app = useApp();
|
||||
<script setup>
|
||||
// ---------------------------------------------------------------------
|
||||
// avue-crud 通用代码
|
||||
// ---------------------------------------------------------------------
|
||||
import { ref, reactive, watch, onMounted, computed, nextTick } from 'vue';
|
||||
import { CRUD_OPTIONS } from '@/config';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const UserStore = useUserStore();
|
||||
const crudRef = ref(null);
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
query: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
const user = UserStore.getUserInfo();
|
||||
console.log('admin 属性:', user.admin);
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
const visible = ref(false);
|
||||
const isReadonly = ref(false);
|
||||
const dialogTitle = ref();
|
||||
const formData = ref({
|
||||
gridName: '',
|
||||
gridAreaCode: '',
|
||||
scope: '',
|
||||
scopeImg: '',
|
||||
note: '',
|
||||
});
|
||||
const initialFormData = { ...formData.value };
|
||||
const resetForm = () => {
|
||||
formData.value = { ...initialFormData };
|
||||
};
|
||||
|
||||
const pageData = ref({
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
const searchForm = ref({
|
||||
gridName: '',
|
||||
keyword: '',
|
||||
regionCode: '',
|
||||
},
|
||||
form: {},
|
||||
selection: [],
|
||||
options: {
|
||||
id: '',
|
||||
status: -1,
|
||||
});
|
||||
const initialSearchForm = { ...searchForm.value };
|
||||
const resetSearch = () => {
|
||||
searchForm.value = { ...initialSearchForm };
|
||||
};
|
||||
// 过滤对象,只保留有值的属性
|
||||
const filterObject = (obj) => {
|
||||
const newObj = {};
|
||||
Object.keys(obj).forEach((key) => {
|
||||
const value = obj[key];
|
||||
// 检查值是否有效,排除空字符串、null 和 undefined
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
newObj[key] = value;
|
||||
}
|
||||
});
|
||||
return newObj;
|
||||
};
|
||||
|
||||
const crudData = ref([]);
|
||||
const crudOptions = reactive({
|
||||
...CRUD_OPTIONS,
|
||||
addBtnText: '添加网格',
|
||||
// detail: true,
|
||||
// detailTitle: '详情',
|
||||
addBtn: false,
|
||||
searchBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
{
|
||||
label: '网格编号',
|
||||
prop: 'id',
|
||||
addDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '网格名称',
|
||||
prop: 'gridName',
|
||||
rules: {
|
||||
required: true,
|
||||
message: '请输入',
|
||||
trigger: 'blur',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'gridAreaName',
|
||||
addDisplay: false,
|
||||
viewDisplay: true,
|
||||
rules: {
|
||||
required: true,
|
||||
message: '请输入',
|
||||
trigger: 'blur',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'cities',
|
||||
type: 'cascader',
|
||||
hide: true,
|
||||
span: 24,
|
||||
width: 300,
|
||||
addDisplay: true,
|
||||
editDisplay: true,
|
||||
viewDisplay: false,
|
||||
emitPath: 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: '网格地图',
|
||||
prop: 'mapUrl',
|
||||
type: 'upload',
|
||||
hide: true,
|
||||
// action: `${VITE_APP_BASE_API}/system/file/upload`,
|
||||
},
|
||||
// {
|
||||
// label: '网格名称',
|
||||
// prop: 'gridName',
|
||||
// type: 'select',
|
||||
// addDisplay: false,
|
||||
// hide: true,
|
||||
// // search: true,
|
||||
// searchLabelWidth: 100,
|
||||
// dicUrl: `${VITE_APP_BASE_API}/land-resource/gridManage/page?regionCode={{key}}`,
|
||||
// props: {
|
||||
// label: 'gridName',
|
||||
// value: 'gridName',
|
||||
// },
|
||||
// dicHeaders: {
|
||||
// authorization: UserStore.token,
|
||||
// },
|
||||
// dicFormatter: (res) => res.data?.records,
|
||||
// },
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'note',
|
||||
type: 'textarea',
|
||||
span: 24,
|
||||
rows: 4,
|
||||
overHidden: true,
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
width: 200,
|
||||
hide: true,
|
||||
display: false,
|
||||
},
|
||||
{ label: '网格编号', prop: 'id' },
|
||||
{ label: '网格名称', prop: 'gridName' },
|
||||
{ label: '所属行政区域', prop: 'gridAreaName' },
|
||||
{ label: '备注', prop: 'note' },
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '查看',
|
||||
icon: 'view',
|
||||
event: ({ row }) => rowView(row),
|
||||
event: ({ row }) => handleView(row),
|
||||
},
|
||||
{
|
||||
name: '编辑',
|
||||
icon: 'edit',
|
||||
event: ({ row }) => rowEdit(row),
|
||||
event: ({ row }) => handleEdit(row),
|
||||
},
|
||||
{
|
||||
type: 'danger',
|
||||
name: '删除',
|
||||
icon: 'delete',
|
||||
event: ({ row }) => rowDel(row),
|
||||
event: ({ row }) => handleDelete(row),
|
||||
},
|
||||
],
|
||||
},
|
||||
pageData: {
|
||||
total: 0,
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
data: [],
|
||||
currentRow: {},
|
||||
});
|
||||
const baseDetailOption = {
|
||||
column: [
|
||||
{
|
||||
label: '网格名称',
|
||||
prop: 'gridName',
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'gridAreaName',
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'note',
|
||||
},
|
||||
],
|
||||
const handleRefresh = async () => {
|
||||
searchForm.value = { ...initialSearchForm };
|
||||
getData();
|
||||
};
|
||||
|
||||
const otherDetailOption = {
|
||||
column: [
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
},
|
||||
// 可以添加更多字段...
|
||||
],
|
||||
const handleCurrentChange = (val) => {
|
||||
pageData.value.currentPage = val;
|
||||
};
|
||||
|
||||
// 加载
|
||||
const loadData = () => {
|
||||
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,
|
||||
const handleSizeChange = (val) => {
|
||||
pageData.value.pageSize = val;
|
||||
};
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
app.$message.error(err.msg);
|
||||
state.data = [];
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false;
|
||||
});
|
||||
const handleView = (row) => {
|
||||
isReadonly.value = true;
|
||||
formData.value = { ...row };
|
||||
dialogTitle.value = '查看网格';
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
loadData();
|
||||
|
||||
// 页数
|
||||
const currentChange = (current) => {
|
||||
state.query.current = current;
|
||||
loadData();
|
||||
const handleEdit = (row) => {
|
||||
isReadonly.value = false;
|
||||
formData.value = { ...row };
|
||||
dialogTitle.value = '编辑网格';
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
// 条数
|
||||
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.rowView(row);
|
||||
};
|
||||
|
||||
const setCity = (row) => {
|
||||
if (!isEmpty(row.cities)) {
|
||||
row.provinceCode = row?.cities[0] ?? null;
|
||||
row.cityCode = row?.cities[1] ?? null;
|
||||
row.gridAreaCode = row?.cities[4] ?? null;
|
||||
row.townCode = row?.cities[3] ?? null;
|
||||
row.village = row?.cities[4] ?? null;
|
||||
// row.village = row?.cities.join(',');
|
||||
}
|
||||
};
|
||||
|
||||
// 新增
|
||||
const rowSave = (row, done, loading) => {
|
||||
setCity(row);
|
||||
row.gridAreaCode = row.cities;
|
||||
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) => {
|
||||
const village = !isEmpty(row.village) ? row.village : [];
|
||||
row.cities = compact([row.provinceCode, row.cityCode, row.gridAreaCode ?? '', row.townCode ?? '', ...village]);
|
||||
crudRef.value.rowEdit(row);
|
||||
};
|
||||
const rowUpdate = (row, index, done, loading) => {
|
||||
setCity(row);
|
||||
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, index, done) => {
|
||||
if (isEmpty(row)) return;
|
||||
app
|
||||
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认删除该网格吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
DeleteEntity({ id: row.id })
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
app.$message.success('删除成功!');
|
||||
loadData();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
app.$message.error(err.msg);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
const response = await deleteGrid(row.id);
|
||||
|
||||
ElMessage.success('删除成功');
|
||||
getData();
|
||||
} catch (error) {
|
||||
if (error === 'cancel') {
|
||||
ElMessage.info('已取消删除');
|
||||
} else {
|
||||
ElMessage.error('删除失败');
|
||||
console.error('删除异常:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 导出
|
||||
const onExport = () => {
|
||||
if (isEmpty(state.data)) {
|
||||
app.$message.error('当前暂时没有可供导出的数据!');
|
||||
return;
|
||||
const handleSubmit = async () => {
|
||||
console.log('提交表单:', formData.value);
|
||||
try {
|
||||
if (dialogTitle.value === '新增网格') {
|
||||
await createGrid(formData.value);
|
||||
ElMessage.success('新增成功');
|
||||
} else {
|
||||
await updateGrid(formData.value);
|
||||
ElMessage.success('更新成功');
|
||||
}
|
||||
state.loading = true;
|
||||
const fileName = '网格明细表';
|
||||
ExportEntity(state.query)
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
downloadFile(res.data, `${fileName}.xlsx`, 'blob');
|
||||
app.$message.success('导出成功!');
|
||||
} catch (error) {
|
||||
ElMessage.error(error.message || '新增失败,请重试');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
app.$message.error('导出失败!');
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 业务代码
|
||||
// ---------------------------------------------------------------------
|
||||
import { createGrid, updateGrid, deleteGrid, fetchGridList, getGridDetail, exportGrid } from '@/apis/landResourceManagement/gridManagement';
|
||||
|
||||
onMounted(() => {
|
||||
getData();
|
||||
});
|
||||
const getData = async () => {
|
||||
const filteredParams = filterObject(searchForm.value);
|
||||
const response = await fetchGridList(filteredParams);
|
||||
crudData.value = Array.isArray(response.data.records) ? response.data.records : [];
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
console.log('handleAdd');
|
||||
resetForm();
|
||||
isReadonly.value = false;
|
||||
dialogTitle.value = '新增网格';
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
getData();
|
||||
};
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px;
|
||||
height: calc(100vh - 300px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.form-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin: 30px 0;
|
||||
color: #333333;
|
||||
}
|
||||
.form-item {
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.dialog-footer {
|
||||
text-align: center;
|
||||
}
|
||||
.custom-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.el-button {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<div class="custom-page">
|
||||
<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-save="rowSave"
|
||||
@row-update="rowUpdate"
|
||||
@row-del="rowDel"
|
||||
>
|
||||
<template #search="{ size }">
|
||||
<AreaCascader v-model:value="state.query" placeholder="选择行政区域与网格" :width="400" />
|
||||
</template>
|
||||
|
||||
<template #menu-left>
|
||||
<el-button type="success" icon="download" @click="onExport">导出</el-button>
|
||||
</template>
|
||||
|
||||
<template #menu="scope">
|
||||
<custom-table-operate :actions="state.options.actions" :data="scope" />
|
||||
</template>
|
||||
|
||||
<template #detail="scope">
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="基本信息">
|
||||
<avue-detail :option="baseDetailOption" :data="scope.row"></avue-detail>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="网格地图">
|
||||
<div v-if="scope.row.mapUrl" style="height: 400px">
|
||||
<img :src="scope.row.mapUrl" style="max-width: 100%; max-height: 100%" />
|
||||
</div>
|
||||
<el-empty v-else description="暂无地图数据"></el-empty>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="其他信息">
|
||||
<avue-detail :option="otherDetailOption" :data="scope.row"></avue-detail>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { useApp } from '@/hooks';
|
||||
import { CRUD_OPTIONS } from '@/config';
|
||||
import { isEmpty, downloadFile } from '@/utils';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { compact } from 'lodash';
|
||||
import { GetEntityList, AddEntity, UpdateEntity, DeleteEntity, ExportEntity } from '@/apis/resource/grid';
|
||||
|
||||
const { VITE_APP_BASE_API } = import.meta.env;
|
||||
const app = useApp();
|
||||
const UserStore = useUserStore();
|
||||
const crudRef = ref(null);
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
query: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
gridName: '',
|
||||
regionCode: '',
|
||||
},
|
||||
form: {},
|
||||
selection: [],
|
||||
options: {
|
||||
...CRUD_OPTIONS,
|
||||
addBtnText: '添加网格',
|
||||
// detail: true,
|
||||
// detailTitle: '详情',
|
||||
column: [
|
||||
{
|
||||
label: '网格编号',
|
||||
prop: 'id',
|
||||
addDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '网格名称',
|
||||
prop: 'gridName',
|
||||
rules: {
|
||||
required: true,
|
||||
message: '请输入',
|
||||
trigger: 'blur',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'gridAreaName',
|
||||
addDisplay: false,
|
||||
viewDisplay: true,
|
||||
rules: {
|
||||
required: true,
|
||||
message: '请输入',
|
||||
trigger: 'blur',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'cities',
|
||||
type: 'cascader',
|
||||
hide: true,
|
||||
span: 24,
|
||||
width: 300,
|
||||
addDisplay: true,
|
||||
editDisplay: true,
|
||||
viewDisplay: false,
|
||||
emitPath: 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: '网格地图',
|
||||
prop: 'mapUrl',
|
||||
type: 'upload',
|
||||
hide: true,
|
||||
// action: `${VITE_APP_BASE_API}/system/file/upload`,
|
||||
},
|
||||
// {
|
||||
// label: '网格名称',
|
||||
// prop: 'gridName',
|
||||
// type: 'select',
|
||||
// addDisplay: false,
|
||||
// hide: true,
|
||||
// // search: true,
|
||||
// searchLabelWidth: 100,
|
||||
// dicUrl: `${VITE_APP_BASE_API}/land-resource/gridManage/page?regionCode={{key}}`,
|
||||
// props: {
|
||||
// label: 'gridName',
|
||||
// value: 'gridName',
|
||||
// },
|
||||
// dicHeaders: {
|
||||
// authorization: UserStore.token,
|
||||
// },
|
||||
// dicFormatter: (res) => res.data?.records,
|
||||
// },
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'note',
|
||||
type: 'textarea',
|
||||
span: 24,
|
||||
rows: 4,
|
||||
overHidden: true,
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
width: 200,
|
||||
hide: true,
|
||||
display: false,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: '查看',
|
||||
icon: 'view',
|
||||
event: ({ row }) => rowView(row),
|
||||
},
|
||||
{
|
||||
name: '编辑',
|
||||
icon: 'edit',
|
||||
event: ({ row }) => rowEdit(row),
|
||||
},
|
||||
{
|
||||
type: 'danger',
|
||||
name: '删除',
|
||||
icon: 'delete',
|
||||
event: ({ row }) => rowDel(row),
|
||||
},
|
||||
],
|
||||
},
|
||||
pageData: {
|
||||
total: 0,
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
data: [],
|
||||
currentRow: {},
|
||||
});
|
||||
const baseDetailOption = {
|
||||
column: [
|
||||
{
|
||||
label: '网格名称',
|
||||
prop: 'gridName',
|
||||
},
|
||||
{
|
||||
label: '所属行政区域',
|
||||
prop: 'gridAreaName',
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'note',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const otherDetailOption = {
|
||||
column: [
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
},
|
||||
// 可以添加更多字段...
|
||||
],
|
||||
};
|
||||
|
||||
// 加载
|
||||
const loadData = () => {
|
||||
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;
|
||||
});
|
||||
};
|
||||
|
||||
loadData();
|
||||
|
||||
// 页数
|
||||
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.rowView(row);
|
||||
};
|
||||
|
||||
const setCity = (row) => {
|
||||
if (!isEmpty(row.cities)) {
|
||||
row.provinceCode = row?.cities[0] ?? null;
|
||||
row.cityCode = row?.cities[1] ?? null;
|
||||
row.gridAreaCode = row?.cities[4] ?? null;
|
||||
row.townCode = row?.cities[3] ?? null;
|
||||
row.village = row?.cities[4] ?? null;
|
||||
// row.village = row?.cities.join(',');
|
||||
}
|
||||
};
|
||||
|
||||
// 新增
|
||||
const rowSave = (row, done, loading) => {
|
||||
setCity(row);
|
||||
row.gridAreaCode = row.cities;
|
||||
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) => {
|
||||
const village = !isEmpty(row.village) ? row.village : [];
|
||||
row.cities = compact([row.provinceCode, row.cityCode, row.gridAreaCode ?? '', row.townCode ?? '', ...village]);
|
||||
crudRef.value.rowEdit(row);
|
||||
};
|
||||
const rowUpdate = (row, index, done, loading) => {
|
||||
setCity(row);
|
||||
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, index, done) => {
|
||||
if (isEmpty(row)) return;
|
||||
app
|
||||
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
DeleteEntity({ id: row.id })
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
app.$message.success('删除成功!');
|
||||
loadData();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
app.$message.error(err.msg);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 导出
|
||||
const onExport = () => {
|
||||
if (isEmpty(state.data)) {
|
||||
app.$message.error('当前暂时没有可供导出的数据!');
|
||||
return;
|
||||
}
|
||||
state.loading = true;
|
||||
const fileName = '网格明细表';
|
||||
ExportEntity(state.query)
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
downloadFile(res.data, `${fileName}.xlsx`, 'blob');
|
||||
app.$message.success('导出成功!');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
app.$message.error('导出失败!');
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false;
|
||||
});
|
||||
};
|
||||
</script>
|
Loading…
x
Reference in New Issue
Block a user