diff --git a/.gitignore b/.gitignore
index 91a3710..92a07e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,4 +23,4 @@ Thumbs.db
.idea/
.vscode/
*.swp
-*.swo
\ No newline at end of file
+*.swoclient/src/.share-done
diff --git a/client/src/App.vue b/client/src/App.vue
index 52908e9..91a03f3 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -81,7 +81,7 @@ page, .theme-light {
/* 卡片 — 纯白微阴影 */
--glass-bg: #ffffff;
- --glass-border: rgba(0, 0, 0, 0.06);
+ --glass-border: rgba(0, 0, 0, 0.08);
--glass-hover: #f8f8ff;
--glass-hover-border: rgba(99, 102, 241, 0.15);
--glass-strong: #ffffff;
@@ -89,8 +89,8 @@ page, .theme-light {
/* 文字 — 清晰深色 */
--text-primary: #0d0d1a;
- --text-secondary: rgba(13, 13, 26, 0.6);
- --text-tertiary: rgba(13, 13, 26, 0.4);
+ --text-secondary: rgba(13, 13, 26, 0.68);
+ --text-tertiary: rgba(13, 13, 26, 0.48);
--text-muted: rgba(13, 13, 26, 0.25);
--text-disabled: rgba(13, 13, 26, 0.15);
diff --git a/client/src/manifest.json b/client/src/manifest.json
index ee62fec..afc376d 100644
--- a/client/src/manifest.json
+++ b/client/src/manifest.json
@@ -1,7 +1,7 @@
{
"name": "宇之然AI维度",
"appid": "wxdad62baf4ccd09e3",
- "versionName": "1.1.5",
+ "versionName": "1.2.7",
"versionCode": "100",
"description": "AI 知识探索社区 — 从5个维度系统理解人工智能",
"uni-app": {
diff --git a/client/src/pages.json b/client/src/pages.json
index bd8c84c..60619f4 100644
--- a/client/src/pages.json
+++ b/client/src/pages.json
@@ -124,6 +124,18 @@
"navigationBarTitleText": "协议",
"navigationStyle": "custom"
}
+ },
+ {
+ "path": "pages/map/map",
+ "style": {
+ "navigationBarTitleText": "AI 知识地图"
+ }
+ },
+ {
+ "path": "pages/map/quiz",
+ "style": {
+ "navigationBarTitleText": "知识闯关"
+ }
}
],
"globalStyle": {
diff --git a/client/src/pages/map/map.vue b/client/src/pages/map/map.vue
new file mode 100644
index 0000000..d6c85fe
--- /dev/null
+++ b/client/src/pages/map/map.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+ {{ level.icon }}
+ {{ level.name }} Lv{{ level.level }}
+
+
+ 💎
+ {{ credits }}
+
+
+
+
+
+
+ {{ island.icon }}
+ {{ island.name }}
+ ⭐
+ 🔒
+
+
+
+
+
+ 完成一个知识关后解锁
+
+
+
+
+
+
+
diff --git a/client/src/pages/map/quiz.vue b/client/src/pages/map/quiz.vue
new file mode 100644
index 0000000..44e54bc
--- /dev/null
+++ b/client/src/pages/map/quiz.vue
@@ -0,0 +1,89 @@
+
+
+
+
+ {{ currentQ.q }}
+
+ {{ labels[i] }}. {{ opt }}
+
+
+ {{ resultText }}
+
+
+
+
+
+
+
+
+
diff --git a/server/src/index.js b/server/src/index.js
index c1b9593..5df959f 100755
--- a/server/src/index.js
+++ b/server/src/index.js
@@ -1,105 +1,109 @@
-require('dotenv').config()
-
-const express = require('express')
-const cors = require('cors')
-const helmet = require('helmet')
-const compression = require('compression')
-const morgan = require('morgan')
-const rateLimit = require('express-rate-limit')
-
-const connectDB = require('./config/database')
-const initRoutes = require('./routes')
-const logger = require('./utils/logger')
-
-// 创建 Express 应用
-const app = express()
-
-// 数据库连接
-connectDB()
-
-// 中间件配置
-app.use(helmet()) // 安全头部
-app.use(cors()) // 跨域支持
-app.use(compression()) // Gzip 压缩
-app.use(express.json({ limit: '10mb' })) // JSON 解析
-app.use(express.urlencoded({ extended: true, limit: '10mb' })) // URL 编码解析
-
-// 日志中间件
-if (process.env.NODE_ENV === 'development') {
- app.use(morgan('dev'))
-} else {
- app.use(morgan('combined'))
-}
-
-// 速率限制
-const limiter = rateLimit({
- windowMs: 15 * 60 * 1000, // 15 分钟
- max: 1000, // 每个 IP 最多 1000 次请求
- message: {
- success: false,
- error: '请求过于频繁,请稍后再试'
- }
-})
-app.use('/api/', limiter)
-
-// 健康检查
-app.get('/health', (req, res) => {
- res.status(200).json({
- status: 'ok',
- timestamp: new Date().toISOString(),
- uptime: process.uptime()
- })
-})
-
-// API 路由
-initRoutes(app)
-
-// 404 处理
-app.use((req, res) => {
- res.status(404).json({
- success: false,
- error: '接口不存在',
- path: req.path
- })
-})
-
-// 全局错误处理
-app.use((err, req, res, next) => {
- logger.error('服务器错误:', err)
-
- res.status(err.status || 500).json({
- success: false,
- error: process.env.NODE_ENV === 'production'
- ? '服务器内部错误'
- : err.message,
- stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
- })
-})
-
-// 启动服务器(仅在直接运行时启动,被测试 import 时不启动)
-const PORT = process.env.PORT || 3000
-let server = null
-
-if (require.main === module) {
- server = app.listen(PORT, () => {
- logger.info(`🚀 服务器启动成功`)
- logger.info(`📍 端口: ${PORT}`)
- logger.info(`🌐 环境: ${process.env.NODE_ENV || 'development'}`)
- logger.info(`📊 健康检查: http://localhost:${PORT}/health`)
- })
-}
-
-// 优雅关闭
-process.on('SIGTERM', () => {
- logger.info('📴 接收到 SIGTERM 信号,正在关闭服务器...')
- if (server) {
- server.close(() => {
- logger.info('✅ 服务器已关闭')
- process.exit(0)
- })
- } else {
- process.exit(0)
- }
-})
-
-module.exports = app
+require('dotenv').config()
+
+const express = require('express')
+const cors = require('cors')
+const helmet = require('helmet')
+const compression = require('compression')
+const morgan = require('morgan')
+const rateLimit = require('express-rate-limit')
+
+const connectDB = require('./config/database')
+const initRoutes = require('./routes')
+const seoRoutes = require('./routes/seo')
+const logger = require('./utils/logger')
+
+// 创建 Express 应用
+const app = express()
+
+// 数据库连接
+connectDB()
+
+// SEO/GEO 路由(robots/sitemap/llms/about)
+app.use('/', seoRoutes)
+
+// 中间件配置
+app.use(helmet()) // 安全头部
+app.use(cors()) // 跨域支持
+app.use(compression()) // Gzip 压缩
+app.use(express.json({ limit: '10mb' })) // JSON 解析
+app.use(express.urlencoded({ extended: true, limit: '10mb' })) // URL 编码解析
+
+// 日志中间件
+if (process.env.NODE_ENV === 'development') {
+ app.use(morgan('dev'))
+} else {
+ app.use(morgan('combined'))
+}
+
+// 速率限制
+const limiter = rateLimit({
+ windowMs: 15 * 60 * 1000, // 15 分钟
+ max: 1000, // 每个 IP 最多 1000 次请求
+ message: {
+ success: false,
+ error: '请求过于频繁,请稍后再试'
+ }
+})
+app.use('/api/', limiter)
+
+// 健康检查
+app.get('/health', (req, res) => {
+ res.status(200).json({
+ status: 'ok',
+ timestamp: new Date().toISOString(),
+ uptime: process.uptime()
+ })
+})
+
+// API 路由
+initRoutes(app)
+
+// 404 处理
+app.use((req, res) => {
+ res.status(404).json({
+ success: false,
+ error: '接口不存在',
+ path: req.path
+ })
+})
+
+// 全局错误处理
+app.use((err, req, res, next) => {
+ logger.error('服务器错误:', err)
+
+ res.status(err.status || 500).json({
+ success: false,
+ error: process.env.NODE_ENV === 'production'
+ ? '服务器内部错误'
+ : err.message,
+ stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
+ })
+})
+
+// 启动服务器(仅在直接运行时启动,被测试 import 时不启动)
+const PORT = process.env.PORT || 3000
+let server = null
+
+if (require.main === module) {
+ server = app.listen(PORT, () => {
+ logger.info(`🚀 服务器启动成功`)
+ logger.info(`📍 端口: ${PORT}`)
+ logger.info(`🌐 环境: ${process.env.NODE_ENV || 'development'}`)
+ logger.info(`📊 健康检查: http://localhost:${PORT}/health`)
+ })
+}
+
+// 优雅关闭
+process.on('SIGTERM', () => {
+ logger.info('📴 接收到 SIGTERM 信号,正在关闭服务器...')
+ if (server) {
+ server.close(() => {
+ logger.info('✅ 服务器已关闭')
+ process.exit(0)
+ })
+ } else {
+ process.exit(0)
+ }
+})
+
+module.exports = app