当前位置: 首页 > news >正文

JavaWeb(前端实战)

页面布局:

准备工作:

启动准备好的基础工程项目

访问 http://localhost:5173

使用 ElementPlus 中提供的 container 容器实现页面原型的布局:

Container 布局容器,用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>:外层容器

<el-header>:顶栏容器

<el-aside>:侧边栏容器

<el-main>:主要区域容器

<el-footer>:底栏容器

<el-container> 子元素中包含 <el-header> <el-footer> 时,全部子元素会垂直上下排列, 否则会水平左右排列

左侧菜单布局:

在 ElementPlus 中对应的菜单组件:

修改后导入到 views/layout/index.vue 的侧边栏区域 <elaside> ... </el-aside>

<el-menu><!-- 首页菜单(一级菜单项,无子菜单) --><el-menu-item index="/index"> <!-- index:菜单项唯一标识,通常对应路由路径 --><el-icon><Promotion /></el-icon> 首页 <!-- 图标 --></el-menu-item><!-- 班级学员管理(二级菜单容器,包含子菜单) --><el-sub-menu index="/manage"> <!-- index:子菜单容器唯一标识 --><template #title> <!-- 子菜单标题区域(展开/折叠的触发部分) --><el-icon><Menu /></el-icon> 班级学员管理 </template><!-- 班级管理子菜单 --><el-menu-item index="/clazz"><el-icon><HomeFilled /></el-icon>班级管理 </el-menu-item><!-- 学员管理子菜单 --><el-menu-item index="/stu"><el-icon><UserFilled /></el-icon>学员管理 </el-menu-item></el-sub-menu><!-- 系统信息管理(二级菜单容器) --><el-sub-menu index="/system"><template #title><el-icon><Tools /></el-icon>系统信息管理 </template><!-- 部门管理子菜单 --><el-menu-item index="/dept"><el-icon><HelpFilled /></el-icon>部门管理 </el-menu-item><!-- 员工管理子菜单 --><el-menu-item index="/emp"><el-icon><Avatar /></el-icon>员工管理 </el-menu-item></el-sub-menu><!-- 数据统计管理(二级菜单容器) --><el-sub-menu index="/report"><template #title><el-icon><Histogram /></el-icon>数据统计管理 </template><!-- 员工信息统计子菜单 --><el-menu-item index="/empReport"><el-icon><InfoFilled /></el-icon>员工信息统计 </el-menu-item><!-- 学员信息统计子菜单 --><el-menu-item index="/stuReport"><el-icon><Share /></el-icon>学员信息统计 </el-menu-item><!-- 日志信息统计子菜单 --><el-menu-item index="/log"><el-icon><Document /></el-icon>日志信息统计 </el-menu-item></el-sub-menu>
</el-menu>

此时点击左侧的菜单还不能使右侧的主区域动态变化,需要通过 VueRouter 解决

VueRouter:

介绍:

Vue Router:Vue的官方路由,为Vue提供富有表现力、可配置的、方便的路由

Vue 中的路由,主要定义的是路径与组件之间的对应关系

VueRouter 主要由以下三个部分组成:

VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件

<router-link>:请求链接组件,浏览器会解析成<a>

<router-view>:动态视图组件,用来渲染展示与路由路径对应的组件

基础路由配置:

在 views/layout/index.vue 中调整代码:

在左侧菜单栏的 <eld-menu> 标签上添加 rounter 属性,让 ElementPlus 的 <el-menu> 组件自动根据路由来激活对应的菜单项

使用 <router-view> 组件来渲染根据路由动态变化的内容

让每个 <el-menu-item> 的 index 属性值与要导航到的路径相匹配

