1、主界面与登录

1.1、主界面的构建

将后台模板下所有的文件都复制到erp_web的webapp目录下

1.2、登录功能实现

(1)登录页面

把登陆页面里的3个文件/文件夹都复制到erp_web的webapp下

修改标题信息,修改login.html的title跟登陆框上的文字信息为“蓝云ERP旗舰版3.1”。

(2)扩展IEmpDao和EmpDao方法

实现按用户名和密码查询实体类功能

Dao接口:

Dao实现:

(3)扩展IEmpBiz接口跟EmpBiz实现

IEmpBiz:

EmpBiz:

(4)添加LoginAction

添加checkUser方法,用于登陆验证

package cn.itcast.erp.action;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;import javax.servlet.http.HttpServletResponse;import org.apache.struts2.ServletActionContext;import com.alibaba.fastjson.JSON;
import com.opensymphony.xwork2.ActionContext;import cn.itcast.erp.biz.IEmpBiz;
import cn.itcast.erp.entity.Emp;/*** 实现用户登陆与登出功能* @author Administrator**/
public class LoginAction {/** 登陆用户名 */private String username;/** 登陆密码 */private String pwd;private IEmpBiz empBiz;/*** 登陆验证请求*/public void checkUser(){try{//验证登陆Emp loginUser = empBiz.findByUsernameAndPwd(username, pwd);if(null == loginUser){ajaxReturn(false, "用户名或密码不正确");return;}//保存到session中,表示用户已经登陆了ActionContext.getContext().getSession().put("loginUser", loginUser);ajaxReturn(true,"");}catch(Exception ex){ex.printStackTrace();ajaxReturn(false,"登陆失败");}}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public void setEmpBiz(IEmpBiz empBiz) {this.empBiz = empBiz;}/*** 返回前端操作结果* @param success* @param message*/public void ajaxReturn(boolean success, String message){//返回前端的JSON数据Map<String, Object> rtn = new HashMap<String, Object>();rtn.put("success",success);rtn.put("message",message);write(JSON.toJSONString(rtn));}/*** 输出字符串到前端* @param jsonString*/public void write(String jsonString){try {//响应对象HttpServletResponse response = ServletActionContext.getResponse();//设置编码response.setContentType("text/html;charset=utf-8"); //输出给页面response.getWriter().write(jsonString);} catch (IOException e) {e.printStackTrace();}}
}

(5)配置Action

applicationContext-action.xml

<!-- 登陆/退出 -->
<bean id="loginAction" class="cn.itcast.erp.action.LoginAction" scope="prototype"><property name="empBiz" ref="empBiz"></property>
</bean>

Struts.xml

<!-- 登陆/退出 -->
<action name="login_*" class="loginAction" method="{1}"></action>

(6)修改Login.html

修改文件名,并添加easyUI引用

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>蓝云ERP旗舰版3.1</title>
<link rel="stylesheet" type="text/css" href="css/login.css"/>
<link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>

登录表单form修改

给用户名输入框加入name=”username”,给密码输入框加入name=”pwd”

给“登陆”按钮加上id属性,用于登陆方法的绑定

编写ajax方法,实现用户登陆

1.3、显示用户登录名

(1)Action修改

增加showName方法

(2)index.html的修改

添加<span>用于显示登陆用户名

(3)index.js的修改

加入showName方法

/*** 显示登陆用户名*/
function showName(){$.ajax({url:'login_showName',method: 'post',dataType: 'json',success: function(rtn){if(rtn.success){//登陆成功的,则显示登陆用户名称$('#username').html(rtn.message);}else{//没有登陆的,则跑转到登陆页面location.href="login.html";}}});
}

在index.js的初始化方法中加入showName()方法调用

1.4、退出登录

(1)修改Action

LoginAction中加入loginOut方法

(2)修改index.js

初始化方法中加入loginOut的绑定单击事件,该事件请求退出登陆

//退出登出
$('#loginOut').bind('click',function(){$.ajax({url: 'login_loginOut',success:function(rtn){location.href="login.html";}});
});

2、菜单动态读取

我们之前每做完一个页面,都需要在index.js中增加相应的菜单链接,才能让其在主页菜单中显示出来。有没有更好的实现?让它动态出现呢?

2.1、菜单表的设计

(1)菜单结构分析

分析index.js中的_menus的json数据。可看出菜单里包含icon, menuid, menuname, url, menus数组

(2)设计数据库菜单表

菜单都有一个上级菜单,我们可以通过层级结构进行设计。给每个菜单设置一个上级菜单(pid),就可以实现无限级别的树形(层级)结构的菜单。

查看数据库模型图,

如果数据库还没有建表,则执行下面的建表语句:

CREATE TABLE MYERPUSER.MENU
(MENUID VARCHAR(30) NOT NULL PRIMARY KEY,MENUNAME VARCHAR(30) NOT NULL,URL VARCHAR(200),ICON VARCHAR(100),PID VARCHAR(30) NOT NULL
) TABLESPACE MYERP;COMMENT ON TABLE MYERPUSER.MENU IS '系统菜单';
COMMENT ON COLUMN MYERPUSER.MENU.MENUID IS '编号';
COMMENT ON COLUMN MYERPUSER.MENU.MENUNAME IS '名称';
COMMENT ON COLUMN MYERPUSER.MENU.URL IS '对应URL';
COMMENT ON COLUMN MYERPUSER.MENU.ICON IS '图标样式';
COMMENT ON COLUMN MYERPUSER.MENU.PID IS '上一级菜单编号';

执行添加菜单脚本:

INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('0', '系统菜单', '-', 'icon-sys', '-1');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('100', '基础数据', '-', 'icon-sys', '0');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('101', '商品类型', 'goodstype.html', 'icon-sys', '100');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('102', '商品', 'goods.html', 'icon-sys', '100');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('105', '仓库', 'store.html', 'icon-sys', '100');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('200', '人事管理', '-', 'icon-sys', '0');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('201', '部门', 'dep.html', 'icon-sys', '200');
INSERT INTO MENU (MENUID, MENUNAME, URL, ICON, PID) VALUES ('202', '员工', 'emp.html', 'icon-sys', '200');
COMMIT;

2.2、代码实现

(1)实现类:实体代码如下

package cn.itcast.erp.entity;import java.util.List;/*** 菜单实体类* @author Administrator **/
public class Menu { private String menuid;//菜单IDprivate String menuname;//菜单名称private String icon;//图标private String url;//URL//private String pid;//上级菜单IDprivate List<Menu> menus;// 子菜单列表public String getMenuid() {       return menuid;}public void setMenuid(String menuid) {this.menuid = menuid;}public String getMenuname() {       return menuname;}public void setMenuname(String menuname) {this.menuname = menuname;}public String getIcon() {     return icon;}public void setIcon(String icon) {this.icon = icon;}public String getUrl() {      return url;}public void setUrl(String url) {this.url = url;}public List<Menu> getMenus() {return menus;}public void setMenus(List<Menu> menus) {this.menus = menus;}
}

配置映射文件,添加自关联,使用order-by指定排序

(2)dao层

因为menu的主键为字符串,原来的get方法类型不能匹配,我们需要重载get方法,可以通过字符串主键获取实体

修改IBaseDao,加入T get(String id)方法

修改BaseDao,加入实现

删除MenuDao红框中的代码

(3)Biz层

修改IBaseBiz,添加T get(String id)方法

修改BaseBiz,加入实现

Action层

修改MenuAction,添加getMenuTree方法

0是顶级菜单的ID,通过自关联就可以把所有的菜单都加载进来。

浏览器访问:http://localhost:8080/erp/menu_getMenuTree

运行结果:

(4)前端js修改

修改index.js,使用ajax请求菜单地址来获取菜单数据

3、密码加密

3.1、概述

我们在前期开发阶段,为了便于测试,密码采用明码存储。一旦程序部署到生产环境上,明友存储密码是非常不安全的,必须要对密码进行加密运算。

加密主要分为两种:可逆运算的和不可逆

可逆运算的加密是通过一个秘钥,对一串字符进行加密运算,同样可以通过这个秘钥进行解密运算。

不可逆运算的加密对一串字符进行加密,但是不能还原成原来的字符串。(散列)

那我们接下来做的加密就是使用不可逆加密的MD5加密算法

3.2、添加shiro依赖

修改erp_parent下的POM.xml文件,

定义shiro的版本号

<shiro.ver>1.2.3</shiro.ver>

加入shiro的依赖

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.ver}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>${shiro.ver}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.ver}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-aspectj</artifactId><version>${shiro.ver}</version></dependency>
</dependencies>

3.3、代码实现

修改EmpBiz类,添加属性

修改EmpBiz类,重写add方法

修改EmpBiz类的findByUsernameAndPwd方法,查询能对密码进行加密

4、修改密码

4.1、需求分析

每个员工都可以修改自己的密码,输入旧密码、新密码、确认密码后即可修改密码。

点击主页右上方 “修改密码”链接

弹出窗口

旧密码必须正确,新密码与确认密码必须相同,点击保存后更新密码

4.2、后端实现

(1)Dao修改,添加接口方法与实现

IEmpDao修改:

EmpDao实现

在erp_biz中创建自定义异常cn.itcast.erp.ERPException,用于处理业务逻辑出错时抛出

修改EmpBiz

抽出加密方法,修改使用到密码加密的地方都调用该方法

/*** MD5加密* @param src 原密码* @param salt 盐* @return*/
private String encrypt(String src, String salt){Md5Hash md5 = new Md5Hash(src,salt, hashIterations);return md5.toString();
}

修改加密码加密的地方都改成调用加密方法:

给IEmpBiz和EmpBiz增加修改密码的方法updatePwd

IEmpBiz

在BaseAction中添加获取当前登陆用户的方法

在EmpAction中添加调用修改密码的方法

添加接收新旧密码的属性:

添加updatePwd方法:

4.3、前端实现

(1)修改index.html

修改 修改密码窗口,改成如下:

<!--修改密码窗口-->
<div id="w" class="easyui-dialog"><div class="easyui-layout" fit="true"><div region="center" border="false" style="padding: 10px; background: #fff;"><table cellpadding=3><tr><td>旧密码:</td><td><input id="txtOldPass" type="password" class="txt01" /></td></tr><tr><td>新密码:</td><td><input id="txtNewPass" type="password" class="txt01" /></td></tr><tr><td>确认密码:</td><td><input id="txtRePass" type="password" class="txt01" /></td></tr></table></div></div>
</div>

(2)修改index.js

修改openPwd()方法,把serverLogin的方法都复制到“保存”按钮的handler中,修改后的openPwd代码如下:

//修改密码
function openPwd() {$('#w').dialog({title: '修改密码',width: 300,modal: true,closed: true,height: 192,buttons:[{text:'保存',iconCls:'icon-save',handler:function(){var $oldpass = $('#txtOldPass');var $newpass = $('#txtNewPass');var $rePass = $('#txtRePass');if (!$oldpass.val()) {$.messager.alert('提示信息','请输入原密码!','info',function(){$oldpass.select();})return false;}if (!$newpass.val()) {$.messager.alert('提示信息','请输入新密码!','info',function(){$newpass.select();})return false;}if (!$rePass.val()) {$.messager.alert('提示信息','请再一次输入密码!','info',function(){$rePass.select();})return false;}if ($newpass.val() != $rePass.val()) {$.messager.alert('提示信息','两次密码不一至!请重新输入','info',function(){$rePass.select();})return false;}$.ajax({url:'emp_updatePwd',dataType:'json',type:'post',data: {oldPwd:$oldpass.val(), newPwd:$newpass.val()},success:function(rtn){$.messager.alert('提示',rtn.message,'info',function(){if(rtn.success){$oldpass.val('');$newpass.val('');$rePass.val('');$('#w').dialog('close');}});}});}},{text:'取消',iconCls:'icon-cancel',handler:function(){$('#w').dialog('close');}}]});
}

5、管理员重置密码

5.1、需求分析

当员工忘记密码的时候,管理员可以重置员工的密码。

我们将员工的密码管理功能,从员工管理中独立出来

点击重置密码超链接,弹出窗口,输入新密码,保存更新密码后,关闭窗口

5.2、后端实现

(1)Biz层实现

修改IEmpBiz,增加updatePwd_reset

修改EmpBiz,增加实现

(2)Action层实现

修改EmpAction,增加updatePwd_reset方法,供页面重置密码时调用

5.3、前端实现

(1)新增pwd.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>重置员工密码</title>
<link rel="stylesheet" type="text/css" href="ui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="ui/themes/icon.css">
<script type="text/javascript" src="ui/jquery.min.js"></script>
<script type="text/javascript" src="ui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="ui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript" src="ui/jquery.serializejson.min.js"></script>
<script type="text/javascript" src="ui/date.js"></script>
<script type="text/javascript" src="js/pwd.js"></script>
</head>
<body>
<table id="grid"></table>
<div id="editDlg" class="easyui-dialog" style="padding:8px;"><form id="editForm"><input name="id" type="hidden"> <table><tr><td>新密码:</td><td><input id="txtpwd" name="newPwd" type="text"></td></tr></table></form>
</div>
</body>
</html>

(2)增加pwd.js

在js目录下创建pwd.js

$(function(){$('#grid').datagrid({title: '员工信息列表',url:'emp_listByPage',columns:[[{checkbox:true},{field:'uuid',title:'编号',width:100},{field:'username',title:'系统登陆名称',width:100},{field:'name',title:'真实姓名',width:100},{field:'gender',title:'性别',width:100,formatter:function(gender){switch(gender){case 0: return '女';case 1: return '男';default: return '未知';}}},{field:'email',title:'电子邮箱地址',width:100},{field:'tele',title:'联系电话',width:100},{field:'address',title:'联系地址',width:100},{field:'birthday',title:'出生年月日',width:100,formatter:function(birthday){if(birthday){return new Date(birthday).Format("yyyy-MM-dd");}return "";}},{field:'dep',title:'部门',width:100,formatter:function(dep){if(dep){return dep.name;}return "";}},{field:'-',title:'操作',width:200,formatter:function(value,row,index){var operation = '<a href="javascript:void(0)" onclick="updatePwd_reset(' + row.uuid + ')">重置密码</a> ';return operation;}}]],singleSelect: true,pagination: true,rownumbers: true});$('#btnSave').bind('click',function(){if($('#formPwdReset').form('validate') == false){return;}var datas = $('#formPwdReset').serializeJSON();$.ajax({url: 'emp_updatePwd_reset',dataType:'json',data: datas,type: 'post',success: function(rtn){if(rtn.success){$.messager.alert("提示信息", "重置密码成功!", 'info', function(){//关闭窗口$('#dlgPwdReset').window('close');//刷新列表$('#grid').datagrid('reload');});}else{$.messager.alert("提示信息", "重置密码失败!<br>" + rtn.message, 'info');}}});});$('#editDlg').dialog({title:"重置员工密码",width:260,height:120,iconCls:'icon-save',modal:true,closed:true,buttons:[{text:'保存',iconCls: 'icon-save',handler:function(){var datas = $('#editForm').serializeJSON();$.ajax({url: 'emp_updatePwd_reset',dataType:'json',data: datas,type: 'post',success: function(rtn){$.messager.alert("提示", rtn.message, 'info', function(){if(rtn.success){//关闭窗口$('#editDlg').dialog('close');//刷新列表$('#grid').datagrid('reload');}else{$.messager.alert("提示", "重置密码失败!<br>" + rtn.message, 'info');}});}});}}]});
});function updatePwd_reset(uuid){//清除表单内容,防止数据混乱$('#editForm').form('load',{id:uuid,newPwd:""});//弹出窗口$('#editDlg').dialog('open');
}

6、员工管理去掉密码修改

6.1、需求分析

我们已经完成了专门的密码管理,那员工管理中的密码部分应该去掉,保证一个统一的入口。

6.2、代码实现

(1)修改emp.html

删除编辑员工中的密码编辑框

问题:当我们修改某个员工后,我们会发现,他的密码也变成空的,这是为什么?怎么解决?有以下3种解决方式

使用触发器,更新的时候,如果密码为空就把旧的密码赋给它

先让对象进入持久化状态,再设置它的属性值

Hbm.xml里加入update=false属性,不更新pwd字段(推荐)

(2)后端代码修改

创建触发器

CREATE OR REPLACE TRIGGER TRI_EMP_UPDATE_PWD
BEFORE
UPDATE OF PWD ON EMP FOR EACH ROW
DECLARE
--声明变量
BEGIN
--如果修改的密码为NULL ,让修改的密码为原密码
--伪记录  :OLD 修改之前的记录  :NEW 修改之后的记录IF :NEW.PWD IS NULL  THEN:NEW.PWD := :OLD.PWD;END IF;
END;

设置持久化状态对象的属性

修改EmpBiz,重写update方法

@Override
public void update(Emp emp){//查出要更新的对象,让其进入持久化状态Emp dbEmp = this.empDao.get(emp.getUuid());if(null == dbEmp){throw new ERPException("没有找到相应的员工!");}//修改真实姓名dbEmp.setName(emp.getName());//修改联系电话dbEmp.setTele(emp.getTele());//修改联系地址dbEmp.setAddress(emp.getAddress());//修改出生年月日dbEmp.setBirthday(emp.getBirthday());//修改邮箱地址dbEmp.setEmail(emp.getEmail());//修改所属部门dbEmp.setDep(emp.getDep());
}

Hbm.xml里加入update=false属性,不更新pwd字段

修改emp.hbm.xml文件:

7、新增员工设置初始密码

7.1、需求分析

我们在新增员工的时候给他一个默认的密码,密码为登陆名

7.2、实现

修改EmpBiz的新增员工方法

8、静态页面传参数

8.1、需求分析

对于采购的订单,我们需要记录它是从哪一家供应商采购的;对于销售订单,我们也需要记录是卖给哪个客户的。因此我们需要管理供应商及客户的信息

供应商信息管理都包括些什么?主键、名称、地址、联系人、电话等。客户信息管理又包括了哪些呢,也是主键、名称、地址、联系人、电话等。大家可以看到它们两个的字段其实是一样的。遇到这种两对不同类型的对象但其字段又相同的情况下,我们通常是把它们记录在同一个表里,用一个字段来区分。我们这里可以用type来进行区分,1:供应商,2:客户

8.2、实现思路

把相似的信息放入同一个表,可以极大的节省开发时间,降低维护成本,这两个信息对应的实体层、数据访问层、业务层、页面都用同一套代码,只是通过参数进行区分。

我们可以在管理供应商的页面进行修改,通过参数,将此功能一分为二。既可实现供应商管理,又能实现客户管理。

静态页面可传参?Of cause, 我们试试看吧

8.3、代码实现

(1)静态页面传参实现

先做个测试,给supplier.html页面传参数type
If(type==1){
页面标题=供应商管理
}
If(type==2){
页面标题=客户管理
}将request.js复制到js目录下,并在supplier.html中加入引用

在supplier.html中添加script

if(Request['type']==1){document.title="供应商管理";
}
if(Request['type']==2){document.title="客户管理";
}

测试运行后发现,我们通过传参?type=value可以改变页面的标题

(2)修改查询

修改SupplierDao类,加上type条件,以区分查询的是供应商还是客户

修改crud.js文件,加入全局变量listParam,根据type的值进入赋值

删除原有type列或行

删除columns中的type列:

(3)修改保存功能

增加saveParam变量,记录保存url提交的type参数

修改btnSave方法,提交的url中加入saveParam

(4)修改菜单url

更新menu表中对应菜单的url,把供应商的url后面加上?type=1;把客户的url后面加上?type=2

打开chrome浏览器的开发工具,验证修改成功

9、总结

9.1.    树状数据结构的表设计
在表中添加一个字段表示上一级ID,使用hibernate建立自关联
9.2.    使用shiro MD5对密码进行加密
9.3.    静态页面传参
会使用request.js插件,实现静态页面的传参
9.4.    项目经验
    1)    对两种或多种以上不同的对象,但又具有相同的属性字段,可以采用一个字段来区分,然后用相同的代码来实现功能。
    2)    修改公用类或公用js文件时,一定要考虑当前的修改是否影响到其它功能。如果有影响应该怎么处理?项目开发中,往往是多人合作开发,会存在多人引用/修改同一个文件,因此在修改时应该要多考虑一下,尽量做到修改后不影响其它功能的正常运行。修改的同时记得加上注释。
    3)    功能尽量单一化。即同一个功能,就只有一个入口。如:修改密码功能的修改,去掉了编辑员工时的密码修改功能,统一由重置功能来实现;新增时使用初始化密码来实现
    4)    使用自定义异常的场景:用于业务逻辑校验不符合时抛出,action端要专门捕获这种已知的异常。
    5)    对多次使用相同的代码块,应该抽出来独立成方法,用到它的地方都调用该方法。如:EmpBiz中的密码加密码方法encrypt,把散列的次数封装到encrypt方法里,保证每次调用后得到的结果都是相符合的。
    6)    项目中用到的常量(数字或字符串),特别是用于判断或session.get/map.get,一定要封装到常量类中,并加上注释。常量可以在接口中定义

蓝云ERP系统项目笔记——登录与密码管理(4)相关推荐

  1. 蓝云ERP系统项目笔记——库存预警(9)

    1.库存预警报表 1.1.需求及实现思路 (1)需求:统计每种商品的库存数量和待发货数量(库存数量小于待发货数量) (2)实现思路:运用关联查询.子查询.聚合统计. 1.2.SQL语句的编写 这种带子 ...

  2. 蓝云ERP系统项目笔记——采购申请(5)

    1.主线业务流程 1.1.采购业务流程 采购业务流程图 1.2.类图设计 1.3.表结构分析 (1)订单与明细 (2)商品库存与变更记录 2.采购申请 2.1.需求分析 选中供应商,可添加多个采购的商 ...

  3. Java全栈开发---Java ERP系统开发:商业ERP(七)登录与密码管理

    登录与密码管理 一.登录与退出 (一)页面的创建于修改 1.管理主界面的构建 (1)在网上找一个后台管理的模板(拷贝到webapp的目录下面) 点击这里下载: (2)访问主界面 2.登录主界面的构建 ...

  4. ERP系统的KPI指标建立与管理介绍

    ERP系统的KPI指标建立与管理介绍    本文从ERP系统的实际应用与管理角度出发,结合不同项目的经历对ERP评价体系进行分析与探讨. ERP系统的KPI应用现况 "重建设.轻评估&quo ...

  5. 企业实施应用ERP系统项目心得

    企业在应用ERP系统后不能充分获益,甚至ERP项目实施失败的原因究竟是什么呢?总结了几条原因: 1.基础数据不准确,不能根据这些数据来指导企业的生产经营活动: 2.企业员工对ERP系统缺乏主人翁的精神 ...

  6. 云尚办公OA系统学习笔记(5.权限管理)

    目录 一.权限管理 1.权限管理介绍 1.1 菜单权限 1.2 按钮权限 1.3 权限管理设计思路 2.JWT 2.1 JWT介绍 2.2 JWT令牌的组成 2.3 项目集成JWT 2.3.1 引入依 ...

  7. 企业如何借助制造业ERP系统,做好生产排产管理?

    随着市场竞争越来越激烈,生产制造行业订单零碎化趋势越发突出.面对品种多,数量小,批次多,个性化需求也多的生产方式,PMC生产排产管理变得非常困难:同时生产过程还会有各种不确定的临时性因素出现,导致排产 ...

  8. 企业在线ERP系统与内控控制因素管理

    2019独角兽企业重金招聘Python工程师标准>>> 企业内部控制是以专业管理制度为基础,以防范风险.有效监管为目的,通过全方位建立过程控制体系.描述关键控制点和以流程形式直观表达 ...

  9. 博奥智源科技,ERP系统项目功能架构分享

    (一)技术要求说明 1.系统环境与用户界面 类别 功能描述 技术协议标准 系统 环境 支持系统平台 Windows Server 2003或2008或2012 支持的数据库 SQL Server200 ...

最新文章

  1. php 常用数组操作
  2. BDC创建物料主数据各个视图
  3. nginx https 访问http_Nginx之Http模块系列之访问控制模块
  4. 对request.getSession(false)的理解(附程序员常疏忽的一个漏洞)
  5. 提搞网站访问速度可做哪些优化
  6. linux快速查找文件中所包含的指定字段的个数
  7. Ubuntu命令大全(转载)
  8. ST电机库无感FOC模式接电机前准备工作(1)----PWM波的生成
  9. 时间序列分析之相关性
  10. Python excel转成html页面 excel 在线预览
  11. mos管和三极管的区别/管子的三种状态
  12. Python的第三次作业——陈灵院
  13. SOLO: Segmenting Objects by Locations 论文学习
  14. Meterpreter渗透测试入门
  15. Kmeans K均值聚类,OpenCV实现
  16. 如何将json类型的数据转换成csv格式
  17. Android多媒体开发(2)————使用Android NKD编译原版FFmpeg
  18. 获取每个账户最大连续逾期期数
  19. 【Python】求200以内能被17整除的最大正整数
  20. 注册会计师和高级会计师哪个含金量高 注册会计师和高级会计师的区别

热门文章

  1. sql同时查询出明细和汇总
  2. Idea创建ssm的MAVEN项目
  3. html页面视口,web移动端---视口viewport
  4. 排序算法之Bogo排序
  5. 5.js获取文本框的value值
  6. linux-top命令查看内存CPU
  7. C++构造函数的参数初始化表
  8. 计算物理基础期中考试2020.5.9
  9. *#*#4636#*#*
  10. mysql 远程登录 1045_MySQL处理远程登录错误1045