转:http://www.cr173.com/html/15518_1.html

“请假管理”应用,应该算是 SharePoint 的“Hello World!”、川菜里面的鱼香肉丝、粤菜里面的蛋炒饭 。。。吧?

怎么样才能做出简易、实用的请假管理,一直都是都是一个问题。完全 code free 不写代码是搞不出来的,完全写代码实现的话又何必用 SharePoint?简洁、轻快的解决方案才是我们追求的。

问题

通常的“请假管理” SharePoint 实现存在这样几个问题:

权限。

要么就是所有人都可以看见你的请假单,要么就是只有你自己可以看到,要了命了。参见 这里 的描述。常见的解决方案,要么就是直接忽略这个问题,或者用视图来过滤筛选,但这不是根本的办法。

预先指定审批人员。

而实用的要求,其实是动态的指定审批人员。而且,往往并不是先由上级职能经理审批,而是先由所在项目的项目经理审批、职能经理一般只要项目经理没意见都会同意的。

年假天数约束。

假别里面如果是年假,则应该有天数的限制,且每年重置。软件应当自动对剩余年假天数做核对,避免需要人工再去查年假天数。

孤立。

没有和 SharePoint 其它应用配合,比如项目、日历。

目标

实用的“请假管理”应该什么样子呢?

1、所有人都可以提出请假申请。如下图所示:

2、自动查找合适的审批人。在项目中则项目经理就是审批人(直接去项目列表中找“项目经理”字段对应的用户),否则就是职能部门经理(如下图所示)。

3、不能申请超出可用年假天数的年假。

4、但是,一旦提交申请,就只有本人、审批人、管理员可以看到。而且审批人有“批准”权限。

注意:SharePoint 只允许每个列表拥有 8000 个独立权限的列表项。所以,后面要配合列表的信息管理策略将完成的请假单转移到别的地方。

5、申请人发起请假流程。

6、审批人审批请假申请。

7、审批完成后不能再修改申请。

配置信息管理策略将“声明为记录”的项在1个月后移动到其它的文档库,避免拥有独立权限的项目超过 SharePoint 对每个列表 8000 条的限制。

8、如果同意了年假申请,那么,自动从当年年假中扣除。

9、申请同意后自动加入请假日历。

该日历可以和其它日历合并在内网门户上显示。

实现

说实话,实现起来并不简单。但是,通过努力,可以保持解决方案的干净、轻快,与整个架构体系融合在一起。

1、所有人都可以提出请假申请。

直接断开“请假单”列表的权限继承,为所有用户设置“参与讨论”权限级别即可。

具体操作参见这里 中断列表或库的权限继承。

2、自动查找合适的审批人。

开发自定义字段,加入“请假单”列表。

此自定义字段将获取申请人所在项目的项目经理或者申请人的上级职能经理。

创建自定义字段类型的文章在这里 创建自定义 SharePoint 2010 字段类型。

获取当前用户的上级职能经理。需要用到 UserProfileManager 对象。



UserProfileManager upm = new UserProfileManager(SPServiceContext.Current);

if (upm.UserExists(user.LoginName))

{   

    UserProfile u = upm.GetUserProfile(user.LoginName);

    UserProfile[] managers = u.GetManagers();

    if (managers != null)

    {

        foreach(UserProfile manager in managers){

            SPUser u_manager = web.SiteUsers[manager[PropertyConstants.AccountName].Value.ToString()];

            // 其它自定义代码。

        }

    }

}

3、不能申请超出可用年假天数的年假。

这里需要用 SharePoint Designer 修改“请假单”列表的“NewForm.aspx”文件,利用 JavaScript 脚本调用 SharePoint 的 Client Object Model 获取剩余年假并显示在界面上。


首先,需要引入几个 js 库:jQuery 和 jQuery.SPServices。jQuery 已经放入 masterpage。

  1. <SharePoint:ScriptLink Name="SP.js" runat="server" OnDemand="true" Localizable="false" />
  2. <script src="http://www.cnblogs.com/DocLib/spservices/jquery.SPServices-0.7.1a.min.js" type="text/javascript"></script>

然后,在选择假别的下拉框内容改变时,读取可用年假天数。 (我当时为什么要用 lj 做变量名?我也很奇怪。)

  1. $('select[title="假别"]').change(function(){
  2. var lj=$(this).val();
  3. if(lj=='年假'){
  4. ExecuteOrDelayUntilScriptLoaded(get_annual_leave_days, "sp.js"); }
  5. else{
  6. $("nobr:contains('请假天数')").children().each(function(){
  7. $(this).html("*");
  8. });
  9. }
  10. });

get_annual_leave_days 方法将读取当前用户所剩余年假天数。下面函数中变量命名方法并不统一,这是这些代码来自多个不同时期的不同项目的印记啊!软件开发是个手艺活儿。


