upload project source code
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
@@ -0,0 +1,49 @@
|
||||
'''
|
||||
Author: caoziyuan ziyuan.cao@zhuying.com
|
||||
Date: 2025-12-23 14:08:15
|
||||
LastEditors: caoziyuan ziyuan.cao@zhuying.com
|
||||
LastEditTime: 2025-12-23 14:24:55
|
||||
FilePath: \naming-backend\app\api\v1\module_common\calendar\controller.py
|
||||
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
'''
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import date
|
||||
from fastapi import APIRouter, Query
|
||||
|
||||
from app.common.response import SuccessResponse
|
||||
from app.api.v1.module_common.calendar.service import CalendarService
|
||||
|
||||
# 定义路由
|
||||
CalendarRouter = APIRouter(prefix="/calendar", tags=["万年历"])
|
||||
|
||||
|
||||
@CalendarRouter.get("/today", summary="获取今日万年历", description="获取今天的农历信息、宜忌等(无需登录)")
|
||||
async def get_today_calendar() -> SuccessResponse:
|
||||
"""
|
||||
获取今日万年历信息
|
||||
|
||||
返回格式:
|
||||
{
|
||||
"lunar": "腊月 十二",
|
||||
"year": "甲辰年",
|
||||
"solar": "2024.01.22",
|
||||
"yi": ["出行", "开市", "交易", "裁衣"],
|
||||
"ji": ["动土", "安葬", "破土", "作灶"]
|
||||
}
|
||||
"""
|
||||
data = CalendarService.get_calendar_info()
|
||||
return SuccessResponse(data=data)
|
||||
|
||||
|
||||
@CalendarRouter.get("/date", summary="获取指定日期万年历", description="获取指定日期的农历信息、宜忌等(无需登录)")
|
||||
async def get_date_calendar(
|
||||
year: int = Query(..., description="年份,如:2024"),
|
||||
month: int = Query(..., ge=1, le=12, description="月份,1-12"),
|
||||
day: int = Query(..., ge=1, le=31, description="日期,1-31")
|
||||
) -> SuccessResponse:
|
||||
"""
|
||||
获取指定日期的万年历信息
|
||||
"""
|
||||
data = CalendarService.get_calendar_info(year, month, day)
|
||||
return SuccessResponse(data=data)
|
||||
@@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import List
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class CalendarOut(BaseModel):
|
||||
"""万年历返回数据结构"""
|
||||
lunar: str = Field(..., description="农历日期,如:腊月 十二")
|
||||
year: str = Field(..., description="农历年份,如:甲辰年")
|
||||
solar: str = Field(..., description="公历日期,如:2024.01.22")
|
||||
yi: List[str] = Field(default=[], description="宜做的事情")
|
||||
ji: List[str] = Field(default=[], description="忌做的事情")
|
||||
@@ -0,0 +1,141 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
from functools import lru_cache
|
||||
from openai import OpenAI
|
||||
from cnlunar import Lunar
|
||||
|
||||
from app.config.setting import settings
|
||||
|
||||
|
||||
class CalendarService:
|
||||
"""万年历服务 - 使用 cnlunar 获取农历信息,DeepSeek 生成宜忌"""
|
||||
|
||||
# 内存缓存,存储日期对应的宜忌数据
|
||||
_yi_ji_cache: dict = {}
|
||||
|
||||
@classmethod
|
||||
def get_calendar_info(cls, year: Optional[int] = None, month: Optional[int] = None, day: Optional[int] = None) -> dict:
|
||||
"""
|
||||
获取万年历信息
|
||||
|
||||
参数:
|
||||
- year: 年份,默认今年
|
||||
- month: 月份,默认本月
|
||||
- day: 日期,默认今天
|
||||
|
||||
返回:
|
||||
- dict: 万年历信息
|
||||
"""
|
||||
# 获取日期
|
||||
if year and month and day:
|
||||
solar_date = datetime(year, month, day)
|
||||
else:
|
||||
solar_date = datetime.now()
|
||||
|
||||
# 使用 cnlunar 获取农历信息
|
||||
lunar = Lunar(solar_date)
|
||||
|
||||
# 获取农历月份和日期
|
||||
lunar_month = lunar.lunarMonthCn # 如:腊月
|
||||
lunar_day = lunar.lunarDayCn # 如:十二
|
||||
|
||||
# 获取天干地支年份
|
||||
gan_zhi_year = lunar.year8Char # 如:甲辰
|
||||
|
||||
# 使用 DeepSeek 生成宜忌(带缓存)
|
||||
yi_list, ji_list = cls._get_yi_ji_cached(solar_date, lunar)
|
||||
|
||||
return {
|
||||
"lunar": f"{lunar_month} {lunar_day}",
|
||||
"year": f"{gan_zhi_year}年",
|
||||
"solar": solar_date.strftime("%Y.%m.%d"),
|
||||
"yi": yi_list,
|
||||
"ji": ji_list,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _get_yi_ji_cached(cls, solar_date: datetime, lunar: Lunar) -> tuple[List[str], List[str]]:
|
||||
"""
|
||||
获取宜忌数据(带缓存)
|
||||
|
||||
同一天的数据只调用一次 API,后续直接返回缓存
|
||||
"""
|
||||
# 用日期字符串作为缓存 key
|
||||
cache_key = solar_date.strftime("%Y-%m-%d")
|
||||
|
||||
# 如果缓存中有数据,直接返回
|
||||
if cache_key in cls._yi_ji_cache:
|
||||
return cls._yi_ji_cache[cache_key]
|
||||
|
||||
# 缓存中没有,调用 API 获取
|
||||
yi_list, ji_list = cls._get_yi_ji_from_deepseek(solar_date, lunar)
|
||||
|
||||
# 存入缓存
|
||||
cls._yi_ji_cache[cache_key] = (yi_list, ji_list)
|
||||
|
||||
# 限制缓存大小,最多保留 30 天的数据
|
||||
if len(cls._yi_ji_cache) > 30:
|
||||
# 删除最早的一条
|
||||
oldest_key = next(iter(cls._yi_ji_cache))
|
||||
del cls._yi_ji_cache[oldest_key]
|
||||
|
||||
return yi_list, ji_list
|
||||
|
||||
@classmethod
|
||||
def _get_yi_ji_from_deepseek(cls, solar_date: datetime, lunar: Lunar) -> tuple[List[str], List[str]]:
|
||||
"""
|
||||
调用 DeepSeek API 生成宜忌数据
|
||||
|
||||
参数:
|
||||
- solar_date: 公历日期
|
||||
- lunar: 农历对象
|
||||
|
||||
返回:
|
||||
- tuple: (宜列表, 忌列表)
|
||||
"""
|
||||
try:
|
||||
# 从配置文件读取 API 配置
|
||||
client = OpenAI(
|
||||
api_key=settings.DEEPSEEK_API_KEY,
|
||||
base_url=settings.DEEPSEEK_BASE_URL
|
||||
)
|
||||
|
||||
# 构建提示词
|
||||
prompt = f"""请根据以下日期信息,生成中国传统黄历的宜忌数据。
|
||||
|
||||
日期信息:
|
||||
- 公历:{solar_date.strftime("%Y年%m月%d日")}
|
||||
- 农历:{lunar.lunarMonthCn}{lunar.lunarDayCn}
|
||||
- 天干地支:{lunar.year8Char}年 {lunar.month8Char}月 {lunar.day8Char}日
|
||||
|
||||
请严格按照以下 JSON 格式返回,不要有其他内容:
|
||||
{{"yi": ["宜做的事1", "宜做的事2", "宜做的事3", "宜做的事4"], "ji": ["忌做的事1", "忌做的事2", "忌做的事3", "忌做的事4"]}}
|
||||
|
||||
要求:
|
||||
1. 宜和忌各返回4-6个项目
|
||||
2. 使用传统黄历术语,如:祭祀、祈福、嫁娶、出行、开市、动土、安葬等
|
||||
3. 只返回 JSON,不要有任何解释"""
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=settings.DEEPSEEK_MODEL,
|
||||
messages=[
|
||||
{"role": "system", "content": "你是一个精通中国传统黄历的专家,请根据日期生成准确的宜忌信息。"},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
max_tokens=200
|
||||
)
|
||||
|
||||
# 解析返回的 JSON
|
||||
result_text = response.choices[0].message.content.strip()
|
||||
result = json.loads(result_text)
|
||||
|
||||
return result.get("yi", []), result.get("ji", [])
|
||||
|
||||
except Exception as e:
|
||||
# 如果 API 调用失败,返回默认值
|
||||
print(f"DeepSeek API 调用失败: {e}")
|
||||
return ["祭祀", "祈福", "出行", "开市"], ["动土", "安葬", "破土", "作灶"]
|
||||
Reference in New Issue
Block a user