提交 fe80acfc authored 作者: songchuancai's avatar songchuancai

ss

上级
BeetleX.Blog/Properties/
BeetleX.Blog/bin/
BeetleX.Blog/obj/
.vs/XBlog/v15/
.vs/
差异被折叠。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
<_LastSelectedProfileId>D:\VisualStudio\BitHub\XBlog\BeetleX.Blog\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
</PropertyGroup>
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
namespace BeetleX.Blog
{
public class CacheHelper
{
private static ConcurrentDictionary<string, CacheItem> mCache = new ConcurrentDictionary<string, CacheItem>();
public static object Get(string key)
{
if (mCache.TryGetValue(key, out CacheItem item))
{
if (TimeWatch.GetTotalSeconds() > item.ActiveTime)
{
return null;
}
return item.Data;
}
return null;
}
public static T Get<T>(string key)
{
return (T)Get(key);
}
public static void Set(string key, object data, double seconds = 60)
{
CacheItem item = new CacheItem();
item.Data = data;
item.ActiveTime = TimeWatch.GetTotalSeconds() + seconds;
mCache[key] = item;
}
class CacheItem
{
public object Data { get; set; }
public double ActiveTime { get; set; }
}
}
}
using BeetleX.FastHttpApi;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
namespace BeetleX.Blog
{
public class JWTHelper
{
public const string TOKEN_KEY = "Token";
private string mIssuer = null;
private string mAudience = null;
private SecurityKey mSecurityKey;
private SigningCredentials mSigningCredentials;
private TokenValidationParameters mTokenValidation = new TokenValidationParameters();
private JwtSecurityTokenHandler mJwtSecurityTokenHandler = new JwtSecurityTokenHandler();
public JWTHelper(string issuer, string audience, byte[] key)
{
mIssuer = issuer;
mAudience = audience;
mSecurityKey = new SymmetricSecurityKey(key);
if (string.IsNullOrEmpty(mIssuer))
{
mTokenValidation.ValidateIssuer = false;
}
else
{
mTokenValidation.ValidIssuer = mIssuer;
}
if (string.IsNullOrEmpty(mAudience))
{
mTokenValidation.ValidateAudience = false;
}
else
{
mTokenValidation.ValidAudience = mAudience;
}
mTokenValidation.IssuerSigningKey = mSecurityKey;
mSigningCredentials = new SigningCredentials(mSecurityKey, SecurityAlgorithms.HmacSha256);
Expires = 60 * 24;
}
public int Expires { get; set; }
public void ClearToken(HttpResponse response)
{
response.SetCookie(TOKEN_KEY, "", "/", DateTime.Now);
}
public void CreateToken(HttpResponse response, string name, string role, int timeout = 20)
{
string token = CreateToken(name, role, timeout);
response.SetCookie(TOKEN_KEY, token, "/", DateTime.Now.AddDays(100));
}
public string CreateToken(string name, string role, int timeout = 20)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim("Name", name));
claimsIdentity.AddClaim(new Claim("Role", role));
var item = mJwtSecurityTokenHandler.CreateEncodedJwt(mIssuer, mAudience, claimsIdentity, DateTime.Now.AddMinutes(-5),
DateTime.Now.AddMinutes(timeout), DateTime.Now,
mSigningCredentials);
return item;
}
public ClaimsPrincipal ValidateToken(string token)
{
return mJwtSecurityTokenHandler.ValidateToken(token, mTokenValidation, out var securityToken);
}
public UserInfo GetUserInfo(HttpRequest request)
{
string token = request.Cookies[TOKEN_KEY];
if (string.IsNullOrEmpty(token))
return null;
try
{
return GetUserInfo(token);
}
catch (Exception e_)
{
HttpApiServer server = request.Server;
if (server.EnableLog(EventArgs.LogType.Info))
{
server.Log(EventArgs.LogType.Info, $"{request.RemoteIPAddress} get token error {e_.Message}");
}
return null;
}
}
public UserInfo GetUserInfo(string token)
{
UserInfo userInfo = new UserInfo();
if (!string.IsNullOrEmpty(token))
{
var info = ValidateToken(token);
ClaimsIdentity identity = info?.Identity as ClaimsIdentity;
userInfo.Name = identity?.Claims?.FirstOrDefault(c => c.Type == "Name")?.Value;
userInfo.Role = identity?.Claims?.FirstOrDefault(c => c.Type == "Role")?.Value;
}
return userInfo;
}
public class UserInfo
{
public string Name;
public string Role;
}
public static JWTHelper Default
{
get;
set;
}
public static void Init()
{
Default = new JWTHelper("BeetleX", "BeetleX", Convert.FromBase64String(DBModules.DBHelper.Default.Setting.JwtKey.Value));
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace BeetleX.Blog
{
public class TCloudCosObject
{
public TCloudCosObject(string secretId, string secretKey, string host)
{
if (host[host.Length - 1] == '/')
host = host.Substring(0, host.Length - 1);
Host = host;
SecretId = secretId;
SecretKey = secretKey;
}
public static int DefaultConnectionLimit
{
get
{
return ServicePointManager.DefaultConnectionLimit;
}
set
{
ServicePointManager.DefaultConnectionLimit = value;
}
}
public string Host { get; set; }
public string SecretId { get; set; }
public string SecretKey { get; set; }
private string GetSignature(string method, string filename)
{
method = method.ToLower();
if (filename.IndexOf("/") != 0)
{
filename = "/" + filename;
}
var baseDate = new System.DateTime(1970, 1, 1);
var now = (int)(DateTime.Now.AddDays(-5) - baseDate).TotalSeconds;
var exp = (int)(DateTime.Now.AddMinutes(2) - baseDate).TotalSeconds;
string signTime = now + ";" + exp;
string keyTime = signTime;
string singKey = HmacSha1Sign(keyTime, SecretKey);
string httpString = method + "\n" + filename + "\n\n\n";
string sha1edHttpString = EncryptToSHA1(httpString);
string stringToSign = $"sha1\n{signTime}\n{sha1edHttpString}\n";
string signature = HmacSha1Sign(stringToSign, singKey);
var authorization = $"q-sign-algorithm=sha1&q-ak={SecretId}&q-sign-time={signTime}&q-key-time={signTime}&q-header-list=&q-url-param-list=&q-signature={signature}";
return authorization;
}
public string GetPutToken(string file)
{
return GetSignature("put", file);
}
public string GetPutUrl(string file)
{
if (file[0] != '/')
file = "/" + file;
return Host + file;
}
private string EncryptToSHA1(string str)
{
var buffer = Encoding.UTF8.GetBytes(str);
var data = System.Security.Cryptography.SHA1.Create().ComputeHash(buffer);
var sb = new StringBuilder();
foreach (var t in data)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString().ToLower();
}
private string HmacSha1Sign(string EncryptText, string EncryptKey)
{
HMACSHA1 myHMACSHA1 = new HMACSHA1(Encoding.Default.GetBytes(EncryptKey));
byte[] RstRes = myHMACSHA1.ComputeHash(Encoding.Default.GetBytes(EncryptText));
StringBuilder EnText = new StringBuilder();
foreach (byte Byte in RstRes)
{
EnText.AppendFormat("{0:x2}", Byte);
}
return EnText.ToString();
}
public bool Put(string file, string localFile)
{
using (System.IO.Stream stream = System.IO.File.OpenRead(localFile))
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
return Put(file, data);
}
}
public bool Put(string file, byte[] data)
{
if (file[0] != '/')
file = "/" + file;
var sign = GetSignature("put", file);
string url = Host + file;
WebClient webClient = new WebClient();
webClient.Headers.Add("Authorization", sign);
webClient.Credentials = CredentialCache.DefaultCredentials;
try
{
Stream postStream = webClient.OpenWrite(url, "PUT");
postStream.Write(data, 0, data.Length);
postStream.Close();
}
catch (WebException webError)
{
string errorText;
using (System.IO.StreamReader reader = new StreamReader(webError.Response.GetResponseStream()))
{
errorText = reader.ReadToEnd();
}
throw new Exception(errorText, webError);
}
return true;
}
public bool Del(string file)
{
if (file[0] != '/')
file = "/" + file;
var sign = GetSignature("DELETE", file);
string url = Host + file;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "DELETE";
request.Headers.Add("Authorization", sign);
try
{
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
catch (WebException webError)
{
string errorText;
using (System.IO.StreamReader reader = new StreamReader(webError.Response.GetResponseStream()))
{
errorText = reader.ReadToEnd();
}
throw new Exception(errorText, webError);
}
return true;
}
}
}
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace BeetleX.Blog
{
class Units
{
public static string MD5Encrypt(string value)
{
using (MD5 md5Hash = MD5.Create())
{
byte[] hash = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(value));
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
public static string ImagePath { get; set; }
public static string GetImageUrl(string url)
{
string[] host = null;
if (string.IsNullOrEmpty(url))
url = "/images/small_img.jpg";
if (!string.IsNullOrEmpty(DBModules.DBHelper.Default.Setting.ImgHost.Value))
{
host = DBModules.DBHelper.Default.Setting.ImgHost.Value.Split(';', StringSplitOptions.RemoveEmptyEntries);
}
if (host == null || host.Length == 0)
return url;
else
{
string imghost = "http://" + host[Math.Abs(url.GetHashCode()) % host.Length];
return imghost + url;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
using Peanut;
using BeetleX.Blog.DBModules;
using System.Linq;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/blog")]
[AdminFilter]
public class AdminBlog
{
[Post]
public void Modify(long id, string title, bool top, string tag, long category, string sourceUrl, string content,
string summary)
{
DBModules.Blog item;
if (id > 0)
{
item = DBContext.Load<DBModules.Blog>(id);
}
else
{
item = new DBModules.Blog();
}
if (item != null)
{
item.Title = title;
item.Top = top;
item.Tags = tag;
item.CategoryID = category;
Category cate = DBContext.Load<Category>(category);
if (cate != null)
item.Category = cate.Name;
item.SourceUrl = sourceUrl;
item.Content = content;
item.Summary = summary;
item.Save();
RefreshBlog refreshBlog = new RefreshBlog();
refreshBlog.BlogID = item.ID;
refreshBlog.Status = 1;
refreshBlog.Save();
}
}
public void AllSyncToES()
{
foreach (DBModules.Blog item in new Expression().List<DBModules.Blog>())
{
RefreshBlog refreshBlog = new RefreshBlog();
refreshBlog.BlogID = item.ID;
refreshBlog.Status = 1;
refreshBlog.Save();
}
}
[Post]
public void Delete(long[] id)
{
if (id != null && id.Length > 0)
{
(DBModules.Blog.iD == id).Delete<DBModules.Blog>();
(DBModules.Comment.blogID == id).Delete<DBModules.Comment>();
foreach (var item in id)
{
RefreshBlog refreshBlog = new RefreshBlog();
refreshBlog.BlogID = item;
refreshBlog.Status = 0;
refreshBlog.Save();
}
}
}
public object Get(long id)
{
var item = DBContext.Load<DBModules.Blog>(id);
if (item != null)
return new { item.ID, item.Title, item.Content, item.CategoryID, item.SourceUrl, item.Tags, item.Top };
return new object();
}
public Object List(long category, int index)
{
int size = 15;
Expression exp = new Expression();
if (category > 0)
exp &= DBModules.Blog.categoryID == category;
int count = exp.Count<DBModules.Blog>();
int pages = count / size;
if (count % size > 0)
pages++;
var datas = exp.List<DBModules.Blog>(new Region(index, size), DBModules.Blog.createTime.Desc);
var items = from a in datas select new { a.ID, a.Title, a.Category, a.Top, CreateTime = a.CreateTime.ToString() };
return new { Index = index, Pages = pages, Items = items };
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var AdminBlogModifyUrl='/admin/blog/Modify';
/**
* 'var result= await AdminBlogModify(params);'
**/
function AdminBlogModify(id,title,top,tag,category,sourceUrl,content,summary,useHttp)
{
return api(AdminBlogModifyUrl,{id:id,title:title,top:top,tag:tag,category:category,sourceUrl:sourceUrl,content:content,summary:summary},useHttp,true).sync();
}
/**
* 'AdminBlogModifyAsync(params).execute(function(result){},useHttp);'
**/
function AdminBlogModifyAsync(id,title,top,tag,category,sourceUrl,content,summary,useHttp)
{
return api(AdminBlogModifyUrl,{id:id,title:title,top:top,tag:tag,category:category,sourceUrl:sourceUrl,content:content,summary:summary},useHttp,true);
}
var AdminBlogAllSyncToESUrl='/admin/blog/AllSyncToES';
/**
* 'var result= await AdminBlogAllSyncToES(params);'
**/
function AdminBlogAllSyncToES(useHttp)
{
return api(AdminBlogAllSyncToESUrl,{},useHttp).sync();
}
/**
* 'AdminBlogAllSyncToESAsync(params).execute(function(result){},useHttp);'
**/
function AdminBlogAllSyncToESAsync(useHttp)
{
return api(AdminBlogAllSyncToESUrl,{},useHttp);
}
var AdminBlogDeleteUrl='/admin/blog/Delete';
/**
* 'var result= await AdminBlogDelete(params);'
**/
function AdminBlogDelete(id,useHttp)
{
return api(AdminBlogDeleteUrl,{id:id},useHttp,true).sync();
}
/**
* 'AdminBlogDeleteAsync(params).execute(function(result){},useHttp);'
**/
function AdminBlogDeleteAsync(id,useHttp)
{
return api(AdminBlogDeleteUrl,{id:id},useHttp,true);
}
var AdminBlogGetUrl='/admin/blog/Get';
/**
* 'var result= await AdminBlogGet(params);'
**/
function AdminBlogGet(id,useHttp)
{
return api(AdminBlogGetUrl,{id:id},useHttp).sync();
}
/**
* 'AdminBlogGetAsync(params).execute(function(result){},useHttp);'
**/
function AdminBlogGetAsync(id,useHttp)
{
return api(AdminBlogGetUrl,{id:id},useHttp);
}
var AdminBlogListUrl='/admin/blog/List';
/**
* 'var result= await AdminBlogList(params);'
**/
function AdminBlogList(category,index,useHttp)
{
return api(AdminBlogListUrl,{category:category,index:index},useHttp).sync();
}
/**
* 'AdminBlogListAsync(params).execute(function(result){},useHttp);'
**/
function AdminBlogListAsync(category,index,useHttp)
{
return api(AdminBlogListUrl,{category:category,index:index},useHttp);
}
using BeetleX.FastHttpApi;
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.Blog.DBModules;
using System.Linq;
using Peanut;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/category")]
[AdminFilter]
public class AdminCategory
{
[Post]
public void Add(string name, string remark)
{
if ((Category.name == name).Count<Category>() == 0)
{
Category category = new Category();
category.Name = name;
category.Remark = remark;
category.Save();
}
}
public void Order(long id, bool up)
{
Category item = DBContext.Load<Category>(id);
if (item != null)
{
if (up)
item.OrderBy -= 1;
else
item.OrderBy += 1;
item.Save();
}
}
public void Del(long id)
{
(Category.iD == id).Delete<Category>();
}
public object List()
{
var items = new Expression().List<Category>(Category.orderBy.Asc);
return from a in items
select new { a.ID, a.Name, a.Remark };
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var AdminCategoryAddUrl='/admin/category/Add';
/**
* 'var result= await AdminCategoryAdd(params);'
**/
function AdminCategoryAdd(name,remark,useHttp)
{
return api(AdminCategoryAddUrl,{name:name,remark:remark},useHttp,true).sync();
}
/**
* 'AdminCategoryAddAsync(params).execute(function(result){},useHttp);'
**/
function AdminCategoryAddAsync(name,remark,useHttp)
{
return api(AdminCategoryAddUrl,{name:name,remark:remark},useHttp,true);
}
var AdminCategoryOrderUrl='/admin/category/Order';
/**
* 'var result= await AdminCategoryOrder(params);'
**/
function AdminCategoryOrder(id,up,useHttp)
{
return api(AdminCategoryOrderUrl,{id:id,up:up},useHttp).sync();
}
/**
* 'AdminCategoryOrderAsync(params).execute(function(result){},useHttp);'
**/
function AdminCategoryOrderAsync(id,up,useHttp)
{
return api(AdminCategoryOrderUrl,{id:id,up:up},useHttp);
}
var AdminCategoryDelUrl='/admin/category/Del';
/**
* 'var result= await AdminCategoryDel(params);'
**/
function AdminCategoryDel(id,useHttp)
{
return api(AdminCategoryDelUrl,{id:id},useHttp).sync();
}
/**
* 'AdminCategoryDelAsync(params).execute(function(result){},useHttp);'
**/
function AdminCategoryDelAsync(id,useHttp)
{
return api(AdminCategoryDelUrl,{id:id},useHttp);
}
var AdminCategoryListUrl='/admin/category/List';
/**
* 'var result= await AdminCategoryList(params);'
**/
function AdminCategoryList(useHttp)
{
return api(AdminCategoryListUrl,{},useHttp).sync();
}
/**
* 'AdminCategoryListAsync(params).execute(function(result){},useHttp);'
**/
function AdminCategoryListAsync(useHttp)
{
return api(AdminCategoryListUrl,{},useHttp);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeetleX.FastHttpApi;
using Peanut;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/comment")]
[AdminFilter]
public class AdminComment
{
public object List(int index)
{
int size = 15;
Expression exp = new Expression();
int Pages;
int count = exp.Count<DBModules.Comment>();
Pages = count / size;
if (count % size > 0)
Pages++;
var items = exp.List<DBModules.TopComment>(new Region(index, size), DBModules.Comment.createTime.At().Desc);
var Items = from a in items select new { a.ID, a.CommentID, a.Title, a.NickName, a.Content, CreateTime = a.CreateTime.ToString() };
return new { Pages, Items };
}
public void Del(long[] id)
{
if (id != null && id.Length > 0)
{
(DBModules.Comment.iD == id).Delete<DBModules.Comment>();
}
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var AdminCommentListUrl='/admin/comment/List';
/**
* 'var result= await AdminCommentList(params);'
**/
function AdminCommentList(index,useHttp)
{
return api(AdminCommentListUrl,{index:index},useHttp).sync();
}
/**
* 'AdminCommentListAsync(params).execute(function(result){},useHttp);'
**/
function AdminCommentListAsync(index,useHttp)
{
return api(AdminCommentListUrl,{index:index},useHttp);
}
var AdminCommentDelUrl='/admin/comment/Del';
/**
* 'var result= await AdminCommentDel(params);'
**/
function AdminCommentDel(id,useHttp)
{
return api(AdminCommentDelUrl,{id:id},useHttp).sync();
}
/**
* 'AdminCommentDelAsync(params).execute(function(result){},useHttp);'
**/
function AdminCommentDelAsync(id,useHttp)
{
return api(AdminCommentDelUrl,{id:id},useHttp);
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
using BeetleX.Blog.DBModules;
using Peanut;
using System.Linq;
using BeetleX.FastHttpApi.Data;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/photo")]
[AdminFilter]
public class AdminPhoto
{
public void Add(string title)
{
Photo photo = new Photo();
photo.Title = title;
photo.Save();
}
public void Del(long[] id)
{
if (id != null && id.Length > 0)
{
(PhotoItem.photoID == id).Delete<PhotoItem>();
(Photo.iD == id).Delete<Photo>();
}
}
private static byte[] mImageBuffer = new byte[1024 * 1024];
public void SetDefault(string id)
{
PhotoItem item = DBContext.Load<PhotoItem>(id);
if (item != null)
{
Photo photo = DBContext.Load<Photo>(item.PhotoID);
if (photo != null)
{
photo.SmallUrl = item.SmallUrl;
photo.LargeUrl = item.LargeUrl;
photo.Save();
}
}
}
public string GetImageID()
{
return DBHelper.Default.GetSequence("photo_key").ToString();
}
[Put]
[NoDataConvert]
public void UploadImage(string id, string file, long photoid, bool large, HttpRequest request)
{
lock (mImageBuffer)
{
Photo photo = DBContext.Load<Photo>(photoid);
if (photo != null)
{
request.Stream.Read(mImageBuffer, 0, request.Length);
if (!large)
file = "s_" + file;
string fileUrl = SaveImage(file, mImageBuffer, request.Length);
PhotoItem item = DBContext.Load<PhotoItem>(id);
if (item == null)
{
item = new PhotoItem();
item.ID = id;
}
item.PhotoID = photo.ID;
if (large)
item.LargeUrl = fileUrl;
else
item.SmallUrl = fileUrl;
item.Save();
if (string.IsNullOrEmpty(photo.LargeUrl) || string.IsNullOrEmpty(photo.SmallUrl))
{
photo.LargeUrl = item.LargeUrl;
photo.SmallUrl = item.SmallUrl;
photo.Save();
}
}
}
}
private string SaveImage(string file, byte[] data, int length)
{
int code = Math.Abs(file.GetHashCode());
string subfolder = (code % 10).ToString("00");
string filename = Units.ImagePath + subfolder
+ System.IO.Path.DirectorySeparatorChar + file;
using (System.IO.Stream stream = System.IO.File.Create(filename))
{
stream.Write(data, 0, length);
stream.Flush();
}
string url = "/images/" + subfolder + "/" + file;
return url;
}
public void DelItem(string[] id)
{
(PhotoItem.iD == id).Delete<PhotoItem>();
}
public object Get(long id)
{
Photo photo = DBContext.Load<Photo>(id);
var items = (PhotoItem.photoID == id).List<PhotoItem>();
var Items = from a in items select new { a.ID, a.SmallUrl };
return new { photo.Title, Items };
}
public object List(int index)
{
int size = 10;
Expression expression = new Expression();
int Count = expression.Count<Photo>();
int Pages = Count / size;
if (Count % size > 0)
Pages++;
var items = expression.List<Photo>(new Region(index, size), Photo.createTime.Desc);
var Items = from a in items
select new
{
a.ID,
a.Title,
CreateTime = a.CreateTime.ToShortDateString(),
SmallUrl = Blog.Units.GetImageUrl(a.SmallUrl)
};
return new { Count, Pages, Items };
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var AdminPhotoAddUrl='/admin/photo/Add';
/**
* 'var result= await AdminPhotoAdd(params);'
**/
function AdminPhotoAdd(title,useHttp)
{
return api(AdminPhotoAddUrl,{title:title},useHttp).sync();
}
/**
* 'AdminPhotoAddAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoAddAsync(title,useHttp)
{
return api(AdminPhotoAddUrl,{title:title},useHttp);
}
var AdminPhotoDelUrl='/admin/photo/Del';
/**
* 'var result= await AdminPhotoDel(params);'
**/
function AdminPhotoDel(id,useHttp)
{
return api(AdminPhotoDelUrl,{id:id},useHttp).sync();
}
/**
* 'AdminPhotoDelAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoDelAsync(id,useHttp)
{
return api(AdminPhotoDelUrl,{id:id},useHttp);
}
var AdminPhotoSetDefaultUrl='/admin/photo/SetDefault';
/**
* 'var result= await AdminPhotoSetDefault(params);'
**/
function AdminPhotoSetDefault(id,useHttp)
{
return api(AdminPhotoSetDefaultUrl,{id:id},useHttp).sync();
}
/**
* 'AdminPhotoSetDefaultAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoSetDefaultAsync(id,useHttp)
{
return api(AdminPhotoSetDefaultUrl,{id:id},useHttp);
}
var AdminPhotoGetImageIDUrl='/admin/photo/GetImageID';
/**
* 'var result= await AdminPhotoGetImageID(params);'
**/
function AdminPhotoGetImageID(useHttp)
{
return api(AdminPhotoGetImageIDUrl,{},useHttp).sync();
}
/**
* 'AdminPhotoGetImageIDAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoGetImageIDAsync(useHttp)
{
return api(AdminPhotoGetImageIDUrl,{},useHttp);
}
var AdminPhotoUploadImageUrl='/admin/photo/UploadImage';
/**
* 'var result= await AdminPhotoUploadImage(params);'
**/
function AdminPhotoUploadImage(id,file,photoid,large,useHttp)
{
return api(AdminPhotoUploadImageUrl,{id:id,file:file,photoid:photoid,large:large},useHttp).sync();
}
/**
* 'AdminPhotoUploadImageAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoUploadImageAsync(id,file,photoid,large,useHttp)
{
return api(AdminPhotoUploadImageUrl,{id:id,file:file,photoid:photoid,large:large},useHttp);
}
var AdminPhotoDelItemUrl='/admin/photo/DelItem';
/**
* 'var result= await AdminPhotoDelItem(params);'
**/
function AdminPhotoDelItem(id,useHttp)
{
return api(AdminPhotoDelItemUrl,{id:id},useHttp).sync();
}
/**
* 'AdminPhotoDelItemAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoDelItemAsync(id,useHttp)
{
return api(AdminPhotoDelItemUrl,{id:id},useHttp);
}
var AdminPhotoGetUrl='/admin/photo/Get';
/**
* 'var result= await AdminPhotoGet(params);'
**/
function AdminPhotoGet(id,useHttp)
{
return api(AdminPhotoGetUrl,{id:id},useHttp).sync();
}
/**
* 'AdminPhotoGetAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoGetAsync(id,useHttp)
{
return api(AdminPhotoGetUrl,{id:id},useHttp);
}
var AdminPhotoListUrl='/admin/photo/List';
/**
* 'var result= await AdminPhotoList(params);'
**/
function AdminPhotoList(index,useHttp)
{
return api(AdminPhotoListUrl,{index:index},useHttp).sync();
}
/**
* 'AdminPhotoListAsync(params).execute(function(result){},useHttp);'
**/
function AdminPhotoListAsync(index,useHttp)
{
return api(AdminPhotoListUrl,{index:index},useHttp);
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.Blog.DBModules;
using BeetleX.FastHttpApi;
using BeetleX.FastHttpApi.Data;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/setting")]
[AdminFilter]
public class AdminSetting : IController
{
private BeetleX.FastHttpApi.HttpApiServer mServer;
public object GetServerInfo()
{
if (mServer.ServerCounter != null)
return mServer.ServerCounter.Next();
return new object();
}
public object GetFileAndTCloudToken(string name)
{
string ext = System.IO.Path.GetExtension(name);
if (string.IsNullOrEmpty(DBHelper.Default.Setting.TCloudID.Value))
{
return new ActionResult(500, "没有配置腾讯云SecretId相关信息!");
}
string filename = name;//Guid.NewGuid().ToString("N") + ext;
filename = "/" + (Math.Abs(filename.GetHashCode()) % 10).ToString("00") + "/" + filename;
TCloudCosObject cloudCosObject = new TCloudCosObject(
DBHelper.Default.Setting.TCloudID.Value,
DBHelper.Default.Setting.TCloudKey.Value,
DBHelper.Default.Setting.TCloudHost.Value
);
string Token = cloudCosObject.GetPutToken(filename);
string Url = cloudCosObject.GetPutUrl(filename);
return new { Token, Url };
;
}
public void SaveTCloudInfo(string id, string key, string host)
{
DBHelper.Default.Setting.SaveTCould(id, key, host);
}
public object GetTCloudInfo()
{
return new
{
SecretId = DBHelper.Default.Setting.TCloudID.Value,
SecretKey = DBHelper.Default.Setting.TCloudKey.Value,
Host = DBHelper.Default.Setting.TCloudHost.Value
};
}
public string ESTest(string word)
{
return string.Join(',', ES.ESHelper.Blog.Analyze(word, Elasticsearch.AnalyzerType.ik_smart));
}
[SkipFilter(typeof(AdminFilter))]
public object Signout(HttpResponse response)
{
JWTHelper.Default.ClearToken(response);
return new FastHttpApi.Move302Result("/");
}
[SkipFilter(typeof(AdminFilter))]
public bool Login(string name, string pwd, HttpResponse response)
{
if (DBHelper.Default.Setting.UserName.Value == name && DBHelper.Default.Setting.PassWord.Value == pwd)
{
string tokey = JWTHelper.Default.CreateToken(name, "admin", 2000);
JWTHelper.Default.CreateToken(response, name, "admin", 2000);
return true;
}
return false;
}
public object ChangePwd(string pwd, string rpwd)
{
if (!string.IsNullOrEmpty(pwd) && pwd == rpwd)
{
DBHelper.Default.Setting.PassWord.Value = Units.MD5Encrypt(pwd);
DBHelper.Default.Setting.Save();
return true;
}
else
{
return new ActionResult(500, "密码为空或不一致!");
}
}
public void UpdateSetting(string title, string host, string about, string imghost)
{
DBHelper.Default.Setting.Title.Value = title;
DBHelper.Default.Setting.ElasticSearch.Value = host;
DBHelper.Default.Setting.About.Value = about;
DBHelper.Default.Setting.ImgHost.Value = imghost;
DBHelper.Default.Setting.Save();
ES.ESHelper.Init(DBHelper.Default.Setting.ElasticSearch.Value);
}
public void ReCreateIndex()
{
ES.ESHelper.ReCreateIndex();
}
private static byte[] mImageBuffer = new byte[1024 * 500];
[Put]
[NoDataConvert]
public object UploadImage(string file, HttpRequest request)
{
lock (mImageBuffer)
{
request.Stream.Read(mImageBuffer, 0, request.Length);
string fileUrl = SaveImage(file, mImageBuffer, request.Length);
return fileUrl;
}
}
private string SaveImage(string file, byte[] data, int length)
{
int code = Math.Abs(file.GetHashCode());
string subfolder = (code % 10).ToString("00");
string filename = Units.ImagePath + subfolder
+ System.IO.Path.DirectorySeparatorChar + file;
using (System.IO.Stream stream = System.IO.File.Create(filename))
{
stream.Write(data, 0, length);
stream.Flush();
}
string url = "/images/" + subfolder + "/" + file;
if (DBHelper.Default.Setting.ImgHost != null)
{
string[] hosts = DBHelper.Default.Setting.ImgHost.Value.Split(';', StringSplitOptions.RemoveEmptyEntries);
if (hosts != null && hosts.Length > 0)
{
url = "http://" + hosts[code % hosts.Length] + url;
}
}
return url;
}
public void ReCreateJWT()
{
DBHelper.Default.Setting.ReCreateJWT();
JWTHelper.Init();
}
public object GetSetting()
{
return new
{
Title = DBHelper.Default.Setting.Title.Value,
ESHost = DBHelper.Default.Setting.ElasticSearch.Value,
About = DBHelper.Default.Setting.About.Value,
ESStatus = ES.ESHelper.Available,
ESError = ES.ESHelper.InitError == null ? "" : ES.ESHelper.InitError.Message,
KEY = DBHelper.Default.Setting.JwtKey.Value,
ImgHost = DBHelper.Default.Setting.ImgHost.Value
};
}
[Post]
public void CloseSession(long[] ids, IHttpContext context)
{
foreach (long item in ids)
{
ISession session = context.Server.BaseServer.GetSession(item);
if (session != null)
session.Dispose();
}
}
public object ListConn(int index, IHttpContext context)
{
int size = 15;
ISession[] sessions = context.Server.BaseServer.GetOnlines();
int pages = sessions.Length / size;
if (sessions.Length % size > 0)
pages++;
List<object> items = new List<object>();
for (int i = index * size; i < (index * size + 20) && i < sessions.Length; i++)
{
ISession item = sessions[i];
HttpToken token = (HttpToken)item.Tag;
items.Add(new
{
item.ID,
item.Name,
Type = token.WebSocket ? "WebSocket" : "http",
CreateTime = DateTime.Now - token.CreateTime,
IPAddress = ((System.Net.IPEndPoint)item.RemoteEndPoint).Address.ToString()
});
}
return new { Index = index, Pages = pages, Items = items, context.Server.BaseServer.Count };
}
[NotAction]
public void Init(BeetleX.FastHttpApi.HttpApiServer server)
{
mServer = server;
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var AdminSettingGetServerInfoUrl='/admin/setting/GetServerInfo';
/**
* 'var result= await AdminSettingGetServerInfo(params);'
**/
function AdminSettingGetServerInfo(useHttp)
{
return api(AdminSettingGetServerInfoUrl,{},useHttp).sync();
}
/**
* 'AdminSettingGetServerInfoAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingGetServerInfoAsync(useHttp)
{
return api(AdminSettingGetServerInfoUrl,{},useHttp);
}
var AdminSettingGetFileAndTCloudTokenUrl='/admin/setting/GetFileAndTCloudToken';
/**
* 'var result= await AdminSettingGetFileAndTCloudToken(params);'
**/
function AdminSettingGetFileAndTCloudToken(name,useHttp)
{
return api(AdminSettingGetFileAndTCloudTokenUrl,{name:name},useHttp).sync();
}
/**
* 'AdminSettingGetFileAndTCloudTokenAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingGetFileAndTCloudTokenAsync(name,useHttp)
{
return api(AdminSettingGetFileAndTCloudTokenUrl,{name:name},useHttp);
}
var AdminSettingSaveTCloudInfoUrl='/admin/setting/SaveTCloudInfo';
/**
* 'var result= await AdminSettingSaveTCloudInfo(params);'
**/
function AdminSettingSaveTCloudInfo(id,key,host,useHttp)
{
return api(AdminSettingSaveTCloudInfoUrl,{id:id,key:key,host:host},useHttp).sync();
}
/**
* 'AdminSettingSaveTCloudInfoAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingSaveTCloudInfoAsync(id,key,host,useHttp)
{
return api(AdminSettingSaveTCloudInfoUrl,{id:id,key:key,host:host},useHttp);
}
var AdminSettingGetTCloudInfoUrl='/admin/setting/GetTCloudInfo';
/**
* 'var result= await AdminSettingGetTCloudInfo(params);'
**/
function AdminSettingGetTCloudInfo(useHttp)
{
return api(AdminSettingGetTCloudInfoUrl,{},useHttp).sync();
}
/**
* 'AdminSettingGetTCloudInfoAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingGetTCloudInfoAsync(useHttp)
{
return api(AdminSettingGetTCloudInfoUrl,{},useHttp);
}
var AdminSettingESTestUrl='/admin/setting/ESTest';
/**
* 'var result= await AdminSettingESTest(params);'
**/
function AdminSettingESTest(word,useHttp)
{
return api(AdminSettingESTestUrl,{word:word},useHttp).sync();
}
/**
* 'AdminSettingESTestAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingESTestAsync(word,useHttp)
{
return api(AdminSettingESTestUrl,{word:word},useHttp);
}
var AdminSettingSignoutUrl='/admin/setting/Signout';
/**
* 'var result= await AdminSettingSignout(params);'
**/
function AdminSettingSignout(useHttp)
{
return api(AdminSettingSignoutUrl,{},useHttp).sync();
}
/**
* 'AdminSettingSignoutAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingSignoutAsync(useHttp)
{
return api(AdminSettingSignoutUrl,{},useHttp);
}
var AdminSettingLoginUrl='/admin/setting/Login';
/**
* 'var result= await AdminSettingLogin(params);'
**/
function AdminSettingLogin(name,pwd,useHttp)
{
return api(AdminSettingLoginUrl,{name:name,pwd:pwd},useHttp).sync();
}
/**
* 'AdminSettingLoginAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingLoginAsync(name,pwd,useHttp)
{
return api(AdminSettingLoginUrl,{name:name,pwd:pwd},useHttp);
}
var AdminSettingChangePwdUrl='/admin/setting/ChangePwd';
/**
* 'var result= await AdminSettingChangePwd(params);'
**/
function AdminSettingChangePwd(pwd,rpwd,useHttp)
{
return api(AdminSettingChangePwdUrl,{pwd:pwd,rpwd:rpwd},useHttp).sync();
}
/**
* 'AdminSettingChangePwdAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingChangePwdAsync(pwd,rpwd,useHttp)
{
return api(AdminSettingChangePwdUrl,{pwd:pwd,rpwd:rpwd},useHttp);
}
var AdminSettingUpdateSettingUrl='/admin/setting/UpdateSetting';
/**
* 'var result= await AdminSettingUpdateSetting(params);'
**/
function AdminSettingUpdateSetting(title,host,about,imghost,useHttp)
{
return api(AdminSettingUpdateSettingUrl,{title:title,host:host,about:about,imghost:imghost},useHttp).sync();
}
/**
* 'AdminSettingUpdateSettingAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingUpdateSettingAsync(title,host,about,imghost,useHttp)
{
return api(AdminSettingUpdateSettingUrl,{title:title,host:host,about:about,imghost:imghost},useHttp);
}
var AdminSettingReCreateIndexUrl='/admin/setting/ReCreateIndex';
/**
* 'var result= await AdminSettingReCreateIndex(params);'
**/
function AdminSettingReCreateIndex(useHttp)
{
return api(AdminSettingReCreateIndexUrl,{},useHttp).sync();
}
/**
* 'AdminSettingReCreateIndexAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingReCreateIndexAsync(useHttp)
{
return api(AdminSettingReCreateIndexUrl,{},useHttp);
}
var AdminSettingUploadImageUrl='/admin/setting/UploadImage';
/**
* 'var result= await AdminSettingUploadImage(params);'
**/
function AdminSettingUploadImage(file,useHttp)
{
return api(AdminSettingUploadImageUrl,{file:file},useHttp).sync();
}
/**
* 'AdminSettingUploadImageAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingUploadImageAsync(file,useHttp)
{
return api(AdminSettingUploadImageUrl,{file:file},useHttp);
}
var AdminSettingReCreateJWTUrl='/admin/setting/ReCreateJWT';
/**
* 'var result= await AdminSettingReCreateJWT(params);'
**/
function AdminSettingReCreateJWT(useHttp)
{
return api(AdminSettingReCreateJWTUrl,{},useHttp).sync();
}
/**
* 'AdminSettingReCreateJWTAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingReCreateJWTAsync(useHttp)
{
return api(AdminSettingReCreateJWTUrl,{},useHttp);
}
var AdminSettingGetSettingUrl='/admin/setting/GetSetting';
/**
* 'var result= await AdminSettingGetSetting(params);'
**/
function AdminSettingGetSetting(useHttp)
{
return api(AdminSettingGetSettingUrl,{},useHttp).sync();
}
/**
* 'AdminSettingGetSettingAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingGetSettingAsync(useHttp)
{
return api(AdminSettingGetSettingUrl,{},useHttp);
}
var AdminSettingCloseSessionUrl='/admin/setting/CloseSession';
/**
* 'var result= await AdminSettingCloseSession(params);'
**/
function AdminSettingCloseSession(ids,useHttp)
{
return api(AdminSettingCloseSessionUrl,{ids:ids},useHttp,true).sync();
}
/**
* 'AdminSettingCloseSessionAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingCloseSessionAsync(ids,useHttp)
{
return api(AdminSettingCloseSessionUrl,{ids:ids},useHttp,true);
}
var AdminSettingListConnUrl='/admin/setting/ListConn';
/**
* 'var result= await AdminSettingListConn(params);'
**/
function AdminSettingListConn(index,useHttp)
{
return api(AdminSettingListConnUrl,{index:index},useHttp).sync();
}
/**
* 'AdminSettingListConnAsync(params).execute(function(result){},useHttp);'
**/
function AdminSettingListConnAsync(index,useHttp)
{
return api(AdminSettingListConnUrl,{index:index},useHttp);
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
namespace BeetleX.Blog.Controller
{
public class HttpCacheFilter : FilterAttribute
{
public HttpCacheFilter(int seconds = 300)
{
Seconds = seconds;
}
public int Seconds { get; set; }
public override void Executed(ActionContext context)
{
base.Executed(context);
if (!context.HttpContext.Server.Options.Debug)
{
if (!context.HttpContext.WebSocket)
{
context.HttpContext.Response.Header.Add(HeaderTypeFactory.CACHE_CONTROL, "public, max-age=" + Seconds);
}
}
}
}
public class ActionCacehFilter : FilterAttribute
{
public ActionCacehFilter(string key, double seconds = 60)
{
Key = key;
Seconds = seconds;
}
public string Key { get; set; }
public double Seconds { get; set; }
public override bool Executing(ActionContext context)
{
if (context.HttpContext.Server.Options.Debug)
return true;
object result = CacheHelper.Get(Key);
if (result != null)
{
context.Result = result;
return false;
}
return base.Executing(context);
}
public override void Executed(ActionContext context)
{
base.Executed(context);
CacheHelper.Set(Key, context.Result, Seconds);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
namespace BeetleX.Blog.Controller
{
public class ESExceptionFilter : FilterAttribute
{
public override bool Executing(ActionContext context)
{
if (ES.ESHelper.Blog == null)
{
context.Result = new ActionResult(500, "检测不到Elastic search服务,请在管理中配置相关服务地址!");
return false;
}
return base.Executing(context);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
namespace BeetleX.Blog.Controller
{
[Controller(BaseUrl = "/admin/files")]
[AdminFilter]
public class FileManager : BeetleX.FastHttpApi.IController
{
private string mPath;
public const string FILE_UPLOAE_MANAGER = "_FILE_UPLOAD_MANAGER";
/// <summary>
/// 创建文件夹
/// </summary>
/// <param name="folder">当前目录</param>
/// <param name="name">新建目录名称</param>
public void CreateFolder(string folder, string name)
{
if (string.IsNullOrEmpty(folder))
folder = System.IO.Path.DirectorySeparatorChar.ToString();
string newFolder = mPath + folder + name;
if (!System.IO.Directory.Exists(newFolder))
System.IO.Directory.CreateDirectory(newFolder);
}
/// <summary>
/// 上传文件信息
/// </summary>
/// <param name="folder">当前目录</param>
/// <param name="info">文件信息</param>
[Post]
public void UploadFile(string folder,UploadInfo info, IHttpContext context)
{
if (string.IsNullOrEmpty(folder))
folder = System.IO.Path.DirectorySeparatorChar.ToString();
UploadManager manager = (UploadManager)context.Session[FILE_UPLOAE_MANAGER];
if (manager == null)
{
manager = new UploadManager();
context.Session[FILE_UPLOAE_MANAGER] = manager;
}
string filename = mPath + folder + info.Name;
UploadWriter uw = manager.GetWriter(filename);
uw.Write(info);
if (info.Eof)
{
manager.CloseWriter(filename);
}
}
/// <summary>
/// 删除资源
/// </summary>
/// <param name="folder">当前目录</param>
/// <param name="name">删除资源名称</param>
/// <param name="file">是否文件</param>
public void DeleteResource(string folder, string name, bool file)
{
if (string.IsNullOrEmpty(folder))
folder = System.IO.Path.DirectorySeparatorChar.ToString();
string recName = mPath + folder + name;
if (file)
{
System.IO.File.Delete(recName);
}
else
{
System.IO.Directory.Delete(recName, true);
}
}
/// <summary>
/// 获取目录资源信息
/// </summary>
/// <param name="folder">当前目录</param>
/// <returns>资源列表</returns>
public object List(string folder)
{
if (string.IsNullOrEmpty(folder))
folder = System.IO.Path.DirectorySeparatorChar.ToString();
List<Resource> items = new List<Resource>();
if (folder != System.IO.Path.DirectorySeparatorChar.ToString())
{
items.Add(new Resource { Name = System.IO.Path.DirectorySeparatorChar.ToString() });
}
foreach (string item in System.IO.Directory.GetDirectories(mPath + folder))
{
Resource rec = new Resource();
rec.Name = System.IO.Path.GetFileName(item);
rec.Path = folder + rec.Name + System.IO.Path.DirectorySeparatorChar;
rec.Url = "/Files" + rec.Path.Replace(System.IO.Path.DirectorySeparatorChar, '/');
items.Add(rec);
}
foreach (string file in System.IO.Directory.GetFiles(mPath + folder))
{
Resource rec = new Resource();
rec.Name = System.IO.Path.GetFileName(file);
rec.Path = folder + rec.Name;
rec.Url = "/Files" + rec.Path.Replace(System.IO.Path.DirectorySeparatorChar, '/');
rec.IsFile = true;
items.Add(rec);
}
return items;
}
[NotAction]
public void Init(BeetleX.FastHttpApi.HttpApiServer server)
{
mPath = server.Options.StaticResourcePath;
if (mPath[mPath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
mPath += System.IO.Path.DirectorySeparatorChar;
mPath += "Files";
if (!System.IO.Directory.Exists(mPath))
System.IO.Directory.CreateDirectory(mPath);
server.HttpDisconnect += (o, e) =>
{
UploadManager manager = (UploadManager)e.Session[FILE_UPLOAE_MANAGER];
if (manager != null)
{
manager.Dispose();
}
};
}
public class Resource
{
public string Name { get; set; }
public bool IsFile { get; set; }
public string Path { get; set; }
public string Url { get; set; }
}
}
public class UploadInfo
{
public bool Eof { get; set; }
public string Data { get; set; }
public string Name { get; set; }
}
public class UploadManager : IDisposable
{
private Dictionary<string, UploadWriter> mWriters = new Dictionary<string, UploadWriter>();
public UploadWriter GetWriter(string name)
{
lock (this)
{
UploadWriter writer;
if (!mWriters.TryGetValue(name, out writer))
{
writer = new UploadWriter(name);
mWriters[name] = writer;
}
return writer;
}
}
public void CloseWriter(string name)
{
lock (this)
{
UploadWriter writer;
if (mWriters.TryGetValue(name, out writer))
{
mWriters.Remove(name);
}
}
}
public void Dispose()
{
lock (this)
{
foreach (UploadWriter item in mWriters.Values)
{
item.Dispose();
}
mWriters.Clear();
}
}
}
public class UploadWriter : IDisposable
{
public UploadWriter(string file)
{
mFileStream = System.IO.File.Create(file);
}
private System.IO.Stream mFileStream;
public void Write(UploadInfo data)
{
mFileStream.Write(Convert.FromBase64String(data.Data));
mFileStream.Flush();
if (data.Eof)
mFileStream.Close();
}
public void Dispose()
{
mFileStream.Close();
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
/**
创建文件夹 url
**/
var FileManagerCreateFolderUrl='/admin/files/CreateFolder';
/** 创建文件夹 'var result=await FileManagerCreateFolder(params)'
/* @param folder 当前目录
/* @param name 新建目录名称
/* @param useHttp only http request
/* @return
**/
function FileManagerCreateFolder(folder,name,useHttp)
{
return api(FileManagerCreateFolderUrl,{folder:folder,name:name},useHttp).sync();
}
/** 创建文件夹 'FileManagerCreateFolderAsync(params).execute(function(result){},useHttp)'
/* @param folder 当前目录
/* @param name 新建目录名称
/* @param useHttp only http request
/* @return
**/
function FileManagerCreateFolderAsync(folder,name,useHttp)
{
return api(FileManagerCreateFolderUrl,{folder:folder,name:name},useHttp);
}
/**
上传文件信息 url
**/
var FileManagerUploadFileUrl='/admin/files/UploadFile';
/** 上传文件信息 'var result=await FileManagerUploadFile(params)'
/* @param folder 当前目录
/* @param info 文件信息
/* @param useHttp only http request
/* @return
**/
function FileManagerUploadFile(folder,info,useHttp)
{
return api(FileManagerUploadFileUrl,{folder:folder,info:info},useHttp,true).sync();
}
/** 上传文件信息 'FileManagerUploadFileAsync(params).execute(function(result){},useHttp)'
/* @param folder 当前目录
/* @param info 文件信息
/* @param useHttp only http request
/* @return
**/
function FileManagerUploadFileAsync(folder,info,useHttp)
{
return api(FileManagerUploadFileUrl,{folder:folder,info:info},useHttp,true);
}
/**
删除资源 url
**/
var FileManagerDeleteResourceUrl='/admin/files/DeleteResource';
/** 删除资源 'var result=await FileManagerDeleteResource(params)'
/* @param folder 当前目录
/* @param name 删除资源名称
/* @param file 是否文件
/* @param useHttp only http request
/* @return
**/
function FileManagerDeleteResource(folder,name,file,useHttp)
{
return api(FileManagerDeleteResourceUrl,{folder:folder,name:name,file:file},useHttp).sync();
}
/** 删除资源 'FileManagerDeleteResourceAsync(params).execute(function(result){},useHttp)'
/* @param folder 当前目录
/* @param name 删除资源名称
/* @param file 是否文件
/* @param useHttp only http request
/* @return
**/
function FileManagerDeleteResourceAsync(folder,name,file,useHttp)
{
return api(FileManagerDeleteResourceUrl,{folder:folder,name:name,file:file},useHttp);
}
/**
获取目录资源信息 url
**/
var FileManagerListUrl='/admin/files/List';
/** 获取目录资源信息 'var result=await FileManagerList(params)'
/* @param folder 当前目录
/* @param useHttp only http request
/* @return 资源列表
**/
function FileManagerList(folder,useHttp)
{
return api(FileManagerListUrl,{folder:folder},useHttp).sync();
}
/** 获取目录资源信息 'FileManagerListAsync(params).execute(function(result){},useHttp)'
/* @param folder 当前目录
/* @param useHttp only http request
/* @return 资源列表
**/
function FileManagerListAsync(folder,useHttp)
{
return api(FileManagerListUrl,{folder:folder},useHttp);
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
namespace BeetleX.Blog.Controller
{
[Controller]
public class Rewrite : IController
{
[NotAction]
public void Init(HttpApiServer server)
{
server.Options.StaticResurceCacheTime = 60 * 5;
server.UrlRewrite.Add("/cate/{0}.html", "/index.html", "html")
.Add("/search/{0}.html", "/index.html", "html")
.Add("/tag/{0}.html", "/index.html", "html")
.Add("/blog/{0}.html", "/blog.html", "html")
.Add("/photos/{0}.html", "/photos.html", "html")
;
server.ResourceCenter.FileResponse += (request, e) =>
{
if (e.Request.Ext == "jpg" || e.Request.Ext == "png")
{
if (!server.Options.Debug)
{
e.Response.Header.Add(HeaderTypeFactory.CACHE_CONTROL, "public, max-age=600000");
}
}
};
#region init imagepath
Units.ImagePath = server.Options.StaticResourcePath;
if (Units.ImagePath[Units.ImagePath.Length - 1] != System.IO.Path.DirectorySeparatorChar)
Units.ImagePath += System.IO.Path.DirectorySeparatorChar;
Units.ImagePath += "images" + System.IO.Path.DirectorySeparatorChar;
if (!System.IO.Directory.Exists(Units.ImagePath))
System.IO.Directory.CreateDirectory(Units.ImagePath);
for (int i = 0; i < 10; i++)
{
string subpath = Units.ImagePath + i.ToString("00");
if (!System.IO.Directory.Exists(subpath))
System.IO.Directory.CreateDirectory(subpath);
}
#endregion
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeetleX.Blog.DBModules;
using BeetleX.Blog.ES;
using BeetleX.Elasticsearch.Search;
using BeetleX.FastHttpApi;
using Peanut;
namespace BeetleX.Blog.Controller
{
[Controller]
[ESExceptionFilter]
public class Site : IController
{
[HttpCacheFilter(60 * 30)]
[ActionCacehFilter("get_title_menus")]
[SkipFilter(typeof(ESExceptionFilter))]
public object GetTitleAndMenu()
{
string Version = typeof(Site).Assembly.GetName().Version.ToString();
string Title = DBHelper.Default.Setting.Title.Value;
var items = new Expression().List<Category>(Category.orderBy.Asc);
var Menus = from a in items
select new { a.ID, a.Name };
return new { Title, Menus, Version };
}
[HttpCacheFilter]
[ActionCacehFilter("get_top_tags")]
public object GetTags(int top)
{
top = 60;
return ESHelper.Blog.Aggs<ESBlog>("group_by_tags", AggsType.terms, "Tags",
t => t.Size(top));
}
[HttpCacheFilter]
[ActionCacehFilter("get_all_tags")]
public object GetAllTags()
{
int size = 1000;
return ESHelper.Blog.Aggs<ESBlog>("group_by_tags", AggsType.terms, "Tags",
t => t.Size(size));
}
[HttpCacheFilter(30)]
[ActionCacehFilter("get_top_comment")]
public object TopComment()
{
Expression exp = new Expression();
var items = exp.List<TopComment>(new Region(0, 20), Comment.createTime.At().Desc);
return from a in items select new { a.ID, a.NickName, a.Title, a.Content, CreateTime = a.CreateTime.ToString() };
}
[HttpCacheFilter]
[ActionCacehFilter("get_top_blog")]
public object TopBlog()
{
var items = ESHelper.Blog.Query<ESBlog>(q => q.OrderBy("CreateTime", OrderType.desc).Term("Top", "true"), 0, 15);
return from a in items select new { a.ID, a.Title };
}
[HttpCacheFilter]
[ActionCacehFilter("get_new_blog")]
public object NewBlog()
{
var item = ESHelper.Blog.Query<ESBlog>(q => q.OrderBy("CreateTime", OrderType.desc), 0, 15);
return from a in item select new { a.ID, a.Title };
}
[HttpCacheFilter]
public object GetAbout()
{
return DBHelper.Default.Setting.About.Value;
}
public object ListCommint(long id)
{
var commints = (DBModules.Comment.blogID == id).List<DBModules.Comment>(DBModules.Comment.createTime.Asc);
return from a in commints select new { a.NickName, a.Content, CreateTime = a.CreateTime.ToString() };
}
public object GetPhoto(int id)
{
var items = (PhotoItem.photoID == id).List<PhotoItem>();
return from a in items select new { a.LargeUrl };
}
[HttpCacheFilter]
public object ListPhoto(int index)
{
int size = 40;
Expression expression = new Expression();
int Count = expression.Count<Photo>();
int Pages = Count / size;
if (Count % size > 0)
Pages++;
var items = expression.List<Photo>(new Region(index, size), Photo.createTime.Desc);
var Items = from a in items
select new
{
a.ID,
a.Title,
CreateTime = a.CreateTime.ToShortDateString(),
SmallUrl = Blog.Units.GetImageUrl(a.SmallUrl)
};
return new { Count, Pages, Items };
}
[Post]
public object Commint(long id, string nickName, string content, HttpRequest request, HttpResponse response)
{
string token = request.Cookies[COMMINT_TOKEN];
if (token != Units.MD5Encrypt(id.ToString() + DateTime.Now.Date))
{
return new ActionResult(500, "凭证无效,无法提交数据!");
}
else
{
response.SetCookie("_nickName", nickName, DateTime.Now.AddYears(1));
DBModules.Comment comment = new Comment();
comment.BlogID = id;
comment.NickName = nickName;
comment.Content = content;
comment.Save();
}
return true;
}
private const string COMMINT_TOKEN = "COMMINT_TOKEN";
[HttpCacheFilter]
public object GetBlog(long id, HttpResponse response, HttpRequest request)
{
DBModules.Blog blog = DBContext.Load<DBModules.Blog>(id);
if (blog != null)
{
string token = Units.MD5Encrypt(id.ToString() + DateTime.Now.Date);
response.SetCookie(COMMINT_TOKEN, token, DateTime.Now.AddMinutes(10));
return new
{
blog.ID,
blog.Title,
blog.Category,
blog.CategoryID,
blog.Content,
Tags = string.IsNullOrEmpty(blog.Tags) ? new string[0] : blog.Tags.Split(' ', StringSplitOptions.RemoveEmptyEntries),
blog.SourceUrl,
CreateTime = blog.CreateTime.ToString(),
NickName = request.Cookies["_nickName"]
};
}
return new object();
}
[NotAction]
public void Init(HttpApiServer server)
{
mServer = server;
}
private HttpApiServer mServer;
[SkipFilter(typeof(ESExceptionFilter))]
public object GetServerInfo()
{
if (mServer.ServerCounter != null)
return mServer.ServerCounter.Next();
return new object();
}
public object Search(long cate, string tag, string query, int index)
{
int size = 15;
int start = size * index;
int count = 0;
IList<ESBlog> esItems;
IQuery esQuery = ESHelper.Blog.CreateQuery();
if (!string.IsNullOrEmpty(query))
{
var ws = ESHelper.Blog.Analyze(query, Elasticsearch.AnalyzerType.ik_smart);
foreach (var k in ws)
{
if (k.Length >= 2 || k.ToLower() == "c")
{
esQuery.Bool.Must.Term("Content", k);
}
}
// esQuery.Bool.ShouldMatch(1);
esQuery.Bool.Should.Terms("Title", ws);
}
else if (!string.IsNullOrEmpty(tag))
{
esQuery.Bool.Must.Term("Tags", tag);
esQuery.OrderBy("CreateTime", OrderType.desc);
}
else if (cate > 0)
{
esQuery.Bool.Must.Term("CategoryID", cate.ToString());
esQuery.OrderBy("CreateTime", OrderType.desc);
}
else
{
esQuery.OrderBy("CreateTime", OrderType.desc);
}
esItems = esQuery.List<ESBlog>(start, size, out count);
int Pages = count / size;
if (count % size > 0)
Pages++;
if (Pages > 100)
Pages = 100;
var Items = from a in esItems
select new
{
a.ID,
a.Title,
a.Summary,
a.SourceUrl,
Tags = string.IsNullOrEmpty(a.Tags) ? new string[0] : a.Tags.Split(' ', StringSplitOptions.RemoveEmptyEntries),
a.Category,
a.CategoryID,
CreateTime = a.CreateTime.ToString()
};
return new { Pages, Items, Count = count };
}
}
}
/************************************************************************************
FastHttpApi javascript api Generator Copyright © henryfan 2018 email:henryfan@msn.com
https://github.com/IKende/FastHttpApi
**************************************************************************************/
var SiteGetTitleAndMenuUrl='/GetTitleAndMenu';
/**
* 'var result= await SiteGetTitleAndMenu(params);'
**/
function SiteGetTitleAndMenu(useHttp)
{
return api(SiteGetTitleAndMenuUrl,{},useHttp).sync();
}
/**
* 'SiteGetTitleAndMenuAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetTitleAndMenuAsync(useHttp)
{
return api(SiteGetTitleAndMenuUrl,{},useHttp);
}
var SiteGetTagsUrl='/GetTags';
/**
* 'var result= await SiteGetTags(params);'
**/
function SiteGetTags(top,useHttp)
{
return api(SiteGetTagsUrl,{top:top},useHttp).sync();
}
/**
* 'SiteGetTagsAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetTagsAsync(top,useHttp)
{
return api(SiteGetTagsUrl,{top:top},useHttp);
}
var SiteGetAllTagsUrl='/GetAllTags';
/**
* 'var result= await SiteGetAllTags(params);'
**/
function SiteGetAllTags(useHttp)
{
return api(SiteGetAllTagsUrl,{},useHttp).sync();
}
/**
* 'SiteGetAllTagsAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetAllTagsAsync(useHttp)
{
return api(SiteGetAllTagsUrl,{},useHttp);
}
var SiteTopCommentUrl='/TopComment';
/**
* 'var result= await SiteTopComment(params);'
**/
function SiteTopComment(useHttp)
{
return api(SiteTopCommentUrl,{},useHttp).sync();
}
/**
* 'SiteTopCommentAsync(params).execute(function(result){},useHttp);'
**/
function SiteTopCommentAsync(useHttp)
{
return api(SiteTopCommentUrl,{},useHttp);
}
var SiteTopBlogUrl='/TopBlog';
/**
* 'var result= await SiteTopBlog(params);'
**/
function SiteTopBlog(useHttp)
{
return api(SiteTopBlogUrl,{},useHttp).sync();
}
/**
* 'SiteTopBlogAsync(params).execute(function(result){},useHttp);'
**/
function SiteTopBlogAsync(useHttp)
{
return api(SiteTopBlogUrl,{},useHttp);
}
var SiteNewBlogUrl='/NewBlog';
/**
* 'var result= await SiteNewBlog(params);'
**/
function SiteNewBlog(useHttp)
{
return api(SiteNewBlogUrl,{},useHttp).sync();
}
/**
* 'SiteNewBlogAsync(params).execute(function(result){},useHttp);'
**/
function SiteNewBlogAsync(useHttp)
{
return api(SiteNewBlogUrl,{},useHttp);
}
var SiteGetAboutUrl='/GetAbout';
/**
* 'var result= await SiteGetAbout(params);'
**/
function SiteGetAbout(useHttp)
{
return api(SiteGetAboutUrl,{},useHttp).sync();
}
/**
* 'SiteGetAboutAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetAboutAsync(useHttp)
{
return api(SiteGetAboutUrl,{},useHttp);
}
var SiteListCommintUrl='/ListCommint';
/**
* 'var result= await SiteListCommint(params);'
**/
function SiteListCommint(id,useHttp)
{
return api(SiteListCommintUrl,{id:id},useHttp).sync();
}
/**
* 'SiteListCommintAsync(params).execute(function(result){},useHttp);'
**/
function SiteListCommintAsync(id,useHttp)
{
return api(SiteListCommintUrl,{id:id},useHttp);
}
var SiteGetPhotoUrl='/GetPhoto';
/**
* 'var result= await SiteGetPhoto(params);'
**/
function SiteGetPhoto(id,useHttp)
{
return api(SiteGetPhotoUrl,{id:id},useHttp).sync();
}
/**
* 'SiteGetPhotoAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetPhotoAsync(id,useHttp)
{
return api(SiteGetPhotoUrl,{id:id},useHttp);
}
var SiteListPhotoUrl='/ListPhoto';
/**
* 'var result= await SiteListPhoto(params);'
**/
function SiteListPhoto(index,useHttp)
{
return api(SiteListPhotoUrl,{index:index},useHttp).sync();
}
/**
* 'SiteListPhotoAsync(params).execute(function(result){},useHttp);'
**/
function SiteListPhotoAsync(index,useHttp)
{
return api(SiteListPhotoUrl,{index:index},useHttp);
}
var SiteCommintUrl='/Commint';
/**
* 'var result= await SiteCommint(params);'
**/
function SiteCommint(id,nickName,content,useHttp)
{
return api(SiteCommintUrl,{id:id,nickName:nickName,content:content},useHttp,true).sync();
}
/**
* 'SiteCommintAsync(params).execute(function(result){},useHttp);'
**/
function SiteCommintAsync(id,nickName,content,useHttp)
{
return api(SiteCommintUrl,{id:id,nickName:nickName,content:content},useHttp,true);
}
var SiteGetBlogUrl='/GetBlog';
/**
* 'var result= await SiteGetBlog(params);'
**/
function SiteGetBlog(id,useHttp)
{
return api(SiteGetBlogUrl,{id:id},useHttp).sync();
}
/**
* 'SiteGetBlogAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetBlogAsync(id,useHttp)
{
return api(SiteGetBlogUrl,{id:id},useHttp);
}
var SiteGetServerInfoUrl='/GetServerInfo';
/**
* 'var result= await SiteGetServerInfo(params);'
**/
function SiteGetServerInfo(useHttp)
{
return api(SiteGetServerInfoUrl,{},useHttp).sync();
}
/**
* 'SiteGetServerInfoAsync(params).execute(function(result){},useHttp);'
**/
function SiteGetServerInfoAsync(useHttp)
{
return api(SiteGetServerInfoUrl,{},useHttp);
}
var SiteSearchUrl='/Search';
/**
* 'var result= await SiteSearch(params);'
**/
function SiteSearch(cate,tag,query,index,useHttp)
{
return api(SiteSearchUrl,{cate:cate,tag:tag,query:query,index:index},useHttp).sync();
}
/**
* 'SiteSearchAsync(params).execute(function(result){},useHttp);'
**/
function SiteSearchAsync(cate,tag,query,index,useHttp)
{
return api(SiteSearchUrl,{cate:cate,tag:tag,query:query,index:index},useHttp);
}
using System;
using System.Collections.Generic;
using System.Text;
using BeetleX.FastHttpApi;
namespace BeetleX.Blog.Controller
{
public class TokenFilter : FastHttpApi.FilterAttribute
{
public override bool Executing(ActionContext context)
{
var user = JWTHelper.Default.GetUserInfo(context.HttpContext.Request);
if (user == null)
{
var result = new ActionResult(403, "没权限操作资源");
result.Data = "/admin/login.html";
context.Result = result;
return false;
}
else
{
context.HttpContext.Data.SetValue("_userName", user.Name);
context.HttpContext.Data.SetValue("_userRole", user.Role);
}
return true;
}
}
public class AdminFilter : TokenFilter
{
public override bool Executing(ActionContext context)
{
if (base.Executing(context))
{
string name = context.HttpContext.Data["_userRole"];
if (name != "admin")
{
var result = new ActionResult(403, "没权限操作资源");
result.Data = "/admin/login.html";
context.Result = result;
return false;
}
else
{
return true;
}
}
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Blog : Peanut.Mappings.DataObject
{
private long mID;
public static Peanut.FieldInfo<long> iD = new Peanut.FieldInfo<long>("Blog", "ID");
private string mTitle;
public static Peanut.FieldInfo<string> title = new Peanut.FieldInfo<string>("Blog", "Title");
private bool mTop;
public static Peanut.FieldInfo<bool> top = new Peanut.FieldInfo<bool>("Blog", "Top");
private string mContent;
public static Peanut.FieldInfo<string> content = new Peanut.FieldInfo<string>("Blog", "Content");
private string mSummary;
public static Peanut.FieldInfo<string> summary = new Peanut.FieldInfo<string>("Blog", "Summary");
private string mCategory;
public static Peanut.FieldInfo<string> category = new Peanut.FieldInfo<string>("Blog", "Category");
private long mCategoryID;
public static Peanut.FieldInfo<long> categoryID = new Peanut.FieldInfo<long>("Blog", "CategoryID");
private string mTags;
public static Peanut.FieldInfo<string> tags = new Peanut.FieldInfo<string>("Blog", "Tags");
private string mSourceUrl;
public static Peanut.FieldInfo<string> sourceUrl = new Peanut.FieldInfo<string>("Blog", "SourceUrl");
private DateTime mCreateTime;
public static Peanut.FieldInfo<DateTime> createTime = new Peanut.FieldInfo<DateTime>("Blog", "CreateTime");
///<summary>
///Type:long
///</summary>
[ID()]
[SequenceID]
public virtual long ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Title
{
get
{
return mTitle;
}
set
{
mTitle = value;
EntityState.FieldChange("Title");
}
}
///<summary>
///Type:bool
///</summary>
[Column()]
[BoolConvter]
public virtual bool Top
{
get
{
return mTop;
}
set
{
mTop = value;
EntityState.FieldChange("Top");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Content
{
get
{
return mContent;
}
set
{
mContent = value;
EntityState.FieldChange("Content");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Summary
{
get
{
return mSummary;
}
set
{
mSummary = value;
EntityState.FieldChange("Summary");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Category
{
get
{
return mCategory;
}
set
{
mCategory = value;
EntityState.FieldChange("Category");
}
}
///<summary>
///Type:long
///</summary>
[Column()]
public virtual long CategoryID
{
get
{
return mCategoryID;
}
set
{
mCategoryID = value;
EntityState.FieldChange("CategoryID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Tags
{
get
{
return mTags;
}
set
{
mTags = value;
EntityState.FieldChange("Tags");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string SourceUrl
{
get
{
return mSourceUrl;
}
set
{
mSourceUrl = value;
EntityState.FieldChange("SourceUrl");
}
}
///<summary>
///Type:DateTime
///</summary>
[Column()]
[DateTimeConvter]
[NowDate]
public virtual DateTime CreateTime
{
get
{
return mCreateTime;
}
set
{
mCreateTime = value;
EntityState.FieldChange("CreateTime");
}
}
}
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class RefreshBlog : Peanut.Mappings.DataObject
{
private long mBlogID;
public static Peanut.FieldInfo<long> blogID = new Peanut.FieldInfo<long>("RefreshBlog", "BlogID");
private DateTime mCreateTime;
public static Peanut.FieldInfo<DateTime> createTime = new Peanut.FieldInfo<DateTime>("RefreshBlog", "CreateTime");
private int mStatus;
public static Peanut.FieldInfo<int> status = new Peanut.FieldInfo<int>("RefreshBlog", "Status");
///<summary>
///Type:long
///</summary>
[Column()]
public virtual long BlogID
{
get
{
return mBlogID;
}
set
{
mBlogID = value;
EntityState.FieldChange("BlogID");
}
}
///<summary>
///Type:DateTime
///</summary>
[Column()]
[DateTimeConvter]
[NowDate]
public virtual DateTime CreateTime
{
get
{
return mCreateTime;
}
set
{
mCreateTime = value;
EntityState.FieldChange("CreateTime");
}
}
///<summary>
///Type:int
///</summary>
[Column()]
public virtual int Status
{
get
{
return mStatus;
}
set
{
mStatus = value;
EntityState.FieldChange("Status");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface IBlog
{
[ID]
[SequenceID]
long ID { get; set; }
[Column]
string Title { get; set; }
[Column]
[BoolConvter]
bool Top { get; set; }
[Column]
string Content { get; set; }
[Column]
string Summary { get; set; }
[Column]
string Category { get; set; }
[Column]
long CategoryID { get; set; }
[Column]
string Tags { get; set; }
[Column]
string SourceUrl { get; set; }
[Column]
[DateTimeConvter]
[NowDate]
DateTime CreateTime { set; get; }
}
[Table]
public interface IRefreshBlog
{
[Column]
long BlogID { get; set; }
[Column]
[DateTimeConvter]
[NowDate]
DateTime CreateTime { get; set; }
[Column]
int Status { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace BeetleX.Blog.DBModules
{
public class BoolConvter : Peanut.Mappings.PropertyCastAttribute
{
public override object ToColumn(object value, Type ptype, object source)
{
if ((bool)value)
{
return 1;
}
else
return 0;
}
public override object ToProperty(object value, Type ptype, object source)
{
return value != null && (long)value > 0;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Category : Peanut.Mappings.DataObject
{
private long mID;
public static Peanut.FieldInfo<long> iD = new Peanut.FieldInfo<long>("Category", "ID");
private string mName;
public static Peanut.FieldInfo<string> name = new Peanut.FieldInfo<string>("Category", "Name");
private string mRemark;
public static Peanut.FieldInfo<string> remark = new Peanut.FieldInfo<string>("Category", "Remark");
private int mOrderBy;
public static Peanut.FieldInfo<int> orderBy = new Peanut.FieldInfo<int>("Category", "OrderBy");
///<summary>
///Type:long
///</summary>
[ID()]
[SequenceID]
public virtual long ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Name
{
get
{
return mName;
}
set
{
mName = value;
EntityState.FieldChange("Name");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Remark
{
get
{
return mRemark;
}
set
{
mRemark = value;
EntityState.FieldChange("Remark");
}
}
///<summary>
///Type:int
///</summary>
[Column()]
public virtual int OrderBy
{
get
{
return mOrderBy;
}
set
{
mOrderBy = value;
EntityState.FieldChange("OrderBy");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface ICategory
{
[ID]
[SequenceID]
long ID { get; set; }
[Column]
string Name { get; set; }
[Column]
string Remark { get; set; }
[Column]
int OrderBy { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Comment : Peanut.Mappings.DataObject
{
private long mID;
public static Peanut.FieldInfo<long> iD = new Peanut.FieldInfo<long>("Comment", "ID");
private string mNickName;
public static Peanut.FieldInfo<string> nickName = new Peanut.FieldInfo<string>("Comment", "NickName");
private string mHeadUrl;
public static Peanut.FieldInfo<string> headUrl = new Peanut.FieldInfo<string>("Comment", "HeadUrl");
private long mBlogID;
public static Peanut.FieldInfo<long> blogID = new Peanut.FieldInfo<long>("Comment", "BlogID");
private string mContent;
public static Peanut.FieldInfo<string> content = new Peanut.FieldInfo<string>("Comment", "Content");
private DateTime mCreateTime;
public static Peanut.FieldInfo<DateTime> createTime = new Peanut.FieldInfo<DateTime>("Comment", "CreateTime");
private string mUserID;
public static Peanut.FieldInfo<string> userID = new Peanut.FieldInfo<string>("Comment", "UserID");
///<summary>
///Type:long
///</summary>
[ID()]
[SequenceID]
public virtual long ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string NickName
{
get
{
return mNickName;
}
set
{
mNickName = value;
EntityState.FieldChange("NickName");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string HeadUrl
{
get
{
return mHeadUrl;
}
set
{
mHeadUrl = value;
EntityState.FieldChange("HeadUrl");
}
}
///<summary>
///Type:long
///</summary>
[Column()]
public virtual long BlogID
{
get
{
return mBlogID;
}
set
{
mBlogID = value;
EntityState.FieldChange("BlogID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Content
{
get
{
return mContent;
}
set
{
mContent = value;
EntityState.FieldChange("Content");
}
}
///<summary>
///Type:DateTime
///</summary>
[Column()]
[NowDate]
[DateTimeConvter]
public virtual DateTime CreateTime
{
get
{
return mCreateTime;
}
set
{
mCreateTime = value;
EntityState.FieldChange("CreateTime");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string UserID
{
get
{
return mUserID;
}
set
{
mUserID = value;
EntityState.FieldChange("UserID");
}
}
}
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table("Comment inner join Blog on Comment.BlogID=Blog.ID")]
public partial class TopComment : Peanut.Mappings.DataObject
{
private long mID;
public static Peanut.FieldInfo<long> iD = new Peanut.FieldInfo<long>("Comment inner join Blog on Comment.BlogID=Blog.ID", "Blog.ID");
private long mCommentID;
public static Peanut.FieldInfo<long> commentID = new Peanut.FieldInfo<long>("Comment inner join Blog on Comment.BlogID=Blog.ID", "Comment.ID");
private string mTitle;
public static Peanut.FieldInfo<string> title = new Peanut.FieldInfo<string>("Comment inner join Blog on Comment.BlogID=Blog.ID", "Title");
private string mContent;
public static Peanut.FieldInfo<string> content = new Peanut.FieldInfo<string>("Comment inner join Blog on Comment.BlogID=Blog.ID", "Comment.Content");
private string mNickName;
public static Peanut.FieldInfo<string> nickName = new Peanut.FieldInfo<string>("Comment inner join Blog on Comment.BlogID=Blog.ID", "NickName");
private DateTime mCreateTime;
public static Peanut.FieldInfo<DateTime> createTime = new Peanut.FieldInfo<DateTime>("Comment inner join Blog on Comment.BlogID=Blog.ID", "Comment.CreateTime");
///<summary>
///Type:long
///</summary>
[Column("Blog.ID")]
public virtual long ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:long
///</summary>
[Column("Comment.ID")]
public virtual long CommentID
{
get
{
return mCommentID;
}
set
{
mCommentID = value;
EntityState.FieldChange("CommentID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Title
{
get
{
return mTitle;
}
set
{
mTitle = value;
EntityState.FieldChange("Title");
}
}
///<summary>
///Type:string
///</summary>
[Column("Comment.Content")]
public virtual string Content
{
get
{
return mContent;
}
set
{
mContent = value;
EntityState.FieldChange("Content");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string NickName
{
get
{
return mNickName;
}
set
{
mNickName = value;
EntityState.FieldChange("NickName");
}
}
///<summary>
///Type:DateTime
///</summary>
[Column("Comment.CreateTime")]
[DateTimeConvter]
public virtual DateTime CreateTime
{
get
{
return mCreateTime;
}
set
{
mCreateTime = value;
EntityState.FieldChange("CreateTime");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface IComment
{
[ID]
[SequenceID]
long ID { get; set; }
[Column]
string NickName { get; set; }
[Column]
string HeadUrl { get; set; }
[Column]
long BlogID { get; set; }
[Column]
string Content { get; set; }
[Column]
[NowDate]
[DateTimeConvter]
DateTime CreateTime { get; set; }
[Column]
string UserID { get; set; }
}
[Table("Comment inner join Blog on Comment.BlogID=Blog.ID")]
public interface ITopComment
{
[Column("Blog.ID")]
long ID { get; set; }
[Column("Comment.ID")]
long CommentID { get; set; }
[Column]
string Title { get; set; }
[Column("Comment.Content")]
string Content { get; set; }
[Column]
string NickName { get; set; }
[Column("Comment.CreateTime")]
[DateTimeConvter]
DateTime CreateTime { get; set; }
}
}
using Peanut;
using System;
using System.Collections.Generic;
using System.Text;
namespace BeetleX.Blog.DBModules
{
public class DBHelper
{
private static DBHelper mDefault;
public long GetSequence(string key)
{
lock (this)
{
Sequence sequence = (Sequence.key == key).ListFirst<Sequence>();
if (sequence == null)
{
sequence = new Sequence();
sequence.Key = key;
sequence.Value = 10000;
}
sequence.Value++;
long result = sequence.Value;
sequence.Save();
return result;
}
}
public static DBHelper Default
{
get
{
if (mDefault == null)
{
lock (typeof(DBHelper))
{
if (mDefault == null)
{
DBContext.SetConnectionDriver<SqliteDriver>(DB.DB1);
DBContext.SetConnectionString(DB.DB1, "Data Source=beetlex_blog.db;Pooling=true;FailIfMissing=false;");
mDefault = new DBHelper();
mDefault.Setting = new Setting();
mDefault.Setting.Init();
mDefault.Setting.Load();
}
}
}
return mDefault;
}
}
public Setting Setting { get; private set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace BeetleX.Blog.DBModules
{
public class DateTimeConvter : Peanut.Mappings.PropertyCastAttribute
{
public override object ToColumn(object value, Type ptype, object source)
{
return ((DateTime)value).Ticks;
}
public override object ToProperty(object value, Type ptype, object source)
{
return new DateTime((long)value);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Photo : Peanut.Mappings.DataObject
{
private long mID;
public static Peanut.FieldInfo<long> iD = new Peanut.FieldInfo<long>("Photo", "ID");
private string mTitle;
public static Peanut.FieldInfo<string> title = new Peanut.FieldInfo<string>("Photo", "Title");
private DateTime mCreateTime;
public static Peanut.FieldInfo<DateTime> createTime = new Peanut.FieldInfo<DateTime>("Photo", "CreateTime");
private string mSmallUrl;
public static Peanut.FieldInfo<string> smallUrl = new Peanut.FieldInfo<string>("Photo", "SmallUrl");
private string mLargeUrl;
public static Peanut.FieldInfo<string> largeUrl = new Peanut.FieldInfo<string>("Photo", "LargeUrl");
///<summary>
///Type:long
///</summary>
[ID()]
[SequenceID]
public virtual long ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Title
{
get
{
return mTitle;
}
set
{
mTitle = value;
EntityState.FieldChange("Title");
}
}
///<summary>
///Type:DateTime
///</summary>
[Column()]
[DateTimeConvter]
[NowDate]
public virtual DateTime CreateTime
{
get
{
return mCreateTime;
}
set
{
mCreateTime = value;
EntityState.FieldChange("CreateTime");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string SmallUrl
{
get
{
return mSmallUrl;
}
set
{
mSmallUrl = value;
EntityState.FieldChange("SmallUrl");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string LargeUrl
{
get
{
return mLargeUrl;
}
set
{
mLargeUrl = value;
EntityState.FieldChange("LargeUrl");
}
}
}
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class PhotoItem : Peanut.Mappings.DataObject
{
private string mID;
public static Peanut.FieldInfo<string> iD = new Peanut.FieldInfo<string>("PhotoItem", "ID");
private long mPhotoID;
public static Peanut.FieldInfo<long> photoID = new Peanut.FieldInfo<long>("PhotoItem", "PhotoID");
private string mLargeUrl;
public static Peanut.FieldInfo<string> largeUrl = new Peanut.FieldInfo<string>("PhotoItem", "LargeUrl");
private string mSmallUrl;
public static Peanut.FieldInfo<string> smallUrl = new Peanut.FieldInfo<string>("PhotoItem", "SmallUrl");
///<summary>
///Type:string
///</summary>
[ID()]
public virtual string ID
{
get
{
return mID;
}
set
{
mID = value;
EntityState.FieldChange("ID");
}
}
///<summary>
///Type:long
///</summary>
[Column()]
public virtual long PhotoID
{
get
{
return mPhotoID;
}
set
{
mPhotoID = value;
EntityState.FieldChange("PhotoID");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string LargeUrl
{
get
{
return mLargeUrl;
}
set
{
mLargeUrl = value;
EntityState.FieldChange("LargeUrl");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string SmallUrl
{
get
{
return mSmallUrl;
}
set
{
mSmallUrl = value;
EntityState.FieldChange("SmallUrl");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface IPhoto
{
[ID]
[SequenceID]
long ID { get; set; }
[Column]
string Title { get; set; }
[Column]
[DateTimeConvter]
[NowDate]
DateTime CreateTime { get; set; }
[Column]
string SmallUrl { get; set; }
[Column]
string LargeUrl { get; set; }
}
[Table]
public interface IPhotoItem
{
[ID]
string ID { get; set; }
[Column]
long PhotoID { get; set; }
[Column]
string LargeUrl { get; set; }
[Column]
string SmallUrl { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Sequence : Peanut.Mappings.DataObject
{
private string mKey;
public static Peanut.FieldInfo<string> key = new Peanut.FieldInfo<string>("Sequence", "Key");
private long mValue;
public static Peanut.FieldInfo<long> value = new Peanut.FieldInfo<long>("Sequence", "Value");
///<summary>
///Type:string
///</summary>
[ID()]
public virtual string Key
{
get
{
return mKey;
}
set
{
mKey = value;
EntityState.FieldChange("Key");
}
}
///<summary>
///Type:long
///</summary>
[Column()]
public virtual long Value
{
get
{
return mValue;
}
set
{
mValue = value;
EntityState.FieldChange("Value");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface ISequence
{
[ID]
string Key { get; set; }
[Column]
long Value { get; set; }
}
public class SequenceID : Peanut.Mappings.ValueAttribute
{
public SequenceID() : base(false)
{
}
public override void Executing(IConnectinContext cc, object data, PropertyMapper pm, string table)
{
long id = DBHelper.Default.GetSequence(table);
pm.Handler.Set(data, id);
base.Executing(cc, data, pm, table);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
///<summary>
///Peanut Generator Copyright @ henryfan 2018 email:henryfan@msn.com
///website:http://www.ikende.com
///</summary>
[Table()]
public partial class Option : Peanut.Mappings.DataObject
{
private string mName;
public static Peanut.FieldInfo<string> name = new Peanut.FieldInfo<string>("Option", "Name");
private string mValue;
public static Peanut.FieldInfo<string> value = new Peanut.FieldInfo<string>("Option", "Value");
///<summary>
///Type:string
///</summary>
[ID()]
public virtual string Name
{
get
{
return mName;
}
set
{
mName = value;
EntityState.FieldChange("Name");
}
}
///<summary>
///Type:string
///</summary>
[Column()]
public virtual string Value
{
get
{
return mValue;
}
set
{
mValue = value;
EntityState.FieldChange("Value");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut.Mappings;
namespace BeetleX.Blog.DBModules
{
[Table]
public interface IOption
{
[ID]
string Name { get; set; }
[Column]
string Value { get; set; }
}
public class Setting
{
public const string USERNAME = "USERNAME";
public const string PASSWORD = "PASSWORD";
public const string BLOG_TITLE = "BLOG_TITLE";
public const string ES_HOST = "ES_HOST";
public const string ABOUT = "ABOUT";
public const string IMG_HOST = "IMG_HOST";
public const string JWTKEY = "JWT_KEY";
public const string TCLOUD_ID = "TCLOUD_ID";
public const string TCLOUD_KEY = "TCLOUD_KEY";
public const string TCLOUD_HOST = "TCLOUD_HOST";
public Option PassWord { get; private set; }
public Option Title { get; private set; }
public Option UserName { get; private set; }
public Option About { get; private set; }
public Option ElasticSearch { get; private set; }
public Option TCloudID { get; private set; }
public Option TCloudKey { get; private set; }
public Option TCloudHost { get; private set; }
public Option JwtKey { get; private set; }
public Option ImgHost { get; private set; }
public void Init()
{
Option option;
if ((Option.name == IMG_HOST).Count<Option>() == 0)
{
option = new Option();
option.Name = IMG_HOST;
option.Value = "";
option.Save();
}
if ((Option.name == TCLOUD_ID).Count<Option>() == 0)
{
option = new Option();
option.Name = TCLOUD_ID;
option.Value = "";
option.Save();
}
if ((Option.name == TCLOUD_KEY).Count<Option>() == 0)
{
option = new Option();
option.Name = TCLOUD_KEY;
option.Value = "";
option.Save();
}
if ((Option.name == TCLOUD_HOST).Count<Option>() == 0)
{
option = new Option();
option.Name = TCLOUD_HOST;
option.Value = "";
option.Save();
}
if ((Option.name == USERNAME).Count<Option>() == 0)
{
option = new Option();
option.Name = USERNAME;
option.Value = "admin";
option.Save();
}
if ((Option.name == PASSWORD).Count<Option>() == 0)
{
option = new Option();
option.Name = PASSWORD;
option.Value = Units.MD5Encrypt("123456");
option.Save();
}
if ((Option.name == BLOG_TITLE).Count<Option>() == 0)
{
option = new Option();
option.Name = BLOG_TITLE;
option.Value = "BeetleX Blog";
option.Save();
}
if ((Option.name == ES_HOST).Count<Option>() == 0)
{
option = new Option();
option.Name = ES_HOST;
option.Value = "http://localhost:9200";
option.Save();
}
if ((Option.name == ABOUT).Count<Option>() == 0)
{
option = new Option();
option.Name = ABOUT;
option.Value = "Copyright © 2018 ikende.com email:henryfan@msn.com| http://github.com/ikende";
option.Save();
}
if ((Option.name == JWTKEY).Count<Option>() == 0)
{
byte[] key = new byte[128];
new Random().NextBytes(key);
string keyStr = Convert.ToBase64String(key);
option = new Option();
option.Name = JWTKEY;
option.Value = keyStr;
option.Save();
}
}
public void Load()
{
UserName = (Option.name == USERNAME).ListFirst<Option>();
PassWord = (Option.name == PASSWORD).ListFirst<Option>();
Title = (Option.name == BLOG_TITLE).ListFirst<Option>();
ElasticSearch = (Option.name == ES_HOST).ListFirst<Option>();
About = (Option.name == ABOUT).ListFirst<Option>();
JwtKey = (Option.name == JWTKEY).ListFirst<Option>();
TCloudID = (Option.name == TCLOUD_ID).ListFirst<Option>();
TCloudKey = (Option.name == TCLOUD_KEY).ListFirst<Option>();
TCloudHost = (Option.name == TCLOUD_HOST).ListFirst<Option>();
ImgHost = (Option.name == IMG_HOST).ListFirst<Option>();
}
public void SaveTCould(string id, string key, string host)
{
TCloudID.Value = id;
TCloudID.Save();
TCloudKey.Value = key;
TCloudKey.Save();
TCloudHost.Value = host;
TCloudHost.Save();
}
public void ReCreateJWT()
{
byte[] key = new byte[128];
new Random().NextBytes(key);
string keyStr = Convert.ToBase64String(key);
JwtKey.Value = keyStr;
JwtKey.Save();
}
public void Save()
{
UserName.Save();
PassWord.Save();
Title.Save();
ElasticSearch.Save();
About.Save();
ImgHost.Save();
}
}
}
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Text;
namespace BeetleX.Blog.DBModules
{
public class SqliteDriver : Peanut.DriverTemplate<
SQLiteConnection,
SQLiteCommand,
SQLiteDataAdapter,
SQLiteParameter,
Peanut.SqlitBuilder>
{
}
}
using BeetleX.Elasticsearch.Mappings;
using System;
using System.Collections.Generic;
using System.Text;
namespace BeetleX.Blog.ES
{
[TableType("Blog")]
public class ESBlog
{
[ID]
[Column(Type = ColumnType._keyword)]
public string ID { get; set; }
[Column(Type = ColumnType._text,
Analyzer = Elasticsearch.AnalyzerType.ik_max_word,
SearchAnalyzer = Elasticsearch.AnalyzerType.ik_smart)]
public string Title { get; set; }
[Column(Type = ColumnType._boolean)]
public bool Top { get; set; }
[Column(Type = ColumnType._text,
Analyzer = Elasticsearch.AnalyzerType.ik_max_word,
SearchAnalyzer = Elasticsearch.AnalyzerType.ik_smart)]
public string Content { get; set; }
[Column(Type = ColumnType._text, Index = false)]
public string Summary { get; set; }
[Column(Type = ColumnType._text, FieldData = true, Analyzer = Elasticsearch.AnalyzerType.whitespace,
SearchAnalyzer = Elasticsearch.AnalyzerType.whitespace)]
public string Category { get; set; }
[Column(Type = ColumnType._long)]
public long CategoryID { get; set; }
[Column(Type = ColumnType._text,
Analyzer = Elasticsearch.AnalyzerType.whitespace,
SearchAnalyzer = Elasticsearch.AnalyzerType.whitespace, FieldData = true)]
public string Tags { get; set; }
[Column(Type = ColumnType._text, Index = false)]
public string SourceUrl { get; set; }
[Column(Type = ColumnType._date)]
public DateTime CreateTime { set; get; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Peanut;
namespace BeetleX.Blog.ES
{
public class ESHelper
{
public static bool Available { get; set; }
public static Elasticsearch.ESDB DB { get; set; }
public static Elasticsearch.Core.IESIndex Blog { get; set; }
public static Exception InitError { get; set; }
public static void ReCreateIndex()
{
DB.DeleteIndex("beetlex");
Blog = DB.GetIndexAndCreate("beetlex");
Blog.CreateType<ESBlog>();
}
public static void Init(string host)
{
try
{
Blog = null;
Available = true;
InitError = null;
DB = new Elasticsearch.ESDB(host);
DB.Status();
Blog = DB.GetIndexAndCreate("beetlex");
Blog.CreateType<ESBlog>();
Available = true;
}
catch (Exception e_)
{
Available = false;
InitError = e_;
}
}
private static void OnSyncData(object state)
{
BeetleX.FastHttpApi.HttpApiServer server = (BeetleX.FastHttpApi.HttpApiServer)state;
if (!Available)
return;
mSyncTimer.Change(-1, -1);
try
{
foreach (var item in new Peanut.Expression().List<DBModules.RefreshBlog>())
{
if (item.Status == 1)
{
DBModules.Blog blog = Peanut.DBContext.Load<DBModules.Blog>(item.BlogID);
if (blog != null)
{
ES.ESBlog eSBlog = new ESBlog();
eSBlog.ID = blog.ID.ToString();
eSBlog.CategoryID = blog.CategoryID;
eSBlog.Content = blog.Content;
eSBlog.CreateTime = blog.CreateTime;
eSBlog.SourceUrl = blog.SourceUrl;
eSBlog.Summary = blog.Summary;
eSBlog.Category = blog.Category;
eSBlog.Tags = blog.Tags;
eSBlog.Title = blog.Title;
eSBlog.Top = blog.Top;
Blog.Put(eSBlog);
(DBModules.RefreshBlog.blogID == blog.ID).Delete<DBModules.RefreshBlog>();
if (server.EnableLog(EventArgs.LogType.Info))
server.Log(EventArgs.LogType.Info, $"update blog {blog.Title} sync to elasticsearch success");
}
}
else
{
(DBModules.RefreshBlog.blogID == item.BlogID).Delete<DBModules.RefreshBlog>();
try
{
Blog.Delete<ESBlog>(item.BlogID.ToString());
if (server.EnableLog(EventArgs.LogType.Info))
server.Log(EventArgs.LogType.Info, $"delete blog {item.BlogID} sync to elasticsearch success");
}
catch (Exception e_)
{
if (server.EnableLog(EventArgs.LogType.Error))
server.Log(EventArgs.LogType.Error, $"delete blog {item.BlogID} sync to elasticsearch error {e_.Message}");
}
}
}
}
catch (Exception e)
{
if (server.EnableLog(EventArgs.LogType.Error))
server.Log(EventArgs.LogType.Error, $"blog sync to elasticsearch error {e.Message}");
}
finally
{
mSyncTimer.Change(5000, 5000);
}
}
private static System.Threading.Timer mSyncTimer;
public static void SyncData(BeetleX.FastHttpApi.HttpApiServer server)
{
mSyncTimer = new System.Threading.Timer(OnSyncData, server, 5000, 5000);
}
}
}
{
"HttpConfig": {
"BufferPoolMaxMemory": 500,
"SessionTimeOut": 3600,
"UseIPv6": true,
"UrlIgnoreCase": true,
"PacketCombined": 0,
"FileManager": false,
"FileManagerPath": null,
"LogToConsole": true,
"NotLoadFolder": "\\Files;\\Images",
"CacheFiles": "html;htm;js;css",
"CacheFileSize": 500,
"LogLevel": 8,
"WebSocketMaxRPS": 100,
"BufferSize": 8096,
"NoGzipFiles": "jpg;jpeg;png;gif;png;ico;zip;rar;bmp",
"MaxConnections": 2000,
"Manager": "admin",
"ManagerPWD": "123456",
"WriteLog": true,
"Host": "",
"Debug": false,
"Port": 8080,
"MaxBodyLength": 2097152,
"OutputStackTrace": false,
"StaticResurceType": "txt;xml;zip;jpg;css;png;htm;woff;svg;gif;woff2;js;html;jpeg;ico;rar",
"DefaultPage": "index.html;index.htm"
}
}
using BeetleX.FastHttpApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace BeetleX.Blog
{
class Program
{
static void Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<HttpServerHosted>();
});
builder.Build().Run();
}
}
public class HttpServerHosted : IHostedService
{
private HttpApiServer mApiServer;
public virtual Task StartAsync(CancellationToken cancellationToken)
{
mApiServer = new HttpApiServer();
DBModules.DBHelper.Default.GetSequence("System");
ES.ESHelper.Init(DBModules.DBHelper.Default.Setting.ElasticSearch.Value);
mApiServer.Debug();
mApiServer.Register(typeof(Program).Assembly);
mApiServer.Open();
ES.ESHelper.SyncData(mApiServer);
JWTHelper.Init();
return Task.CompletedTask;
}
public virtual Task StopAsync(CancellationToken cancellationToken)
{
mApiServer.Dispose();
return Task.CompletedTask;
}
}
}
[
{
"outputFileName": "views/js/bundle.js",
"inputFiles": [
"views/js/bootstrap.js",
"views/js/FastHttpApi.js",
"views/js/highlight_pack.js",
"views/js/jquery_goup.js",
"views/js/lodash.js",
"views/js/marked.js",
"views/js/md5.js",
"views/js/ModuleLoader.js",
"views/js/Monitor.js",
"views/js/Site.js"
]
},
{
"outputFileName": "views/css/bundle.css",
"inputFiles": [
"views/css/bootstrap.css",
"views/css/bootstrap-theme.css",
"views/css/site.css"
]
}
]
/*
Navicat SQLite Data Transfer
Source Server : beetlexBlog
Source Server Version : 30623
Source Host : localhost:0
Target Server Type : SQLite
Target Server Version : 30623
File Encoding : 65001
Date: 2019-01-03 15:05:29
*/
PRAGMA foreign_keys = OFF;
-- ----------------------------
-- Table structure for "main"."Blog"
-- ----------------------------
DROP TABLE "main"."Blog";
CREATE TABLE "Blog" (
"ID" INTEGER,
"Title" TEXT,
"Top" INTEGER,
"Content" TEXT,
"Summary" TEXT,
"Category" TEXT,
"CategoryID" INTEGER,
"Tags" TEXT,
"SourceUrl" TEXT,
"CreateTime" INTEGER,
PRIMARY KEY ("ID" ASC)
);
-- ----------------------------
-- Records of Blog
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."Category"
-- ----------------------------
DROP TABLE "main"."Category";
CREATE TABLE "Category" (
"ID" INTEGER,
"Name" TEXT,
"Remark" TEXT,
"OrderBy" INTEGER,
PRIMARY KEY ("ID" ASC)
);
-- ----------------------------
-- Records of Category
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."Comment"
-- ----------------------------
DROP TABLE "main"."Comment";
CREATE TABLE "Comment" (
"ID" INTEGER,
"NickName" TEXT,
"BlogID" INTEGER,
"Content" TEXT,
"CreateTime" INTEGER,
"HeadUrl" TEXT,
"UserID" TEXT,
PRIMARY KEY ("ID" ASC)
);
-- ----------------------------
-- Records of Comment
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."Option"
-- ----------------------------
DROP TABLE "main"."Option";
CREATE TABLE "Option" (
"Name" TEXT,
"Value" TEXT,
PRIMARY KEY ("Name")
);
-- ----------------------------
-- Records of Option
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."Photo"
-- ----------------------------
DROP TABLE "main"."Photo";
CREATE TABLE "Photo" (
"ID" INTEGER,
"Title" TEXT,
"CreateTime" INTEGER,
"SmallUrl" TEXT,
"LargeUrl" TEXT,
PRIMARY KEY ("ID" ASC)
);
-- ----------------------------
-- Records of Photo
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."PhotoItem"
-- ----------------------------
DROP TABLE "main"."PhotoItem";
CREATE TABLE "PhotoItem" (
"ID" TEXT,
"PhotoID" INTEGER,
"LargeUrl" TEXT,
"SmallUrl" TEXT,
PRIMARY KEY ("ID" ASC)
);
-- ----------------------------
-- Records of PhotoItem
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."RefreshBlog"
-- ----------------------------
DROP TABLE "main"."RefreshBlog";
CREATE TABLE "RefreshBlog" (
"BlogID" INTEGER,
"CreateTime" INTEGER,
"Status" INTEGER
);
-- ----------------------------
-- Records of RefreshBlog
-- ----------------------------
-- ----------------------------
-- Table structure for "main"."Sequence"
-- ----------------------------
DROP TABLE "main"."Sequence";
CREATE TABLE "Sequence" (
"Key" TEXT,
"Value" INTEGER,
PRIMARY KEY ("Key")
);
<templates>
<template id="site-header">
<div class="container" id="siteHeader">
<div class="navbar-header">
<button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" style="color:white;" href="/" :title="['v:'+Data.Version]">
<img src="/images/home_icon.png" style="float:left;margin-top:-6px;padding-right:6px;" />{{Data.Title}}
</a>
</div>
<div class="navbar-collapse collapse" role="navigation">
<ul class="nav navbar-nav">
<li v-for="item in Data.Menus">
<a :href="['/cate/'+item.ID+'.html']">{{item.Name}}</a>
</li>
<li><a href="/photos/0.html">相册</a></li>
<li>
<div class="form-group form-inline form-group-sm" style="padding-top:10px;margin-bottom:0px;margin-left:20px;">
<label for="inputPassword2" class="sr-only">Password</label>
<input id="txtSearch" type="text" onkeypress="if (event.keyCode == 13) { blogSearch();}" class="form-control" placeholder="查询">
<a href="javascript:void(0)" onclick="blogSearch()"><img src="/images/search.png" style="width:16px;" /></a>
</div>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
</li>
<li><a href="/admin/">管理</a></li>
</ul>
</div>
</div>
<script>
var siteHeader;
siteHeader = new Vue({ el: '#siteHeader', data: { Data: { Title: '', Menus: [] } } });
SiteGetTitleAndMenu().execute(function (r) {
siteHeader.Data = r.Data;
if (document.title)
document.title = r.Data.Title + " " + document.title;
else
document.title = r.Data.Title;
})
</script>
</template>
<template id="topBlog">
<ul id="lstTopBlog">
<li v-for="item in Data"><a :href="['/blog/'+item.ID+'.html']"> {{item.Title}}</a></li>
</ul>
<script>
var lstNewBlog;
lstTopBlog = new Vue({ el: "#lstTopBlog", data: { Data: [] } });
SiteTopBlog().execute(function (r) {
lstTopBlog.Data = r.Data;
});
</script>
</template>
<template id="topComment">
<ul id="lstTopComment">
<li v-for="item in Data">
<a :href="['/blog/'+item.ID+'.html']"> {{item.Title}}</a>
<div>
<span class="btn btn-xs"><img src="/images/date.png" />{{item.CreateTime}}</span>
<span class="btn btn-xs">({{item.NickName}})</span>
</div>
<div v-html="marked(item.Content, { sanitize: true })"></div>
</li>
</ul>
<script>
var lstTopComment;
lstTopComment = new Vue({ el: "#lstTopComment", data: { Data: [] } });
SiteTopComment().execute(function (r) {
lstTopComment.Data = r.Data;
});
</script>
</template>
<template id="newBlog">
<ul id="lstNewBlog">
<li v-for="item in Data"><a :href="['/blog/'+item.ID+'.html']"> {{item.Title}}</a></li>
</ul>
<script>
var lstNewBlog;
lstNewBlog = new Vue({ el: "#lstNewBlog", data: { Data: [] } });
SiteNewBlog().execute(function (r) {
lstNewBlog.Data = r.Data;
})
</script>
</template>
<template id="about">
<div id="aboutInfo">
<div v-html="compiledMarkdown">
</div>
</div>
<script>
var aboutInfo;
aboutInfo = new Vue({
el: '#aboutInfo',
data: { Data: '' },
computed: {
compiledMarkdown: function () {
return marked(this.Data, { sanitize: true })
}
}
});
SiteGetAbout().execute(function (r) {
aboutInfo.Data = r.Data;
});
</script>
</template>
<template id="tags">
<div id="lstTags">
<a :href="['/tag/'+encodeURIComponent(item.Name)+'.html']" v-for="(item,i) in Data"
:class="[getColor()]">{{item.Name}}({{item.Value}})</a>
<a href="/tags.html">更多标签...</a>
</div>
<script>
var lstTags;
lstTags = new Vue({ el: '#lstTags', data: { Data: [] } });
SiteGetTags().execute(function (r) {
lstTags.Data = r.Data;
});
</script>
</template>
<template id="header">
<div class="navbar-header" >
<a class="navbar-brand" href="/admin/" style="color:white;width:220px;">
<img src="/images/admin/admin.png" style="float:left;margin-top:-2px;margin-right:10px;" /><span>BeetleX Blog</span>
</a>
</div>
<div id="navbar" class="navbar-collapse collapse ">
<ul class="nav navbar-nav main_menu">
<li>
<a href="/"><img src="/images/admin/home.png" />返回主页</a>
</li>
<li>
<a href="index.html"><img src="/images/admin/blog.png" />文章管理</a>
</li>
<li><a href="categories.html"><img src="/images/admin/cate.png" />分类管理</a></li>
<li><a href="photos.html"><img src="/images/admin/photo.png" />个人相册</a></li>
<li><a href="comments.html"><img src="/images/admin/talk.png" />留言管理</a></li>
<li><a href="files.html"><img src="/images/admin/file.png" />文件管理</a></li>
<li><a href="system.html"><img src="/images/admin/system.png" />系统资源</a></li>
<li><a href="connections.html"><img src="/images/admin/connections.png" />在线连接</a></li>
<li><a href="setting.html"><img src="/images/admin/setting.png" />设置</a></li>
<li><a href="/admin/setting/Signout"><img src="/images/admin/exit.png" />退出</a></li>
</ul>
</div>
</template>
<template id="footer">
<div class="blog-footer">
<hr />
<p>XBlog Copyright © 2018 <a href="http://www.ikende.com" target="_blank">ikende.com</a> email:henryfan@msn.com <a href="https://github.com/ikende" target="_blank">github.com</a></p>
</div>
</template>
<template id="system_info">
<div id="serverInfo">
<div class="panel-body" style="height:60px;padding:1px;">
<canvas width="400" height="70" id="cpuCanavas" style="width:100%;height:100%;"></canvas>
</div>
<div class="panel-body" style="height:60px;padding:1px;">
<canvas width="400" height="70" id="requestCanvas" style="width:100%;height:100%;"></canvas>
</div>
<div class="panel-body" style="height:60px;padding:1px;">
<canvas width="400" height="70" id="networkCanvas" style="width:100%;height:100%;"></canvas>
</div>
<script>
var cpuMonitor;
var cpu;
var requestMonitor;
var request;
var networkMonitor;
var netInput;
var netOutput;
var serverInfoControl;
serverInfoControl = new Vue({
el: '#serverInfo',
data: {
Data: {}
}
});
function GetServerInfo() {
SiteGetServerInfo().execute(function (result) {
serverInfoControl.Data = result.Data;
cpu.push(result.Data.Cpu);
cpuMonitor.draw();
request.push(result.Data.RequestPer);
requestMonitor.draw();
netInput.push(result.Data.ReceiveBytesPer);
netOutput.push(result.Data.SendBytesPer);
networkMonitor.draw();
});
}
cpuMonitor = new Monitor('cpuCanavas');
cpu = cpuMonitor.create();
cpu.label = "Cpu";
requestMonitor = new Monitor('requestCanvas');
request = requestMonitor.create();
request.maxValue = 5000;
request.changeMaxValue = true;
request.label = "Request";
networkMonitor = new Monitor('networkCanvas');
netInput = networkMonitor.create();
netInput.maxValue = 10;
netInput.label = "Network Input(MB)";
netOutput = networkMonitor.create();
netOutput.maxValue = 10;
netOutput.label = "Network Output(MB)";
GetServerInfo();
setInterval(function () { GetServerInfo(); }, 1000);
</script>
</div>
</template>
</templates>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link href="/css/bootstrap.css" rel="stylesheet" />
<link href="/css/bootstrap-theme.css" rel="stylesheet" />
<link href="/css/admin.css" rel="stylesheet" />
<script src="/js/jquery.js"></script>
<script src="/js/ModuleLoader.js"></script>
<script src="/js/bootstrap.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="/js/FastHttpApi.js"></script>
<script src="/js/AdminController.js"></script>
<script src="/js/marked.js"></script>
<script src="/js/lodash.js"></script>
<title>BeetleX Blog Admin</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-left" style="background-color:#9f9e9e;background-image:none;border:none;" slot="header">
</div>
<div class="container bs-docs-container" style="padding-top:0px;">
<div class="row">
<ul class="nav nav-tabs" slot="admin-manager-nav"></ul>
<div style="padding:5px;">
<form class="navbar-form navbar-left btn-group-sm" style="display:contents;margin-bottom:4px;" role="search">
<a href="DocEditor.html" class="btn btn-default">添加</a>
<a href="javascript:void(0)" onclick="deleteDoc()" class="btn btn-default">删除</a>
</form>
</div>
<table class="table table-hover" id="lstDoc">
<thead>
<tr>
<th style="width:40px;"><input onclick="selectAll(this)" type="checkbox" /></th>
<th>标签</th>
<th>标题</th>
<th>创建时间</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="item in Data">
<th><input v-bind:id="item.ID" type="checkbox" /></th>
<td>{{item.Tag}}</td>
<td> <a v-bind:href="['DocEditor.html?ID='+item.ID]">{{item.Title}}</a></td>
<td>{{item.CreateTime}}</td>
<td><a v-bind:href="['Comment.html?ID='+item.ID]">查看疑问</a></td>
</tr>
</table>
<nav aria-label="Page navigation">
<ul id="pagination" class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<li><a href="javascript:void(0)" onclick="search(0)">1</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="container" style="text-align:center;" slot="footer">
</div>
</body>
</html>
\ No newline at end of file
差异被折叠。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link href="/css/bootstrap.css" rel="stylesheet" />
<link href="/css/bootstrap-theme.css" rel="stylesheet" />
<link href="/css/admin.css" rel="stylesheet" />
<script src="/js/jquery.js"></script>
<script src="/js/ModuleLoader.js"></script>
<script src="/js/bootstrap.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="/js/FastHttpApi.js"></script>
<script src="/js/admin/AdminCategory.js"></script>
<script src="/js/marked.js"></script>
<script src="/js/lodash.js"></script>
<title>BeetleX Blog Admin</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-left" slot="header">
</div>
<div class="page-title">
<img src="/images/admin/nav.png" /> <h3>分类管理</h3>
</div>
<div class="container bs-docs-container">
<div class="row">
<div style="padding:5px;">
<form class="form-inline form-group-sm" id="cateCreater">
<div class="form-group">
<label for="exampleInputName2">名称</label>
<input type="text" class="form-control" v-model:value="title" placeholder="name">
</div>
<div class="form-group">
<label for="exampleInputEmail2">描述</label>
<input type="text" style="width:250px;" v-model:value="remark" class="form-control" placeholder="remark">
</div>
<button type="button" onclick="Add();" class="btn btn-default btn-sm">添加</button>
</form>
</div>
<table class="table table-hover" id="lstCate">
<thead>
<tr>
<th></th>
<th>名称</th>
<th>描述</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in Data">
<td style="width:30px;">
<a href="javascript:void(0)" v-on:click="OrderBy(item.ID,true,index)"><img src="/images/admin/up.png" /></a>
</td>
<td style="width:200px;">{{item.Name}}</td>
<td> {{item.Remark}}</td>
<td style="width:60px;"><a href="javascript:void(0)" v-on:click="Delete(item.ID)">删除</a></td>
</tr>
</table>
</div>
</div>
<div class="container" style="text-align:center;" slot="footer">
</div>
<script>
var cateCreater;
var lstCate;
$(document).ready(function () {
lstCate = new Vue({ el: '#lstCate', data: { Data: [] } });
cateCreater = new Vue({
el: '#cateCreater',
data: {
remark: '',
title: ''
}
});
List();
});
function OrderBy(id, up, index) {
if (index == 0)
return;
AdminCategoryOrder(id, up).execute(function () {
List();
});
}
function Delete(id) {
if (confirm('是否要删除分类?')) {
AdminCategoryDel(id).execute(function () {
List();
});
}
}
function List() {
AdminCategoryList().execute(function (r) {
lstCate.Data = r.Data;
});
}
function Add() {
if (!cateCreater.title) {
alert("请输入分类名称!");
return;
}
if (!cateCreater.remark) {
alert("请输入分类描述!");
return;
}
AdminCategoryAdd(cateCreater.title, cateCreater.remark).execute(function (r) {
cateCreater.title = '';
cateCreater.remark = '';
List();
});
}
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<link href="/css/bootstrap.css" rel="stylesheet" />
<link href="/css/bootstrap-theme.css" rel="stylesheet" />
<link href="/css/admin.css" rel="stylesheet" />
<script src="/js/jquery.js"></script>
<script src="/js/ModuleLoader.js"></script>
<script src="/js/bootstrap.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="/js/FastHttpApi.js"></script>
<script src="/js/admin/AdminComment.js"></script>
<script src="/js/marked.js"></script>
<script src="/js/lodash.js"></script>
<title>BeetleX Blog Admin</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-left" slot="header">
</div>
<div class="page-title">
<img src="/images/admin/nav.png" /> <h3>评论</h3>
</div>
<div class="container bs-docs-container">
<div class="row">
<div class="col-md-8" role="main">
<div style="padding:5px;">
<form class="navbar-form navbar-left btn-group-sm" style="display:contents;margin-bottom:4px;" role="search">
<a href="javascript:void(0)" onclick="delComment()" class="btn btn-default">删除</a>
</form>
</div>
<table class="table table-hover" id="lstComments">
<thead>
<tr>
<th style="width:40px;"><input onclick="selectAll(this)" type="checkbox" /></th>
<th>文章</th>
<th>评论人</th>
<th>创建时间</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Data">
<th><input v-bind:id="item.CommentID" type="checkbox" /></th>
<td> <a @mouseenter="$('#viewComment').html(marked(item.Content, { sanitize: true }))" v-bind:href="['/blog/'+item.ID+'.html']">{{item.Title}}</a></td>
<td>{{item.NickName}}</td>
<td>{{item.CreateTime}}</td>
</tr>
</table>
<nav aria-label="Page navigation">
<ul id="pagination" class="pagination"></ul>
</nav>
</div>
<div class="col-md-4" style="padding-top:50px;">
<div id="viewComment">
</div>
</div>
</div>
</div>
<div class="container" style="text-align:center;" slot="footer">
</div>
<script>
var lstComments;
$(document).ready(function () {
lstComments = new Vue({ el: "#lstComments", data: { Data: [] } });
pageChange(0);
});
function delComment() {
var items = getSelectItems();
if (items.length > 0) {
if (confirm('是否要删除评论?')) {
AdminCommentDel(items).execute(function (r) {
pageChange(0);
});
}
}
else {
alert('选择需要删除的评论');
}
}
function pageChange(index) {
AdminCommentList(index).execute(function (r) {
lstComments.Data = r.Data.Items;
pagination(index, r.Data.Pages);
});
}
function selectAll(e) {
var checkedOfAll = $(e).prop("checked");
$("input[type='checkbox']").prop("checked", checkedOfAll);
}
function getSelectItems() {
var items = new Array();
$("input[type='checkbox']").each(function () {
if ($(this).prop("checked") == true && $(this).prop("id"))
items.push($(this).attr('id'));
});
return items;
}
</script>
</body>
</html>
\ No newline at end of file
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
This source diff could not be displayed because it is too large. You can view the blob instead.
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论