初步可用后台
This commit is contained in:
parent
104cfb2463
commit
c448afdd1d
@ -1,18 +0,0 @@
|
||||
using JXCMS.CMS.Attribute;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JXCMS.CMS.Admin.Controllers
|
||||
{
|
||||
[Area("Admin")]
|
||||
[AdminAuthentication]
|
||||
public class ArticleController : Controller
|
||||
{
|
||||
// GET
|
||||
public IActionResult Index()
|
||||
{
|
||||
ViewBag.title = "所有文章";
|
||||
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
73
CMS/JXCMS.CMS.Movie/Admin/Controllers/ClassifyController.cs
Normal file
73
CMS/JXCMS.CMS.Movie/Admin/Controllers/ClassifyController.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using System.Linq;
|
||||
using FreeSql;
|
||||
using JXCMS.CMS.Attribute;
|
||||
using JXCMS.CMS.Entity;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.CMS.Movie.Spider;
|
||||
using JXCMS.CMS.Movie.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
{
|
||||
[Area("Admin")]
|
||||
[AdminAuthentication]
|
||||
public class ClassifyController : Controller
|
||||
{
|
||||
public IActionResult Index(int pageNumber = 1, int pageSize = 20)
|
||||
{
|
||||
var list = ClassifyEntity.Select.Include(x => x.Parent).Count(out long count).Page(pageNumber, pageSize).ToList(
|
||||
x => new ClassifyEntity{Id = x.Id, Name = x.Name, Alias = x.Alias, ParentId = x.ParentId, Parent = x.Parent, UpdateTime = x.UpdateTime,
|
||||
Count = MovieEntity.Select.Where(y => y.ClassifyId == x.Id).Count()});
|
||||
ViewBag.count = count;
|
||||
ViewBag.pageNumber = pageNumber;
|
||||
ViewBag.totlePage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
|
||||
return View(list);
|
||||
}
|
||||
|
||||
public IActionResult ClassifyDialog(int id)
|
||||
{
|
||||
|
||||
ClassifyEntity classifyEntity = null;
|
||||
if (id == 0)
|
||||
{
|
||||
classifyEntity = new ClassifyEntity();
|
||||
ViewBag.title = "添加新分类";
|
||||
ViewBag.classifyEntities = ClassifyEntity.Select.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
classifyEntity = ClassifyEntity.Find(id);
|
||||
ViewBag.title = "修改分类" + classifyEntity.Name;
|
||||
ViewBag.classifyEntities = Classify.FindAllNotChildren(ClassifyEntity.Select.ToList(), id);
|
||||
}
|
||||
return View(classifyEntity);
|
||||
}
|
||||
|
||||
public IActionResult DeleteClassify(int id)
|
||||
{
|
||||
if (MovieEntity.Select.Any(x => x.ClassifyId == id))
|
||||
{
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
|
||||
if (ClassifyEntity.Select.Any(x => x.ParentId == id))
|
||||
{
|
||||
ClassifyEntity.Where(x => x.ParentId == id).ToUpdate().Set(x => x.ParentId, 0).ExecuteAffrows();
|
||||
}
|
||||
|
||||
ClassifyEntity.Find(id).Delete();
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
|
||||
public IActionResult ModifyClassify(ClassifyEntity classifyEntity)
|
||||
{
|
||||
if (classifyEntity.Id != 0 &&
|
||||
Classify.FindAllChildren(ClassifyEntity.Select.ToList(), classifyEntity.Id).Any(x => x.Id == classifyEntity.ParentId))
|
||||
{
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
classifyEntity.Save();
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using FreeSql;
|
||||
using JXCMS.CMS.Attribute;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.CMS.Movie.Jobs;
|
||||
using JXCMS.CMS.Movie.Spider;
|
||||
using JXCMS.CMS.Movie.Utils;
|
||||
using JXCMS.Core.TimingTask;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Quartz;
|
||||
@ -16,7 +20,11 @@ namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
public IActionResult Index(int pageNumber = 1, int pageSize = 20)
|
||||
{
|
||||
ViewBag.title = "采集地址";
|
||||
var website = WebSiteEntity.Select.Count(out long count).Page(pageNumber, pageSize).ToList();
|
||||
var website = WebSiteEntity.Select.Count(out long count).Page(pageNumber, pageSize).ToList().Select(x =>
|
||||
{
|
||||
x.NextRunTime = x.IsEnable ? QuartzTask.GetCronSchedule(x.Cron, 1, DateTimeOffset.Now) : "已禁用";
|
||||
return x;
|
||||
}).ToList();
|
||||
ViewBag.website = website;
|
||||
ViewBag.count = count;
|
||||
ViewBag.pageNumber = pageNumber;
|
||||
@ -27,6 +35,10 @@ namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
[HttpPost]
|
||||
public IActionResult AddWebSite(WebSiteEntity webSiteEntity)
|
||||
{
|
||||
if (!CronExpression.IsValidExpression(webSiteEntity.Cron))
|
||||
{
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
webSiteEntity.Save();
|
||||
if (webSiteEntity.IsEnable)
|
||||
{
|
||||
@ -87,7 +99,26 @@ namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
}
|
||||
return View(webSiteEntity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public IActionResult BindingClassifyDialog(int id)
|
||||
{
|
||||
var classifyEntities = Classify.Structured(ClassifyEntity.Select.ToList());
|
||||
var webSiteClassifyEntities = WebSiteClassifyEntity.Where(x => x.WebSiteId == id).ToList();
|
||||
var webSiteEntity = WebSiteEntity.Find(id);
|
||||
classifyEntities.Insert(0, new ClassifyEntity(){Id = 0, Name = "未绑定"});
|
||||
ViewBag.classifyEntities = classifyEntities;
|
||||
ClassifySpider.GetAllClassifyFromUrl(id, webSiteEntity.ApiUrl, webSiteClassifyEntities);
|
||||
ViewBag.title = "修改" + webSiteEntity.WebSiteName + "的类型绑定";
|
||||
return View(webSiteClassifyEntities);
|
||||
}
|
||||
|
||||
public IActionResult UpdateBindingClassify(WebSiteClassifyEntity[] webSiteClassifyEntities)
|
||||
{
|
||||
foreach (var webSiteClassifyEntity in webSiteClassifyEntities)
|
||||
{
|
||||
webSiteClassifyEntity.Save();
|
||||
}
|
||||
return Redirect(Url.Action("Index"));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,15 @@
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using JXCMS.CMS.Attribute;
|
||||
using JXCMS.CMS.Entity;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.CMS.Utils;
|
||||
using JXCMS.Core.Auth;
|
||||
using JXCMS.Core.Encrypt;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JXCMS.CMS.Admin.Controllers
|
||||
namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
{
|
||||
[Area("Admin")]
|
||||
[AdminAuthentication]
|
||||
|
@ -73,6 +73,180 @@ namespace JXCMS.CMS.Admin.Controllers
|
||||
Type = "Settings"
|
||||
});
|
||||
BaseEntity.Orm.Insert(settings).ExecuteInserted();
|
||||
var classify = new ClassifyEntity()
|
||||
{
|
||||
Name = "电影",
|
||||
Alias = "dianying",
|
||||
ParentId = 0
|
||||
};
|
||||
classify.Save();
|
||||
List<ClassifyEntity> classifyEntities = new List<ClassifyEntity>();
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "动作片",
|
||||
Alias = "dongzuo",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "喜剧片",
|
||||
Alias = "xiju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "爱情片",
|
||||
Alias = "aiqing",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "科幻片",
|
||||
Alias = "kehuan",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "恐怖片",
|
||||
Alias = "kongbu",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "剧情片",
|
||||
Alias = "juqing",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "战争片",
|
||||
Alias = "zhanzheng",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "纪录片",
|
||||
Alias = "jilupian",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "微电影",
|
||||
Alias = "weidianying",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "伦理片",
|
||||
Alias = "lunli",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
BaseEntity.Orm.Insert(classifyEntities).ExecuteAffrows();
|
||||
classify = new ClassifyEntity()
|
||||
{
|
||||
Name = "电视剧",
|
||||
Alias = "tv",
|
||||
ParentId = 0
|
||||
};
|
||||
classify.Save();
|
||||
classifyEntities.Clear();
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "国产剧",
|
||||
Alias = "guochanju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "香港剧",
|
||||
Alias = "xianggangju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "韩国剧",
|
||||
Alias = "hanguoju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "欧美剧",
|
||||
Alias = "oumeiju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "台湾剧",
|
||||
Alias = "taiwanju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "日本剧",
|
||||
Alias = "ribenju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "海外剧",
|
||||
Alias = "haiwaiju",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
BaseEntity.Orm.Insert(classifyEntities).ExecuteAffrows();
|
||||
classify = new ClassifyEntity()
|
||||
{
|
||||
Name = "综艺片",
|
||||
Alias = "zongyi",
|
||||
ParentId = 0
|
||||
};
|
||||
classify.Save();
|
||||
classifyEntities.Clear();
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "内地综艺",
|
||||
Alias = "neidizongyi",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "日韩综艺",
|
||||
Alias = "rihanzongyi",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "欧美综艺",
|
||||
Alias = "oumeizongyi",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
BaseEntity.Orm.Insert(classifyEntities).ExecuteAffrows();
|
||||
classify = new ClassifyEntity()
|
||||
{
|
||||
Name = "动漫片",
|
||||
Alias = "dongman",
|
||||
ParentId = 0
|
||||
};
|
||||
classify.Save();
|
||||
classifyEntities.Clear();
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "国产动漫",
|
||||
Alias = "guochandongman",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "日韩动漫",
|
||||
Alias = "rihandongman",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
classifyEntities.Add(new ClassifyEntity()
|
||||
{
|
||||
Name = "欧美动漫",
|
||||
Alias = "oumeidongman",
|
||||
ParentId = classify.Id
|
||||
});
|
||||
BaseEntity.Orm.Insert(classifyEntities).ExecuteAffrows();
|
||||
System.IO.File.Create("install.lock");
|
||||
return View();
|
||||
}
|
||||
|
21
CMS/JXCMS.CMS.Movie/Admin/Controllers/MovieController.cs
Normal file
21
CMS/JXCMS.CMS.Movie/Admin/Controllers/MovieController.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using JXCMS.CMS.Attribute;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Admin.Controllers
|
||||
{
|
||||
[Area("Admin")]
|
||||
[AdminAuthentication]
|
||||
public class MovieController : Controller
|
||||
{
|
||||
public IActionResult Index(int pageNumber = 1, int pageSize = 20)
|
||||
{
|
||||
var model = MovieEntity.Select.Count(out long count).Page(pageNumber, pageSize)
|
||||
.Include(x => x.DirectorEntity).Include(x => x.ClassifyEntity).ToList();
|
||||
ViewBag.count = count;
|
||||
ViewBag.pageNumber = pageNumber;
|
||||
ViewBag.totlePage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,265 +0,0 @@
|
||||
<div class="container-fluid p-t-15">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar clearfix">
|
||||
<form class="pull-right search-bar" method="get" action="#!" role="form">
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<input type="hidden" name="search_field" id="search-field" value="title">
|
||||
<button class="btn btn-default dropdown-toggle" id="search-btn" data-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
|
||||
标题 <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li> <a tabindex="-1" href="javascript:void(0)" data-field="title">标题</a> </li>
|
||||
<li> <a tabindex="-1" href="javascript:void(0)" data-field="cat_name">栏目</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="text" class="form-control" value="" name="keyword" placeholder="请输入名称">
|
||||
</div>
|
||||
</form>
|
||||
<div class="toolbar-btn-action">
|
||||
<a class="btn btn-primary m-r-5" href="#!"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
<a class="btn btn-success m-r-5" href="#!"><i class="mdi mdi-check"></i> 启用</a>
|
||||
<a class="btn btn-warning m-r-5" href="#!"><i class="mdi mdi-block-helper"></i> 禁用</a>
|
||||
<a class="btn btn-danger" href="#!"><i class="mdi mdi-window-close"></i> 删除</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" id="check-all"><span></span>
|
||||
</label>
|
||||
</th>
|
||||
<th>编号</th>
|
||||
<th>标题</th>
|
||||
<th>书籍</th>
|
||||
<th>作者</th>
|
||||
<th>阅读量</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="1"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>1</td>
|
||||
<td>第01章 天涯思君不可忘</td>
|
||||
<td>《倚天屠龙记》</td>
|
||||
<td>金庸</td>
|
||||
<td>36</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="2"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>2</td>
|
||||
<td>第01章 古道腾驹惊白发,危峦快剑识青翎</td>
|
||||
<td>《书剑恩仇录》</td>
|
||||
<td>金庸</td>
|
||||
<td>44</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="3"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>3</td>
|
||||
<td>一个戴水獭皮帽子的朋友</td>
|
||||
<td>《湘行散记》</td>
|
||||
<td>沈从文</td>
|
||||
<td>39</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="4"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>4</td>
|
||||
<td>你是要灼灼容颜,还是要宜其室家</td>
|
||||
<td>《诗三百:思无邪》</td>
|
||||
<td>安意如</td>
|
||||
<td>36</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="5"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>5</td>
|
||||
<td>海上的消息</td>
|
||||
<td>《打开心内的窗》</td>
|
||||
<td>林清玄</td>
|
||||
<td>32</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="6"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>6</td>
|
||||
<td>楔子 一阕词来 南国清秋魂梦绕 十年人散 绣房红烛剑光寒</td>
|
||||
<td>《七剑下天山》</td>
|
||||
<td>梁羽生</td>
|
||||
<td>42</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="7"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>7</td>
|
||||
<td>祝福</td>
|
||||
<td>《彷徨》</td>
|
||||
<td>鲁迅</td>
|
||||
<td>40</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="8"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>8</td>
|
||||
<td>一个女长年的故事</td>
|
||||
<td>《莫泊桑短篇小说集》</td>
|
||||
<td>莫泊桑</td>
|
||||
<td>36</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="9"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>9</td>
|
||||
<td>第一回 赈民饥包公奉旨 图谋害庞相施计</td>
|
||||
<td>《五虎征西》</td>
|
||||
<td>李雨堂</td>
|
||||
<td>35</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="10"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>10</td>
|
||||
<td>第一回 于按察山东赴任 邹其仁赴路登程</td>
|
||||
<td>《于公案》</td>
|
||||
<td>佚名</td>
|
||||
<td>37</td>
|
||||
<td><font class="text-success">正常</font></td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip"><i class="mdi mdi-pencil"></i></a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip"><i class="mdi mdi-window-close"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
<li class="disabled"><span>«</span></li>
|
||||
<li class="active"><span>1</span></li>
|
||||
<li><a href="#1">2</a></li>
|
||||
<li><a href="#1">3</a></li>
|
||||
<li><a href="#1">4</a></li>
|
||||
<li><a href="#1">5</a></li>
|
||||
<li><a href="#1">6</a></li>
|
||||
<li><a href="#1">7</a></li>
|
||||
<li><a href="#1">8</a></li>
|
||||
<li class="disabled"><span>...</span></li>
|
||||
<li><a href="#!">14452</a></li>
|
||||
<li><a href="#!">14453</a></li>
|
||||
<li><a href="#!">»</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
@using JXCMS.CMS.Movie.Entity
|
||||
@model JXCMS.CMS.Movie.Entity.ClassifyEntity
|
||||
|
||||
@{
|
||||
Layout = "_DialogLayout";
|
||||
}
|
||||
|
||||
<form id="modify_classify" action="@Url.Action("ModifyClassify")" method="post">
|
||||
<input type="hidden" id="id" name="id" value="@Model.Id"/>
|
||||
<div class="form-group">
|
||||
<label for="name" class="control-label">分类名称:</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="@Model.Name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="alias" class="control-label">别名:</label>
|
||||
<input type="text" class="form-control" id="alias" name="alias" value="@Model.Alias">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="parentId" class="control-label">父级分类:</label>
|
||||
<select class="form-control" id="parentId" name="parentId">
|
||||
<option value="0">无</option>
|
||||
@foreach (ClassifyEntity classify in ViewBag.classifyEntities)
|
||||
{
|
||||
@:<option value="@classify.Id" @(Model.ParentId == classify.Id ? "selected" : "")>@classify.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@section dialogScript
|
||||
{
|
||||
<script type="text/javascript">
|
||||
$('#commit').click(function() {
|
||||
var name = $("#name").val();
|
||||
if (name === ""){
|
||||
lightyear.notify('分类名称不能为空', 'danger', 100);
|
||||
return;
|
||||
}
|
||||
$('#modify_classify').submit();
|
||||
})
|
||||
</script>
|
||||
}
|
160
CMS/JXCMS.CMS.Movie/Admin/Views/Classify/Index.cshtml
Normal file
160
CMS/JXCMS.CMS.Movie/Admin/Views/Classify/Index.cshtml
Normal file
@ -0,0 +1,160 @@
|
||||
@using JXCMS.CMS.Movie.Entity
|
||||
@using JXCMS.Core.Extensions
|
||||
@model List<JXCMS.CMS.Movie.Entity.ClassifyEntity>
|
||||
|
||||
@{
|
||||
ViewBag.Title = "分类目录";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container-fluid p-t-15">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar clearfix">
|
||||
<div class="toolbar-btn-action">
|
||||
<a data-src="@Url.Action("ClassifyDialog", "Classify", new {id = 0})" class="btn btn-primary m-r-5" id="new" data-toggle="modal" data-target="#exampleModal"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>别名</th>
|
||||
<th>上级分类</th>
|
||||
<th>视频数量</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Model.Count == 0)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="5" style="text-align: center">无数据</td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (var classifyEntity in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@classifyEntity.Name</td>
|
||||
<td>@(classifyEntity.Alias.IsNullOrEmpty() ? "-" : classifyEntity.Alias)</td>
|
||||
<td>@(classifyEntity.Parent == null ? "无" : classifyEntity.Parent.Name)</td>
|
||||
<td>@classifyEntity.Count</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" data-src="@Url.Action("ClassifyDialog", "Classify", new {id = classifyEntity.Id})" title="编辑" data-toggle="modal" data-target="#exampleModal">
|
||||
<i class="mdi mdi-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-xs btn-default" title="删除" data-toggle="tooltip" onclick="delClassify(@classifyEntity.Id, '@classifyEntity.Name')"
|
||||
@if (classifyEntity.Count > 0)
|
||||
{
|
||||
@:disabled
|
||||
}>
|
||||
<i class="mdi mdi-window-close"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
@if (ViewBag.pageNumber != 1)
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Classify")"><<</a>
|
||||
</li>
|
||||
}
|
||||
@for (int i = ViewBag.pageNumber - 3; i < ViewBag.pageNumber + 3; i++)
|
||||
{
|
||||
if (i < 1 || i > ViewBag.totlePage)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (i == ViewBag.pageNumber)
|
||||
{
|
||||
<li class="active">
|
||||
<span>@i</span>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Classify", new {pageNumber = i})">@i</a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
@if (ViewBag.pageNumber < ViewBag.totlePage)
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Classify", new {pageNumber = ViewBag.totlePage})">>></a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
正在加载,请稍后...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form id="delForm" action="@Url.Action("DeleteClassify")" method="post">
|
||||
<input type="hidden" name="id" id="delId"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@section style
|
||||
{
|
||||
<link rel="stylesheet" href="@Url.ContentAdmin("js/jconfirm/jquery-confirm.min.css")">
|
||||
}
|
||||
|
||||
@section script
|
||||
{
|
||||
<script src="@Url.ContentAdmin("js/bootstrap-notify.min.js")"></script>
|
||||
<script type="text/javascript" src="@Url.ContentAdmin("js/lightyear.js")"></script>
|
||||
<script src="@Url.ContentAdmin("js/jconfirm/jquery-confirm.min.js")"></script>
|
||||
<script type="text/javascript">
|
||||
$('#exampleModal').on('show.bs.modal', function(event) {
|
||||
var button = $(event.relatedTarget); // Button that triggered the modal
|
||||
var recipient = button.data('src'); // Extract info from data-* attributes
|
||||
var content = $(this).find(".modal-content");
|
||||
content.html("正在加载,请稍后...");
|
||||
$.get(recipient, function(data, status) {
|
||||
if (status === "success") {
|
||||
content.html(data)
|
||||
} else{
|
||||
content.html("发生错误,请重试")
|
||||
}
|
||||
})
|
||||
});
|
||||
function delClassify(id, name) {
|
||||
$.alert({
|
||||
title: '删除分类地址' + name,
|
||||
content: '是否删除' + name + ',?(如果该分类下有子分类,子分类将变为顶级分类)<br />该操作不可恢复',
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: '是',
|
||||
btnClass: 'btn-primary',
|
||||
action: function(){
|
||||
$('#delId').val(id);
|
||||
$('#delForm').submit();
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: '否'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
@{
|
||||
Layout = "_DialogLayout";
|
||||
}
|
||||
@using JXCMS.CMS.Movie.Entity
|
||||
@model List<JXCMS.CMS.Movie.Entity.WebSiteClassifyEntity>
|
||||
@{
|
||||
var classifyEntities = (List<ClassifyEntity>) ViewBag.classifyEntities;
|
||||
}
|
||||
<form id="modify_website" action="@Url.Action("UpdateBindingClassify")" method="post">
|
||||
@for (int i = 0; i < Model.Count; i++)
|
||||
{
|
||||
@Html.HiddenFor(x => x[i].Id)
|
||||
@Html.HiddenFor(x => x[i].WebSiteId)
|
||||
@Html.HiddenFor(x => x[i].TypeName)
|
||||
@Html.HiddenFor(x => x[i].TypeId)
|
||||
<div class="input-daterange input-group" style="margin-bottom: 10px">
|
||||
<span class="form-control">@Model[i].TypeName</span>
|
||||
<span class="input-group-addon">
|
||||
<i class="mdi mdi-link-variant"></i>
|
||||
</span>
|
||||
@Html.DropDownListFor(x => x[i].ClassifyId, new SelectList(classifyEntities, "Id", "Name", Model[i].ClassifyId),
|
||||
new {@class = "form-control"})
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
|
||||
@section dialogScript
|
||||
{
|
||||
|
||||
<script type="text/javascript">
|
||||
$('#commit').click(function() {
|
||||
$('#modify_website').submit();
|
||||
})
|
||||
</script>
|
||||
}
|
@ -47,10 +47,17 @@
|
||||
<th>网站url</th>
|
||||
<th>采集cron</th>
|
||||
<th>状态</th>
|
||||
<th>下次执行时间</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (ViewBag.website.Count == 0)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="7" style="text-align: center">无数据</td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (WebSiteEntity webSiteEntity in ViewBag.website)
|
||||
{
|
||||
<tr>
|
||||
@ -65,12 +72,13 @@
|
||||
<td>
|
||||
<span class="text-success">@(webSiteEntity.IsEnable ? "正常" : "已禁用")</span>
|
||||
</td>
|
||||
<td>@webSiteEntity.NextRunTime</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" data-src="@Url.Action("WebSiteDialog", "Collection", new {id = webSiteEntity.Id})" title="编辑" data-toggle="modal" data-target="#exampleModal">
|
||||
<i class="mdi mdi-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-xs btn-default" href="#" title="绑定分类" onclick="delWebsite(@webSiteEntity.Id, '@webSiteEntity.WebSiteName')">
|
||||
<a class="btn btn-xs btn-default" data-src="@Url.Action("BindingClassifyDialog", "Collection", new {id = webSiteEntity.Id})" data-toggle="modal" data-target="#exampleModal">
|
||||
<i class="mdi mdi-link-variant"></i>
|
||||
</a>
|
||||
<a class="btn btn-xs btn-default" href="#" title="删除" onclick="delWebsite(@webSiteEntity.Id, '@webSiteEntity.WebSiteName')">
|
||||
|
@ -34,11 +34,10 @@
|
||||
<ul class="nav nav-drawer">
|
||||
<li class="nav-item active"> <a class="multitabs" href="@Url.Action("Home")"><i class="mdi mdi-home"></i> <span>后台首页</span></a> </li>
|
||||
<li class="nav-item nav-item-has-subnav">
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-format-align-justify"></i> <span>文章</span></a>
|
||||
<a href="javascript:void(0)"><i class="mdi mdi-format-align-justify"></i> <span>影视</span></a>
|
||||
<ul class="nav nav-subnav">
|
||||
<li> <a class="multitabs" href="@Url.Action("Index", "Article")">所有文章</a> </li>
|
||||
<li> <a class="multitabs" href="lyear_forms_radio.html">写文章</a> </li>
|
||||
<li> <a class="multitabs" href="lyear_forms_checkbox.html">分类目录</a> </li>
|
||||
<li> <a class="multitabs" href="@Url.Action("Index", "Movie")">所有影视</a> </li>
|
||||
<li> <a class="multitabs" href="@Url.Action("Index", "Classify")">分类目录</a> </li>
|
||||
<li> <a class="multitabs" href="lyear_forms_switch.html">标签</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
131
CMS/JXCMS.CMS.Movie/Admin/Views/Movie/Index.cshtml
Normal file
131
CMS/JXCMS.CMS.Movie/Admin/Views/Movie/Index.cshtml
Normal file
@ -0,0 +1,131 @@
|
||||
@model List<JXCMS.CMS.Movie.Entity.MovieEntity>
|
||||
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="container-fluid p-t-15">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-toolbar clearfix">
|
||||
<form class="pull-right search-bar" method="get" action="#!" role="form">
|
||||
<div class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<input type="hidden" name="search_field" id="search-field" value="title">
|
||||
<button class="btn btn-default dropdown-toggle" id="search-btn" data-toggle="dropdown" type="button" aria-haspopup="true" aria-expanded="false">
|
||||
标题 <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a tabindex="-1" href="javascript:void(0)" data-field="title">标题</a>
|
||||
</li>
|
||||
<li>
|
||||
<a tabindex="-1" href="javascript:void(0)" data-field="cat_name">栏目</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="text" class="form-control" value="" name="keyword" placeholder="请输入名称">
|
||||
</div>
|
||||
</form>
|
||||
<div class="toolbar-btn-action">
|
||||
<a class="btn btn-primary m-r-5" href="#!"><i class="mdi mdi-plus"></i> 新增</a>
|
||||
<a class="btn btn-success m-r-5" href="#!"><i class="mdi mdi-check"></i> 显示</a>
|
||||
<a class="btn btn-warning m-r-5" href="#!"><i class="mdi mdi-block-helper"></i> 隐藏</a>
|
||||
<a class="btn btn-danger" href="#!"><i class="mdi mdi-window-close"></i> 删除</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" id="check-all"><span></span>
|
||||
</label>
|
||||
</th>
|
||||
<th>名称</th>
|
||||
<th>导演</th>
|
||||
<th>年份</th>
|
||||
<th>语种</th>
|
||||
<th>分类</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var movieEntity in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="lyear-checkbox checkbox-primary">
|
||||
<input type="checkbox" name="ids[]" value="1"><span></span>
|
||||
</label>
|
||||
</td>
|
||||
<td>@movieEntity.Name</td>
|
||||
<td>@movieEntity.DirectorEntity.DirectorName</td>
|
||||
<td>@movieEntity.Year</td>
|
||||
<td>@movieEntity.Lang</td>
|
||||
<td>@movieEntity.ClassifyEntity.Name</td>
|
||||
<td>
|
||||
<font class="text-success">@(movieEntity.IsEnable ? "正常" : "已隐藏")</font>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-xs btn-default" href="#!" title="编辑" data-toggle="tooltip">
|
||||
<i class="mdi mdi-pencil"></i>
|
||||
</a>
|
||||
<a class="btn btn-xs btn-default" href="#!" title="删除" data-toggle="tooltip">
|
||||
<i class="mdi mdi-window-close"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="pagination">
|
||||
@if (ViewBag.pageNumber != 1)
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Collection")"><<</a>
|
||||
</li>
|
||||
}
|
||||
@for (int i = ViewBag.pageNumber - 3; i < ViewBag.pageNumber + 3; i++)
|
||||
{
|
||||
if (i < 1 || i > ViewBag.totlePage)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (i == ViewBag.pageNumber)
|
||||
{
|
||||
<li class="active">
|
||||
<span>@i</span>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Collection", new {pageNumber = i})">@i</a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
@if (ViewBag.pageNumber < ViewBag.totlePage)
|
||||
{
|
||||
<li>
|
||||
<a href="@Url.Action("Index", "Collection", new {pageNumber = ViewBag.totlePage})">>></a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
@ -6,6 +6,8 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using JXCMS.CMS.Models;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.CMS.Movie.Spider;
|
||||
using JXCMS.Core.Themes;
|
||||
|
||||
namespace JXCMS.CMS.Controllers
|
||||
@ -35,5 +37,10 @@ namespace JXCMS.CMS.Controllers
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
|
||||
public IActionResult Test()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
CMS/JXCMS.CMS.Movie/Entity/ActorEntity.cs
Normal file
14
CMS/JXCMS.CMS.Movie/Entity/ActorEntity.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class ActorEntity : BaseEntity<ActorEntity, int>
|
||||
{
|
||||
public string ActorName { get; set; }
|
||||
|
||||
[Navigate(ManyToMany = typeof(MovieActorEntity))]
|
||||
public List<MovieEntity> MovieEntities { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
@ -6,6 +9,17 @@ namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Alias { get; set; }
|
||||
|
||||
public int ParentId { get; set; }
|
||||
|
||||
[Navigate("ParentId")]
|
||||
public ClassifyEntity Parent { get; set; }
|
||||
|
||||
public ICollection<ClassifyEntity> Childs { get; set; }
|
||||
|
||||
[Column(IsIgnore = true)]
|
||||
public long Count { get; set; }
|
||||
|
||||
}
|
||||
}
|
9
CMS/JXCMS.CMS.Movie/Entity/DirectorEntity.cs
Normal file
9
CMS/JXCMS.CMS.Movie/Entity/DirectorEntity.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using FreeSql;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class DirectorEntity : BaseEntity<DirectorEntity, int>
|
||||
{
|
||||
public string DirectorName { get; set; }
|
||||
}
|
||||
}
|
18
CMS/JXCMS.CMS.Movie/Entity/MovieActorEntity.cs
Normal file
18
CMS/JXCMS.CMS.Movie/Entity/MovieActorEntity.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class MovieActorEntity : BaseEntity<MovieActorEntity, int>
|
||||
{
|
||||
public int ActorId { get; set; }
|
||||
|
||||
[Navigate("ActorId")]
|
||||
public ActorEntity ActorEntity { get; set; }
|
||||
|
||||
public int MovieId { get; set; }
|
||||
|
||||
[Navigate("MovieId")]
|
||||
public MovieEntity MovieEntity { get; set; }
|
||||
}
|
||||
}
|
44
CMS/JXCMS.CMS.Movie/Entity/MovieEntity.cs
Normal file
44
CMS/JXCMS.CMS.Movie/Entity/MovieEntity.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class MovieEntity : BaseEntity<MovieEntity, int>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Pic { get; set; }
|
||||
|
||||
public int ClassifyId { get; set; }
|
||||
|
||||
public string Lang { get; set; }
|
||||
|
||||
public string Area { get; set; }
|
||||
|
||||
public string Year { get; set; }
|
||||
|
||||
public int DirectorId { get; set; }
|
||||
|
||||
public DateTime LastUpdate { get; set; }
|
||||
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
[StringLength(-1)]
|
||||
public string Des { get; set; }
|
||||
|
||||
[Navigate("DirectorId")]
|
||||
public virtual DirectorEntity DirectorEntity { get; set; }
|
||||
|
||||
[Navigate("ClassifyId")]
|
||||
public virtual ClassifyEntity ClassifyEntity { get; set; }
|
||||
|
||||
[Navigate(ManyToMany = typeof(MovieActorEntity))]
|
||||
public virtual List<ActorEntity> ActorEntities { get; set; }
|
||||
|
||||
[Navigate("Id")]
|
||||
public virtual List<MovieListEntity> MovieListEntities { get; set; }
|
||||
}
|
||||
}
|
22
CMS/JXCMS.CMS.Movie/Entity/MovieListEntity.cs
Normal file
22
CMS/JXCMS.CMS.Movie/Entity/MovieListEntity.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class MovieListEntity : BaseEntity<MovieListEntity, int>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string PlayUrl { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public int MovieId { get; set; }
|
||||
|
||||
public int WebSiteId { get; set; }
|
||||
|
||||
[Navigate("MovieId")]
|
||||
public virtual MovieEntity MovieEntity { get; set; }
|
||||
|
||||
}
|
||||
}
|
19
CMS/JXCMS.CMS.Movie/Entity/WebSiteClassifyEntity.cs
Normal file
19
CMS/JXCMS.CMS.Movie/Entity/WebSiteClassifyEntity.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
public class WebSiteClassifyEntity : BaseEntity<WebSiteClassifyEntity, int>
|
||||
{
|
||||
public int WebSiteId { get; set; }
|
||||
|
||||
public int TypeId { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public int ClassifyId { get; set; }
|
||||
|
||||
[Navigate("WebSiteId")]
|
||||
public virtual WebSiteEntity WebSiteEntity { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Entity
|
||||
{
|
||||
@ -11,5 +14,15 @@ namespace JXCMS.CMS.Movie.Entity
|
||||
public string Cron { get; set; } = "0 0 * * * ?";
|
||||
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
public string LatestMovieNote { get; set; }
|
||||
|
||||
public DateTime LatestMoveTime { get; set; }
|
||||
|
||||
[Navigate("Id")]
|
||||
public List<ClassifyEntity> WebSiteClassifyEntities { get; set; }
|
||||
|
||||
[Column(IsIgnore = true)]
|
||||
public string NextRunTime { get; set; }
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Admin\Content" />
|
||||
<Folder Include="Logs" />
|
||||
<Folder Include="Views\Default" />
|
||||
</ItemGroup>
|
||||
|
||||
|
33
CMS/JXCMS.CMS.Movie/Models/MovieListInfoModel.cs
Normal file
33
CMS/JXCMS.CMS.Movie/Models/MovieListInfoModel.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Models
|
||||
{
|
||||
public class MovieListInfoModel
|
||||
{
|
||||
public string RecordCount { get; set; }
|
||||
|
||||
public string PageSize { get; set; }
|
||||
|
||||
public string CurrentPage { get; set; }
|
||||
|
||||
public string PageCount { get; set; }
|
||||
|
||||
public List<MovieInfoModel> MovieInfoModels { get; set; } = new List<MovieInfoModel>();
|
||||
}
|
||||
|
||||
public class MovieInfoModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string TypeId { get; set; }
|
||||
|
||||
public DateTime LastUpdateTime { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog;
|
||||
|
||||
namespace JXCMS.CMS
|
||||
{
|
||||
@ -22,6 +23,6 @@ namespace JXCMS.CMS
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}).UseSerilog();
|
||||
}
|
||||
}
|
||||
|
38
CMS/JXCMS.CMS.Movie/Spider/ClassifySpider.cs
Normal file
38
CMS/JXCMS.CMS.Movie/Spider/ClassifySpider.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using SufeiUtil;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Spider
|
||||
{
|
||||
public class ClassifySpider
|
||||
{
|
||||
public static void GetAllClassifyFromUrl(int websiteId, string url, List<WebSiteClassifyEntity> webSiteClassifyEntities)
|
||||
{
|
||||
var helper = new HttpHelper();
|
||||
var item = new HttpItem();
|
||||
item.URL = url;
|
||||
var result = helper.GetHtml(item);
|
||||
if (result.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(result.Html);
|
||||
var classNode = doc.SelectSingleNode("/rss/class");
|
||||
|
||||
foreach (XmlNode childNode in classNode.ChildNodes)
|
||||
{
|
||||
if (webSiteClassifyEntities.All(x => x.TypeId.ToString() != childNode.Attributes["id"].Value))
|
||||
{
|
||||
WebSiteClassifyEntity webSiteClassifyEntity = new WebSiteClassifyEntity();
|
||||
webSiteClassifyEntity.TypeId = int.Parse(childNode.Attributes["id"].Value);
|
||||
webSiteClassifyEntity.TypeName = childNode.InnerText;
|
||||
webSiteClassifyEntity.WebSiteId = websiteId;
|
||||
webSiteClassifyEntities.Add(webSiteClassifyEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
265
CMS/JXCMS.CMS.Movie/Spider/MovieSpider.cs
Normal file
265
CMS/JXCMS.CMS.Movie/Spider/MovieSpider.cs
Normal file
@ -0,0 +1,265 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Xml;
|
||||
using FreeSql;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.CMS.Movie.Models;
|
||||
using JXCMS.Core.Extensions;
|
||||
using JXCMS.Core.Log;
|
||||
using SufeiUtil;
|
||||
using Log = Serilog.Log;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Spider
|
||||
{
|
||||
public class MovieSpider
|
||||
{
|
||||
|
||||
private readonly List<WebSiteClassifyEntity> _webSiteClassifyEntities;
|
||||
private readonly List<ActorEntity> _actorEntities;
|
||||
private readonly List<DirectorEntity> _directorEntities;
|
||||
|
||||
private static MovieSpider _instance;
|
||||
|
||||
public static MovieSpider Instance => _instance ??= new MovieSpider();
|
||||
|
||||
private MovieSpider()
|
||||
{
|
||||
_webSiteClassifyEntities = WebSiteClassifyEntity.Select.ToList();
|
||||
_actorEntities = ActorEntity.Select.ToList();
|
||||
_directorEntities = DirectorEntity.Select.ToList();
|
||||
}
|
||||
|
||||
public MovieListInfoModel GetMovieList(WebSiteEntity webSiteEntity, int number)
|
||||
{
|
||||
HttpItem item = new HttpItem();
|
||||
item.URL = $"{webSiteEntity.ApiUrl}?pg={number}";
|
||||
HttpHelper helper = new HttpHelper();
|
||||
var result = helper.GetHtml(item);
|
||||
if (result.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
Log.Logger.Information($"{{@name}} 成功获取地址:{item.URL}", webSiteEntity.WebSiteName);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(result.Html);
|
||||
var listNode = doc.SelectSingleNode("/rss/list");
|
||||
MovieListInfoModel movieListInfoModel = new MovieListInfoModel();;
|
||||
movieListInfoModel.CurrentPage = listNode.Attributes["page"].Value;
|
||||
movieListInfoModel.PageCount = listNode.Attributes["pagecount"].Value;
|
||||
movieListInfoModel.PageSize = listNode.Attributes["pagesize"].Value;
|
||||
movieListInfoModel.RecordCount = listNode.Attributes["recordcount"].Value;
|
||||
var videos = listNode.SelectNodes("//video");
|
||||
foreach (XmlNode video in videos)
|
||||
{
|
||||
MovieInfoModel model = new MovieInfoModel
|
||||
{
|
||||
LastUpdateTime = DateTime.Parse(video.SelectSingleNode("last").InnerText),
|
||||
Name = video.SelectSingleNode("name").InnerText,
|
||||
TypeId = video.SelectSingleNode("tid").InnerText,
|
||||
Id = video.SelectSingleNode("id").InnerText,
|
||||
TypeName = video.SelectSingleNode("type").InnerText
|
||||
};
|
||||
movieListInfoModel.MovieInfoModels.Add(model);
|
||||
}
|
||||
return movieListInfoModel;
|
||||
}
|
||||
Log.Warning($"{{@name}} 获取api失败,错误码{result.StatusCode}", webSiteEntity.WebSiteName);
|
||||
return null;
|
||||
}
|
||||
|
||||
public DateTime GetMovieInfos(WebSiteEntity webSiteEntity, List<(string id, string name, string typeId)> idNameTypes)
|
||||
{
|
||||
HttpItem item = new HttpItem();
|
||||
item.URL = $"{webSiteEntity.ApiUrl}?ac=videolist&ids={string.Join(",", idNameTypes.Select(x => x.id))}";
|
||||
HttpHelper helper = new HttpHelper();
|
||||
var result = helper.GetHtml(item);
|
||||
if (result.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
DateTime dt = DateTime.MinValue;
|
||||
Log.Logger.Information($"{{@name}} 成功获取地址:{item.URL}", webSiteEntity.WebSiteName);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(result.Html);
|
||||
var videoNode = doc.SelectNodes("/rss/list/video");
|
||||
foreach (XmlNode video in videoNode)
|
||||
{
|
||||
var name = video.SelectSingleNode("name").InnerText;
|
||||
var director = video.SelectSingleNode("director").InnerText;
|
||||
if (director.IsNullOrEmpty())
|
||||
{
|
||||
director = "未知";
|
||||
}
|
||||
var movieEntity = MovieEntity.Select.Include(x => x.DirectorEntity)
|
||||
.Where(x => x.Name == name && x.DirectorEntity.DirectorName == director).First();
|
||||
if (movieEntity == null)
|
||||
{
|
||||
movieEntity = new MovieEntity();
|
||||
movieEntity.Area = video.SelectSingleNode("area").InnerText == "" ? "未知":video.SelectSingleNode("area").InnerText;
|
||||
movieEntity.Des = video.SelectSingleNode("des").InnerText == "" ? "暂无介绍":video.SelectSingleNode("des").InnerText;
|
||||
movieEntity.Lang = video.SelectSingleNode("lang").InnerText == "" ? "未知":video.SelectSingleNode("lang").InnerText;
|
||||
movieEntity.Name = video.SelectSingleNode("name").InnerText;
|
||||
movieEntity.Pic = video.SelectSingleNode("pic").InnerText == "" ? "/img/cover.jpg":video.SelectSingleNode("lang").InnerText;
|
||||
movieEntity.Year = video.SelectSingleNode("year").InnerText == "" || video.SelectSingleNode("year").InnerText == "0" ? "未知":video.SelectSingleNode("year").InnerText;
|
||||
movieEntity.ClassifyId = int.Parse(idNameTypes.First(x => x.id == video.SelectSingleNode("id").InnerText).typeId);
|
||||
var directorId = _directorEntities.FirstOrDefault(x => x.DirectorName == director)?.Id;
|
||||
if (directorId == null)
|
||||
{
|
||||
DirectorEntity directorEntity = new DirectorEntity();
|
||||
directorEntity.DirectorName = director;
|
||||
directorEntity.Save();
|
||||
directorId = directorEntity.Id;
|
||||
}
|
||||
|
||||
movieEntity.DirectorId = directorId.Value;
|
||||
movieEntity.LastUpdate = DateTime.Parse(video.SelectSingleNode("last").InnerText);
|
||||
movieEntity.Save();
|
||||
if (movieEntity.LastUpdate > dt)
|
||||
{
|
||||
dt = movieEntity.LastUpdate;
|
||||
}
|
||||
var actorStr = video.SelectSingleNode("actor").InnerText;
|
||||
if (actorStr.IsNullOrEmpty())
|
||||
{
|
||||
actorStr = "未知";
|
||||
}
|
||||
var actorsStr = actorStr.Split(',', ' ');
|
||||
var actors = _actorEntities.Where(x => actorsStr.Contains(x.ActorName)).ToList();
|
||||
foreach (var actor in actorsStr)
|
||||
{
|
||||
var id = actors.FirstOrDefault(x => x.ActorName == actor)?.Id;
|
||||
if (id == null)
|
||||
{
|
||||
ActorEntity actorEntity = new ActorEntity {ActorName = actor};
|
||||
actorEntity.Save();
|
||||
id = actorEntity.Id;
|
||||
}
|
||||
|
||||
MovieActorEntity movieActorEntity = new MovieActorEntity
|
||||
{
|
||||
ActorId = id.Value, MovieId = movieEntity.Id
|
||||
};
|
||||
movieActorEntity.Save();
|
||||
}
|
||||
}
|
||||
|
||||
var dds = video.SelectNodes("dl/dd");
|
||||
var movieListEntity = MovieListEntity.Where(x => x.MovieId == movieEntity.Id && x.WebSiteId == webSiteEntity.Id)
|
||||
.OrderByDescending(x => x.Id).First();
|
||||
if (movieListEntity == null)
|
||||
{
|
||||
foreach (XmlNode dd in dds)
|
||||
{
|
||||
var number = dd.InnerText.Split('#');
|
||||
if (number.Length <= 0 || !number[0].Split('$')[1].ToLower().EndsWith("m3u8"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Log.Logger.Information("{@name} 获取到m3u8列表!", webSiteEntity.WebSiteName);
|
||||
var movieListEntities = number.Select(x =>
|
||||
{
|
||||
var sp = x.Split('$');
|
||||
return new MovieListEntity
|
||||
{
|
||||
Name = sp[0],
|
||||
Type = sp[2],
|
||||
MovieId = movieEntity.Id,
|
||||
PlayUrl = sp[1],
|
||||
WebSiteId = webSiteEntity.Id
|
||||
};
|
||||
});
|
||||
BaseEntity.Orm.Insert(movieListEntities).ExecuteAffrows();
|
||||
Log.Logger.Information($"{{@name}} 插入剧集{movieEntity.Name}成功!", webSiteEntity.WebSiteName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var node = dds.Cast<XmlNode>().FirstOrDefault(x => x.Attributes["flag"].Value == movieListEntity.Type);
|
||||
if (node == null)
|
||||
{
|
||||
Log.Logger.Error("{@name} 未找到指定的剧集列表!", webSiteEntity.WebSiteName);
|
||||
}
|
||||
bool flag = false;
|
||||
foreach (var number in node.InnerText.Split('#'))
|
||||
{
|
||||
var sp = number.Split('$');
|
||||
if (sp[0] == movieListEntity.Name)
|
||||
{
|
||||
flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
new MovieListEntity()
|
||||
{
|
||||
Name = sp[0],
|
||||
MovieId = movieEntity.Id,
|
||||
PlayUrl = sp[1],
|
||||
Type = sp[2],
|
||||
WebSiteId = webSiteEntity.Id
|
||||
}.Save();
|
||||
Log.Logger.Information($"{{@name}} 插入剧集{movieEntity.Name}-{sp[0]}成功!", webSiteEntity.WebSiteName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
public void StartSpider(WebSiteEntity webSiteEntity, bool reGetAll = false)
|
||||
{
|
||||
var model = GetMovieList(webSiteEntity, 1);
|
||||
if (model == null)
|
||||
{
|
||||
Log.Logger.Error("{@name} 获取信息失败,采集结束!", webSiteEntity.WebSiteName);
|
||||
return;
|
||||
}
|
||||
int number = 1;
|
||||
if (!int.TryParse(model.PageCount, out int count))
|
||||
{
|
||||
Log.Logger.Error("{@name} 获取总页数失败,采集结束!", webSiteEntity.WebSiteName);
|
||||
return;
|
||||
}
|
||||
DateTime dt = DateTime.MinValue;
|
||||
do
|
||||
{
|
||||
model = GetMovieList(webSiteEntity, number++);
|
||||
if (model == null)
|
||||
{
|
||||
Log.Logger.Error("{@name} 获取信息失败,采集结束!", webSiteEntity.WebSiteName);
|
||||
return;
|
||||
}
|
||||
List<(string id, string name, string typeId)> idNameTypes = new List<(string, string, string)>();
|
||||
foreach (var modelMovieInfoModel in model.MovieInfoModels)
|
||||
{
|
||||
if (webSiteEntity.LatestMoveTime > modelMovieInfoModel.LastUpdateTime)
|
||||
{
|
||||
Log.Logger.Information("{@name} 已检查到最后一条", webSiteEntity.WebSiteName);
|
||||
break;
|
||||
}
|
||||
if (!_webSiteClassifyEntities.Any(x => x.WebSiteId == webSiteEntity.Id && x.TypeId.ToString() == modelMovieInfoModel.TypeId))
|
||||
{
|
||||
Log.Logger.Warning($"{{@name}} 未找到与{modelMovieInfoModel.TypeName}对应的分类,自动跳过", webSiteEntity.WebSiteName);
|
||||
continue;
|
||||
}
|
||||
idNameTypes.Add((modelMovieInfoModel.Id, modelMovieInfoModel.Name, modelMovieInfoModel.TypeId));
|
||||
}
|
||||
|
||||
if (idNameTypes.Count == 0)
|
||||
{
|
||||
if (webSiteEntity.LatestMoveTime < dt)
|
||||
{
|
||||
webSiteEntity.LatestMoveTime = dt;
|
||||
webSiteEntity.Save();
|
||||
}
|
||||
Log.Information("{@name} 采集完成!", webSiteEntity.WebSiteName);
|
||||
return;
|
||||
}
|
||||
dt = GetMovieInfos(webSiteEntity, idNameTypes);
|
||||
} while (number <= count);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,12 +8,15 @@ using JXCMS.CMS.Entity;
|
||||
using JXCMS.Core;
|
||||
using JXCMS.Core.Auth;
|
||||
using JXCMS.Core.Db;
|
||||
using JXCMS.Core.Log;
|
||||
using JXCMS.Core.Themes;
|
||||
using JXCMS.Core.Utils;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -28,6 +31,8 @@ namespace JXCMS.CMS
|
||||
{
|
||||
Configuration = configuration;
|
||||
Environment = environment;
|
||||
ConfigHelper.Configs = Configuration;
|
||||
Log.Init();
|
||||
}
|
||||
|
||||
public IHostEnvironment Environment { get; }
|
||||
@ -53,6 +58,10 @@ namespace JXCMS.CMS
|
||||
services.AddJXAuth();
|
||||
|
||||
services.AddCms();
|
||||
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
|
||||
|
||||
}
|
||||
|
||||
|
46
CMS/JXCMS.CMS.Movie/Utils/Classify.cs
Normal file
46
CMS/JXCMS.CMS.Movie/Utils/Classify.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JXCMS.CMS.Movie.Entity;
|
||||
using JXCMS.Core.Extensions;
|
||||
|
||||
namespace JXCMS.CMS.Movie.Utils
|
||||
{
|
||||
public static class Classify
|
||||
{
|
||||
public static List<ClassifyEntity> FindAllChildren(List<ClassifyEntity> classifyEntities, int baseId, bool includeSelf = true)
|
||||
{
|
||||
var returnValue = new List<ClassifyEntity>();
|
||||
if (includeSelf)
|
||||
{
|
||||
returnValue.AddRange(classifyEntities.Where(x => x.Id == baseId));
|
||||
}
|
||||
var classifyEntityList = classifyEntities.Where(x => x.ParentId == baseId).ToList();
|
||||
returnValue.AddRange(classifyEntityList);
|
||||
foreach (var classifyEntity in classifyEntityList)
|
||||
{
|
||||
returnValue.AddRange(FindAllChildren(classifyEntities, classifyEntity.Id, false));
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static List<ClassifyEntity> FindAllNotChildren(List<ClassifyEntity> classifyEntities, int baseId)
|
||||
{
|
||||
var children = FindAllChildren(classifyEntities, baseId, true);
|
||||
return classifyEntities.Where(x => !children.Contains(x)).ToList();
|
||||
}
|
||||
|
||||
public static List<ClassifyEntity> Structured(List<ClassifyEntity> classifyEntities, int baseId = 0, int hierarchy = 0)
|
||||
{
|
||||
var returnValue = new List<ClassifyEntity>();
|
||||
var classifyEntityList = classifyEntities.Where(x => x.ParentId == baseId).ToList();
|
||||
foreach (var classifyEntity in classifyEntityList)
|
||||
{
|
||||
classifyEntity.Name = classifyEntity.Name.InsertMultipleString("-", hierarchy * 2);
|
||||
returnValue.Add(classifyEntity);
|
||||
returnValue.AddRange(Structured(classifyEntities, classifyEntity.Id, hierarchy + 1));
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
}
|
848
CMS/JXCMS.CMS.Movie/Utils/HttpHelper.cs
Normal file
848
CMS/JXCMS.CMS.Movie/Utils/HttpHelper.cs
Normal file
@ -0,0 +1,848 @@
|
||||
/// <summary>
|
||||
/// 类说明:HttpHelper类,用来实现Http访问,Post或者Get方式的,直接访问,带Cookie的,带证书的等方式,可以设置代理
|
||||
/// 重要提示:请不要自行修改本类,如果因为你自己修改后将无法升级到新版本。如果确实有什么问题请到官方网站提建议,
|
||||
/// 我们一定会及时修改
|
||||
/// 编码日期:2011-09-20
|
||||
/// 编 码 人:苏飞
|
||||
/// 联系方式:361983679
|
||||
/// 官方网址:http://www.sufeinet.com/thread-3-1-1.html
|
||||
/// 修改日期:2020-02-10
|
||||
/// 版 本 号:2.2.9
|
||||
/// </summary>
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Net.Security;
|
||||
using System.Linq;
|
||||
using System.Net.Cache;
|
||||
|
||||
namespace SufeiUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Http连接操作帮助类
|
||||
/// </summary>
|
||||
public class HttpHelper
|
||||
{
|
||||
#region 预定义方变量
|
||||
//默认的编码
|
||||
private Encoding encoding = Encoding.Default;
|
||||
//Post数据编码
|
||||
private Encoding postencoding = Encoding.Default;
|
||||
//HttpWebRequest对象用来发起请求
|
||||
private HttpWebRequest request = null;
|
||||
//获取影响流的数据对象
|
||||
private HttpWebResponse response = null;
|
||||
//设置本地的出口ip和端口
|
||||
private IPEndPoint _IPEndPoint = null;
|
||||
#endregion
|
||||
|
||||
#region Public
|
||||
|
||||
/// <summary>
|
||||
/// 根据相传入的数据,得到相应页面数据
|
||||
/// </summary>
|
||||
/// <param name="item">参数类对象</param>
|
||||
/// <returns>返回HttpResult类型</returns>
|
||||
public HttpResult GetHtml(HttpItem item)
|
||||
{
|
||||
//返回参数
|
||||
HttpResult result = new HttpResult();
|
||||
try
|
||||
{
|
||||
//准备参数
|
||||
SetRequest(item);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//配置参数时出错
|
||||
return new HttpResult() { Cookie = string.Empty, Header = null, Html = ex.Message, StatusDescription = "配置参数时出错:" + ex.Message };
|
||||
}
|
||||
try
|
||||
{
|
||||
//请求数据
|
||||
using (response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
GetData(item, result);
|
||||
}
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
if (ex.Response != null)
|
||||
{
|
||||
using (response = (HttpWebResponse)ex.Response)
|
||||
{
|
||||
GetData(item, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Html = ex.Message;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Html = ex.Message;
|
||||
}
|
||||
if (item.IsToLower) result.Html = result.Html.ToLower();
|
||||
//重置request,response为空
|
||||
if (item.IsReset)
|
||||
{
|
||||
request = null;
|
||||
response = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetData
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据的并解析的方法
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="result"></param>
|
||||
private void GetData(HttpItem item, HttpResult result)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#region base
|
||||
//获取StatusCode
|
||||
result.StatusCode = response.StatusCode;
|
||||
//获取StatusDescription
|
||||
result.StatusDescription = response.StatusDescription;
|
||||
//获取Headers
|
||||
result.Header = response.Headers;
|
||||
//获取最后访问的URl
|
||||
result.ResponseUri = response.ResponseUri.ToString();
|
||||
//获取CookieCollection
|
||||
if (response.Cookies != null) result.CookieCollection = response.Cookies;
|
||||
//获取set-cookie
|
||||
if (response.Headers["set-cookie"] != null) result.Cookie = response.Headers["set-cookie"];
|
||||
#endregion
|
||||
|
||||
#region byte
|
||||
|
||||
//处理网页Byte
|
||||
byte[] ResponseByte = GetByte();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Html
|
||||
if (ResponseByte != null && ResponseByte.Length > 0)
|
||||
{
|
||||
//设置编码
|
||||
SetEncoding(item, result, ResponseByte);
|
||||
//得到返回的HTML
|
||||
result.Html = encoding.GetString(ResponseByte);
|
||||
}
|
||||
else
|
||||
{
|
||||
//没有返回任何Html代码
|
||||
result.Html = string.Empty;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置编码
|
||||
/// </summary>
|
||||
/// <param name="item">HttpItem</param>
|
||||
/// <param name="result">HttpResult</param>
|
||||
/// <param name="ResponseByte">byte[]</param>
|
||||
private void SetEncoding(HttpItem item, HttpResult result, byte[] ResponseByte)
|
||||
{
|
||||
//是否返回Byte类型数据
|
||||
if (item.ResultType == ResultType.Byte) result.ResultByte = ResponseByte;
|
||||
//从这里开始我们要无视编码了
|
||||
if (encoding == null)
|
||||
{
|
||||
Match meta = Regex.Match(Encoding.Default.GetString(ResponseByte), "<meta[^<]*charset=([^<]*)[\"']", RegexOptions.IgnoreCase);
|
||||
string c = string.Empty;
|
||||
if (meta != null && meta.Groups.Count > 0)
|
||||
{
|
||||
c = meta.Groups[1].Value.ToLower().Trim();
|
||||
}
|
||||
if (c.Length > 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
encoding = Encoding.GetEncoding(c.Replace("\"", string.Empty).Replace("'", "").Replace(";", "").Replace("iso-8859-1", "gbk").Trim());
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (string.IsNullOrEmpty(response.CharacterSet))
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(response.CharacterSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(response.CharacterSet))
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding = Encoding.GetEncoding(response.CharacterSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 提取网页Byte
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private byte[] GetByte()
|
||||
{
|
||||
byte[] ResponseByte = null;
|
||||
using (MemoryStream _stream = new MemoryStream())
|
||||
{
|
||||
//GZIIP处理
|
||||
if (response.ContentEncoding != null && response.ContentEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
//开始读取流并设置编码方式
|
||||
new GZipStream(response.GetResponseStream(), CompressionMode.Decompress).CopyTo(_stream, 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
//开始读取流并设置编码方式
|
||||
response.GetResponseStream().CopyTo(_stream, 1024);
|
||||
}
|
||||
//获取Byte
|
||||
ResponseByte = _stream.ToArray();
|
||||
}
|
||||
return ResponseByte;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetRequest
|
||||
|
||||
/// <summary>
|
||||
/// 为请求准备参数
|
||||
/// </summary>
|
||||
///<param name="item">参数列表</param>
|
||||
private void SetRequest(HttpItem item)
|
||||
{
|
||||
|
||||
// 验证证书
|
||||
SetCer(item);
|
||||
if (item.IPEndPoint != null)
|
||||
{
|
||||
_IPEndPoint = item.IPEndPoint;
|
||||
//设置本地的出口ip和端口
|
||||
request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
|
||||
}
|
||||
//设置Header参数
|
||||
if (item.Header != null && item.Header.Count > 0) foreach (string key in item.Header.AllKeys)
|
||||
{
|
||||
request.Headers.Add(key, item.Header[key]);
|
||||
}
|
||||
// 设置代理
|
||||
SetProxy(item);
|
||||
if (item.ProtocolVersion != null) request.ProtocolVersion = item.ProtocolVersion;
|
||||
request.ServicePoint.Expect100Continue = item.Expect100Continue;
|
||||
//请求方式Get或者Post
|
||||
request.Method = item.Method;
|
||||
request.Timeout = item.Timeout;
|
||||
request.KeepAlive = item.KeepAlive;
|
||||
request.ReadWriteTimeout = item.ReadWriteTimeout;
|
||||
if (!string.IsNullOrWhiteSpace(item.Host))
|
||||
{
|
||||
request.Host = item.Host;
|
||||
}
|
||||
if (item.IfModifiedSince != null) request.IfModifiedSince = Convert.ToDateTime(item.IfModifiedSince);
|
||||
if (item.Date!=null)
|
||||
{
|
||||
request.Date = Convert.ToDateTime(item.Date);
|
||||
}
|
||||
//Accept
|
||||
request.Accept = item.Accept;
|
||||
//ContentType返回类型
|
||||
request.ContentType = item.ContentType;
|
||||
//UserAgent客户端的访问类型,包括浏览器版本和操作系统信息
|
||||
request.UserAgent = item.UserAgent;
|
||||
// 编码
|
||||
encoding = item.Encoding;
|
||||
//设置安全凭证
|
||||
request.Credentials = item.ICredentials;
|
||||
//设置Cookie
|
||||
SetCookie(item);
|
||||
//来源地址
|
||||
request.Referer = item.Referer;
|
||||
//是否执行跳转功能
|
||||
request.AllowAutoRedirect = item.Allowautoredirect;
|
||||
if (item.MaximumAutomaticRedirections > 0)
|
||||
{
|
||||
request.MaximumAutomaticRedirections = item.MaximumAutomaticRedirections;
|
||||
}
|
||||
//设置Post数据
|
||||
SetPostData(item);
|
||||
//设置最大连接
|
||||
if (item.Connectionlimit > 0) request.ServicePoint.ConnectionLimit = item.Connectionlimit;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置证书
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private void SetCer(HttpItem item)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(item.CerPath))
|
||||
{
|
||||
//这一句一定要写在创建连接的前面。使用回调的方法进行证书验证。
|
||||
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
|
||||
//初始化对像,并设置请求的URL地址
|
||||
request = (HttpWebRequest)WebRequest.Create(item.URL);
|
||||
SetCerList(item);
|
||||
//将证书添加到请求里
|
||||
request.ClientCertificates.Add(new X509Certificate(item.CerPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
//初始化对像,并设置请求的URL地址
|
||||
request = (HttpWebRequest)WebRequest.Create(item.URL);
|
||||
SetCerList(item);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置多个证书
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private void SetCerList(HttpItem item)
|
||||
{
|
||||
if (item.ClentCertificates != null && item.ClentCertificates.Count > 0)
|
||||
{
|
||||
foreach (X509Certificate c in item.ClentCertificates)
|
||||
{
|
||||
request.ClientCertificates.Add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置Cookie
|
||||
/// </summary>
|
||||
/// <param name="item">Http参数</param>
|
||||
private void SetCookie(HttpItem item)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Cookie)) request.Headers[HttpRequestHeader.Cookie] = item.Cookie;
|
||||
//设置CookieCollection
|
||||
if (item.ResultCookieType == ResultCookieType.CookieCollection)
|
||||
{
|
||||
request.CookieContainer = new CookieContainer();
|
||||
if (item.CookieCollection != null && item.CookieCollection.Count > 0)
|
||||
{
|
||||
//默认为20个,如果超出需要增加长度
|
||||
if (item.CookieCollection.Count > 20)
|
||||
{
|
||||
request.CookieContainer.PerDomainCapacity = item.CookieCollection.Count;
|
||||
}
|
||||
request.CookieContainer.Add(item.CookieCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置Post数据
|
||||
/// </summary>
|
||||
/// <param name="item">Http参数</param>
|
||||
private void SetPostData(HttpItem item)
|
||||
{
|
||||
//验证在得到结果时是否有传入数据
|
||||
if (!request.Method.Trim().ToLower().Contains("get"))
|
||||
{
|
||||
if (item.PostEncoding != null)
|
||||
{
|
||||
postencoding = item.PostEncoding;
|
||||
}
|
||||
byte[] buffer = null;
|
||||
//写入Byte类型
|
||||
if (item.PostDataType == PostDataType.Byte && item.PostdataByte != null && item.PostdataByte.Length > 0)
|
||||
{
|
||||
//验证在得到结果时是否有传入数据
|
||||
buffer = item.PostdataByte;
|
||||
}//写入文件
|
||||
else if (item.PostDataType == PostDataType.FilePath && !string.IsNullOrWhiteSpace(item.Postdata))
|
||||
{
|
||||
StreamReader r = new StreamReader(item.Postdata, postencoding);
|
||||
buffer = postencoding.GetBytes(r.ReadToEnd());
|
||||
r.Close();
|
||||
} //写入字符串
|
||||
else if (!string.IsNullOrWhiteSpace(item.Postdata))
|
||||
{
|
||||
buffer = postencoding.GetBytes(item.Postdata);
|
||||
}
|
||||
if (buffer != null)
|
||||
{
|
||||
request.ContentLength = buffer.Length;
|
||||
request.GetRequestStream().Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.ContentLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置代理
|
||||
/// </summary>
|
||||
/// <param name="item">参数对象</param>
|
||||
private void SetProxy(HttpItem item)
|
||||
{
|
||||
bool isIeProxy = false;
|
||||
if (!string.IsNullOrWhiteSpace(item.ProxyIp))
|
||||
{
|
||||
isIeProxy = item.ProxyIp.ToLower().Contains("ieproxy");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(item.ProxyIp) && !isIeProxy)
|
||||
{
|
||||
//设置代理服务器
|
||||
if (item.ProxyIp.Contains(":"))
|
||||
{
|
||||
string[] plist = item.ProxyIp.Split(':');
|
||||
WebProxy myProxy = new WebProxy(plist[0].Trim(), Convert.ToInt32(plist[1].Trim()));
|
||||
//建议连接
|
||||
myProxy.Credentials = new NetworkCredential(item.ProxyUserName, item.ProxyPwd);
|
||||
//给当前请求对象
|
||||
request.Proxy = myProxy;
|
||||
}
|
||||
else
|
||||
{
|
||||
WebProxy myProxy = new WebProxy(item.ProxyIp, false);
|
||||
//建议连接
|
||||
myProxy.Credentials = new NetworkCredential(item.ProxyUserName, item.ProxyPwd);
|
||||
//给当前请求对象
|
||||
request.Proxy = myProxy;
|
||||
}
|
||||
}
|
||||
else if (isIeProxy)
|
||||
{
|
||||
//设置为IE代理
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Proxy = item.WebProxy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region private main
|
||||
/// <summary>
|
||||
/// 回调验证证书问题
|
||||
/// </summary>
|
||||
/// <param name="sender">流对象</param>
|
||||
/// <param name="certificate">证书</param>
|
||||
/// <param name="chain">X509Chain</param>
|
||||
/// <param name="errors">SslPolicyErrors</param>
|
||||
/// <returns>bool</returns>
|
||||
private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; }
|
||||
|
||||
/// <summary>
|
||||
/// 通过设置这个属性,可以在发出连接的时候绑定客户端发出连接所使用的IP地址。
|
||||
/// </summary>
|
||||
/// <param name="servicePoint"></param>
|
||||
/// <param name="remoteEndPoint"></param>
|
||||
/// <param name="retryCount"></param>
|
||||
/// <returns></returns>
|
||||
private IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
|
||||
{
|
||||
return _IPEndPoint;//端口号
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region public calss
|
||||
/// <summary>
|
||||
/// Http请求参考类
|
||||
/// </summary>
|
||||
public class HttpItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求URL必须填写
|
||||
/// </summary>
|
||||
public string URL { get; set; }
|
||||
string _Method = "GET";
|
||||
/// <summary>
|
||||
/// 请求方式默认为GET方式,当为POST方式时必须设置Postdata的值
|
||||
/// </summary>
|
||||
public string Method
|
||||
{
|
||||
get { return _Method; }
|
||||
set { _Method = value; }
|
||||
}
|
||||
int _Timeout = 100000;
|
||||
/// <summary>
|
||||
/// 默认请求超时时间
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return _Timeout; }
|
||||
set { _Timeout = value; }
|
||||
}
|
||||
int _ReadWriteTimeout = 30000;
|
||||
/// <summary>
|
||||
/// 默认写入Post数据超时间
|
||||
/// </summary>
|
||||
public int ReadWriteTimeout
|
||||
{
|
||||
get { return _ReadWriteTimeout; }
|
||||
set { _ReadWriteTimeout = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置Host的标头信息
|
||||
/// </summary>
|
||||
public string Host { get; set; }
|
||||
Boolean _KeepAlive = true;
|
||||
/// <summary>
|
||||
/// 获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接默认为true。
|
||||
/// </summary>
|
||||
public Boolean KeepAlive
|
||||
{
|
||||
get { return _KeepAlive; }
|
||||
set { _KeepAlive = value; }
|
||||
}
|
||||
string _Accept = "text/html, application/xhtml+xml, */*";
|
||||
/// <summary>
|
||||
/// 请求标头值 默认为text/html, application/xhtml+xml, */*
|
||||
/// </summary>
|
||||
public string Accept
|
||||
{
|
||||
get { return _Accept; }
|
||||
set { _Accept = value; }
|
||||
}
|
||||
string _ContentType = "text/html";
|
||||
/// <summary>
|
||||
/// 请求返回类型默认 text/html
|
||||
/// </summary>
|
||||
public string ContentType
|
||||
{
|
||||
get { return _ContentType; }
|
||||
set { _ContentType = value; }
|
||||
}
|
||||
string _UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
|
||||
/// <summary>
|
||||
/// 客户端访问信息默认Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
|
||||
/// </summary>
|
||||
public string UserAgent
|
||||
{
|
||||
get { return _UserAgent; }
|
||||
set { _UserAgent = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回数据编码默认为NUll,可以自动识别,一般为utf-8,gbk,gb2312
|
||||
/// </summary>
|
||||
public Encoding Encoding { get; set; }
|
||||
private PostDataType _PostDataType = PostDataType.String;
|
||||
/// <summary>
|
||||
/// Post的数据类型
|
||||
/// </summary>
|
||||
public PostDataType PostDataType
|
||||
{
|
||||
get { return _PostDataType; }
|
||||
set { _PostDataType = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Post请求时要发送的字符串Post数据
|
||||
/// </summary>
|
||||
public string Postdata { get; set; }
|
||||
/// <summary>
|
||||
/// Post请求时要发送的Byte类型的Post数据
|
||||
/// </summary>
|
||||
public byte[] PostdataByte { get; set; }
|
||||
/// <summary>
|
||||
/// Cookie对象集合
|
||||
/// </summary>
|
||||
public CookieCollection CookieCollection { get; set; }
|
||||
/// <summary>
|
||||
/// 请求时的Cookie
|
||||
/// </summary>
|
||||
public string Cookie { get; set; }
|
||||
/// <summary>
|
||||
/// 来源地址,上次访问地址
|
||||
/// </summary>
|
||||
public string Referer { get; set; }
|
||||
/// <summary>
|
||||
/// 证书绝对路径
|
||||
/// </summary>
|
||||
public string CerPath { get; set; }
|
||||
/// <summary>
|
||||
/// 设置代理对象,不想使用IE默认配置就设置为Null,而且不要设置ProxyIp
|
||||
/// </summary>
|
||||
public WebProxy WebProxy { get; set; }
|
||||
private Boolean isToLower = false;
|
||||
/// <summary>
|
||||
/// 是否设置为全文小写,默认为不转化
|
||||
/// </summary>
|
||||
public Boolean IsToLower
|
||||
{
|
||||
get { return isToLower; }
|
||||
set { isToLower = value; }
|
||||
}
|
||||
private DateTime? _Date = null;
|
||||
/// <summary>
|
||||
/// 获取或设置要在 HTTP 请求中使用的 Date HTTP 标头值。默认不填写
|
||||
/// </summary>
|
||||
public DateTime? Date
|
||||
{
|
||||
get { return _Date; }
|
||||
set { _Date = value; }
|
||||
}
|
||||
private Boolean allowautoredirect = false;
|
||||
/// <summary>
|
||||
/// 支持跳转页面,查询结果将是跳转后的页面,默认是不跳转
|
||||
/// </summary>
|
||||
public Boolean Allowautoredirect
|
||||
{
|
||||
get { return allowautoredirect; }
|
||||
set { allowautoredirect = value; }
|
||||
}
|
||||
private int connectionlimit = 1024;
|
||||
/// <summary>
|
||||
/// 最大连接数
|
||||
/// </summary>
|
||||
public int Connectionlimit
|
||||
{
|
||||
get { return connectionlimit; }
|
||||
set { connectionlimit = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 代理Proxy 服务器用户名
|
||||
/// </summary>
|
||||
public string ProxyUserName { get; set; }
|
||||
/// <summary>
|
||||
/// 代理 服务器密码
|
||||
/// </summary>
|
||||
public string ProxyPwd { get; set; }
|
||||
/// <summary>
|
||||
/// 代理 服务IP,如果要使用IE代理就设置为ieproxy
|
||||
/// </summary>
|
||||
public string ProxyIp { get; set; }
|
||||
private ResultType resulttype = ResultType.String;
|
||||
/// <summary>
|
||||
/// 设置返回类型String和Byte
|
||||
/// </summary>
|
||||
public ResultType ResultType
|
||||
{
|
||||
get { return resulttype; }
|
||||
set { resulttype = value; }
|
||||
}
|
||||
private WebHeaderCollection header = new WebHeaderCollection();
|
||||
/// <summary>
|
||||
/// header对象
|
||||
/// </summary>
|
||||
public WebHeaderCollection Header
|
||||
{
|
||||
get { return header; }
|
||||
set { header = value; }
|
||||
}
|
||||
/// <summary>
|
||||
// 获取或设置用于请求的 HTTP 版本。返回结果:用于请求的 HTTP 版本。默认为 System.Net.HttpVersion.Version11。
|
||||
/// </summary>
|
||||
public Version ProtocolVersion { get; set; }
|
||||
private Boolean _expect100continue = false;
|
||||
/// <summary>
|
||||
/// 获取或设置一个 System.Boolean 值,该值确定是否使用 100-Continue 行为。如果 POST 请求需要 100-Continue 响应,则为 true;否则为 false。默认值为 true。
|
||||
/// </summary>
|
||||
public Boolean Expect100Continue
|
||||
{
|
||||
get { return _expect100continue; }
|
||||
set { _expect100continue = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置509证书集合
|
||||
/// </summary>
|
||||
public X509CertificateCollection ClentCertificates { get; set; }
|
||||
/// <summary>
|
||||
/// 设置或获取Post参数编码,默认的为Default编码
|
||||
/// </summary>
|
||||
public Encoding PostEncoding { get; set; }
|
||||
private ResultCookieType _ResultCookieType = ResultCookieType.String;
|
||||
/// <summary>
|
||||
/// Cookie返回类型,默认的是只返回字符串类型
|
||||
/// </summary>
|
||||
public ResultCookieType ResultCookieType
|
||||
{
|
||||
get { return _ResultCookieType; }
|
||||
set { _ResultCookieType = value; }
|
||||
}
|
||||
private ICredentials _ICredentials = CredentialCache.DefaultCredentials;
|
||||
/// <summary>
|
||||
/// 获取或设置请求的身份验证信息。
|
||||
/// </summary>
|
||||
public ICredentials ICredentials
|
||||
{
|
||||
get { return _ICredentials; }
|
||||
set { _ICredentials = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置请求将跟随的重定向的最大数目
|
||||
/// </summary>
|
||||
public int MaximumAutomaticRedirections { get; set; }
|
||||
private DateTime? _IfModifiedSince = null;
|
||||
/// <summary>
|
||||
/// 获取和设置IfModifiedSince,默认为当前日期和时间
|
||||
/// </summary>
|
||||
public DateTime? IfModifiedSince
|
||||
{
|
||||
get { return _IfModifiedSince; }
|
||||
set { _IfModifiedSince = value; }
|
||||
}
|
||||
#region ip-port
|
||||
private IPEndPoint _IPEndPoint = null;
|
||||
/// <summary>
|
||||
/// 设置本地的出口ip和端口
|
||||
/// </summary>]
|
||||
/// <example>
|
||||
///item.IPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"),80);
|
||||
/// </example>
|
||||
public IPEndPoint IPEndPoint
|
||||
{
|
||||
get { return _IPEndPoint; }
|
||||
set { _IPEndPoint = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool _isReset = false;
|
||||
/// <summary>
|
||||
/// 是否重置request,response的值,默认不重置,当设置为True时request,response将被设置为Null
|
||||
/// </summary>
|
||||
public bool IsReset
|
||||
{
|
||||
get { return _isReset; }
|
||||
set { _isReset = value; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Http返回参数类
|
||||
/// </summary>
|
||||
public class HttpResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Http请求返回的Cookie
|
||||
/// </summary>
|
||||
public string Cookie { get; set; }
|
||||
/// <summary>
|
||||
/// Cookie对象集合
|
||||
/// </summary>
|
||||
public CookieCollection CookieCollection { get; set; }
|
||||
private string _html = string.Empty;
|
||||
/// <summary>
|
||||
/// 返回的String类型数据 只有ResultType.String时才返回数据,其它情况为空
|
||||
/// </summary>
|
||||
public string Html
|
||||
{
|
||||
get { return _html; }
|
||||
set { _html = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回的Byte数组 只有ResultType.Byte时才返回数据,其它情况为空
|
||||
/// </summary>
|
||||
public byte[] ResultByte { get; set; }
|
||||
/// <summary>
|
||||
/// header对象
|
||||
/// </summary>
|
||||
public WebHeaderCollection Header { get; set; }
|
||||
/// <summary>
|
||||
/// 返回状态说明
|
||||
/// </summary>
|
||||
public string StatusDescription { get; set; }
|
||||
/// <summary>
|
||||
/// 返回状态码,默认为OK
|
||||
/// </summary>
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
/// <summary>
|
||||
/// 最后访问的URl
|
||||
/// </summary>
|
||||
public string ResponseUri { get; set; }
|
||||
/// <summary>
|
||||
/// 获取重定向的URl
|
||||
/// </summary>
|
||||
public string RedirectUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Header != null && Header.Count > 0)
|
||||
{
|
||||
if (Header.AllKeys.Any(k => k.ToLower().Contains("location")))
|
||||
{
|
||||
string baseurl = Header["location"].ToString().Trim();
|
||||
string locationurl = baseurl.ToLower();
|
||||
if (!string.IsNullOrWhiteSpace(locationurl))
|
||||
{
|
||||
bool b = locationurl.StartsWith("http://") || locationurl.StartsWith("https://");
|
||||
if (!b)
|
||||
{
|
||||
baseurl = new Uri(new Uri(ResponseUri), baseurl).AbsoluteUri;
|
||||
}
|
||||
}
|
||||
return baseurl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回类型
|
||||
/// </summary>
|
||||
public enum ResultType
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示只返回字符串 只有Html有数据
|
||||
/// </summary>
|
||||
String,
|
||||
/// <summary>
|
||||
/// 表示返回字符串和字节流 ResultByte和Html都有数据返回
|
||||
/// </summary>
|
||||
Byte
|
||||
}
|
||||
/// <summary>
|
||||
/// Post的数据格式默认为string
|
||||
/// </summary>
|
||||
public enum PostDataType
|
||||
{
|
||||
/// <summary>
|
||||
/// 字符串类型,这时编码Encoding可不设置
|
||||
/// </summary>
|
||||
String,
|
||||
/// <summary>
|
||||
/// Byte类型,需要设置PostdataByte参数的值编码Encoding可设置为空
|
||||
/// </summary>
|
||||
Byte,
|
||||
/// <summary>
|
||||
/// 传文件,Postdata必须设置为文件的绝对路径,必须设置Encoding的值
|
||||
/// </summary>
|
||||
FilePath
|
||||
}
|
||||
/// <summary>
|
||||
/// Cookie返回类型
|
||||
/// </summary>
|
||||
public enum ResultCookieType
|
||||
{
|
||||
/// <summary>
|
||||
/// 只返回字符串类型的Cookie
|
||||
/// </summary>
|
||||
String,
|
||||
/// <summary>
|
||||
/// CookieCollection格式的Cookie集合同时也返回String类型的cookie
|
||||
/// </summary>
|
||||
CookieCollection
|
||||
}
|
||||
#endregion
|
||||
}
|
16
CMS/JXCMS.CMS.Movie/Views/Default/Home/Test.cshtml
Normal file
16
CMS/JXCMS.CMS.Movie/Views/Default/Home/Test.cshtml
Normal file
@ -0,0 +1,16 @@
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
@Html.Action("Index")
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -110,12 +110,9 @@ namespace JXCMS.Core.Db
|
||||
jsonObject.Add("Db", JObject.FromObject(dbConfig));
|
||||
}
|
||||
|
||||
using (var writer = new StreamWriter(filePath))
|
||||
using (JsonTextWriter jsonwriter = new JsonTextWriter(writer))
|
||||
{
|
||||
jsonwriter.Formatting = Formatting.Indented;
|
||||
jsonObject.WriteTo(jsonwriter);
|
||||
}
|
||||
using var writer = new StreamWriter(filePath);
|
||||
using JsonTextWriter jsonWriter = new JsonTextWriter(writer) {Formatting = Formatting.Indented};
|
||||
jsonObject.WriteTo(jsonWriter);
|
||||
}
|
||||
}
|
||||
}
|
99
Core/JXCMS.Core/Extensions/HtmlHelperViewExtensions.cs
Normal file
99
Core/JXCMS.Core/Extensions/HtmlHelperViewExtensions.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Rendering
|
||||
{
|
||||
public static class HtmlHelperViewExtensions
|
||||
{
|
||||
public static IHtmlContent Action(this IHtmlHelper helper, string action, object parameters = null)
|
||||
{
|
||||
var controller = (string)helper.ViewContext.RouteData.Values["controller"];
|
||||
|
||||
return Action(helper, action, controller, parameters);
|
||||
}
|
||||
|
||||
public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, object parameters = null)
|
||||
{
|
||||
var area = (string)helper.ViewContext.RouteData.Values["area"];
|
||||
|
||||
return Action(helper, action, controller, area, parameters);
|
||||
}
|
||||
|
||||
public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
|
||||
{
|
||||
if (action == null)
|
||||
throw new ArgumentNullException("action");
|
||||
|
||||
if (controller == null)
|
||||
throw new ArgumentNullException("controller");
|
||||
|
||||
|
||||
var task = RenderActionAsync(helper, action, controller, area, parameters);
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
private static async Task<IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
|
||||
{
|
||||
// fetching required services for invocation
|
||||
var serviceProvider = helper.ViewContext.HttpContext.RequestServices;
|
||||
var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
|
||||
var httpContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IHttpContextAccessor>();
|
||||
var actionSelector = serviceProvider.GetRequiredService<IActionSelector>();
|
||||
|
||||
// creating new action invocation context
|
||||
var routeData = new RouteData();
|
||||
foreach (var router in helper.ViewContext.RouteData.Routers)
|
||||
{
|
||||
routeData.PushState(router, null, null);
|
||||
}
|
||||
routeData.PushState(null, new RouteValueDictionary(new { controller = controller, action = action, area = area }), null);
|
||||
routeData.PushState(null, new RouteValueDictionary(parameters ?? new { }), null);
|
||||
|
||||
//get the actiondescriptor
|
||||
RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext) { RouteData = routeData };
|
||||
var candidates = actionSelector.SelectCandidates(routeContext);
|
||||
var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates);
|
||||
|
||||
var originalActionContext = actionContextAccessor.ActionContext;
|
||||
var originalhttpContext = httpContextAccessor.HttpContext;
|
||||
try
|
||||
{
|
||||
var newHttpContext = serviceProvider.GetRequiredService<IHttpContextFactory>().Create(helper.ViewContext.HttpContext.Features);
|
||||
if (newHttpContext.Items.ContainsKey(typeof(IUrlHelper)))
|
||||
{
|
||||
newHttpContext.Items.Remove(typeof(IUrlHelper));
|
||||
}
|
||||
newHttpContext.Response.Body = new MemoryStream();
|
||||
var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
|
||||
actionContextAccessor.ActionContext = actionContext;
|
||||
var invoker = serviceProvider.GetRequiredService<IActionInvokerFactory>().CreateInvoker(actionContext);
|
||||
await invoker.InvokeAsync();
|
||||
newHttpContext.Response.Body.Position = 0;
|
||||
using (var reader = new StreamReader(newHttpContext.Response.Body))
|
||||
{
|
||||
return new HtmlString(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new HtmlString(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
actionContextAccessor.ActionContext = originalActionContext;
|
||||
httpContextAccessor.HttpContext = originalhttpContext;
|
||||
if (helper.ViewContext.HttpContext.Items.ContainsKey(typeof(IUrlHelper)))
|
||||
{
|
||||
helper.ViewContext.HttpContext.Items.Remove(typeof(IUrlHelper));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
namespace JXCMS.Core.Extensions
|
||||
using System.Text;
|
||||
|
||||
namespace JXCMS.Core.Extensions
|
||||
{
|
||||
public static class StringExtension
|
||||
{
|
||||
@ -6,5 +8,18 @@
|
||||
{
|
||||
return string.IsNullOrEmpty(str);
|
||||
}
|
||||
|
||||
public static string InsertMultipleString(this string str, string insertStr, int count)
|
||||
{
|
||||
StringBuilder returnValue = new StringBuilder();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
returnValue.Append(insertStr);
|
||||
}
|
||||
|
||||
returnValue.Append(str);
|
||||
return returnValue.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
@ -11,12 +11,12 @@
|
||||
<PackageReference Include="BouncyCastle" Version="1.8.5" />
|
||||
<PackageReference Include="DeviceDetector.NET" Version="4.1.0" />
|
||||
<PackageReference Include="DotnetSpider" Version="4.0.7" />
|
||||
<PackageReference Include="FreeSql.Extensions.BaseEntity" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Provider.MySql" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Provider.Oracle" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Provider.PostgreSQL" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Provider.SqlServer" Version="0.11.20" />
|
||||
<PackageReference Include="FreeSql.Extensions.BaseEntity" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="FreeSql.Provider.MySql" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="FreeSql.Provider.Oracle" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="FreeSql.Provider.PostgreSQL" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="FreeSql.Provider.SqlServer" Version="1.2.0-preview1" />
|
||||
<PackageReference Include="McMaster.NETCore.Plugins" Version="0.3.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Quartz" Version="3.0.7" />
|
||||
|
@ -52,6 +52,42 @@ namespace JXCMS.Core.TimingTask
|
||||
{
|
||||
return await _scheduler.DeleteJobs(jobKeys);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Corn表达式的运行时间
|
||||
/// </summary>
|
||||
/// <param name="cron">表达式</param>
|
||||
/// <param name="times">计算次数</param>
|
||||
/// <param name="startTime">开始时间</param>
|
||||
/// <returns></returns>
|
||||
public static string GetCronSchedule(String cron, int times, DateTimeOffset startTime)
|
||||
{
|
||||
String timeSchedule = "";
|
||||
if (!CronExpression.IsValidExpression(cron))
|
||||
{
|
||||
return "Cron表达式不合法!";
|
||||
}
|
||||
try
|
||||
{
|
||||
ITrigger trigger1 = TriggerBuilder.Create()
|
||||
|
||||
.WithCronSchedule(cron)
|
||||
.StartNow()
|
||||
.Build();
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
DateTimeOffset? s = trigger1.GetFireTimeAfter(startTime);
|
||||
DateTime? time = s?.LocalDateTime;
|
||||
timeSchedule = time?.ToString("F");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
timeSchedule = "未知时间";
|
||||
}
|
||||
|
||||
return timeSchedule;
|
||||
}
|
||||
}
|
||||
}
|
15
Core/JXCMS.Core/Utils/ConfigHelper.cs
Normal file
15
Core/JXCMS.Core/Utils/ConfigHelper.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace JXCMS.Core.Utils
|
||||
{
|
||||
public class ConfigHelper
|
||||
{
|
||||
public static IConfiguration Configs { get; set; }
|
||||
|
||||
public static string GetValue(string key)
|
||||
{
|
||||
var res = Configs.GetSection(key).Value;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user