"_x5269__x4f59__x5e74__x5047__x59" 是字段“剩余年假天数”的 InnerName。

  1. var _ctx = null;
  2. var _items = null;
  3. function get_annual_leave_days(){
  4. _ctx = new SP.ClientContext.get_current();
  5. var web = _ctx.get_web();
  6. var lists = web.get_lists();
  7. var list_annual_leave = lists.getByTitle("年假汇总");
  8.  
  9. var currentDate = new Date();
  10. var year = currentDate.getFullYear();
  11. var currentUserID = $().SPServices.SPGetCurrentUser({
  12. fieldName: "ID",
  13. debug: false
  14. });
  15.  
  16. var camlQuery = new SP.CamlQuery();
  17. var strCaml = "<View>" +
  18. "<Query>" +
  19. "<Where>"+
  20. "<And>"+
  21. "<Eq>"+
  22. "<FieldRef Name='_x4eba__x5458_' LookupId='TRUE' />"+
  23. "<Value Type='Lookup'>"+currentUserID+"</Value>"+
  24. "</Eq>"+
  25. "<Eq>"+
  26. "<FieldRef Name='_x5e74__x4efd_' />"+
  27. "<Value Type='Integer'>"+year+"</Value>"+
  28. "</Eq>"+
  29. "</And>"+
  30. "</Where>"+
  31. "</Query>" +
  32. "</View>";
  33. camlQuery.set_viewXml(strCaml);
  34. this._items = list_annual_leave.getItems(camlQuery);
  35. _ctx.load(_items);
  36.  
  37. _ctx.executeQueryAsync(Function.createDelegate(this, this.onSuccess), Function.createDelegate(this, this.onFail));
  38. }
  39. function onSuccess(sender, args) {
  40. var listItemEnumerator = this._items.getEnumerator();
  41. while(listItemEnumerator.moveNext()) {
  42. var oListItem = listItemEnumerator.get_current();
  43. var days = oListItem.get_item("_x5269__x4f59__x5e74__x5047__x59");
  44. $("nobr:contains('请假天数')").children().each(function(){
  45. $(this).html("(剩余 "+days+" 天)*");
  46. });
  47. }
  48. }
  49. function onFail(sender, args) {
  50. alert('获取年假天数时出错:' + args.get_message());
  51. }

更多的技术细节可以参考 ECMAScript 对象模型系列,这个系列讲解很细致了。另外,JS 脚本调用 SharePoint 的 JSCOM 时是异步操作,回调次数多了代码会很乱,这篇 使用Jscex增强SharePoint 2010 JavaScript Client Object Model (JSOM) 提供了一优化代码的解决方案可供参考。

4、但是,一旦提交申请,就只有本人、审批人、管理员可以看到。而且审批人有“批准”权限。

为实现这个功能,需要处理列表的 Create 事件。

先断开现有的继承权限。

  1. item.BreakRoleInheritance(false);

然后,绑定新的权限。

  1. protected void bind_role(SPListItem item, SPPrincipal principal, SPRoleDefinition definition)
  2. {
  3. try
  4. {
  5. SPRoleAssignment assignment = new SPRoleAssignment(principal);
  6. assignment.RoleDefinitionBindings.Add(definition);
  7. item.RoleAssignments.Add(assignment);
  8. }
  9. catch (Exception ex)
  10. {
  11. throw ex;
  12. }
  13. }

对某个用户执行绑定角色的操作。

  1. bind_role(item, user, web.RoleDefinitions["参与讨论"]);

5、申请人发起请假流程。

用 SharePoint Designer 建立请假流程。

6、审批人审批请假申请。

审批即可。可以用 InfoPath Designer 从 SPD 中打开美化一下任务界面。

如果需要对任务也实施和“请假单”相同的权限控制,可以参考对“请假单”的处理一样进行。

7、审批完成后不能再修改申请。

需要开发处理工作流事件的代码,声明当前项目为记录。

  1. SPWorkflow wf = new SPWorkflow(web, properties.InstanceId);
  2. SPList list = web.Lists[wf.ListId];
  3. if (list.Title == "请假单")
  4. {
  5. SPListItem item = list.Items.GetItemById(wf.ItemId);
  6. title = item.Title;
  7. if (!Records.IsRecord(item))
  8. {
  9.      Records.DeclareItemAsRecord(item);
  10.      }
  11. }

还需要配置信息管理策略,自动备份已经完成流程的“请假单”到归档库中。

8、如果同意了年假申请,那么,自动从当年年假中扣除。

同样在工作流事件代码中处理,扣除年假天数。做减法即可。由于申请人本人没有直接修改年假天数的权限(这是当然的),所以需要提升权限才能操作。而这也意味着要服务器场解决方案,“全程沙盒方案”梦想破灭。

9、申请同意后自动加入请假日历。

在 SPD 工作流中处理。

10、签入代码和 SPD 文件(导出来备份,或者直接 stsadm –o backup 备份网站集),写好部署操作手册。完工。

