求助 QueryView 插件无法渲染证件倒计时组件(代码已验证有效)

问题描述

我通过腾讯元宝 AI 生成了一个证件倒计时组件代码(功能完整),在以下环境中已验证运行正常:
✅ 腾讯元宝 AI 自带预览功能
✅ 第三方在线代码运行工具网站

但使用思源笔记的 Query&View 插件 时,始终无法渲染出倒计时效果。


我的操作步骤

  1. 安装插件
  • 通过集市安装最新版 Query & View 插件(版本:v1.2.3 )
  1. 插入查询块
  • 新建文档后,输入 / 调出插入菜单
  • 尝试过以下插入方式:
    • Query & View 基本模板
    • HTML 块
    • 嵌入块
    • 代码块(语言设置为 JavaScript)
  1. 粘贴代码
  • 全选复制 AI 生成的代码(代码见下方)
  • 完全覆盖 查询块中的默认内容
  1. 触发渲染
  • 点击代码块外部区域
  • 预期:插件自动解析 JS 代码并渲染组件
  • 实际:无任何变化,页面空白

代码与效果

证件倒计时代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>车辆证件到期倒计时</title>
<style>
  /* 核心样式 - 思源笔记兼容 */
  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f8f9fa;
    color: #333;
  }

  #licenses-container {
    display: flex;
    justify-content: space-around;
    flex-wrap: wrap;
    gap: 20px;
    max-width: 1200px;
    margin: 20px auto;
    padding: 0 15px;
  }

  .license-card {
    background-color: #fff;
    border-radius: 12px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
    padding: 24px;
    min-width: 320px;
    max-width: 360px;
    flex: 1;
    transition: transform 0.3s ease;
    position: relative;
  }

  .license-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
  }

  .card-header {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
    padding-bottom: 15px;
    border-bottom: 1px solid #eef2f7;
  }

  .icon-container {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 15px;
    font-size: 22px;
    font-weight: bold;
  }

  .card-title {
    font-size: 20px;
    font-weight: 600;
    color: #2c3e50;
  }

  .date-info {
    margin-bottom: 25px;
  }

  .date-row {
    display: flex;
    margin-bottom: 12px;
  }

  .date-label {
    min-width: 80px;
    color: #777;
    font-size: 14px;
  }

  .date-value {
    font-weight: 500;
    font-size: 15px;
    color: #444;
  }

  .countdown-section {
    background-color: #f9fafb;
    border-radius: 8px;
    padding: 15px;
    margin-bottom: 20px;
    text-align: center;
  }

  .days-count {
    font-size: 32px;
    font-weight: 700;
    margin-bottom: 5px;
  }

  .days-label {
    font-size: 14px;
    color: #666;
  }

  .status-section {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .status-indicator {
    padding: 6px 14px;
    border-radius: 20px;
    font-size: 14px;
    font-weight: 600;
  }

  .progress-container {
    flex-grow: 1;
    margin-left: 15px;
  }

  .progress-header {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: #777;
    margin-bottom: 6px;
  }

  .progress-bar {
    height: 10px;
    background-color: #e9ecef;
    border-radius: 5px;
    overflow: hidden;
  }

  .progress-value {
    height: 100%;
    transition: width 0.8s ease;
    border-radius: 5px;
  }

  /* 证件专属颜色 */
  #driver-card .icon-container { background-color: #e3f2fd; color: #1565c0; }
  #driver-card .progress-value { background-color: #42a5f5; }

  #vehicle-card .icon-container { background-color: #e8f5e9; color: #2e7d32; }
  #vehicle-card .progress-value { background-color: #66bb6a; }

  #inspection-card .icon-container { background-color: #f3e5f5; color: #7b1fa2; }
  #inspection-card .progress-value { background-color: #ab47bc; }

  /* 状态颜色 */
  .status-normal { background-color: #e8f5e9; color: #2e7d32; }
  .status-warning { background-color: #fff8e1; color: #f57c00; animation: pulse 2s infinite; }
  .status-expired { background-color: #ffebee; color: #d32f2f; }

  @keyframes pulse {
    0% { opacity: 1; }
    50% { opacity: 0.7; }
    100% { opacity: 1; }
  }

  /* 响应式设计 */
  @media (max-width: 1000px) {
    #licenses-container {
      flex-direction: column;
      align-items: center;
    }
  
    .license-card {
      width: 100%;
      max-width: 500px;
    }
  }

  @media (max-width: 500px) {
    .license-card {
      min-width: unset;
      padding: 18px;
    }
  
    .card-header {
      flex-direction: column;
      align-items: flex-start;
    }
  
    .icon-container {
      margin-bottom: 12px;
      margin-right: 0;
    }
  }
</style>
</head>
<body>
<div id="licenses-container">
  <!-- 驾驶证卡片 -->
  <div class="license-card" id="driver-card">
    <div class="card-header">
      <div class="icon-container">D</div>
      <div class="card-title">驾驶证</div>
    </div>
  
    <div class="date-info">
      <div class="date-row">
        <div class="date-label">领取日期:</div>
        <div class="date-value" id="driver-issue">2020-12-28</div>
      </div>
      <div class="date-row">
        <div class="date-label">到期日期:</div>
        <div class="date-value" id="driver-expiry">2026-12-28</div>
      </div>
    </div>
  
    <div class="countdown-section">
      <div class="days-count" id="driver-days">计算中...</div>
      <div class="days-label">剩余天数</div>
    </div>
  
    <div class="status-section">
      <div class="status-indicator" id="driver-status">正常</div>
      <div class="progress-container">
        <div class="progress-header">
          <span>有效期进度</span>
          <span id="driver-progress-label">0%</span>
        </div>
        <div class="progress-bar">
          <div class="progress-value" id="driver-progress" style="width: 0%"></div>
        </div>
      </div>
    </div>
  </div>
  
  <!-- 行驶证卡片 -->
  <div class="license-card" id="vehicle-card">
    <div class="card-header">
      <div class="icon-container">V</div>
      <div class="card-title">行驶证</div>
    </div>
  
    <div class="date-info">
      <div class="date-row">
        <div class="date-label">领取日期:</div>
        <div class="date-value" id="vehicle-issue">2021-06-15</div>
      </div>
      <div class="date-row">
        <div class="date-label">到期日期:</div>
        <div class="date-value" id="vehicle-expiry">2027-06-15</div>
      </div>
    </div>
  
    <div class="countdown-section">
      <div class="days-count" id="vehicle-days">计算中...</div>
      <div class="days-label">剩余天数</div>
    </div>
  
    <div class="status-section">
      <div class="status-indicator" id="vehicle-status">正常</div>
      <div class="progress-container">
        <div class="progress-header">
          <span>有效期进度</span>
          <span id="vehicle-progress-label">0%</span>
        </div>
        <div class="progress-bar">
          <div class="progress-value" id="vehicle-progress" style="width: 0%"></div>
        </div>
      </div>
    </div>
  </div>
  
  <!-- 检验合格标志卡片 -->
  <div class="license-card" id="inspection-card">
    <div class="card-header">
      <div class="icon-container">C</div>
      <div class="card-title">检验合格标志</div>
    </div>
  
    <div class="date-info">
      <div class="date-row">
        <div class="date-label">领取日期:</div>
        <div class="date-value" id="inspection-issue">2025-04-07</div>
      </div>
      <div class="date-row">
        <div class="date-label">到期日期:</div>
        <div class="date-value" id="inspection-expiry">2027-06-30</div>
      </div>
    </div>
  
    <div class="countdown-section">
      <div class="days-count" id="inspection-days">计算中...</div>
      <div class="days-label">剩余天数</div>
    </div>
  
    <div class="status-section">
      <div class="status-indicator" id="inspection-status">正常</div>
      <div class="progress-container">
        <div class="progress-header">
          <span>有效期进度</span>
          <span id="inspection-progress-label">0%</span>
        </div>
        <div class="progress-bar">
          <div class="progress-value" id="inspection-progress" style="width: 0%"></div>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
// 证件数据
const documents = {
  driver: {
    title: "驾驶证",
    icon: "D",
    issueDate: "2020-12-28",
    expiryDate: "2026-12-28"
  },
  vehicle: {
    title: "行驶证",
    icon: "V",
    issueDate: "2021-06-15",
    expiryDate: "2027-06-15"
  },
  inspection: {
    title: "检验合格标志",
    icon: "C",
    issueDate: "2025-04-07",
    expiryDate: "2027-06-30"
  }
};

// 计算剩余天数
function calculateRemainingDays(expiryDateStr) {
  const expiryDate = new Date(expiryDateStr);
  const now = new Date();
  
  // 将时间设置为00:00:00进行比较
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  expiryDate.setHours(0, 0, 0, 0);
  
  const diffTime = expiryDate.getTime() - today.getTime();
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}

// 计算有效期进度百分比
function calculateProgress(issueDateStr, expiryDateStr) {
  const issueDate = new Date(issueDateStr);
  const expiryDate = new Date(expiryDateStr);
  const now = new Date();
  
  // 将时间设置为00:00:00进行比较
  issueDate.setHours(0, 0, 0, 0);
  expiryDate.setHours(0, 0, 0, 0);
  
  const totalDuration = expiryDate.getTime() - issueDate.getTime();
  const elapsedDuration = now.getTime() - issueDate.getTime();
  
  return Math.max(0, Math.min(100, Math.floor((elapsedDuration / totalDuration) * 100)));
}

// 更新证件状态信息
function updateDocumentStatus(type, daysRemaining, progress) {
  const daysElement = document.getElementById(`${type}-days`);
  const statusElement = document.getElementById(`${type}-status`);
  const progressElement = document.getElementById(`${type}-progress`);
  const progressLabel = document.getElementById(`${type}-progress-label`);
  
  // 更新剩余天数
  daysElement.textContent = daysRemaining;
  
  // 更新进度条
  progressElement.style.width = `${progress}%`;
  progressLabel.textContent = `${progress}%`;
  
  // 更新状态标签
  if (daysRemaining < 0) {
    daysElement.style.color = '#d32f2f';
    statusElement.className = 'status-indicator status-expired';
    statusElement.textContent = `已过期 ${Math.abs(daysRemaining)} 天`;
  } else if (daysRemaining === 0) {
    daysElement.style.color = '#d32f2f';
    statusElement.className = 'status-indicator status-expired';
    statusElement.textContent = '今天到期';
  } else if (daysRemaining <= 30) {
    daysElement.style.color = '#f57c00';
    statusElement.className = 'status-indicator status-warning';
    statusElement.textContent = `即将到期 (${daysRemaining}天)`;
  } else {
    daysElement.style.color = '#2e7d32';
    statusElement.className = 'status-indicator status-normal';
    statusElement.textContent = '状态正常';
  }
}

// 更新所有证件信息
function updateAllDocuments() {
  for (const type in documents) {
    const doc = documents[type];
  
    // 更新页面上的日期显示
    document.getElementById(`${type}-issue`).textContent = doc.issueDate;
    document.getElementById(`${type}-expiry`).textContent = doc.expiryDate;
  
    // 计算剩余天数
    const daysRemaining = calculateRemainingDays(doc.expiryDate);
  
    // 计算进度条百分比
    const progress = calculateProgress(doc.issueDate, doc.expiryDate);
  
    // 更新组件显示
    updateDocumentStatus(type, daysRemaining, progress);
  }
}

// 初始化
document.addEventListener('DOMContentLoaded', () => {
  // 第一次更新
  updateAllDocuments();
  
  // 设置每日更新的定时器 (12小时更新一次)
  setInterval(updateAllDocuments, 12 * 60 * 60 * 1000);
});
</script>
</body>
</html>

代码显示效果(在线工具运行截图):

20250728210343.png

主要功能展示:

  • 三张卡片并排显示:驾驶证、行驶证、检验合格标志
  • 证件信息:清晰的领取日期和到期日期
  • 倒计时显示:显眼的剩余天数
  • 进度条:直观展示有效期进度百分比
  • 状态指示:绿色(正常)、橙色(临期)、红色(过期)
  • 实时更新:每天自动刷新倒计时

已排查项

检查项 状态 说明
插件启用状态 ✔️ 正常 插件管理界面显示已开启
代码独立运行能力 ✔️ 有效 在线工具网站可正常渲染
块类型选择 ❓ 不清楚 尝试过多种块类型均失败
浏览器开发者工具报错 ❓ 看不懂 控制台错误信息每次不同

环境信息

  • 思源笔记版本:当前版本 v3.2.1
  • 操作系统:Windows 10 专业版
  • 使用方式:本地存储 电脑客户端

求助方向

  1. 插件的使用方式
    • QueryView 插件究竟该如何操作?是否需要特殊声明?
    • 是否需在代码外包裹特定容器?
    • 选择插入哪种块查询?Query & View 基本模板、HTML 块、嵌入块、代码块(语言设置为 JavaScript)?
  2. 权限和教程问题
    • 插件是否需要额外授权才能执行?
    • 有没有简单一些的插件使用教程?最好通俗易懂点,本人程序小白一枚~~

感谢

恳请社区高手协助! 若有需要补充的信息请随时告知,感谢! 🙏

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    28446 引用 • 119783 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    11155 引用 • 50664 回帖 • 52 关注
2 操作
xueluo 在 2025-07-28 21:22:57 更新了该帖
xueluo 在 2025-07-28 21:21:38 更新了该帖

相关帖子

被采纳的回答

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...