diff --git a/src/composables/useKnowledge.js b/src/composables/useKnowledge.js
index d3cd477..29952d4 100644
--- a/src/composables/useKnowledge.js
+++ b/src/composables/useKnowledge.js
@@ -4,6 +4,7 @@ import {
mockEbooks,
mockEbookChapters,
} from '@/data/mockData.js'
+import { ACCESS_LEVEL } from '@/utils/access.js'
export async function fetchEbooks() {
return [...mockEbooks]
@@ -35,3 +36,22 @@ export async function fetchCourse(courseId) {
const list = await fetchCourses()
return list.find((item) => String(item.id) === String(courseId)) || null
}
+
+/** 获取各课程的首个免费试看章节 */
+export async function fetchFreeTrialChapters() {
+ const courses = await fetchCourses()
+ const result = []
+ for (const course of courses) {
+ const chapters = mockCourseChapters[course.id] || []
+ const freeChapter = chapters.find((ch) => ch.access_level === ACCESS_LEVEL.FREE)
+ if (freeChapter) {
+ result.push({
+ courseId: course.id,
+ courseTitle: course.title,
+ chapterId: freeChapter.id,
+ chapterTitle: freeChapter.title,
+ })
+ }
+ }
+ return result
+}
diff --git a/src/config/app.js b/src/config/app.js
index 7620a29..880a3a8 100644
--- a/src/config/app.js
+++ b/src/config/app.js
@@ -8,3 +8,48 @@ export const NAV_ITEMS = [
{ path: '/', label: '首页' },
{ path: '/vip', label: '会员' },
]
+
+/** 网盘配置 - 多个独立资源 */
+export const NETDISK_CONFIG = {
+ enabled: true,
+ items: [
+ { id: 1, name: '大模型', desc: 'GPT、Claude、国产大模型资源包', url: 'https://pan.baidu.com', icon: 'fire-o' },
+ { id: 2, name: '懒人安装包', desc: '一键安装,开箱即用', url: 'https://pan.baidu.com', icon: 'down' },
+ { id: 3, name: '课程讲义', desc: '配套 PPT、思维导图', url: 'https://pan.baidu.com', icon: 'notes-o' },
+ { id: 4, name: '源码合集', desc: '课程示例代码与项目', url: 'https://pan.baidu.com', icon: 'records-o' },
+ ],
+}
+
+/** 限时优惠配置 */
+export const PROMO_CONFIG = {
+ enabled: false,
+ title: '限时优惠',
+ desc: '报名立享 8 折,仅限本周',
+ endAt: null, // 如 '2025-03-18 23:59:59' 可显示倒计时
+ href: '/vip',
+}
+
+/** 免费试看配置 */
+export const FREE_TRIAL_CONFIG = {
+ enabled: false,
+}
+
+/** 课程预告配置 */
+export const COMING_SOON_CONFIG = {
+ enabled: true,
+ items: [
+ { id: 'soon-1', title: '多模态 AI 实战', desc: '图文理解、语音识别、视频生成', eta: '即将上线' },
+ { id: 'soon-2', title: 'AI 副业变现', desc: '从 0 到 1 打造 AI 产品', eta: '筹备中' },
+ ],
+}
+
+/** 学习群配置 - 仅展示 QQ 群,微信群隐藏 */
+export const STUDY_GROUP_CONFIG = {
+ enabled: true,
+ title: '加入学习群',
+ desc: '与 AI 学习者一起交流,获取最新资料与答疑',
+ items: [
+ { id: 'wechat', name: '微信学习群', icon: 'chat-o', desc: '扫码加入,每日更新', href: '#', type: 'wechat', hidden: true },
+ { id: 'qq', name: 'QQ 交流群', icon: 'friends-o', desc: '群号 123456789', href: '#', type: 'qq' },
+ ],
+}
diff --git a/src/data/mockData.js b/src/data/mockData.js
index 7ad43f8..880c87b 100644
--- a/src/data/mockData.js
+++ b/src/data/mockData.js
@@ -1,24 +1,27 @@
import { getCourseMarkdownRef, getEbookMarkdownRef } from '@/markdown/config.js'
import { ACCESS_LEVEL } from '@/utils/access.js'
-export const mockEbooks = [
- {
- id: 1,
- title: 'Prompt 工程实战手册',
- cover: 'https://picsum.photos/400/300?random=ai1',
- description: '从零到精通:提示词设计、Few-shot、思维链,让大模型听懂你的需求。',
- category_id: 'ai',
- sort_order: 1,
- },
- {
- id: 2,
- title: 'AI Agent 开发指南',
- cover: 'https://picsum.photos/400/300?random=ai2',
- description: 'RAG、Function Calling、多 Agent 协作,打造可落地的智能体应用。',
- category_id: 'ai',
- sort_order: 2,
- },
+/** 本地封面占位图(SVG data URI,含标题文字,无网络请求) */
+function localCover(title, gradient = 0, scale = 1) {
+ const gradients = [
+ ['#059669', '#047857'],
+ ['#0891b2', '#0e7490'],
+ ['#6366f1', '#4f46e5'],
+ ['#8b5cf6', '#7c3aed'],
+ ]
+ const [c1, c2] = gradients[gradient % gradients.length]
+ const baseSize = String(title).length > 12 ? 18 : 22
+ const fontSize = Math.round(baseSize * scale)
+ const safe = String(title).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"')
+ const svg = ``
+ return 'data:image/svg+xml,' + encodeURIComponent(svg)
+}
+
+const ebookData = [
+ { id: 1, title: 'Prompt 工程实战手册', description: '从零到精通:提示词设计、Few-shot、思维链,让大模型听懂你的需求。', category_id: 'ai', sort_order: 1 },
+ { id: 2, title: 'AI Agent 开发指南', description: 'RAG、Function Calling、多 Agent 协作,打造可落地的智能体应用。', category_id: 'ai', sort_order: 2 },
]
+export const mockEbooks = ebookData.map((item, i) => ({ ...item, cover: localCover(item.title, i) }))
export const mockEbookChapters = {
1: [
@@ -67,24 +70,11 @@ export const mockEbookChapters = {
],
}
-export const mockCourses = [
- {
- id: 1,
- title: 'ChatGPT 与大模型实战',
- cover: 'https://picsum.photos/400/300?random=ai3',
- description: 'GPT-4、Claude、国产大模型 API 调用,从 Prompt 到 RAG 全流程实战。',
- category_id: 'ai',
- sort_order: 1,
- },
- {
- id: 2,
- title: 'AI Agent 从 0 到 1',
- cover: 'https://picsum.photos/400/300?random=ai4',
- description: 'LangChain、AutoGPT、多 Agent 协作,打造能自主完成任务的智能体。',
- category_id: 'ai',
- sort_order: 2,
- },
+const courseData = [
+ { id: 1, title: 'ChatGPT 与大模型实战', description: 'GPT-4、Claude、国产大模型 API 调用,从 Prompt 到 RAG 全流程实战。', category_id: 'ai', sort_order: 1 },
+ { id: 2, title: 'AI Agent 从 0 到 1', description: 'LangChain、AutoGPT、多 Agent 协作,打造能自主完成任务的智能体。', category_id: 'ai', sort_order: 2 },
]
+export const mockCourses = courseData.map((item, i) => ({ ...item, cover: localCover(item.title, i, 2) }))
export const mockCourseChapters = {
1: [
diff --git a/src/views/CourseDetail.vue b/src/views/CourseDetail.vue
index 295872f..0fef8e7 100644
--- a/src/views/CourseDetail.vue
+++ b/src/views/CourseDetail.vue
@@ -11,8 +11,8 @@