Winform开发框架中实现信息阅读状态的显示和存储

在很多项目中,可能会有要求对一些数据的阅读状态进行记录,用户阅读过或者未阅读过,都做不同的标识,方便了解数据的状态。如在我的客户关系管理系统中,对于客户的状态进行跟踪,如果最近联系时间超过配置天数的,那么特别显示出来。类似的应用场景,还有很多地方应用到,如对于通知公告、流程记录、内部信息等状态查看都可能是这样的类型。那么如何解决这些通用的需求呢,是需要每个都设置一个表来记录这些状态吗?

1、应用需求场景

前面说了,我们可能在一些数据上需要记录不同用户的阅读状态,如下面是我客户关系管理系统里面,对于最近没有联系的客户列表,其中对他们的查看状态进行特别显示。
当然,在我们业务系统里面,可能还有其他类似的场景。



对于这些相似的需求我们把这些应用场景的状态,用一个表来存储它的数据变化就可以做到了,我们设计一个表TB_InformationStatus来存储这些数据的状态。



上面的Information_ID就是对应不同表数据的ID,Status为我们需要记录的状态,User_ID为对应使用人员,这样对于不同业务表,不同的人员都可以把他们的数据记录起来,供我们处理显示了。

2、功能实现

对于这个信息状态的记录表,我们需要定义几个接口来进行信息的处理。

/// <summary>
/// 设置状态
/// </summary>
/// <param name="UserID">用户ID</param>
/// <param name="InfoType">信息类型</param>
/// <param name="InfoID">信息主键ID</param>
/// <param name="Status">状态:0未读 1已读 </param>
void SetStatus(string UserID, InformationCategory InfoType, string InfoID, int Status);

/// <summary>
/// 匹配状态
/// </summary>
/// <param name="UserID">用户ID</param>
/// <param name="InfoType">信息类型</param>
/// <param name="InfoID">信息主键ID</param>
/// <param name="Status">状态:0未读 1已读 </param>
/// <returns></returns>
bool CheckStatus(string UserID, InformationCategory InfoType, string InfoID, int Status);
               
/// <summary>
/// 查看指定的记录是否已读
/// </summary>
/// <param name="UserID">用户ID</param>
/// <param name="InfoType">信息类型</param>
/// <param name="InfoID">信息主键ID</param>
/// <returns></returns>
bool IsReadedStatus(string UserID, InformationCategory InfoType, string InfoID);

我们设计了上面的辅助表TB_InformationStatus来存储这些数据的状态,但并没有改变主表的字段数据,但是我们在显示主表的数据的时候,联合处理一下就可以了。
以客户信息为例,我们联合处理,获得的数据,依旧是客户信息的列表,如下代码所示。

/// <summary>
/// 获取用户的最近未联系客户列表
/// </summary>
/// <returns></returns>
private List<CustomerInfo> GetUnContactList()
{
    string KeyName = "FollowExpireDays";
    int FollowExpireDays = config.AppConfigGet(KeyName).ToInt32();
    if (FollowExpireDays < 1)
    {
        FollowExpireDays = 1;
    }
    List<CustomerInfo> list = BLLFactory<Customer>.Instance.GetUnContactList(FollowExpireDays, LoginUserInfo.ID.ToString());
    return list;
}

在业务层,我们只需要构造我们的过滤条件获取到用户的数据,并处理它状态就可以了。

condition.AddCondition("LastContactDate", today.AddDays(-1 * FollowExpireDays), SqlOperator.LessThanOrEqual);
condition.AddCondition("Deleted", 0, SqlOperator.Equal);//不显示删除的
condition.AddCondition("Creator", userId, SqlOperator.Equal);//仅仅选择该用户的记录

string where = condition.BuildConditionSql().Replace("Where", "");

List<CustomerInfo> list = baseDal.Find(where);
foreach (CustomerInfo info in list)
{
    bool readed = BLLFactory<InformationStatus>.Instance.IsReadedStatus(userId, InformationCategory.客户联系, info.ID);
    info.Data1 = readed ? "已读" : "未读";
}

上面代码的Data1是我们实体类基类的属性,这里我们很方面用它来记录状态,否则我们需要把实体类集合转换为DataTable类型了。

这样我们返回的数据就带有这个记录的阅读状态,我们只需要在显示的时候,把Data1属性的别名修改一下就可以了。

/// <summary>
/// 绑定列表数据
/// </summary>
private void BindData()
{
    this.winGridViewPager1.DisplayColumns = displayColumns;
    this.winGridViewPager1.ColumnNameAlias = BLLFactory<Customer>.Instance.GetColumnNameAlias();//字段列显示名称转义
    this.winGridViewPager1.AddColumnAlias("Data1", "查看状态");

    List<CustomerInfo> list = GetUnContactList();
    this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<CustomerInfo>(list);
    this.winGridViewPager1.PrintTitle = "未联系客户信息列表";
}

3、功能扩展

