Skip to content

搜索

警告

实例中的所有代码为 ts,主要看思路

如果要使用,请自己 build + babel(corejs)!!!

否则很多 BOM API IE10 下是无法运行的!!!

请求华龙网 API 时,参数是需要签名,需要使用华龙网提供的 js 文件进行处理。

生产环境直接且必须使用华龙网提供的线上文件

html
<script type="text/javascript" src="/public/bundle.min.js"></script>

如果本地开发需要调试,可以之前的 老版本文件

新版本

还在为 华龙芯 频繁变动而烦恼?

还在为跟不上版本而 心力交瘁

快来试试 “传新版本” 的华龙芯搜索方式 ‼️

💗 夜 💗 深 💗 人 💗 静 💗
💓 Bu 💓 g 💓 动 💓 人 💓
‼️ 点‼️ 击‼️ 链‼️ 接 ‼️
👉 最新版 及 代码示例
👉 最新版 及 代码示例
👉 最新版 及 代码示例
❤️‍🔥 立 ❤️‍🔥 即 ❤️‍🔥 学 ❤️‍🔥 习 ❤️‍🔥

✨ 1、用户点击查询

ts
window.addEventListener("DOMContentLoaded", () => {
  const searchs = document.querySelectorAll(".hlx-search");

  searchs.forEach((search) => {
    const input = search.querySelector(".hlx-search-input") as HTMLInputElement;
    const button = search.querySelector(".hlx-search-btn");

    if (button) {
      button.addEventListener("click", () => {
        if (input && input.value) {
          const value = input.value;
          console.log(value);
        }

        hlx_to_search_page(input.value);
      });
    }

    if (input) {
      input.addEventListener("keyup", (e) => {
        if (e.key === "Enter") {
          hlx_to_search_page(input.value);
        }
      });
    }
  });
});

function hlx_to_search_page(keyword: string) {
  const SEARCH_URL = "/web/column/col5003964.html";

  window.location.href = SEARCH_URL + "?keyword=" + keyword;
}

例子中将 用户查询的关键字 通过 keyword 进行传递。

但这并非硬性需求,可以根据自己需求灵活变更。

✨ 2、搜索页处理

搜索 API 固定为 /foreground-gateway/retrieval/intensify/search

ts
window.addEventListener("DOMContentLoaded", () => {
  const APP_ID = 30101;
  const HLX_SERCH_URL = "/foreground-gateway/retrieval/intensify/search";

  // 解析 url 中的 query
  const param = parseSearchParams();

  // 华龙网的 加密(签名) 方式
  const { data, signature, nonce, timestamp } = createHlxSearchParam(
    APP_ID,
    param
  );

  // 组装华龙网请求 url
  const url = `${HLX_SERCH_URL}?signature=${signature}&nonce=${nonce}&timestamp=${timestamp}`;

  // 发起 http 请求
  post(url, data, {
    onSuccess: (data) => {
      // 更具结果,渲染界面
      onHlxSearchSuccess(JSON.parse(data));
    },
    onError: (error) => {
      console.error(error);
    },
  });
});
parseSearchParams
ts
interface SearchParam {
  keyword: string | null;
  pageSize: number | null;
  currentPage: number | null;
}

export function getURLQuery(name: string) {
  const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
  const r = window.location.search.substr(1).match(reg);
  if (r != null) return decodeURIComponent(r[2]);
  return null;
}

export function parseSearchParams(): SearchParam {
  const keyword = getURLQuery("keyword");
  const pageSize = getURLQuery("pageSize");
  const currentPage = getURLQuery("currentPage");

  return {
    keyword: keyword,
    pageSize: pageSize ? +pageSize : null,
    currentPage: currentPage ? +currentPage : null,
  };
}
createHlxSearchParam
js
interface SearchParam {
  keyword: string | null;
  pageSize: number | null;
  currentPage: number | null;
}

export function createHlxSearchParam(appId: number, param: SearchParam) {
  const data = {
    appId: appId,
    fuzzyWord: param.keyword,
    currentPage: param.currentPage || 1,
    pageSize: param.pageSize || 20,
  };

  const nonce = createUniqueId();
  const timestamp = new Date().getTime();
  // @ts-ignore
  const signature = Encrypts.encryptParams(data, {
    nonce: nonce,
    timestamp: timestamp,
  });

  return {
    data: data,
    nonce: nonce,
    timestamp: timestamp,
    signature: signature,
  };
}

