Merge branch '18.x+bi' into 18.x

This commit is contained in:
qixinzhi
2024-02-05 09:24:26 +08:00
224 changed files with 4722 additions and 3603 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
<?php
<?php
/**
* The ciresults entry point of ZenTaoPMS.
* The ci results entry point of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
+1 -1
View File
@@ -46,7 +46,7 @@ class testcaseEntry extends entry
$oldCase = $this->loadModel('testcase')->getByID($caseID);
/* Set $_POST variables. */
$fields = 'title,pri,story,type,stage,product,module,branch,precondition,script';
$fields = 'title,pri,story,type,stage,product,module,branch,precondition,script,keywords';
$this->batchSetPost($fields, $oldCase);
if(isset($this->requestBody->auto)) $this->setPost('auto', 'auto');
if(isset($this->requestBody->script)) $this->setPost('auto', 'auto');
+23 -1
View File
@@ -6,8 +6,30 @@ ALTER TABLE `zt_story` ADD COLUMN `retractedBy` varchar(30) NOT NULL DEFAULT '';
ALTER TABLE `zt_story` ADD COLUMN `retractedDate` datetime;
ALTER table `zt_metric` ADD `dateType` varchar(50) NOT NULL DEFAULT '';
ALTER table `zt_metric` ADD `lastCalcRows` int NOT NULL DEFAULT 0 AFTER `order`;
ALTER table `zt_metric` ADD `lastCalcRows` mediumint NOT NULL DEFAULT 0 AFTER `order`;
ALTER table `zt_metric` ADD `lastCalcTime` datetime DEFAULT NULL AFTER `lastCalcRows`;
INSERT INTO `zt_metric`(`purpose`, `scope`, `object`, `stage`, `type`, `name`, `code`, `unit`, `collector`, `desc`, `definition`, `when`, `createdBy`, `createdDate`, `builtin`, `deleted`, `dateType`) VALUES
('scale', 'system', 'execution', 'released', 'php', '按系统统计的年度完成执行数', 'count_of_annual_finished_execution', 'count', NULL, '按系统统计的年度完成执行数是指在某年度已经完成的执行数。该度量项反映了团队或组织在某年的工作效率和完成能力。较高的年度完成执行数表示团队或组织在完成任务方面表现出较高的效率,反之则可能需要审查工作流程和资源分配情况,以提高执行效率。', '所有的执行个数求和\r\n实际完成日期为某年\r\n过滤已删除的执行', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year');
UPDATE `zt_metric` SET `createdBy` = 'system' WHERE `createdBy` = '';
UPDATE `zt_metric` SET `createdDate` = '2023-08-22 08:00:00' WHERE `createdDate` IS NULL;
UPDATE `zt_metric` SET `definition` = '所有测试单中的用例个数求和(不去重)\r\n指派给某人\r\n过滤已删除的用例\r\n过滤已删除的测试单中的用例\r\n过滤已关闭的测试单中的用例\r\n' WHERE `code` = 'count_of_assigned_case_in_user';
UPDATE `zt_metric` SET `definition` = '所有任务个数求和\r\n指派给为某人\r\n过滤已关闭的任务\r\n过滤已取消的任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务\r\n过滤多人任务中某人任务状态为已完成的任务\r\n过滤任务关联的执行和项目都为挂起状态时的任务' WHERE `code` = 'count_of_assigned_task_in_user';
UPDATE `zt_metric` SET `definition` = '所有研发需求个数求和\r\n过滤已删除的研发需求\r\n过滤状态为已关闭的研发需求\r\n过滤已删除产品下的研发需求\r\n过滤已删除的无产品项目下的研发需求' WHERE `code` = 'count_of_pending_story_in_user';
UPDATE `zt_metric` SET `definition` = '所有研发需求个数求和\r\n评审人为某人\r\n评审结果为空\r\n评审状态为评审中或变更中\r\n过滤已删除的需求\r\n过滤已删除产品的需求' WHERE `code` = 'count_of_reviewing_story_in_user';
UPDATE `zt_metric` SET `definition` = '所有Bug个数求和\r\nbug状态为已解决和已关闭\r\n解决者为某人\r\n解决日期为某日\r\n过滤已删除的bug\r\n过滤已删除产品的bug' WHERE `code` = 'count_of_daily_fixed_bug_in_user';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n状态为已完成\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_finished_task';
UPDATE `zt_metric` SET `definition` = '复用:\r\n按系统统计的任务总数\r\n按系统统计的已完成任务数\r\n公式:\r\n按系统统计的未完成任务数=按系统统计的任务总数-按系统统计的已完成任务数' WHERE `code` = 'count_of_unfinished_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n状态为已关闭\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_closed_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n创建时间为某年\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_annual_created_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n完成时间为某年\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_annual_finished_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n创建时间为某年某月\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_monthly_created_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n完成时间为某年某月\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_monthly_finished_task';
UPDATE `zt_metric` SET `definition` = '所有的任务的预计工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'estimate_of_task';
UPDATE `zt_metric` SET `definition` = '所有的任务的消耗工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'consume_of_task';
UPDATE `zt_metric` SET `definition` = '所有的任务的剩余工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'left_of_task';
UPDATE `zt_metric` SET `definition` = '所有的任务个数求和\r\n完成时间为某日\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务' WHERE `code` = 'count_of_daily_finished_task';
+20 -18
View File
@@ -15981,6 +15981,7 @@ CREATE TABLE IF NOT EXISTS `zt_metric` (
`object` char(30) NOT NULL DEFAULT '',
`stage` enum('wait','released') NULL DEFAULT 'wait',
`type` enum('php', 'sql') NULL DEFAULT 'php',
`dateType` varchar(50) NOT NULL DEFAULT '',
`name` varchar(90) NOT NULL DEFAULT '',
`code` varchar(90) NOT NULL DEFAULT '',
`unit` varchar(10) NOT NULL DEFAULT '',
@@ -16003,7 +16004,7 @@ CREATE TABLE IF NOT EXISTS `zt_metric` (
`builtin` enum('0', '1') NOT NULL DEFAULT '0',
`fromID` mediumint unsigned NOT NULL DEFAULT 0,
`order` mediumint unsigned NOT NULL DEFAULT '0',
`lastCalcRows` int NOT NULL DEFAULT '0',
`lastCalcRows` mediumint unsigned NOT NULL DEFAULT 0,
`lastCalcTime` datetime DEFAULT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
@@ -16034,7 +16035,8 @@ CREATE TABLE IF NOT EXISTS `zt_metriclib` (
CREATE INDEX `metricID` ON `zt_metriclib`(`metricID`);
CREATE INDEX `metricCode` ON `zt_metriclib`(`metricCode`);
INSERT INTO `zt_metric`(`purpose`, `scope`, `object`, `stage`, `type`, `name`, `code`, `unit`, `desc`, `definition`, `when`, `createdBy`, `createdDate`, `builtin`, `deleted`, `dateType`) VALUES ('scale', 'system', 'program', 'released', 'php', '按系统统计的所有层级的项目集总数', 'count_of_program', 'count', '按系统统计的所有层级的项目集总数表示在整个组织范围内的项目集数量。此度量项反映了整个组织所管理的项目集数量。可以作为评估组织规模和复杂度的指标。', '所有项目集的个数求和\r\n过滤已删除的项目集', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
INSERT INTO `zt_metric`(`purpose`, `scope`, `object`, `stage`, `type`, `name`, `code`, `unit`, `desc`, `definition`, `when`, `createdBy`, `createdDate`, `builtin`, `deleted`, `dateType`) VALUES
('scale', 'system', 'program', 'released', 'php', '按系统统计的所有层级的项目集总数', 'count_of_program', 'count', '按系统统计的所有层级的项目集总数表示在整个组织范围内的项目集数量。此度量项反映了整个组织所管理的项目集数量。可以作为评估组织规模和复杂度的指标。', '所有项目集的个数求和\r\n过滤已删除的项目集', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'program', 'released', 'php', '按系统统计的所有层级进行中项目集数', 'count_of_doing_program', 'count', '按系统统计的所有层级进行中项目集数表示当前正在进行中的项目集数量。此度量项反映了组织当前正在进行中的项目集数量,可以用于评估组织的项目集管理进展和资源分配情况。', '所有项目集的个数求和\r\n状态为进行中\r\n过滤已删除的项目集', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'program', 'released', 'php', '按系统统计的所有层级已关闭项目集数', 'count_of_closed_program', 'count', '按系统统计的所有层级已关闭项目集数反映了系统关闭的项目集数量,用于评估组织项目集层面的管理成果。', '所有项目集的个数求和\r\n状态为已关闭\r\n过滤已删除的项目集', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'program', 'released', 'php', '按系统统计的所有层级已挂起项目集数', 'count_of_suspended_program', 'count', '按系统统计的所有层级已挂起项目集数反映了系统内因为某种原因暂时中止或搁置的项目集数量,用于评估组织项目集层面的风险和不确定性。', '所有项目集的个数求和\r\n状态为已挂起\r\n过滤已删除的项目集', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
@@ -16129,18 +16131,18 @@ INSERT INTO `zt_metric`(`purpose`, `scope`, `object`, `stage`, `type`, `name`, `
('rate', 'system', 'story', 'released', 'php', '按系统统计的研发需求交付率', 'rate_of_delivered_story', 'percentage', '按系统统计的研发需求交付率反映了组织在研发过程中按时交付需求的能力和表现。用于评估组织对于评估交付能力、客户满意度和信任建立、项目管理和资源优化、竞争力和市场表现,以及持续改进和效率提升具有重要意义。', '复用:\r\n按系统统计的已交付研发需求数\r\n按系统统计的有效研发需求数\r\n公式:\r\n按系统统计的研发需求完成率=按系统统计的已交付研发需求数/按系统统计的有效研发需求数*100%', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('rate', 'system', 'story', 'released', 'php', '按系统统计的年度研发需求完成率', 'rate_of_annual_finished_story', 'percentage', '按系统统计的年度研发需求完成率反映了组织在年度研发过程中完成需求的能力和表现,反映了组织对于评估项目目标达成、资源规划和优化、业务决策和战略执行、绩效评估和激励机制,以及持续改进和效率提升具有重要意义。', '复用:\r\n按系统统计的年度完成研发需求数\r\n按系统统计的年度有效研发需求数\r\n公式:\r\n按系统统计的年度研发需求完成率=按系统统计的年度完成研发需求数/按系统统计的年度有效研发需求数*100%', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('rate', 'system', 'story', 'released', 'php', '按系统统计的年度研发需求交付率', 'rate_of_annual_delivered_story', 'percentage', '按系统统计的年度研发需求交付率反映了组织在年度研发过程中按时交付需求的能力和表现,用于评估组织对于评估项目交付能力、客户满意度和信任建立、项目进度管理和风险控制、绩效评估和激励机制,以及持续改进和效率提升具有重要意义。', '复用:\r\n按系统统计的年度交付研发需求数\r\n按系统统计的年度有效研发需求数\r\n公式:\r\n按系统统计的年度研发需求完成率=按系统统计的年度交付研发需求数/按系统统计的年度有效研发需求数*100%', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务总数', 'count_of_task', 'count', '按系统统计的任务总数是指整个团队或组织当前存在的任务总量。该度量项可以用来跟踪任务的规模和复杂性,为资源分配和工作计划提供基础。较大的任务总数可能需要更多的资源和时间来完成,而较小的任务总数可能意味着团队负荷较轻或项目进展较好。', '所有的任务个数求和\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的已完成任务数', 'count_of_finished_task', 'count', '按系统统计的已完成任务数是指团队或组织已经完成的任务总量。该度量项可以衡量任务完成的进度和效率,以及团队成员或组织的工作质量和产出。较高的已完成任务总数可能表明团队在交付工作方面表现出较好的能力。', '所有的任务个数求和\r\n状态为已完成\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务总数', 'count_of_task', 'count', '按系统统计的任务总数是指整个团队或组织当前存在的任务总量。该度量项可以用来跟踪任务的规模和复杂性,为资源分配和工作计划提供基础。较大的任务总数可能需要更多的资源和时间来完成,而较小的任务总数可能意味着团队负荷较轻或项目进展较好。', '所有的任务个数求和\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的已完成任务数', 'count_of_finished_task', 'count', '按系统统计的已完成任务数是指团队或组织已经完成的任务总量。该度量项可以衡量任务完成的进度和效率,以及团队成员或组织的工作质量和产出。较高的已完成任务总数可能表明团队在交付工作方面表现出较好的能力。', '所有的任务个数求和\r\n状态为已完成\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的未完成任务数', 'count_of_unfinished_task', 'count', '按系统统计的未完成任务数是指团队或组织未完成的任务总量。该度量项可以用来评估项目进展和未来工作量,同时也可以帮助进行资源分配和优先级确定。较大的未完成任务总数可能需要更多的努力和调整来确保任务按时完成。', '复用:\r\n按系统统计的任务总数\r\n按系统统计的已完成任务数\r\n公式:\r\n按系统统计的未完成任务数=按系统统计的任务总数-按系统统计的已完成任务数', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的已关闭任务数', 'count_of_closed_task', 'count', '按系统统计的已关闭任务数是指团队或组织已经关闭的任务总量。该度量项可以用来评估项目或团队的运营情况和任务管理效果。较高的已关闭任务总数可能表明团队在任务管理方面表现出较好的能力,同时也可以释放资源和优先处理其他任务。', '所有的任务个数求和\r\n状态为已关闭\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的年度新增任务数', 'count_of_annual_created_task', 'count', '按系统统计的年度新增任务数是指一年内新添加的任务总量。该度量项可以用来衡量团队或组织在某年内所承担的新增工作量。较高的年度新增任务数可能需要额外的资源和计划调整来满足需求。', '所有的任务个数求和\r\n创建时间为某年\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的年度完成任务数', 'count_of_annual_finished_task', 'count', '按系统统计的年度完成任务数是指某年内已经完成的任务总量。该度量项可以用来评估团队或组织在某年内的工作效率和完成能力。较高的年度完成任务数表示团队或组织在项目执行方面表现出较好的效率。', '所有的任务个数求和\r\n完成时间为某年\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的月度新增任务数', 'count_of_monthly_created_task', 'count', '按系统统计的月度新增任务数是指在某月新添加的任务总量。该度量项可以用来衡量团队或组织在某月内所承担的新增工作量,以及对项目规划和资源分配的影响。较高的月度新增任务数可能需要额外的资源和计划调整来满足需求。', '所有的任务个数求和\r\n创建时间为某年某月\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'month'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的月度完成任务数', 'count_of_monthly_finished_task', 'count', '按系统统计的月度完成任务数是指在某月已经完成的任务总量。该度量项可以用来评估团队或组织在某月内的工作效率和完成能力。较高的月度完成任务数表示团队或组织在项目执行方面表现出较好的效率。', '所有的任务个数求和\r\n完成时间为某年某月\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'month'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务预计工时数', 'estimate_of_task', 'hour', '按系统统计的任务预计工时数是指所有任务预计完成所需的工时总和。该度量项可以用来规划资源和预估工期,为项目管理和团队协作提供依据。较准确的任务预计工时总数可以帮助团队更好地安排时间和资源,提高任务的完成效率。', '所有的任务的预计工时数求和\r\n过滤父任务\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务消耗工时数', 'consume_of_task', 'hour', '按系统统计的任务消耗工时数是指已经花费的工时总和,用于完成所有任务。该度量项可以用来评估团队或组织在任务执行过程中的工时投入情况,以及在完成任务方面的效率和资源利用情况。较高的任务消耗工时总数可能表明需要审查工作流程和资源分配,以提高工作效率。', '所有的任务的消耗工时数求和\r\n过滤父任务\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务剩余工时数', 'left_of_task', 'hour', '按系统统计的任务剩余工时数是指任务当前剩余工时的总和,用于完成所有任务。该度量项可以用来评估团队或组织在任务执行过程中剩余的工作量和时间,以及为完成任务所需的资源和计划。较小的任务剩余工时总数可能表示团队即将完成任务。', '所有的任务的剩余工时数求和\r\n过滤父任务\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的每日完成任务数', 'count_of_daily_finished_task', 'count', '按系统统计的每日完成任务数是指每日完成的任务总量。该度量项可以用来评估团队或组织每日的工作效率和任务完成能力。', '所有的任务个数求和\r\n完成时间为某日\r\n过滤已删除的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的已关闭任务数', 'count_of_closed_task', 'count', '按系统统计的已关闭任务数是指团队或组织已经关闭的任务总量。该度量项可以用来评估项目或团队的运营情况和任务管理效果。较高的已关闭任务总数可能表明团队在任务管理方面表现出较好的能力,同时也可以释放资源和优先处理其他任务。', '所有的任务个数求和\r\n状态为已关闭\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的年度新增任务数', 'count_of_annual_created_task', 'count', '按系统统计的年度新增任务数是指一年内新添加的任务总量。该度量项可以用来衡量团队或组织在某年内所承担的新增工作量。较高的年度新增任务数可能需要额外的资源和计划调整来满足需求。', '所有的任务个数求和\r\n创建时间为某年\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的年度完成任务数', 'count_of_annual_finished_task', 'count', '按系统统计的年度完成任务数是指某年内已经完成的任务总量。该度量项可以用来评估团队或组织在某年内的工作效率和完成能力。较高的年度完成任务数表示团队或组织在项目执行方面表现出较好的效率。', '所有的任务个数求和\r\n完成时间为某年\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'year'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的月度新增任务数', 'count_of_monthly_created_task', 'count', '按系统统计的月度新增任务数是指在某月新添加的任务总量。该度量项可以用来衡量团队或组织在某月内所承担的新增工作量,以及对项目规划和资源分配的影响。较高的月度新增任务数可能需要额外的资源和计划调整来满足需求。', '所有的任务个数求和\r\n创建时间为某年某月\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'month'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的月度完成任务数', 'count_of_monthly_finished_task', 'count', '按系统统计的月度完成任务数是指在某月已经完成的任务总量。该度量项可以用来评估团队或组织在某月内的工作效率和完成能力。较高的月度完成任务数表示团队或组织在项目执行方面表现出较好的效率。', '所有的任务个数求和\r\n完成时间为某年某月\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'month'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务预计工时数', 'estimate_of_task', 'hour', '按系统统计的任务预计工时数是指所有任务预计完成所需的工时总和。该度量项可以用来规划资源和预估工期,为项目管理和团队协作提供依据。较准确的任务预计工时总数可以帮助团队更好地安排时间和资源,提高任务的完成效率。', '所有的任务的预计工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务消耗工时数', 'consume_of_task', 'hour', '按系统统计的任务消耗工时数是指已经花费的工时总和,用于完成所有任务。该度量项可以用来评估团队或组织在任务执行过程中的工时投入情况,以及在完成任务方面的效率和资源利用情况。较高的任务消耗工时总数可能表明需要审查工作流程和资源分配,以提高工作效率。', '所有的任务的消耗工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的任务剩余工时数', 'left_of_task', 'hour', '按系统统计的任务剩余工时数是指任务当前剩余工时的总和,用于完成所有任务。该度量项可以用来评估团队或组织在任务执行过程中剩余的工作量和时间,以及为完成任务所需的资源和计划。较小的任务剩余工时总数可能表示团队即将完成任务。', '所有的任务的剩余工时数求和\r\n过滤父任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'task', 'released', 'php', '按系统统计的每日完成任务数', 'count_of_daily_finished_task', 'count', '按系统统计的每日完成任务数是指每日完成的任务总量。该度量项可以用来评估团队或组织每日的工作效率和任务完成能力。', '所有的任务个数求和\r\n完成时间为某日\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'system', 'bug', 'released', 'php', '按系统统计的Bug总数', 'count_of_bug', 'count', '按系统统计的Bug总数是指在整个系统中发现的所有Bug的数量。这个度量项反映了系统或项目的整体Bug质量情况。Bug总数越多可能代表系统或项目的代码质量存在问题,需要进行进一步的解决和改进。', '所有Bug个数求和\r\n过滤已删除的Bug\r\n过滤已删除的产品', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'bug', 'released', 'php', '按系统统计的激活Bug数', 'count_of_activated_bug', 'count', '按系统统计的激活Bug数是指当前尚未解决的Bug数量。这个度量项反映了系统或项目当前存在的待解决问题数量。激活Bug总数越多可能代表系统或项目的稳定性较低,需要加强Bug解决的速度和质量。', '所有Bug个数求和\r\n状态为激活\r\n过滤已删除的Bug\r\n过滤已删除的产品', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'system', 'bug', 'released', 'php', '按系统统计的已解决Bug数', 'count_of_resolved_bug', 'count', '按系统统计的已解决Bug数是指已经被开发团队解决的Bug数量。反映了组织在特定时间段内已解决的Bug数量,用于评估系统质量、用户满意度、资源管理、过程改进和绩效评估等方面。通过跟踪和分析已解决的Bug数,可以及时发现问题、改进开发过程、提高用户满意度,并为团队绩效评估和优化提供依据。', '所有Bug个数求和\r\n状态为已解决\r\n过滤已删除的Bug\r\n过滤已删除的产品', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
@@ -16291,14 +16293,14 @@ INSERT INTO `zt_metric`(`purpose`, `scope`, `object`, `stage`, `type`, `name`, `
('hour', 'execution', 'task', 'released', 'php', '按执行统计的任务消耗工时数', 'consume_of_task_in_execution', 'hour', '按执行统计的任务消耗工时数是指已经花费的工时总和,用于完成所有任务。该度量项反映了任务的实际完成情况和资源使用情况,可以帮助团队掌握任务的进展情况和资源利用效率。', '执行中任务的消耗工时数求和\r\n过滤已删除的任务\r\n过滤父任务\r\n过滤已删除的执行\r\n过滤已删除的项目', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('hour', 'execution', 'task', 'released', 'php', '按执行统计的任务剩余工时数', 'left_of_task_in_execution', 'hour', '按执行统计的任务剩余工时数是指当前未消耗的工时总和,用于完成所有任务。该度量项反映了任务完成的剩余工作量,可以帮助团队预测任务的完成时间和资源需求。', '执行中任务的剩余工时数求和\r\n过滤已删除的任务\r\n过滤父任务\r\n过滤已删除的执行\r\n过滤已删除的项目', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('rate', 'execution', 'task', 'released', 'php', '按执行统计的任务进度', 'progress_of_task_in_execution', 'percentage', '按执行统计的任务进度是指执行团队按已消耗的工时数与已消耗和剩余的工时数的比率。该度量项反映了任务的执行进展情况,可以帮助团队评估任务是否按计划进行并做出相应调整。', '复用:\r\n按执行统计的任务消耗工时数\r\n按执行统计的任务剩余工时数\r\n公式:\r\n按执行统计的任务进度=按执行统计的任务消耗工时数/(按执行统计的任务消耗工时数+按执行统计的任务剩余工时数)', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'story', 'released', 'php', '按人员统计的待评审研发需求数', 'count_of_reviewing_story_in_user', 'count', '按人员统计的待评审研发需求数表示每个人需要评审的研发需求数量之和。反映了每个人需要评审的研发需求的规模。该数值越大,说明需要投入越多的时间评审需求。', '所有研发需求个数求和\r\n状态为评审中\r\n指派给为某人\r\n过滤已删除的研发需求\r\n过滤已删除产品的研发需求', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'story', 'released', 'php', '按人员统计的待评审研发需求数', 'count_of_reviewing_story_in_user', 'count', '按人员统计的待评审研发需求数表示每个人需要评审的研发需求数量之和。反映了每个人需要评审的研发需求的规模。该数值越大,说明需要投入越多的时间评审需求。', '所有研发需求个数求和\r\n评审人为某人\r\n评审结果为空\r\n评审状态为评审中或变更中\r\n过滤已删除的需求\r\n过滤已删除产品的需求', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'story', 'released', 'php', '按人员统计的每日评审研发需求数', 'count_of_daily_review_story_in_user', 'count', '按人员统计的日评审研发需求数表示每个人每日评审的研发需求数量之和。反映了每个人每日评审研发需求的规模。该数值越大,说明工作量越大。', '所有研发需求个数求和\r\n评审者为某人\r\n评审时间为某日\r\n过滤已删除的研发需求\r\n过滤已删除产品的研发需求', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'user', 'story', 'released', 'php', '按人员统计的待处理研发需求数', 'count_of_pending_story_in_user', 'count', '按人员统计的待处理研发需求数表示每个人待处理的研发需求数量之和。反映了每个人员需要处理的研发需求数量的规模。该数值越大,说明需要投入越多的时间处理研发需求。', '所有研发需求个数求和\r\n指派给为某人\r\n过滤已删除的研发需求\r\n过滤已删除产品的研发需求', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'story', 'released', 'php', '按人员统计的待处理研发需求数', 'count_of_pending_story_in_user', 'count', '按人员统计的待处理研发需求数表示每个人待处理的研发需求数量之和。反映了每个人员需要处理的研发需求数量的规模。该数值越大,说明需要投入越多的时间处理研发需求。', '所有研发需求个数求和\r\n过滤已删除的研发需求\r\n过滤状态为已关闭的研发需求\r\n过滤已删除产品下的研发需求\r\n过滤已删除的无产品项目下的研发需求', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'task', 'released', 'php', '按人员统计的每日完成任务数', 'count_of_daily_finished_task_in_user', 'count', '按人员统计的日完成任务数表示每个人每日完成的任务数量之和。反映了每个人每日完成的任务规模。该数值越大,可能说明工作效率越高,任务完成速度越快。', '某人某日完成的任务个数求和', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'user', 'task', 'released', 'php', '按人员统计的待处理任务数', 'count_of_assigned_task_in_user', 'count', '按人员统计的待处理任务数表示每个人待处理的任务数量之和。反映了每个人在需要处理的任务数量上的规模。该数值越大,说明需要投入越多的时间处理任务。', '所有任务个数求和\r\n指派给为某人\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'bug', 'released', 'php', '按人员统计的日解决Bug数', 'count_of_daily_fixed_bug_in_user', 'count', '按人员统计的日解决Bug数表示每个人每日解决的Bug数量之和。反映了每个人每日解决Bug的规模。该数值越大,可能说明Bug的解决能力越强,工作效率越高。', '所有Bug个数求和\r\n解决者为某人', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'user', 'task', 'released', 'php', '按人员统计的待处理任务数', 'count_of_assigned_task_in_user', 'count', '按人员统计的待处理任务数表示每个人待处理的任务数量之和。反映了每个人在需要处理的任务数量上的规模。该数值越大,说明需要投入越多的时间处理任务。', '所有任务个数求和\r\n指派给为某人\r\n过滤已关闭的任务\r\n过滤已取消的任务\r\n过滤已删除的任务\r\n过滤已删除项目的任务\r\n过滤已删除执行的任务\r\n过滤多人任务中某人任务状态为已完成的任务\r\n过滤任务关联的执行和项目都为挂起状态时的任务', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'bug', 'released', 'php', '按人员统计的日解决Bug数', 'count_of_daily_fixed_bug_in_user', 'count', '按人员统计的日解决Bug数表示每个人每日解决的Bug数量之和。反映了每个人每日解决Bug的规模。该数值越大,可能说明Bug的解决能力越强,工作效率越高。', '所有Bug个数求和\r\nbug状态为已解决和已关闭\r\n解决者为某人\r\n解决日期为某日\r\n过滤已删除的bug\r\n过滤已删除产品的bug', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
('scale', 'user', 'bug', 'released', 'php', '按人员统计的待处理Bug数', 'count_of_assigned_bug_in_user', 'count', '按人员统计的待处理Bug数表示每个人待处理的Bug数量之和。反映了每个人需要处理的Bug数量上的规模。该数值越大,说明需要投入越多的时间解决Bug。', '所有Bug个数求和\r\n指派给为某人\r\n过滤已删除的Bug\r\n过滤已删除产品的Bug', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'case', 'released', 'php', '按人员统计的待处理用例数', 'count_of_assigned_case_in_user', 'count', '按人员统计的待处理用例数表示每个人待处理的用例数量之和。反映了每个人需要处理的用例数量上的规模。该数值越大,说明需要投入越多的时间处理用例。', '所有用例个数求和\r\n指派给为某人\r\n过滤已删除的用例\r\n过滤已删除产品的用例', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'case', 'released', 'php', '按人员统计的待处理用例数', 'count_of_assigned_case_in_user', 'count', '按人员统计的待处理用例数表示每个人待处理的用例数量之和。反映了每个人需要处理的用例数量上的规模。该数值越大,说明需要投入越多的时间处理用例。', '所有测试单中的用例个数求和(不去重)\r\n指派给某人\r\n过滤已删除的用例\r\n过滤已删除的测试单中的用例\r\n过滤已关闭的测试单中的用例\r\n', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'feedback', 'released', 'php', '按人员统计的待处理反馈数', 'count_of_assigned_feedback_in_user', 'count', '按人员统计的待处理反馈数表示每个人待处理的反馈数量之和。反映了每个人需要处理的反馈数量上的规模。该数值越大,说明需要投入越多的时间处理反馈。', '所有反馈个数求和\r\n指派给为某人\r\n过滤已删除的反馈\r\n过滤已删除产品的反馈', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'feedback', 'released', 'php', '按人员统计的待评审反馈数', 'count_of_reviewing_feedback_in_user', 'count', '按人员统计的待评审反馈数表示每个人待评审的反馈数量之和。反映了每个人需要评审的反馈的规模。该数值越大,说明需要投入越多的时间评审反馈。', '所有反馈个数求和\r\n状态为待评审\r\n指派给为某人\r\n过滤已删除的反馈\r\n过滤已删除产品的反馈', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'nodate'),
('scale', 'user', 'feedback', 'released', 'php', '按人员统计的每日评审反馈数', 'count_of_daily_review_feedback_in_user', 'count', '按人员统计的日评审反馈数表示每个人每日评审的反馈数量之和。反映了每个人每日评审的反馈的规模。该数值越大,说明工作量越大。', '所有反馈个数求和\r\n由谁评审为某人\r\n评审时间为某日\r\n过滤已删除的反馈\r\n过滤已删除产品的反馈', 'realtime', 'system', '2023-08-22 08:00:00', '1', '0', 'day'),
+20
View File
@@ -417,6 +417,7 @@ class baseRouter
$this->loadClass('filter', $static = true);
$this->loadClass('form', $static = true);
$this->loadClass('dbh', $static = true);
$this->loadClass('sqlite', $static = true);
$this->loadClass('dao', $static = true);
$this->loadClass('mobile', $static = true);
@@ -2940,6 +2941,25 @@ class baseRouter
}
}
/**
* 连接SQLite数据库。
* Connect SQLite database.
*
* @param object $params
* @access public
* @return object
*/
public function connectSqlite($params = null)
{
if(empty($params))
{
$params = new stdclass();
$params->file = $this->getTmpRoot() . 'sqlite.db';
}
return new sqlite($params);
}
/**
* Query from database, use master or slave db.
*
+224
View File
@@ -0,0 +1,224 @@
<?php
/**
* The control file of sqlite class of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author liuyongkai <liuyongkai@easycorp.ltd>
* @package sqlite
* @link http://www.zentao.net
*/
class sqlite
{
/**
* 全局$app对象。
* The global app object.
*
* @var object
* @access public
*/
public $app;
/**
* 全局$config对象。
* The global config object.
*
* @var object
* @access public
*/
public $config;
/**
* 全局$mysql对象。
* The global mysql object.
*
* @var object
* @access public
*/
public $mysql;
/**
* 全局$sqlite对象。
* The global sqlite object.
*
* @var object
* @access public
*/
public $dbh = null;
/**
* __construct.
*
* @access public
* @return void
*/
public function __construct(object $params)
{
global $app, $config, $dbh;
$this->app = $app;
$this->mysql = $dbh;
$this->config = $config;
$file = empty($params) || !isset($params->file) ? '' : $params->file;
$this->connectSqlite($file);
}
/**
* 使用PDO连接SQLite数据库。
* Connect to sqlite database by PDO.
*
* @param string $sqliteFile
* @access public
* @return object
*/
public function connectSqlite(string $sqliteFile = ''): object
{
$tmpRoot = $this->app->getTmpRoot();
if(empty($sqliteFile) || !is_file($sqliteFile)) $sqliteFile = $tmpRoot . 'sqlite.db';
$sqliteFile = realpath($sqliteFile);
if(strpos($sqliteFile, $tmpRoot) !== 0) return helper::end("The sqlite file '$sqliteFile' is not in the tmp root '$tmpRoot'");
if(!is_file($sqliteFile)) return helper::end("The sqlite file '$sqliteFile' is not exists");
$dbh = new PDO("sqlite:$sqliteFile");
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbh = $dbh;
return $this;
}
/**
* 将MySQL数据类型转化为SQLite数据类型。
* Convert MySQL attr to SQLite attr.
*
* @param string $sql
* @access public
* @return string
*/
public function formatAttr(string $sql): string
{
$sql = str_replace('`', '', $sql);
$sql = preg_replace('/\s*int\s*\(\d+\)\s*NOT NULL AUTO_INCREMENT/i', ' INTEGER PRIMARY KEY AUTOINCREMENT', $sql);
$sql = preg_replace('/\s*int\s*\(\d+\)\s*AUTO_INCREMENT/i', ' INTEGER PRIMARY KEY AUTOINCREMENT', $sql);
$sql = preg_replace('/\s*tinyint\(\d+\)/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*smallint\(\d+\)/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*mediumint\(\d+\)/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*int\(\d+\)/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*bigint\(\d+\)/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*float/i', ' REAL', $sql);
$sql = preg_replace('/\s*double/i', ' REAL', $sql);
$sql = preg_replace('/\s*decimal/i', ' REAL', $sql);
$sql = preg_replace('/\s*datetime/i', ' TEXT', $sql);
$sql = preg_replace('/\s*timestamp/i', ' TEXT', $sql);
$sql = preg_replace('/\s*time/i', ' TEXT', $sql);
$sql = preg_replace('/\s*date/i', ' TEXT', $sql);
$sql = preg_replace('/\s*enum\([^)]*\)/i', ' TEXT', $sql);
$sql = preg_replace('/\s*set\([^)]*\)/i', ' TEXT', $sql);
$sql = preg_replace('/\s*year/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*bit/i', ' INTEGER', $sql);
$sql = preg_replace('/\s*UNSIGNED/i', '', $sql);
$sql = preg_replace('/\s*DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP/i', '', $sql);
return $sql;
}
/**
* 处理SQL语句。
* Format sql.
*
* @param string $sql
* @access public
* @return string
*/
public function formatSQL(string $sql): string
{
// $sql = $this->formatAttr($sql);
return $sql;
}
/**
* 尝试从SQLite中执行查询语句,如果抛出异常,则从MySQL中执行查询语句。
* Query sql by SQLite, if throw exception, query sql by MySQL.
*
* @param string $sql
* @access public
* @return PDOStatement|false
*/
public function query(string $sql): PDOStatement|false
{
try
{
return $this->dbh->query($this->formatSQL($sql));
}
catch(PDOException $e)
{
return $this->mysql->query($sql);
}
}
/**
* 执行查询语句。
* Query sql without format.
*
* @param string $sql
* @access public
* @return PDOStatement|false
*/
public function rawQuery($sql): PDOStatement|false
{
$stmt = $this->dbh->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* 执行SQL语句,返回受影响的行数。
* Execute sql.
*
* @param string $sql
* @access public
* @return int|false
*/
public function exec(string $sql): int|false
{
return $this->dbh->exec($sql);
}
/**
* 开始事务。
* Begin transaction.
*
* @access public
* @return bool
*/
public function beginTransaction(): bool
{
return $this->dbh->beginTransaction();
}
/**
* 回滚事务。
* Roll back if transaction failed.
*
* @access public
* @return bool
*/
public function rollBack(): bool
{
return $this->dbh->rollBack();
}
/**
* 提交事务。
* Commit transaction.
*
* @access public
* @return bool
*/
public function commit(): bool
{
return $this->dbh->commit();
}
}
+7 -2
View File
@@ -91,17 +91,22 @@ class chart extends control
$type = $filter['type'];
$default = isset($filter['default']) ? $filter['default'] : '';
$saveAs = isset($filter['saveAs']) ? $filter['saveAs'] : '';
$saveAsClass = $type == 'select' ? '' : 'hidden'; // 只有是选择的时候,才展示显示为
$options = array();
if($type == 'select')
{
$fieldSetting = $fieldSettings[$field];
$options = $this->chart->getSysOptions(zget($fieldSetting, 'type', ''), zget($fieldSetting, 'object', ''), zget($fieldSetting, 'field', ''), $sql);
$options = $this->chart->getSysOptions(zget($fieldSetting, 'type', ''), zget($fieldSetting, 'object', ''), zget($fieldSetting, 'field', ''), $sql, zget($filter, 'saveAs', ''));
}
$filterHtml = array();
/* field html */
$filterHtml['field'] = html::select('field', $fieldPairs, $field, "class='form-control picker-select' onchange='initFilterForm(this, this.value)'");
$filterHtml['field'] = html::select('field', $fieldPairs, $field, "class='form-control picker-select' onchange='initFilterForm(this, this.value)'");
$filterHtml['saveAs'] = html::select('saveAs', array('' => '') + $fieldPairs, $saveAs, "class='form-control picker-select' onchange='changeSaveAs(this, this.value)'");
$filterHtml['saveAsClass'] = $saveAsClass;
/* default html */
$filterHtml['default'] = '';
+44 -9
View File
@@ -670,10 +670,14 @@ class chartModel extends model
* Get sys options.
*
* @param string $type
* @param string $object
* @param string $field
* @param string $sql
* @param string $saveAs
* @access public
* @return array
*/
public function getSysOptions($type, $object = '', $field = '', $sql = '')
public function getSysOptions($type, $object = '', $field = '', $sql = '', $saveAs = '')
{
$options = array('' => '');
switch($type)
@@ -707,20 +711,24 @@ class chartModel extends model
case 'object':
if($field)
{
$table = zget($this->config->objectTables, $object, '');
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
if($sql and $saveAs)
{
$options = $this->getOptionsFromSql($sql, $field, $saveAs);
}
else
{
$table = zget($this->config->objectTables, $object, '');
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
}
}
break;
case 'string':
case 'number':
if($field and $sql)
{
$cols = $this->dbh->query($sql)->fetchAll();
foreach($cols as $col)
{
$data = $col->$field;
$options[$data] = $data;
}
$keyField = $field;
$valueField = $saveAs ? $saveAs : $field;
$options = $this->getOptionsFromSql($sql, $keyField, $valueField);
}
break;
}
@@ -728,6 +736,33 @@ class chartModel extends model
return $options;
}
/**
* Get pairs from column by keyField and valueField.
*
* @param string $sql
* @param string $keyField
* @param string $valueField
* @access public
* @return array
*/
public function getOptionsFromSql($sql, $keyField, $valueField)
{
$options = array();
$cols = $this->dbh->query($sql)->fetchAll();
$sample = current($cols);
if(!isset($sample->$keyField) or !isset($sample->$valueField)) return $options;
foreach($cols as $col)
{
$key = $col->$keyField;
$value = $col->$valueField;
$options[$key] = $value;
}
return $options;
}
public function getFilterFormat($filters)
{
$filterFormat = array();
+1
View File
@@ -59,6 +59,7 @@ $lang->dataview->relatedField = 'Field';
$lang->dataview->multilingual = 'After switching the system language, the corresponding name will be displayed';
$lang->dataview->duplicateField = 'Duplicate field names exist: <strong>%s</strong>. You are advised to: (1) Modify the <strong>*</strong> query to a specific field. (2) Use <strong>as</strong> to alias the field.';
$lang->dataview->errorField = 'The current field %s is an invalid character. Please [as] it in English or English underscore format.';
$lang->dataview->queryFilterTip = 'Query filter is a way to implement dynamic query filtering by inserting variables into SQL. The result filter configured in the third step is to further filter the SQL query results.';
$lang->dataview->varFilter = new stdclass();
$lang->dataview->varFilter->varCode = 'Var Code';
+1
View File
@@ -59,6 +59,7 @@ $lang->dataview->relatedField = 'Field';
$lang->dataview->multilingual = 'After switching the system language, the corresponding name will be displayed';
$lang->dataview->duplicateField = 'Duplicate field names exist: <strong>%s</strong>. You are advised to: (1) Modify the <strong>*</strong> query to a specific field. (2) Use <strong>as</strong> to alias the field.';
$lang->dataview->errorField = 'The current field %s is an invalid character. Please [as] it in English or English underscore format.';
$lang->dataview->queryFilterTip = 'Query filter is a way to implement dynamic query filtering by inserting variables into SQL. The result filter configured in the third step is to further filter the SQL query results.';
$lang->dataview->varFilter = new stdclass();
$lang->dataview->varFilter->varCode = 'Var Code';
+1
View File
@@ -59,6 +59,7 @@ $lang->dataview->relatedField = 'Field';
$lang->dataview->multilingual = 'After switching the system language, the corresponding name will be displayed';
$lang->dataview->duplicateField = 'Duplicate field names exist: <strong>%s</strong>. You are advised to: (1) Modify the <strong>*</strong> query to a specific field. (2) Use <strong>as</strong> to alias the field.';
$lang->dataview->errorField = 'The current field %s is an invalid character. Please [as] it in English or English underscore format.';
$lang->dataview->queryFilterTip = 'Query filter is a way to implement dynamic query filtering by inserting variables into SQL. The result filter configured in the third step is to further filter the SQL query results.';
$lang->dataview->varFilter = new stdclass();
$lang->dataview->varFilter->varCode = 'Var Code';
+1
View File
@@ -59,6 +59,7 @@ $lang->dataview->relatedField = '对应字段';
$lang->dataview->multilingual = '切换系统语言项后,将显示对应名称';
$lang->dataview->duplicateField = '存在重复的字段名: <strong>%s</strong>。建议您:(1)修改 <strong>*</strong> 查询为具体的字段。(2)使用 <strong>as</strong> 为字段设置别名。';
$lang->dataview->errorField = '当前字段%s为非法字符,请[as]成英文或英文下划线的格式。';
$lang->dataview->queryFilterTip = '查询筛选器是通过在 SQL 中插入变量实现动态查询的筛选方式,第三步配置的结果筛选器是对SQL查询结果进行进一步筛选。';
$lang->dataview->varFilter = new stdclass();
$lang->dataview->varFilter->varCode = '变量代号';
+4 -4
View File
@@ -206,9 +206,9 @@ class dataviewModel extends model
* @access public
* @return array
*/
public function getColumns($sql)
public function getColumns($sql, $columns = null)
{
$columns = $this->dao->getColumns($sql);
if(empty($columns)) $columns = $this->dao->getColumns($sql);
$columnTypes = new stdclass();
foreach($columns as $column)
@@ -232,9 +232,9 @@ class dataviewModel extends model
* @access public
* @return bool
*/
public function checkUniColumn($sql, $repeat = false)
public function checkUniColumn($sql, $repeat = false, $columns = null)
{
$columns = $this->dao->getColumns($sql);
if(empty($columns)) $columns = $this->dao->getColumns($sql);
$isUnique = true;
$columnList = array();
+27 -2
View File
@@ -66,6 +66,30 @@ class fileModel extends model
return $files;
}
/**
* Delete files by object.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return bool
*/
public function deleteByObject($objectType, $objectID)
{
$files = $this->dao->select('*')->from(TABLE_FILE)
->where('objectType')->eq($objectType)
->andWhere('objectID')->in($objectID)
->andWhere('deleted')->eq('0')
->fetchAll('id');
foreach($files as $file)
{
$this->dao->update(TABLE_FILE)->set('deleted')->eq(1)->where('id')->eq($file->id)->exec();
}
return true;
}
/**
* Get info of a file.
*
@@ -264,10 +288,11 @@ class fileModel extends model
* get uploaded file from zui.uploader.
*
* @param string $htmlTagName
* @param string $name
* @access public
* @return array
*/
public function getUploadFile($htmlTagName = 'file')
public function getUploadFile($htmlTagName = 'file', $name = '')
{
if(!isset($_FILES[$htmlTagName]) || empty($_FILES[$htmlTagName]['name'])) return;
@@ -278,7 +303,7 @@ class fileModel extends model
extract($_FILES[$htmlTagName]);
if(!validater::checkFileName($name)) return array();
if($this->post->name) $name = $this->post->name;
if(empty($name) && $this->post->name) $name = $this->post->name;
$file = array();
$file['id'] = 0;
+3 -2
View File
@@ -263,16 +263,17 @@ class pivot extends control
* @param string $type
* @param string $object
* @param string $field
* @param string $saveAs
* @access public
* @return string
*/
public function ajaxGetSysOptions($type, $object = '', $field = '')
public function ajaxGetSysOptions($type, $object = '', $field = '', $saveAs = '')
{
$sql = isset($_POST['sql']) ? $_POST['sql'] : '';
$filters = isset($_POST['filters']) ? $_POST['filters'] : '';
$sql = $this->loadModel('chart')->parseSqlVars($sql, $filters);
$options = $this->pivot->getSysOptions($type, $object, $field, $sql);
$options = $this->pivot->getSysOptions($type, $object, $field, $sql, $saveAs);
return print(html::select('default[]', array('' => '') + $options, '', "class='form-control form-select picker-select' multiple"));
}
+2
View File
@@ -35,3 +35,5 @@
.pivot-design {padding-left: 24px; padding-right: 12px;}
.pivot-edit {padding-left: 12px; padding-right: 12px;}
.pivot-delete {padding-left: 12px; padding-right: 8px;}
#pivotGroups > li a {white-space: nowrap; overflow: hidden; }
+4 -3
View File
@@ -260,8 +260,9 @@ function initQueryControl(container, filter, object, field)
function initResultControl(container, filter, object, field)
{
var type = filter.type;
var value = filter.default;
var type = filter.type;
var value = filter.default;
var saveAs = 'saveAs' in filter ? filter.saveAs : '';
container.find('.default-block').addClass('hidden');
container.find('.default-block input[name^="default"]').val('');
@@ -307,7 +308,7 @@ function initResultControl(container, filter, object, field)
if(value !== '') pickerOptions.defaultValue = value;
var pivotParams = {sql: pivot.sql, filters: getQueryFilters(pivot)};
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field), pivotParams, function(resp)
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field + '&saveAs=' + saveAs), pivotParams, function(resp)
{
control.html($(resp).html());
control.picker(pickerOptions);
+1
View File
@@ -225,6 +225,7 @@ $lang->pivot->resultFilter = 'Result Filter';
$lang->pivot->queryFilter = 'Query Filter';
$lang->pivot->noName = 'Unnamed';
$lang->pivot->filterName = 'Name';
$lang->pivot->showAs = 'Show as';
$lang->pivot->default = 'Default';
$lang->pivot->unlimited = 'Unlimited';
$lang->pivot->colon = 'To';
+1
View File
@@ -225,6 +225,7 @@ $lang->pivot->resultFilter = 'Result Filter';
$lang->pivot->queryFilter = 'Query Filter';
$lang->pivot->noName = 'Unnamed';
$lang->pivot->filterName = 'Name';
$lang->pivot->showAs = 'Show as';
$lang->pivot->default = 'Default';
$lang->pivot->unlimited = 'Unlimited';
$lang->pivot->colon = 'To';
+1
View File
@@ -225,6 +225,7 @@ $lang->pivot->resultFilter = 'Result Filter';
$lang->pivot->queryFilter = 'Query Filter';
$lang->pivot->noName = 'Unnamed';
$lang->pivot->filterName = 'Name';
$lang->pivot->showAs = 'Show as';
$lang->pivot->default = 'Default';
$lang->pivot->unlimited = 'Unlimited';
$lang->pivot->colon = 'To';
+1
View File
@@ -213,6 +213,7 @@ $lang->pivot->resultFilter = 'Result Filter';
$lang->pivot->queryFilter = 'Query Filter';
$lang->pivot->noName = 'Unnamed';
$lang->pivot->filterName = 'Name';
$lang->pivot->showAs = 'Show as';
$lang->pivot->default = 'Default';
$lang->pivot->unlimited = 'Unlimited';
$lang->pivot->colon = 'To';
+1
View File
@@ -225,6 +225,7 @@ $lang->pivot->resultFilter = '结果筛选器';
$lang->pivot->queryFilter = '查询筛选器';
$lang->pivot->noName = '未命名';
$lang->pivot->filterName = '名称';
$lang->pivot->showAs = '显示为';
$lang->pivot->default = '默认值';
$lang->pivot->unlimited = '不限';
$lang->pivot->colon = '至';
+60 -14
View File
@@ -172,7 +172,7 @@ class pivotModel extends model
* @access public
* @return object|array
*/
public function processPivot($pivots, $isObject = true)
public function processPivot($pivots, $isObject = true, $processFieldSettings = true)
{
if($isObject) $pivots = array($pivots);
@@ -209,7 +209,7 @@ class pivotModel extends model
$pivots[$index]->used = $this->screen->checkIFChartInUse($pivot->id, 'pivot', $screenList);
}
if($isObject and $pivots[$index]->stage == 'published') $pivots[$index] = $this->processFieldSettings($pivots[$index]);
if($isObject and $processFieldSettings and $pivots[$index]->stage == 'published') $pivots[$index] = $this->processFieldSettings($pivots[$index]);
}
return $isObject ? reset($pivots) : $pivots;
@@ -2482,7 +2482,7 @@ class pivotModel extends model
* @access public
* @return array
*/
public function getSysOptions($type, $object = '', $field = '', $sql = '')
public function getSysOptions($type, $object = '', $field = '', $source = '', $saveAs = '')
{
$options = array('' => '');
switch($type)
@@ -2520,9 +2520,18 @@ class pivotModel extends model
case 'object':
if($field)
{
$table = zget($this->config->objectTables, $object, '');
if($table)
if(is_array($source))
{
$options = array();
foreach($source as $row) $options[$row->id] = $row->$field;
}
elseif($saveAs)
{
$options = $this->getOptionsFromSql($source, $field, $saveAs);
}
else
{
$table = zget($this->config->objectTables, $object, '');
$columns = $this->dbh->query("SHOW COLUMNS FROM $table")->fetchAll();
foreach($columns as $id => $column) $columns[$id] = (array)$column;
$fieldList = array_column($columns, 'Field');
@@ -2532,17 +2541,19 @@ class pivotModel extends model
}
break;
case 'string':
case 'number':
if($field)
{
$options = array();
if($sql)
if(is_string($source) and !empty($source))
{
$cols = $this->dbh->query($sql)->fetchAll();
foreach($cols as $col)
{
$data = $col->$field;
$options[$data] = $data;
}
$keyField = $field;
$valueField = $saveAs ? $saveAs : $field;
$options = $this->getOptionsFromSql($source, $keyField, $valueField);
}
else if(is_array($source))
{
foreach($source as $row) $options[$row->$field] = $row->$field;
}
}
break;
@@ -2550,6 +2561,33 @@ class pivotModel extends model
return $options;
}
/**
* Get pairs from column by keyField and valueField.
*
* @param string $sql
* @param string $keyField
* @param string $valueField
* @access public
* @return array
*/
public function getOptionsFromSql($sql, $keyField, $valueField)
{
$options = array();
$cols = $this->dbh->query($sql)->fetchAll();
$sample = current($cols);
if(!isset($sample->$keyField) or !isset($sample->$valueField)) return $options;
foreach($cols as $col)
{
$key = $col->$keyField;
$value = $col->$valueField;
$options[$key] = $value;
}
return $options;
}
/**
* Get tree of pivots and groups.
*
@@ -2903,7 +2941,7 @@ class pivotModel extends model
return $sql;
}
public function getFieldsOptions($fields, $sql)
public function getFieldsOptions($fieldSettings, $sql)
{
$options = array();
$tableObjects = array();
@@ -2936,7 +2974,15 @@ class pivotModel extends model
foreach($fieldSettings as $key => $fieldSetting)
{
$options[$key] = $this->getSysOptions($field['type'], $field['object'], $field['field'], $sql);
$type = $fieldSetting['type'];
$object = $fieldSetting['object'];
$field = $fieldSetting['field'];
$source = $sql;
if($type == 'object' and isset($tableRecords[$object])) $source = $tableRecords[$object];
if($type == 'string') $source = $sqlRecords;
$options[$key] = $this->getSysOptions($type, $object, $field, $source);
}
return $options;
+23 -1
View File
@@ -4,6 +4,26 @@ $config->screen->builtinChart = array(10018, 10019, 10020, 10021, 10022, 10211,
$config->screen->builtinPivot = array(1000, 1001, 1002);
$config->screen->phpChart = array(20002, 20004, 20007, 20010, 20011, 20012, 20013);
$config->screen->editCanvasConfig = new stdclass();
$config->screen->editCanvasConfig->width = 1300;
$config->screen->editCanvasConfig->height = 1080;
$config->screen->editCanvasConfig->filterShow = false;
$config->screen->editCanvasConfig->hueRotate = 0;
$config->screen->editCanvasConfig->saturate = 1;
$config->screen->editCanvasConfig->contrast = 1;
$config->screen->editCanvasConfig->brightness = 1;
$config->screen->editCanvasConfig->opacity = 1;
$config->screen->editCanvasConfig->rotateZ = 0;
$config->screen->editCanvasConfig->rotateX = 0;
$config->screen->editCanvasConfig->rotateY = 0;
$config->screen->editCanvasConfig->skewX = 0;
$config->screen->editCanvasConfig->skewY = 0;
$config->screen->editCanvasConfig->blendMode = 'normal';
$config->screen->editCanvasConfig->background = '#001028';
$config->screen->editCanvasConfig->selectColor = true;
$config->screen->editCanvasConfig->chartThemeColor = 'dark';
$config->screen->editCanvasConfig->previewScaleType = 'scrollY';
$config->screen->chartConfig = array();
$config->screen->chartConfig['cluBarX'] = '{"category" : "Bars", "categoryName" : "柱状图", "chartFrame" : "echarts", "chartKey" : "VBarCommon", "conKey" : "VCBarCommon", "image" : "bar_x.png", "key" : "BarCommon", "package" : "Charts", "title" : "簇状柱形图", "dataset" : {}}';
$config->screen->chartConfig['cluBarY'] = '{"category" : "Bars", "categoryName" : "柱状图", "chartFrame" : "echarts", "chartKey" : "VBarCrossrange", "conKey" : "VCBarCrossrange", "image" : "bar_y.png", "key" : "BarCrossrange", "package" : "Charts", "title" : "簇状条形图", "dataset" : {}}';
@@ -16,6 +36,7 @@ $config->screen->chartConfig['line'] = '{"category" : "Lines", "categoryN
$config->screen->chartConfig['table'] = '{"category" : "Tables", "categoryName" : "列表", "chartFrame" : "common", "chartKey" : "VTableMergeCell", "conKey" : "VCTableMergeCell", "image" : "table_scrollboard.png", "key" : "TableMergeCell", "package" : "Tables", "title" : "透视表", "dataset" : {}, "tableInfo": {}}';
$config->screen->chartConfig['card'] = '{"category" : "Texts", "categoryName" : "文本", "chartFrame" : "common", "chartKey" : "VTextCommon", "conKey" : "VCTextCommon", "image" : "text_static.png", "key" : "TextCommon", "package" : "Informations", "title" : "文字", "dataset" : {}}';
$config->screen->chartConfig['waterpolo'] = '{"category" : "Mores", "categoryName" : "更多", "chartFrame" : "common", "chartKey" : "VWaterPolo", "conKey" : "VCWaterPolo", "image" : "water_WaterPolo.png", "key" : "WaterPolo", "package" : "Charts", "title" : "水球图", "dataset" : {}}';
$config->screen->chartConfig['metric'] = '{"category" : "Metrics", "categoryName" : "度量项", "chartFrame" : "common", "chartKey" : "VMetrics", "conKey" : "VCMetrics", "image" : "bar_x.png", "key" : "Metrics", "package" : "Metrics", "title" : "度量项", "dataset" : {}}';
$config->screen->chartOption['cluBarX'] = '{"legend":{"show":true,"top":40,"textStyle":{"color":"#B9B8CE"},"left":"center"},"xAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"bottom","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":false,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"category"},"yAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"left","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":true,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"value"},"grid":{"show":false,"left":"10%","top":90,"right":"10%","bottom":"60"},"title":{"text":"","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"tooltip":{"show":true,"trigger":"axis","axisPointer":{"show":true,"type":"shadow"}},"dataset":{},"series":[{"type":"bar","barWidth":15,"label":{"show":true,"position":"top","color":"#fff","fontSize":12},"itemStyle":{"color":null,"borderRadius":2}}],"backgroundColor":"rgba(0,0,0,0)"}';
$config->screen->chartOption['cluBarY'] = '{"legend":{"show":true,"top":40,"textStyle":{"color":"#B9B8CE"},"left":"center"},"xAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"bottom","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":false,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"value"},"yAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"left","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":true,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"category"},"grid":{"show":false,"left":"10%","top":70,"right":"10%","bottom":"60"},"title":{"text":"","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"tooltip":{"show":true,"trigger":"axis","axisPointer":{"show":true,"type":"shadow"}},"dataset":{},"series":[{"type":"bar","barWidth":null,"label":{"show":true,"position":"right","color":"#fff","fontSize":12},"itemStyle":{"color":null,"borderRadius":0}}],"backgroundColor":"rgba(0,0,0,0)"}';
@@ -24,8 +45,9 @@ $config->screen->chartOption['stackedBarY'] = '{"legend":{"show":true,"top":40,"
$config->screen->chartOption['pie'] = '{"legend":{"show":true,"top":30,"textStyle":{"color":"#B9B8CE"},"left":"center"},"title":{"text":"","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"type":"nomal","tooltip":{"show":true,"trigger":"item"},"grid":{"top":70},"dataset":{},"series":[{"type":"pie","radius":["40%","65%"],"center":["50%","60%"],"label":{"show":true,"formatter":"{b} {d}%","fontSize":12}}],"backgroundColor":"rgba(0,0,0,0)"}';
$config->screen->chartOption['radar'] = '{"legend":{"show":true,"top":40,"textStyle":{"color":"#B9B8CE"},"data":[],"left":"center"},"title":{"text":"\u6298\u7ebf\u56fe","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"tooltip":{"show":true},"grid":{"top":90},"dataset":{},"radar":{"shape":"polygon","radius":["0%","60%"],"center":["50%","55%"],"splitArea":{"show":true},"splitLine":{"show":true},"axisName":{"show":true,"color":"#eee","fontSize":12},"axisLine":{"show":true},"axisTick":{"show":true},"indicator":[]},"series":[{"name":"radar","type":"radar","areaStyle":{"opacity":0.1},"data":[]}],"backgroundColor":"rgba(0,0,0,0)"}';
$config->screen->chartOption['line'] = '{"legend":{"show":true,"top":40,"textStyle":{"color":"#B9B8CE"},"left":"center"},"xAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"bottom","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":false,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"category"},"yAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"left","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":true,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"value"},"grid":{"show":false,"left":"10%","top":90,"right":"10%","bottom":"60"},"title":{"text":"","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"tooltip":{"show":true,"trigger":"axis","axisPointer":{"type":"line"}},"dataset":{},"series":[{"type":"line","label":{"show":true,"position":"top","color":"#fff","fontSize":12},"symbolSize":5,"itemStyle":{"color":null,"borderRadius":0},"lineStyle":{"type":"solid","width":3,"color":null}},{"type":"line","label":{"show":true,"position":"top","color":"#fff","fontSize":12},"symbolSize":5,"itemStyle":{"color":null,"borderRadius":0},"lineStyle":{"type":"solid","width":3,"color":null}}],"backgroundColor":"rgba(0,0,0,0)"}';
$config->screen->chartOption['waterpolo'] = '{"dataset":{},"series":[{"type":"liquidFill","shape":"circle","radius":"90%","data":[0],"center":["50%","50%"],"color":[{"type":"linear","x":0,"y":0,"x2":0,"y2":1,"colorStops":[{"offset":0,"color":"#446bf5"},{"offset":1,"color":"#2ca3e2"}],"globalCoord":false}],"backgroundStyle":{"borderWidth":1,"color":"rgba(51,66,127,0.7)"},"label":{"normal":{"textStyle":{"fontSize":50,"color":"#fff"}}},"outline":{"show":false,"borderDistance":10,"itemStyle":{"borderWidth":2,"borderColor":"#112165"}}}]}';
$config->screen->chartOption['table'] = '{}';
$config->screen->chartOption['waterpolo'] = '{}';
$config->screen->chartOption['metric'] = '{"legend":{"show":true,"top":40,"textStyle":{"color":"#B9B8CE"},"left":"center"},"xAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"bottom","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":false,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"category"},"yAxis":{"show":true,"name":"","nameGap":15,"nameTextStyle":{"color":"#B9B8CE","fontSize":12},"inverse":false,"axisLabel":{"show":true,"fontSize":12,"color":"#B9B8CE","rotate":0},"position":"left","axisLine":{"show":true,"lineStyle":{"color":"#B9B8CE","width":1},"onZero":true},"axisTick":{"show":true,"length":5},"splitLine":{"show":true,"lineStyle":{"color":"#484753","width":1,"type":"solid"}},"type":"value"},"grid":{"show":false,"left":"10%","top":90,"right":"10%","bottom":"60"},"title":{"text":"","show":true,"textStyle":{"color":"#BFBFBF","fontSize":18},"subtextStyle":{"color":"#A2A2A2","fontSize":14},"top":10,"x":"center"},"tooltip":{"show":true,"trigger":"axis","axisPointer":{"show":true,"type":"shadow"}},"dataset":{},"series":[{"type":"bar","barWidth":15,"label":{"show":true,"position":"top","color":"#fff","fontSize":12},"itemStyle":{"color":null,"borderRadius":2}}],"backgroundColor":"#0B1727FF"}';
$config->screen->fieldConfig = new stdclass();
$config->screen->fieldConfig->bug = new stdclass();
+64 -13
View File
@@ -23,8 +23,12 @@ class screen extends control
$dimensionID = $this->loadModel('dimension')->setSwitcherMenu($dimensionID);
$this->checkShowGuide();
$screens = $this->screen->getList($dimensionID);
$screens = $this->screen->getThumbnail($screens);
$screens = $this->screen->removeScheme($screens);
$this->view->title = $this->lang->screen->common;
$this->view->screens = $this->screen->getList($dimensionID);
$this->view->screens = $screens;
$this->view->dimension = $dimensionID;
$this->display();
}
@@ -84,7 +88,7 @@ class screen extends control
return;
}
$screen = $this->screen->getByID($screenID, $year, $month, $dept, $account);
$screen = $this->screen->getByID($screenID, $year, $month, $dept, $account, false);
$this->view->title = $screen->name;
$this->view->screen = $screen;
@@ -106,6 +110,12 @@ class screen extends control
}
}
public function ajaxGetScreenScheme($screenID, $year = 0, $month = 0, $dept = 0, $account = '')
{
$screen = $this->screen->getByID($screenID, $year, $month, $dept, $account);
echo(json_encode($screen));
}
/**
* Ajax get chart.
*
@@ -118,11 +128,19 @@ class screen extends control
{
$chartID = $this->post->sourceID;
$type = $this->post->type;
$queryType = isset($_POST['queryType']) ? $this->post->queryType : 'filter';
$type = ($type == 'Tables' or $type == 'pivot') ? 'pivot' : 'chart';
if($type == 'Filters')
{
$filterComponent = $this->screen->genFilterComponent($chartID);
return print(json_encode($filterComponent));
}
$table = $type == 'chart' ? TABLE_CHART : TABLE_PIVOT;
$queryType = isset($_POST['queryType']) ? $this->post->queryType : 'filter';
$component = isset($_POST['component']) ? json_decode($this->post->component) : null;
$type = $this->screen->getChartType($type);
$table = $this->config->objectTables[$type];
$chart = $this->dao->select('*')->from($table)->where('id')->eq($chartID)->fetch();
$filterFormat = '';
@@ -134,6 +152,8 @@ class screen extends control
foreach($filters as $index => $filter)
{
if($filterParams[$index]['default'] === null) continue;
$default = isset($filterParams[$index]['default']) ? $filterParams[$index]['default'] : null;
$filterType = $filter['type'];
if($filterType == 'date' or $filterType == 'datetime')
@@ -165,19 +185,50 @@ class screen extends control
$mergeFilters[] = $filter;
}
if($table == TABLE_PIVOT)
if($type != 'metric')
{
list($sql, $filterFormat) = $this->loadModel($type)->getFilterFormat($chart->sql, $mergeFilters);
$chart->sql = $sql;
}
else
{
$filterFormat = $this->loadModel($type)->getFilterFormat($mergeFilters);
if($table == TABLE_PIVOT)
{
list($sql, $filterFormat) = $this->loadModel($type)->getFilterFormat($chart->sql, $mergeFilters);
$chart->sql = $sql;
}
else
{
$filterFormat = $this->loadModel($type)->getFilterFormat($mergeFilters);
}
}
}
$chartData = $this->screen->genComponentData($chart, $type, null, $filterFormat);
if($type == 'metric')
{
$metric = $this->loadModel('metric')->getByID($chartID);
$chartData = $this->screen->genMetricComponent($metric, $component, (array)$filterParams);
}
else
{
$chartData = $this->screen->genComponentData($chart, $type, $component, $filterFormat);
}
print(json_encode($chartData));
}
}
/**
* 获取度量数据。
* Ajax get metric data.
*
* @access public
* @return void
*/
public function ajaxGetMetricData()
{
$metricID = $this->post->metricID;
$metric = $this->loadModel('metric')->getByID($metricID);
$result = $this->metric->getResultByCode($metric->code, $_POST, 'cron');
$metricData = new stdclass();
$metricData->header = $this->metric->getViewTableHeader($metric);
$metricData->data = $this->metric->getViewTableData($metric, $result);
echo(json_encode($metricData));
}
}
+2 -1
View File
@@ -26,6 +26,7 @@ self["MonacoEnvironment"] = (function(paths) {
});
location.hash = '#/chart/preview/' + screen.id;
window.chartData = screen.chartData;
window.location.replace(window.location.href.toString().replace(window.location.hash, '')+'#/chart/preview/' + screen.id)
window.fetchChartApi = createLink('screen', 'ajaxGetChart');
window.fetchMetricDataApi = createLink('screen', 'ajaxGetMetricData');
window.fetchScreenSchemeApi = createLink('screen', 'ajaxGetScreenScheme', 'screenID=' + screen.id + '&year=' + year + '&month=' + month + '&dept=' + dept + '&account=' + account);
+4
View File
@@ -9,3 +9,7 @@ $lang->screen->allUsers = 'All users';
$lang->screen->noData = 'No Data';
$lang->screen->noDesc = 'No Desc';
$lang->screen->bizGuide = 'For more Organization-wide Overview Reports please contact us';
$lang->screen->globalFilter = 'Global Filter';
$lang->screen->belong = '';
$lang->screen->dateRange = 'Date';
+4
View File
@@ -9,3 +9,7 @@ $lang->screen->allUsers = 'All users';
$lang->screen->noData = 'No Data';
$lang->screen->noDesc = 'No Desc';
$lang->screen->bizGuide = 'For more Organization-wide Overview Reports please contact us';
$lang->screen->globalFilter = 'Global Filter';
$lang->screen->belong = '';
$lang->screen->dateRange = 'Date';
+4
View File
@@ -9,3 +9,7 @@ $lang->screen->allUsers = 'All users';
$lang->screen->noData = 'No Data';
$lang->screen->noDesc = 'No Desc';
$lang->screen->bizGuide = 'For more Organization-wide Overview Reports please contact us';
$lang->screen->globalFilter = 'Global Filter';
$lang->screen->belong = '';
$lang->screen->dateRange = 'Date';
+4
View File
@@ -9,3 +9,7 @@ $lang->screen->allUsers = '所有用户';
$lang->screen->noData = '暂时没有数据';
$lang->screen->noDesc = '暂无描述';
$lang->screen->bizGuide = '更多大屏请联系我们';
$lang->screen->globalFilter = '全局筛选器';
$lang->screen->belong = '所属';
$lang->screen->dateRange = '日期范围';
+742 -104
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -2,6 +2,7 @@
<script type="module" crossorigin src="<?php echo $webRoot;?>static/js/index.js"></script>
<?php js::set('screen', $screen);?>
<?php js::set('year', $year);?>
<?php js::set('month', $month);?>
<?php js::set('dept', $dept);?>
<?php js::set('account', $account);?>
<div id="appProvider" style="display: none;"></div>
+4
View File
@@ -983,4 +983,8 @@ $config->upgrade->recoveryActions->testcase->review['position'] = 'browseandview
$config->upgrade->missedFlowFieldVersions = array('max4_4_alpha1', 'max4_4_beta1', 'max4_4', 'max4_5', 'biz8_4_alpha1', 'biz8_4_beta1', 'biz8_4', 'biz8_5');
$config->upgrade->dbFieldLengths['int'] = array('tinyint' => 4, 'smallint' => 6, 'mediumint' => 9, 'int' => 11, 'integer' => 11, 'bigint' => 20);
$config->upgrade->dbFieldLengths['unsigned'] = array('tinyint' => 3, 'smallint' => 5, 'mediumint' => 8, 'int' => 10, 'integer' => 10, 'bigint' => 20);
$config->upgrade->dbFieldLengths['text'] = array('tinytext' => 8, 'text' => 16, 'mediumtext' => 24, 'longtext' => 32);
include dirname(__FILE__) . DS . 'config' . DS . 'upgradeflow.php';
+1
View File
@@ -92,6 +92,7 @@ $config->upgrade->execFlow['18_6'] = array('functions' => 'removeProductL
$config->upgrade->execFlow['18_7'] = array('functions' => 'processHistoryDataForMetric,metric-updateMetricDate');
$config->upgrade->execFlow['18_8'] = array('functions' => 'upgradeTesttaskMembers,deleteGeneralReportBlock,stopOldCron');
$config->upgrade->execFlow['18_9'] = array('functions' => 'addDefaultTraincoursePriv,renameBIModule,migrateXuanClientSettings');
$config->upgrade->execFlow['18_10'] = array('functions' => 'updateMetricDateType');
if(!empty($config->isINT))
{
+15
View File
@@ -9539,4 +9539,19 @@ class upgradeModel extends model
->andWhere('section')->eq('settings')
->exec();
}
/**
* Update metric datetype.
*
* @access public
* @return void
*/
public function updateMetricDateType()
{
$this->loadModel('metric');
foreach($this->config->metric->dateType as $code => $dateType)
{
$this->dao->update(TABLE_METRIC)->set('dateType')->eq($dateType)->where('code')->eq($code)->exec();
}
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More