using System; using System.Collections.Generic; using System.Text; using System.Data; //using System.Linq; using WeiSha.Common; using Song.Entities; using WeiSha.Data; using Song.ServiceInterfaces; using System.Data.Common; using System.Xml.Serialization; using System.Threading; using System.Xml; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using System.IO; using pili_sdk; namespace Song.ServiceImpls { public class OutlineCom : IOutline { #region 课程章节管理 /// /// 添加章节 /// /// 业务实体 public void OutlineAdd(Outline entity) { using (DbTrans tran = Gateway.Default.BeginTrans()) { try { if (entity.Org_ID <= 0) { Song.Entities.Organization org = Business.Do().OrganCurrent(); if (org != null) entity.Org_ID = org.Org_ID; } //所属专业 if (entity.Sbj_ID <= 0 && entity.Cou_ID > 0) { Song.Entities.Course cou = Business.Do().CourseSingle(entity.Cou_ID); entity.Sbj_ID = cou.Sbj_ID; } //计算排序号 object obj = tran.Max(Outline._.Ol_Tax, Outline._.Cou_ID == entity.Cou_ID && Outline._.Ol_PID == entity.Ol_PID); entity.Ol_Tax = obj is int ? (int)obj + 1 : 1; //唯一id string uid = string.IsNullOrWhiteSpace(entity.Ol_UID) ? WeiSha.Common.Request.UniqueID() : entity.Ol_UID; do { uid = WeiSha.Common.Request.UniqueID(); } while (Gateway.Default.Count(Outline._.Ol_UID == uid) > 0); entity.Ol_UID = uid; ////层级 //entity.Ol_Level = _ClacLevel(entity); //entity.Ol_XPath = _ClacXPath(entity); //如果是直播章节 if (entity.Ol_IsLive) { string liveid = string.Format("{0}_{1}_{2}", entity.Cou_ID, entity.Ol_ID, entity.Ol_UID); try { pili_sdk.pili.Stream stream = Business.Do().StreamCreat(liveid); entity.Ol_LiveID = stream.Title; } catch (Exception ex) { throw new Exception("无法创建直播流," + ex.Message); } tran.Update(Course._.Cou_ExistLive, true, Course._.Cou_ID == entity.Cou_ID); } tran.Save(entity); tran.Commit(); this.OnSave(null, EventArgs.Empty); } catch (Exception ex) { tran.Rollback(); throw ex; } finally { tran.Close(); } } } /// /// 批量添加章节,可用于导入时 /// /// 机构id /// 专业id /// 课程(或课程)id /// 名称,可以是用逗号分隔的多个名称 /// public Outline OutlineBatchAdd(int orgid, int sbjid, int couid, string names) { //整理名称信息 names = names.Replace(",", ","); List listName = new List(); foreach (string str in names.Split(',')) { string s = str.Replace("\n", "").Replace(" ", "").Replace("\t", "").Replace("\r", ""); if (s.Trim() != "") listName.Add(s.Trim()); } // int pid = 0; Song.Entities.Outline last = null; for (int i = 0; i < listName.Count; i++) { Song.Entities.Outline current = OutlineIsExist(orgid, sbjid, couid, pid, listName[i]); if (current == null) { current = new Outline(); current.Ol_Name = listName[i]; current.Ol_IsUse = true; current.Org_ID = orgid; current.Sbj_ID = sbjid; current.Cou_ID = couid; current.Ol_PID = pid; current.Ol_IsFinish = true; //默认为完结 this.OutlineAdd(current); } last = current; pid = current.Ol_ID; } return last; } /// /// 是否已经存在章节 /// /// 机构id /// 专业id /// 课程(或课程)id /// 上级id /// /// public Outline OutlineIsExist(int orgid, int sbjid, int couid, int pid, string name) { WhereClip wc = Outline._.Org_ID == orgid; if (sbjid > 0) wc &= Outline._.Sbj_ID == sbjid; if (couid > 0) wc &= Outline._.Cou_ID == couid; if (pid >= 0) wc &= Outline._.Ol_PID == pid; return Gateway.Default.From().Where(wc && Outline._.Ol_Name == name.Trim()).ToFirst(); } /// /// 修改章节 /// /// 业务实体 public void OutlineSave(Outline entity) { Outline old = Gateway.Default.From().Where(Outline._.Ol_ID == entity.Ol_ID).ToFirst(); if (old.Ol_PID != entity.Ol_PID) { object obj = Gateway.Default.Max(Outline._.Ol_Tax, Outline._.Org_ID == entity.Org_ID && Outline._.Ol_PID == entity.Ol_PID); entity.Ol_Tax = obj is int ? (int)obj + 1 : 0; } //如果有下级,设置为章节节点 int childCount = Gateway.Default.Count(Outline._.Ol_PID == entity.Ol_ID); entity.Ol_IsNode = childCount > 0; //如果有视频,设置视频节点 int videoCount = Gateway.Default.Count(Accessory._.As_Type == "CourseVideo" && Accessory._.As_Uid==entity.Ol_UID); entity.Ol_IsVideo = videoCount > 0; //路径 entity.Ol_Level = _ClacLevel(entity); entity.Ol_XPath = _ClacXPath(entity); //如果是直播章节 if (entity.Ol_IsLive) { pili_sdk.pili.Stream stream = null; if (string.IsNullOrWhiteSpace(entity.Ol_LiveID)) { try { stream = Business.Do().StreamCreat(); } catch (Exception ex) { //throw new Exception("直播流创建失败," + ex.Message); } if (stream != null) entity.Ol_LiveID = stream.Title; } else { try { stream = pili_sdk.Pili.API().GetForTitle(entity.Ol_LiveID); if (stream != null) pili_sdk.Pili.API().Enable(stream); } catch { } } } else { //禁用直播 if (!string.IsNullOrWhiteSpace(entity.Ol_LiveID)) { pili_sdk.pili.Stream stream = pili_sdk.Pili.API().GetForTitle(entity.Ol_LiveID); if (stream != null) pili_sdk.Pili.API().Disable(stream); } } Gateway.Default.Save(entity); Business.Do().IsLiveCourse(entity.Cou_ID, true); this.OnSave(entity, EventArgs.Empty); } /// /// 更新章节的试题数 /// /// 章节Id /// 试题数 /// public int UpdateQuesCount(int olid, int count) { Gateway.Default.Update(Outline._.Ol_QuesCount, count, Outline._.Ol_ID == olid); return count; } /// /// 导入章节,导入时不立即生成缓存 /// /// public void OutlineInput(Outline entity) { //计算排序号 object obj = Gateway.Default.Max(Outline._.Ol_Tax, Outline._.Cou_ID == entity.Cou_ID && Outline._.Ol_PID == entity.Ol_PID); entity.Ol_Tax = obj is int ? (int)obj + 1 : 1; if (string.IsNullOrWhiteSpace(entity.Ol_UID)) entity.Ol_UID = WeiSha.Common.Request.UniqueID(); //层级 entity.Ol_Level = _ClacLevel(entity); entity.Ol_XPath = _ClacXPath(entity); Gateway.Default.Save(entity); } /// /// 导出课程章节到Excel /// /// /// 课程ID /// public string OutlineExport4Excel(string path, int couid) { HSSFWorkbook hssfworkbook = new HSSFWorkbook(); //xml配置文件 XmlDocument xmldoc = new XmlDocument(); string confing = WeiSha.Common.App.Get["ExcelInputConfig"].VirtualPath + "课程章节.xml"; xmldoc.Load(WeiSha.Common.Server.MapPath(confing)); XmlNodeList nodes = xmldoc.GetElementsByTagName("item"); //当前课程的所有章节 Song.Entities.Outline[] outls = this.OutlineCount(couid, -1, null, -1); DataTable dt = WeiSha.WebControl.Tree.ObjectArrayToDataTable.To(outls); WeiSha.WebControl.Tree.DataTableTree tree = new WeiSha.WebControl.Tree.DataTableTree(); tree.IdKeyName = "OL_ID"; tree.ParentIdKeyName = "OL_PID"; tree.TaxKeyName = "Ol_Tax"; tree.Root = 0; dt = tree.BuilderTree(dt); //取最大深度 int level = 0; foreach (Outline ol in outls) { if (ol.Ol_Level > level) level = ol.Ol_Level; } Song.Entities.Course course = Business.Do().CourseSingle(couid); ISheet sheet = hssfworkbook.CreateSheet(course.Cou_Name); //创建工作簿对象 //创建数据行对象 IRow rowHead = sheet.CreateRow(0); int index = 0; for (int i = 0; i < nodes.Count; i++) { //是否导出 string exExport = nodes[i].Attributes["export"] != null ? nodes[i].Attributes["export"].Value : ""; if (exExport.ToLower() == "false") continue; //如果是章节,可能存在多级 if (nodes[i].Attributes["Column"].Value == "章节名称" && level > 0) { index = i; rowHead.CreateCell(i).SetCellValue(nodes[i].Attributes["Column"].Value); for (int l = 1; l <= level + 1; l++) { rowHead.CreateCell(i + l).SetCellValue(nodes[i].Attributes["Column"].Value + l.ToString()); } } else { if (i > index) rowHead.CreateCell(i + level).SetCellValue(nodes[i].Attributes["Column"].Value); else rowHead.CreateCell(i).SetCellValue(nodes[i].Attributes["Column"].Value); } } //生成数据行 ICellStyle style_size = hssfworkbook.CreateCellStyle(); style_size.WrapText = true; for (int i = 0; i < dt.Rows.Count; i++) { IRow row = sheet.CreateRow(i + 1); //创建Excel行 DataRow obj = dt.Rows[i]; //数据项 for (int j = 0; j < nodes.Count; j++) { string exExport = nodes[j].Attributes["export"] != null ? nodes[j].Attributes["export"].Value : ""; //是否导出 if (exExport.ToLower() == "false") continue; string column = nodes[j].Attributes["Column"] != null ? nodes[j].Attributes["Column"].Value : ""; string field = nodes[j].Attributes["Field"] != null ? nodes[j].Attributes["Field"].Value : ""; string format = nodes[j].Attributes["Format"] != null ? nodes[j].Attributes["Format"].Value : ""; string datatype = nodes[j].Attributes["DataType"] != null ? nodes[j].Attributes["DataType"].Value : ""; string defvalue = nodes[j].Attributes["DefautValue"] != null ? nodes[j].Attributes["DefautValue"].Value : ""; string value = ""; switch (datatype) { case "date": DateTime tm = Convert.ToDateTime(obj); value = tm > DateTime.Now.AddYears(-100) ? tm.ToString(format) : ""; break; default: value = obj.ToString(); break; } if (defvalue.Trim() != "") { foreach (string s in defvalue.Split('|')) { string h = s.Substring(0, s.IndexOf("=")); string f = s.Substring(s.LastIndexOf("=") + 1); if (value == h) value = f; } } row.CreateCell(j).SetCellValue(value); } } //输出成Excel文件 FileStream file = new FileStream(path, FileMode.Create); hssfworkbook.Write(file); file.Close(); return path; } /// /// 删除章节 /// /// 业务实体 public void OutlineDelete(Outline entity) { if (entity == null) return; List acs = Business.Do().GetAll(entity.Ol_UID); using (DbTrans tran = Gateway.Default.BeginTrans()) { try { //删除附件 Business.Do().Delete(entity.Ol_UID, tran); //先清理试题 tran.Delete(Questions._.Ol_ID == entity.Ol_ID); //清除学习记录 tran.Delete(LogForStudentStudy._.Ol_ID == entity.Ol_ID); tran.Delete(LogForStudentQuestions._.Ol_ID == entity.Ol_ID); //删除章节 tran.Delete(Outline._.Ol_ID == entity.Ol_ID); tran.Commit(); //删除直播流 if (!string.IsNullOrWhiteSpace(entity.Ol_LiveID)) { try { Pili.API().Delete(entity.Ol_LiveID); } catch { } } this.OnDelete(entity, null); } catch (Exception ex) { tran.Rollback(); throw ex; } finally { tran.Close(); } } } /// /// 删除,按主键ID; /// /// 实体的主键 public void OutlineDelete(int identify) { Song.Entities.Outline ol = this.OutlineSingle(identify); this.OutlineDelete(ol); } /// /// 获取单一实体对象,按主键ID; /// /// 实体的主键 /// public Outline OutlineSingle(int identify) { //当前章节 Outline curr = null; //try //{ // //从缓存中读取 // List list = WeiSha.Common.Cache.Data.List; // if (list == null || list.Count < 1) list = this.OutlineBuildCache(); // List tm = (from l in list // where l.Ol_ID == identify // select l).ToList(); // if (tm.Count > 0) curr = tm[0]; //} //catch //{ //} if (curr == null) curr = Gateway.Default.From().Where(Outline._.Ol_ID == identify).ToFirst(); return curr; } /// /// 获取单一实体对象,按唯一值,即UID; /// /// 全局唯一值 /// public Outline OutlineSingle(string uid) { //当前章节 Outline curr = null; ////从缓存中读取 //List list = WeiSha.Common.Cache.Data.List; //if (list == null || list.Count < 1) list = this.OutlineBuildCache(); //List tm = (from l in list // where l.Ol_UID == uid // select l).ToList(); //if (tm.Count > 0) curr = tm[0]; if (curr == null) curr = Gateway.Default.From().Where(Outline._.Ol_UID == uid).ToFirst(); return curr; } /// /// 获取某个课程内的章节,按级别取 /// /// 课程ID /// 多级名称 /// public Outline OutlineSingle(int couid, List names) { Outline curr = null; int index = 0; while (curr != null && index >= names.Count) { curr = Gateway.Default.From(). Where(Outline._.Cou_ID == couid && Outline._.Ol_Name == names[index]) .ToFirst(); } return curr; } /// /// 当前章节下的所有子章节id /// /// /// public List TreeID(int id) { List ints = new List(); Outline ol = this.OutlineSingle(id); if (ol == null) return ints; //取同一个课程下的所有章节 Outline[] ols = this.OutlineCount(ol.Cou_ID, -1, true, -1); ints = _treeid(id, ols); return ints; } private List _treeid( int id,Outline[] ols) { List list = new List(); list.Add(id); foreach (Outline o in ols) { if (o.Ol_PID != id) continue; List tm = _treeid(o.Ol_ID, ols); foreach (int t in tm) list.Add(t); } return list; } /// /// 获取某个课程下第一个章节 /// /// 课程Id /// 是否包括只是允许的章节,null取所有范围,true只是允许采用的章节,false反之 /// public Outline OutlineFirst(int couid, bool? isUse) { Song.Entities.Outline[] outlines = null; WhereClip wc = Outline._.Cou_ID == couid; if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); outlines = Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(); Song.Entities.Outline ol = null; if (outlines != null && outlines.Length > 0) { foreach (Song.Entities.Outline t in outlines) { if (t.Ol_PID == 0) { ol = t; break; } } if (ol == null) ol = outlines[0]; } return ol; } /// /// 获取章节名称,如果为多级,则带上父级名称 /// /// /// public string OutlineName(int identify) { Outline entity = this.OutlineSingle(identify); if (entity == null) return ""; string xpath = entity.Ol_Name; Song.Entities.Outline tm = Gateway.Default.From().Where(Outline._.Ol_ID == entity.Ol_PID).ToFirst(); while (tm != null) { xpath = tm.Ol_Name + "," + xpath; if (tm.Ol_PID == 0) break; if (tm.Ol_PID != 0) { tm = Gateway.Default.From().Where(Outline._.Ol_ID == entity.Ol_PID).ToFirst(); } } return xpath; } /// /// 获取所有课程章节 /// /// 所属课程id /// /// public Outline[] OutlineAll(int couid, bool? isUse) { ////从缓存中读取 //try //{ // List list = WeiSha.Common.Cache.Data.List; // if (list == null || list.Count < 1) list = this.OutlineBuildCache(); // //linq查询 // var from = from l in list select l; // if (couid > 0) from = from.Where(p => p.Cou_ID == couid); // if (isUse != null) from = from.Where(p => p.Ol_IsUse == (bool)isUse); // List tm = from.OrderBy(c => c.Ol_Tax).ToList(); // if (tm.Count > 0) return tm.ToArray(); //} //catch //{ //} //orm查询 WhereClip wc = new WhereClip(); if (couid > 0) wc.And(Outline._.Cou_ID == couid); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(); } #region 生成树形结构的章节列表 /// /// 生成树形结构的章节列表 /// /// /// public DataTable OutlineTree(Song.Entities.Outline[] outlines) { //计算树形的运算时间 //DateTime beforDT = System.DateTime.Now; //WeiSha.Common.Log.Debug(this.GetType().Name, "---开始计算章节树形:" + beforDT.ToString("yyyy年MM月dd日 hh:mm:ss")); DataTable dt = WeiSha.WebControl.Tree.ObjectArrayToDataTable.To(outlines); WeiSha.WebControl.Tree.DataTableTree tree = new WeiSha.WebControl.Tree.DataTableTree(); tree.IdKeyName = "OL_ID"; tree.ParentIdKeyName = "OL_PID"; tree.TaxKeyName = "Ol_Tax"; tree.Root = 0; dt = tree.BuilderTree(dt); //DateTime afterDT = System.DateTime.Now; //TimeSpan ts = afterDT.Subtract(beforDT); //if (ts.TotalMilliseconds >= 500) //{ // //WeiSha.Common.Log.Debug(this.GetType().Name, string.Format("计算章节树形,耗时:{0}ms", ts.TotalMilliseconds)); //} return buildOutlineTree(dt, 0, 0, ""); } /// /// 生成章节的等级序号 /// /// /// 上级ID /// 层深 /// 序号前缀 /// private DataTable buildOutlineTree(DataTable outlines, int pid, int level, string prefix) { if (outlines == null) return null; int index = 1; foreach (DataRow ol in outlines.Rows) { if (Convert.ToInt32(ol["Ol_PID"]) == pid) { ol["Ol_XPath"] = prefix + index.ToString() + "."; ol["Ol_Level"] = level; buildOutlineTree(outlines, Convert.ToInt32(ol["Ol_ID"]), level + 1, ol["Ol_XPath"].ToString()); index++; } } return outlines; } #endregion /// /// 清除章节下的试题、附件等 /// /// public void OutlineClear(int identify) { //清理试题 Gateway.Default.Delete(Questions._.Ol_ID == identify); //清理附件 Outline ol = this.OutlineSingle(identify); if (ol != null) { Business.Do().Delete(ol.Ol_UID); } } /// /// 清理无效章节 /// /// 课程ID /// public int OutlineCleanup(int couid) { WhereClip wc = new WhereClip(); if (couid > 0) wc &= Outline._.Cou_ID == couid; List outs = Gateway.Default.From().Where(wc && Outline._.Ol_PID != 0).ToList(); int count = 0; foreach (Outline o in outs) { using (DbTrans tran = Gateway.Default.BeginTrans()) { try { int num = tran.Count(Outline._.Ol_ID == o.Ol_PID); if (num <= 0) { //先清理学习记录 tran.Delete(LogForStudentStudy._.Ol_ID == o.Ol_ID); tran.Delete(Outline._.Ol_ID == o.Ol_ID); tran.Commit(); count++; } } catch (Exception ex) { tran.Rollback(); throw ex; } finally { tran.Close(); } } } return count; } //private static object lock_cache_build = new object(); ///// ///// 构建缓存 ///// //public List OutlineBuildCache() //{ // lock (lock_cache_build) // { // try // { // WeiSha.Common.Cache.Data.Clear(); // } // catch // { // } // finally // { // Song.Entities.Outline[] outls = Gateway.Default.From().ToArray(); // WeiSha.Common.Cache.Data.Fill(outls); // } // ////计算每个章节下的试题数 // //foreach (Outline o in outls) // //{ // // o.Ol_QuesCount = this.QuesOfCount(o.Ol_ID, -1, true, true); // // Gateway.Default.Save(o); // //} // return WeiSha.Common.Cache.Data.List; // } //} /// /// 获取指定个数的课程列表 /// /// 所属课程id /// /// 取多少条记录,如果小于等于0,则取所有 /// public Outline[] OutlineCount(int couid, string search, bool? isUse, int count) { return OutlineCount(couid, null, search, isUse, count); } /// /// 直播中的章节 /// /// /// /// public List OutlineLiving(int orgid, int count) { pili_sdk.pili.StreamList streams = null; try { streams = Business.Do().StreamList(string.Empty, true, count); } catch { return null; } if (streams == null || streams.Streams.Count < 1) return null; List list = new List(); foreach (pili_sdk.pili.Stream stream in streams.Streams) { WhereClip wc = new WhereClip(); if (orgid > 0) wc &= Outline._.Org_ID == orgid; Outline outline = Gateway.Default.From().Where( wc & Outline._.Ol_LiveID == stream.Title).ToFirst(); if (outline != null) list.Add(outline); } return list; } /// /// 获取指定个数的章节列表 /// /// /// 是否是直播章节 /// /// /// /// public Outline[] OutlineCount(int couid, bool? islive, string search, bool? isUse, int count) { WhereClip wc = Outline._.Cou_ID == couid; if (!string.IsNullOrWhiteSpace(search)) wc.And(Outline._.Ol_Name.Like("%" + search + "%")); if (islive != null) wc.And(Outline._.Ol_IsLive == (bool)islive); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(count); } public Outline[] OutlineCount(int couid, int pid, bool? isUse, int count) { //List tm = null; //try //{ // //从缓存中读取 // List list = WeiSha.Common.Cache.Data.List; // if (list == null || list.Count < 1) list = this.OutlineBuildCache(); // //linq查询 // var from = from l in list select l; // if (couid > 0) from = from.Where(p => p.Cou_ID == couid); // if (pid >= 0) from = from.Where(p => p.Ol_PID == pid); // if (isUse != null) from = from.Where(p => p.Ol_IsUse == (bool)isUse); // if (count > 0) // { // tm = from.OrderBy(c => c.Ol_Tax).Take(count).ToList(); // } // else // { // tm = from.OrderBy(c => c.Ol_Tax).ToList(); // } //} //catch //{ //} //if (tm != null && tm.Count > 0) return tm.ToArray(); //从数据库读取 WhereClip wc = Outline._.Cou_ID == couid; if (pid >= 0) wc.And(Outline._.Ol_PID == pid); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(count); } public Outline[] OutlineCount(int orgid, int sbjid, int couid, int pid, bool? isUse, int count) { WhereClip wc = new WhereClip(); if (orgid > 0) wc &= Outline._.Org_ID == orgid; if (sbjid > 0) wc &= Outline._.Sbj_ID == sbjid; if (couid > 0) wc &= Outline._.Cou_ID == couid; if (pid > -1) wc &= Outline._.Ol_PID == pid; if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(count); } /// /// 当前课程下的章节数 /// /// 课程id /// /// /// public int OutlineOfCount(int couid, int pid, bool? isUse) { WhereClip wc = Outline._.Cou_ID == couid; if (pid >= 0) wc.And(Outline._.Ol_PID == pid); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.Count(wc); } public int OutlineOfCount(int orgid, int sbjid, int couid, int pid, bool? isUse) { WhereClip wc = new WhereClip(); if (orgid > 0) wc &= Outline._.Org_ID == orgid; if (sbjid > 0) wc &= Outline._.Sbj_ID == sbjid; if (couid > 0) wc &= Outline._.Cou_ID == couid; if (pid > -1) wc &= Outline._.Ol_PID == pid; if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.Count(wc); } /// /// 当前课程下的章节数 /// /// 课程id /// 父id /// 是否启用 /// 是否有视频 /// public int OutlineOfCount(int couid, int pid, bool? isUse, bool? isVideo, bool? isFinish) { WhereClip wc = new WhereClip(); if (couid > 0) wc &= Outline._.Cou_ID == couid; if (pid > -1) wc &= Outline._.Ol_PID == pid; if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); if (isVideo != null) wc.And(Outline._.Ol_IsVideo == (bool)isVideo); if (isFinish != null) wc.And(Outline._.Ol_IsFinish == (bool)isFinish); return Gateway.Default.Count(wc); } /// /// 是否有子级章节 /// /// 课程id /// 父id /// /// public bool OutlineIsChildren(int couid, int pid, bool? isUse) { WhereClip wc = Outline._.Cou_ID == couid; if (pid >= 0) wc.And(Outline._.Ol_PID == pid); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); int count = Gateway.Default.Count(wc); return count > 0; } /// /// 当前章节是否有试题 /// /// /// /// public bool OutlineIsQues(int olid, bool? isUse) { WhereClip wc = Questions._.Ol_ID == olid; if (isUse != null) wc.And(Questions._.Qus_IsUse == (bool)isUse); int count = Gateway.Default.Count(wc); return count > 0; } /// /// 当前章节的子级章节 /// /// /// /// /// public Outline[] OutlineChildren(int couid, int pid, bool? isUse,int count) { WhereClip wc = Outline._.Cou_ID == couid; if (pid >= 0) wc.And(Outline._.Ol_PID == pid); if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(count); } /// /// 分页取课程章节的信息 /// /// 所属课程id /// /// /// /// /// /// public Outline[] OutlinePager(int couid, bool? isUse, string searTxt, int size, int index, out int countSum) { WhereClip wc = Outline._.Cou_ID == couid; if (isUse != null) wc.And(Outline._.Ol_IsUse == (bool)isUse); if (!string.IsNullOrWhiteSpace(searTxt)) wc.And(Outline._.Ol_Name.Like("%" + searTxt + "%")); countSum = Gateway.Default.Count(wc); return Gateway.Default.From().Where(wc).OrderBy(Outline._.Ol_Tax.Asc).ToArray(size, (index - 1) * size); } /// /// 当前章节的试题 /// /// /// /// /// /// public Questions[] QuesCount(int olid, int type, bool? isUse, int count) { WhereClip wc = new WhereClip(); if (olid > 0) wc.And(Questions._.Ol_ID == olid); if (type > 0) wc.And(Questions._.Qus_Type == type); if (isUse != null) wc.And(Questions._.Qus_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(Questions._.Qus_ID.Desc).ToArray(count); } /// /// 当前章节有多少道试题 /// /// /// /// /// 是否取所有(当前章节下所有子章节的试题一块算) /// public int QuesOfCount(int olid, int type, bool? isUse, bool isAll) { WhereClip wc = Questions._.Qus_IsError == false && Questions._.Qus_IsWrong == false; if (type > 0) wc.And(Questions._.Qus_Type == type); if (isUse != null) wc.And(Questions._.Qus_IsUse == (bool)isUse); if (olid > 0 && isAll) { WhereClip wcSbjid = new WhereClip(); List list = TreeID(olid); foreach (int l in list) wcSbjid.Or(Questions._.Ol_ID == l); wc.And(wcSbjid); } return Gateway.Default.Count(wc); } /// /// 将当前项目向上移动;仅在当前对象的同层移动,即同一父节点下的对象这前移动; /// /// /// 如果已经处于顶端,则返回false;移动成功,返回true public bool OutlineUp(int couid, int id) { //当前对象 Outline current = Gateway.Default.From().Where(Outline._.Ol_ID == id).ToFirst(); int tax = (int)current.Ol_Tax; //上一个对象,即兄长对象;兄长不存则直接返回false; Outline prev = Gateway.Default.From() .Where(Outline._.Ol_Tax < tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == current.Ol_PID) .OrderBy(Outline._.Ol_Tax.Desc).ToFirst(); //有当前等级哥哥对像 if (prev != null) { //交换排序号 current.Ol_Tax = prev.Ol_Tax; prev.Ol_Tax = tax; using (DbTrans tran = Gateway.Default.BeginTrans()) { try { tran.Save(current); tran.Save(prev); tran.Commit(); } catch { tran.Rollback(); throw; } finally { tran.Close(); } } this.OnSave(null, EventArgs.Empty); return true; } else { if (current.Ol_PID == 0) return false; //没有当前等级哥哥对像 Song.Entities.Outline top = Gateway.Default.From().Where(Outline._.Ol_ID == current.Ol_PID).ToFirst(); if (top == null) return false; //父级的哥哥 Song.Entities.Outline topPrev = Gateway.Default.From() .Where(Outline._.Ol_Tax < top.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == top.Ol_PID) .OrderBy(Outline._.Ol_Tax.Desc).ToFirst(); if (topPrev == null) return false; //父级哥哥的子级的最大序号 object obj = Gateway.Default.Max(Outline._.Ol_Tax, Outline._.Ol_PID == topPrev.Ol_ID); current.Ol_Tax = obj is int ? (int)obj + 1 : 1; current.Ol_PID = topPrev.Ol_ID; current.Ol_Level = 1; Gateway.Default.Save(current); this.OnSave(null, EventArgs.Empty); return true; } } /// /// 将当前项目向下移动;仅在当前对象的同层移动,即同一父节点下的对象这前移动; /// /// /// 如果已经处于顶端,则返回false;移动成功,返回true public bool OutlineDown(int couid, int id) { //当前对象 Outline current = Gateway.Default.From().Where(Outline._.Ol_ID == id).ToFirst(); int tax = (int)current.Ol_Tax; //下一个对象,即弟弟对象;弟弟不存则直接返回false; Outline next = Gateway.Default.From() .Where(Outline._.Ol_Tax > tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == current.Ol_PID) .OrderBy(Outline._.Ol_Tax.Asc).ToFirst(); if (next != null) { current.Ol_Tax = next.Ol_Tax; next.Ol_Tax = tax; using (DbTrans tran = Gateway.Default.BeginTrans()) { try { tran.Save(current); tran.Save(next); tran.Commit(); } catch { tran.Rollback(); throw; } finally { tran.Close(); } } this.OnSave(null, EventArgs.Empty); return true; } else { if (current.Ol_PID == 0) return false; //没有当前等级父对象 Song.Entities.Outline parent = Gateway.Default.From().Where(Outline._.Ol_ID == current.Ol_PID).ToFirst(); if (parent == null) return false; //父级的弟弟 Song.Entities.Outline topNext = Gateway.Default.From() .Where(Outline._.Ol_Tax > parent.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == parent.Ol_PID) .OrderBy(Outline._.Ol_Tax.Asc).ToFirst(); if (topNext == null) return false; //父级弟弟的子级 Song.Entities.Outline[] child = this.OutlineCount(couid, topNext.Ol_ID, null, -1); using (DbTrans tran = Gateway.Default.BeginTrans()) { try { current.Ol_Tax = 1; current.Ol_PID = topNext.Ol_ID; tran.Save(current); //父级弟弟的子级的排序号重排 for (int i = 0; i < child.Length; i++) tran.Update(Outline._.Ol_Tax, i + 2, Outline._.Ol_ID == child[i].Ol_ID); tran.Commit(); } catch { tran.Rollback(); throw; } finally { tran.Close(); } } } this.OnSave(null, EventArgs.Empty); return true; } /// /// 将当前章节升级 /// /// /// public bool OutlineToLeft(int couid, int id) { //当前对象 Outline current = Gateway.Default.From().Where(Outline._.Ol_ID == id).ToFirst(); //当前父对象 Outline parent = Gateway.Default.From().Where(Outline._.Ol_ID == current.Ol_PID).ToFirst(); //顶级列表 Song.Entities.Outline[] top = Gateway.Default.From() .Where(Outline._.Ol_Tax > parent.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == parent.Ol_PID) .OrderBy(Outline._.Ol_Tax.Asc).ToArray(); //当前父的同级中,比自己大的子级(即自身后面的) Song.Entities.Outline[] child = Gateway.Default.From() .Where(Outline._.Ol_Tax > current.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == current.Ol_PID) .OrderBy(Outline._.Ol_Tax.Asc).ToArray(); // using (DbTrans tran = Gateway.Default.BeginTrans()) { try { current.Ol_PID = 0; current.Ol_Level = 0; current.Ol_Tax = parent.Ol_Tax + 1; current.Attach(); tran.Save(current); //处理升级后的顶级排序问题 for (int i = 0; i < top.Length; i++) { top[i].Ol_Tax = top[i].Ol_Tax + 1; top[i].Attach(); tran.Save(top[i]); } //处理升级后,同级的子级的排序号 for (int i = 0; i < child.Length; i++) { child[i].Ol_Tax = i + 1; child[i].Ol_PID = current.Ol_ID; child[i].Ol_Level = 1; child[i].Attach(); tran.Save(child[i]); } tran.Commit(); } catch { tran.Rollback(); throw; } finally { tran.Close(); } } this.OnSave(null, EventArgs.Empty); return true; } /// /// 将当前章节退级 /// /// /// public bool OutlineToRight(int couid, int id) { //当前对象 Outline current = Gateway.Default.From().Where(Outline._.Ol_ID == id).ToFirst(); if (current.Ol_Tax == 1) throw new WeiSha.Common.ExceptionForAlert("最顶级的第一个章节,不可以降级"); //上一个对象,即兄长对象;兄长不存则直接返回false; Outline prev = Gateway.Default.From() .Where(Outline._.Ol_Tax < current.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == current.Ol_PID) .OrderBy(Outline._.Ol_Tax.Desc).ToFirst(); object objmaxTax = Gateway.Default.Max(Outline._.Ol_Tax, Outline._.Ol_PID == prev.Ol_ID); int maxTax = objmaxTax is int ? (int)objmaxTax : 0; //当前对象的子级 Song.Entities.Outline[] child = Gateway.Default.From() .Where(Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == current.Ol_ID) .OrderBy(Outline._.Ol_Tax.Asc).ToArray(); //顶级列表 Song.Entities.Outline[] top = Gateway.Default.From() .Where(Outline._.Ol_Tax > prev.Ol_Tax && Outline._.Cou_ID == current.Cou_ID && Outline._.Ol_PID == prev.Ol_PID && Outline._.Ol_ID != current.Ol_ID) .OrderBy(Outline._.Ol_Tax.Asc).ToArray(); // using (DbTrans tran = Gateway.Default.BeginTrans()) { try { current.Ol_PID = prev.Ol_ID; current.Ol_Level = 1; current.Ol_Tax = maxTax + 1; tran.Save(current); //处理升级后,同级的子级的排序号 for (int i = 0; i < child.Length; i++) { child[i].Ol_Tax = i + 2 + maxTax; child[i].Ol_PID = prev.Ol_ID; child[i].Attach(); tran.Save(child[i]); } for (int i = 0; i < top.Length; i++) { top[i].Ol_Tax = top[i].Ol_Tax - 1; top[i].Attach(); tran.Save(top[i]); } tran.Commit(); } catch { tran.Rollback(); throw; } finally { tran.Close(); } } this.OnSave(null, EventArgs.Empty); return true; } #endregion #region 私有方法 /// /// 计算当前对象在多级分类中的层深 /// /// /// private int _ClacLevel(Song.Entities.Outline entity) { //if (entity.Ol_PID == 0) return 1; int level = 0; Song.Entities.Outline tm = Gateway.Default.From().Where(Outline._.Ol_ID == entity.Ol_PID).ToFirst(); while (tm != null) { level++; if (tm.Ol_PID == 0) break; if (tm.Ol_PID != 0) { tm = Gateway.Default.From().Where(Outline._.Ol_ID == tm.Ol_PID).ToFirst(); } } entity.Ol_Level = level; Gateway.Default.Save(entity); Song.Entities.Outline[] childs = Gateway.Default.From().Where(Outline._.Ol_PID == entity.Ol_ID).ToArray(); foreach (Outline s in childs) { _ClacLevel(s); } return level; } /// /// 计算当前对象在多级分类中的路径 /// /// /// private string _ClacXPath(Song.Entities.Outline entity) { //if (entity.Ol_PID == 0) return ""; string xpath = ""; Song.Entities.Outline tm = Gateway.Default.From().Where(Outline._.Ol_ID == entity.Ol_PID).ToFirst(); while (tm != null) { xpath = tm.Ol_ID + "," + xpath; if (tm.Ol_PID == 0) break; if (tm.Ol_PID != 0) { tm = Gateway.Default.From().Where(Outline._.Ol_ID == tm.Ol_PID).ToFirst(); } } entity.Ol_XPath = xpath; Gateway.Default.Save(entity); Song.Entities.Outline[] childs = Gateway.Default.From().Where(Outline._.Ol_PID == entity.Ol_ID).ToArray(); foreach (Outline s in childs) { _ClacXPath(s); } return xpath; } #endregion #region 章节视频事件 /// /// 添加章节中视频播放事件 /// /// public void EventAdd(OutlineEvent entity) { Song.Entities.Organization org = Business.Do().OrganCurrent(); if (org != null) entity.Org_ID = org.Org_ID; entity.Oe_CrtTime = DateTime.Now; Gateway.Default.Save(entity); } /// /// 修改播放事件 /// /// public void EventSave(OutlineEvent entity) { Gateway.Default.Save(entity); } /// /// 删除事件 /// /// public void EventDelete(OutlineEvent entity) { Gateway.Default.Delete(entity); } /// /// 删除事件 /// /// public void EventDelete(int identify) { Gateway.Default.Delete(OutlineEvent._.Oe_ID == identify); } /// /// 获取单一实体对象,按主键ID; /// /// 实体的主键 /// public OutlineEvent EventSingle(int identify) { return Gateway.Default.From().Where(OutlineEvent._.Oe_ID == identify).ToFirst(); } /// /// 返回章节下的事件 /// /// 课程ID /// 章节ID,不可以为零,否则会取所有 /// 事件类型,1为提醒,2为知识展示,3课堂提问,4实时反馈(例如,选择某项后跳转到某秒) /// /// public OutlineEvent[] EventAll(int couid, int olid, int type, bool? isUse) { WhereClip wc = OutlineEvent._.Ol_ID == olid; if (couid > 0) wc.And(OutlineEvent._.Oe_IsUse == (bool)isUse); if (type > 0) wc.And(OutlineEvent._.Oe_EventType == type); if (isUse != null) wc.And(OutlineEvent._.Oe_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(OutlineEvent._.Oe_TriggerPoint.Asc).ToArray(); } /// /// 返回章节下所有事件 /// /// 课程ID /// 章节的全局唯一值 /// /// /// public OutlineEvent[] EventAll(int couid, string uid, int type, bool? isUse) { WhereClip wc = OutlineEvent._.Ol_UID == uid; if (couid > 0) wc.And(OutlineEvent._.Oe_IsUse == (bool)isUse); if (type > 0) wc.And(OutlineEvent._.Oe_EventType == type); if (isUse != null) wc.And(OutlineEvent._.Oe_IsUse == (bool)isUse); return Gateway.Default.From().Where(wc).OrderBy(OutlineEvent._.Oe_TriggerPoint.Asc).ToArray(); } /// /// 获取试题类型的信息,事件类型:1为提醒,2为知识展示,3课堂提问,4实时反馈 /// /// /// public DataTable EventQues(int oeid) { OutlineEvent oev = Gateway.Default.From().Where(OutlineEvent._.Oe_ID == oeid).ToFirst(); if (oev == null) return null; //1为提醒,2为知识展示,3课堂提问,4实时反馈 if (oev.Oe_EventType != 3) return null; string xml = oev.Oe_Datatable; if (string.IsNullOrWhiteSpace(oev.Oe_Datatable) || oev.Oe_Datatable.Trim() == "") return null; //转成datatable try { XmlSerializer xmlSerial = new XmlSerializer(typeof(DataTable)); DataTable dt = (DataTable)xmlSerial.Deserialize(new System.IO.StringReader(oev.Oe_Datatable)); return dt; } catch { return null; } } /// /// 获取时间反馈的信息 /// /// /// public DataTable EventFeedback(int oeid) { OutlineEvent oev = Gateway.Default.From().Where(OutlineEvent._.Oe_ID == oeid).ToFirst(); if (oev == null) return null; //1为提醒,2为知识展示,3课堂提问,4实时反馈 if (oev.Oe_EventType != 4) return null; string xml = oev.Oe_Datatable; if (string.IsNullOrWhiteSpace(oev.Oe_Datatable) || oev.Oe_Datatable.Trim() == "") return null; //转成datatable try { XmlSerializer xmlSerial = new XmlSerializer(typeof(DataTable)); DataTable dt = (DataTable)xmlSerial.Deserialize(new System.IO.StringReader(oev.Oe_Datatable)); return dt; } catch { return null; } } #endregion #region 事件 public event EventHandler Save; public event EventHandler Add; public event EventHandler Delete; public void OnSave(object sender, EventArgs e) { if (sender != null) { //if (!(sender is Outline)) return; //Outline ol = (Outline)sender; //Song.Entities.Outline old = this.OutlineSingle(ol.Ol_ID); //ol.Ol_QuesCount = Business.Do().QuesOfCount(ol.Ol_ID, -1, true, true); //WeiSha.Common.Cache.Data.Update(old, ol); } else { //填充章节数据到缓存 //this.OutlineBuildCache(); } if (Save != null) Save(sender, e); } public void OnAdd(object sender, EventArgs e) { //当前对象(即sender),写入到缓存 if (sender != null) { //if (!(sender is Outline)) return; //Outline ol = (Outline)sender; //WeiSha.Common.Cache.Data.Add(ol); } if (Add != null) Add(sender, e); } public void OnDelete(object sender, EventArgs e) { //当前对象(即sender),写入到缓存 if (sender != null) { //if (!(sender is Outline)) return; //Outline ol = (Outline)sender; //WeiSha.Common.Cache.Data.Delete(ol); ////重建试题缓存(取所有试题进缓存) //new Thread(new ThreadStart(() => //{ // Song.Entities.Questions[] ques = Business.Do().QuesCount(-1, null, -1); // Song.ServiceImpls.QuestionsMethod.QuestionsCache.Singleton.Delete("all"); // Song.ServiceImpls.QuestionsMethod.QuestionsCache.Singleton.Add(ques, int.MaxValue, "all"); //})).Start(); } if (Delete != null) Delete(sender, e); } #endregion } }