From 35cacc18d10d33af067980e22a3abac8a0e72d10 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Fri, 19 Jan 2024 10:55:08 +0800 Subject: [PATCH] * Add productsBox to project::create. --- module/project/css/common.ui.css | 3 - module/project/css/create.ui.css | 1 - module/project/js/common.ui.js | 352 ++++++++++++++--------------- module/project/js/create.ui.js | 122 +++++----- module/project/ui/common.field.php | 26 +-- module/project/ui/create.field.php | 4 - module/project/ui/create.html.php | 2 + module/project/zen.php | 11 + 8 files changed, 263 insertions(+), 258 deletions(-) diff --git a/module/project/css/common.ui.css b/module/project/css/common.ui.css index 6e1fe44922..c7a5fa39de 100644 --- a/module/project/css/common.ui.css +++ b/module/project/css/common.ui.css @@ -1,9 +1,6 @@ .items-center {align-items: center !important;} #ignore {text-decoration: underline; cursor: pointer; color: #ef7b0f;} -.productBox .input-group-addon {background: #fff} -.productBox .form-group.no-label {padding-left: 1px} - #project-model {font-weight: 500; font-size: 14px;} .items-center {align-items: center !important} diff --git a/module/project/css/create.ui.css b/module/project/css/create.ui.css index 0c2c614432..f7ce5254d5 100644 --- a/module/project/css/create.ui.css +++ b/module/project/css/create.ui.css @@ -9,7 +9,6 @@ #copyProjects .btn.primary-outline {background-color: var(--color-primary-50);} #copyProjects .btn.primary-outline:after {position: absolute; content: '\e92f'; font-family: ZentaoIcon; font-size: 20px; right: 10px;} #copyProjects .btn.primary-outline span {color: rgba(var(--color-fore-rgb),var(--tw-text-opacity));} -.productBox .line-btn {width: 48px; margin-right: 32px;} .productBox div[id^=plan] {flex: 1 1;} #mainContent .input-group.required {position: relative;} #mainContent .input-group.required:after {content: '*'; color: rgba(var(--color-danger-500-rgb),var(--tw-text-opacity)); position: absolute; top: 0.5rem; right: 0.125rem;} diff --git a/module/project/js/common.ui.js b/module/project/js/common.ui.js index 18ac628336..6ac8540c49 100644 --- a/module/project/js/common.ui.js +++ b/module/project/js/common.ui.js @@ -77,8 +77,8 @@ function computeDaysDelta(date1, date2) */ function computeWorkDays() { - const begin = $('#begin').zui('datePicker').$.value; - const end = $('#end').zui('datePicker').$.value; + const begin = $('[name=begin]').val(); + const end = $('[name=end]').val(); if(end == LONG_TIME) { @@ -299,177 +299,177 @@ function ignoreTip(tip) } /** - * Add new line for link product. - * - * @param obj e - * @access public - * @return void - */ -window.addNewLine = function(e) -{ - const obj = e.target - const newLine = $(obj).closest('.form-row').clone(); - - let index = 0; - let options = zui.Picker.query("[name^='products']").options; - - /* 将已有产品下拉的最大name属性的值加1赋值给新行. */ - $("[name^='products']").each(function() - { - let id = $(this).attr('name').replace(/[^\d]/g, ''); - - id = parseInt(id); - id ++; - - index = id > index ? id : index; - }) - - /* 处理新一行控件的显示/隐藏,宽度/是否居中等样式问题. */ - newLine.addClass('newLine'); - newLine.find('.form-label').html(''); - newLine.find('.removeLine').removeClass('disabled'); - newLine.find('[name="newProduct"]').closest('div.items-center').remove(); - newLine.find('.form-group').eq(0).addClass('w-1/2').removeClass('w-1/4'); - newLine.find('.form-group').eq(1).addClass('hidden'); - newLine.find("div[id^='plan']").attr('id', 'plan' + index); - - $(obj).closest('.form-row').after(newLine); - - /* 重新初始化新一行的下拉控件. */ - newLine.find('.form-group').eq(0).find('.picker-box').empty(); - newLine.find('.form-group').eq(0).find('.picker-box').append(`
`); - - newLine.find('div[id^=plan] .picker-box').empty(); - newLine.find('div[id^=plan] .picker-box').append(`
`); - - options.name = `products[${index}]`; - options.defaultValue = ''; - new zui.Picker(`#products${index}`, options); - - new zui.Picker(`#plans${index}`, { - items:[], - multiple: true, - name: `plans[${index}]`, - }); -} - -/** - * Remove line for link product. - * - * @param obj e - * @access public - * @return void - */ -window.removeLine = function(e) -{ - const obj = e.target; - - /* Dsiabled btn can't remove line. */ - if($(obj).closest('.btn').hasClass('disabled')) return false; - - $(obj).closest('.form-row').remove(); - - let chosenProducts = 0; - $("[name^='products']").each(function() - { - if($(this).val() > 0) chosenProducts ++; - }); - - (chosenProducts.length > 1 && (model == 'waterfall' || model == 'waterfallplus')) ? $('.stageBy').removeClass('hidden') : $('.stageBy').addClass('hidden'); -} - -/** - * Load branches. - * - * @param int $product - * @access public - * @return void - */ -window.loadBranches = function(product) -{ - /* When selecting a product, delete a plan that is empty by default. */ - $("#planDefault").remove(); - - let chosenProducts = []; - let $product = $(product); - $("[name^='products']").each(function() - { - let productID = $(this).val(); - if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID); - if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id')) - { - zui.Modal.alert(errorSameProducts); - $(`#${product.id}`).zui('picker').$.setValue(0); - return false; - } - }); - - (chosenProducts.length > 1 && (model == 'waterfall' || model == 'waterfallplus')) ? $('.stageBy').removeClass('hidden') : $('.stageBy').addClass('hidden'); - - let $formRow = $(product).closest('.form-row'); - let index = $formRow.find("[name^='products']").first().attr('name').match(/\d+/)[0]; - let oldBranch = $(product).attr('data-branch') !== undefined ? $(product).attr('data-branch') : 0; - - if(!multiBranchProducts[$(product).val()]) - { - $formRow.find('.form-group').last().find('select').val(''); - $formRow.find('.form-group').eq(0).addClass('w-1/2').removeClass('w-1/4'); - $formRow.find('.form-group').eq(1).addClass('hidden').find('select').val(''); - $formRow.find('.form-group').eq(0).find('.newProductBox').removeClass('hidden'); - } - - $.getJSON($.createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=" + oldBranch + "¶m=active"), function(data) - { - if(data.length > 0) - { - $formRow.find('.form-group').eq(1).find('.picker-box').empty(); - $formRow.find('.form-group').eq(1).find('.picker-box').append(`
`); - - $formRow.find('.form-group').eq(0).addClass('w-1/4').removeClass('w-1/2'); - $formRow.find('.form-group').eq(1).removeClass('hidden'); - $formRow.find('.form-group').eq(0).find('.newProductBox').addClass('hidden'); - - new zui.Picker(`#branch${index}`, { - items: data, - multiple: true, - name: `branch[${index}]`, - }); - } - - let branch = $('#branch' + index); - loadPlans(product, branch); - }); -} - -/** - * Load plans. - * - * @param obj $product - * @param obj $branchID - * @access public - * @return void - */ -window.loadPlans = function(product, branch) -{ - let productID = $(product).val(); - let branchID = $(branch).val() == null ? 0 : '0,' + $(branch).val(); - let planID = $(product).attr('data-plan') !== undefined ? $(product).attr('data-plan') : 0; - let index = $(product).attr('name').match(/\d+/)[0]; - - $.get($.createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=' + branchID + '&planID=' + planID + '&fieldID&needCreate=&expired=unexpired,noclosed¶m=skipParent,multiple'), function(data) - { - if(data) - { - data = JSON.parse(data); - - $("div#plan" + index).find('.picker-box').empty(); - $("div#plan" + index).find('.picker-box').append(`
`); - - new zui.Picker(`#plans${productID}`, { - items: data, - multiple: true, - name: `plans[${productID}]`, - }); - } - }); -} +// * Add new line for link product. +// * +// * @param obj e +// * @access public +// * @return void +// */ +// window.addNewLine = function(e) +// { +// const obj = e.target +// const newLine = $(obj).closest('.form-row').clone(); +// +// let index = 0; +// let options = zui.Picker.query("[name^='products']").options; +// +// /* 将已有产品下拉的最大name属性的值加1赋值给新行. */ +// $("[name^='products']").each(function() +// { +// let id = $(this).attr('name').replace(/[^\d]/g, ''); +// +// id = parseInt(id); +// id ++; +// +// index = id > index ? id : index; +// }) +// +// /* 处理新一行控件的显示/隐藏,宽度/是否居中等样式问题. */ +// newLine.addClass('newLine'); +// newLine.find('.form-label').html(''); +// newLine.find('.removeLine').removeClass('disabled'); +// newLine.find('[name="newProduct"]').closest('div.items-center').remove(); +// newLine.find('.form-group').eq(0).addClass('w-1/2').removeClass('w-1/4'); +// newLine.find('.form-group').eq(1).addClass('hidden'); +// newLine.find("div[id^='plan']").attr('id', 'plan' + index); +// +// $(obj).closest('.form-row').after(newLine); +// +// /* 重新初始化新一行的下拉控件. */ +// newLine.find('.form-group').eq(0).find('.picker-box').empty(); +// newLine.find('.form-group').eq(0).find('.picker-box').append(`
`); +// +// newLine.find('div[id^=plan] .picker-box').empty(); +// newLine.find('div[id^=plan] .picker-box').append(`
`); +// +// options.name = `products[${index}]`; +// options.defaultValue = ''; +// new zui.Picker(`#products${index}`, options); +// +// new zui.Picker(`#plans${index}`, { +// items:[], +// multiple: true, +// name: `plans[${index}]`, +// }); +// } +// +// /** +// * Remove line for link product. +// * +// * @param obj e +// * @access public +// * @return void +// */ +// window.removeLine = function(e) +// { +// const obj = e.target; +// +// /* Dsiabled btn can't remove line. */ +// if($(obj).closest('.btn').hasClass('disabled')) return false; +// +// $(obj).closest('.form-row').remove(); +// +// let chosenProducts = 0; +// $("[name^='products']").each(function() +// { +// if($(this).val() > 0) chosenProducts ++; +// }); +// +// (chosenProducts.length > 1 && (model == 'waterfall' || model == 'waterfallplus')) ? $('.stageBy').removeClass('hidden') : $('.stageBy').addClass('hidden'); +// } +// +// /** +// * Load branches. +// * +// * @param int $product +// * @access public +// * @return void +// */ +// window.loadBranches = function(product) +// { +// /* When selecting a product, delete a plan that is empty by default. */ +// $("#planDefault").remove(); +// +// let chosenProducts = []; +// let $product = $(product); +// $("[name^='products']").each(function() +// { +// let productID = $(this).val(); +// if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID); +// if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id')) +// { +// zui.Modal.alert(errorSameProducts); +// $(`#${product.id}`).zui('picker').$.setValue(0); +// return false; +// } +// }); +// +// (chosenProducts.length > 1 && (model == 'waterfall' || model == 'waterfallplus')) ? $('.stageBy').removeClass('hidden') : $('.stageBy').addClass('hidden'); +// +// let $formRow = $(product).closest('.form-row'); +// let index = $formRow.find("[name^='products']").first().attr('name').match(/\d+/)[0]; +// let oldBranch = $(product).attr('data-branch') !== undefined ? $(product).attr('data-branch') : 0; +// +// if(!multiBranchProducts[$(product).val()]) +// { +// $formRow.find('.form-group').last().find('select').val(''); +// $formRow.find('.form-group').eq(0).addClass('w-1/2').removeClass('w-1/4'); +// $formRow.find('.form-group').eq(1).addClass('hidden').find('select').val(''); +// $formRow.find('.form-group').eq(0).find('.newProductBox').removeClass('hidden'); +// } +// +// $.getJSON($.createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=" + oldBranch + "¶m=active"), function(data) +// { +// if(data.length > 0) +// { +// $formRow.find('.form-group').eq(1).find('.picker-box').empty(); +// $formRow.find('.form-group').eq(1).find('.picker-box').append(`
`); +// +// $formRow.find('.form-group').eq(0).addClass('w-1/4').removeClass('w-1/2'); +// $formRow.find('.form-group').eq(1).removeClass('hidden'); +// $formRow.find('.form-group').eq(0).find('.newProductBox').addClass('hidden'); +// +// new zui.Picker(`#branch${index}`, { +// items: data, +// multiple: true, +// name: `branch[${index}]`, +// }); +// } +// +// let branch = $('#branch' + index); +// loadPlans(product, branch); +// }); +// } +// +// /** +// * Load plans. +// * +// * @param obj $product +// * @param obj $branchID +// * @access public +// * @return void +// */ +// window.loadPlans = function(product, branch) +// { +// let productID = $(product).val(); +// let branchID = $(branch).val() == null ? 0 : '0,' + $(branch).val(); +// let planID = $(product).attr('data-plan') !== undefined ? $(product).attr('data-plan') : 0; +// let index = $(product).attr('name').match(/\d+/)[0]; +// +// $.get($.createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=' + branchID + '&planID=' + planID + '&fieldID&needCreate=&expired=unexpired,noclosed¶m=skipParent,multiple'), function(data) +// { +// if(data) +// { +// data = JSON.parse(data); +// +// $("div#plan" + index).find('.picker-box').empty(); +// $("div#plan" + index).find('.picker-box').append(`
`); +// +// new zui.Picker(`#plans${productID}`, { +// items: data, +// multiple: true, +// name: `plans[${productID}]`, +// }); +// } +// }); +// } diff --git a/module/project/js/create.ui.js b/module/project/js/create.ui.js index 57a44ec7ae..ffbacc11cb 100644 --- a/module/project/js/create.ui.js +++ b/module/project/js/create.ui.js @@ -31,67 +31,67 @@ function removeAllTips() $('.text-warning').remove(); } -window.addProduct = function(e) -{ - if($(e.target).prop('checked')) - { - $('.productBox').addClass('hidden'); - $('#addProductBox').removeClass('hidden'); - $("[name^='newProduct']").prop('checked', true); - } - else - { - $('.productBox').removeClass('hidden'); - $('#addProductBox').addClass('hidden'); - $("[name^='newProduct']").prop('checked', false); - } -} - -window.productChange = function(target) -{ - loadBranches(target); - - let $this = $(target); - let current = $this.val(); - let last = $this.attr('last'); - let lastBranch = $this.attr('data-lastBranch'); - let $newProduct = $this.closest('.productBox').find('[name=newProduct]').closest('.checkbox-primary').parent(); - - if($newProduct.length > 0) $newProduct.toggleClass('hidden', current > 0); - $this.attr('data-last', current); - - let $branch = $this.closest('.has-branch').find("[name^='branch']"); - if($branch.length) - { - let branchID = $branch.val(); - $this.attr('data-lastBranch', branchID); - } - else - { - $this.removeAttr('data-lastBranch'); - } - - let chosenProducts = 0; - $(".productBox [name^='products']").each(function() - { - if($(this).val() > 0) chosenProducts ++; - }); - - if(chosenProducts > 1) $('.stageBy').removeClass('hidden'); - if(chosenProducts <= 1) $('.stageBy').addClass('hidden'); -} - -window.branchChange = function(e) -{ - let current = $(e.target).val(); - let last = $(e.target).attr('data-last'); - $(e.target).attr('data-last', current); - - let $product = $(e.target).closest('.form-row').find("[name^='products']"); - $product.attr('data-lastBranch', current); - - loadPlans($product, $(e.target)); -} +// window.addProduct = function(e) +// { +// if($(e.target).prop('checked')) +// { +// $('.productBox').addClass('hidden'); +// $('#addProductBox').removeClass('hidden'); +// $("[name^='newProduct']").prop('checked', true); +// } +// else +// { +// $('.productBox').removeClass('hidden'); +// $('#addProductBox').addClass('hidden'); +// $("[name^='newProduct']").prop('checked', false); +// } +// } +// +// window.productChange = function(target) +// { +// loadBranches(target); +// +// let $this = $(target); +// let current = $this.val(); +// let last = $this.attr('last'); +// let lastBranch = $this.attr('data-lastBranch'); +// let $newProduct = $this.closest('.productBox').find('[name=newProduct]').closest('.checkbox-primary').parent(); +// +// if($newProduct.length > 0) $newProduct.toggleClass('hidden', current > 0); +// $this.attr('data-last', current); +// +// let $branch = $this.closest('.has-branch').find("[name^='branch']"); +// if($branch.length) +// { +// let branchID = $branch.val(); +// $this.attr('data-lastBranch', branchID); +// } +// else +// { +// $this.removeAttr('data-lastBranch'); +// } +// +// let chosenProducts = 0; +// $(".productBox [name^='products']").each(function() +// { +// if($(this).val() > 0) chosenProducts ++; +// }); +// +// if(chosenProducts > 1) $('.stageBy').removeClass('hidden'); +// if(chosenProducts <= 1) $('.stageBy').addClass('hidden'); +// } +// +// window.branchChange = function(e) +// { +// let current = $(e.target).val(); +// let last = $(e.target).attr('data-last'); +// $(e.target).attr('data-last', current); +// +// let $product = $(e.target).closest('.form-row').find("[name^='products']"); +// $product.attr('data-lastBranch', current); +// +// loadPlans($product, $(e.target)); +// } $(document).on('click', '#copyProjects button', function() { diff --git a/module/project/ui/common.field.php b/module/project/ui/common.field.php index a9460c6c92..914f8558b8 100644 --- a/module/project/ui/common.field.php +++ b/module/project/ui/common.field.php @@ -54,19 +54,19 @@ $fields->field('begin') $fields->field('days')->label($lang->project->days . $lang->project->daysUnit)->control('input'); -$fields->field('products[]') - ->wrapBefore() - ->control('picker') - ->setClass('className', 'productBox') - ->checkbox(array('text' => $lang->project->newProduct, 'name' => 'newProduct', 'checked' => false)) - ->items(data('allProducts')) - ->label($lang->project->manageProducts); - -$fields->field('plans[]') - ->control('picker') - ->setClass('className', 'productBox') - ->items(array()) - ->label($lang->project->managePlans); +$fields->field('productsBox') + ->width('full') + ->control(array + ( + 'control' => 'productsBox', + 'productItems' => data('allProducts'), + 'branchGroups' => data('branchGroups'), + 'planGroups' => data('productPlans'), + 'linkedProducts' => data('linkedProducts'), + 'linkedBranches' => data('linkedBranches'), + 'project' => data('copyProject'), + 'isStage' => data('isStage') + )); if($model == 'waterfall' || $model == 'waterfallplus') { diff --git a/module/project/ui/create.field.php b/module/project/ui/create.field.php index 540f58c7e2..1f3a60f53a 100644 --- a/module/project/ui/create.field.php +++ b/module/project/ui/create.field.php @@ -35,10 +35,6 @@ if($hasCode) $fields->field('days')->control('input', array('className' => $copyProject ? 'has-warning' : '')); -$fields->field('products[]')->hidden($copyProject ? !data('copyProject.hasProduct') : false); - -$fields->field('plans[]')->hidden($copyProject ? !data('copyProject.hasProduct') : false); - if($model == 'waterfall' || $model == 'waterfallplus') { $fields->field('stageBy')->className('hidden'); diff --git a/module/project/ui/create.html.php b/module/project/ui/create.html.php index d01fcfa4e3..ab813b864a 100644 --- a/module/project/ui/create.html.php +++ b/module/project/ui/create.html.php @@ -19,6 +19,8 @@ jsVar('currencySymbol', $lang->project->currencySymbol); jsVar('parentBudget', $lang->project->parentBudget); jsVar('budgetUnitLabel', $lang->project->tenThousandYuan); jsVar('budgetUnitValue', $config->project->budget->tenThousand); +jsVar('+projectID', $copyProjectID); +jsVar('LONG_TIME', LONG_TIME); $modelMenuItems = array(); foreach($lang->project->modelList as $key => $text) diff --git a/module/project/zen.php b/module/project/zen.php index 12956daf5b..357a4966ff 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -274,6 +274,12 @@ class projectZen extends project $allProducts = $this->program->getProductPairs($programID, 'all', 'noclosed', '', $shadow, $withProgram); $parentProgram = $this->loadModel('program')->getByID($programID); + if($copyProjectID) + { + $copyProjectBranches = $this->project->getBranchesByProject($copyProjectID); + $linkedProducts = $this->product->getProducts($copyProjectID, 'all', '', true, $copyProjectBranches, false); + } + $this->view->title = $this->lang->project->create; $this->view->gobackLink = (isset($output['from']) && $output['from'] == 'global') ? $this->createLink('project', 'browse') : ''; $this->view->model = $model; @@ -292,6 +298,11 @@ class projectZen extends project $this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs(); $this->view->availableBudget = $parentProgram ? $this->program->getBudgetLeft($parentProgram) : 0; $this->view->budgetUnitList = $this->project->getBudgetUnitList(); + $this->view->branchGroups = $this->loadModel('execution')->getBranchByProduct(array_keys($allProducts)); + $this->view->productPlans = $this->loadModel('productplan')->getGroupByProduct(array_keys($allProducts), 'skipparent|unexpired'); + $this->view->linkedProducts = isset($linkedProducts) ? $linkedProducts : array(); + $this->view->linkedBranches = $this->project->getBranchesByProject($copyProjectID); + $this->view->isStage = in_array($model, array('waterfall', 'waterfallplus', 'ipd')); $this->display(); }