148 lines
4.1 KiB
Python
148 lines
4.1 KiB
Python
from odoo import fields, models, api
|
||
|
||
|
||
class Textbook(models.Model):
|
||
_name = 'yuthon.school.textbook'
|
||
_description = '教材'
|
||
_order = 'category_id, sequence, name'
|
||
|
||
name = fields.Char(
|
||
string='教材名称',
|
||
required=True,
|
||
help='如:Odoo 18 基础入门、Odoo 18 视图开发实战',
|
||
)
|
||
sequence = fields.Integer(
|
||
string='排序',
|
||
default=10,
|
||
)
|
||
category_id = fields.Many2one(
|
||
'yuthon.school.category',
|
||
string='学习分类',
|
||
ondelete='restrict',
|
||
help='该教材所属的学习分类',
|
||
)
|
||
description = fields.Text(
|
||
string='教材简介',
|
||
help='教材的内容概要和适用人群',
|
||
)
|
||
difficulty = fields.Selection(
|
||
[('beginner', '入门'), ('intermediate', '进阶'), ('advanced', '高级')],
|
||
string='难度等级',
|
||
default='beginner',
|
||
)
|
||
state = fields.Selection(
|
||
[('draft', '草稿'), ('published', '已发布')],
|
||
string='状态',
|
||
default='draft',
|
||
)
|
||
total_hours = fields.Float(
|
||
string='总学时',
|
||
compute='_compute_total_hours',
|
||
store=True,
|
||
help='自动统计各章学时之和',
|
||
)
|
||
total_chapters = fields.Integer(
|
||
string='章节数',
|
||
compute='_compute_total_chapters',
|
||
store=True,
|
||
)
|
||
total_videos = fields.Integer(
|
||
string='视频数',
|
||
compute='_compute_total_videos',
|
||
store=True,
|
||
)
|
||
chapter_ids = fields.One2many(
|
||
'yuthon.school.chapter',
|
||
'textbook_id',
|
||
string='章节',
|
||
)
|
||
active = fields.Boolean(
|
||
string='启用',
|
||
default=True,
|
||
)
|
||
|
||
@api.depends('chapter_ids.hours')
|
||
def _compute_total_hours(self):
|
||
for record in self:
|
||
record.total_hours = sum(record.chapter_ids.mapped('hours'))
|
||
|
||
@api.depends('chapter_ids')
|
||
def _compute_total_chapters(self):
|
||
for record in self:
|
||
record.total_chapters = len(record.chapter_ids)
|
||
|
||
@api.depends('chapter_ids.video_ids')
|
||
def _compute_total_videos(self):
|
||
for record in self:
|
||
record.total_videos = sum(len(ch.video_ids) for ch in record.chapter_ids)
|
||
|
||
def action_confirm(self):
|
||
"""发布教材:将状态从草稿改为已发布"""
|
||
self.write({'state': 'published'})
|
||
|
||
def action_set_draft(self):
|
||
"""退回草稿:将状态从已发布改回草稿"""
|
||
self.write({'state': 'draft'})
|
||
|
||
|
||
class Chapter(models.Model):
|
||
_name = 'yuthon.school.chapter'
|
||
_description = '章节'
|
||
_order = 'textbook_id, sequence, name'
|
||
|
||
_sql_constraints = [
|
||
('unique_chapter_seq',
|
||
'unique(textbook_id, sequence)',
|
||
'同一教材下章节序号不能重复!'),
|
||
]
|
||
|
||
name = fields.Char(
|
||
string='章节标题',
|
||
required=True,
|
||
)
|
||
sequence = fields.Integer(
|
||
string='排序',
|
||
default=10,
|
||
)
|
||
textbook_id = fields.Many2one(
|
||
'yuthon.school.textbook',
|
||
string='所属教材',
|
||
required=True,
|
||
ondelete='cascade',
|
||
)
|
||
summary = fields.Text(
|
||
string='内容概述',
|
||
help='本章涵盖的内容概述',
|
||
)
|
||
key_points = fields.Text(
|
||
string='知识要点',
|
||
help='本章需要掌握的关键知识点',
|
||
)
|
||
hours = fields.Float(
|
||
string='学时',
|
||
default=1.0,
|
||
help='本章预计学习时长(小时)',
|
||
)
|
||
video_ids = fields.One2many(
|
||
'yuthon.school.video',
|
||
'chapter_id',
|
||
string='视频',
|
||
)
|
||
video_count = fields.Integer(
|
||
string='视频数',
|
||
compute='_compute_video_count',
|
||
store=True,
|
||
)
|
||
|
||
@api.depends('video_ids')
|
||
def _compute_video_count(self):
|
||
for record in self:
|
||
record.video_count = len(record.video_ids)
|
||
|
||
@api.onchange('video_ids')
|
||
def _onchange_video_ids(self):
|
||
"""当视频列表变化时,自动建议学时(每个视频按 0.5 学时计算)"""
|
||
if self.video_ids:
|
||
suggested = max(1.0, len(self.video_ids) * 0.5)
|
||
self.hours = suggested
|