@@ -1,3 +1,4 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
|
||||
from . import controllers
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
|
||||
'yuthon_account_report/static/src/js/collection_create_button.js',
|
||||
'yuthon_account_report/static/src/js/summary_create_button.js',
|
||||
'yuthon_account_report/static/src/xml/collection_create_button.xml',
|
||||
'yuthon_account_report/static/src/xml/summary_create_button.xml',
|
||||
|
||||
'yuthon_account_report/static/src/css/*.css',
|
||||
'yuthon_account_report/static/src/js/*.js',
|
||||
'yuthon_account_report/static/src/xml/*.xml'
|
||||
|
||||
@@ -1,153 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.exceptions import ValidationError
|
||||
import datetime
|
||||
# from odoo import http
|
||||
# from odoo.http import request
|
||||
# from odoo.exceptions import ValidationError
|
||||
# import datetime
|
||||
|
||||
|
||||
class Statement(http.Controller):
|
||||
|
||||
@http.route('/get/account/title', auth='user', type='json', methods=['POST'])
|
||||
def getAccountTitle(self, **kw):
|
||||
data = kw.get('data', '')
|
||||
companyGroups = [
|
||||
{
|
||||
'id': 1,
|
||||
'groupName': "天河投资",
|
||||
'items': [
|
||||
{'id': 101, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 102, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 103, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 104, 'name': "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'groupName': "天投城建",
|
||||
'items': [
|
||||
{'id': 201, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 202, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'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': []
|
||||
}
|
||||
|
||||
# class Statement(http.Controller):
|
||||
|
||||
# @http.route('/statement/statement/objects', auth='public')
|
||||
# def list(self, **kw):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime
|
||||
import datetime
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
@@ -90,5 +90,85 @@ class FinancialSheetLine(models.Model):
|
||||
same_last_year = fields.Integer(string='上年同期数')
|
||||
remake = fields.Text(string='说明')
|
||||
|
||||
def compute_total(self, date, company=None, employee=None):
|
||||
company = company or []
|
||||
if company == 0:
|
||||
company = []
|
||||
employee = employee or []
|
||||
if employee == 0:
|
||||
employee = []
|
||||
|
||||
# 构建查询条件
|
||||
domain = [('create_date', '<=', date)]
|
||||
if company:
|
||||
domain.append(('sheet_id.company_id', 'in', company))
|
||||
if employee:
|
||||
domain.append(('employee_ids', 'in', employee))
|
||||
|
||||
# 执行查询
|
||||
cons = self.search(domain)
|
||||
sum_total = {}
|
||||
date_obj = datetime.datetime.strptime(date, "%Y-%m-%d").date()
|
||||
# 获取目标年月
|
||||
target_year = date_obj.year or None
|
||||
target_month = date_obj.month or None
|
||||
|
||||
for con in cons:
|
||||
# 只处理同年同月的数据
|
||||
if target_year and target_month:
|
||||
if con.create_date.year != target_year or con.create_date.month != target_month:
|
||||
continue
|
||||
|
||||
collection_id = con.collection_id
|
||||
company_id = con.sheet_id.company_id
|
||||
|
||||
# 确保财务项字典存在
|
||||
collection_dict = sum_total.setdefault(collection_id, {})
|
||||
|
||||
# 定义新key的基础部分
|
||||
base_key = str(company_id)
|
||||
|
||||
# 定义各个新key
|
||||
key_101 = f"{base_key}101" # 本期数
|
||||
key_102 = f"{base_key}102" # 上年同期数
|
||||
key_103 = f"{base_key}103" # 同比增长率
|
||||
key_104 = f"{base_key}104" # 备注
|
||||
|
||||
# 初始化各个key的值(如果不存在)
|
||||
if key_101 not in collection_dict:
|
||||
collection_dict[key_101] = 0 # 本期数
|
||||
if key_102 not in collection_dict:
|
||||
collection_dict[key_102] = 0 # 上年同期数
|
||||
if key_104 not in collection_dict:
|
||||
collection_dict[key_104] = [] # 备注列表
|
||||
# key_103不初始化,将在计算后设置
|
||||
|
||||
# 累加数据
|
||||
collection_dict[key_101] += con.this_issue_number
|
||||
collection_dict[key_102] += con.same_last_year
|
||||
if con.remake:
|
||||
collection_dict[key_104].append(con.remake)
|
||||
|
||||
# 计算同比增长率(仅当上年同期数大于0时)
|
||||
if collection_dict[key_102] > 0:
|
||||
growth_rate = round(collection_dict[key_101] / collection_dict[key_102] * 100, 2)
|
||||
collection_dict[key_103] = growth_rate
|
||||
else:
|
||||
# 如果上年同期数为0或负数,增长率为None
|
||||
collection_dict[key_103] = None
|
||||
|
||||
# 将备注列表转换为字符串
|
||||
for collection_dict in sum_total.values():
|
||||
keys_to_remove = []
|
||||
for key, value in collection_dict.items():
|
||||
if key.endswith("104") and isinstance(value, list):
|
||||
# 去重并拼接备注
|
||||
unique_remarks = []
|
||||
for remark in value:
|
||||
if remark and remark not in unique_remarks:
|
||||
unique_remarks.append(remark)
|
||||
collection_dict[key] = '/'.join(unique_remarks) if unique_remarks else ''
|
||||
|
||||
return sum_total
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from datetime import datetime
|
||||
from odoo import models, fields, api
|
||||
import datetime
|
||||
|
||||
|
||||
class InformationSummaryTable(models.Model):
|
||||
@@ -13,6 +14,7 @@ class InformationSummaryTable(models.Model):
|
||||
account_type = fields.Selection([('to', '待确认', ), ('ok', '已确认')], string='状态', default='to')
|
||||
summary_line = fields.One2many('information.summary.line', 'summary_id', string='汇总表')
|
||||
month = fields.Selection(selection=[(str(i), str(i)) for i in range(1, 13)], string='月份')
|
||||
year = fields.Integer('年')
|
||||
create_date = fields.Datetime(string='创建日期', default=fields.Datetime.now)
|
||||
|
||||
def open_record(self):
|
||||
@@ -67,6 +69,65 @@ class InformationSummaryTable(models.Model):
|
||||
'remake': ''
|
||||
})
|
||||
|
||||
def compute_total(self, date, company=None):
|
||||
company = company or []
|
||||
if company == 0:
|
||||
company = []
|
||||
# 转变为日期格式方便取月份
|
||||
date_obj = datetime.datetime.strptime(date, "%Y-%m-%d").date()
|
||||
year = date_obj.year
|
||||
month = date_obj.month
|
||||
domain = [('month', '=', month), ('year', '=', year)]
|
||||
if len(company) > 0:
|
||||
domain.append(('company_id', 'in', company))
|
||||
cons = self.search(domain)
|
||||
one = {}
|
||||
# 各项本期数B 说明 公司当期数
|
||||
for con in cons:
|
||||
for re in con.summary_line:
|
||||
if re.table_id not in one.keys():
|
||||
one[re.table_id] = {'B': re.this_year or 0, 'E': re.remake or ""}
|
||||
one[re.table_id][con.company_id.id] = re.this_year
|
||||
else:
|
||||
one[re.table_id]['B'] += re.this_year
|
||||
one[re.table_id]['E'] += re.this_year
|
||||
# 去年年底A
|
||||
last_domain = [('month', '=', 12), ('year', '=', year-1)]
|
||||
if len(company) > 0:
|
||||
last_domain.append(('company_id', 'in', company))
|
||||
last_cons = self.search(last_domain)
|
||||
for last_con in last_cons:
|
||||
for last_re in last_con.summary_line:
|
||||
if last_re.table_id not in one.keys():
|
||||
one[last_re.table_id] = {"A": last_re.this_year or 0}
|
||||
else:
|
||||
if 'A' not in one[last_re.table_id].keys():
|
||||
one[last_re.table_id]["A"] = last_re.this_year or 0
|
||||
else:
|
||||
one[last_re.table_id]["A"] += last_re.this_year
|
||||
# 去年同期C
|
||||
lat_domain = [('month', '=', month), ('year', '=', year-1)]
|
||||
if len(company) > 0:
|
||||
lat_domain.append(('company_id', 'in', company))
|
||||
lat_cons = self.search(lat_domain)
|
||||
for lat_con in lat_cons:
|
||||
for lat_re in lat_con.summary_line:
|
||||
if lat_re.table_id not in one.keys():
|
||||
one[lat_re.table_id] = {"C": lat_re.this_year or 0}
|
||||
else:
|
||||
if 'C' not in one[lat_re.table_id].keys():
|
||||
one[lat_re.table_id]["C"] = lat_re.this_year or 0
|
||||
else:
|
||||
one[lat_re.table_id]["C"] += lat_re.this_year
|
||||
|
||||
# 同比增长D
|
||||
for key, val in one.items():
|
||||
if val['C'] > 0:
|
||||
val['D'] = round((val['B'] - val['C']) / val['C'] * 100, 2)
|
||||
else:
|
||||
val['D'] = 0
|
||||
return one
|
||||
|
||||
|
||||
class InformationSummaryLine(models.Model):
|
||||
_name = 'information.summary.line'
|
||||
@@ -76,3 +137,4 @@ class InformationSummaryLine(models.Model):
|
||||
table_id = fields.Many2one('summary.table.setting', string='项目名称')
|
||||
this_year = fields.Float(string='本年底')
|
||||
remake = fields.Text(string='说明')
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: white !important;
|
||||
color: black !important;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ class FinancialPage extends Component {
|
||||
employeeName: "所有员工"
|
||||
},
|
||||
pageTitle: "各公司主要财务数据",
|
||||
setting: {type: 'default'},
|
||||
setting: {
|
||||
type: 'default',
|
||||
},
|
||||
loading: false,
|
||||
demo: {
|
||||
companyGroups: [
|
||||
@@ -43,10 +45,10 @@ class FinancialPage extends Component {
|
||||
'id': 1,
|
||||
'groupName': "天河投资",
|
||||
'items': [
|
||||
{'id': 101, 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': 102, 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': 103, 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': 104, 'name': "说明"}
|
||||
{'id': '101', 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': '102', 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': '103', 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': '104', 'name': "说明"}
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -55,56 +57,139 @@ class FinancialPage extends Component {
|
||||
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"
|
||||
'101': "10000.00",
|
||||
'102': "2000.00",
|
||||
'103': "1500.00",
|
||||
'104': "说明1",
|
||||
}
|
||||
},
|
||||
{
|
||||
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"
|
||||
'101': "5000.00",
|
||||
'102': "1200.00",
|
||||
'103': "800.00",
|
||||
'104': "说明3",
|
||||
}
|
||||
},
|
||||
{
|
||||
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"
|
||||
'101': "3000.00",
|
||||
'102': "800.00",
|
||||
'103': "500.00",
|
||||
'104': "说明5",
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
companys : [
|
||||
{id:0, name:'所有公司'}
|
||||
],
|
||||
staffs : [
|
||||
{id:0, name:'所有员工'}
|
||||
],
|
||||
items : [
|
||||
{'id': '101', 'name': "本期数", 'fieldType': "万元"},
|
||||
{'id': '102', 'name': "上年同期", 'fieldType': "万元"},
|
||||
{'id': '103', 'name': "增幅", 'fieldType': "%"},
|
||||
{'id': '104', 'name': "说明"}
|
||||
],
|
||||
fixedGroups : [
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{id: 'A101', name: "本期数", fieldType: "万元"},
|
||||
{id: 'A102', name: "上年同期", fieldType: "万元"},
|
||||
{id: 'A103', name: "增幅", fieldType: "%"},
|
||||
{id: 'A104', name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{id: 'B101', name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 'B102', name: "完成率", fieldType: "%"},
|
||||
{id: 'B103', name: "集团目标", fieldType: "%"},
|
||||
{id: 'B104', name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
],
|
||||
companyGroups: []
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
});
|
||||
|
||||
onWillStart(async () => {
|
||||
const companys = await this.orm.searchRead(
|
||||
'res.company',
|
||||
[],
|
||||
['id', 'name']
|
||||
);
|
||||
this.gethearder(companys)
|
||||
await this.getstaffs()
|
||||
await this.loadInitialData();
|
||||
});
|
||||
}
|
||||
|
||||
async getstaffs(){
|
||||
const staffs = await this.orm.searchRead(
|
||||
'financial.sheet.collection',
|
||||
[],
|
||||
['id', 'employee_id']
|
||||
);
|
||||
staffs.forEach(re=>{
|
||||
if(re.employee_id){
|
||||
this.state.staffs.push({
|
||||
id: re.employee_id[0],
|
||||
name: re.employee_id[1]
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
gethearder(companys) {
|
||||
if(this.state.filters.company != '所有公司' && this.state.filters.company){
|
||||
this.state.companyGroups = []
|
||||
}
|
||||
this.state.companys = [{id:0, name:'所有公司'}]
|
||||
companys.forEach(re => {
|
||||
// 创建新的 items 数组,避免修改原始数据
|
||||
const coms = this.state.items.map(item => ({
|
||||
...item,
|
||||
id: `${re.id}${item.id}` // 创建新的 ID
|
||||
}));
|
||||
if(this.state.filters.company != '所有公司' && this.state.filters.company){
|
||||
if(re.id === this.state.filters.company * 1){
|
||||
this.state.pageTitle = re.name + '主要财务数据'
|
||||
this.state.companyGroups.push({
|
||||
id: re.id,
|
||||
groupName: re.name,
|
||||
items: coms
|
||||
});
|
||||
}
|
||||
}else{
|
||||
this.state.pageTitle = '各公司主要财务数据'
|
||||
this.state.companyGroups.push({
|
||||
id: re.id,
|
||||
groupName: re.name,
|
||||
items: coms
|
||||
});
|
||||
}
|
||||
this.state.companys.push({
|
||||
id: re.id,
|
||||
name: re.name
|
||||
});
|
||||
});
|
||||
this.state.tableData.displayHeaders = [...this.state.companyGroups, ...this.state.fixedGroups];
|
||||
}
|
||||
|
||||
getCurrentDate() {
|
||||
const today = new Date();
|
||||
const year = today.getFullYear();
|
||||
@@ -114,76 +199,22 @@ class FinancialPage extends Component {
|
||||
}
|
||||
|
||||
async loadInitialData() {
|
||||
try {
|
||||
const settings = await this.orm.searchRead(
|
||||
const settings = await this.orm.searchRead(
|
||||
'sheet.collection.setting',
|
||||
[],
|
||||
['id', 'name', 'type'],
|
||||
{limit: 1}
|
||||
['id', 'name'],
|
||||
{order: 'sequence'}
|
||||
);
|
||||
|
||||
if (settings.length > 0) {
|
||||
this.state.setting = settings[0];
|
||||
this.state.pageTitle = settings[0].name;
|
||||
await this.loadTableData(settings[0].id);
|
||||
} else {
|
||||
await this.loadDefaultData();
|
||||
}
|
||||
} catch (error) {
|
||||
if (settings.length > 0) {
|
||||
await this.loadTableData(settings);
|
||||
} else {
|
||||
await this.loadDefaultData();
|
||||
}
|
||||
}
|
||||
|
||||
async loadDefaultData() {
|
||||
this.state.pageTitle = "各公司主要财务数据";
|
||||
this.state.setting = {type: 'default'};
|
||||
|
||||
try {
|
||||
// 通过RPC调用后端接口
|
||||
const companyGroups = await this.rpc('/get/account/title');
|
||||
|
||||
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: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 合并分组,确保固定分组在最后
|
||||
this.state.tableData.displayHeaders = [...companyGroups, ...fixedGroups];
|
||||
|
||||
// 计算并添加合计数据
|
||||
const rowsWithTotals = this.calculateTotals(rawRows, companyGroups);
|
||||
this.state.tableData.rows = rowsWithTotals;
|
||||
} else {
|
||||
// 如果后端没有返回数据,使用demo数据
|
||||
this.useDemoData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载数据失败:", error);
|
||||
// 如果RPC调用失败,使用demo数据
|
||||
this.useDemoData();
|
||||
}
|
||||
// 如果后端没有返回数据,使用demo数据
|
||||
await this.useDemoData();
|
||||
}
|
||||
|
||||
// 添加一个使用demo数据的辅助方法
|
||||
@@ -196,20 +227,20 @@ class FinancialPage extends Component {
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{id: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
{id: 'A101', name: "本期数", fieldType: "万元"},
|
||||
{id: 'A102', name: "上年同期", fieldType: "万元"},
|
||||
{id: 'A103', name: "增幅", fieldType: "%"},
|
||||
{id: 'A104', name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
{id: 'B101', name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 'B102', name: "完成率", fieldType: "%"},
|
||||
{id: 'B103', name: "集团目标", fieldType: "%"},
|
||||
{id: 'B104', name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -230,357 +261,160 @@ class FinancialPage extends Component {
|
||||
*/
|
||||
calculateTotals(rows, companyGroups) {
|
||||
return rows.map(row => {
|
||||
// 确保 row.values 存在
|
||||
const rowValues = row.values || {};
|
||||
const newRow = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
values: {...row.values}
|
||||
values: { ...rowValues } // 浅拷贝原始值
|
||||
};
|
||||
|
||||
// 提取每个公司的本期数ID
|
||||
// 计算固定分组的值
|
||||
const currentPeriodIds = [];
|
||||
companyGroups.forEach(group => {
|
||||
const currentPeriodItem = group.items.find(item => item.name === "本期数");
|
||||
if (currentPeriodItem) {
|
||||
currentPeriodIds.push(currentPeriodItem.id);
|
||||
}
|
||||
});
|
||||
|
||||
// 提取每个公司的上年同期ID
|
||||
const lastYearIds = [];
|
||||
|
||||
companyGroups.forEach(group => {
|
||||
const lastYearItem = group.items.find(item => item.name === "上年同期");
|
||||
if (lastYearItem) {
|
||||
lastYearIds.push(lastYearItem.id);
|
||||
}
|
||||
// 查找每个公司的本期数和上年同期数字段
|
||||
group.items.forEach(item => {
|
||||
if (item.id.endsWith('101')) {
|
||||
currentPeriodIds.push(item.id);
|
||||
} else if (item.id.endsWith('102')) {
|
||||
lastYearIds.push(item.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 计算本期数合计
|
||||
// 计算合计
|
||||
let totalCurrentPeriod = 0;
|
||||
let totalLastYear = 0;
|
||||
|
||||
currentPeriodIds.forEach(id => {
|
||||
const value = parseFloat(newRow.values[id]) || 0;
|
||||
totalCurrentPeriod += value;
|
||||
});
|
||||
|
||||
// 计算上年同期合计
|
||||
let totalLastYear = 0;
|
||||
lastYearIds.forEach(id => {
|
||||
const value = parseFloat(newRow.values[id]) || 0;
|
||||
totalLastYear += value;
|
||||
});
|
||||
|
||||
// 添加合计数据
|
||||
newRow.values[1001] = totalCurrentPeriod.toFixed(2); // 合计本期数
|
||||
newRow.values[1002] = totalLastYear.toFixed(2); // 合计上年同期
|
||||
// 设置合计值
|
||||
// 使用固定分组的字段 ID
|
||||
newRow.values['A101'] = totalCurrentPeriod.toFixed(2);
|
||||
newRow.values['A102'] = totalLastYear.toFixed(2);
|
||||
|
||||
// 计算增幅(本期数合计/上年同期合计 - 1)
|
||||
// 计算增幅
|
||||
let increaseRate = "0.00";
|
||||
if (totalLastYear !== 0) {
|
||||
increaseRate = ((totalCurrentPeriod - totalLastYear) / totalLastYear * 100).toFixed(2);
|
||||
}
|
||||
newRow.values[10003] = increaseRate;
|
||||
newRow.values[10004] = "合计说明"; // 合计说明
|
||||
newRow.values['A103'] = increaseRate;
|
||||
newRow.values['A104'] = rowValues['A104'] || "合计说明";
|
||||
|
||||
// 预算相关数据可以留空或设置默认值
|
||||
newRow.values[20001] = ""; // 预测财局下达目标
|
||||
newRow.values[20002] = ""; // 完成率
|
||||
newRow.values[20003] = ""; // 集团目标
|
||||
newRow.values[20004] = ""; // 完成率
|
||||
// 设置预算相关字段
|
||||
newRow.values['B101'] = rowValues['B101'] || "";
|
||||
newRow.values['B102'] = rowValues['B102'] || "";
|
||||
newRow.values['B103'] = rowValues['B103'] || "";
|
||||
newRow.values['B104'] = rowValues['B104'] || "";
|
||||
|
||||
return newRow;
|
||||
});
|
||||
}
|
||||
|
||||
async loadTableData(settingId) {
|
||||
async loadTableData(settings) {
|
||||
try {
|
||||
this.state.loading = true;
|
||||
|
||||
const headers = await this.orm.searchRead(
|
||||
'sheet.collection.setting.header',
|
||||
[['setting_id', '=', settingId]],
|
||||
['id', 'sequence', 'group_name', 'vertical_header_name'],
|
||||
{order: 'sequence'}
|
||||
// 获取数据
|
||||
const processedSettings = await this.consolidatedstatements(settings);
|
||||
|
||||
// 计算并添加合计数据
|
||||
const rowsWithTotals = this.calculateTotals(
|
||||
processedSettings,
|
||||
this.state.companyGroups
|
||||
);
|
||||
|
||||
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'}
|
||||
);
|
||||
|
||||
const dataRows = await this.orm.searchRead(
|
||||
'sheet.collection.setting.data',
|
||||
[['setting_id', '=', settingId]],
|
||||
['id', 'sequence', 'name'],
|
||||
{order: 'sequence'}
|
||||
);
|
||||
|
||||
const dataValues = await this.orm.searchRead(
|
||||
'sheet.collection.setting.data.value',
|
||||
[['data_id.setting_id', '=', settingId]],
|
||||
['id', 'data_id', 'header_item_id', 'value']
|
||||
);
|
||||
|
||||
// 处理数据并确保合计和预算在最后
|
||||
await this.processAndCalculateData(headers, headerItems, dataRows, dataValues);
|
||||
|
||||
this.state.tableData.rows = rowsWithTotals;
|
||||
} catch (error) {
|
||||
await this.loadDefaultData();
|
||||
console.error('Error loading table data:', error);
|
||||
// 出错时使用 demo 数据
|
||||
await this.useDemoData();
|
||||
} finally {
|
||||
this.state.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据并计算合计
|
||||
*/
|
||||
async processAndCalculateData(headers, headerItems, dataRows, dataValues) {
|
||||
const settingType = this.state.setting.type || 'default';
|
||||
|
||||
if (settingType === 'default') {
|
||||
// 分离公司分组和固定分组
|
||||
const companyHeaders = headers.filter(header =>
|
||||
header.group_name !== "合计" && header.group_name !== "本年度预算"
|
||||
async consolidatedstatements(settings) {
|
||||
try {
|
||||
let soup = {date: this.state.filters.date}
|
||||
if(this.state.filters.company != '所有公司' && this.state.filters.company) {
|
||||
soup['company'] = [this.state.displayInfo.companyId * 1]
|
||||
}
|
||||
if(this.state.filters.employee != '所有员工' && this.state.filters.employee){
|
||||
soup['employee'] = [this.state.displayInfo.employee * 1]
|
||||
}
|
||||
const result = await this.orm.call(
|
||||
'financial.sheet.line',
|
||||
'compute_total',
|
||||
[[]],
|
||||
{ date: this.state.filters.date }
|
||||
);
|
||||
// result 是一个对象,不是数组
|
||||
if (result && Object.keys(result).length > 0) {
|
||||
// 确保每个设置项都有 values 对象
|
||||
|
||||
const totalHeader = headers.find(header => header.group_name === "合计");
|
||||
const budgetHeader = headers.find(header => header.group_name === "本年度预算");
|
||||
|
||||
// 处理公司分组
|
||||
const companyGroups = [];
|
||||
companyHeaders.forEach(header => {
|
||||
const items = headerItems.filter(item => item.header_id[0] === header.id);
|
||||
if (items.length > 0) {
|
||||
companyGroups.push({
|
||||
id: header.id,
|
||||
groupName: header.group_name,
|
||||
items: items.map(item => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
fieldType: item.field_type
|
||||
}))
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 处理固定分组
|
||||
const fixedGroups = [];
|
||||
|
||||
// 处理合计分组
|
||||
if (totalHeader) {
|
||||
const totalItems = headerItems.filter(item => item.header_id[0] === totalHeader.id);
|
||||
if (totalItems.length > 0) {
|
||||
fixedGroups.push({
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: totalHeader.group_name,
|
||||
items: totalItems.map(item => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
fieldType: item.field_type
|
||||
}))
|
||||
});
|
||||
}
|
||||
return settings.map(res => {
|
||||
return {
|
||||
...res,
|
||||
values: result[res.id] || {} // 如果 result 中没有对应 ID,返回空对象
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// 处理预算分组
|
||||
if (budgetHeader) {
|
||||
const budgetItems = headerItems.filter(item => item.header_id[0] === budgetHeader.id);
|
||||
if (budgetItems.length > 0) {
|
||||
fixedGroups.push({
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: budgetHeader.group_name,
|
||||
items: budgetItems.map(item => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
fieldType: item.field_type
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有固定分组,添加默认的
|
||||
if (fixedGroups.length === 0) {
|
||||
fixedGroups.push(...[
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.TOTAL,
|
||||
groupName: "合计",
|
||||
items: [
|
||||
{id: 10001, name: "本期数", fieldType: "万元"},
|
||||
{id: 10002, name: "上年同期", fieldType: "万元"},
|
||||
{id: 10003, name: "增幅", fieldType: "%"},
|
||||
{id: 10004, name: "说明"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: this.FIXED_GROUP_IDS.BUDGET,
|
||||
groupName: "本年度预算",
|
||||
items: [
|
||||
{id: 20001, name: "预测财局下达目标", fieldType: "万元"},
|
||||
{id: 20002, name: "完成率", fieldType: "%"},
|
||||
{id: 20003, name: "集团目标", fieldType: "%"},
|
||||
{id: 20004, name: "完成率", fieldType: "%"}
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
// 合并分组,确保固定分组在最后
|
||||
this.state.tableData.displayHeaders = [...companyGroups, ...fixedGroups];
|
||||
|
||||
// 处理行数据并计算合计
|
||||
this.processRowsWithTotals(dataRows, dataValues, companyGroups, fixedGroups);
|
||||
|
||||
} else {
|
||||
// 其他类型的处理逻辑
|
||||
this.processHeadersForOtherTypes(headers, headerItems);
|
||||
this.processRows(dataRows, dataValues, headerItems);
|
||||
}
|
||||
|
||||
this.state.tableData.headers = headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理行数据并计算合计
|
||||
*/
|
||||
processRowsWithTotals(dataRows, dataValues, companyGroups, fixedGroups) {
|
||||
const rows = [];
|
||||
|
||||
// 首先获取原始数据
|
||||
dataRows.forEach(dataRow => {
|
||||
const rowData = {
|
||||
id: dataRow.id,
|
||||
name: dataRow.name,
|
||||
// 如果没有数据,返回带有空 values 的设置项
|
||||
return settings.map(res => ({
|
||||
...res,
|
||||
values: {}
|
||||
};
|
||||
|
||||
const rowValues = dataValues.filter(v => v.data_id[0] === dataRow.id);
|
||||
|
||||
// 收集所有公司的数据
|
||||
companyGroups.forEach(group => {
|
||||
group.items.forEach(item => {
|
||||
const valueRecord = rowValues.find(v => v.header_item_id[0] === item.id);
|
||||
rowData.values[item.id] = valueRecord ? valueRecord.value : '0.00';
|
||||
});
|
||||
});
|
||||
|
||||
// 收集固定分组的数据(如果后端提供了)
|
||||
const totalGroup = fixedGroups.find(g => g.groupName === "合计");
|
||||
const budgetGroup = fixedGroups.find(g => g.groupName === "本年度预算");
|
||||
|
||||
if (totalGroup) {
|
||||
totalGroup.items.forEach(item => {
|
||||
const valueRecord = rowValues.find(v => v.header_item_id[0] === item.id);
|
||||
if (valueRecord) {
|
||||
rowData.values[item.id] = valueRecord.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (budgetGroup) {
|
||||
budgetGroup.items.forEach(item => {
|
||||
const valueRecord = rowValues.find(v => v.header_item_id[0] === item.id);
|
||||
if (valueRecord) {
|
||||
rowData.values[item.id] = valueRecord.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
rows.push(rowData);
|
||||
});
|
||||
|
||||
// 计算合计并添加到行数据
|
||||
const rowsWithTotals = this.calculateTotals(rows, companyGroups);
|
||||
this.state.tableData.rows = rowsWithTotals;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理其他类型的表头
|
||||
*/
|
||||
processHeadersForOtherTypes(headers, headerItems) {
|
||||
const settingType = this.state.setting.type || 'default';
|
||||
|
||||
if (settingType === 'horizontal') {
|
||||
// 横向表头:所有项平铺
|
||||
const flatHeaders = [];
|
||||
|
||||
headers.forEach(header => {
|
||||
const items = headerItems.filter(item => item.header_id[0] === header.id);
|
||||
items.forEach(item => {
|
||||
flatHeaders.push({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
fieldType: item.field_type,
|
||||
groupName: header.group_name
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.state.tableData.displayHeaders = flatHeaders;
|
||||
|
||||
} else if (settingType === 'vertical') {
|
||||
// 竖向表头:表头在左侧
|
||||
const verticalHeaders = [];
|
||||
|
||||
headers.forEach(header => {
|
||||
verticalHeaders.push({
|
||||
id: header.id,
|
||||
name: header.vertical_header_name || header.group_name,
|
||||
type: 'vertical'
|
||||
});
|
||||
});
|
||||
|
||||
this.state.tableData.displayHeaders = verticalHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理行数据(用于非默认类型)
|
||||
*/
|
||||
processRows(dataRows, dataValues, headerItems) {
|
||||
const rows = [];
|
||||
|
||||
dataRows.forEach(dataRow => {
|
||||
const rowData = {
|
||||
id: dataRow.id,
|
||||
name: dataRow.name,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error in consolidatedstatements:', error);
|
||||
// 出错时返回带有空 values 的设置项
|
||||
return settings.map(res => ({
|
||||
...res,
|
||||
values: {}
|
||||
};
|
||||
|
||||
// 收集该行的所有数据值
|
||||
const rowValues = dataValues.filter(v => v.data_id[0] === dataRow.id);
|
||||
|
||||
headerItems.forEach(item => {
|
||||
const valueRecord = rowValues.find(v => v.header_item_id[0] === item.id);
|
||||
rowData.values[item.id] = valueRecord ? valueRecord.value : '0.00';
|
||||
});
|
||||
|
||||
rows.push(rowData);
|
||||
});
|
||||
|
||||
this.state.tableData.rows = rows;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// 查询按钮点击事件
|
||||
async onSearch() {
|
||||
|
||||
// 更新显示信息
|
||||
this.state.displayInfo.reportDate = this.state.filters.date || this.getCurrentDate();
|
||||
this.state.displayInfo.companyName = this.state.filters.company || "所有公司";
|
||||
this.state.displayInfo.employeeName = this.state.filters.employee || "所有员工";
|
||||
|
||||
this.state.displayInfo.companyId = this.state.filters.company || "所有公司";
|
||||
this.state.displayInfo.employeeId = this.state.filters.employee || "所有员工";
|
||||
// 如果有筛选条件,可以重新加载数据
|
||||
if (this.state.filters.company || this.state.filters.employee) {
|
||||
await this.loadTableData(this.state.setting.id);
|
||||
if (this.state.filters.company != '所有公司' && this.state.filters.company) {
|
||||
const companys = await this.orm.searchRead(
|
||||
'res.company',
|
||||
[],
|
||||
['id', 'name']
|
||||
);
|
||||
await this.gethearder(companys)
|
||||
await this.loadInitialData();
|
||||
}else if(this.state.filters.employee != '所有员工' && this.state.filters.employee){
|
||||
await this.loadInitialData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 重置筛选条件
|
||||
onReset() {
|
||||
this.state.filters = {
|
||||
date: this.getCurrentDate(),
|
||||
company: "",
|
||||
employee: "",
|
||||
company: 0,
|
||||
employee: 0,
|
||||
};
|
||||
this.onSearch();
|
||||
}
|
||||
|
||||
@@ -22,9 +22,16 @@ export class FinancialSinglePage extends Component {
|
||||
department: "",
|
||||
},
|
||||
tableData: {
|
||||
headers: [],
|
||||
headers: [{id: 'A', title: "去年底", subtitle: ""},
|
||||
{id: 'B', title: "本年当月", subtitle: ""},
|
||||
{id: 'C', title: "去年同月", subtitle: ""},
|
||||
{id: 'D', title: "同比增长", subtitle: "%"},
|
||||
{id: 'E', title: "说明", subtitle: ""}],
|
||||
rows: [],
|
||||
},
|
||||
companys : [
|
||||
{id:0, name:'所有公司'}
|
||||
],
|
||||
displayInfo: {
|
||||
reportDate: this.getCurrentDate(),
|
||||
companyName: "所有公司",
|
||||
@@ -35,11 +42,11 @@ export class FinancialSinglePage extends Component {
|
||||
// 演示数据
|
||||
demoData: {
|
||||
headers: [
|
||||
{id: 1, title: "去年底", subtitle: ""},
|
||||
{id: 2, title: "本年当月", subtitle: ""},
|
||||
{id: 3, title: "去年同月", subtitle: ""},
|
||||
{id: 4, title: "同比增长", subtitle: "%"},
|
||||
{id: 5, title: "说明", subtitle: ""},
|
||||
{id: 'A', title: "去年底", subtitle: ""},
|
||||
{id: 'B', title: "本年当月", subtitle: ""},
|
||||
{id: 'C', title: "去年同月", subtitle: ""},
|
||||
{id: 'D', title: "同比增长", subtitle: "%"},
|
||||
{id: 'E', title: "说明", subtitle: ""},
|
||||
{id: 6, title: "天河公司", subtitle: ""},
|
||||
{id: 7, title: "天河物管", subtitle: ""},
|
||||
{id: 8, title: "天河粮储", subtitle: ""},
|
||||
@@ -48,73 +55,73 @@ export class FinancialSinglePage extends Component {
|
||||
{
|
||||
id: 1,
|
||||
name: '一、总资产',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '二、总负债',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '其中:有息负债',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '利息支出',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '三、净资产',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '四、经营收入(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '其中:物业租赁收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 1
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '储备粮轮换收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '利息收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '其他业务收入',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 2
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '五、利润总额(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: '六、净利润(累计当年)',
|
||||
values: {1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "", 8: ""},
|
||||
values: {A: "", B: "", C: "", D: "", E: "", 6: "", 7: "", 8: ""},
|
||||
indent: 0
|
||||
}
|
||||
]
|
||||
@@ -125,6 +132,7 @@ export class FinancialSinglePage extends Component {
|
||||
this.tableRef = useRef("table");
|
||||
|
||||
onWillStart(async () => {
|
||||
await this.getcompany()
|
||||
await this.loadData();
|
||||
});
|
||||
|
||||
@@ -140,13 +148,98 @@ export class FinancialSinglePage extends Component {
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
async getcompany(){
|
||||
const companys = await this.orm.searchRead(
|
||||
'res.company',
|
||||
[],
|
||||
['id', 'name']
|
||||
);
|
||||
this.state.companys = [{id:0, name:'所有公司'}]
|
||||
await companys.forEach(res=>{
|
||||
this.state.companys.push({
|
||||
id: res.id,
|
||||
name: res.name
|
||||
})
|
||||
})
|
||||
this.state.tableData.headers = [
|
||||
{id: 'A', title: "去年底", subtitle: ""},
|
||||
{id: 'B', title: "本年当月", subtitle: ""},
|
||||
{id: 'C', title: "去年同月", subtitle: ""},
|
||||
{id: 'D', title: "同比增长", subtitle: "%"},
|
||||
{id: 'E', title: "说明", subtitle: ""}]
|
||||
if(this.state.filters.company){
|
||||
await companys.forEach(res=>{
|
||||
if(this.state.filters.company == res.id){
|
||||
this.state.tableData.headers.push({
|
||||
id: res.id,
|
||||
title: res.name,
|
||||
subtitle: ""
|
||||
})
|
||||
}
|
||||
})
|
||||
}else{
|
||||
await companys.forEach(res=>{
|
||||
this.state.tableData.headers.push({
|
||||
id: res.id,
|
||||
title: res.name,
|
||||
subtitle: ""
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async getsetting() {
|
||||
const setting = await this.orm.searchRead(
|
||||
'summary.table.setting',
|
||||
[],
|
||||
['sequence', 'name'],
|
||||
{ order: 'sequence' }
|
||||
);
|
||||
|
||||
if (!setting?.length) return [];
|
||||
|
||||
return setting.map(res => {
|
||||
const name = res.name || '';
|
||||
const hasColon = name.includes(':') || name.includes(':');
|
||||
const hasPause = name.includes('、');
|
||||
|
||||
return {
|
||||
id: res.sequence,
|
||||
name: name,
|
||||
indent: hasColon ? 1 : hasPause ? 0 : 2
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async loadData() {
|
||||
try {
|
||||
this.state.loading = true;
|
||||
|
||||
// 先尝试从后端获取数据
|
||||
await this.loadFromBackend();
|
||||
const setting = await this.getsetting()
|
||||
const result = await this.orm.call(
|
||||
'information.summary.table',
|
||||
'compute_total',
|
||||
[[]],
|
||||
{ date: this.state.filters.date }
|
||||
);
|
||||
if(result && result.length > 0){
|
||||
await setting.forEach(res=>{
|
||||
res['values'] = result[res.id]
|
||||
})
|
||||
}else{
|
||||
let val = {"A": 100, "B": 200, "C": 100, "D": 100, "E": '说明'}
|
||||
let tar = this.state.tableData.headers.slice(5);
|
||||
console.log('tar', tar)
|
||||
let long = this.state.tableData.headers.length - 5
|
||||
for(let i=0;i<long;i++){
|
||||
val[tar[i].id] = 100
|
||||
}
|
||||
await setting.forEach(res=>{
|
||||
res['values'] = val
|
||||
})
|
||||
}
|
||||
|
||||
this.state.tableData.rows = setting;
|
||||
} catch (error) {
|
||||
console.error("从后端加载数据失败:", error);
|
||||
// 如果后端加载失败,使用演示数据
|
||||
@@ -156,27 +249,6 @@ export class FinancialSinglePage extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -193,43 +265,43 @@ export class FinancialSinglePage extends Component {
|
||||
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[0].values = {A: "12,500.00", B: "15,000.00", C: "11,800.00", D: "27.12", E: "较去年增长", 6: "8,000.00", 7: "4,000.00", 8: "3,000.00"};
|
||||
D
|
||||
// 二、总负债
|
||||
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[1].values = {A: "7,500.00", B: "8,200.00", C: "6,800.00", D: "20.59", E: "负债率控制在合理范围", 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[2].values = {A: "3,200.00", B: "3,500.00", C: "2,800.00", D: "25.00", E: "银行贷款为主", 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[3].values = {A: "85.00", B: "92.50", C: "78.20", D: "18.29", E: "利率有所下降", 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[4].values = {A: "5,000.00", B: "6,800.00", C: "5,000.00", D: "36.00", E: "净资产稳步增长", 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[5].values = {A: "8,200.00", B: "9,500.00", C: "7,500.00", D: "26.67", E: "收入稳步增长", 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[6].values = {A: "3,500.00", B: "4,200.00", C: "3,200.00", D: "31.25", E: "出租率提升", 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[7].values = {A: "2,800.00", B: "3,000.00", C: "2,500.00", D: "20.00", E: "轮换计划完成", 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[8].values = {A: "350.00", B: "420.00", C: "300.00", D: "40.00", E: "存款利息", 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[9].values = {A: "1,550.00", B: "1,880.00", C: "1,500.00", D: "25.33", E: "多元化经营", 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[10].values = {A: "1,200.00", B: "1,650.00", C: "1,050.00", D: "57.14", E: "利润增长显著", 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[11].values = {A: "850.00", B: "1,180.00", C: "720.00", D: "63.89", E: "净利润率提升", 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"};
|
||||
rows[12].values = {A: "120,000", B: "150,000", C: "115,000", D: "30.43", E: "平方米", 6: "80,000", 7: "50,000", 8: "20,000"};
|
||||
|
||||
}
|
||||
|
||||
@@ -237,8 +309,10 @@ export class FinancialSinglePage extends Component {
|
||||
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 || "所有部门";
|
||||
|
||||
if(this.state.filters.company){
|
||||
await this.getcompany()
|
||||
}
|
||||
await this.loadData();
|
||||
}
|
||||
|
||||
@@ -246,8 +320,8 @@ export class FinancialSinglePage extends Component {
|
||||
onReset() {
|
||||
this.state.filters = {
|
||||
date: this.getCurrentDate(),
|
||||
company: "",
|
||||
department: "",
|
||||
company: 0,
|
||||
department: 0,
|
||||
};
|
||||
this.onSearch();
|
||||
}
|
||||
@@ -277,16 +351,26 @@ export class FinancialSinglePage extends Component {
|
||||
* 获取表头颜色
|
||||
*/
|
||||
getHeaderColor(index) {
|
||||
const rainbowColors = [
|
||||
"#FF0000", // 红色
|
||||
"#FF7F00", // 橙色
|
||||
"#FFFF00", // 黄色
|
||||
"#00FF00", // 绿色
|
||||
"#007FFF", // 天蓝色
|
||||
"#0000FF", // 蓝色
|
||||
"#8B00FF" // 紫色
|
||||
];
|
||||
const colors = [
|
||||
"#667eea", // 去年底 - 蓝色
|
||||
"#f6ad55", // 本年当月 - 橙色
|
||||
"#68d391", // 去年同月 - 绿色
|
||||
"#fc8181", // 同比增长 - 红色
|
||||
"#a0aec0", // 说明 - 灰色
|
||||
"#4c51bf", // 天河公司 - 深蓝
|
||||
"#38a169", // 天河物管 - 绿色
|
||||
"#d69e2e", // 天河粮储 - 金色
|
||||
];
|
||||
let lond = this.state.tableData.headers.length - 5
|
||||
for(let i=0;i<lond;i++){
|
||||
colors.push(rainbowColors[i%7])
|
||||
}
|
||||
return colors[index % colors.length];
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,9 @@
|
||||
id="company_filter"
|
||||
t-model="state.filters.company"
|
||||
>
|
||||
<option value="">所有公司</option>
|
||||
<option value="company1">公司A</option>
|
||||
<option value="company2">公司B</option>
|
||||
<option value="company3">公司C</option>
|
||||
<t t-foreach="state.companys" t-as="company" t-key="company.id">
|
||||
<option t-att-value="company.id"><t t-esc="company.name" /></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -42,10 +41,9 @@
|
||||
id="employee_filter"
|
||||
t-model="state.filters.employee"
|
||||
>
|
||||
<option value="">所有员工</option>
|
||||
<option value="employee1">员工A</option>
|
||||
<option value="employee2">员工B</option>
|
||||
<option value="employee3">员工C</option>
|
||||
<t t-foreach="state.staffs" t-as="staff" t-key="staff.id">
|
||||
<option t-att-value="staff.id"><t t-esc="staff.name" /></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -144,121 +142,6 @@
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<!-- 横向表头 -->
|
||||
<t t-elif="state.setting.type === 'horizontal'">
|
||||
<t t-set="hasGroups" t-value="false"/>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<t t-if="header.groupName">
|
||||
<t t-set="hasGroups" t-value="true"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 如果有分组,显示两行表头 -->
|
||||
<t t-if="hasGroups">
|
||||
<tr>
|
||||
<th rowspan="2" class="sticky-column project-header diagonal-header">
|
||||
<div class="diagonal-text-container">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="diagonal-company">公司</div>
|
||||
<div class="diagonal-project">项目</div>
|
||||
</div>
|
||||
</th>
|
||||
<t t-set="currentGroup" t-value="false"/>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<t t-if="header.groupName !== currentGroup">
|
||||
<t t-set="groupItems" t-value="0"/>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="h" t-key="h.id">
|
||||
<t t-if="h.groupName === header.groupName">
|
||||
<t t-set="groupItems" t-value="groupItems + 1"/>
|
||||
</t>
|
||||
</t>
|
||||
<th t-att-colspan="groupItems" class="text-center group-header">
|
||||
<div class="group-title">
|
||||
<t t-esc="header.groupName"/>
|
||||
</div>
|
||||
</th>
|
||||
<t t-set="currentGroup" t-value="header.groupName"/>
|
||||
</t>
|
||||
</t>
|
||||
</tr>
|
||||
<!-- 第二行:具体项目 -->
|
||||
<tr>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<th class="text-center item-header">
|
||||
<div class="item-title">
|
||||
<t t-esc="header.name"/>
|
||||
<t t-if="header.fieldType">
|
||||
<div class="item-unit">
|
||||
(<t t-esc="header.fieldType"/>)
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<!-- 如果没有分组,只显示一行表头 -->
|
||||
<t t-if="hasGroups === false">
|
||||
<tr>
|
||||
<th class="sticky-column project-header diagonal-header">
|
||||
<div class="diagonal-text-container">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="diagonal-company">公司</div>
|
||||
<div class="diagonal-project">项目</div>
|
||||
</div>
|
||||
</th>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<th class="text-center item-header">
|
||||
<div class="item-title">
|
||||
<t t-esc="header.name"/>
|
||||
<t t-if="header.fieldType">
|
||||
<div class="item-unit">
|
||||
(<t t-esc="header.fieldType"/>)
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 竖向表头 -->
|
||||
<t t-elif="state.setting.type === 'vertical'">
|
||||
<tr>
|
||||
<th class="sticky-column project-header diagonal-header">
|
||||
<div class="diagonal-text-container">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="diagonal-company">公司</div>
|
||||
<div class="diagonal-project">项目</div>
|
||||
</div>
|
||||
</th>
|
||||
<t t-foreach="state.tableData.rows" t-as="dataRow" t-key="dataRow.id">
|
||||
<th class="text-center item-header">
|
||||
<div class="item-title">
|
||||
<t t-esc="dataRow.name"/>
|
||||
</div>
|
||||
</th>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<!-- 默认表头(无数据时) -->
|
||||
<t t-if="state.tableData.displayHeaders.length === 0">
|
||||
<tr>
|
||||
<th class="sticky-column project-header diagonal-header">
|
||||
<div class="diagonal-text-container">
|
||||
<div class="diagonal-line"></div>
|
||||
<div class="diagonal-company">公司</div>
|
||||
<div class="diagonal-project">项目</div>
|
||||
</div>
|
||||
</th>
|
||||
<th class="text-center item-header">
|
||||
<div class="item-title">数据</div>
|
||||
</th>
|
||||
</tr>
|
||||
</t>
|
||||
</thead>
|
||||
|
||||
<!-- 表格体 -->
|
||||
@@ -283,42 +166,6 @@
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 横向数据 -->
|
||||
<t t-elif="state.setting.type === 'horizontal' and state.tableData.rows.length > 0">
|
||||
<t t-foreach="state.tableData.rows" t-as="dataRow" t-key="dataRow.id">
|
||||
<tr>
|
||||
<td class="sticky-column project-cell">
|
||||
<div class="project-name">
|
||||
<t t-esc="dataRow.name"/>
|
||||
</div>
|
||||
</td>
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<td class="text-end data-cell">
|
||||
<t t-esc="dataRow.values[header.id] || '0.00'"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 竖向数据 -->
|
||||
<t t-elif="state.setting.type === 'vertical' and state.tableData.displayHeaders.length > 0">
|
||||
<t t-foreach="state.tableData.displayHeaders" t-as="header" t-key="header.id">
|
||||
<tr>
|
||||
<td class="sticky-column project-cell">
|
||||
<div class="project-name">
|
||||
<t t-esc="header.name"/>
|
||||
</div>
|
||||
</td>
|
||||
<t t-foreach="state.tableData.rows" t-as="dataRow" t-key="dataRow.id">
|
||||
<td class="text-end data-cell">
|
||||
<t t-esc="dataRow.values[header.id] || '0.00'"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- 无数据时显示空状态 -->
|
||||
<t t-if="state.tableData.rows.length === 0">
|
||||
<tr>
|
||||
|
||||
@@ -29,30 +29,28 @@
|
||||
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>
|
||||
<t t-foreach="state.companys" t-as="company" t-key="company.id">
|
||||
<option t-att-value="company.id"><t t-esc="company.name" /></option>
|
||||
</t>
|
||||
</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">-->
|
||||
<!-- <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">
|
||||
@@ -198,14 +196,14 @@
|
||||
共 <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 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>
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
</record>
|
||||
|
||||
|
||||
<!-- <menuitem id="financial_sheet_collection_report_menu"-->
|
||||
<!-- name="财务数据表报表"-->
|
||||
<!-- action="yuthon_account_report.financial_data_action"-->
|
||||
<!-- sequence="10"/>-->
|
||||
|
||||
<!-- <menuitem id="information_summary_table_report_menu"-->
|
||||
<!-- name="信息汇总报表"-->
|
||||
<!-- action="yuthon_account_report.information_aggregation_action"-->
|
||||
<!-- sequence="10"/>-->
|
||||
|
||||
|
||||
<!-- <record id="information_aggregation_action" model="ir.actions.client">-->
|
||||
<!-- <field name="name">信息汇总报表</field>-->
|
||||
<!-- <field name="tag">information_aggregation_action</field>-->
|
||||
|
||||
Reference in New Issue
Block a user