生产经营主体组件替换
This commit is contained in:
		
							parent
							
								
									a554d3753d
								
							
						
					
					
						commit
						38f508e043
					
				| @ -2,21 +2,35 @@ | ||||
|   <section class="custom-page"> | ||||
|     <!-- 四个固定 Tabs --> | ||||
|     <el-tabs v-model="activeCrudTab" @tab-click="handleTabChange"> | ||||
|       <!-- <el-tab-pane label="待提交" name="0" /> --> | ||||
|       <el-tab-pane label="待审核" name="1" /> | ||||
|       <el-tab-pane label="已通过" name="2" /> | ||||
|       <el-tab-pane label="已驳回" name="3" /> | ||||
|     </el-tabs> | ||||
| 
 | ||||
|     <!-- 表格 --> | ||||
|     <avue-crud ref="crudRef" v-model:page="pageData" :data="crudData" :option="crudOptions" :table-loading="loading"> | ||||
|       <template v-if="activeCrudTab === '0'" #menu-left> | ||||
|         <el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button> | ||||
|       </template> | ||||
|       <template #menu="scope"> | ||||
|     <!-- 功能区域 --> | ||||
|     <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 - 300px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> | ||||
|     </avue-crud> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|       <el-tabs v-model="activeTab" class="tabs-wrapper"> | ||||
|         <el-tab-pane label="基础信息" name="basic"> | ||||
| @ -48,8 +62,7 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, reactive, watch, onMounted, computed } from 'vue'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { ref, reactive, computed, onMounted } from 'vue'; | ||||
| import { ElMessage, ElMessageBox } from 'element-plus'; | ||||
| import TabBasicInfo from './components/TabBasicInfo.vue'; | ||||
| import TabRegister from './components/TabRegister.vue'; | ||||
| @ -57,41 +70,47 @@ import TabBusinessInfo from './components/TabBusinessInfo.vue'; | ||||
| import TabCreditEvaluation from './components/TabCreditEvaluation.vue'; | ||||
| import TabMember from './components/TabMember.vue'; | ||||
| import { getEnterList, getEnterById, addEnter, updateEnter, approvalEnter, deleteEnter } from '@/apis/businessEntity'; | ||||
| import { useUserStore } from '@/store/modules/user'; | ||||
| 
 | ||||
| // 控制弹窗显示 | ||||
| // 常量定义 | ||||
| const DIALOG_TITLE = { | ||||
|   VIEW: '查看', | ||||
|   EDIT: '编辑', | ||||
|   ADD: '新增', | ||||
| }; | ||||
| 
 | ||||
| const TAB_ORDER = ['basic', 'register', 'business', 'credit']; | ||||
| 
 | ||||
| // 响应式数据 | ||||
| const visible = ref(false); | ||||
| const activeCrudTab = ref('1'); | ||||
| const activeTab = ref('basic'); | ||||
| const dialogTitle = ref('新增'); | ||||
| const dialogTitle = ref(DIALOG_TITLE.ADD); | ||||
| const isReadonly = ref(false); | ||||
| const loading = ref(false); | ||||
| const tableData = ref([]); | ||||
| 
 | ||||
