Skip to main content
Version: v24.03

自定义 JS 与 CSS

该功能允许用户在腾讯问卷中引入自定义的 JS 与 CSS,以达到对一些页面的个性化定制

caution

引入自定义JS与CSS需要慎重,有可能会导致页面加载异常

以及腾讯问卷在版本升级后,原有页面的元素可能会发生变化,导致自定义JS与CSS失效

自定义 JS#

.env 修改 THIRD_PARTY_JAVASCRIPTS 值,添加自定义 JS 地址,支持多个地址,使用逗号分割,支持 https://, http://, // 等3种协议(双斜杠为自适应),例如:

THIRD_PARTY_JAVASCRIPTS=https://code.jquery.com/jquery-3.6.3.slim.min.js,https://example.com/myjavascript.js

自定义 CSS#

.env 修改 THIRD_PARTY_STYLESHEETS 值,添加自定义 CSS 地址,支持多个地址,使用逗号分割,支持 https://, http://, // 等3种协议(双斜杠为自适应),例如:

THIRD_PARTY_STYLESHEETS=https://example.com/my-css-1.css,https://example.com/my-css-2.css

重启#

配置完成后执行以下命令进行重启

docker restart backend-go-web

效果#

自定义 JS 与 CSS 会以指定的顺序在所有页面加载

plugin-inspect.png

实践案例#

需求背景#

腾讯问卷投放页在线上有小程序分享,但由于私有化标准版并无企业方 appid 等相关信息,所以在标准版无小程序投放能力。

Alt text

代码注入#

在投放分享页按照上述的方式注入以下代码。

/** 监听 dom 是否注册成功 */function waitForSelector(selector) {  return new Promise(function (resolve) {    var start_at = new Date().getTime();
    /** 轮训获取 dom */    var theWaitForSelectorLoop = function theWaitForSelectorLoop() {      var now = new Date().getTime();
      if (document.querySelectorAll(selector).length > 0) {        resolve(document.querySelector(selector));      } else if (now - start_at > 60 * 1000) {        // get timeout, Do nothing & stop.      } else {        window.requestAnimationFrame(theWaitForSelectorLoop);      }    };
    theWaitForSelectorLoop();  });}
/** 请求数据 */var request = function (params) {  /** TODO:请求的 url,这里更换成业务所需 */  var BASE_URL = "https://wj.qq.com";
  var url = params.url;  var method = params.method;  var body = params.body;
  var data = {    headers: { "content-type": "application/json" },    credentials: "include",    method,  };  if (method === "POST" || method === "PATCH" || method === "DELETE") {    if (body instanceof FormData) {      delete data.headers;      Object.assign(data, {        body,      });    } else {      Object.assign(data, {        body: JSON.stringify(body),      });    }  }
  return fetch(BASE_URL + url, data)    .then(function (resp) {      return Promise.all([resp.json(), Promise.resolve(resp.status)]);    })    .then(function (res) {      if (res.status !== 200) {        throw new Error(res.resp);      }      return res.resp;    })    .catch(function (err) {      /** TODO:设置异常 */      console.error(err);    });};
/** 下载二维码 */var downloadIamge = function (src) {  var image = new Image();  image.setAttribute("crossOrigin", "anonymous");  image.onload = function () {    var canvas = document.createElement("canvas");    canvas.width = image.width;    canvas.height = image.height;    var context = canvas.getContext("2d");    context.drawImage(image, 0, 0, image.width, image.height);    var url = canvas.toDataURL("image/png");    // 生成一个a元素    var a = document.createElement("a");    a.style.display = "none";    a.download = "qrcode.png";    a.href = url;    document.body.appendChild(a);    // 创建一个单击事件    var event = new MouseEvent("click");    // 触发a的单击事件    a.dispatchEvent(event);  };  image.src = src;};
window.addEventListener("load", function () {  var pathname = new URL(location.href).pathname;
  if (pathname === "/deliver.html") {    /**      * 取出页面中的 sid 和 hash     * 一个数据获取的参考,暂时没有用到     */    waitForSelector(".share-method__item-link").then(function (el) {      var uri = new URL(el.innerHTML);      var keyArr = uri.pathname.replace("/s2/", "").split("/");      var sid = keyArr[0];      var hash = keyArr[1];
      // 存到全局变量      window.__INJECT_SID__ = sid;      window.__INJECT_HASH__ = hash;    });
    /** 加上小程序二维码 */    waitForSelector(".share-method__item-wrap").then(function (el) {      /** 获取 sid */      var sid = new URL(location.href).searchParams.get("sid");
      request({        /** 获取问卷下的小程序二维码 */        url: "/api/surveys/" + sid + "/weapp_qrcode_unlimited",        method: "GET",      }).then((res) => {        /** 从接口获取图片 */        const qrcode = res.data.qrcode;
        /** 加上 base 64 格式 */        var img = "data:image/png;base64, " + qrcode;
        /** 创建一个 div */        var div = document.createElement("div");        div.className = "share-method__item";
        /** 直接从页面上按照格式 copy 一份 */        var innerHTML = '<p class="share-method__item-info">小程序扫码分享</p>';
        /** 小程序太阳图 html */        innerHTML +=          '<div class="share-method__item-qrcode"><img class="pic" src="' +          img +          '"></img></div>';
        /** 操作按钮 */        innerHTML +=          '<div class="share-method__item-operate"><button class="btn" id="qrcode-download">下载</button>';        div.innerHTML = innerHTML;
        /** 注入 html */        el.appendChild(div);
        /** 监听点击事件 */        document.querySelector("#qrcode-download").onclick = function () {          downloadIamge(img);        };      });    });  }});

效果展示#

Alt text