Greasy Fork is available in English.

Zentao Utils

7/27/2021, 4:53:18 PM

// ==UserScript==
// @name        Zentao Utils
// @namespace   Violentmonkey Scripts
// @match       http://zentao.inovance.com/pro/*
// @match       http://10.44.244.63/pro/*
// @icon        https://blog.sbw.so/favicon.ico
// @grant       GM_getValue
// @grant       GM_setValue
// @version     1.10
// @license     MIT
// @author      sbw <sbw@sbw.so>
// @description 7/27/2021, 4:53:18 PM
// ==/UserScript==


(function() {
  
  // 显示 alert 对话框
  function show_alert(message)
  {
    bootAlert(message);
  }
  
  // 显示对话框
  function update_dialog(title, content)
  {
    $('#dialog .modal-title').html(title);
    $('#dialog .modal-body').html(content);
  }
  
  // 获取当前项目中的模块分类
  function update_module_on_dialog()
  {
    var url = "/tree-ajaxGetOptionMenu-149-bug-0-0-html--true.html";
    $.get(url, function(data, status){
      update_dialog('更新模块', data);
      
      // 清除事件
      $('.form-control').off('change');
      $('.form-control').removeAttr('onchange');
    });
  }
  
  // 更新任务所属模块
  function update_jobs_module(e)
  {
    // 禁止默认的响应
    e.preventDefault();
    
    update_module_on_dialog();
    
    // 绑定对话框确定按钮的事件
    $('#dialog .btn-primary').off('click');
    var basicInfoPanel = $('#legendBasicInfo');
    if (basicInfoPanel.length > 0) {
      $('#dialog .btn-primary').click(submit_jobs_module_inline);
    } else {
      $('#dialog .btn-primary').click(submit_jobs_module);
    }
  }
  
  function submit_modify_job(jobId, fun)
  {
    // 修改任务的地址
    var url = '/pro/bug-edit-' + jobId + '.html';
    $.get(url, function(data, status) {
      // 从任务修改界面获取初始数据集
      var resData = $.parseHTML(data, true);
      var formData = new FormData($(resData).find('form')[0]);
      fun(resData, formData);

      // 发送数据
      $.ajax({
        type: 'post',
        url: url, 
        data: formData, 
        contentType: false,
        processData: false,
        success: function(data, status) { 
          /*$('html').html(data);*/
          new $.zui.Messager('任务 ' + jobId + ' 更新完成', { icon: 'bell' }).show();
          
          // // 刷新当前页面
          // location.reload();
        }
      });
    });
  }
  
  function submit_jobs_module()
  {
    // 获取选择的数据
    var choose = $('#module').find(":selected").val();
    
    // 隐藏对话框
    $('#dialog').modal('hide');
    
    // 获取选中的任务列表
    $('#bugList tr').filter('.checked').each(function () {
      var id = $(this).find('.c-id input').val();
      var title = $(this).find('.text-left').attr('title');
      if (typeof(title) === "undefined") {
        title = $(this).find('.text-left > a').attr('title');
      }
      
      submit_modify_job(id, function(resData, formData) {
        // 修改所属模块
        formData.set('module', choose);
      });
    });
  }
  
  function submit_jobs_module_inline()
  {
    // 获取选择的数据
    var choose = $('#module').find(":selected").val();
    
    // 隐藏对话框
    $('#dialog').modal('hide');
    
    // 当前任务 id
    var id = $('.label-id').text();
    submit_modify_job(id, function(resData, formData) {
      // 修改所属模块
      formData.set('module', choose);
    });
  }
  
  // 从 bug 页面获取关键词列表
  function get_keywords_from_bug_page()
  {
    var keywords = $('#legendBasicInfo tr:nth-child(25) td:first')[0].childNodes[0].nodeValue;
    keywords = split_keywords(keywords);
    
    return keywords;
  }
  
  // 从 GM 中获取存储的最近使用的关键词列表
  function get_last_recent_used_keywords()
  {
    var default_keywords = ["待评审", "无效", "延期处理", "不复现"]
    var keywords = GM_getValue('last_recent_used_keywords', default_keywords);
    if (!Array.isArray(keywords))
      return default_keywords;
    
    return keywords;
  }
  
  // 更新最近使用的关键词列表
  function update_last_recent_used_keywords(keywords)
  {
    // bug 中的关键词列表
    var bugKeywords = get_keywords_from_bug_page();
    // 上次的关键字列表
    var lastKeywords = get_last_recent_used_keywords();
    // 提交的关键词中去掉 bug 中的
    var newKeywords = keywords.filter(x => !bugKeywords.includes(x));
    
    // 最后的列表中移除新的,并把新的添加到前面
    lastKeywords = lastKeywords.filter(x => !newKeywords.includes(x));
    lastKeywords = newKeywords.concat(lastKeywords);
    if (lastKeywords.length > 10)
      lastKeywords.length = 10;
    
    GM_setValue('last_recent_used_keywords', lastKeywords);
  }
  
  // 分隔关键词列表
  function split_keywords(keywords)
  {
    if (!keywords || keywords.trim().length === 0)
      return [];

    // 分隔已有的关键词列表
    var re = /\s+|,|,|;|;/;
    var keywords = keywords.split(re).map(x => x.trim()).filter(x => x && x.length > 0);
    
    return keywords;
  }
  
  // 更新输入框元素列表
  function update_keywords_input()
  {
    // 是否自定义
    var custom = $('.custom-keywords').is(":checked");
    $('#keywords-input').prop('disabled', !custom);
    
    // 非自定义,由用户输入决定结果
    if (!custom) {
      // 非自定义,由标签决定结果,遍历所有标签
      var keywords = [];
      $('.checkbox input:checked').each(function() {
        keywords.push($(this)[0].nextSibling.nodeValue.trim());
      });
      
      // 输入框数据
      $('#keywords-input').val(keywords.join(", "));
    }
  }
  
  // 用户提交编辑后的关键字列表
  function submit_keywords()
  {    
    var keywords = $('#keywords-input').val();
    keywords = split_keywords(keywords);
    
    // 隐藏对话框
    $('#dialog').modal('hide');
    
    // 关键词列表提交保存
    update_last_recent_used_keywords(keywords);
    
    // 提交修改
    var keywords = keywords.join(", ");
    
    // 当前任务 id
    var id = $('.label-id').text();
    submit_modify_job(id, function(resData, formData) {
      // 修改关键字数据
      formData.set('keywords', keywords);
    });
  }
  
  function assign_back(e) {
    // 禁止默认的响应
    e.preventDefault();
    
    // 获取选中的任务列表
    $('#bugList tr').filter('.checked').each(function () {
      var id = $(this).find('.c-id input').val();
      
      submit_modify_job(id, function(resData, formData) {
        // 找到创建者名字和 id
        var creater = $(resData).find('.detail:nth-child(3) > .table-form td:first').text();
        var creater_id = '';
        
        var options = $(resData).find('#assignedTo > option');
        for (var i = 0; i != options.length; ++i) {
          if (options[i].title == creater) {
            creater_id = options[i].value;
            break;
          }
        }
        
        formData.set('assignedTo', creater_id);
      });
    });
  }
  
  function update_jobs_keywords(e)
  {
    // 禁止默认的响应
    e.preventDefault();
    
    // 获取当前关键词列表
    var keywords = get_keywords_from_bug_page();
    
    // 最后使用的 keywords
    var last_keywords = get_last_recent_used_keywords();
    
    // 合并去重后的选项列表
    var options = keywords.filter(x => !last_keywords.includes(x)).concat(last_keywords);
    // 创建选项组
    var divBox = $("<div></div>");
    options.forEach(x => {
      var select = $("<div class='checkbox'><label><input type='checkbox'>" + x + "</label></div>");
      
      // 勾选事件
      $(select).find('input').change(update_keywords_input);
      if (keywords.includes(x)) {
        $(select).find('input').prop('checked', true);
      }
      
      $(divBox).append(select);
    });
    // 输入框
    var inputGroup = $("<div class='checkbox'><label><input class='custom-keywords' type='checkbox'>自定义</label>&nbsp;<div class='input-control'><input id='keywords-input' type='text' class='form-control'></div></div>");
    // 标签和输入框居中
    $(inputGroup).css({"display": "flex", "align-items": "center"});
    // 输入框伸长
    $(inputGroup).find('.input-control').css({"flex-grow": "1"});
    // 输入框勾选自定义
    $(inputGroup).find('.custom-keywords').change(update_keywords_input);
    $(divBox).append(inputGroup);
    
    // 更新对话框
    update_dialog('更新关键词', divBox);  
    // 更新对话框的提交事件
    $('#dialog .btn-primary').off('click');
    $('#dialog .btn-primary').click(submit_keywords);
    // 更新元素状态
    update_keywords_input();
  }
  
  // 添加对话框
  $("body").append("<div class='modal fade' id='dialog'><div class='modal-dialog modal-sm'><div class='modal-content'><div class='modal-header'><h4 class='modal-title'></h4></div><div class='modal-body'></div><div class='modal-footer'><button type='button' class='btn btn-default' data-dismiss='modal'>关闭</button><button type='button' class='btn btn-primary'>保存</button></div></div></div></div>");

  // 添加模块修改按钮
  $('.table-actions').append('<button class="btn" id="update-module" data-toggle="modal" data-target="#dialog">修改所属模块</button>');
  // 更新模块点击的事件
  $('#update-module').click(update_jobs_module);
  
  // 添加一键指回 bug 提出人按钮
  $('.table-actions').append('<button class="btn" id="assign-back">指派给提出人</button>');
  // 事件
  $('#assign-back').click(assign_back);

  // 如果在 bug view 界面,增加快速修改按钮
  var basicInfoPanel = $('#legendBasicInfo');
  if (basicInfoPanel.length > 0)
  {
    // 更新模块
    var btn = '<button class="btn" id="update-module-x" data-toggle="modal" data-target="#dialog">更新模块</button>';
    $('#legendBasicInfo tr:nth-child(2) td:first').append(btn);
    $('#update-module-x').click(update_jobs_module);
    
    // 更新关键词
    var btn = '<button class="btn" id="update-keywords-x" data-toggle="modal" data-target="#dialog">更新关键词</button>';
    $('#legendBasicInfo tr:nth-child(25) td:first').append(btn);
    $('#update-keywords-x').click(update_jobs_keywords);
  }
  
  // 如果在 bug 列表界面,计算 bug 解决率
  if ($('.table-footer > .text').length > 0) 
  {
    var items = $('.table-footer > .text > strong');
    var total = parseInt($(items[0]).text(), 10);
    var unresolved = parseInt($(items[1]).text(), 10);
    
    $('.table-footer > .text > strong:last-child').after(',解决率 <strong>' + (100.0 * (total - unresolved) / total).toFixed(2) + '%</strong>');
  }
})();