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);
    }

注意上這些,使用枚舉就一切都順利了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM