小组件:一站式 AI 行业信息源

经验创意 · 88 次浏览
我的梦想捐钱修路建学校 创建于 22天10小时前

一站式 AI 行业信息源 Virxact AI HOT

当下的 AI 一直在不断的革命性发展,这让我们很难快速的了解业内最新动态。

这是一个用来监控全网与 AI 技术相关的优质信息的网站,总共168个优质信息源,

涵盖模型、产品、行业、论文和技巧,通过AI评分与精选,帮你精准获取信息。

https://aihot.virxact.com/

 

GPT老师写的

AI生成不一定完美,有朋友手动调整过的可把修改更完美的版本发出来给大伙用用

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Virxact AI HOT</title>
<style>
html,body{
    margin:0;
    width:100%;
    height:100%;
    overflow:hidden;
    background:transparent;
    font-family:"Microsoft YaHei",sans-serif;
    font-size:13px;
}
*{box-sizing:border-box}
button,input{
    border:none;
    outline:none;
    font:inherit;
}
button{
    cursor:pointer;
    transition:.16s ease;
}
button:active{
    transform:scale(.98);
}
.card{
    width:100%;
    height:100%;
    border-radius:18px;
    border:1px solid rgba(120,180,255,.22);
    background:linear-gradient(180deg,rgba(30,38,55,.98),rgba(14,18,28,.98));
    box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 10px 30px rgba(0,0,0,.35);
    display:flex;
    flex-direction:column;
    overflow:hidden;
    color:#dbe7ff;
}
.header{
    padding:12px 14px;
    display:flex;
    align-items:center;
    gap:8px;
    border-bottom:1px solid rgba(255,255,255,.08);
}
.logo{
    width:10px;
    height:10px;
    border-radius:50%;
    background:#6fb3ff;
    box-shadow:0 0 10px rgba(111,179,255,.8);
    flex:0 0 auto;
}
.title{
    flex:1;
    font-weight:700;
    font-size:14px;
    letter-spacing:.2px;
}
.toolbar-row{
    display:flex;
    align-items:center;
    gap:8px;
    padding:10px 12px;
    border-bottom:1px solid rgba(255,255,255,.06);
}
.topbar{
    display:flex;
    align-items:center;
    gap:6px;
    flex:1;
    min-width:0;
}
.topbar button,
.epdff-fixed-highlight > button{
    height:34px;
    border-radius:10px;
    padding:0 12px;
    color:#fff;
    background:rgba(255,255,255,.08);
    border:1px solid rgba(255,255,255,.06);
    font-size:12px;
}
.topbar button:hover,
.epdff-fixed-highlight > button:hover{
    background:rgba(111,179,255,.22);
    border-color:rgba(111,179,255,.26);
}
.topbar button.active{
    background:linear-gradient(180deg,rgba(111,179,255,.28),rgba(111,179,255,.16));
    border-color:rgba(111,179,255,.45);
    box-shadow:0 0 0 1px rgba(111,179,255,.08) inset;
}

.epdff-fixed-highlight{
    position:relative;
    display:block;
}

