增加信息汇总表报表
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
import json
|
||||
from odoo.exceptions import ValidationError
|
||||
import datetime
|
||||
|
||||
|
||||
class Statement(http.Controller):
|
||||
@@ -29,10 +30,125 @@ class Statement(http.Controller):
|
||||
{'id': 203, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 204, 'name': "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
'groupName': "物管公司",
|
||||
'items': [
|
||||
{'id': 201, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 202, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 203, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 204, 'name': "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
'groupName': "粮储公司",
|
||||
'items': [
|
||||
{'id': 201, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 202, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 203, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 204, 'name': "说明"}
|
||||
]
|
||||
}
|
||||
]
|
||||
return companyGroups
|
||||
|
||||
@http.route('/get/account/project', auth='user', type='json', methods=['POST'])
|
||||
def getAccountProject(self, **kw):
|
||||
data = kw.get('data', '')
|
||||
values = {
|
||||
'101': "10000.00",
|
||||
'102': "2000.00",
|
||||
'103': "1500.00",
|
||||
'104': "说明1",
|
||||
'201': "8000.00",
|
||||
'202': "1000.00",
|
||||
'203': "800.00",
|
||||
'204': "说明2"
|
||||
}
|
||||
rawRows = []
|
||||
cons = request.env['sheet.collection.setting'].search([])
|
||||
for con in cons:
|
||||
result = con.check_today()
|
||||
if isinstance(result, str):
|
||||
raise ValidationError(result)
|
||||
else:
|
||||
if result:
|
||||
one = {
|
||||
'id': con.sequence,
|
||||
'name': con.name,
|
||||
'values': values
|
||||
}
|
||||
rawRows.append(one)
|
||||
rawRows.sort(key=lambda x: int(x['id']))
|
||||
return rawRows
|
||||
|
||||
@http.route('/financial/single/get/data', type='json', auth='user', methods=['POST'])
|
||||
def get_financial_data(self, filters=None, **kwargs):
|
||||
"""获取财务数据"""
|
||||
try:
|
||||
# 解析筛选条件
|
||||
date = filters.get('date',
|
||||
datetime.date.today().isoformat()) if filters else datetime.date.today().isoformat()
|
||||
company = filters.get('company', '')
|
||||
department = filters.get('department', '')
|
||||
|
||||
data = {
|
||||
'headers': [
|
||||
{'id': 1, 'title': "去年底", 'subtitle': ""},
|
||||
{'id': 2, 'title': "本年当月", 'subtitle': ""},
|
||||
{'id': 3, 'title': "去年同月", 'subtitle': ""},
|
||||
{'id': 4, 'title': "同比增长", 'subtitle': "%"},
|
||||
{'id': 5, 'title': "说明", 'subtitle': ""},
|
||||
{'id': 6, 'title': "天河公司", 'subtitle': ""},
|
||||
{'id': 7, 'title': "天河物管", 'subtitle': ""},
|
||||
{'id': 8, 'title': "天河粮储", 'subtitle': ""},
|
||||
],
|
||||
'filters': {
|
||||
'date': date,
|
||||
'company': company,
|
||||
'department': department
|
||||
}
|
||||
}
|
||||
|
||||
# 这里应该从数据库中获取实际数据
|
||||
values = {'1': 100, '2': 200, '3': 300, '4': 400, '5': 500, '6': 600, '7': 700, '8': 800}
|
||||
# 暂时返回演示数据
|
||||
cons = request.env['summary.table.setting'].search([])
|
||||
rows = []
|
||||
for con in cons:
|
||||
result = con.check_today()
|
||||
if isinstance(result, str):
|
||||
raise ValidationError(result)
|
||||
else:
|
||||
if result:
|
||||
one = {
|
||||
'id': con.sequence,
|
||||
'name': con.name,
|
||||
'values': values
|
||||
}
|
||||
if ':' in con.name or ':' in con.name:
|
||||
one['indent'] = 1
|
||||
elif '、' in con.name:
|
||||
one['indent'] = 0
|
||||
else:
|
||||
one['indent'] = 2
|
||||
rows.append(one)
|
||||
rows.sort(key=lambda x: int(x['id']))
|
||||
|
||||
data['rows'] = rows
|
||||
|
||||
return data
|
||||
|
||||
except Exception as e:
|
||||
|
||||
return {
|
||||
'headers': [],
|
||||
'rows': []
|
||||
}
|
||||
|
||||
|
||||
# @http.route('/statement/statement/objects', auth='public')
|
||||
# def list(self, **kw):
|
||||
# return http.request.render('statement.listing', {
|
||||
|
||||
@@ -48,6 +48,19 @@ class SheetCollectionSetting(models.Model):
|
||||
'context': {'default_financial_ids': collection_ids.ids}
|
||||
}
|
||||
|
||||
def check_today(self):
|
||||
self.ensure_one()
|
||||
today = fields.Date.today()
|
||||
if self.start_date and self.end_date:
|
||||
return self.start_date <= today <= self.end_date
|
||||
elif self.start_date and not self.end_date:
|
||||
return self.start_date <= today
|
||||
elif not self.start_date and self.end_date:
|
||||
return today <= self.end_date
|
||||
else:
|
||||
return '缺少参数'
|
||||
|
||||
|
||||
class SummaryTableSetting(models.Model):
|
||||
_name = 'summary.table.setting'
|
||||
_description = '信息汇总表项目配置'
|
||||
@@ -92,3 +105,15 @@ class SummaryTableSetting(models.Model):
|
||||
'target': 'new',
|
||||
'context': {'default_information_ids': table_ids.ids}
|
||||
}
|
||||
|
||||
def check_today(self):
|
||||
self.ensure_one()
|
||||
today = fields.Date.today()
|
||||
if self.start_date and self.end_date:
|
||||
return self.start_date <= today <= self.end_date
|
||||
elif self.start_date and not self.end_date:
|
||||
return self.start_date <= today
|
||||
elif not self.start_date and self.end_date:
|
||||
return today <= self.end_date
|
||||
else:
|
||||
return '缺少参数'
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* Financial Page Component Styles
|
||||
* 财务页面组件样式 - 独立CSS文件,使用.financial-container命名空间避免污染
|
||||
*/
|
||||
|
||||
/* 主容器 */
|
||||
.financial-container {
|
||||
@@ -19,27 +15,35 @@
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
/* 固定表头 */
|
||||
.financial-container .sticky-header th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: white;
|
||||
z-index: 100;
|
||||
z-index: 90; /* 降低z-index */
|
||||
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 固定第一列 */
|
||||
.financial-container .sticky-column {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background: white;
|
||||
z-index: 99;
|
||||
z-index: 100; /* 提高z-index */
|
||||
box-shadow: 2px 0 2px -1px rgba(0, 0, 0, 0.1);
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
/* 对角线表头特殊处理 - 最高优先级 */
|
||||
.financial-container .diagonal-header {
|
||||
z-index: 110 !important; /* 最高z-index */
|
||||
position: sticky;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: #f8f9fa !important;
|
||||
padding: 0 !important;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.financial-container .financial-table {
|
||||
margin: 0;
|
||||
border-collapse: separate;
|
||||
@@ -59,21 +63,13 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 对角线表头 - 修正方向:左上到右下,公司在上,项目在下 */
|
||||
.financial-container .diagonal-header {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding: 0 !important;
|
||||
width: 200px;
|
||||
background: #f8f9fa !important;
|
||||
}
|
||||
|
||||
.financial-container .diagonal-text-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 80px;
|
||||
padding: 8px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.financial-container .diagonal-line {
|
||||
@@ -82,7 +78,6 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* 修正:左上到右下(from top-left to bottom-right) */
|
||||
background: linear-gradient(to bottom left,
|
||||
transparent calc(50% - 1px),
|
||||
#333 calc(50% - 1px),
|
||||
@@ -113,7 +108,6 @@
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 表头样式 */
|
||||
.financial-container .group-header {
|
||||
background: linear-gradient(to bottom, #4e73df, #224abe) !important;
|
||||
color: white !important;
|
||||
@@ -121,6 +115,7 @@
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
min-width: 80px;
|
||||
z-index: 90; /* 确保不会超过对角线表头 */
|
||||
}
|
||||
|
||||
.financial-container .item-header {
|
||||
@@ -135,7 +130,6 @@
|
||||
border-right: 2px solid #1a237e !important;
|
||||
}
|
||||
|
||||
/* 表格内容样式 */
|
||||
.financial-container .project-cell {
|
||||
background: #f8f9fa !important;
|
||||
font-weight: 600;
|
||||
@@ -155,7 +149,6 @@
|
||||
background: #f0f8ff !important;
|
||||
}
|
||||
|
||||
/* 表头标题样式 */
|
||||
.financial-container .group-title {
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
@@ -179,7 +172,6 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 斑马纹效果 */
|
||||
.financial-container .financial-table tbody tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
@@ -189,7 +181,7 @@
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
|
||||
.financial-container .loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -212,14 +204,12 @@
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.financial-container .empty-state {
|
||||
padding: 40px;
|
||||
color: #6c757d;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.financial-container {
|
||||
padding: 10px;
|
||||
@@ -263,7 +253,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 合计行特殊样式 */
|
||||
.financial-container .financial-table tbody tr:last-child {
|
||||
background: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%) !important;
|
||||
font-weight: 700;
|
||||
@@ -273,7 +262,6 @@
|
||||
background: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%) !important;
|
||||
}
|
||||
|
||||
/* 预算行特殊样式 */
|
||||
.financial-container .financial-table tbody tr:nth-last-child(2) {
|
||||
background: linear-gradient(to right, #d4fc79 0%, #96e6a1 100%) !important;
|
||||
}
|
||||
@@ -282,7 +270,6 @@
|
||||
background: linear-gradient(to right, #d4fc79 0%, #96e6a1 100%) !important;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.financial-container .table-responsive-container::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@@ -302,7 +289,6 @@
|
||||
background: #555;
|
||||
}
|
||||
|
||||
/* 卡片样式优化 */
|
||||
.financial-container .card {
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
@@ -321,7 +307,6 @@
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
||||
}
|
||||
|
||||
/* 按钮样式优化 */
|
||||
.financial-container .btn-sm {
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
@@ -332,7 +317,6 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 筛选区域优化 */
|
||||
.financial-container .form-label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 3px;
|
||||
@@ -351,7 +335,6 @@
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
/* 信息行样式 */
|
||||
.financial-container .bg-light {
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
@@ -360,7 +343,6 @@
|
||||
border-bottom: 1px solid #dee2e6 !important;
|
||||
}
|
||||
|
||||
/* 工具按钮组 */
|
||||
.financial-container .btn-group {
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@@ -374,7 +356,6 @@
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 图标样式 */
|
||||
.financial-container .fa {
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -383,7 +364,6 @@
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/* 自适应调整 */
|
||||
@media (min-width: 1200px) {
|
||||
.financial-container .sticky-column {
|
||||
min-width: 250px;
|
||||
@@ -433,9 +413,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 确保不污染其他样式 - 严格的命名空间 */
|
||||
.financial-container *:not(.financial-container) {
|
||||
/* 重置所有非金融容器内的样式影响 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -445,7 +423,6 @@
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
/* 高度自适应 */
|
||||
.financial-container .row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/* 财务单一报表专用样式 - 独立作用域 */
|
||||
.financial-single-container * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 表格容器 */
|
||||
.financial-single-container .table-responsive-container {
|
||||
overflow-x: auto;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 表格样式 - 使用更具体的选择器 */
|
||||
.financial-single-container .financial-single-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.financial-single-container .financial-single-table th,
|
||||
.financial-single-container .financial-single-table td {
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 8px 12px;
|
||||
vertical-align: middle;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 固定表头 */
|
||||
.financial-single-container .sticky-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 固定第一列 */
|
||||
.financial-single-container .sticky-column {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
z-index: 5;
|
||||
border-right: 2px solid #dee2e6 !important;
|
||||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.financial-single-container .project-header {
|
||||
min-width: 250px;
|
||||
background-color: #f8f9fa !important;
|
||||
font-weight: 600;
|
||||
position: relative;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.financial-single-container .project-cell {
|
||||
min-width: 250px;
|
||||
background-color: white;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* 对角线表头样式 - 修复斜线 */
|
||||
.financial-single-container .diagonal-header {
|
||||
background-color: #f8f9fa;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
}
|
||||
|
||||
.financial-single-container .diagonal-text-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.financial-single-container .diagonal-line {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to bottom left,
|
||||
transparent calc(50% - 1px),
|
||||
#333 calc(50% - 1px),
|
||||
#333 calc(50% + 1px),
|
||||
transparent calc(50% + 1px));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.financial-single-container .diagonal-company {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 25px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
transform: translateX(50%);
|
||||
}
|
||||
|
||||
.financial-single-container .diagonal-project {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/* 表头样式 */
|
||||
.financial-single-container .single-header {
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: white !important;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
}
|
||||
|
||||
.financial-single-container .header-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.financial-single-container .header-title {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.financial-single-container .header-subtitle {
|
||||
font-size: 11px;
|
||||
opacity: 0.9;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* 数据行样式 */
|
||||
.financial-single-container .main-row {
|
||||
font-weight: 600;
|
||||
background-color: #f8f9fa !important;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-1 {
|
||||
font-weight: 500;
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-2 {
|
||||
font-weight: 400;
|
||||
background-color: #fff !important;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-1 .project-name {
|
||||
padding-left: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-1 .project-name::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-2 .project-name {
|
||||
padding-left: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.financial-single-container .sub-row-2 .project-name::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 28px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: #999;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.financial-single-container .data-cell {
|
||||
min-width: 100px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/* 卡片标题样式 - 白色字体 */
|
||||
.financial-single-container .card-header.bg-primary {
|
||||
background-color: #667eea !important;
|
||||
border-bottom: 1px solid #5569d6;
|
||||
}
|
||||
|
||||
.financial-single-container .card-header.bg-primary .card-title {
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.financial-single-container .card-header.bg-primary .card-title small {
|
||||
color: rgba(255, 255, 255, 0.85) !important;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.financial-single-container .card-header.bg-primary .card-title i {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.financial-single-container .card-header.bg-primary .btn-group .btn-light {
|
||||
background-color: rgba(255, 255, 255, 0.9) !important;
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
color: #667eea !important;
|
||||
}
|
||||
|
||||
.financial-single-container .card-header.bg-primary .btn-group .btn-light:hover {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* 筛选区域样式 */
|
||||
.financial-single-container .filter-card {
|
||||
border: 1px solid #e3e6f0;
|
||||
border-radius: 0.35rem;
|
||||
}
|
||||
|
||||
.financial-single-container .form-label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
color: #5a5c69;
|
||||
}
|
||||
|
||||
.financial-single-container .form-control-sm,
|
||||
.financial-single-container .form-select-sm {
|
||||
font-size: 13px;
|
||||
padding: 4px 8px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.financial-single-container .btn-sm {
|
||||
padding: 4px 12px;
|
||||
font-size: 13px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.financial-single-container .btn-primary {
|
||||
background-color: #667eea;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.financial-single-container .btn-primary:hover {
|
||||
background-color: #5a6fd8;
|
||||
border-color: #5a6fd8;
|
||||
}
|
||||
|
||||
.financial-single-container .btn-outline-secondary {
|
||||
color: #858796;
|
||||
border-color: #d1d3e2;
|
||||
}
|
||||
|
||||
.financial-single-container .btn-outline-secondary:hover {
|
||||
background-color: #eaecf4;
|
||||
border-color: #d1d3e2;
|
||||
color: #5a5c69;
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.financial-single-container .loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.financial-single-container .spinner-container {
|
||||
text-align: center;
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #e3e6f0;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.financial-single-container .empty-state {
|
||||
padding: 40px 0;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.financial-single-container .empty-state i {
|
||||
color: #d1d3e2;
|
||||
}
|
||||
|
||||
/* 卡片脚注 */
|
||||
.financial-single-container .card-footer {
|
||||
background-color: #f8f9fa !important;
|
||||
border-top: 1px solid #e3e6f0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.financial-single-container .card-footer .text-muted {
|
||||
color: #858796 !important;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.financial-single-container .project-header,
|
||||
.financial-single-container .project-cell {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.financial-single-container .single-header {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.financial-single-container .card-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.financial-single-container .card-title small {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
@media print {
|
||||
.financial-single-container .card-header.bg-primary {
|
||||
background-color: #667eea !important;
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
.financial-single-container .card-title,
|
||||
.financial-single-container .card-title small,
|
||||
.financial-single-container .card-title i {
|
||||
color: white !important;
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
.financial-single-container .sticky-column {
|
||||
position: static;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.financial-single-container .table-responsive-container {
|
||||
overflow: visible;
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import {registry} from "@web/core/registry";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
const { Component, useState, onWillStart, onMounted } = owl;
|
||||
const {Component, useState, onWillStart, onMounted} = owl;
|
||||
|
||||
class FinancialPage extends Component {
|
||||
setup() {
|
||||
@@ -35,21 +35,65 @@ class FinancialPage extends Component {
|
||||
employeeName: "所有员工"
|
||||
},
|
||||
pageTitle: "各公司主要财务数据",
|
||||
setting: { type: 'default' },
|
||||
setting: {type: 'default'},
|
||||
loading: false,
|
||||
demo: {
|
||||
companyGroups : [
|
||||
{
|
||||
'id': 1,
|
||||
'groupName': "天河投资",
|
||||
'items': [
|
||||
{'id': 101, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 102, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 103, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 104, 'name': "说明"}
|
||||
]
|
||||
}
|
||||
companyGroups: [
|
||||
{
|
||||
'id': 1,
|
||||
'groupName': "天河投资",
|
||||
'items': [
|
||||
{'id': 101, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 102, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 103, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 104, 'name': "说明"}
|
||||
]
|
||||
}
|
||||
],
|
||||
rawRows: [
|
||||
{
|
||||
id: 1,
|
||||
name: '资产总额',
|
||||
values: {
|
||||
101: "10000.00",
|
||||
102: "2000.00",
|
||||
103: "1500.00",
|
||||
104: "说明1",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明2"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '本年营业收入',
|
||||
values: {
|
||||
101: "5000.00",
|
||||
102: "1200.00",
|
||||
103: "800.00",
|
||||
104: "说明3",
|
||||
201: "4000.00",
|
||||
202: "900.00",
|
||||
203: "600.00",
|
||||
204: "说明4"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '本年利润总额',
|
||||
values: {
|
||||
101: "3000.00",
|
||||
102: "800.00",
|
||||
103: "500.00",
|
||||
104: "说明5",
|
||||
201: "2000.00",
|
||||
202: "600.00",
|
||||
203: "400.00",
|
||||
204: "说明6"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -75,7 +119,7 @@ class FinancialPage extends Component {
|
||||
'sheet.collection.setting',
|
||||
[],
|
||||
['id', 'name', 'type'],
|
||||
{ limit: 1 }
|
||||
{limit: 1}
|
||||
);
|
||||
|
||||
if (settings.length > 0) {
|
||||
@@ -92,33 +136,35 @@ class FinancialPage extends Component {
|
||||
|
||||
async loadDefaultData() {
|
||||
this.state.pageTitle = "各公司主要财务数据";
|
||||
this.state.setting = { type: 'default' };
|
||||
this.state.setting = {type: 'default'};
|
||||
|
||||
try {
|
||||
// 通过RPC调用后端接口
|
||||
const companyGroups = await this.rpc('/get/account/title');
|
||||
|
||||
if (companyGroups && companyGroups.length > 0) {
|
||||
const rawRows = await this.rpc('/get/account/project');
|
||||
|
||||
if (companyGroups && rawRows && companyGroups.length > 0 && rawRows.length > 0) {
|
||||
// 固定分组(合计和预算)
|
||||
const fixedGroups = [
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{ id: 1001, name: "本期数", fieldType: "万元" },
|
||||
{ id: 1002, name: "上年同期", fieldType: "万元" },
|
||||
{ id: 1003, name: "增幅", fieldType: "%" },
|
||||
{ id: 1004, name: "说明" }
|
||||
{id: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{ id: 2001, name: "预测财局下达目标", fieldType: "万元" },
|
||||
{ id: 2002, name: "完成率", fieldType: "%" },
|
||||
{ id: 2003, name: "集团目标", fieldType: "%" },
|
||||
{ id: 2004, name: "完成率", fieldType: "%" }
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -126,24 +172,6 @@ class FinancialPage extends Component {
|
||||
// 合并分组,确保固定分组在最后
|
||||
this.state.tableData.displayHeaders = [...companyGroups, ...fixedGroups];
|
||||
|
||||
// 原始行数据(不包含合计的计算)
|
||||
const rawRows = [
|
||||
{
|
||||
id: 1,
|
||||
name: '资产总额',
|
||||
values: {
|
||||
101: "10000.00",
|
||||
102: "2000.00",
|
||||
103: "1500.00",
|
||||
104: "说明1",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明2"
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
// 计算并添加合计数据
|
||||
const rowsWithTotals = this.calculateTotals(rawRows, companyGroups);
|
||||
this.state.tableData.rows = rowsWithTotals;
|
||||
@@ -168,168 +196,27 @@ class FinancialPage extends Component {
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{ id: 1001, name: "本期数", fieldType: "万元" },
|
||||
{ id: 1002, name: "上年同期", fieldType: "万元" },
|
||||
{ id: 1003, name: "增幅", fieldType: "%" },
|
||||
{ id: 1004, name: "说明" }
|
||||
{id: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{ id: 2001, name: "预测财局下达目标", fieldType: "万元" },
|
||||
{ id: 2002, name: "完成率", fieldType: "%" },
|
||||
{ id: 2003, name: "集团目标", fieldType: "%" },
|
||||
{ id: 2004, name: "完成率", fieldType: "%" }
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
this.state.tableData.displayHeaders = [...companyGroups, ...fixedGroups];
|
||||
|
||||
const rawRows = [
|
||||
{
|
||||
id: 1,
|
||||
name: '资产总额',
|
||||
values: {
|
||||
101: "10000.00",
|
||||
102: "2000.00",
|
||||
103: "1500.00",
|
||||
104: "说明1",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明2"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '本年营业收入',
|
||||
values: {
|
||||
101: "5000.00",
|
||||
102: "1200.00",
|
||||
103: "800.00",
|
||||
104: "说明3",
|
||||
201: "4000.00",
|
||||
202: "900.00",
|
||||
203: "600.00",
|
||||
204: "说明4"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '本年利润总额',
|
||||
values: {
|
||||
101: "3000.00",
|
||||
102: "800.00",
|
||||
103: "500.00",
|
||||
104: "说明5",
|
||||
201: "2000.00",
|
||||
202: "600.00",
|
||||
203: "400.00",
|
||||
204: "说明6"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '(自有物业)可出租面积(万平方米)',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明7",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明8"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '(自有物业)已出租面积(万平方米)',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明9",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明10"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '自有物业出租率',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明11",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明12"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '(代管物业)可出租面积(万平方米)',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明13",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明14"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '(代管物业)已出租面积(万平方米)',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明15",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明16"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '代管物业出租率',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明17",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明18"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '整体出租率',
|
||||
values: {
|
||||
101: "8000.00",
|
||||
102: "1000.00",
|
||||
103: "800.00",
|
||||
104: "说明19",
|
||||
201: "8000.00",
|
||||
202: "1000.00",
|
||||
203: "800.00",
|
||||
204: "说明20"
|
||||
}
|
||||
}
|
||||
];
|
||||
const rawRows = this.state.demo.rawRows
|
||||
|
||||
const rowsWithTotals = this.calculateTotals(rawRows, companyGroups);
|
||||
this.state.tableData.rows = rowsWithTotals;
|
||||
@@ -346,7 +233,7 @@ class FinancialPage extends Component {
|
||||
const newRow = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
values: { ...row.values }
|
||||
values: {...row.values}
|
||||
};
|
||||
|
||||
// 提取每个公司的本期数ID
|
||||
@@ -390,14 +277,14 @@ class FinancialPage extends Component {
|
||||
if (totalLastYear !== 0) {
|
||||
increaseRate = ((totalCurrentPeriod - totalLastYear) / totalLastYear * 100).toFixed(2);
|
||||
}
|
||||
newRow.values[1003] = increaseRate;
|
||||
newRow.values[1004] = "合计说明"; // 合计说明
|
||||
newRow.values[10003] = increaseRate;
|
||||
newRow.values[10004] = "合计说明"; // 合计说明
|
||||
|
||||
// 预算相关数据可以留空或设置默认值
|
||||
newRow.values[2001] = ""; // 预测财局下达目标
|
||||
newRow.values[2002] = ""; // 完成率
|
||||
newRow.values[2003] = ""; // 集团目标
|
||||
newRow.values[2004] = ""; // 完成率
|
||||
newRow.values[20001] = ""; // 预测财局下达目标
|
||||
newRow.values[20002] = ""; // 完成率
|
||||
newRow.values[20003] = ""; // 集团目标
|
||||
newRow.values[20004] = ""; // 完成率
|
||||
|
||||
return newRow;
|
||||
});
|
||||
@@ -411,21 +298,21 @@ class FinancialPage extends Component {
|
||||
'sheet.collection.setting.header',
|
||||
[['setting_id', '=', settingId]],
|
||||
['id', 'sequence', 'group_name', 'vertical_header_name'],
|
||||
{ order: 'sequence' }
|
||||
{order: 'sequence'}
|
||||
);
|
||||
|
||||
const headerItems = await this.orm.searchRead(
|
||||
'sheet.collection.setting.header.item',
|
||||
[['header_id.setting_id', '=', settingId]],
|
||||
['id', 'header_id', 'sequence', 'name', 'field_type'],
|
||||
{ order: 'sequence' }
|
||||
{order: 'sequence'}
|
||||
);
|
||||
|
||||
const dataRows = await this.orm.searchRead(
|
||||
'sheet.collection.setting.data',
|
||||
[['setting_id', '=', settingId]],
|
||||
['id', 'sequence', 'name'],
|
||||
{ order: 'sequence' }
|
||||
{order: 'sequence'}
|
||||
);
|
||||
|
||||
const dataValues = await this.orm.searchRead(
|
||||
@@ -518,20 +405,20 @@ class FinancialPage extends Component {
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{ id: 1001, name: "本期数", fieldType: "万元" },
|
||||
{ id: 1002, name: "上年同期", fieldType: "万元" },
|
||||
{ id: 1003, name: "增幅", fieldType: "%" },
|
||||
{ id: 1004, name: "说明" }
|
||||
{id: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{ id: 2001, name: "预测财局下达目标", fieldType: "万元" },
|
||||
{ id: 2002, name: "完成率", fieldType: "%" },
|
||||
{ id: 2003, name: "集团目标", fieldType: "%" },
|
||||
{ id: 2004, name: "完成率", fieldType: "%" }
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import {registry} from "@web/core/registry";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
const {Component, useState, onWillStart, useRef, onMounted} = owl;
|
||||
|
||||
export class FinancialSinglePage extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.orm = useService("orm");
|
||||
this.action = useService("action");
|
||||
this.rpc = useService("rpc");
|
||||
this.notification = useService("notification");
|
||||
|
||||
// 初始化状态
|
||||
this.state = useState({
|
||||
filters: {
|
||||
date: this.getCurrentDate(),
|
||||
company: "",
|
||||
department: "",
|
||||
},
|
||||
tableData: {
|
||||
headers: [],
|
||||
rows: [],
|
||||
},
|
||||
displayInfo: {
|
||||
reportDate: this.getCurrentDate(),
|
||||
companyName: "所有公司",
|
||||
departmentName: "所有部门"
|
||||
},
|
||||
pageTitle: "信息汇总表",
|
||||
loading: false,
|
||||
// 演示数据
|
||||
demoData: {
|
||||
headers: [
|
||||
{id: 1, title: "去年底", subtitle: ""},
|
||||
{id: 2, title: "本年当月", subtitle: ""},
|
||||
{id: 3, title: "去年同月", subtitle: ""},
|
||||
{id: 4, title: "同比增长", subtitle: "%"},
|
||||
{id: 5, title: "说明", subtitle: ""},
|
||||
{id: 6, title: "天河公司", subtitle: ""},
|
||||
{id: 7, title: "天河物管", subtitle: ""},
|
||||
{id: 8, title: "天河粮储", subtitle: ""},
|
||||
],
|
||||
rows: [
|
||||
{
|
||||
id: 1,
|
||||
name: '一、总资产',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '二、总负债',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '其中:有息负债',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '利息支出',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '三、净资产',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '四、经营收入(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '其中:物业租赁收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '储备粮轮换收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '利息收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '其他业务收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '五、利润总额(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: '六、净利润(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
// 引用
|
||||
this.tableRef = useRef("table");
|
||||
|
||||
onWillStart(async () => {
|
||||
await this.loadData();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
});
|
||||
}
|
||||
|
||||
getCurrentDate() {
|
||||
const today = new Date();
|
||||
const year = today.getFullYear();
|
||||
const month = String(today.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(today.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
async loadData() {
|
||||
try {
|
||||
this.state.loading = true;
|
||||
|
||||
// 先尝试从后端获取数据
|
||||
await this.loadFromBackend();
|
||||
|
||||
} catch (error) {
|
||||
console.error("从后端加载数据失败:", error);
|
||||
// 如果后端加载失败,使用演示数据
|
||||
await this.loadDemoData();
|
||||
} finally {
|
||||
this.state.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async loadFromBackend() {
|
||||
try {
|
||||
// 这里调用后端RPC接口
|
||||
const data = await this.rpc('/financial/single/get/data', {
|
||||
filters: this.state.filters
|
||||
});
|
||||
|
||||
if (data && data.headers && data.rows) {
|
||||
this.state.tableData.headers = data.headers;
|
||||
this.state.tableData.rows = data.rows;
|
||||
this.notification.add("数据加载成功", { type: "success" });
|
||||
} else {
|
||||
// 如果后端返回的数据格式不正确,使用演示数据
|
||||
throw new Error("数据格式不正确");
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("后端接口不可用,使用演示数据:", error);
|
||||
await this.loadDemoData();
|
||||
}
|
||||
}
|
||||
|
||||
async loadDemoData() {
|
||||
// 使用演示数据
|
||||
this.state.tableData.headers = this.state.demoData.headers;
|
||||
this.state.tableData.rows = this.state.demoData.rows;
|
||||
|
||||
// 填充一些示例数据
|
||||
this.fillExampleData();
|
||||
|
||||
this.notification.add("使用演示数据", { type: "info" });
|
||||
}
|
||||
|
||||
fillExampleData() {
|
||||
// 填充一些示例数据以便预览
|
||||
const rows = this.state.tableData.rows;
|
||||
|
||||
// 一、总资产
|
||||
rows[0].values = {1: "12,500.00", 2: "15,000.00", 3: "11,800.00", 4: "27.12", 5: "较去年增长", 6: "8,000.00", 7: "4,000.00", 8: "3,000.00"};
|
||||
|
||||
// 二、总负债
|
||||
rows[1].values = {1: "7,500.00", 2: "8,200.00", 3: "6,800.00", 4: "20.59", 5: "负债率控制在合理范围", 6: "4,500.00", 7: "2,500.00", 8: "1,200.00"};
|
||||
|
||||
// 其中:有息负债
|
||||
rows[2].values = {1: "3,200.00", 2: "3,500.00", 3: "2,800.00", 4: "25.00", 5: "银行贷款为主", 6: "2,000.00", 7: "1,000.00", 8: "500.00"};
|
||||
|
||||
// 利息支出
|
||||
rows[3].values = {1: "85.00", 2: "92.50", 3: "78.20", 4: "18.29", 5: "利率有所下降", 6: "50.00", 7: "30.00", 8: "12.50"};
|
||||
|
||||
// 三、净资产
|
||||
rows[4].values = {1: "5,000.00", 2: "6,800.00", 3: "5,000.00", 4: "36.00", 5: "净资产稳步增长", 6: "3,500.00", 7: "1,500.00", 8: "1,800.00"};
|
||||
|
||||
// 四、经营收入(累计当年)
|
||||
rows[5].values = {1: "8,200.00", 2: "9,500.00", 3: "7,500.00", 4: "26.67", 5: "收入稳步增长", 6: "5,200.00", 7: "2,800.00", 8: "1,500.00"};
|
||||
|
||||
// 其中:物业租赁收入
|
||||
rows[6].values = {1: "3,500.00", 2: "4,200.00", 3: "3,200.00", 4: "31.25", 5: "出租率提升", 6: "2,500.00", 7: "1,200.00", 8: "500.00"};
|
||||
|
||||
// 储备粮轮换收入
|
||||
rows[7].values = {1: "2,800.00", 2: "3,000.00", 3: "2,500.00", 4: "20.00", 5: "轮换计划完成", 6: "", 7: "", 8: "3,000.00"};
|
||||
|
||||
// 利息收入
|
||||
rows[8].values = {1: "350.00", 2: "420.00", 3: "300.00", 4: "40.00", 5: "存款利息", 6: "200.00", 7: "120.00", 8: "100.00"};
|
||||
|
||||
// 其他业务收入
|
||||
rows[9].values = {1: "1,550.00", 2: "1,880.00", 3: "1,500.00", 4: "25.33", 5: "多元化经营", 6: "500.00", 7: "1,000.00", 8: "380.00"};
|
||||
|
||||
// 五、利润总额(累计当年)
|
||||
rows[10].values = {1: "1,200.00", 2: "1,650.00", 3: "1,050.00", 4: "57.14", 5: "利润增长显著", 6: "900.00", 7: "450.00", 8: "300.00"};
|
||||
|
||||
// 六、净利润(累计当年)
|
||||
rows[11].values = {1: "850.00", 2: "1,180.00", 3: "720.00", 4: "63.89", 5: "净利润率提升", 6: "650.00", 7: "320.00", 8: "210.00"};
|
||||
|
||||
// 七、经管物业面积
|
||||
rows[12].values = {1: "120,000", 2: "150,000", 3: "115,000", 4: "30.43", 5: "平方米", 6: "80,000", 7: "50,000", 8: "20,000"};
|
||||
|
||||
}
|
||||
|
||||
// 查询按钮点击事件
|
||||
async onSearch() {
|
||||
this.state.displayInfo.reportDate = this.state.filters.date || this.getCurrentDate();
|
||||
this.state.displayInfo.companyName = this.state.filters.company || "所有公司";
|
||||
this.state.displayInfo.departmentName = this.state.filters.department || "所有部门";
|
||||
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
// 重置筛选条件
|
||||
onReset() {
|
||||
this.state.filters = {
|
||||
date: this.getCurrentDate(),
|
||||
company: "",
|
||||
department: "",
|
||||
};
|
||||
this.onSearch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据为Excel
|
||||
*/
|
||||
onExport() {
|
||||
this.notification.add("导出功能正在开发中...", { type: "info" });
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印报表
|
||||
*/
|
||||
onPrint() {
|
||||
window.print();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新数据
|
||||
*/
|
||||
async onRefresh() {
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表头颜色
|
||||
*/
|
||||
getHeaderColor(index) {
|
||||
const colors = [
|
||||
"#667eea", // 去年底 - 蓝色
|
||||
"#f6ad55", // 本年当月 - 橙色
|
||||
"#68d391", // 去年同月 - 绿色
|
||||
"#fc8181", // 同比增长 - 红色
|
||||
"#a0aec0", // 说明 - 灰色
|
||||
"#4c51bf", // 天河公司 - 深蓝
|
||||
"#38a169", // 天河物管 - 绿色
|
||||
"#d69e2e", // 天河粮储 - 金色
|
||||
];
|
||||
return colors[index % colors.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取行样式类
|
||||
*/
|
||||
getRowClass(row) {
|
||||
if (row.indent === 0) return "main-row";
|
||||
if (row.indent === 1) return "sub-row-1";
|
||||
if (row.indent === 2) return "sub-row-2";
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目名称的缩进样式
|
||||
*/
|
||||
getProjectIndentStyle(row) {
|
||||
const basePadding = 15; // 基础缩进
|
||||
const indentSize = 20; // 每级缩进大小
|
||||
return `padding-left: ${basePadding + (row.indent * indentSize)}px;`;
|
||||
}
|
||||
}
|
||||
|
||||
FinancialSinglePage.template = "statement.FinancialSingleComponent";
|
||||
FinancialSinglePage.components = {};
|
||||
|
||||
// 正确的注册方式
|
||||
registry.category("actions").add("financial_single_data_action", FinancialSinglePage);
|
||||
@@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="statement.FinancialSingleComponent" owl="1">
|
||||
<div class="financial-single-container">
|
||||
<!-- 筛选区域 -->
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm filter-card">
|
||||
<div class="card-body p-3">
|
||||
<div class="row g-2 align-items-center">
|
||||
<!-- 日期选择 -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<label for="date_filter" class="form-label">报表日期</label>
|
||||
<input
|
||||
type="date"
|
||||
class="form-control form-control-sm"
|
||||
id="date_filter"
|
||||
t-att-value="state.filters.date"
|
||||
t-on-input="(ev) => state.filters.date = ev.target.value"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 公司选择 -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<label for="company_filter" class="form-label">公司</label>
|
||||
<select
|
||||
class="form-select form-select-sm"
|
||||
id="company_filter"
|
||||
t-att-value="state.filters.company"
|
||||
t-on-change="(ev) => state.filters.company = ev.target.value"
|
||||
>
|
||||
<option value="">所有公司</option>
|
||||
<option value="company1">天河公司</option>
|
||||
<option value="company2">天河物管</option>
|
||||
<option value="company3">天河粮储</option>
|
||||
<option value="company4">其他公司</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 部门选择 -->
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<label for="department_filter" class="form-label">部门</label>
|
||||
<select
|
||||
class="form-select form-select-sm"
|
||||
id="department_filter"
|
||||
t-att-value="state.filters.department"
|
||||
t-on-change="(ev) => state.filters.department = ev.target.value"
|
||||
>
|
||||
<option value="">所有部门</option>
|
||||
<option value="dept1">财务部</option>
|
||||
<option value="dept2">市场部</option>
|
||||
<option value="dept3">销售部</option>
|
||||
<option value="dept4">行政部</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 按钮区域 -->
|
||||
<div class="col-lg-3 col-md-6 d-flex gap-2 align-items-end">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm flex-grow-1"
|
||||
t-att-disabled="state.loading"
|
||||
t-on-click="onSearch"
|
||||
>
|
||||
<t t-if="state.loading">
|
||||
<i class="fa fa-spinner fa-spin me-1"/>
|
||||
查询中...
|
||||
</t>
|
||||
<t t-else="">
|
||||
<i class="fa fa-search me-1"/>
|
||||
查询
|
||||
</t>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary btn-sm"
|
||||
t-att-disabled="state.loading"
|
||||
t-on-click="onReset"
|
||||
>
|
||||
<i class="fa fa-refresh me-1"/>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 报表区域 -->
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white p-3">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3 class="card-title mb-0">
|
||||
<i class="fa fa-bar-chart me-2"></i>
|
||||
<t t-esc="state.pageTitle"/>
|
||||
</h3>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-light btn-sm" t-on-click="onRefresh" title="刷新">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-light btn-sm" t-on-click="onExport" title="导出Excel">
|
||||
<i class="fa fa-download"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-light btn-sm" t-on-click="onPrint" title="打印">
|
||||
<i class="fa fa-print"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<!-- 动态表格 -->
|
||||
<div class="table-responsive-container">
|
||||
<table class="table table-striped table-hover table-sm financial-single-table">
|
||||
<!-- 单行表头 -->
|
||||
<thead class="table-light sticky-header">
|
||||
<tr>
|
||||
<!-- 对角线表头 -->
|
||||
<th class="sticky-column project-header diagonal-header">
|
||||
<div class="diagonal-text-container">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="diagonal-project">项目</div>
|
||||
<div class="diagonal-company">时间(公司)</div>
|
||||
</div>
|
||||
</th>
|
||||
|
||||
<!-- 动态生成单行表头 -->
|
||||
<t t-foreach="state.tableData.headers" t-as="header" t-key="header.id">
|
||||
<th
|
||||
class="single-header"
|
||||
t-att-style="'background: linear-gradient(135deg, ' + getHeaderColor(header_index) + ' 0%, ' + getHeaderColor(header_index) + 'dd 100%) !important;'"
|
||||
>
|
||||
<div class="header-content">
|
||||
<div class="header-title">
|
||||
<t t-esc="header.title"/>
|
||||
</div>
|
||||
<t t-if="header.subtitle">
|
||||
<div class="header-subtitle">
|
||||
<t t-esc="header.subtitle"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<!-- 表格体 -->
|
||||
<tbody>
|
||||
<!-- 数据行 -->
|
||||
<t t-if="state.tableData.rows.length > 0">
|
||||
<t t-foreach="state.tableData.rows" t-as="dataRow" t-key="dataRow.id">
|
||||
<tr t-att-class="getRowClass(dataRow)">
|
||||
<!-- 项目名称列 - 根据缩进级别设置样式 -->
|
||||
<td class="sticky-column project-cell">
|
||||
<div class="project-name" t-att-style="getProjectIndentStyle(dataRow)">
|
||||
<t t-esc="dataRow.name"/>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- 数据列 -->
|
||||
<t t-foreach="state.tableData.headers" t-as="header" t-key="header.id">
|
||||
<td class="text-center data-cell">
|
||||
<t t-esc="dataRow.values[header.id] || ''"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 无数据时显示空状态 -->
|
||||
<t t-if="state.tableData.rows.length === 0">
|
||||
<tr>
|
||||
<td t-att-colspan="state.tableData.headers.length + 1" class="text-center text-muted py-5">
|
||||
<div class="empty-state">
|
||||
<i class="fa fa-database fa-2x mb-3"></i>
|
||||
<p class="mb-0">暂无数据</p>
|
||||
<p class="small mt-2">请选择筛选条件后查询</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格脚注 -->
|
||||
<div class="card-footer bg-light p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<small class="text-muted">
|
||||
<i class="fa fa-info-circle me-1"></i>
|
||||
数据更新时间: <t t-esc="state.displayInfo.reportDate"/>
|
||||
<span class="mx-2">|</span>
|
||||
共 <t t-esc="state.tableData.rows.length"/> 条记录
|
||||
</small>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<small class="text-muted">
|
||||
<i class="fa fa-lightbulb-o me-1"></i>
|
||||
提示: 鼠标悬停在数据单元格上可查看详情
|
||||
<span class="mx-2">|</span>
|
||||
双击单元格可编辑
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<t t-if="state.loading">
|
||||
<div class="loading-overlay">
|
||||
<div class="spinner-container">
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
|
||||
<span class="visually-hidden">正在加载...</span>
|
||||
</div>
|
||||
<p class="mt-3 fs-5">数据加载中,请稍候...</p>
|
||||
<p class="small text-muted">正在获取最新的财务数据</p>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -5,6 +5,12 @@
|
||||
<field name="tag">financial_data_action</field>
|
||||
</record>
|
||||
|
||||
<record id="information_aggregation_action" model="ir.actions.client">
|
||||
<field name="name">信息汇总报表</field>
|
||||
<field name="tag">financial_single_data_action</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- <record id="information_aggregation_action" model="ir.actions.client">-->
|
||||
<!-- <field name="name">信息汇总报表</field>-->
|
||||
<!-- <field name="tag">information_aggregation_action</field>-->
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<tree string="财务数据表收集" editable="bottom" create="False" delete="False"
|
||||
decoration-danger="account_type == 'to'"
|
||||
decoration-success="account_type == 'ok'">
|
||||
>
|
||||
<field name="employee_id" required="1"/>
|
||||
<field name="cycle"/>
|
||||
<field name="company_id"/>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<tree string="信息汇总表" editable="bottom" create="False" delete="False"
|
||||
decoration-danger="account_type == 'to'"
|
||||
decoration-success="account_type == 'ok'">
|
||||
>
|
||||
<field name="employee_id" required="1"/>
|
||||
<field name="month"/>
|
||||
<field name="company_id"/>
|
||||
|
||||
@@ -810,7 +810,7 @@
|
||||
<menuitem id="information_summary_table_report_menu"
|
||||
name="信息汇总报表"
|
||||
parent="yuthon_account_report"
|
||||
action="yuthon_account_report.financial_sheet_collection_action"
|
||||
action="yuthon_account_report.information_aggregation_action"
|
||||
sequence="15"/>
|
||||
<menuitem id="table_setting_menu"
|
||||
name="配置"
|
||||
|
||||
Reference in New Issue
Block a user