Merge branch dev/task-149051 of zentao/zentaopms (#11388)

This commit is contained in:
刘刚
2025-09-10 11:10:31 +08:00
committed by Gitfox
18 changed files with 530 additions and 21 deletions
+3
View File
@@ -809,7 +809,10 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
`template` varchar(30) NOT NULL DEFAULT '',
`templateType` varchar(30) NOT NULL DEFAULT '',
`templateDesc` text NULL,
`objects` text NULL,
`chapterType` varchar(30) NOT NULL DEFAULT '',
`cycle` char(10) NOT NULL DEFAULT '',
`cycleConfig` text NULL,
`module` varchar(30) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT '',
`keywords` varchar(255) NOT NULL DEFAULT '',
+1
View File
@@ -92,6 +92,7 @@ $config->action->needGetRelateField = ',branch,story,epic,requirement,prod
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,instance,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,pivot,scene,boardspace,auditplan,auditresult,productline,chapter,doc,';
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn';
$config->action->ignoreActions4Dynamic = 'disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan,editmr,removemr,syncdoingbyticket,syncdoingbystory,syncdoingbyuserstory,syncdoingbyepic,syncdoingbytask,syncdoingbybug,syncdoingbytodo,syncdoingbydemand';
if(in_array($config->edition, array('open', 'biz'))) $config->action->ignoreObjectType4Dynamic .= ',reporttemplate';
$config->action->latestDateList = array('today', 'yesterday', 'thisWeek', 'lastWeek', 'thisMonth');
+1 -1
View File
@@ -127,7 +127,7 @@ class actionModel extends model
$this->file->updateObjectID($uid, $objectID, $objectType);
$this->loadModel('message')->send(strtolower($objectType), $objectID, $actionType, $actionID, $actor, $extra);
if(empty($this->app->installing) && empty($this->app->upgrading)) $this->loadModel('message')->send(strtolower($objectType), $objectID, $actionType, $actionID, $actor, $extra);
$this->saveIndex($objectType, $objectID, $actionType);
+1
View File
@@ -309,6 +309,7 @@ class install extends control
$mode = form::data()->get()->mode;
$this->loadModel('setting')->setItem('system.common.global.mode', $mode);
$this->loadModel('custom')->disableFeaturesByMode($mode);
$this->loadModel('weekly')->addBuiltinWeeklyTemplate();
return $this->send(array('result' => 'success', 'load' => inlink('step5')));
}
+8
View File
@@ -0,0 +1,8 @@
<?php
$config->weekly->charts['weekly_term'] = array('date' => '$thisWeek');
$config->weekly->charts['weekly_staff'] = array('date' => '$thisWeek');
$config->weekly->charts['project_progress_summary'] = array();
$config->weekly->charts['task_basicStatistic_finished'] = array('date' => '$thisWeek');
$config->weekly->charts['task_basicStatistic_unfinished'] = array('date' => '$thisWeek');
$config->weekly->charts['task_basicStatistic_workplan'] = array('date' => '$nextWeek');
$config->weekly->charts['project_basicStatistic_workload'] = array();
+13 -5
View File
@@ -22,10 +22,11 @@ $lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->projectTemplate = "{$lang->projectCommon} Weekly Report Template";
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the ' . $lang->projectCommon;
@@ -38,10 +39,15 @@ $lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->builtinDesc = "The system's built-in {$lang->projectCommon} weekly report template automatically generates this week's report under the {$lang->projectCommon} every Monday.";
$lang->weekly->exportWeeklyReport = 'Export Weekly Report';
$lang->weekly->builtInScopes = array();
$lang->weekly->builtInScopes['rnd'] = array();
$lang->weekly->builtInScopes['rnd']['project'] = 'Project';
$lang->weekly->reportHelpNotice = <<<EOD
<h2>PV Planned Value</h2>
Calculation method:
@@ -143,3 +149,5 @@ Calculation method: SV(%) = -1 * (1 - (EV / PV))%
<h2>CV(%) Schedule Variance</h2>
Calculation method: CV(%) = -1 * (1 - (EV / AC))%
EOD;
$lang->weekly->builtinRawContent = '{"type":"page","meta":{"id":"DzzHUxGuzi","title":"Project Weekly Report Template","createDate":1757395000965,"tags":[]},"blocks":{"type":"block","id":"cJZg7QCPpE","flavour":"affine:page","version":2,"props":{"title":{"$blocksuite:internal:text$":true,"delta":[{"insert":"Project Weekly Report Template"}]}},"children":[{"type":"block","id":"aS-yFwCosD","flavour":"affine:note","version":1,"props":{"xywh":"[0,0,498,92]","background":"--affine-note-background-white","index":"a0","lockedBySelf":false,"hidden":false,"displayMode":"both","edgeless":{"style":{"borderRadius":8,"borderSize":4,"borderStyle":"none","shadowType":"--affine-note-shadow-box"}}},"children":[{"type":"block","id":"YCy8XkfbbP","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[{"insert":" ","attributes":{"holder":{"id":"tsoxyETETF","name":"weekly_term","text":"Report Term","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_term","blockID":2746,"hint":"Filter: “Date Range”BetweenThis Week","text":"Report Term"}}}},{"insert":" weekly report: "},{"insert":" ","attributes":{"holder":{"id":"q1YcO2kmC7","name":"property_name","text":"Name","hint":"Name"}}},{"insert":" is managed by the project manager "},{"insert":" ","attributes":{"holder":{"id":"eefTgQguvL","name":"property_PM","text":"Manager","hint":"Manager"}}},{"insert":", the number of people involved is "},{"insert":" ","attributes":{"holder":{"id":"jwupyH0HTa","name":"weekly_staff","text":"Staff Number","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_staff","blockID":2747,"hint":"Filter: “Date Range”BetweenThis Week","text":"Staff Number"}}}},{"insert":"."}]},"collapsed":false},"children":[]},{"type":"block","id":"cL0cyfMcnI","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_progress_summary&blockID=__TML_ZENTAOCHART__{project_progress_summary}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Progress Summary"}},"children":[]},{"type":"block","id":"FqBsfENZPf","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_finished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_finished}","clearBeforeLoad":false,"isTemplate":true,"title":"Finished Tasks"}},"children":[]},{"type":"block","id":"egherwGMIV","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_unfinished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_unfinished}","clearBeforeLoad":false,"isTemplate":true,"title":"Unfinished Tasks"}},"children":[]},{"type":"block","id":"xfmvHk6o3o","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_workplan&blockID=__TML_ZENTAOCHART__{task_basicStatistic_workplan}","clearBeforeLoad":false,"isTemplate":true,"title":"Work Plan"}},"children":[]},{"type":"block","id":"ZZ4Jsuq4Bq","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_basicStatistic_workload&blockID=__TML_ZENTAOCHART__{project_basicStatistic_workload}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Plan Workload Statistic"}},"children":[]},{"type":"block","id":"BPy4La92az","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[]},"collapsed":false},"children":[]}]}]}}';
+13 -5
View File
@@ -22,10 +22,11 @@ $lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->projectTemplate = "{$lang->projectCommon} Weekly Report Template";
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the ' . $lang->projectCommon;
@@ -38,10 +39,15 @@ $lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->builtinDesc = "The system's built-in {$lang->projectCommon} weekly report template automatically generates this week's report under the {$lang->projectCommon} every Monday.";
$lang->weekly->exportWeeklyReport = 'Export Weekly Report';
$lang->weekly->builtInScopes = array();
$lang->weekly->builtInScopes['rnd'] = array();
$lang->weekly->builtInScopes['rnd']['project'] = 'Project';
$lang->weekly->reportHelpNotice = <<<EOD
<h2>PV Planned Value</h2>
Calculation method:
@@ -143,3 +149,5 @@ Calculation method: SV(%) = -1 * (1 - (EV / PV))%
<h2>CV(%) Schedule Variance</h2>
Calculation method: CV(%) = -1 * (1 - (EV / AC))%
EOD;
$lang->weekly->builtinRawContent = '{"type":"page","meta":{"id":"DzzHUxGuzi","title":"Project Weekly Report Template","createDate":1757395000965,"tags":[]},"blocks":{"type":"block","id":"cJZg7QCPpE","flavour":"affine:page","version":2,"props":{"title":{"$blocksuite:internal:text$":true,"delta":[{"insert":"Project Weekly Report Template"}]}},"children":[{"type":"block","id":"aS-yFwCosD","flavour":"affine:note","version":1,"props":{"xywh":"[0,0,498,92]","background":"--affine-note-background-white","index":"a0","lockedBySelf":false,"hidden":false,"displayMode":"both","edgeless":{"style":{"borderRadius":8,"borderSize":4,"borderStyle":"none","shadowType":"--affine-note-shadow-box"}}},"children":[{"type":"block","id":"YCy8XkfbbP","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[{"insert":" ","attributes":{"holder":{"id":"tsoxyETETF","name":"weekly_term","text":"Report Term","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_term","blockID":2746,"hint":"Filter: “Date Range”BetweenThis Week","text":"Report Term"}}}},{"insert":" weekly report: "},{"insert":" ","attributes":{"holder":{"id":"q1YcO2kmC7","name":"property_name","text":"Name","hint":"Name"}}},{"insert":" is managed by the project manager "},{"insert":" ","attributes":{"holder":{"id":"eefTgQguvL","name":"property_PM","text":"Manager","hint":"Manager"}}},{"insert":", the number of people involved is "},{"insert":" ","attributes":{"holder":{"id":"jwupyH0HTa","name":"weekly_staff","text":"Staff Number","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_staff","blockID":2747,"hint":"Filter: “Date Range”BetweenThis Week","text":"Staff Number"}}}},{"insert":"."}]},"collapsed":false},"children":[]},{"type":"block","id":"cL0cyfMcnI","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_progress_summary&blockID=__TML_ZENTAOCHART__{project_progress_summary}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Progress Summary"}},"children":[]},{"type":"block","id":"FqBsfENZPf","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_finished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_finished}","clearBeforeLoad":false,"isTemplate":true,"title":"Finished Tasks"}},"children":[]},{"type":"block","id":"egherwGMIV","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_unfinished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_unfinished}","clearBeforeLoad":false,"isTemplate":true,"title":"Unfinished Tasks"}},"children":[]},{"type":"block","id":"xfmvHk6o3o","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_workplan&blockID=__TML_ZENTAOCHART__{task_basicStatistic_workplan}","clearBeforeLoad":false,"isTemplate":true,"title":"Work Plan"}},"children":[]},{"type":"block","id":"ZZ4Jsuq4Bq","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_basicStatistic_workload&blockID=__TML_ZENTAOCHART__{project_basicStatistic_workload}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Plan Workload Statistic"}},"children":[]},{"type":"block","id":"BPy4La92az","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[]},"collapsed":false},"children":[]}]}]}}';
+13 -5
View File
@@ -22,10 +22,11 @@ $lang->weekly->postponed = 'Work unfinished this week';
$lang->weekly->nextWeek = 'Work planned for next week';
$lang->weekly->workloadByType = 'Workload Summary';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->term = 'Reporting Cycle';
$lang->weekly->project = $lang->projectCommon . ' Name';
$lang->weekly->master = 'Project Manager ';
$lang->weekly->staff = 'Weekly Effort';
$lang->weekly->projectTemplate = "{$lang->projectCommon} Weekly Report Template";
$lang->weekly->weekDesc = 'Week % s (% s ~% s)';
$lang->weekly->progress = 'Progress of the ' . $lang->projectCommon;
@@ -38,10 +39,15 @@ $lang->weekly->ac = 'Actual Cost(AC)';
$lang->weekly->sv = 'Schedule Variance(SV%)';
$lang->weekly->cv = 'Cost Variance(CV%)';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->totalCount = 'Total : %u tasks';
$lang->weekly->builtinDesc = "The system's built-in {$lang->projectCommon} weekly report template automatically generates this week's report under the {$lang->projectCommon} every Monday.";
$lang->weekly->exportWeeklyReport = 'Export Weekly Report';
$lang->weekly->builtInScopes = array();
$lang->weekly->builtInScopes['rnd'] = array();
$lang->weekly->builtInScopes['rnd']['project'] = 'Project';
$lang->weekly->reportHelpNotice = <<<EOD
<h2>PV Planned Value</h2>
Calculation method:
@@ -143,3 +149,5 @@ Calculation method: SV(%) = -1 * (1 - (EV / PV))%
<h2>CV(%) Schedule Variance</h2>
Calculation method: CV(%) = -1 * (1 - (EV / AC))%
EOD;
$lang->weekly->builtinRawContent = '{"type":"page","meta":{"id":"DzzHUxGuzi","title":"Project Weekly Report Template","createDate":1757395000965,"tags":[]},"blocks":{"type":"block","id":"cJZg7QCPpE","flavour":"affine:page","version":2,"props":{"title":{"$blocksuite:internal:text$":true,"delta":[{"insert":"Project Weekly Report Template"}]}},"children":[{"type":"block","id":"aS-yFwCosD","flavour":"affine:note","version":1,"props":{"xywh":"[0,0,498,92]","background":"--affine-note-background-white","index":"a0","lockedBySelf":false,"hidden":false,"displayMode":"both","edgeless":{"style":{"borderRadius":8,"borderSize":4,"borderStyle":"none","shadowType":"--affine-note-shadow-box"}}},"children":[{"type":"block","id":"YCy8XkfbbP","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[{"insert":" ","attributes":{"holder":{"id":"tsoxyETETF","name":"weekly_term","text":"Report Term","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_term","blockID":2746,"hint":"Filter: “Date Range”BetweenThis Week","text":"Report Term"}}}},{"insert":" weekly report: "},{"insert":" ","attributes":{"holder":{"id":"q1YcO2kmC7","name":"property_name","text":"Name","hint":"Name"}}},{"insert":" is managed by the project manager "},{"insert":" ","attributes":{"holder":{"id":"eefTgQguvL","name":"property_PM","text":"Manager","hint":"Manager"}}},{"insert":", the number of people involved is "},{"insert":" ","attributes":{"holder":{"id":"jwupyH0HTa","name":"weekly_staff","text":"Staff Number","hint":"Filter: “Date Range”BetweenThis Week","data":{"type":"weekly_staff","blockID":2747,"hint":"Filter: “Date Range”BetweenThis Week","text":"Staff Number"}}}},{"insert":"."}]},"collapsed":false},"children":[]},{"type":"block","id":"cL0cyfMcnI","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_progress_summary&blockID=__TML_ZENTAOCHART__{project_progress_summary}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Progress Summary"}},"children":[]},{"type":"block","id":"FqBsfENZPf","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_finished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_finished}","clearBeforeLoad":false,"isTemplate":true,"title":"Finished Tasks"}},"children":[]},{"type":"block","id":"egherwGMIV","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_unfinished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_unfinished}","clearBeforeLoad":false,"isTemplate":true,"title":"Unfinished Tasks"}},"children":[]},{"type":"block","id":"xfmvHk6o3o","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_workplan&blockID=__TML_ZENTAOCHART__{task_basicStatistic_workplan}","clearBeforeLoad":false,"isTemplate":true,"title":"Work Plan"}},"children":[]},{"type":"block","id":"ZZ4Jsuq4Bq","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_basicStatistic_workload&blockID=__TML_ZENTAOCHART__{project_basicStatistic_workload}","clearBeforeLoad":false,"isTemplate":true,"title":"Project Plan Workload Statistic"}},"children":[]},{"type":"block","id":"BPy4La92az","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[]},"collapsed":false},"children":[]}]}]}}';
+13 -5
View File
@@ -22,10 +22,11 @@ $lang->weekly->postponed = '本周未完成工作';
$lang->weekly->nextWeek = '下周工作计划';
$lang->weekly->workloadByType = '工作量统计';
$lang->weekly->term = '报告周期';
$lang->weekly->project = $lang->projectCommon . '名称';
$lang->weekly->master = '项目经理 ';
$lang->weekly->staff = '本周投入人数';
$lang->weekly->term = '报告周期';
$lang->weekly->project = $lang->projectCommon . '名称';
$lang->weekly->master = '项目经理 ';
$lang->weekly->staff = '本周投入人数';
$lang->weekly->projectTemplate = "{$lang->projectCommon}周报模板";
$lang->weekly->weekDesc = '第 %s 周( %s ~ %s)';
$lang->weekly->progress = $lang->projectCommon . '当前进展状况';
@@ -38,10 +39,15 @@ $lang->weekly->ac = '实际花费的成本(AC)';
$lang->weekly->sv = '进度偏差率(SV%)';
$lang->weekly->cv = '成本偏差率(CV%)';
$lang->weekly->totalCount = '总计 : %u 个任务';
$lang->weekly->totalCount = '总计 : %u 个任务';
$lang->weekly->builtinDesc = "系统内置的{$lang->projectCommon}周报模板,每周一在{$lang->projectCommon}下自动生成本周周报。";
$lang->weekly->exportWeeklyReport = '导出周报';
$lang->weekly->builtInScopes = array();
$lang->weekly->builtInScopes['rnd'] = array();
$lang->weekly->builtInScopes['rnd']['project'] = '项目';
$lang->weekly->reportHelpNotice = <<<EOD
<h2>PV 计划完成的工作</h2>
计算方式:
@@ -144,3 +150,5 @@ $lang->weekly->blockHelpNotice = <<<EOD
<h2>CV(%) 成本偏差率</h2>
计算方式:CV(%) = -1 * (1 - (EV / AC))%
EOD;
$lang->weekly->builtinRawContent = '{"type":"page","meta":{"id":"pGFGrn8mbr","title":"项目周报模板","createDate":1757379096204,"tags":[]},"blocks":{"type":"block","id":"Z3C1batqB7","flavour":"affine:page","version":2,"props":{"title":{"$blocksuite:internal:text$":true,"delta":[{"insert":"项目周报模板"}]}},"children":[{"type":"block","id":"kDFfXsGBPr","flavour":"affine:note","version":1,"props":{"xywh":"[0,0,498,92]","background":"--affine-note-background-white","index":"a0","lockedBySelf":false,"hidden":false,"displayMode":"both","edgeless":{"style":{"borderRadius":8,"borderSize":4,"borderStyle":"none","shadowType":"--affine-note-shadow-box"}}},"children":[{"type":"block","id":"A8QUW_uBSE","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[{"insert":" ","attributes":{"holder":{"id":"yqEBqqGHil","name":"weekly_term","text":"报告周期","hint":"筛选条件:“date”介于本周","data":{"type":"weekly_term","blockID":2737,"hint":"筛选条件:“date”介于本周","text":"报告周期"}}}},{"insert":"周报:"},{"insert":" ","attributes":{"holder":{"id":"PcqpwqBES3","name":"property_name","text":"项目名称","hint":"项目名称"}}},{"insert":"项目由项目经理"},{"insert":" ","attributes":{"holder":{"id":"p7Gw9A-ktu","name":"property_PM","text":"负责人","hint":"负责人"}}},{"insert":"负责,投入人数为"},{"insert":" ","attributes":{"holder":{"id":"uZ3j7QvSxb","name":"weekly_staff","text":"投入人数","hint":"筛选条件:“date”介于本周","data":{"type":"weekly_staff","blockID":2738,"hint":"筛选条件:“date”介于本周","text":"投入人数"}}}},{"insert":"。"}]},"collapsed":false},"children":[]},{"type":"block","id":"V5pHY6-x0A","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_progress_summary&blockID=__TML_ZENTAOCHART__{project_progress_summary}","clearBeforeLoad":false,"isTemplate":true,"title":"项目进展状况"}},"children":[]},{"type":"block","id":"cbuO57uG59","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_finished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_finished}","clearBeforeLoad":false,"isTemplate":true,"title":"已完成任务情况"}},"children":[]},{"type":"block","id":"r3Mi7MQ4Jq","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_unfinished&blockID=__TML_ZENTAOCHART__{task_basicStatistic_unfinished}","clearBeforeLoad":false,"isTemplate":true,"title":"未完成任务情况"}},"children":[]},{"type":"block","id":"jrqVmVb0Ze","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=task_basicStatistic_workplan&blockID=__TML_ZENTAOCHART__{task_basicStatistic_workplan}","clearBeforeLoad":false,"isTemplate":true,"title":"工作计划"}},"children":[]},{"type":"block","id":"RhBxuJ6tj-","flavour":"affine:embed-zui-custom","version":1,"props":{"index":"a0","xywh":"[0,0,0,0]","lockedBySelf":false,"rotate":0,"content":{"fetcher":"/index.php?m=reporttemplate&f=ajaxZentaoChart&type=project_basicStatistic_workload&blockID=__TML_ZENTAOCHART__{project_basicStatistic_workload}","clearBeforeLoad":false,"isTemplate":true,"title":"项目计划工作量统计"}},"children":[]},{"type":"block","id":"mpqkXURxFF","flavour":"affine:paragraph","version":1,"props":{"align":"left","type":"text","text":{"$blocksuite:internal:text$":true,"delta":[]},"collapsed":false},"children":[]}]}]}}';
+193
View File
@@ -591,4 +591,197 @@ class weeklyModel extends model
return $data;
}
/**
* 添加内置项目周报模板。
* Add builtin project weekly report template.
*
* @access public
* @return bool
*/
public function addBuiltinWeeklyTemplate()
{
/* Set scope data. */
$scopeID = $this->addBuiltinScope();
if(!$scopeID) return false;
/* Set category data. */
$categoryID = $this->addBuiltinCategory($scopeID);
/* Set docblock data. */
$blockIdList = array();
$docBlock = new stdclass();
foreach($this->config->weekly->charts as $chartKey => $chartContent)
{
$docBlock->type = $chartKey;
$docBlock->content = json_encode($chartContent);
$this->dao->insert(TABLE_DOCBLOCK)->data($docBlock)->exec();
$blockIdList[$chartKey] = $this->dao->lastInsertId();
}
/* Set template data. */
$this->addBuiltinTemplate($scopeID, $categoryID, $blockIdList);
return !dao::isError();
}
/**
* 添加内置报告模板范围。
* Add builtin report template scope.
*
* @access public
* @return int|bool
*/
public function addBuiltinScope(): int|bool
{
$scope = $this->dao->select('id')->from(TABLE_DOCLIB)->where('type')->eq('reportTemplate')->andWhere('main')->eq(1)->andWhere('vision')->eq($this->config->vision)->fetch();
if($scope) return false;
$this->loadModel('setting');
/* Set scope data. */
$scope = new stdClass();
$scope->type = 'reportTemplate';
$scope->main = '1';
$scope->vision = $this->config->vision;
$scope->addedBy = 'system';
$scope->addedDate = helper::now();
foreach($this->lang->weekly->builtInScopes as $vision => $scopeList)
{
$scopeMaps = array();
$scope->vision = $vision;
foreach($scopeList as $scopeKey => $scopeName)
{
if(empty($scopeName)) continue;
$scope->name = $scopeName;
$this->dao->insert(TABLE_DOCLIB)->data($scope)->exec();
$scopeMaps[$scopeKey] = $this->dao->lastInsertID();
}
if(!empty($scopeMaps)) $this->setting->setItem("system.reporttemplate.builtInScopeMaps@{$vision}", json_encode($scopeMaps));
}
return array_push($scopeMaps);
}
/**
* 添加内置报告模板分类。
* Add builtin report template category.
*
* @param int $scopeID
* @access public
* @return int
*/
public function addBuiltinCategory(int $scopeID): int
{
/* Set category data. */
$category = new stdClass();
$category->root = $scopeID;
$category->name = $this->lang->projectCommon;
$category->grade = 1;
$category->type = 'reportTemplate';
$this->dao->insert(TABLE_MODULE)->data($category)->exec();
$categoryID = $this->dao->lastInsertID();
$this->dao->update(TABLE_MODULE)->set('`path`')->eq(",{$categoryID},")->where('id')->eq($categoryID)->exec();
return $categoryID;
}
/**
* 添加内置报告模板。
* Add builtin report template.
*
* @param int $libID
* @param int $moduleID
* @param array $blockIdList
* @access public
* @return bool
*/
public function addBuiltinTemplate(int $libID, int $moduleID, array $blockIdList): bool
{
$now = helper::now();
$cycleConfig = array('turnon' => 'on', 'frequency' => 'week', 'acl' => 'open', 'readGroups' => array(), 'readUsers' => array(), 'groups' => array(), 'users' => array());
$objects = $this->dao->select('id')->from(TABLE_WORKFLOWGROUP)->where('type')->eq('project')->andWhere('projectModel')->eq('waterfall')->andWhere('status')->eq('normal')->andWhere('vision')->eq($this->config->vision)->andWhere('objectID')->eq(0)->andWhere('deleted')->eq(0)->fetchPairs('id');
$template = new stdclass();
$template->lib = $libID;
$template->module = $moduleID;
$template->title = $this->lang->weekly->projectTemplate;
$template->type = 'text';
$template->status = 'normal';
$template->acl = 'open';
$template->builtIn = 1;
$template->templateType = 'reportTemplate';
$template->templateDesc = $this->lang->weekly->builtinDesc;
$template->cycle = 'week';
$template->cycleConfig = json_encode($cycleConfig);
$template->objects = ',' . implode(',', $objects) . ',';
$template->addedBy = 'system';
$template->addedDate = $now;
$this->dao->insert(TABLE_DOC)->data($template)->exec();
$templateID = $this->dao->lastInsertID();
$this->dao->update(TABLE_DOC)->set('`path`')->eq(",{$templateID},")->set('`order`')->eq($templateID)->where('id')->eq($templateID)->exec();
$this->dao->update(TABLE_DOCBLOCK)->set('doc')->eq($templateID)->where('id')->in(array_values($blockIdList))->exec();
$templateContent = new stdclass();
$templateContent->doc = $templateID;
$templateContent->title = $template->title;
$templateContent->type = 'doc';
$templateContent->version = 1;
$templateContent->rawContent = $this->getBuildinRawContent($blockIdList);
$templateContent->addedBy = 'system';
$templateContent->addedDate = $now;
$this->dao->insert(TABLE_DOCCONTENT)->data($templateContent)->exec();
$this->loadModel('action')->create('reportTemplate', $templateID, 'Created', '', '', 'system');
return !dao::isError();
}
/**
* 获取内置项目周报模板内容。
* Get builtin project weekly report template content.
*
* @param array $blockIdList
* @access public
* @return string
*/
public function getBuildinRawContent(array $blockIdList): string
{
$blockCodes = array();
foreach($blockIdList as $blockKey => $blockID) $blockCodes[] = '{' . $blockKey . '}';
$rawContent = json_decode($this->lang->weekly->builtinRawContent);
foreach($rawContent as $content)
{
if(isset($content->id)) $content->id = uniqid();
if(isset($content->createDate)) $content->createDate = time();
if(empty($content->children)) continue;
foreach($content->children as $childList)
{
if(isset($childList->id)) $childList->id = uniqid();
if(empty($childList->children)) continue;
foreach($childList->children as $child)
{
if(isset($child->id)) $child->id = uniqid();
if(!empty($child->props->text->delta))
{
foreach($child->props->text->delta as $delta)
{
if(isset($delta->attributes->holder->id)) $delta->attributes->holder->id = uniqid();
if(isset($delta->attributes->holder->name) && isset($blockIdList[$delta->attributes->holder->name])) $delta->attributes->holder->name = "{$delta->attributes->holder->name}_{$blockIdList[$delta->attributes->holder->name]}";
if(isset($delta->attributes->holder->data->blockID) && isset($blockIdList[$delta->attributes->holder->data->type])) $delta->attributes->holder->data->blockID = $blockIdList[$delta->attributes->holder->data->type];
}
}
if(!empty($child->props->content)) $child->props->content->fetcher = str_replace($blockCodes, array_values($blockIdList), $child->props->content->fetcher);
}
}
}
return json_encode($rawContent);
}
}
@@ -373,4 +373,78 @@ class weeklyTest
return $objects;
}
/**
* 添加内置报告模板范围。
* Add built-in report template scope.
*
* @access public
* @return bool|object
*/
public function addBuiltinScopeTest(): bool|object
{
$scopeID = $this->objectModel->addBuiltinScope();
if(!$scopeID) return false;
return $this->objectModel->dao->select('*')->from(TABLE_DOCLIB)->where('id')->eq($scopeID)->fetch();
}
/**
* 添加内置分类。
* Add built-in category.
*
* @access public
* @return object
*/
public function addBuiltinCategoryTest(): object
{
$scopeID = $this->objectModel->addBuiltinScope();
$categroyID = $this->objectModel->addBuiltinCategory($scopeID);
return $this->objectModel->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($categroyID)->fetch();
}
/**
* 添加内置报告模板。
* Add builtin report template.
*
* @access public
* @return array|object
*/
public function addBuiltinTemplateTest(): array|object
{
$scopeID = $this->objectModel->addBuiltinScope();
$categroyID = $this->objectModel->addBuiltinCategory($scopeID);
$this->objectModel->addBuiltinTemplate($scopeID, $categroyID, array());
if(dao::isError()) return dao::getError();
return $this->objectModel->dao->select('*')->from(TABLE_DOC)->fetch();
}
/**
* 获取内置项目周报模板内容。
* Get builtin project weekly report template content.
*
* @access public
* @return array
*/
public function getBuildinRawContentTest(): array
{
$content = $this->objectModel->getBuildinRawContent(array());
return json_decode($content, true);
}
/**
* 添加内置项目周报模板。
* Add builtin project weekly report template.
*
* @access public
* @return bool|object
*/
public function addBuiltinWeeklyTemplateTest():bool|object
{
$result = $this->objectModel->addBuiltinWeeklyTemplate();
if(!$result) return false;
return $this->objectModel->dao->select('*')->from(TABLE_DOC)->fetch();
}
}
@@ -0,0 +1,26 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->addBuiltinCategory();
timeout=0
cid=1
- 测试添加内置分类
- 属性id @1
- 属性root @1
- 属性name @项目
- 属性grade @1
- 属性type @reportTemplate
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/weekly.unittest.class.php';
zenData('doclib')->gen(0);
zenData('module')->gen(0);
zenData('user')->gen(5);
su('admin');
$weeklyTester = new weeklyTest();
r($weeklyTester->addBuiltinCategoryTest()) && p('id,root,name,grade,type') && e('1,1,项目,1,reportTemplate'); // 测试添加内置分类
@@ -0,0 +1,26 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->addBuiltinScope();
timeout=0
cid=1
- 测试添加内置范围
- 属性name @项目
- 属性type @reportTemplate
- 属性main @1
- 属性addedBy @system
- 测试重复添加内置范围 @0
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/weekly.unittest.class.php';
zenData('doclib')->gen(0);
zenData('user')->gen(5);
su('admin');
$weeklyTester = new weeklyTest();
r($weeklyTester->addBuiltinScopeTest()) && p('name,type,main,addedBy') && e('项目,reportTemplate,1,system'); // 测试添加内置范围
r($weeklyTester->addBuiltinScopeTest()) && p() && e('0'); // 测试重复添加内置范围
@@ -0,0 +1,33 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->addBuiltinTemplate();
timeout=0
cid=1
- 测试添加内置模板
- 属性title @项目周报模板
- 属性type @text
- 属性status @normal
- 属性acl @open
- 属性builtIn @1
- 属性templateType @reportTemplate
- 属性cycle @week
- 属性addedBy @system
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/weekly.unittest.class.php';
zenData('action')->gen(0);
zenData('doclib')->gen(0);
zenData('module')->gen(0);
zenData('workflowgroup')->gen(0);
zenData('doc')->gen(0);
zenData('doccontent')->gen(0);
zenData('user')->gen(5);
su('admin');
$weeklyTester = new weeklyTest();
r($weeklyTester->addBuiltinTemplateTest()) && p('title,type,status,acl,builtIn,templateType,cycle,addedBy') && e('项目周报模板,text,normal,open,1,reportTemplate,week,system'); // 测试添加内置模板
@@ -0,0 +1,35 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->addBuiltinWeeklyTemplate();
timeout=0
cid=1
- 测试添加内置周报模板
- 属性title @项目周报模板
- 属性type @text
- 属性status @normal
- 属性acl @open
- 属性builtIn @1
- 属性templateType @reportTemplate
- 属性cycle @week
- 属性addedBy @system
- 测试重复添加内置周报模板 @0
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/weekly.unittest.class.php';
zenData('docblock')->gen(0);
zenData('doclib')->gen(0);
zenData('module')->gen(0);
zenData('workflowgroup')->gen(0);
zenData('doc')->gen(0);
zenData('doccontent')->gen(0);
zenData('user')->gen(5);
su('admin');
$weeklyTester = new weeklyTest();
r($weeklyTester->addBuiltinWeeklyTemplateTest()) && p('title,type,status,acl,builtIn,templateType,cycle,addedBy') && e('项目周报模板,text,normal,open,1,reportTemplate,week,system'); // 测试添加内置周报模板
r($weeklyTester->addBuiltinWeeklyTemplateTest()) && p() && e('0'); // 测试重复添加内置周报模板
@@ -0,0 +1,29 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->getBuildinRawContent();
timeout=0
cid=1
- 检查模板标题属性title @项目周报模板
- 获取holder数据
- 属性name @weekly_term
- 属性text @报告周期
- 属性hint @筛选条件:“date”介于本周
- 检查区块数量 @6
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/weekly.unittest.class.php';
zenData('user')->gen(5);
su('admin');
$weeklyTester = new weeklyTest();
$content = $weeklyTester->getBuildinRawContentTest();
r($content['meta']) && p('title') && e('项目周报模板'); // 检查模板标题
r($content['blocks']['children'][0]['children'][0]['props']['text']['delta'][0]['attributes']['holder']) && p('name,text,hint') && e('weekly_term,报告周期,筛选条件:“date”介于本周'); // 获取holder数据
r(count($content['blocks'])) && p() && e('6'); // 检查区块数量
@@ -0,0 +1,30 @@
#!/usr/bin/env php
<?php
/**
title=测试 weeklyModel->getReportData();
timeout=0
cid=1
- 检查是否存在pv属性 @1
- 检查是否存在ev属性 @1
- 检查是否存在project属性 @1
- 检查是否存在staff属性 @1
- 检查是否存在progress属性 @1
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
zenData('project')->loadYaml('project')->gen(5);
zenData('task')->loadYaml('task')->gen(30);
zenData('user')->gen(5);
su('admin');
global $tester;
$weeklyModel = $tester->loadModel('weekly');
$result = $weeklyModel->getReportData(1);
r(isset($result->pv)) && p() && e('1'); // 检查是否存在pv属性
r(isset($result->ev)) && p() && e('1'); // 检查是否存在ev属性
r(isset($result->project)) && p() && e('1'); // 检查是否存在project属性
r(isset($result->staff)) && p() && e('1'); // 检查是否存在staff属性
r(isset($result->progress)) && p() && e('1'); // 检查是否存在progress属性
+18
View File
@@ -0,0 +1,18 @@
title: project.
desc: project data.
author: Sun Guangming
version: "1.0"
fields:
- field: id
range: 1-100
- field: name
note: "名称"
fields:
- field: name1
range: 敏捷项目,瀑布项目,看板项目
- field: name2
range: 1-100
- field: model
range: scrum,waterfall,kanban
- field: type
range: project