/**
 * 创建唯一标识
 * @returns {string} 唯一标识
 */
function createUniqueId() {
  var UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var LowerCase = "abcdefghijklmnopqrstuvwxyz";
  var num = "0123456789";

  var id = "";

  for (var i = 0; i < 6; i++) {
    var banks = UpperCase + LowerCase + num;
    var randomIndex = Math.floor(Math.random() * banks.length);
    id += banks[randomIndex];
  }

  return id;
}
post
ts
type IHttpHeaders = Record<string, string>;
interface JSONType {
  [key: string]: string | number | boolean | null | JSONType;
}

interface IHttpOptions {
  method?: "POST" | "GET" | "PUT" | "DELETE";
  headers?: IHttpHeaders;
  onSuccess: (data: string) => void;
  onError: (error: any) => void;
}

class HttpError extends Error {
  constructor(message: string, public status: number) {
    super(message);
  }
}

export const request = (
  url: string,
  data: JSONType | FormData,
  config: IHttpOptions
) => {
  const defaultOptions: IHttpHeaders = {
    "Content-Type": "application/json",
  };

  const method =
    config.method && typeof config.method === "string"
      ? config.method.toLocaleUpperCase()
      : "GET";

  const http = new XMLHttpRequest();

  let url2 = url;
  if (method === "GET") {
    if (data instanceof FormData) {
      throw new Error("GET 的 data **不** 应该是 FormData");
    }
    const queryString = dataToQueryString(data);

    url2 = url + "?" + queryString;
  }

  http.open(method, url2, true);

  const headers = { ...defaultOptions, ...config.headers };

  let contentType = "";
  for (const key in headers) {
    if (key.toLocaleUpperCase() === "CONTENT-TYPE") {
      contentType = headers[key];
    } else {
      http.setRequestHeader(key, headers[key]);
    }
  }

  if (method === "POST" || method === "PUT") {
    const isFromData = data instanceof FormData;

    if (contentType === "application/json") {
      if (isFromData) {
        throw new Error("application/json 的 data **不** 应该是 FormData");
      }
      onPostByJson(http, data);
    } else if (contentType === "application/x-www-form-urlencoded") {
      if (isFromData) {
        throw new Error(
          "application/x-www-form-urlencoded 的 data **不** 应该是 FormData"
        );
      }
      onPostByUrlEncoded(http, data);
    } else if (contentType === "multipart/form-data") {
      if (isFromData) {
        onPostByFormData(http, data);
      } else {
        throw new Error("multipart/form-data 的 data 应该是 FormData");
      }
    } else {
      throw new Error("未实现的 content type: " + contentType);
    }
  }

  http.onreadystatechange = function () {
    // readyState
    // 0: 未初始化
    // 1: 已打开
    // 2: 已发送
    // 3: 接收中
    // 4: 完成

    if (http.readyState === 4) {
      if (http.status === 200) {
        config.onSuccess(http.responseText);
      } else {
        config.onError(new HttpError("请求失败", http.status));
      }
    }
  };
};

export const get = (url: string, data: JSONType, config: IHttpOptions) => {
  return request(url, data, { ...config, method: "GET" });
};

export const post = (url: string, data: JSONType, config: IHttpOptions) => {
  return request(url, data, { ...config, method: "POST" });
};

// ------------------------------------------------------------

function onPostByJson(xhr: XMLHttpRequest, data: JSONType) {
  xhr.setRequestHeader("Content-Type", "application/json");
  const body = JSON.stringify(data);
  xhr.send(body);
}

function onPostByUrlEncoded(xhr: XMLHttpRequest, data: JSONType) {
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

  const queryString = dataToQueryString(data);

  xhr.send(queryString);
}

function onPostByFormData(xhr: XMLHttpRequest, data: FormData) {
  if (!data) throw new Error("data is required");

  if (data instanceof FormData === false) {
    throw new Error("data must be a FormData instance");
  }

  xhr.setRequestHeader("Content-Type", "multipart/form-data");
  xhr.send(data);
}

function dataToQueryString(data: JSONType) {
  const params: string[] = [];

  if (data) {
    for (const key in data) {
      const value = data[key];
      params.push(`${key}=${value}`);
    }
  }

  return params.join("&");
}