Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
姚俊旭 2025-06-13 14:26:19 +08:00
commit b48ed6b5cb
22 changed files with 1041 additions and 738 deletions

View File

@ -4,7 +4,7 @@
基于 qiankun + vue2&vue3 + Vite + vite-plugin-qiankun 技术栈实现的前端微应用架构,实现了主子应用切换。
1、主应用介绍
1、主应用介绍
技术栈 Vite+Vue3 + Element-plus + qiankun + Pinia

View File

@ -17,5 +17,5 @@ VITE_APP_UPLOAD_API = '/uploadApis'
# VITE_APP_UPLOAD_URL = 'http://47.109.205.240:9300'
# 内网接口地址
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:8080'
VITE_APP_VIST_URL = 'http://192.168.18.99'
VITE_APP_UPLOAD_URL = 'http://192.168.18.74:8080'
# VITE_APP_VIST_URL = 'http://192.168.18.99'

View File

@ -14,4 +14,4 @@ VITE_APP_UPLOAD_API = '/uploadApis'
# 内网接口地址
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:8080'
VITE_APP_UPLOAD_URL = 'http://192.168.18.74:8080'

View File

@ -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',
});
}

View File

@ -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" style="flex: 1" :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" style="flex: 1" :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',
},
});
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);
// computed regionModel & gridModel
const regionModel = computed({
get() {
return props.regionCode;
},
set(val) {
emit('update:regionCode', val);
// reset grid when region changes
emit('update:gridId', '');
gridOptions.value = [];
fetchGridList(val);
},
});
const gridModel = computed({
get() {
return props.gridId;
},
set(val) {
emit('update:gridId', val);
},
});
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) => {
emit('update:regionCode', val);
selectedGridId.value = ''; // gridId
emit('update:gridId', '');
fetchGridList(val);
});
watch(selectedGridId, (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,62 @@ 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;
/* background-color: antiquewhite; */
}
.area-cascader-separator {
align-self: center;
font-size: 16px;
color: #606266;
}
</style>

View File

@ -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();

View File

@ -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;
}

View File

@ -0,0 +1,15 @@
import { defineStore } from 'pinia';
import { getEnterList } from '@/apis/businessEntity';
export const useCoop = defineStore('useCoop', {
state: () => ({
data: {},
}),
actions: {
//订单
getData(params) {
return Promise.resolve((useCoop().$state.data = params));
},
},
getters: {},
});

View File

