COMCMS v0.9 版本发布,带前后端的一个响应式企业站
前言:踏入十二月,人生也即将进入下一个阶段。
最近忙于其他,代码也是偶尔更新。目前算是0.9的版本,就是基本上可以完成一个简单的企业站/博客的功能。
主要特点:前台完整演示:文章、产品、留言。界面响应式:响应PC和手机
预计:1.0版本的话,带有app端(预计只有安卓版本,苹果版本没有证书-_-')演示,也算是可以应用于app、小程序(微信小程序、支付宝、百度小程序)。当然只是预告而已ORZ
github地址:https://github.com/hogenwang/comcms_core
讨论Q群:1600800
本次最重要的是,加上前台的完整前端。一方面,让整个小cms系统更加完整。另外一方面,也是演示了,如何搭配前端view进行开发。还有就是XCode如是使用。
之前有人提到,希望有多一点的二次开发文档。这个我尽量抽时间写写,其实主要还是XCode的用法。
话不多说,先看整体的效果吧:

以下就简单说一下,前台的一些特点和二次开发注意的内容:
1、前台控制器继承:HomeBaseController 主要是:
提供了后台配置,和前后端交互的json基础类JsonTip
所有需要展示网站完整页面的需要加入:
ViewBag.cfg = cfg;
2、ServerController 为数据交互提交方法,可以将所有需要交互的数据,方法都写在本控制器,当然,你也可以写在其他的。
而一般,提交的方法,都使用POST外加:AutoValidateAntiforgeryToken 保证数据提交的安全,最后,统一都返回一个json:
/// <summary>
/// 系统JSON提示实体类
/// </summary>
[Serializable]
public class JsonTip
{
public JsonTip() { }
/// <summary>
/// 成功状态
/// </summary>
public static readonly string SUCCESS = "success";
/// <summary>
/// 失败状态
/// </summary>
public static readonly string ERROR = "error";
/// <summary>
/// 请求返回状态 默认 error(错误);成功:success
/// </summary>
public string Status { get; set; } = ERROR;
/// <summary>
/// 提示信息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 其他信息
/// </summary>
public string Other { get; set; }
/// <summary>
/// Id 可选
/// </summary>
public int Id { get; set; } = ;
/// <summary>
/// 返回URL
/// </summary>
public string ReturnUrl { get; set; } /// <summary>
/// 获取JSON字符串
/// </summary>
/// <param name="json">JsonTip实体类</param>
/// <returns></returns>
public static string GetJsonString(JsonTip json)
{
if (json != null)
return JsonConvert.SerializeObject(json);
else
return string.Empty;
}
}
如演示里面的提交留言:
#region 提交前台底部留言
[HttpPost]
[AutoValidateAntiforgeryToken]
public IActionResult DoPostMessage(string name,string phone,string content)
{
if (string.IsNullOrWhiteSpace(name))
{
tip.Message = "请填写您的姓名!";
return Json(tip);
}
if (!Utils.IsTel(phone))
{
tip.Message = "请填写正确的手机号码!";
return Json(tip);
}
if (string.IsNullOrWhiteSpace(content))
{
tip.Message = "请填写您的留言内容!";
return Json(tip);
} Guestbook entity = new Guestbook()
{
AddTime = DateTime.Now,
IP = Utils.GetIP(),
KId = ,
Nickname = name,
Content = Utils.NoHTML(content),
Tel = phone
};
entity.Insert(); tip.Message = "留言成功,感谢您的留言!";
tip.Status = JsonTip.SUCCESS;
return Json(tip);
}
#endregion
可以看到,涉及到XCode的用法也是非常简单的,new一个对象后,最后调用Insert();就可以插入数据了。值得一提的是,如果插入这个数据后,想获取主键Id的值:entity.Id就可以了。不要用Insert() 返回值。
3、为了方便演示,我大部分获取数据都写在views里面,建议还是写在Controller里面。如首页模板
IList<Link> listLinks = Link.FindAll(Link._.KId == , Link._.Sequence.Asc(), null, , );
//处理bannr广告
var bannerPC = Ads.GetSlideAds();
var bannerMobile = Ads.GetSlideAds();
4、后台文章,可以配置相应的模板,可以根据不同情况配置不同模板。如演示,关于我们、联系我们和新闻中心模板就不一样。
因为编译了模板,所以选择模板使用反射实现:
//获取模板 模板规则,以Index_开头的,为栏目列表,以Detial_开头的为文章详情
List<string> listTpls = new List<string>();
var asms = AppDomain.CurrentDomain.GetAssemblies();
foreach (var asmItem in asms)
{
var types = asmItem.GetTypes().Where(e => e.Name.StartsWith("Views_Article")).ToList();
if (types.Count == ) continue;
foreach (var type in types)
{
string viewName = type.Name.Replace("Views_Article_", "") + ".cshtml";
listTpls.Add(viewName);
}
}
ViewBag.ListTpl = listTpls;
注意看注释部分内容哦。
5、列表分页的,这里我使用了手动计算分页的形式:
IList<Article> list = new List<Article>();
int numPerPage, currentPage, startRowIndex;
numPerPage = model.PageSize;
if (page > 0)
currentPage = page;
else
currentPage = 1; startRowIndex = (currentPage - 1) * numPerPage; var ex = Article._.IsHide != 1 & Article._.IsDel != 1; //如果显示下级栏目文章
if (model.IsShowSubDetail == 1)
{
//获取下级所有栏目
List<int> allsubkids = new List<int>();
allsubkids.Add(model.Id); IList<ArticleCategory> allkind = ArticleCategory.FindAllSubKinds(model.Id);
if (allkind != null && allkind.Count > 0)
{
foreach (var s in allkind)
{
allsubkids.Add(s.Id);
}
}
ex &= Article._.KId.In(allsubkids);
}
else
ex &= Article._.KId == model.Id;
long totalCount = Article.FindCount(ex, Article._.Sequence.Asc().And(Article._.Id.Desc()), null, startRowIndex, numPerPage);
int pageCount = (int)totalCount / numPerPage;//总页数
if (totalCount % numPerPage > 0)
{
pageCount += 1;
}
list = Article.FindAll(ex, Article._.Sequence.Asc().And(Article._.Id.Desc()), null, startRowIndex, numPerPage);
ViewBag.list = list;//列表
//分页信息
ViewBag.totalCount = totalCount;
ViewBag.pageCount = pageCount;
ViewBag.page = page;
ViewBag.pagesize = numPerPage;
而views里面调用分页代码:
@Html.Raw(Pages.GetPageStr(ViewBag.pagesize, (int)ViewBag.totalCount, ViewBag.page, $"/Article/Index/{Model.Id}" + "?page={0}", , , ""))
6、后台权限使用方法
由于上面提到统一执行post返回一个标准的json。所以后台权限,目前设计验证两种,一种是普通的验证,错误返回提示页面,另外一种是提交验证,错误返回一个json。也就是POST提交的时候。
用法也是很简单,给方法名加上:
[MyAuthorize( "viewlist", "articlecategory")]
[MyAuthorize( "add", "articlecategory", "JSON")]
其中第一个参数为事件权限,在后台:后台权限》事件权限管理管理

第二个参数为页面的key。这个在后台栏目权限管理中设置:

这样,在二次开发中,就可以很快速的添加功能和权限控制了。
其他方面暂不一一列出。如果有什么不明白的,可以给我留言。
也欢迎大家点个star。
最后再次提醒,讨论Q群:1600800
COMCMS v0.9 版本发布,带前后端的一个响应式企业站的更多相关文章
- Jeecg-Boot 2.0.1 版本发布,前后端分离快速开发平台
Jeecg-Boot项目简介 Jeecg-boot 是一款基于代码生成器的快速开发平台! 采用前后端分离技术:SpringBoot,Mybatis,Shiro,JWT,Vue & Ant De ...
- 由浅入深,带你用JavaScript实现响应式原理(Vue2、Vue3响应式原理)
由浅入深,带你用JavaScript实现响应式原理 前言 为什么前端框架Vue能够做到响应式?当依赖数据发生变化时,会对页面进行自动更新,其原理还是在于对响应式数据的获取和设置进行了监听,一旦监听到数 ...
- django开发最完美手机购物商城APP带前后端源码
后端和数据接口,全采用django开发 从0到大神的进阶之路 一句话,放弃单文件引用vue.js练手的学习方式 马上从vue-cli4练手,要不然,学几年,你也不懂组件式开发,不懂VUEX,不懂路由, ...
- ajax向Django前后端提交请求和CSRF跨站请求伪造
1.ajax登录示例 urls.py from django.conf.urls import url from django.contrib import admin from app01 impo ...
- (转)也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
原文链接:http://ued.taobao.org/blog/2014/04/full-stack-development-with-nodejs/ 随着不同终端(pad/mobile/pc)的兴起 ...
- 也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的NodeJS,试图 ...
- vue菜鸟从业记:公司项目里如何进行前后端接口联调
最近我的朋友王小闰进入一家新的公司,正好公司项目采用的是前后端分离架构,技术栈是王小闰非常熟悉的vue全家桶,后端用的是Java语言. 在前后端开发人员碰面之后,协商确定好了前端需要的数据接口(扯那么 ...
- 基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离) 前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们 ...
- SSM框架中的前后端分离
认识前后端分离 在传统的web应用开发中,大多数的程序员会将浏览器作为前后端的分界线.将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端. ...
随机推荐
- 钉钉扫码登录web网站
钉钉扫码登录网站 前言 由于本公司前后台分离,这里主要讲述后台的实现逻辑与过程,前端相关的一略而过.前端我们采用的是把二维码内嵌到我们的网页中. 流程如下: 1.登录钉钉后台创建一个企业应用 2.根 ...
- oracle测试环境表空间清理
测试场景下,使用的oralce遇到表空间的占用超大,可以采用如下的方式进行空间的清理 首先使用sqlplus连接数据库sqlplus sys/password@orcl as sysdba 之类进行数 ...
- [20190101]块内重整.txt
[20190101]块内重整.txt --//我不知道用什么术语表达这样的情况,我仅仅一次开会对方这么讲,我现在也照用这个术语.--//当dml插入数据到数据块时,预留一定的空间(pctfree的百分 ...
- EXT.NET初学
1.ext:Hidden 必须在body里面有ext:ResourceManager的情况下才能运行 2.ext:Store里面不能有文字
- PostgreSQL分页
转自 https://blog.csdn.net/tomcat_2014/article/details/49947711 如果用过mysql,那么对 select * from xxx limit ...
- ASP.Net上传文件
在做Web项目时,上传文件是经常会碰到的需求.ASP.Net的WebForm开发模式中,封装了FileUpload控件,可以方便的进行文件上传操作.但有时,你可能不希望使用ASP.Net中的服务器控件 ...
- 什么是JDK?什么是JRE?JDK与JRE的区别和用途
一.编程环境与运行环境 JDK(Java Development Kit)称为Java开发包或Java开发工具.是一个编写Java的Applet小程序和应用程序的程序开发环境.JDK是整个Java的核 ...
- win10显示许可证即将过期,但在激活界面显示的仍是已激活问题解决
win10开机显示"许可证即将过期"怎么办? 很多win10用户在开机的时候遇见了"许可证即将过期"请转到设置种激活windows的问题,但是查询自己的win1 ...
- 我为什么要写 blog?
从事软件测试工作10余年,也没在网上留下些什么.最近忙着找工作,年龄上又遇到了瓶颈,发现好多工作岗位需要技术博客,正好趁这个机会,梳理一下自己的知识点,记录下来和大家一起学习探讨,共同进步.欢迎加我微 ...
- 如何指定一个计划和目标——6W
作为一名IT人员,需要自己指定一个计划和目标,来保证完成进度和高效的完成任务. 参考管理学如何制作计划和目标的,套用过来,也是同样适用的.来先看看管理学的相关知识吧. 计划的概念:计划是为实现组织目标 ...