fix(wish-tree): 修复切换树时导航栏消失问题
- Canvas添加z-index: 1,确保不覆盖导航栏 - top-bar添加pointer-events: none,子元素恢复auto - WXML添加trees.length保护,防止空数组访问 - switchTree添加空数组保护
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
# 部署通知配置指南
|
||||
|
||||
本文档说明如何配置 Gitea Actions 的部署通知功能,支持 Telegram 和 Discord 双渠道通知。
|
||||
|
||||
## 功能说明
|
||||
|
||||
- ✅ **自动触发**:部署成功或失败时自动发送通知
|
||||
- ✅ **双渠道**:同时支持 Telegram 和 Discord
|
||||
- ✅ **详细信息**:包含仓库、分支、提交、作者、工作流等信息
|
||||
- ✅ **失败容错**:通知发送失败不会影响部署流程
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 1. Telegram Bot 配置
|
||||
|
||||
#### 1.1 创建 Telegram Bot
|
||||
|
||||
1. 在 Telegram 中搜索 `@BotFather`
|
||||
2. 发送 `/newbot` 创建新机器人
|
||||
3. 按提示设置机器人名称和用户名
|
||||
4. 获得 Bot Token,格式类似:`123456789:ABCdefGHIjklMNOpqrsTUVwxyz`
|
||||
|
||||
#### 1.2 获取 Chat ID
|
||||
|
||||
**方法 1:通过 Bot API**
|
||||
1. 将你的 Bot 添加到目标群组或频道
|
||||
2. 发送任意消息给 Bot
|
||||
3. 访问:`https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates`
|
||||
4. 在返回的 JSON 中找到 `chat.id`
|
||||
|
||||
**方法 2:使用第三方 Bot**
|
||||
1. 添加 `@userinfobot` 到你的群组
|
||||
2. 它会自动显示 Chat ID
|
||||
|
||||
### 2. Discord Webhook 配置
|
||||
|
||||
1. 打开 Discord 服务器设置
|
||||
2. 进入 **集成** → **Webhook**
|
||||
3. 点击 **新建 Webhook**
|
||||
4. 设置名称和头像(可选)
|
||||
5. 选择目标频道
|
||||
6. 复制 Webhook URL,格式类似:
|
||||
```
|
||||
https://discord.com/api/webhooks/123456789/abcdefghijklmnopqrstuvwxyz
|
||||
```
|
||||
|
||||
### 3. 配置 Gitea Secrets
|
||||
|
||||
由于 Gitea Actions API 在该实例不可用,需要直接写入 MySQL 数据库。
|
||||
|
||||
#### 3.1 连接到 Gitea 数据库
|
||||
|
||||
```bash
|
||||
# SSH 到 Gitea 服务器
|
||||
ssh doc79
|
||||
|
||||
# 连接 MySQL(根据实际情况调整)
|
||||
mysql -u gitea -p gitea
|
||||
```
|
||||
|
||||
#### 3.2 插入 Secrets
|
||||
|
||||
```sql
|
||||
-- Telegram Bot Token
|
||||
INSERT INTO action_variable (owner_id, repo_id, name, data, created_unix, updated_unix)
|
||||
VALUES (0, 0, 'TELEGRAM_BOT_TOKEN', '你的Bot Token', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
|
||||
|
||||
-- Telegram Chat ID
|
||||
INSERT INTO action_variable (owner_id, repo_id, name, data, created_unix, updated_unix)
|
||||
VALUES (0, 0, 'TELEGRAM_CHAT_ID', '你的Chat ID', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
|
||||
|
||||
-- Discord Webhook URL
|
||||
INSERT INTO action_variable (owner_id, repo_id, name, data, created_unix, updated_unix)
|
||||
VALUES (0, 0, 'DISCORD_WEBHOOK_URL', '你的Webhook URL', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- `owner_id=0` 表示全局变量,所有仓库可用
|
||||
- 如果只想对特定仓库生效,需要查询该仓库的 `repo_id` 并替换
|
||||
|
||||
#### 3.3 验证配置
|
||||
|
||||
```sql
|
||||
-- 查看所有 Actions 变量
|
||||
SELECT id, owner_id, repo_id, name, LEFT(data, 20) as data_preview
|
||||
FROM action_variable
|
||||
WHERE name IN ('TELEGRAM_BOT_TOKEN', 'TELEGRAM_CHAT_ID', 'DISCORD_WEBHOOK_URL');
|
||||
```
|
||||
|
||||
### 4. 测试通知
|
||||
|
||||
配置完成后,推送代码到 main 分支触发部署:
|
||||
|
||||
```bash
|
||||
# 测试后端部署通知
|
||||
git add server/
|
||||
git commit -m "test: 测试部署通知"
|
||||
git push origin main
|
||||
|
||||
# 测试小程序部署通知
|
||||
git add mini/
|
||||
git commit -m "test: 测试小程序通知"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## 通知示例
|
||||
|
||||
### Telegram 通知
|
||||
|
||||
```
|
||||
✅ 后端服务部署成功
|
||||
|
||||
状态: 成功
|
||||
仓库: gouki/lunar
|
||||
分支: main
|
||||
提交: abc1234
|
||||
作者: gouki
|
||||
工作流: Build and Deploy Server #42
|
||||
|
||||
部署包已保存到: /opt/lunar/ci-artifacts/server-deploy-latest.tar.gz
|
||||
|
||||
查看详情
|
||||
```
|
||||
|
||||
### Discord 通知
|
||||
|
||||
Discord 会显示一个嵌入消息卡片,包含:
|
||||
- 标题和状态图标
|
||||
- 仓库、分支、提交、作者信息
|
||||
- 部署详情
|
||||
- 时间戳
|
||||
- 可点击的链接跳转到 Actions 页面
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 通知未发送
|
||||
|
||||
1. **检查 Secrets 配置**
|
||||
```sql
|
||||
SELECT * FROM action_variable WHERE name LIKE '%TELEGRAM%' OR name LIKE '%DISCORD%';
|
||||
```
|
||||
|
||||
2. **查看 Actions 日志**
|
||||
- 在 Gitea 网页界面查看 Actions 运行日志
|
||||
- 查找 "发送 Telegram 通知" 或 "发送 Discord 通知" 相关输出
|
||||
|
||||
3. **检查网络连接**
|
||||
- 确保运行器可以访问 `api.telegram.org` 和 `discord.com`
|
||||
- 你的运行器在海外,理论上没有问题
|
||||
|
||||
### Telegram 通知失败
|
||||
|
||||
- **Bot Token 错误**:检查 Token 是否正确
|
||||
- **Chat ID 错误**:确保 Bot 已加入群组/频道,且 Chat ID 正确
|
||||
- **权限问题**:确保 Bot 有发送消息的权限
|
||||
|
||||
### Discord 通知失败
|
||||
|
||||
- **Webhook URL 错误**:检查 URL 是否完整
|
||||
- **Webhook 被删除**:重新创建 Webhook
|
||||
- **频道权限**:确保 Webhook 有权限在目标频道发送消息
|
||||
|
||||
## 高级配置
|
||||
|
||||
### 自定义通知内容
|
||||
|
||||
编辑 `.gitea/workflows/server-deploy.yml` 或 `.gitea/workflows/miniapp-preview.yml`,修改通知步骤的消息内容:
|
||||
|
||||
```yaml
|
||||
.gitea/scripts/notify.sh success \
|
||||
"自定义标题" \
|
||||
"自定义消息内容"
|
||||
```
|
||||
|
||||
### 只使用单一渠道
|
||||
|
||||
如果只想使用 Telegram 或 Discord 之一,只需配置对应的 Secrets 即可。脚本会自动跳过未配置的渠道。
|
||||
|
||||
### 添加更多通知渠道
|
||||
|
||||
可以扩展 `.gitea/scripts/notify.sh` 脚本,添加其他通知渠道(如 Slack、钉钉、企业微信等)。
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **保护 Secrets**:不要将 Bot Token、Chat ID、Webhook URL 提交到代码仓库
|
||||
2. **定期轮换**:定期更换 Bot Token 和 Webhook URL
|
||||
3. **权限最小化**:Telegram Bot 只授予发送消息权限,Discord Webhook 只用于特定频道
|
||||
4. **监控异常**:如果发现异常通知,立即检查 Secrets 是否泄露
|
||||
|
||||
## 相关文件
|
||||
|
||||
- 通知脚本:`.gitea/scripts/notify.sh`
|
||||
- 后端部署工作流:`.gitea/workflows/server-deploy.yml`
|
||||
- 小程序部署工作流:`.gitea/workflows/miniapp-preview.yml`
|
||||
|
||||
## 更新日志
|
||||
|
||||
- 2026-08-07: 初始版本,支持 Telegram 和 Discord 双渠道通知
|
||||
@@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
# 部署通知脚本 - 支持 Telegram 和 Discord
|
||||
# 使用方法: ./notify.sh <status> <title> <message> [color]
|
||||
# status: success 或 failure
|
||||
# title: 通知标题
|
||||
# message: 通知内容
|
||||
# color: Discord 消息颜色(可选,默认根据 status 自动选择)
|
||||
|
||||
set -e
|
||||
|
||||
STATUS="$1"
|
||||
TITLE="$2"
|
||||
MESSAGE="$3"
|
||||
COLOR="${4:-}"
|
||||
|
||||
# 根据状态设置默认值
|
||||
if [ "$STATUS" = "success" ]; then
|
||||
EMOJI="✅"
|
||||
DEFAULT_COLOR="3066993" # 绿色
|
||||
STATUS_TEXT="成功"
|
||||
elif [ "$STATUS" = "failure" ]; then
|
||||
EMOJI="❌"
|
||||
DEFAULT_COLOR="15158332" # 红色
|
||||
STATUS_TEXT="失败"
|
||||
else
|
||||
EMOJI="ℹ️"
|
||||
DEFAULT_COLOR="3447003" # 蓝色
|
||||
STATUS_TEXT="通知"
|
||||
fi
|
||||
|
||||
COLOR="${COLOR:-$DEFAULT_COLOR}"
|
||||
|
||||
# 获取 Git 信息
|
||||
REPO="${GITEA_REPO:-unknown}"
|
||||
BRANCH="${GITEA_REF_NAME:-unknown}"
|
||||
COMMIT_SHA="${GITEA_SHA:-unknown}"
|
||||
COMMIT_SHORT="${COMMIT_SHA:0:7}"
|
||||
AUTHOR="${GITEA_ACTOR:-unknown}"
|
||||
WORKFLOW="${GITEA_WORKFLOW:-unknown}"
|
||||
RUN_NUMBER="${GITEA_RUN_NUMBER:-unknown}"
|
||||
RUN_URL="${GITEA_SERVER_URL:-}/${GITEA_REPO}/actions/runs/${GITEA_RUN_ID:-}"
|
||||
|
||||
# ==================== Telegram 通知 ====================
|
||||
send_telegram() {
|
||||
if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then
|
||||
echo "⚠️ Telegram 配置缺失,跳过通知"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local tg_message="${EMOJI} <b>${TITLE}</b>
|
||||
|
||||
<b>状态:</b> ${STATUS_TEXT}
|
||||
<b>仓库:</b> ${REPO}
|
||||
<b>分支:</b> ${BRANCH}
|
||||
<b>提交:</b> <code>${COMMIT_SHORT}</code>
|
||||
<b>作者:</b> ${AUTHOR}
|
||||
<b>工作流:</b> ${WORKFLOW} #${RUN_NUMBER}
|
||||
|
||||
${MESSAGE}
|
||||
|
||||
<a href=\"${RUN_URL}\">查看详情</a>"
|
||||
|
||||
echo "📤 发送 Telegram 通知..."
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST \
|
||||
"https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
-d "text=${tg_message}" \
|
||||
-d "parse_mode=HTML" \
|
||||
-d "disable_web_page_preview=true")
|
||||
|
||||
if echo "$response" | grep -q '"ok":true'; then
|
||||
echo "✅ Telegram 通知发送成功"
|
||||
else
|
||||
echo "❌ Telegram 通知发送失败: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ==================== Discord 通知 ====================
|
||||
send_discord() {
|
||||
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
|
||||
echo "⚠️ Discord Webhook 配置缺失,跳过通知"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "📤 发送 Discord 通知..."
|
||||
|
||||
# 构建 Discord Embed JSON
|
||||
local discord_payload
|
||||
discord_payload=$(cat <<EOF
|
||||
{
|
||||
"embeds": [{
|
||||
"title": "${EMOJI} ${TITLE}",
|
||||
"description": "${MESSAGE}",
|
||||
"color": ${COLOR},
|
||||
"fields": [
|
||||
{
|
||||
"name": "状态",
|
||||
"value": "${STATUS_TEXT}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "仓库",
|
||||
"value": "${REPO}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "分支",
|
||||
"value": "${BRANCH}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "提交",
|
||||
"value": "\`${COMMIT_SHORT}\`",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "作者",
|
||||
"value": "${AUTHOR}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "工作流",
|
||||
"value": "${WORKFLOW} #${RUN_NUMBER}",
|
||||
"inline": true
|
||||
}
|
||||
],
|
||||
"footer": {
|
||||
"text": "Gitea Actions"
|
||||
},
|
||||
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"url": "${RUN_URL}"
|
||||
}]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST \
|
||||
"$DISCORD_WEBHOOK_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$discord_payload")
|
||||
|
||||
if [ -z "$response" ] || echo "$response" | grep -q '"id"'; then
|
||||
echo "✅ Discord 通知发送成功"
|
||||
else
|
||||
echo "❌ Discord 通知发送失败: $response"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ==================== 主流程 ====================
|
||||
main() {
|
||||
echo "🔔 开始发送部署通知..."
|
||||
echo "状态: $STATUS"
|
||||
echo "标题: $TITLE"
|
||||
echo "消息: $MESSAGE"
|
||||
echo ""
|
||||
|
||||
local failed=0
|
||||
|
||||
# 发送 Telegram 通知
|
||||
if ! send_telegram; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 发送 Discord 通知
|
||||
if ! send_discord; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ $failed -eq 0 ]; then
|
||||
echo "✅ 所有通知发送完成"
|
||||
else
|
||||
echo "⚠️ 部分通知发送失败 ($failed 个)"
|
||||
# 不退出脚本,避免影响主流程
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
@@ -93,6 +93,32 @@ jobs:
|
||||
cp mini/ci-artifacts/upload-result.json /ci-artifacts/miniapp-upload-latest.json
|
||||
ls -la /ci-artifacts/miniapp-upload-latest.json
|
||||
echo "Upload result saved on runner host: /opt/lunar/ci-artifacts/miniapp-upload-latest.json"
|
||||
|
||||
- name: Send success notification
|
||||
if: success()
|
||||
env:
|
||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
VERSION="$(tr -d '\n' < mini/ci-artifacts/resolved-version.txt)"
|
||||
chmod +x .gitea/scripts/notify.sh
|
||||
.gitea/scripts/notify.sh success \
|
||||
"小程序开发版上传成功" \
|
||||
"版本: ${VERSION}\n上传结果已保存到: /opt/lunar/ci-artifacts/miniapp-upload-latest.json"
|
||||
|
||||
- name: Send failure notification
|
||||
if: failure()
|
||||
env:
|
||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
chmod +x .gitea/scripts/notify.sh
|
||||
.gitea/scripts/notify.sh failure \
|
||||
"小程序开发版上传失败" \
|
||||
"请检查 Actions 日志了解失败原因"
|
||||
|
||||
- name: Remove temporary credentials
|
||||
if: always()
|
||||
run: rm -f "$RUNNER_TEMP/wechat-ci.key"
|
||||
|
||||
@@ -69,6 +69,30 @@ jobs:
|
||||
ls -la /ci-artifacts/server-deploy-latest.tar.gz
|
||||
echo "Deployment package saved on runner host: /opt/lunar/ci-artifacts/server-deploy-latest.tar.gz"
|
||||
|
||||
- name: Send success notification
|
||||
if: success()
|
||||
env:
|
||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
chmod +x .gitea/scripts/notify.sh
|
||||
.gitea/scripts/notify.sh success \
|
||||
"后端服务部署成功" \
|
||||
"部署包已保存到: /opt/lunar/ci-artifacts/server-deploy-latest.tar.gz"
|
||||
|
||||
- name: Send failure notification
|
||||
if: failure()
|
||||
env:
|
||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
run: |
|
||||
chmod +x .gitea/scripts/notify.sh
|
||||
.gitea/scripts/notify.sh failure \
|
||||
"后端服务部署失败" \
|
||||
"请检查 Actions 日志了解失败原因"
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
|
||||
@@ -939,6 +939,8 @@ Page({
|
||||
const direction = e.currentTarget.dataset.direction;
|
||||
const { trees, currentTreeIndex } = this.data;
|
||||
|
||||
if (!trees.length) return;
|
||||
|
||||
let newIndex = currentTreeIndex;
|
||||
if (direction === 'prev') {
|
||||
newIndex = (currentTreeIndex - 1 + trees.length) % trees.length;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<view class="switch-btn" bindtap="switchTree" data-direction="prev">
|
||||
<text class="switch-icon">‹</text>
|
||||
</view>
|
||||
<view class="tree-name">{{trees[currentTreeIndex].name || '许愿树'}}</view>
|
||||
<view class="tree-name">{{trees.length > 0 ? trees[currentTreeIndex].name : '许愿树'}}</view>
|
||||
<view class="switch-btn" bindtap="switchTree" data-direction="next">
|
||||
<text class="switch-icon">›</text>
|
||||
</view>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 顶部导航 */
|
||||
@@ -26,6 +27,11 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 100;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.top-bar > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.tree-switcher {
|
||||
|
||||
@@ -269,14 +269,60 @@ function getConstellation(month, day) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取节气 */
|
||||
function getSolarTerm(year, month, day) {
|
||||
const termDates = SOLAR_TERM_DATES[month - 1];
|
||||
if (day === termDates[0]) {
|
||||
return SOLAR_TERMS[(month - 1) * 2];
|
||||
} else if (day === termDates[1]) {
|
||||
return SOLAR_TERMS[(month - 1) * 2 + 1];
|
||||
/** 计算某年某节气的公历日期(21世纪 C 值法,误差±1天) */
|
||||
function getSolarTermDate(year, termIndex) {
|
||||
// 21世纪 C 值表(小寒=0, 大寒=1, 立春=2 ... 冬至=23)
|
||||
const C21 = [
|
||||
6.11, 20.84, 4.6295, 19.4599, 6.3826, 21.4155, // 小寒 大寒 立春 雨水 惊蛰 春分
|
||||
5.59, 20.888, 6.318, 21.86, 6.5, 22.20, // 清明 谷雨 立夏 小满 芒种 夏至
|
||||
7.928, 23.65, 8.35, 23.95, 8.44, 23.822, // 小暑 大暑 立秋 处暑 白露 秋分
|
||||
9.098, 24.218, 8.218, 23.08, 7.9, 22.60 // 寒露 霜降 立冬 小雪 大雪 冬至
|
||||
];
|
||||
// 20世纪 C 值表
|
||||
const C20 = [
|
||||
6.9, 21.37, 5.4055, 20.12, 7.1082, 22.83,
|
||||
6.38, 21.646, 7.108, 22.36, 7.5, 23.13,
|
||||
8.318, 24.64, 9.35, 24.77, 9.74, 24.643,
|
||||
9.878, 24.918, 9.11, 23.65, 8.8, 23.54
|
||||
];
|
||||
const Y = year % 100;
|
||||
const C = year >= 2000 ? C21[termIndex] : C20[termIndex];
|
||||
// 闰年修正:小寒、大寒、立春、雨水(1-2月)
|
||||
let leapAdjust = 0;
|
||||
if (termIndex <= 3 && isLeapYear(year)) leapAdjust = 1;
|
||||
// 特殊修正
|
||||
if (year === 2026 && termIndex === 3) leapAdjust = -1; // 2026雨水
|
||||
if (year === 2084 && termIndex === 3) leapAdjust = 1;
|
||||
if (year === 1911 && termIndex === 6) leapAdjust = 1; // 清明
|
||||
if (year === 1984 && termIndex === 7) leapAdjust = -1; // 谷雨
|
||||
if (year === 1911 && termIndex === 8) leapAdjust = 1; // 立夏
|
||||
if (year === 1981 && termIndex === 10) leapAdjust = -1; // 芒种
|
||||
if (year === 1902 && termIndex === 11) leapAdjust = 1; // 夏至
|
||||
if (year === 1928 && termIndex === 12) leapAdjust = 1; // 小暑
|
||||
if (year === 1925 && termIndex === 13) leapAdjust = -1; // 大暑
|
||||
if (year === 2002 && termIndex === 14) leapAdjust = 1; // 立秋
|
||||
if (year === 1927 && termIndex === 16) leapAdjust = 1; // 白露
|
||||
if (year === 1942 && termIndex === 17) leapAdjust = 1; // 秋分
|
||||
if (year === 2089 && termIndex === 18) leapAdjust = 1; // 寒露
|
||||
if (year === 2089 && termIndex === 19) leapAdjust = 1; // 霜降
|
||||
if (year === 1978 && termIndex === 20) leapAdjust = 1; // 立冬
|
||||
if (year === 1954 && termIndex === 21) leapAdjust = -1; // 小雪
|
||||
if (year === 1918 && termIndex === 22) leapAdjust = 1; // 大雪
|
||||
if (year === 2021 && termIndex === 22) leapAdjust = -1;
|
||||
if (year === 1902 && termIndex === 23) leapAdjust = 1; // 冬至
|
||||
|
||||
return Math.floor(Y * 0.2422 + C) - Math.floor((Y - 1) / 4) + leapAdjust;
|
||||
}
|
||||
|
||||
/** 获取节气(准确算法) */
|
||||
function getSolarTerm(year, month, day) {
|
||||
// 每月两个节气:第1个在 index (month-1)*2,第2个在 (month-1)*2+1
|
||||
const idx1 = (month - 1) * 2;
|
||||
const idx2 = idx1 + 1;
|
||||
const d1 = getSolarTermDate(year, idx1);
|
||||
const d2 = getSolarTermDate(year, idx2);
|
||||
if (day === d1) return SOLAR_TERMS[idx1];
|
||||
if (day === d2) return SOLAR_TERMS[idx2];
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user