前言

最近接了个XX工单审核的锅,根据规定,审核过的工单要有记录,如果有变化要写备注。
为什么不直接在XX工单系统导出数据?并没有这个功能。
为什么不写个爬虫定时爬数据?审核过的工单经常会有变化(被运维打回,需要修改之类),有些工单状态错误爬下来还要人工修改。

最初接这个锅的同事是用 Excel 来记录的,后来估计他也觉得这样手工记录非常 Silly,于是写了个程序……
输入XX工单系统的 Cookie -> 输入工单号 -> 获取工单信息 -> 打开 Excel 追加一行记录 -> 有变化的话加备注。

这个程序槽点非常多,先不提每次 Cookie 过期都要重新登陆复制粘贴 Cookie,为啥就非得用又慢又难用的 Excel 呢?

纠结了一下决定写个 Chrome 扩展来简化工作。

文档

首先是开发文档,官方文档在此,中文版有个 360 的,年代久远排版糟糕,非常不推荐,实在要看中文的可以看看这个

但是官方文档有个坑,实例程序里用来获取图片的 API https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=xx 已经不能用了:

20170315153315.png

Demo

仿照官方的实例程序写了个 demo,其实和写网页差不多。
贴一下 popup.js :

function getCurrentTabUrl(callback) {
  var queryInfo = {
    active: true,
    currentWindow: true
  };

  chrome.tabs.query(queryInfo, function(tabs) {
    var tab = tabs[0];
    var url = tab.url;
    // 判断插件是不是在工单详情页打开
    if (url == 'string' ||
     url.indexOf('https://xx.com/xxx/order/detail/') == -1) {
      renderStatus('本插件只能在工单详情页使用');
    } else {
      callback(url);
    }
  });
}

function getOrderData(url, callback, errorCallback) {
  // 从当前 URL 提取工单号
  var pattern = /\d{5,6}/g;
  var orderID = url.match(pattern);
  // 从 API 获取当前工单信息
  var apiUrl = "https://xx.com/xxx/detail/task/" + orderID + "/user/xxx/";
  var x = new XMLHttpRequest();
  x.open('GET', apiUrl);
  x.responseType = 'json';
  x.onload = function() {
    var response = x.response;
    if (!response || response.result.length == 0) {
      errorCallback('该工单没有数据!');
      return;
    }
    var data = response.result;

    callback(data);
  };
  x.onerror = function() {
    errorCallback('网络错误');
  };
  x.send();
}

function renderStatus(statusText) {
  document.getElementById('status').textContent = statusText;
}

function parseData(data) {
  var opDiv = document.getElementById('data');
  // 添加选择栏
  var choices = ["确认", "驳回", "其他"];

  var selection = document.createElement("select");
  selection.id = "mySelect";
  opDiv.appendChild(selection);

  for (var i = 0; i <= choices.length - 1; i++) {
    var option = document.createElement("option");
    option.value = choices[i];
    option.text = choices[i];
    selection.appendChild(option);
  }

  // 添加备注框
  var note = document.createElement("textarea");
  note.id = "myNote";
  note.placeholder = "备注";
  opDiv.appendChild(note);

  // 确定按钮
  var confirm = document.createElement("button");
  confirm.id = "myConfirm";
  confirm.textContent = "确定"
  opDiv.appendChild(confirm);

  opDiv.hidden = false;

  confirm.addEventListener('click', function() {
    // 添加选择和备注数据
    data.Choice = document.getElementById("mySelect").value;
    data.Note = document.getElementById("myNote").value;
    // 发送数据
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("POST", "http://127.0.0.1:5000/api/add");
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.onerror = function() {
      errorCallback('网络错误');
    };
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState === 4) {
        if (xmlhttp.response == '1') {
          renderStatus("添加成功 ~");
          opDiv.hidden = true;
        } else {
          renderStatus("添加失败,请检查");
        }
      }
    };
    xmlhttp.send(JSON.stringify(data));
  });
}

document.addEventListener('DOMContentLoaded', function() {
  getCurrentTabUrl(function(url) {
    renderStatus("数据加载中...");
    getOrderData(url, function(data) {
      renderStatus("工单:" + data.TaskID);
      parseData(data);
    }, function(errorMessage) {
      renderStatus('出错啦:' + errorMessage);
    });
  });
});

打开插件是这样子的:

sp170315_155008.png

点确定后会向后端的 API 发数据,因为功能比较简单,直接用 Flask + SQLite,添加数据后来个展示页面就 OK 了:

1489564536(1.png

装上插件后,对于没有什么问题的工单,点两下鼠标就能搞定。

调试

方法一:

  • 点击插件图标
  • 在弹出的对话框中点右键 - “检查”

方法二:

  • chrome://extensions/
  • 检查视图:背景页

修改代码后在 console 中输入 location.reload(true) 即可刷新。

推荐

推荐一些 Chrome 扩展: