118 lines
3.0 KiB
Go
118 lines
3.0 KiB
Go
package database
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
_ "modernc.org/sqlite"
|
||
)
|
||
|
||
// DB 数据库实例
|
||
type DB struct {
|
||
*sql.DB
|
||
}
|
||
|
||
// InitDB 初始化数据库
|
||
func InitDB(dbPath string) (*DB, error) {
|
||
// 确保数据库目录存在
|
||
dbDir := filepath.Dir(dbPath)
|
||
if err := os.MkdirAll(dbDir, 0755); err != nil {
|
||
return nil, fmt.Errorf("创建数据库目录失败: %v", err)
|
||
}
|
||
|
||
// 打开数据库连接(使用modernc.org/sqlite驱动)
|
||
db, err := sql.Open("sqlite", dbPath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("打开数据库失败: %v", err)
|
||
}
|
||
|
||
// 测试连接
|
||
if err := db.Ping(); err != nil {
|
||
return nil, fmt.Errorf("数据库连接测试失败: %v", err)
|
||
}
|
||
|
||
// 创建表
|
||
if err := createTables(db); err != nil {
|
||
return nil, fmt.Errorf("创建数据表失败: %v", err)
|
||
}
|
||
|
||
fmt.Println("✅ 数据库初始化成功:", dbPath)
|
||
return &DB{db}, nil
|
||
}
|
||
|
||
// createTables 创建数据表
|
||
func createTables(db *sql.DB) error {
|
||
// 公众号表
|
||
officialAccountTable := `
|
||
CREATE TABLE IF NOT EXISTS official_accounts (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
biz TEXT NOT NULL UNIQUE,
|
||
nickname TEXT NOT NULL,
|
||
homepage TEXT,
|
||
description TEXT,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_biz ON official_accounts(biz);
|
||
CREATE INDEX IF NOT EXISTS idx_nickname ON official_accounts(nickname);
|
||
`
|
||
|
||
// 文章表
|
||
articleTable := `
|
||
CREATE TABLE IF NOT EXISTS articles (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
official_id INTEGER NOT NULL,
|
||
title TEXT NOT NULL,
|
||
author TEXT,
|
||
link TEXT UNIQUE,
|
||
publish_time TEXT,
|
||
create_time TEXT,
|
||
comment_id TEXT,
|
||
read_num INTEGER DEFAULT 0,
|
||
like_num INTEGER DEFAULT 0,
|
||
share_num INTEGER DEFAULT 0,
|
||
content_preview TEXT,
|
||
paragraph_count INTEGER DEFAULT 0,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (official_id) REFERENCES official_accounts(id)
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_official_id ON articles(official_id);
|
||
CREATE INDEX IF NOT EXISTS idx_title ON articles(title);
|
||
CREATE INDEX IF NOT EXISTS idx_publish_time ON articles(publish_time);
|
||
CREATE INDEX IF NOT EXISTS idx_link ON articles(link);
|
||
`
|
||
|
||
// 文章内容表
|
||
articleContentTable := `
|
||
CREATE TABLE IF NOT EXISTS article_contents (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
article_id INTEGER NOT NULL UNIQUE,
|
||
html_content TEXT,
|
||
text_content TEXT,
|
||
paragraphs TEXT,
|
||
images TEXT,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_article_id ON article_contents(article_id);
|
||
`
|
||
|
||
// 执行创建表语句
|
||
tables := []string{officialAccountTable, articleTable, articleContentTable}
|
||
for _, table := range tables {
|
||
if _, err := db.Exec(table); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Close 关闭数据库连接
|
||
func (db *DB) Close() error {
|
||
return db.DB.Close()
|
||
}
|