@ -99,7 +99,13 @@
<template #default>
<el-form ref="planForm" :model="formData" :rules="formRules" label-width="120px" class="common-dialog">
<el-form-item label="" label-width="0px">
<AreaCascader v-model:value="areaFormData" split-rows label="所属行政区域-网格" :width="500" />
<AreaCascader
v-model:region-code="formData.regionCode"
v-model:grid-id="formData.gridId"
split-rows
label="所属行政区域-网格"
:width="500"
/>
</el-form-item>
<!-- <AreaCascader v-model:value="areaFormData" split-rows label="所属行政区域-网格" :width="500" /> -->
<el-form-item label="计划名称">
@ -215,6 +221,7 @@ const fetchDetailData = async (id) => {
const res = await getAnnualDetail(id);
if (res.code === 200) {
currentDetailRow.value = res.data;
formData.value = res.data;
} else {
app.$message.error(res.msg || '获取详情数据失败');
}
@ -332,8 +339,8 @@ const state = reactive({
currentAction.value = 'reCreate';
formData.value = { ...row };
if (isGridMember.value) {
formData.value.regionName = row.regionName;
formData.value.gridName = row.gridName;
formData.value.regionCode = row.regionCode;
formData.value.gridId = row.gridId;
}
formData.value.growthCycleUnit = row.growthCycleUnit || '1';
commonDialogVisible.value = true;
@ -349,6 +356,7 @@ const state = reactive({
formData.value.regionName = row.regionName;
formData.value.gridName = row.gridName;
}
formData.value.plantingArea = row.plantingAreaActual;
formData.value.growthCycleUnit = row.growthCycleUnit || '1';
commonDialogVisible.value = true;
},
@ -399,6 +407,7 @@ const submitForm = async () => {
app.$message.success('重新制定计划成功');
} else if (currentAction.value === 'fillActual') {
//
formData.value.planId = formData.value.id;
await saveActualProgress(formData.value);
app.$message.success('填写实际种植信息成功');
} else if (currentAction.value === 'add') {

View File

@ -81,14 +81,7 @@
</el-form>
</el-tab-pane>
<el-tab-pane label="土地产权信息" name="property">
<el-form
ref="propertyFormRef"
:model="formDataProperty"
:rules="propertyRules"
:disabled="disabledProperty"
label-width="120px"
class="form-container"
>
<el-form ref="propertyFormRef" :model="formDataProperty" :rules="propertyRules" label-width="120px" class="form-container">
<el-form-item label="地块名称">
<el-input v-model="formDataProperty.landName" disabled />
</el-form-item>
@ -102,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>
@ -120,7 +104,7 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="addDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleAddSubmit('basic')">提交</el-button>
<el-button v-if="activeTab === 'basic'" type="primary" @click="handleAddSubmit('basic')">提交</el-button>
<el-button v-if="activeTab === 'basic'" :disabled="disabledProperty" @click="activeTab = 'property'">下一步</el-button>
<el-button v-else @click="activeTab = 'basic'">上一步</el-button>
<el-button v-if="activeTab === 'property'" type="primary" @click="handleAddSubmit('property')"> 提交 </el-button>
@ -154,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
@ -167,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" />
@ -197,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>
@ -395,7 +353,7 @@ const option = reactive({
column: [
{ label: '地块名称', prop: 'landName' },
{ label: '所属网格', prop: 'gridName' },
{ label: '面积', prop: 'area' },
{ label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${cellValue}` },
{ label: '土地类型', prop: 'landTypeName' },
{ label: '所属行政区域', prop: 'fullRegionName' },
{ label: '具体位置', prop: 'address' },

View File

@ -25,12 +25,14 @@
>
<el-icon><Plus /></el-icon>
</el-upload>
<!-- <FileUploader v-model="localForm.cooperativePhoto" :limit="1" /> -->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址">
<area-select v-model="localForm.addressArr" :disabled="readonly" :label="null" />
<!-- <el-cascader v-model="localForm.addressArr" :options="options" @change="handleChange" /> -->
</el-form-item>
<el-form-item label="经营产品">
<el-input v-model="localForm.primaryProduct" placeholder="请输入" />
@ -45,7 +47,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 +58,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>
@ -70,6 +73,8 @@ import cloneDeep from 'lodash/cloneDeep';
import { CommonUpload } from '@/apis/index';
import { ElMessage } from 'element-plus';
import Attrs from './Attrs.vue';
import { useCoop } from '../../../../store/modules/coop';
const localForm = useCoop().$state.data;
const props = defineProps({
modelValue: {
@ -77,7 +82,7 @@ const props = defineProps({
required: true,
default: () => ({}),
},
readonly: Boolean,
// readonly: Boolean,
});
const ossUrl = 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/';
@ -87,16 +92,16 @@ const businessLicenceList = ref([]);
const emit = defineEmits(['update:modelValue']);
// props
const localForm = ref({ ...props.modelValue });
// const localForm = ref({ ...props.modelValue });
//
watch(
localForm,
(newVal) => {
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
// watch(
// localForm,
// (newVal) => {
// emit('update:modelValue', { ...newVal });
// },
// { deep: true }
// );
// watch(
// () => props.modelValue,
// (newVal) => {
@ -149,21 +154,21 @@ const handleExceed = () => {
};
//
if (localForm.value.cooperativePhoto) {
if (localForm.cooperativePhoto) {
cooperativePhotoList.value = [
{
name: '合作社照片',
url: ossUrl + localForm.value.cooperativePhoto,
url: ossUrl + localForm.cooperativePhoto,
status: 'success',
},
];
}
if (localForm.value.businessLicence) {
if (localForm.businessLicence) {
businessLicenceList.value = [
{
name: '营业执照',
url: ossUrl + localForm.value.businessLicence,
url: ossUrl + localForm.businessLicence,
status: 'success',
},
];

View File

@ -71,6 +71,8 @@
import { reactive, watch } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import cloneDeep from 'lodash/cloneDeep';
import { useCoop } from '../../../../store/modules/coop';
const localForm = useCoop().$state.data;
const props = defineProps({
modelValue: {
@ -86,23 +88,23 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
//
const localForm = reactive(cloneDeep(props.modelValue));
// const localForm = reactive(cloneDeep(props.modelValue));
// watch
watch(
() => localForm,
(val) => {
emit('update:modelValue', { ...val });
},
{ deep: true }
);
watch(
() => props.modelValue,
(newVal) => {
Object.assign(localForm, cloneDeep(newVal));
},
{ deep: true }
);
// watch(
// () => localForm,
// (val) => {
// emit('update:modelValue', { ...val });
// },
// { deep: true }
// );
// watch(
// () => props.modelValue,
// (newVal) => {
// Object.assign(localForm, cloneDeep(newVal));
// },
// { deep: true }
// );
//
function downloadTemplate(type) {

View File

@ -28,6 +28,8 @@
<script setup>
import { reactive, watch } from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import { useCoop } from '../../../../store/modules/coop';
const localForm = useCoop().$state.data;
const props = defineProps({
modelValue: {
@ -40,22 +42,22 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
const localForm = reactive(cloneDeep(props.modelValue));
// const localForm = reactive(cloneDeep(props.modelValue));
watch(
localForm,
(newVal) => {
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
watch(
() => props.modelValue,
(newVal) => {
Object.assign(localForm, cloneDeep(newVal));
},
{ deep: true }
);
// watch(
// localForm,
// (newVal) => {
// emit('update:modelValue', { ...newVal });
// },
// { deep: true }
// );
// watch(
// () => props.modelValue,
// (newVal) => {
// Object.assign(localForm, cloneDeep(newVal));
// },
// { deep: true }
// );
</script>
<style scoped lang="scss">
.credit-evaluation {

View File

@ -105,6 +105,8 @@ import { ref, reactive, watch, onMounted, computed } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import { ElMessageBox, ElMessage } from 'element-plus';
import { getMemberList, addMember, updateMember, deleteMembers } from '@/apis/businessEntity';
import { useCoop } from '../../../../store/modules/coop';
const defaultFormData = useCoop().$state.data;
const dialogTitle = ref('新增');
const dialogVisible = ref(false);
@ -124,31 +126,31 @@ const searchForm = ref({
});
const crudData = ref([]);
//
const defaultFormData = {
id: '',
entId: '',
name: '',
idType: '101',
idCard: '',
sex: '1',
age: '',
phone: '',
provinceCode: '', //
cityCode: '', //
countyCode: '', //
townCode: '', //
street: '', //
addressArr: [],
detailAddress: '',
area: '',
planCrop: '',
planCropName: '',
address: '',
createTime: '',
createUser: '',
updateTime: '',
updateUser: '',
};
// const defaultFormData = {
// id: '',
// entId: '',
// name: '',
// idType: '101',
// idCard: '',
// sex: '1',
// age: '',
// phone: '',
// provinceCode: '', //
// cityCode: '', //
// countyCode: '', //
// townCode: '', //
// street: '', //
// addressArr: [],
// detailAddress: '',
// area: '',
// planCrop: '',
// planCropName: '',
// address: '',
// createTime: '',
// createUser: '',
// updateTime: '',
// updateUser: '',
// };
// 使
const formData = ref({ ...defaultFormData });
const resetForm = () => {
@ -264,18 +266,18 @@ const handleSave = async () => {
}
};
watch(
() => formData.value.addressArr,
(newValue) => {
if (newValue.length <= 3) {
formData.value.provinceCode = '530000';
formData.value.cityCode = '530900';
formData.value.countyCode = newValue[0];
formData.value.townCode = newValue[1];
formData.value.street = newValue[2];
}
}
);
// watch(
// () => formData.value.addressArr,
// (newValue) => {
// if (newValue.length <= 3) {
// formData.value.provinceCode = '530000';
// formData.value.cityCode = '530900';
// formData.value.countyCode = newValue[0];
// formData.value.townCode = newValue[1];
// formData.value.street = newValue[2];
// }
// }
// );
const handleAdd = () => {
isReadonly.value = false; //
resetForm();

View File

@ -73,6 +73,8 @@
<script setup>
import { reactive, watch } from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import { useCoop } from '../../../../store/modules/coop';
const localForm = useCoop().$state.data;
const props = defineProps({
modelValue: {
@ -86,23 +88,23 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
// props
const localForm = reactive(cloneDeep(props.modelValue));
// const localForm = reactive(cloneDeep(props.modelValue));
//
watch(
localForm,
(newVal) => {
emit('update:modelValue', { ...newVal });
},
{ deep: true }
);
watch(
() => props.modelValue,
(newVal) => {
Object.assign(localForm, cloneDeep(newVal));
},
{ deep: true }
);
// watch(
// localForm,
// (newVal) => {
// emit('update:modelValue', { ...newVal });
// },
// { deep: true }
// );
// watch(
// () => props.modelValue,
// (newVal) => {
// Object.assign(localForm, cloneDeep(newVal));
// },
// { deep: true }
// );
</script>
<style scoped lang="scss">

View File

@ -58,6 +58,9 @@ import TabCreditEvaluation from './components/TabCreditEvaluation.vue';
import TabMember from './components/TabMember.vue';
import { getEnterList, getEnterById, addEnter, updateEnter, approvalEnter, deleteEnter } from '@/apis/businessEntity';
import { cloneDeep } from 'lodash';
import { useCoop } from '../../../store/modules/coop';
const useCoopData = useCoop();
//
const visible = ref(false);
@ -128,6 +131,12 @@ const handleSubmit = async () => {
getData(); //
}
} else if (dialogTitle.value === '编辑') {
formData.value.provinceCode = formData.value.addressArr[0];
formData.value.cityCode = formData.value.addressArr[1];
formData.value.countyCode = formData.value.addressArr[2];
formData.value.townCode = formData.value.addressArr[3];
formData.value.villageCode = formData.value.addressArr[4];
response = await updateEnter(formData.value);
if (response.code === 200) {
ElMessage.success('编辑成功');
@ -336,6 +345,7 @@ function handleTabChange(tab) {
}
const handleAdd = () => {
useCoopData.getData({});
isReadonly.value = false;
// resetForm();
dialogTitle.value = '新增';
@ -358,6 +368,10 @@ const handleView = async (row) => {
//
const handleEdit = async (row) => {
console.log(row);
formData.value = row;
formData.value.addressArr = [row.provinceCode, row.cityCode, row.countyCode, row.townCode, row.villageCode];
useCoopData.getData(formData.value);
loading.value = true;
dialogTitle.value = '编辑';
try {

View File

@ -2,389 +2,266 @@
<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 #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>
</template>
<template #menu-left>
<el-button type="success" icon="download" @click="onExport">导出</el-button>
<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="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>
<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';
// ---------------------------------------------------------------------
// avue-crud
// ---------------------------------------------------------------------
import { ref, reactive, watch, onMounted, computed, nextTick } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import { isEmpty, downloadFile } from '@/utils';
import { ElMessage, ElMessageBox } from 'element-plus';
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',
},
{
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 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 baseDetailOption = {
const initialFormData = { ...formData.value };
const resetForm = () => {
formData.value = { ...initialFormData };
};
const pageData = ref({
currentPage: 1,
pageSize: 10,
total: 0,
});
const searchForm = ref({
gridName: '',
keyword: '',
regionCode: '',
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,
addBtn: false,
searchBtn: false,
emptyBtn: false,
column: [
{ label: '网格编号', prop: 'id' },
{ label: '网格名称', prop: 'gridName' },
{ label: '所属行政区域', prop: 'gridAreaName' },
{ label: '备注', prop: 'note' },
],
actions: [
{
label: '网格名称',
prop: 'gridName',
name: '查看',
icon: 'view',
event: ({ row }) => handleView(row),
},
{
label: '所属行政区域',
prop: 'gridAreaName',
name: '编辑',
icon: 'edit',
event: ({ row }) => handleEdit(row),
},
{
label: '备注',
prop: 'note',
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => handleDelete(row),
},
],
});
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,
};
}
})
.catch((err) => {
app.$message.error(err.msg);
state.data = [];
})
.finally(() => {
state.loading = false;
});
const handleSizeChange = (val) => {
pageData.value.pageSize = val;
};
loadData();
//
const currentChange = (current) => {
state.query.current = current;
loadData();
const handleView = (row) => {
isReadonly.value = true;
formData.value = { ...row };
dialogTitle.value = '查看网格';
visible.value = true;
};
//
const sizeChange = (size) => {
state.query.size = size;
loadData();
const handleEdit = (row) => {
isReadonly.value = false;
formData.value = { ...row };
dialogTitle.value = '编辑网格';
visible.value = true;
};
//
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);
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('新增成功');
resetForm();
visible.value = false;
getData();
} else {
await updateGrid(formData.value);
ElMessage.success('更新成功');
resetForm();
visible.value = false;
getData();
}
} catch (error) {
ElMessage.error(error.message || '新增失败,请重试');
}
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;
});
};
// ---------------------------------------------------------------------
//
// ---------------------------------------------------------------------
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>

View File

@ -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>

View File

@ -48,26 +48,27 @@
</template>
</avue-crud>
<el-dialog v-model="addDialogVisible" :title="isEdit ? '编辑网格员' : '新增网格员'" width="600px">
<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="120px">
<el-dialog :key="dialogTitle" v-model="addDialogVisible" :title="isEdit ? '编辑网格员' : '新增网格员'" width="60%" align-center :draggable="true">
<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="120px" class="form-item">
<p class="form-title">填写网格员信息</p>
<el-form-item label="网格员姓名" prop="memberName">
<el-input v-model="addForm.memberName" style="width: 380px" />
<el-input v-model="addForm.memberName" />
</el-form-item>
<el-form-item label="" prop="gridId" label-width="0px">
<!-- 假设 AreaCascader 是行政区域-网格的级联选择组件 -->
<AreaCascader v-model:region-code="addForm.gridAreaCode" v-model:grid-id="addForm.gridId" split-rows label="" />
</el-form-item>
<el-form-item label="电话号码" prop="phone">
<el-input v-model="addForm.phone" style="width: 380px" />
<el-input v-model="addForm.phone" />
</el-form-item>
<el-form-item label="备注" prop="note">
<el-input v-model="addForm.note" type="textarea" style="width: 380px" />
<el-input v-model="addForm.note" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="addDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitAddForm">确定</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</span>
</template>
</el-dialog>
@ -270,6 +271,7 @@ const selectionChange = (rows) => {
};
const rowView = (row) => {
isEdit.value = false;
crudRef.value.rowView(row);
};
@ -280,6 +282,7 @@ const rowEdit = (row) => {
};
//
const onAdd = () => {
isEdit.value = false;
addDialogVisible.value = true;
//
Object.keys(addForm).forEach((key) => {
@ -351,6 +354,11 @@ const onExport = () => {
</script>
<style scoped lang="scss">
:deep(.el-dialog__body) {
padding: 20px;
height: calc(100vh - 300px);
overflow-y: auto;
}
.custom-page {
padding: 20px;
.custom-search {
@ -394,4 +402,23 @@ const onExport = () => {
}
}
}
.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;
}
:deep(.area-cascader-label) {
padding: 0 12px 0 0;
margin: 0;
width: 120px;
box-sizing: border-box;
}
</style>

View File

@ -86,10 +86,10 @@
<el-button :disabled="data.length == 0" :type="data.length != 0 ? 'primary' : 'info'" @click="toSettlement">结算</el-button>
</div>
</div>
<!-- <div class="pagination">
<div style="color: #999999; font-size: 15px">{{ data.total }}</div>
<el-pagination :page-size="20" :pager-count="11" layout="prev, pager, next" :total="data.total" />
</div> -->
<div class="pagination">
<div style="color: #999999; font-size: 15px">{{ total }}</div>
<el-pagination :page-size="20" :pager-count="11" layout="prev, pager, next" :total="total" @change="pagination" />
</div>
</div>
</div>
</template>
@ -112,12 +112,12 @@ const route = useRoute();
const router = useRouter();
let number = ref(1);
let total = ref(99);
let total = ref(0);
let isAll = ref(false);
let data = ref([]);
let page = reactive({
current: 1,
size: 100,
size: 20,
});
let ids = ref([]);
@ -157,10 +157,19 @@ let datalist = reactive([
onMounted(() => {
shoppingCart(page).then((res) => {
data.value = res.data.records;
total.value = res.data.total;
addIsCheckProperty(data);
});
});
const pagination = (value) => {
page.current = value;
shoppingCart(page).then((res) => {
data.value = res.data.records;
addIsCheckProperty(data);
});
};
function addIsCheckProperty(data) {
if (Array.isArray(data)) {
data.forEach((item) => {
@ -411,6 +420,7 @@ function removeCheckedItems(data) {
background: $color-fff;
}
.fix-top {
z-index: 999;
top: 0;
display: inline-flex;
justify-content: space-between;
@ -461,8 +471,8 @@ function removeCheckedItems(data) {
bottom: 38px;
}
.fix-bottom {
// bottom: 30px;
bottom: 0;
bottom: 30px;
// bottom: 0;
display: inline-flex;
justify-content: space-between;
width: 100%;

View File

@ -40,6 +40,7 @@
</div>
</el-scrollbar>
</div>
<!-- <div style="background-color: #fff; margin-bottom: 20px">订单备注</div> -->
<div class="order-info">
<div class="order-info-top">确认订单信息</div>

View File

@ -341,6 +341,9 @@ const back = () => {
.order-list-warp-left {
width: 55%;
height: 70vh;
overflow: hidden;
overflow-y: scroll;
scrollbar-width: none;
.order-list-warp-left-title {
margin-top: 20px;
font-size: 18px;