From 782bea26af2b4a8753b9658cc51cd3d46104183e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Fri, 26 Jun 2026 09:40:27 +0800 Subject: [PATCH] 1 --- yuthon_notice/__init__.py | 3 + yuthon_notice/__manifest__.py | 33 ++ yuthon_notice/controllers/__init__.py | 1 + yuthon_notice/controllers/main.py | 133 ++++++ yuthon_notice/data/notice_code_data.xml | 24 ++ yuthon_notice/data/notice_cron_data.xml | 15 + yuthon_notice/data/notice_type_data.xml | 7 + yuthon_notice/models/__init__.py | 6 + yuthon_notice/models/yuthon_confirm_users.py | 38 ++ yuthon_notice/models/yuthon_notice.py | 206 +++++++++ yuthon_notice/models/yuthon_notice_type.py | 11 + yuthon_notice/security/ir.model.access.csv | 6 + yuthon_notice/static/description/icon.png | Bin 0 -> 7790 bytes yuthon_notice/static/scss/notice_scss.scss | 5 + .../static/src/js/custom_create_button.js | 29 ++ .../static/src/xml/custom_create_button.xml | 10 + .../views/yuthon_confirm_users_views.xml | 38 ++ yuthon_notice/views/yuthon_cs_tree_views.xml | 17 + .../views/yuthon_notice_type_views.xml | 33 ++ yuthon_notice/views/yuthon_notice_views.xml | 216 ++++++++++ yuthon_will_task/__init__.py | 2 + yuthon_will_task/__manifest__.py | 31 ++ yuthon_will_task/controllers/__init__.py | 1 + yuthon_will_task/controllers/main.py | 282 +++++++++++++ yuthon_will_task/data/mail_template.xml | 18 + yuthon_will_task/data/task_code_data.xml | 10 + yuthon_will_task/data/tsak_time_data.xml | 28 ++ yuthon_will_task/data/will_task_time_data.xml | 31 ++ yuthon_will_task/models/__init__.py | 3 + yuthon_will_task/models/yuthon_dates_task.py | 11 + yuthon_will_task/models/yuthon_task_time.py | 20 + yuthon_will_task/models/yuthon_will_task.py | 397 ++++++++++++++++++ yuthon_will_task/security/ir.model.access.csv | 7 + .../security/yuthon_will_task_security.xml | 17 + yuthon_will_task/static/description/icon.png | Bin 0 -> 3480 bytes .../static/src/js/task_create_button.js | 28 ++ .../static/src/scss/yuthon_will_task.scss | 4 + .../static/src/xml/task_create_button.xml | 10 + .../views/yuthon_dates_task_views.xml | 38 ++ yuthon_will_task/views/yuthon_task_menu.xml | 26 ++ .../views/yuthon_task_time_views.xml | 21 + .../views/yuthon_will_task_views.xml | 371 ++++++++++++++++ 42 files changed, 2187 insertions(+) create mode 100644 yuthon_notice/__init__.py create mode 100644 yuthon_notice/__manifest__.py create mode 100644 yuthon_notice/controllers/__init__.py create mode 100644 yuthon_notice/controllers/main.py create mode 100644 yuthon_notice/data/notice_code_data.xml create mode 100644 yuthon_notice/data/notice_cron_data.xml create mode 100644 yuthon_notice/data/notice_type_data.xml create mode 100644 yuthon_notice/models/__init__.py create mode 100644 yuthon_notice/models/yuthon_confirm_users.py create mode 100644 yuthon_notice/models/yuthon_notice.py create mode 100644 yuthon_notice/models/yuthon_notice_type.py create mode 100644 yuthon_notice/security/ir.model.access.csv create mode 100644 yuthon_notice/static/description/icon.png create mode 100644 yuthon_notice/static/scss/notice_scss.scss create mode 100644 yuthon_notice/static/src/js/custom_create_button.js create mode 100644 yuthon_notice/static/src/xml/custom_create_button.xml create mode 100644 yuthon_notice/views/yuthon_confirm_users_views.xml create mode 100644 yuthon_notice/views/yuthon_cs_tree_views.xml create mode 100644 yuthon_notice/views/yuthon_notice_type_views.xml create mode 100644 yuthon_notice/views/yuthon_notice_views.xml create mode 100644 yuthon_will_task/__init__.py create mode 100644 yuthon_will_task/__manifest__.py create mode 100644 yuthon_will_task/controllers/__init__.py create mode 100644 yuthon_will_task/controllers/main.py create mode 100644 yuthon_will_task/data/mail_template.xml create mode 100644 yuthon_will_task/data/task_code_data.xml create mode 100644 yuthon_will_task/data/tsak_time_data.xml create mode 100644 yuthon_will_task/data/will_task_time_data.xml create mode 100644 yuthon_will_task/models/__init__.py create mode 100644 yuthon_will_task/models/yuthon_dates_task.py create mode 100644 yuthon_will_task/models/yuthon_task_time.py create mode 100644 yuthon_will_task/models/yuthon_will_task.py create mode 100644 yuthon_will_task/security/ir.model.access.csv create mode 100644 yuthon_will_task/security/yuthon_will_task_security.xml create mode 100644 yuthon_will_task/static/description/icon.png create mode 100644 yuthon_will_task/static/src/js/task_create_button.js create mode 100644 yuthon_will_task/static/src/scss/yuthon_will_task.scss create mode 100644 yuthon_will_task/static/src/xml/task_create_button.xml create mode 100644 yuthon_will_task/views/yuthon_dates_task_views.xml create mode 100644 yuthon_will_task/views/yuthon_task_menu.xml create mode 100644 yuthon_will_task/views/yuthon_task_time_views.xml create mode 100644 yuthon_will_task/views/yuthon_will_task_views.xml diff --git a/yuthon_notice/__init__.py b/yuthon_notice/__init__.py new file mode 100644 index 0000000..724cd13 --- /dev/null +++ b/yuthon_notice/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import models +from . import controllers \ No newline at end of file diff --git a/yuthon_notice/__manifest__.py b/yuthon_notice/__manifest__.py new file mode 100644 index 0000000..fd3f9e7 --- /dev/null +++ b/yuthon_notice/__manifest__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Yuthon notice", + 'summary': "通知公告", + 'description': """ + + """, + 'author': 'pengyuthon', + 'website': 'https://www.pengyuthon.com', + 'category': 'Human Resources/Attendances', + 'version': '0.1', + 'license': 'LGPL-3', + 'depends': ['base', 'hr', 'mail'], + 'data': [ + 'security/ir.model.access.csv', + 'data/notice_code_data.xml', + 'data/notice_cron_data.xml', + 'data/notice_type_data.xml', + 'views/yuthon_notice_views.xml', + 'views/yuthon_notice_type_views.xml', + 'views/yuthon_cs_tree_views.xml', + 'views/yuthon_confirm_users_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'yuthon_notice/static/src/js/custom_create_button.js', + 'yuthon_notice/static/src/xml/custom_create_button.xml', + 'yuthon_notice/static/scss/notice_scss.scss', + ], + }, + 'installable': True, + 'application': True, +} \ No newline at end of file diff --git a/yuthon_notice/controllers/__init__.py b/yuthon_notice/controllers/__init__.py new file mode 100644 index 0000000..527c0a0 --- /dev/null +++ b/yuthon_notice/controllers/__init__.py @@ -0,0 +1 @@ +from . import main \ No newline at end of file diff --git a/yuthon_notice/controllers/main.py b/yuthon_notice/controllers/main.py new file mode 100644 index 0000000..cd0af36 --- /dev/null +++ b/yuthon_notice/controllers/main.py @@ -0,0 +1,133 @@ +import base64 +import json + +from odoo import http, fields +from odoo.http import request +from urllib.parse import quote + + +class YuthonNotice(http.Controller): + + @http.route('/yuthon/yuthon/notice', methods=['POST'], type='http', auth='none', csrf=False) + def index(self, **kwargs): + id = kwargs.get('id') + + data = request.env['yuthon.notice'].sudo().search([("id", "=", int(id))]) + documents = [] + for document in data.documents_ids: + documents.append({ + 'id': document.id, + 'name': document.name, + 'url': document.url, + 'type': document.type, + 'file_size': document.file_size, + 'file_size_display':document.file_size_display, + 'mimetype': document.mimetype, + 'datas': document.datas.decode('utf-8') if document.datas else None, + }) + + result = { + 'id': data.id, + 'title': data.name, + 'code': data.code, + 'create_date1': fields.Date.to_string(data.create_date1), + 'notice_text': data.notice_text, + 'documents':documents, + 'user_name':data.users_id.name, + 'read_number': data.read_number, + } + return json.dumps({ + 'data':result, + 'code':200, + 'message':'success' + }) + + @http.route('/yuthon/notice/list', methods=['POST'], type='http', auth='none', csrf=False) + def yuthon_notice_list(self, **kwargs): + user_id = kwargs.get('users_id') # 按创建人筛选 + domain = [] + if user_id: + user_id_int = int(user_id) + domain.append(('users_id', '=', user_id_int)) + notice_data = request.env['yuthon.notice'].sudo().search(domain) + result_list = [] + urgency_map = {'normal': '普件', 'urgent': '急件', 'emergency': '特急件'} + for notice in notice_data: + department_list = [] + file_list = [] + for attach in notice.documents_ids: + file_url = 'http://view.officeapps.live.com/op/view.aspx?src=' + quote('https://oa.thtzjt.com' + '/web/content/office_preview/' + str(attach.id)) + file_list.append({'file_url': file_url, 'file_name': attach.display_name}) + result = { + 'id': notice.id, + 'title': notice.name, + 'code': notice.code, + 'notice_text': notice.notice_text, + 'create_date1': fields.Date.to_string(notice.create_date1), + 'user_name': notice.users_id.name, + 'read_number': notice.read_number or 0, + 'department_ids': department_list, + 'file_list': file_list, + 'urgency_level': notice.urgency_level, + 'urgency_name': urgency_map.get(notice.urgency_level, ''), + } + result_list.append(result) + return json.dumps({ + 'data': result_list, + 'code': 200, + 'message': 'success' + }) + + + @http.route('/yuthon/notice/record', methods=['POST'], type='http', auth='none', csrf=False) + def yuthon_notice_record(self, **kwargs): + id = kwargs.get('id') + + data = request.env['yuthon.notice'].sudo().search([("id", "=", int(id))]) + + department_list = [] + for dept in data.department_ids: + department_list.append({ + 'id': dept.id, + 'name': dept.name, + }) + + role_group_list = [ + {'id': group.id, 'name': group.name} # res.groups的name字段是角色组名称 + for group in data.users_role_group_ids + ] + + file_list = [] + for attach in data.documents_ids: + attach_id = request.env['ir.attachment'].sudo().search([('id', '=', attach.id)]) + file_url = 'http://view.officeapps.live.com/op/view.aspx?src=' + quote('https://oa.thtzjt.com' + '/web/content/office_preview/' + str(attach_id.id)) + file_list.append({ + 'file_url': file_url, + 'file_name': attach_id.display_name, + }) + + urgency_map = {'normal': '普件','urgent': '急件','emergency': '特急件',} + + urgency_name = urgency_map.get(data.urgency_level) + + result = { + 'id': data.id, + 'title': data.name, + 'code': data.code, + 'notice_text': data.notice_text, + 'create_date1': fields.Date.to_string(data.create_date1), + 'user_name': data.users_id.name, + 'read_number': data.read_number, + 'department_ids': department_list, + 'users_role_group_ids': role_group_list, + 'file_list': file_list, + 'urgency_name': urgency_name, + } + return json.dumps({ + 'data':result, + 'code':200, + 'message':'success' + }) + + + diff --git a/yuthon_notice/data/notice_code_data.xml b/yuthon_notice/data/notice_code_data.xml new file mode 100644 index 0000000..69a0950 --- /dev/null +++ b/yuthon_notice/data/notice_code_data.xml @@ -0,0 +1,24 @@ + + + + 通知公告编号 + notice_code + TZ%(y)s%(month)s%(day)s + 3 + + + + + diff --git a/yuthon_notice/data/notice_cron_data.xml b/yuthon_notice/data/notice_cron_data.xml new file mode 100644 index 0000000..c9c3b55 --- /dev/null +++ b/yuthon_notice/data/notice_cron_data.xml @@ -0,0 +1,15 @@ + + + + + 公告未确认通知 + + code + model.sync_confirm_users_notices() + + + 1 + days + + + \ No newline at end of file diff --git a/yuthon_notice/data/notice_type_data.xml b/yuthon_notice/data/notice_type_data.xml new file mode 100644 index 0000000..ce6d7e6 --- /dev/null +++ b/yuthon_notice/data/notice_type_data.xml @@ -0,0 +1,7 @@ + + + 通知 + 公告 + 决定 + 其他 + \ No newline at end of file diff --git a/yuthon_notice/models/__init__.py b/yuthon_notice/models/__init__.py new file mode 100644 index 0000000..b3a43c5 --- /dev/null +++ b/yuthon_notice/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- + +from . import yuthon_notice +from . import yuthon_notice_type +from . import yuthon_confirm_users + diff --git a/yuthon_notice/models/yuthon_confirm_users.py b/yuthon_notice/models/yuthon_confirm_users.py new file mode 100644 index 0000000..a1e013c --- /dev/null +++ b/yuthon_notice/models/yuthon_confirm_users.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models, tools +from odoo.exceptions import UserError, ValidationError + + +class YuthonConfirmUsers(models.Model): + _name = "yuthon.confirm.users" + _description = "公告确认信息" + + employee_id = fields.Many2one('hr.employee', string='员工') + notice_id = fields.Many2one('yuthon.notice', string="公告名称") + notice_code = fields.Char(string="公告编号") + notice_name = fields.Char(string="公告名称") + state = fields.Selection([('no', '未确认'), ('yes', '已确认')], string="状态") + + def sync_confirm_users_notices(self): + menu_id = self.env['ir.ui.menu'].search([('name', '=', '通知公告')]) + for record in self.search([('state', '=', 'no')]): + partner_ids = record.employee_id.user_id.partner_id.id + record.with_context(lang=record.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_notice.message_yuthon_confirm_users_data') + url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=yuthon.notice&view_type=list&menu_id={menu_id.id}' + self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=record.employee_id.wecom_userid, title="通知公告", + description="您有待确认的通知公告请尽快确认", url=url, btntxt="详细信息") + + def reminders_notice(self): + for rem in self: + if rem.state == 'yes': + raise UserError('已确认不可催办') + confirm_noice_ids = self.env["yuthon.confirm.users"].browse(self._context.get('active_ids', self._context.get('active_id'))) + for rec in confirm_noice_ids: + menu_id = self.env['ir.ui.menu'].search([('name', '=', '通知公告')]) + url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=yuthon.notice&view_type=list&menu_id={menu_id.id}' + self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=rec.employee_id.wecom_userid, + title="通知公告(催办)", description="您有待确认的通知公告请尽快确认", + url=url, btntxt="详细信息") + partner_ids = rec.employee_id.user_id.partner_id.id + rec.with_context(lang=rec.env.lang)._message_auto_subscribe_notify(partner_ids, + 'yuthon_notice.message_yuthon_confirm_users_data') diff --git a/yuthon_notice/models/yuthon_notice.py b/yuthon_notice/models/yuthon_notice.py new file mode 100644 index 0000000..46cfa01 --- /dev/null +++ b/yuthon_notice/models/yuthon_notice.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models, tools, _ +from odoo.exceptions import ValidationError, UserError +import logging + +_logger = logging.getLogger(__name__) + + +class YuthonNotice(models.Model): + _name = "yuthon.notice" + _description = '通知公告' + _inherit = ['mail.thread.main.attachment', 'mail.activity.mixin'] + _rec_name = 'name' + _order = "sequence desc" + + name = fields.Char(string='标题') + code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('notice_code')) + users_id = fields.Many2one('res.users', string="发布人", default=lambda self: self.env.user) + company_id = fields.Many2one(related="users_id.employee_id.company_id", string="公司", store=True) + department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门") + notice_type_id = fields.Many2one('yuthon.notice.type', string="类型") + create_date1 = fields.Date(string="发布日期", default=fields.Date.today()) + start_date = fields.Date(string="生效日期", default=fields.Date.today()) + end_date = fields.Date(string="终止日期") + sequence = fields.Integer(string="顺序",compute='_compute_sequence',store=True) + employee_ids = fields.Many2many('hr.employee', string="人员范围") + department_ids = fields.Many2many('hr.department', string='部门范围') + users_role_ids = fields.Many2many('res.groups', string='角色范围') + users_role_group_ids = fields.Many2many('res.groups', string='角色组', relation='yuthon_notice_role_group_rel') + notice_state = fields.Selection([('no', '未发布'), ('yes', '已发布'), ('stop', '已终止')], default='no', string="公告状态") + documents_ids = fields.Many2many('ir.attachment', string="附件") + is_notice_roger = fields.Selection([('yes', '已读'), ('no', '未读')], default='no', string="确认状态") + is_change_notice = fields.Boolean(string="是否发送通知", default=True) + attn_notice = fields.Html(string="经办人意见") + notice_text = fields.Html(string="正文") + read_number = fields.Integer(string='阅读量', compute="_compute_read_number", store=True) + is_this_company = fields.Boolean(string='本公司', default=True) + approval_user_id = fields.Many2one('res.users', string="审核人") + approval_date = fields.Datetime(string="审核日期") + is_sticky = fields.Boolean(string="是否置顶") + urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度', default='normal') + active = fields.Boolean('Active', default=True, tracking=True) + + work_end = fields.Boolean(string="结束") + users_ids = fields.Many2many( + 'res.users', + relation='yuthon_notice_users_rel', + column1='notice_id', + column2='user_id', + string='用户' + ) + self_users_ids = fields.Many2many( + 'res.users', + relation='yuthon_notice_current_users_rel', + column1='notice_id', + column2='user_id', + string="当前经办人", + store=True, + ) + + @api.model_create_multi + def create(self, vals_list): + for i in vals_list: + if i['department_ids'] == i['employee_ids'] == i['users_role_ids'] == i['users_role_group_ids']: + raise UserError('请填写发布的范围') + return super().create(vals_list) + + def _get_default_name_title(self): + return self._description if self._description else self._name + + name_title = fields.Char(default=_get_default_name_title) + + @api.constrains('employee_ids', 'department_ids', 'users_role_ids', 'users_role_group_ids') + def _constrains_employee_related_fields(self): + + def get_department_employees(department_id): + valid_user_ids = set() + employee_ids = self.env['hr.employee'].search([('department_id', '=', department_id.id)]) + valid_user_ids.update([emp.user_id.id for emp in employee_ids if emp.user_id]) + child_ids = self.env['hr.department'].search([('parent_id', '=', department_id.id)]) + for child in child_ids: + valid_user_ids.update(get_department_employees(child)) + return valid_user_ids + + for notice in self: + if notice.env.context.get('skip_constrains'): + continue + + department_user_ids = set() + for department_id in notice.department_ids: + department_user_ids.update(get_department_employees(department_id)) + group_role_ids = notice.users_role_group_ids + all_users = set( + notice.employee_ids.mapped('user_id').ids + + group_role_ids.mapped('users').ids + + notice.users_role_ids.mapped('users').ids + + list(department_user_ids) + ) + notice.with_context(skip_constrains=True).users_ids = [(6, 0, list(all_users))] + + def get_no_read_count(self): + return self.search_count([('is_notice_roger', '=', 'no'), ('notice_state', '=', 'yes')]) + + def read(self, fields=None, load='_classic_read'): + for con in self: + con_id = self.env['yuthon.confirm.users'].search([('notice_id', '=', con.id), ('employee_id', '=', con.env.user.employee_id.id)]) + if con_id.employee_id == con.env.user.employee_id: + con.is_notice_roger = 'yes' + con_id.write({'state': 'yes'}) + return super(YuthonNotice, self).read(fields=fields, load=load) + + @api.depends('read_number') + def _compute_read_number(self): + notice_confirm_ids = self.env['yuthon.confirm.users'].search( + [('notice_id.id', '=', self.id), ('state', '=', 'yes')]) + for read in self: + if notice_confirm_ids: + read.read_number = len(notice_confirm_ids) + else: + read.read_number = 0 + + def on_sequence(self): + self.sequence = 1 + + @api.onchange('is_sticky') + def _compute_sequence(self): + for i in self: + if i.is_sticky: + i.sequence = 1 + else: + i.sequence = 0 + + def no_sequence(self): + self.sequence = 0 + + def notice_publish(self): + if self.is_change_notice: + conf_old = self.env['yuthon.confirm.users'].search([('notice_id', '=', self.id), ('employee_id', 'in', self.users_ids.ids)]) + for user_id in self.users_ids: + url = f'http://oa.thtzjt.com/webh5#/notice?id={self.id}' + if conf_old: + for co in conf_old: + co.write({'state': 'no'}) + else: + self.env['yuthon.confirm.users'].create({ + 'notice_id': self.id, + 'employee_id': user_id.employee_ids.id, + 'notice_code': self.code, + 'notice_name': self.name, + 'state': 'no', + }) + we_id = self.env['hr.employee'].search([('id', '=', user_id.employee_ids.id)]).wecom_userid + self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=we_id, title="通知公告", + description=self.name + '发布人:' + self.users_id.name, + url=url, btntxt="详细信息") + self.write({"notice_state": 'yes'}) + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'type': 'success', + 'message': '通知公告已经发布', + 'sticky': False, + } + } + else: + raise UserError('该公告不允许通知,请勾选通知') + + + def look_up_notice_users(self): + return { + "type": "ir.actions.act_window", + "name": "通知公告确认信息", + "domain": [("notice_id", "=", self.id)], + "res_model": "yuthon.confirm.users", + "view_mode": "tree", + "context": { + "search_default_group_state": True, + }, + } + + def stop_notice(self): + self.write({ + 'notice_state': 'stop', + 'end_date': fields.Date.today(), + }) + + +class YuthonCsTree(models.Model): + _name = 'yuthon.cs.tree' + _description = 'Yuthon Customer Service Tree' + + name = fields.Char(string='Name', required=True) + + def _compute_sequence(self): + for record in self: + record.sequence = 1 + + + + +# 工作流的指定申请人逻辑? +# 转交的时候选择条件,进行优化 + +# 报表合同和产品业务 +# 企业微信等三方平台框架--和工作流 \ No newline at end of file diff --git a/yuthon_notice/models/yuthon_notice_type.py b/yuthon_notice/models/yuthon_notice_type.py new file mode 100644 index 0000000..abe2295 --- /dev/null +++ b/yuthon_notice/models/yuthon_notice_type.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models, tools +from odoo.exceptions import ValidationError, UserError + + +class YuthonNoticeType(models.Model): + _name = "yuthon.notice.type" + _description = "通知公告类型管理" + + name = fields.Char(string="类型名称") + note = fields.Char(string="说明") diff --git a/yuthon_notice/security/ir.model.access.csv b/yuthon_notice/security/ir.model.access.csv new file mode 100644 index 0000000..fd6f27c --- /dev/null +++ b/yuthon_notice/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_yuthon_notice,yuthon_notice,model_yuthon_notice,,1,1,1,1 +access_yuthon_notice_type,yuthon_notice_type,model_yuthon_notice_type,base.group_user,1,1,1,1 +access_yuthon_confirm_users,yuthon_confirm_users,model_yuthon_confirm_users,base.group_user,1,1,1,1 +access_yuthon_cs_tree,yuthon_cs_tree,model_yuthon_cs_tree,base.group_user,1,1,1,1 + diff --git a/yuthon_notice/static/description/icon.png b/yuthon_notice/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f2d4dacc2b932582e54cacb842b0c0d72c450c GIT binary patch literal 7790 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

4+%aS# z2ossHFMx>v#)UMmx`bh1QG)ok&Q#uisujOUnWc?Y~@lOph;TUv*fG|1LT z4i#sOt#}hoC!*8AI0J-tNd?gOIw-(+4TNRPygZ@SF7He&*;t2B8WOUl4YI95gLhc( zqfLCqh*^LW8ls*a<+hUZ8))9(vx(A#=fDwm6MRg7g zxC&V25tetQ>|aDR&!Bn5(jeQ4F;vW)%&ev{dmkNnHXq0EAqGul z#*~I`0E)mJ;cqY_!lML!Wb<(Yj~QwEsR*Ri^c1u~c2ENMcB>1U;P055494W3P4Ajs z;Tc1Bv19VDj> zQf1ZLg7sMtzEmYV+AzjdM%w;zw3CcRcG@6S)}dUO*X>c|VFGrok}?7#@NYe+EN$62 zxhKGT0`w1W?4;b2NB)jI>8*eBX)iPQfBZiQD49pQVzog8m3JNMP5}PiY|+KQ54ueIG!bbOaLKX0Pr#`GV%}w#w)hyd0OQ1h zq75P_W7*00TZ3;FP~L?4O}M*z>}!H>-^m#qu&xQ(^m+3u+MJ}Bza@-3+98HEh_K2f z$MWB11vw!rl+#*kIUSgRN4iYARksQVD-{l08$_t1>sX%vuuw?b7JjK=+Wz_Q;>&d` z|Ge;Ti-~U$&NECq*vU>c4BE<6ZIA%fa~;8qWuueK>c$;lk6Kp6&R2S|4- zW6b$s-DhgH1F6auF~bW*Kj zG5E|bGrz3XIPJ#Q1_@a4av^&y6JH#Vz8xB^BjV@$A28GY0E-?c?<@~ux-OZ{T@qfd z?Gs5Gq=s6%j^&^C9`&~^KQTM%7(&VG=s2)O z2*4g8h82XOK`@;irQWuJjp_Y@{jZcK%)Jg7~##)e$RH^XUz z)JfUFg7tqC`9`VxtI10Y@5(N7ey&baY3s1sAayLi|7ucU{uFIFNh|b=fdz`aZzt39 z_1=!q)!hCLcZX0%_L%qU949pB;I09~G57!$#_I+W*(=m3efHp`2?~byQ{aD50 zqm=TO%kxow2lwiRXTKZ#!=8sn5{e#f=8ew)N23AZ=ZKJ^9fT&;}VzA^r2VRzMr1t;??`KbivC zAfqXyf8N##XoIwM`Ss*SQ$QPJG==of+ggGD55QZ&P)S99JOBUy07*qoM6N<$g7i)X A8vp + + + + + + + diff --git a/yuthon_notice/views/yuthon_confirm_users_views.xml b/yuthon_notice/views/yuthon_confirm_users_views.xml new file mode 100644 index 0000000..6cc06e4 --- /dev/null +++ b/yuthon_notice/views/yuthon_confirm_users_views.xml @@ -0,0 +1,38 @@ + + + + yuthon.confirm.users.tree + yuthon.confirm.users + + +

+
+ + + + + + + + + + yuthon.confirm.users.search + yuthon.confirm.users + + + + + + + + + + + 公告确认信息 + yuthon.confirm.users + list + + + \ No newline at end of file diff --git a/yuthon_notice/views/yuthon_cs_tree_views.xml b/yuthon_notice/views/yuthon_cs_tree_views.xml new file mode 100644 index 0000000..eec7a0e --- /dev/null +++ b/yuthon_notice/views/yuthon_cs_tree_views.xml @@ -0,0 +1,17 @@ + + + + yuthon.cs.tree + yuthon.cs.tree + + + + + + + + Yuthon CS Tree + yuthon.cs.tree + list + + \ No newline at end of file diff --git a/yuthon_notice/views/yuthon_notice_type_views.xml b/yuthon_notice/views/yuthon_notice_type_views.xml new file mode 100644 index 0000000..5e0b009 --- /dev/null +++ b/yuthon_notice/views/yuthon_notice_type_views.xml @@ -0,0 +1,33 @@ + + + + yuthon.notice.type.tree + yuthon.notice.type + + + + + + + + + + + 公告类型管理 + yuthon.notice.type + list + + + + + + + \ No newline at end of file diff --git a/yuthon_notice/views/yuthon_notice_views.xml b/yuthon_notice/views/yuthon_notice_views.xml new file mode 100644 index 0000000..b206c5b --- /dev/null +++ b/yuthon_notice/views/yuthon_notice_views.xml @@ -0,0 +1,216 @@ + + + + yuthon.notice.tree + yuthon.notice + + + + + + + + + + + + + + diff --git a/yuthon_will_task/views/yuthon_dates_task_views.xml b/yuthon_will_task/views/yuthon_dates_task_views.xml new file mode 100644 index 0000000..7a3c170 --- /dev/null +++ b/yuthon_will_task/views/yuthon_dates_task_views.xml @@ -0,0 +1,38 @@ + + + + yuthon.dates.task.tree + yuthon.dates.task + + + + + + + + + + + yuthon.dates.task.search + yuthon.dates.task + + + + + + + + + + + 日程任务 + yuthon.dates.task + tree + + + {'search_default_task_state':1} + + diff --git a/yuthon_will_task/views/yuthon_task_menu.xml b/yuthon_will_task/views/yuthon_task_menu.xml new file mode 100644 index 0000000..7a54cb0 --- /dev/null +++ b/yuthon_will_task/views/yuthon_task_menu.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/yuthon_will_task/views/yuthon_task_time_views.xml b/yuthon_will_task/views/yuthon_task_time_views.xml new file mode 100644 index 0000000..5ddad4e --- /dev/null +++ b/yuthon_will_task/views/yuthon_task_time_views.xml @@ -0,0 +1,21 @@ + + + + yuthon.task.time.tree + yuthon.task.time + + + + + + + + + + + + 提醒时长配置 + yuthon.task.time + tree + + diff --git a/yuthon_will_task/views/yuthon_will_task_views.xml b/yuthon_will_task/views/yuthon_will_task_views.xml new file mode 100644 index 0000000..a47e339 --- /dev/null +++ b/yuthon_will_task/views/yuthon_will_task_views.xml @@ -0,0 +1,371 @@ + + + + yuthon.will.task.tree + yuthon.will.task + + + + + + + + + + + +