Skip to main content
Version: latest

自定义 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