.epdff-fixed-highlight > button{
    display:flex;
    align-items:center;
    gap:8px;
    justify-content:space-between;
    white-space:nowrap;
}
.chev{
    width:0;
    height:0;
    border-left:5px solid transparent;
    border-right:5px solid transparent;
    border-top:6px solid rgba(255,255,255,.9);
    opacity:.85;
}
.menu{
    position:absolute;
    top:42px;
    right:0;
    width:260px;
    z-index:30;
    display:none;
    border-radius:16px;
    border:1px solid rgba(132,176,255,.24);
    background:linear-gradient(180deg,rgba(10,14,24,.98),rgba(18,24,38,.98));
    box-shadow:0 18px 45px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.06);
    overflow:hidden;
    backdrop-filter:blur(10px);
}
.menu.open{display:block}
.menu-head{
    padding:12px 12px 10px;
    border-bottom:1px solid rgba(255,255,255,.07);
    background:rgba(255,255,255,.02);
}
.menu-title{
    font-size:12px;
    font-weight:700;
    color:#f2f7ff;
    line-height:1.3;
}
.menu-sub{
    margin-top:4px;
    font-size:11px;
    color:#9eb4d8;
    line-height:1.45;
}
.menu-list{
    max-height:280px;
    overflow:auto;
    padding:8px;
}
.menu-list::-webkit-scrollbar,
.content::-webkit-scrollbar{
    width:8px;
}
.menu-list::-webkit-scrollbar-thumb,
.content::-webkit-scrollbar-thumb{
    background:#394357;
    border-radius:20px;
}
.menu-item{
    width:100%;
    text-align:left;
    padding:10px 11px;
    border-radius:12px;
    color:#e8f1ff;
    background:transparent;
    border:1px solid transparent;
    display:flex;
    align-items:flex-start;
    gap:10px;
    font-size:12px;
}
.menu-item:hover{
    background:rgba(111,179,255,.12);
    border-color:rgba(111,179,255,.18);
}
.menu-item.active{
    background:linear-gradient(180deg,rgba(111,179,255,.22),rgba(111,179,255,.12));
    border-color:rgba(111,179,255,.34);
}
.menu-dot{
    width:8px;
    height:8px;
    margin-top:5px;
    border-radius:50%;
    background:#7dbbff;
    box-shadow:0 0 10px rgba(125,187,255,.7);
    flex:0 0 auto;
}
.menu-text{
    min-width:0;
    flex:1;
}
.menu-name{
    font-size:12px;
    font-weight:700;
    line-height:1.3;
}
.menu-desc{
    margin-top:3px;
    font-size:11px;
    color:#aab9d4;
    line-height:1.4;
}
.search{
    display:flex;
    gap:6px;
    padding:0 12px 10px;
}
.search input{
    flex:1;
    height:36px;
    border-radius:10px;
    padding:0 10px;
    background:rgba(255,255,255,.08);
    color:#fff;
    font-size:12px;
}
.search input::placeholder{
    color:#a0b2d6;
}
.search button{
    height:36px;
    padding:0 14px;
    border-radius:10px;
    background:rgba(255,255,255,.08);
    color:#fff;
    border:1px solid rgba(255,255,255,.06);
    font-size:12px;
}
.search button:hover{
    background:rgba(111,179,255,.22);
    border-color:rgba(111,179,255,.26);
}
.content{
    flex:1;
    overflow:auto;
    padding:10px 12px;
}
.item{
    padding:10px;
    border:1px solid rgba(255,255,255,.06);
    background:rgba(255,255,255,.03);
    border-radius:12px;
    margin-bottom:8px;
}
.item:hover{
    background:rgba(255,255,255,.05);
}
.item-title{
    font-size:14px;
    font-weight:700;
    line-height:1.45;
}
.link{
    cursor:pointer;
}
.meta{
    margin-top:6px;
    display:flex;
    gap:8px;
    flex-wrap:wrap;
    font-size:12px;
    color:#93a6cb;
}
.summary{
    margin-top:8px;
    font-size:12px;
    color:#d7e2f6;
    line-height:1.55;
}
.score{
    color:#7ed6a7;
    font-weight:700;
}
.tag{
    padding:2px 6px;
    border-radius:999px;
    background:rgba(111,179,255,.15);
    color:#d7e8ff;
}
.footer{
    padding:10px 12px;
    display:flex;
    gap:8px;
    border-top:1px solid rgba(255,255,255,.06);
}
.status{
    flex:1;
    font-size:12px;
    color:#91a6d0;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
}
.ui-btn{
    height:34px;
    padding:0 14px;
    border-radius:10px;
    color:#fff;
    background:rgba(255,255,255,.08);
    border:1px solid rgba(255,255,255,.06);
    font-size:12px;
    cursor:pointer;
    transition:.16s ease;
}
.ui-btn:hover{
    background:rgba(111,179,255,.22);
    border-color:rgba(111,179,255,.26);
}
.ui-btn:active{
    transform:scale(.98);
}
.daily-block{
    margin-bottom:14px;
}
.daily-title{
    font-size:16px;
    font-weight:700;
    margin-bottom:8px;
}
.section{
    margin-bottom:12px;
}
.section h4{
    margin:0 0 8px;
    color:#7db5ff;
    font-size:13px;
}
.empty{
    opacity:.7;
    padding:10px 2px;
}
@media (max-width:520px){
    .toolbar-row{
        gap:6px;
    }
    .menu{
        width:min(260px,calc(100vw - 24px));
    }
}
</style>
</head>
<body>
<div class="card">
    <div class="header">
        <div class="logo"></div>
        <div class="title">Virxact AI HOT</div>
    </div>

    <div class="toolbar-row">
        <div class="topbar">
            <button id="tabNews" class="active">AI动态</button>
            <button id="tabDaily">最新日报</button>
            <button id="tabArchive">日报归档</button>
        </div>

        <div class="epdff-fixed-highlight">
            <button id="projectBtn" type="button" aria-haspopup="true" aria-expanded="false">
                <span id="projectLabel">精选</span>
                <span class="chev"></span>
            </button>

            <div id="projectMenu" class="menu" role="menu" aria-label="项目选择">
                <div class="menu-head">
                    <div class="menu-title">切换项目</div>
                    <div class="menu-sub">更改后会立即刷新下方内容,不需要再点一次。</div>
                </div>
                <div id="projectList" class="menu-list"></div>
            </div>
        </div>
    </div>

    <div class="search">
        <input id="keyword" placeholder="搜索 OpenAI、Claude、Gemini..." />
        <button id="searchBtn">搜索</button>
    </div>

    <div id="content" class="content">
        <div class="empty">正在初始化...</div>
    </div>

    <div class="footer">
        <div id="status" class="status">就绪</div>
        <button id="moreBtn" class="ui-btn">更多</button>
    </div>
