- NavClick 加 anon_id 字段(已为历史表自动迁移) - 后端静默下发 wk_anon cookie(uuid4,1 年,HttpOnly) - 点击埋点写入 anon_id;新增 GET /site/api/my-top 与 POST /site/api/my-clear - 首页服务端渲染「我常访问」区(时间衰减加权分),与「热门网址」共显 - 前端 localStorage 累计 + 与服务端榜取 max 合并;冷启动阈值 2 个网址 - 一键清除:清 localStorage + 服务端删该匿名 ID 的全部记录 - 移动端抽屉、顶部导航同步加「我常访问」入口 - 底部隐私说明更新
49 lines
1.8 KiB
Python
49 lines
1.8 KiB
Python
"""一次性脚本:给已有的 site_nav_click 表加 anon_id 列(幂等,可重复执行)。
|
||
|
||
用法: PYTHONPATH=. python scripts/ensure_nav_click_anon_id.py
|
||
"""
|
||
import os
|
||
import sqlite3
|
||
|
||
from app import app
|
||
from applications.extensions import db
|
||
|
||
with app.app_context():
|
||
uri = str(db.engine.url)
|
||
if not uri.startswith('sqlite'):
|
||
print('非 SQLite,跳过(MySQL 请用 flask db migrate/upgrade 或手工 ALTER TABLE)')
|
||
raise SystemExit(0)
|
||
|
||
# 注意:用 engine.url.database,而不是配置里的相对路径(配置可能是 sqlite:///../pear.db)
|
||
path = db.engine.url.database or ''
|
||
path = os.path.abspath(os.path.normpath(path))
|
||
print('DB:', path)
|
||
|
||
conn = sqlite3.connect(path)
|
||
cur = conn.cursor()
|
||
cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='site_nav_click'")
|
||
if not cur.fetchone():
|
||
print('表不存在,交给 db.create_all() 处理')
|
||
conn.close()
|
||
from applications.extensions import db
|
||
from applications.models import NavClick # noqa: F401
|
||
db.create_all()
|
||
print('OK: 已建表(含 anon_id)')
|
||
raise SystemExit(0)
|
||
|
||
cur.execute('PRAGMA table_info(site_nav_click)')
|
||
cols = [r[1] for r in cur.fetchall()]
|
||
print('现有列:', cols)
|
||
|
||
if 'anon_id' in cols:
|
||
print('OK: anon_id 已存在,无需变更')
|
||
else:
|
||
cur.execute("ALTER TABLE site_nav_click ADD COLUMN anon_id VARCHAR(36) DEFAULT ''")
|
||
cur.execute('CREATE INDEX IF NOT EXISTS ix_site_nav_click_anon_id ON site_nav_click (anon_id)')
|
||
conn.commit()
|
||
print('OK: 已添加 anon_id 列 + 索引')
|
||
|
||
cur.execute('PRAGMA table_info(site_nav_click)')
|
||
print('变更后列:', [r[1] for r in cur.fetchall()])
|
||
conn.close()
|