虚拟币论坛
![BBS论坛(四)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F10002_3ff458040f.jpg&w=3840&q=75)
BBS论坛(四)
4.1.cms登录页面csrf保护(1)Perfect_bbs.py代码语言:javascript复制from flask_wtf import CSRFProtect
CSRFProtect(app)添加csrf保护后,现在再去登录 (2)cms/cms_login.html添加csrf保护代码语言:javascript复制<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">4.2.cms后台修改密码界面布局完成(1)cms.views.py代码语言:javascript复制class ResetPwdView(views.MethodView):
decorators = [login_required]
def get(self):
return render_template('cms/cms_resetpwd.html')
def post(self):
pass
bp.add_url_rule('/resetpwd/',view_func=ResetPwdView.as_view('resetpwd'))(2)cms/cms_base.html代码语言:javascript复制 <li><a href="{{ url_for('cms.resetpwd') }}">修改密码</a></li>(3)cms/cms_resetpwd.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
修改密码
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block head %}
<style>
.form-container{
width: 300px;
}
</style>
{% endblock %}
{% block main_content %}
<form method="post">
<div class="form-container">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">旧密码</span>
<input type="password" class="form-control" name="oldpwd" placeholder="请输入旧密码">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">新密码</span>
<input type="password" class="form-control" name="newpwd" placeholder="请输入新密码">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">确认新密码</span>
<input type="password" class="form-control" name="newpwd2" placeholder="请确认新密码">
</div>
</div>
<div class="form-group">
<button class="btn btn-primary">立即保存</button>
</div>
</div>
</form>
{% endblock %}效果:
![BBS论坛(十五)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F10001_d0e03790f4.png&w=3840&q=75)
BBS论坛(十五)
15.1.登录界面完成(1)front/signbase.html代码语言:javascript复制{% from 'common/_macros.html' import static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{% block title %}{% endblock %}</title>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="{{ static('common/zlajax.js') }}"></script>
<link rel="stylesheet" href="{{ static("common/sweetalert/sweetalert.css") }}">
<script src="{{ static("common/sweetalert/sweetalert.min.js") }}"></script>
<script src="{{ static("common/sweetalert/zlalert.js") }}"></script>
<script src="{{ static('common/zlparam.js') }}"></script>
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
<link rel="stylesheet" href="{{ static('front/css/front_signbase.css') }}">
{% block head %}
{% endblock %}
</head>
<body>
<div class="outer-box">
<div class="logo-box">
<a href="/">
<img src="{{ static('common/images/logo.jpg') }}" alt="">
</a>
</div>
<h2 class="page-title">
{% block h2_block %}
{% endblock %}
</h2>
<div class="sign-box">
{% block signbox %}
{% endblock %}
</div>
<span style="display: none" id="return-to-span">{{ return_to }}</span>
</div>
</body>
</html>(2)front/signup代码语言:javascript复制{% extends 'front/signbase.html' %}
{% from 'common/_macros.html' import static %}
{% block title %}
仙剑论坛注册
{% endblock %}
{% block head %}
<script src="{{ static('front/js/front_signup.js') }}"></script>
{% endblock %}
{% block h2_block %}
仙剑论坛注册
{% endblock %}
{% block signbox %}
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="telephone" placeholder="手机号码">
<span class="input-group-btn">
<button id="sms-captcha-btn" class="btn btn-default">发送验证码</button>
</span>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control" name="sms_captcha" placeholder="短信验证码">
</div>
<div class="form-group">
<input type="text" class="form-control" name="username" placeholder="用户名">
</div>
<div class="form-group">
<input type="password" class="form-control" name="password1" placeholder="密码">
</div>
<div class="form-group">
<input type="password" class="form-control" name="password2" placeholder="确认密码">
</div>
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="graph_captcha" placeholder="图形验证码">
<span class="input-group-addon captcha-addon">
<img id="captcha-img" class="captcha-img" src="{{ url_for('common.graph_captcha') }}" alt="">
</span>
</div>
</div>
<div class="form-group">
<button id="submit-btn" class="btn btn-warning btn-block">立即注册</button>
</div>
{% endblock %}(3)front/css/front_signbase.css把之前signup中的css放到公共的地方,登录页面也需要代码语言:javascript复制body {
background: #f3f3f3;
}
.outer-box {
width: 854px;
background: #fff;
margin: 0 auto;
overflow: hidden;
}
.logo-box {
text-align: center;
padding-top: 40px;
}
.logo-box img {
width: 60px;
height: 60px;
}
.page-title {
text-align: center;
}
.sign-box {
width: 300px;
margin: 0 auto;
padding-top: 50px;
}
.captcha-addon {
padding: 0;
overflow: hidden;
}
.captcha-img {
width: 94px;
height: 32px;
cursor: pointer;
}(4)front/signin.html代码语言:javascript复制{% extends 'front/signbase.html' %}
{% from 'common/_macros.html' import static %}
{% block title %}
仙剑论坛登录
{% endblock %}
{% block head %}
<style>
.resetpwd-link{
float:right;
}
</style>
{% endblock %}
{% block h2_block %}
仙剑论坛账号登录
{% endblock %}
{% block signbox %}
<div class="form-group">
<input class="form-control" type="text" name="telephone" placeholder="手机号" >
</div>
<div class="form-group">
<input class="form-control" type="password" name="password" placeholder="密码" >
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="remember" value="1">记住我
</label>
</div>
<div class="form-group">
<button id="submit-btn" class="btn btn-warning btn-block">立即登录</button>
</div>
<div class="form-group">
<a href="{{ url_for('front.signup') }}" class="signup-link">没有账号?立即注册</a>
<a href="#" class="resetpwd-link">忘记密码?</a>
</div>
{% endblock %}
![BBS论坛(三)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F10001_cbeb5197c3.jpg&w=3840&q=75)
BBS论坛(三)
3.1.cms用户名渲染和注销功能实现显示登录的用户名(1)app/cms/hooks.py代码语言:javascript复制from .views import bp
import config
from flask import session,g
from .models import CMSUser
@bp.before_request
def before_request():
if config.CMS_USER_ID in session:
user_id = session.get(config.CMS_USER_ID)
user = CMSUser.query.get(user_id)
if user:
g.cms_user = user(2)app/cms/init.py要导入一下才可以,否则不会执行hooks.py里面的代码代码语言:javascript复制import apps.cms.hooks(3)cms/cms_index.html代码语言:javascript复制<li><a href="#">{{ g.cms_user.username }}<span>[超级管理员]</span></a></li>注销功能cms/views.py代码语言:javascript复制@bp.route('/logout/')
@login_required
def logout():
del session[config.CMS_USER_ID]
return redirect(url_for('cms.login'))cms/cms_index.html代码语言:javascript复制 <li><a href="{{ url_for('cms.logout') }}">注销</a></li>3.2.cms模板抽离和个人信息页面完成(1)cms/cms_base.html代码语言:javascript复制{% from "common/_macros.html" import static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="{{ static('cms/css/base.css') }}">
<script src="{{ static('cms/js/base.js')}}"></script>
{% block head %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<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" href="#">Zhang_derek论坛管理后台</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">{{ g.cms_user.username }}<span>[超级管理员]</span></a></li>
<li><a href="{{ url_for('cms.logout') }}">注销</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="查找...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav-sidebar">
<li class="unfold"><a href="{{ url_for('cms.index') }}">首页</a></li>
<li class="profile-li">
<a href="#">个人中心<span></span></a>
<ul class="subnav">
<li><a href="{{ url_for('cms.profile') }}">个人信息</a></li>
<li><a href="#">修改密码</a></li>
<li><a href="#">修改邮箱</a></li>
</ul>
</li>
<li class="nav-group post-manage"><a href="#">帖子管理</a></li>
<li class="comments-manage"><a href="#">评论管理</a></li>
<li class="board-manage"><a href="#">板块管理</a></li>
<li class="nav-group user-manage"><a href="#">用户管理</a></li>
<li class="nav-group cmsuser-manage"><a href="#">CMS用户管理</a></li>
<li class="cmsrole-manage"><a href="#">CMS组管理</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1>{% block page_title %}{% endblock %}</h1>
<div class="main_content">
{% block main_content %}{% endblock %}
</div>
</div>
</div>
</div>
</body>
</html>(2)cms/cms_index.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
Zhang_derek论坛管理后台
{% endblock %}
{% block page_title %}
我的论坛
{% endblock %}(3)cms/views.py代码语言:javascript复制@bp.route('/profile/')
@login_required
def profile():
return render_template('cms/cms_profile.html')(4)cms/cms_profile.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
个人信息
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
{% set user=g.cms_user %}
<table class="table table-bordered">
<tbody>
<tr>
<td>用户名:</td>
<td>{{ user.username }}</td>
</tr>
<tr>
<td>邮箱:</td>
<td>{{ user.email }}</td>
</tr>
<tr>
<td>角色:</td>
<td>xxxxxxx</td>
</tr>
<tr>
<td>权限:</td>
<td>xxxxxx</td>
</tr>
<tr>
<td>加入时间:</td>
<td>{{ user.join_time }}</td>
</tr>
</tbody>
</table>
{% endblock %}效果:
![BBS论坛(九)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F10_0a3ee04561.jpg&w=3840&q=75)
BBS论坛(九)
9.1.权限和角色模型定义(1)cms/models代码语言:javascript复制class CMSPermission(object):
ALL_PERMISSION = 0b11111111
# 1.访问者的权限
VISITOR = 0b00000001
# 2.管理帖子的权限
POSTER = 0b00000010
# 3.管理评论的权限
COMMENTER = 0b00000100
# 4.管理板块的权限
BOARDER = 0b00001000
# 5.管理前台用户的权限
FRONTUSER = 0b00010000
# 6.管理后台用户的权限
CMSUSER = 0b00100000
# 7.管理后台管理员的权限
ADMINER = 0b01000000
cms_role_user = db.Table(
'cms_role_user',
db.Column('cms_role_id',db.Integer,db.ForeignKey('cms_role.id'),primary_key=True),
db.Column('cms_user_id',db.Integer,db.ForeignKey('cms_user.id'),primary_key=True)
)
class CMSRole(db.Model):
__tablename__ = 'cms_role'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(50), nullable=False)
desc = db.Column(db.String(200),nullable=True)
create_time = db.Column(db.DateTime,default=datetime.now)
permissions = db.Column(db.Integer,default=CMSPermission.VISITOR)
users = db.relationship('CMSUser',secondary=cms_role_user,backref='roles')生成到数据库代码语言:javascript复制python manage.py db migrate
python manage.py db upgrade(2)manage.py代码语言:javascript复制CMSRole = cms_models.CMSRole
CMSPermission = cms_models.CMSPermission
@manager.command
def create_role():
# 1.访问者(可以修改个人信息)
visitor = CMSRole(name='访问者',desc='只能访问数据,不能修改')
visitor.permissions = CMSPermission.VISITOR
# 2.运营人员(修改个人信息,管理帖子,管理评论,管理前台用户)
operator = CMSRole(name='运营',desc='管理帖子,管理评论,管理前台用户,')
operator.permissions = CMSPermission.VISITOR|CMSPermission.POSTER\
|CMSPermission.COMMENTER|CMSPermission.FRONTUSER
# 3.管理员(拥有所有权限)
admin = CMSRole(name='管理员',desc='拥有本系统所有权限')
admin.permissions = CMSPermission.VISITOR|CMSPermission.POSTER|CMSPermission.CMSUSER\
|CMSPermission.COMMENTER|CMSPermission.FRONTUSER|CMSPermission.BOARDER
# 4.开发者
developer = CMSRole(name='开发者',desc='开发人员专用角色')
developer.permissions = CMSPermission.ALL_PERMISSION
db.session.add_all([visitor,operator,admin,developer])
db.session.commit()创建角色代码语言:javascript复制python manage.py create_role9.2.封装权限判断功能(1)cms/models.py代码语言:javascript复制class CMSUser(db.Model):
#.......
@property
def permissions(self):
#用户拥有的权限
if not self.roles:
return 0
all_permissions = 0
#用户所有的角色
for role in self.roles:
#取出用户所有角色的所有权限
permissions = role.permissions
#把所有权限通过“|=”整合到all_permissions
all_permissions |= permissions
return all_permissions
def has_permission(self,permission):
# 判断用户是否有‘xxx’权限
#通过与操作,判断用户是否有‘permission’;得到的结果相等返回true,不相等返回false
return self.permissionspermission == permission
@property
def is_developer(self):
#判断是不是开发者
return self.has_permission(CMSPermission.ALL_PERMISSION)(2)manage.py代码语言:javascript复制@manager.option('-e','--email',dest='email') #用户邮箱
@manager.option('-n','--name',dest='name') #角色名字
def add_user_to_role(email,name):
'''添加用户到某个角色'''
user = CMSUser.query.filter_by(email=email).first()
if user:
role = CMSRole.query.filter_by(name=name).first()
if role:
#把用户添加到角色里面
role.users.append(user)
db.session.commit()
print("用户添加到角色成功!")
else:
print("没有这个角色:%s" %role)
else:
print("%s邮箱没有这个用户!"%email)
@manager.command
def test_permission():
'''测试用户是否有xxx权限'''
user = CMSUser.query.first()
if user.has_permission(CMSPermission.VISITOR):
print("这个用户有访问者权限")
else:
print("这个用户没有访问者权限")(3)cms终端把用户添加到角色代码语言:javascript复制#添加用户到角色
python manage.py add_user_to_role -e [email protected] -n 访问者
#测试
python manage.py test_permission
![BBS论坛(六)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F699_b2b232ed10.jpeg&w=3840&q=75)
BBS论坛(六)
6.1.优化json数据的返回(1)新建utils/restful.py代码语言:javascript复制# utils/restful.py
from flask import jsonify
class HttpCode(object):
ok = 200
unautherror = 401
paramserror = 400
servererror = 500
def restful_result(code,message,data):
return jsonify({"code":code,"message":message,"data":data or {}})
def success(message="",data=None):
return restful_result(code=HttpCode.ok,message=message,data=data)
def unauth_error(message=""):
return restful_result(code=HttpCode.unautherror,message=message,data=None)
def params_error(message=""):
return restful_result(code=HttpCode.paramserror,message=message,data=None)
def server_error(message=""):
return restful_result(code=HttpCode.servererror,message=message or "服务器内部错误",data=None)(2)cms/views.py代码语言:javascript复制class ResetPwdView(views.MethodView):
.
.
.
.
if user.check_password(oldpwd):
user.password = newpwd
db.session.commit()
return restful.success()
else:
return restful.params_error("旧密码错误")
else:
return restful.params_error(form.get_error())6.2.sweetalert优化修改密码结果反馈(1)把sweetalert文件夹放到static/common下面(2)在cms/cms_base.html中引用代码语言:javascript复制 <link rel="stylesheet" href="{{ static("common/sweetalert/sweetalert.css") }}">
<script src="{{ static("common/sweetalert/sweetalert.min.js") }}"></script>
<script src="{{ static("common/sweetalert/zlalert.js") }}"></script>(3)cms/js/resetpwd.js代码语言:javascript复制/**
* Created by derek on 2018/6/3.
*/
$(function () {
$("#submit").click(function (event) {
//阻止按钮的提交表单的事件
event.preventDefault();
//分别获取三个标签
var oldpwdE = $("input[name=oldpwd]");
var newpwdE = $("input[name=newpwd]");
var newpwd2E = $("input[name=newpwd2]");
var oldpwd = oldpwdE.val();
var newpwd = newpwdE.val();
var newpwd2 = newpwd2E.val();
//1.要在模板的meta标签中渲染一个csrf-token
//2.在ajax请求的头部汇总设置X-CSRFtoken
zlajax.post({
'url':'/cms/resetpwd',
'data':{
'oldpwd':oldpwd,
'newpwd':newpwd,
'newpwd2':newpwd2
},
'success':function (data) {
if (data['code'] == 200){
zlalert.alertSuccessToast("恭喜!密码修改成功!");
oldpwd.val('');
newpwd.val('');
newpwd2.val('');
}else {
var message = data['message'];
zlalert.alertInfo(message);
}
},
'fail':function (error) {
zlalert.alertNetworkError(error);
}
});
});
});修改密码弹出的信息旧密码输错的提示信息
![BBS论坛(三十)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F696_73a6c73787.png&w=3840&q=75)
BBS论坛(三十)
30.显示评论和添加评论功能完成(1)apps/models.py代码语言:javascript复制class CommentModel(db.Model):
__tablename__='comment'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
content=db.Column(db.Text,nullable=False)
create_time=db.Column(db.DateTime,default=datetime.now)
post_id=db.Column(db.Integer,db.ForeignKey('post.id'))
author_id = db.Column(db.String(50), db.ForeignKey('front_user.id'), nullable=False)
post=db.relationship('PostModel',backref='comments')
author=db.relationship('FrontUser',backref='comments')生成到数据库代码语言:javascript复制python manage.py migrate
python manage.py upgrade(2)front/forms.py代码语言:javascript复制class AddCommentForm(BaseForm):
content=StringField(validators=[InputRequired(message='请输入评论内容')])
post_id=IntegerField(validators=[InputRequired(message='请输入评论内容')])(3)front/views.py代码语言:javascript复制@bp.route('/acomment/',methods=['POST'])
@login_requried
def add_comment():
form=AddCommentForm(request.form)
if form.validate():
content=form.content.data
post_id=form.post_id.data
post=PostModel.query.get(post_id)
if post:
comment=CommentModel(content=content)
comment.post=post
comment.author=g.front_user
db.session.add(comment)
db.session.commit()
return restful.success()
else:
return restful.params_error(message='没有这个帖子')
else:
return restful.params_error(form.get_error())(4)front/front_base.html代码语言:javascript复制<span id="login-tag" data-is-login="1"></span>(5)front/front_pdetail.html代码语言:javascript复制{% extends 'front/front_base.html' %}
{% from 'common/_macros.html' import static %}
{% block title %}
{{ post.title }}
{% endblock %}
{% block head %}
<script src="{{ static('ueditor/ueditor.config.js') }}"></script>
<script src="{{ static('ueditor/ueditor.all.min.js') }}"></script>
<script src="{{ static('front/js/front_pdetail.js') }}"></script>
<link rel="stylesheet" href="{{ static('front/css/front_pdetail.css') }}">
{% endblock %}
{% block body %}
<div class="lg-container">
<div class="post-container">
<h2>{{ post.title }}</h2>
<p class="post-info-group">
<span>发表时间:{{ post.create_time }}</span>
<span>作者:{{ post.author.username }}</span>
<span>版块:{{ post.board.name }}</span>
<span>阅读数:{{ post.read_count }}</span>
<span>评论数:0</span>
</p>
<article class="post-content" id="post-content" data-id="{{ post.id }}">
{{ post.content|safe }}
</article>
</div>
<div class="comment-group">
<h4>评论列表:</h4>
<ul class="comment-list-group">
{% for comment in post.comments %}
<li>
<div class="avatar-group">
<img src="{{ comment.author.avatar or static('common/images/logo.jpg') }}" alt="">
</div>
<div class="comment-content">
<p class="author-info">
<span>{{ comment.author.username }}</span>
<span>{{ comment.create_time }}</span>
</p>
<p class="comment-txt">
{{ comment.content|safe }}
</p>
</div>
</li>
{% endfor %}
</ul>
</div>
<div class="add-comment-group">
<h3>添加评论</h3>
<script id="editor" style="height:100px;" type="text/plain"></script>
<div class="add_comment_btn">
<button class="btn btn-primary" id='comment-btn'>发表评论</button>
</div>
</div>
</div>
<div class="sm-container"></div>
{% endblock %}(6)front/css/front_pdetail.css代码语言:javascript复制.comment-group{
border:1px solid #e8e8e8;
margin-top: 20px;
padding: 10px;
}
.add-comment-group{
border:1px solid #e8e8e8;
margin-top: 20px;
}
.add_comment_btn{
text-align: right;
margin: 10px;
}
.add-comment-group h3{
margin: 10px;
}
.comment-list-group li{
overflow:hidden;
border-bottom:1px solid #e8e8e8;
}
.avatar-group{
float:left;
}
.avatar-group img{
width: 50px;
height: 50px;
border-radius: 50%;
}
.comment-content{
float: left;
margin-left: 20px;
}
.comment-content .author-info{
font-size: 12px;
color:#8c8c8c;
}
.author-info span{
margin-right:10px;
}
.comment-content .comment-txt{
margin-top: 10px;
}(7)front/front_pdetail.js代码语言:javascript复制$(function(){
var ue=UE.getEditor('editor',{
'serverUrl':'/ueditor/upload/',
"toolbars": [
[
'undo', //撤销
'redo', //重做
'bold', //加粗
'italic', //斜体
'blockquote', //引用
'selectall', //全选
'fontfamily', //字体
'fontsize', //字号
'simpleupload', //单图上传
'emotion' //表情
]
]
});
window.ue=ue;
});
$(function(){
$('#comment-btn').on('click',function(event){
event.preventDefault();
var login_tag=$('#login-tag').attr('data-is-login');
if (! login_tag){
window.location='/signin/'
}else{
var content=window.ue.getContent();
var post_id=$('#post-content').attr('data-id');
zlajax.post({
'url':'/acomment/' ,
'data':{
'content':content,
'post_id':post_id
},
'success':function(data){
if(data['code']==200){
zlalert.alertSuccessToast(msg='评论发表成功');
window.location.reload();
}else{
zlalert.alertInfo(data['message']);
}
}
});
}
}) ;
});
![BBS论坛(五)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F692_61fbe4a7ca.jpeg&w=3840&q=75)
BBS论坛(五)
5.1.cms后台修改密码功能完成(1)新建app/forms.py代码语言:javascript复制# app/forms.py
from wtforms import Form
class BaseForm(Form):
def get_error(self):
message = self.errors.popitem()[1][0]
return message(2)cms/forms.py代码语言:javascript复制# cmd/forms.py
from wtforms import StringField,IntegerField
from wtforms.validators import Email,InputRequired,Length,EqualTo
from ..forms import BaseForm
class LoginForm(BaseForm):
email = StringField(validators=[Email(message='请输入正确的邮箱格式'),
InputRequired(message='请输入邮箱')])
password = StringField(validators=[Length(6,20,message='密码长度不够或超出')])
remember = IntegerField()
class ResetpwdForm(BaseForm):
oldpwd = StringField(validators=[Length(6,20,message="请输入正确格式的旧密码")])
newpwd = StringField(validators=[Length(6,20,message="请输入正确格式的新密码")])
newpwd2 = StringField(validators=[EqualTo('newpwd',message="两次输入的密码不一致")])(3)cms/views.py代码语言:javascript复制class ResetPwdView(views.MethodView):
decorators = [login_required]
def get(self):
return render_template('cms/cms_resetpwd.html')
def post(self):
form = ResetpwdForm(request.form)
if form.validate():
oldpwd = form.oldpwd.data
newpwd = form.newpwd.data
user = g.cms_user
if user.check_password(oldpwd):
user.password = newpwd
db.session.commit()
return jsonify({"code":200,"message":""})
else:
return jsonify({"code": 400, "message": "旧密码错误"})
else:
message = form.get_error()
return jsonify({"code": 400, "message": message})
bp.add_url_rule('/resetpwd/',view_func=ResetPwdView.as_view('resetpwd'),strict_slashes=False)(4)新建static/common/zlajax,js代码语言:javascript复制// 对jquery的ajax的封装
'use strict';
var zlajax = {
'get':function(args) {
args['method'] = 'get';
this.ajax(args);
},
'post':function(args) {
args['method'] = 'post';
this.ajax(args);
},
'ajax':function(args) {
// 设置csrftoken
this._ajaxSetup();
$.ajax(args);
},
'_ajaxSetup': function() {
$.ajaxSetup({
'beforeSend':function(xhr,settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) !this.crossDomain) {
var csrftoken = $('meta[name=csrf-token]').attr('content');
// console.log(csrftoken);
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
});
}
};(5)cms/js/resetpwd.js代码语言:javascript复制/**
* Created by Administrator on 2018/6/3.
*/
$(function () {
$("#submit").click(function (event) {
//阻止按钮的提交表单的事件
event.preventDefault();
//分别获取三个标签
var oldpwdE = $("input[name=oldpwd]");
var newpwdE = $("input[name=newpwd]");
var newpwd2E = $("input[name=newpwd2]");
var oldpwd = oldpwdE.val();
var newpwd = newpwdE.val();
var newpwd2 = newpwd2E.val();
//1.要在模板的meta标签中渲染一个csrf-token
//2.在ajax请求的头部汇总设置X-CSRFtoken
zlajax.post({
'url':'/cms/resetpwd',
'data':{
'oldpwd':oldpwd,
'newpwd':newpwd,
'newpwd2':newpwd2
},
'success':function (data) {
console.log(data);
},
'fail':function (error) {
console.log(error);
}
});
});
});(6)cms/cmc_base.html代码语言:javascript复制 <meta name="csrf-token" content="{{ csrf_token() }}">
<script src="{{ static('common/zlajax.js') }}"></script>(7)cms/cms_resetpwd.html代码语言:javascript复制{% from 'common/_macros.html' import static %}
<script src="{{ static('cms/js/resetpwd.js')}}"></script>测试看能不能修改密码成功和输入错误的密码会不会提示密码不对
![视频社交洞悉(下)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F692_5769169a86.jpeg&w=3840&q=75)
视频社交洞悉(下)
前言在 视频社交洞悉(上)我们通过调研视频社交市场现状,分析和拆解了视频社交的概念。得出“视频社交”的本质一种“实时社交”的结论,进而分析了视频社交的优点和缺点。本篇我们将讨论视频社交的用户特点以及可能的机会点。微信、微博、贴吧、陌陌、探探……,过去几年是“异步社交”狂飙突进的几年。现实生活中很多人内心敏感、与人相处谨小慎,社交压力已经很大。所以异步社交的模式降低了他们的社交成本,同时掩盖了社交能力的不足,也更符合现代人碎片化的生活习惯。那么高压力的同步社交会有机会吗?这要从这部分新用户的特点说起。视频社交用户的特点先看几个典型场景:你是广西人,高中辍学来东莞4年了。当年的同学很多都大学毕业在城市写字楼里上班。你喜欢的穿白衬衫的女生去了广州读大学,朋友圈的发的照片都很好看。这几年你从橡胶厂到了塑料厂又到了玩具厂。一天工作12小时两班倒没社保没医保,加班费低得可怜,在机床从你早上站到晚上下班耳边都是轰隆隆是机器声音,除了下班后三三两两的啤酒局你也没地方说话。半夜下了班你坐在台阶上,给伊对的“红娘”和“相亲对象”开始打赏,一百接一百,你开始讲起学生时代时的故事,讲你为了那个白衬衫女生在街头单挑一群人...没人知道你为了考进一个这种类型的事业编付出了多少努力。刚来一个月你就明显不适应。一方面,你融入不到在你身边每天讨论婆媳关系和小孩上学的同事中去;另一方面,岗位职责之外杂七杂八的工作令你疲惫,你终于明白招聘启事里“完成领导交代的其他任务”的含义了。白天你要和其他比你年长数岁的大哥大姐叔叔阿姨关在一个办公室里,他们的话题你完全插不上嘴;但在晚上,你十点半睡觉前会专门空出一个小时,点开 Soul 的脸基尼匹配,希望在面具的遮盖下,遇到一个能陪你说话的同龄人。你是一个“深二代“,去年被被爸妈送到美国来读高中。爸妈是零几年大学毕业来深圳定居的。你最有印象的是小时候你们家小区之前周围都是土堆工地,你和小伙伴们都在放学后跑游戏厅一起打游戏。你最喜欢的颜色是绿色,所以今年生日爸爸送给你的礼物是这部墨绿色的苹果手机。每天下午的课间时间你会用Monkey匹配女生聊天儿,然后和同学们比较谁匹配到的女生更漂亮。还扬言一定要约到哪个最漂亮的。其实你最喜欢昨天匹配到的那个隔壁学校的女生,因为她长得很像艾丽·范宁。看看这些场景归纳一下会发现一个共同点:这些用户都是年轻人。我们可以尽力去回想一下那些年我们的青春期,然后不难发现这些年轻用户的特点大概可以概括为以下。年轻用户更多元。伴随着社会不可避免的阶层分化,年轻人也不可避免地走向分化。不同地域、不同阶层家庭的孩子表现出巨大的不同,这在未来会是一个越发明显的趋势。有大都市初入职场的白领,有下沉市场中的厂工厂妹,有青春无处安放的在校学生…所以我们越来越难以做一个统一明确的画像来描述年轻用户或00后就是怎样的。年轻用户时间更多。他们不会像我们那样追求效率和结果,可能更加走心和兴趣导向。所以“杀时间”是一个很重要的需求。这就好像我们今天约一个人出来,总是有着明确的目标性,否则就是“无效社交”,而他们不会,他们有大把的时间去浪费和消耗。在这里不用说什么“一寸光阴一寸金”,你下班之后还不是要打几盘游戏或者看几集网综?年轻用户的社交冲动更强。社交需求更旺盛,“嘴巴上”也会更大胆。因为他们以往的圈子比较单一狭窄,所以好奇心十足更愿意尝试新鲜事物,去看看不同的人和世界。而我们大多数人圈子已经定型,出现了社交倦怠,宁可宅着也不想太多社交。年轻人涉世未深没吃过多少亏,所以相对而言戒备心更弱更能放得开;而我们的戒备心更足,社交中的神经敏感性更强。关于机会点的论证视频社交有市场吗?机会点在哪里?我们需要注意几个改变:“异步社交”需求已经高度满足
从微信、微博,到陌陌、快手,异步AIO消息已经几乎是今天绝大多数社交或者社区类新创产品的标配,人们对这种“低压力、无需立即回复”的模式已经司空见惯。
相反,优秀的“同步”社交产品反而是稀缺的。snapchat在北美高中生群体爆火,但国内的复制品却遭遇水土不服。尚未成功不代表这种模式本身存在问题,需求一定是存在的。而长期的稀缺会不会已经累积了新的需求势能呢?实时娱乐产业正在兴起
这些年的年互联网红利主要集中在工具类和平台领域,解决的是“效率”的问题。现在,效率已经前所未有的提升,伴随AI技术的出现和应用,某些领域甚至有些效率过剩了。
在这样的背景下,消解孤独、缓解焦虑、杀时间的娱乐类产品出现了爆发的态势。
对年轻人来说,看一个产品,往往短期内更看重好玩,而非实用。从以往的单机游戏到实时联网手游,从录播到直播,从刷贴盖楼到屏幕实时弹幕……王者荣耀、狼人杀、B站,这些产品的特点广泛普适、碎片场景、在多人沟通中的实时娱乐化。智能手机、5G移动网络等基础建设提供更多支持
智能手机快速普及,伴随5G的来临,运营商资费越来越廉价。让视频这种社交媒介有了具备普及的基础要求。技术的演进也会带来新的沟通与生活方式,这个在下面会具体展开讨论。以上三点,人们对“异步”已经腻了,对“同步”的需求正在增强,加之硬件和网络基建越来越好。这就是未来视频社交的机会点,直播的爆火已经是一次启蒙。实时社交体验好坏的关键,就是看当下获得的互动反馈数量和质量。是划了无数卡片一个没聊到,还是至少和一个妹子真正聊满5分钟?对于时间稀缺的上班族来说,碎片化的异步社交是能更好地适应。但是对时间大把的学生党和下沉用户群体来说,他们敢于尝试更有压力却也更加刺激的实时同步社交。我们肯定会担心即便人们喜欢用视频社交,可是会不会就像陌陌、探探一样,只是当作“发现新关系”的工具?而一旦新关系稳固深化,又会转移到qq、微信上?之所以会这样,一个很重要的原因是其沟通方式和功能(IM、图文)和微信没差别,从方便和集中的角度当然微信更好。但是视频聊天是有不同的:当下仅仅是需要一个人的实时陪伴,吐槽也好闲聊也罢就刚好遇到这个人而已,至于是谁并不重要,当下的需求满足了,过期不候。所以通过视频社交获得的关系,没必要转到熟人平台。视频聊天工具一旦加了“美颜”,无疑女性用户会更愿意留下,因为微信的真实画面没法直视。在美颜的烘托下任何女生都会获得男生的搭讪,这解决了部分女性在现实生活中无人问津的情况,满足了虚荣心。一般使用文字语音,更多是作为消除尴尬、试探性的缓冲。一旦双方一上来已经使用了“最刺激”的沟通方式,再转到微信用文字图片这样降维的聊天,其实已经意义不大。
生活方式变迁与技术演进的推动生活方式变迁与技术演进会推动视频沟通逐渐成为熟人的日常沟通方式。视频聊天成为主流,也许在我们心中几乎不可想象,但是对于“互联网原住民”的“Z世代”也许大有可为。对我们来说,使用免费、盗版几乎是我们青春期最正常的体验,所以今天很多内容要付费,真是有一点违和感。但是互联网原住民的一代,版权意识、付费习惯就明显要好很多。那么,他们是否也更容易接受视频聊天成为一种生活方式呢?只有新的生活方式的形成,才是最好的护城河。如果这个假设是对的,那就算加了微信、qq号也没事,一来因为后两者的视频聊天体验太差,二来这两个产品目前都是越来越复杂,越来越重。如果做一个轻量化的视频工具,用户想要视频了还是会回来。另一方面,在人来历史上,技术的演进对人的沟通方式产生了数次的变革。从信件、电报到有线电话,人类实现了跨距离的实时沟通。BB机(寻呼机)的出现又解决了电话固定而人是移动的问题,被呼叫、然后回拨在某种程度上保证了一定的时效性。移动电话的发明完全解决了随时随地实时沟通的时效性问题。互联网IM工具的发明,实现了多媒体和实时画面传输。也产生了陌生人之间的社交。智能手机和移动网络的普及,使得视频这种社交媒介有了具备普及的基础要求。目前的问题是受制于手机这样的设备,实时视频在某些场景下是不方便不容易进行的。比如手机忘记带了,比如在拥挤的地铁上或会议室等。也许未来借助眼镜、手表等可穿戴设备、加上全息投影等技术,可以实现随时随地可接通且为安全的状态。结语至此,文章已经接近尾声。感谢你的阅读!总结上下两篇全文的内容和观点如下:视频社交市场上三类产品形态:内容社区,陌生社交,熟人工具。视频社交可以拆解为关系的发现、建立、维护。分别对应上述三种产品形态。视频社交的本质一种“实时社交”,具备明显清晰的优势和劣势。视频社交用户是具备多元化、杀时间、强社交冲动的年轻人。视频社交从市场机会、用户需求、技术基础三方面论证,存在机会点。视频社交会因为生活方式变迁与技术演进而逐渐成为熟人的日常沟通方式。最后想引用Tiki创始人吴永辉的一段话:「Tiki创造的是一个用户完全实时在线的场景,产品的重心在于实时而不在于视频。用户在Tiki上的行为逻辑分为两个层面:首先是匹配聊天,之后才是共同游戏,深化用户的社交行为。」归根到底,“视频社交”的本质一种“实时社交”。但反过来“实时社交”包含但不限于“视频社交”或者陌生人社交。实时社交未来也许成为下一个QQ或者微信。未来实时社交可能会切入到更多的丰富的场景和人群当中去。它像是一个未来版本的电话,每个人可能会通过这种方式来进行通讯。你如何看待视频社交的未来呢?欢迎留言交流。如果这篇文章对你有用,欢迎点击右下角「在看」并分享到朋友圈。朋友们我们下期再见。
![社群经济与粉丝经济:误解和澄清](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F691_27c774edd6.png&w=3840&q=75)
社群经济与粉丝经济:误解和澄清
胡泳 北京大学新闻与传播学院教授 宋宇齐 北京大学新闻与传播学院研究生 随着社会交流方式特别是网络的发展,社群的涵义产生了极大的变化。经典理论下的社群有一定的特点和限制条件,诸如:社群内成员的构成要以一定的社会关系作为基础;其成员从事的社会活动有一定的地域限制;社群内部应形成一定的文化,并能使社群成员产生归属感与认同感;同时,社群的建立与维护需要一定的基础设施。但在互联网时代,交流与沟通打破了原有的时空限制,使得社群可以不依托现实社会中的某些条件而建立。在地域上,因为互联网的全球性,社群成员的组成可以摆脱原有的地域限制,做到异地的交流沟通;在时间上,社群成员可以通过网络进行非实时的交流。社群活动也因此不仅仅局限于特定时间地点的特定活动,极大地便利了社群的维护和发展。 社群经济正是基于社群而形成的一种经济思维与模式,它依靠社群成员对社群的归属感和认同感而建立,借由社群内部的横向沟通,发现社群及成员的需求,其重点在于通过服务这些需求而获得相应的增值,并进一步建立社群内部的生态系统。这种内部生态的满足也使得社群本身通过优化社群环境、增加社群认同感等方式产生增值,从而有了更强的外拓资本。在互联网环境下,超强的传播效应与社群本身超低的边际成本使得社群的拓展具备更大的经济价值。 国内知名时尚网站P1在成立之初以街拍来为摄影爱好者及时尚人士提供摄影和穿着方面的交流平台,这就形成了一个以摄影和时尚为核心的社群。其账号体系便是利用社群经济的一个典型案例:P1并不开放注册账号,在用户心理上,P1通过不开放注册的方式设立准入门槛为其社群成员构建了较高的自我认同感。这种高自我认同感在社群成员的社会交流中会被作为一种资本进行表述,从而使有意加入该社群的非社群成员对获得账号有了更高的渴望,这种渴望极易在现实中产生经济价值,也就出现了倒卖P1邀请码的情况。 图片说明:P1街拍 如前文所述,社群经济的方式是通过对内部生态的满足产生经济价值并进一步外延。目前有相当一部分理论将粉丝经济等同于社群经济。其实,粉丝经济是一种单项的价值流通,它通过塑造一个品牌(这个品牌可以是人、物、观念等),来笼络对该品牌有较高认知度与喜好的受众成为其粉丝,这样的关系构成使得其内部的信息传递具有单向性的特点,即品牌传达某些信息,粉丝接受信息并向品牌做出反馈。这样的纵向信息传递方式有着极强的向心性及非理性因素。粉丝因缺少横向交流及获取外界信息的渠道与方式而产生对品牌主体的盲目崇拜。纵使品牌主体没有从物理上屏蔽粉丝获取外界信息的渠道,但其对粉丝灌输的价值体系使其在心理上自觉排斥了外界信息。这一点被用在很多的营销案例中,从早期的歌手粉丝到现今诸如苹果、小米类的品牌粉丝。它们的核心都是旨在营造一种目标受众的狂热崇拜。在这种狂热的崇拜下,品牌主体及其运营者通过开发品牌价值及周边产品获得经营性创收。 在互联网时代,社交媒体同样为粉丝经济的发展创造了更好的发展条件。它有效拉近了品牌主体与粉丝间的距离,扩大了品牌主体的信息传播范围,降低了其传播难度,使得品牌主体能够聚集更多粉丝,获得更大收益。同时,社交媒体与电商、互联网金融的结合也为粉丝经济产品的销售提供了便利有效的途径,进一步增加了收益。 例如,小米便是利用社交媒体和粉丝经济的一把好手。小米利用社交媒体进行粉丝吸引和维护的方式可谓应有尽有,几乎涵盖了当下所有的主流社交媒体。在微博上,雷军的个人账号成为推广小米的最主要力量。作为一个标榜创新的科技公司,其掌舵者的个人效应受到广泛关注,这个掌舵者自然而然成为品牌主体下的子品牌。雷军微博粉丝1237万,每日更新微博,其微博在小米品牌推广初期几乎条条与小米有关。在微信方面,小米各子品牌开设微信服务号,但由于服务号一月只能进行一次推送,其账号作用并不侧重于粉丝的招募宣传,而是在于既有粉丝的维护。在腾讯空间方面,小米拥有大量关注者。腾讯的QQ空间历来是一块粉丝营销不怎么投入的阵地,但是小米在QQ空间聚集了两千余万粉丝,说说的转发率在几千到上万不等,流量相当可观。同时,据网络数据分析,经由空间跳转至小米官网的流量占小米官网流量的5%以上。 虽然无论是在微博、微信还是QQ空间上,粉丝理论上都能与品牌主体进行互动并进行粉丝间交流,但实际能够与主体进行互动的粉丝仅占极少数,粉丝与粉丝间的有效交流更是寥寥无几。他们对品牌主体的凝集力几乎全部由品牌主体进行单方向维护。这与社群的构成要素及社群成员凝聚力的构建要素存在很大差异。 社群经济与粉丝经济之比较 社群经济与粉丝经济的最直观的差异在于,社群经济以社群间内部成员的横向交流为纽带,通过对社群的服务与创造社群价值获得经济效益;这显著区别于粉丝经济通过粉丝对品牌主体的向心性依托而获得经营性收益的做法。不过,因社交媒体互动性强的交流特点,粉丝经济与社群经济的界限并非全然泾渭分明。好的社群能够树立自有品牌从而聚集人气,形成一定的品牌向心性;粉丝经济也可以利用社交媒体的互动机制为粉丝提供一种类似于社群的归属感。这也就导致了社群经济与粉丝经济在社交媒体中容易混淆的现象。但如果我们深入来看,二者不难区分,可以通过以下三种方法进行分辨: (1)成员之间的互动程度 社群依托社群成员间的联系形成,社交媒体在网络时代起到的正是交流平台的作用,平台给予社群成员自由交流与沟通的方式和渠道。而社交媒体对于粉丝与品牌之间起到的大多是信息传播载体的作用,其信息有较强的单向性传播特点。以微博为例,社群的主体微博多发布与社群主题相关的内容供社群成员阅读、转发。社群成员间通过交流相结识,进一步建立网状关系。社群主体的运营者即微博运营者通过组织线上线下活动、服务社群成员而获得经济效益。但在粉丝经济中,品牌主体以发布某一新产品为内容核心,敦促粉丝通过接受其内容产生消费。其成员极少在主体发布的内容下有深入交流,多为自说自话的评论,粉丝间也很难通过该平台进行相互间的联系。 最典型的例子便是明星微博账号。明星微博账号主体是明星及其公关团队发布的用于维护明星价值的资讯消息,为的是让明星粉丝被动接受以维持崇拜心理。然而,基于明星粉丝群体而形成的诸多明星粉丝团与后援会却是社群形式,其通过微博发布明星信息及社群活动信息获得粉丝群体关注,并将粉丝群体迁移到微信群等即时通讯平台中,为粉丝间提供线上线下的交流平台,最终通过组织粉丝相关活动获得经济效益。 (2)成员与主体互动深入度 社群与社群主体间的互动程度要远远高于粉丝与品牌主体间的互动程度,其同成员间互动程度的本质一样,仍然与两者的构成机制与交流方式相关,即社群是基于社群成员的相同喜好、认知而建立的自发性互动性组织,而粉丝则是基于对品牌主体的崇拜而建立的一种上下关系。当社交媒体账号主体在社交媒体中发布消息后,社群中会产生相关话题,社群成员与账号主体的交流能够得到相应的回复与问题解答;而在粉丝群体中,品牌主体往往仅进行相关信息发布,而不会与粉丝产生除转发以外的多余互动,在消息评论中,粉丝往往也不会做出交流举动,而是以单纯表达崇拜为主。当然,在某些情况下,二者可以相互融合与共存,这主要取决于成员个体对于平台的自身诉求。 小米论坛便是集粉丝经济和社群经济为一体的一个BBS平台。其间有针对小米粉丝的在粉丝经济思想指导下的营销内容,也有针对技术与产品问题的互动交流内容。营销内容毫无疑问是提高粉丝购买欲的粉丝经济方式,而反馈贴及技术展望内容则实现了成员与社群主体即小米的沟通,用户通过产品问题的反馈和对新产品的预想展望为小米提供了直接的问题与期望采样资料,从而使小米能够对产品做出有针对性的改进研发,获得更大的市场收益。 (3)主体账号的运营维护方式 主体账号的维护方式也是区分粉丝经济和社群经济的重要标志。社群的主体账号以服务社群成员获得增值,其重点更多是在建立和维护交流平台上,账号的主要运营者通常也是社群成员,以业余时间进行平台的维护和拓展,社群成员也会自发加入到账号的内容维护中,发布社群主题相关内容与社群成员互动。因此社群账号也有着随意性强的特点。因其更多地承载平台职能,在一些社交媒体中社群不以明显的账号形式存在,比如百度贴吧、论坛类社交媒体。而粉丝经济中的主体账号因承担的是信息发布与传递的属性,故其会在成本允许的情况下雇佣专人或团队维护主体账号,撰写内容,选择合适时机发布。所以粉丝经济的主体账号维护方式有着一定的程式化及操作规律可循,并因其需求延伸出了相关行业。但是,随着社群知名度的提高及社群成员基数的发展等因素的推动,社群的经济效益逐步显现,为满足日常运营需求,社群主体账号也会出现专职维护人员。这也就与粉丝经济主体账号产生了一定的相似性,在这种情况下,就需要通过主体账号运作的目的性来进行甄别和判断。 社群经济在社交媒体中的发展现状及展望 因为社群经济在我国起步较晚,且社群相对独立分散,在缺乏专业运营人员及团队的情况下,社群自身的经济价值并未在社群内部被有效开发。更多的社群经济开发被社群所在社交媒体平台通过细分市场的形式进行广告推送以获得盈利。这也是社群经济较发展较为成熟的一个方向,社群账号的平台提供商通过对社群主题及成员的甄别划分,进行点到点、点到面的广告推送,以获得较常规广告投放更收益更高的增值收益。社交软件陌陌就通过群信息标签中的特点分类为群成员提供相关广告推送,并在这类广告推送的基础上增加微商接口,引入微商,打通微商到客户的对应渠道,获得相关金融流转收益。 这种联通平台用户及线下商业网络的模式也成为了近年来各大平台提供商针对社群经济进行拓展的主要方向,但这种发展完全抛开了社群这一经济载体,实质是开发社群聚集的账号价值进行增值。以汽车论坛汽车之家为例,其利用论坛用户规模及汽车相关性推出养车之家等客户端,上线线下养车服务商,提供养车服务及配件售卖,以获得线上交易带来的现金流。作为宽泛的社群来说,汽车之家论坛本身即为一个大的汽车用户及汽车爱好者社群。但就狭义社群概念而言,其社群的实际存在形式却在论坛分类里得到细分,社群成员的交流及归属感也多集中于细分的论坛之中。因此,其将社群的增值作用偷换为用户聚集效应产生的增殖作用其实有失偏颇。 本篇开头所介绍的P1时尚论坛的社群经济发展模式则有一定的可取性。它利用社群的品牌价值获得针对社群成员及准社群成员的经济价值。其经济价值由社群成员对于社群的价值认知和定位产生,围绕社群本身进行增值,而不是利用用户搭建平台获得现金流。在对被街拍的人“如何穿,穿什么”的关注中,社群成员自然会对品牌进行探究,再适当以帖子、介绍等形式引入品牌宣传内容,从而可以在不被社群成员反感的基础上获得广告收入,并依据成员的社群主题需求(在这里是时尚)展示诸如照片分享、拍照软件等内容进行社群经济的开发。 与此同时,如何将粉丝经济转化为社群经济是当今环境下所面临的重要问题。当粉丝被伪社群的宣传营造出的社群认同感欺骗时,真正的社群会被受到伤害的粉丝群体所质疑,从而使社会对社群失去部分信心。另一方面,粉丝经济的强大聚集效应带来的向心力便于提高经济效益,这使得将粉丝经济转化为社群经济变成了一条发展社群经济的捷径。依据前文中对于社群经济及粉丝经济差异性的分析,我们认为,在社交媒体中将粉丝转化为社群成员、从而使粉丝经济转化为社群经济的核心,是增强群体间的互动交流,增加价值认同,使得群体获得超出信息接收者的参与感。 谷歌的模块手机便是将谷歌安卓系统粉丝转化为社群成员的一个重要手段。在经历了从非智能机到智能机的迭代期后,谷歌和苹果各自拥有了自己的粉丝群,但这样的粉丝经济下产品用户的消费习惯过度依赖于对于品牌的崇拜,而模块手机的推出使得安卓系统的粉丝能够自由配置手机模块,玩出不同花样,在满足粉丝动手需求与个性需求的基础上,其进一步满足的社交需求无疑是粉丝群体在乎的一项重要诉求,粉丝间及不同粉丝群体间能够以此为话题进行深入的、有自我意识的交流。这无形中弥补了粉丝经济中依赖于垂直信息传递而忽略粉丝间横向交流的不足,将粉丝群在保持其粉丝经济价值的基础上迁移至社群,有效地发展了社群经济,并依靠社群成员的自发性及高认知度特点,进一步避免了粉丝流失。 前文简述了社群平台提供商的盈利模式及发展策略,但更多的中小型社群依然各自为营,较难开发经济价值,这也就需要从社群本质属性入手,利用社交媒体的时空便利,有针对性地为社群成员提供适合于他们的增值服务来挖掘价值。
![BBS论坛(十二)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F690_e7975d22d1.jpeg&w=3840&q=75)
BBS论坛(十二)
12.1.图形验证码生成(1)utils/captcha/init.py代码语言:javascript复制import random
import string
# Image:一个画布
# ImageDraw:一个画笔
# ImageFont:画笔的字体
from PIL import Image,ImageDraw,ImageFont
# pip install pillow
# Captcha验证码
class Captcha(object):
# 生成几位数的验证码
number = 4
# 验证码图片的宽度和高度
size = (100,30)
# 验证码字体大小
fontsize = 25
# 加入干扰线的条数
line_number = 2
# 构建一个验证码源文本
SOURCE = list(string.ascii_letters)
for index in range(0, 10):
SOURCE.append(str(index))
#用来绘制干扰线
@classmethod
def __gene_line(cls,draw,width,height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill = cls.__gene_random_color(),width=2)
# 用来绘制干扰点
@classmethod
def __gene_points(cls,draw,point_chance,width,height):
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=cls.__gene_random_color())
# 生成随机的颜色
@classmethod
def __gene_random_color(cls,start=0,end=255):
random.seed()
return (random.randint(start,end),random.randint(start,end),random.randint(start,end))
# 随机选择一个字体
@classmethod
def __gene_random_font(cls):
fonts = [
'msyh.ttf',
'msyhbd.ttf',
'simkai.ttf',
'simsun.ttc',
'webdings.ttf'
]
font = random.choice(fonts)
# print(font)
return 'utils/captcha/'+font
# 用来随机生成一个字符串(包括英文和数字)
@classmethod
def gene_text(cls, number):
# number是生成验证码的位数
return ''.join(random.sample(cls.SOURCE, number))
#生成验证码
@classmethod
def gene_graph_captcha(cls):
# 验证码图片的宽和高
width,height = cls.size
# 创建图片
# R:Red(红色)0-255
# G:G(绿色)0-255
# B:B(蓝色)0-255
# A:Alpha(透明度)
image = Image.new('RGBA',(width,height),cls.__gene_random_color(0,100))
# 验证码的字体
font = ImageFont.truetype(cls.__gene_random_font(),cls.fontsize)
# 创建画笔
draw = ImageDraw.Draw(image)
# 生成字符串
text = cls.gene_text(cls.number)
# 获取字体的尺寸
font_width, font_height = font.getsize(text)
# 填充字符串
draw.text(((width - font_width) / 2, (height - font_height) / 2),text,font= font,fill=cls.__gene_random_color(150,255))
# 绘制干扰线
for x in range(0, cls.line_number):
cls.__gene_line(draw, width, height)
# 绘制噪点
cls.__gene_points(draw, 10, width, height)
# with open('captcha.png','wb') as fp:
# image.save(fp)
return (text,image)(2)在utils/captcha文件下面放几种字体(3)front/views.py代码语言:javascript复制@bp.route('/captcha/')
def graph_captcha():
text,image = Captcha.gene_graph_captcha()
out = BytesIO()
image.save(out,'png') #指定格式为png
out.seek(0) #把指针指到开始位置
resp = make_response(out.read())
resp.content_type = 'image/png'
return resp(4)生成验证码运行项目,浏览器访问:http://127.0.0.1:5000/captcha/,可以看到生成的随机验证码
![用JAVA的DEA算法衡量社交媒体页面的流行度](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F690_c80081eb66.jpeg&w=3840&q=75)
用JAVA的DEA算法衡量社交媒体页面的流行度
Measuring the Social Media Popularity of Pages with DEA in JAVA原文作者:Vasilis Vryniotis原文地址:http://blog.datumbox.com/measuring-the-social-media-popularity-of-pages-with-dea-in-java/译者微博:@从流域到海域译者博客:blog.csdn.net/solo95用JAVA的DEA算法衡量社交媒体页面的流行度在前面的文章中,我们讨论了数据包络分析(Data Envelopment Analysis)技术,我们已经看到它如何被用作一个有效的非参数排序算法。在这篇博文中,我们将开发出一个JAVA数据包络分析的实例,我们将用它来评估网络上的网页和文章的社交媒体流行度。该代码是开源的(在GPL v3 license下),您可以从Github免费下载。更新:Datumbox机器学习框架现在是开源的,可以免费下载。查看包com.datumbox.framework.algorithms.dea以查看Java中Data Envelopment Analysis的实现。数据包络分析在JAVA中的实现代码是用JAVA编写的,可以直接从Github下载。它是根据GPLv3许可的,所以可以随意使用它,修改它,或者再分发。该代码实现了数据包络分析(Data Envelopment Analysis)算法,使用lp_solve库来解决线性规划问题,并使用Web搜索引擎优化分析(Web SEO Analytics )索引提取的数据,以构建基于Facebook,Google Plus和推特上分享的一个混合的社交媒体页面流行度矩阵。在前面的文章中介绍了算法的所有理论部分,在源代码中可以找到关于其实现的详细的javadoc注释。(原博文之后数据包络分析(Data Envelopment Analysis)算法及其实现全部简称了DEA,请读者注意,译者注。)下面我们提供一个关于其架构实现的高级别描述:1. lp_solve 5.5 library为了解决各种线性规划问题,我们使用一个名为lp\_solve的开源库。某些特定的lib是用ANSI C编写的,并使用JAVA包装来调用库方法。因此,在运行代码之前,您必须在您的系统上安装lp_solve。该库的二进制文件在[Linux和Windows都可以使用,您可以在lp_solve文档中阅读更多有关安装的信息。在尝试运行JAVA代码之前,请确保您的系统上安装了(相关的)特定库。有关安装和配置库的任何问题,请参阅lp_solve文档。2.DataEnvelopmentAnalysis Class这是DEA算法的主要实现类。它实现了一个名为estimateEfficiency()的公共方法,它获取记录的Map并返回它们的DEA得分。3. DeaRecord ObjectDeaRecord是一个特殊的对象,用于存储我们记录的数据。由于DEA需要分离输入和输出,因此DeaRecord对象将以DEA可以处理的方式分别存储我们的数据。4. SocialMediaPopularity ClassSocialMediaPopularity是一个应用程序,它使用DEA来评估社交媒体网络上Facebook的like,Google的 +1和twitter的Tweets的网页流行度。它实现了两个受保护的方法:calculatePopularity()和estimatePercentiles()以及两个公共方法loadFile()和getPopularity()。calculatePopularity()使用DEA实现根据社交媒体计数来估计页面的得分数。estimatedPercentiles()方法获取DEA分数并将其转换为百分位数。总的来说,百分比比DEA分数更容易解释; 因此当我们说一个网页的流行分数是70%时,这意味着该网页比70%的其他网页更受欢迎。为了能够估计一个特定页面的流行度,我们必须有一个包含其他页面的社交媒体数据的数据集。这是有原因的,因为需要预测哪个网页是受欢迎的,哪些不是,您必须能够将其与网络上的其他页面进行比较。为此,我们使用来自以txt格式提供的Web SEO分析索引的小型的匿名样本。您可以通过从网页上的更多页面提取社交媒体计数来构建自己的数据库。(社交媒体计数,比如点赞数、转发数、评论数)loadFile()方法用于加载DEA的上述统计信息,getPopularity()方法是一种易于使用的方法,可以获取Facebook的like,Google的+1和一个页面的Tweets数量,并以此评估其在社交媒体上的流行度。如何使用数据包络分析的JAVA实现在DataEnvelopmentAnalysisExample类中,我提供了2个不同的关于如何使用代码的例子。第一个例子直接使用DEA方法来根据它们的输出(ISSUES,RECEIPTS,REQS)和输入(STOCK,WAGES)来评估组织单位的效率。这个例子来自DEAzone.com的一篇文章。代码语言:txt复制Map<String, DeaRecord> records = new LinkedHashMap<>();
records.put("Depot1", new DeaRecord(new double[]{40.0,55.0,30.0}, new double[]{3.0,5.0}));
//...adding more records here...
DataEnvelopmentAnalysis dea = new DataEnvelopmentAnalysis();
Map<String, Double> results = dea.estimateEfficiency(records);
System.out.println((new TreeMap<>(results)).toString());第二个示例使用我们的社交媒体流行度应用程序,通过使用来自社交媒体的数据来评估页面的流行度,例如Facebook的like,Google的+1和Tweets。所有的社交媒体计数都被标记为输出,我们传递给DEA一个空的输入向量。代码语言:txt复制SocialMediaPopularity rank = new SocialMediaPopularity();
rank.loadFile(DataEnvelopmentAnalysisExample.class.getResource("/datasets/socialcounts.txt"));
Double popularity = rank.getPopularity(135, 337, 9079); //Facebook likes, Google +1s, Tweets
System.out.println("Page Social Media Popularity: "+popularity.toString());必要的扩展(上面)所提供的代码只是DEA如何被用作排名算法的一个例子。为了改进其实现,需要进行下面的扩展:1.加速(算法的)实现特定的DEA算法实现会评估数据库中所有记录的DEA得分。由于我们需要解决如同数据库中记录数量那样多的线性规划问题,这使得实现变得缓慢。如果我们不需要计算所有记录的分数,那么我们可以显著地加快执行速度。因此,该算法的小扩展可以使我们更好地控制哪些记录应该被解决掉,哪些只能被用作约束。2.扩大社交媒体统计数据库(这篇文章所)提供的社交媒体统计数据库由来自Web SEO Analytics索引的1111个样本组成。为了能够估计更准确的流行(度)分数,需要更大的样本。您可以通过统计来自网络上更多页面的社交媒体计数来创建自己的数据库。3.添加更多的社交媒体网络该实现使用Facebook的喜欢,Google的+1和推文的数量来评估文章的受欢迎程度。不过,来自其他社交媒体网络的指标可以很容易地被考虑在内。您只需要从您感兴趣的网络中构建一个社交媒体数据库,然后扩展SocialMediaPopularity类来处理它们。关于实施的最终意见为了能够扩展(算法的)实现,您必须对Data Envelopment Analysis的工作原理有一个很好的理解。这在前面的文章中已经介绍过了,所以在继续进行任何更改之前,请确保您阅读了之前的教程。此外,为了使用JAVA代码,您必须在您的系统中安装lp\_solve库(参见上文)。如果你在一个有趣的项目中使用这个实现,那么就给我们一条线索,我们将在我们的博客上展示你的项目。另外,如果你喜欢这篇文章,请花点时间在Twitter或Facebook分享。
![社交网络成受黑客攻击重灾区](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F689_4ef93e48f2.jpeg&w=3840&q=75)
社交网络成受黑客攻击重灾区
据报道,随着社交媒体在人们生活中作用的迅速提升,网络黑客已经利用电脑技术开发并出售虚假用户评价,比如“好评”(likes)和“追随者”(followers)。而Facebook、照片分享应用Instagram、Twitter、谷歌(微博)YouTube、职业社交网站 LinkedIn以及其他热门社交网站都不幸成为黑客制造僵尸粉的重点攻击对象。 网络安全专家表示,最近一款名为Zeus的专门盗取信用卡数据的电脑木马病毒已经变体成能够制造虚假Instagram“好评”的僵尸病毒。 在互联网黑客论坛上,这些僵尸粉被打包成每份1000个进行出售,黑客还在论坛上兜售信用卡账号和从用户个人电脑上窃取来的其他信息。根据RSA的统计,在黑客论坛上,1000个Instagram虚假“追随者”售价为15美元,而1000个Instagram虚假“好评”的售价则高达30美元。与此形成鲜明对比的是,1000个信用卡账号的售价则低至6美元。虚假社交媒体账户比真实的信用卡账号更值钱,这似乎有些不可思议。但互联网营销专家则表示,出于自身原因或业务需要,有些人愿意在互联网上投资以便制造轰动效应,比如让一款新产品看起来颇受消费者欢迎。 数据分析师维克多·潘(Victor Pan)指出:“人们认识到了趋势的重要性。这就是所谓的‘从众效应’(bandwagon effect)”。 Facebook在去年斥资10亿美元收购了Instagram,并表示该公司正在对Instagram的安全系统进行升级。Instagram的新闻发言人迈克尔·科克兰德(Michael Kirkland)也表示,Instagram将拥有与Facebook同等级别的安全系统。Facebook的全球用户已经接近12亿,而Instagram的活跃用户也接近1.3亿。他还指出:“我们一直在努力减少服务中包含的垃圾邮件,并禁止通过非授权或自动方式新建用户账户。”他还鼓励用户通过Facebook网站和应用里的链接报告可疑的网络行为。 长期追踪网络犯罪行为的专业人士指出,变体后的Zeus病毒是截至目前发现的第一款专门在社交网络上制造僵尸粉的恶意软件。使用自动软件程序制造虚假“好评”成为黑客普遍采用的方式。变体后的Zeus病毒可以通过中央服务器控制受感染电脑,迫使电脑向具体用户发送“好评”。根据RSA的调查,经过精心设计的Zeus病毒还可以介入其它网络活动或下载其它类型的恶意软件。 目前,变体后的病毒已经开始把攻击目标锁定在Instagram。这进一步突显出社交媒体在市场营销过程中不断上升的重要性,而黑客也在不断提升利用这种趋势进行牟利的复杂性。 专家们同时指出,操纵社交网络的行为很难自动消失。创建虚假社交媒体账户的目的比制造僵尸粉更加邪恶,比如窃取用户的身份信息。 加州大学伯克利分校的电脑安全专家克里斯·格里尔(Chris Grier)指出:“这些虚假账户仅仅是接触终端用户的一种途径而已。网络罪犯总是希望借此来牟利。”格里尔领导的团队已经花费了一年时间来调查Twitter上的虚假账户情况。
![密友社交设计探索](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F689_d2fd40f5f9.jpeg&w=3840&q=75)
密友社交设计探索
腾讯ISUXisux.tencent.com社交用户体验设计
1 社交现状与痛点保持距离、经营人设、礼貌分寸,我们努力维系与迎合,去成为在社交关系中受欢迎的角色。曾几何时,人们在使用社交APP时越来越忐忑,“这句话这样说是否合适?”“是否影响到了我的公众形象?””这样会不会太矫情?”又或是,大家开始抱怨社交产品上的红点提示,似乎永远也删不完。想联系的人找不到,不想联系的,却又碍于社交礼仪,只能礼貌的客套。许多人在问,那个想说什么就说什么的“我”去了哪儿?2 痛点分析美国社会学家格兰诺维特曾提出,人和人之间的连接分为“强”“弱”两种关系。强关系常产生于家庭成员、同事、同学等之间,他们在生活和工作中有较多的互动机会。由于已经有了固定的情感基础,社交动机以具体的”人“为维度,沟通与互动是主要场景。弱关系中,人与人之间联系较少,可能只是聊过几句或是打过招呼,人们关注的更多是信息的质量和信息的传播。主流社交APP,在产品早期主要聚焦于强关系链。但随着用户数量的持续大量增长,私密性和封闭性逐步被打破。原本只承载强社交关系的圈子,变成了一个充满看客的强弱社交关系混合的广场。因此,虽然刺激用户社交的功能一直在不停的迭代与增加,用户却因为社交环境的变化,导致分享沟通更有负担。3 解决方案与设计目标关系,决定了人与人之间产生交互;场景,决定了人与人之间产生什么样行为。具体的社交行为,是关系和场景这两个要素的叠加。为尝试解决现有的社交困境,DOV定位于“强关系”这一明确的关系链,清晰分隔混合的社交环境,聚焦于核心的密友社交场景,探索搭建合适的APP,为用户提供新的社交帮助。4 引导用户导入建立合适的强关系群体第一步,需要引导用户导入和建立合适的强关系联系人。我们将“强关系”定义为一个用户更好理解的概念--“密友”,根据基本的用户使用地图,我们在推荐渠道,新手引导和功能设定三个步骤上,突出“密友”的概念。4.1 从推荐渠道建立认知首先,在各个推荐渠道中强调“密友”概念。用户需要通过一份”真假朋友大考验“,才能获得友谊的通行券。在诸多运营活动页面的设计中,DOV使用了同一套字体系统和类似的四方连续底纹,保证设计风格和氛围的统一化。整体设计风格偏娱乐化,同时兼顾DOV的品牌风格,深化产品在用户心中的形象定位,帮助用户首次接触DOV这个产品时,留下完整性的品牌印象。4.2 从闪屏页与新手引导教育用户当用户首次登录DOV时,一则趣味化的小短片,也向用户表达了产品的主要核心:“虽然我们和多数人相识,却只能和少数人亲密。这里,是只属于你和密友们的新天地。”首屏小短片需要给用户营造一种热闹的气氛,视觉上会更加活泼来吸引用户的眼球,采用黄黑与黑白两种高对比对色彩去加重需要用户所悉知的内容。同样,在短片中延续整个DOV常用的四方连续的设计手法。
4.3 从功能的设定强化概念尽管人们可以借助社交网络实现“好友”遍天下,但真正的密友屈指可数,而且数量基本保持不变,结交一个新朋友往往会冷落一个老友。在DOV的密友生态环境中,我们希望杜绝泛泛之交,去限制每个用户的密友的数量,从而让用户去珍惜每一个名额。视觉样式上采用卡片的形式,强化视觉上的个人意识。通过大投影的卡片来与背景的白色拉开层次距离,让整体卡片更加立体。同样,排版上采用左齐的排版设计样式,采用大字体的标题设计,偏向于海报的排版 。DOV的首TAB页,如同一个所有好友的集居地。用户可以轻松的看到所有的好友每日状态,如果好友更新了日迹内容,好友的卡片会透传视频内容和未读数。点击好友卡片,就会以连续的小视频播放展示好友24小时内发布的生活小视频。扁平设计已经流行了好几年,但是过于扁平的设计会让整体空间层次混乱,在DOV的设计中大量运用卡片以及大投影的设计来为空间层次感增效。同样在动态的设计中,我们给2D图形赋予更多的伪3D的一种动态质感,让整体动态以及界面的视觉呈现上更加立体,让层次更加丰富细腻。5 维系与加强已有的情感基础引导用户导入了强关系链联系人之后,如何维系与加强已有的情感基础就成了主要的目的。在网络上,社交情感的维系依靠信息,特别是真正有价值的属于“你与我”的独有的信息。在交互设计中,参照实际的物理的社会互动因素,可极大提升用户界面的参与感和趣味性。5.1 实时体现社交情感温度DOV的AIO背景,从视觉层面体现实时的社交情感温度。背景颜色会随着聊天热度变化从淡漠的浅灰色逐渐升温到柔情的橙黄色,最终到达至炙热的红紫色。通过视觉的表达上的色温感受来透传好友之间的亲密热度。5.2 即时同步行为状态好友的意义,除了实际的沟通,精神上的陪伴感也非常重要。当两个用户同时出现在AIO窗口中时,会激活”小状态“功能。他或者正在写着什么给你,或者正在等待着你说话。这些依据用户行为触发趣味性动效,可以有效的拉近情感空间。即便地理位置上也许相隔甚远,但通过一块共同的屏幕,却仿佛就在眼前。合理运用迪士尼的动画设计原则,更加拟人化的动态设计可以更好地调动用户的内心情绪,夸张的表现手法也同样会赋予UI界面更多的戏剧性效果。5.3 丰富信息交换的载体
视频,能传达丰富的信息。但传统的视频聊天作为一种非常需要双人同步在线的重社交方式,存在天然痛点。比如旅行途中,我想给朋友看看我正在进行时的美景美食,朋友却在会议中,不能接收视频聊天邀请。鉴于此,DOV新设定了一个同框功能,允许只打开一方的摄像头,并且默认语音静默。这样如果用户想将现在所处的环境展示给朋友,就不需要发起一个非常重的视频聊天,而只需要打开同框功能,将摄像头内拍摄到的内容作为AIO背景同步给好友。而当时间点方便时,好友也可以选择加入同框,成为一个类似视频聊天的体验。此时,按下“记录”的按钮,就生成了一张拍立得质感的记录图片,沉淀在AIO内,成为友谊的见证。5.4 提升信息交换的效率强关系的一大特征在于有高频的信息交换诉求。在QQ,微信等诸多社交软件的培养下,异步发布自己的生活点滴和心情,分享给好友,已经成为了一种非常天然的心理诉求和用户习惯作为好朋友,常常会互相告知所在的位置,心情,所做的事情,等等。DOV在AIO内加入了一个“此时此刻”功能,可以快速拉起摄像头拍摄现在的场景,再用加上简单有趣的图像化状态说明。相比一本正经的汇报现状,更强调分享生活小点滴,以及自己的碎碎念和小心情,是一种更具有趣味性和轻量化的沟通分享能力。5.5 创建更多C2C沟通场景当朋友们在谈论社交网络中的内容时,经常说一句话是 “嘿,你看到那张照片了吗?”DOV将C2C的沟通起点,前置于观看场景。当用户看见朋友的生活小视频时,可以用消息和轻互动直接开启聊天。异步分享成为了即时沟通的社交动机,因此而开启更多的可能的沟通场景。同时,DOV的分享体系下,视频不仅仅是一种异步分享方式,而是想对着所有好友说的碎碎念。所以,相比一般发在朋友圈里的那种展现美好生活形态的记录,DOV内更多的是我的各种好的坏的大的小的当下心情与境遇。因此,朋友的即时反馈就极为重要。好友的回复,是对分享发表的直接正向鼓励,可以有效的刺激更多的内容产出。6 结语所有人的社交圈,都是分层的。有的是无话不说的兄弟或闺蜜,有的是兴趣结识的同好,有的是工作中结识的同事,有的是一起度过学校时光的同窗,有的是无法割舍的亲人,有的是萍水相逢的点头之交。面对不同的社交圈层,我们往往要扮演不同的社交形象,选择性的交流或分享。年轻一代往往希望更纯粹的社交,让沟通分享脱离功利,回归纯粹的友谊。围绕着这种年轻人的新诉求,为他们搭建舒适贴心的沟通与分享场景,一直以来,都是DOV的产品创新设计的主路径。或许将来的社交潮流,是更多的是小社交,每个人都有自己的小圈子,既有独立性,也有合作性,而且各有各自的规则,私密和公开相结合,去正式化,去平台化。社交模式创新的尝试,路阻且长。但望,流年笑掷,未来可期。最后,附上DOV二维码,欢迎大家下载体验。以下ISUX文章,你可能也感兴趣
▽DOV社交探索 | 贴纸极致设计 DOV原创驱动-短视频社交设计思考 ISUX Showreel 2018 拨动情绪的内容设计 情感化IP体验设计感谢阅读,以上内容均由腾讯ISUX团队原创设计,以及腾讯ISUX版权所有,转载请注明出处,违者必究,谢谢您的合作。注明出处格式:
文章来自公众号:腾讯ISUX(https://isux.tencent.com/articles/dov-social.html)↓点击前往 ISUX 官网
![CVPR新规严禁审稿期间公开宣传论文,可发arXiv,LeCun:疯了吧!](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F688_75391fd189.jpeg&w=3840&q=75)
CVPR新规严禁审稿期间公开宣传论文,可发arXiv,LeCun:疯了吧!
机器之心报道编辑:蛋酱、泽南打击投机取巧行为。除了标题各种 all you need 之外,投稿之后在推特知乎上宣传一波,油管上发个介绍视频现在几乎是 AI 顶会热门研究的「标配」。在社交网络如此发达的今天,「酒香不怕巷子深」的美好世界看起来越来越难以实现了。在论文水平差距不大的情况下,PR 能力成为了不少人比拼的方向。但众所周知,自我宣传有可能影响到审稿人的判断,进而让身处大型实验室的研究者们更容易获益。最近几天,人工智能领域最热门的会议 CVPR 决定拿社交媒体开刀了。在近日召开的 CVPR 2021 PAMI TC 会议上,马普智能系统研究所所长 Michael Black 提出了一项动议:审稿期间禁止在社交媒体上宣传论文。在 arXiv 上自动发布的预印本论文除外。这项动议得到了一部分研究者认同,但同时也引来许多争议。有研究者表示,这项动议的宗旨是解决同行评审中的偏见问题,但打击社区内交流的消极后果是,同行评审中的偏见问题并不会改善。在最终通过的投票版本中,内容如下:PAMITC 当前的政策是禁止作者发布新闻稿或谈论正处于 IEEE/CVF 审查阶段的论文。这有利于双盲审查,并有助于保持公众对科研同行审查过程的信任。
随着研究者们越来越多地使用社交媒体来传播科研成果,这项政策需要更新。特别是社交媒体动态已经在很大程度上取代了传统的新闻发布。按照目前的政策,此类内容处理起来会有些模棱两可,但只要作者没有在社交媒体上说这篇论文正在接受 IEEE/CVF 会议的审查,就可能会被解释为允许这样做。这个漏洞违反了最初媒体禁令的原则。问题在于,拥有大量关注者的一部分以及在社交媒体上发起的宣传活动,让审稿人接触到这篇论文,而它所受到的关注可能会影响他们的判断。这让关注者较少或不参加这类活动的那部分人处于不利地位,并会使同行评审过程出现偏差。
同行评审是科学的支柱。这个过程能够让研究公布之前被发现错误或虚假的内容,减少了研究被撤回的风险,并增加公众对科学进步的信任。本质上,科研在资金和独立性方面都有赖于这种信任的建立,任何破坏这种信任的行为都会对基础研究产生长期的负面影响。对于人们最为关心的一些问题,CVPR 组织方也进行了解答:Q:新规定生效之后我把投 CVPR 的论文放在 arXiv 上,这能行吗?A:将论文放在 arXiv 上显然有助于计算机视觉研究信息的快速传播。arXiv 论文并不是「已发表」,而应该被理解为「预发表」的状态。这种开放的预先发表模式为研究社区提供了一种有效的查错模式,与同行评审效果类似。arXiv 论文经常会被更正和修改,这一网站的建立就是为了这样的科学修订过程。将论文放在 arXiv 上供专家进行早期分析,与在社交媒体上向广大受众进行宣传有本质不同。Q:那我在推特上转发 arXiv 上转发的 CVPR 论文投稿,这样可以吗?A:没问题。这是一个自然而然的过程,并不构成作者宣传他们的工作。arXiv 推文主要是由该领域的专家而非普通公众关注,其讨论的工作可被认为是具有完整性的,且处于预发表状态的,因此判断为可行。但这与在社交媒体上流传的论文宣传视频不同。Q:这种规定难道不会让科学研究的传播速度变慢?A:并不。实际上是该领域专家实现科学进步,而不是普通大众。对 arXiv 的豁免意味着研究社区仍然可以提前获得研究进展,并可以将其效果评估为「非同行评审」。「允许,但又不允许宣传论文」的设置看起来很合理,也为研究人员们讨论业内最新研究留下了空间。目前,这项动议已经以 370:83 的票数在 CVPR 2021 投票通过。反对者:这规定漏洞太多虽然动议都在 PAMI-TC 的会议上以很大优势通过了,但仍有一些人对于新规表达了不满。人们表示:首先就会有一种情况,如果有一部分研究达成了「共识」,代表对方在社交媒体发布内容,宣传对方的研究。原本在审查过程中就存在的一些「利益团体」,在这里依旧会出现。以及,关于研究审查过程中的禁令,很大的一个影响是阻止了众多科研进展在 arXiv 上发布。除非是像 ACL 会议一样对预印本论文发布和双盲审稿之间权衡出合理的提交方案。还有一种可能存在的情况。那些不遵守规则并找到漏洞的人,之后从宣传研究上获得收益要比现在还要大,比如采用匿名的社交媒体账户宣传就可逃避该政策。Reddit 上的机器学习版块最受非议的一点就是非实名制发帖,我们是否希望推特也变成这样?这项动议针对的是那些来自大型实验室或拥有大量粉丝的研究者,但同时也极大地阻碍到了小型实验室的人。图灵奖得主、深度学习先驱 Yann LeCun 则直接在推特上表示:这种行为会限制科学信息的交流,损害技术进步且违反道德规范。简而言之就是疯了。在今年的大会结束后,CVPR 2022 计划将于明年 6 月 21-24 日在美国的新奥尔良举行。论文提交的 Deadline 则是今年 11 月 16 日。对于这项新规,你怎么看呢?参考内容:https://amytabb.com/ts/2021-06-16-cvpr-motion-position/WAIC AI开发者论坛:后深度学习的AI时代7月8日—10日,AI 开发者论坛将通过三大核心模块:AI开发者论坛、WAIC· 开发者黑客松和WAIC· 云帆奖展示本年度人工智能领域最前沿的研究方向和技术成果。7月10日,WAIC AI开发者论坛邀请到多位业界大咖带来精彩分享,主题涵盖大规模语言智能、SysML(机器学习系统)、多模态机器学习及大规模自动生成技术、RISC-V技术及生态、AI 原生计算机系统等热门话题,满足 AI 开发者多层次的学习需求。在精彩的分享外,我们还准备了RTX 3060 显卡、HHKB键盘、Air Tag、人工智能专业书籍、桌搭鼠标垫,现场签到即可参与抽取。识别下方二维码,立即报名。
©THE END转载请联系本公众号获得授权投稿或寻求报道:[email protected]
![java美食论坛系统发帖子系统美食论坛网站美食分享论坛源码](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F687_827a7e1641.jpeg&w=3840&q=75)
java美食论坛系统发帖子系统美食论坛网站美食分享论坛源码
ssm开发的美食论坛系统,用户注册之后可以发布关于美食的帖子,其他人可以回帖,评论,点赞回复和评论,分为楼主,第一楼,第二楼等。可以再个人中心查看我对别人的回复,以及别人对我的回复。演示视频 https://www.bilibili.com/video/BV1zq4y1q74r/?share_source=copy_webvd_source=ed0f04fbb713154db5cc611225d92156环境:jdk8+mysql5+tomcat8.5技术:ssm(spring+springMVC+myibats)+maven+pagehlper+css+jq+js+ajax+simditor+bootstrap功能:首页最新帖子展示,最近发布时间几秒前,几分钟前,几个天前,几个月前,分页;最热帖子展示,根据回复量倒序排列,展示前30条数据;根据帖子标题搜索;发帖功能,可以发图文信息,根据图文信息自动在首页展示1张或者2到三张图片;没有图片则只展示文字标题;登录;注册;帖子详情页,回复主贴,可回复图文信息,点击用户头像即可回复用户,回复楼中楼展示,收藏帖子,点赞回复,删除回复;个人中心,编辑资料,上传头像,修改密码,修改个性签名;查看我发布的帖子,删除我发布的帖子,分页展示;查看我的收藏,取消收藏,分页展示;查看我回复了谁,删除我的回复,分页展示;查看谁回复了我,不下再现实回复信息,分页展示;退出账号;快捷按钮菜单:主页,刷新,返回上一页,发帖,回复,收藏等.管理员功能分类管理:分页,添加,编辑,删除,根据名称搜索帖子管理:分页,审核通过,审核不通过,根据标题、用户昵称、分类、审核状态搜索回复评论管理:分页,删除,根据回复内容查找用户管理:分页,禁用,启用,根据昵称、禁启用状态查找修改密码退出登录在这里插入图片描述在这里插入图片描述
![BBS论坛(二)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F686_1f975f1808.png&w=3840&q=75)
BBS论坛(二)
2.1.cms后台登录界面完成(1)templates/cms/cms_login.html代码语言:javascript复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<title>CMS登录界面</title>
<!-- Bootstrap core CSS -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{{ url_for('static',filename='cms/css/signin.css') }}" rel="stylesheet">
</head>
<body>
<div class="container">
<form class="form-signin">
<h2 class="form-signin-heading">请登录</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail" class="form-control" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密吗</label>
<input type="password" id="inputPassword" class="form-control" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
</div> <!-- /container -->
</body>
</html>(2)static/cms/css/signin.css代码语言:javascript复制body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #eee;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}(3)cms/views.py代码语言:javascript复制# cmd/views.py
__author__ = 'derek'
from flask import Blueprint,views,render_template
bp = Blueprint("cms",__name__,url_prefix='/cms')
@bp.route('/')
def index():
return 'cms index'
class LoginView(views.MethodView):
def get(self):
return render_template('cms/cms_login.html')
def post(self):
pass
bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))浏览器访问:http://127.0.0.1:5000/cms/login/2.2.cms后台登录功能完成(1)cms/cms_login.html代码语言:javascript复制 <form class="form-signin" method="post">
<h2 class="form-signin-heading">请登录</h2>
<label for="inputEmail" class="sr-only">邮箱:</label>
<input type="email" id="inputEmail" class="form-control" name="email" placeholder="邮箱" required autofocus>
<label for="inputPassword" class="sr-only">密吗</label>
<input type="password" id="inputPassword" class="form-control" name="password" placeholder="密码" required>
<div class="checkbox">
<label>
<input type="checkbox" value="1" name="remember"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
</form>
{% if message %}
<p style="text-align: center" class="text-danger">{{ message }}</p>
{% endif %}(2)cms/forms.py代码语言:javascript复制# cmd/forms.py
from wtforms import Form,StringField,IntegerField
from wtforms.validators import Email,InputRequired,Length
class LoginForm(Form):
email = StringField(validators=[Email(message='请输入正确的邮箱格式'),
InputRequired(message='请输入邮箱')])
password = StringField(validators=[Length(6,20,message='密码长度不够或超出')])
remember = IntegerField()(4)cms/views.py代码语言:javascript复制# cmd/views.py
__author__ = 'derek'
from flask import Blueprint,views,render_template,request,session
from flask import url_for,redirect
from .forms import LoginForm
from .models import CMSUser
bp = Blueprint("cms",__name__,url_prefix='/cms')
@bp.route('/')
def index():
return 'cms index'
class LoginView(views.MethodView):
def get(self,message=None):
return render_template('cms/cms_login.html',message=message)
def post(self):
form = LoginForm(request.form)
if form.validate():
email = form.email.data
password = form.password.data
remember = form.remember.data
user = CMSUser.query.filter_by(email=email).first()
if user and user.check_password(password):
session['user_id'] = user.id
if remember:
# 31天后过期
session.permanent = True
return redirect(url_for('cms.index'))
else:
return self.get(message='用户名或密码错误')
else:
#form.errors的错误信息格式,是一个字典,value是列表的形式
# {'email': ['请输入正确的邮箱格式'], 'password': ['密码长度不够或超出']}
message = form.errors.popitem()[1][0]
return self.get(message=message)
bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))(4)config.py代码语言:javascript复制import os
SECRET_KEY = os.urandom(24)2.3.cms后台登录限制(1)config.py代码语言:javascript复制CMS_USER_ID = 'abcdefg' #随便写一值,这样session更加安全(2)修改LoginView代码语言:javascript复制session[config.CMS_USER_ID] = user.id(3)cms/decorators.py代码语言:javascript复制# cms/decorators.py
from flask import session,redirect,url_for
from functools import wraps
import config
def login_required(func):
@wraps(func)
def inner(*args,**kwargs):
if config.CMS_USER_ID in session:
return func(*args,**kwargs)
else:
return redirect(url_for('cms.login'))
return inner(4)cms/cms_login.py代码语言:javascript复制@bp.route('/')
@login_required
def index():
return 'cms index'2.4.cms后台模板渲染完成(1)static/cms/css/base.css代码语言:javascript复制/*
* Base structure
*/
/* Move down content because we have a fixed navbar that is 50px tall */
body {
padding-top: 50px;
overflow: hidden;
}
/*
* Global add-ons
*/
.sub-header {
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
/*
* Top navigation
* Hide default border to remove 1px line.
*/
.navbar-fixed-top {
border: 0;
}
/*
* Sidebar
*/
/* Hide for mobile, show later */
.sidebar {
display: none;
}
@media (min-width: 768px) {
.sidebar {
position: fixed;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: #363a47;
border-right: 1px solid #eee;
margin-top: -1px;
}
}
.nav-sidebar{
padding: 5px 0;
margin-left: -20px;
margin-right: -20px;
}
.nav-sidebar > li{
background: #494f60;
border-bottom: 1px solid #363a47;
border-top: 1px solid #666;
line-height: 35px;
}
.nav-sidebar > li > a {
background: #494f60;
color: #9b9fb1;
margin-left: 25px;
display: block;
}
.nav-sidebar > li a span{
float: right;
width: 10px;
height:10px;
border-style: solid;
border-color: #9b9fb1 #9b9fb1 transparent transparent;
border-width: 1px;
transform: rotate(45deg);
position: relative;
top: 10px;
margin-right: 10px;
}
.nav-sidebar > li > a:hover{
color: #fff;
background: #494f60;
text-decoration: none;
}
.nav-sidebar > li > .subnav{
display: none;
}
.nav-sidebar > li.unfold{
background: #494f60;
}
.nav-sidebar > li.unfold > .subnav{
display: block;
}
.nav-sidebar > li.unfold > a{
color: #db4055;
}
.nav-sidebar > li.unfold > a span{
transform: rotate(135deg);
top: 5px;
border-color: #db4055 #db4055 transparent transparent;
}
.subnav{
padding-left: 10px;
padding-right: 10px;
background: #363a47;
overflow: hidden;
}
.subnav li{
overflow: hidden;
margin-top: 10px;
line-height: 25px;
height: 25px;
}
.subnav li.active{
background: #db4055;
}
.subnav li a{
/*display: block;*/
color: #9b9fb1;
padding-left: 30px;
height:25px;
line-height: 25px;
}
.subnav li a:hover{
color: #fff;
}
.nav-group{
margin-top: 10px;
}
.main {
padding: 20px;
}
@media (min-width: 768px) {
.main {
padding-right: 40px;
padding-left: 40px;
}
}
.main .page-header {
margin-top: 0;
}
/*
* Placeholder dashboard ideas
*/
.placeholders {
margin-bottom: 30px;
text-align: center;
}
.placeholders h4 {
margin-bottom: 0;
}
.placeholder {
margin-bottom: 20px;
}
.placeholder img {
display: inline-block;
border-radius: 50%;
}
.main_content{
margin-top: 20px;
}
.top-group{
padding: 5px 10px;
border-radius: 2px;
background: #ecedf0;
overflow: hidden;
}
.top-box{
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}(2)static/cms/js/base.js代码语言:javascript复制/**
* Created by Administrator on 2018/6/2.
*/
/**
* Created by Administrator on 2016/12/17.
*/
$(function () {
$('.nav-sidebar>li>a').click(function (event) {
var that = $(this);
if(that.children('a').attr('href') == '#'){
event.preventDefault();
}
if(that.parent().hasClass('unfold')){
that.parent().removeClass('unfold');
}else{
that.parent().addClass('unfold').siblings().removeClass('unfold');
}
console.log('coming....');
});
$('.nav-sidebar a').mouseleave(function () {
$(this).css('text-decoration','none');
});
});
$(function () {
var url = window.location.href;
if(url.indexOf('profile') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(0).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('resetpwd') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(1).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('resetemail') >= 0){
var profileLi = $('.profile-li');
profileLi.addClass('unfold').siblings().removeClass('unfold');
profileLi.children('.subnav').children().eq(2).addClass('active').siblings().removeClass('active');
} else if(url.indexOf('posts') >= 0){
var postManageLi = $('.post-manage');
console.log(postManageLi);
postManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('boards') >= 0){
var boardManageLi = $('.board-manage');
boardManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('permissions') >= 0){
var permissionManageLi = $('.permission-manage');
permissionManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('fusers') >= 0){
var userManageLi = $('.user-manage');
userManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('cusers') >= 0){
var cmsuserManageLi = $('.cmsuser-manage');
cmsuserManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('croles') >= 0){
var cmsroleManageLi = $('.cmsrole-manage');
cmsroleManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('comments') >= 0) {
var commentsManageLi = $('.comments-manage');
commentsManageLi.addClass('unfold').siblings().removeClass('unfold');
}else if(url.indexOf('banners')>=0){
var bannerManageLi=$('.banner-manage');
bannerManageLi.addClass('unfold').siblings().removeClass('unfold');
}
});(3)templates/common/_macros.html创建一个宏代码语言:javascript复制{#“-”表示去掉换行#}
{% macro static(filename) -%}
{{ url_for("static",filename=filename) }}
{%- endmacro %}(4)templates/cms/cms_index.html代码语言:javascript复制{% from "common/_macros.html" import static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>标题</title>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="{{ static('cms/css/base.css') }}">
<script src="{{ static('cms/js/base.js')}}"></script>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<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" href="#">Zhang_derek论坛管理后台</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">derek<span>[超级管理员]</span></a></li>
<li><a href="#">注销</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="查找...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav-sidebar">
<li class="unfold"><a href="#">首页</a></li>
<li class="profile-li">
<a href="#">个人中心<span></span></a>
<ul class="subnav">
<li><a href="#">个人信息</a></li>
<li><a href="#">修改密码</a></li>
<li><a href="#">修改邮箱</a></li>
</ul>
</li>
<li class="nav-group post-manage"><a href="#">帖子管理</a></li>
<li class="comments-manage"><a href="#">评论管理</a></li>
<li class="board-manage"><a href="#">板块管理</a></li>
<li class="nav-group user-manage"><a href="#">用户管理</a></li>
<li class="nav-group cmsuser-manage"><a href="#">CMS用户管理</a></li>
<li class="cmsrole-manage"><a href="#">CMS组管理</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1>我的论坛</h1>
</div>
</div>
</div>
</body>
</html>(5)app/cms/views.py代码语言:javascript复制@bp.route('/')
@login_required
def index():
return render_template('cms/cms_index.html')访问:http://127.0.0.1:5000/cms/
![web安全论坛](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F685_a2ab9b9b40.png&w=3840&q=75)
web安全论坛
1.web应用程序所采用的防卫机制的几个核心构成:1、处理用户对应用程序的数据和功能的访问,以防止用户未经授权访问。2、处理用户的输入,以防止恶意的输入导致未预期的行为。3、处理攻击,以确保应用程序在 1.web应用程序所采用的防卫机制的几个核心构成:1、处理用户对应用程序的数据和功能的访问,以防止用户未经授权访问。
2、处理用户的输入,以防止恶意的输入导致未预期的行为。
3、处理攻击,以确保应用程序在被直接攻击时作出恰当的行为,如采取适当的防御和进攻性措施,以挫败攻击。
4、通过使管理员能够监控应用程序的活动和配置应用程序的功能来管理应用程序本身。1.1处理用户访问大多数web应用程序都使用下面的三重相关的安全机制来处理访问:
1、验证
2、会话管理
3、访问控制1.1.1验证验证机制在一个应用程序的用户访问处理中是一个最基本的部分。验证就是确
定该用户的有效性。大多数的web应用程序都采用常规的验证模型,即用户提
交一个用户名和密码,应用程序检查它的有效性。在安全性很重要的应用程序
中,如在线银行,这个基本的验证模型常增加额外的证书和多级登录过程。在
安全性要求更高的时候,其它的一些验证模型可以被用,如客户端证书,智能
卡或挑战/应答(challenge-response)tokens。challenge-responsetokens的过程:
用户要求登录时,系统产生一个随机数字串发送给用户。用户将这个串输入到
token设备中,token设备将这个串与用户的秘密口令按特定的算法进行运算并
产生一个回应串发送给系统,系统用同样的算法做验算即可验证用户身份。除了核心的登录过程外,验证机制也常采用其它的一些辅助功能,如自注册
(self-registration,比如注册后通过邮件中的链接激活帐户),帐户恢复以及
密码更改功能。尽管验证机制表面上简单,但是验证机制在设计和实现方面却
存在着广泛的缺陷。一般的问题可能使一个攻击者能够识别其他用户的用户名
,猜测他们的密码或者通过利用验证的逻辑缺陷绕过这个登录函数。当你攻击
一个web应用程序时,你应该花大量的注意力在该web应用程序所包含的各种
验证相关的功能方面。验证方面的缺陷将使你能够未经授权地访问敏感数据和
功能。1.1.2会话管理处理用户访问的下一个工作是管理授权用户的会话。在成功登录到应用程序后,用户将从他们的浏览发送一系列的HTTP请求来访问一些页面和功能。同时,该应用程序将接收无数来自不同用户的其它的请求,有授权的用户,也有匿名的用户。为了实施有效的访问控制,应用程序需要一个方法来识别和处理这一系列来自每个不同用户的请求。实际上大多数的web应用程序都通过为每个用户创建一个会话和发送给用户一个令牌(token)来识别会话。会话本身是位于服务上的一套数据结构,它被用来跟踪与应用程序交互的用户的状态。令牌是一个具有唯一性的字符串,应用程序将它映射到会话。当一个用户已经收到一个令牌时,浏览器在随后的每次HTTP请求中会自动将这个令牌提交给服务器,以使得应用程序能够将该请求与用户相关联起来。尽管许多应用程序使用隐藏的表单域或URL查询字符串来实现这一目的,但是HTTPcookies是传送会话令牌的标准方法。如果一个用户在指定的时间内没有产生一个请求,那么会话将被认为结束。对于之后的访问,web应用程序会要求你重新登录。就攻击而言,会话管理机制高度地依赖于它的令牌的安全性。针对会话管理机制的多数攻击都是试图损害发送给别的用户的令牌。有可能的话,一个攻击者可以伪装成受害的授权用户来使用web应用程序。这一漏洞主要来自于两方面,其一是令牌生成的方法的缺陷,使得攻击者能够猜测到发送给别的用户的令牌,其二是令牌的后续处理的方法的缺陷,使得攻击者能够捕获别的用户的令牌。有少部分的应用程序通过另外的识别方式省掉了会话令牌的需要,比如,如果一个HTTP的内建的授权机制被使用的话,那么浏览器对于每次的请求都自动重新提交用户的证书,使得应用程序能够直接从证书识别用户。也存在其它别的方法,应用程序存储状态信息在客户端而非服务器上,这些状态信息通常采用加密的形式以防止被篡改。1.1.3访问控制处理用户访问的最后一步是正确决定对于每个独立的请求是允许还是拒绝。如果前面的机制都工作正常,那么应用程序就知道每个被接受到的请求所来自的用户的id。它据此决定用户对所请求要执行的动作或要访问的数据是否得到了授权。
访问控制机制通常需要根据对应用程序的不同部分或不同类型的功能的考虑,实现一些小而好的逻辑。一个应用程序可能支持许多不同的用户角色,每个都牵涉到特定权限的不同组合。个别的用户可能会被允许访问该应用程序所容纳的整个数据的一个子集。特定的函数能够实现事务限制和其它的检查,所有这些都需要基于用户的id来得到正确的实施。
由于访问控制本身的复杂性,这使得它成为使得一个攻击者能够获得未授权访问数据和功能这一安全漏洞的常见根源。开发者经常对用户会如何与应用程序交互作出有缺陷的假设,以及经常由于省略了对某些应用程序功能的访问控制检查而造成疏忽。由于对于每项功能都需要重复相同的检查,所以探查这些漏洞通常是十分费力的。然而由于访问控制缺陷的普遍性,当你攻击一个web应用程序时这种努力是值得的。1.2处理用户的输入
很多针对web应用程序的攻击都涉及到提交未预期的输入,它导致了该应用程序设计者没有料到的行为。因此,对于应用程序安全性防护的一个关键的要求是它必须以一个安全的方式处理用户的输入。基于输入的漏洞可能出现在一个应用程序的功能的任何地方,并与每上通常使用的技术类型相关。对于这种攻击,输入验证是常用的必要防护。不存在通用的单一的防护机制。
1.2.1各种类型的输入
一个典型的web应用程序在不同范围形式内处理用户提供的数据。某种类型的输入验证可能对于所有这些输入形式是不可行的。
在许多情况下,一个应用程序对于特定的输入项能够实施非常严格的验证检查。比如提交给登录函数的用户名可以要求最大长度和只能包含字母。
在另外一些情况下,应用程序必须容纳更大范围的可能性的输入。比如提交给一个个人信息页面的地址字段,它可以包含字母、数字、空格、连接符,撇号以及其它字符。对于这种类型,仍然需要加以可行限制,如不能超过合适的长度,以及不能包含HTML标记。
在某些情形下,一个应用程序可能需要接受来自用户的任意的输入。比如,一个blog应用程序的用户,他创建的博客的主题的web应用程序攻击,那么他提交的内容则可以包含明显的所要讨论的攻击字符串。该应用程序需要以一个安全的方法把这些输入存储在一个数据库中并写到磁盘上,以及回显给用户。所以该应用程序就不能因为输入看起来有潜在的恶意简单拒绝。
除了来自用户的浏览器的各种输入外,典型的应用程序也接受从服务器到客户端,然后回传给服务器的数据。这些项目包括诸如cookies和隐藏的表单字段这些,它们不会被这个应用程序的普通用户所看到,但是对于攻击者来说是可见和可修改的。在这些情况中,应用程序可以对所接收的数据进行特定的验证。例如要求参数必须有一个指定数值集中的值,如表明用户所偏爱的语言的cookie,或以一个指定的格式,如一个客户的ID号。进一步说,当应用程序发现返回自用户的由服务器生成的数据已经被修改了的话,这通常就表明该用户正在探测应用程序的漏洞。在此类情况下,应用程序应该拒绝请求并记录下这个探测事件。1.2.2处理输入的方式
处理用户的输入有很多方式.不同的方式适合不同的情形和不同的输入类型,有些时候一个组合的方式是可取的.
1.2.2.1黑名单
这种方式通常使用一个黑名单,它包含已知的被用在攻击方面的一套字面上的字符串或模式.验证机制阻挡任何匹配黑名单的数据.
一般来说,这种方式是被认为对于检查用户的输入效果最差的一种方式.主要有两个原因,首先是,web应用程序中的一个典型的漏洞可以使用很多种不同的输入来被利用,输入可以是被加密的或以各种不同的方法表示.其二,漏洞利用的技术是在不断地改进的.有关利用已存在的漏洞类型的新的方法不可能被当前黑名单阻挡.
1.2.2.2白名单
这种方式采用一个白名单,它包含一套字面上的字符串或模式,或一套标准,它们用来匹配符合要求的输入.这种检查机制允许匹配白名单的数据,阻止之外的任何数据.这种方式虽然最有效,但不是通用的,比如撇号和连字符可以被用于对数据库的攻击,但是有时应用程序却应该允许它的输入.
1.2.2.3过滤
这种方式下,潜在的恶意字符被删除,留下安全的字符,或者在进一步处理被执行之前,它们被适当地加密或去掉.
基于数据过滤的方式通常是十分有效的,并且在许多情形中,可作为处理恶意输入的通用解决方案.比如,针对跨站脚本攻击的通常的防护是在字符被嵌入到应用程序的页面之前进行HTML加密.然而如果几种潜在的恶意数据在一个输入项中话,有效的过滤是困难的.在这种情况下,边界检查方法则是更适用的.
1.2.2.4安全地处理数据
非常多的web应用程序漏洞的出现是因为用户提供的数据是以不安全的方法被处理的.在一些情况下,存在安全的编程方法能够避免通常的问题.例如,SQL注入攻击能够通过正确的参数查询被阻止.在另外的情况中,应用程序功能设计的方法存在内在的不安全性,比如把用户的输入传递给操作系统的命令解释器.
安全处理数据的方式不能适用于web应用程序需要执行的每种工作,但是它对于处理潜在的恶意输入是通常有效的方式.
1.2.2.5语义检查
语义检查用于防止各种变形数据的输入,这些数据的内容被精心制作来干扰应用程序的处理。然而对于有一些漏洞,攻击者的输入在表面看来和普通用户的输入是一样的,说到底检查就失去了作用。例如一个攻击者可能会通过改变隐藏的表意字段中的帐号来试图获得对他人银行帐户的访问。要阻止这种未授权的访问,应用程序需要验证帐号是否属于该用户。
1.2.2.5边界检查
对于web应用程序,核心安全问题的出现是因为接受自用户的数据是不可信任的.尽管在客户端实现的输入验证检查能够能够提高性能和用户体验,但是这对于实际到达服务器的数据却没有任何担保.用户的数据在被服务端应用程序第一时间接受到的一刻就是边界,此时应用程序需要采取步骤来防卫恶意的输入.
鉴于核心问题的本质,对于互联网边界间的输入检查这一问题的思考是很有意义的.哪些是"恶意的"或不可信任的,以及服务端应用程序哪些是"好的"或可信任的.我们给出一个简单的想法:输入验证的角色是清除到达的数据中的潜在的恶意数据,然后把干净的数据传递给可信任的应用程序.据此,这些数据可以被信任和处理而不做进一步的检查或考虑可能的攻击.
当我们开始检查一些实际的漏洞的时候,会很明显地发现上面的简单的想法是不充分的.原因如下:(1).鉴于web应用程序实现的功能的广泛性,以及所应用的技术的不同,一个典型的web应用程序需要防卫大量的不同的基于输入的攻击.每种输入攻击都可能采用了一套不同的数据.针对外部边界仅设计单一的一个机制来防卫所有这些攻击是非常困难的.(2).许多应用程序的函数包含相互牵连的一系列不同的处理,单个用户所提交的一块数据可能导致不同组件之间的许多操作,上一个的输出可能作为下一个的输入.当数据被传送时,它可能有所变化,与最初的输入可能有所不同,这样一个熟练的黑客可能能够操纵这个应用程序以在处理的关键阶段导致恶意输入的产生,也就是攻击接受该数据的组件.这对于在外部边界预见用户输入的每块数据的处理的所有结果来实现一个验证机制是十分困难的.(3).防卫不同种类的输入攻击可能需要对用户的输入执行不同的验证检查,这些验证检查是不兼容的。例如阻止跨站脚本攻击可以要求HTML加密“>”为"gt";而阻止命令注入攻击(commandinject)可能需要阻止包含&和;字符的输入。试图在应用程序的外部边界同时阻止所有种类的攻击有时是不可能的。一个使用边界检查概念的更有效的模型是,服务器端的每个组件或功能单元把它的输入当作是来自一个潜在的恶意源。数据检查除了在客户端和服务端之间的边界外,也在这些认为可信的边界被执行。这个模型对前面列出的问题列表提供了一个解决方案。每个组件针对自身可能的漏洞的特定的输入攻击能够自我防卫。当数据在不同的组件间传递时,验证检查就可以对前面传来数据进行检查,由于不同有验证检查是在不同的处理阶段被执行的,所以他们之间不会产生冲突。下图演示了一个防卫恶意输入最有效的方式,用户登录致使对用户提交的输入进行了几步处理,并且每步上都执行了适当的检查。
(1).应用程序接受用户的登录的详细数据.表单处理检查输入的每一项,包括允许的字符、长度是否在指定的范围内、以及不能包含任何已知的攻击特征码.
(2).应用程序执行一个SQL查询来验证用户的证书.为了阻止SQL注入攻击,用户输入的任何可能攻击数据库的字符在构造查询之前都被去掉.
(3).如果登录成功,应用程序将把来自用户的数据传递给一个SOAP服务器以检索他的帐户的更多的信息.为了阻止SOAP注入攻击,用户数据中的任何XML元字符都被适当地加密处理.
(4).应用程序把用户的账户信息回传给用户的浏览器以显示.为了防止跨站脚本攻击,应用程序HTML加密嵌在返回的页面中的用户提供的任何数据.总之,所有牵涉的组件间都应作边界检查.情况的变化会导致所涉及的组件发生变化.例如如果登录失败后,应用程序会发送一个警告邮件给该用户的话,那么任何合并到该邮件中的用户数据可能需要针对SMTP注入攻击作检查.1.2.2.6多步检查和恢复如果对用户的输入没有进行仔细的多级检查的话,攻击者构建的输入就可能会得逞。当一个应用程序试图通过删除或加密特定的字符或表达式来过滤用户的输入的话,这种情况就可能会出现。例如,一个应用程序可能试图从用户提交的数据中通过去掉表达式<script>来防止某些跨站脚本攻击,那么攻击者可能通过输入<scr<script>ipt>来绕过这个过滤。这是因为这个过滤没有被递归地使用,当<scr<script>ipt>中间的<script>被去掉后,剩下的还是<script>。类似的情况就是,攻击者可以利用多步检查的顺序来绕过这个过滤。例如如果一个应用程序第一是递归地去掉<script>表达式,然后是去掉"符号的话,那么<scr"ipt>就可以成功绕过这个过滤。另一个问题是在用户输入的数据被解密时会发生的。从用户浏览器过来的数据会是以不同方法加密了的数据,那么就需要对这些数据进行恢复,也就是转换或解密为通常的字符。如果解密是在输入过滤之后,那么攻击者就可以通过加密来绕过这个检查机制。例如,如果一个应用程序通过删除用户输入数据中"号来防止某些SQL注入攻击的话,由于过滤先于恢复,那么攻击者可以使用"号的URL加密形式%27来绕过这个检查机制。同理,如果检查机制也会去掉%27话,只要没有递归处理,那么%%2727就能够得逞。有时候避免多步检查和恢复中存在的问题是比较困难的。不存在单一的方案能够解决这些问题。有些情况下,递归地处理一个有问题的字符可能会导致死循环,通常,这只能在所执行的检查类型上来根据情况处理,情况允许的话,更好的方法就是简单地拒绝某些类型的恶意输入。今天文章到此就结束了,感谢您的阅读。
![BBS论坛(十)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F684_0f6abf140e.png&w=3840&q=75)
BBS论坛(十)
10.1.客户端权限验证功能完成(1)cms/cms_profile显示当前用户的角色和权限代码语言:javascript复制 <tr>
<td>角色:</td>
<td>
{% for role in user.roles %}
{{ role.name }}
{% if not loop.last %},{% endif %}
{% endfor %}
</td>
</tr>
<tr>
<td>权限:</td>
<td>
{% for role in user.roles %}
{{ role.desc }}
{% if not loop.last %}/{% endif %}
{% endfor %}
</td>
</tr>(2)cms/hooks.py代码语言:javascript复制@bp.context_processor
def cms_context_pocessor():
return {'CMSPermission':CMSPermission}(3)cms/cms_base.html不同的角色,显示不同的内容代码语言:javascript复制{% set cms_user = g.cms_user %}
{% if cms_user.has_permission(CMSPermission.POSTER) %}
<li class="nav-group post-manage"><a href="#">帖子管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.COMMENTER) %}
<li class="comments-manage"><a href="#">评论管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.BOARDER) %}
<li class="board-manage"><a href="#">板块管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.FRONTUSER) %}
<li class="nav-group user-manage"><a href="#">前台用户管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.CMSUSER) %}
<li class="nav-group cmsuser-manage"><a href="#">CMS用户管理</a></li>
{% endif %}
{% if cms_user.is_developer %}
<li class="cmsrole-manage"><a href="#">CMS组管理</a></li>
{% endif %}(4)添加用户和角色代码语言:javascript复制#添加访问者
python manage.py create_cms_user -u 我是访问者 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 访问者
#添加运营者
python manage.py create_cms_user -u 我是运营者 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 运营
#添加管理员
python manage.py create_cms_user -u 我是管理员 -p 123456 -e [email protected]
python manage.py add_user_to_role -e [email protected] -n 管理员不同的用户登录到后台cms显示不同的内容 开发者访问者10.2.服务端权限验证功能完成(1)后台剩余的html页面cms_posts.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
帖子管理
{% endblock %}
{% block head %}
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
帖子管理页面
{% endblock %}其它几个一样代码语言:javascript复制cms_comments.html
cms_boards.html
cms_fusers.html
cms_cusers.html
cms_croles.html(2)cms/decorators.py添加一个权限验证的装饰器代码语言:javascript复制def permission_required(permission):
def outter(func):
@wraps(func)
def inner(*args,**kwargs):
user = g.cms_user
if user.has_permission(permission):
return func(*args,**kwargs)
else:
return redirect(url_for('cms.index'))
return inner
return outter(3)cms/views.py代码语言:javascript复制@bp.route('/posts/')
@login_required
@permission_required(CMSPermission.POSTER)
def posts():
return render_template('cms/cms_posts.html')
@bp.route('/comments/')
@login_required
@permission_required(CMSPermission.COMMENTER)
def comments():
return render_template('cms/cms_comments.html')
@bp.route('/boards/')
@login_required
@permission_required(CMSPermission.BOARDER)
def boards():
return render_template('cms/cms_boards.html')
@bp.route('/fusers/')
@login_required
@permission_required(CMSPermission.FRONTUSER)
def fusers():
return render_template('cms/cms_fusers.html')
@bp.route('/cusers/')
@login_required
@permission_required(CMSPermission.CMSUSER)
def cusers():
return render_template('cms/cms_cusers.html')
@bp.route('/croles/')
@login_required
@permission_required(CMSPermission.ALL_PERMISSION)
def croles():
return render_template('cms/cms_croles.html')(4)cms/cms_base.html修改url链接代码语言:javascript复制 {% set cms_user = g.cms_user %}
{% if cms_user.has_permission(CMSPermission.POSTER) %}
<li class="nav-group post-manage"><a href="{{ url_for('cms.posts') }}">帖子管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.COMMENTER) %}
<li class="comments-manage"><a href="{{ url_for('cms.comments') }}">评论管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.BOARDER) %}
<li class="board-manage"><a href="{{ url_for('cms.boards') }}">板块管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.FRONTUSER) %}
<li class="nav-group user-manage"><a href="{{ url_for('cms.fusers') }}">前台用户管理</a></li>
{% endif %}
{% if cms_user.has_permission(CMSPermission.CMSUSER) %}
<li class="nav-group cmsuser-manage"><a href="{{ url_for('cms.cusers') }}">CMS用户管理</a></li>
{% endif %}
{% if cms_user.is_developer %}
<li class="cmsrole-manage"><a href="{{ url_for('cms.croles') }}">CMS组管理</a></li>
{% endif %}
![BBS论坛(十九)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F683_979440b7e1.png&w=3840&q=75)
BBS论坛(十九)
19.1.cms轮播图管理页面布局(1)cms/cms_base.html代码语言:javascript复制<li class="nav-group banner-manage"><a href="{{ url_for('cms.banners') }}">轮播图管理</a></li>(2)views.y代码语言:javascript复制@bp.route('/banners/')
@login_required
def banners():
return render_template('cms/cms_banners.html')(3)cms/banners.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
轮播图管理
{% endblock %}
{% block head %}
<style>
.top-box{
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}
.top-box button{
float: right;
}
</style>
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
<div class="top-box">
<button class="btn btn-warning">添加轮播图</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<td>名称</td>
<td>图片链接</td>
<td>优先级</td>
<td>跳转链接</td>
<td>创建日期</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
{% endblock %}19.2.添加轮播图模态对话框的制作cms_banners.html代码语言:javascript复制{% block main_content %}
<div class="top-box">
<button class="btn btn-warning" data-toggle="modal" data-target="#banner-dialog">添加轮播图</button>
</div>
<!-- Modal -->
<div class="modal fade" id="banner-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">times;</span></button>
<h4 class="modal-title" id="myModalLabel">轮播图</h4>
</div>
<div class="modal-body">
<form action="" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" placeholder="轮播图名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">图片</label>
<div class="col-sm-7">
<input type="text" class="form-control" name="img_url" placeholder="轮播图图片">
</div>
<button class="col-sm-2 btn btn-info">添加图片</button>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">跳转</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="link_url" placeholder="跳转链接">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">权重</label>
<div class="col-sm-10">
<input type="number" class="form-control" name="priority" placeholder="权重">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">保存</button>
</div>
</div>
</div>
</div>
{% endblock %}代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title %}
轮播图管理
{% endblock %}
{% block head %}
<style>
.top-box {
overflow: hidden;
background: #ecedf0;
padding: 10px 5px;
}
.top-box button {
float: right;
}
</style>
{% endblock %}
{% block page_title %}
{{ self.title() }}
{% endblock %}
{% block main_content %}
<div class="top-box">
<button class="btn btn-warning" data-toggle="modal" data-target="#banner-dialog">添加轮播图</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<td>名称</td>
<td>图片链接</td>
<td>优先级</td>
<td>跳转链接</td>
<td>创建日期</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr>
</tr>
</tbody>
</table>
<!-- Modal -->
<div class="modal fade" id="banner-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">times;</span></button>
<h4 class="modal-title" id="myModalLabel">轮播图</h4>
</div>
<div class="modal-body">
<form action="" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" placeholder="轮播图名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">图片</label>
<div class="col-sm-7">
<input type="text" class="form-control" name="img_url" placeholder="轮播图图片">
</div>
<button class="col-sm-2 btn btn-info">添加图片</button>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">跳转</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="link_url" placeholder="跳转链接">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">权重</label>
<div class="col-sm-10">
<input type="number" class="form-control" name="priority" placeholder="权重">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">保存</button>
</div>
</div>
</div>
</div>
{% endblock %}
![BBS论坛(七)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F682_1289953925.png&w=3840&q=75)
BBS论坛(七)
7.1.修改邮箱界面完成(1)cms/cms_resetemail.html代码语言:javascript复制{% extends 'cms/cms_base.html' %}
{% block title -%}
修改邮箱
{%- endblock %}
{% block head %}
{% endblock %}
{% block page_title -%}
{{ self.title() }}
{%- endblock %}
{% block main_content %}
<form action="" method="post">
<div class="form-container">
<div class="form-group">
<div class="input-group">
<input type="email" name="email" placeholder="新邮箱" class="form-control">
<span class="input-group-addon">获取验证码</span>
</div>
</div>
<div class="form-group">
<div class="input-group">
<input type="text" name="captcha" placeholder="邮箱验证码" class="form-control">
</div>
</div>
<div class="form-group">
<button class="btn btn-primary" id="submit">立即修改</button>
</div>
</div>
</form>
{% endblock %}(2)cms.views.py代码语言:javascript复制class ResetEmail(views.MethodView):
def get(self):
return render_template('cms/cms_resetemail.html')
def post(self):
pass
bp.add_url_rule('/resetemail/',view_func=ResetEmail.as_view('resetemail'))(3)cms/cms_base.html代码语言:javascript复制<li><a href="{{ url_for('cms.resetemail') }}">修改邮箱</a></li>(3)static/cms/css/base.css把cms_resetpwd.html中下面的样式放到base.css里面去,这样cms_resetemail和cms_resetpwd都可以用代码语言:javascript复制.form-container{
width: 300px;
}修改邮箱界面:7.2.Flask-mail的使用以及邮箱的配置(1)exts.py代码语言:javascript复制from flask_mail import Mail
mail = Mail()(2)Perfect_bbs.py代码语言:javascript复制from exts import db,mail
mail.init_app(app)(3)config.py代码语言:javascript复制MAIL_SERVER = "SMTP.qq.com"
MAIL_PORT = "587"
MAIL_USE_TLS = True
# MAIL_USE_SSL
MAIL_USERNAME = "[email protected]"
MAIL_PASSWORD = "zusbbabvfbdyqihxag"
MAIL_DEFAULT_SENDER = "[email protected]"(4)cms/views.py代码语言:javascript复制@bp.route('/email/')
def send_email():
#1.标题,2.收件人,3.发送的正文内容
message = Message(subject='derek论坛密码修改邮件发送',recipients=['[email protected]',],body='第一次测试发送邮件')
mail.send(message) #发送邮件
return '邮件发送成功'测试功能,访问地址就会发送邮件:http://127.0.0.1:5000/cms/email/
![QQ、微博、陌陌:社交难逃社交命](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F681_d89be5bb24.png&w=3840&q=75)
QQ、微博、陌陌:社交难逃社交命
1994年,大陆第一个互联网BBS——曙光站上线。之后,水木清华、猫扑、西祠胡同等BBS网站接连出现,国内社交媒体正式进入成长期。1999年,被腾讯人称为“饿死鬼小精灵”的OICQ诞生。腾讯QQ在即时通讯领域一骑绝尘,成为社交王者。2002年Blog传入中国,以此为原型的博客中国成立。随着“木子美”事件的助推,各大网站都在进军博客,新浪、网易等门户网站相继开火,门户博客全面爆发。2005年,校内网上线;2008年,开心网上线,5Q网、底片网等SNS网站陆续推出,SNS网站呈现出强劲生命力。2007年,被誉为“中国最早的微博”的饭否网上线,但饭否网两年后被关停。2009年,新浪微博悄然上线,正式进入微博时代。2011年,微信上线。此后,微信势如破竹,一步步攻入其他玩家的腹地,一举成为社交霸主。同年,陌陌踏入陌生人社交赛道,引起巨大反响。此后,小红书、抖音等互联网产品接连问世,也都不约而同地踏入社交领域。社交赛道硝烟滚滚,不断有新的社交产品进入市场,试图讲出新故事。时至今日,虽然QQ、微博、陌陌、微信等社交产品依旧活跃在应用榜上,但也有无数社交产品成为时代的眼泪,更有甚者都来不及被广大用户群知晓,就已经没了身影。从大红大紫到老态龙钟社交是人类社会永恒的需求,但没有哪类产品能够永垂不朽。纵使是QQ、微博、陌陌这些资深玩家也难免会力不从心,毕竟这条赛道永远都不缺讲故事的人。QQ的衰落集中表现为月活数的下滑。QQ在IM领域是当之无愧的头号玩家,而即时通讯软件成败的关键就在于活跃的用户基数,连年下滑的月活数拖垮了QQ。2016年二季度QQ月活就达到8.99亿,自2017年开始出现连续下滑迹象,此后两年,QQ的月活一直徘徊在8亿左右。至2019年一季度QQ的月活是8.23亿,而2020年一季度QQ的月活仅为6.94亿,一年时间跌了近1.3亿用户。至2021年一季度QQ的月活仅为6.06亿,一年时间再次跌去近9000万用户。而今年二季度QQ月活为5.91亿,至三季度,QQ的月活已经跌至5.74亿。换句话说,在2021年前三季度,QQ每季度平均跌掉1600万用户。从QQ连年下跌的月活来看,这一数据似乎还有下跌空间。微博的衰落表现在营收和净利的增长上。从微博历年财报来看,微博陷入了增长瓶颈。2018年-2020年微博总营收分别为17.19亿美元、17.67亿美元、16.9亿美元,增速分别为49.4%、2.8%、-4.4%;年净利润分别为5.73亿美元、4.93亿美元、3.15亿美元,增速分别为63.7%、-14%、-36%。这三年里微博的营收和净利润都不容乐观。陌陌的衰落体现在无力发展上。截止2021年第二季度,陌陌虽然已经持续26个季度盈利,但是用户数据的下滑坐实了陌陌的衰落。对陌陌而言,生存不是问题,发展才是问题。陌陌的月活和付费率都在失速。从2018年二季度开始,陌陌的月活同比增速就持续下滑,到2019年第四季度,陌陌的月活同比增速仅为1%。2020年第一季度,陌陌的月活直接进入负增长状态。付费用户同比增速也从2018年第三季度开始接连下滑,2020年一季度陌陌的付费用户同比减少120万。这也导致陌陌营收和净利双双下滑。从2020年第一季度到2021第二季度,陌陌的营收已经连续五个季度下滑。其中,2021年第一季度净营收同比下降3.4%,归属于陌陌公司的净利润同比下降14.3%。无论是用户持续减少的QQ,还是营收净利不断下滑的微博,抑或是发展乏力的陌陌都失去了想象空间,三大社交软件不约而同地走上了下坡路。QQ:学不会的断舍离QQ虽然完成了从PC时代向移动时代的跨越,但是却没学到新时代的“断舍离”观念。当然QQ也有做过减法,但是并没有从根本上解决问题,也未能调动优秀产品的活力。一方面,QQ摆脱不了PC端的包袱。PC时代见证了QQ的黄金十年,它无疑是PC时代最成功的社交产品。但时代的洪流滚滚向前,保留PC时代特征的QQ并不一定适合变化越来越快的移动时代。其一,缺乏移动IM的逻辑。移动互联网环境下,不管用户是否在线,软件都会默认用户永远在线,这也是移动IM的重要逻辑。而QQ的“离线、在线、隐身”等状态是PC时代的特性,至今仍保持着这一功能。PC时代的产品特点与移动时代的逻辑有所冲突,这一产品矛盾或许让QQ离用户需求越来越远。其二,臃肿的产品体系让其丢失了老年群体和办公场景。“大而全”是PC时代互联网产品的呈现方式,而移动时代更需要精而简。QQ所推出的厘米秀、微视、兴趣部落、QQ看点等功能让QQ的产品过重,各种花里胡哨的功能加剧了老年群体和办公群体的用户流失。从老年群体角度来看,QQ功能繁多,不易操作,而他们对新事物的接受能力较弱,面对功能复杂的QQ就只能绕道而行。从职场群体角度来看,QQ的信息驳杂,页面杂乱,极大地影响了办公效率,而钉钉等软件的兴起也取代了QQ的办公场景。最为重要的是,QQ的“年轻化”战略也让其贴上了“低龄化”的标签,越来越多的80后、90后出走QQ。另一方面,QQ的附属产品没有发挥出应有的价值。QQ在发展的过程中开发了一系列的附属产品,包括QQ空间、QQ农场、QQ钱包等玩法。这些附属产品对于早期的QQ而言,有完善生态的作用,也有各自的高光时刻,但无法持续为QQ的事业发光发热。拿QQ钱包来看,QQ钱包缺乏生活支付场景,难发挥支付价值。冲Q币、冲会员等形式是QQ钱包最早的消费场景,此后QQ就在“游戏、二次元、直播”等娱乐场景上狂奔。而其他选手早已发力生活场景,成为重要支付方式之一,比如微信支付、支付宝等。QQ也因缺乏生活支付场景而无法跻身到支付领域中去,难以满足用户的支付需求。微博:自我束缚微博的危机源于不吸取教训,任凭流量裹挟平台,将自己置于险地。首先,微博没有找到新的增长引擎。微博的营收业务分为广告业务和增值业务两部分,但从微博近年财报可以看出,微博每年的广告业务占总营收的九成左右。这意味着,微博下一步的发展还要继续依赖广告收入的增长,但广告业务的不稳定因素还有很多。其次,微博的走向正在偏离社交媒体的轨道。社交媒体是人们彼此之间用来分享意见、见解、经验和观点的平台,让普罗大众关注到公共事务,并为此表达自己的看法,参与社会事务之中。这也是新浪微博能够打赢其他三大微博玩家的原因,而现在微博正在丢掉它的优势。一是变了味的热搜。常听人戏称:微博养活新浪,热搜养活微博,买卖热搜已经不是秘密了。据财经天下周刊报道,热搜三条的刊例价为100万左右;开屏的价格在200-300万左右,这还是一天的价格。热搜不再是报道时事,而是有钱就能上,比如2018年“紫光阁地沟油”的热搜闹剧,热搜早就不是关注时事的地方了。二是失了控的饭圈经济。饭圈经济为微博的营收带来巨大贡献,但失控的饭圈也让微博无力招架。在微博上,为了自己的爱豆谩骂互撕是常有的事,比如227事件;而为爱豆氪金打榜也不足为奇,比如周杰伦和蔡徐坤的粉丝打榜大战、“倒奶”事件。饭圈经济让微博多了几分乌烟,也在不断挤出其他用户群体。三是监管不到位。众所周知,微博不生产内容,只是内容发布的审核方。既然微博有审核之责,理应严格审查发布在平台上的信息,合理筛选公共信息,去虚留真。而微博并没有吸取早年“大V入狱”事件的教训,再一次变成舆论的操纵场和虚假消息的发源地。微博的生态在恶化,让用户的体验越来越差。用户无法从微博获得想要的公共信息,反而被种种乱象包裹,自然会迁徙到其他社交媒体平台。最后,失败的打法在直播领域和短视频领域败北。微博早在2013年就看到了短视频风口,投资一下科技,到给予秒拍流量扶持,都彰显着微博的短视频野心。但是,秒拍趋向微博的中心化思维,根本抓不住用户的眼球,而抖快依靠去中心化蹿红后,秒拍毫无招架之力。之后微博也推出多款短视频应用,但风口已逝,即使重启微博视频号也没能激起水花。陌陌:扶不起的社交业务虽然陌陌的创始人始终强调陌陌是个社交平台,但从其营收结构来看,仅占三成营收的社交业务并不能撑起陌陌的商业化野心,陌陌在一点点丢掉社交基本盘。一来鱼龙混杂的社交挫伤了用户的积极性。陌生人社交的门槛本就不高,一旦对平台用户疏于管理,各种问题也就悄然而来。平台内男性用户的骚扰让女性用户逃离陌陌,失去了女性用户,男性用户自然会对平台失去信心。二来广撒网战略也不能为陌陌留住用户。陌陌推出了是他、瞧瞧、Cue、赫兹、ZAO、对对等多款社交产品,试图从多维度挤进社交领域,但多元的社交产品矩阵也没能在社交市场激起水花,唯一爆火的ZAO也因为网络数据安全问题而迅速暴毙。除了自己孵化的APP没能为陌陌带来助力,收购的探探也成了陌陌的拖累。自完成收购后,探探的付费用户增长极其有限。数据显示,探探的付费用户占陌陌总体付费中的26.7%-35.7%。换言之,探探付费用户的增减直接影响陌陌的营收。虽然探探的亏损在收窄,但三年来都处于亏损状态的探探拉低了陌陌的净利润增长。三来陌生人社交本身的流量已经接近尾声。随着互联网交友的方式多元化,用户对交友平台的选择也更加多元化。在各种各样的社交模式冲击下,传统的陌生人交友形式已经不再具有吸引力。而疫情也缩减了陌生人交友的需求,加速了陌陌社交业务的溃败。陌陌疏于管理的社交业务滋生出种种乱象,既催生了其他陌生人社交平台的崛起,又加速了平台流量的流失。时代洗礼22岁的QQ与11岁的微博和陌陌共同走过了移动社交时代、视频社交时代,现在正在迈向虚拟社交时代。前两场社交厮杀,它们平稳渡过,但现在沉疴缠身的它们还能顺利挺过第三场厮杀吗?移动社交时代:微信抢人微信诞生之初既是为了对抗米聊对QQ的冲击,也是为了拓展腾讯的社交群体。后来,微信不仅打败了米聊,也成了其他社交产品的噩梦。对于即时通讯软件来说,简单就是最大的成功。彼时的QQ经过十余年的积累,为用户提供的功能越来越多,却让不少中老年群体无从下手。于是,操作简单、界面简单的微信让社交也变得简单起来。直白的聊天方式赢得了老年人以及职场人士的喜爱。随着微信对熟人社交关系链的沉淀,以亲人、朋友、同事等为核心的熟人社交让用户们不得不留在微信或转投微信,加剧了QQ用户流失。而微信又逐渐发展成一款生活综合软件,集支付、出行、防疫等功能于一体,实现了生活场景的全覆盖,进一步带走QQ用户。对微博来说2013年是最难忘的一年,但这都要从2012年微信推出微信公众平台功能说起。当微信高调地成为移动社交赛道的焦点后,越来越多的微博大V、名人开通自己的微信公众平台,一头扎进熟人社交关系中,通过公众号写作来吸引用户,走向自媒体道路。据《中国互联网络发展状况统计报告》显示,2013年,微博用户下滑了22.8%,微博产品的使用时间仅增加了12.7%。截至2013年年底,手机微博用户数为1.96亿,较2012年年底减少了596万。同时,手机微博的使用率仅为39.3%,比2012年底降低了8.9个百分点。在互联网渗透期的2003年,微博的用户使用率接连下滑,对微博的打击不可谓不小。对陌陌来说,微信简直就是悬在头顶的剑。2011年8月4日陌陌上线,而微信8月3号上线LBS功能——附近的人。微信除了给陌陌带来压迫感,也给陌陌带来了不可逆的用户流失。当两个陌生人在陌陌上聊得非常投机,已经发展出稳定的社交关系后,自然会转向熟人社交,进而流入微信,彻底进入熟人社交阶段,陌陌的活跃用户就面临彻底流失。在陌生人关系转化中,陌陌成了导流工具,微信的熟人社交反而成了最大赢家。视频社交时代:视频平台抢用户时长当流量红利已经见顶,用户时长成了互联网赛事里争夺的焦点。纵观这场赛事,抖音、快手、B站等视频平台成了用户停留最久的软件。据极光大数据显示,2021年Q3快手用户日使用时长均值达到125.3分钟,同比增长30.9%,而抖音的日使用时长均值更是达到144.6分钟。另据QuestMobil统计显示,2019年3月,移动社交、短视频的日均使用时长分别是982亿分钟、358亿分钟;到了今年6月,这两个数字依次为953亿分钟、888亿分钟,短视频的用户时长实现了148%的增长。由数据可知,用户们每天有两个多小时都在刷短视频,短视频占据了人们越来越多的时间。而据《娱乐传媒行业深度报告》显示,QQ 用户时长从约50分钟降至30分钟左右。QQ不仅留不住用户,连用户时长也逐渐下滑,最后只剩下满是记忆的通讯录。而微博的用户时长也更不容乐观。据易观千帆统计显示,2019年5月-2020年4月,微博月均用户使用时长在10小时上下徘徊,换算下来,用户平均一天使用时长20分钟,相比于抖、快的用户时长相距甚远,并且根据走势来看,微博的日均用户使用时长还在下降。微博丢掉的不仅是用户时长,还有广告业务。据微博招股书披露,其广告客户数量也在不断下滑,2018年-2020年微博的广告客户数量分别为290万、160万、240万。至今年6月,微博的广告主已经腰斩至60万。在社交赛道里,不仅微博的商业化受到短视频平台的阻击,短视频平台也在蚕食着陌陌的商业能力。陌陌目前的主要营收来自秀场直播业务,这势必需要大量美女主播,但抖、快两大平台巨大的流量与超强的印钞能力也抢走了陌陌的主播资源。据媒体报道,受到疫情和抖音对主播大力扶植的影响,陌陌旗下的主播40%都出走抖音。互联网公司的变现方式无外乎广告业务、增值业务、付费业务这几类,但在格局已定的情况下,短视频平台想要分一杯羹,就需要从其他玩家身上割下来几块肉,不幸的是,QQ、微博、陌陌这三位社交赛道细分领域的头部玩家率先成为被割肉的对象。虚拟社交时代:社交元宇宙成劲敌社交赛道总有新玩法,随着扎克伯格将Facebook集团名字换成“Meta”,再次将社交元宇宙推上新高度。而国内也早已涉及社交元宇宙。比如主打灵魂社交的Soul、百度推出的希壤等社交元宇宙玩法正在重塑社交赛道的话语权,这无疑会冲击老牌社交平台。其实,社交元宇宙最大的优势就是虚拟化。每个用户在社交中都有一个虚拟身份,不用顾虑现实社交中存在的种种问题,将现实生活与社交元宇宙分割开来。社交元宇宙平台依托5G、XR、实时互联网等技术,辅以游戏等多元玩法,为用户打造一种沉浸式虚拟社交,给用户圈画出一个理想世界。社交元宇宙正在成为社交的新宠,比如国内社交元宇宙黑马Soul已经展现出强劲的活力。据Soul的招股书显示,Soul的DAU已达千万量级,同比增长94.4%。Soul 的日均DAU打开次数为24次,为行业最高。从2020年7月开始至今,Soul每月的MAU用户增长速度,平均保持在105%以上。而在用户粘性上,2021年3月,每月活跃天数超15天的比例达56.4%。2020年12月活跃超15天的用户中,有78.4%的用户在三个月后仍维持同样的活跃度。另招股书显示,2019年到2021年一季度,Soul营收分别为7070万元、4.98亿元、2.38亿元,2020年的营收在同比增长604.3%的情况下,今年第一季度同比再增长260%。Soul以一种强劲的增长势能正在创造社交新焦点。QQ、微博、陌陌:逃不出社交命QQ、微博和陌陌各自代表着社交细分赛道的牌面,一路走来风浪无数,但都顽强存活下来了。QQ尝试定位年轻化,拉动月活增长。微博和陌陌尝试转型多元化,探索更加健康的商业结构。这表明,它们并非坐以待毙,只是目前都没有太大成效。那么,QQ、微博、陌陌的社交命运,到底该何去何从呢?一是如早期的社交先烈们一般留在回忆中。偷菜、抢车位的开心网,“找同学,上人人”的人人网,无一不是社交赛道的佼佼者,都有过各自的辉煌年代。但太阳总会有下山的时候,无论散发着多耀眼的光芒,也会从西边落下。开心网和人人网成为80后和90后的美好回忆,QQ、微博、陌陌也会成为一代人的回忆。二是主动出击,扳回一城。在玩法新奇、对手林立的社交赛道,QQ、微博、陌陌等老玩家想要继续占据一席之地,势必要一改过去的防守状态,以攻代守,改变自身的被动局面。纵观社交赛道的形态变化,经历了从基础社交到内容社交再到精神社交的演变。这表明,用户需求并不局限于已有的社会性社交,而是转向具有新意的“下一代社交”。“下一代社交”需要依托技术,帮助所有人摆脱传统的“中国式孤独”,在任何语境下都给用户带来愉悦的精神享受。对于QQ、微博、陌陌来说,在基于用户心理的情况下,依托技术来建立新的社交关系,在满足用户基础社交体验之外,也考虑到用户的心理需求。或许,通过对平台的精细化运营,能够完成对存量用户的争夺,以及对沉默用户的召回。
![BBS论坛(二十)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F680_da97a54e91.jpeg&w=3840&q=75)
BBS论坛(二十)
20.1.cms添加轮播图后台逻辑代码完成(1)apps/models.py代码语言:javascript复制from exts import db
from datetime import datetime
class BannerModel(db.Model):
__tablename__ = 'banner'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(255), nullable=False)
img_url = db.Column(db.String(255), nullable=False)
link_url = db.Column(db.String(255), nullable=False)
priority = db.Column(db.Integer, default=0)
create_time = db.Column(db.DateTime, default=datetime.now)(2)manage.py代码语言:javascript复制from apps.models import BannerModel(3)生成到数据库代码语言:javascript复制python manage.py db migrate
python manage.py db upgrade(4)cms/forms.py代码语言:javascript复制class AddBannerForm(BaseForm):
name=StringField(validators=[InputRequired(message='请输入轮播图名称')])
img_url=StringField(validators=[InputRequired(message='请输入轮播图链接')])
link_url=StringField(validators=[InputRequired(message='请输入轮播图跳转链接')])
priority=IntegerField(validators=[InputRequired(message='请输入轮播图优先级')])(5)cms/views.py代码语言:javascript复制@bp.route('/abanner/',methods=['POST'])
def abanner():
form=AddBannerForm(request.form)
if form.validate():
name=form.name.data
img_url=form.img_url.data
link_url=form.link_url.data
priority=form.priority.data
banner=BannerModel(name=name,img_url=img_url,link_url=link_url,priority=priority)
db.session.add(banner)
db.session.commit()
return restful.success()
else:
return restful.params_error(message=form.get_error())20.2.cms添加轮播图前台逻辑完成(1)cms/js/banner.js代码语言:javascript复制$(function () {
$('#save_banner_btn').click(function (event) {
event.preventDefault();
var dialog = $('#banner-dialog');
var nameInput = $("input[name='name']");
var imgInput = $("input[name='img_url']");
var linkInput = $("input[name='link_url']");
var priorityInput = $("input[name='priority']");
var name = nameInput.val();
var img_url = imgInput.val();
var link_url = linkInput.val();
var priority = priorityInput.val();
if (!name || !img_url || !link_url || !priority) {
zlalert.alertInfo('请输入完整的轮播图数据');
return;
}
zlajax.post({
'url': '/cms/abanner/',
'data': {
'name': name,
'img_url': img_url,
'link_url': link_url,
'priority': priority
},
'success': function (data) {
if (data['code'] == 200) {
dialog.modal('hide');
window.location.reload()
} else {
zlalert.alertInfo(data['message']);
}
},
'fail': function (error) {
zlalert.alertNetworkError()
}
});
});
});(2)cms/cms_banners.html代码语言:javascript复制{% from 'common/_macros.html' import static %}
<script src="{{ static('cms/js/banners.js') }}"></script>(3)cms/views.py代码语言:javascript复制@bp.route('/banners/')
@login_required
def banners():
banners = BannerModel.query.all()
return render_template('cms/cms_banners.html',banners=banners)(4)cms_banners.html代码语言:javascript复制<tbody>
{% for banner in banners %}
<tr>
<td>{{ banner.name }}</td>
<td><a href="{{ banner.img_url }}" target="_blank">{{ banner.img_url }}</a></td>
<td><a href="{{ banner.link_url }}" target="_blank">{{ banner.link_url }}</a></td>
<td>{{ banner.priority }}</td>
<td>{{ banner.create_time }}</td>
<td>
<button class="btn btn-default btn-xs edit-banner-btn">编辑</button>
<button class="btn btn-danger btn-xs delete-banner-btn">删除</button>
</td>
</tr>
{% endfor %}
</tbody>
![BBS论坛(十八)](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F679_9916ef5e69.jpeg&w=3840&q=75)
BBS论坛(十八)
18.首页轮播图实现(1)front/css/front_base.css代码语言:javascript复制.main-container{
width: 990px;
margin: 0 auto;
overflow: hidden;
}
.lg-container{
width: 730px;
float:left;
}
.sm-container{
width: 250px;
float:right;
}(2)front_base.html代码语言:javascript复制<link rel="stylesheet" href="{{ url_for('static',filename='front/css/front_base.css') }}">
<div class="main-container">
{% block body %}
{% endblock %}
</div>(3)front_index.html代码语言:javascript复制{% extends "front/front_base.html" %}
{% block title %}
仙剑论坛
{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ static('front/css/front_index.css') }}">
{% endblock %}
{% block body %}
<div class="lg-container">
<div id="carousel-example-generic" class="carousel slide index-banner" data-ride="carousel">
<!-- 指示器 -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- 轮播图-->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="https://static-image.xfz.cn/1512989310_955.jpg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
<div class="item">
<img src="https://static-image.xfz.cn/1528079965_535.jpeg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
...
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<div class="sm-container">
</div>
{% endblock %}(4)front/css/front_index.css代码语言:javascript复制.index-banner{
border-radius: 10px;
overflow: hidden;
height: 190px;
}
.index-banner img{
height: 190px;
}
![#自媒体#新媒体课堂——自媒体平台知多少?自媒体平台有哪些?](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F678_cb0e044a94.png&w=3840&q=75)
#自媒体#新媒体课堂——自媒体平台知多少?自媒体平台有哪些?
自媒体带起了一波创业者的高潮,做自媒体的主要就是两类人,要么是为了流量,获得用户关注;要么是为了阅读量,广告变现。说白了就是为了名利!有很多人都想做自媒体,但是该怎么做才好呢?做自媒体,写文章虽然重要,但是发文章比写重要10倍以上,只有让更多的人看到你的文章,你的文章才能给你带来更大的价值,一篇文章写出来,你发的平台不对,也不行。今天知道君整理了一些可以免费注册与发布的自媒体平台,如果你把文章发布到这些自媒体平台,你的每篇文章最少都有几万人看到,效果怎么样, 就不用多说了。现在直接分享给大家:微信公众平台微信公众平台,给个人、企业和组织提供业务服务与用户管理能力的全新服务平台。… 给企业和组织提供更强大的业务服务与用户管理能力,帮助企业快速实现全新的公众号服务平台是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.weixin.qq.com今日头条今日头条是一款基于数据挖掘的推荐引擎产品,它为用户推荐有价值的、个性化的信息,提供连接人与信息的新型服务,是国内移动互联网领域成长最快的产品服务之一是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.toutiao.com/百度百家百家是百度新闻的原创内容类平台。每日发布的优质内容将会在百度新闻的网页版、移动端呈现,并被百度搜索和百度其他产品线收录。是否免费:免费操作难度:简单应用类型:全部应用网址:http://baijia.baidu.com/搜狐媒体平台搜狐媒体平台是在搜狐门户改革背景下全新打造的内容发布和分类分发全平台。各个行业的优质内容供给者(媒体、自媒体)均可免费申请入驻,为搜狐提供内容;利用搜狐强大的媒体影响力,入驻媒体和自媒体可获取自己的用户,提升个人的品牌影响力是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.sohu.com/一点资讯一点资讯是一款高度智能的新闻资讯应用,通过它你可以搜索并订阅任意关键词,它会自动帮你聚合整理并实时更新相关资讯,同时会智能分析你的兴趣爱好,为你推荐感兴趣的内容。看新闻资讯,一点就够了!是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.yidianzixun.com/网易媒体平台网易订阅,聚合旅游、时尚、财经、科技资讯、时事新闻、RSS等众多内容,提供个性化的阅读服务是否免费:免费操作难度:简单应用类型:全部应用网址:http://dy.163.com/wemedia/login.html企鹅媒体平台企鹅媒体平台是2016年3月1日,企鹅媒体平台正式推出,腾讯将提供四个方面的能力。是否免费:免费操作难度:简单应用类型:全部应用网址:https://om.qq.com/userAuth/index北京时间号北京时间互联网门户全新领导者,依托强大的推荐引擎与专业的媒体人团队为用户实时呈现最具价值的新鲜资讯。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.btime.com/QQ公众号QQ公众平台聚合着无限可能。凭借16年来积累的8亿用户资源,依托强势平台技术、数据沉淀和社交关系,QQ公众平台将有效聚集品牌和消费者,以开放合作的姿态与你一起打造未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.qq.com/凤凰自媒体“凤凰自媒体”正式更名为“凤凰号”。据了解,凤凰自媒体平台更名后,希望能加快品牌特色化进程,深耕高质量内容领域,由此形成行业差异化竞争格局,实现优质文章在凤凰新闻客户端、凤凰网、手机凤凰网、凤凰视频客户端等渠道的有效分发。是否免费:免费操作难度:简单应用类型:全部应用网址:http://fhh.ifeng.com/login大鱼号大鱼号是阿里文娱体系为内容创作者提供的统一账号。大鱼号实现了阿里文娱体系一点接入,多点分发。内容创作者一点接入大鱼号,上传图文/视频可被分发到UC、优酷、土豆、淘系客户端,未来还会扩展到豌豆荚、神马搜索、PP助手等。是否免费:免费操作难度:简单应用类型:全部应用网址:http://mp.uc.cn/index.html知乎一个真实的网络问答社区,帮助你寻找答案,分享知识。..是否免费:免费操作难度:简单应用类型:全部应用网址:https://www.zhihu.com/钛媒体【钛媒体官方网站】钛媒体是国内首家TMT公司人社群媒体,最有钛度的一人一媒体平台,集信息交流融合、IT技术信息、新媒体于一身的媒体平台。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.tmtpost.com/LIKE.TG+社区LIKE.TG最新又推出了一款扶持计划-『自媒体分享计划』满足条件的自媒体,入驻LIKE.TG+社区,可分享总价值百万资源包是否免费:免费操作难度:困难应用类型:全部应用网址:https://cloud.tencent.com/developer/support-plan?invite_code=oc38tj48tn8qhttp://www.tmtpost.com/虎嗅网聚合优质的创新信息与人群,捕获精选|深度|犀利的商业科技资讯。在虎嗅,不错过互联网的每个重要时刻。是否免费:免费操作难度:简单应用类型:全部应用网址:https://www.huxiu.com/砍柴网砍柴网创立于2013年,是一家拥有全球视野的前沿科技媒体,我们始终秉承观点独到、全面深入、有料有趣的宗旨,在科技与人文之间寻找商业新价值,坚持以人文的视角解读科技,用专业的精神剖析时代,孜孜不倦探索科技与商业的未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.ikanchai.com/i黑马i黑马是面向创业者的创新型综合服务平台,掌握创业创新领域强有力话语权的媒体矩阵,致力于帮助创业者获得投资、人才、宣传和经验。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.iheima.com/雷锋网雷锋网是国内最早关注人工智能和智能硬件领域的互联网科技媒体,内容涵盖人工智能、智能硬件、机器人、智能驾驶、ARVR、网络安全、物联网、未来医疗、金融科技等9大领域。雷锋网致力于连接和服务学术界、工业界与投资界,为用户提供更专业的互联网科技资讯和培训服务,让用户读懂智能与未来。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.leiphone.com/猎云网猎云网坚守用心服务创业者的理念,专注创业创新,互联网创业项目推荐,关注新产品、新公司、新模式,以原创独家报道、分析以及美国硅谷的一手报道闻名业界。为创业者、投资人及相关业内人士提供交流学习、资源对接的桥梁。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.lieyunwang.com/锌媒体锌媒体是一个关注前沿科技资讯、移动互联网,发现以及商业创新价值的泛科技自媒体平台。精选最新科技新闻,分享即时的移动互联网行业动态和以及提供最具商业价值的互联网创业案例,投资案例。提供绝对给力的干货、,在科技与人文之间挖掘商业新价值。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.xinmeti.com/派代网派代网定位为中国电子商务的入口,目前是中国最活跃、最具影响力的电子商务行业交流平台,聚集了大量的电子商务领军企业创始人群。提供电商学习、人才招聘、企业贷款等电子商务综合服务。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.paidai.com/简书致力于开发维护一套集合文字的书写、编集、发布功能于一体的在线写作编辑工具是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.jianshu.com/亿欧网亿欧是一家专注于新科技、新理念与各产业结合,以助力产业创新升级为使命的服务平台。亿欧旗下有4款产品,分别是亿欧网、视也、天窗、企服盒子。自2014年2月9日开始运营后,迅速成为互联网创业者和产业创新者的首选学习平台,是上百家知名企业的首选商业合作伙伴;先后获得盈动资本、高榕资本、盛景网联领投的三轮融资是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.iyiou.com/思达派思达派是专注创业服务市场的新媒体平台,定位“创业干货分享”,一站集成创业经验、教训等干货,帮助创业者少走弯路。同时还将举办各种线下创业分享和交流活动,分享创业心得,对接人脉、资本、以及公关推广等资源。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.startup-partner.com/界面界面是最受中国中产阶级欢迎的新闻及商业社交平台,旗下拥有精品新闻业务界面新闻、专业投资资讯平台摩尔金融及中国最大独立设计师电商网站尤物。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.jiemian.com/爱范儿聚焦新创和消费主题的科技媒体,成立于 2008 年 10 月,关注产品及体验,致力于“独立,前瞻,深入”的原创报道和分析评论,是国内唯一一家在产业和产品领域同时具有强势影响力的科技媒体。旗下现有 ifanr.com、SocialBase.cn、AppSolution、玩物志、创业及产品社区 MindStore 等多个细分领域的知名产品。是否免费:免费操作难度:简单应用类型:全部应用网址:http://www.ifanr.com/36氪36氪为您提供创业资讯、科技新闻、投融资对接、股权投资、极速融资等创业服务,致力成为创业者可以依赖的创业服务平台,为创业者提供最好的产品和服务。是否免费:免费操作难度:简单应用类型:全部应用网址:http://36kr.com如果一篇文章在一个平台一天有100个阅读量,在50个平台上就是5000阅读,那么10天呢,一年356天呢,可能前期会辛苦一点,但是你需要坚持,越到后面,你在互联网上发布的文章越多,加你的人也会越多,而且这些文章将会在多年以后都能够继续为你带来流量,有的人两年前写的文章,现在还有人看了还会加v信。外加两个,趣头条,惠头条。有的人可能会问,这么多平台,发文章比写文章还累!额。。。。。。你需要学会找工具,早就有人开发出来了一键发布功能,一篇文章可以同时发布到多个自媒体平台上!什么工具呢?百度一下,你就知道!以上,是今天给大家提供的一些思路,希望对大家有帮助!这些仅仅是各大门户网站的自媒体开放平台,没有精确到各种类型的全部平台,如小视频类app、综合视频类网站都没有开始说,由于篇幅的原因,留到以后再进行补充吧。
![RT论坛_Thread](/_next/image?url=https%3A%2F%2Fcms.like.tg%2Fuploads%2F677_216aa4455d.png&w=3840&q=75)
RT论坛_Thread
大家好,又见面了,我是你们的朋友全栈君。
文章主要参考:https://blog.csdn.net/killercode11/article/details/104290949,借鉴了rt_hw_console_getchar()的定义。
文章目录将 FinSH源码添加到工程开启 FinSH定义终端读取函数体验 FinSH遇到的问题 本文不介绍 RT-Thread 的串口配置,如有需要,可以参考:重映射串口到 rt_kprintf 函数
将 FinSH源码添加到工程FinSH源码在 RT-Thread 源码目录的 components\finsh\ 目录下,将其导入到工程中,具体操作这里不做介绍,记得要把头文件包含进来,开启 FinSH修改 rtconfig.h,开启 finsh config,下面是使用 Configuration Wizard 向导进行图形化配置,
其实就是将 finsh_fonfig.h 头文件包含到工程中,这个头文件里有 FisSH 的基本参数配置,定义终端读取函数移植完 FinSH 源码后,初次编译一般会报一个错误,需要将弱化函数 rt_hw_console_getchar() 里的 #error 这行屏蔽掉(记得先把该文件的只读属性关闭)
接着我们在 board.c 文件手动重新定义 rt_hw_console_getchar() 函数,函数内容如下,这是标准库版本,如果需要 HAL库版本,可以参考文章最前面的链接。代码语言:javascript复制char rt_hw_console_getchar(void)
{
/* Note: the initial value of ch must < 0 */
int ch = -1;
if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) != RESET)
{
//USART_ClearITPendingBit(USART_DEBUG, USART_FLAG_RXNE);
ch = USART_ReceiveData(DEBUG_USARTx) 0xFF;
}
else
{
if(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_ORE) != RESET)
{
USART_ClearITPendingBit(DEBUG_USARTx, USART_FLAG_ORE);
}
rt_thread_mdelay(10);
}
return ch;
} Jetbrains全家桶1年46,售后保障稳定 体验 FinSH我使用 SSCOM 来作为终端,效果还不错,命令直接在显示窗口里输入。
或许有人会问为什么不用 PuTTy、XShell 这类常用的终端软件,我也想用,但连接上这类终端软件后,开发板就不运行了。遇到的问题1.段错误导致这种错误的原因有很多种,比如 RT_MAIN_THREAD_STACK_SIZE 太小,而我是因为 RT_THREAD_PRIORITY_MAX 设置得太小(只设置为 8),小于 FINSH_THREAD_PRIORITY 的默认值 21,所以解决办法就是将 FINSH 的线程优先级(数值)改小或者将系统优先级最大值(数值范围)改大。2.终端工具无法打印使用 PuTTy、XShell,终端没反应,且开发板会卡住。初步分析的原因是 “正点原子一键下载电路和终端工具冲突”(网上他人结论),所以只能用串口调试助手来操作 Finsh 了。3.程序不运行这个问题可能的原因也很多,但需要注意的是:如果要使用 FinSH,就不能开启串口中断,至于为什么,我目前也没去了解。版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。 发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/210436.html原文链接:https://javaforall.cn