release: v2.0 - 完整功能管理系统

主要功能:
- 完整的Flask-Admin后台管理系统
- 网站/标签/新闻管理功能
- 用户登录认证系统
- 科技感/未来风UI设计
- 标签分类系统(取代传统分类)
- 详情页面展示
- 数据库迁移脚本
- 书签导入解析工具

技术栈:
- Flask + SQLAlchemy
- Flask-Admin管理界面
- Bootstrap 4响应式设计
- 用户认证与权限管理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jowe
2025-12-28 19:21:17 +08:00
parent 2fbca6ebc7
commit 9e47ebe749
49 changed files with 6274 additions and 1353 deletions

View File

@@ -0,0 +1,62 @@
"""添加code字段的迁移脚本"""
import sys
import os
import random
# 添加项目根目录到系统路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app import create_app
from models import db, Site
from sqlalchemy import text
# 创建应用上下文
app = create_app()
def generate_unique_code():
"""生成唯一的8位数字编码"""
while True:
# 生成10000000-99999999之间的随机数
code = str(random.randint(10000000, 99999999))
# 检查是否已存在
if not Site.query.filter_by(code=code).first():
return code
with app.app_context():
try:
print("Step 1: Adding code column to sites table...")
# 添加code列先允许为空
with db.engine.connect() as connection:
connection.execute(text('ALTER TABLE sites ADD COLUMN code VARCHAR(8) NULL COMMENT "8位数字编码"'))
connection.commit()
print(" - Column added successfully!")
print("\nStep 2: Generating codes for existing sites...")
# 为现有网站生成code
sites = Site.query.all()
for site in sites:
site.code = generate_unique_code()
print(f" - Site #{site.id} '{site.name}': code = {site.code}")
db.session.commit()
print(f" - Generated codes for {len(sites)} sites!")
print("\nStep 3: Making code column NOT NULL and UNIQUE...")
# 现在修改列为NOT NULL和UNIQUE
with db.engine.connect() as connection:
connection.execute(text('ALTER TABLE sites MODIFY COLUMN code VARCHAR(8) NOT NULL'))
connection.execute(text('ALTER TABLE sites ADD UNIQUE INDEX idx_site_code (code)'))
connection.commit()
print(" - Code column constraints added!")
print("\n✓ Migration completed successfully!")
except Exception as e:
print(f"\n✗ Migration failed: {str(e)}")
import traceback
traceback.print_exc()
db.session.rollback()

View File

@@ -0,0 +1,17 @@
"""添加news表的迁移脚本"""
import sys
import os
# 添加项目根目录到系统路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app import create_app
from models import db, News
# 创建应用上下文
app = create_app()
with app.app_context():
# 创建news表
db.create_all()
print("✓ News表创建成功")

View File

@@ -0,0 +1,73 @@
"""修复空slug的迁移脚本"""
import sys
import os
import re
# 添加项目根目录到系统路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app import create_app
from models import db, Site
from datetime import datetime
from pypinyin import lazy_pinyin
# 创建应用上下文
app = create_app()
def generate_slug(name, site_id=None):
"""从名称生成slug"""
# 将中文转换为拼音
slug = ''.join(lazy_pinyin(name))
# 转换为小写,移除特殊字符
slug = slug.lower()
slug = re.sub(r'[^\w\s-]', '', slug)
slug = re.sub(r'[-\s]+', '-', slug).strip('-')
# 如果转换后为空使用ID或时间戳
if not slug:
if site_id:
slug = f"site-{site_id}"
else:
slug = f"site-{datetime.now().strftime('%Y%m%d%H%M%S')}"
# 确保slug唯一
base_slug = slug
counter = 1
while Site.query.filter(Site.slug == slug, Site.id != site_id).first():
slug = f"{base_slug}-{counter}"
counter += 1
return slug
with app.app_context():
try:
# 查找所有slug为空或包含乱码的网站
all_sites = Site.query.all()
sites_to_fix = []
for site in all_sites:
# 检查slug是否为空、None、或包含乱码
if (not site.slug or
site.slug == 'None' or
site.slug.strip() == '' or
any(ord(char) > 127 and not char.isalpha() for char in site.slug)):
sites_to_fix.append(site)
if not sites_to_fix:
print("No sites to fix. All good!")
else:
print(f"Found {len(sites_to_fix)} sites to fix...")
for site in sites_to_fix:
old_slug = site.slug
site.slug = generate_slug(site.name, site.id)
print(f" - Site #{site.id} '{site.name}': '{old_slug}' -> '{site.slug}'")
db.session.commit()
print(f"Successfully fixed {len(sites_to_fix)} sites!")
except Exception as e:
print(f"Migration failed: {str(e)}")
import traceback
traceback.print_exc()
db.session.rollback()

View File

@@ -0,0 +1,25 @@
"""修改slug字段为可空的迁移脚本"""
import sys
import os
# 添加项目根目录到系统路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app import create_app
from models import db
from sqlalchemy import text
# 创建应用上下文
app = create_app()
with app.app_context():
# 使用原生SQL修改列属性
try:
# MySQL语法修改slug列为可空
with db.engine.connect() as connection:
connection.execute(text('ALTER TABLE sites MODIFY COLUMN slug VARCHAR(100) NULL'))
connection.commit()
print("slug field successfully updated to nullable!")
except Exception as e:
print(f"Migration failed: {str(e)}")
print("Note: If the field is already nullable, you can ignore this error.")