diff --git a/bun.lockb b/bun.lockb index 2df1c7b..f91fe08 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/database/development.sqlite3-shm b/database/development.sqlite3-shm index 5ef3ae7..e97f00a 100644 Binary files a/database/development.sqlite3-shm and b/database/development.sqlite3-shm differ diff --git a/database/development.sqlite3-wal b/database/development.sqlite3-wal index ab870b4..805e8c0 100644 Binary files a/database/development.sqlite3-wal and b/database/development.sqlite3-wal differ diff --git a/entrypoint.sh b/entrypoint.sh index f96b133..4796b52 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,6 +3,7 @@ set -e # 数据库文件路径(可根据实际环境调整) DB_FILE=./database/db.sqlite3 +ENV=${NODE_ENV:-production} # 检查 bun 是否存在 if command -v bun >/dev/null 2>&1; then @@ -16,8 +17,8 @@ fi # 如果数据库文件不存在,先 migrate 再 seed if [ ! -f "$DB_FILE" ]; then echo "Database not found, running migration and seed..." - $RUNNER npx knex migrate:latest - $RUNNER npx knex seed:run + $RUNNER npx knex migrate:latest --env $ENV + $RUNNER npx knex seed:run --env $ENV else echo "Database exists, running migration only..." $RUNNER npx knex migrate:latest diff --git a/package.json b/package.json index 6ae4bd6..8ff90bb 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "bun --hot src/main.js", "start": "bun run src/main.js", + "build": "vite build", "migrate:make": "npx knex migrate:make ", "migrate": "npx knex migrate:latest", "seed:make": "npx knex seed:make ", @@ -13,7 +14,8 @@ }, "devDependencies": { "@types/bun": "latest", - "@types/node": "^24.0.1" + "@types/node": "^24.0.1", + "vite": "^7.0.0" }, "dependencies": { "bcryptjs": "^3.0.2", @@ -31,7 +33,8 @@ "node-cron": "^4.1.0", "path-to-regexp": "^8.2.0", "pug": "^3.0.3", - "sqlite3": "^5.1.7" + "sqlite3": "^5.1.7", + "vite-plugin-static-copy": "^3.1.0" }, "_moduleAliases": { "@": "./src", diff --git a/public/css/page/index.css b/public/css/page/index.css new file mode 100644 index 0000000..fdc3fa9 --- /dev/null +++ b/public/css/page/index.css @@ -0,0 +1,12 @@ +.home-hero { + margin: 20px 20px 40px; + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(12px); +} + +@media screen and (max-width: 768px) { + .home-hero { + margin: 0; + margin-top: 20px; + } +} \ No newline at end of file diff --git a/public/styles.css b/public/styles.css index ae1b050..14841b6 100644 --- a/public/styles.css +++ b/public/styles.css @@ -123,4 +123,37 @@ body::after { background: rgba(255, 255, 255, 0.25); backdrop-filter: blur(18px); color: #fff; +} + + +@media screen and (max-width: 768px) { + .nav { + width: 0; + height: 0; + overflow: hidden; + padding: 0; + margin: 0; + } + .flota-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + width: 100%; + display: flex; + z-index: 9999; + padding: 0 10px; + height: 40px; + border-radius: 0; + } + + .flota-nav .item{ + margin-bottom: 0; + padding: 0 10px; + } + + .content { + padding: 0 10px; + padding-top: 40px; + } } \ No newline at end of file diff --git a/src/db/seeds/20250621013324_site_config_seed.mjs b/src/db/seeds/20250621013324_site_config_seed.mjs index afb8a67..e182c53 100644 --- a/src/db/seeds/20250621013324_site_config_seed.mjs +++ b/src/db/seeds/20250621013324_site_config_seed.mjs @@ -4,7 +4,8 @@ export const seed = async (knex) => { // 插入常用站点配置项 await knex('site_config').insert([ - { key: 'site_title', value: '🥔未野明的小屋' }, + { key: 'site_title', value: '罗非鱼的秘密' }, + { key: 'site_author', value: '罗非鱼' }, { key: 'site_description', value: '一屋很小,却也很大' }, { key: 'site_logo', value: '/static/logo.png' }, { key: 'site_bg', value: '/static/bg.jpg' }, diff --git a/src/utils/ForRegister.js b/src/utils/ForRegister.js index ad0499f..21a1df7 100644 --- a/src/utils/ForRegister.js +++ b/src/utils/ForRegister.js @@ -3,6 +3,14 @@ import fs from "fs" import path from "path" +// 保证不会被摇树(tree-shaking),即使在生产环境也会被打包 +if (import.meta.env.PROD) { + // 通过引用返回值,防止被摇树优化 + let controllers = import.meta.glob("../controllers/**/*Controller.js", { eager: true }) + controllers = null + console.log(controllers); +} + /** * 自动扫描 controllers 目录,注册所有导出的路由 * 自动检测 routes 目录下已手动注册的 controller,避免重复注册 diff --git a/src/views/htmx/footer.pug b/src/views/htmx/footer.pug index dbe4f62..ce17895 100644 --- a/src/views/htmx/footer.pug +++ b/src/views/htmx/footer.pug @@ -1,16 +1,16 @@ .footer-panel .footer-content - p © 2023-2025 My Website. 保留所有权利。 + p © 2023-#{new Date().getFullYear()} #{$site.site_title}. 保留所有权利。 ul.footer-links li a(href="/about") 关于我们 - li - a(href="/contact") 联系方式 - li - a(href="/privacy") 隐私 + //- li + //- a(href="/contact") 联系方式 + //- li + //- a(href="/privacy") 隐私 style. .footer-panel { - background: rgba(34,34,34,.6); + background: rgba(34,34,34,.3); backdrop-filter: blur(12px); color: #eee; padding: 40px 0 24px 0; diff --git a/src/views/layouts/base.pug b/src/views/layouts/base.pug index 1e5118a..cc6c9ec 100644 --- a/src/views/layouts/base.pug +++ b/src/views/layouts/base.pug @@ -4,7 +4,7 @@ mixin include() mixin css(url, extranl = false) if extranl || url.startsWith('http') || url.startsWith('//') - style(type="text/css" href=url) + link(rel="stylesheet" type="text/css" href=url) else link(rel="stylesheet", href=($config && $config.base || "") + url) diff --git a/src/views/layouts/page.pug b/src/views/layouts/page.pug index d9395b3..f6353e1 100644 --- a/src/views/layouts/page.pug +++ b/src/views/layouts/page.pug @@ -5,7 +5,6 @@ block head block pageHead block content - // 页面整体flex布局,footer吸底 .page-layout .page - const navs = []; diff --git a/src/views/page/index/index.pug b/src/views/page/index/index.pug index 5026816..97b371c 100644 --- a/src/views/page/index/index.pug +++ b/src/views/page/index/index.pug @@ -1,88 +1,10 @@ extends /layouts/page.pug +block pageHead + +css("css/page/index.css") + block pageContent - .home-hero + .card.home-hero h1 #{$site.site_title} p.subtitle #{$site.site_description} - - style. - .home-hero { - text-align: center; - padding: 60px 0 40px 0; - margin: 20px 20px; - //- background: linear-gradient(90deg, #4fc3f7 0%, #1976d2 100%); - background: rgba(255, 255, 255, 0.1); - backdrop-filter: blur(12px); - color: #fff; - border-radius: 12px; - margin-bottom: 40px; - } - .home-hero h1 { - font-size: 2.8em; - margin-bottom: 42px; - letter-spacing: 2px; - } - .home-hero .subtitle { - font-size: 1.3em; - margin-bottom: 28px; - color: #e3f2fd; - } - .home-hero .actions { - margin-top: 18px; - } - .btn-primary, .btn-secondary { - display: inline-block; - padding: 10px 28px; - border-radius: 24px; - font-size: 1em; - margin: 0 10px; - text-decoration: none; - transition: background 0.2s, color 0.2s; - } - .btn-primary { - background: #fff; - color: #1976d2; - font-weight: bold; - border: none; - } - .btn-primary:hover { - background: #e3f2fd; - color: #1565c0; - } - .btn-secondary { - background: transparent; - color: #fff; - border: 1px solid #fff; - } - .btn-secondary:hover { - background: #1976d2; - color: #fff; - border-color: #e3f2fd; - } - .features { - display: flex; - justify-content: space-around; - margin-top: 40px; - gap: 24px; - flex-wrap: wrap; - } - .feature { - background: #fafbfc; - border-radius: 10px; - box-shadow: 0 2px 8px rgba(30, 136, 229, 0.08); - padding: 28px 24px; - flex: 1 1 220px; - min-width: 220px; - max-width: 320px; - text-align: center; - margin: 0 8px; - } - .feature h2 { - font-size: 1.3em; - margin-bottom: 10px; - color: #1976d2; - } - .feature p { - color: #333; - font-size: 1em; - margin: 0; \ No newline at end of file + diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..fcf832d --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,83 @@ +import { dirname, resolve } from "node:path" +import { fileURLToPath } from "node:url" +import module from "node:module" +import { defineConfig } from "vite" +import pkg from "./package.json" +import { viteStaticCopy } from "vite-plugin-static-copy" + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +function getExternal(): string[] { + return [...Object.keys(pkg.dependencies || {}), ...module.builtinModules] +} + +export default defineConfig({ + publicDir: false, + resolve: { + alias: { + "@": resolve(__dirname, "src"), + db: resolve(__dirname, "src/db"), + config: resolve(__dirname, "src/config"), + utils: resolve(__dirname, "src/utils"), + services: resolve(__dirname, "src/services"), + }, + }, + build: { + lib: { + entry: resolve(__dirname, "src/main.js"), + formats: ["es"], + fileName: () => `[name].js`, + }, + outDir: resolve(__dirname, "dist"), + rollupOptions: { + external: getExternal(), + // watch: { + // include: "src/**", + // exclude: "node_modules/**", + // }, + output: { + preserveModules: true, + preserveModulesRoot: "src", + inlineDynamicImports: false, + }, + }, + }, + plugins: [ + viteStaticCopy({ + targets: [ + { + src: "public", + dest: "", + }, + { + src: "src/views", + dest: "", + }, + { + src: "src/db/migrations", + dest: "db", + }, + { + src: "src/db/seeds", + dest: "db", + }, + { + src: "entrypoint.sh", + dest: "", + }, + { + src: "package.json", + dest: "", + }, + { + src: "knexfile.mjs", + dest: "", + }, + { + src: "bun.lockb", + dest: "", + }, + ], + }), + ], +})