<script setup></script><template><div class="common-layout"><el-container><!-- Header 区域 --><el-header class="header"><span class="title">Tlias智能学习辅助系统</span><span class="right_tool"><a href=""><el-icon><EditPen /></el-icon> 修改密码 &nbsp;&nbsp;&nbsp; |  &nbsp;&nbsp;&nbsp;</a><a href=""><el-icon><SwitchButton /></el-icon> 退出登录</a></span></el-header><el-container><!-- 左侧菜单 --><el-aside width="200px" class="aside"><el-menu router><!-- 首页菜单(一级菜单项,无子菜单) --><el-menu-item index="/index"> <!-- index:菜单项唯一标识,通常对应路由路径 --><el-icon><Promotion /></el-icon> 首页 <!-- 图标 --></el-menu-item><!-- 班级学员管理(二级菜单容器,包含子菜单) --><el-sub-menu index="/manage"> <!-- index:子菜单容器唯一标识 --><template #title> <!-- 子菜单标题区域(展开/折叠的触发部分) --><el-icon><Menu /></el-icon> 班级学员管理 </template><!-- 班级管理子菜单 --><el-menu-item index="/clazz"><el-icon><HomeFilled /></el-icon>班级管理 </el-menu-item><!-- 学员管理子菜单 --><el-menu-item index="/stu"><el-icon><UserFilled /></el-icon>学员管理 </el-menu-item></el-sub-menu><!-- 系统信息管理(二级菜单容器) --><el-sub-menu index="/system"><template #title><el-icon><Tools /></el-icon>系统信息管理 </template><!-- 部门管理子菜单 --><el-menu-item index="/dept"><el-icon><HelpFilled /></el-icon>部门管理 </el-menu-item><!-- 员工管理子菜单 --><el-menu-item index="/emp"><el-icon><Avatar /></el-icon>员工管理 </el-menu-item></el-sub-menu><!-- 数据统计管理(二级菜单容器) --><el-sub-menu index="/report"><template #title><el-icon><Histogram /></el-icon>数据统计管理 </template><!-- 员工信息统计子菜单 --><el-menu-item index="/empReport"><el-icon><InfoFilled /></el-icon>员工信息统计 </el-menu-item><!-- 学员信息统计子菜单 --><el-menu-item index="/stuReport"><el-icon><Share /></el-icon>学员信息统计 </el-menu-item><!-- 日志信息统计子菜单 --><el-menu-item index="/log"><el-icon><Document /></el-icon>日志信息统计 </el-menu-item></el-sub-menu></el-menu></el-aside><el-main><router-view></router-view></el-main></el-container></el-container></div>
</template><style scoped>
.header {background-image: linear-gradient(to right, #00547d, #007fa4, #00aaa0, #00d072, #a8eb12);
}.title {color: white;font-size: 40px;font-family: 楷体;line-height: 60px;font-weight: bolder;
}.right_tool{float: right;line-height: 60px;
}a {color: white;text-decoration: none;
}.aside {width: 220px;border-right: 1px solid #ccc;height: 730px;
}
</style>

在 router/index.js 中配置请求路径与组件之间的关系:

//从 vue-router 库中导入创建路由的核心工具
//createRouter:用于创建路由实例的函数
//createWebHistory:用于创建 HTML5 History 模式的路由
import { createRouter, createWebHistory } from 'vue-router';//导入各个页面组件(.vue 文件)
//@ 是路径别名,通常指向项目的 src 目录
import IndexView from '@/views/index/index.vue'; //首页组件
import ClazzView from '@/views/clazz/index.vue'; //班级管理页面组件
import StuView from '@/views/stu/index.vue'; //学生管理页面组件
import DeptView from '@/views/dept/index.vue'; //部门管理页面组件
import EmpView from '@/views/emp/index.vue'; //员工管理页面组件
import EmpReportView from '@/views/report/emp/index.vue'; //员工报表页面组件
import StuReportView from '@/views/report/stu/index.vue'; //学生报表页面组件
import LogView from '@/views/log/index.vue'; //日志管理页面组件
import LoginView from '@/views/login/index.vue'; //登录页面组件//定义路由规则数组
//每个对象表示一条路由:path(URL路径)对应 component(页面组件)
const routes = [{ path: '/index', component: IndexView },//访问 /index 时,渲染首页组件{ path: '/clazz', component: ClazzView },//访问 /clazz 时,渲染班级管理组件{ path: '/stu', component: StuView },{ path: '/dept', component: DeptView }, { path: '/emp', component: EmpView }, { path: '/empReport', component: EmpReportView },{ path: '/stuReport', component: StuReportView }, { path: '/log', component: LogView }, { path: '/login', component: LoginView }, 
];//创建路由实例
const router = createRouter({history: createWebHistory(),//配置路由模式为 HTML5 Historyroutes,//传入上面定义的路由规则数组
});//导出路由实例,供全局使用(通常在 main.js 中引入并挂载到 Vue 应用)
export default router;

完善路由配置:

问题:访问 /login 路径时,登录页面错误的在 layout 页面中嵌套展示:

在 router/index.js 中做如下优化:

//从 vue-router 库中导入创建路由的核心工具
//createRouter:用于创建路由实例的函数
//createWebHistory:用于创建 HTML5 History 模式的路由
import { createRouter, createWebHistory } from 'vue-router';//导入各个页面组件(.vue 文件)
//@ 是路径别名,通常指向项目的 src 目录
import IndexView from '@/views/index/index.vue'
import ClazzView from '@/views/clazz/index.vue'
import DeptView from '@/views/dept/index.vue'
import EmpView from '@/views/emp/index.vue'
import LogView from '@/views/log/index.vue'
import StuView from '@/views/stu/index.vue'
import EmpReportView from '@/views/report/emp/index.vue'
import StuReportView from '@/views/report/stu/index.vue'
import LayoutView from '@/views/layout/index.vue'
import LoginView from '@/views/login/index.vue'//创建路由实例
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),//创建 HTML5 History 模式的路由//定义路由规则(routes 数组),数组中的每个对象都是一条路由规则routes:[//路由规则一:父路由(用于布局){path:'/',//匹配网站的根路径(例如:http://localhost:5173/)name:'',// 路由名称(可选),父路由通常可以省略或留空component:LayoutView,// 指定根路径对应的组件是 LayoutView(布局组件)redirect:'/index',//重定向规则,当用户访问根路径 '/' 时,自动将其导航到 '/index' 路径children:[//嵌套路由的组件会渲染到父路由组件(LayoutView)内部的 <router-view /> 标签位置{path: 'index', name: 'index', component: IndexView},{path: 'clazz', name: 'clazz', component: ClazzView},{path: 'stu', name: 'stu', component: StuView},{path: 'dept', name: 'dept', component: DeptView},{path: 'emp', name: 'emp', component: EmpView},{path: 'log', name: 'log', component: LogView},{path: 'empReport', name: 'empReport', component: EmpReportView},{path: 'stuReport', name: 'stuReport', component: StuReportView},],},//路由规则二:登录页面路由(独立路由){path:'/login',name:'login',component:LoginView}]
});//导出路由实例,供全局使用(通常在 main.js 中引入并挂载到 Vue 应用)
export default router;

