非遗油纸伞文化数字体验平台
一、项目概述
1.1 项目定位
本项目是一个面向非物质文化遗产油纸伞文化传播与数字交互的综合 Web 平台。平台以「文化展示 + 沉浸体验 + 用户创作 + 知识传播」为主线,将油纸伞的历史渊源、制作工艺、文化内涵与现代 Web 技术相结合,帮助公众以可感知、可参与的方式了解并传承这一传统技艺。
1.2 核心目标
| 文化传播 | 通过时间轴叙事、工艺视频、图文解读等方式呈现油纸伞千年发展史 |
| 数字交互 | 提供 3D 模型旋转缩放、DIY 伞面绘制等沉浸式体验 |
| 用户参与 | 支持用户创作作品、发布至虚拟展厅,并进行点赞、收藏、评论 |
| 知识巩固 | 提供分级知识问答,记录答题成绩,促进学习效果 |
| 平台运营 | 配套管理后台,支持用户、作品、题库的集中管理与数据统计 |
1.3 适用场景
- 非遗文化数字化展示与教学
- 计算机设计 / 课程设计类 Web 全栈项目
- 传统文化主题互动体验站点
二、技术架构
2.1 整体架构
采用经典前后端分离架构:前端 Vue3 SPA 负责页面渲染与交互,后端 Express 提供 RESTful API,MySQL 持久化业务数据。
#mermaid-svg-Y8mlJqs7VUhexNGB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Y8mlJqs7VUhexNGB .error-icon{fill:#552222;}#mermaid-svg-Y8mlJqs7VUhexNGB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Y8mlJqs7VUhexNGB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Y8mlJqs7VUhexNGB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Y8mlJqs7VUhexNGB .marker.cross{stroke:#333333;}#mermaid-svg-Y8mlJqs7VUhexNGB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Y8mlJqs7VUhexNGB p{margin:0;}#mermaid-svg-Y8mlJqs7VUhexNGB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster-label text{fill:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster-label span{color:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster-label span p{background-color:transparent;}#mermaid-svg-Y8mlJqs7VUhexNGB .label text,#mermaid-svg-Y8mlJqs7VUhexNGB span{fill:#333;color:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB .node rect,#mermaid-svg-Y8mlJqs7VUhexNGB .node circle,#mermaid-svg-Y8mlJqs7VUhexNGB .node ellipse,#mermaid-svg-Y8mlJqs7VUhexNGB .node polygon,#mermaid-svg-Y8mlJqs7VUhexNGB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Y8mlJqs7VUhexNGB .rough-node .label text,#mermaid-svg-Y8mlJqs7VUhexNGB .node .label text,#mermaid-svg-Y8mlJqs7VUhexNGB .image-shape .label,#mermaid-svg-Y8mlJqs7VUhexNGB .icon-shape .label{text-anchor:middle;}#mermaid-svg-Y8mlJqs7VUhexNGB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Y8mlJqs7VUhexNGB .rough-node .label,#mermaid-svg-Y8mlJqs7VUhexNGB .node .label,#mermaid-svg-Y8mlJqs7VUhexNGB .image-shape .label,#mermaid-svg-Y8mlJqs7VUhexNGB .icon-shape .label{text-align:center;}#mermaid-svg-Y8mlJqs7VUhexNGB .node.clickable{cursor:pointer;}#mermaid-svg-Y8mlJqs7VUhexNGB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Y8mlJqs7VUhexNGB .arrowheadPath{fill:#333333;}#mermaid-svg-Y8mlJqs7VUhexNGB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Y8mlJqs7VUhexNGB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Y8mlJqs7VUhexNGB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y8mlJqs7VUhexNGB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Y8mlJqs7VUhexNGB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y8mlJqs7VUhexNGB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster text{fill:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB .cluster span{color:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Y8mlJqs7VUhexNGB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Y8mlJqs7VUhexNGB rect.text{fill:none;stroke-width:0;}#mermaid-svg-Y8mlJqs7VUhexNGB .icon-shape,#mermaid-svg-Y8mlJqs7VUhexNGB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y8mlJqs7VUhexNGB .icon-shape p,#mermaid-svg-Y8mlJqs7VUhexNGB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Y8mlJqs7VUhexNGB .icon-shape .label rect,#mermaid-svg-Y8mlJqs7VUhexNGB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y8mlJqs7VUhexNGB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Y8mlJqs7VUhexNGB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Y8mlJqs7VUhexNGB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
服务端
浏览器
/api 代理
/uploads 代理
Vue3 前端端口 5174
Express API端口 4923
MySQLoilpaper_umbrella_platform
本地文件 uploads/
2.2 技术栈明细
前端(vue3/)
| 框架 | Vue 3 + Vite 7 | 页面开发与构建 |
| 路由 / 状态 | Vue Router 4、Pinia | 路由导航、用户登录态 |
| UI 组件 | Element Plus | 表单、表格、弹窗等管理端组件 |
| 网络请求 | Axios | 封装 /api 请求与 Token 拦截 |
| 3D 渲染 | Three.js | 油纸伞 GLB 模型加载与交互 |
| 画布绘制 | Fabric.js | DIY 工坊伞面图案创作 |
| 动画 | GSAP、Animate.css、Swiper | 首页时间轴、工艺页滚动动效 |
| 图表 | ECharts + vue-echarts | 管理后台数据可视化 |
| 富文本 | Marked + highlight.js | Markdown 内容渲染 |
| 样式 | Sass | 组件级样式与主题变量 |
后端(express/)
| 运行时 | Node.js | 服务端运行环境 |
| Web 框架 | Express 4 | HTTP 服务与路由 |
| 数据库 | MySQL 8 + mysql2 连接池 | 数据持久化 |
| 鉴权 | jsonwebtoken + bcrypt | JWT 登录态、密码加密 |
| 文件上传 | Multer | 作品图片上传至 uploads/ |
| 跨域 | cors | 开发环境跨域支持 |
2.3 接口约定
- 基础路径:/api
- 统一响应格式:
{
"code": 200,
"msg": "success",
"data": {}
}
- 鉴权方式:请求头 Authorization: Bearer <token>
- 前端代理:开发时 Vite 将 /api、/uploads 代理至 http://localhost:4923
三、项目目录结构
chinese-oil-paper-umbrella/
├── oilpaper_umbrella_platform.sql # 数据库完整结构与初始数据
├── 项目说明.md # 本文档
│
├── express/ # 后端服务
│ ├── app.js # Express 应用入口(CORS、静态资源、路由挂载)
│ ├── bin/www # HTTP 服务启动(默认端口 4923)
│ ├── config/
│ │ ├── db.js # MySQL 连接池配置
│ │ ├── index.js # 应用级配置(密钥等)
│ │ └── security.js # 安全相关配置
│ ├── controllers/ # 控制器:auth / user / works / quiz / upload / admin
│ ├── routes/ # 路由定义,统一挂载于 /api
│ ├── middlewares/
│ │ └── auth.js # JWT 鉴权、可选鉴权、管理员鉴权
│ ├── util/ # 工具:加密、角色、微信等
│ ├── scripts/ # 数据库初始化 SQL 片段
│ ├── uploads/ # 用户上传图片存储目录
│ └── public/ # 后端静态资源
│
└── vue3/ # 前端应用
├── index.html
├── vite.config.js # 开发服务器、路径别名、API 代理
├── src/
│ ├── api/ # 接口封装(request.js + index.js)
│ ├── assets/ # 图片、视频、音频、字体、全局样式
│ ├── components/ # 公共组件(导航栏、页脚、上传、编辑器等)
│ ├── config/ # 背景音乐、点击音效映射
│ ├── directives/ # 自定义指令(如点击音效)
│ ├── layouts/ # WebsiteLayout(前台)、MainLayout(后台)
│ ├── router/index.js # 路由与权限守卫
│ ├── stores/user.js # 用户登录态 Pinia Store
│ ├── utils/ # 格式化、加密等工具
│ └── views/ # 页面视图(见下文功能模块)
└── public/
└── models/model.glb # 3D 油纸伞模型文件
四、功能模块说明
4.1 前台功能
| / | 首页 | 左侧历史时间轴 + 全屏画卷式幻灯,按朝代(春秋末期→近现代)讲述油纸伞发展史;支持滚动/点击切换,配合背景音乐与水墨视觉动效 |
| /craft | 工艺解读 | 五道古法工艺流程(选竹、制骨、裱纸、绘花、上油),左侧流程轴 + 右侧视频/图文详情,GSAP 滚动联动 |
| /model3d | 3D 交互 | 基于 Three.js 加载 GLB 模型,支持旋转、缩放、部件高亮;水墨风格背景与自定义光标 |
| /model-3d | 3D 交互(备用) | 另一套 3D 展示实现,可按需选用 |
| /diy | DIY 工坊 | Fabric.js 画布,支持画笔/橡皮、墨色选择、伞面底色(纯色/渐变)、贴纸纹样;可导出作品并发布至展厅 |
| /quiz | 知识回顾 | 展示答题分类(历史渊源、制作工艺、文化内涵与传承),含难度标识 |
| /quiz/:categoryId | 答题详情 | 按分类逐题作答,提交后记录得分与答题记录 |
| /gallery | 虚拟展厅 | 公开展示用户作品,支持排序、标签筛选 |
| /gallery/create | 发布作品 | 上传 DIY 作品或图片,填写标题、描述、标签 |
| /gallery/:id | 作品详情 | 查看大图、作者信息,登录用户可点赞、收藏、评论 |
| /profile | 个人中心 | 查看/编辑个人资料,管理我的作品、收藏与答题记录 |
| /login | 登录注册 | 用户登录与注册,登录后跳转原页面或首页 |
体验增强特性
- 背景音乐(BgmFab):首页、3D 页等支持切换与播放控制
- 点击音效(clickSfx):关键交互按钮附带传统风格音效
- 思源字体 + 水墨视觉:整体 UI 偏向中式非遗美学
4.2 管理后台(/admin)
需 管理员角色(role = 99) 登录后访问,路由守卫与后端 adminAuth 双重校验。
| /admin/dashboard | 数据概览:注册用户、作品总数、答题人次;答题分类饼图;最近作品与用户列表 |
| /admin/users | 用户列表查询,修改用户角色(普通用户 / 工作人员 / 管理员) |
| /admin/works | 全站作品管理,编辑公开状态、标题描述等 |
| /admin/quiz | 题库管理:分类 CRUD、题目 CRUD(含选项 JSON、正确答案、解析) |
4.3 用户角色体系
| 0 | 普通用户 | 前台全部功能:DIY、发布作品、答题、互动 |
| 1 | 工作人员 | 预留角色,可按业务扩展 |
| 99 | 管理员 | 访问 /admin 管理后台全部功能 |
五、数据库设计
数据库名:oilpaper_umbrella_platform,字符集 utf8mb4。
5.1 表结构概览
| users | 用户表 | username, password(bcrypt), nickname, avatar, role, is_delete |
| works | 虚拟展厅作品 | author_id, title, cover_url, work_url, description, tags, is_public, like/favorite/comment_count |
| work_likes | 作品点赞 | user_id, work_id(联合唯一) |
| work_favorites | 作品收藏 | user_id, work_id(联合唯一) |
| work_comments | 作品评论 | user_id, work_id, content, is_delete |
| quiz_categories | 答题分类 | name, sort, difficulty(easy/medium/hard), status |
| quiz_questions | 答题题目 | category_id, title, options(JSON), correct_answer, analysis |
| quiz_records | 答题记录 | user_id, category_id, score, total_questions |
表间通过外键关联,删除用户或分类时级联处理关联数据。
5.2 初始化数据
执行根目录 oilpaper_umbrella_platform.sql 可一次性创建库表并导入:
- 默认管理员账号:admin(role=99)
- 3 个答题分类、9 道示例题目
- 6 件示例展厅作品
六、API 接口一览
6.1 认证 /api/auth
| POST | /login | 用户登录,返回 JWT | 否 |
| POST | /register | 用户注册 | 否 |
6.2 用户 /api/users
| GET | /profile | 获取当前用户资料 | 是 |
| PUT | /profile | 更新昵称、头像等 | 是 |
6.3 作品 /api/works
| GET | / | 公开作品列表(分页、排序) | 否 |
| GET | /my | 我的作品 | 是 |
| GET | /favorites | 我的收藏 | 是 |
| GET | /:id | 作品详情 | 可选 |
| GET | /:id/comments | 作品评论列表 | 否 |
| POST | / | 发布作品 | 是 |
| POST | /:id/like | 点赞 | 是 |
| POST | /:id/like/cancel | 取消点赞 | 是 |
| POST | /:id/favorite | 收藏 | 是 |
| POST | /:id/favorite/cancel | 取消收藏 | 是 |
| POST | /:id/comment | 发表评论 | 是 |
| DELETE | /:id | 删除作品(作者本人) | 是 |
6.4 问答 /api/quiz
| GET | /categories | 答题分类列表 | 否 |
| GET | /questions | 按分类获取题目 | 否 |
| GET | /records | 答题记录 | 可选 |
| POST | /records | 提交答题结果 | 是 |
6.5 上传 /api/upload
| POST | / | 上传图片,返回可访问 URL | 是 |
6.6 管理 /api/admin
以上接口均需 登录 + role=99。
| 统计 | GET /stats |
| 用户 | GET /users、PUT /users/:id/role |
| 作品 | GET /works、PUT /works/:id |
| 题库 | 分类与题目的增删改查(/quiz/categories、/quiz/questions) |
七、环境要求与启动指南
7.1 环境要求
| Node.js | ≥ 20.19.0 或 ≥ 22.12.0(前端 engines 约束) |
| MySQL | 8.x |
| 包管理器 | npm / pnpm / yarn 均可 |
7.2 数据库配置
mysql -u root -p < oilpaper_umbrella_platform.sql
{
host: "localhost",
port: "3306",
user: "root",
password: "你的密码",
database: "oilpaper_umbrella_platform"
}
7.3 启动后端
cd express
npm install # 或 pnpm install
npm run dev # nodemon 启动,默认 http://localhost:4923
7.4 启动前端
cd vue3
npm install
npm run dev # 默认 http://localhost:5174,自动打开浏览器
7.5 生产构建
# 前端打包
cd vue3 && npm run build # 产物在 vue3/dist/
# 后端可将 dist 静态文件托管,或前后端分域名部署
# 生产环境需配置前端 API 基地址,并设置 JWT_SECRET 环境变量
7.6 默认访问地址
| 前台首页 | http://localhost:5174 |
| 管理后台 | http://localhost:5174/admin |
| API 服务 | http://localhost:4923/api |
| 上传资源 | http://localhost:4923/uploads/ |
八、安全与配置说明
8.1 JWT 密钥
后端 middlewares/auth.js 使用环境变量 JWT_SECRET,未设置时回退默认值 oil_paper_umbrella_secret。生产环境务必通过环境变量配置强密钥。
8.2 密码存储
用户密码使用 bcrypt 加盐哈希,明文不存入数据库。
8.3 CORS
当前后端 app.js 配置 origin: "*",适合开发调试;生产环境建议收紧为前端实际域名。
8.4 上传限制
图片上传经 Multer 处理,存储于 express/uploads/,通过 /uploads 静态路径访问。注意磁盘空间与文件类型校验。
九、前端路由与权限
路由定义见 vue3/src/router/index.js:
- 前台路由嵌套在 WebsiteLayout 下,共享导航栏与页脚
- /admin/* 路由设置 meta.requireAdmin: true
- 全局 beforeEach 守卫:未登录跳转 /login?redirect=…;非管理员访问后台则重定向首页
- 页面 document.title 格式:{页面标题} – 非遗油纸伞文化平台
十、项目亮点总结
十一、常见问题
Q:前端请求 404 或跨域失败?
确认后端已启动在 4923 端口,且 vite.config.js 代理配置未被修改。
Q:数据库连接失败?
检查 MySQL 服务是否运行、db.js 账号密码是否正确、是否已导入 SQL。
Q:无法进入管理后台?
确认登录账号 role 为 99,可在数据库 users 表中修改。
Q:3D 模型不显示?
确认 vue3/public/models/model.glb 存在;浏览器需支持 WebGL。
Q:上传图片无法访问?
确认 express/uploads 目录存在写权限,且通过 /uploads/文件名 访问。

