美文网首页SpringBootspring boot
使用Ajax技术开发简易版人事管理系统(了解)

使用Ajax技术开发简易版人事管理系统(了解)

作者: 测试老杨 | 来源:发表于2019-05-29 17:06 被阅读212次

    项目介绍

    所有功能使用Ajax技术,浏览器发送Ajax请求给后台,后台返回json格式的数据,JS回调函数对返回的JSON数据进行处理。针对浏览器禁用cookies的情况,通过URL地址重写技术将sessionId放到URL地址里面。用户的登录状态以及权限使用session缓存。

    后台开发使用的框架:Spring + Spring MVC + MyBatis
    前端开发使用的框架:BootStrap + EasyUI
    服务器软件:tomcat
    数据库软件:mysql
    开发工具:eclipse + maven

    主要功能:
    权限管理(已完成)部门管理(已完成),员工管理(未完成),考勤管理(未完成),薪资管理(未完成),我的考勤(未完成),我的薪资(未完成)

    主要角色:
    管理员,人事专员,考勤员,薪资福利专员,普通员工


    image.png
    image.png

    部门管理功能实现的思路

    1、从github上下载某开源项目的代码
    2、执行数据初始化的脚本(建库和建表)
    3、创建部门表
    4、界面配置部门管理功能的URL地址
    5、给管理员角色分配部门管理功能的权限
    6、设计部门模板类Dept(可以通过工具自动生成)
    7、设计部门分页查询工具类DeptExample(可以通过工具自动生成)
    8、设计部门表单类DeptForm
    9、设计表单实体转换类DeptConvert
    10、开发DeptService接口
    11、开发DeptService接口的实现类
    12、开发数据库访问接口DeptMapper(能够对部门表进行增删改查)
    13、设计部门表映射文件DeptMapper.xml(可以通过工具自动生成)
    14、开发控制器DeptController(处理浏览器发送过来的请求)
    15、控制器DeptController里面会调用DeptService
    16、DeptService里面会调用数据库接口DeptMapper
    17、设计部门列表页面的JSP代码
    18、设计部门表单页面的JSP代码
    19、设计部门管理功能的JS代码(发送Ajax请求和回调函数)

    从github下载某开源项目的源代码

    image.png

    创建部门表

    CREATE TABLE `dept` (
      `id` bigint(19) NOT NULL AUTO_INCREMENT COMMENT '主键id',
      `name` varchar(64) NOT NULL COMMENT '部门名',
      `address` varchar(100) DEFAULT NULL COMMENT '地址',
      `code` varchar(64) NOT NULL COMMENT '编号',
      `icon` varchar(32) DEFAULT NULL COMMENT '图标',
      `pid` bigint(19) DEFAULT NULL COMMENT '父级主键',
      `is_leaf` tinyint(1) DEFAULT '0' COMMENT '叶子节点',
      `seq` tinyint(2) NOT NULL DEFAULT '0' COMMENT '排序',
      `del_flag` tinyint(1) DEFAULT '0' COMMENT '删除标记',
      `update_time` datetime DEFAULT NULL COMMENT '更新时间',
      `create_time` datetime NOT NULL COMMENT '创建时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8 COMMENT='部门表';
    

    配置部门管理功能的URL地址

    image.png

    给系统管理员角色分配部门管理的权限

    image.png

    开发控制器DeptController(处理浏览器发送过来的请求)

    代码如下:

    package com.testin.hr.web;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.testin.hr.service.DeptService;
    import com.testin.hr.web.form.DeptForm;
    
    /**
     * 
     * @author yangzc
     *
     */
    @Controller
    public class DeptController {
    
        @Autowired
        DeptService deptService;
    
        @RequestMapping(value = "/hr/depts/ui/{ui}", method = RequestMethod.GET)
        public String ui(@PathVariable("ui") String ui) {
            return "hr/dept/dept-" + ui;
        }
    
        @RequestMapping(value = "/hr/depts", method = RequestMethod.POST)
        @ResponseBody
        public Object save(DeptForm form) {
            return deptService.saveOrUpdate(form);
        }
    
        @RequestMapping(value = "/hr/depts/{ids}", method = RequestMethod.DELETE)
        @ResponseBody
        public Object delete(@PathVariable("ids") String ids) {
            return deptService.deleteByIds(ids);
        }
    
        @RequestMapping(value = "/hr/depts", method = RequestMethod.GET)
        @ResponseBody
        public Object list(DeptForm form) {
            return deptService.listPage(form);
        }
    
        @RequestMapping(value = "/hr/depts/tree", method = RequestMethod.GET)
        @ResponseBody
        public Object tree(DeptForm form) {
            return deptService.tree(form);
        }
    
        @RequestMapping(value = "/hr/depts/{id}", method = RequestMethod.GET)
        @ResponseBody
        public Object get(@PathVariable("id") Long id) {
            return deptService.get(id);
        }
    }
    
    

    DeptService接口实现类的设计

    代码如下:

    package com.testin.hr.service.impl;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.testin.common.base.BaseResult;
    import com.testin.common.base.EUTreeGridResult;
    import com.testin.common.base.Tree;
    import com.testin.hr.convert.DeptConvert;
    import com.testin.hr.dao.DeptMapper;
    import com.testin.hr.domain.Dept;
    import com.testin.hr.domain.DeptExample;
    import com.testin.hr.service.DeptService;
    import com.testin.hr.web.form.DeptForm;
    import com.testin.sys.convert.SysOrgConvert;
    import com.testin.sys.domain.SysOrg;
    
    @Service
    @Transactional
    public class DeptServiceImpl implements DeptService {
    
        @Autowired
        DeptMapper deptMapper;
    
        public BaseResult delete(Long id) {
            deptMapper.deleteByPrimaryKey(id);
            return BaseResult.ok("删除成功");
        }
    
        @Override
        public BaseResult deleteByIds(String ids) {
            DeptExample example = new DeptExample();
            example.createCriteria().andIdIn(idsToList(ids));
            List<Dept> deptList = deptMapper.selectByExample(example);
            for (Dept org : deptList) {
                org.setDelFlag(1);
                deptMapper.updateByPrimaryKeySelective(org);
            }
            return BaseResult.ok("删除成功");
        }
    
    
        @Override
        public BaseResult get(Long id) {
            Dept dept = deptMapper.selectByPrimaryKey(id);
            return BaseResult.ok("查询成功", DeptConvert.entityToForm(dept));
        }
    
        @Override
        public BaseResult list(DeptForm form) {
            DeptExample example = new DeptExample();
            example.createCriteria().andDelFlagEqualTo(0);
            List<Dept> deptList = deptMapper.selectByExample(example);
            return BaseResult.ok("查询成功", DeptConvert.entityListToFormList(deptList));
        }
    
        @Override
        public EUTreeGridResult listPage(DeptForm form) {
            DeptExample example = new DeptExample();
            //设置分页
            example.setStart((form.getPage() - 1) * form.getRows());
            example.setSize(form.getRows());
    
            //排序
            example.setOrderByClause("seq ASC");
    
            //查询条件
            if (form != null) {
                DeptExample.Criteria criteria = example.createCriteria();
                //条件-关键字
                if (form.getKeyword() != null && !form.getKeyword().equals("")) {
                    criteria.andNameLike("%" + form.getKeyword() + "%");
                    example.or().andAddressLike("%" + form.getKeyword() + "%");
                }
                //其它条件
                criteria.andDelFlagEqualTo(0);
            }
    
            //查询总记录
            long count = deptMapper.countByExample(example);
            //查询分页列表
            List<Dept> deptList = deptMapper.selectPageByExample(example);
    
            //返回结果
            EUTreeGridResult result = new EUTreeGridResult(count, DeptConvert.entityListToFormList(deptList));
            return result;
        }
    
        @Override
        public List<Tree> tree(DeptForm form) {
            DeptExample example = new DeptExample();
            example.setOrderByClause("seq ASC");
            example.createCriteria().andDelFlagEqualTo(0);
            List<Dept> deptList = deptMapper.selectByExample(example);
            return prepareTree(deptList);
        }
    
        private List<Tree> prepareTree(List<Dept> deptList) {
            List<Tree> allTreeList = deptListToTreeList(deptList);
            List<Tree> topList = new ArrayList<>();
            for (Tree tree : allTreeList) {
                // 遍历所有节点,将父菜单id与传过来的id比较
                if (tree.getPid() == null) {
                    tree.setChildren(prepareTreeChiled(tree.getId(), allTreeList));
                    topList.add(tree);
                }
            }
            return topList;
        }
    
        private List<Tree> prepareTreeChiled(Long id, List<Tree> allTreeList) {
            // 子菜单
            List<Tree> childList = new ArrayList<>();
            for (Tree tree : allTreeList) {
                // 遍历所有节点,将父菜单id与传过来的id比较
                if (tree.getPid() != null && tree.getPid().equals(id)) {
                    childList.add(tree);
                }
            }
            // 把子菜单的子菜单再循环一遍
            for (Tree tree : childList) {
                if (tree.getIsLeaf() == 1) {
                    tree.setChildren(prepareTreeChiled(tree.getId(), allTreeList));
                }
            }
            // 递归退出条件
            if (childList.size() == 0) {
                return null;
            }
            return childList;
        }
    
        private List<Tree> deptListToTreeList(List<Dept> deptList) {
            List<Tree> treeList = new ArrayList<>();
            if (deptList != null && deptList.size() > 0) {
                for (Dept dept : deptList) {
                    treeList.add(deptToTree(dept));
                }
            }
            return treeList;
        }
    
        private Tree deptToTree(Dept dept) {
            Tree tree = new Tree();
            tree.setId(dept.getId());
            tree.setText(dept.getName());
            tree.setIconCls(dept.getIcon());
            tree.setIsLeaf(dept.getIsLeaf());
            tree.setPid(dept.getPid());
            return tree;
        }
    
        @Override
        public BaseResult saveOrUpdate(DeptForm form) {
            Dept entity = DeptConvert.formToEntity(form);
    
            if (entity.getId() != null) {
                entity.setUpdateTime(new Date());
                deptMapper.updateByPrimaryKeySelective(entity);
            } else {
                entity.setIsLeaf(0);
                entity.setDelFlag(0);
                entity.setUpdateTime(new Date());
                entity.setCreateTime(new Date());
                deptMapper.insert(entity);
            }
    
            //更新父部门状态
            if (entity.getPid() != null) {
                Dept dept = deptMapper.selectByPrimaryKey(entity.getPid());
                dept.setIsLeaf(1);
                deptMapper.updateByPrimaryKey(dept);
            }
            return BaseResult.ok("保存成功");
        }
    
        @Override
        public BaseResult update(DeptForm form) {
            DeptExample example = new DeptExample();
            deptMapper.updateByExample(DeptConvert.formToEntity(form), example);
            return BaseResult.ok("更新成功");
        }
    
        private List<Long> idsToList(String ids) {
            String[] id = ids.split(",");
            List<Long> idList = new ArrayList<>();
            for (int i = 0; i < id.length; i++) {
                idList.add(Long.parseLong(id[i]));
            }
            return idList;
        }
    }
    

    部门列表页面的JSP脚本设计

    代码如下:

    <%--
    Created by IntelliJ IDEA.
    Date: 2016-12-30
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <!-- 权限控制标签库 -->
    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    <!-- 工具栏 -->
    <div id="DeptToolbar" style="padding:5px;height:auto">
        <div>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add'" plain="true" onclick="javascript:Dept.list.add()">增加</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" plain="true" onclick="javascript:Dept.list.delete()">删除</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit'" plain="true" onclick="javascript:Dept.list.edit()">编辑</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-reload'" plain="true" onclick="javascript:Dept.list.reload()">刷新</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-standard-plugin-delete'" plain="true" onclick="javascript:Dept.list.collapseAll()">折叠</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-standard-plugin-add'" plain="true" onclick="javascript:Dept.list.expandAll()">展开</a>
            <!-- 权限控制标签 对应com.testin.common.shiro.ShiroDbRealm.doGetAuthorizationInfo方法 -->
            <shiro:hasPermission name="user:create1">
                <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-remove" plain="true" data-options="disabled:false" onclick="del()">删除</a>
                <span class="toolbar-item dialog-tool-separator"></span>
            </shiro:hasPermission>
        <span style="float: right;margin-right: 10px;padding: 1px">
            <span>关键字:</span>
            <input lang="searchDept" name="keyword" style="line-height:19px;border:1px solid #ccc">
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-clear'" plain="true" onclick="javascript:Dept.list.clear()">清除</a>
            <a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-search'" plain="true" onclick="javascript:Dept.list.search()">搜索</a>
        </span>        
        </div>
    </div>
    <!-- 列表 -->
    <table id="DeptList" data-options="border:false"  style="width: 100%;" title="部门列表"></table>
    <!-- 弹窗  --> <!-- inline:true 不然多次打开tab会重复提交表单 -->
    <div id="DeptEdit" title="编辑部门" style="width:500px;height:400px;top: 100px;padding: 10px;display: none" data-options="iconCls: 'icon-save',closed: true,modal: true,inline:true,buttons:[{text:'保存',iconCls:'icon-save',handler:function(){Dept.input.submitForm()}},{text:'取消',iconCls:'icon-cancel',handler:function(){Dept.input.close()}}]"  ></div>
    <script src="<%=request.getContextPath()%>/jsp/hr/dept/dept.js"></script>
    <script>
        Dept.list.init('<%=request.getContextPath()%>');
    </script>
    

    部门编辑界面的JSP脚本设计

    代码如下:

    <%--
    Created by IntelliJ IDEA.
    Date: 2016-12-30
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <form id="DeptForm" method="post">
         <table class="com_table"  align="center">
            <input type="hidden" name="id">
            <input type="hidden" name="isLeaf">
            <tr>
                <td></td>
                <td><label>部门名:</label></td>
                <td><input class="easyui-textbox com_input" name="name" data-options="required:true"/></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><label>地址:</label></td>
                <td><input class="easyui-textbox com_input" name="address" data-options="required:false"/></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><label>编号:</label></td>
                <td><input class="easyui-textbox com_input" name="code" data-options="required:false"/></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><label>图标:</label></td>
                <td><input class="easyui-textbox com_input" name="icon" data-options="required:false"/></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><label>上级部门:</label></td>
                <td><select class="easyui-combobox com_input"  id="parentDept"  name="pid" data-options="textField:'text',valueField:'id'"></select></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td><label>排序:</label></td>
                <td><input class="easyui-numberspinner" name="seq" data-options="min:0,max:10000,editable:true,required:false,value:0"/></td>
                <td></td>
            </tr>
        </table>
    </form>
    
    <script src="<%=request.getContextPath()%>/jsp/hr/dept/dept.js"></script>
    <script>
        Dept.input.init('<%=request.getContextPath()%>');
    </script>
    

    部门管理功能的JS脚本设计

    代码如下:

    var ctx = "";//项目部署的工程名
    var DeptList;
    var DeptEdit;
    var DeptForm;
    
    //其它组件
    var parentDept;
    
    var Dept = {
        URL: {
            inputUI: function () {
                return ctx + "/hr/depts/ui/input";
            },
            listUI: function () {
                return ctx + "/hr/depts/ui/list";
            },
            list: function () {
                return ctx + "/hr/depts/";
            },
            tree: function () {
                return ctx + "/hr/depts/tree";
            },
            save: function () {
                return ctx + "/hr/depts/";
            },
            delete: function (ids) {
                return ctx + "/hr/depts/" + ids;
            },
            get: function (id) {
                return ctx + "/hr/depts/" + id;
            }
        },
        input: {
            init: function (ct) {
                ctx = ct;
                Dept.input.initComponent();
                Dept.input.initForm();
            },
            initComponent: function () {
                DeptForm = $("#DeptForm");
                parentDept = $("#parentDept");
            },
            initForm: function () {
                DeptForm.form({
                    url: Dept.URL.save(),
                    onSubmit: function () {
                        // do some check
                        // return false to prevent submit;
                    },
                    success: function (data) {
                        var data = eval('(' + data + ')');
                        if (data.code == 200) {
                            Dept.input.close();
                            Dept.list.reload();
                        }
                    }
                });
            },
            submitForm: function () {
                // submit the form
                DeptForm.submit();
            },
            close: function () {
                DeptEdit.dialog('close');
            },
        },
        list: {
            init: function (ct) {
                ctx = ct;
                Dept.list.initComponent();
                Dept.list.initList();
            },
            initComponent: function () {
                DeptList = $("#DeptList");
                DeptEdit = $('#DeptEdit');
            },
            initList: function () {
                DeptList.treegrid({
                    url: Dept.URL.list(),
                    method: 'get',
                    pagination: true,
                    pageSize: 30,
                    toolbar: '#DeptToolbar',//SysOrg.list.toolbar,
                    singleSelect: false,
                    collapsible: false,
                    idField: 'id',
                    treeField: 'name',
                    parentField: 'pid',
                    columns: [[
                        {field: 'ck', checkbox: true},
                        {field: 'id', title: '主键id', hidden: true},
                        {field: 'name', title: '部门名', width: '13.571%', hidden: false},
                        {field: 'address', title: '地址', width: '13.571%', hidden: false},
                        {field: 'code', title: '编号', width: '13.571%', hidden: false},
                        {field: 'icon', title: '图标', width: '13.571%', hidden: false},
                        {field: 'pid', title: '父级主键', width: '13.571%', hidden: true},
                        {field: 'seq', title: '排序', width: '13.571%', hidden: false},
                        {field: 'createTime', title: '创建时间', width: '13.571%', hidden: false},
                    ]],
                    //设置选中事件,清除之前的行选择
                    onClickRow: function (row) {
                        DeptList.treegrid("unselectAll");
                        DeptList.treegrid("selectRow",row.id);
                    },
                    loadFilter: function (data, parentId) {
                        var opt = $(this).data().treegrid.options;
                        var parentField;
                        if (opt.parentField) {
                            parentField = opt.parentField;
                            var jsonStr = JSON.stringify(data); //可以将json对象转换成json对符串
                            jsonStr = jsonStr.replace(new RegExp(parentField, "gm"), "_parentId");
                            return JSON.parse(jsonStr); //可以将json字符串转换成json对象
                        }
                    }
                });
            },
            getSelectionsIds: function () {
                var sels = DeptList.datagrid("getSelections");
                var ids = [];
                for (var i in sels) {
                    ids.push(sels[i].id);
                }
                ids = ids.join(",");
                return ids;
            },
            //增
            add: function () {
                DeptEdit.dialog({
                        href: Dept.URL.inputUI(),
                        onLoad: function () {
                            parentDept.combotree({
                                url: Dept.URL.tree(),
                                method: 'get',
                                panelHeight: 'auto'
                            });
                        }
                    })
                    .dialog("open");
            },
            //改
            edit: function () {
                var sels = DeptList.treegrid("getSelections");
                if (sels.length < 1) {
                    $.messager.alert("对话框", "至少选择一行");
                    return;
                }
    
                if (sels.length > 1) {
                    $.messager.alert("对话框", "只能选择一行");
                    return;
                }
    
                DeptEdit.dialog({
                        href: Dept.URL.inputUI(),
                        onLoad: function () {
                            //方案一:使用Form的load去load数据
                            //SysOrgForm.form("load", SysOrg.URL.get(sels[0].id));
                            //方案二:直接使用列表的row数据
                            //SysOrgForm.form("load",sels[0]);
                            //方案三:使用Ajax请求数据
                            $.ajax({
                                type: "GET",
                                url: Dept.URL.get(sels[0].id),
                                success: function (data) {
                                    if (data.code == 200) {
                                        DeptForm.form("load", data.data);
                                        parentDept.combotree({
                                            url: Dept.URL.tree(),
                                            method: 'get',
                                            panelHeight: 'auto',
                                            onLoadSuccess: function () {
                                                parentDept.combotree('setValue', data.data.pid);
                                            }
                                        });
                                    }
                                }
                            });
                        }
                    })
                    .dialog("open");
            },
            //删
            delete: function () {
                var ids = Dept.list.getSelectionsIds();
                if (ids.length == 0) {
                    $.messager.alert("对话框", "至少选择一行");
                    return;
                }
    
                $.messager.confirm({
                    title: '确认提示框',
                    msg: '你确定要删除吗?',
                    fn: function (r) {
                        if (r) {
                            $.ajax({
                                type: "DELETE",
                                url: Dept.URL.delete(ids),
                                success: function () {
                                    Dept.list.reload();
                                    Dept.list.clearSelectionsAndChecked();
                                }
                            });
                        }
                    }
                });
            },
            //刷新
            reload: function () {
                DeptList.treegrid("reload");
            },
            collapseAll: function () {
                var roots = DeptList.treegrid("getRoots");
                for (var i in roots) {
                    DeptList.treegrid("collapseAll", roots[i].id);
                }
            },
            expandAll: function () {
                var roots = DeptList.treegrid("getRoots");
                for (var i in roots) {
                    DeptList.treegrid("expandAll", roots[i].id);
                }
            },
            clearSelectionsAndChecked: function () {
                DeptList.treegrid("clearChecked");
                DeptList.treegrid("clearSelections");
            },
            //搜索
            search: function () {
                var searchName = [];
                var searchValue = [];
                $("input[lang='searchDept']").each(function (i) {
                    searchName[i] = $(this).attr("name");
                    searchValue[i] = $(this).val();
                });
    
                var queryParamsArr = [];
                for (var i = 0; i < searchName.length; i++) {
                    queryParamsArr.push(searchName[i] + ":'" + searchValue[i] + "'")
                }
                var queryParams = "{" + queryParamsArr.join(",") + "}";
    
                DeptList.treegrid({
                    queryParams: eval('(' + queryParams + ')'),
                    onLoadSuccess: function (data) {
                        //回显搜索内容
                        $("input[lang='searchDept']").each(function (i) {
                            $(this).val(searchValue[i]);
                        });
                    }
                });
            },
            //清空
            clear: function () {
                $("input[lang='searchDept']").each(function (i) {
                    $(this).val("");
                });
            }
        }
    }
    

    参考资料

    [01] jquery+easyui实现页面布局和增删改查操作(SSH2框架支持)
    https://blessht.iteye.com/blog/1069749/
    [02] EasyUi – 布局Layout + 登录界面
    https://www.cnblogs.com/tangge/p/3224595.html
    [03] 前端框架 EasyUI 页面布局 Layout
    https://www.bbsmax.com/A/LRnJWwwJqY/
    [04] 基于SSM-EasyUI的权限管理系统
    https://blog.csdn.net/uq_jin/article/details/56283719
    https://github.com/cskun/rds-sys
    [05]cookie禁用后session怎么使用url重写详细讲解
    https://blog.csdn.net/weixin_40648117/article/details/78844100
    [06] 设置shiro超时时间
    https://blog.csdn.net/wahaha13168/article/details/82389982
    [07] springmvc easyui全局处理session过期时跳转的登陆页面内嵌至tab页中
    https://www.oschina.net/question/1017341_236885
    [08] 解决easyui在session过期后iframe跳转到登录页面的问题
    https://blog.csdn.net/ace_place/article/details/53053282
    [09] 基于SSM框架和easyUI框架的简易人事管理系统
    https://blog.csdn.net/qq_34247759/article/details/82993706
    [10] SpringMvc+Mybatis实现一个简单人事管理系统
    https://blog.csdn.net/qq_35709874/article/details/77477955

    微信扫一扫关注该公众号【测试开发者部落】

    image.png
    点击链接加入群聊【软件测试学习交流群】
    https://jq.qq.com/?_wv=1027&k=5eVEhfN
    软件测试学习交流QQ群号:511619105

    相关文章

      网友评论

        本文标题:使用Ajax技术开发简易版人事管理系统(了解)

        本文链接:https://www.haomeiwen.com/subject/prbytctx.html