App.vue:

<script setup></script><template><router-view></router-view>
</template><style scoped></style>

具体的执行访问流程:

部门管理:

部门列表:

基础布局:

部门管理组件 src/views/dept/index.vue 的页面布局:

<script setup>
import { ref } from 'vue';
//示例数据
const deptList= ref([{ id: 1, name: '学工部', createTime: '2024-09-01T23:06:29', updateTime: '2024-09-01T23:06:29' },{ id: 2, name: '教研部', createTime: '2024-09-01T23:06:29', updateTime: '2024-09-01T23:06:29' }
]);
//编辑部门 - 根据ID查询回显数据
const handleEdit = (id) => {console.log(`Edit item with ID ${id}`);//实现编辑功能
};
//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);//实现删除功能
};
</script><template><h1>部门管理</h1><!-- 按钮靠页面右侧显示 --><el-button type="primary" @click="handleEdit" style="float: right;"> + 新增部门</el-button> <br><br><el-table :data="deptList" border style="width: 100%;"><el-table-column type="index" label="序号" width="100" align="center"/><el-table-column prop="name" label="部门名称" width="300" align="center"/><el-table-column prop="updateTime" label="最后修改时间" width="300" align="center"/><el-table-column fixed="right" label="操作" align="center"><template #default="scope"><el-button size="small" @click="handleEdit(scope.row.id)">修改</el-button><el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button></template></el-table-column></el-table>
</template><style scoped></style>

