该版本新增了发表评论功能,在install/create_table.zl脚本中,新增了评论相关的表结构,游客可以在前台访问文章页面时发表评论。评论发表成功后,需要进行审核,在后台新增了评论列表,用于对评论进行审核...
...................................................... // 创建评论表 if(mysqlQuery(con, "DROP TABLE IF EXISTS comment")) finish_with_error(con); endif if(mysqlQuery(con, "CREATE TABLE comment( id int NOT NULL AUTO_INCREMENT, nickname varchar(80) NOT NULL DEFAULT '' COMMENT '评论人昵称', aid int NOT NULL DEFAULT '0' COMMENT '评论所属文章ID', pid int NOT NULL DEFAULT '0' COMMENT '回复所属的评论ID', content varchar(3000) NOT NULL DEFAULT '' COMMENT '评论内容', status tinyint NOT NULL DEFAULT '0' COMMENT '评论状态:0表示待审核,1表示审核通过,2表示审核不通过', reject_reason varchar(100) NOT NULL DEFAULT '' COMMENT '拒绝理由(不通过理由)', `created_at` timestamp NULL DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET utf8 COLLATE utf8_general_ci COMMENT='评论表'")) finish_with_error(con); endif ...................................................... |
inc 'common.zl'; inc 'helper.zl'; querys = rqtGetQuery(); action = querys['act'] ? querys['act'] : 'list'; if(action == 'list') Comment.list(); elif(action == 'pass') Comment.pass(); elif(action == 'reject') Comment.reject(); else print 'invalid act'; endif class Comment // 评论列表 fun list() global menus, querys; data['title'] = '评论列表:'; setCurMenu(menus, 'comment.zl'); data['menus'] = menus; data['csses', 0] = 'comment_list.css'; db = Comment.initDB(); where = " where 1 "; stitle = bltStr(&querys['stitle']); if(stitle) // 根据标题搜索 where += ' and a.title like "%' + Mysql.Escape(db, stitle) + '%"'; data['stitle'] = stitle; endif snickname = bltStr(&querys['snickname']); if(snickname) // 根据昵称搜索 where += ' and c.nickname like "%' + Mysql.Escape(db, snickname) + '%"'; data['snickname'] = snickname; endif if(bltIsNone(&querys['search_status'])) data['search_status'] = -1; else search_status = bltInt(querys['search_status']); if(search_status >= 0) // 根据状态搜索 where += ' and c.status = ' + search_status; endif data['search_status'] = search_status; endif tmp = Mysql.fetchOne(db, "select count(1) as cnt from comment c inner join article a on a.id=c.aid " + where); 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['comments'] = Mysql.fetchAll(db, "select c.id, c.nickname, c.content, c.status, c.reject_reason, c.created_at, c.aid, a.title from comment c " + " inner join article a on a.id=c.aid " + where + " order by c.id desc limit " + page['offset'] + "," + page['limit']); for(i=0;bltIterArray(data['comments'],&i,&v);) switch(v['status']) case 0: v['status_text'] = '<span class="label label-default">待审核</span>'; break; case 1: v['status_text'] = '<span class="label label-success">审核通过</span>'; break; case 2: v['status_text'] = '<span class="label label-danger">审核不通过</span>'; break; default: v['status_text'] = '<span class="label label-warning">未知状态</span>'; endswitch bltHtmlEscape(&v['content'], TRUE); bltStrReplace(&v['content'], '\n', '<br/>', TRUE); endfor print bltMustacheFileRender("tpl/comment_list.tpl", data); endfun // 初始化数据库连接 fun initDB() global config; db = bltArray(); Mysql.init(db, config, "tpl/error.tpl"); return db; endfun // 审核通过 fun pass() global querys; db = Comment.initDB(); id = querys['id'] ? bltInt(querys['id']) : 0; if(id <= 0) ajax_return('无效的评论id'); endif Mysql.Exec(db, "UPDATE comment SET status=1,reject_reason='' WHERE id=" + id); ajax_return(); endfun // 拒绝,审核不通过 fun reject() posts = rqtGetBodyAsArray(); db = Comment.initDB(); id = posts['id'] ? bltInt(posts['id']) : 0; if(id <= 0) ajax_return('无效的评论id'); endif data['reject_reason'] = bltStr(&posts['reject_reason']); data['status'] = 2; Mysql.Update(db, 'comment', data, " id=" + id); ajax_return(); endfun endclass |
use builtin, request, mysql, session; def TRUE 1; def FALSE 0; inc 'config.zl'; inc 'mysql.zl'; querys = rqtGetQuery(); action = querys['act'] ? querys['act'] : 'list'; if(action == 'list') Comment.list(); elif(action == 'add') Comment.add(); else print 'invalid act'; endif class Comment // 显示评论列表 fun list() global querys; page = bltInt(querys['page']); if(page <= 0) page = 1; endif per_page = 10; offset = (page - 1) * per_page; aid = bltInt(querys['aid']); db = Comment.initDB(); data['comments'] = Mysql.fetchAll(db, "select id,nickname,content,created_at from comment where status=1 and aid="+aid+" order by id desc limit " + offset + ', ' + per_page); for(i=0;bltIterArray(data['comments'],&i,&v);) bltHtmlEscape(&v['nickname'], TRUE); bltHtmlEscape(&v['content'], TRUE); endfor data['per_page'] = per_page; data['msg'] = 'success'; rqtSetResponseHeader("Content-Type: application/json"); print bltJsonEncode(data); endfun // 添加评论 fun add() global sess_id; cookies = rqtGetCookie(); sess_id = cookies['SESSION']; sess_data = sessGetData(sess_id); posts = rqtGetBodyAsArray(); bltStr(&posts['captcha'], TRUE); bltStr(&sess_data['captcha'], TRUE); if(sess_data['captcha'] && sess_data['captcha'] == posts['captcha']) insert_data['nickname'] = bltStr(&posts['nickname']); if(insert_data['nickname'] == '') Comment.error('昵称不能为空!'); endif insert_data['content'] = bltStr(&posts['content']); if(insert_data['content'] == '') Comment.error('内容不能为空'); endif if(bltUtfStrLen(insert_data['content']) < 5) Comment.error('内容太短'); endif if(bltUtfStrLen(insert_data['content']) > 500) Comment.error('内容太长'); endif db = Comment.initDB(); insert_data['aid'] = bltInt(posts['aid']); article_data = Mysql.fetchOne(db, "select id from article where id='"+insert_data['aid']+"'"); if(!bltCount(article_data)) Comment.error('无效的文章ID'); endif insert_data['created_at'] = bltDate('%Y-%m-%d %H:%M:%S'); Mysql.Insert(db, 'comment', insert_data); data['msg'] = 'success'; rqtSetResponseHeader("Content-Type: application/json"); print bltJsonEncode(data); else Comment.error('无效的图形验证码'); endif endfun // 初始化数据库连接 fun initDB() global config; db = bltArray(); Mysql.init(db, config, "tpl/error.tpl"); return db; endfun fun error(errmsg) global sess_id; data['msg'] = 'failed'; data['errmsg'] = errmsg; rqtSetResponseHeader("Content-Type: application/json"); print bltJsonEncode(data); sessDelete(sess_id); bltExit(); endfun endclass |
use builtin, magick, request, session; def TRUE 1; def FALSE 0; wand = magickNewWand(); p_wand = magickNewPixelWand(); magickPixelSetColor(p_wand, "white"); magickNewImage(wand, 85, 30, p_wand); d_wand = magickNewDrawingWand(); // magickDrawSetFont(d_wand, "Helvetica Regular"); magickDrawSetFont(d_wand, "assets/font/xerox_serif_narrow.ttf"); magickDrawSetFontSize(d_wand, 24); magickDrawSetTextAntialias(d_wand, TRUE); // magickDrawSetTextAntialias(d_wand, FALSE); captcha = bltRandomStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 6); magickDrawAnnotation(d_wand, 4, 20, captcha); magickDrawImage(wand, d_wand); magickSwirlImage(wand, 20); magickClearDrawingWand(d_wand); magickDrawLine(d_wand, bltRand( 0, 70 ), bltRand( 0, 30 ), bltRand( 0, 70 ), bltRand( 0, 30 )); magickDrawLine(d_wand, bltRand( 0, 70 ), bltRand( 0, 30 ), bltRand( 0, 70 ), bltRand( 0, 30 )); magickDrawLine(d_wand, bltRand( 0, 70 ), bltRand( 0, 30 ), bltRand( 0, 70 ), bltRand( 0, 30 )); magickDrawLine(d_wand, bltRand( 0, 70 ), bltRand( 0, 30 ), bltRand( 0, 70 ), bltRand( 0, 30 )); magickDrawLine(d_wand, bltRand( 0, 70 ), bltRand( 0, 30 ), bltRand( 0, 70 ), bltRand( 0, 30 )); magickDrawImage(wand, d_wand); magickSetImageFormat(wand, "jpg"); output = magickGetImageBlob(wand, &length); rqtSetResponseHeader("Content-Type: image/" + magickGetImageFormat(wand)); cookies = rqtGetCookie(); sess_id = cookies['SESSION']; if(!sess_id) sess_id = sessMakeId(); rqtSetResponseHeader("Set-Cookie: SESSION="+sess_id+"; path=/"); else data = sessGetData(sess_id); endif data['captcha'] = captcha; sessSetData(sess_id, data); bltOutputBlob(output, length); |