</div>

<script>
(function(){

const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124 Safari/537.36";

const PROJECTS = [
    { id: "selected",   label: "精选",    desc: "优先显示精选内容" },
    { id: "all",        label: "全部",    desc: "显示全部项目" },
    { id: "ai-models",  label: "模型",    desc: "大模型、推理、基础模型" },
    { id: "ai-products", label: "产品",   desc: "AI 产品、应用、工具" },
    { id: "industry",   label: "行业",    desc: "行业动态与趋势" },
    { id: "paper",      label: "论文",    desc: "研究论文与技术报告" },
    { id: "tip",        label: "技巧",    desc: "实用技巧与工作流" }
];

const state = {
    mode: "news",
    cursor: null,
    loading: false,
    project: "selected"
};

function $(id){ return document.getElementById(id); }
const content = $("content");
const statusEl = $("status");
const projectBtn = $("projectBtn");
const projectMenu = $("projectMenu");
const projectList = $("projectList");
const projectLabel = $("projectLabel");

function setStatus(t){
    statusEl.textContent = t || "";
}

function esc(v){
    return String(v ?? "")
        .replace(/&/g,"&amp;")
        .replace(/</g,"&lt;")
        .replace(/>/g,"&gt;")
        .replace(/"/g,"&quot;");
}

function waitHost(){
    if(window.fudao && typeof window.fudao.invoke === "function"){
        init();
        return;
    }
    setTimeout(waitHost, 300);
}

async function hostInvoke(method, args){
    return await window.fudao.invoke(method, args);
}

async function httpGet(url){
    const res = await hostInvoke("http.get", {
        url,
        timeoutMs: 15000,
        headers: {
            "User-Agent": UA
        }
    });

    if(!res || !res.ok){
        throw new Error("HTTP " + (res?.status || "ERR"));
    }

    return JSON.parse(res.text);
}

async function openUrl(url){
    try{
        await hostInvoke("url.open", {
            url,
            closeAfterOpen: false
        });
    }catch(e){}
}

function setActiveTab(id){
    ["tabNews","tabDaily","tabArchive"].forEach(x => {
        $(x).classList.toggle("active", x === id);
    });
}

function getProjectMeta(id){
    return PROJECTS.find(p => p.id === id) || PROJECTS[0];
}

function syncProjectUI(){
    const p = getProjectMeta(state.project);
    projectLabel.textContent = p.label;
    projectBtn.setAttribute("aria-expanded", projectMenu.classList.contains("open") ? "true" : "false");
    projectList.querySelectorAll(".menu-item").forEach(el => {
        el.classList.toggle("active", el.dataset.project === state.project);
    });
}

function closeProjectMenu(){
    projectMenu.classList.remove("open");
    projectBtn.setAttribute("aria-expanded", "false");
}

function toggleProjectMenu(){
    projectMenu.classList.toggle("open");
    projectBtn.setAttribute("aria-expanded", projectMenu.classList.contains("open") ? "true" : "false");
    syncProjectUI();
}

function buildProjectMenu(){
    projectList.innerHTML = PROJECTS.map(p => `
        <button class="menu-item ${p.id === state.project ? "active" : ""}" data-project="${esc(p.id)}" type="button">
            <span class="menu-dot"></span>
            <span class="menu-text">
                <div class="menu-name">${esc(p.label)}</div>
                <div class="menu-desc">${esc(p.desc)}</div>
            </span>
        </button>
    `).join("");

    projectList.querySelectorAll(".menu-item").forEach(btn => {
        btn.onclick = () => applyProject(btn.dataset.project);
    });

    syncProjectUI();
}

function projectToQuery(){
    if(state.project === "selected"){
        return { mode: "selected", category: "" };
    }
    if(state.project === "all"){
        return { mode: "all", category: "" };
    }
    return { mode: "selected", category: state.project };
}

function renderItems(items, append){
    if(!append) content.innerHTML = "";

    if(!items || !items.length){
        if(!append){
            content.innerHTML = `<div class="empty">暂无数据</div>`;
        }
        return;
    }

    const html = items.map(item => `
        <div class="item">
            <div class="item-title link" data-url="${esc(item.url)}">
                ${esc(item.title)}
            </div>

            <div class="meta">
                <span>${esc(item.source || "-")}</span>
                ${item.category ? `<span class="tag">${esc(item.category)}</span>` : ""}
                ${item.score != null ? `<span class="score">★ ${esc(item.score)}</span>` : ""}
                ${item.selected ? `<span class="tag">精选</span>` : ""}
            </div>

            ${item.summary ? `
            <div class="summary">
                ${esc(item.summary)}
            </div>` : ""}
        </div>
    `).join("");

    if(append){
        content.insertAdjacentHTML("beforeend", html);
    }else{
        content.innerHTML = html;
    }

    content.querySelectorAll("[data-url]").forEach(el => {
        el.onclick = () => openUrl(el.dataset.url);
    });
}

async function loadNews(reset = true){
    if(state.loading) return;
    state.loading = true;

    try{
        if(reset){
            state.cursor = null;
        }

        setActiveTab("tabNews");
        setStatus("加载AI动态...");

        const keyword = $("keyword").value.trim();
        const qp = projectToQuery();

        let url = "https://aihot.virxact.com/api/public/items?take=50";
        url += "&mode=" + encodeURIComponent(qp.mode);

        if(qp.category){
            url += "&category=" + encodeURIComponent(qp.category);
        }

        if(keyword){
            url += "&q=" + encodeURIComponent(keyword);
        }

        if(state.cursor){
            url += "&cursor=" + encodeURIComponent(state.cursor);
        }

        const data = await httpGet(url);

        state.cursor = data.nextCursor;
        renderItems(data.items, !reset);

        setStatus(`共 ${data.count ?? 0} 条 · ${data.hasNext ? "可继续翻页" : "已到底"}`);
    }catch(e){
        content.innerHTML = `<div class="empty">加载失败:${esc(e.message)}</div>`;
        setStatus("请求失败");
    }

    state.loading = false;
}

async function loadDaily(){
    state.mode = "daily";
    setActiveTab("tabDaily");

    try{
        setStatus("加载最新日报...");
        content.innerHTML = "";

        const data = await httpGet("https://aihot.virxact.com/api/public/daily");

        let html = `
            <div class="daily-block">
                <div class="daily-title">${esc(data.date || "")}</div>
            </div>
        `;

        if(data.lead){
            html += `
                <div class="item">
                    <div class="item-title">${esc(data.lead.title || "")}</div>
                    <div class="summary">${esc(data.lead.leadParagraph || "")}</div>
                </div>
            `;
        }

        (data.sections || []).forEach(sec => {
            html += `
                <div class="section">
                    <h4>${esc(sec.label || "")}</h4>
                    ${
                        (sec.items || []).map(i => `
                            <div class="item">
                                <div class="item-title">${esc(i.title || "")}</div>
                                <div class="summary">${esc(i.summary || "")}</div>
                            </div>
                        `).join("") || `<div class="empty">暂无内容</div>`
                    }
                </div>
            `;
        });

        if(data.flashes && data.flashes.length){
            html += `<div class="section"><h4>快讯</h4>`;
            data.flashes.forEach(f => {
                html += `
                    <div class="item">
                        <div class="item-title link" data-url="${esc(f.sourceUrl || "")}">
                            ${esc(f.title || "")}
                        </div>
                        <div class="meta">${esc(f.sourceName || "")}</div>
                    </div>
                `;
            });
            html += `</div>`;
        }

        content.innerHTML = html;

        content.querySelectorAll("[data-url]").forEach(el => {
            el.onclick = () => openUrl(el.dataset.url);
        });

        setStatus("日报加载完成");
    }catch(e){
        content.innerHTML = `<div class="empty">加载失败:${esc(e.message)}</div>`;
        setStatus("请求失败");
    }
}

async function loadArchive(){
    state.mode = "archive";
    setActiveTab("tabArchive");

    try{
        setStatus("加载日报归档...");
        content.innerHTML = "";

        const data = await httpGet("https://aihot.virxact.com/api/public/dailies?take=180");

        content.innerHTML = (data.items || []).map(d => `
            <div class="item">
                <div class="item-title">${esc(d.date || "")}</div>
                <div class="summary">${esc(d.leadTitle || "无标题")}</div>
            </div>
        `).join("") || `<div class="empty">暂无归档</div>`;

        setStatus(`共 ${data.count ?? 0} 期日报`);
    }catch(e){
        content.innerHTML = `<div class="empty">加载失败:${esc(e.message)}</div>`;
        setStatus("请求失败");
    }
}

function applyProject(projectId){
    state.project = projectId;
    buildProjectMenu();
    closeProjectMenu();

    state.mode = "news";
    setActiveTab("tabNews");
    loadNews(true);
}

function bindEvents(){
    $("tabNews").onclick = () => {
        state.mode = "news";
        loadNews(true);
    };

    $("tabDaily").onclick = loadDaily;
    $("tabArchive").onclick = loadArchive;

    $("searchBtn").onclick = () => {
        state.mode = "news";
        setActiveTab("tabNews");
        loadNews(true);
    };

    $("keyword").addEventListener("keydown", (e) => {
        if(e.key === "Enter"){
            e.preventDefault();
            $("searchBtn").click();
        }
    });

    $("moreBtn").onclick = () => {
        if(state.mode === "news" && state.cursor){
            loadNews(false);
        }
    };

    projectBtn.onclick = (e) => {
        e.stopPropagation();
        toggleProjectMenu();
    };

    document.addEventListener("click", () => closeProjectMenu());

    projectMenu.addEventListener("click", (e) => {
        e.stopPropagation();
    });

    document.addEventListener("keydown", (e) => {
        if(e.key === "Escape"){
            closeProjectMenu();
        }
    });
}

function init(){
    buildProjectMenu();
    bindEvents();
    loadNews(true);
}

waitHost();

})();
</script>
</body>
</html>

我的梦想捐钱修路建学校 最后更新于 2026/6/11

回复内容
暂无回复
回复主贴