牛刀小试、用SharePoint 实现请假管理功能的更多相关文章

  1. SharePoint\O365 "See also"功能 and site feature 激活\禁用小节

    博客地址:http://blog.csdn.net/FoxDave 最近因为问题发现了SharePoint的"See also"功能,该功能是由SharePoint自动的Feat ...

  2. SharePoint 2010 产品六大功能模块

    对IT专业人员来说,新的产品,意味着新的功能,IT生产力提高的契机,更加关心如何使用新产品投入更少,产出更多.在本文中我们通过对SharePoint 2010产品的功能介绍.管理中心新功能介绍.系统新 ...

  3. .Net Core MVC 网站开发(Ninesky) 2.2、栏目管理功能-System区域添加

    在asp或asp.net中为了方便网站的结构清晰,通常把具有类似功能的页面放到一个文件夹中,用户管理功能都放在Admin文件夹下,用户功能都放在Member文件夹下,在MVC中,通常使用区域(Area ...

  4. 解析大型.NET ERP系统 通用附件管理功能

    大型系统具备一个通用的附件管理功能,对于单据中无法清晰表达的字段,用一个附件图片或附件文档表示是最好的方法了.比如物料清单附加一张CAD图纸,销售订单评审功能中附加客户的各种表格,通用附件功能对系统起 ...

  5. C#开发微信门户及应用(25)-微信企业号的客户端管理功能

    我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...

  6. C#开发微信门户及应用(37)--微信公众号标签管理功能

    微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能.开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建.查询.修改.删除等操作, ...

  7. AgileEAS.NET SOA 中间件Web运行容器管理功能已全部开源,欢迎大家下载、使用、反馈

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  8. yii2-basic后台管理功能开发之三:自定义GridView列显示

    在第二篇 yii2-basic后台管理功能开发之二:创建CRUD增删改查 中,我们利用gii工具生成的结果一般并不是我们想要的结果. 我们需要根据自己的需求自定义列显示.我遇到的主要是一下变更: 时间 ...

  9. [.NET领域驱动设计实战系列]专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能

    一.引言 在当前的电子商务平台中,用户下完订单之后,然后店家会在后台看到客户下的订单,然后店家可以对客户的订单进行发货操作.此时客户会在自己的订单状态看到店家已经发货.从上面的业务逻辑可以看出,当用户 ...

随机推荐

  1. Solr使用初探——SolrJ的使用

    二.SolrJ的使用 SolrJ覆盖了solr的全部功能,下面将自己在实际开发中所使用的程序粘贴出来并适当加以解释,由于本人比较菜,代码书写不是那么的精练,还请见谅. 1.  创建solrserver ...

  2. Object-C类目(Category)

    类目是Object-C中最有用的一个特性.实质上,类目允许你为一个已存在的类添加一些方法而不用子类化该类,也不需要你了解该类的实现细节. 这是特别有用的,因为你可以给一个内建的对象添加方法.当你想在你 ...

  3. C#下如何用NPlot绘制期货股票K线图(2):读取数据文件让K线图自动更新

    [内容介绍]上一篇介绍了K线图的基本绘制方法,但很不完善,本篇增加了它直接读取数据的功能,这对于金融市场的数据量大且又需要动态刷新功能的实现很重要. [实现方法] 1.需要一个数据文件,这里用的是直接 ...

  4. javascript——四种函数调用形式

    此文的目的是分析函数的四种调用形式,弄清楚函数中this的意义,明确构造函对象的过程,学会使用上下文调用函数. 在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而 ...

  5. 基于SSM框架的简易的分页功能——包含maven项目的搭建

    新人第一次发帖,有什么不对的地方请多多指教~~ 分页这个功能经常会被使用到,我之前学习的时候找了很多资源,可都看不懂(笨死算了),最后还是在朋友帮助下做出了这个分页.我现在把我所能想到的知识 做了一个 ...

  6. 给python类动态添加方法(method)

    群里有人问如何做到 def foo(): pass class Bar(object): pass Bar.set_instance_method(foo) b = Bar() b.foo() 这个其 ...

  7. Make Ubuntu 14.04 Fullscreen and virtualbox

    sudo apt-get remove libcheese-gtk23 sudo apt-get install xserver-xorg-core sudo apt-get install virt ...

  8. 构建 struts2 spring3 mybatis 的maven项目 构建 pom.xml

    学习maven项目时 搭建个ssm项目 算是给自己留个备份吧 环境说明: MyEclipse10 Maven   3.2.3 框架: struts2    2.3.24.1 spring3    3. ...

  9. jQuery DataTables 插件使用笔记

    初始化 在页面中 <!DOCTYPE html> <html> <head> <link rel="stylesheet" type=&q ...

  10. 使用自定义 jQuery 插件的一个选项卡Demo

    前几天闲着没事,想着编写一个 jQuery 插件,或许这将是一个美好的开始. 这里是html页面: <!DOCTYPE html> <html lang="en" ...