| // 搜索表单模型 | ||||
| const searchForm = ref({ | ||||
|   businessName: '', | ||||
|   uscc: '', | ||||
|   productType: '', | ||||
|   primaryProduct: '', | ||||
| const pageData = reactive({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| const initialSearchForm = { ...searchForm.value }; | ||||
| // 数据和状态 | ||||
| const formData = ref({ | ||||
| 
 | ||||
| const initialFormData = { | ||||
|   id: '', | ||||
|   // 基础信息 basicInfo | ||||
|   businessName: '', | ||||
|   area: '', | ||||
|   contactPerson: '', | ||||
|   cooperativePhoto: '', // 合作社照片 | ||||
|   cooperativePhoto: '', | ||||
|   addressArr: [], | ||||
|   primaryProduct: '', | ||||
|   phone: '', | ||||
|   businessLicence: '', // 营业执照 | ||||
|   businessLicence: '', | ||||
|   provinceCode: '', | ||||
|   cityCode: '', | ||||
|   countyCode: '', | ||||
|   townCode: '', | ||||
|   villageCode: '', | ||||
|   // 登记注册信息 registerInfo | ||||
|   // businessName: '', | ||||
|   legalRep: '', | ||||
|   comType: '', | ||||
|   regAuthority: '', | ||||
| @ -102,22 +121,53 @@ const formData = ref({ | ||||
|   totalCapital: '', | ||||
|   address: '', | ||||
|   businessScope: '', | ||||
|   // 经营信息 | ||||
|   debtFiles: [], | ||||
|   profitFiles: [], | ||||
|   cashflowFiles: [], | ||||
|   // 信用评价 | ||||
|   creditEvaluation: 5, | ||||
|   supportedFarmers: 4, | ||||
|   socialImpact: 3, | ||||
|   techApplication: 2, | ||||
|   productQuality: 1, | ||||
| }); | ||||
| const initialFormData = { ...formData.value }; | ||||
| }; | ||||
| 
 | ||||
| const formData = ref({ ...initialFormData }); | ||||
| 
 | ||||
| // 计算属性 | ||||
| const currentTabIndex = computed(() => TAB_ORDER.indexOf(activeTab.value)); | ||||
| const isFirstTab = computed(() => currentTabIndex.value === 0); | ||||
| const isLastTab = computed(() => currentTabIndex.value === TAB_ORDER.length - 1); | ||||
| 
 | ||||
| // 表格配置 | ||||
| const columns = ref([ | ||||
|   { label: '生产经营主体编码', prop: 'id' }, | ||||
|   { label: '企业名称', prop: 'businessName' }, | ||||
|   { label: '企业负责人', prop: 'contactPerson' }, | ||||
|   { label: '联系方式', prop: 'phone' }, | ||||
|   { label: '企业地址', prop: 'address' }, | ||||
|   { label: '地块数量', prop: 'landCount' }, | ||||
|   { label: '地块编号', prop: 'landNumber' }, | ||||
|   { label: '地块名称', prop: 'landName' }, | ||||
|   { label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|   { label: '所属行政区划', prop: 'address' }, | ||||
|   { label: '所属网格', prop: 'gridCode' }, | ||||
|   { label: '种植作物', prop: 'planCrop' }, | ||||
|   // { label: '账号(手机号)', prop: 'phone' }, | ||||
|   { label: '信息录入时间', prop: 'createTime' }, | ||||
|   { label: '信息更新时间', prop: 'updateTime' }, | ||||
|   { label: '操作', prop: 'action', slotName: 'action', fixed: 'right' }, | ||||
| ]); | ||||
| 
 | ||||
| // 用户信息 | ||||
| const userStore = useUserStore(); | ||||
| const user = computed(() => userStore.getUserInfo()); | ||||
| const isAdmin = computed(() => user.value.admin); | ||||
| 
 | ||||
| // 方法 | ||||
| const resetForm = () => { | ||||
|   formData.value = { ...initialFormData }; | ||||
| }; | ||||
| 
 | ||||
| const syncAddressToForm = () => { | ||||
|   const arr = Array.isArray(formData.value.addressArr) ? formData.value.addressArr : []; | ||||
|   formData.value.provinceCode = arr[0] || ''; | ||||
| @ -127,101 +177,18 @@ const syncAddressToForm = () => { | ||||
|   formData.value.villageCode = arr[4] || ''; | ||||
| }; | ||||
| 
 | ||||
| // 保存处理 | ||||
| const handleSubmit = async () => { | ||||
|   try { | ||||
|     loading.value = true; | ||||
|     let response; | ||||
|     if (dialogTitle.value === '新增') { | ||||
|       formData.value.id = ''; | ||||
|       syncAddressToForm(); | ||||
|       response = await addEnter(formData.value); | ||||
|       if (response.code === 200) { | ||||
|         ElMessage.success('新增成功'); | ||||
|         visible.value = false; | ||||
|         getData(); | ||||
|       } | ||||
|     } else if (dialogTitle.value === '编辑') { | ||||
|       syncAddressToForm(); | ||||
|       response = await updateEnter(formData.value); | ||||
|       if (response.code === 200) { | ||||
|         ElMessage.success('编辑成功'); | ||||
|         visible.value = false; | ||||
|         getData(); | ||||
|       } | ||||
|     } | ||||
|   } catch (e) { | ||||
|     ElMessage.error('保存失败'); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| const pageData = ref({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| 
 | ||||
| const crudData = ref([]); | ||||
| 
 | ||||
| const loading = ref(false); | ||||
| 
 | ||||
| const crudOptions = reactive({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   addBtn: false, | ||||
|   searchBtn: false, | ||||
|   emptyBtn: false, | ||||
|   column: [ | ||||
|     { label: '生产经营主体编码', prop: 'id' }, | ||||
|     { label: '企业名称', prop: 'businessName' }, | ||||
|     { label: '企业负责人', prop: 'contactPerson' }, | ||||
|     { label: '联系方式', prop: 'phone' }, | ||||
|     { label: '企业地址', prop: 'address' }, | ||||
|     { label: '地块数量', prop: 'landCount' }, | ||||
|     { label: '地块编号', prop: 'landNumber' }, | ||||
|     { label: '地块名称', prop: 'landName' }, | ||||
|     { label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|     { label: '所属行政区划', prop: 'address' }, | ||||
|     { label: '所属网格', prop: 'gridCode' }, | ||||
|     { label: '种植作物', prop: 'planCrop' }, | ||||
|     // { label: '账号(手机号)', prop: 'phone' }, | ||||
|     { label: '信息录入时间', prop: 'createTime' }, | ||||
|     { label: '信息更新时间', prop: 'updateTime' }, | ||||
|   ], | ||||
| }); | ||||
| // 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('行政区划数据错误'); | ||||
| //     } | ||||
| //   } | ||||
| // ); | ||||
| 
 | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
| }); | ||||
| 
 | ||||
| const getData = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     const response = await getEnterList({ | ||||
|       ...searchForm.value, | ||||
|       status: activeCrudTab.value, | ||||
|       page: pageData.value.currentPage, | ||||
|       size: pageData.value.pageSize, | ||||
|       page: pageData.currentPage, | ||||
|       size: pageData.pageSize, | ||||
|     }); | ||||
|     crudData.value = response.data.records; | ||||
|     pageData.value.total = response.data.total; | ||||
|     pageData.value.currentPage = response.data.current; | ||||
|     pageData.value.pageSize = response.data.size; | ||||
|     tableData.value = response.data.records; | ||||
|     pageData.total = response.data.total; | ||||
|     pageData.currentPage = response.data.current; | ||||
|     pageData.pageSize = response.data.size; | ||||
|   } catch (error) { | ||||
|     ElMessage.error('加载数据失败'); | ||||
|   } finally { | ||||
| @ -235,7 +202,6 @@ const getEnterDetail = async (id) => { | ||||
|     const response = await getEnterById(id); | ||||
|     formData.value = { | ||||
|       ...response.data, | ||||
|       // 确保addressArr始终是5个元素,不足的用空字符串填充 | ||||
|       addressArr: [ | ||||
|         response.data.provinceCode || '', | ||||
|         response.data.cityCode || '', | ||||
| @ -246,25 +212,55 @@ const getEnterDetail = async (id) => { | ||||
|     }; | ||||
|   } catch (error) { | ||||
|     ElMessage.error(`获取详情失败:${error.message || '请稍后重试'}`); | ||||
|     throw error; | ||||
|   } | ||||
| }; | ||||
| function handleSearch() { | ||||
| 
 | ||||
| const handleSubmit = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     syncAddressToForm(); | ||||
|     let response; | ||||
| 
 | ||||
|     if (dialogTitle.value === DIALOG_TITLE.ADD) { | ||||
|       formData.value.id = ''; | ||||
|       response = await addEnter(formData.value); | ||||
|     } else { | ||||
|       response = await updateEnter(formData.value); | ||||
|     } | ||||
| 
 | ||||
|     if (response.code === 200) { | ||||
|       ElMessage.success(`${dialogTitle.value}成功`); | ||||
|       visible.value = false; | ||||
|       getData(); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error(`${dialogTitle.value}失败`); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| const handlePageChange = ({ page, pageSize }) => { | ||||
|   pageData.currentPage = page; | ||||
|   pageData.pageSize = pageSize; | ||||
|   getData(); | ||||
| } | ||||
| function handleTabChange(tab) { | ||||
|   handleSearch(); | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| const handleTabChange = () => { | ||||
|   getData(); | ||||
| }; | ||||
| 
 | ||||
| const handleAdd = () => { | ||||
|   isReadonly.value = false; | ||||
|   resetForm(); | ||||
|   dialogTitle.value = '新增'; | ||||
|   dialogTitle.value = DIALOG_TITLE.ADD; | ||||
|   visible.value = true; | ||||
| }; | ||||
| // 查看详情(只读模式) | ||||
| 
 | ||||
| const handleView = async (row) => { | ||||
|   loading.value = true; | ||||
|   dialogTitle.value = '查看'; | ||||
|   dialogTitle.value = DIALOG_TITLE.VIEW; | ||||
|   try { | ||||
|     await getEnterDetail(row.id); | ||||
|     isReadonly.value = true; | ||||
| @ -275,10 +271,9 @@ const handleView = async (row) => { | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // 编辑详情(可修改) | ||||
| const handleEdit = async (row) => { | ||||
|   loading.value = true; | ||||
|   dialogTitle.value = '编辑'; | ||||
|   dialogTitle.value = DIALOG_TITLE.EDIT; | ||||
|   try { | ||||
|     await getEnterDetail(row.id); | ||||
|     isReadonly.value = false; | ||||
| @ -288,127 +283,97 @@ const handleEdit = async (row) => { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| // 提交审核 | ||||
| 
 | ||||
| const handleSubmitApprove = async (row) => { | ||||
|   try { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', // 待审核 | ||||
|       status: '1', | ||||
|       reason: '提交审核', | ||||
|     }; | ||||
|     const res = await approvalEnter(params); | ||||
|     if (res.code === 200) { | ||||
|       ElMessage.success('提交审核成功'); | ||||
|       row.status = '1'; | ||||
|       getData(); // 刷新表格数据 | ||||
|     } else { | ||||
|       ElMessage.error(res.msg || '提交审核失败'); | ||||
|       getData(); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error('提交审核失败'); | ||||
|   } | ||||
| }; | ||||
| // 重新提交(被驳回 → 待审核) | ||||
| function handleResubmit(row) { | ||||
|   ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', // 待审核 | ||||
|       reason: '重新提交审核', | ||||
|     }; | ||||
|     approvalEnter(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: '用户主动撤销', | ||||
|     }; | ||||
|     approvalEnter(params) | ||||
|       .then(() => { | ||||
|         console.log(`ID=${row.id} 撤销审核`); | ||||
|         row.status = '0'; | ||||
|         getData(); | ||||
|         ElMessage.success('已撤销,状态已变为"待提交"'); | ||||
| const handleResubmit = (row) => { | ||||
|   ElMessageBox.confirm('确认重新提交吗?', '重新提交') | ||||
|     .then(() => | ||||
|       approvalEnter({ | ||||
|         id: row.id, | ||||
|         status: '1', | ||||
|         reason: '重新提交审核', | ||||
|       }) | ||||
|       .catch((error) => { | ||||
|         console.error('撤销失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '撤销失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
|     ) | ||||
|     .then(() => { | ||||
|       getData(); | ||||
|       ElMessage.success('已重新提交,状态已变为"待审核"'); | ||||
|     }) | ||||
|     .catch(() => {}); | ||||
| }; | ||||
| 
 | ||||
| // 审核通过(待审核 → 已通过) | ||||
| function handleApprove(row) { | ||||
|   ElMessageBox.confirm('确认通过审核?', '审核通过').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '2', // 已通过 | ||||
|       reason: '审核通过', | ||||
|     }; | ||||
|     approvalEnter(params) | ||||
|       .then(() => { | ||||
|         console.log(`ID=${row.id} 审核通过`); | ||||
|         row.status = '2'; | ||||
|         getData(); | ||||
|         ElMessage.success('审核已通过'); | ||||
| const handleWithdraw = (row) => { | ||||
|   ElMessageBox.confirm('确认撤销本次审核吗?', '撤销') | ||||
|     .then(() => | ||||
|       approvalEnter({ | ||||
|         id: row.id, | ||||
|         status: '0', | ||||
|         reason: '用户主动撤销', | ||||
|       }) | ||||
|       .catch((error) => { | ||||
|         console.error('审核通过操作失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '审核操作失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
|     ) | ||||
|     .then(() => { | ||||
|       getData(); | ||||
|       ElMessage.success('已撤销,状态已变为"待提交"'); | ||||
|     }) | ||||
|     .catch(() => {}); | ||||
| }; | ||||
| 
 | ||||
| // 审核驳回(待审核 → 已驳回),需要填写驳回原因 | ||||
| function handleReject(row) { | ||||
| const handleApprove = (row) => { | ||||
|   ElMessageBox.confirm('确认通过审核?', '审核通过') | ||||
|     .then(() => | ||||
|       approvalEnter({ | ||||
|         id: row.id, | ||||
|         status: '2', | ||||
|         reason: '审核通过', | ||||
|       }) | ||||
|     ) | ||||
|     .then(() => { | ||||
|       getData(); | ||||
|       ElMessage.success('审核已通过'); | ||||
|     }) | ||||
|     .catch(() => {}); | ||||
| }; | ||||
| 
 | ||||
| const handleReject = (row) => { | ||||
|   ElMessageBox.prompt('请输入驳回原因', '审核驳回', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     inputPattern: /.+/, // 必须输入内容 | ||||
|     inputPattern: /.+/, | ||||
|     inputErrorMessage: '驳回原因不能为空', | ||||
|   }) | ||||
|     .then(({ value }) => { | ||||
|       const params = { | ||||
|     .then(({ value }) => | ||||
|       approvalEnter({ | ||||
|         id: row.id, | ||||
|         status: '3', // 已驳回 | ||||
|         status: '3', | ||||
|         reason: value.trim(), | ||||
|       }; | ||||
|       return approvalEnter(params).then(() => { | ||||
|         console.log(`ID=${row.id} 驳回,原因:${value.trim()}`); | ||||
|         row.status = '3'; | ||||
|         row.rejectReason = value.trim(); | ||||
|         getData(); | ||||
|         ElMessage.success('已驳回'); | ||||
|       }); | ||||
|       }) | ||||
|     ) | ||||
|     .then(() => { | ||||
|       getData(); | ||||
|       ElMessage.success('已驳回'); | ||||
|     }) | ||||
|     .catch((error) => { | ||||
|       if (error !== 'cancel') { | ||||
|         console.error('驳回操作失败:', error); | ||||
|         ElMessage.error(error.response?.data?.msg || '驳回操作失败'); | ||||
|       } | ||||
|     }); | ||||
| } | ||||
| // 查看/弹窗 驳回原因 | ||||
| function showRejectReason(row) { | ||||
|     .catch(() => {}); | ||||
| }; | ||||
| 
 | ||||
| const showRejectReason = (row) => { | ||||
|   ElMessageBox.alert(row.reason || '无驳回原因', '驳回原因'); | ||||
| } | ||||
| // 删除操作 | ||||
| }; | ||||
| 
 | ||||
| const handleDelete = async (id) => { | ||||
|   try { | ||||
|     await ElMessageBox.confirm('确认删除该合作社信息?', '提示', { | ||||
| @ -418,54 +383,40 @@ const handleDelete = async (id) => { | ||||
|     const res = await deleteEnter(id); | ||||
|     if (res.code === 200) { | ||||
|       ElMessage.success('删除成功'); | ||||
|       getData(); // 刷新数据 | ||||
|     } else { | ||||
|       ElMessage.error(res.msg || '删除失败'); | ||||
|       getData(); | ||||
|     } | ||||
|   } catch (e) { | ||||
|     if (e !== 'cancel') { | ||||
|   } catch (error) { | ||||
|     if (error !== 'cancel') { | ||||
|       ElMessage.error('删除失败'); | ||||
|     } | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| // 新增 tabs 顺序列表 | ||||
| const tabOrder = ['basic', 'register', 'business', 'credit']; | ||||
| 
 | ||||
| const currentTabIndex = computed(() => tabOrder.indexOf(activeTab.value)); | ||||
| const isFirstTab = computed(() => currentTabIndex.value === 0); | ||||
| const isLastTab = computed(() => currentTabIndex.value === tabOrder.length - 1); | ||||
| /** 跳转到下一 Tab */ | ||||
| function handleNext() { | ||||
|   if (currentTabIndex.value < tabOrder.length - 1) { | ||||
|     activeTab.value = tabOrder[currentTabIndex.value + 1]; | ||||
| const handleNext = () => { | ||||
|   if (currentTabIndex.value < TAB_ORDER.length - 1) { | ||||
|     activeTab.value = TAB_ORDER[currentTabIndex.value + 1]; | ||||
|   } | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| /** 跳转到上一 Tab */ | ||||
| function handlePrev() { | ||||
| const handlePrev = () => { | ||||
|   if (currentTabIndex.value > 0) { | ||||
|     activeTab.value = tabOrder[currentTabIndex.value - 1]; | ||||
|     activeTab.value = TAB_ORDER[currentTabIndex.value - 1]; | ||||
|   } | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| /** 跳过当前步骤 */ | ||||
| function handleSkip() { | ||||
| const handleSkip = () => { | ||||
|   handleNext(); | ||||
| } | ||||
| /** 跳过并保存 */ | ||||
| function handleSkipSave() { | ||||
| }; | ||||
| 
 | ||||
| const handleSkipSave = () => { | ||||
|   handleSkip(); | ||||
|   handleSubmit(); | ||||
| } | ||||
| import { useUserStore } from '@/store/modules/user'; | ||||
| const UserStore = useUserStore(); | ||||
| const user = UserStore.getUserInfo(); | ||||
| console.log('admin 属性:', user.admin); | ||||
| const isAdmin = user.admin; | ||||
| }; | ||||
| 
 | ||||
| const getActions = (row) => { | ||||
|   const actions = [ | ||||
|   const baseActions = [ | ||||
|     { | ||||
|       name: '查看', | ||||
|       icon: 'view', | ||||
| @ -486,7 +437,7 @@ const getActions = (row) => { | ||||
| 
 | ||||
|   switch (row.status) { | ||||
|     case '0': // 待提交 | ||||
|       actions.push( | ||||
|       baseActions.push( | ||||
|         { | ||||
|           name: '提交审核', | ||||
|           icon: 'check', | ||||
| @ -501,8 +452,8 @@ const getActions = (row) => { | ||||
|       break; | ||||
| 
 | ||||
|     case '1': // 待审核 | ||||
|       if (isAdmin) { | ||||
|         actions.push( | ||||
|       if (isAdmin.value) { | ||||
|         baseActions.push( | ||||
|           { | ||||
|             name: '通过', | ||||
|             icon: 'check-circle', | ||||
| @ -515,7 +466,7 @@ const getActions = (row) => { | ||||
|           } | ||||
|         ); | ||||
|       } else { | ||||
|         actions.push({ | ||||
|         baseActions.push({ | ||||
|           name: '撤销', | ||||
|           icon: 'undo', | ||||
|           event: () => handleWithdraw(row), | ||||
| @ -523,12 +474,8 @@ const getActions = (row) => { | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|     case '2': // 已通过 | ||||
|       // 仅基础操作 | ||||
|       break; | ||||
| 
 | ||||
|     case '3': // 已驳回 | ||||
|       actions.push({ | ||||
|       baseActions.push({ | ||||
|         name: '驳回原因', | ||||
|         icon: 'warning', | ||||
|         event: () => showRejectReason(row), | ||||
| @ -536,8 +483,13 @@ const getActions = (row) => { | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   return actions; | ||||
|   return baseActions; | ||||
| }; | ||||
| 
 | ||||
| // 生命周期 | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="scss"> | ||||
| @ -545,26 +497,26 @@ const getActions = (row) => { | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   // background-color: #7daaaa; | ||||
| 
 | ||||
|   :deep(.el-tabs__item) { | ||||
|     font-size: 16px; | ||||
|     color: #555555; | ||||
|     font-weight: 500; | ||||
|     // border: 1 solid #f000; | ||||
|   } | ||||
| 
 | ||||
|   :deep(.el-tabs__content) { | ||||
|     padding: 20px; | ||||
|     width: 100%; | ||||
|     // background-color: #f5f5f5; | ||||
|     border-radius: 4px; | ||||
|     height: calc(100vh - 300px); | ||||
|     overflow-y: auto; | ||||
|   } | ||||
| 
 | ||||
|   :deep(.el-tab-pane) { | ||||
|     margin: 0 auto; | ||||
|     width: 80%; | ||||
|   } | ||||
| 
 | ||||
|   :deep(.el-tab-pane:nth-child(5)) { | ||||
|     margin: 0 auto; | ||||
|     width: 100%; | ||||
|  | ||||
| @ -1,6 +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 /> | ||||
| @ -11,26 +11,39 @@ | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
| 
 | ||||
|     <!-- 四个固定 Tabs --> | ||||
|     <!-- 状态Tabs --> | ||||
|     <el-tabs v-model="activeTab" @tab-click="handleTabChange"> | ||||
|       <!-- <el-tab-pane label="待提交" name="0" /> --> | ||||
|       <el-tab-pane label="待审核" name="1" /> | ||||
|       <el-tab-pane label="已通过" name="2" /> | ||||
|       <el-tab-pane label="已驳回" name="3" /> | ||||
|     </el-tabs> | ||||
| 
 | ||||
|     <!-- 表格 --> | ||||
|     <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"> | ||||
|     <!-- 功能按钮 --> | ||||
|     <section v-if="activeTab === '0'" 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 - 300px)" | ||||
|       @page-change="handlePageChange" | ||||
|     > | ||||
|       <template #action="scope"> | ||||
|         <custom-table-operate :actions="getActions(scope.row)" :data="scope" /> | ||||
|       </template> | ||||
|     </avue-crud> | ||||
|     </TableComponent> | ||||
| 
 | ||||
|     <!-- 新增弹窗 --> | ||||
|     <el-dialog :key="dialogTitle" v-model="dialogVisible" :title="dialogTitle" width="60%" align-center :draggable="true"> | ||||
|     <!-- 表单弹窗 --> | ||||
|     <el-dialog :key="dialogType" 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"> | ||||
| @ -48,6 +61,7 @@ | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
| 
 | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="证件号码" prop="idCard"> | ||||
| @ -63,6 +77,7 @@ | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
| 
 | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="年龄" prop="age"> | ||||
| @ -75,11 +90,11 @@ | ||||
|             </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"> | ||||
| @ -88,6 +103,7 @@ | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
| 
 | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="种植面积" prop="area"> | ||||
| @ -96,9 +112,6 @@ | ||||
|           </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" | ||||
| @ -111,6 +124,7 @@ | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
| 
 | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">取消</el-button> | ||||
| @ -122,62 +136,62 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, computed, reactive, onMounted, watch, nextTick } from 'vue'; | ||||
| import { ElMessageBox, ElMessage } from 'element-plus'; | ||||
| import { CRUD_OPTIONS } from '@/config'; | ||||
| import { ref, computed, reactive, onMounted } from 'vue'; | ||||
| import { ElMessage, ElMessageBox } from 'element-plus'; | ||||
| 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 DIALOG_TYPE = { | ||||
|   VIEW: 'view', | ||||
|   EDIT: 'edit', | ||||
|   ADD: 'add', | ||||
| }; | ||||
| 
 | ||||
| // 角色判断的计算属性 | ||||
| const isSuperAdmin = computed(() => role.value === 'superadmin'); | ||||
| const isAuditor = computed(() => role.value === 'auditor'); | ||||
| const STATUS = { | ||||
|   PENDING: '0', | ||||
|   REVIEWING: '1', | ||||
|   APPROVED: '2', | ||||
|   REJECTED: '3', | ||||
| }; | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 2. Tab 与数据的状态控制 | ||||
| // --------------------------------------------------------------------- | ||||
| const activeTab = ref('1'); | ||||
| const dialogTitle = ref('新增'); | ||||
| // ==================== 状态管理和响应式数据 ==================== | ||||
| const loading = ref(false); | ||||
| const dialogVisible = ref(false); | ||||
| const dialogType = ref(DIALOG_TYPE.ADD); | ||||
| const isReadonly = ref(false); | ||||
| // 搜索表单模型 | ||||
| const searchForm = ref({ | ||||
| const activeTab = ref(STATUS.REVIEWING); | ||||
| const cropsOptions = ref([]); | ||||
| 
 | ||||
| const searchForm = reactive({ | ||||
|   name: '', | ||||
|   idCard: '', | ||||
|   phone: '', | ||||
|   status: '', | ||||
|   userId: '', | ||||
| }); | ||||
| const loading = ref(false); | ||||
| const crudRef = ref(); | ||||
| // 分页数据 | ||||
| const pageData = ref({ | ||||
| 
 | ||||
| const pageData = reactive({ | ||||
|   currentPage: 1, | ||||
|   pageSize: 10, | ||||
|   total: 0, | ||||
| }); | ||||
| // 模拟的原始数据列表(通常从后端接口拿到) | ||||
| const crudData = ref([]); | ||||
| 
 | ||||
| // 新增弹窗显示状态 | ||||
| const dialogVisible = ref(false); | ||||
| // 定义默认表单数据 | ||||
| const tableData = ref([]); | ||||
| 
 | ||||
| const defaultFormData = { | ||||
|   id: '', | ||||
|   name: '', | ||||
|   idType: '101', | ||||
|   idCard: '', | ||||
|   sex: '1', | ||||
|   age: '', | ||||
|   phone: '', | ||||
|   provinceCode: '', // 省 | ||||
|   cityCode: '', // 市 | ||||
|   countyCode: '', // 区县 | ||||
|   townCode: '', // 镇 | ||||
|   villageCode: '', // 村 | ||||
|   provinceCode: '', | ||||
|   cityCode: '', | ||||
|   countyCode: '', | ||||
|   townCode: '', | ||||
|   villageCode: '', | ||||
|   address: '', | ||||
|   addressArr: [], | ||||
|   detailAddress: '', | ||||
| @ -185,187 +199,92 @@ const defaultFormData = { | ||||
|   planCrop: '', | ||||
|   reason: '', | ||||
| }; | ||||
| // 新增表单数据,使用默认数据初始化 | ||||
| const formData = ref({ ...defaultFormData }); | ||||
| 
 | ||||
| // 重置表单数据的方法 | ||||
| const resetForm = () => { | ||||
|   formData.value = { ...defaultFormData }; | ||||
| }; | ||||
| const formData = reactive({ ...defaultFormData }); | ||||
| 
 | ||||
| // ============================== | ||||
| // CRUD 配置 | ||||
| // ============================== | ||||
| const crudOptions = reactive({ | ||||
|   ...CRUD_OPTIONS, | ||||
|   addBtn: false, | ||||
|   searchBtn: false, | ||||
|   emptyBtn: false, | ||||
|   refreshBtn: false, | ||||
|   column: [ | ||||
|     { label: '生产经营主体编码', prop: 'id' }, | ||||
|     { label: '姓名', prop: 'name' }, | ||||
|     { label: '联系方式', prop: 'phone' }, | ||||
|     // 地址 | ||||
|     { label: '地址', prop: 'address', width: '300px' }, | ||||
|     { label: '地块数量', prop: 'landCount' }, | ||||
|     { label: '地块编号', prop: 'landNumber' }, | ||||
|     { label: '地块名称', prop: 'landName' }, | ||||
|     { label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|     { label: '所属行政区划', prop: 'address' }, | ||||
|     { label: '所属网格', prop: 'gridCode' }, | ||||
|     { label: '种植作物', prop: 'planCropName' }, | ||||
|     // { label: '账号(手机号)', prop: 'phone' }, | ||||
|     { label: '创建时间', prop: 'createTime' }, | ||||
|     { label: '更新时间', prop: 'updateTime' }, | ||||
|   ], | ||||
| // ==================== 计算属性 ==================== | ||||
| const dialogTitle = computed(() => { | ||||
|   const titles = { | ||||
|     [DIALOG_TYPE.VIEW]: '查看', | ||||
|     [DIALOG_TYPE.EDIT]: '编辑', | ||||
|     [DIALOG_TYPE.ADD]: '新增', | ||||
|   }; | ||||
|   return titles[dialogType.value]; | ||||
| }); | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 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); | ||||
|   } | ||||
| // ==================== 表单操作 ==================== | ||||
| const resetForm = () => { | ||||
|   Object.assign(formData, defaultFormData); | ||||
| }; | ||||
| function handleSearch() { | ||||
|   getData(); | ||||
| } | ||||
| function handleReset() { | ||||
|   searchForm.value.keyword = ''; | ||||
| 
 | ||||
| const syncAddress = () => { | ||||
|   const arr = formData.addressArr || []; | ||||
|   formData.provinceCode = arr[0] || ''; | ||||
|   formData.cityCode = arr[1] || ''; | ||||
|   formData.countyCode = arr[2] || ''; | ||||
|   formData.townCode = arr[3] || ''; | ||||
|   formData.villageCode = arr[4] || ''; | ||||
| }; | ||||
| 
 | ||||
| const handleSearch = () => { | ||||
|   pageData.currentPage = 1; | ||||
|   fetchData(); | ||||
| }; | ||||
| 
 | ||||
| const handleReset = () => { | ||||
|   Object.assign(searchForm, { | ||||
|     name: '', | ||||
|     idCard: '', | ||||
|     phone: '', | ||||
|     status: '', | ||||
|     userId: '', | ||||
|   }); | ||||
|   handleSearch(); | ||||
| } | ||||
| function handleTabChange(tab) { | ||||
| }; | ||||
| 
 | ||||
| const handleTabChange = () => { | ||||
|   handleSearch(); | ||||
| } | ||||
| // 新增 | ||||
| }; | ||||
| 
 | ||||
| const handleAdd = () => { | ||||
|   isReadonly.value = false; // 设置为可编辑模式 | ||||
|   dialogType.value = DIALOG_TYPE.ADD; | ||||
|   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 { | ||||
|     syncAddress(); | ||||
|     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 (dialogType.value === DIALOG_TYPE.ADD) { | ||||
|       response = await saveFarmerList(formData); | ||||
|     } else { | ||||
|       response = await editFarmer(formData); | ||||
|     } | ||||
| 
 | ||||
|     if (response && response.code === 200) { | ||||
|     if (response?.code === 200) { | ||||
|       ElMessage.success(`${dialogTitle.value}成功`); | ||||
|       dialogVisible.value = false; | ||||
|       getData(); // 重新获取数据 | ||||
|       fetchData(); | ||||
|     } | ||||
|   } catch (error) { | ||||
|     if (dialogTitle.value === '新增') { | ||||
|       ElMessage.error('新增失败,请稍后重试'); | ||||
|     } else { | ||||
|       ElMessage.error('编辑失败,请稍后重试'); | ||||
|     } | ||||
|     ElMessage.error(`${dialogTitle.value}失败`); | ||||
|   } | ||||
| }; | ||||
| 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(() => { | ||||
| const handleView = async (row) => { | ||||
|   dialogType.value = DIALOG_TYPE.VIEW; | ||||
|   isReadonly.value = true; | ||||
| 
 | ||||
|   if (await getFarmerDetail(row.id)) { | ||||
|     dialogVisible.value = true; | ||||
|   }); | ||||
| } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // 编辑(修改/填写) | ||||
| async function handleEdit(row) { | ||||
|   if (row.status === '2') { | ||||
| const handleEdit = async (row) => { | ||||
|   if (row.status === STATUS.APPROVED) { | ||||
|     try { | ||||
|       await ElMessageBox.confirm('编辑后数据将需要重新审核,是否继续?', '确认编辑', { | ||||
|         confirmButtonText: '继续编辑', | ||||
| @ -376,159 +295,99 @@ async function handleEdit(row) { | ||||
|       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 = '编辑'; | ||||
| 
 | ||||
|   dialogType.value = DIALOG_TYPE.EDIT; | ||||
|   isReadonly.value = false; | ||||
|   nextTick(() => { | ||||
| 
 | ||||
|   if (await getFarmerDetail(row.id)) { | ||||
|     dialogVisible.value = true; | ||||
|   }); | ||||
| } | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // 提交审核(待提交 → 待审核) | ||||
| function handleSubmit(row) { | ||||
|   ElMessageBox.confirm('确定提交审核吗?', '提交审核').then(() => { | ||||
| const handleStatusChange = async (row, newStatus, reason = '') => { | ||||
|   try { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', | ||||
|       reason: row.reason || '', | ||||
|       status: newStatus, | ||||
|       reason, | ||||
|     }; | ||||
|     approveFarmer(params) | ||||
|       .then(() => { | ||||
|         row.rejectReason = ''; // 清空驳回原因 | ||||
|         getData(); // 重新获取数据 | ||||
|       }) | ||||
|       .catch(() => { | ||||
|         ElMessage.error('提交审核失败,请稍后重试'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // 重新提交(被驳回 → 待审核) | ||||
| function handleResubmit(row) { | ||||
|   ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => { | ||||
|     const params = { | ||||
|       id: row.id, | ||||
|       status: '1', // 待审核 | ||||
|       reason: '重新提交审核', | ||||
|     await approveFarmer(params); | ||||
|     fetchData(); | ||||
| 
 | ||||
|     const messages = { | ||||
|       [STATUS.PENDING]: '已撤销', | ||||
|       [STATUS.REVIEWING]: '已提交审核', | ||||
|       [STATUS.APPROVED]: '审核已通过', | ||||
|       [STATUS.REJECTED]: '已驳回', | ||||
|     }; | ||||
|     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 || '撤销失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
|     ElMessage.success(messages[newStatus]); | ||||
|   } catch (error) { | ||||
|     ElMessage.error('操作失败'); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // 审核通过(待审核 → 已通过) | ||||
| 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 || '审核操作失败'); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| const handleSubmit = (row) => { | ||||
|   ElMessageBox.confirm('确定提交审核吗?', '提交审核').then(() => handleStatusChange(row, STATUS.REVIEWING)); | ||||
| }; | ||||
| 
 | ||||
| // 审核驳回(待审核 → 已驳回),需要填写驳回原因 | ||||
| function handleReject(row) { | ||||
| const handleResubmit = (row) => { | ||||
|   ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => handleStatusChange(row, STATUS.REVIEWING, '重新提交审核')); | ||||
| }; | ||||
| 
 | ||||
| const handleWithdraw = (row) => { | ||||
|   ElMessageBox.confirm('确认撤销本次审核吗?', '撤销').then(() => handleStatusChange(row, STATUS.PENDING, '用户主动撤销')); | ||||
| }; | ||||
| 
 | ||||
| const handleApprove = (row) => { | ||||
|   ElMessageBox.confirm('确认通过审核?', '审核通过').then(() => handleStatusChange(row, STATUS.APPROVED, '审核通过')); | ||||
| }; | ||||
| 
 | ||||
| const handleReject = (row) => { | ||||
|   ElMessageBox.prompt('请输入驳回原因', '审核驳回', { | ||||
|     confirmButtonText: '确定', | ||||
|     cancelButtonText: '取消', | ||||
|     inputPattern: /.+/, // 必须输入内容 | ||||
|     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 || '驳回操作失败'); | ||||
|       } | ||||
|     }); | ||||
| } | ||||
|   }).then(({ value }) => handleStatusChange(row, STATUS.REJECTED, value.trim())); | ||||
| }; | ||||
| 
 | ||||
| // 查看/弹窗 驳回原因 | ||||
| function showRejectReason(row) { | ||||
| const showRejectReason = (row) => { | ||||
|   ElMessageBox.alert(row.reason || '无驳回原因', '驳回原因'); | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| async function handleDelete(row) { | ||||
| const handleDelete = async (row) => { | ||||
|   try { | ||||
|     await ElMessageBox.confirm('确定删除该条记录?', '删除提示'); | ||||
| 
 | ||||
|     console.log(`删除 ID=${row.id}`); | ||||
|     await deleteFarmers(row.id); // 直接传递单ID | ||||
|     await getData(); | ||||
|     await deleteFarmers(row.id); | ||||
|     await fetchData(); | ||||
|     ElMessage.success('已删除'); | ||||
|   } catch (error) { | ||||
|     if (error !== 'cancel') { | ||||
|       ElMessage.error(`删除失败: ${error.message || '请稍后重试'}`); | ||||
|       ElMessage.error('删除失败'); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // 定义操作映射 | ||||
| const ACTION_MAP = { | ||||
| }; | ||||
| // ==================== 表格配置 ==================== | ||||
| const columns = ref([ | ||||
|   { label: '生产经营主体编码', prop: 'id' }, | ||||
|   { label: '姓名', prop: 'name' }, | ||||
|   { label: '联系方式', prop: 'phone' }, | ||||
|   { label: '地址', prop: 'address', width: '300px' }, | ||||
|   { label: '地块数量', prop: 'landCount' }, | ||||
|   { label: '地块编号', prop: 'landNumber' }, | ||||
|   { label: '地块名称', prop: 'landName' }, | ||||
|   { label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)} 亩` }, | ||||
|   { label: '所属行政区划', prop: 'address' }, | ||||
|   { label: '所属网格', prop: 'gridCode' }, | ||||
|   { label: '种植作物', prop: 'planCropName' }, | ||||
|   { label: '创建时间', prop: 'createTime' }, | ||||
|   { label: '更新时间', prop: 'updateTime' }, | ||||
|   { label: '操作', prop: 'action', slotName: 'action', fixed: 'right' }, | ||||
| ]); | ||||
| // 操作按钮配置 | ||||
| const ACTION_CONFIG = { | ||||
|   view: { name: '查看', icon: 'view', handler: handleView }, | ||||
|   edit: { name: '编辑', icon: 'edit', handler: handleEdit }, | ||||
|   submit: { name: '提交审核', icon: 'submit', handler: handleSubmit }, | ||||
| @ -541,56 +400,100 @@ const ACTION_MAP = { | ||||
|   modify: { name: '修改', icon: 'edit', handler: handleEdit }, | ||||
| }; | ||||
| 
 | ||||
| // 定义角色和状态对应的操作配置 | ||||
| const ROLE_STATUS_ACTIONS = { | ||||
| const ROLE_ACTIONS = { | ||||
|   superadmin: { | ||||
|     0: ['view', 'edit', 'submit', 'delete'], | ||||
|     1: ['view', 'approve', 'reject', 'withdraw', 'delete'], | ||||
|     2: ['view', 'modify', 'delete'], | ||||
|     3: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|     [STATUS.PENDING]: ['view', 'edit', 'submit', 'delete'], | ||||
|     [STATUS.REVIEWING]: ['view', 'approve', 'reject', 'withdraw', 'delete'], | ||||
|     [STATUS.APPROVED]: ['view', 'modify', 'delete'], | ||||
|     [STATUS.REJECTED]: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|   }, | ||||
|   auditor: { | ||||
|     0: [], | ||||
|     1: ['view', 'approve', 'reject'], | ||||
|     2: ['view', 'delete'], | ||||
|     3: ['view', 'reason', 'delete'], | ||||
|     [STATUS.PENDING]: [], | ||||
|     [STATUS.REVIEWING]: ['view', 'approve', 'reject'], | ||||
|     [STATUS.APPROVED]: ['view', 'delete'], | ||||
|     [STATUS.REJECTED]: ['view', 'reason', 'delete'], | ||||
|   }, | ||||
|   submitter: { | ||||
|     0: ['view', 'edit', 'submit', 'delete'], | ||||
|     1: ['view', 'withdraw', 'delete'], | ||||
|     2: ['view', 'modify', 'delete'], | ||||
|     3: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|     [STATUS.PENDING]: ['view', 'edit', 'submit', 'delete'], | ||||
|     [STATUS.REVIEWING]: ['view', 'withdraw', 'delete'], | ||||
|     [STATUS.APPROVED]: ['view', 'modify', 'delete'], | ||||
|     [STATUS.REJECTED]: ['view', 'edit', 'reason', 'resubmit', 'delete'], | ||||
|   }, | ||||
| }; | ||||
| 
 | ||||
| // 根据角色和状态动态生成操作按钮 | ||||
| function getActions(row) { | ||||
|   const currentRole = role.value; | ||||
|   const status = row.status; | ||||
|   const actionKeys = ROLE_STATUS_ACTIONS[currentRole]?.[status] || []; | ||||
| const getActions = (row) => { | ||||
|   const role = 'superadmin'; // TODO: 实际项目中应从用户信息获取 | ||||
|   const actions = ROLE_ACTIONS[role]?.[row.status] || []; | ||||
| 
 | ||||
|   return actionKeys.map((key) => { | ||||
|     const action = ACTION_MAP[key]; | ||||
|     return { | ||||
|       ...action, | ||||
|       event: () => action.handler(row), | ||||
|   return actions.map((key) => ({ | ||||
|     ...ACTION_CONFIG[key], | ||||
|     event: () => ACTION_CONFIG[key].handler(row), | ||||
|   })); | ||||
| }; | ||||
| // ==================== 表格操作 ==================== | ||||
| const handlePageChange = ({ page, pageSize }) => { | ||||
|   pageData.currentPage = page; | ||||
|   pageData.pageSize = pageSize; | ||||
|   fetchData(); | ||||
| }; | ||||
| // ==================== 数据获取 ==================== | ||||
| const fetchData = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     const params = { | ||||
|       ...searchForm, | ||||
|       status: activeTab.value, | ||||
|       current: pageData.currentPage, | ||||
|       size: pageData.pageSize, | ||||
|     }; | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| // --------------------------------------------------------------------- | ||||
| // 4. 示例:页面加载时可以从后端获取 crudData | ||||
| // --------------------------------------------------------------------- | ||||
|     const response = await fetchFarmerList(params); | ||||
|     if (response.code === 200 && response.data) { | ||||
|       tableData.value = response.data.records; | ||||
|       pageData.total = response.data.total; | ||||
|       pageData.currentPage = response.data.current; | ||||
|       pageData.pageSize = response.data.size; | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error('获取数据失败'); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| const fetchCropsData = async () => { | ||||
|   try { | ||||
|     const res = await pageCropsList({ status: '0' }); | ||||
|     if (res.code === 200) { | ||||
|       cropsOptions.value = res.data.records; | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('获取种植作物列表失败:', error); | ||||
|   } | ||||
| }; | ||||
| const getFarmerDetail = async (id) => { | ||||
|   try { | ||||
|     const response = await fetchFarmerById(id); | ||||
|     if (response.code === 200 && response.data) { | ||||
|       const data = response.data; | ||||
|       const addressArr = [data.provinceCode, data.cityCode, data.countyCode, data.townCode, data.villageCode].filter(Boolean); | ||||
| 
 | ||||
|       Object.assign(formData, data, { addressArr }); | ||||
|       return true; | ||||
|     } | ||||
|   } catch (error) { | ||||
|     ElMessage.error('获取详情失败'); | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
| // ==================== 生命周期 ==================== | ||||
| onMounted(() => { | ||||
|   getData(); | ||||
|   fetchCropsList(); // 初始化种植作物列表 | ||||
|   fetchData(); | ||||
|   fetchCropsData(); | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="scss"> | ||||
| // :deep(.avue-crud__header) { | ||||
| //   display: none; | ||||
| // } | ||||
| .custom-page { | ||||
|   padding: 20px; | ||||
|   height: calc(100vh - 150px); | ||||
| @ -600,6 +503,7 @@ onMounted(() => { | ||||
|     margin-bottom: 20px; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| :deep(.el-dialog__body) { | ||||
|   padding: 20px; | ||||
|   height: calc(100vh - 300px); | ||||
| @ -612,13 +516,14 @@ onMounted(() => { | ||||
|   .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包含在宽度内 | ||||
|     max-width: 100%; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user