将代码复制到哪吒面板后台的自定义代码

日期+剩余天数

<script>
window.onload = function() {
  // 定义产品的详细数据,包括价格、周期、开始和到期日期以及商家名称
  const extraData = {
    1: { price: '0.84€', cycle: 'Month', start: '2024-10-30', expire: '2024-10-31', merchant: 'MerchantA' },
    2: { price: 'FREE', cycle: 'Month', start: '2021-04-15', expire: '∞', merchant: 'MerchantB' },
    3: { price: '24¥', cycle: 'Month', start: '2023-12-24', expire: '2024-12-25', merchant: 'MerchantC' },
    4: { price: '5$', cycle: 'Month', start: '2024-03-05', expire: '2024-05-31', merchant: 'MerchantA' },
    5: { price: 'FREE', cycle: 'Year', start: '2023-05-03', expire: '2025-04-03', merchant: 'MerchantB' }
  };

  // 定义商家与其支付页面的 URL 映射
  const merchantUrls = {
    MerchantA: 'https://merchantA.com/payment',
    MerchantB: 'https://merchantB.com/payment',
    MerchantC: 'https://merchantC.com/payment'
  };

  // 设置到期阈值,当进度条超过此百分比时颜色变为红色
  const threshold = 80;

  // 获取页面上所有的 .ui.accordion 元素
  const cats = document.querySelectorAll('.ui.accordion');
  cats.forEach((e, i) => {
    let $catsTitle = e.querySelector('.title');  
    let ct = $catsTitle.innerText.trim();        
    if (ct === '默认') return; // 跳过标题为“默认”的元素

    let $itemCard = e.querySelectorAll('.ui.card');  
    let uiCardCount = $itemCard.length;              
    $catsTitle.innerHTML = $catsTitle.innerHTML.replace(ct, `${ct} (${uiCardCount})`); // 在标题中显示卡片数量

    // 遍历每个卡片,插入价格和到期信息
    $itemCard.forEach((ee, ii) => {
      let $descriptionGrid = ee.querySelector('.description .ui.grid');  
      let id = ee.getAttribute('id');  

      // 确保 id 存在于 extraData 中
      if (extraData.hasOwnProperty(id)) {
        let { price, start, expire, cycle, merchant } = extraData[id];

        if (price) {
          // 插入价格标签
          let $priceL = document.createElement('div');
          $priceL.setAttribute('class', 'three wide column');
          $priceL.innerHTML = '价格';
          $descriptionGrid.insertBefore($priceL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $priceR = document.createElement('div');
          $priceR.setAttribute('class', 'thirteen wide column');
          // 在价格标签中插入周期链接,点击后跳转到商家的支付页面
          $priceR.innerHTML = `  
            <div class="ui green label" style="border-radius: 8px; display: inline-block;">
              <i class="money bill alternate yellow icon"></i>${price}
              <a href="${merchantUrls[merchant]}" target="_blank" class="detail" style="color: inherit; text-decoration: underline;">${cycle}</a>
            </div>`;
          $descriptionGrid.insertBefore($priceR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }

        if (expire) {
          // 插入到期标签
          let $expireL = document.createElement('div');
          $expireL.setAttribute('class', 'three wide column');
          $expireL.innerHTML = '到期';
          $descriptionGrid.insertBefore($expireL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $expireR = document.createElement('div');
          let beginTime = new Date(start).getTime();
          let endTime = expire === '∞' ? Infinity : new Date(expire).getTime();
          let nowTime = new Date().getTime();

          // 计算总天数、已过去的天数和剩余天数
          let totalDays = expire === '∞' ? 1 : Math.ceil((endTime - beginTime) / (1000 * 60 * 60 * 24)); // 总天数
          let passedDays = expire === '∞' ? 0 : Math.ceil((nowTime - beginTime) / (1000 * 60 * 60 * 24)); // 已过去的天数
          let remainingDays = expire === '∞' ? 0 : Math.ceil((endTime - nowTime) / (1000 * 60 * 60 * 24)); // 剩余天数

          if (remainingDays < 0) {
            remainingDays = 0; // 设置为0,避免负值
          }

          // 计算进度条的百分比
          let percentage = expire === '∞' ? 100 : (passedDays / totalDays) * 100;
          percentage = Math.min(percentage, 100); // 确保不超过100%

          // 根据剩余天数设置进度条颜色和标签文本
          let progressColor;
          let progressType;
          let labelText;

          if (expire === '∞') {
            progressColor = '#48c9b0'; // 绿色代表永久
            progressType = 'success';
            labelText = '永久'; // 表示这是永久的
          } else {
            if (nowTime > endTime) {
              progressColor = '#7f8c8d'; // 灰色代表已过期
              progressType = 'expired';
              labelText = '已过期';
              percentage = 100; // 进度条宽度设置为100%
            } else {
              if (percentage >= threshold) {
                progressColor = '#e74c3c'; // 红色代表超出阈值
                progressType = 'error';
              } else {
                progressColor = '#48c9b0'; // 绿色代表安全范围
                progressType = 'success';
              }
              // 格式化到期日期和剩余天数
              const expireDate = new Date(expire).toISOString().split('T')[0]; // 将日期格式化为 YYYY-MM-DD
              labelText = `${remainingDays}天 (${expireDate})`; // 显示剩余天数和到期日期
            }
          }

          // 设置到期进度条的样式
          $expireR.setAttribute('class', 'thirteen wide column');
          $expireR.innerHTML = `
            <div class="ui progress ${progressType}" style="border-radius: 8px; width: 100%;">
              <div class="progress-bar" style="border-radius: 8px; transition-duration: 300ms; background-color: ${progressColor}; width: ${percentage}%; padding-left: 0.2em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
                <small style="display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${labelText}</small> <!-- 这里显示剩余天数和到期日期 -->
              </div>
            </div>`;
          $descriptionGrid.insertBefore($expireR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }
      }
    });
  });
}
</script>

剩余天数+日期

<script>
window.onload = function() {
  // 定义产品的详细数据,包括价格、周期、开始和到期日期以及商家名称
  const extraData = {
    1: { price: '0.84€', cycle: 'Month', start: '2024-10-30', expire: '2024-10-31', merchant: 'MerchantA' },
    2: { price: 'FREE', cycle: 'Month', start: '2021-04-15', expire: '∞', merchant: 'MerchantB' },
    3: { price: '24¥', cycle: 'Month', start: '2023-12-24', expire: '2024-12-25', merchant: 'MerchantC' },
    4: { price: '5$', cycle: 'Month', start: '2024-03-05', expire: '2024-05-31', merchant: 'MerchantA' },
    5: { price: 'FREE', cycle: 'Year', start: '2023-05-03', expire: '2025-04-03', merchant: 'MerchantB' }
  };

  // 定义商家与其支付页面的 URL 映射
  const merchantUrls = {
    MerchantA: 'https://merchantA.com/payment',
    MerchantB: 'https://merchantB.com/payment',
    MerchantC: 'https://merchantC.com/payment'
  };

  // 设置到期阈值,当进度条超过此百分比时颜色变为红色
  const threshold = 80;

  // 获取页面上所有的 .ui.accordion 元素
  const cats = document.querySelectorAll('.ui.accordion');
  cats.forEach((e, i) => {
    let $catsTitle = e.querySelector('.title');  
    let ct = $catsTitle.innerText.trim();        
    if (ct === '默认') return; // 跳过标题为“默认”的元素

    let $itemCard = e.querySelectorAll('.ui.card');  
    let uiCardCount = $itemCard.length;              
    $catsTitle.innerHTML = $catsTitle.innerHTML.replace(ct, `${ct} (${uiCardCount})`); // 在标题中显示卡片数量

    // 遍历每个卡片,插入价格和到期信息
    $itemCard.forEach((ee, ii) => {
      let $descriptionGrid = ee.querySelector('.description .ui.grid');  
      let id = ee.getAttribute('id');  

      // 确保 id 存在于 extraData 中
      if (extraData.hasOwnProperty(id)) {
        let { price, start, expire, cycle, merchant } = extraData[id];

        if (price) {
          // 插入价格标签
          let $priceL = document.createElement('div');
          $priceL.setAttribute('class', 'three wide column');
          $priceL.innerHTML = '价格';
          $descriptionGrid.insertBefore($priceL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $priceR = document.createElement('div');
          $priceR.setAttribute('class', 'thirteen wide column');
          // 在价格标签中插入周期链接,点击后跳转到商家的支付页面
          $priceR.innerHTML = `  
            <div class="ui green label" style="border-radius: 8px; display: inline-block;">
              <i class="money bill alternate yellow icon"></i>${price}
              <a href="${merchantUrls[merchant]}" target="_blank" class="detail" style="color: inherit; text-decoration: underline;">${cycle}</a>
            </div>`;
          $descriptionGrid.insertBefore($priceR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }

        if (expire) {
          // 插入到期标签
          let $expireL = document.createElement('div');
          $expireL.setAttribute('class', 'three wide column');
          $expireL.innerHTML = '到期';
          $descriptionGrid.insertBefore($expireL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $expireR = document.createElement('div');
          let beginTime = new Date(start).getTime();
          let endTime = expire === '∞' ? Infinity : new Date(expire).getTime();
          let nowTime = new Date().getTime();

          // 计算总天数、已过去的天数和剩余天数
          let totalDays = expire === '∞' ? 1 : Math.ceil((endTime - beginTime) / (1000 * 60 * 60 * 24)); // 总天数
          let passedDays = expire === '∞' ? 0 : Math.ceil((nowTime - beginTime) / (1000 * 60 * 60 * 24)); // 已过去的天数
          let remainingDays = expire === '∞' ? 0 : Math.ceil((endTime - nowTime) / (1000 * 60 * 60 * 24)); // 剩余天数

          if (remainingDays < 0) {
            remainingDays = 0; // 设置为0,避免负值
          }

          // 计算进度条的百分比
          let percentage = expire === '∞' ? 100 : (passedDays / totalDays) * 100;
          percentage = Math.min(percentage, 100); // 确保不超过100%

          // 根据剩余天数设置进度条颜色和标签文本
          let progressColor;
          let progressType;
          let labelText;

          if (expire === '∞') {
            progressColor = '#48c9b0'; // 绿色代表永久
            progressType = 'success';
            labelText = '永久'; // 表示这是永久的
          } else {
            if (nowTime > endTime) {
              progressColor = '#7f8c8d'; // 灰色代表已过期
              progressType = 'expired';
              labelText = '已过期';
              percentage = 100; // 进度条宽度设置为100%
            } else {
              if (percentage >= threshold) {
                progressColor = '#e74c3c'; // 红色代表超出阈值
                progressType = 'error';
              } else {
                progressColor = '#48c9b0'; // 绿色代表安全范围
                progressType = 'success';
              }
              // 格式化到期日期和剩余天数
              const expireDate = new Date(expire).toISOString().split('T')[0]; // 将日期格式化为 YYYY-MM-DD
              labelText = `${expireDate} (${remainingDays}天)`; // 显示到期日期和剩余天数
            }
          }

          // 设置到期进度条的样式
          $expireR.setAttribute('class', 'thirteen wide column');
          $expireR.innerHTML = `
            <div class="ui progress ${progressType}" style="border-radius: 8px; width: 100%;">
              <div class="progress-bar" style="border-radius: 8px; transition-duration: 300ms; background-color: ${progressColor}; width: ${percentage}%; padding-left: 0.2em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
                <small style="display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${labelText}</small> <!-- 这里显示到期日期和剩余天数 -->
              </div>
            </div>`;
          $descriptionGrid.insertBefore($expireR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }
      }
    });
  });
}
</script>

自动续期

<script>
window.onload = function() {
  const extraData = {
    1: { price: '0.84€', cycle: 'Month', start: '2024-10-02', merchant: 'MerchantA', autoRenewal: 1 },
    2: { price: 'FREE', cycle: 'Month', start: '2021-04-15', merchant: 'MerchantB', autoRenewal: 1 },
    3: { price: '24¥', cycle: 'Month', start: '2023-12-24', merchant: 'MerchantC', autoRenewal: 1 },
    4: { price: '5$', cycle: 'Month', start: '2024-03-05', merchant: 'MerchantA', autoRenewal: 0 },
    5: { price: 'FREE', cycle: 'Year', start: '2023-05-03', merchant: 'MerchantB', autoRenewal: 1 },
    6: { price: '10$', cycle: 'Year', start: '∞', merchant: 'MerchantA', autoRenewal: 1 }  // Example with start '∞'
  };

  const merchantUrls = {
    MerchantA: 'https://merchantA.com/payment',
    MerchantB: 'https://merchantB.com/payment',
    MerchantC: 'https://merchantC.com/payment'
  };

  const threshold = 80;

  const cats = document.querySelectorAll('.ui.accordion');
  cats.forEach((e, i) => {
    let $catsTitle = e.querySelector('.title');  
    let ct = $catsTitle.innerText.trim();        
    if (ct === '默认') return;

    let $itemCard = e.querySelectorAll('.ui.card');  
    let uiCardCount = $itemCard.length;              
    $catsTitle.innerHTML = $catsTitle.innerHTML.replace(ct, `${ct} (${uiCardCount})`);

    $itemCard.forEach((ee, ii) => {
      let $descriptionGrid = ee.querySelector('.description .ui.grid');  
      let id = ee.getAttribute('id');  

      if (extraData.hasOwnProperty(id)) {
        let { price, start, cycle, merchant, autoRenewal } = extraData[id];

        if (price) {
          let $priceL = document.createElement('div');
          $priceL.setAttribute('class', 'three wide column');
          $priceL.innerHTML = '价格';
          $descriptionGrid.insertBefore($priceL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $priceR = document.createElement('div');
          $priceR.setAttribute('class', 'thirteen wide column');
          $priceR.innerHTML = `  
            <div class="ui green label" style="border-radius: 8px; display: inline-block;">
              <i class="money bill alternate yellow icon"></i>${price}
              <a href="${merchantUrls[merchant]}" target="_blank" class="detail" style="color: inherit; text-decoration: underline;">${cycle}</a>
            </div>`;
          $descriptionGrid.insertBefore($priceR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }

        if (autoRenewal || cycle) {
          let $expireL = document.createElement('div');
          $expireL.setAttribute('class', 'three wide column');
          $expireL.innerHTML = '到期';
          $descriptionGrid.insertBefore($expireL, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
          
          let $expireR = document.createElement('div');
          let beginTime;
          let endTime;

          // Handle '∞' case for permanent subscriptions
          if (start === '∞') {
            beginTime = Infinity;
            endTime = Infinity;
          } else {
            beginTime = new Date(start);
            endTime = new Date(start);

            if (autoRenewal) {
              if (cycle === 'Month') {
                while (endTime < new Date()) {
                  endTime.setMonth(endTime.getMonth() + 1);
                }
                beginTime.setMonth(endTime.getMonth() - 1);  // Set start date to current cycle
              } else if (cycle === 'Year') {
                while (endTime < new Date()) {
                  endTime.setFullYear(endTime.getFullYear() + 1);
                }
                beginTime.setFullYear(endTime.getFullYear() - 1);
              }
            } else {
              if (cycle === 'Month') {
                endTime.setMonth(beginTime.getMonth() + 1);
              } else if (cycle === 'Year') {
                endTime.setFullYear(beginTime.getFullYear() + 1);
              }
            }
          }

          let progressColor;
          let progressType;
          let labelText;
          let percentage;

          if (start === '∞') {
            progressColor = '#48c9b0';
            progressType = 'success';
            labelText = '永久';
            percentage = 100;  // Full progress bar for permanent
          } else {
            const now = new Date();
            let totalDays = Math.ceil((endTime - beginTime) / (1000 * 60 * 60 * 24));
            let passedDays = Math.ceil((now - beginTime) / (1000 * 60 * 60 * 24));
            let remainingDays = Math.ceil((endTime - now) / (1000 * 60 * 60 * 24));
            if (remainingDays < 0) remainingDays = 0;

            percentage = (passedDays / totalDays) * 100;
            if (passedDays <= 1) percentage = 0;
            percentage = Math.min(percentage, 100);

            if (now > endTime) {
              progressColor = '#7f8c8d';
              progressType = 'expired';
              labelText = '已过期';
              percentage = 100;
            } else {
              if (percentage >= threshold) {
                progressColor = '#e74c3c';
                progressType = 'error';
              } else {
                progressColor = '#48c9b0';
                progressType = 'success';
              }
              const expireDate = endTime.toISOString().split('T')[0];
              labelText = `${remainingDays}天 (${expireDate})`;
            }
          }

          $expireR.setAttribute('class', 'thirteen wide column');
          $expireR.innerHTML = `
            <div class="ui progress ${progressType}" style="border-radius: 8px; width: 100%;">
              <div class="progress-bar" style="border-radius: 8px; transition-duration: 300ms; background-color: ${progressColor}; width: ${percentage}%; padding-left: 0.2em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
                <small style="display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${labelText}</small>
              </div>
            </div>`;
          $descriptionGrid.insertBefore($expireR, $descriptionGrid.childNodes[$descriptionGrid.childNodes.length - 3]);
        }
      }
    });
  });
}

</script>