当前版本添加了公告功能,可以在首页显示一些站点公告信息。在install/create_table.zl脚本中,增加了与公告相关的表结构的创建语句,要正常使用公告功能,需要先执行该脚本,在数据库中创建好notice公告表结构。

    页面导航:

项目下载地址:

    zenglBlog源代码的相关地址:https://github.com/zenglong/zenglBlog  最新版本对应的tag标签为:v0.7.0

zenglBlog v0.7.0:

    当前版本添加了公告功能,可以在首页显示一些站点公告信息。在install/create_table.zl脚本中,增加了与公告相关的表结构的创建语句:

// 创建公告表
if(mysqlQuery(con, "CREATE TABLE notice(
	id int NOT NULL AUTO_INCREMENT, 
	title varchar(255) NOT NULL DEFAULT '' COMMENT '公告标题',
	description varchar(2048) NOT NULL DEFAULT '' COMMENT '公告详细描述',
	`created_at` timestamp NULL DEFAULT NULL COMMENT '创建时间',
	`updated_at` timestamp NULL DEFAULT NULL COMMENT '更新时间',
	PRIMARY KEY (id)
	) ENGINE=MyISAM DEFAULT CHARSET utf8 COLLATE utf8_general_ci COMMENT='公告表'"))
	finish_with_error(con);
endif

    要正常使用公告功能,需要先执行该脚本,在数据库中创建好notice公告表结构。如果之前执行过此脚本的话,需要先将install/install.lock安装锁文件删除掉,然后将其他的表结构创建语句,以及插入管理员用户信息的语句给注释掉,接着就可以正常执行该脚本来创建公告表结构了。当前版本移除了create_table.zl中的"DROP TABLE IF EXISTS ..."语句,因为这条语句容易误删除之前安装过的表结构。

    在后台添加了公告列表,用于对公告进行管理:

图1:后台公告列表

    公告列表右上角有添加公告按钮,列表中有编辑和删除按钮,可以方便的进行公告的添加、修改和删除操作:

图2:公告的添加、修改及删除按钮

    在后台添加了公告后,就可以在前台首页看到相关的公告信息了(首页公告按照更新时间排序):

图3:首页展示的公告信息

    如果使用index.zl动态脚本访问首页的话,马上就能看到类似上面所示的公告信息,但是如果之前生成过index.html首页静态文件,那么要看到index.html中包含的公告信息的话,就需要在后台执行生成静态页面的操作。

    和后台公告列表相关的脚本为admin/notice.zl :

inc 'common.zl';
inc 'helper.zl';

querys = rqtGetQuery();
action = querys['act'] ? querys['act'] : 'list';
if(action == 'list')
	Notice.list();
elif(action == 'add')
	Notice.add();
elif(action == 'edit')
	Notice.edit();
elif(action == 'delete')
	Notice.delete();
else
	print 'invalid act';
endif

class Notice
	// 显示公告列表
	fun list()
		global menus, querys;
		data['title'] = '公告列表:';
		setCurMenu(menus, 'notice.zl');
		data['menus'] = menus;
		db = Notice.initDB();
		tmp = Mysql.fetchOne(db, "select count(1) as cnt from notice ");
		total = bltInt(tmp['cnt']);
		page = get_page(10, total, 10);
		for(i=page['start']; i <= page['end'];i++)
			cur = (page['curpage'] == i) ? ' class="active"' : '';
			pages[] = '<li'+cur+'><a href="'+page['link']+'page='+i+'">'+i+'</a></li>';
		endfor
		data['page'] = page;
		data['pages'] = pages;
		data['notices'] = Mysql.fetchAll(db, "select * from notice order by id desc limit " + page['offset'] + "," + page['limit']);
		print bltMustacheFileRender("tpl/notice_list.tpl", data);
	endfun

	// 初始化数据库连接
	fun initDB()
		global config;
		db = bltArray();
		Mysql.init(db, config, "tpl/error.tpl");
		return db;
	endfun

	// 显示添加或编辑公告的页面
	fun showAdd(db, data, isadd = TRUE)
		global menus;
		setCurMenu(menus, 'notice.zl');
		csses = bltArray('notice_add.css');
		data['csses'] = csses;
		data['menus'] = menus;
		data['title'] = isadd ? '添加公告' : '编辑公告';
		data['act'] = isadd ? 'add' : 'edit';
		print bltMustacheFileRender("tpl/notice_add.tpl",data);
	endfun

	// 校验数据
	fun validate(db, posts, isadd = TRUE)
		bltStr(&posts['title'], TRUE);
		bltStr(&posts['description'], TRUE);
		if(!posts['title'])
			data['err_msg'] = '公告标题不能为空';
		elif(!posts['description'])
			data['err_msg'] = '公告详情不能为空';
		elif(!isadd && !posts['id'])
			data['err_msg'] = '无效的公告ID';
		endif
		if(data['err_msg'])
			data['posts'] = posts;
			if(posts['id'])
				data['id'] = posts['id'];
			endif
			Notice.showAdd(db, data, isadd);
			bltExit();
		endif
	endfun

	// 添加公告
	fun add()
		posts = rqtGetBodyAsArray();
		db = Notice.initDB();
		if(posts['submit'])
			Notice.validate(db, posts);
			bltUnset(&posts['submit']);
			posts['created_at'] = bltDate('%Y-%m-%d %H:%M:%S');
			posts['updated_at'] = posts['created_at'];
			Mysql.Insert(db, 'notice', posts);
			data['success_msg'] = '添加公告成功';
		endif
		Notice.showAdd(db, data);
	endfun

	// 编辑公告
	fun edit()
		global querys;
		posts = rqtGetBodyAsArray();
		db = Notice.initDB();
		if(posts['submit'])
			id = bltInt(posts['id']);
			Notice.validate(db, posts, FALSE);
			bltUnset(&posts['submit']);
			posts['updated_at'] = bltDate('%Y-%m-%d %H:%M:%S');
			Mysql.Update(db, 'notice', posts, 'id=' + id);
			data['success_msg'] = '编辑公告成功';
		else
			id = bltInt(querys['id']);
		endif
		data['posts'] = Mysql.fetchOne(db, "select * from notice where id='"+id+"'");
		if(!bltCount(data['posts']))
			data['err_msg'] = '无效的公告ID';
			id = 0;
		endif
		data['id'] = id;
		Notice.showAdd(db, data, FALSE);
	endfun

	// 删除公告
	fun delete()
		global querys;
		db = Notice.initDB();
		id = querys['id'] ? bltInt(querys['id']) : 0;
		if(id <= 0) 
			ajax_return('无效的公告id'); 
		endif
		Mysql.Exec(db, "DELETE FROM notice WHERE id="+id);
		ajax_return();
	endfun
endclass

    这段代码的执行逻辑和文章操作的执行逻辑是差不多的。公告列表使用的模板文件为:admin/tpl/notice_list.tpl,添加和编辑公告所使用的模板文件为:admin/tpl/notice_add.tpl。上面脚本中模板路径使用的是相对于当前脚本的路径,因此,就省略了admin目录。

    前台首页的主脚本:index.class.zl也进行了调整,用于显示公告信息:

class Index
	// 首页内容
	fun index(static = FALSE)
		global querys, categories, db, config;
		data['head_title'] = data['site_name'] = config['site_name'];
		data['description'] = config['site_desc'];
		data['csses'] = bltArray('index.css?v=20181003');
		data['head_js'] = bltArray('jquery.yestop.js');
		data['thumb_articles'] = Mysql.fetchAll(db, "select id,title,thumbnail,created_at,DATE_FORMAT(created_at, '%Y%m') as format_created from article " + 
							" where thumbnail != '' order by id desc limit 0,4");
		data['latest_articles'] = Mysql.fetchAll(db, "select id,title,thumbnail,description,created_at,DATE_FORMAT(created_at, '%Y%m') as format_created from article " + 
							" order by id desc limit 0,5");
		data['latest_articles_cnt'] = bltCount(data['latest_articles']);
		data['notices'] = Mysql.fetchAll(db, "select id,title,description,created_at from notice order by updated_at desc");
		data['notices_cnt'] = bltCount(data['notices']);
		data['categories'] = categories;
		data['static'] = static;
		for(i=0;i < 10 && bltIterArray(categories,&i,&v);)
			item = bltArray();
			item['cate_id'] = v['id'];
			item['cate_name'] = v['name'];
			item['articles'] = Mysql.fetchAll(db, "select id,title,description,thumbnail,created_at,DATE_FORMAT(created_at, '%Y%m') as format_created from article where cid = "+v['id']+" order by id desc limit 0,5");
			items[] = item;
		endfor
		data['items'] = items;
		content = bltMustacheFileRender("/tpl/index.tpl", data);
		if(!static)
			print content;
		else
			return content;
		endif
	endfun
endclass

    在上面这个首页内容脚本中,data['notices']中存储了从数据库中查询出来的公告信息,而data['notices_cnt']则保存了公告的数量,当公告数量为0时,首页就不会显示和公告相关的界面元素。此外,当前版本的首页中还增加了最近更新数据,这些数据就存储在上面脚本中的data['latest_articles']数组成员中。

    前台首页和列表页都增加和内容页一样的返回顶部按钮,当数据很多时,以及在手机上浏览信息时,可以方便的返回顶部。

    内容页图片通过js脚本实现了自适应,在手机上可以自动调整图片尺寸,让图片能够在不同尺寸的设备上都能完整的显示出来:

图4:内容页图片自适应

    内容页调整的js代码位于tpl/article_show.tpl模板文件中:

<script type="text/javascript">
	$(document).ready(function () { 
		$.fn.yestop({yes_image: '/assets/image/yestop.png'});
		$(".row .content img").removeAttr("style").addClass("img-responsive center-block");
	});
	...................................................
</script>

    通过给img标签加入img-responsive样式让图片实现自适应。

    最后,当前版本还调整了favicon.ico图标,之前的图标占了几十K的大小,现在的图标是个ZL标志,只有几K大小,更适合当前的网站样式:

图5:favicon.ico图标调整

结束语:

    有人这样说过:在人的身体里有两只狼,在不停的竞争,搏杀,一只代表仇恨,嫉妒和恐惧,另一只代表美好,善良和博爱。

—— 《天坑鹰猎》

上下篇

下一篇: zenglBlog v0.8.0 增加保存草稿,友情链接,内容页上下篇,手机端返回顶部图片

上一篇: zenglBlog v0.6.0-v0.6.2 生成静态页面

相关文章

zenglBlog v0.1.0 登录和后台界面

zenglBlog v0.6.0-v0.6.2 生成静态页面

zenglBlog v0.8.0 增加保存草稿,友情链接,内容页上下篇,手机端返回顶部图片

zenglBlog v0.5.0 发表评论,图形验证码

zenglBlog v0.4.0 前台首页,文章列表,文章内容页

zenglBlog v0.3.0 文章管理,图片上传,生成缩略图