/** @jsxImportSource https://esm.d8d.fun/hono@4.7.4/jsx */ import { Hono } from 'hono' import { Auth } from '@d8d-appcontainer/auth' import type { User as AuthUser } from '@d8d-appcontainer/auth' import React from 'hono/jsx' import type { FC } from 'hono/jsx' import { cors } from 'hono/cors' import type { Context as HonoContext } from 'hono' import { serveStatic } from 'hono/deno' import { APIClient } from '@d8d-appcontainer/api' import debug from "debug" import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import type { SystemSettingRecord, GlobalConfig } from '../client/share/types.ts'; import { SystemSettingKey, OssType, MapMode } from '../client/share/types.ts'; import { createKnowInfoRoutes, createFileCategoryRoutes, createFileUploadRoutes, createThemeRoutes, createSystemSettingsRoutes, } from "./routes_sys.ts"; import { createMapRoutes, } from "./routes_maps.ts"; import { createChartRoutes, } from "./routes_charts.ts"; // 导入基础路由 import { createAuthRoutes } from "./routes_auth.ts"; import { createUserRoutes } from "./routes_users.ts"; import { createMessagesRoutes } from "./routes_messages.ts"; import { createMigrationsRoutes } from "./routes_migrations.ts"; import { createHomeRoutes } from "./routes_home.ts"; dayjs.extend(utc) // 初始化debug实例 const log = { app: debug('app:server'), auth: debug('auth:server'), api: debug('api:server'), debug: debug('debug:server') } const GLOBAL_CONFIG: GlobalConfig = { OSS_BASE_URL: Deno.env.get('OSS_BASE_URL') || 'https://d8d-appcontainer-user.oss-cn-beijing.aliyuncs.com', OSS_TYPE: Deno.env.get('OSS_TYPE') === OssType.MINIO ? OssType.MINIO : OssType.ALIYUN, API_BASE_URL: '/api', APP_NAME: Deno.env.get('APP_NAME') || '应用Starter', ENV: Deno.env.get('ENV') || 'development', DEFAULT_THEME: 'light', // 默认主题 MAP_CONFIG: { KEY: Deno.env.get('AMAP_KEY') || '您的地图API密钥', VERSION: '2.0', PLUGINS: ['AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation'], MAP_MODE: Deno.env.get('MAP_MODE') === MapMode.OFFLINE ? MapMode.OFFLINE : MapMode.ONLINE, }, CHART_THEME: 'default', // 图表主题 ENABLE_THEME_CONFIG: false, // 主题配置开关 THEME: null }; log.app.enabled = true log.auth.enabled = true log.api.enabled = true log.debug.enabled = true // 定义自定义上下文类型 export interface Variables { auth: Auth user?: AuthUser apiClient: APIClient moduleDir: string systemSettings?: SystemSettingRecord } // 定义登录历史类型 interface LoginHistory { id: number user_id: number login_time: string ip_address?: string user_agent?: string } // 定义仪表盘数据类型 interface DashboardData { lastLogin: string loginCount: number fileCount: number userCount: number systemInfo: { version: string lastUpdate: string } } interface EsmScriptConfig { src: string href: string denoJson: string refresh: boolean prodPath?: string prodSrc?: string } // Auth实例 let authInstance: Auth | null = null // 初始化Auth实例 const initAuth = async (apiClient: APIClient) => { try { if (authInstance) { return authInstance } log.auth('正在初始化Auth实例') authInstance = new Auth(apiClient as any, { jwtSecret: Deno.env.get("JWT_SECRET") || 'your-jwt-secret-key', initialUsers: [], storagePrefix: '', userTable: 'users', fieldNames: { id: 'id', username: 'username', password: 'password', phone: 'phone', email: 'email', is_disabled: 'is_disabled', is_deleted: 'is_deleted' }, tokenExpiry: 24 * 60 * 60, refreshTokenExpiry: 7 * 24 * 60 * 60 }) log.auth('Auth实例初始化完成') return authInstance } catch (error) { log.auth('Auth初始化失败:', error) throw error } } // 初始化系统设置 const initSystemSettings = async (apiClient: APIClient) => { try { const systemSettings = await apiClient.database.table('system_settings') .select() // 将系统设置转换为键值对形式 const settings = systemSettings.reduce((acc: Record, setting: any) => { acc[setting.key] = setting.value return acc }, {}) as SystemSettingRecord // 更新全局配置 if (settings[SystemSettingKey.SITE_NAME]) { GLOBAL_CONFIG.APP_NAME = String(settings[SystemSettingKey.SITE_NAME]) } // 设置其他全局配置项 if (settings[SystemSettingKey.SITE_FAVICON]) { GLOBAL_CONFIG.DEFAULT_THEME = String(settings[SystemSettingKey.SITE_FAVICON]) } if (settings[SystemSettingKey.SITE_LOGO]) { GLOBAL_CONFIG.MAP_CONFIG.KEY = String(settings[SystemSettingKey.SITE_LOGO]) } if (settings[SystemSettingKey.SITE_DESCRIPTION]) { GLOBAL_CONFIG.CHART_THEME = String(settings[SystemSettingKey.SITE_DESCRIPTION]) } // 设置主题配置开关 if (settings[SystemSettingKey.ENABLE_THEME_CONFIG]) { GLOBAL_CONFIG.ENABLE_THEME_CONFIG = settings[SystemSettingKey.ENABLE_THEME_CONFIG] === 'true' } // 查询ID1管理员的主题配置 const adminTheme = await apiClient.database.table('theme_settings') .where('user_id', 1) .first() if (adminTheme) { GLOBAL_CONFIG.THEME = adminTheme.settings } return settings } catch (error) { log.app('获取系统设置失败:', error) return {} as SystemSettingRecord } } // 中间件:验证认证 const withAuth = async (c: HonoContext<{ Variables: Variables }>, next: () => Promise) => { try { const auth = c.get('auth') const token = c.req.header('Authorization')?.replace('Bearer ', '') if (token) { const userData = await auth.verifyToken(token) if (userData) { c.set('user', userData) await next() return } } return c.json({ error: '未授权' }, 401) } catch (error) { log.auth('认证失败:', error) return c.json({ error: '无效凭证' }, 401) } } // 导出withAuth类型定义 export type WithAuth = typeof withAuth; // 定义模块参数接口 interface ModuleParams { apiClient: APIClient app: Hono moduleDir: string } export default function({ apiClient, app, moduleDir }: ModuleParams) { const honoApp = app // 添加CORS中间件 honoApp.use('/*', cors()) // 创建API路由 const api = new Hono<{ Variables: Variables }>() // // 使用数据库中间件 // api.use('/*', withDatabase) // 设置环境变量 api.use('*', async (c, next) => { c.set('apiClient', apiClient) c.set('moduleDir', moduleDir) c.set('auth', await initAuth(apiClient)) c.set('systemSettings', await initSystemSettings(apiClient)) await next() }) // 查询仪表盘数据 api.get('/dashboard', withAuth, async (c) => { try { const user = c.get('user')! const apiClient = c.get('apiClient') const lastLogin = await apiClient.database.table('login_history') .where('user_id', user.id) .orderBy('login_time', 'desc') .limit(1) .first() // 获取登录总次数 const loginCount = await apiClient.database.table('login_history') .where('user_id', user.id) .count() // 获取系统数据统计 const fileCount = await apiClient.database.table('file_library') .where('is_deleted', 0) .count() const userCount = await apiClient.database.table('users') .where('is_deleted', 0) .count() // 返回仪表盘数据 const dashboardData: DashboardData = { lastLogin: lastLogin ? lastLogin.login_time : new Date().toISOString(), loginCount: loginCount, fileCount: Number(fileCount), userCount: Number(userCount), systemInfo: { version: '1.0.0', lastUpdate: new Date().toISOString() } } return c.json(dashboardData) } catch (error) { log.api('获取仪表盘数据失败:', error) return c.json({ error: '获取仪表盘数据失败' }, 500) } }) // 注册基础路由 api.route('/auth', createAuthRoutes(withAuth)) api.route('/users', createUserRoutes(withAuth)) api.route('/know-infos', createKnowInfoRoutes(withAuth)) api.route('/upload', createFileUploadRoutes(withAuth)) // 添加文件上传路由 api.route('/file-categories', createFileCategoryRoutes(withAuth)) // 添加文件分类管理路由 api.route('/theme', createThemeRoutes(withAuth)) // 添加主题设置路由 api.route('/charts', createChartRoutes(withAuth)) // 添加图表数据路由 api.route('/map', createMapRoutes(withAuth)) // 添加地图数据路由 api.route('/settings', createSystemSettingsRoutes(withAuth)) // 添加系统设置路由 api.route('/messages', createMessagesRoutes(withAuth)) // 添加消息路由 api.route('/migrations', createMigrationsRoutes(withAuth)) // 添加数据库迁移路由 api.route('/home', createHomeRoutes(withAuth)) // 添加首页路由 // 注册API路由 honoApp.route('/api', api) // 首页路由 - SSR honoApp.get('/', async (c: HonoContext) => { const systemName = GLOBAL_CONFIG.APP_NAME return c.html( {systemName}
{/* 系统介绍区域 */}

{systemName}

全功能应用Starter

这是一个基于Hono和React的应用Starter,提供了用户认证、文件管理、图表分析、地图集成和主题切换等常用功能。

{/* 管理入口按钮 */}
进入管理后台 {/* 移动端入口按钮 */} 进入移动端
) }) // 创建一个函数,用于生成包含全局配置的HTML页面 const createHtmlWithConfig = (scriptConfig: EsmScriptConfig, title = '应用Starter') => { return (c: HonoContext) => { const isProd = GLOBAL_CONFIG.ENV === 'production'; return c.html( {title} {isProd ? ( ) : ( )} {isProd ? () : ()}