Compare commits
No commits in common. "36b6cb1e0ef2d4bc5d9b622bd2f85dadc8d908a6" and "0b2a587b69524dafde97f76bad27721afebdcddb" have entirely different histories.
36b6cb1e0e
...
0b2a587b69
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
learning_center/models/__pycache__/teach_class.cpython-312.pyc
Normal file
BIN
learning_center/models/__pycache__/teach_class.cpython-312.pyc
Normal file
Binary file not shown.
@ -14,7 +14,6 @@ class CourseHomework(models.Model):
|
|||||||
requirement = fields.Html(string='作业要求')
|
requirement = fields.Html(string='作业要求')
|
||||||
course_id = fields.Many2one('learning.course', string='所属课程', required=True, ondelete='cascade')
|
course_id = fields.Many2one('learning.course', string='所属课程', required=True, ondelete='cascade')
|
||||||
chapter_id = fields.Many2one('course.chapter', string='关联章节')
|
chapter_id = fields.Many2one('course.chapter', string='关联章节')
|
||||||
|
|
||||||
total_score = fields.Float(string='作业总分', default=100.0, required=True)
|
total_score = fields.Float(string='作业总分', default=100.0, required=True)
|
||||||
publish_time = fields.Datetime(string='发布时间')
|
publish_time = fields.Datetime(string='发布时间')
|
||||||
deadline = fields.Datetime(string='提交截止时间', required=True)
|
deadline = fields.Datetime(string='提交截止时间', required=True)
|
||||||
@ -29,21 +28,12 @@ class CourseHomework(models.Model):
|
|||||||
total_students = fields.Integer(string='应提交人数', compute='_compute_submit_stats')
|
total_students = fields.Integer(string='应提交人数', compute='_compute_submit_stats')
|
||||||
submitted_count = fields.Integer(string='已提交人数', compute='_compute_submit_stats')
|
submitted_count = fields.Integer(string='已提交人数', compute='_compute_submit_stats')
|
||||||
late_count = fields.Integer(string='逾期提交人数', compute='_compute_submit_stats')
|
late_count = fields.Integer(string='逾期提交人数', compute='_compute_submit_stats')
|
||||||
course_score_item_id=fields.Many2one('course.score.item',string='作业类型')
|
|
||||||
unsubmitted_count = fields.Integer(string='未提交人数', compute='_compute_submit_stats')
|
unsubmitted_count = fields.Integer(string='未提交人数', compute='_compute_submit_stats')
|
||||||
# 添加教学班关联
|
# 添加教学班关联
|
||||||
teaching_class_id = fields.Many2one('course.teaching_class', string='教学班',
|
teaching_class_id = fields.Many2one('course.teaching_class', string='教学班',
|
||||||
ondelete='cascade', domain="[('course_id', '=', course_id)]")
|
ondelete='cascade', domain="[('course_id', '=', course_id)]")
|
||||||
submit_ids = fields.One2many('course.homework.submit', 'homework_id', string='提交记录')
|
submit_ids = fields.One2many('course.homework.submit', 'homework_id', string='提交记录')
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
score_item_ids = fields.One2many('course.score.item', 'homework_id', string='成绩项目')
|
|
||||||
=======
|
|
||||||
score_item_ids = fields.One2many('course.score.item', 'homework_id', string='成绩项')
|
score_item_ids = fields.One2many('course.score.item', 'homework_id', string='成绩项')
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
score_item_ids = fields.One2many('course.score.item', 'homework_id', string='成绩项')
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
|
|
||||||
# ====================== 新增:自动计算提交通道是否开启 ======================
|
# ====================== 新增:自动计算提交通道是否开启 ======================
|
||||||
@api.depends('state', 'deadline')
|
@api.depends('state', 'deadline')
|
||||||
@ -90,72 +80,9 @@ class CourseHomework(models.Model):
|
|||||||
self.publish_time = fields.Datetime.now()
|
self.publish_time = fields.Datetime.now()
|
||||||
# 1. 批量为本班学生生成空白未提交记录
|
# 1. 批量为本班学生生成空白未提交记录
|
||||||
self._auto_create_empty_submit()
|
self._auto_create_empty_submit()
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
# 新增:自动生成对应作业的学生成绩明细
|
|
||||||
self._auto_create_homework_score_detail()
|
|
||||||
# 2. 推送作业通知给学生
|
# 2. 推送作业通知给学生
|
||||||
self._send_homework_notice_to_students()
|
self._send_homework_notice_to_students()
|
||||||
|
|
||||||
def _auto_create_homework_score_detail(self):
|
|
||||||
self.ensure_one()
|
|
||||||
# 修正字段名 course_score_item_id
|
|
||||||
if not self.teaching_class_id or not self.course_score_item_id:
|
|
||||||
return
|
|
||||||
score_item = self.course_score_item_id
|
|
||||||
|
|
||||||
# 获取教学班在册学生
|
|
||||||
enroll_records = self.env['course.teaching_class.enrollment'].search([
|
|
||||||
('teaching_class_id', '=', self.teaching_class_id.id),
|
|
||||||
('state', '=', 'enrolled')
|
|
||||||
])
|
|
||||||
student_ids = enroll_records.mapped('student_id').ids
|
|
||||||
if not student_ids:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 查询当前作业+当前分项已存在明细
|
|
||||||
exist_details = self.env['course.student.score.detail'].search([
|
|
||||||
('course_id', '=', self.course_id.id),
|
|
||||||
('score_item_id', '=', score_item.id),
|
|
||||||
('homework_id', '=', self.id),
|
|
||||||
('student_id', 'in', student_ids)
|
|
||||||
])
|
|
||||||
exist_student_ids = exist_details.mapped('student_id').ids
|
|
||||||
target_student_ids = [sid for sid in student_ids if sid not in exist_student_ids]
|
|
||||||
if not target_student_ids:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 批量查询学生总成绩,避免循环查库
|
|
||||||
all_student_scores = self.env['course.student.score'].search([
|
|
||||||
('course_id', '=', self.course_id.id),
|
|
||||||
('student_id', 'in', target_student_ids)
|
|
||||||
])
|
|
||||||
score_map = {rec.student_id.id: rec for rec in all_student_scores}
|
|
||||||
|
|
||||||
detail_vals_list = []
|
|
||||||
for stu_id in target_student_ids:
|
|
||||||
student_score = score_map.get(stu_id)
|
|
||||||
if not student_score:
|
|
||||||
continue
|
|
||||||
detail_vals_list.append({
|
|
||||||
'student_score_id': student_score.id,
|
|
||||||
'homework_id': self.id,
|
|
||||||
'score_item_id': score_item.id,
|
|
||||||
'score': 0.0,
|
|
||||||
'remark': f'{self.course_score_item_id.name}:{self.name}'
|
|
||||||
})
|
|
||||||
|
|
||||||
if detail_vals_list:
|
|
||||||
self.env['course.student.score.detail'].create(detail_vals_list)
|
|
||||||
=======
|
|
||||||
# 2. 推送作业通知给学生
|
|
||||||
self._send_homework_notice_to_students()
|
|
||||||
|
|
||||||
=======
|
|
||||||
# 2. 推送作业通知给学生
|
|
||||||
self._send_homework_notice_to_students()
|
|
||||||
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
def _send_homework_notice_to_students(self):
|
def _send_homework_notice_to_students(self):
|
||||||
"""发布作业后推送消息给教学班学生"""
|
"""发布作业后推送消息给教学班学生"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@ -184,10 +111,6 @@ class CourseHomework(models.Model):
|
|||||||
partner_ids=student_users.mapped('partner_id').ids,
|
partner_ids=student_users.mapped('partner_id').ids,
|
||||||
subtype_xmlid='mail.mt_comment'
|
subtype_xmlid='mail.mt_comment'
|
||||||
)
|
)
|
||||||
<<<<<<< HEAD
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
|
|
||||||
def _auto_create_empty_submit(self):
|
def _auto_create_empty_submit(self):
|
||||||
"""仅发布时执行:自动给教学班所有已选课学生生成空白未提交记录"""
|
"""仅发布时执行:自动给教学班所有已选课学生生成空白未提交记录"""
|
||||||
@ -215,53 +138,11 @@ class CourseHomework(models.Model):
|
|||||||
batch_vals.append({
|
batch_vals.append({
|
||||||
'homework_id': self.id,
|
'homework_id': self.id,
|
||||||
'student_id': stu_id,
|
'student_id': stu_id,
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
'course_score_item_id':self.course_score_item_id.id,
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
'state': 'unsubmit' # 默认未提交
|
'state': 'unsubmit' # 默认未提交
|
||||||
})
|
})
|
||||||
# 批量创建空白提交记录
|
# 批量创建空白提交记录
|
||||||
submit_model.create(batch_vals)
|
submit_model.create(batch_vals)
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
def _send_homework_notice_to_students(self):
|
|
||||||
"""发布作业后推送消息给教学班学生"""
|
|
||||||
self.ensure_one()
|
|
||||||
if not self.teaching_class_id:
|
|
||||||
return
|
|
||||||
# 获取当前教学班所有已选课学生
|
|
||||||
enrolls = self.env['course.teaching_class.enrollment'].search([
|
|
||||||
('teaching_class_id', '=', self.teaching_class_id.id),
|
|
||||||
('state', '=', 'enrolled')
|
|
||||||
])
|
|
||||||
student_users = enrolls.mapped('student_id.user_id').filtered(lambda u: u)
|
|
||||||
if not student_users:
|
|
||||||
return
|
|
||||||
# 消息内容
|
|
||||||
subject = f"新作业发布:{self.name}"
|
|
||||||
body = f"""
|
|
||||||
<p>课程:{self.course_id.name}</p>
|
|
||||||
<p>作业名称:{self.name}</p>
|
|
||||||
<p>截止时间:{self.deadline or '无'}</p>
|
|
||||||
<p>作业要求:{self.requirement or '无'}</p>
|
|
||||||
"""
|
|
||||||
# 发送消息(关联当前作业记录,学生在消息中心可直接跳转)
|
|
||||||
self.message_post(
|
|
||||||
subject=subject,
|
|
||||||
body=body,
|
|
||||||
partner_ids=student_users.mapped('partner_id').ids,
|
|
||||||
subtype_xmlid='mail.mt_note'
|
|
||||||
)
|
|
||||||
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
# ====================== 草稿/关闭作业 ======================
|
# ====================== 草稿/关闭作业 ======================
|
||||||
def action_draft(self):
|
def action_draft(self):
|
||||||
self.state = 'draft'
|
self.state = 'draft'
|
||||||
@ -388,21 +269,4 @@ class CourseHomework(models.Model):
|
|||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
homework_record = super().create(vals)
|
homework_record = super().create(vals)
|
||||||
# 草稿状态不执行自动生成提交记录,移到action_publish
|
# 草稿状态不执行自动生成提交记录,移到action_publish
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
target_a = self.env["course.score.item"].search([
|
|
||||||
("name", "=", "作业"),
|
|
||||||
("create_uid", "=", self.env.uid)
|
|
||||||
], limit=1)
|
|
||||||
|
|
||||||
if target_a:
|
|
||||||
# 将刚新建的B追加到A的多对多字段
|
|
||||||
target_a.write({
|
|
||||||
"homework_ids": [(4, homework_record.id)]
|
|
||||||
})
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
return homework_record
|
return homework_record
|
||||||
@ -28,7 +28,6 @@ class CourseHomeworkSubmit(models.Model):
|
|||||||
student_no = fields.Char(related="student_id.stu_num", string="学号", readonly=True)
|
student_no = fields.Char(related="student_id.stu_num", string="学号", readonly=True)
|
||||||
student_class_id = fields.Many2one(related="student_id.class_id", string="班级", readonly=True)
|
student_class_id = fields.Many2one(related="student_id.class_id", string="班级", readonly=True)
|
||||||
student_major_id = fields.Many2one(related="student_id.major_id", string="专业", readonly=True)
|
student_major_id = fields.Many2one(related="student_id.major_id", string="专业", readonly=True)
|
||||||
course_score_item_id = fields.Many2one('course.score.item', string='作业类型')
|
|
||||||
student_phone = fields.Char(related="student_id.stu_phone", string="手机号", readonly=True)
|
student_phone = fields.Char(related="student_id.stu_phone", string="手机号", readonly=True)
|
||||||
submit_file = fields.Binary(string='提交文件', attachment=True)
|
submit_file = fields.Binary(string='提交文件', attachment=True)
|
||||||
submit_filename = fields.Char(string='文件名')
|
submit_filename = fields.Char(string='文件名')
|
||||||
@ -93,13 +92,6 @@ class CourseHomeworkSubmit(models.Model):
|
|||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
submit_rec = super().create(vals)
|
submit_rec = super().create(vals)
|
||||||
self._check_submit_change_state(submit_rec)
|
self._check_submit_change_state(submit_rec)
|
||||||
<<<<<<< HEAD
|
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
=======
|
|
||||||
>>>>>>> 0b2a587b69524dafde97f76bad27721afebdcddb
|
|
||||||
return submit_rec
|
return submit_rec
|
||||||
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class CourseScoreItem(models.Model):
|
|||||||
course_code = fields.Char(related="course_id.code", string="课程代码", readonly=True)
|
course_code = fields.Char(related="course_id.code", string="课程代码", readonly=True)
|
||||||
course_credit = fields.Float(related="course_id.credit", string="学分", readonly=True)
|
course_credit = fields.Float(related="course_id.credit", string="学分", readonly=True)
|
||||||
course_exam_type = fields.Selection(related="course_id.exam_type", string="考核方式", readonly=True)
|
course_exam_type = fields.Selection(related="course_id.exam_type", string="考核方式", readonly=True)
|
||||||
homework_id = fields.Many2one('course.homework', string='作业', ondelete='cascade')
|
homework_id = fields.Many2one('course.homework', string='作业', required=True, ondelete='cascade')
|
||||||
sequence = fields.Integer(string="排序", default=10)
|
sequence = fields.Integer(string="排序", default=10)
|
||||||
score_type = fields.Selection([
|
score_type = fields.Selection([
|
||||||
('homework', '作业'),
|
('homework', '作业'),
|
||||||
@ -30,7 +30,7 @@ class CourseScoreItem(models.Model):
|
|||||||
full_score = fields.Float(string='满分', default=100.0)
|
full_score = fields.Float(string='满分', default=100.0)
|
||||||
is_active = fields.Boolean(string='是否启用', default=True)
|
is_active = fields.Boolean(string='是否启用', default=True)
|
||||||
homework_ids = fields.Many2many('course.homework', string='关联作业')
|
homework_ids = fields.Many2many('course.homework', string='关联作业')
|
||||||
course_student_score=fields.Many2one('course.student.score',string='学生成绩')
|
|
||||||
# 统计字段
|
# 统计字段
|
||||||
student_count = fields.Integer(string='学生人数', compute='_compute_stats')
|
student_count = fields.Integer(string='学生人数', compute='_compute_stats')
|
||||||
avg_score = fields.Float(string='平均分', compute='_compute_stats')
|
avg_score = fields.Float(string='平均分', compute='_compute_stats')
|
||||||
|
|||||||
@ -24,7 +24,6 @@ class CourseStudentScore(models.Model):
|
|||||||
student_class_id = fields.Many2one( string="班级", related="student_id.class_id", readonly=True)
|
student_class_id = fields.Many2one( string="班级", related="student_id.class_id", readonly=True)
|
||||||
student_major_id = fields.Many2one( string="专业", related="student_id.major_id", readonly=True)
|
student_major_id = fields.Many2one( string="专业", related="student_id.major_id", readonly=True)
|
||||||
stu_name=fields.Char(related='student_id.stu_name',required=True, ondelete='cascade',string='学生姓名')
|
stu_name=fields.Char(related='student_id.stu_name',required=True, ondelete='cascade',string='学生姓名')
|
||||||
score_item_ids=fields.One2many('course.score.item','course_student_score',string='成绩类型')
|
|
||||||
score_ids = fields.One2many('course.student.score.detail', 'student_score_id', string='成绩明细')
|
score_ids = fields.One2many('course.student.score.detail', 'student_score_id', string='成绩明细')
|
||||||
teaching_class_id=fields.Many2one('course.teaching_class',string='教学班')
|
teaching_class_id=fields.Many2one('course.teaching_class',string='教学班')
|
||||||
# 教学班相关只读关联字段
|
# 教学班相关只读关联字段
|
||||||
@ -33,7 +32,7 @@ class CourseStudentScore(models.Model):
|
|||||||
teaching_class_main_teacher = fields.Many2one('hr.employee', string="主讲教师",
|
teaching_class_main_teacher = fields.Many2one('hr.employee', string="主讲教师",
|
||||||
related="teaching_class_id.main_teacher_id", readonly=True)
|
related="teaching_class_id.main_teacher_id", readonly=True)
|
||||||
total_score = fields.Float(string='综合成绩', compute='_compute_total_score', store=True)
|
total_score = fields.Float(string='综合成绩', compute='_compute_total_score', store=True)
|
||||||
course_score_item_id = fields.Many2one('course.score.item', string='成绩分项')
|
|
||||||
grade_level = fields.Selection([
|
grade_level = fields.Selection([
|
||||||
('A', '优秀(A)'),
|
('A', '优秀(A)'),
|
||||||
('B', '良好(B)'),
|
('B', '良好(B)'),
|
||||||
@ -78,8 +77,8 @@ class CourseStudentScoreDetail(models.Model):
|
|||||||
student_score_id = fields.Many2one('course.student.score', string='学生成绩', required=True, ondelete='cascade')
|
student_score_id = fields.Many2one('course.student.score', string='学生成绩', required=True, ondelete='cascade')
|
||||||
student_score_displayname=fields.Char(related='student_score_id.display_name',required=True, ondelete='cascade',string='显示名称')
|
student_score_displayname=fields.Char(related='student_score_id.display_name',required=True, ondelete='cascade',string='显示名称')
|
||||||
# 关联成绩项目
|
# 关联成绩项目
|
||||||
score_item_id = fields.Many2one('course.score.item', string='成绩项目', ondelete='restrict')
|
score_item_id = fields.Many2one('course.score.item', string='成绩项目', required=True, ondelete='restrict')
|
||||||
homework_id=fields.Many2one('course.homework',string='作业')
|
|
||||||
# 得分
|
# 得分
|
||||||
score = fields.Float(string='得分', help='该项目实际得分')
|
score = fields.Float(string='得分', help='该项目实际得分')
|
||||||
|
|
||||||
|
|||||||
@ -215,32 +215,12 @@ class CourseTeachingClassEnrollment(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
"""新增选课记录校验人数上限 + 自动生成学生总成绩记录"""
|
"""新增选课记录校验人数上限"""
|
||||||
res = super().create(vals)
|
res = super().create(vals)
|
||||||
cls = res.teaching_class_id
|
cls = res.teaching_class_id
|
||||||
student = res.student_id
|
|
||||||
course = cls.course_id
|
|
||||||
|
|
||||||
# 1. 人数上限校验原有逻辑保留
|
|
||||||
valid_num = len(cls.enrollment_ids.filtered(lambda e: e.state == 'enrolled'))
|
valid_num = len(cls.enrollment_ids.filtered(lambda e: e.state == 'enrolled'))
|
||||||
if cls.max_students and valid_num > cls.max_students:
|
if cls.max_students and valid_num > cls.max_students:
|
||||||
raise ValidationError("该教学班人数已达上限,无法继续添加学生!")
|
raise ValidationError("该教学班人数已达上限,无法继续添加学生!")
|
||||||
|
|
||||||
# 2. 查找是否已经存在该学生+该课程+该教学班的成绩主记录,避免重复创建
|
|
||||||
exist_score = self.env['course.student.score'].search([
|
|
||||||
('student_id', '=', student.id),
|
|
||||||
('course_id', '=', course.id),
|
|
||||||
('teaching_class_id', '=', cls.id)
|
|
||||||
], limit=1)
|
|
||||||
|
|
||||||
# 不存在则自动创建一条空成绩主记录
|
|
||||||
if not exist_score:
|
|
||||||
self.env['course.student.score'].create({
|
|
||||||
'course_id': course.id,
|
|
||||||
'student_id': student.id,
|
|
||||||
'teaching_class_id': cls.id
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<list>
|
<list>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="course_id"/>
|
<field name="course_id"/>
|
||||||
<!-- <field name="chapter_id"/>-->
|
<field name="chapter_id"/>
|
||||||
<field name="total_score"/>
|
<field name="total_score"/>
|
||||||
<field name="deadline"/>
|
<field name="deadline"/>
|
||||||
<field name="submitted_count" sum="合计"/>
|
<field name="submitted_count" sum="合计"/>
|
||||||
@ -38,10 +38,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<group name="basic_info" string="基本信息">
|
<group name="basic_info" string="基本信息">
|
||||||
<group>
|
<group>
|
||||||
<field name="course_id" options="{'no_create': True}"/>
|
|
||||||
<field name="teaching_class_id"/>
|
<field name="teaching_class_id"/>
|
||||||
<field name="course_score_item_id" />
|
<field name="course_id" options="{'no_create': True}"/>
|
||||||
<!-- <field name="chapter_id" options="{'no_create': True}"/>-->
|
<field name="chapter_id" options="{'no_create': True}"/>
|
||||||
<field name="total_score"/>
|
<field name="total_score"/>
|
||||||
<field name="state" widget="statusbar"/>
|
<field name="state" widget="statusbar"/>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@ -45,11 +45,17 @@
|
|||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="作业明细">
|
|
||||||
<field name="score_ids" view_id="list_course_student_score_score_ids_om"/>
|
|
||||||
</page>
|
|
||||||
<page string="成绩明细">
|
<page string="成绩明细">
|
||||||
<field name="score_item_ids" view_id="list_course_student_score_item_om"/>
|
<field name="score_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="score_item_id" options="{'no_create': True}"/>
|
||||||
|
<field name="score"/>
|
||||||
|
<field name="full_score" readonly="1"/>
|
||||||
|
<field name="weight" readonly="1"/>
|
||||||
|
<field name="completion_rate" widget="progressbar"/>
|
||||||
|
<field name="remark"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
</page>
|
</page>
|
||||||
<page string="课程信息">
|
<page string="课程信息">
|
||||||
<group string="课程详情">
|
<group string="课程详情">
|
||||||
@ -83,74 +89,6 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="list_course_student_score_detail_ids_om" model="ir.ui.view">
|
|
||||||
<field name="name">list.course.student.score.detail.ids.om</field>
|
|
||||||
<field name="model">course.student.score.detail</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<list editable="bottom">
|
|
||||||
<field name="display_name"/>
|
|
||||||
<field name="score"/>
|
|
||||||
|
|
||||||
<field name="full_score" readonly="1"/>
|
|
||||||
<!-- <field name="weight" readonly="1"/>-->
|
|
||||||
<!-- <field name="completion_rate" widget="progressbar"/>-->
|
|
||||||
<field name="remark"/>
|
|
||||||
</list>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="list_course_student_score_item_om" model="ir.ui.view">
|
|
||||||
<field name="name">list.course.student.score.item.om</field>
|
|
||||||
<field name="model">course.score.item</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<list>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="course_id"/>
|
|
||||||
<field name="weight"/>
|
|
||||||
<field name="full_score"/>
|
|
||||||
</list>
|
|
||||||
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 学生成绩动作 ==================== -->
|
|
||||||
<record id="act_course_student_score" model="ir.actions.act_window">
|
|
||||||
<field name="name">学生成绩</field>
|
|
||||||
<field name="res_model">course.student.score</field>
|
|
||||||
<field name="view_mode">list,form</field>
|
|
||||||
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 按课程查看学生成绩的动作 ==================== -->
|
|
||||||
<record id="act_course_student_score_by_course" model="ir.actions.act_window">
|
|
||||||
<field name="name">学生成绩</field>
|
|
||||||
<field name="res_model">course.student.score</field>
|
|
||||||
<field name="view_mode">list,form</field>
|
|
||||||
<field name="view_id" ref="list_course_student_score"/>
|
|
||||||
<field name="domain">[('course_id', '=', active_id)]</field>
|
|
||||||
<field name="context">{'default_course_id': active_id}</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 按教学班查看学生成绩的动作 ==================== -->
|
|
||||||
<record id="act_course_student_score_by_teaching_class" model="ir.actions.act_window">
|
|
||||||
<field name="name">学生成绩</field>
|
|
||||||
<field name="res_model">course.student.score</field>
|
|
||||||
<field name="view_mode">list,form</field>
|
|
||||||
<field name="view_id" ref="list_course_student_score"/>
|
|
||||||
<field name="domain">[('teaching_class_id', '=', active_id)]</field>
|
|
||||||
<field name="context">{'default_teaching_class_id': active_id}</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 二级菜单 ==================== -->
|
|
||||||
<record id="menu_course_student_score" model="ir.ui.menu">
|
|
||||||
<field name="name">学生成绩</field>
|
|
||||||
<field name="parent_id" ref="menu_learning_center_root"/>
|
|
||||||
<field name="action" ref="act_course_student_score"/>
|
|
||||||
<field name="sequence">60</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ==================== 学生成绩明细列表视图 ==================== -->
|
<!-- ==================== 学生成绩明细列表视图 ==================== -->
|
||||||
<record id="view_course_student_score_detail_list" model="ir.ui.view">
|
<record id="view_course_student_score_detail_list" model="ir.ui.view">
|
||||||
@ -210,17 +148,15 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_course_student_score_detail_search" model="ir.ui.view">
|
|
||||||
<field name="name">view.course.student.score.detail.search</field>
|
<!-- ==================== 学生成绩动作 ==================== -->
|
||||||
<field name="model">course.student.score.detail</field>
|
<record id="act_course_student_score" model="ir.actions.act_window">
|
||||||
<field name="arch" type="xml">
|
<field name="name">学生成绩</field>
|
||||||
<search>
|
<field name="res_model">course.student.score</field>
|
||||||
<searchpanel>
|
<field name="view_mode">list,form</field>
|
||||||
<field name="score_item_id" select="multi"/>
|
|
||||||
</searchpanel>
|
|
||||||
</search>
|
|
||||||
</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- ==================== 学生成绩明细动作 ==================== -->
|
<!-- ==================== 学生成绩明细动作 ==================== -->
|
||||||
<record id="act_course_student_score_detail" model="ir.actions.act_window">
|
<record id="act_course_student_score_detail" model="ir.actions.act_window">
|
||||||
<field name="name">成绩明细</field>
|
<field name="name">成绩明细</field>
|
||||||
@ -229,6 +165,34 @@
|
|||||||
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- ==================== 按课程查看学生成绩的动作 ==================== -->
|
||||||
|
<record id="act_course_student_score_by_course" model="ir.actions.act_window">
|
||||||
|
<field name="name">学生成绩</field>
|
||||||
|
<field name="res_model">course.student.score</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="view_id" ref="list_course_student_score"/>
|
||||||
|
<field name="domain">[('course_id', '=', active_id)]</field>
|
||||||
|
<field name="context">{'default_course_id': active_id}</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- ==================== 按教学班查看学生成绩的动作 ==================== -->
|
||||||
|
<record id="act_course_student_score_by_teaching_class" model="ir.actions.act_window">
|
||||||
|
<field name="name">学生成绩</field>
|
||||||
|
<field name="res_model">course.student.score</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="view_id" ref="list_course_student_score"/>
|
||||||
|
<field name="domain">[('teaching_class_id', '=', active_id)]</field>
|
||||||
|
<field name="context">{'default_teaching_class_id': active_id}</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- ==================== 二级菜单 ==================== -->
|
||||||
|
<record id="menu_course_student_score" model="ir.ui.menu">
|
||||||
|
<field name="name">学生成绩</field>
|
||||||
|
<field name="parent_id" ref="menu_learning_center_root"/>
|
||||||
|
<field name="action" ref="act_course_student_score"/>
|
||||||
|
<field name="sequence">60</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<!-- ==================== 成绩明细二级菜单 ==================== -->
|
<!-- ==================== 成绩明细二级菜单 ==================== -->
|
||||||
<record id="menu_course_student_score_detail" model="ir.ui.menu">
|
<record id="menu_course_student_score_detail" model="ir.ui.menu">
|
||||||
<field name="name">成绩明细</field>
|
<field name="name">成绩明细</field>
|
||||||
|
|||||||
@ -36,8 +36,6 @@
|
|||||||
<group name="basic_info" string="基本信息">
|
<group name="basic_info" string="基本信息">
|
||||||
<group>
|
<group>
|
||||||
<field name="homework_id" options="{'no_create': True}"/>
|
<field name="homework_id" options="{'no_create': True}"/>
|
||||||
<field name="course_score_item_id" />
|
|
||||||
|
|
||||||
<field name="student_id" options="{'no_create': True}"/>
|
<field name="student_id" options="{'no_create': True}"/>
|
||||||
<field name="submit_time" readonly="1"/>
|
<field name="submit_time" readonly="1"/>
|
||||||
<field name="is_late" widget="boolean_toggle" readonly="1"/>
|
<field name="is_late" widget="boolean_toggle" readonly="1"/>
|
||||||
|
|||||||
@ -104,18 +104,18 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_course_syllabus_list" model="ir.ui.view">
|
<!-- <record id="view_course_syllabus_list" model="ir.ui.view">-->
|
||||||
<field name="name">course.syllabus.list</field>
|
<!-- <field name="name">course.syllabus.list</field>-->
|
||||||
<field name="model">course.syllabus</field>
|
<!-- <field name="model">course.syllabus</field>-->
|
||||||
<field name="arch" type="xml">
|
<!-- <field name="arch" type="xml">-->
|
||||||
<list>
|
<!-- <list>-->
|
||||||
<field name="title"/>
|
<!-- <field name="title"/>-->
|
||||||
<field name="syllabus_type" widget="badge"/>
|
<!-- <field name="syllabus_type" widget="badge"/>-->
|
||||||
<field name="version"/>
|
<!-- <field name="version"/>-->
|
||||||
<field name="is_published" widget="boolean_toggle"/>
|
<!-- <field name="is_published" widget="boolean_toggle"/>-->
|
||||||
</list>
|
<!-- </list>-->
|
||||||
</field>
|
<!-- </field>-->
|
||||||
</record>
|
<!-- </record>-->
|
||||||
|
|
||||||
<record id="view_course_chapter_resource_list" model="ir.ui.view">
|
<record id="view_course_chapter_resource_list" model="ir.ui.view">
|
||||||
<field name="name">course.chapter.resource.list</field>
|
<field name="name">course.chapter.resource.list</field>
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
from . import models
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
'name': 'Permission Manager',
|
|
||||||
'version': '18.0.1.0.0',
|
|
||||||
'category': 'Tools',
|
|
||||||
'summary': '权限管理',
|
|
||||||
'depends': ['base'],
|
|
||||||
'data': [
|
|
||||||
'security/ir.model.access.csv',
|
|
||||||
'views/role_views.xml',
|
|
||||||
],
|
|
||||||
'installable': True,
|
|
||||||
}
|
|
||||||
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
from . import permission_role
|
|
||||||
Binary file not shown.
Binary file not shown.
@ -1,134 +0,0 @@
|
|||||||
from odoo import api, fields, models
|
|
||||||
|
|
||||||
class PermissionRole(models.Model):
|
|
||||||
_name = 'permission.role'
|
|
||||||
_description = '权限角色'
|
|
||||||
_rec_name = 'name'
|
|
||||||
_order = 'sequence, id'
|
|
||||||
name = fields.Char(string='角色名称', required=True)
|
|
||||||
code = fields.Char(string='角色代码', required=True, help='如:student, teacher, admin')
|
|
||||||
sequence = fields.Integer(string='序号', default=10)
|
|
||||||
description = fields.Text(string='角色描述')
|
|
||||||
active = fields.Boolean(string='启用', default=True)
|
|
||||||
# 角色类型
|
|
||||||
role_type = fields.Selection([
|
|
||||||
('student', '学生'),
|
|
||||||
('teacher', '教师'),
|
|
||||||
('admin', '管理员'),
|
|
||||||
('custom', '自定义'),
|
|
||||||
], string='角色类型', default='custom')
|
|
||||||
# 关联的权限组
|
|
||||||
group_ids = fields.Many2many('res.groups', string='权限组')
|
|
||||||
# 可见菜单
|
|
||||||
menu_ids = fields.Many2many('ir.ui.menu', string='可见菜单')
|
|
||||||
# 用户
|
|
||||||
user_ids = fields.Many2many('res.users', string='用户')
|
|
||||||
user_count = fields.Integer(string='用户数', compute='_compute_user_count')
|
|
||||||
# 统计字段
|
|
||||||
group_count = fields.Integer(string='权限组数', compute='_compute_group_count')
|
|
||||||
menu_count = fields.Integer(string='菜单数', compute='_compute_menu_count')
|
|
||||||
|
|
||||||
@api.depends('user_ids')
|
|
||||||
def _compute_user_count(self):
|
|
||||||
for record in self:
|
|
||||||
record.user_count = len(record.user_ids)
|
|
||||||
|
|
||||||
@api.depends('group_ids')
|
|
||||||
def _compute_group_count(self):
|
|
||||||
for record in self:
|
|
||||||
record.group_count = len(record.group_ids)
|
|
||||||
|
|
||||||
@api.depends('menu_ids')
|
|
||||||
def _compute_menu_count(self):
|
|
||||||
for record in self:
|
|
||||||
record.menu_count = len(record.menu_ids)
|
|
||||||
|
|
||||||
def action_assign_users(self):
|
|
||||||
"""分配用户"""
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': '分配用户',
|
|
||||||
'res_model': 'res.users',
|
|
||||||
'view_mode': 'list,form',
|
|
||||||
'target': 'new',
|
|
||||||
'domain': [('id', 'not in', self.user_ids.ids)],
|
|
||||||
'context': {
|
|
||||||
'default_role_ids': [(4, self.id)],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def action_view_users(self):
|
|
||||||
"""查看角色下的用户"""
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': f'角色用户 - {self.name}',
|
|
||||||
'res_model': 'res.users',
|
|
||||||
'view_mode': 'list,form',
|
|
||||||
'domain': [('id', 'in', self.user_ids.ids)],
|
|
||||||
}
|
|
||||||
|
|
||||||
def action_copy_permissions(self):
|
|
||||||
"""复制权限(从其他角色)"""
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': '复制权限',
|
|
||||||
'res_model': 'permission.copy.wizard',
|
|
||||||
'view_mode': 'form',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {'default_target_role_id': self.id},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ResUsersInherit(models.Model):
|
|
||||||
_inherit = 'res.users'
|
|
||||||
|
|
||||||
role_ids = fields.Many2many('permission.role', string='权限角色')
|
|
||||||
role_count = fields.Integer(string='角色数', compute='_compute_role_count')
|
|
||||||
|
|
||||||
@api.depends('role_ids')
|
|
||||||
def _compute_role_count(self):
|
|
||||||
for record in self:
|
|
||||||
record.role_count = len(record.role_ids)
|
|
||||||
|
|
||||||
def action_view_roles(self):
|
|
||||||
"""查看用户角色"""
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': '用户角色',
|
|
||||||
'res_model': 'permission.role',
|
|
||||||
'view_mode': 'list,form',
|
|
||||||
'domain': [('id', 'in', self.role_ids.ids)],
|
|
||||||
}
|
|
||||||
|
|
||||||
def action_sync_permissions(self):
|
|
||||||
"""同步权限:将角色的权限组和菜单同步到用户"""
|
|
||||||
for user in self:
|
|
||||||
groups = user.role_ids.mapped('group_ids')
|
|
||||||
menus = user.role_ids.mapped('menu_ids')
|
|
||||||
user.write({
|
|
||||||
'groups_id': [(6, 0, groups.ids)],
|
|
||||||
})
|
|
||||||
# 菜单权限需要单独处理
|
|
||||||
for menu in menus:
|
|
||||||
# 这里可以添加自定义菜单权限逻辑
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PermissionCopyWizard(models.TransientModel):
|
|
||||||
_name = 'permission.copy.wizard'
|
|
||||||
_description = '复制权限向导'
|
|
||||||
|
|
||||||
target_role_id = fields.Many2one('permission.role', string='目标角色', readonly=True)
|
|
||||||
source_role_id = fields.Many2one('permission.role', string='源角色', required=True)
|
|
||||||
copy_groups = fields.Boolean(string='复制权限组', default=True)
|
|
||||||
copy_menus = fields.Boolean(string='复制菜单权限', default=True)
|
|
||||||
|
|
||||||
def action_copy(self):
|
|
||||||
self.ensure_one()
|
|
||||||
vals = {}
|
|
||||||
if self.copy_groups:
|
|
||||||
vals['group_ids'] = [(6, 0, self.source_role_id.group_ids.ids)]
|
|
||||||
if self.copy_menus:
|
|
||||||
vals['menu_ids'] = [(6, 0, self.source_role_id.menu_ids.ids)]
|
|
||||||
self.target_role_id.write(vals)
|
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|
||||||
access_permission_role,permission.role,model_permission_role,base.group_system,1,1,1,1
|
|
||||||
access_res_users,res.users.access,model_res_users,base.group_system,1,1,1,1
|
|
||||||
access_permission_copy_wizard,permission.copy.wizard.access,model_permission_copy_wizard,base.group_system,1,1,1,1
|
|
||||||
|
@ -1,166 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
|
|
||||||
<!-- ==================== 角色列表视图 ==================== -->
|
|
||||||
<record id="view_permission_role_list" model="ir.ui.view">
|
|
||||||
<field name="name">permission.role.list</field>
|
|
||||||
<field name="model">permission.role</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<list>
|
|
||||||
<field name="sequence" widget="handle"/>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="code"/>
|
|
||||||
<field name="role_type" widget="badge"/>
|
|
||||||
<field name="user_count" sum="合计"/>
|
|
||||||
<field name="active" widget="boolean_toggle"/>
|
|
||||||
</list>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 角色表单视图 ==================== -->
|
|
||||||
<record id="view_permission_role_form" model="ir.ui.view">
|
|
||||||
<field name="name">permission.role.form</field>
|
|
||||||
<field name="model">permission.role</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="权限角色">
|
|
||||||
<sheet>
|
|
||||||
<div class="oe_title">
|
|
||||||
<h1>
|
|
||||||
<field name="name" placeholder="角色名称"/>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="oe_button_box" name="button_box">
|
|
||||||
<button name="action_copy_permissions" type="object" string="复制权限" class="btn-secondary"/>
|
|
||||||
</div>
|
|
||||||
<group name="basic_info" string="基本信息">
|
|
||||||
<group>
|
|
||||||
<field name="code"/>
|
|
||||||
<field name="role_type"/>
|
|
||||||
<field name="sequence"/>
|
|
||||||
<field name="active" widget="boolean_toggle"/>
|
|
||||||
</group>
|
|
||||||
<group>
|
|
||||||
<field name="description" nolabel="1" placeholder="角色描述"/>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
<notebook>
|
|
||||||
<page string="权限组">
|
|
||||||
<field name="group_ids" widget="many2many_tags"/>
|
|
||||||
<div class="alert alert-info" role="alert">
|
|
||||||
<i class="fa fa-info-circle"/> 权限组决定用户对模型的操作权限(增删改查)
|
|
||||||
</div>
|
|
||||||
</page>
|
|
||||||
<page string="可见菜单">
|
|
||||||
<field name="menu_ids">
|
|
||||||
<list>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="parent_id"/>
|
|
||||||
<field name="sequence"/>
|
|
||||||
</list>
|
|
||||||
</field>
|
|
||||||
</page>
|
|
||||||
<page string="用户">
|
|
||||||
<group>
|
|
||||||
<field name="user_count"/>
|
|
||||||
<div class="oe_button_box">
|
|
||||||
<button name="action_assign_users" type="object" string="分配用户" class="btn-primary"/>
|
|
||||||
<button name="action_view_users" type="object" string="查看用户" class="btn-secondary"/>
|
|
||||||
</div>
|
|
||||||
</group>
|
|
||||||
<field name="user_ids" widget="many2many_tags"/>
|
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 角色搜索视图 ==================== -->
|
|
||||||
<record id="view_permission_role_search" model="ir.ui.view">
|
|
||||||
<field name="name">permission.role.search</field>
|
|
||||||
<field name="model">permission.role</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<search>
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="code"/>
|
|
||||||
<filter name="active" string="启用" domain="[('active', '=', True)]"/>
|
|
||||||
<filter name="inactive" string="禁用" domain="[('active', '=', False)]"/>
|
|
||||||
<separator/>
|
|
||||||
<filter name="group_by_type" string="角色类型" context="{'group_by': 'role_type'}"/>
|
|
||||||
<filter name="group_by_active" string="状态" context="{'group_by': 'active'}"/>
|
|
||||||
</search>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 角色动作 ==================== -->
|
|
||||||
<record id="act_permission_role" model="ir.actions.act_window">
|
|
||||||
<field name="name">角色管理</field>
|
|
||||||
<field name="res_model">permission.role</field>
|
|
||||||
<field name="view_mode">list,form</field>
|
|
||||||
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 复制权限向导视图 ==================== -->
|
|
||||||
<record id="view_permission_copy_wizard" model="ir.ui.view">
|
|
||||||
<field name="name">permission.copy.wizard.form</field>
|
|
||||||
<field name="model">permission.copy.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="复制权限">
|
|
||||||
<sheet>
|
|
||||||
<group>
|
|
||||||
<field name="target_role_id" readonly="1"/>
|
|
||||||
<field name="source_role_id" required="1"/>
|
|
||||||
<field name="copy_groups"/>
|
|
||||||
<field name="copy_menus"/>
|
|
||||||
</group>
|
|
||||||
<footer>
|
|
||||||
<button name="action_copy" type="object" string="复制" class="btn-primary"/>
|
|
||||||
<button string="取消" class="btn-secondary" special="cancel"/>
|
|
||||||
</footer>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- ==================== 继承用户表单,添加角色选项卡 ==================== -->
|
|
||||||
<record id="view_res_users_form_inherit" model="ir.ui.view">
|
|
||||||
<field name="name">res.users.form.inherit</field>
|
|
||||||
<field name="model">res.users</field>
|
|
||||||
<field name="inherit_id" ref="base.view_users_form"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//notebook" position="inside">
|
|
||||||
<page string="权限角色" name="permission_role_page">
|
|
||||||
<group string="角色分配">
|
|
||||||
<field name="role_ids" widget="many2many_tags"/>
|
|
||||||
<field name="role_count"/>
|
|
||||||
<div class="oe_button_box">
|
|
||||||
<button name="action_view_roles" type="object" string="查看角色" class="btn-secondary"/>
|
|
||||||
<button name="action_sync_permissions" type="object" string="同步权限" class="btn-primary"/>
|
|
||||||
</div>
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 权限管理根菜单 -->
|
|
||||||
<record id="menu_permission_root" model="ir.ui.menu">
|
|
||||||
<field name="name">权限管理</field>
|
|
||||||
<field name="sequence">100</field>
|
|
||||||
<field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- 角色管理子菜单 -->
|
|
||||||
<record id="menu_permission_role" model="ir.ui.menu">
|
|
||||||
<field name="name">角色管理</field>
|
|
||||||
<field name="parent_id" ref="menu_permission_root"/>
|
|
||||||
<field name="action" ref="act_permission_role"/>
|
|
||||||
<field name="sequence">10</field>
|
|
||||||
<field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user