468 lines
15 KiB
Vue
468 lines
15 KiB
Vue
<template>
|
|
<div class="custom-page">
|
|
<!-- 搜索区域 -->
|
|
<el-form :inline="true" :model="searchForm" class="search-bar">
|
|
<el-form-item label="关键词">
|
|
<el-input v-model="searchForm.name" placeholder="请输入关键词" clearable />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
|
<el-button @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
<!-- 功能区域 - 只在开发环境显示 -->
|
|
<section v-if="showAddButton" class="function-bar">
|
|
<el-button type="primary" @click="handleAdd">新增</el-button>
|
|
</section>
|
|
<!-- 表格区域 -->
|
|
<div class="table-container">
|
|
<TableComponent
|
|
:loading="loading"
|
|
:columns="columns"
|
|
:table-data="tableData"
|
|
:current-page="pageData.currentPage"
|
|
:page-size="pageData.pageSize"
|
|
:total="pageData.total"
|
|
:show-pagination="true"
|
|
:show-border="true"
|
|
:show-sort="true"
|
|
@page-change="handlePageChange"
|
|
>
|
|
<template #action="scope">
|
|
<custom-table-operate :actions="actions" :data="scope" />
|
|
</template>
|
|
</TableComponent>
|
|
</div>
|
|
|
|
<!-- 详情/编辑对话框 -->
|
|
<el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true">
|
|
<el-tabs v-model="activeFormTab" class="tabs-wrapper">
|
|
<!-- 基本信息标签页 -->
|
|
<el-tab-pane label="基地基本信息" name="basic">
|
|
<el-form ref="basicFormRef" :model="formData" :disabled="isReadonly" label-width="120px">
|
|
<p class="form-title">基地信息</p>
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<!-- 基地编码 -->
|
|
<el-form-item label="基地编码" prop="code">
|
|
<el-input v-model="formData.code" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 所属行政区域 -->
|
|
<el-form-item label="所属行政区域" prop="regionName">
|
|
<el-cascader
|
|
v-model="formData.regionName"
|
|
:options="regionOptions"
|
|
:props="{ checkStrictly: true }"
|
|
:disabled="isReadonly"
|
|
clearable
|
|
/>
|
|
</el-form-item>
|
|
|
|
<!-- 具体位置 -->
|
|
<el-form-item label="具体位置" prop="address">
|
|
<el-input v-model="formData.address" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 气候条件 -->
|
|
<el-form-item label="气候条件" prop="weather">
|
|
<el-select v-model="formData.weather" :disabled="isReadonly" clearable>
|
|
<el-option v-for="item in weatherOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<!-- 面积(亩) -->
|
|
<el-form-item label="面积(亩)" prop="area">
|
|
<el-input-number v-model="formData.area" :min="0" :precision="2" :disabled="isReadonly" controls-position="right" />
|
|
</el-form-item>
|
|
|
|
<!-- 投入使用时间 -->
|
|
<el-form-item label="投入使用时间" prop="commissioningTime">
|
|
<el-date-picker
|
|
v-model="formData.commissioningTime"
|
|
type="date"
|
|
:disabled="isReadonly"
|
|
value-format="YYYY-MM-DD"
|
|
placeholder="选择日期"
|
|
/>
|
|
</el-form-item>
|
|
</el-col>
|
|
|
|
<el-col :span="12">
|
|
<!-- 基地名称 -->
|
|
<el-form-item label="基地名称" prop="name">
|
|
<el-input v-model="formData.name" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 所属网格 -->
|
|
<el-form-item label="所属网格" prop="gridName">
|
|
<el-input v-model="formData.gridName" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 经纬度 -->
|
|
<el-form-item label="经纬度">
|
|
<div class="coordinate-container">
|
|
<el-input v-model="formData.longitude" placeholder="经度" :readonly="isReadonly" style="width: 45%" />
|
|
<span style="margin: 0 5px">,</span>
|
|
<el-input v-model="formData.latitude" placeholder="纬度" :readonly="isReadonly" style="width: 45%" />
|
|
<!-- <el-button v-if="!isReadonly" type="primary" link @click="handleSelectOnMap"> 地图选取 </el-button> -->
|
|
</div>
|
|
</el-form-item>
|
|
|
|
<!-- 海拔 -->
|
|
<el-form-item label="海拔(米)" prop="altitude">
|
|
<el-input-number v-model="formData.altitude" :min="0" :precision="0" :disabled="isReadonly" controls-position="right" />
|
|
</el-form-item>
|
|
|
|
<!-- 基地使用状态 -->
|
|
<el-form-item label="使用状态" prop="status">
|
|
<el-select v-model="formData.status" :disabled="isReadonly" clearable>
|
|
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<!-- 基地照片 -->
|
|
<el-form-item label="基地照片">
|
|
<el-upload
|
|
action="#"
|
|
list-type="picture-card"
|
|
:file-list="formData.baseImages"
|
|
:disabled="isReadonly"
|
|
:auto-upload="false"
|
|
:limit="3"
|
|
:on-change="handleImageChange"
|
|
>
|
|
<el-icon><Plus /></el-icon>
|
|
</el-upload>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<p class="form-title">经营主体信息</p>
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<!-- 经营主体代码 -->
|
|
<el-form-item label="经营主体代码" prop="businessCode">
|
|
<el-input v-model="formData.businessCode" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 经营主体名称 -->
|
|
<el-form-item label="经营主体名称" prop="businessSubjectName">
|
|
<el-input v-model="formData.businessSubjectName" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 联系电话 -->
|
|
<el-form-item label="联系电话" prop="contactPhone">
|
|
<el-input v-model="formData.contactPhone" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
</el-col>
|
|
|
|
<el-col :span="12">
|
|
<!-- 经营主体类型 -->
|
|
<el-form-item label="经营主体类型" prop="businessType">
|
|
<el-select v-model="formData.businessType" :disabled="isReadonly" clearable>
|
|
<el-option v-for="item in businessTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<!-- 联系人 -->
|
|
<el-form-item label="联系人" prop="contactPerson">
|
|
<el-input v-model="formData.contactPerson" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
</el-tab-pane>
|
|
|
|
<!-- 种植信息标签页 -->
|
|
<el-tab-pane label="基地种植信息" name="plantInfo">
|
|
<el-form ref="propertyFormRef" :model="formData" :disabled="isReadonly" label-width="150px">
|
|
<el-row v-for="(item, index) in formData.plantInfoList" :key="index" :gutter="20">
|
|
<el-col :span="12">
|
|
<!-- 地块编号 -->
|
|
<el-form-item label="地块编号" :prop="`plantInfoList.${index}.plotCode`">
|
|
<el-input v-model="item.plotCode" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 面积(亩) -->
|
|
<el-form-item label="面积(亩)" :prop="`plantInfoList.${index}.area`">
|
|
<el-input-number v-model="item.area" :min="0" :precision="2" :disabled="isReadonly" controls-position="right" />
|
|
</el-form-item>
|
|
|
|
<!-- 品种名称 -->
|
|
<el-form-item label="品种名称" :prop="`plantInfoList.${index}.varietyName`">
|
|
<el-input v-model="item.varietyName" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
</el-col>
|
|
|
|
<el-col :span="12">
|
|
<!-- 地块名称 -->
|
|
<el-form-item label="地块名称" :prop="`plantInfoList.${index}.plotName`">
|
|
<el-input v-model="item.plotName" :readonly="isReadonly" clearable />
|
|
</el-form-item>
|
|
|
|
<!-- 作物名称 -->
|
|
<el-form-item label="作物名称" :prop="`plantInfoList.${index}.cropName`">
|
|
<el-select v-model="item.cropName" :disabled="isReadonly" clearable>
|
|
<el-option v-for="crop in cropOptions" :key="crop.value" :label="crop.label" :value="crop.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
|
|
<template #footer>
|
|
<span class="dialog-footer">
|
|
<el-button @click="visible = false">取消</el-button>
|
|
<template v-if="!isReadonly">
|
|
<el-button type="primary" @click="submitAll">修改</el-button>
|
|
</template>
|
|
</span>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, computed } from 'vue';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import { createBase, updateBase, deleteBase, deleteBaseBatch, fetchBaseList, getBaseDetail } from '@/apis/planting/base';
|
|
import { mockData } from './mockData';
|
|
|
|
// ==================== 常量定义 ====================
|
|
const DIALOG_TITLE = {
|
|
VIEW: '查看基地信息',
|
|
EDIT: '编辑基地信息',
|
|
ADD: '新增基地信息',
|
|
};
|
|
// 获取环境变量
|
|
const env = import.meta.env.VITE_MODE;
|
|
console.log('环境变量:', env);
|
|
// ==================== 状态管理 ====================
|
|
const loading = ref(false);
|
|
const visible = ref(false);
|
|
const isReadonly = ref(false);
|
|
const dialogTitle = ref('');
|
|
const activeFormTab = ref('basic');
|
|
|
|
// 表单数据
|
|
const searchForm = ref({});
|
|
const formData = ref({});
|
|
const initialFormData = { ...formData.value };
|
|
|
|
// 分页数据
|
|
const pageData = ref({
|
|
currentPage: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
});
|
|
|
|
// 表格数据
|
|
const tableData = ref([]);
|
|
|
|
// ==================== 表格配置 ====================
|
|
const columns = ref([
|
|
{ label: '基地编码', prop: 'code' },
|
|
{ label: '基地名称', prop: 'name' },
|
|
{ label: '所属行政区域', prop: 'regionName' },
|
|
{ label: '所属网格', prop: 'gridName' },
|
|
{ label: '具体位置', prop: 'location' },
|
|
{
|
|
label: '经纬度',
|
|
prop: 'coordinate',
|
|
// formatter: (row) => `${row.longitude}, ${row.latitude}`,
|
|
},
|
|
{ label: '气候条件', prop: 'climate' },
|
|
{ label: '海拔(米)', prop: 'altitude' },
|
|
{
|
|
label: '面积(亩)',
|
|
prop: 'area',
|
|
formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩`,
|
|
},
|
|
{ label: '使用状态', prop: 'statusName' },
|
|
{ label: '经营主体代码', prop: 'businessId' },
|
|
{ label: '经营主体类型', prop: 'businessTypeName' },
|
|
{ label: '经营主体名称', prop: 'businessName' },
|
|
{ label: '创建时间', prop: 'createTime' },
|
|
{
|
|
label: '操作',
|
|
prop: 'action',
|
|
slotName: 'action',
|
|
fixed: 'right',
|
|
},
|
|
]);
|
|
|
|
const actions = [
|
|
{
|
|
name: '查看',
|
|
icon: 'view',
|
|
event: ({ row }) => handleView(row),
|
|
},
|
|
{
|
|
name: '编辑',
|
|
icon: 'edit',
|
|
event: ({ row }) => handleEdit(row),
|
|
},
|
|
{
|
|
type: 'danger',
|
|
name: '删除',
|
|
icon: 'delete',
|
|
event: ({ row }) => handleDelete(row.id),
|
|
},
|
|
];
|
|
|
|
// ==================== 生命周期 ====================
|
|
onMounted(() => {
|
|
getData();
|
|
});
|
|
|
|
// ==================== 计算属性 ====================
|
|
const showAddButton = computed(() => {
|
|
return env === 'DEV';
|
|
});
|
|
|
|
// ==================== 数据获取 ====================
|
|
const getData = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const res = await fetchBaseList({
|
|
...searchForm.value,
|
|
current: pageData.value.currentPage,
|
|
size: pageData.value.pageSize,
|
|
});
|
|
|
|
tableData.value = res.data.records || [];
|
|
pageData.value.total = res.data.total || 0;
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// ==================== 表格操作 ====================
|
|
const handlePageChange = ({ page, pageSize }) => {
|
|
pageData.value.currentPage = page;
|
|
pageData.value.pageSize = pageSize;
|
|
getData();
|
|
};
|
|
|
|
// ==================== 表单操作 ====================
|
|
const handleAdd = () => {
|
|
resetForm();
|
|
dialogTitle.value = DIALOG_TITLE.ADD;
|
|
visible.value = true;
|
|
};
|
|
|
|
const handleView = async (row) => {
|
|
isReadonly.value = true;
|
|
dialogTitle.value = DIALOG_TITLE.VIEW;
|
|
formData.value = { ...row };
|
|
visible.value = true;
|
|
};
|
|
|
|
const handleEdit = (row) => {
|
|
isReadonly.value = false;
|
|
dialogTitle.value = DIALOG_TITLE.EDIT;
|
|
formData.value = { ...row };
|
|
visible.value = true;
|
|
};
|
|
|
|
const handleDelete = async (id) => {
|
|
await ElMessageBox.confirm('确定删除该基地信息吗?', '提示', {
|
|
type: 'warning',
|
|
});
|
|
await deleteBase(id);
|
|
ElMessage.success('删除成功');
|
|
getData();
|
|
};
|
|
|
|
const resetForm = () => {
|
|
formData.value = { ...initialFormData };
|
|
};
|
|
|
|
const handleSearch = () => {
|
|
pageData.value.currentPage = 1;
|
|
getData();
|
|
};
|
|
|
|
const handleReset = () => {
|
|
searchForm.value = {};
|
|
resetForm();
|
|
handleSearch();
|
|
};
|
|
|
|
const submitAll = () => {
|
|
console.log('提交表单', formData.value);
|
|
visible.value = false;
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.custom-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: calc(100vh - 150px);
|
|
.search-bar {
|
|
flex-shrink: 0;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.table-container {
|
|
flex: 1;
|
|
min-height: 0; /* 解决flex容器内滚动问题 */
|
|
display: flex;
|
|
flex-direction: column;
|
|
:deep(.el-table) {
|
|
flex: 1;
|
|
overflow: auto;
|
|
}
|
|
}
|
|
.tabs-wrapper {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.el-tabs__header {
|
|
width: 100%;
|
|
|
|
.el-tabs__nav-scroll {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.el-tabs__item {
|
|
font-size: 16px;
|
|
color: #555555;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
:deep(.el-tabs__content) {
|
|
padding: 20px;
|
|
border-radius: 4px;
|
|
width: 80%;
|
|
height: calc(100vh - 400px);
|
|
overflow-y: auto;
|
|
|
|
.el-tab-pane {
|
|
margin: 0 auto;
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.form-title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
margin: 30px 0;
|
|
color: #333333;
|
|
}
|
|
|
|
.dialog-footer {
|
|
display: block;
|
|
text-align: center;
|
|
}
|
|
}
|
|
</style>
|