为了更有效展示不同类型客户的记录,我们可能需要设置普通客户7天需要跟进,VIP客户5天跟进,高级VIP客户3天跟进的时效,也就是对于同一个记录,不同属性类型,可能要求不同。
我们如果要实现这个需求,那么就需要再另外一个表里面记录客户类型和间隔天数的数据了。



然后在业务逻辑层处理返回未联系客户的时候,对他们进行分别处理,获取数据后进行合并,如下代码所示。

/// <summary>
/// 获得指定间隔时间内未联系的客户列表
/// </summary>
/// <param name="unContactDays">和最后联系日期的间隔天数</param>
/// <param name="userId">当前用户</param>
/// <returns></returns>
public List<CustomerInfo> GetUnContactList(int unContactDays, string userId)
{
    List<CustomerInfo> listAll = new List<CustomerInfo>();

    //根据用户配置的信息进行逐条处理,然后合并记录
    List<CustomerAlarmInfo> alarmList = BLLFactory<CustomerAlarm>.Instance.FindByUser(userId);
    foreach (CustomerAlarmInfo alarmInfo in alarmList)
    {
        //如果存在高级查询对象信息,则使用高级查询条件,否则使用主表条件查询
        SearchCondition condition = new SearchCondition();
        DateTime today = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd"));
        int FollowExpireDays = alarmInfo.Days;
        if (FollowExpireDays < 1)
        {
            FollowExpireDays = 1;
        }

        condition.AddCondition("Grade", alarmInfo.Grade, SqlOperator.Equal);
        condition.AddCondition("LastContactDate", today.AddDays(-1 * FollowExpireDays), SqlOperator.LessThanOrEqual);
        condition.AddCondition("Deleted", 0, SqlOperator.Equal);//不显示删除的
        condition.AddCondition("Creator", userId, SqlOperator.Equal);//仅仅选择该用户的记录

        string where = condition.BuildConditionSql().Replace("Where", "");

        List<CustomerInfo> list = baseDal.Find(where);
        foreach (CustomerInfo info in list)
        {
            bool readed = BLLFactory<InformationStatus>.Instance.IsReadedStatus(userId, InformationCategory.客户联系, info.ID);
            info.Data1 = readed ? "已读" : "未读";
        }

        listAll.AddRange(list);
    }
    return listAll;
}

对于混合架构上的应用,我们注意到接口的地方,需要使用一个枚举的参数(信息类别名称),我们在接口定义的时候,需要特别声明几个地方,否则容易出现错误。

枚举的对象需要声明一下的。

/// <summary>
/// 信息分类
/// </summary>
[DataContract]
public enum InformationCategory 
{
    [EnumMember]
    客户联系,

    [EnumMember]
    通知公告,

    [EnumMember]
    其他 
};

定义的WCF接口,用到了枚举类型的参数,也需要特别声明枚举的类型

[ServiceContract]
[ServiceKnownType(typeof(InformationCategory))]
public interface IInformationStatusService : IBaseService<InformationStatusInfo>
{
    /// <summary>
    /// 设置状态
    /// </summary>
    /// <param name="UserID">用户ID</param>
    /// <param name="InfoType">信息类型</param>
    /// <param name="InfoID">信息主键ID</param>
    /// <param name="Status">状态:0未读 1已读 </param>
    [OperationContract]
    void SetStatus(string UserID, InformationCategory InfoType, string InfoID, int Status);

    /// <summary>
    /// 匹配状态
    /// </summary>
    /// <param name="UserID">用户ID</param>
    /// <param name="InfoType">信息类型</param>
    /// <param name="InfoID">信息主键ID</param>
    /// <param name="Status">状态:0未读 1已读 </param>
    /// <returns></returns>
    [OperationContract]
    bool CheckStatus(string UserID, InformationCategory InfoType, string InfoID, int Status);
                   
    /// <summary>
    /// 查看指定的记录是否已读
    /// </summary>
    /// <param name="UserID">用户ID</param>
    /// <param name="InfoType">信息类型</param>
    /// <param name="InfoID">信息主键ID</param>
    /// <returns></returns>
    [OperationContract]
    bool IsReadedStatus(string UserID, InformationCategory InfoType, string InfoID);
}

注意上这些,使用枚举就一切都顺利了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,727评论 2 9
  • 每天过好自己, 余下的无须多想, 老天自有安排, 该来的都在路上。
    渡岸孤山阅读 396评论 16 26
  • 一、参数设置 1.参数类型 a)stringb)intc)float 2.未指定参数类型 在url中传入参数时,如...
    kris_lp阅读 9,590评论 1 1
  • 生活总得有些变化,辞了班主任的工作,好好教书吧。
    3rose阅读 206评论 0 0
  • 宝剑锋自磨砺出,梅花香自苦寒来,一个人所有的从容与淡定,都是磨砺出来的。只有能把小事做到精湛的人,才能让别人...
    駿澤Abin阅读 655评论 3 16