from odoo import api, fields, models from odoo.tools import human_size import base64 import os class CourseSyllabus(models.Model): _name = 'course.syllabus' _description = '教学大纲/教案' _rec_name = 'title' _order = 'course_id, syllabus_type, version desc' _inherit = ['mail.thread'] title = fields.Char(string='标题', required=True) syllabus_type = fields.Selection([ ('syllabus', '教学大纲'), ('lesson_plan', '教案'), ], string='类型', required=True) course_id = fields.Many2one('learning.course', string='所属课程', required=True, ondelete='cascade') course_name = fields.Char(related="course_id.name", 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_exam_type = fields.Selection(related="course_id.exam_type", string="考核方式", readonly=True) chapter_id = fields.Many2one('course.chapter', string='关联章节') chapter_name = fields.Char(related="chapter_id.name", string="章节名称", readonly=True) chapter_sequence = fields.Integer(related="chapter_id.sequence", string="章节序号", readonly=True) chapter_is_published = fields.Boolean(related="chapter_id.is_published", string="发布状态", readonly=True) # 文件核心字段 file = fields.Binary(string='文件', attachment=True, required=True) file_name = fields.Char(string='文件名') file_size = fields.Integer(string='文件大小(字节)', readonly=True) file_size_str = fields.Char(string='文件大小', readonly=True) # 友好显示:KB/MB file_suffix = fields.Char(string='文件格式', readonly=True) # 后缀:docx/pptx/pdf version = fields.Char(string='版本号', default='1.0') version_note = fields.Char(string='版本说明') publish_date = fields.Date(string='发布日期', default=fields.Date.today) is_published = fields.Boolean(string='是否发布', default=True) download_count = fields.Integer(string='下载次数', default=0) teaching_class_id = fields.Many2one( 'course.teaching_class', string='教学班', ondelete='cascade', domain="[('course_id', '=', course_id)]" ) # 监听文件上传,自动赋值文件名、大小、后缀 @api.onchange('file', 'file_name') def _onchange_file_upload(self): for record in self: if record.file and record.file_name: # 计算文件大小(base64 换算) file_data = base64.b64decode(record.file) size_bytes = len(file_data) record.file_size = size_bytes record.file_size_str = human_size(size_bytes) # 提取文件后缀 name, suffix = os.path.splitext(record.file_name) record.file_suffix = suffix.lower().strip('.') else: record.file_size = 0 record.file_size_str = '' record.file_suffix = '' # 修复批量下载问题 + 优化下载响应 def action_download(self): for rec in self: rec.download_count += 1 if rec.file_name: # 携带真实文件名,浏览器正常识别 url = f'/web/content/course.syllabus/{rec.id}/file/{rec.file_name}?download=true' else: url = f'/web/content/course.syllabus/{rec.id}/file?download=true' return { 'type': 'ir.actions.act_url', 'url': url, 'target': 'self', # self 强制下载,new 新标签页打开 }