feat:土地功能优化
This commit is contained in:
		
							parent
							
								
									8fc8a2094d
								
							
						
					
					
						commit
						6fc598e35e
					
				| @ -9,12 +9,6 @@ export default [ | |||||||
|     redirect: '/sub-government-affairs-service/trace-home', |     redirect: '/sub-government-affairs-service/trace-home', | ||||||
|     meta: { title: '溯源管理', icon: 'Document' }, |     meta: { title: '溯源管理', icon: 'Document' }, | ||||||
|     children: [ |     children: [ | ||||||
|       { |  | ||||||
|         path: '/sub-government-affairs-service/trace-index', |  | ||||||
|         name: 'trace-index', |  | ||||||
|         component: () => import('@/views/trace/statistic/index.vue'), |  | ||||||
|         meta: { title: '溯源首页', icon: 'Document' }, |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         path: '/sub-government-affairs-service/record', |         path: '/sub-government-affairs-service/record', | ||||||
|         name: 'record', |         name: 'record', | ||||||
| @ -78,6 +72,12 @@ export default [ | |||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
|       }, |       }, | ||||||
|  |       { | ||||||
|  |         path: '/sub-government-affairs-service/trace-statistic', | ||||||
|  |         name: 'trace-statistic', | ||||||
|  |         component: () => import('@/views/trace/statistic/index.vue'), | ||||||
|  |         meta: { title: '溯源统计', icon: 'Document' }, | ||||||
|  |       }, | ||||||
|     ], |     ], | ||||||
|   }, |   }, | ||||||
| ]; | ]; | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
|  * @Author: zenghua.wang |  * @Author: zenghua.wang | ||||||
|  * @Date: 2022-02-23 21:12:37 |  * @Date: 2022-02-23 21:12:37 | ||||||
|  * @LastEditors: zenghua.wang |  * @LastEditors: zenghua.wang | ||||||
|  * @LastEditTime: 2025-02-11 17:18:36 |  * @LastEditTime: 2025-03-24 10:05:36 | ||||||
|  */ |  */ | ||||||
| import lodash from 'lodash'; | import lodash from 'lodash'; | ||||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||||
| @ -123,6 +123,26 @@ export const setDicLabel = (dicData, value) => { | |||||||
|   } |   } | ||||||
|   return label; |   return label; | ||||||
| }; | }; | ||||||
|  | /** | ||||||
|  |  * @Title 将tree数据结构打平 | ||||||
|  |  * @param {*} tree | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | export const flattenTree = (tree) => { | ||||||
|  |   const result = []; | ||||||
|  |   function traverse(node) { | ||||||
|  |     result.push(node); | ||||||
|  |     if (node.children && node.children.length > 0) { | ||||||
|  |       node.children.forEach((child) => traverse(child)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   if (Array.isArray(tree)) { | ||||||
|  |     tree.forEach((item) => traverse(item)); | ||||||
|  |   } else { | ||||||
|  |     traverse(tree); | ||||||
|  |   } | ||||||
|  |   return result; | ||||||
|  | }; | ||||||
| /** | /** | ||||||
|  * @Title 数组交集 |  * @Title 数组交集 | ||||||
|  * @param {*} arr1 |  * @param {*} arr1 | ||||||
|  | |||||||
| @ -0,0 +1,421 @@ | |||||||
|  | <template> | ||||||
|  |   <CustomCard> | ||||||
|  |     <div> | ||||||
|  |       <el-row :gutter="20"> | ||||||
|  |         <el-col :span="4"> | ||||||
|  |           <el-tree | ||||||
|  |             style="max-width: 600px" | ||||||
|  |             :data="treeData" | ||||||
|  |             node-key="id" | ||||||
|  |             :default-expanded-keys="[selectTreeNode.id]" | ||||||
|  |             :props="{ value: 'id' }" | ||||||
|  |             :expand-on-click-node="false" | ||||||
|  |             @node-click="handleNodeClick" | ||||||
|  |           > | ||||||
|  |             <template #default="{ data }"> | ||||||
|  |               <div class="tree_node_" :class="{ nodeActive: data.id == selectTreeNode.id || data.id == selectTreeNode.pId }"> | ||||||
|  |                 {{ data.label }} | ||||||
|  |               </div> | ||||||
|  |             </template> | ||||||
|  |           </el-tree> | ||||||
|  |         </el-col> | ||||||
|  |         <el-col :span="20"> | ||||||
|  |           <avue-crud | ||||||
|  |             ref="crudRef" | ||||||
|  |             v-model="state.form" | ||||||
|  |             v-model:search="state.query" | ||||||
|  |             v-model:page="state.pageData" | ||||||
|  |             :table-loading="state.loading" | ||||||
|  |             :data="state.data" | ||||||
|  |             :option="state.options" | ||||||
|  |             @refresh-change="refreshChange" | ||||||
|  |             @search-reset="searchChange" | ||||||
|  |             @search-change="searchChange" | ||||||
|  |             @selection-change="selectionChange" | ||||||
|  |             @current-change="currentChange" | ||||||
|  |             @size-change="sizeChange" | ||||||
|  |             @row-del="rowDel" | ||||||
|  |             @row-save="rowSave" | ||||||
|  |             @row-update="rowUpdate" | ||||||
|  |           > | ||||||
|  |             <template #menu-left> | ||||||
|  |               <el-button type="primary" icon="Plus" @click="onAdd">新增</el-button> | ||||||
|  |               <el-button type="success" icon="download" @click="onExport">导出</el-button> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template #menu="scope"> | ||||||
|  |               <custom-table-operate :actions="state.options.actions" :data="scope" /> | ||||||
|  |             </template> | ||||||
|  |           </avue-crud> | ||||||
|  |         </el-col> | ||||||
|  |       </el-row> | ||||||
|  |     </div> | ||||||
|  |   </CustomCard> | ||||||
|  | </template> | ||||||
|  | <script setup> | ||||||
|  | import { ref, reactive, onMounted, nextTick } from 'vue'; | ||||||
|  | import { useApp } from '@/hooks'; | ||||||
|  | import { CRUD_OPTIONS } from '@/config'; | ||||||
|  | import CustomCard from '@/components/CustomCard.vue'; | ||||||
|  | import { getLandTypeTree, landTypeSave, getLandType, exportLandType, delLandType, editLandType } from '@/apis/baseInfo'; | ||||||
|  | import { ElMessage } from 'element-plus'; | ||||||
|  | 
 | ||||||
|  | const { VITE_APP_BASE_API } = import.meta.env; | ||||||
|  | const app = useApp(); | ||||||
|  | 
 | ||||||
|  | const selectTreeNode = ref({ | ||||||
|  |   id: '', | ||||||
|  |   label: '', | ||||||
|  |   pId: '', | ||||||
|  |   pName: '', | ||||||
|  |   level: 0, | ||||||
|  | }); | ||||||
|  | const landTypesDic = ref([]); | ||||||
|  | const crudRef = ref(null); | ||||||
|  | const state = reactive({ | ||||||
|  |   loading: false, | ||||||
|  |   query: { | ||||||
|  |     current: 1, | ||||||
|  |     size: 10, | ||||||
|  |   }, | ||||||
|  |   form: {}, | ||||||
|  |   selection: [], | ||||||
|  |   options: { | ||||||
|  |     ...CRUD_OPTIONS, | ||||||
|  |     addBtnText: '', | ||||||
|  |     addBtn: false, | ||||||
|  |     dialogWidth: 680, | ||||||
|  |     selection: false, | ||||||
|  |     refreshBtn: false, | ||||||
|  |     column: [ | ||||||
|  |       { label: '编号', prop: 'id', addDisplay: false, editDisplay: false }, | ||||||
|  |       { | ||||||
|  |         label: '用地分类', | ||||||
|  |         prop: 'landType', | ||||||
|  |         dicData: landTypesDic, | ||||||
|  |         // type: 'select', | ||||||
|  |         multiple: true, | ||||||
|  |         span: 23, | ||||||
|  |         props: { | ||||||
|  |           value: 'id', | ||||||
|  |           label: 'childLandCategory', | ||||||
|  |         }, | ||||||
|  |         rules: [ | ||||||
|  |           { | ||||||
|  |             required: true, | ||||||
|  |             message: '请输入', | ||||||
|  |             trigger: 'blur', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |         render: ({ row }) => { | ||||||
|  |           return row.landType; | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         label: '土地类别', | ||||||
|  |         prop: 'landCategory', | ||||||
|  |         addDisplay: false, | ||||||
|  |         rules: [ | ||||||
|  |           { | ||||||
|  |             required: true, | ||||||
|  |             message: '请输入', | ||||||
|  |             trigger: 'blur', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |         render: ({ row }) => { | ||||||
|  |           return row.landCategory; | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         label: '状态', | ||||||
|  |         prop: 'status', | ||||||
|  |         render: ({ row }) => { | ||||||
|  |           return row.status == '1' ? '启用' : '禁用'; | ||||||
|  |         }, | ||||||
|  |         addDisplay: false, | ||||||
|  |         editDisplay: false, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |     actions: [ | ||||||
|  |       { | ||||||
|  |         name: ({ row }) => `${row.status == '0' ? '启' : '禁'}用`, | ||||||
|  |         icon: 'edit', | ||||||
|  |         event: ({ row }) => rowStatus(row), | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         name: '编辑', | ||||||
|  |         icon: 'edit', | ||||||
|  |         event: ({ row }) => rowEdit(row), | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         type: 'danger', | ||||||
|  |         name: '删除', | ||||||
|  |         icon: 'delete', | ||||||
|  |         event: ({ row }) => rowDel(row), | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |   }, | ||||||
|  |   pageData: { | ||||||
|  |     total: 0, | ||||||
|  |     currentPage: 1, | ||||||
|  |     pageSize: 10, | ||||||
|  |   }, | ||||||
|  |   data: [], | ||||||
|  |   currentRow: {}, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const treeData = ref([]); | ||||||
|  | 
 | ||||||
|  | const loadData = () => { | ||||||
|  |   state.loading = true; | ||||||
|  |   getLandType({ | ||||||
|  |     pid: selectTreeNode.value.id, | ||||||
|  |     ...state.query, | ||||||
|  |   }) | ||||||
|  |     .then((res) => { | ||||||
|  |       if (res.code === 200) { | ||||||
|  |         const { current, size, total, records } = res.data; | ||||||
|  |         state.data = records; | ||||||
|  |         state.pageData = { | ||||||
|  |           currentPage: current || 1, | ||||||
|  |           pageSize: size || 10, | ||||||
|  |           total: total, | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     .catch((err) => { | ||||||
|  |       app.$message.error(err.msg); | ||||||
|  |       state.data = []; | ||||||
|  |     }) | ||||||
|  |     .finally(() => { | ||||||
|  |       state.loading = false; | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  |   getLandTree(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | async function getLandTree() { | ||||||
|  |   let res = await getLandTypeTree(); | ||||||
|  |   if (res.code == 200) { | ||||||
|  |     treeData.value = newTree(res.data, 0); | ||||||
|  |     landTypesDic.value = res.data.map((v) => { | ||||||
|  |       return { | ||||||
|  |         id: v.id, | ||||||
|  |         label: v.prentLandType, | ||||||
|  |       }; | ||||||
|  |     }); | ||||||
|  |     console.log('treeData', treeData.value); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | function newTree(arr, i) { | ||||||
|  |   arr.forEach((v) => { | ||||||
|  |     if (i == 0) { | ||||||
|  |       v.label = v.prentLandType; | ||||||
|  |     } else { | ||||||
|  |       v.label = v.childLandCategory; | ||||||
|  |     } | ||||||
|  |     if (v.children) v.children = newTree(v.children, i + 1); | ||||||
|  |   }); | ||||||
|  |   return arr; | ||||||
|  | } | ||||||
|  | // 页数 | ||||||
|  | const currentChange = (current) => { | ||||||
|  |   state.query.current = current; | ||||||
|  |   loadData(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 条数 | ||||||
|  | const sizeChange = (size) => { | ||||||
|  |   state.query.current = 1; | ||||||
|  |   state.query.size = size; | ||||||
|  |   loadData(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 搜索 | ||||||
|  | const searchChange = (params, done) => { | ||||||
|  |   if (done) done(); | ||||||
|  |   state.query = params; | ||||||
|  |   state.query.current = 1; | ||||||
|  |   loadData(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 刷新 | ||||||
|  | const refreshChange = () => { | ||||||
|  |   loadData(); | ||||||
|  |   app.$message.success('刷新成功'); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 选择 | ||||||
|  | const selectionChange = (rows) => { | ||||||
|  |   state.selection = rows; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const handleNodeClick = (data, node) => { | ||||||
|  |   const { id } = data; | ||||||
|  |   if (selectTreeNode.value.id != id) { | ||||||
|  |     if (node.level < 2) { | ||||||
|  |       selectTreeNode.value = handleNodeData({ data, level: node.level }); | ||||||
|  |     } else selectTreeNode.value = handleNodeData({ data: node.parent.data, level: node.level }); | ||||||
|  |     loadData(); | ||||||
|  |   } else { | ||||||
|  |     selectTreeNode.value = { id: '', label: '', level: 0 }; | ||||||
|  |     state.data = []; | ||||||
|  |   } | ||||||
|  |   if (selectTreeNode.value.level < 1) { | ||||||
|  |     state.options.dialogWidth = 680; | ||||||
|  |     state.options.column[1].span = 23; | ||||||
|  |     state.options.column[2].addDisplay = false; | ||||||
|  |     delete state.options.column[1].addDisabled; | ||||||
|  |     delete state.options.column[1].value; | ||||||
|  |   } else { | ||||||
|  |     state.options.column[2].addDisplay = true; | ||||||
|  |     state.options.column[1].addDisabled = true; | ||||||
|  |     state.options.column[1].value = selectTreeNode.value.label; | ||||||
|  |     delete state.options.dialogWidth; | ||||||
|  |     delete state.options.column[1].type; | ||||||
|  |     delete state.options.column[1].span; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | function handleNodeData({ data, level }) { | ||||||
|  |   return { | ||||||
|  |     id: data.id, | ||||||
|  |     label: data.label, | ||||||
|  |     level, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | // 编辑状态 | ||||||
|  | async function rowStatus(row) { | ||||||
|  |   console.info('操作状态', row.$index); | ||||||
|  |   const { id } = row; | ||||||
|  |   let status = row.status == '1' ? '0' : '1'; | ||||||
|  |   let params = { | ||||||
|  |     id, | ||||||
|  |     status, | ||||||
|  |   }; | ||||||
|  |   let res = await editLandType(params); | ||||||
|  |   if (res.code == 200) { | ||||||
|  |     ElMessage.success('操作成功'); | ||||||
|  |     nextTick(() => { | ||||||
|  |       state.data[row.$index].status = status; | ||||||
|  |       loadData(); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | async function rowDel(row, done, loading) { | ||||||
|  |   let res = await delLandType(row.id); | ||||||
|  |   if (res.code === 200) { | ||||||
|  |     app.$message.success('已删除!'); | ||||||
|  |     loadData(); | ||||||
|  |     done(); | ||||||
|  |   } | ||||||
|  |   loading(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const rowEdit = (row) => { | ||||||
|  |   crudRef.value && crudRef.value.rowEdit(row); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const onAdd = () => { | ||||||
|  |   crudRef.value && crudRef.value.rowAdd(); | ||||||
|  | }; | ||||||
|  | async function onExport() { | ||||||
|  |   console.log('test ---'); | ||||||
|  |   if (selectTreeNode.value.level < 1) return ElMessage.warning('请选择用地分类'); | ||||||
|  |   let res = await exportLandType({ | ||||||
|  |     pid: selectTreeNode.value.id, | ||||||
|  |   }); | ||||||
|  |   console.log('edxport', res); | ||||||
|  |   if (res.status == 200) { | ||||||
|  |     let a = document.createElement('a'); | ||||||
|  |     let blob = new Blob([res.data]); | ||||||
|  |     let link = window.URL.createObjectURL(blob); | ||||||
|  |     a.href = link; | ||||||
|  |     a.download = '用地分类.xlsx'; | ||||||
|  |     document.body.appendChild(a); | ||||||
|  |     a.click(); | ||||||
|  |     document.body.removeChild(a); | ||||||
|  |     window.URL.revokeObjectURL(link); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | const rowSave = async (val, done, loading) => { | ||||||
|  |   console.info('新增', val); | ||||||
|  |   let data = {}; | ||||||
|  |   if (selectTreeNode.value.level < 1) { | ||||||
|  |     data.landType = val.landType; | ||||||
|  |   } else { | ||||||
|  |     data = { | ||||||
|  |       pid: selectTreeNode.value.id, | ||||||
|  |       landCategory: val.landCategory, | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |   let res = await landTypeSave(data); | ||||||
|  |   if (res.code == 200) { | ||||||
|  |     ElMessage.success('创建成功'); | ||||||
|  |     getLandTree(); | ||||||
|  |     if (selectTreeNode.value.level > 0) loadData(); | ||||||
|  |     done(); | ||||||
|  |   } | ||||||
|  |   // saveOperationRecord(row) | ||||||
|  |   //   .then((res) => { | ||||||
|  |   //     if (res.code === 200) { | ||||||
|  |   //       app.$message.success('添加成功!'); | ||||||
|  |   //       done(); | ||||||
|  |   //       loadData(); | ||||||
|  |   //     } | ||||||
|  |   //   }) | ||||||
|  |   //   .catch((err) => { | ||||||
|  |   //     app.$message.error(err.msg); | ||||||
|  |   //   }) | ||||||
|  |   //   .finally(() => { | ||||||
|  |   //     loading(); | ||||||
|  |   //   }); | ||||||
|  |   loading(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const rowUpdate = (row, index, done, loading) => { | ||||||
|  |   console.info('更新'); | ||||||
|  |   console.log('row', row); | ||||||
|  |   editLandType({ | ||||||
|  |     id: row.id, | ||||||
|  |     landCategory: row.landCategory, | ||||||
|  |   }).then((res) => { | ||||||
|  |     if (res.code === 200) { | ||||||
|  |       app.$message.success('更新成功!'); | ||||||
|  |       loadData(); | ||||||
|  |       done(); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |   loading(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // #endregion | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .tree_node_ { | ||||||
|  |   padding: 0 6px; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   height: calc(100% - 4px); | ||||||
|  |   border-radius: 2px; | ||||||
|  |   user-select: none; | ||||||
|  | } | ||||||
|  | .nodeActive { | ||||||
|  |   background-color: rgb(172, 223, 243); | ||||||
|  | } | ||||||
|  | ::v-deep() { | ||||||
|  |   .is-current { | ||||||
|  |     .el-tree-node__content { | ||||||
|  |       background-color: rgba($color: #000000, $alpha: 0); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   .el-tree-node__content { | ||||||
|  |     &:hover { | ||||||
|  |       background-color: rgba($color: #000000, $alpha: 0); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @ -1,107 +1,90 @@ | |||||||
| <template> | <template> | ||||||
|   <CustomCard> |   <div class="custom-page"> | ||||||
|     <div> |     <el-row :gutter="20"> | ||||||
|       <el-row :gutter="20"> |       <el-col :span="4"> | ||||||
|         <el-col :span="4"> |         <custom-table-tree title="土地用途分类信息" :data="treeData" :option="treeOption" filter @node-click="handleNodeClick"> | ||||||
|           <el-tree |           <template #default="{ data }"> | ||||||
|             style="max-width: 600px" |             <div :class="{ 'text-primary': data.id == treeSelected.id || data.id == treeSelected.pId }"> | ||||||
|             :data="treeData" |               {{ data.landType }} | ||||||
|             node-key="id" |             </div> | ||||||
|             :default-expanded-keys="[selectTreeNode.id]" |           </template> | ||||||
|             :props="{ value: 'id' }" |         </custom-table-tree> | ||||||
|             :expand-on-click-node="false" |       </el-col> | ||||||
|             @node-click="handleNodeClick" |       <el-col :span="20"> | ||||||
|           > |         <avue-crud | ||||||
|             <template #default="{ data }"> |           ref="crudRef" | ||||||
|               <div class="tree_node_" :class="{ nodeActive: data.id == selectTreeNode.id || data.id == selectTreeNode.pId }"> |           v-model="state.form" | ||||||
|                 {{ data.label }} |           v-model:search="state.query" | ||||||
|               </div> |           v-model:page="state.pageData" | ||||||
|             </template> |           :table-loading="state.loading" | ||||||
|           </el-tree> |           :data="state.data" | ||||||
|         </el-col> |           :option="state.options" | ||||||
|         <el-col :span="20"> |           @refresh-change="refreshChange" | ||||||
|           <avue-crud |           @search-reset="searchChange" | ||||||
|             ref="crudRef" |           @search-change="searchChange" | ||||||
|             v-model="state.form" |           @selection-change="selectionChange" | ||||||
|             v-model:search="state.query" |           @current-change="currentChange" | ||||||
|             v-model:page="state.pageData" |           @size-change="sizeChange" | ||||||
|             :table-loading="state.loading" |           @row-del="rowDel" | ||||||
|             :data="state.data" |           @row-save="rowSave" | ||||||
|             :option="state.options" |           @row-update="rowUpdate" | ||||||
|             @refresh-change="refreshChange" |         > | ||||||
|             @search-reset="searchChange" |           <template #menu-left> | ||||||
|             @search-change="searchChange" |             <el-button type="success" icon="download" @click="onExport">导出</el-button> | ||||||
|             @selection-change="selectionChange" |           </template> | ||||||
|             @current-change="currentChange" |  | ||||||
|             @size-change="sizeChange" |  | ||||||
|             @row-del="rowDel" |  | ||||||
|             @row-save="rowSave" |  | ||||||
|             @row-update="rowUpdate" |  | ||||||
|           > |  | ||||||
|             <template #menu-left> |  | ||||||
|               <el-button type="primary" icon="Plus" @click="onAdd">新增</el-button> |  | ||||||
|               <el-button type="success" icon="download" @click="onExport">导出</el-button> |  | ||||||
|             </template> |  | ||||||
| 
 | 
 | ||||||
|             <template #menu="scope"> |           <template #status="{ row }"> | ||||||
|               <custom-table-operate :actions="state.options.actions" :data="scope" /> |             <el-tag v-if="row.status == 1" type="success">启用</el-tag> | ||||||
|             </template> |             <el-tag v-if="row.status == 0" type="danger">禁用</el-tag> | ||||||
|           </avue-crud> |           </template> | ||||||
|         </el-col> | 
 | ||||||
|       </el-row> |           <template #menu="scope"> | ||||||
|     </div> |             <custom-table-operate :actions="state.options.actions" :data="scope" /> | ||||||
|   </CustomCard> |           </template> | ||||||
|  |         </avue-crud> | ||||||
|  |       </el-col> | ||||||
|  |     </el-row> | ||||||
|  |   </div> | ||||||
| </template> | </template> | ||||||
| <script setup> | <script setup> | ||||||
| import { ref, reactive, onMounted, nextTick } from 'vue'; | import { ref, reactive, onMounted, nextTick, watch } from 'vue'; | ||||||
| import { useApp } from '@/hooks'; | import { useApp } from '@/hooks'; | ||||||
| import { CRUD_OPTIONS } from '@/config'; | import { CRUD_OPTIONS } from '@/config'; | ||||||
| import CustomCard from '@/components/CustomCard.vue'; |  | ||||||
| import { getLandTypeTree, landTypeSave, getLandType, exportLandType, delLandType, editLandType } from '@/apis/baseInfo'; | import { getLandTypeTree, landTypeSave, getLandType, exportLandType, delLandType, editLandType } from '@/apis/baseInfo'; | ||||||
| import { ElMessage } from 'element-plus'; | import { useUserStore } from '@/store/modules/user'; | ||||||
|  | import { isEmpty, flattenTree, setDicLabel, downloadFile } from '@/utils'; | ||||||
| 
 | 
 | ||||||
| const { VITE_APP_BASE_API } = import.meta.env; | const { VITE_APP_BASE_API } = import.meta.env; | ||||||
| const app = useApp(); | const app = useApp(); | ||||||
| 
 | const UserStore = useUserStore(); | ||||||
| /* --------------- data --------------- */ |  | ||||||
| // #region |  | ||||||
| const selectTreeNode = ref({ |  | ||||||
|   id: '', |  | ||||||
|   label: '', |  | ||||||
|   pId: '', |  | ||||||
|   pName: '', |  | ||||||
|   level: 0, |  | ||||||
| }); |  | ||||||
| const landTypesDic = ref([]); |  | ||||||
| const crudRef = ref(null); | const crudRef = ref(null); | ||||||
|  | const treeData = ref([]); | ||||||
|  | const treeOption = ref({ | ||||||
|  |   nodeKey: 'id', | ||||||
|  |   props: { children: 'children', label: 'landType', id: 'id' }, | ||||||
|  | }); | ||||||
|  | const treeSelected = ref({}); | ||||||
|  | const treeDicData = ref([]); | ||||||
| const state = reactive({ | const state = reactive({ | ||||||
|   loading: false, |   loading: false, | ||||||
|   query: { |   query: { | ||||||
|     current: 1, |     current: 1, | ||||||
|     size: 10, |     size: 10, | ||||||
|   }, |   }, | ||||||
|   form: {}, |   form: { | ||||||
|  |     status: 1, | ||||||
|  |   }, | ||||||
|   selection: [], |   selection: [], | ||||||
|   options: { |   options: { | ||||||
|     ...CRUD_OPTIONS, |     ...CRUD_OPTIONS, | ||||||
|     addBtnText: '', |     dialogWidth: 600, | ||||||
|     addBtn: false, |  | ||||||
|     dialogWidth: 680, |  | ||||||
|     selection: false, |     selection: false, | ||||||
|     refreshBtn: false, |  | ||||||
|     column: [ |     column: [ | ||||||
|       { label: '编号', prop: 'id', addDisplay: false, editDisplay: false }, |       { label: '编号', prop: 'id', addDisplay: false, editDisplay: false }, | ||||||
|       { |       { | ||||||
|         label: '用地分类', |         label: '分类名称', | ||||||
|         prop: 'landType', |         prop: 'landType', | ||||||
|         dicData: landTypesDic, |         span: 24, | ||||||
|         // type: 'select', |  | ||||||
|         multiple: true, |  | ||||||
|         span: 23, |  | ||||||
|         props: { |  | ||||||
|           value: 'id', |  | ||||||
|           label: 'childLandCategory', |  | ||||||
|         }, |  | ||||||
|         rules: [ |         rules: [ | ||||||
|           { |           { | ||||||
|             required: true, |             required: true, | ||||||
| @ -109,14 +92,35 @@ const state = reactive({ | |||||||
|             trigger: 'blur', |             trigger: 'blur', | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         label: '用途分类', | ||||||
|  |         prop: 'pid', | ||||||
|  |         display: false, | ||||||
|         render: ({ row }) => { |         render: ({ row }) => { | ||||||
|           return row.landType; |           return setDicLabel(treeDicData.value, row.pid); | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         label: '土地类别', |         label: '用途分类', | ||||||
|         prop: 'landCategory', |         prop: 'pids', | ||||||
|         addDisplay: false, |         type: 'cascader', | ||||||
|  |         checkStrictly: true, | ||||||
|  |         hide: true, | ||||||
|  |         addDisplay: true, | ||||||
|  |         editDisplay: true, | ||||||
|  |         viewDisplay: false, | ||||||
|  |         props: { | ||||||
|  |           label: 'landType', | ||||||
|  |           value: 'id', | ||||||
|  |           children: 'children', | ||||||
|  |         }, | ||||||
|  |         dicUrl: `${VITE_APP_BASE_API}/land-resource/baseInfo/landTree`, | ||||||
|  |         dicHeaders: { | ||||||
|  |           authorization: UserStore.token, | ||||||
|  |         }, | ||||||
|  |         dicFormatter: (res) => [{ id: null, landType: '土地分类', children: res.data }], | ||||||
|  |         span: 24, | ||||||
|         rules: [ |         rules: [ | ||||||
|           { |           { | ||||||
|             required: true, |             required: true, | ||||||
| @ -124,16 +128,22 @@ const state = reactive({ | |||||||
|             trigger: 'blur', |             trigger: 'blur', | ||||||
|           }, |           }, | ||||||
|         ], |         ], | ||||||
|         render: ({ row }) => { |  | ||||||
|           return row.landCategory; |  | ||||||
|         }, |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         label: '状态', |         label: '状态', | ||||||
|         prop: 'status', |         prop: 'status', | ||||||
|         render: ({ row }) => { |         type: 'select', | ||||||
|           return row.status == '1' ? '启用' : '禁用'; |         dicData: [ | ||||||
|         }, |           { | ||||||
|  |             label: '启用', | ||||||
|  |             value: 1, | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             label: '禁用', | ||||||
|  |             value: 0, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |         value: 1, | ||||||
|         addDisplay: false, |         addDisplay: false, | ||||||
|         editDisplay: false, |         editDisplay: false, | ||||||
|       }, |       }, | ||||||
| @ -166,15 +176,35 @@ const state = reactive({ | |||||||
|   currentRow: {}, |   currentRow: {}, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const treeData = ref([]); | watch( | ||||||
|  |   () => treeData.value, | ||||||
|  |   (val) => { | ||||||
|  |     if (!isEmpty(val)) { | ||||||
|  |       const list = flattenTree(val); | ||||||
|  |       treeDicData.value = list.map((item) => { | ||||||
|  |         return { label: item.landType, value: item.id }; | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ); | ||||||
| 
 | 
 | ||||||
| // #endregion | const getLandTree = async () => { | ||||||
|  |   try { | ||||||
|  |     const res = await getLandTypeTree(); | ||||||
|  |     if (res.code == 200) { | ||||||
|  |       treeData.value = [{ id: null, landType: '土地分类', children: res.data }]; | ||||||
|  |     } | ||||||
|  |   } catch (err) { | ||||||
|  |     app.$message.error(err.msg); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | getLandTree(); | ||||||
| 
 | 
 | ||||||
| /* --------------- methods --------------- */ |  | ||||||
| const loadData = () => { | const loadData = () => { | ||||||
|   state.loading = true; |   state.loading = true; | ||||||
|   getLandType({ |   getLandType({ | ||||||
|     pid: selectTreeNode.value.id, |     pid: treeSelected.value?.id ?? null, | ||||||
|     ...state.query, |     ...state.query, | ||||||
|   }) |   }) | ||||||
|     .then((res) => { |     .then((res) => { | ||||||
| @ -197,34 +227,15 @@ const loadData = () => { | |||||||
|     }); |     }); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const handleNodeClick = (data, node) => { | ||||||
|  |   treeSelected.value = data; | ||||||
|  |   loadData(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   getLandTree(); |   loadData(); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| async function getLandTree() { |  | ||||||
|   let res = await getLandTypeTree(); |  | ||||||
|   if (res.code == 200) { |  | ||||||
|     treeData.value = newTree(res.data, 0); |  | ||||||
|     landTypesDic.value = res.data.map((v) => { |  | ||||||
|       return { |  | ||||||
|         id: v.id, |  | ||||||
|         label: v.prentLandType, |  | ||||||
|       }; |  | ||||||
|     }); |  | ||||||
|     console.log('treeData', treeData.value); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| function newTree(arr, i) { |  | ||||||
|   arr.forEach((v) => { |  | ||||||
|     if (i == 0) { |  | ||||||
|       v.label = v.prentLandType; |  | ||||||
|     } else { |  | ||||||
|       v.label = v.childLandCategory; |  | ||||||
|     } |  | ||||||
|     if (v.children) v.children = newTree(v.children, i + 1); |  | ||||||
|   }); |  | ||||||
|   return arr; |  | ||||||
| } |  | ||||||
| // 页数 | // 页数 | ||||||
| const currentChange = (current) => { | const currentChange = (current) => { | ||||||
|   state.query.current = current; |   state.query.current = current; | ||||||
| @ -257,42 +268,8 @@ const selectionChange = (rows) => { | |||||||
|   state.selection = rows; |   state.selection = rows; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const handleNodeClick = (data, node) => { | // 启用 | ||||||
|   const { id } = data; |  | ||||||
|   if (selectTreeNode.value.id != id) { |  | ||||||
|     if (node.level < 2) { |  | ||||||
|       selectTreeNode.value = handleNodeData({ data, level: node.level }); |  | ||||||
|     } else selectTreeNode.value = handleNodeData({ data: node.parent.data, level: node.level }); |  | ||||||
|     loadData(); |  | ||||||
|   } else { |  | ||||||
|     selectTreeNode.value = { id: '', label: '', level: 0 }; |  | ||||||
|     state.data = []; |  | ||||||
|   } |  | ||||||
|   if (selectTreeNode.value.level < 1) { |  | ||||||
|     state.options.dialogWidth = 680; |  | ||||||
|     state.options.column[1].span = 23; |  | ||||||
|     state.options.column[2].addDisplay = false; |  | ||||||
|     delete state.options.column[1].addDisabled; |  | ||||||
|     delete state.options.column[1].value; |  | ||||||
|   } else { |  | ||||||
|     state.options.column[2].addDisplay = true; |  | ||||||
|     state.options.column[1].addDisabled = true; |  | ||||||
|     state.options.column[1].value = selectTreeNode.value.label; |  | ||||||
|     delete state.options.dialogWidth; |  | ||||||
|     delete state.options.column[1].type; |  | ||||||
|     delete state.options.column[1].span; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| function handleNodeData({ data, level }) { |  | ||||||
|   return { |  | ||||||
|     id: data.id, |  | ||||||
|     label: data.label, |  | ||||||
|     level, |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| // 编辑状态 |  | ||||||
| async function rowStatus(row) { | async function rowStatus(row) { | ||||||
|   console.info('操作状态', row.$index); |  | ||||||
|   const { id } = row; |   const { id } = row; | ||||||
|   let status = row.status == '1' ? '0' : '1'; |   let status = row.status == '1' ? '0' : '1'; | ||||||
|   let params = { |   let params = { | ||||||
| @ -301,7 +278,7 @@ async function rowStatus(row) { | |||||||
|   }; |   }; | ||||||
|   let res = await editLandType(params); |   let res = await editLandType(params); | ||||||
|   if (res.code == 200) { |   if (res.code == 200) { | ||||||
|     ElMessage.success('操作成功'); |     app.$message.success('操作成功!'); | ||||||
|     nextTick(() => { |     nextTick(() => { | ||||||
|       state.data[row.$index].status = status; |       state.data[row.$index].status = status; | ||||||
|       loadData(); |       loadData(); | ||||||
| @ -309,118 +286,85 @@ async function rowStatus(row) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // 删除 | ||||||
| async function rowDel(row, done, loading) { | async function rowDel(row, done, loading) { | ||||||
|   let res = await delLandType(row.id); |   let res = await delLandType(row.id); | ||||||
|   if (res.code === 200) { |   if (res.code === 200) { | ||||||
|     app.$message.success('已删除!'); |     app.$message.success('已删除!'); | ||||||
|  |     getLandTree(); | ||||||
|     loadData(); |     loadData(); | ||||||
|     done(); |     done(); | ||||||
|   } |   } | ||||||
|   loading(); |   loading(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const setPid = (row) => { | ||||||
|  |   if (!isEmpty(row.pids)) { | ||||||
|  |     const len = row.pids.length; | ||||||
|  |     row.pid = row?.pids[len - 1] ?? null; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 新增 | ||||||
|  | const rowSave = async (row, done, loading) => { | ||||||
|  |   setPid(row); | ||||||
|  |   landTypeSave(row) | ||||||
|  |     .then((res) => { | ||||||
|  |       if (res.code === 200) { | ||||||
|  |         app.$message.success('添加成功!'); | ||||||
|  |         done(); | ||||||
|  |         getLandTree(); | ||||||
|  |         loadData(); | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     .catch((err) => { | ||||||
|  |       app.$message.error(err.msg); | ||||||
|  |     }) | ||||||
|  |     .finally(() => { | ||||||
|  |       loading(); | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 编辑 | ||||||
| const rowEdit = (row) => { | const rowEdit = (row) => { | ||||||
|   crudRef.value && crudRef.value.rowEdit(row); |   crudRef.value && crudRef.value.rowEdit(row); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const onAdd = () => { |  | ||||||
|   crudRef.value && crudRef.value.rowAdd(); |  | ||||||
| }; |  | ||||||
| async function onExport() { |  | ||||||
|   console.log('test ---'); |  | ||||||
|   if (selectTreeNode.value.level < 1) return ElMessage.warning('请选择用地分类'); |  | ||||||
|   let res = await exportLandType({ |  | ||||||
|     pid: selectTreeNode.value.id, |  | ||||||
|   }); |  | ||||||
|   console.log('edxport', res); |  | ||||||
|   if (res.status == 200) { |  | ||||||
|     let a = document.createElement('a'); |  | ||||||
|     let blob = new Blob([res.data]); |  | ||||||
|     let link = window.URL.createObjectURL(blob); |  | ||||||
|     a.href = link; |  | ||||||
|     a.download = '用地分类.xlsx'; |  | ||||||
|     document.body.appendChild(a); |  | ||||||
|     a.click(); |  | ||||||
|     document.body.removeChild(a); |  | ||||||
|     window.URL.revokeObjectURL(link); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| const rowSave = async (val, done, loading) => { |  | ||||||
|   console.info('新增', val); |  | ||||||
|   let data = {}; |  | ||||||
|   if (selectTreeNode.value.level < 1) { |  | ||||||
|     data.landType = val.landType; |  | ||||||
|   } else { |  | ||||||
|     data = { |  | ||||||
|       pid: selectTreeNode.value.id, |  | ||||||
|       landCategory: val.landCategory, |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|   let res = await landTypeSave(data); |  | ||||||
|   if (res.code == 200) { |  | ||||||
|     ElMessage.success('创建成功'); |  | ||||||
|     getLandTree(); |  | ||||||
|     if (selectTreeNode.value.level > 0) loadData(); |  | ||||||
|     done(); |  | ||||||
|   } |  | ||||||
|   // saveOperationRecord(row) |  | ||||||
|   //   .then((res) => { |  | ||||||
|   //     if (res.code === 200) { |  | ||||||
|   //       app.$message.success('添加成功!'); |  | ||||||
|   //       done(); |  | ||||||
|   //       loadData(); |  | ||||||
|   //     } |  | ||||||
|   //   }) |  | ||||||
|   //   .catch((err) => { |  | ||||||
|   //     app.$message.error(err.msg); |  | ||||||
|   //   }) |  | ||||||
|   //   .finally(() => { |  | ||||||
|   //     loading(); |  | ||||||
|   //   }); |  | ||||||
|   loading(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const rowUpdate = (row, index, done, loading) => { | const rowUpdate = (row, index, done, loading) => { | ||||||
|   console.info('更新'); |   setPid(row); | ||||||
|   console.log('row', row); |   editLandType(row).then((res) => { | ||||||
|   editLandType({ |  | ||||||
|     id: row.id, |  | ||||||
|     landCategory: row.landCategory, |  | ||||||
|   }).then((res) => { |  | ||||||
|     if (res.code === 200) { |     if (res.code === 200) { | ||||||
|       app.$message.success('更新成功!'); |       app.$message.success('更新成功!'); | ||||||
|       loadData(); |       loadData(); | ||||||
|  |       getLandTree(); | ||||||
|       done(); |       done(); | ||||||
|     } |     } | ||||||
|   }); |   }); | ||||||
|   loading(); |   loading(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // #endregion | // 导出 | ||||||
|  | const onExport = () => { | ||||||
|  |   if (isEmpty(state.data)) { | ||||||
|  |     app.$message.error('请先选择用地分类!'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   state.loading = true; | ||||||
|  |   const fileName = '用地分类.xlsx'; | ||||||
|  |   exportLandType({ | ||||||
|  |     pid: treeSelected.value.id, | ||||||
|  |   }) | ||||||
|  |     .then((res) => { | ||||||
|  |       if (res.status === 200) { | ||||||
|  |         downloadFile(res.data, fileName, 'blob'); | ||||||
|  |         app.$message.success('导出成功!'); | ||||||
|  |       } | ||||||
|  |     }) | ||||||
|  |     .catch((err) => { | ||||||
|  |       app.$message.error('导出失败!'); | ||||||
|  |     }) | ||||||
|  |     .finally(() => { | ||||||
|  |       state.loading = false; | ||||||
|  |     }); | ||||||
|  | }; | ||||||
| </script> | </script> | ||||||
| 
 |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .tree_node_ { |  | ||||||
|   padding: 0 6px; |  | ||||||
|   display: flex; |  | ||||||
|   align-items: center; |  | ||||||
|   height: calc(100% - 4px); |  | ||||||
|   border-radius: 2px; |  | ||||||
|   user-select: none; |  | ||||||
| } |  | ||||||
| .nodeActive { |  | ||||||
|   background-color: rgb(172, 223, 243); |  | ||||||
| } |  | ||||||
| ::v-deep() { |  | ||||||
|   .is-current { |  | ||||||
|     .el-tree-node__content { |  | ||||||
|       background-color: rgba($color: #000000, $alpha: 0); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   .el-tree-node__content { |  | ||||||
|     &:hover { |  | ||||||
|       background-color: rgba($color: #000000, $alpha: 0); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user