MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
VUE的绑定语法十分有规律,初学者使用并不困难,首先看一下绑定流程
........
<div id="content">
{{ message }}
</div>
........
<script src="jquery.min.js"></script>
<script src="vue.min.js"></script>
<script>
var vue = new Vue({
el: "#content",
data: {
message: "hello world"
},
methods: {
say_hello: function(){
alert("hello world")
}
}
})
</script>
用来指定数据绑定的范围,只有在这个范围之内才可以使用vue绑定范围,采用JQ选择器进行指定。
data节点就是vue的data节点用作数据绑定,data下的最好是一个对象,对象名取名为当前组件名+info组成,对象下再去写需要绑定的字段信息,这样做的目的是为 多个组件之间取相同的字段名称 导致影响显示效果。
初始化节点,用来初始化加载后台数据,是一个功能函数,在页面加载之后自动执行,用来加载页面初始化数据,比如第一页数据。
组件在加载时执行的代码可以放到这里,访问method下的方法时必须使用v-on进行绑定,触发函数执行。
主要用于属性绑定,Vue官方提供了一个简写方式 :bind,我们可以给v-bind:class 一个对象,以动态地切换class。注意:v-bind:class指令可以与普通的class特性共存
<button v-on:click="btnClick">按钮</button>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
active: 'active',
line: 'line',
isActive: true,
isLine: true,
},
methods: {
btnClick: function () {
this.isActive = !this.isActive;
},
getClasses: function () {
return {active: this.isActive, line: this.isLine};
},
getClassesArray: function () {
return [this.active, this.isLine];
}
}
});
</script>
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
HTML
<div id="app">
<div v-if=" role == 'admin' || role == 'super_admin' ">您好;admin</div>
<div v-else-if=" role == 'hr' ">您好:hr</div>
<div v-else="">您无权访问</div>
</div>
js
var vm = new Vue({
el:"#app",
data:{
role:"super_admin",
}
});
当需要将一个数组遍历或枚举一个对象循环显示时候,我常用的就是列表渲染指令v-for. 它需要结合着in 或者of来使用,如下
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div id='app'>
<p v-for="user in listObj">--id--{{user.id}} --姓名--{{user.name}}</p>
</div>
</body>
<script src="vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
listObj:[
{id:1, name:'武松'},
{id:2, name:'鲁智深'},
{id:3, name:'林冲'},
{id:4, name:'宋江'},
{id:5, name:'时迁'},
{id:6, name:'李逵'}
]
}
});
</script>
</html>
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
用在普通元素上时,只能监听原生DOM事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
import os
class Dubug:
BASE_DIR = os.path.dirname(
os.path.abspath(__file__)
)
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(BASE_DIR, "db.sqlite")
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = "123abc"
DEBUG = True
class Runner:
BASE_DIR = os.path.dirname(
os.path.abspath(__file__)
)
SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(BASE_DIR, "run.sqlite")
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = "123abc"
DEBUG = False
import os
import datetime
from functools import wraps
from flask import render_template
from flask import request #负责接收数据的参数
from flask import redirect #跳转页面
from flask import session
from FlaskPro import csrf
from FlaskPro.OAPrint import oaPro
from FlaskPro.models import *
from FlaskPro.OAPrint.forms import *
def valid_person(fun):
@wraps(fun)
def inner(*args, **kwargs):
user_id = request.cookies.get("user_id")
user = Person.query.get(int(user_id))
user_positon = user.per_pos.id
boss = Position.query.filter_by(p_name="董事长").first()
hr = Position.query.filter_by(p_name = "HR").first()
if user_positon in [hr.id,boss.id]:
return fun(*args, **kwargs)
else:
return "抱歉,你没有访问这个页面的权限"
return inner
def loginValid(fun):
@wraps(fun) #这个装饰器可以保证被装饰后采用原理的名字
def inner(*args,**kwargs):
username = request.cookies.get("user_name") # 从cookie当中获取数据
user_id = request.cookies.get("user_id")
s_user_id = session.get("user_id") #获取session当中的值
user = Person.query.filter_by(per_id=username, id=user_id).first() # 开始检测cookie的是否正确
if user:
return fun(*args,**kwargs)
else:
return redirect("/login/")
return inner
@oaPro.route("/depart/")
@loginValid
def depart():
depart_list = Department.query.all()
return render_template("department.html",**locals())
@oaPro.route("/add_department/",methods = ["GET","POST"])
@loginValid
def add_department():
if request.method == "POST":
#request.method 返回请求的方式,注意,页面加载是get请求
d_name = request.form.get("d_name")
desc = request.form.get("description")
#保存数据
dep = Department()
dep.d_name = d_name
dep.d_description = desc
dep.save()
return redirect("/depart/")
return render_template("add_department.html")
@oaPro.route("/edit_department/<int:d_id>/",methods = ["GET","POST"])
@loginValid
def edit_department(d_id):
d = Department.query.get(d_id)
if request.method == "POST":
d_name = request.form.get("name")
d_description = request.form.get("description")
d.d_name = d_name
d.d_description = d_description
d.update()
return redirect("/depart/")
return render_template("edit_department.html",**locals())
@oaPro.route("/del_department/<int:d_id>/")
@loginValid
def del_department(d_id):
d = Department.query.get(d_id)
d.delete()
return redirect("/depart/")
@oaPro.route("/position/<int:d_id>/",methods = ["GET","POST"])
@loginValid
def position(d_id):
#查询当前部门对于的所有职位
d = Department.query.get(d_id)
if request.method == "POST":
p_id = request.form.get("p_id")
name = request.form.get("name")
level = request.form.get("level")
if p_id: #如果pid有值
p = Position.query.get(p_id) #获取当前数据
else: #如果pid没有值
p = Position() #创建一条新的数据
#保存职位信息
p.p_name = name
p.p_level = level
p.p_department = d_id
p.save()
# 部门所有对应的职位
p_list = d.d_position
return render_template("position.html",**locals())
@oaPro.route("/del_position/<int:p_id>/")
@loginValid
def del_position(p_id):
p = Position.query.get(p_id)
p.delete()
url = request.referrer
print(url)
return redirect(url)
from flask import jsonify
@oaPro.route("/get_position/<int:p_id>/")
@loginValid
def get_position(p_id):
p = Position.query.get(p_id) #获取数据
result = {"id": p.id,"p_name": p.p_name,"p_level": p.p_level} #定义返回字典
return jsonify(result) #封装为json进行返回
@oaPro.route("/person/")
@valid_person
@loginValid
def person():
page = int(request.args.get("page",1)) #尝试获取get请求的参数,如果没有,默认为1
p_list = Person.query.paginate(page, 2)
if page - 2 <= 0:
start = 0
else:
start = page - 2
if page+3 > p_list.pages:
end = p_list.pages
else:
end = page + 3
page_range = list(
range(1,p_list.pages+1)
)[start:end]#形成页码列表
return render_template("person.html",**locals())
import hashlib
def setPassword(password):
md5 = hashlib.md5() #创建md5实例
md5.update(password.encode()) #进行加密
result = md5.hexdigest() #获取加密=结果
return result
@oaPro.route("/add_person/",methods = ["GET","POST"])
@valid_person
@loginValid
def add_person():
position_list = Position.query.all()
department_list = Department.query.all()
if request.method == "POST":
#接收前端的数据
username = request.form.get("username")
password = request.form.get("password")
nickname = request.form.get("nickname")
gender = request.form.get("gender")
age = request.form.get("age")
phone = request.form.get("phone")
email = request.form.get("email")
address = request.form.get("address")
department_id = request.form.get("department_id")
position_id = request.form.get("position_id")
photo = request.files.get("photo") # 接收图片需要用request.files接收
p = Person()
#保存常规数据
p.per_name = nickname
p.per_id = username
p.password = setPassword(password)
p.gender = gender
p.age = age
p.per_phone = phone
p.per_email = email
p.address = address
p.join_time = datetime.datetime.now()
p.per_department = department_id
p.per_position = position_id
#保存图片
#保存图片到服务器
file_name = photo.filename
static_dir = os.path.join(
os.path.dirname(
os.path.dirname(
os.path.abspath(__file__)
)
)
,"static"
)
print(static_dir)
file_path = os.path.join("img",file_name)
save_path = os.path.join(static_dir,file_path)
photo.save(save_path) #将图片保存到指定的路径下
#保存图片路径到数据库
p.per_photo = file_path
p.save()
return jsonify({"result": "success"})
return render_template("add_person.html",**locals())
@oaPro.route("/")
@loginValid
def index():
return render_template("index.html")
@csrf.exempt #避免csrf,不进行csrf检测
@oaPro.route("/login/",methods=["GET","POST"])
def login():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
if username and password:
#使用用户提交的用户名和密码进行查询,如果有结果,代表合法 first获取第一个结果
user = Person.query.filter_by(per_id = username,password = setPassword(password)).first()
if user:
response = redirect("/")
response.set_cookie("user_id",str(user.id))
response.set_cookie("user_name", user.per_id)
response.set_cookie("nick_name",user.per_name)
session["user_id"] = user.id #设置session
return response
return render_template("login.html")
@oaPro.route("/logout/")
def logout():
response = redirect("/login/")
response.delete_cookie("user_id")
response.delete_cookie("user_name")
response.delete_cookie("nick_name")
del session["user_id"] #删除session
return response
@oaPro.route("/attendance_me/",methods = ["GET","POST"])
def attendance_me():
#获取所有直属领导
#查找自己
user_id = request.cookies.get("user_id") #通过cookie获取用户id
my_self = Person.query.get(int(user_id)) #获取id获取个人身份
#获取部门id
d_id = my_self.person_deparment.id
#获取直属领导职级
p_level = int(my_self.per_pos.p_level)+1
#查询直属领导的职位(查找所有自己部门职级大于自己一级的职位)
p_position = Position.query.filter_by(p_level = p_level,p_department = d_id).all()
#获取所有的直属领导
leader_list = []
for p in p_position:
l_list = [{"name": i.per_name, "id": i.id} for i in p.p_person]
leader_list.extend(l_list)
# 接收假条数据
if request.method == "POST":
reason = request.form.get("reason")
a_type = request.form.get("a_type")
long = request.form.get("a_time") #时长
a_time = request.form.get("start") #请假时间
verify_person = request.form.get("verify_person")
# 保存假条
# 假条申请中 0 申请中
attendance = Attendance()
attendance.a_type = a_type #请假类型
attendance.a_reason = reason #请假理由
attendance.a_time = datetime.datetime.strptime(a_time,"%Y-%m-%d") #时间需要按照格式进行转换
attendance.a_long = long #假条时长
attendance.a_state = 0 #假条的状态
attendance.verify_person = verify_person #假条的审核人
attendance.a_person = user_id #假条申请人,就是当前用户
attendance.save() #字段数据的错误一定是在save保存
#假条展示:展示自己的所有假条
attendance_list = my_self.p_attendance
return render_template("attendance_me.html",**locals())
@oaPro.route("/attendance_subordinate/")
def attendance_subordinate():
user_id = request.cookies.get("user_id")
a_list = Attendance.query.filter_by(
verify_person = int(user_id)
).order_by("a_state","a_time")
return render_template("attendance_subordinate.html",**locals())
@oaPro.route("/verify/<int:id>/")
def verify(id):
change = request.args.get("change")
referer = request.referrer
if change:
attendance = Attendance.query.get(id)
attendance.a_state = int(change)
attendance.update()
return redirect(referer)
#定义一个函数
def get_verify_name(id):
p = Person.query.get(int(id))
return p.per_name
#将函数按照到app或者蓝图上
#按照蓝图
oaPro.add_app_template_filter(get_verify_name,"v_name")
#安装到app
# app.add_template_filter(get_verify_name,"v_name")
@oaPro.route("/test/",methods = ["GET","POST"])
def test():
p_list = Person.query.paginate(2,2) #这里返回的是一个分页对象
print(dir(p_list))
#'has_next', 'has_prev', 'items', 'iter_pages', 'next', 'next_num', 'page', 'pages', 'per_page', 'prev', 'prev_num', 'query', 'total'
return render_template("test_page.html",**locals())
@oaPro.route("/test_data/")
def test_data():
result = {
"x_data": ["a","b","c","d","e"],
"y_data": [1,2,5,2,4]
}
return jsonify(result)
def get_page():
"""
全局展示页面的权限 的变量
"""
result = {
"news": False,
"permission": False,
"subordinate": False,
"hr": False
}
user_id = request.cookies.get("user_id")
if user_id:
user = Person.query.get(int(user_id))
boss = Position.query.filter_by(p_name="董事长").first()
#董事长和新媒体运营有发布文章的权限
#获取职位
user_positon = user.per_pos.id
news_person = Position.query.filter_by(p_name = "新媒体拓展").first()
if user_positon in [news_person.id,boss.id]:
result["news"] = True
#只有董事长拥有权限管理
if user_positon == boss.id:
result["permission"] = True
#职级大于1才可以有下属考勤
user_level = user.per_pos.p_level
if user_level > 1: #>=2
result["subordinate"] = True
#HR和boos可以进行人事管理
hr = Position.query.filter_by(p_name = "HR").first()
if user_positon in [hr.id,boss.id]:
result["hr"] = True
return result
oaPro.add_app_template_global(get_page,"get_page")
from flask_wtf import FlaskForm #导入构建form类的基类
import wtforms #导入构建form类的元素类
from wtforms import validators
from wtforms.validators import ValidationError
class KeyWords:
def __init__(self,message): #init当中用来接收报错的提示语
self.message = message
self.pull = ["admin"]
def __call__(self, form, field): #像函数一样被调用
keywords = field.data #获取form表单提交的数据
if keywords in self.pull: #进行逻辑判断
raise ValidationError(self.message) #弹出错误
def len9(form, field):
keywords = field.data
if len(keywords) == 9:
raise ValidationError("用户名长度不可以为9") # 弹出错误
class LoginForm(FlaskForm): #继承flaskForm定义自己的表单类
username = wtforms.StringField(
validators = [
validators.Length(
min = 3,
max = 8,
message = "用户名的长度必须是6到8位"
),
KeyWords("用户名不可以是关键字"),
len9
]
) #定义表单的元素
password = wtforms.StringField()
from FlaskPro import db
class Base(db.Model):
__abstract__ = True #防止被继承之后创建Base表在数据库
id = db.Column(db.Integer, primary_key = True, autoincrement = True)
def save(self):
session = db.session
session.add(self)
session.commit()
def update(self):
session = db.session
session.commit()
def delete(self):
session = db.session
session.delete(self)
session.commit()
class Department(Base):
"部门表"
__tablename__ = "department"
d_name = db.Column(db.String(32))
d_description = db.Column(db.Text)
#构建与职位表外键的反向映射
d_position = db.relationship(
"Position",
backref = "p_dep"
)
# 构建与职员表外键的反向映射
d_person = db.relationship(
"Person",
backref="person_deparment"
)
#权限和职位的多对多中间表
pos_per = db.Table(
"pos_per",
db.Column("pos_id",db.Integer,db.ForeignKey("position.id")),
db.Column("per_id", db.Integer, db.ForeignKey("permission.id"))
)
#权限和职员的多对多中间表
per = db.Table(
"per",
db.Column("pos_id",db.Integer,db.ForeignKey("person.id")),
db.Column("pms_id", db.Integer, db.ForeignKey("permission.id"))
)
class Permission(Base):
"权限表"
__tablename__ = "permission"
p_description = db.Column(db.Text)
p_table = db.Column(db.String(32))
p_obj_id = db.Column(db.Integer) # 0 代表整个表 其他正整数代表具体一条数据
p_type = db.Column(db.String(2)) # a增 d删 u改 s查
class Position(Base):
"职位表"
__tablename__ = "position"
p_name = db.Column(db.String(32))
p_level = db.Column(db.Integer) #职级
#构建与部门表进行关联的外键
p_department = db.Column(db.Integer,db.ForeignKey("department.id"))
#构建和权限的反向映射
p_permission = db.relationship(
"Permission",
secondary = pos_per,
backref = "person_position"
)
#搭建关联职员的反向映射
p_person = db.relationship(
"Person",
backref = "per_pos" #值不可以和Person表当中的外键字段一样
)
class Person(Base):
"职员表"
__tablename__ = "person"
per_name = db.Column(db.String(32))
per_id = db.Column(db.String(8))
password = db.Column(db.String(32))
gender = db.Column(db.String(4)) #性别
age = db.Column(db.Integer)
per_phone = db.Column(db.String(32))
per_email = db.Column(db.String(64))
address = db.Column(db.Text)
per_photo = db.Column(db.String(128))
join_time = db.Column(db.Date) #采用当前时间
#创建关联职位的外键
per_position = db.Column(db.Integer,db.ForeignKey("position.id"))
#创建关联部门的外键
per_department = db.Column(db.Integer,db.ForeignKey("department.id"))
# 构建职员和权限的反向映射
p_permission = db.relationship(
"Permission",
secondary= per,
backref="per_pos"
)
# 构建和考勤的反向映射
p_attendance = db.relationship(
"Attendance",
backref="a_per"
)
class Attendance(Base):
"""
考勤表
请假类型
请假原因
请假时间
请假时长
请假状态
0 申请中
1 通过
2 驳回
3 销假
请假人
"""
__tablename__ = "attendance"
a_type = db.Column(db.String(32))
a_reason = db.Column(db.Text)
a_time = db.Column(db.Date)
a_long = db.Column(db.Float) #单位是天
a_state = db.Column(db.Integer) #请假状态
verify_person = db.Column(db.Integer) #审核的逻辑是直属领导审核 同一部门,职级大于本人一级的员工
a_person = db.Column(db.Integer,db.ForeignKey("person.id"))
class New(Base):
__tablename__ = "new"
title = db.Column(db.String(32))
author = db.Column(db.String(32))
n_time = db.Column(db.Date)
content = db.Column(db.Text)