加载数据:

基于 axios 发送异步请求,动态获取数据

修改 src/views/dept/index.vue 中代码,在页面加载完成发送异步请求(https://apifoxmock.com/m1/3128855-1224313-default/depts):

<script setup>
import { ref,onMounted } from 'vue';
import axios from 'axios'
//声明列表展示数据
let deptList= ref([])
//动态加载数据-查询部门
const queryAll = async () => {const result = await axios.get('https://apifoxmock.com/m1/3128855-1224313-default/depts')deptList.value = result.data.data
}
//钩子函数
onMounted(() => {queryAll()
})
//编辑部门 - 根据ID查询回显数据
const handleEdit = (id) => {console.log(`Edit item with ID ${id}`);//实现编辑功能
};
//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);//实现删除功能
};
</script><template><h1>部门管理</h1><!-- 按钮靠页面右侧显示 --><el-button type="primary" @click="handleEdit" style="float: right;"> + 新增部门</el-button> <br><br><el-table :data="deptList" border style="width: 100%;"><el-table-column type="index" label="序号" width="100" align="center"/><el-table-column prop="name" label="部门名称" width="300" align="center"/><el-table-column prop="updateTime" label="最后修改时间" width="300" align="center"/><el-table-column fixed="right" label="操作" align="center"><template #default="scope"><el-button size="small" @click="handleEdit(scope.row.id)">修改</el-button><el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button></template></el-table-column></el-table>
</template><style scoped></style>

程序优化:

定义一个请求处理的工具类 src/utils/request.js 对 axios 进行封装:

import axios from 'axios'
//创建axios实例对象
const request = axios.create({baseURL: '/api',//接口请求的基础路径,所有通过这个实例发起的请求,其 URL 都会自动拼接上这个基础路径timeout: 600000//请求超时时间,axios 会自动中断请求并抛出错误,单位为毫秒
})
//axios的响应 response 拦截器
//拦截 Axios 的响应结果,对成功/失败的响应做统一处理
request.interceptors.response.use((response) => { //成功回调//response 对象包含了完整的响应信息,包括状态码、响应头、响应体等//response.data 是后端返回的实际数据体(通常是 JSON 对象)return response.data},(error) => { //失败回调//error 对象包含了错误信息return Promise.reject(error)}
)
//将配置好的 axios 实例导出
export default request

将与服务端进行异步交互的逻辑封装到 src/api/dept.js 中:

import request from "@/utils/request"
//列表查询
export const queryAllApi = () => {request.get('/depts')
}

修改 src/views/dept/index.vue 中代码:

<script setup>
import { ref,onMounted } from 'vue';
import {queryAllApi} from '@/api/dept'
//声明列表展示数据
let deptList= ref([])
//动态加载数据-查询部门
const queryAll = async () => {const result = await queryAllApi()deptList.value = result.data
}
//钩子函数
onMounted(() => {queryAll()
})
//编辑部门 - 根据ID查询回显数据
const handleEdit = (id) => {console.log(`Edit item with ID ${id}`);//实现编辑功能
};
//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);//实现删除功能
};
</script>

在 vite.config.js 中配置前端请求服务器的信息:

import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},server: {proxy: {//将所有以 /api 开头的请求代理到 http://localhost:8080'/api': {//目标后端服务器的基础 URLtarget: 'http://localhost:8080',//改变请求源地址为目标服务器地址changeOrigin: true,//重写路径,将 /api 前缀替换为空字符串,确保后端接口路径正确rewrite: (path) => path.replace(/^\/api/, '')}}}
})

新增部门:

功能实现:

新增部门和编辑部门可以同用一个 Dialog 对话框,在这个对话框中包括 Dialog 对话框组件和 Form 表单组件

在 src/views/dept/index.vue 中完成页面布局,编写交互逻辑完成数据绑定:

