|
After Width: | Height: | Size: 198 KiB |
@ -0,0 +1,2 @@
|
||||
# 复制此文件为.env并填入你的API密钥
|
||||
DEEPSEEK_API_KEY=sk-2685bfd0fe054c9f82a12ac7905dd80d
|
||||
@ -0,0 +1,2 @@
|
||||
# 复制此文件为.env并填入你的API密钥
|
||||
DEEPSEEK_API_KEY=sk-2685bfd0fe054c9f82a12ac7905dd80d
|
||||
@ -0,0 +1,3 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv1" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.13 (PythonProject2)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/PythonProject2.iml" filepath="$PROJECT_DIR$/.idea/PythonProject2.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
@ -0,0 +1,17 @@
|
||||
#OpenAI SDK
|
||||
# Please install OpenAI SDK first: `pip3 install openai`
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(api_key="sk-2685bfd0fe054c9f82a12ac7905dd80d", base_url="https://api.deepseek.com")
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model="deepseek-chat",
|
||||
messages=[
|
||||
{"role": "system", "content": "你是一个情绪分析大师,请用委婉的语气说话"},
|
||||
{"role": "user", "content": "输入日记内容"},
|
||||
],
|
||||
stream=False
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
@ -0,0 +1,24 @@
|
||||
import sqlite3
|
||||
|
||||
# 连接到数据库
|
||||
try:
|
||||
conn = sqlite3.connect('database.db')
|
||||
c = conn.cursor()
|
||||
|
||||
# 查看所有表
|
||||
print("数据库中的表:")
|
||||
c.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
||||
tables = c.fetchall()
|
||||
for table in tables:
|
||||
print(f"- {table[0]}")
|
||||
|
||||
# 查看表结构
|
||||
print(f" {table[0]}表结构:")
|
||||
c.execute(f"PRAGMA table_info({table[0]});")
|
||||
columns = c.fetchall()
|
||||
for column in columns:
|
||||
print(f" - {column[1]} ({column[2]})")
|
||||
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"检查数据库出错: {e}")
|
||||
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 153 KiB |
@ -0,0 +1,5 @@
|
||||
flask==2.3.3
|
||||
flask-cors==4.0.0
|
||||
requests==2.31.0
|
||||
python-dotenv==1.0.0
|
||||
openai==1.3.7
|
||||
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 280 KiB |
|
After Width: | Height: | Size: 286 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 382 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 434 KiB |
|
After Width: | Height: | Size: 499 KiB |
|
After Width: | Height: | Size: 471 KiB |
|
After Width: | Height: | Size: 451 KiB |
|
After Width: | Height: | Size: 429 KiB |
|
After Width: | Height: | Size: 453 KiB |
|
After Width: | Height: | Size: 408 KiB |
|
After Width: | Height: | Size: 459 KiB |
|
After Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 486 KiB |
|
After Width: | Height: | Size: 480 KiB |
|
After Width: | Height: | Size: 456 KiB |
|
After Width: | Height: | Size: 421 KiB |
|
After Width: | Height: | Size: 452 KiB |
|
After Width: | Height: | Size: 348 KiB |
|
After Width: | Height: | Size: 445 KiB |
|
After Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 65 KiB |
@ -0,0 +1,169 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}我的卡册 - AI日记{% endblock %}
|
||||
{% block extra_css %}
|
||||
<style>
|
||||
.containe {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
header {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
/* 抽卡按钮样式*/
|
||||
#drawCardBtn {
|
||||
background-color: #efec8e;
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 15px 30px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
box-shadow: 0 4px 12px rgba(255,215,0,0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
#drawCardBtn:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 16px rgba(255,215,0,0.4);
|
||||
}
|
||||
|
||||
/* 分类卡片样式 */
|
||||
.category-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
/* 分类标题(点击折叠/展开) */
|
||||
.category-header {
|
||||
background: #fff;
|
||||
padding: 25px 20px; /* 增加上下padding */
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
/* 分类下的卡片列表 */
|
||||
.category-cards {
|
||||
display: none;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); /* 自适应列数 */
|
||||
gap: 15px;
|
||||
padding: 15px 20px;
|
||||
background: #fff;
|
||||
border-radius: 0 0 8px 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
margin-top: -10px; /* 与标题无缝衔接 */
|
||||
}
|
||||
/* 单张卡片样式 */
|
||||
.card-item {
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.card-item:hover {
|
||||
transform: translateY(-5px); /* hover时轻微上浮 */
|
||||
}
|
||||
.card-item img {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
.card-item p {
|
||||
margin: 8px 0 0;
|
||||
color: #666;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.card-item .time {
|
||||
font-size: 0.85rem;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="containe">
|
||||
<header>
|
||||
<h1>我的卡册</h1>
|
||||
<button id="drawCardBtn" onclick="window.location.href='/showcard'">今日抽卡</button>
|
||||
</header>
|
||||
|
||||
<div id="categoryContainer">
|
||||
<p style="text-align: center; color: #666;">加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
// 页面加载时,按分类渲染用户已拥有的卡片
|
||||
window.onload = async () => {
|
||||
try {
|
||||
const response = await fetch('/get_cards_by_category');
|
||||
const categoryCards = await response.json(); // 格式:{分类名: [卡片列表]}
|
||||
const container = document.getElementById('categoryContainer');
|
||||
container.innerHTML = '';
|
||||
|
||||
// 无卡片时显示提示
|
||||
if (Object.keys(categoryCards).length === 0) {
|
||||
container.innerHTML = '<p style="text-align: center; color: #666;">暂无卡片,快去抽卡吧!</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历每个分类,生成折叠卡片组
|
||||
for (const [category, cards] of Object.entries(categoryCards)) {
|
||||
const categoryHtml = `
|
||||
<div class="category-group">
|
||||
<!-- 分类标题 -->
|
||||
<div class="category-header" onclick="toggleCategory(this)">
|
||||
<span>${category}</span>
|
||||
<span>▼</span> <!-- 折叠/展开箭头 -->
|
||||
</div>
|
||||
<!-- 分类下的卡片列表 -->
|
||||
<div class="category-cards">
|
||||
${cards.map(card => `
|
||||
<div class="card-item">
|
||||
<img src="${card.imageUrl}" alt="${card.name}">
|
||||
<p>${card.name}</p>
|
||||
<p class="time">${card.collectedAt}</p>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.innerHTML += categoryHtml;
|
||||
}
|
||||
} catch (error) {
|
||||
document.getElementById('categoryContainer').innerHTML =
|
||||
'<p style="text-align: center; color: #ff4444;">加载失败,请刷新页面</p>';
|
||||
}
|
||||
};
|
||||
|
||||
// 折叠/展开分类卡片
|
||||
function toggleCategory(header) {
|
||||
const cardsList = header.nextElementSibling; // 卡片列表容器
|
||||
const arrow = header.querySelector('span:last-child'); // 箭头元素
|
||||
|
||||
if (cardsList.style.display === 'grid') {
|
||||
// 折叠:隐藏卡片列表,箭头变“▼”
|
||||
cardsList.style.display = 'none';
|
||||
arrow.textContent = '▼';
|
||||
} else {
|
||||
// 展开:显示卡片列表,箭头变“▲”
|
||||
cardsList.style.display = 'grid';
|
||||
arrow.textContent = '▲';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -0,0 +1,69 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}我的日记 - AI日记{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-8">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto fade-in">
|
||||
<div class="card card-enhanced">
|
||||
<div class="card-header bg-white d-flex justify-content-between align-items-center">
|
||||
<h3 class="mb-0"><i class="fas fa-book text-primary-yellow me-2"></i>我的日记</h3>
|
||||
<a href="{{ url_for('diary') }}" class="btn btn-primary-yellow text-gray-800 btn-feedback">
|
||||
<i class="fas fa-plus me-1"></i>写新日记
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if diaries %}
|
||||
<div class="list-group">
|
||||
{% for diary in diaries %}
|
||||
<div class="list-group-item list-group-item-action mb-3 rounded shadow-sm">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h4 class="mb-1 text-xl font-bold">{{ diary[1] }}</h4>
|
||||
<div class="text-right">
|
||||
<small class="text-muted">
|
||||
{% if diary[5] != diary[4] %}
|
||||
最后编辑: {{ diary[5].split(' ')[0] }}
|
||||
{% else %}
|
||||
创建于: {{ diary[4].split(' ')[0] }}
|
||||
{% endif %}
|
||||
</small>
|
||||
<div class="mt-2">
|
||||
<a href="{{ url_for('diary', id=diary[0]) }}" class="text-primary-yellow me-3">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('diary_delete', diary_id=diary[0]) }}" class="text-red-500 me-3" onclick="return confirm('确定要删除这篇日记吗?')">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('diary_view', diary_id=diary[0]) }}" class="text-blue-500">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if diary[3] %}
|
||||
<div class="flex-wrap gap-2 mt-2">
|
||||
{% for tag in diary[3].split(',') %}
|
||||
<span class="badge bg-primary-yellow text-gray-800">{{ tag.strip() }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-8">
|
||||
<i class="fas fa-book-open text-4xl text-gray-300 mb-4"></i>
|
||||
<h4 class="text-gray-500">还没有日记呢</h4>
|
||||
<p class="text-gray-400 mb-4">点击上方按钮开始记录你的第一篇日记吧</p>
|
||||
<a href="{{ url_for('diary') }}" class="btn btn-primary-yellow text-gray-800 btn-feedback">
|
||||
<i class="fas fa-pen me-1"></i>开始写日记
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||