农户档案、种植基地档案、种植批次档案、农事作业档案
This commit is contained in:
		
							parent
							
								
									a72183b3ac
								
							
						
					
					
						commit
						43b61e29e2
					
				| @ -1,5 +1,6 @@ | ||||
| <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 /> | ||||
| @ -23,83 +24,301 @@ | ||||
|         <el-button @click="handleReset">重置</el-button> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <avue-crud | ||||
|       ref="crudRef" | ||||
|       v-model:page="pagination" | ||||
|       :data="crudData" | ||||
|       :option="crudOptions" | ||||
|       :table-loading="loading" | ||||
|       @current-change="handleCurrentChange" | ||||
|       @size-change="handleSizeChange" | ||||
|     <!-- 功能区域 --> | ||||
|     <section class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <!-- <template #menu="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> --> | ||||
|     </avue-crud> | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <el-form ref="basicFormRef" :model="formData" :disabled="isReadonly" label-width="120px"> | ||||
|         <p class="form-title">种植信息</p> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="4"> | ||||
|             <!-- 作物图片 --> | ||||
|             <FileUploader v-model="formData.cropUrl" :limit="1" /> | ||||
|           </el-col> | ||||
|           <el-col :span="10"> | ||||
|             <!-- 种植作物 --> | ||||
|             <el-form-item label="种植作物" prop="cropName"> | ||||
|               <el-input v-model="formData.cropName" placeholder="请输入种植作物名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 地块编号 --> | ||||
|             <el-form-item label="地块编号" prop="plotCode"> | ||||
|               <el-input v-model="formData.plotCode" placeholder="请输入地块编号" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地编号 --> | ||||
|             <el-form-item label="种植基地编号" prop="baseCode"> | ||||
|               <el-input v-model="formData.baseCode" placeholder="请输入种植基地编号" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植批次编号 --> | ||||
|             <el-form-item label="种植批次编号" prop="batchCode"> | ||||
|               <el-input v-model="formData.batchCode" placeholder="请输入种植批次编号" clearable /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
| 
 | ||||
|           <el-col :span="10"> | ||||
|             <!-- 作物品种 --> | ||||
|             <el-form-item label="作物品种" prop="cropVariety"> | ||||
|               <el-select v-model="formData.cropVariety" placeholder="请选择作物品种" clearable filterable> | ||||
|                 <el-option v-for="item in cropVarieties" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 地块名称 --> | ||||
|             <el-form-item label="地块名称" prop="plotName"> | ||||
|               <el-input v-model="formData.plotName" placeholder="请输入地块名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地 --> | ||||
|             <el-form-item label="种植基地" prop="baseName"> | ||||
|               <el-input v-model="formData.baseName" placeholder="请输入种植基地名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植批次 --> | ||||
|             <el-form-item label="种植批次" prop="batchName"> | ||||
|               <el-input v-model="formData.batchName" placeholder="请输入种植批次名称" clearable /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
| 
 | ||||
|         <p class="form-title">农事作业管理</p> | ||||
|         <el-form-item label="农事作业列表"> | ||||
|           <el-card v-for="(task, index) in formData.farmingTasks" :key="index" class="mb-4"> | ||||
|             <el-row :gutter="20"> | ||||
|               <el-col :span="4"> | ||||
|                 <!-- 作业图片占位,可加上传组件 --> | ||||
|                 <div | ||||
|                   style=" | ||||
|                     width: 100px; | ||||
|                     height: 100px; | ||||
|                     background-color: #f0f0f0; | ||||
|                     border: 1px solid #ccc; | ||||
|                     display: flex; | ||||
|                     align-items: center; | ||||
|                     justify-content: center; | ||||
|                   " | ||||
|                 > | ||||
|                   <FileUploader v-model="formData.cropUrl" :limit="1" /> | ||||
|                 </div> | ||||
|               </el-col> | ||||
|               <el-col :span="20"> | ||||
|                 <el-row> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="作业类型"> | ||||
|                       <el-input v-model="task.type" placeholder="如:种子处理、播种等" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="负责人"> | ||||
|                       <el-input v-model="task.responsible" placeholder="请输入负责人" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-row> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="开始时间"> | ||||
|                       <el-date-picker v-model="task.startDate" type="date" placeholder="选择开始日期" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="结束时间"> | ||||
|                       <el-date-picker v-model="task.endDate" type="date" placeholder="选择结束日期" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-form-item label="作业内容"> | ||||
|                   <el-input v-model="task.content" type="textarea" rows="3" placeholder="请输入具体作业内容" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="实际作业情况"> | ||||
|                   <el-input v-model="task.actual" type="textarea" rows="2" placeholder="如:肥料使用量:XX 公斤/亩" /> | ||||
|                 </el-form-item> | ||||
|                 <el-button type="danger" @click="removeTask(index)">删除此作业</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|           </el-card> | ||||
|           <el-button type="primary" plain @click="addTask">新增作业</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
| 
 | ||||
|       <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, watch, onMounted, computed } from 'vue'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { mockData } from './mockData'; | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
| }); | ||||
| const getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   crudData.value = mockData; | ||||
|   pagination.value.total = crudData.value.length; | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '农事作业详情', | ||||
|   EDIT: '编辑农事作业信息', | ||||
|   ADD: '新增农事作业', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| const loading = ref(false); | ||||
| const visible = ref(false); | ||||
| const isReadonly = ref(false); | ||||
| const dialogTitle = ref(''); | ||||
| // const activeFormTab = ref('basic'); | ||||
| 
 | ||||
| // 表单数据 | ||||
| const searchForm = ref({}); | ||||
| 
 | ||||