<script setup>
import { ref,onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { queryAllApi,addDeptApi } from '@/api/dept'
//声明列表展示数据
let deptList= ref([])//响应式数组
//动态加载数据-查询部门
const queryAll = async () => {//(async关键字)异步函数const result = await queryAllApi()deptList.value = result.data
}
//钩子函数
//页面加载时自动获取部门列表
onMounted(() => {queryAll()//将 queryAll 函数注册到 onMounted 生命周期钩子中
})
//编辑部门 - 根据ID查询回显数据
const handleEdit = (id) => {console.log(`Edit item with ID ${id}`);//实现编辑功能
};
//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);//实现删除功能
};
const formTitle = ref('')//用于动态设置对话框的标题
//新增部门
const add = () => {formTitle.value = '新增部门'showDialog.value = true//显示对话框deptForm.value = {name:''}//重置表单数据
}
//新增部门对话框的状态
const showDialog = ref(false)//响应式布尔值
//表单数据
const deptForm = ref({name:''})//响应式对象,name属性为空字符串
//表单验证规则
const formRules = ref({//响应式对象name:[{ required: true/*表示必填项*/, message: '请输入部门名称'/*验证失败时的提示信息*/, trigger: 'blur'/*输入框失去焦点时触发验证*/ },{ min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }]
})
//表单引用
const deptFormRef = ref(null)//响应式引用对象
//重置表单
const resetForm = () => {deptFormRef.value.resetFields()
}
//提交表单
const save = async () => {await deptFormRef.value.validate(async valid => {//validate 方法会根据 formRules 对表单进行校验if(!valid) return//提交表单const result = await addDeptApi(deptForm.value)if(result.code){ElMessage.success('操作成功')//关闭对话框showDialog.value = false//重置表单resetForm()//重新加载数据queryAll()}else{ElMessage.error(result.msg)}})
}
</script><template><h1>部门管理</h1><!-- 按钮靠页面右侧显示 --><el-button type="primary" @click="add()" style="float:right"> + 新增部门</el-button> <br><br><!-- 表格 --><el-table :data="deptList" border style="width: 100%;"><el-table-column type="index" label="序号" width="100" align="center"/><el-table-column prop="name" label="部门名称" width="300" align="center"/><el-table-column prop="updateTime" label="最后修改时间" width="300" align="center"/><el-table-column fixed="right" label="操作" align="center"><template #default="scope"><el-button size="small" @click="handleEdit(scope.row.id)">修改</el-button><el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button></template></el-table-column></el-table><!-- 新增部门对话框 --><el-dialog v-model="showDialog":title="formTitle" width="30%" @close="resetForm"><el-form :model="deptForm":rules="formRules" ref="deptFormRef"><el-form-item label="部门名称" prop="name" label-width="80px"><el-input v-model="deptForm.name" autocomplete="off"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="showDialog = false">取消</el-button><el-button type="primary" @click="save">确定</el-button></div></template></el-dialog></template><style scoped></style>

修改 src/api/dept.js 中代码:

//导入配置好的 request 工具
import request from "@/utils/request"
//列表查询
export const queryAllApi = () => request.get('/depts')
//添加部门
export const addDeptApi = (data) => request.post('/depts',data)

表单效验:

Form 组件提供了表单验证的功能,只需为 rules 属性传入约定的验证规则,并将 form-Itemprop 属性设置为需要验证的特殊键值即可

操作步骤:

通过 ref 属性注册元素的引用;定义表单校验规则,通过 rules 属性与表单绑定,并通过 prop 属性绑定对应的表单项;表单提交时,校验表单,校验通过,则允许提交表单

修改部门:

交互逻辑:

点击 编辑 按钮,根据 ID 进行查询,弹出对话框,完成页面回显展示(查询回显)

点击 确定 按钮,保存修改后的数据,完成数据更新操作(保存修改)

查询回显:

在 src/api/dept.js 中定义根据 ID 查询的请求:

//根据ID查询
export const queryInfoApi = (id) => request.get(`/depts/${id}`)

在 src/views/dept/index.vue 中添加根据 ID 查询回显的逻辑为修改按钮绑定事件:

<el-button size="small" @click="handleEdit(scope.row.id)">修改</el-button>

<script> </script> 添加 JS 逻辑:

//编辑部门 - 根据ID查询回显数据
const handleEdit = async (id) => {console.log(`Edit item with ID ${id}`);//控制台打印formTitle.value = '修改部门'//对话框标题showDialog.value = true//显示对话框deptForm.value = {name:''}//重置表单数据const result = await queryInfoApi(id)//根据ID查询部门信息if(result.code){//successdeptForm.value = result.data//将查询到的部门名称赋值给表单的name属性}
};

保存修改:

由于新增部门和修改部门使用的是同一个 Dialog 对话框,当点击 “确定” 按钮的时候,有可能执行的是新增操作,也有可能是修改操作,只需根据 deptForm 对象的 id 属性值来判断即可

在 src/api/dept.js 中定义修改部门的请求:

//修改部门
export const updateDeptApi = (data) => request.put('/depts', data)

在 src/views/dept/index.vue 中修改 save 函数的逻辑:

//提交表单
const save = async () => {await deptFormRef.value.validate(async valid => {//validate 方法会根据 formRules 对表单进行校验if(!valid) return//提交表单let result = null;if(deptForm.value.id){result = await updateDeptApi(deptForm.value)}else{result = await addDeptApi(deptForm.value)}if(result.code){ElMessage.success('操作成功')//关闭对话框showDialog.value = false//重置表单resetForm()//重新加载数据queryAll()}else{ElMessage.error(result.msg)}})
}

删除部门:

点击删除按钮,需要删除当前这条数据,删除完成之后,刷新页面,展示出最新的数据

由于删除是一个比较危险的操作,为避免误操作,通常会在点击删除之后,弹出确认框进行确认

Element 组件:ElMessageBox 消息弹出框组件

具体操作步骤:

在 src/api/dept.js 中定义删除部门的请求:

//删除部门
export const deleteDeptApi = (id) => request.delete(`/depts?id=${id}`)

在 src/views/dept/index.vue 中为 删除 按钮绑定事件:

 <el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button>

在 src/views/dept/index.vue 编写根据 ID 删除数据的函数:

//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);ElMessageBox.confirm('此操作将永久删除该部门,是否继续','提示',{/*提示信息 对话框标题 配置对象*/confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async () => {//删除部门const result = await deleteDeptApi(id)if(result.code){ElMessage.success('删除成功')queryAll()}})
};

完整代码:

<script setup>
import { ref,onMounted } from 'vue';
import { ElMessage,ElMessageBox } from 'element-plus';
import { queryAllApi,addDeptApi,queryInfoApi,updateDeptApi,deleteDeptApi } from '@/api/dept'
//声明列表展示数据
let deptList= ref([])//响应式数组
//动态加载数据-查询部门
const queryAll = async () => {//(async关键字)异步函数const result = await queryAllApi()deptList.value = result.data
}
//钩子函数
//页面加载时自动获取部门列表
onMounted(() => {queryAll()//将 queryAll 函数注册到 onMounted 生命周期钩子中
})
//编辑部门 - 根据ID查询回显数据
const handleEdit = async (id) => {console.log(`Edit item with ID ${id}`);//控制台打印formTitle.value = '修改部门'//对话框标题showDialog.value = true//显示对话框deptForm.value = {name:''}//重置表单数据const result = await queryInfoApi(id)//根据ID查询部门信息if(result.code){//successdeptForm.value = result.data//将查询到的部门名称赋值给表单的name属性}
};
//删除部门 - 根据ID删除部门
const handleDelete = (id) => {console.log(`Delete item with ID ${id}`);ElMessageBox.confirm('此操作将永久删除该部门,是否继续','提示',{/*提示信息 对话框标题 配置对象*/confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async () => {//删除部门const result = await deleteDeptApi(id)if(result.code){ElMessage.success('删除成功')queryAll()}})
};
const formTitle = ref('')//用于动态设置对话框的标题
//新增部门
const add = () => {formTitle.value = '新增部门'showDialog.value = true//显示对话框deptForm.value = {name:''}//重置表单数据
}
//新增部门对话框的状态
const showDialog = ref(false)//响应式布尔值
//表单数据
const deptForm = ref({name:''})//响应式对象,name属性为空字符串
//表单验证规则
const formRules = ref({//响应式对象name:[{ required: true/*表示必填项*/, message: '请输入部门名称'/*验证失败时的提示信息*/, trigger: 'blur'/*输入框失去焦点时触发验证*/ },{ min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }]
})
//表单引用
const deptFormRef = ref(null)//响应式引用对象
//重置表单
const resetForm = () => {deptFormRef.value.resetFields()
}
//提交表单
const save = async () => {await deptFormRef.value.validate(async valid => {//validate 方法会根据 formRules 对表单进行校验if(!valid) return//提交表单let result = null;if(deptForm.value.id){result = await updateDeptApi(deptForm.value)}else{result = await addDeptApi(deptForm.value)}if(result.code){ElMessage.success('操作成功')//关闭对话框showDialog.value = false//重置表单resetForm()//重新加载数据queryAll()}else{ElMessage.error(result.msg)}})
}
</script><template><h1>部门管理</h1><!-- 按钮靠页面右侧显示 --><el-button type="primary" @click="add()" style="float:right"> + 新增部门</el-button> <br><br><!-- 表格 --><el-table :data="deptList" border style="width: 100%;"><el-table-column type="index" label="序号" width="100" align="center"/><el-table-column prop="name" label="部门名称" width="300" align="center"/><el-table-column prop="updateTime" label="最后修改时间" width="300" align="center"/><el-table-column fixed="right" label="操作" align="center"><template #default="scope"><el-button size="small" @click="handleEdit(scope.row.id)">修改</el-button><el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button></template></el-table-column></el-table><!-- 新增部门对话框 --><el-dialog v-model="showDialog":title="formTitle" width="30%" @close="resetForm"><el-form :model="deptForm":rules="formRules" ref="deptFormRef"><el-form-item label="部门名称" prop="name" label-width="80px"><el-input v-model="deptForm.name" autocomplete="off"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="showDialog = false">取消</el-button><el-button type="primary" @click="save">确定</el-button></div></template></el-dialog></template><style scoped></style>

http://www.dtcms.com/a/614946.html

相关文章:

  • 新网站多久收录内页4399任天堂
  • 买网站做网站设计怎么学
  • Qt Core 模块中的函数详解
  • 网站备案检验单网站搭建免费
  • 设置网站模板免费的app软件下载安装
  • 滁州 来安县建设局网站建设局是做什么的
  • 异常的介绍
  • [LivePortrait] LivePortraitPipeline
  • 织梦wap网站模版wordpress的注册文件在哪儿
  • 汝州住房和城乡建设局新网站网站编辑做多久可以升职
  • 做淘宝网站宝安中心区
  • 36_FastMCP 2.x 中文文档之FastMCP客户端高级功能:接收并处理服务端进度报告详解
  • 手机网站 制作技术百度seo官网
  • 上海个人网站建做的最好的紫砂网站
  • 前端工程化面试题
  • 武安市网站建设费用成都网站建设_创新互联
  • 关于 mariadb开源数据库忘记密码 的解决方法
  • [优选算法专题七.分治-快排 ——NO.42~44 颜色分类、排序数组、数组中的第K个最大元素]
  • 2025云安全渗透:如何拿下一台云主机-附加复现实验加原理(全网独一份小白必看)
  • 网站优化公司收费我要注册公司怎么办
  • 傻瓜式网站制作互动网站的核心技术
  • 拓扑排序-java实现
  • 有什么做海报网站ps网页设计作品欣赏
  • 外贸网站建设收款通道崇左网站建设公司
  • 学校部门网站建设WordPress如何添加cnzz
  • ThinkPad 电脑热键修复(静音常亮导致电脑无声音 )
  • 网站数据库怎么做同步吗学院网站模板
  • 宽带技术网网站做亚马逊运营要看哪些网站
  • 淘宝网站怎么做特价做商城网站的公司推荐
  • C语言在线编译 | 高效调试与学习平台