投后结案(流量分析)

云图扩展工具

  1. // ==UserScript==
  2. // @name 投后结案(流量分析)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.4
  5. // @description 云图扩展工具
  6. // @author siji-Xian
  7. // @match *://yuntu.oceanengine.com/yuntu_brand/evaluation_brand/task_list?*
  8. // @icon https://lf3-static.bytednsdoc.com/obj/eden-cn/prhaeh7pxvhn/yuntu/yuntu-logo_default.svg
  9. // @grant none
  10. // @license MIT
  11. // @require https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.2.1/jquery.min.js
  12. // @require https://cdn.bootcss.com/moment.js/2.20.1/moment.min.js
  13. // @require https://gf.qytechs.cn/scripts/404478-jsonexportexcel-min/code/JsonExportExcelmin.js?version=811266
  14. // @require https://gf.qytechs.cn/scripts/455576-qmsg/code/Qmsg.js?version=1122361
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. "use strict";
  19. var new_element = document.createElement("link");
  20. new_element.setAttribute("rel", "stylesheet");
  21. new_element.setAttribute("href", "https://qmsg.refrain.xyz/message.min.css");
  22. document.body.appendChild(new_element);
  23.  
  24. const button = document.createElement("div");
  25. button.textContent = "流量分析";
  26. Object.assign(button.style, {
  27. height: "34px",
  28. lineHeight: "var(--line-height, 34px)",
  29. alignItems: "center",
  30. color: "white",
  31. background: "linear-gradient(90deg, rgba(0, 239, 253), rgba(64, 166, 254))",
  32. borderRadius: "5px",
  33. marginLeft: "10px",
  34. fontSize: "13px",
  35. padding: "0 10px",
  36. cursor: "pointer",
  37. fontWeight: "500"
  38. });
  39. button.addEventListener("click", urlClick);
  40.  
  41. //获取brand信息
  42. let brand = localStorage.getItem("__Garfish__platform__yuntu_user") || "";
  43. let brands = JSON.parse(brand);
  44.  
  45. //获取industry_id
  46. let industry_id = null;
  47.  
  48. (function listen() {
  49. var origin = {
  50. open: XMLHttpRequest.prototype.open,
  51. send: XMLHttpRequest.prototype.send,
  52. };
  53. XMLHttpRequest.prototype.open = function (a, b) {
  54. this.addEventListener("load", replaceFn);
  55. origin.open.apply(this, arguments);
  56. };
  57. XMLHttpRequest.prototype.send = function (a, b) {
  58. origin.send.apply(this, arguments);
  59. };
  60. function replaceFn(obj) {
  61. if (
  62. this?._url?.slice(0, 42) == "/yuntu_ng/api/v1/get_brand_competitor_list"
  63. ) {
  64. industry_id = JSON.parse(obj?.target?.response).data[0].industry_id;
  65. }
  66. }
  67. })();
  68.  
  69. function getQueryVariable(variable) {
  70. var query = window.location.search.substring(1);
  71. var vars = query.split("&");
  72. for (var i = 0; i < vars.length; i++) {
  73. var pair = vars[i].split("=");
  74. if (pair[0] == variable) {
  75. return pair[1];
  76. }
  77. }
  78. return false;
  79. }
  80.  
  81. //message.js
  82. let loadingMsg = null;
  83.  
  84. function appendDoc() {
  85. const likeComment = document.querySelector(".index__btnWrapper--gvaIn");
  86. if (likeComment) {
  87. likeComment.append(button);
  88. return;
  89. }
  90. setTimeout(appendDoc, 1000);
  91. }
  92. appendDoc();
  93.  
  94. const getRequestOptions = {
  95. method: "GET",
  96. redirect: "follow",
  97. };
  98.  
  99. async function fetchFun(url, data, requestOptions = getRequestOptions()) {
  100. const params = new URLSearchParams(data).toString();
  101. try {
  102. const response = await fetch(`${url}?${params}`, requestOptions);
  103. if (response.ok) {
  104. const result = await response.json();
  105. return result;
  106. } else {
  107. throw new Error(`Fetch failed: ${response.status}`);
  108. }
  109. } catch (error) {
  110. loadingMsg.close();
  111. Qmsg.error({
  112. content: `网络请求错误: ${error.message}`,
  113. timeout: 5000
  114. });
  115. throw error;
  116. }
  117. }
  118.  
  119. //活动总览tabs数据获取
  120. async function getTabs1Data(e,task) {
  121. var myHeaders = new Headers();
  122. myHeaders.append("content-type", "application/json;charset=UTF-8");
  123.  
  124. let bodyData = {
  125. task_id:task.task_id,
  126. benchmark_type: 2,
  127. stat_types: [1, 2, 7],
  128. if_level_3_trigger_point: true,
  129. trigger_point: {
  130. level_1_trigger_point: { query_type_point_id: e },
  131. },
  132. };
  133. let postRequestOptions = {
  134. method: "POST",
  135. headers: myHeaders,
  136. body: JSON.stringify(bodyData),
  137. redirect: "follow",
  138. };
  139. let data = {
  140. aadvid: getQueryVariable("aadvid"),
  141. };
  142.  
  143. let requestData = await fetchFun(
  144. "https://yuntu.oceanengine.com/measurement/api/v2/get_evaluation_flow_by_day_result",
  145. data,
  146. postRequestOptions
  147. );
  148.  
  149. let expData = requestData?.data?.item_list?.map((v, i) => {
  150. let data = {};
  151. Object.keys(v.by_day_list).map((r) => {
  152. //pv:曝光次数 uv:曝光人数 cost:消耗金额
  153. data[r] = v.by_day_list[r]?.cost;
  154. });
  155. let a = Object.values(v.trigger_point).map((v) => {
  156. return v.query_type_point_name_zh;
  157. });
  158. data["point_name"] = a.join("/");
  159. return {
  160. data,
  161. };
  162. });
  163. console.log(expData,1111)
  164. return expData.map((v) => v?.data);
  165. }
  166.  
  167. async function task_list(e) {
  168. loadingMsg = Qmsg.loading("正在导出,请勿重复点击!");
  169.  
  170. let offset = +(e.startPage - 1 + "0");
  171. let count = +(e.endPage - offset / 10 + "0");
  172. let search_word = document.querySelector(".evaluation-input.evaluation-input-size-md")?.value
  173.  
  174. let params = {
  175. main_brand_id: brands.brand_id,
  176. level_1_industry_id: industry_id,
  177. offset: offset,
  178. count: count,
  179. order_type: 1
  180. }
  181.  
  182. if (search_word) {
  183. params.search_word = search_word
  184. }
  185.  
  186. let raw = JSON.stringify(params);
  187. let data = {
  188. aadvid: getQueryVariable("aadvid"),
  189. };
  190. let myHeaders = new Headers();
  191. myHeaders.append("content-type", "application/json");
  192.  
  193. let postRequestOptions = {
  194. method: "POST",
  195. headers: myHeaders,
  196. body: raw,
  197. redirect: "follow",
  198. };
  199. let taskList = await fetchFun(
  200. "https://yuntu.oceanengine.com/measurement/api/v2/get_evaluation_task_list_v2",
  201. data,
  202. postRequestOptions
  203. );
  204. let res = taskList?.data?.task_list
  205. ?.map((v) => {
  206. return { task_name: v.task_name, task_id: v.task_id, task_status:v.task_status };
  207. })
  208. .filter((v) => v.task_id != "2280" && v.task_status == 3);
  209.  
  210.  
  211. let expExcelData = await Promise.all(
  212. res.map((v) => {
  213. let data = getData(v);
  214. return data;
  215. })
  216. );
  217. // console.log(expExcelData);
  218. expExcel(expExcelData);
  219. }
  220.  
  221.  
  222. function expExcel(e) {
  223. let title = {
  224. "触点/日期": "point_name",
  225. };
  226.  
  227.  
  228.  
  229. let datas = e.map(v=>{
  230. let contrast = {}
  231. let maxCount = 0;
  232. let maxObj;
  233. v.value.forEach(obj => {
  234. const count = Object.keys(obj).length;
  235. if (count > maxCount) {
  236. maxCount = count;
  237. maxObj = obj;
  238. }
  239. });
  240. Object.keys(maxObj).map((item) => {
  241. if (item!=='point_name') {
  242. contrast[moment(item).format("YYYY-MM-DD")] = item;
  243. }
  244. });
  245. console.log(v.value)
  246. let datas = {
  247. sheetName: v?.key,
  248. sheetData: v?.value,
  249. sheetHeader: Object.keys({ ...title, ...contrast }),
  250. sheetFilter: Object.values({ ...title, ...contrast }),
  251. columnWidths: [], // 列宽
  252. };
  253. return datas
  254. })
  255.  
  256. let option = {};
  257. option.fileName = "流量分析_byDay"; //文件名
  258. option.datas = datas
  259. var toExcel = new ExportJsonExcel(option);
  260. toExcel.saveExcel();
  261. loadingMsg.close();
  262. }
  263.  
  264. async function getData(task) {
  265. let pointId = ["130000", "150000"];
  266. let promiseData = await Promise.all(
  267. pointId.map(async (v) => {
  268. let data = await getTabs1Data(v,task);
  269. return data;
  270. })
  271. );
  272. let res = {key:task.task_name,value:promiseData.flat()}
  273. return res
  274. }
  275.  
  276. function urlClick() {
  277. try {
  278. let res = prompt("页码,例: 1,2 (起始页和结束页中间用英文逗号分隔)");
  279. if (res) {
  280. let [startPage, endPage] = res.split(",");
  281. startPage = parseInt(startPage);
  282. endPage = parseInt(endPage);
  283. if (isNaN(startPage) || isNaN(endPage) || endPage < startPage) {
  284. throw new Error("页码格式错误!");
  285. }
  286. task_list({ startPage, endPage });
  287. }
  288. } catch (err) {
  289. Qmsg.error(err.message);
  290. }
  291. }
  292.  
  293. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址