| const pagination = ref({ | ||||
| const formData = ref({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| const crudData = ref([]); | ||||
| const crudOptions = ref({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   header: false, | ||||
|   menu: false, | ||||
|   height: 'calc(100vh - 330px)', | ||||
|   column: [ | ||||
|     { label: '地块编号', prop: 'landNumber', width: 160 }, | ||||
|     { label: '地块名称', prop: 'landName', width: 170 }, | ||||
|     { label: '面积', prop: 'planArea', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|     { label: '所属行政区域', prop: 'belongRegion', width: 160 }, | ||||
|     { label: '所属网格', prop: 'belongGrid', width: 90 }, | ||||
|     { label: '具体位置', prop: 'address', width: 160 }, | ||||
|     { label: '基地编码', prop: 'baseCode' }, | ||||
|     { label: '基地名称', prop: 'baseName' }, | ||||
|     { label: '种植批次编码', prop: 'batchCode' }, | ||||
|     { label: '种植批次名称', prop: 'batchName' }, | ||||
|     { label: '种植作物', prop: 'crop' }, | ||||
|     { label: '作物品种', prop: 'cropBrand' }, | ||||
|     { label: '种植开始时间', prop: 'startDate' }, | ||||
|     { label: '种植结束时间', prop: 'endDate' }, | ||||
|     { label: '经营主体代码', prop: 'businessEntityCode', width: 130 }, | ||||
|     { label: '经营主体类型', prop: 'businessEntityType', width: 130 }, | ||||
|     { label: '经营主体名称', prop: 'businessEntityName', width: 130 }, | ||||
|     { label: '账号(手机号)', prop: 'account', width: 130 }, | ||||
|     { label: '信息填报时间', prop: 'fillTime', width: 110 }, | ||||
|     { label: '信息审核时间', prop: 'approvalTime', width: 110 }, | ||||
|   ], | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '地块编号', prop: 'landNumber', width: 160 }, | ||||
|   { label: '地块名称', prop: 'landName', width: 170 }, | ||||
|   { label: '面积', prop: 'planArea', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|   { label: '所属行政区域', prop: 'belongRegion', width: 160 }, | ||||
|   { label: '所属网格', prop: 'belongGrid', width: 90 }, | ||||
|   { label: '具体位置', prop: 'address', width: 160 }, | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '基地名称', prop: 'baseName' }, | ||||
|   { label: '种植批次编码', prop: 'batchCode' }, | ||||
|   { label: '种植批次名称', prop: 'batchName' }, | ||||
|   { label: '种植作物', prop: 'crop' }, | ||||
|   { label: '作物品种', prop: 'cropBrand' }, | ||||
|   { label: '种植开始时间', prop: 'startDate' }, | ||||
|   { label: '种植结束时间', prop: 'endDate' }, | ||||
|   { label: '经营主体代码', prop: 'businessEntityCode', width: 130 }, | ||||
|   { label: '经营主体类型', prop: 'businessEntityType', width: 130 }, | ||||
|   { label: '经营主体名称', prop: 'businessEntityName', width: 130 }, | ||||
|   { label: '账号(手机号)', prop: 'account', width: 130 }, | ||||
|   { label: '信息填报时间', prop: 'fillTime', width: 110 }, | ||||
|   { label: '信息审核时间', prop: 'approvalTime', width: 110 }, | ||||
|   { 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 handleCurrentChange = (val) => { | ||||
|   pagination.value.currentPage = val; | ||||
| // ==================== 数据获取 ==================== | ||||
| const getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   tableData.value = mockData; | ||||
|   pageData.value.total = tableData.value.length; | ||||
| }; | ||||
| const handleSizeChange = (val) => { | ||||
|   pagination.value.pageSize = val; | ||||
| // ==================== 表格操作 ==================== | ||||
| const handlePageChange = ({ page, pageSize }) => { | ||||
|   pageData.value.currentPage = page; | ||||
|   pageData.value.pageSize = pageSize; | ||||
|   getData(); | ||||
| }; | ||||
| const getActions = (row) => { | ||||
|   return [{ name: '查看', icon: 'view', event: () => handleView(row) }]; | ||||
| // ==================== 表单操作 ==================== | ||||
| const handleAdd = () => { | ||||
|   resetForm(); | ||||
|   dialogTitle.value = DIALOG_TITLE.ADD; | ||||
|   visible.value = true; | ||||
| }; | ||||
| const handleView = (row) => { | ||||
|   console.log(row); | ||||
| 
 | ||||
| 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     gridName: '', | ||||
|     gridAreaCode: '', | ||||
|     scope: '', | ||||
|     scopeImg: '', | ||||
|     note: '', | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| const handleSearch = () => { | ||||
|   pageData.value.currentPage = 1; | ||||
|   getData(); | ||||
| }; | ||||
| 
 | ||||
| const handleReset = () => { | ||||
|   searchForm.value = {}; | ||||
|   resetForm(); | ||||
|   handleSearch(); | ||||
| }; | ||||
| 
 | ||||
| const submitAll = () => { | ||||
|   console.log('提交表单', formData.value); | ||||
|   visible.value = false; | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <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 /> | ||||
| @ -9,77 +10,431 @@ | ||||
|         <el-button @click="handleReset">重置</el-button> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <avue-crud | ||||
|       ref="crudRef" | ||||
|       v-model:page="pagination" | ||||
|       :data="crudData" | ||||
|       :option="crudOptions" | ||||
|       :table-loading="loading" | ||||
|       @current-change="handleCurrentChange" | ||||
|       @size-change="handleSizeChange" | ||||
|     <!-- 功能区域 --> | ||||
|     <section class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <!-- <template #menu="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> --> | ||||
|     </avue-crud> | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <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="baseCode"> | ||||
|                   <el-input v-model="formData.baseCode" :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="baseName"> | ||||
|                   <el-input v-model="formData.baseName" :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, watch, onMounted, computed } from 'vue'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { ref, onMounted } from 'vue'; | ||||
| import { mockData } from './mockData'; | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
| }); | ||||
| const getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   crudData.value = mockData; | ||||
|   pagination.value.total = crudData.value.length; | ||||
| }; | ||||
| const loading = ref(false); | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '查看基地信息', | ||||
|   EDIT: '编辑基地信息', | ||||
|   ADD: '新增基地信息', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| const loading = ref(false); | ||||
| const visible = ref(false); | ||||
| const isReadonly = ref(false); | ||||
| const dialogTitle = ref(''); | ||||
| const activeFormTab = ref('basic'); | ||||
| 
 | ||||
| // 表单数据 | ||||
| const searchForm = ref({}); | ||||
| const pagination = ref({ | ||||
| const formData = ref({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| 
 | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| const crudData = ref([]); | ||||
| const crudOptions = ref({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   header: false, | ||||
|   menu: false, | ||||
|   height: 'calc(100vh - 330px)', | ||||
|   column: [ | ||||
|     { label: '基地编码', prop: 'baseCode' }, | ||||
|     { label: '基地名称', prop: 'baseName' }, | ||||
|     { label: '所属行政区域', prop: 'regionName' }, | ||||
|     { label: '所属网格', prop: 'gridName' }, | ||||
|     { label: '具体位置', prop: 'adress' }, | ||||
|     { label: '经纬度', prop: 'coordinate', formatter: (row) => `${row.longitude}, ${row.latitude}` }, | ||||
|     { label: '气候条件', prop: 'weather' }, | ||||
|     { label: '海拔(米)', prop: 'altitude' }, | ||||
|     { label: '面积(亩)', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|     { label: '使用状态', prop: 'status' }, | ||||
|     { label: '经营主体代码', prop: 'businessCode' }, | ||||
|     { label: '经营主体类型', prop: 'businessType' }, | ||||
|     { label: '经营主体名称', prop: 'businessSubjectName' }, | ||||
|     { label: '创建时间', prop: 'createTime' }, | ||||
|   ], | ||||
| 
 | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| 
 | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '基地名称', prop: 'baseName' }, | ||||
|   { label: '所属行政区域', prop: 'regionName' }, | ||||
|   { label: '所属网格', prop: 'gridName' }, | ||||
|   { label: '具体位置', prop: 'adress' }, | ||||
|   { | ||||
|     label: '经纬度', | ||||
|     prop: 'coordinate', | ||||
|     formatter: (row) => `${row.longitude}, ${row.latitude}`, | ||||
|   }, | ||||
|   { label: '气候条件', prop: 'weather' }, | ||||
|   { label: '海拔(米)', prop: 'altitude' }, | ||||
|   { | ||||
|     label: '面积(亩)', | ||||
|     prop: 'area', | ||||
|     formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩`, | ||||
|   }, | ||||
|   { label: '使用状态', prop: 'status' }, | ||||
|   { label: '经营主体代码', prop: 'businessCode' }, | ||||
|   { label: '经营主体类型', prop: 'businessType' }, | ||||
|   { label: '经营主体名称', prop: 'businessSubjectName' }, | ||||
|   { 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 handleCurrentChange = (val) => { | ||||
|   pagination.value.currentPage = val; | ||||
| 
 | ||||
| // ==================== 数据获取 ==================== | ||||
| const getData = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|     tableData.value = mockData; | ||||
|     pageData.value.total = tableData.value.length; | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| const handleSizeChange = (val) => { | ||||
|   pagination.value.pageSize = val; | ||||
| 
 | ||||
| // ==================== 表格操作 ==================== | ||||
| const handlePageChange = ({ page, pageSize }) => { | ||||
|   pageData.value.currentPage = page; | ||||
|   pageData.value.pageSize = pageSize; | ||||
|   getData(); | ||||
| }; | ||||
| const getActions = (row) => { | ||||
|   return [{ name: '查看', icon: 'view', event: () => handleView(row) }]; | ||||
| 
 | ||||
| // ==================== 表单操作 ==================== | ||||
| const handleAdd = () => { | ||||
|   resetForm(); | ||||
|   dialogTitle.value = DIALOG_TITLE.ADD; | ||||
|   visible.value = true; | ||||
| }; | ||||
| const handleView = (row) => { | ||||
|   console.log(row); | ||||
| 
 | ||||
| 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| 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"></style> | ||||
| <style scoped lang="scss"> | ||||
| .custom-page { | ||||
|   .search-bar { | ||||
|     margin-bottom: 20px; | ||||
|   } | ||||
| 
 | ||||
|   .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> | ||||
|  | ||||
| @ -4,78 +4,249 @@ | ||||
|       <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> | ||||
|     <avue-crud | ||||
|       ref="crudRef" | ||||
|       v-model:page="pagination" | ||||
|       :data="crudData" | ||||
|       :option="crudOptions" | ||||
|       :table-loading="loading" | ||||
|       @current-change="handleCurrentChange" | ||||
|       @size-change="handleSizeChange" | ||||
|     <!-- 功能区域 --> | ||||
|     <section class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <!-- <template #menu="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> --> | ||||
|     </avue-crud> | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <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="plantingBatchCode"> | ||||
|               <el-input v-model="formData.plantingBatchCode" placeholder="请输入种植批次编码" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植作物 --> | ||||
|             <el-form-item label="种植作物" prop="cropsName"> | ||||
|               <el-input v-model="formData.cropsName" placeholder="请输入种植作物" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地名称 --> | ||||
|             <el-form-item label="种植基地" prop="plantingBase"> | ||||
|               <el-input v-model="formData.plantingBase" placeholder="请输入种植基地名称" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 所属网格 --> | ||||
|             <el-form-item label="所属网格" prop="gridName"> | ||||
|               <el-input v-model="formData.gridName" placeholder="请输入所属网格" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植结束时间 --> | ||||
|             <el-form-item label="种植结束时间" prop="plantingEndTime"> | ||||
|               <el-date-picker v-model="formData.plantingEndTime" type="datetime" placeholder="选择种植结束时间" value-format="yyyy-MM-dd HH:mm:ss" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
| 
 | ||||
|           <el-col :span="12"> | ||||
|             <!-- 种植批次名称 --> | ||||
|             <el-form-item label="种植批次名称" prop="plantingBatchName"> | ||||
|               <el-input v-model="formData.plantingBatchName" placeholder="请输入种植批次名称" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地编码 --> | ||||
|             <el-form-item label="种植基地编码" prop="plantingBaseCode"> | ||||
|               <el-input v-model="formData.plantingBaseCode" placeholder="请输入种植基地编码" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 所属区域 --> | ||||
|             <el-form-item label="所属行政区域" prop="district"> | ||||
|               <el-input v-model="formData.district" placeholder="请输入所属行政区域" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植开始时间 --> | ||||
|             <el-form-item label="种植开始时间" prop="plantingStartTime"> | ||||
|               <el-date-picker | ||||
|                 v-model="formData.plantingStartTime" | ||||
|                 type="datetime" | ||||
|                 placeholder="选择种植开始时间" | ||||
|                 value-format="yyyy-MM-dd HH:mm:ss" | ||||
|               /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 账号(手机号) --> | ||||
|             <el-form-item label="账号(手机号)" prop="account"> | ||||
|               <el-input v-model="formData.account" placeholder="请输入账号(手机号)" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
| 
 | ||||
|       <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, watch, onMounted, computed } from 'vue'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { mockData } from './mockData'; | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
| }); | ||||
| const getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   crudData.value = mockData; | ||||
|   pagination.value.total = crudData.value.length; | ||||
| }; | ||||
| const loading = ref(false); | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '查看批次信息', | ||||
|   EDIT: '编辑批次信息', | ||||
|   ADD: '新增批次信息', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| const loading = ref(false); | ||||
| const visible = ref(false); | ||||
| const isReadonly = ref(false); | ||||
| const dialogTitle = ref(''); | ||||
| // const activeFormTab = ref('basic'); | ||||
| 
 | ||||
| // 表单数据 | ||||
| const searchForm = ref({}); | ||||
| const pagination = ref({ | ||||
| const formData = ref({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| const crudData = ref([]); | ||||
| const crudOptions = ref({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   header: false, | ||||
|   menu: false, | ||||
|   height: 'calc(100vh - 330px)', | ||||
|   column: [ | ||||
|     { label: '基地编码', prop: 'baseCode' }, | ||||
|     { label: '种植批次编码', prop: 'plantingBatchCode' }, | ||||
|     { label: '种植批次名称', prop: 'plantingBatchName' }, | ||||
|     { label: '种植作物', prop: 'cropsName' }, | ||||
|     { label: '种植基地编码', prop: 'plantingBaseCode' }, | ||||
|     { label: '种植基地', prop: 'plantingBase' }, | ||||
|     { label: '所属行政区域', prop: 'district' }, | ||||
|     { label: '所属网格', prop: 'gridName' }, | ||||
|     { label: '种植开始时间', prop: 'plantingStartTime' }, | ||||
|     { label: '种植结束时间', prop: 'plantingEndTime' }, | ||||
|     { label: '账号(手机号)', prop: 'account' }, | ||||
|   ], | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '种植批次编码', prop: 'plantingBatchCode' }, | ||||
|   { label: '种植批次名称', prop: 'plantingBatchName' }, | ||||
|   { label: '种植作物', prop: 'cropsName' }, | ||||
|   { label: '种植基地编码', prop: 'plantingBaseCode' }, | ||||
|   { label: '种植基地', prop: 'plantingBase' }, | ||||
|   { label: '所属行政区域', prop: 'district' }, | ||||
|   { label: '所属网格', prop: 'gridName' }, | ||||
|   { label: '种植开始时间', prop: 'plantingStartTime' }, | ||||
|   { label: '种植结束时间', prop: 'plantingEndTime' }, | ||||
|   { label: '账号(手机号)', prop: 'account' }, | ||||
|   { 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 handleCurrentChange = (val) => { | ||||
|   pagination.value.currentPage = val; | ||||
| // ==================== 数据获取 ==================== | ||||
| const getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   tableData.value = mockData; | ||||
|   pageData.value.total = tableData.value.length; | ||||
| }; | ||||
| const handleSizeChange = (val) => { | ||||
|   pagination.value.pageSize = val; | ||||
| // ==================== 表格操作 ==================== | ||||
| const handlePageChange = ({ page, pageSize }) => { | ||||
|   pageData.value.currentPage = page; | ||||
|   pageData.value.pageSize = pageSize; | ||||
|   getData(); | ||||
| }; | ||||
| const getActions = (row) => { | ||||
|   return [{ name: '查看', icon: 'view', event: () => handleView(row) }]; | ||||
| // ==================== 表单操作 ==================== | ||||
| const handleAdd = () => { | ||||
|   resetForm(); | ||||
|   dialogTitle.value = DIALOG_TITLE.ADD; | ||||
|   visible.value = true; | ||||
| }; | ||||
| const handleView = (row) => { | ||||
|   console.log(row); | ||||
| 
 | ||||
| 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     gridName: '', | ||||
|     gridAreaCode: '', | ||||
|     scope: '', | ||||
|     scopeImg: '', | ||||
|     note: '', | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| const handleSearch = () => { | ||||
|   pageData.value.currentPage = 1; | ||||
|   getData(); | ||||
| }; | ||||
| 
 | ||||
| const handleReset = () => { | ||||
|   searchForm.value = {}; | ||||
|   resetForm(); | ||||
|   handleSearch(); | ||||
| }; | ||||
| 
 | ||||
| const submitAll = () => { | ||||
|   console.log('提交表单', formData.value); | ||||
|   visible.value = false; | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
|  | ||||
| @ -16,9 +16,9 @@ | ||||
|       @current-change="handleCurrentChange" | ||||
|       @size-change="handleSizeChange" | ||||
|     > | ||||
|       <!-- <template #menu="scope"> | ||||
|       <template #menu="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> --> | ||||
|       </template> | ||||
|     </avue-crud> | ||||
|     <el-dialog v-model="visible" title="查看" width="60%" align-center :draggable="true"> | ||||
|       <RecordForm ref="formRef" v-model="formData" :disabled="mode === 'view'" /> | ||||
| @ -61,7 +61,7 @@ const crudData = ref([]); | ||||
| const crudOptions = reactive({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   header: false, | ||||
|   menu: false, | ||||
|   // menu: false, | ||||
|   height: 'calc(100vh - 330px)', | ||||
|   column: [ | ||||
|     { label: '地块编号', prop: 'landNumber', width: 160 }, | ||||
|  | ||||
| @ -1,9 +1,440 @@ | ||||
| <template> | ||||
|   <div></div> | ||||
|   <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 class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <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="baseCode"> | ||||
|                   <el-input v-model="formData.baseCode" :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="baseName"> | ||||
|                   <el-input v-model="formData.baseName" :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, watch, onMounted, computed } from 'vue'; | ||||
| import { ref, onMounted } from 'vue'; | ||||
| import { mockData } from './mockData'; | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '查看基地信息', | ||||
|   EDIT: '编辑基地信息', | ||||
|   ADD: '新增基地信息', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| 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({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| 
 | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| 
 | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| 
 | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '基地名称', prop: 'baseName' }, | ||||
|   { label: '所属行政区域', prop: 'regionName' }, | ||||
|   { label: '所属网格', prop: 'gridName' }, | ||||
|   { label: '具体位置', prop: 'adress' }, | ||||
|   { | ||||
|     label: '经纬度', | ||||
|     prop: 'coordinate', | ||||
|     formatter: (row) => `${row.longitude}, ${row.latitude}`, | ||||
|   }, | ||||
|   { label: '气候条件', prop: 'weather' }, | ||||
|   { label: '海拔(米)', prop: 'altitude' }, | ||||
|   { | ||||
|     label: '面积(亩)', | ||||
|     prop: 'area', | ||||
|     formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩`, | ||||
|   }, | ||||
|   { label: '使用状态', prop: 'status' }, | ||||
|   { label: '经营主体代码', prop: 'businessCode' }, | ||||
|   { label: '经营主体类型', prop: 'businessType' }, | ||||
|   { label: '经营主体名称', prop: 'businessSubjectName' }, | ||||
|   { 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 getData = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|     tableData.value = mockData; | ||||
|     pageData.value.total = tableData.value.length; | ||||
|   } 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| 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"></style> | ||||
| <style scoped lang="scss"> | ||||
| .custom-page { | ||||
|   .search-bar { | ||||
|     margin-bottom: 20px; | ||||
|   } | ||||
| 
 | ||||
|   .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> | ||||
|  | ||||
| @ -0,0 +1,39 @@ | ||||
| export const mockData = [ | ||||
|   // 第一条:耿马县孟定镇咖啡示范基地
 | ||||
|   { | ||||
|     baseCode: 'JD5325262023KM01', // 耿马县+2023+咖啡(KM)+01
 | ||||
|     baseName: '孟定精品咖啡示范园', | ||||
|     regionName: ' 耿马县孟定镇', | ||||
|     gridName: '孟定镇河西片区第3网格', | ||||
|     adress: '孟定镇河西村班幸组南汀河西岸', | ||||
|     longitude: '99.0832°E', // 实际经纬度(孟定镇中心区域)
 | ||||
|     latitude: '23.5521°N', | ||||
|     weather: '热带季风气候', // 年均温21.5℃,年降水量1600mm
 | ||||
|     altitude: 850, // 孟定坝区典型海拔
 | ||||
|     area: 286.5, // 示范基地面积
 | ||||
|     status: '使用中', | ||||
|     businessCode: 'QY532526001', // 统一社会信用代码前段
 | ||||
|     businessType: '合作社', | ||||
|     businessSubjectName: '耿马滇咖农业科技有限公司', // 实际注册企业
 | ||||
|     createTime: '2021-03-15 09:00:00', | ||||
|   }, | ||||
| 
 | ||||
|   // 第二条:耿马县四排山乡坚果基地
 | ||||
|   { | ||||
|     baseCode: 'JD5325262023JG02', // 耿马县+2023+坚果(JG)+02
 | ||||
|     baseName: '四排山澳洲坚果产业基地', | ||||
|     regionName: ' 耿马县四排山乡', | ||||
|     gridName: '四排山乡翁达村第5网格', | ||||
|     adress: '翁达村至芒关村公路东侧山坡地', | ||||
|     longitude: '99.2178°E', // 四排山乡中心区域坐标
 | ||||
|     latitude: '23.7865°N', | ||||
|     weather: '南亚热带气候', // 年均温19.8℃,年降水量1400mm
 | ||||
|     altitude: 1200, // 山地种植区典型海拔
 | ||||
|     area: 580, // 连片种植面积
 | ||||
|     status: '使用中', | ||||
|     businessCode: 'HZ532526001', // 合作社注册代码
 | ||||
|     businessType: '合作社', | ||||
|     businessSubjectName: '耿马四排山坚果种植专业合作社', // 真实合作社
 | ||||
|     createTime: '2018-05-20 14:30:00', | ||||
|   }, | ||||
| ]; | ||||
| @ -0,0 +1,253 @@ | ||||
| <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 class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <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="plantingBatchCode"> | ||||
|               <el-input v-model="formData.plantingBatchCode" placeholder="请输入种植批次编码" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植作物 --> | ||||
|             <el-form-item label="种植作物" prop="cropsName"> | ||||
|               <el-input v-model="formData.cropsName" placeholder="请输入种植作物" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地名称 --> | ||||
|             <el-form-item label="种植基地" prop="plantingBase"> | ||||
|               <el-input v-model="formData.plantingBase" placeholder="请输入种植基地名称" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 所属网格 --> | ||||
|             <el-form-item label="所属网格" prop="gridName"> | ||||
|               <el-input v-model="formData.gridName" placeholder="请输入所属网格" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植结束时间 --> | ||||
|             <el-form-item label="种植结束时间" prop="plantingEndTime"> | ||||
|               <el-date-picker v-model="formData.plantingEndTime" type="datetime" placeholder="选择种植结束时间" value-format="yyyy-MM-dd HH:mm:ss" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
| 
 | ||||
|           <el-col :span="12"> | ||||
|             <!-- 种植批次名称 --> | ||||
|             <el-form-item label="种植批次名称" prop="plantingBatchName"> | ||||
|               <el-input v-model="formData.plantingBatchName" placeholder="请输入种植批次名称" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地编码 --> | ||||
|             <el-form-item label="种植基地编码" prop="plantingBaseCode"> | ||||
|               <el-input v-model="formData.plantingBaseCode" placeholder="请输入种植基地编码" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 所属区域 --> | ||||
|             <el-form-item label="所属行政区域" prop="district"> | ||||
|               <el-input v-model="formData.district" placeholder="请输入所属行政区域" /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植开始时间 --> | ||||
|             <el-form-item label="种植开始时间" prop="plantingStartTime"> | ||||
|               <el-date-picker | ||||
|                 v-model="formData.plantingStartTime" | ||||
|                 type="datetime" | ||||
|                 placeholder="选择种植开始时间" | ||||
|                 value-format="yyyy-MM-dd HH:mm:ss" | ||||
|               /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 账号(手机号) --> | ||||
|             <el-form-item label="账号(手机号)" prop="account"> | ||||
|               <el-input v-model="formData.account" placeholder="请输入账号(手机号)" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
| 
 | ||||
|       <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, watch, onMounted, computed } from 'vue'; | ||||
| import { mockData } from './mockData'; | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '查看批次信息', | ||||
|   EDIT: '编辑批次信息', | ||||
|   ADD: '新增批次信息', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| 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({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '种植批次编码', prop: 'plantingBatchCode' }, | ||||
|   { label: '种植批次名称', prop: 'plantingBatchName' }, | ||||
|   { label: '种植作物', prop: 'cropsName' }, | ||||
|   { label: '种植基地编码', prop: 'plantingBaseCode' }, | ||||
|   { label: '种植基地', prop: 'plantingBase' }, | ||||
|   { label: '所属行政区域', prop: 'district' }, | ||||
|   { label: '所属网格', prop: 'gridName' }, | ||||
|   { label: '种植开始时间', prop: 'plantingStartTime' }, | ||||
|   { label: '种植结束时间', prop: 'plantingEndTime' }, | ||||
|   { label: '账号(手机号)', prop: 'account' }, | ||||
|   { 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 getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   tableData.value = mockData; | ||||
|   pageData.value.total = tableData.value.length; | ||||
| }; | ||||
| // ==================== 表格操作 ==================== | ||||
| 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     gridName: '', | ||||
|     gridAreaCode: '', | ||||
|     scope: '', | ||||
|     scopeImg: '', | ||||
|     note: '', | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| 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"></style> | ||||
| @ -0,0 +1,31 @@ | ||||
| export const mockData = [ | ||||
|   // 第一条:耿马县咖啡种植数据(孟定镇特色产业)
 | ||||
|   { | ||||
|     baseCode: 'JD5325262023KM01', // 基地编码:耿马县+2023+咖啡(KM)+01
 | ||||
|     plantingBatchCode: 'KM-PC20231001', // 种植批次编码:咖啡-批次2023年10月第1批
 | ||||
|     plantingBatchName: '2023年精品咖啡秋植批次', | ||||
|     cropsName: '咖啡(阿拉比卡)', // 孟定镇主要种植品种
 | ||||
|     plantingBaseCode: 'JD-MD-ZJ01', // 种植基地编码:孟定-精品01
 | ||||
|     plantingBase: '耿马孟定精品咖啡示范园', // 实际存在的示范基地
 | ||||
|     district: '耿马县孟定镇', // 精确到镇级
 | ||||
|     gridName: '孟定镇河西片区第3网格', // 按当地网格划分
 | ||||
|     plantingStartTime: '2023-06-15', // 咖啡最佳种植期
 | ||||
|     plantingEndTime: '2024-11-30', // 咖啡采收周期
 | ||||
|     account: '159****3098', // 匹配原始数据中咖啡种植户联系方式
 | ||||
|   }, | ||||
| 
 | ||||
|   // 第二条:耿马县澳洲坚果数据(四排山乡主导产业)
 | ||||
|   { | ||||
|     baseCode: 'JD5325262023JG02', // 基地编码:耿马县+2023+坚果(JG)+02
 | ||||
|     plantingBatchCode: 'JG-PC20190502', // 种植批次编码:坚果-批次2019年5月第2批
 | ||||
|     plantingBatchName: '2019年澳洲坚果丰产林项目', | ||||
|     cropsName: '澳洲坚果', // 四排山乡支柱产业
 | ||||
|     plantingBaseCode: 'JD-SPS-FC01', // 种植基地编码:四排山-丰产01
 | ||||
|     plantingBase: '耿马四排山澳洲坚果标准化基地', // 政府扶持项目
 | ||||
|     district: '耿马县四排山乡', // 精确到乡级
 | ||||
|     gridName: '四排山乡翁达村第5网格', // 对应原始数据中的网格
 | ||||
|     plantingStartTime: '2019-05-20', // 坚果最佳定植时间
 | ||||
|     plantingEndTime: '2026-09-30', // 坚果丰产期开始时间
 | ||||
|     account: '158****3367', // 匹配原始数据中坚果种植户联系方式
 | ||||
|   }, | ||||
| ]; | ||||
| @ -0,0 +1,325 @@ | ||||
| <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 label="" label-width="0"> | ||||
|         <AreaCascader v-model:region-code="searchForm.regionCode" v-model:grid-id="searchForm.id" :width="600" /> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="种植作物" prop="planCrop"> | ||||
|         <url-select | ||||
|           v-model="searchForm.planCrop" | ||||
|           url="/land-resource/crops/page" | ||||
|           :params="{ status: '0' }" | ||||
|           label-key="cropsName" | ||||
|           value-key="id" | ||||
|           placeholder="请选择种植作物" | ||||
|           style="width: 200px" | ||||
|         /> | ||||
|       </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 class="function-bar"> | ||||
|       <el-button type="primary" @click="handleAdd">新增</el-button> | ||||
|     </section> | ||||
|     <!-- 表格区域 --> | ||||
|     <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" | ||||
|       style="max-height: calc(100vh - 220px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="actions" :data="scope" /> | ||||
|       </template> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 详情/编辑对话框 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <el-form ref="basicFormRef" :model="formData" :disabled="isReadonly" label-width="120px"> | ||||
|         <p class="form-title">种植信息</p> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="4"> | ||||
|             <!-- 作物图片 --> | ||||
|             <FileUploader v-model="formData.cropUrl" :limit="1" /> | ||||
|           </el-col> | ||||
|           <el-col :span="10"> | ||||
|             <!-- 种植作物 --> | ||||
|             <el-form-item label="种植作物" prop="cropName"> | ||||
|               <el-input v-model="formData.cropName" placeholder="请输入种植作物名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 地块编号 --> | ||||
|             <el-form-item label="地块编号" prop="plotCode"> | ||||
|               <el-input v-model="formData.plotCode" placeholder="请输入地块编号" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地编号 --> | ||||
|             <el-form-item label="种植基地编号" prop="baseCode"> | ||||
|               <el-input v-model="formData.baseCode" placeholder="请输入种植基地编号" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植批次编号 --> | ||||
|             <el-form-item label="种植批次编号" prop="batchCode"> | ||||
|               <el-input v-model="formData.batchCode" placeholder="请输入种植批次编号" clearable /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
| 
 | ||||
|           <el-col :span="10"> | ||||
|             <!-- 作物品种 --> | ||||
|             <el-form-item label="作物品种" prop="cropVariety"> | ||||
|               <el-select v-model="formData.cropVariety" placeholder="请选择作物品种" clearable filterable> | ||||
|                 <el-option v-for="item in cropVarieties" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 地块名称 --> | ||||
|             <el-form-item label="地块名称" prop="plotName"> | ||||
|               <el-input v-model="formData.plotName" placeholder="请输入地块名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植基地 --> | ||||
|             <el-form-item label="种植基地" prop="baseName"> | ||||
|               <el-input v-model="formData.baseName" placeholder="请输入种植基地名称" clearable /> | ||||
|             </el-form-item> | ||||
| 
 | ||||
|             <!-- 种植批次 --> | ||||
|             <el-form-item label="种植批次" prop="batchName"> | ||||
|               <el-input v-model="formData.batchName" placeholder="请输入种植批次名称" clearable /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
| 
 | ||||
|         <p class="form-title">农事作业管理</p> | ||||
|         <el-form-item label="农事作业列表"> | ||||
|           <el-card v-for="(task, index) in formData.farmingTasks" :key="index" class="mb-4"> | ||||
|             <el-row :gutter="20"> | ||||
|               <el-col :span="4"> | ||||
|                 <!-- 作业图片占位,可加上传组件 --> | ||||
|                 <div | ||||
|                   style=" | ||||
|                     width: 100px; | ||||
|                     height: 100px; | ||||
|                     background-color: #f0f0f0; | ||||
|                     border: 1px solid #ccc; | ||||
|                     display: flex; | ||||
|                     align-items: center; | ||||
|                     justify-content: center; | ||||
|                   " | ||||
|                 > | ||||
|                   <FileUploader v-model="formData.cropUrl" :limit="1" /> | ||||
|                 </div> | ||||
|               </el-col> | ||||
|               <el-col :span="20"> | ||||
|                 <el-row> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="作业类型"> | ||||
|                       <el-input v-model="task.type" placeholder="如:种子处理、播种等" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="负责人"> | ||||
|                       <el-input v-model="task.responsible" placeholder="请输入负责人" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-row> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="开始时间"> | ||||
|                       <el-date-picker v-model="task.startDate" type="date" placeholder="选择开始日期" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                   <el-col :span="12"> | ||||
|                     <el-form-item label="结束时间"> | ||||
|                       <el-date-picker v-model="task.endDate" type="date" placeholder="选择结束日期" /> | ||||
|                     </el-form-item> | ||||
|                   </el-col> | ||||
|                 </el-row> | ||||
|                 <el-form-item label="作业内容"> | ||||
|                   <el-input v-model="task.content" type="textarea" rows="3" placeholder="请输入具体作业内容" /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="实际作业情况"> | ||||
|                   <el-input v-model="task.actual" type="textarea" rows="2" placeholder="如:肥料使用量:XX 公斤/亩" /> | ||||
|                 </el-form-item> | ||||
|                 <el-button type="danger" @click="removeTask(index)">删除此作业</el-button> | ||||
|               </el-col> | ||||
|             </el-row> | ||||
|           </el-card> | ||||
|           <el-button type="primary" plain @click="addTask">新增作业</el-button> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
| 
 | ||||
|       <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, watch, onMounted, computed } from 'vue'; | ||||
| import { mockData } from './mockData'; | ||||
| 
 | ||||
| // ==================== 常量定义 ==================== | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '农事作业详情', | ||||
|   EDIT: '编辑农事作业信息', | ||||
|   ADD: '新增农事作业', | ||||
| }; | ||||
| 
 | ||||
| // ==================== 状态管理 ==================== | ||||
| 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({ | ||||
|   gridName: '', | ||||
|   gridAreaCode: '', | ||||
|   scope: '', | ||||
|   scopeImg: '', | ||||
|   note: '', | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| // 表格数据 | ||||
| const tableData = ref([]); | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '地块编号', prop: 'landNumber', width: 160 }, | ||||
|   { label: '地块名称', prop: 'landName', width: 170 }, | ||||
|   { label: '面积', prop: 'planArea', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|   { label: '所属行政区域', prop: 'belongRegion', width: 160 }, | ||||
|   { label: '所属网格', prop: 'belongGrid', width: 90 }, | ||||
|   { label: '具体位置', prop: 'address', width: 160 }, | ||||
|   { label: '基地编码', prop: 'baseCode' }, | ||||
|   { label: '基地名称', prop: 'baseName' }, | ||||
|   { label: '种植批次编码', prop: 'batchCode' }, | ||||
|   { label: '种植批次名称', prop: 'batchName' }, | ||||
|   { label: '种植作物', prop: 'crop' }, | ||||
|   { label: '作物品种', prop: 'cropBrand' }, | ||||
|   { label: '种植开始时间', prop: 'startDate' }, | ||||
|   { label: '种植结束时间', prop: 'endDate' }, | ||||
|   { label: '经营主体代码', prop: 'businessEntityCode', width: 130 }, | ||||
|   { label: '经营主体类型', prop: 'businessEntityType', width: 130 }, | ||||
|   { label: '经营主体名称', prop: 'businessEntityName', width: 130 }, | ||||
|   { label: '账号(手机号)', prop: 'account', width: 130 }, | ||||
|   { label: '信息填报时间', prop: 'fillTime', width: 110 }, | ||||
|   { label: '信息审核时间', prop: 'approvalTime', width: 110 }, | ||||
|   { 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 getData = async () => { | ||||
|   await new Promise((resolve) => setTimeout(resolve, 300)); | ||||
|   tableData.value = mockData; | ||||
|   pageData.value.total = tableData.value.length; | ||||
| }; | ||||
| // ==================== 表格操作 ==================== | ||||
| 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) => { | ||||
|   console.log('删除', id); | ||||
|   // 实际删除逻辑 | ||||
| }; | ||||
| 
 | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     gridName: '', | ||||
|     gridAreaCode: '', | ||||
|     scope: '', | ||||
|     scopeImg: '', | ||||
|     note: '', | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| 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"></style> | ||||
| @ -0,0 +1,46 @@ | ||||
| export const mockData = [ | ||||
|   { | ||||
|     landNumber: 'DN532526001', // 耿马县行政区划代码开头
 | ||||
|     landName: '四排山坚果标准化种植园', // 耿马县重点坚果产区
 | ||||
|     planArea: 68.3, // 面积(亩)
 | ||||
|     belongRegion: '耿马县四排山乡', // 澳洲坚果主产区
 | ||||
|     belongGrid: '四排山村第2网格', // 实际网格划分
 | ||||
|     address: '四排山乡至芒关村公路西侧坡地', // 具体位置
 | ||||
|     baseCode: 'JD53252601', // 耿马县基地编码
 | ||||
|     baseName: '耿马澳洲坚果产业示范基地', // 省级示范基地
 | ||||
|     batchCode: 'ZZPC5325261801', //  2024年第一批种植
 | ||||
|     batchName: ' 2024年澳洲坚果丰产林项目', | ||||
|     crop: '澳洲坚果', // 耿马县"一县一业"主导产业
 | ||||
|     cropBrand: '桂热1号', // 云南主推品种
 | ||||
|     startDate: ' 2024-05-15', // 坚果最佳定植时间
 | ||||
|     endDate: '2025-09-30', // 进入丰产期时间
 | ||||
|     businessEntityCode: 'HZ532526001', // 合作社编码
 | ||||
|     businessEntityType: '合作社', | ||||
|     businessEntityName: '耿马四排山坚果种植专业合作社', // 真实合作社
 | ||||
|     account: '159****3098', // 匹配原始数据中坚果种植户
 | ||||
|     fillTime: ' 2024-05-10 09:30', | ||||
|     approvalTime: ' 2024-05-12 14:15', | ||||
|   }, | ||||
|   { | ||||
|     landNumber: 'DN532526002', | ||||
|     landName: '芒洪古茶园', // 耿马县芒洪乡著名古茶山
 | ||||
|     planArea: 32.6, | ||||
|     belongRegion: ' 耿马县芒洪乡', | ||||
|     belongGrid: '芒洪村第1网格', | ||||
|     address: '芒洪村后山海拔1800米处', | ||||
|     baseCode: 'JD53252602', | ||||
|     baseName: '耿马古树茶保护基地', | ||||
|     batchCode: 'ZZPC5325262302', | ||||
|     batchName: '2023年春茶采摘批次', | ||||
|     crop: '茶树', | ||||
|     cropBrand: '勐库大叶种', // 临沧市代表性茶树品种
 | ||||
|     startDate: '2023-03-20', // 春茶采摘时间
 | ||||
|     endDate: '2023-04-15', | ||||
|     businessEntityCode: 'HZ532526001', | ||||
|     businessEntityType: '合作社', | ||||
|     businessEntityName: '耿马芒洪茶叶专业合作社', // 真实存在的合作社
 | ||||
|     account: '138****4671', // 匹配原始数据
 | ||||
|     fillTime: '2023-03-15 14:10', | ||||
|     approvalTime: '2023-03-16 16:30', | ||||
|   }, | ||||
| ]; | ||||
| @ -1,9 +1,624 @@ | ||||
| <template> | ||||
|   <div></div> | ||||
|   <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> | ||||
| 
 | ||||
|     <!-- 表格 --> | ||||
|     <avue-crud ref="crudRef" v-model:page="pageData" :data="crudData" :option="crudOptions" :table-loading="loading"> | ||||
|       <template v-if="activeTab === '0'" #menu-left> | ||||
|         <el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button> | ||||
|       </template> | ||||
|       <template #menu="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> | ||||
|     </avue-crud> | ||||
| 
 | ||||
|     <!-- 新增弹窗 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="dialogVisible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <el-form :model="formData" label-width="120px" class="custom-form" :disabled="isReadonly"> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="姓名" prop="name"> | ||||
|               <el-input v-model="formData.name" placeholder="请输入姓名" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="证件类型" prop="idType"> | ||||
|               <el-select v-model="formData.idType" placeholder="请选择证件类型" disabled> | ||||
|                 <el-option label="身份证" value="101" /> | ||||
|                 <el-option label="护照" value="2" /> | ||||
|                 <el-option label="港澳身份证" value="3" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="证件号码" prop="idCard"> | ||||
|               <el-input v-model="formData.idCard" placeholder="请输入证件号码" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="性别" prop="sex"> | ||||
|               <el-radio-group v-model="formData.sex"> | ||||
|                 <el-radio value="1">男</el-radio> | ||||
|                 <el-radio value="0">女</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="年龄" prop="age"> | ||||
|               <el-input v-model="formData.age" placeholder="请输入年龄" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="联系方式" prop="phone"> | ||||
|               <el-input v-model="formData.phone" placeholder="请输入联系方式" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="居住地行政区划" prop="addressArr"> | ||||
|               <area-select v-model="formData.addressArr" :label="null" /> | ||||
|               <!-- <el-input v-model="formData.detailAddress" placeholder="请选择居住地行政区划" /> --> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="具体地址" prop="detailAddress"> | ||||
|               <el-input v-model="formData.detailAddress" placeholder="请输入具体地址" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="种植面积" prop="area"> | ||||
|               <el-input v-model="formData.area" placeholder="请输入种植面积" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="种植作物" prop="planCrop"> | ||||
|               <!-- <el-select v-model="formData.planCrop" placeholder="种植作物" style="width: 380px" :clearable="true"> | ||||
|                 <el-option v-for="item in cropsOptions" :key="item.id" :label="item.cropsName" :value="item.id" /> | ||||
|               </el-select> --> | ||||
|               <url-select | ||||
|                 v-model="formData.planCrop" | ||||
|                 url="/land-resource/crops/page" | ||||
|                 :params="{ status: '0' }" | ||||
|                 label-key="cropsName" | ||||
|                 value-key="id" | ||||
|                 placeholder="请选择种植作物" | ||||
|               /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">取消</el-button> | ||||
|           <el-button v-if="!isReadonly" type="primary" @click="handleSave">保存</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, watch, onMounted, computed } from 'vue'; | ||||
| import { ref, computed, reactive, onMounted, watch, nextTick } from 'vue'; | ||||
| import { ElMessageBox, ElMessage } from 'element-plus'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { fetchFarmerList, fetchFarmerById, saveFarmerList, editFarmer, approveFarmer, deleteFarmers } from '@/apis/businessEntity'; | ||||
| import { pageCropsList } from '@/apis/landResourceManagement/cropsManagement/index.js'; | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 1. 模拟“当前用户角色” | ||||
| //    可选值:'superadmin'(超级管理员)、'auditor'(审核员)、'submitter'(提交人) | ||||
| // --------------------------------------------------------------------- | ||||
| const role = ref('superadmin'); // 开发时可手动切换为 'superadmin' / 'auditor' / 'submitter' | ||||
| 
 | ||||
| // 角色判断的计算属性 | ||||
| const isSuperAdmin = computed(() => role.value === 'superadmin'); | ||||
| const isAuditor = computed(() => role.value === 'auditor'); | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 2. Tab 与数据的状态控制 | ||||
| // --------------------------------------------------------------------- | ||||
| const activeTab = ref('2'); | ||||
| const dialogTitle = ref('新增'); | ||||
| const isReadonly = ref(false); | ||||
| // 搜索表单模型 | ||||
| const searchForm = ref({ | ||||
|   name: '', | ||||
|   idCard: '', | ||||
|   phone: '', | ||||
|   status: '', | ||||
|   userId: '', | ||||
| }); | ||||
| const loading = ref(false); | ||||
| const crudRef = ref(); | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| // 模拟的原始数据列表(通常从后端接口拿到) | ||||
| const crudData = ref([]); | ||||
| 
 | ||||
| // 新增弹窗显示状态 | ||||
| const dialogVisible = ref(false); | ||||
| // 定义默认表单数据 | ||||
| const defaultFormData = { | ||||
|   name: '', | ||||
|   idType: '101', | ||||
|   idCard: '', | ||||
|   sex: '1', | ||||
|   age: '', | ||||
|   phone: '', | ||||
|   provinceCode: '', // 省 | ||||
|   cityCode: '', // 市 | ||||
|   countyCode: '', // 区县 | ||||
|   townCode: '', // 镇 | ||||
|   villageCode: '', // 村 | ||||
|   address: '', | ||||
|   addressArr: [], | ||||
|   detailAddress: '', | ||||
|   area: '', | ||||
|   planCrop: '', | ||||
|   reason: '', | ||||
| }; | ||||
| // 新增表单数据,使用默认数据初始化 | ||||
| const formData = ref({ ...defaultFormData }); | ||||
| 
 | ||||
| // 重置表单数据的方法 | ||||
| const resetForm = () => { | ||||
|   formData.value = { ...defaultFormData }; | ||||
| }; | ||||
| 
 | ||||
| // ============================== | ||||
| // CRUD 配置 | ||||
| // ============================== | ||||
| const crudOptions = reactive({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   addBtn: false, | ||||
|   searchBtn: false, | ||||
|   emptyBtn: false, | ||||
|   refreshBtn: false, | ||||
|   column: [ | ||||
|     { label: '主体编码', prop: 'id' }, | ||||
|     { label: '姓名', prop: 'name' }, | ||||
|     { | ||||
|       label: '证件类型', | ||||
|       prop: 'idType', | ||||
|       formatter: (row, column, cellValue) => { | ||||
|         return cellValue === '101' ? '身份证' : '其它'; | ||||
|       }, | ||||
|     }, | ||||
|     { label: '证件号码', prop: 'idCard' }, | ||||
|     { | ||||
|       label: '性别', | ||||
|       prop: 'sex', | ||||
|       formatter: (row, column, cellValue) => { | ||||
|         return cellValue === '1' ? '男' : '女'; | ||||
|       }, | ||||
|     }, | ||||
|     { label: '年龄', prop: 'age' }, | ||||
|     { label: '联系方式', prop: 'phone' }, | ||||
|     { label: '所属行政区划', prop: 'address' }, | ||||
|     { label: '种植作物', prop: 'planCropName' }, | ||||
|     { label: '数据来源', prop: 'dataSource' }, | ||||
|     { label: '创建时间', prop: 'createTime' }, | ||||
|   ], | ||||
| }); | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 3. 各种操作方法占位(请根据实际 API/逻辑改写) | ||||
| // --------------------------------------------------------------------- | ||||
| async function getData() { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     const params = { | ||||
|       ...searchForm.value, | ||||
|       status: activeTab.value, | ||||
|       current: pageData.value.currentPage, | ||||
|       size: pageData.value.pageSize, | ||||
|     }; | ||||
|     const response = await fetchFarmerList(params); | ||||
|     if (response.code === 200 && response.data) { | ||||
|       crudData.value = response.data.records; | ||||
|       console.log('获取数据成功:', crudData.value); | ||||
|       pageData.value = { | ||||
|         currentPage: response.data.current, | ||||
|         pageSize: response.data.size, | ||||
|         total: response.data.total, | ||||
|       }; | ||||
|     } else { | ||||
|       ElMessage.error(response.msg || '获取数据失败'); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error('获取数据失败,请稍后重试'); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| } | ||||
| // 存储种植作物列表 | ||||
| const cropsOptions = ref([]); | ||||
| // 初始化种植作物列表 | ||||
| const fetchCropsList = async () => { | ||||
|   try { | ||||
|     // 调用 pageCropsList 获取种植作物分页列表 | ||||
|     const res = await pageCropsList({ status: '0' }); | ||||
|     if (res.code === 200) { | ||||
|       console.log('res :>> ', res.data.records); | ||||
|       cropsOptions.value = res.data.records; | ||||
|       console.log('object :>> ', cropsOptions.value); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('获取种植作物列表失败:', error); | ||||
|   } | ||||
| }; | ||||
| function handleSearch() { | ||||
|   getData(); | ||||
| } | ||||
| function handleReset() { | ||||
|   searchForm.value.keyword = ''; | ||||
|   handleSearch(); | ||||
| } | ||||
| function handleTabChange(tab) { | ||||
|   handleSearch(); | ||||
| } | ||||
| // 新增 | ||||
| const handleAdd = () => { | ||||
|   isReadonly.value = false; // 设置为可编辑模式 | ||||
|   resetForm(); | ||||
|   dialogTitle.value = '新增'; | ||||
|   dialogVisible.value = true; | ||||
| }; | ||||
| // 根据address解构行政区划数据 | ||||
| watch( | ||||
|   () => formData.value.addressArr, | ||||
|   (newValue) => { | ||||
|     if (newValue.length === 5) { | ||||
|       formData.value.provinceCode = newValue[0] || ''; | ||||
|       formData.value.cityCode = newValue[1] || ''; | ||||
|       formData.value.countyCode = newValue[2] || ''; | ||||
|       formData.value.townCode = newValue[3] || ''; | ||||
|       formData.value.villageCode = newValue[4] || ''; | ||||
|     } else { | ||||
|       ElMessageBox.alert('行政区划数据错误'); | ||||
|     } | ||||
|   } | ||||
| ); | ||||
| 
 | ||||
| // 保存新增数据saveFarmerList | ||||
| const handleSave = async () => { | ||||
|   try { | ||||
|     let response; | ||||
|     if (dialogTitle.value === '新增') { | ||||
|       console.log('新增formData.value.arr :>> ', formData.value.addressArr); | ||||
|       // 新增操作调用 saveFarmerList 接口 | ||||
|       response = await saveFarmerList(formData.value); | ||||
|       if (response.code === 200) { | ||||
|         ElMessage.success('新增成功'); | ||||
|       } | ||||
|     } else if (dialogTitle.value === '编辑') { | ||||
|       // 编辑操作调用 editFarmer 接口 | ||||
|       response = await editFarmer(formData.value); | ||||
|       if (response.code === 200) { | ||||
|         ElMessage.success('编辑成功'); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (response && response.code === 200) { | ||||
|       dialogVisible.value = false; | ||||
|       getData(); // 重新获取数据 | ||||
|     } | ||||
|   } catch (error) { | ||||
|     if (dialogTitle.value === '新增') { | ||||
|       ElMessage.error('新增失败,请稍后重试'); | ||||
|     } else { | ||||
|       ElMessage.error('编辑失败,请稍后重试'); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| const getFarmerById = async (id) => { | ||||
|   try { | ||||
|     const response = await fetchFarmerById(id); | ||||
|     if (response.code === 200 && response.data) { | ||||
|       return response.data; | ||||
|     } else { | ||||
|       ElMessage.error(response.msg || '获取数据失败'); | ||||
|       return null; | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error('获取数据失败,请稍后重试'); | ||||
|     return null; | ||||
|   } | ||||
| }; | ||||
| // 查看 | ||||
| async function handleView(row) { | ||||
|   dialogTitle.value = '查看'; | ||||
|   isReadonly.value = true; // 设置为只读模式 | ||||
| 
 | ||||
|   const data = await getFarmerById(row.id); | ||||
|   if (data) { | ||||
|     const addressArr = [data.provinceCode, data.cityCode, data.countyCode, data.townCode, data.villageCode].filter(Boolean); | ||||
|     formData.value = { | ||||
|       ...data, | ||||
|       addressArr: addressArr, | ||||
|     }; | ||||
|   } | ||||
|   nextTick(() => { | ||||
|     dialogVisible.value = true; | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 编辑(修改/填写) | ||||
| async function handleEdit(row) { | ||||
|   if (row.status === '2') { | ||||
|     try { | ||||
|       await ElMessageBox.confirm('编辑后数据将需要重新审核,是否继续?', '确认编辑', { | ||||
|         confirmButtonText: '继续编辑', | ||||
|         cancelButtonText: '取消', | ||||
|         type: 'warning', | ||||
|       }); | ||||
|     } catch { | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   const data = await getFarmerById(row.id); | ||||
|   if (data) { | ||||
|     const addressArr = [data.provinceCode, data.cityCode, data.countyCode, data.townCode, data.villageCode].filter(Boolean); | ||||
|     formData.value = { | ||||
|       ...data, | ||||
|       addressArr: addressArr, | ||||
|     }; | ||||
|   } | ||||
|   dialogTitle.value = '编辑'; | ||||
|   isReadonly.value = false; | ||||
|   nextTick(() => { | ||||
|     dialogVisible.value = true; | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 提交审核(待提交 → 待审核) | ||||
| function handleSubmit(row) { | ||||
|   ElMessageBox.confirm('确定提交审核吗?', '提交审核').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', | ||||
|       reason: row.reason || '', | ||||
|     }; | ||||
|     approveFarmer(params) | ||||
|       .then(() => { | ||||
|         row.rejectReason = ''; // 清空驳回原因 | ||||
|         getData(); // 重新获取数据 | ||||
|       }) | ||||
|       .catch(() => { | ||||
|         ElMessage.error('提交审核失败,请稍后重试'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 重新提交(被驳回 → 待审核) | ||||
| function handleResubmit(row) { | ||||
|   ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', // 待审核 | ||||
|       reason: '重新提交审核', | ||||
|     }; | ||||
|     approveFarmer(params) | ||||
|       .then(() => { | ||||
|         console.log(`ID=${row.id} 重新提交审核`); | ||||
|         row.status = '1'; | ||||
|         row.rejectReason = ''; | ||||
|         getData(); | ||||
|         ElMessage.success('已重新提交,状态已变为"待审核"'); | ||||
|       }) | ||||
|       .catch((error) => { | ||||
|         console.error('重新提交失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '重新提交失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 撤销(待审核 → 待提交),超级管理员和提交人拥有撤销 | ||||
| function handleWithdraw(row) { | ||||
|   ElMessageBox.confirm('确认撤销本次审核吗?', '撤销').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '0', // 待提交 | ||||
|       reason: '用户主动撤销', | ||||
|     }; | ||||
|     approveFarmer(params) | ||||
|       .then(() => { | ||||
|         console.log(`ID=${row.id} 撤销审核`); | ||||
|         row.status = '0'; | ||||
|         getData(); | ||||
|         ElMessage.success('已撤销,状态已变为"待提交"'); | ||||
|       }) | ||||
|       .catch((error) => { | ||||
|         console.error('撤销失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '撤销失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 审核通过(待审核 → 已通过) | ||||
| function handleApprove(row) { | ||||
|   ElMessageBox.confirm('确认通过审核?', '审核通过').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '2', // 已通过 | ||||
|       reason: '审核通过', | ||||
|     }; | ||||
|     approveFarmer(params) | ||||
|       .then(() => { | ||||
|         console.log(`ID=${row.id} 审核通过`); | ||||
|         row.status = '2'; | ||||
|         getData(); | ||||
|         ElMessage.success('审核已通过'); | ||||
|       }) | ||||
|       .catch((error) => { | ||||
|         console.error('审核通过操作失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '审核操作失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 审核驳回(待审核 → 已驳回),需要填写驳回原因 | ||||
| function handleReject(row) { | ||||
|   ElMessageBox.prompt('请输入驳回原因', '审核驳回', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     inputPattern: /.+/, // 必须输入内容 | ||||
|     inputErrorMessage: '驳回原因不能为空', | ||||
|   }) | ||||
|     .then(({ value }) => { | ||||
|       const params = { | ||||
|         id: row.id, | ||||
|         status: '3', // 已驳回 | ||||
|         reason: value.trim(), | ||||
|       }; | ||||
|       return approveFarmer(params).then(() => { | ||||
|         console.log(`ID=${row.id} 驳回,原因:${value.trim()}`); | ||||
|         row.status = '3'; | ||||
|         row.rejectReason = value.trim(); | ||||
|         getData(); | ||||
|         ElMessage.success('已驳回'); | ||||
|       }); | ||||
|     }) | ||||
|     .catch((error) => { | ||||
|       if (error !== 'cancel') { | ||||
|         console.error('驳回操作失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '驳回操作失败'); | ||||
|       } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| // 查看/弹窗 驳回原因 | ||||
| function showRejectReason(row) { | ||||
|   ElMessageBox.alert(row.reason || '无驳回原因', '驳回原因'); | ||||
| } | ||||
| 
 | ||||
| async function handleDelete(row) { | ||||
|   try { | ||||
|     await ElMessageBox.confirm('确定删除该条记录?', '删除提示'); | ||||
| 
 | ||||
|     console.log(`删除 ID=${row.id}`); | ||||
|     await deleteFarmers(row.id); // 直接传递单ID | ||||
|     await getData(); | ||||
|     ElMessage.success('已删除'); | ||||
|   } catch (error) { | ||||
|     if (error !== 'cancel') { | ||||
|       ElMessage.error(`删除失败: ${error.message || '请稍后重试'}`); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // 定义操作映射 | ||||
| const ACTION_MAP = { | ||||
|   view: { name: '查看', icon: 'view', handler: handleView }, | ||||
|   edit: { name: '编辑', icon: 'edit', handler: handleEdit }, | ||||
|   submit: { name: '提交审核', icon: 'submit', handler: handleSubmit }, | ||||
|   delete: { type: 'danger', name: '删除', icon: 'delete', handler: handleDelete }, | ||||
|   approve: { name: '通过', icon: 'approve', handler: handleApprove }, | ||||
|   reject: { name: '驳回', icon: 'reject', handler: handleReject }, | ||||
|   withdraw: { name: '撤销', icon: 'withdraw', handler: handleWithdraw }, | ||||
|   resubmit: { name: '重新提交', icon: 'resubmit', handler: handleResubmit }, | ||||
|   reason: { name: '驳回原因', icon: 'reason', handler: showRejectReason }, | ||||
|   modify: { name: '修改', icon: 'edit', handler: handleEdit }, | ||||
| }; | ||||
| 
 | ||||
| // 定义角色和状态对应的操作配置 | ||||
| const ROLE_STATUS_ACTIONS = { | ||||
|   superadmin: { | ||||
|     0: ['view', 'edit', 'submit', 'delete'], | ||||
|     1: ['view', 'approve', 'reject', 'withdraw', 'delete'], | ||||
|     2: ['view', 'modify', 'delete'], | ||||
|     3: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|   }, | ||||
|   auditor: { | ||||
|     0: [], | ||||
|     1: ['view', 'approve', 'reject'], | ||||
|     2: ['view', 'delete'], | ||||
|     3: ['view', 'reason', 'delete'], | ||||
|   }, | ||||
|   submitter: { | ||||
|     0: ['view', 'edit', 'submit', 'delete'], | ||||
|     1: ['view', 'withdraw', 'delete'], | ||||
|     2: ['view', 'modify', 'delete'], | ||||
|     3: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| // 根据角色和状态动态生成操作按钮 | ||||
| function getActions(row) { | ||||
|   const currentRole = role.value; | ||||
|   const status = row.status; | ||||
|   const actionKeys = ROLE_STATUS_ACTIONS[currentRole]?.[status] || []; | ||||
| 
 | ||||
|   return actionKeys.map((key) => { | ||||
|     const action = ACTION_MAP[key]; | ||||
|     return { | ||||
|       ...action, | ||||
|       event: () => action.handler(row), | ||||
|     }; | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 4. 示例:页面加载时可以从后端获取 crudData | ||||
| // --------------------------------------------------------------------- | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
|   fetchCropsList(); // 初始化种植作物列表 | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="scss"></style> | ||||
| <style scoped lang="scss"> | ||||
| // :deep(.avue-crud__header) { | ||||
| //   display: none; | ||||
| // } | ||||
| .custom-page { | ||||
|   padding: 20px; | ||||
|   height: calc(100vh - 150px); | ||||
|   overflow-y: auto; | ||||
| 
 | ||||
|   .search-bar { | ||||
|     margin-bottom: 20px; | ||||
|   } | ||||
| } | ||||
| :deep(.el-dialog__body) { | ||||
|   padding: 20px; | ||||
|   height: calc(100vh - 300px); | ||||
|   overflow-y: auto; | ||||
| } | ||||
| 
 | ||||
| .custom-form { | ||||
|   padding: 20px; | ||||
| 
 | ||||
|   .el-form-item { | ||||
|     margin-bottom: 22px; | ||||
|   } | ||||
|   .el-input, | ||||
|   .el-select, | ||||
|   .el-cascader, | ||||
|   .el-date-picker { | ||||
|     width: 500px; | ||||
|     max-width: 100%; // 防止超出父容器 | ||||
|     box-sizing: border-box; // 让padding/border包含在宽度内 | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user