mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	vue3:【menu】
1. 添加 TODO 修改建议 2. 增加注释 3. 调整一些 import、const 的顺序
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| <template> | ||||
|   <ContentWrap> | ||||
|     <!-- 搜索工作栏 --> | ||||
|     <el-form :model="queryParams" ref="queryForm" :inline="true"> | ||||
|       <el-form-item label="菜单名称" prop="name"> | ||||
|         <el-input v-model="queryParams.name" placeholder="请输入菜单名称" /> | ||||
| @@ -15,17 +16,20 @@ | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|       <el-form-item> | ||||
|         <!-- 操作:搜索 --> | ||||
|         <XButton | ||||
|           type="primary" | ||||
|           preIcon="ep:search" | ||||
|           :title="t('common.query')" | ||||
|           @click="handleQuery()" | ||||
|         /> | ||||
|         <!-- 操作:重置 --> | ||||
|         <XButton preIcon="ep:refresh-right" :title="t('common.reset')" @click="resetQuery()" /> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <vxe-toolbar> | ||||
|       <template #buttons> | ||||
|         <!-- 操作:新增 --> | ||||
|         <XButton | ||||
|           type="primary" | ||||
|           preIcon="ep:zoom-in" | ||||
| @@ -37,6 +41,8 @@ | ||||
|         <XButton title="关闭所有" @click="xTable?.clearTreeExpand()" /> | ||||
|       </template> | ||||
|     </vxe-toolbar> | ||||
|     <!-- 列表 --> | ||||
|     <!-- TODO 星语:是不是也搞成 grid 会好点,后续代码就统一走 grid 风格? --> | ||||
|     <vxe-table | ||||
|       show-overflow | ||||
|       keep-source | ||||
| @@ -73,12 +79,14 @@ | ||||
|       <vxe-column title="创建时间" field="createTime" formatter="formatDate" /> | ||||
|       <vxe-column title="操作" width="200"> | ||||
|         <template #default="{ row }"> | ||||
|           <!-- 操作:修改 --> | ||||
|           <XTextButton | ||||
|             preIcon="ep:edit" | ||||
|             :title="t('action.edit')" | ||||
|             v-hasPermi="['system:menu:update']" | ||||
|             @click="handleUpdate(row)" | ||||
|           /> | ||||
|           <!-- 操作:删除 --> | ||||
|           <XTextButton | ||||
|             preIcon="ep:delete" | ||||
|             :title="t('action.del')" | ||||
| @@ -89,6 +97,7 @@ | ||||
|       </vxe-column> | ||||
|     </vxe-table> | ||||
|   </ContentWrap> | ||||
|   <!-- 添加或修改菜单对话框 --> | ||||
|   <XModal v-model="dialogVisible" id="menuModel" :title="dialogTitle"> | ||||
|     <template #default> | ||||
|       <!-- 对话框(添加 / 修改) --> | ||||
| @@ -227,7 +236,7 @@ | ||||
|       </el-form> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <!-- 操作按钮 --> | ||||
|       <!-- 按钮:保存 --> | ||||
|       <XButton | ||||
|         v-if="['create', 'update'].includes(actionType)" | ||||
|         type="primary" | ||||
| @@ -235,22 +244,17 @@ | ||||
|         @click="submitForm" | ||||
|         :title="t('action.save')" | ||||
|       /> | ||||
|       <!-- 按钮:关闭 --> | ||||
|       <XButton :loading="actionLoading" @click="dialogVisible = false" :title="t('dialog.close')" /> | ||||
|     </template> | ||||
|   </XModal> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import * as MenuApi from '@/api/system/menu' | ||||
| import { MenuVO } from '@/api/system/menu/types' | ||||
| // 全局相关的 import | ||||
| import { onMounted, reactive, ref } from 'vue' | ||||
| import { useI18n } from '@/hooks/web/useI18n' | ||||
| import { useMessage } from '@/hooks/web/useMessage' | ||||
| import { IconSelect } from '@/components/Icon' | ||||
| import { Tooltip } from '@/components/Tooltip' | ||||
| import { required } from '@/utils/formRules.js' | ||||
| import { onMounted, reactive, ref } from 'vue' | ||||
| import { VxeTableInstance } from 'vxe-table' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' | ||||
| // TODO @星语:是不是 'element-plus' 和 '@/components/Tooltip' 和 '@/components/Icon' 全局直接引入 | ||||
| import { | ||||
|   ElRow, | ||||
|   ElCol, | ||||
| @@ -264,17 +268,29 @@ import { | ||||
|   ElRadioGroup, | ||||
|   ElRadioButton | ||||
| } from 'element-plus' | ||||
| import { Tooltip } from '@/components/Tooltip' | ||||
| import { IconSelect } from '@/components/Icon' | ||||
| import { VxeTableInstance } from 'vxe-table' | ||||
| // 业务相关的 import | ||||
| import * as MenuApi from '@/api/system/menu' | ||||
| import { MenuVO } from '@/api/system/menu/types' | ||||
| import { required } from '@/utils/formRules.js' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' | ||||
| import { handleTree } from '@/utils/tree' | ||||
|  | ||||
| const { t } = useI18n() // 国际化 | ||||
| const message = useMessage() | ||||
| const message = useMessage() // 消息弹窗 | ||||
| // 列表相关的变量 | ||||
| const xTable = ref<VxeTableInstance>() | ||||
| const tableLoading = ref(false) | ||||
| const tableData = ref() | ||||
| const actionLoading = ref(false) // 遮罩层 | ||||
| const actionType = ref('') // 操作按钮的类型 | ||||
| // 弹窗相关的变量 | ||||
| const dialogVisible = ref(false) // 是否显示弹出层 | ||||
| const dialogTitle = ref('edit') // 弹出层标题 | ||||
| const statusOption = ref() // 状态选项 | ||||
| const actionType = ref('') // 操作按钮的类型 | ||||
| const actionLoading = ref(false) // 遮罩层 | ||||
| // 新增和修改的表单值 | ||||
| const menuForm = ref<MenuVO>({ | ||||
|   id: 0, | ||||
|   name: '', | ||||
| @@ -290,12 +306,24 @@ const menuForm = ref<MenuVO>({ | ||||
|   keepAlive: true, | ||||
|   createTime: '' | ||||
| }) | ||||
| // 新增和修改的表单校验 | ||||
| const rules = reactive({ | ||||
|   name: [required], | ||||
|   sort: [required], | ||||
|   path: [required], | ||||
|   status: [required] | ||||
| }) | ||||
|  | ||||
| // ========== 下拉框[上级菜单] ========== | ||||
| // 下拉框[上级菜单]的配置项目 | ||||
| // TODO @星语:menuProps 貌似也可以抽到全局? | ||||
| const menuProps = { | ||||
|   checkStrictly: true, | ||||
|   children: 'children', | ||||
|   label: 'name', | ||||
|   value: 'id' | ||||
| } | ||||
| // TODO @星语:Tree 可以是全局的 | ||||
| interface Tree { | ||||
|   id: number | ||||
|   name: string | ||||
| @@ -309,6 +337,7 @@ const getTree = async () => { | ||||
|   menu.children = handleTree(res) | ||||
|   menuOptions.value.push(menu) | ||||
| } | ||||
|  | ||||
| // ========== 查询 ========== | ||||
| const queryParams = reactive({ | ||||
|   name: null, | ||||
| @@ -316,58 +345,47 @@ const queryParams = reactive({ | ||||
| }) | ||||
| const getList = async () => { | ||||
|   tableLoading.value = true | ||||
|   statusOption.value = getIntDictOptions(DICT_TYPE.COMMON_STATUS) | ||||
|   const res = await MenuApi.getMenuListApi(queryParams) | ||||
|   tableData.value = res | ||||
|   tableLoading.value = false | ||||
| } | ||||
| // 设置标题 | ||||
| const setDialogTile = (type: string) => { | ||||
|   dialogTitle.value = t('action.' + type) | ||||
|   actionType.value = type | ||||
|   dialogVisible.value = true | ||||
| } | ||||
| // 新建操作 | ||||
| const handleCreate = () => { | ||||
|   setDialogTile('create') | ||||
| } | ||||
| // 修改操作 | ||||
| const handleUpdate = async (row: MenuVO) => { | ||||
|   // 设置数据 | ||||
|   const res = await MenuApi.getMenuApi(row.id) | ||||
|   console.log(res) | ||||
|   menuForm.value = res | ||||
|   setDialogTile('update') | ||||
| } | ||||
| // 删除操作 | ||||
| const handleDelete = async (row: MenuVO) => { | ||||
|   message.confirm(t('common.delDataMessage'), t('common.confirmTitle')).then(async () => { | ||||
|     await MenuApi.deleteMenuApi(row.id) | ||||
|     message.success(t('common.delSuccess')) | ||||
|     await getList() | ||||
|   }) | ||||
| } | ||||
| // 表单校验 | ||||
| const rules = reactive({ | ||||
|   name: [required], | ||||
|   sort: [required], | ||||
|   path: [required], | ||||
|   status: [required] | ||||
| }) | ||||
|  | ||||
| // 查询操作 | ||||
| const handleQuery = async () => { | ||||
|   await getList() | ||||
| } | ||||
|  | ||||
| // 重置操作 | ||||
| const resetQuery = async () => { | ||||
|   queryParams.name = null | ||||
|   queryParams.status = null | ||||
|   await getList() | ||||
| } | ||||
| // 保存操作 | ||||
| const isExternal = (path: string) => { | ||||
|   return /^(https?:|mailto:|tel:)/.test(path) | ||||
|  | ||||
| // ========== 新增/修改 ========== | ||||
|  | ||||
| // 设置标题 | ||||
| const setDialogTile = (type: string) => { | ||||
|   dialogTitle.value = t('action.' + type) | ||||
|   actionType.value = type | ||||
|   dialogVisible.value = true | ||||
| } | ||||
|  | ||||
| // 新建操作 | ||||
| const handleCreate = () => { | ||||
|   setDialogTile('create') | ||||
|   // TODO @星语:重置表单 | ||||
| } | ||||
|  | ||||
| // 修改操作 | ||||
| const handleUpdate = async (row: MenuVO) => { | ||||
|   setDialogTile('update') | ||||
|   // 设置数据 | ||||
|   const res = await MenuApi.getMenuApi(row.id) | ||||
|   menuForm.value = res | ||||
| } | ||||
|  | ||||
| // 提交新增/修改的表单 | ||||
| const submitForm = async () => { | ||||
|   actionLoading.value = true | ||||
|   // 提交请求 | ||||
| @@ -400,8 +418,26 @@ const submitForm = async () => { | ||||
|     actionLoading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 判断 path 是不是外部的 HTTP 等链接 | ||||
| const isExternal = (path: string) => { | ||||
|   return /^(https?:|mailto:|tel:)/.test(path) | ||||
| } | ||||
|  | ||||
| // ========== 删除 ========== | ||||
| // 删除操作 | ||||
| const handleDelete = async (row: MenuVO) => { | ||||
|   message.confirm(t('common.delDataMessage'), t('common.confirmTitle')).then(async () => { | ||||
|     await MenuApi.deleteMenuApi(row.id) | ||||
|     message.success(t('common.delSuccess')) | ||||
|     await getList() | ||||
|   }) | ||||
| } | ||||
|  | ||||
| // ========== 初始化 ========== | ||||
| onMounted(async () => { | ||||
|   await getList() | ||||
|   // TODO @星语:这个告警解决下;是不是改成新增和修改点击的时候,去加载下好一点哈? | ||||
|   getTree() | ||||
| }) | ||||
| </script> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV