Compare commits

...

2 Commits

Author SHA1 Message Date
lychang
fedffd5c2d fix problems
All checks were successful
Xiaoshiliu / build (push) Successful in 42s
2025-10-04 20:19:07 +08:00
lychang
c5212930b0 fix problems 2025-10-04 20:17:47 +08:00
59 changed files with 11 additions and 13182 deletions

View File

@@ -15,7 +15,7 @@ jobs:
EXTERNAL_FLAG: ""
steps:
- name: Checkout Code
uses: https://gitea.com/actions/checkout@v4
uses: http://192.168.1.100:3000/tools/checkout@v4
- name: Stop container
run: |
if [[ "$(sudo docker ps -q --filter name=$SERVICE_NAME)" != "" ]];then

275
README.md
View File

@@ -1,275 +0,0 @@
<p align="center">
<img alt="logo" src="./doc/imgs/卜卜.png" width="100" />
</p>
<h1 align="center" style="margin: 20px 30px 0px 30px; font-weight: bold;">XiaoShiLiu</h1>
---
<p align="center">
<b>基于 Express + Vue 前后端分离仿小红书项目</b>
</p>
<p align="center">
<i>一个高仿小红书的图文社区项目,支持图文发布、社交互动等核心功能,旨在提供从前端到后端的完整实践范本</i>
<p align="center"><a href="https://www.shiliu.space">演示网站</a> · <a href="https://www.bilibili.com/video/BV1J4agztEBX/?spm_id_from=333.1387.homepage.video_card.click">视频介绍</a>
</p>
<p align="center"><a href="https://github.com/ZTMYO/XiaoShiLiu">简体中文</a>|<a href="doc/i18n/README_En.md">English</a>|<a href="doc/i18n/README_zh-Hant.md">繁體中文</a>
<p align="center">
<a href="https://github.com/ZTMYO/XiaoShiLiu/stargazers">
<img src="https://img.shields.io/github/stars/ZTMYO/XiaoShiLiu?style=flat&logo=github&color=brightgreen&label=Stars">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/network/members">
<img src="https://img.shields.io/github/forks/ZTMYO/XiaoShiLiu?style=round-square&color=brightgreen&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiBmaWxsPSJub25lIj4KPHBhdGggZmlsbD0id2hpdGUiIGQ9Ik01IDUuMzcydi44NzhjMCAuNDE0LjMzNi43NS43NS43NWg0LjVhLjc1Ljc1IDAgMCAwIC43NS0uNzV2LS44NzhhMi4yNSAyLjI1IDAgMSAxIDEuNSAwdi44NzhhMi4yNSAyLjI1IDAgMCAxLTIuMjUgMi4yNWgtMS41djIuMTI4YTIuMjUxIDIuMjUxIDAgMSAxLTEuNSAwVjguNWgtMS41QTIuMjUgMi4yNSAwIDAgMSAzLjUgNi4yNXYtLjg3OGEyLjI1IDIuMjUgMCAxIDEgMS41IDBaTTUgMy4yNWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWm02Ljc1Ljc1YS43NS43NSAwIDEgMCAwLTEuNS43NS43NSAwIDAgMCAwIDEuNVptLTMgOC43NWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWiI+PC9wYXRoPgo8L3N2Zz4=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu">
<img src="https://img.shields.io/badge/XiaoShiLiu-v1.2.0-brightgreen.svg?logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIj4KPHBhdGggZD0iTTAgMCBDNC4yMzMwMTEyMSAyLjgyMjAwNzQ3IDcuMTcxNTk2NjQgNS45NTIyODk5MiA4LjgxMjUgMTAuODc1IEM5LjE4MDc2MjI0IDE2LjQ5MDk5OTE2IDkuMDI4MDYwMDcgMjAuMDUxNjU5ODkgNS44MTI1IDI0Ljg3NSBDMS44ODAxNjE5MSAyOC44NTAzMTQ0NiAtMS4zMzIwOTg0OSAzMC43NTMzMzQzMyAtNyAzMS4xMjUgQy0xMS43MTg5MjIyMyAzMS4wMzg1NzI4NSAtMTUuMjAxOTI2NjkgMjkuODM5MTA3NjUgLTE4LjYzMjgxMjUgMjYuNDQ1MzEyNSBDLTIyLjQ1Nzc0Mjg2IDIyLjA1MjEwNjc3IC0yMy41MDQ5MDc2NCAxOC43NDI5NTY4OSAtMjMuMzk4NDM3NSAxMi45Mjk2ODc1IEMtMjIuOTEyNTgwNTggOC4xOTcwODExNiAtMjAuNjcwMDc0MTQgNS4wOTQ1OTE5MSAtMTcuMTg3NSAyLjA2MjUgQy0xMS43NzQzMTUyMyAtMS44ODQ2MTM5IC02LjE5MjU0NDY4IC0yLjE4NTYwNDAxIDAgMCBaIE0tNy4xODc1IDQuODc1IEMtOC4xNzc1IDUuNTM1IC05LjE2NzUgNi4xOTUgLTEwLjE4NzUgNi44NzUgQy0xMC4xODc1IDcuNTM1IC0xMC4xODc1IDguMTk1IC0xMC4xODc1IDguODc1IEMtMTAuODA2MjUgOS4xNDMxMjUgLTExLjQyNSA5LjQxMTI1IC0xMi4wNjI1IDkuNjg3NSBDLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE2LjE4NzUgMTMuODc1IEMtMTYuNTc3NjM3MTYgMTUuODY0Njk5NSAtMTYuOTE5NTI2NDkgMTcuODY1MTk4NjkgLTE3LjE4NzUgMTkuODc1IEMtMTYuMTk3NSAyMC4zNyAtMTYuMTk3NSAyMC4zNyAtMTUuMTg3NSAyMC44NzUgQy0xNC40NjU5MDU3NiAyMi41MTg2MzEzNCAtMTMuNzkzOTg1NzkgMjQuMTg1NTAzODYgLTEzLjE4NzUgMjUuODc1IEMtMTIuNTI3NSAyNS44NzUgLTExLjg2NzUgMjUuODc1IC0xMS4xODc1IDI1Ljg3NSBDLTEwLjg1NzUgMjYuODY1IC0xMC41Mjc1IDI3Ljg1NSAtMTAuMTg3NSAyOC44NzUgQy05LjUyNzUgMjcuODg1IC04Ljg2NzUgMjYuODk1IC04LjE4NzUgMjUuODc1IEMtNi44Njc1IDI1Ljg3NSAtNS41NDc1IDI1Ljg3NSAtNC4xODc1IDI1Ljg3NSBDLTMuODU3NSAyNi44NjUgLTMuNTI3NSAyNy44NTUgLTMuMTg3NSAyOC44NzUgQy0zLjE4NzUgMjcuODg1IC0zLjE4NzUgMjYuODk1IC0zLjE4NzUgMjUuODc1IEMtMi4xOTc1IDI1LjU0NSAtMS4yMDc1IDI1LjIxNSAtMC4xODc1IDI0Ljg3NSBDMC40MDMyMDAxNCAyMi45Mjg5NjcyNiAwLjQwMzIwMDE0IDIyLjkyODk2NzI2IDAuODEyNSAyMC44NzUgQzEuNDcyNSAyMC4yMTUgMi4xMzI1IDE5LjU1NSAyLjgxMjUgMTguODc1IEMxLjU3OTU5MDMxIDEzLjExMDE4NTAyIDEuNTc5NTkwMzEgMTMuMTEwMTg1MDIgLTIuMTg3NSA4Ljg3NSBDLTIuODQ3NSA4Ljg3NSAtMy41MDc1IDguODc1IC00LjE4NzUgOC44NzUgQy00LjE4NzUgNy44ODUgLTQuMTg3NSA2Ljg5NSAtNC4xODc1IDUuODc1IEMtNS4xNzc1IDUuNTQ1IC02LjE2NzUgNS4yMTUgLTcuMTg3NSA0Ljg3NSBaIE0tMTguMTg3NSAxOS44NzUgQy0xOC4xODc1IDIyLjg3NSAtMTguMTg3NSAyMi44NzUgLTE4LjE4NzUgMjIuODc1IFogTTIuODEyNSAxOS44NzUgQzMuMTQyNSAyMC44NjUgMy40NzI1IDIxLjg1NSAzLjgxMjUgMjIuODc1IEMzLjgxMjUgMjEuODg1IDMuODEyNSAyMC44OTUgMy44MTI1IDE5Ljg3NSBDMy40ODI1IDE5Ljg3NSAzLjE1MjUgMTkuODc1IDIuODEyNSAxOS44NzUgWiAiIGZpbGw9IiNGQ0ZDRkMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzLjE4NzUsMS4xMjUpIi8+CjxwYXRoIGQ9Ik0wIDAgQzIuMDYyNSAwLjQzNzUgMi4wNjI1IDAuNDM3NSA0IDEgQzQgMS45OSA0IDIuOTggNCA0IEM0Ljk5IDQuMzMgNS45OCA0LjY2IDcgNSBDMy43ODU0ODczMSA2LjYwNzI1NjM1IDAuNTYzODc0NjQgNi4wNTc0ODE4NSAtMyA2IEMtMS4xMjUgMS4xMjUgLTEuMTI1IDEuMTI1IDAgMCBaICIgZmlsbD0iI0U5RTlFOSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTUsMjYpIi8+Cjwvc3ZnPgo=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/ZTMYO/XiaoShiLiu?color=8ebc06">
</a>
</p>
<p align="center">
<img src="https://img.shields.io/static/v1?message=Vue&color=4f4f4f&logo=Vue.js&logoColor=4FC08D&label=">
<img
src="https://img.shields.io/static/v1?&message=JavaScript&color=4f4f4f&logo=JavaScript&logoColor=F7DF1E&label=">
</a>
</p>
> **声明**
> 本项目基于 [GPLv3 协议](./LICENSE),免费开源,仅供学习交流,禁止转卖,谨防受骗。如需商用请保留版权信息,确保合法合规使用,运营风险自负,与作者无关。
---
> 📁 **项目结构说明**:本项目包含完整的前后端代码,前端位于 `vue3-project/` 目录,后端位于 `express-project/` 目录。详细结构请查看 [项目结构文档](./doc/PROJECT_STRUCTURE.md)。
## 项目展示
### PC端界面
<table>
<tr>
<td><img src="./doc/imgs/1.png" alt="PC端界面1" width="300"/></td>
<td><img src="./doc/imgs/2.png" alt="PC端界面2" width="300"/></td>
<td><img src="./doc/imgs/3.png" alt="PC端界面3" width="300"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/4.png" alt="PC端界面4" width="300"/></td>
<td><img src="./doc/imgs/5.png" alt="PC端界面5" width="300"/></td>
<td><img src="./doc/imgs/6.png" alt="PC端界面6" width="300"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/7.png" alt="PC端界面7" width="300"/></td>
<td><img src="./doc/imgs/8.png" alt="PC端界面8" width="300"/></td>
<td><img src="./doc/imgs/9.png" alt="PC端界面9" width="300"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/10.png" alt="PC端界面10" width="300"/></td>
<td><img src="./doc/imgs/11.png" alt="PC端界面11" width="300"/></td>
<td><img src="./doc/imgs/12.png" alt="PC端界面12" width="300"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/13.png" alt="PC端界面13" width="300"/></td>
<td><img src="./doc/imgs/14.png" alt="PC端界面14" width="300"/></td>
<td><img src="./doc/imgs/15.png" alt="PC端界面15" width="300"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/16.png" alt="PC端界面16" width="300"/></td>
<td><img src="./doc/imgs/17.png" alt="PC端界面17" width="300"/></td>
<td><img src="./doc/imgs/18.png" alt="PC端界面18" width="300"/></td>
</tr>
</table>
### 移动端界面
<table>
<tr>
<td><img src="./doc/imgs/m1.png" alt="移动端界面1" width="200"/></td>
<td><img src="./doc/imgs/m2.png" alt="移动端界面2" width="200"/></td>
<td><img src="./doc/imgs/m3.png" alt="移动端界面3" width="200"/></td>
<td><img src="./doc/imgs/m4.png" alt="移动端界面4" width="200"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/m5.png" alt="移动端界面5" width="200"/></td>
<td><img src="./doc/imgs/m6.png" alt="移动端界面6" width="200"/></td>
<td><img src="./doc/imgs/m7.png" alt="移动端界面7" width="200"/></td>
<td><img src="./doc/imgs/m8.png" alt="移动端界面8" width="200"/></td>
</tr>
<tr>
<td><img src="./doc/imgs/m9.png" alt="移动端界面9" width="200"/></td>
<td><img src="./doc/imgs/m10.png" alt="移动端界面10" width="200"/></td>
<td><img src="./doc/imgs/m11.png" alt="移动端界面11" width="200"/></td>
<td><img src="./doc/imgs/m12.png" alt="移动端界面12" width="200"/></td>
</tr>
</table>
## 项目文档
| 文档 | 说明 |
|------|------|
| [部署指南](./doc/DEPLOYMENT.md) | 部署配置和环境搭建说明 |
| [项目结构](./doc/PROJECT_STRUCTURE.md) | 项目目录结构架构说明 |
| [数据库设计](./doc/DATABASE_DESIGN.md) | 数据库表结构设计文档 |
| [API接口文档](./doc/API_DOCS.md) | 后端API接口说明和示例 |
## 项目亮点
- **工程化:** 环境配置、代码规范、构建与产物优化的完整流程
- **业务能力:** 鉴权流程、路由守卫、状态管理与接口封装
- **体验优化:** 骨架屏、懒加载、预加载、无障碍与响应式适配
- **组件与分层:** 可复用组件拆分、按领域分组与别名引入
- **后台管理:** 基础CRUD、数据管理与配置面板支持后续扩展权限与统计
- **快速部署:** 基于 Docker 的一键部署方案,支持多环境配置与自动化部署
## 技术栈
> 💡点击可展开查看详细内容
<details>
<summary><b>前端技术</b></summary>
- **Vue.js 3** - 前端框架Composition API
- **Vue Router 4** - 路由管理
- **Pinia** - 状态管理
- **Vite** - 构建工具和开发服务器
- **Axios** - HTTP客户端
- **VueUse** - Vue组合式工具库
- **CropperJS** - 图片裁剪
- **Vue3 Emoji Picker** - 表情选择器
- **svg-captcha** - 验证码生成器
</details>
<details>
<summary><b>后端技术</b></summary>
- **Node.js** - 运行环境
- **Express.js** - Web框架
- **MySQL** - 数据库
- **JWT** - 身份认证
- **Multer** - 文件上传
- **bcrypt** - 密码加密
- **CORS** - 跨域资源共享
</details>
## 第三方API
- **图片存储:** 灌装的示例图片来自 [栗次元图床](https://t.alcy.cc/),提供稳定的图片存储服务
- **图片上传:** 用户上传图片使用了 [夏柔API](https://api.aa1.cn/doc/xinyew_jdtc.html),确保图片上传的稳定性和速度
- **属地查询:** IP属地查询服务使用 [保罗API](https://api.pearktrue.cn/dashboard/detail/290)实现精准的IP属地定位功能
## 环境要求
| 组件 | 版本要求 |
|------|----------|
| Node.js | >= 16.0.0 |
| MySQL | >= 5.7 |
| MariaDB | >= 10.3 |
| npm | >= 8.0.0 |
| yarn | >= 1.22.0 |
| 浏览器 | 支持ES6+ |
> 提示:上述为传统本地开发的最低版本要求。若使用 Docker 部署默认镜像版本如下MySQL 8.0、Node 18-alpine前后端构建/运行、Nginx alpineDocker >= 20、Docker Compose >= 2。详见[部署指南文档](./doc/DEPLOYMENT.md)。
## 环境配置
项目使用环境变量进行配置管理,前后端分别有独立的 `.env` 文件:
### 后端配置 (express-project/.env)
```env
# 服务器配置
PORT=3001
NODE_ENV=development
# 数据库配置
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# JWT配置
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
# 上传配置
UPLOAD_MAX_SIZE=50mb
# 图片上传策略 (local: 本地存储, imagehost: 第三方图床)
UPLOAD_STRATEGY=imagehost
# 本地存储配置
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# 第三方图床配置
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
```
### 前端配置 (vue3-project/.env)
```env
# API基础URL配置
VITE_API_BASE_URL=http://localhost:3001/api
# 应用配置
VITE_USE_REAL_API=true
VITE_APP_TITLE=卜卜世界
```
> 💡 **配置说明**
> - 后端支持本地存储和第三方图床两种上传策略
> - 前端使用 Vite 环境变量,变量名需以 `VITE_` 开头
> - 详细配置说明请参考 [部署指南](./doc/DEPLOYMENT.md)
### 1. 安装依赖
```bash
# 使用 cnpm或npm
cnpm install
# 或使用 yarn
yarn install
```
### 2. 启动开发服务器
```bash
# 启动开发服务器
npm run dev
# 或使用 yarn
yarn dev
```
开发服务器将在 `http://localhost:5173` 启动
### 3. 构建生产版本
```bash
# 构建生产版本
npm run build
# 预览生产版本
npm run preview
```
> ⚠️ **重要提醒**:前端项目需要配合后端服务使用,详细配置请查看 [部署指南](./doc/DEPLOYMENT.md)
## Star历史
[![Star History Chart](https://api.star-history.com/svg?repos=ZTMYO/XiaoShiLiu&type=Date)](https://www.star-history.com/#ZTMYO/XiaoShiLiu&Date)
---
<div align="center">
Copyright © 2025 - **XiaoShiLiu**\
By ZTMYO\
Made with ❤️ & ⌨️
</div>

View File

@@ -1,161 +0,0 @@
#!/usr/bin/env pwsh
param(
[switch]$Build,
[switch]$Stop,
[switch]$Clean,
[switch]$Logs,
[switch]$Status,
[switch]$Help,
[switch]$Seed
)
function Write-ColorOutput {
param(
[string]$Message,
[string]$Color = "White"
)
Write-Host $Message -ForegroundColor $Color
}
function Show-Help {
Write-ColorOutput "卜卜世界 Docker 部署脚本" "Cyan"
Write-ColorOutput "用法: .\deploy.ps1 [选项]" "Yellow"
Write-ColorOutput ""
Write-ColorOutput "选项:" "Green"
Write-ColorOutput " -Build 强制重新构建镜像并启动服务" "White"
Write-ColorOutput " -Stop 停止所有服务" "White"
Write-ColorOutput " -Clean 清理所有容器、镜像和数据卷" "White"
Write-ColorOutput " -Logs 查看服务日志" "White"
Write-ColorOutput " -Status 查看服务状态" "White"
Write-ColorOutput " -Seed 启动后灌装示例数据(可选)" "White"
Write-ColorOutput " -Help 显示此帮助信息" "White"
}
function Test-Docker {
try {
docker --version | Out-Null
docker-compose --version | Out-Null
return $true
}
catch {
Write-ColorOutput "错误: 未找到 Docker 或 Docker Compose" "Red"
return $false
}
}
function Wait-ContainerHealthy {
param(
[string]$ContainerName,
[int]$TimeoutSeconds = 120
)
$start = Get-Date
while ((Get-Date) - $start -lt [TimeSpan]::FromSeconds($TimeoutSeconds)) {
try {
$status = docker inspect -f '{{.State.Health.Status}}' $ContainerName 2>$null
if ($status -and $status.Trim() -eq 'healthy') { return $true }
}
catch { }
Start-Sleep -Seconds 2
}
return $false
}
function Seed-Data {
Write-ColorOutput "准备灌装示例数据..." "Cyan"
$mysqlHealthy = Wait-ContainerHealthy -ContainerName 'xiaoshiliu-mysql' -TimeoutSeconds 180
$backendHealthy = Wait-ContainerHealthy -ContainerName 'xiaoshiliu-backend' -TimeoutSeconds 180
if (-not $mysqlHealthy -or -not $backendHealthy) {
Write-ColorOutput "等待服务健康超时,跳过灌装。" "Yellow"
return
}
Write-ColorOutput "开始灌装数据(时间较长请耐心等待)..." "Yellow"
docker-compose -p xiaoshiliu exec -T backend node scripts/generate-data.js
if ($LASTEXITCODE -eq 0) {
Write-ColorOutput "灌装完成" "Green"
}
else {
Write-ColorOutput "灌装失败,请查看日志" "Red"
}
}
function Start-Services {
Write-ColorOutput "启动卜卜世界服务..." "Green"
if ($Build) {
Write-ColorOutput "重新构建镜像..." "Yellow"
docker-compose -p xiaoshiliu down
docker-compose -p xiaoshiliu build --no-cache
}
docker-compose -p xiaoshiliu up -d
if ($LASTEXITCODE -eq 0) {
Write-ColorOutput "服务启动成功!" "Green"
Write-ColorOutput "访问地址:" "Cyan"
Write-ColorOutput " 前端: http://localhost:8080" "White"
Write-ColorOutput " 后端API: http://localhost:3001" "White"
Write-ColorOutput " 数据库: localhost:3307" "White"
if ($Seed) {
Seed-Data
}
}
else {
Write-ColorOutput "服务启动失败!" "Red"
}
}
function Stop-Services {
Write-ColorOutput "停止服务..." "Yellow"
docker-compose -p xiaoshiliu down
if ($LASTEXITCODE -eq 0) {
Write-ColorOutput "服务已停止" "Green"
}
else {
Write-ColorOutput "停止服务时出现错误" "Red"
}
}
function Clean-Resources {
Write-ColorOutput "警告: 此操作将删除所有容器、镜像和数据卷!" "Red"
$confirmation = Read-Host "确认继续? (y/N)"
if ($confirmation -match '^[Yy]$') {
Write-ColorOutput "清理Docker资源..." "Yellow"
docker-compose -p xiaoshiliu down -v --rmi all
docker system prune -f | Out-Null
Write-ColorOutput "清理完成" "Green"
}
else {
Write-ColorOutput "操作已取消" "Yellow"
}
}
function Show-Logs {
Write-ColorOutput "查看服务日志 (按 Ctrl+C 退出):" "Cyan"
docker-compose -p xiaoshiliu logs -f
}
function Show-Status {
Write-ColorOutput "服务状态:" "Cyan"
docker-compose -p xiaoshiliu ps
}
if ($Help) {
Show-Help
exit 0
}
if (-not (Test-Docker)) {
exit 1
}
switch ($true) {
$Clean { Clean-Resources }
$Logs { Show-Logs }
$Status { Show-Status }
$Stop { Stop-Services }
default { Start-Services }
}
Write-ColorOutput "操作完成" "Green"

215
deploy.sh
View File

@@ -1,215 +0,0 @@
#!/bin/bash
# 卜卜世界 Docker 一键部署脚本
# Bash 版本
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 显示帮助信息
show_help() {
echo -e "${CYAN}卜卜世界 Docker 部署脚本${NC}"
echo -e "${YELLOW}用法: ./deploy.sh [选项]${NC}"
echo ""
echo -e "${GREEN}选项:${NC}"
echo -e " --build 强制重新构建镜像并启动服务"
echo -e " --stop 停止所有服务"
echo -e " --clean 清理所有容器、镜像和数据卷"
echo -e " --logs 查看服务日志"
echo -e " --status 查看服务状态"
echo -e " --seed 初始化数据库并生成测试数据"
echo -e " --help 显示此帮助信息"
echo ""
echo -e "${GREEN}示例:${NC}"
echo -e " ./deploy.sh # 启动服务"
echo -e " ./deploy.sh --build # 重新构建并启动"
echo -e " ./deploy.sh --stop # 停止服务"
echo -e " ./deploy.sh --seed # 生成测试数据"
}
# 检查Docker是否安装
check_docker() {
if ! command -v docker &> /dev/null; then
echo -e "${RED}错误: 未找到 Docker${NC}"
echo -e "${YELLOW}请先安装 Docker: https://docs.docker.com/get-docker/${NC}"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo -e "${RED}错误: 未找到 Docker Compose${NC}"
echo -e "${YELLOW}请先安装 Docker Compose: https://docs.docker.com/compose/install/${NC}"
exit 1
fi
}
# 检查环境变量文件
check_env_file() {
if [ ! -f ".env" ]; then
if [ -f ".env.docker" ]; then
echo -e "${YELLOW}复制 .env.docker 到 .env${NC}"
cp .env.docker .env
else
echo -e "${YELLOW}警告: 未找到 .env 文件,将使用默认配置${NC}"
fi
fi
}
# 启动服务
start_services() {
echo -e "${GREEN}启动卜卜世界服务...${NC}"
if [ "$1" = "--build" ]; then
echo -e "${YELLOW}重新构建镜像...${NC}"
docker-compose down
docker-compose build --no-cache
fi
docker-compose up -d
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ 所有服务已成功启动!${NC}"
echo -e "\n${BLUE}服务访问地址:${NC}"
echo -e " 前端界面: ${GREEN}http://localhost:8080${NC}"
echo -e " 后端API: ${GREEN}http://localhost:3001${NC}"
echo -e " 数据库: ${GREEN}localhost:3307${NC}"
echo -e "\n${YELLOW}注意:容器已配置为中国时区(Asia/Shanghai)${NC}"
echo ""
echo -e "${YELLOW}使用 './deploy.sh --logs' 查看日志${NC}"
echo -e "${YELLOW}使用 './deploy.sh --status' 查看服务状态${NC}"
else
echo -e "${RED}服务启动失败!${NC}"
echo -e "${YELLOW}请检查日志: docker-compose logs${NC}"
exit 1
fi
}
# 停止服务
stop_services() {
echo -e "${YELLOW}停止卜卜世界服务...${NC}"
docker-compose down
if [ $? -eq 0 ]; then
echo -e "${GREEN}服务已停止${NC}"
else
echo -e "${RED}停止服务时出现错误${NC}"
exit 1
fi
}
# 清理资源
clean_resources() {
echo -e "${RED}警告: 此操作将删除所有容器、镜像和数据!${NC}"
read -p "确认继续? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}清理Docker资源...${NC}"
docker-compose down -v --rmi all
docker system prune -f
echo -e "${GREEN}清理完成${NC}"
else
echo -e "${YELLOW}操作已取消${NC}"
fi
}
# 查看日志
show_logs() {
echo -e "${CYAN}查看服务日志 (按 Ctrl+C 退出):${NC}"
docker-compose logs -f
}
# 查看状态
show_status() {
echo -e "${CYAN}服务状态:${NC}"
docker-compose ps
echo ""
echo -e "${CYAN}资源使用情况:${NC}"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
}
# 初始化数据库并生成测试数据
seed_database() {
echo -e "${YELLOW}初始化数据库并生成测试数据...${NC}"
# 检查后端容器是否运行
if ! docker-compose ps | grep -q "xiaoshiliu-backend.*Up"; then
echo -e "${RED}错误: 后端服务未运行,请先启动服务${NC}"
echo -e "${YELLOW}使用 './deploy.sh' 启动服务${NC}"
exit 1
fi
echo -e "${CYAN}步骤1: 初始化数据库结构...${NC}"
docker-compose exec backend node scripts/init-database.js
if [ $? -eq 0 ]; then
echo -e "${GREEN}数据库初始化成功!${NC}"
echo -e "${CYAN}步骤2: 生成测试数据...${NC}"
docker-compose exec backend node scripts/generate-data.js
if [ $? -eq 0 ]; then
echo -e "${GREEN}测试数据生成成功!${NC}"
echo -e "${CYAN}数据库已包含:${NC}"
echo -e " - 50个测试用户"
echo -e " - 200篇测试笔记"
echo -e " - 800条测试评论"
echo -e " - 完整的分类和标签数据"
else
echo -e "${RED}测试数据生成失败!${NC}"
exit 1
fi
else
echo -e "${RED}数据库初始化失败!${NC}"
exit 1
fi
}
# 主逻辑
case "$1" in
--help)
show_help
exit 0
;;
--stop)
check_docker
stop_services
;;
--clean)
check_docker
clean_resources
;;
--logs)
check_docker
show_logs
;;
--status)
check_docker
show_status
;;
--seed)
check_docker
seed_database
;;
--build)
check_docker
check_env_file
start_services --build
;;
"")
check_docker
check_env_file
start_services
;;
*)
echo -e "${RED}未知选项: $1${NC}"
show_help
exit 1
;;
esac
echo -e "${GREEN}操作完成${NC}"

File diff suppressed because it is too large Load Diff

View File

@@ -1,211 +0,0 @@
# 图文社区项目数据库设计
## 概述
基于卜卜风格的图文社区项目,简化版数据库结构设计,包含用户管理、内容发布、社交互动等核心功能。
### 字符集和排序规则
- 数据库字符集:`utf8mb4`
- 排序规则:`utf8mb4_unicode_ci`
- 存储引擎:`InnoDB`
## 核心数据表结构
### 1. 用户表 (users)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 用户ID | 主键,自增 |
| password | VARCHAR(255) | 密码 | 可为空 |
| user_id | VARCHAR(50) | 卜卜号 | 唯一标识 |
| nickname | VARCHAR(100) | 昵称 | 显示名称 |
| avatar | VARCHAR(500) | 头像URL | 用户头像 |
| bio | TEXT | 个人简介 | 用户介绍 |
| location | VARCHAR(100) | IP属地 | 地理位置 |
| follow_count | INT | 关注数 | 统计字段默认0 |
| fans_count | INT | 粉丝数 | 统计字段默认0 |
| like_count | INT | 获赞数 | 统计字段默认0 |
| is_active | TINYINT(1) | 是否激活 | 默认1 |
| last_login_at | TIMESTAMP | 最后登录时间 | 可为空 |
| created_at | TIMESTAMP | 创建时间 | 注册时间 |
| updated_at | TIMESTAMP | 更新时间 | 自动更新 |
| gender | VARCHAR(10) | 性别 | 可为空 |
| zodiac_sign | VARCHAR(20) | 星座 | 可为空 |
| mbti | VARCHAR(4) | MBTI人格类型 | 可为空 |
| education | VARCHAR(50) | 学历 | 可为空 |
| major | VARCHAR(100) | 专业 | 可为空 |
| interests | JSON | 兴趣爱好 | JSON数组可为空 |
| verified | TINYINT(1) | 认证状态 | 0-未认证1-已认证默认0 |
### 2. 分类表 (categories)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | INT | 分类ID | 主键,自增 |
| name | VARCHAR(50) | 分类名称 | 唯一,如:学习、校园、情感等 |
| category_title | VARCHAR(50) | 分类英文标题 | 唯一用于URL生成study、campus、emotion等 |
| created_at | TIMESTAMP | 创建时间 | 分类创建时间 |
**索引:**
- PRIMARY KEY (`id`)
- UNIQUE KEY `name` (`name`)
- UNIQUE KEY `category_title` (`category_title`)
- KEY `idx_name` (`name`)
- KEY `idx_category_title` (`category_title`)
**初始数据:**
- 学习 (study)
- 校园 (campus)
- 情感 (emotion)
- 兴趣 (interest)
- 生活 (life)
- 社交 (social)
- 求助 (help)
- 观点 (opinion)
- 毕业 (graduation)
- 职场 (career)
### 3. 笔记表 (posts)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 笔记ID | 主键,自增 |
| user_id | BIGINT | 发布用户ID | 外键关联users |
| title | VARCHAR(200) | 标题 | 笔记标题 |
| content | TEXT | 内容 | 笔记描述 |
| category_id | INT | 分类ID | 外键关联categories表可为空 |
| type | INT | 笔记类型 | 1-图片笔记2-视频笔记默认1 |
| is_draft | TINYINT(1) | 是否为草稿 | 1-草稿0-已发布默认1 |
| view_count | BIGINT | 浏览量 | 统计字段默认0 |
| like_count | INT | 点赞数 | 统计字段默认0 |
| collect_count | INT | 收藏数 | 统计字段默认0 |
| comment_count | INT | 评论数 | 统计字段默认0 |
| created_at | TIMESTAMP | 发布时间 | 创建时间 |
### 3. 笔记图片表 (post_images)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 图片ID | 主键,自增 |
| post_id | BIGINT | 笔记ID | 外键关联posts |
| image_url | VARCHAR(500) | 图片URL | 原图地址 |
### 4. 笔记视频表 (post_videos)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 视频ID | 主键,自增 |
| post_id | BIGINT | 笔记ID | 外键关联posts |
| cover_url | VARCHAR(500) | 视频封面URL | 视频封面图片,可为空 |
| video_url | VARCHAR(500) | 视频URL | 视频文件地址 |
### 5. 标签表 (tags)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | INT | 标签ID | 主键,自增 |
| name | VARCHAR(50) | 标签名 | 标签内容,唯一 |
| use_count | INT | 使用次数 | 热度统计默认0 |
| created_at | TIMESTAMP | 创建时间 | 首次使用时间 |
### 6. 笔记标签关联表 (post_tags)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 关联ID | 主键,自增 |
| post_id | BIGINT | 笔记ID | 外键关联posts |
| tag_id | INT | 标签ID | 外键关联tags |
| created_at | TIMESTAMP | 创建时间 | 关联时间 |
### 7. 关注关系表 (follows)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 关注ID | 主键,自增 |
| follower_id | BIGINT | 关注者ID | 外键关联users |
| following_id | BIGINT | 被关注者ID | 外键关联users |
| created_at | TIMESTAMP | 关注时间 | 创建时间 |
### 8. 点赞表 (likes)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 点赞ID | 主键,自增 |
| user_id | BIGINT | 用户ID | 外键关联users |
| target_type | TINYINT | 目标类型 | 1-笔记, 2-评论 |
| target_id | BIGINT | 目标ID | 笔记或评论ID |
| created_at | TIMESTAMP | 点赞时间 | 创建时间 |
### 9. 收藏表 (collections)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 收藏ID | 主键,自增 |
| user_id | BIGINT | 用户ID | 外键关联users |
| post_id | BIGINT | 笔记ID | 外键关联posts |
| created_at | TIMESTAMP | 收藏时间 | 创建时间 |
### 10. 评论表 (comments)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 评论ID | 主键,自增 |
| post_id | BIGINT | 笔记ID | 外键关联posts |
| user_id | BIGINT | 评论用户ID | 外键关联users |
| parent_id | BIGINT | 父评论ID | 回复评论时使用,可为空 |
| content | TEXT | 评论内容 | 评论文本 |
| like_count | INT | 点赞数 | 统计字段默认0 |
| created_at | TIMESTAMP | 评论时间 | 创建时间 |
### 11. 通知表 (notifications)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 通知ID | 主键,自增 |
| user_id | BIGINT | 接收用户ID | 外键关联users |
| sender_id | BIGINT | 发送用户ID | 外键关联users |
| type | TINYINT | 通知类型 | 1-点赞笔记, 2-点赞评论, 3-收藏, 4-评论笔记, 5-回复评论, 6-关注, 7-评论提及, 8-笔记提及 |
| title | VARCHAR(200) | 通知标题 | 通知内容 |
| target_id | BIGINT | 关联目标ID | 笔记或评论ID可为空 |
| comment_id | BIGINT | 关联评论ID | 用于评论和回复通知,可为空 |
| is_read | TINYINT(1) | 是否已读 | 默认0 |
| created_at | TIMESTAMP | 通知时间 | 创建时间 |
### 12. 用户会话表 (user_sessions)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 会话ID | 主键,自增 |
| user_id | BIGINT | 用户ID | 外键关联users |
| token | VARCHAR(255) | 访问令牌 | 唯一 |
| refresh_token | VARCHAR(255) | 刷新令牌 | 可为空 |
| expires_at | TIMESTAMP | 过期时间 | 令牌过期时间 |
| user_agent | TEXT | 用户代理 | 浏览器信息,可为空 |
| is_active | TINYINT(1) | 是否激活 | 默认1 |
| created_at | TIMESTAMP | 创建时间 | 会话创建时间 |
| updated_at | TIMESTAMP | 更新时间 | 自动更新 |
### 13. 管理员表 (admin)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 管理员ID | 主键,自增 |
| username | VARCHAR(50) | 管理员用户名 | 唯一 |
| password | VARCHAR(255) | 管理员密码 | 加密存储 |
| created_at | TIMESTAMP | 创建时间 | 账号创建时间 |
### 14. 审核表 (audit)
| 字段名 | 类型 | 说明 | 备注 |
|--------|------|------|------|
| id | BIGINT | 审核ID | 主键,自增 |
| user_id | BIGINT | 用户ID | 外键关联users |
| type | TINYINT | 审核类型 | 1-用户审核2-内容审核3-评论审核 |
| content | TEXT | 审核内容 | 待审核的具体内容 |
| created_at | TIMESTAMP | 创建时间 | 提交审核时间 |
| audit_time | TIMESTAMP | 审核时间 | 完成审核时间,可为空 |
| status | TINYINT(1) | 审核状态 | 0-待审核1-审核通过默认0 |

View File

@@ -1,388 +0,0 @@
# 卜卜世界部署指南
## 项目简介
卜卜世界是一个基于 Express + Vue3 的现代化图文社区平台,支持用户注册、发布图文内容、互动交流等功能。
## 系统要求
- **Docker 部署**Docker 20.10+ 和 Docker Compose 2.0+
- **传统部署**Node.js 18+、MySQL 8.0+、npm 或 yarn
## 🐋 Docker 一键部署(推荐)
### 1. 克隆项目
```bash
git clone https://github.com/ZTMYO/XiaoShiLiu
cd XiaoShiLiu
```
### 2. 配置环境变量
复制环境配置文件:
```bash
cp .env.docker .env
```
编辑 `.env` 文件,根据需要修改配置:
```env
# 数据库配置
DB_HOST=mysql
DB_USER=xiaoshiliu_user
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# JWT配置
JWT_SECRET=xiaoshiliu_secret_key_2025_docker
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# 上传配置
UPLOAD_MAX_SIZE=50mb
# 图片上传策略 (local: 本地存储, imagehost: 第三方图床, r2: Cloudflare R2)
UPLOAD_STRATEGY=imagehost
# 第三方图床配置当UPLOAD_STRATEGY=imagehost时使用
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# Cloudflare R2 配置当UPLOAD_STRATEGY=r2时使用
# 如需使用R2存储请取消注释并填入真实配置
# R2_ACCESS_KEY_ID=your_r2_access_key_id_here
# R2_SECRET_ACCESS_KEY=your_r2_secret_access_key_here
# R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com
# R2_BUCKET_NAME=your_bucket_name_here
# R2_ACCOUNT_ID=your_account_id_here
# R2_REGION=auto
# R2_PUBLIC_URL=https://your-custom-domain.com
# 服务端口配置
FRONTEND_PORT=80
BACKEND_PORT=3001
DB_PORT_EXTERNAL=3306
```
### 3. 启动服务
使用 PowerShell 脚本Windows 推荐):
```powershell
# 基本启动
.\deploy.ps1
# 重新构建并启动
.\deploy.ps1 -Build
# 启动并灌装示例数据
.\deploy.ps1 -Seed
# 查看帮助
.\deploy.ps1 -Help
```
或使用 Docker Compose
```bash
# 启动服务
docker-compose up -d
# 重新构建并启动
docker-compose up -d --build
```
### 4. 访问应用
- **前端界面**http://localhost:8080
- **后端API**http://localhost:3001
- **数据库**localhost:3307
### 5. 常用管理命令
```powershell
# 查看服务状态
.\deploy.ps1 -Status
# 查看日志
.\deploy.ps1 -Logs
# 停止服务
.\deploy.ps1 -Stop
# 清理所有数据(谨慎使用)
.\deploy.ps1 -Clean
```
## 🛠️ 传统部署
### 1. 环境准备
确保已安装:
- Node.js 18+
- MySQL 8.0+
- Git
### 2. 克隆项目
```bash
git clone <项目地址>
cd XiaoShiLiu
```
### 3. 数据库配置
确保 MySQL 服务已启动,数据库将通过脚本自动创建和初始化。
### 4. 后端配置
进入后端目录:
```bash
cd express-project
```
复制并配置环境文件:
```bash
cp .env.example .env
```
编辑 `.env` 文件:
```env
# 服务器配置
PORT=3001
NODE_ENV=development
# JWT配置
JWT_SECRET=xiaoshiliu_secret_key_2025_production
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# 数据库配置
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# API配置
API_BASE_URL=http://localhost:3001
# 上传配置
UPLOAD_MAX_SIZE=50mb
# 图片上传策略 (local: 本地存储, imagehost: 第三方图床, r2: Cloudflare R2)
UPLOAD_STRATEGY=imagehost
# 本地存储配置
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# 第三方图床配置当UPLOAD_STRATEGY=imagehost时使用
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# Cloudflare R2 配置当UPLOAD_STRATEGY=r2时使用
# 请从 Cloudflare 控制台获取您自己的配置信息
R2_ACCESS_KEY_ID=your_r2_access_key_id_here
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key_here
R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your_bucket_name_here
R2_ACCOUNT_ID=your_account_id_here
R2_REGION=auto
# 可选:如果有自定义域名,可以设置 R2_PUBLIC_URL
# R2_PUBLIC_URL=https://your-custom-domain.com
# CORS配置
CORS_ORIGIN=http://localhost:5173
```
安装依赖并初始化数据库:
```bash
npm install
# 初始化数据库结构
cd scripts
node init-database.js
# 生成示例数据(可选)
node generate-data.js
```
启动后端服务:
```bash
npm start
```
### 5. 前端配置
打开新终端,进入前端目录:
```bash
cd vue3-project
```
复制并配置环境文件:
```bash
cp .env.example .env
```
编辑 `.env` 文件,根据后端配置调整:
```env
# 开发环境配置
# API基础URL需要与后端端口一致
VITE_API_BASE_URL=http://localhost:3001/api
# 是否使用真实API
VITE_USE_REAL_API=true
# 应用标题
VITE_APP_TITLE=卜卜世界
```
安装依赖:
```bash
npm install
```
开发模式启动:
```bash
npm run dev
```
生产模式构建:
```bash
npm run build
npm run preview
```
### 6. 访问应用
- **开发模式**http://localhost:5173
- **生产模式**http://localhost:4173
- **后端API**http://localhost:3001
## 📁 项目结构
```
XiaoShiLiu/
├── express-project/ # 后端项目
│ ├── app.js # 应用入口
│ ├── package.json # 后端依赖
│ ├── .env.example # 后端环境配置模板
│ ├── Dockerfile # 后端Docker配置
│ └── scripts/
│ └── init-database.sql # 数据库初始化脚本
├── vue3-project/ # 前端项目
│ ├── package.json # 前端依赖
│ ├── Dockerfile # 前端Docker配置
│ └── nginx.conf # Nginx配置
├── docker-compose.yml # Docker编排配置
├── .env.docker # Docker环境配置模板
├── deploy.ps1 # Windows部署脚本
└── doc/
└── DEPLOYMENT.md # 本文档
```
## 🔧 配置说明
### 上传策略配置
项目支持三种图片上传策略:
1. **本地存储** (`UPLOAD_STRATEGY=local`)
```env
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
```
2. **第三方图床** (`UPLOAD_STRATEGY=imagehost`)
```env
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
```
3. **Cloudflare R2** (`UPLOAD_STRATEGY=r2`)
```env
R2_ACCESS_KEY_ID=your_access_key
R2_SECRET_ACCESS_KEY=your_secret_key
R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your_bucket_name
R2_ACCOUNT_ID=your_account_id
R2_REGION=auto
```
### Cloudflare R2 配置步骤
1. 登录 Cloudflare 控制台
2. 进入 R2 Object Storage
3. 创建存储桶
4. 生成 API 令牌权限R2:Edit
5. 获取账户 ID
6. 配置环境变量
## 🚨 故障排除
### Docker 部署问题
1. **端口冲突**
```bash
# 检查端口占用
netstat -ano | findstr :8080
# 修改 .env 中的端口配置
```
2. **容器启动失败**
```bash
# 查看日志
docker-compose logs
# 重新构建
docker-compose up -d --build
```
3. **数据库连接失败**
```bash
# 检查数据库容器状态
docker-compose ps
# 重启数据库服务
docker-compose restart mysql
```
### 传统部署问题
1. **Node.js 版本不兼容**
```bash
# 检查版本
node --version
# 使用 nvm 切换版本
nvm use 18
```
2. **数据库连接失败**
- 检查 MySQL 服务是否启动
- 验证数据库用户权限
- 确认防火墙设置
3. **依赖安装失败**
```bash
# 清理缓存
npm cache clean --force
# 删除 node_modules 重新安装
rm -rf node_modules
npm install
```
## 📝 注意事项
1. **生产环境部署**
- 修改默认密码和密钥
- 配置 HTTPS
- 设置防火墙规则
- 定期备份数据
2. **性能优化**
- 使用 CDN 加速静态资源
- 配置数据库索引
- 启用 Gzip 压缩
3. **安全建议**
- 不要将 `.env` 文件提交到版本控制
- 定期更新依赖包
- 使用强密码策略
**祝您部署顺利!** 🎉

View File

@@ -1,163 +0,0 @@
# 项目结构
本文档详细介绍了卜卜世界项目的目录结构和文件组织。
## 总体结构
```
卜卜世界/
├── vue3-project/ # 前端项目
├── express-project/ # 后端项目
├── README.md # 项目主文档
├── DEPLOYMENT.md # 部署指南
└── PROJECT_STRUCTURE.md # 项目结构说明(本文档)
```
## 前端项目结构vue3-project/
```
vue3-project/
├── public/ # 静态资源目录
│ └── logo.ico # 网站图标
├── src/ # 源代码目录
│ ├── api/ # API接口封装
│ ├── assets/ # 静态资源(图片、样式等)
│ ├── components/ # 公共组件
│ ├── composables/ # 组合式函数
│ ├── config/ # 配置文件
│ ├── directives/ # 自定义指令
│ ├── router/ # 路由配置
│ ├── stores/ # Pinia状态管理
│ ├── utils/ # 工具函数
│ ├── views/ # 页面组件
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── .env.example # 环境变量模板
├── index.html # HTML模板
├── package.json # 项目配置
├── vite.config.js # Vite配置
└── README.md # 前端项目说明
```
### 前端目录详细说明
| 目录/文件 | 说明 | 主要内容 |
|-----------|------|----------|
| `public/` | 静态资源目录 | 网站图标、不需要编译的静态文件 |
| `src/api/` | API接口封装 | HTTP请求封装、接口定义 |
| `src/assets/` | 静态资源 | 图片、字体、样式文件等 |
| `src/components/` | 公共组件 | 可复用的Vue组件 |
| `src/composables/` | 组合式函数 | Vue 3 Composition API逻辑复用 |
| `src/config/` | 配置文件 | 应用配置、常量定义 |
| `src/directives/` | 自定义指令 | Vue自定义指令 |
| `src/router/` | 路由配置 | Vue Router路由定义 |
| `src/stores/` | 状态管理 | Pinia状态管理模块 |
| `src/utils/` | 工具函数 | 通用工具函数、辅助方法 |
| `src/views/` | 页面组件 | 页面级Vue组件 |
| `App.vue` | 根组件 | 应用程序根组件 |
| `main.js` | 入口文件 | 应用程序入口点 |
| `vite.config.js` | Vite配置 | 构建工具配置 |
## 后端项目结构express-project/
```
express-project/
├── config/ # 配置文件目录
│ ├── config.js # 主配置文件
│ └── database.js # 数据库配置
├── routes/ # 路由文件目录
│ ├── auth.js # 认证路由
│ ├── users.js # 用户路由
│ ├── posts.js # 笔记路由
│ ├── comments.js # 评论路由
│ └── ... # 其他路由文件
├── middleware/ # 中间件目录
│ ├── auth.js # 认证中间件
│ └── crudFactory.js # CRUD工厂
├── utils/ # 工具函数目录
├── scripts/ # 脚本文件目录
│ ├── init-database.js # 数据库初始化脚本
│ ├── init-database.sql # SQL初始化脚本
│ ├── generate-data.js # 测试数据生成脚本
│ └── update-sample-images.js # 示例图片更新脚本
├── app.js # 应用入口文件
├── package.json # 项目配置
└── .env.example # 环境变量模板
```
### 后端目录详细说明
| 目录/文件 | 说明 | 主要内容 |
|-----------|------|----------|
| `config/` | 配置文件目录 | 应用配置、数据库配置 |
| `routes/` | 路由文件目录 | Express路由定义、API端点 |
| `middleware/` | 中间件目录 | Express中间件、认证逻辑 |
| `utils/` | 工具函数目录 | 通用工具函数、辅助方法 |
| `scripts/` | 脚本文件目录 | 数据库初始化、数据生成脚本 |
| `app.js` | 应用入口文件 | Express应用程序入口 |
### 路由文件说明
| 路由文件 | 功能 | 主要端点 |
|----------|------|----------|
| `auth.js` | 用户认证 | 登录、注册、token验证 |
| `users.js` | 用户管理 | 用户信息CRUD、关注关系 |
| `posts.js` | 笔记管理 | 笔记发布、编辑、删除、查询 |
| `comments.js` | 评论管理 | 评论发布、删除、查询 |
### 脚本文件说明
| 脚本文件 | 功能 | 使用场景 |
|----------|------|----------|
| `init-database.js` | 数据库初始化 | 首次部署时创建数据库结构 |
| `init-database.sql` | SQL初始化脚本 | 直接在MySQL客户端执行 |
| `generate-data.js` | 测试数据生成 | 开发环境填充测试数据 |
| `update-sample-images.js` | 图片链接更新 | 更新示例图片资源 |
## 技术架构
### 前端架构
```
┌─────────────────────────────────────┐
│ Vue 3 App │
├─────────────────────────────────────┤
│ Views (页面) │ Components (组件) │
├─────────────────────────────────────┤
│ Router (路由) │ Stores (状态管理) │
├─────────────────────────────────────┤
│ API (接口) │ Utils (工具) │
├─────────────────────────────────────┤
│ Vite (构建工具) │
└─────────────────────────────────────┘
```
### 后端架构
```
┌─────────────────────────────────────┐
│ Express Server │
├─────────────────────────────────────┤
│ Routes (路由) │ Middleware (中间件) │
├─────────────────────────────────────┤
│ Config (配置) │ Utils (工具) │
├─────────────────────────────────────┤
│ MySQL Database │
└─────────────────────────────────────┘
```
## 数据流向
```
前端 Vue App
↓ HTTP请求
Express 路由
↓ 数据处理
中间件验证
↓ 数据库操作
MySQL 数据库
↓ 返回数据
前端状态更新
↓ 视图渲染
用户界面展示
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,200 +0,0 @@
# Image-Text Community Project Database Design
## Overview
Database structure design for the Xiaoshiliu-style image-text community project (simplified version), including core functionalities such as user management, content publishing, and social interactions.
### Character Set and Collation
- Database Character Set: `utf8mb4`
- Collation: `utf8mb4_unicode_ci`
- Storage Engine: `InnoDB`
## Core Database Table Structure
### 1. Users Table (users)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | User ID | Primary key, auto-increment |
| password | VARCHAR(255) | Password | Nullable |
| user_id | VARCHAR(50) | Xiaoshiliu ID | Unique identifier |
| nickname | VARCHAR(100) | Nickname | Display name |
| avatar | VARCHAR(500) | Avatar URL | User avatar |
| bio | TEXT | Personal Bio | User introduction |
| location | VARCHAR(100) | IP Location | Geographic location |
| follow_count | INT | Following Count | Statistics field, default 0 |
| fans_count | INT | Followers Count | Statistics field, default 0 |
| like_count | INT | Likes Received | Statistics field, default 0 |
| is_active | TINYINT(1) | Is Active | Default 1 |
| last_login_at | TIMESTAMP | Last Login Time | Nullable |
| created_at | TIMESTAMP | Creation Time | Registration time |
| updated_at | TIMESTAMP | Update Time | Auto-update |
| gender | VARCHAR(10) | Gender | Nullable |
| zodiac_sign | VARCHAR(20) | Zodiac Sign | Nullable |
| mbti | VARCHAR(4) | MBTI Personality Type | Nullable |
| education | VARCHAR(50) | Education | Nullable |
| major | VARCHAR(100) | Major | Nullable |
| interests | JSON | Interests | JSON array, nullable |
| verified | TINYINT(1) | Verification Status | 0-Unverified, 1-Verified, default 0 |
### 2. Categories Table (categories)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | INT | Category ID | Primary key, auto-increment |
| name | VARCHAR(50) | Category Name | Unique, e.g., Study, Campus, Emotion |
| created_at | TIMESTAMP | Creation Time | Category creation time |
**Indexes:**
- PRIMARY KEY (`id`)
- UNIQUE KEY `name` (`name`)
- KEY `idx_name` (`name`)
**Initial Data:**
- 学习 (Study)
- 校园 (Campus)
- 情感 (Emotion)
- 兴趣 (Interest)
- 生活 (Life)
- 社交 (Social)
- 帮助 (Help)
- 观点 (Opinion)
- 毕业 (Graduation)
- 职场 (Career)
### 3. Posts Table (posts)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Post ID | Primary key, auto-increment |
| user_id | BIGINT | Publisher User ID | Foreign key to users |
| title | VARCHAR(200) | Title | Post title |
| content | TEXT | Content | Post description |
| category_id | INT | Category ID | Foreign key to categories table, nullable |
| is_draft | TINYINT(1) | Is Draft | 1-Draft, 0-Published, default 1 |
| view_count | BIGINT | View Count | Statistics field, default 0 |
| like_count | INT | Like Count | Statistics field, default 0 |
| collect_count | INT | Collection Count | Statistics field, default 0 |
| comment_count | INT | Comment Count | Statistics field, default 0 |
| created_at | TIMESTAMP | Publish Time | Creation time |
### 3. Post Images Table (post_images)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Image ID | Primary key, auto-increment |
| post_id | BIGINT | Post ID | Foreign key to posts |
| image_url | VARCHAR(500) | Image URL | Original image address |
### 4. Tags Table (tags)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | INT | Tag ID | Primary key, auto-increment |
| name | VARCHAR(50) | Tag Name | Tag content, unique |
| use_count | INT | Usage Count | Popularity statistics, default 0 |
| created_at | TIMESTAMP | Creation Time | First usage time |
### 5. Post Tags Association Table (post_tags)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Association ID | Primary key, auto-increment |
| post_id | BIGINT | Post ID | Foreign key to posts |
| tag_id | INT | Tag ID | Foreign key to tags |
| created_at | TIMESTAMP | Creation Time | Association time |
### 6. Follow Relationships Table (follows)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Follow ID | Primary key, auto-increment |
| follower_id | BIGINT | Follower ID | Foreign key to users |
| following_id | BIGINT | Following ID | Foreign key to users |
| created_at | TIMESTAMP | Follow Time | Creation time |
### 7. Likes Table (likes)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Like ID | Primary key, auto-increment |
| user_id | BIGINT | User ID | Foreign key to users |
| target_type | TINYINT | Target Type | 1-Post, 2-Comment |
| target_id | BIGINT | Target ID | Post or comment ID |
| created_at | TIMESTAMP | Like Time | Creation time |
### 8. Collections Table (collections)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Collection ID | Primary key, auto-increment |
| user_id | BIGINT | User ID | Foreign key to users |
| post_id | BIGINT | Post ID | Foreign key to posts |
| created_at | TIMESTAMP | Collection Time | Creation time |
### 9. Comments Table (comments)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Comment ID | Primary key, auto-increment |
| post_id | BIGINT | Post ID | Foreign key to posts |
| user_id | BIGINT | Commenter User ID | Foreign key to users |
| parent_id | BIGINT | Parent Comment ID | Used for reply comments, nullable |
| content | TEXT | Comment Content | Comment text |
| like_count | INT | Like Count | Statistics field, default 0 |
| created_at | TIMESTAMP | Comment Time | Creation time |
### 10. Notifications Table (notifications)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Notification ID | Primary key, auto-increment |
| user_id | BIGINT | Recipient User ID | Foreign key to users |
| sender_id | BIGINT | Sender User ID | Foreign key to users |
| type | TINYINT | Notification Type | 1-Like Post, 2-Like Comment, 3-Collection, 4-Comment Post, 5-Reply Comment, 6-Follow, 7-Comment Mention, 8-Post Mention |
| title | VARCHAR(200) | Notification Title | Notification content |
| target_id | BIGINT | Associated Target ID | Post or comment ID, nullable |
| comment_id | BIGINT | Associated Comment ID | For comment and reply notifications, nullable |
| is_read | TINYINT(1) | Is Read | Default 0 |
| created_at | TIMESTAMP | Notification Time | Creation time |
### 11. User Sessions Table (user_sessions)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Session ID | Primary key, auto-increment |
| user_id | BIGINT | User ID | Foreign key to users |
| token | VARCHAR(255) | Access Token | Unique |
| refresh_token | VARCHAR(255) | Refresh Token | Nullable |
| expires_at | TIMESTAMP | Expiration Time | Token expiration time |
| user_agent | TEXT | User Agent | Browser information, nullable |
| is_active | TINYINT(1) | Is Active | Default 1 |
| created_at | TIMESTAMP | Creation Time | Session creation time |
| updated_at | TIMESTAMP | Update Time | Auto-update |
### 12. Admin Table (admin)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Admin ID | Primary key, auto-increment |
| username | VARCHAR(50) | Admin Username | Unique |
| password | VARCHAR(255) | Admin Password | Encrypted storage |
| created_at | TIMESTAMP | Creation Time | Account creation time |
### 13. Audit Table (audit)
| Field Name | Type | Description | Notes |
|------------|------|-------------|-------|
| id | BIGINT | Audit ID | Primary key, auto-increment |
| user_id | BIGINT | User ID | Foreign key to users table |
| type | TINYINT | Audit Type | 1-User audit, 2-Content audit, 3-Comment audit |
| content | TEXT | Audit Content | Specific content to be audited |
| created_at | TIMESTAMP | Creation Time | Time when audit was submitted |
| audit_time | TIMESTAMP | Audit Time | Time when audit was completed, nullable |
| status | TINYINT(1) | Audit Status | 0-Pending, 1-Approved, default 0 |
---
*Last Updated: January 16, 2025*
*Database Version: 1.0.3*

View File

@@ -1,201 +0,0 @@
# 圖文社區項目資料庫設計
## 概述
基於卜卜風格的圖文社區項目,簡化版資料庫結構設計,包含使用者管理、內容發佈、社交互動等核心功能。
### 字元集和排序規則
- 資料庫字元集:`utf8mb4`
- 排序規則:`utf8mb4_unicode_ci`
- 儲存引擎:`InnoDB`
## 核心資料表結構
### 1. 使用者表 (users)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 使用者ID | 主鍵,自增 |
| password | VARCHAR(255) | 密碼 | 可為空 |
| user_id | VARCHAR(50) | 卜卜號 | 唯一標識 |
| nickname | VARCHAR(100) | 暱稱 | 顯示名稱 |
| avatar | VARCHAR(500) | 頭像URL | 使用者頭像 |
| bio | TEXT | 個人簡介 | 使用者介紹 |
| location | VARCHAR(100) | IP屬地 | 地理位置 |
| follow_count | INT | 關注數 | 統計欄位預設0 |
| fans_count | INT | 粉絲數 | 統計欄位預設0 |
| like_count | INT | 獲讚數 | 統計欄位預設0 |
| is_active | TINYINT(1) | 是否啟用 | 預設1 |
| last_login_at | TIMESTAMP | 最後登入時間 | 可為空 |
| created_at | TIMESTAMP | 建立時間 | 註冊時間 |
| updated_at | TIMESTAMP | 更新時間 | 自動更新 |
| gender | VARCHAR(10) | 性別 | 可為空 |
| zodiac_sign | VARCHAR(20) | 星座 | 可為空 |
| mbti | VARCHAR(4) | MBTI人格類型 | 可為空 |
| education | VARCHAR(50) | 學歷 | 可為空 |
| major | VARCHAR(100) | 專業 | 可為空 |
| interests | JSON | 興趣愛好 | JSON陣列可為空 |
| verified | TINYINT(1) | 認證狀態 | 0-未認證1-已認證預設0 |
### 2. 分類表 (categories)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | INT | 分類ID | 主鍵,自增 |
| name | VARCHAR(50) | 分類名稱 | 唯一,如:學習、校園、情感等 |
| category_title | VARCHAR(50) | 英文標題 | 唯一用於URL路由study、campus、emotion等 |
| created_at | TIMESTAMP | 建立時間 | 分類建立時間 |
**索引:**
- PRIMARY KEY (`id`)
- UNIQUE KEY `name` (`name`)
- KEY `idx_name` (`name`)
**初始資料:**
- 學習
- 校園
- 情感
- 興趣
- 生活
- 社交
- 幫助
- 觀點
- 畢業
- 職場
### 3. 筆記表 (posts)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 筆記ID | 主鍵,自增 |
| user_id | BIGINT | 發佈使用者ID | 外鍵關聯users |
| title | VARCHAR(200) | 標題 | 筆記標題 |
| content | TEXT | 內容 | 筆記描述 |
| category_id | INT | 分類ID | 外鍵關聯categories表可為空 |
| is_draft | TINYINT(1) | 是否為草稿 | 1-草稿0-已發佈預設1 |
| view_count | BIGINT | 瀏覽量 | 統計欄位預設0 |
| like_count | INT | 按讚數 | 統計欄位預設0 |
| collect_count | INT | 收藏數 | 統計欄位預設0 |
| comment_count | INT | 評論數 | 統計欄位預設0 |
| created_at | TIMESTAMP | 發佈時間 | 建立時間 |
### 3. 筆記圖片表 (post_images)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 圖片ID | 主鍵,自增 |
| post_id | BIGINT | 筆記ID | 外鍵關聯posts |
| image_url | VARCHAR(500) | 圖片URL | 原圖地址 |
### 4. 標籤表 (tags)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | INT | 標籤ID | 主鍵,自增 |
| name | VARCHAR(50) | 標籤名 | 標籤內容,唯一 |
| use_count | INT | 使用次數 | 熱度統計預設0 |
| created_at | TIMESTAMP | 建立時間 | 首次使用時間 |
### 5. 筆記標籤關聯表 (post_tags)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 關聯ID | 主鍵,自增 |
| post_id | BIGINT | 筆記ID | 外鍵關聯posts |
| tag_id | INT | 標籤ID | 外鍵關聯tags |
| created_at | TIMESTAMP | 建立時間 | 關聯時間 |
### 6. 關注關係表 (follows)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 關注ID | 主鍵,自增 |
| follower_id | BIGINT | 關注者ID | 外鍵關聯users |
| following_id | BIGINT | 被關注者ID | 外鍵關聯users |
| created_at | TIMESTAMP | 關注時間 | 建立時間 |
### 7. 按讚表 (likes)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 按讚ID | 主鍵,自增 |
| user_id | BIGINT | 使用者ID | 外鍵關聯users |
| target_type | TINYINT | 目標類型 | 1-筆記, 2-評論 |
| target_id | BIGINT | 目標ID | 筆記或評論ID |
| created_at | TIMESTAMP | 按讚時間 | 建立時間 |
### 8. 收藏表 (collections)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 收藏ID | 主鍵,自增 |
| user_id | BIGINT | 使用者ID | 外鍵關聯users |
| post_id | BIGINT | 筆記ID | 外鍵關聯posts |
| created_at | TIMESTAMP | 收藏時間 | 建立時間 |
### 9. 評論表 (comments)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 評論ID | 主鍵,自增 |
| post_id | BIGINT | 筆記ID | 外鍵關聯posts |
| user_id | BIGINT | 評論使用者ID | 外鍵關聯users |
| parent_id | BIGINT | 父評論ID | 回覆評論時使用,可為空 |
| content | TEXT | 評論內容 | 評論文字 |
| like_count | INT | 按讚數 | 統計欄位預設0 |
| created_at | TIMESTAMP | 評論時間 | 建立時間 |
### 10. 通知表 (notifications)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 通知ID | 主鍵,自增 |
| user_id | BIGINT | 接收使用者ID | 外鍵關聯users |
| sender_id | BIGINT | 發送使用者ID | 外鍵關聯users |
| type | TINYINT | 通知類型 | 1-按讚筆記, 2-按讚評論, 3-收藏, 4-評論筆記, 5-回覆評論, 6-關注, 7-評論提及, 8-筆記提及 |
| title | VARCHAR(200) | 通知標題 | 通知內容 |
| target_id | BIGINT | 關聯目標ID | 筆記或評論ID可為空 |
| comment_id | BIGINT | 關聯評論ID | 用於評論和回覆通知,可為空 |
| is_read | TINYINT(1) | 是否已讀 | 預設0 |
| created_at | TIMESTAMP | 通知時間 | 建立時間 |
### 11. 使用者會話表 (user_sessions)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 會話ID | 主鍵,自增 |
| user_id | BIGINT | 使用者ID | 外鍵關聯users |
| token | VARCHAR(255) | 存取權杖 | 唯一 |
| refresh_token | VARCHAR(255) | 重新整理權杖 | 可為空 |
| expires_at | TIMESTAMP | 過期時間 | 權杖過期時間 |
| user_agent | TEXT | 使用者代理 | 瀏覽器信息,可為空 |
| is_active | TINYINT(1) | 是否啟用 | 預設1 |
| created_at | TIMESTAMP | 建立時間 | 會話建立時間 |
| updated_at | TIMESTAMP | 更新時間 | 自動更新 |
### 12. 管理員表 (admin)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 管理員ID | 主鍵,自增 |
| username | VARCHAR(50) | 管理員使用者名稱 | 唯一 |
| password | VARCHAR(255) | 管理員密碼 | 加密儲存 |
| created_at | TIMESTAMP | 建立時間 | 帳號建立時間 |
### 13. 審核表 (audit)
| 欄位名 | 類型 | 說明 | 備註 |
|--------|------|------|------|
| id | BIGINT | 審核ID | 主鍵,自增 |
| user_id | BIGINT | 使用者ID | 外鍵關聯users |
| type | TINYINT | 審核類型 | 1-使用者審核2-內容審核3-評論審核 |
| content | TEXT | 審核內容 | 待審核的具體內容 |
| created_at | TIMESTAMP | 建立時間 | 提交審核時間 |
| audit_time | TIMESTAMP | 審核時間 | 完成審核時間,可為空 |
| status | TINYINT(1) | 審核狀態 | 0-待審核1-審核通過預設0 |
---
*最後更新: 2025年1月16日*
*資料庫版本: 1.0.3*

View File

@@ -1,658 +0,0 @@
# Deployment Guide
This document provides a detailed introduction to the deployment process and configuration instructions for the XiaoShiLiu image and text community project.
## Deployment Methods
The project supports two deployment methods:
1. **Docker One-Click Deployment** (recommended) - Simple and quick, suitable for production environments
2. **Traditional Deployment** - Manual configuration, suitable for development environments
---
## 🐳 Docker One-Click Deployment (Recommended)
### Environment Requirements
- Docker >= 20.0
- Docker Compose >= 2.0
- Available Memory >= 2GB
- Available Disk Space >= 5GB
### Image and Version Description
| Component | Image/Source | Version/Tag | Description |
|-----------|--------------|-------------|-------------|
| Database | mysql | 8.0 | Uses the official image `mysql:8.0` with utf8mb4 default configuration |
| Backend Runtime | node | 18-alpine | `express-project/Dockerfile` uses `node:18-alpine` |
| Frontend Build | node | 18-alpine | `vue3-project/Dockerfile` uses this for the build phase |
| Frontend Runtime | nginx | alpine | Uses `nginx:alpine` to provide static files |
| Compose Health Check | wget | - | Frontend health check uses `wget --spider http://localhost/` |
> Note: The above versions are consistent with `docker-compose.yml` and the front-end and back-end `Dockerfile`; if changes are required, please synchronize adjustments to the corresponding files and documentation.
### Quick Start
#### 1. Clone the Project
```bash
git clone https://github.com/ZTMYO/XiaoShiLiu.git
cd XiaoShiLiu
```
#### 2. Configure Environment Variables (Optional)
```bash
# Optional: If you have custom environment variables, you can create a .env file
# This repository does not provide .env.docker, so you can skip it if there is no special need. You can use the default values in docker-compose.yml instead.
```
#### 3. One-Click Start
**Windows Users:**
```powershell
# Start services
.\deploy.ps1
# Rebuild and start
.\deploy.ps1 -Build
# Start and seed example data (optional)
.\deploy.ps1 -Build -Seed
# Or seed data separately after the service has started
.\deploy.ps1 -Seed
# Check service status
.\deploy.ps1 -Status
# View logs
.\deploy.ps1 -Logs
# Stop services
.\deploy.ps1 -Stop
```
**Linux/macOS Users:**
```bash
# Grant execution permission to the script
chmod +x deploy.sh
# Start services
./deploy.sh
# Rebuild and start
./deploy.sh --build
# Check service status
./deploy.sh --status
# View logs
./deploy.sh --logs
# Stop services
./deploy.sh --stop
```
#### 4. Access the Application
After the service starts successfully, you can access the application through the following addresses:
| Service | Address | Description |
|---------|---------|-------------|
| Frontend Interface | http://localhost:8080 | Main access entry |
| Backend API | http://localhost:3001 | API service |
| Database | localhost:3307 | MySQL database |
### Docker Deployment Architecture
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Frontend │ │ Backend │ │ MySQL │
│ (Nginx) │◄───┤ (Express) │◄───┤ (Database) │
│ Port: 80 │ │ Port: 3001 │ │ Port: 3306 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### Environment Variable Configuration
The project uses a `.env` file for configuration, with separate environment configurations for the frontend and backend:
#### Backend Environment Variables (express-project/.env)
```env
# Server Configuration
PORT=3001
NODE_ENV=development
# JWT Configuration
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# Database Configuration
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# Upload Configuration
UPLOAD_MAX_SIZE=50mb
# Image Upload Strategy (local: Local Storage, imagehost: Third-party Image Hosting, r2: Cloudflare R2 Storage)
UPLOAD_STRATEGY=imagehost
# Local Storage Configuration
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# Third-party Image Hosting Configuration
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# Cloudflare R2 Storage Configuration
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your_bucket_name
R2_ACCOUNT_ID=your_account_id
R2_REGION=auto
# Optional: Custom Domain URL (if a custom domain is configured)
R2_PUBLIC_URL=https://your-custom-domain.com
# Upload Strategy: local (Local Storage), imagehost (Third-party Image Hosting), or r2 (Cloudflare R2 Storage)
UPLOAD_STRATEGY=local
# Local Storage Configuration
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# Third-party Image Hosting Configuration
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# API Configuration
API_BASE_URL=http://localhost:3001
# CORS Configuration
CORS_ORIGIN=http://localhost:5173
```
#### Frontend Environment Variables (vue3-project/.env)
```env
# API Base URL Configuration
VITE_API_BASE_URL=http://localhost:3001/api
# Use Real API
VITE_USE_REAL_API=true
# Application Title
VITE_APP_TITLE=Small Pear Graphic Community
```
#### Docker Environment Variable Description
When deploying with Docker, environment variables are configured through `docker-compose.yml`:
```env
# Database Configuration (Docker Environment)
DB_HOST=mysql
DB_USER=xiaoshiliu_user
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
# JWT Configuration
JWT_SECRET=xiaoshiliu_secret_key_2025_docker
JWT_EXPIRES_IN=7d
# Upload Configuration
UPLOAD_MAX_SIZE=50mb
# Image Upload Strategy (local: Local Storage, imagehost: Third-party Image Hosting, r2: Cloudflare R2 Storage)
UPLOAD_STRATEGY=imagehost
# API Configuration
API_BASE_URL=http://localhost:3001
```
### Common Commands
```bash
# Check service status
docker-compose ps
# View service logs
docker-compose logs -f
# Restart a specific service
docker-compose restart backend
# Enter the container (sh is used since alpine images typically do not have bash)
docker-compose exec backend sh
# Or enter the MySQL client
docker-compose exec mysql mysql -u root -p
# Backup the database
docker-compose exec mysql mysqldump -u root -p xiaoshiliu > backup.sql
# Restore the database
docker-compose exec -T mysql mysql -u root -p xiaoshiliu < backup.sql
```
### Data Persistence
Docker uses volumes for data persistence in deployment:
- `mysql_data`: MySQL database files
- `backend_uploads`: Backend upload files
### Troubleshooting
#### 1. Port Conflicts
If port conflicts occur, you can modify the port mappings in the `docker-compose.yml` file:
```yaml
services:
frontend:
ports:
- "8080:80" # Modify the frontend port
backend:
ports:
- "3002:3001" # Modify the backend port
```
#### 2. Memory Insufficient
Ensure the system has enough memory, and you can view resource usage with the following command:
```bash
docker stats
```
#### 3. Database Connection Failure / Loading Data
- Check if the database service is started normally:
```bash
docker-compose logs mysql
```
- Load sample data (Windows):
```powershell
.\deploy.ps1 -Seed
```
- Load sample data (manual execution):
```bash
docker-compose exec -T backend node scripts/generate-data.js
```
#### 4. File Upload Permission Issues
**Problem Phenomena**:
- When uploading files from the frontend, a 400 error is returned
- Backend logs show: `EACCES: permission denied, open '/app/uploads/xxx.png'`
**Cause Analysis**:
Permission issue in the Docker container's uploads directory. The directory belongs to the root user, but the application runs under the nodejs user.
**Solution**:
1. **Check the permissions of the uploads directory**:
```bash
docker-compose exec backend ls -la /app/uploads
```
2. **Fix the permission issue**:
```bash
# Modify the directory owner to root user using root user
docker-compose exec --user root backend chown -R nodejs:nodejs /app/uploads
```
3. **Verify the permission fix**:
```bash
# Confirm that the directory now belongs to the nodejs user
docker-compose exec backend ls -la /app/uploads
```
**Preventive Measures**:
- Ensure the uploads directory permissions are set correctly in the Dockerfile
- Automatically fix permissions issues when the container starts
#### 5. Upload Strategy Configuration
The project supports three file upload strategies:
**Local Storage Mode** (recommended for development and small deployments):
```yaml
# Set in docker-compose.yml
environment:
UPLOAD_STRATEGY: local
```
**Third-party Image Hosting Mode** (recommended for production environments):
```yaml
# Set in docker-compose.yml
environment:
UPLOAD_STRATEGY: imagehost
```
**Cloudflare R2 Storage Mode** (recommended for production environments, supports CDN acceleration):
```yaml
# Setting in docker-compose.yml
environment:
UPLOAD_STRATEGY: r2
R2_ACCESS_KEY_ID: your_r2_access_key_id
R2_SECRET_ACCESS_KEY: your_r2_secret_access_key
R2_ENDPOINT: https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME: your_bucket_name
R2_ACCOUNT_ID: your_account_id
R2_REGION: auto
# Optional: Custom domain
R2_PUBLIC_URL: https://your-custom-domain.com
> **Note**: To use Cloudflare R2 storage, you need to first create an R2 bucket and obtain the corresponding access key in the Cloudflare console.
#### 6. Cleanup and Reset
If you encounter problems and need to start over:
```bash
# Windows
.\deploy.ps1 -Clean
# Linux/macOS
./deploy.sh --clean
```
---
## 📋 Traditional Deployment Method
## System Requirements
| Component | Version Requirement | Description |
|-----------|---------------------|-------------|
| Node.js | >= 16.0.0 | Runtime environment |
| MySQL | >= 5.7 | Database |
| MariaDB | >= 10.3 | Database (optional) |
| npm | >= 8.0.0 | Package manager |
| yarn | >= 1.22.0 | Package manager (optional) |
| Browser | Supports ES6+ | Modern browser |
## Quick Start
### 1. Install Dependencies
```bash
# Using cnpm
cnpm install
# Or using yarn
yarn install
```
### 2. Configure Backend API Address
Create an environment configuration file (optional):
```bash
# Copy environment configuration template
cp .env.example .env
```
Edit the `.env` file to configure the backend API address:
```env
# Backend API address
VITE_API_BASE_URL=http://localhost:3001
# Other configurations...
```
### 3. Start Development Server
```bash
# Start development server
npm run dev
# Or using yarn
yarn dev
```
The development server will start at `http://localhost:5173`.
### 4. Build Production Version
```bash
# Build production version
npm run build
# Preview production version
npm run preview
```
## Backend Service Configuration
⚠️ **Important Reminder**: The frontend project needs to be used with the backend service.
1. **Start Backend Service**:
```bash
# Navigate to the backend project directory
cd ../express-project
# Install backend dependencies
npm install
# Start backend service
npm start
```
2. **Backend Service Address**: `http://localhost:3001`
3. **API Documentation**: Check the `API_DOCS.md` file in the backend project.
## Development Environment Configuration
### Environment Check
```bash
# Check Node.js version
node --version
# Check npm version
npm --version
```
### Development Server
```bash
# Start development server (hot reload)
npm run dev
# Access address: http://localhost:5173
```
### Code Conventions
- Use Vue 3 Composition API
- Adhere to the official Vue.js style guide
- Component naming in PascalCase
- File naming in kebab-case
## Explanation of Configuration Files
### Frontend Configuration Files (vue3-project directory)
| File | Description |
|------|-------------|
| `.env` | Environment variable configuration file |
| `vite.config.js` | Vite build tool configuration |
| `package.json` | Project dependencies and script configuration |
| `jsconfig.json` | JavaScript project configuration |
### Backend Configuration Files (express-project directory)
| File | Description |
|------|-------------|
| `config/config.js` | Main configuration file |
| `.env` | Environment variable configuration file |
| `database_design.md` | Database design document |
| `scripts/init-database.js` | Database initialization script |
| `generate-data.js` | Test data generation script |
## npm Script Commands
### Frontend Scripts (to be executed in the vue3-project directory)
| Command | Description |
|---------|-------------|
| `npm run dev` | Start the development server |
| `npm run build` | Build the production version |
| `npm run preview` | Preview the production version |
### Backend Scripts (to be executed in the express-project directory)
| Command | Description |
|---------|-------------|
| `npm start` | Start the server |
| `npm run dev` | Start the development server (hot reload) |
| `npm run init-db` | Initialize the database |
| `npm run generate-data` | Generate test data |
## Environment Variable Configuration
### Frontend Environment Variables (vue3-project/.env)
```env
# API server address
VITE_API_BASE_URL=http://localhost:3001/api
# Other frontend configurations
VITE_APP_TITLE=Small石榴Image and Text Community
VITE_USE_REAL_API=true
```
### Backend Environment Variables (express-project/.env)
```env
# Server configuration
NODE_ENV=development
PORT=3001
# JWT configuration
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# Database configuration
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# API configuration
API_BASE_URL=http://localhost:3001
# Upload configuration
UPLOAD_MAX_SIZE=50mb
```
## Database Script Description
The database-related scripts for the project are all placed in the `express-project/scripts/` directory for easy management and use:
### Script File Introduction
#### 1. Database Initialization Script
- **File Location**: `scripts/init-database.js`
- **Function**: Create the database and all table structures
- **Usage Method**:
```bash
cd express-project
node scripts/init-database.js
```
- **Description**: Must be run for the first deployment, which will automatically create the `xiaoshiliu` database and 12 data tables
#### 2. Test Data Generation Script
- **File Location**: `scripts/generate-data.js`
- **Function**: Generate mock user, note, comment, and other test data
- **Usage Method**:
```bash
cd express-project
node scripts/generate-data.js
```
- **Description**: Optional to run, used to quickly populate test data, including 50 users, 200 notes, and 800 comments, etc.
#### 3. SQL Initialization File
- **File Location**: `scripts/init-database.sql`
- **Function**: Pure SQL version of the database initialization script
- **Usage Method**: Can be directly executed in the MySQL client
- **Description**: Has the same function as `init-database.js`, providing an SQL version for reference
#### 4. Sample Image Update Script
- **File Location**: `scripts/update-sample-images.js`
- **Function**: Automatically obtain the latest image links and update the sample images in the database
- **Usage Method**:
```bash
cd express-project
node scripts/update-sample-images.js
```
- **Description**:
- Automatically fetches the latest image links from the Liziwen API
- Updates `imgLinks/avatar_link.txt` (50 avatar links)
- Updates `imgLinks/post_img_link.txt` (300 note image links)
- Batch updates user avatars and note images in the database
- Supports statistics showing the number of images before and after the update
## Development Environment Startup Process
### 1. Start Backend Service
```bash
# Open the first terminal, navigate to the backend directory
cd express-project
# Install backend dependencies (first run)
npm install
# Configure the database (first run)
# Edit config/config.js or .env file
# Initialize the database (first run)
node scripts/init-database.js
# Generate test data (optional)
node scripts/generate-data.js
# Start the backend service
npm start
# The backend service runs at http://localhost:3001
```
### 2. Start Frontend Service
```bash
# Open the second terminal, navigate to the frontend directory
cd vue3-project
# Install frontend dependencies (first run)
npm install
# Configure API address (optional)
# Edit .env file, set VITE_API_BASE_URL
# Start the frontend development server
npm run dev
# The frontend service runs at http://localhost:5173
```
### 3. Access the Application
| Service | Address |
|---------|---------|
| Frontend Interface | http://localhost:5173 |
| Backend API | http://localhost:3001 |

View File

@@ -1,658 +0,0 @@
# 部署指南
本文件提供 XiaoShiLiu 圖文社區項目的部署流程及配置說明。
## 部署方法
項目支援兩種部署方法:
1. **Docker 一鍵部署**(推薦)- 簡單快捷,適合生產環境
2. **傳統部署** - 手動配置,適合開發環境
---
## 🐳 Docker 一鍵部署(推薦)
### 環境需求
- Docker >= 20.0
- Docker Compose >= 2.0
- 可用記憶體 >= 2GB
- 可用磁碟空間 >= 5GB
### 圖像和版本說明
| 部件 | 圖像/來源 | 版本/標籤 | 說明 |
|------|-----------|-------------|-------------|
| 數據庫 | mysql | 8.0 | 使用官方圖像 `mysql:8.0`,默認配置為 utf8mb4 |
| 後端運行時 | node | 18-alpine | `express-project/Dockerfile` 使用 `node:18-alpine` |
| 前端編譯 | node | 18-alpine | `vue3-project/Dockerfile` 在編譯階段使用此圖像 |
| 前端運行時 | nginx | alpine | 使用 `nginx:alpine` 提供靜態文件 |
| Compose 健康檢查 | wget | - | 前端健康檢查使用 `wget --spider http://localhost/` |
> 記錄:上述版本與 `docker-compose.yml` 及前端和後端 `Dockerfile` 的版本一致;如需進行修改,請同步調整相關文件和文件說明。
### 快速啟動
#### 1. 克隆項目
```bash
git clone https://github.com/ZTMYO/XiaoShiLiu.git
cd XiaoShiLiu
```
#### 2. 配置環境變數(選擇性)
```bash
# 選擇性:如果您有自定義環境變數,您可以建立一個 .env 文件
# 此儲存庫不提供 .env.docker所以如果您沒有特殊需求可以跳過它。您可以使用 docker-compose.yml 中的默認值。您可以使用 docker-compose.yml 中的默認值。
```
#### 3. 一鍵啟動
**Windows 用戶:**
```powershell
#啟動服務
.\deploy.ps1
# 重新編譯並啟動
.\deploy.ps1 -Build
# 啟動並種植範例數據(選擇性)
.\deploy.ps1 -Build -Seed
# 或者服務啟動後分別種植數據
.\deploy.ps1 -Seed
# 檢查服務狀態
.\deploy.ps1 -Status
# 檢視日誌
.\deploy.ps1 -Logs
# 停止服務
.\deploy.ps1 -Stop
```
**Linux/macOS 用戶:**
```bash
# 賦予腳本執行權限
chmod +x deploy.sh
# 啟動服務
./deploy.sh
# 重新編譯並啟動
./deploy.sh --build
# 檢查服務狀態
./deploy.sh --status
# 檢視日誌
./deploy.sh --logs
# 停止服務
./deploy.sh --stop
```
#### 4. 存取應用程序
服務成功啟動後,您可以通过以下地址存取應用程序:
| 服務 | 地址 | 說明 |
|------|------|------|
| 前端介面 | http://localhost:8080 | 主要存取入口 |
| 後端 API | http://localhost:3001 | API 服務 |
| 數據庫 | localhost:3307 | MySQL 數據庫 |
### Docker 部署架構
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 前端 │ │ 後端 │ │ MySQL │
│ (Nginx) │◄───┤ (Express) │◄───┤ (資料庫) │
│ 網路通訊埠: 80 │ │ 網路通訊埠: 3001│ │ 網路通訊埠: 3306│
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 環境變數配置
此專案使用 `.env` 文件進行配置,為前端和後端提供分離的環境配置:
#### 後端環境變數 (.env)
```env
# 伺服器配置
PORT=3001
NODE_ENV=development
# JWT 配置
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# 資料庫配置
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# 上傳配置
UPLOAD_MAX_SIZE=50mb
# 圖片上傳策略 (local: 本地儲存空間, imagehost: 第三方圖片伺服r2: Cloudflare R2 儲存空間)
UPLOAD_STRATEGY=imagehost
# 本地儲存空間配置
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# 第三方圖片伺服配置
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# Cloudflare R2 儲存空間配置
R2_ACCESS_KEY_ID=your_r2_access_key_id
R2_SECRET_ACCESS_KEY=your_r2_secret_access_key
R2_ENDPOINT=https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME=your_bucket_name
R2_ACCOUNT_ID=your_account_id
R2_REGION=auto
# 選擇性:自定義域名 URL (如果已配置自定義域名)
R2_PUBLIC_URL=https://your-custom-domain.com
# 上傳策略local (本地儲存空間), imagehost (第三方圖片伺服), 或 r2 (Cloudflare R2 儲存空間)
UPLOAD_STRATEGY=local
# 本地儲存空間配置
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# 第三方圖片伺服配置
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
# API 配置
API_BASE_URL=http://localhost:3001
# CORS 配置
CORS_ORIGIN=http://localhost:5173
```
#### 前端環境變數 (.env)
```env
# API 基底 URL 配置
VITE_API_BASE_URL=http://localhost:3001/api
# 使用真實 API
VITE_USE_REAL_API=true
# 應用程式標題
VITE_APP_TITLE=Small Pear Graphic Community
```
#### Docker 環境變數說明
當使用 Docker 部署時,環境變數通過 `docker-compose.yml` 配置:
```env
# 資料庫配置 (Docker 環境)
DB_HOST=mysql
DB_USER=小石麗珠_user
DB_PASSWORD=123456
DB_NAME=小石麗珠
# JWT 配置
JWT_SECRET=小石麗珠_secret_key_2025_docker
JWT_EXPIRES_IN=7d
# 上傳配置
UPLOAD_MAX_SIZE=50mb
# 圖片上傳策略 (local: 本地存儲, imagehost: 第三方圖片存儲, r2: Cloudflare R2 存儲)
UPLOAD_STRATEGY=imagehost
# API 配置
API_BASE_URL=http://localhost:3001
```
### 常見命令
```bash
# 檢查服務狀態
docker-compose ps
# 查看服務日誌
docker-compose logs -f
# 重啟特定服務
docker-compose restart backend
# 遷入容器 (使用 sh 為了因為 alpine 鏡像通常沒有 bash)
docker-compose exec backend sh
# 或遷入 MySQL 客戶端
docker-compose exec mysql mysql -u root -p
# 備份資料庫
docker-compose exec mysql mysqldump -u root -p 小石麗珠 > backup.sql
# 恢復資料庫
docker-compose exec -T mysql mysql -u root -p 小石麗珠 < backup.sql
```
### 資料持久化
Docker 使用卷來在部署中進行資料持久化:
- `mysql_data`: MySQL 資料庫文件
- `backend_uploads`: 後端上傳文件
### 故障排除
#### 1. 頻道衝突
如果發生頻道衝突,您可以修改 `docker-compose.yml` 文件中的端口映射:
```yaml
services:
frontend:
ports:
- "8080:80" # 修改前端端口
backend:
ports:
- "3002:3001" # 修改後端端口
```
#### 2. 變動不夠
請確保系統有足夠的記憶體,您可以使用以下命令查看資源使用情況:
```bash
docker stats
```
#### 3. 資料庫連接失敗 / 載入數據
- 檢查資料庫服務是否正常啟動:
```bash
docker-compose logs mysql
```
- 載入範例數據 (Windows):
```powershell
.\deploy.ps1 -Seed
```
- 手動執行載入範例數據:
```bash
docker-compose exec -T backend node scripts/generate-data.js
```
#### 4. 文件上傳權限問題
**問題現象**:
- 從前端上傳文件時,返回 400 錯誤
- 後端日誌顯示: `EACCES: permission denied, open '/app/uploads/xxx.png'`
**原因分析**:
Docker 容器上傳目錄的權限問題。目錄屬於 root 用戶,但應用程式在 nodejs 用戶下運行。
**解決方案**:
1. **檢查上傳目錄的權限**:
```bash
docker-compose exec backend ls -la /app/uploads
```
2. **修復權限問題**:
```bash
# 使用 root 用戶修改目錄所有權限
docker-compose exec --user root backend chown -R nodejs:nodejs /app/uploads
```
3. **確認權限修復**:
```bash
# 確認目錄現在屬於 nodejs 用戶
docker-compose exec backend ls -la /app/uploads
```
**預防措施**:
- 確保 Dockerfile 中上傳目錄的權限設定正確
- 在容器啟動時自動修復權限問題
#### 5. 上傳策略配置
此專案支援三種檔案上傳策略:
**本地儲存模式**(推薦用於開發和小型部署):
```yaml
# 設定於 docker-compose.yml
環境變數:
UPLOAD_STRATEGY: local
```
**第三方圖片伺服器模式**(推薦用於生產環境):
```yaml
# 設定於 docker-compose.yml
環境變數:
UPLOAD_STRATEGY: imagehost
```
**Cloudflare R2 儲存模式**(推薦用於生產環境,支援 CDN 加速):
```yaml
# 設定於 docker-compose.yml
環境變數:
UPLOAD_STRATEGY: r2
R2_ACCESS_KEY_ID: your_r2_access_key_id
R2_SECRET_ACCESS_KEY: your_r2_secret_access_key
R2_ENDPOINT: https://your_account_id.r2.cloudflarestorage.com
R2_BUCKET_NAME: your_bucket_name
R2_ACCOUNT_ID: your_account_id
R2_REGION: auto
# 可選:自定義域名
R2_PUBLIC_URL: https://your-custom-domain.com
```
> **注意**:要使用 Cloudflare R2 儲存,您需要先在 Cloudflare 控制台中創建 R2 桶和獲取相對應的存取金鑰。
#### 6. 清理與重置
如果您遇到問題並需要從頭開始:
```bash
# Windows
.\deploy.ps1 -Clean
# Linux/macOS
./deploy.sh --clean
```
---
## 📋 傳統部署方法
## 系統需求
| 槽件 | 版本要求 | 描述 |
|------|----------|------|
| Node.js | >= 16.0.0 | 运行環境 |
| MySQL | >= 5.7 | 數據庫 |
| MariaDB | >= 10.3 | 數據庫(選擇性) |
| npm | >= 8.0.0 | 對象管理器 |
| yarn | >= 1.22.0 | 對象管理器(選擇性) |
| Browser | 支援 ES6+ | 現代瀏覽器 |
## 快速開始
### 1. 安裝依賴項
```bash
# 使用 cnpm
cnpm install
# 或使用 yarn
yarn install
```
### 2. 設定後端 API 地址
建立環境配置檔案(可選):
```bash
# 複製環境配置範本
cp .env.example .env
```
編輯 `.env` 檔案以設定後端 API 地址:
```env
# 後端 API 地址
VITE_API_BASE_URL=http://localhost:3001
# 其他設定...
```
### 3. 啟動開發伺服器
```bash
# 啟動開發伺服器
npm run dev
# 或使用 yarn
yarn dev
```
開發伺服器將在 `http://localhost:5173` 啟動。
### 4. 建立生產版本
```bash
# 建立生產版本
npm run build
# 預覽生產版本
npm run preview
```
## 後端服務配置
⚠️ **重要提醒**:前端專案需要與後端服務一起使用。
1. **啟動後端服務**
```bash
# 導航至後端專案目錄
cd ../express-project
# 安裝後端依賴
npm install
# 啟動後端服務
npm start
```
2. **後端服務地址**`http://localhost:3001`
3. **API 文件**:檢查後端專案中的 `API_DOCS.md` 文件。
## 開發環境配置
### 環境檢查
```bash
# 檢查 Node.js 版本
node --version
# 檢查 npm 版本
npm --version
### 開發伺服器
```bash
# 開啟開發伺服器(熱重載)
npm run dev
# 存取地址http://localhost:5173
```
### 代碼規範
- 使用 Vue 3 Composition API
- 遵循官方 Vue.js 風格指南
- 成分命名使用 PascalCase
- 檔名命名使用 kebab-case
## 配置檔說明
### 前端配置檔vue3-project 目錄)
| 檔名 | 描述 |
|------|-------------|
| `.env` | 環境變數配置檔 |
| `vite.config.js` | Vite 建置工具配置 |
| `package.json` | 專案依賴和腳本配置 |
| `jsconfig.json` | JavaScript 專案配置 |
### 後端配置檔express-project 目錄)
| 檔名 | 描述 |
|------|-------------|
| `config/config.js` | 主要配置檔 |
| `.env` | 環境變數配置檔 |
| `database_design.md` | 資料庫設計文件 |
| `scripts/init-database.js` | 資料庫初始化腳本 |
| `generate-data.js` | 測試資料生成腳本 |
## npm 腳本命令
### 前端腳本(在 vue3-project 目錄中執行)
| 命令 | 描述 |
|---------|-------------|
| `npm run dev` | 開啟開發伺服器 |
| `npm run build` | 建置生產版本 |
| `npm run preview` | 預覽生產版本 |
### 後端腳本(在 express-project 目錄中執行)
| 命令 | 描述 |
|---------|-------------|
| `npm start` | 開啟伺服器 |
| `npm run dev` | 開啟開發伺服器(熱重載) |
| `npm run init-db` | 初始化資料庫 |
| `npm run generate-data` | 生成測試資料 |
## 環境變數配置
### 前端環境變數vue3-project/.env
```env
# API 伺服器地址
VITE_API_BASE_URL=http://localhost:3001/api
# 其他前端配置
VITE_APP_TITLE=Small石榴Image and Text Community
VITE_USE_REAL_API=true
```
### 後端環境變數express-project/.env
```env
# 伺服器配置
NODE_ENV=development
PORT=3001
# JWT 配置
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
# 資料庫配置
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# API 配置
API_BASE_URL=http://localhost:3001
# 上傳配置
UPLOAD_MAX_SIZE=50mb
```
## 資料庫腳本說明
專案中相關的資料庫腳本都放在 `express-project/scripts/` 目錄中,以便於管理和使用:
### 腳本檔案介紹
#### 1. 資料庫初始化腳本
- **檔案位置**: `scripts/init-database.js`
- **功能**: 創建資料庫和所有表結構
- **使用方法**:
```bash
cd express-project
node scripts/init-database.js
- **描述**:必須執行首次部署,將自動建立 `xiaoshiliu` 資料庫及 12 個資料表
#### 2. 測試資料生成腳本
- **檔案位置**`scripts/generate-data.js`
- **功能**:生成模擬用戶、筆記、評論及其他測試資料
- **使用方法**
```bash
cd express-project
node scripts/generate-data.js
```
- **描述**:可選執行,用於快速填充測試資料,包括 50 個用戶、200 則筆記、800 則評論等。
#### 3. SQL 初始化檔案
- **檔案位置**`scripts/init-database.sql`
- **功能**:資料庫初始化腳本的純 SQL 版本
- **使用方法**:可直接在 MySQL 客戶端執行
- **描述**:與 `init-database.js` 有相同功能,提供 SQL 版本供參考
#### 4. 示範圖片更新腳本
- **檔案位置**`scripts/update-sample-images.js`
- **功能**:自動獲取最新圖片鏈接並更新資料庫中的示範圖片
- **使用方法**
```bash
cd express-project
node scripts/update-sample-images.js
```
- **描述**
- 自動從 Liziwen API 獲取最新圖片鏈接
- 更新 `imgLinks/avatar_link.txt`50 個頭像鏈接)
- 更新 `imgLinks/post_img_link.txt`300 則筆記圖片鏈接)
- 批量更新資料庫中的用戶頭像和筆記圖片
- 支援顯示更新前後圖片數量的統計數據
## 開發環境啟動流程
### 1. 啟動後端服務
```bash
# 開啟第一個終端,切換到後端目錄
cd express-project
# 安裝後端依賴(首次運行)
npm install
# 配置資料庫(首次運行)
# 編輯 config/config.js 或 .env 檔案
# 初始化資料庫(首次運行)
node scripts/init-database.js
# 生成測試資料(可選)
node scripts/generate-data.js
# 啟動後端服務
npm start
# 後端服務運行於 http://localhost:3001
```
### 2. 啟動前端服務
```bash
# 開啟第二個終端,切換到前端目錄
cd vue3-project
# 安裝前端依賴(首次運行)
npm install
# 配置 API 地址(可選)
# 編輯 .env 檔案,設定 VITE_API_BASE_URL
# 啟動前端開發服務器
npm run dev
# 前端服務運行於 http://localhost:5173
```
### 3. 適用服務
| 服務 | 地址 |
|------|------|
| 前端介面 | http://localhost:5173 |
| 後端 API | http://localhost:3001 |

View File

@@ -1,163 +0,0 @@
# Project Structure
This document provides a detailed overview of the directory structure and file organization of the XiaoShiLiu Image & Text Community project.
## Overall Structure
```
XiaoShiLiu Community/
├── vue3-project/ # Frontend project
├── express-project/ # Backend project
├── README.md # Main project documentation
├── DEPLOYMENT.md # Deployment guide
└── PROJECT_STRUCTURE.md # Project structure documentation (this document)
```
## Frontend Project Structure (vue3-project/)
```
vue3-project/
├── public/ # Static assets directory
│ └── logo.ico # Website favicon
├── src/ # Source code directory
│ ├── api/ # API interface encapsulation
│ ├── assets/ # Static assets (images, styles, etc.)
│ ├── components/ # Reusable components
│ ├── composables/ # Composable functions
│ ├── config/ # Configuration files
│ ├── directives/ # Custom directives
│ ├── router/ # Router configuration
│ ├── stores/ # Pinia state management
│ ├── utils/ # Utility functions
│ ├── views/ # Page components
│ ├── App.vue # Root component
│ └── main.js # Entry file
├── .env.example # Environment variables template
├── index.html # HTML template
├── package.json # Project configuration
├── vite.config.js # Vite configuration
└── README.md # Frontend project documentation
```
### Frontend Directory Details
| Directory/File | Description | Main Content |
|----------------|-------------|-------------|
| `public/` | Static assets directory | Website favicon, static files that don't need compilation |
| `src/api/` | API interface encapsulation | HTTP request wrappers, interface definitions |
| `src/assets/` | Static assets | Images, fonts, style files, etc. |
| `src/components/` | Reusable components | Reusable Vue components |
| `src/composables/` | Composable functions | Vue 3 Composition API logic reuse |
| `src/config/` | Configuration files | Application configuration, constant definitions |
| `src/directives/` | Custom directives | Vue custom directives |
| `src/router/` | Router configuration | Vue Router route definitions |
| `src/stores/` | State management | Pinia state management modules |
| `src/utils/` | Utility functions | Common utility functions, helper methods |
| `src/views/` | Page components | Page-level Vue components |
| `App.vue` | Root component | Application root component |
| `main.js` | Entry file | Application entry point |
| `vite.config.js` | Vite configuration | Build tool configuration |
## Backend Project Structure (express-project/)
```
express-project/
├── config/ # Configuration files directory
│ ├── config.js # Main configuration file
│ └── database.js # Database configuration
├── routes/ # Route files directory
│ ├── auth.js # Authentication routes
│ ├── users.js # User routes
│ ├── posts.js # Post routes
│ ├── comments.js # Comment routes
│ └── ... # Other route files
├── middleware/ # Middleware directory
│ ├── auth.js # Authentication middleware
│ └── crudFactory.js # CRUD factory
├── utils/ # Utility functions directory
├── scripts/ # Script files directory
│ ├── init-database.js # Database initialization script
│ ├── init-database.sql # SQL initialization script
│ ├── generate-data.js # Test data generation script
│ └── update-sample-images.js # Sample image update script
├── app.js # Application entry file
├── package.json # Project configuration
└── .env.example # Environment variables template
```
### Backend Directory Details
| Directory/File | Description | Main Content |
|----------------|-------------|-------------|
| `config/` | Configuration files directory | Application configuration, database configuration |
| `routes/` | Route files directory | Express route definitions, API endpoints |
| `middleware/` | Middleware directory | Express middleware, authentication logic |
| `utils/` | Utility functions directory | Common utility functions, helper methods |
| `scripts/` | Script files directory | Database initialization, data generation scripts |
| `app.js` | Application entry file | Express application entry point |
### Route Files Description
| Route File | Function | Main Endpoints |
|------------|----------|----------------|
| `auth.js` | User authentication | Login, registration, token validation |
| `users.js` | User management | User information CRUD, follow relationships |
| `posts.js` | Post management | Post publishing, editing, deletion, querying |
| `comments.js` | Comment management | Comment publishing, deletion, querying |
### Script Files Description
| Script File | Function | Use Case |
|-------------|----------|----------|
| `init-database.js` | Database initialization | Create database structure on first deployment |
| `init-database.sql` | SQL initialization script | Execute directly in MySQL client |
| `generate-data.js` | Test data generation | Fill test data in development environment |
| `update-sample-images.js` | Image link update | Update sample image resources |
## Technical Architecture
### Frontend Architecture
```
┌─────────────────────────────────────┐
│ Vue 3 App │
├─────────────────────────────────────┤
│ Views (Pages) │ Components │
├─────────────────────────────────────┤
│ Router │ Stores (State) │
├─────────────────────────────────────┤
│ API │ Utils │
├─────────────────────────────────────┤
│ Vite (Build Tool) │
└─────────────────────────────────────┘
```
### Backend Architecture
```
┌─────────────────────────────────────┐
│ Express Server │
├─────────────────────────────────────┤
│ Routes │ Middleware │
├─────────────────────────────────────┤
│ Config │ Utils │
├─────────────────────────────────────┤
│ MySQL Database │
└─────────────────────────────────────┘
```
## Data Flow
```
Frontend Vue App
↓ HTTP Request
Express Routes
↓ Data Processing
Middleware Validation
↓ Database Operations
MySQL Database
↓ Return Data
Frontend State Update
↓ View Rendering
User Interface Display
```

View File

@@ -1,163 +0,0 @@
# 項目結構
本文檔詳細介紹了卜卜圖文社區項目的目錄結構和文件組織。
## 總體結構
```
卜卜圖文社區/
├── vue3-project/ # 前端項目
├── express-project/ # 後端項目
├── README.md # 項目主文檔
├── DEPLOYMENT.md # 部署指南
└── PROJECT_STRUCTURE.md # 項目結構說明(本文檔)
```
## 前端項目結構vue3-project/
```
vue3-project/
├── public/ # 靜態資源目錄
│ └── logo.ico # 網站圖示
├── src/ # 原始碼目錄
│ ├── api/ # API接口封裝
│ ├── assets/ # 靜態資源(圖片、樣式等)
│ ├── components/ # 公共元件
│ ├── composables/ # 組合式函數
│ ├── config/ # 配置文件
│ ├── directives/ # 自訂指令
│ ├── router/ # 路由配置
│ ├── stores/ # Pinia狀態管理
│ ├── utils/ # 工具函數
│ ├── views/ # 頁面元件
│ ├── App.vue # 根元件
│ └── main.js # 入口文件
├── .env.example # 環境變數範本
├── index.html # HTML範本
├── package.json # 項目配置
├── vite.config.js # Vite配置
└── README.md # 前端項目說明
```
### 前端目錄詳細說明
| 目錄/文件 | 說明 | 主要內容 |
|-----------|------|----------|
| `public/` | 靜態資源目錄 | 網站圖示、不需要編譯的靜態文件 |
| `src/api/` | API接口封裝 | HTTP請求封裝、接口定義 |
| `src/assets/` | 靜態資源 | 圖片、字型、樣式文件等 |
| `src/components/` | 公共元件 | 可複用的Vue元件 |
| `src/composables/` | 組合式函數 | Vue 3 Composition API邏輯複用 |
| `src/config/` | 配置文件 | 應用程式配置、常數定義 |
| `src/directives/` | 自訂指令 | Vue自訂指令 |
| `src/router/` | 路由配置 | Vue Router路由定義 |
| `src/stores/` | 狀態管理 | Pinia狀態管理模組 |
| `src/utils/` | 工具函數 | 通用工具函數、輔助方法 |
| `src/views/` | 頁面元件 | 頁面級Vue元件 |
| `App.vue` | 根元件 | 應用程式根元件 |
| `main.js` | 入口文件 | 應用程式入口點 |
| `vite.config.js` | Vite配置 | 建置工具配置 |
## 後端項目結構express-project/
```
express-project/
├── config/ # 配置文件目錄
│ ├── config.js # 主配置文件
│ └── database.js # 資料庫配置
├── routes/ # 路由文件目錄
│ ├── auth.js # 認證路由
│ ├── users.js # 使用者路由
│ ├── posts.js # 貼文路由
│ ├── comments.js # 評論路由
│ └── ... # 其他路由文件
├── middleware/ # 中介軟體目錄
│ ├── auth.js # 認證中介軟體
│ └── crudFactory.js # CRUD工廠
├── utils/ # 工具函數目錄
├── scripts/ # 腳本文件目錄
│ ├── init-database.js # 資料庫初始化腳本
│ ├── init-database.sql # SQL初始化腳本
│ ├── generate-data.js # 測試資料產生腳本
│ └── update-sample-images.js # 範例圖片更新腳本
├── app.js # 應用程式入口文件
├── package.json # 項目配置
└── .env.example # 環境變數範本
```
### 後端目錄詳細說明
| 目錄/文件 | 說明 | 主要內容 |
|-----------|------|----------|
| `config/` | 配置文件目錄 | 應用程式配置、資料庫配置 |
| `routes/` | 路由文件目錄 | Express路由定義、API端點 |
| `middleware/` | 中介軟體目錄 | Express中介軟體、認證邏輯 |
| `utils/` | 工具函數目錄 | 通用工具函數、輔助方法 |
| `scripts/` | 腳本文件目錄 | 資料庫初始化、資料產生腳本 |
| `app.js` | 應用程式入口文件 | Express應用程式入口 |
### 路由文件說明
| 路由文件 | 功能 | 主要端點 |
|----------|------|----------|
| `auth.js` | 使用者認證 | 登入、註冊、token驗證 |
| `users.js` | 使用者管理 | 使用者信息CRUD、關注關係 |
| `posts.js` | 貼文管理 | 貼文發布、編輯、刪除、查詢 |
| `comments.js` | 評論管理 | 評論發布、刪除、查詢 |
### 腳本文件說明
| 腳本文件 | 功能 | 使用場景 |
|----------|------|----------|
| `init-database.js` | 資料庫初始化 | 首次部署時建立資料庫結構 |
| `init-database.sql` | SQL初始化腳本 | 直接在MySQL客戶端執行 |
| `generate-data.js` | 測試資料產生 | 開發環境填充測試資料 |
| `update-sample-images.js` | 圖片連結更新 | 更新範例圖片資源 |
## 技術架構
### 前端架構
```
┌─────────────────────────────────────┐
│ Vue 3 App │
├─────────────────────────────────────┤
│ Views (頁面) │ Components (元件) │
├─────────────────────────────────────┤
│ Router (路由) │ Stores (狀態管理) │
├─────────────────────────────────────┤
│ API (接口) │ Utils (工具) │
├─────────────────────────────────────┤
│ Vite (建置工具) │
└─────────────────────────────────────┘
```
### 後端架構
```
┌─────────────────────────────────────┐
│ Express Server │
├─────────────────────────────────────┤
│ Routes (路由) │ Middleware (中介軟體) │
├─────────────────────────────────────┤
│ Config (配置) │ Utils (工具) │
├─────────────────────────────────────┤
│ MySQL Database │
└─────────────────────────────────────┘
```
## 資料流向
```
前端 Vue App
↓ HTTP請求
Express 路由
↓ 資料處理
中介軟體驗證
↓ 資料庫操作
MySQL 資料庫
↓ 返回資料
前端狀態更新
↓ 視圖渲染
使用者界面展示
```

View File

@@ -1,273 +0,0 @@
<p align="center">
<img alt="logo" src="../imgs/卜卜.png" width="100" />
</p>
<h1 align="center" style="margin: 20px 30px 0px 30px; font-weight: bold;">XiaoShiLiu</h1>
---
<p align="center">
<b>Express + Vue Separation of Frontend and Backend Xiaohongshu Clone Project</b>
</p>
<p align="center">
<i>A high-fidelity Xiaohongshu-style graphic community project supporting core features like graphic posting and social interaction, designed to provide a complete frontend-to-backend practice template</i>
<p align="center"><a href="https://www.shiliu.space">Demo Site</a> · <a href="https://www.bilibili.com/video/BV1J4agztEBX/?spm_id_from=333.1387.homepage.video_card.click">Video Introduction</a>
</p>
<p align="center"><a href="https://github.com/ZTMYO/XiaoShiLiu">简体中文</a>|<a href="README_En.md">English</a>|<a href="README_zh-Hant.md">繁體中文</a>
<p align="center">
<a href="https://github.com/ZTMYO/XiaoShiLiu/stargazers">
<img src="https://img.shields.io/github/stars/ZTMYO/XiaoShiLiu?style=flat&logo=github&color=brightgreen&label=Stars">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/network/members">
<img src="https://img.shields.io/github/forks/ZTMYO/XiaoShiLiu?style=round-square&color=brightgreen&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiBmaWxsPSJub25lIj4KPHBhdGggZmlsbD0id2hpdGUiIGQ9Ik01IDUuMzcydi44NzhjMCAuNDE0LjMzNi43NS43NS43NWg0LjVhLjc1Ljc1IDAgMCAwIC43NS0uNzV2LS44NzhhMi4yNSAyLjI1IDAgMSAxIDEuNSAwdi44NzhhMi4yNSAyLjI1IDAgMCAxLTIuMjUgMi4yNWgtMS41djIuMTI4YTIuMjUxIDIuMjUxIDAgMSAxLTEuNSAwVjguNWgtMS41QTIuMjUgMi4yNSAwIDAgMSAzLjUgNi4yNXYtLjg3OGEyLjI1IDIuMjUgMCAxIDEgMS41IDBaTTUgMy4yNWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWm02Ljc1Ljc1YS43NS43NSAwIDEgMCAwLTEuNS43NS43NSAwIDAgMCAwIDEuNVptLTMgOC43NWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWiI+PC9wYXRoPgo8L3N2Zz4=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu">
<img src="https://img.shields.io/badge/XiaoShiLiu-v1.2.0-brightgreen.svg?logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIj4KPHBhdGggZD0iTTAgMCBDNC4yMzMwMTEyMSAyLjgyMjAwNzQ3IDcuMTcxNTk2NjQgNS45NTIyODk5MiA4LjgxMjUgMTAuODc1IEM5LjE4MDc2MjI0IDE2LjQ5MDk5OTE2IDkuMDI4MDYwMDcgMjAuMDUxNjU5ODkgNS44MTI1IDI0Ljg3NSBDMS44ODAxNjE5MSAyOC44NTAzMTQ0NiAtMS4zMzIwOTg0OSAzMC43NTMzMzQzMyAtNyAzMS4xMjUgQy0xMS43MTg5MjIyMyAzMS4wMzg1NzI4NSAtMTUuMjAxOTI2NjkgMjkuODM5MTA3NjUgLTE4LjYzMjgxMjUgMjYuNDQ1MzEyNSBDLTIyLjQ1Nzc0Mjg2IDIyLjA1MjEwNjc3IC0yMy41MDQ5MDc2NCAxOC43NDI5NTY4OSAtMjMuMzk4NDM3NSAxMi45Mjk2ODc1IEMtMjIuOTEyNTgwNTggOC4xOTcwODExNiAtMjAuNjcwMDc0MTQgNS4wOTQ1OTE5MSAtMTcuMTg3NSAyLjA2MjUgQy0xMS43NzQzMTUyMyAtMS44ODQ2MTM5IC02LjE5MjU0NDY4IC0yLjE4NTYwNDAxIDAgMCBaIE0tNy4xODc1IDQuODc1IEMtOC4xNzc1IDUuNTM1IC05LjE2NzUgNi4xOTUgLTEwLjE4NzUgNi44NzUgQy0xMC4xODc1IDcuNTM1IC0xMC4xODc1IDguMTk1IC0xMC4xODc1IDguODc1IEMtMTAuODA2MjUgOS4xNDMxMjUgLTExLjQyNSA5LjQxMTI1IC0xMi4wNjI1IDkuNjg3NSBDLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE2LjE4NzUgMTMuODc1IEMtMTYuNTc3NjM3MTYgMTUuODY0Njk5NSAtMTYuOTE5NTI2NDkgMTcuODY1MTk4NjkgLTE3LjE4NzUgMTkuODc1IEMtMTYuMTk3NSAyMC4zNyAtMTYuMTk3NSAyMC4zNyAtMTUuMTg3NSAyMC44NzUgQy0xNC40NjU5MDU3NiAyMi41MTg2MzEzNCAtMTMuNzkzOTg1NzkgMjQuMTg1NTAzODYgLTEzLjE4NzUgMjUuODc1IEMtMTIuNTI3NSAyNS44NzUgLTExLjg2NzUgMjUuODc1IC0xMS4xODc1IDI1Ljg3NSBDLTEwLjg1NzUgMjYuODY1IC0xMC41Mjc1IDI3Ljg1NSAtMTAuMTg3NSAyOC44NzUgQy05LjUyNzUgMjcuODg1IC04Ljg2NzUgMjYuODk1IC04LjE4NzUgMjUuODc1IEMtNi44Njc1IDI1Ljg3NSAtNS41NDc1IDI1Ljg3NSAtNC4xODc1IDI1Ljg3NSBDLTMuODU3NSAyNi44NjUgLTMuNTI3NSAyNy44NTUgLTMuMTg3NSAyOC44NzUgQy0zLjE4NzUgMjcuODg1IC0zLjE4NzUgMjYuODk1IC0zLjE4NzUgMjUuODc1IEMtMi4xOTc1IDI1LjU0NSAtMS4yMDc1IDI1LjIxNSAtMC4xODc1IDI0Ljg3NSBDMC40MDMyMDAxNCAyMi45Mjg5NjcyNiAwLjQwMzIwMDE0IDIyLjkyODk2NzI2IDAuODEyNSAyMC44NzUgQzEuNDcyNSAyMC4yMTUgMi4xMzI1IDE5LjU1NSAyLjgxMjUgMTguODc1IEMxLjU3OTU5MDMxIDEzLjExMDE4NTAyIDEuNTc5NTkwMzEgMTMuMTEwMTg1MDIgLTIuMTg3NSA4Ljg3NSBDLTIuODQ3NSA4Ljg3NSAtMy41MDc1IDguODc1IC00LjE4NzUgOC44NzUgQy00LjE4NzUgNy44ODUgLTQuMTg3NSA2Ljg5NSAtNC4xODc1IDUuODc1IEMtNS4xNzc1IDUuNTQ1IC02LjE2NzUgNS4yMTUgLTcuMTg3NSA0Ljg3NSBaIE0tMTguMTg3NSAxOS44NzUgQy0xOC4xODc1IDIyLjg3NSAtMTguMTg3NSAyMi44NzUgLTE4LjE4NzUgMjIuODc1IFogTTIuODEyNSAxOS44NzUgQzMuMTQyNSAyMC44NjUgMy40NzI1IDIxLjg1NSAzLjgxMjUgMjIuODc1IEMzLjgxMjUgMjEuODg1IDMuODEyNSAyMC44OTUgMy44MTI1IDE5Ljg3NSBDMy40ODI1IDE5Ljg3NSAzLjE1MjUgMTkuODc1IDIuODEyNSAxOS44NzUgWiAiIGZpbGw9IiNGQ0ZDRkMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzLjE4NzUsMS4xMjUpIi8+CjxwYXRoIGQ9Ik0wIDAgQzIuMDYyNSAwLjQzNzUgMi4wNjI1IDAuNDM3NSA0IDEgQzQgMS45OSA0IDIuOTggNCA0IEM0Ljk5IDQuMzMgNS45OCA0LjY2IDcgNSBDMy43ODU0ODczMSA2LjYwNzI1NjM1IDAuNTYzODc0NjQgNi4wNTc0ODE4NSAtMyA2IEMtMS4xMjUgMS4xMjUgLTEuMTI1IDEuMTI1IDAgMCBaICIgZmlsbD0iI0U5RTlFOSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTUsMjYpIi8+Cjwvc3ZnPgo=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/ZTMYO/XiaoShiLiu?color=8ebc06">
</a>
</p>
<p align="center">
<img src="https://img.shields.io/static/v1?message=Vue&color=4f4f4f&logo=Vue.js&logoColor=4FC08D&label=">
<img
src="https://img.shields.io/static/v1?&message=JavaScript&color=4f4f4f&logo=JavaScript&logoColor=F7DF1E&label=">
</a>
</p>
> **Disclaimer**
> This project is licensed under the [GPLv3 License](./LICENSE), free and open-source, for learning and communication purposes only. Resale is prohibited; please beware of scams. For commercial use, retain copyright information to ensure legal compliance. Operational risks shall be borne by the user, and the author is not liable.
---
> 📁 **Project Structure Explanation**: This project contains complete frontend and backend code. The frontend is located in the `vue3-project/` directory, and the backend is in the `express-project/` directory. For detailed structure, please refer to the [Project Structure Document](PROJECT_STRUCTURE_En.md).
## Project Demonstration
### PC Interface
<table>
<tr>
<td><img src="../imgs/1.png" alt="PC Interface 1" width="300"/></td>
<td><img src="../imgs/2.png" alt="PC Interface 2" width="300"/></td>
<td><img src="../imgs/3.png" alt="PC Interface 3" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/4.png" alt="PC Interface 4" width="300"/></td>
<td><img src="../imgs/5.png" alt="PC Interface 5" width="300"/></td>
<td><img src="../imgs/6.png" alt="PC Interface 6" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/7.png" alt="PC Interface 7" width="300"/></td>
<td><img src="../imgs/8.png" alt="PC Interface 8" width="300"/></td>
<td><img src="../imgs/9.png" alt="PC Interface 9" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/10.png" alt="PC Interface 10" width="300"/></td>
<td><img src="../imgs/11.png" alt="PC Interface 11" width="300"/></td>
<td><img src="../imgs/12.png" alt="PC Interface 12" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/13.png" alt="PC Interface 13" width="300"/></td>
<td><img src="../imgs/14.png" alt="PC Interface 14" width="300"/></td>
<td><img src="../imgs/15.png" alt="PC Interface 15" width="300"/></td>
</tr>
</tr>
<tr>
<td><img src="./doc/imgs/16.png" alt="PC端界面16" width="300"/></td>
<td><img src="./doc/imgs/17.png" alt="PC端界面17" width="300"/></td>
<td><img src="./doc/imgs/18.png" alt="PC端界面18" width="300"/></td>
</tr>
</table>
### Mobile Interface
<table>
<tr>
<td><img src="../imgs/m1.png" alt="Mobile Interface 1" width="200"/></td>
<td><img src="../imgs/m2.png" alt="Mobile Interface 2" width="200"/></td>
<td><img src="../imgs/m3.png" alt="Mobile Interface 3" width="200"/></td>
<td><img src="../imgs/m4.png" alt="Mobile Interface 4" width="200"/></td>
</tr>
<tr>
<td><img src="../imgs/m5.png" alt="Mobile Interface 5" width="200"/></td>
<td><img src="../imgs/m6.png" alt="Mobile Interface 6" width="200"/></td>
<td><img src="../imgs/m7.png" alt="Mobile Interface 7" width="200"/></td>
<td><img src="../imgs/m8.png" alt="Mobile Interface 8" width="200"/></td>
</tr>
<tr>
<td><img src="../imgs/m9.png" alt="Mobile Interface 9" width="200"/></td>
<td><img src="../imgs/m10.png" alt="Mobile Interface 10" width="200"/></td>
<td><img src="../imgs/m11.png" alt="Mobile Interface 11" width="200"/></td>
<td><img src="../imgs/m12.png" alt="Mobile Interface 12" width="200"/></td>
</tr>
</table>
## Project Documents
| Document | Description |
|----------|-------------|
| [Deployment Guide](DEPLOYMENT_En.md) | Deployment configuration and environment setup instructions |
| [Project Structure](PROJECT_STRUCTURE_En.md) | Project directory structure and architecture explanation |
| [Database Design](DATABASE_DESIGN_En.md) | Database table structure design document |
| [API Docs](API_DOCS_En.md) | Backend API interface description and examples |
## Project Highlights
- **Engineering Practice**: Complete workflow of environment configuration, code standards, building, and product optimization
- **Business Capabilities**: Authentication flow, route guards, state management, and interface encapsulation
- **Experience Optimization**: Skeleton screens, lazy loading, preloading, accessibility, and responsive adaptation
- **Component & Layering**: Reusable component splitting, domain-based grouping, and alias introduction
- **Backend Management**: Basic CRUD, data management, configuration panel, supporting subsequent permission and statistics expansion
- **Quick Deployment**: Docker-based one-click deployment solution, supporting multi-environment configuration and automated deployment
## Technology Stack
> 💡 Click to expand for details
<details>
<summary><b>Frontend Technology</b></summary>
- **Vue.js 3** - Frontend framework (Composition API)
- **Vue Router 4** - Routing management
- **Pinia** - State management
- **Vite** - Build tool and development server
- **Axios** - HTTP client
- **VueUse** - Vue composable utility library
- **CropperJS** - Image cropping tool
- **Vue3 Emoji Picker** - Emoji selector
- **svg-captcha** - CAPTCHA generator
</details>
<details>
<summary><b>Backend Technology</b></summary>
- **Node.js** - Runtime environment
- **Express.js** - Web framework
- **MySQL** - Database
- **JWT** - Identity authentication
- **Multer** - File upload handling
- **bcrypt** - Password encryption
- **CORS** - Cross-origin resource sharing
</details>
## Third-Party APIs
- **Image Storage**: Sample images are from [Liciyuan Image Hosting](https://t.alcy.cc/), providing stable image storage service
- **Image Upload**: User-uploaded images use [Xiarou API](https://api.aa1.cn/doc/xinyew_jdtc.html) to ensure stability and speed
- **IP Location Query**: IP location service uses [Baoluo API](https://api.pearktrue.cn/dashboard/detail/290) for accurate IP positioning
## Environment Requirements
| Component | Version Requirement |
|-----------|---------------------|
| Node.js | >= 16.0.0 |
| MySQL | >= 5.7 |
| MariaDB | >= 10.3 |
| npm | >= 8.0.0 |
| yarn | >= 1.22.0 |
| Browser | ES6+ supported |
> Note: The above are the minimum version requirements for traditional local development. For Docker deployment, the default image versions are as follows: MySQL 8.0, Node 18-alpine (frontend/backend build/run), Nginx alpine; Docker >= 20, Docker Compose >= 2. See [Deployment Guide](DEPLOYMENT_En.md) for details.
## Environment Configuration
The project uses environment variables for configuration management, with separate `.env` files for frontend and backend:
### Backend Configuration (express-project/.env)
```env
# Server configuration
PORT=3001
NODE_ENV=development
# Database configuration
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# JWT configuration
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
# Upload configuration
UPLOAD_MAX_SIZE=50mb
# Image upload strategy (local: local storage, imagehost: third-party image hosting)
UPLOAD_STRATEGY=imagehost
# Local storage configuration
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# Third-party image hosting configuration
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
```
### Frontend Configuration (vue3-project/.env)
```env
# API base URL configuration
VITE_API_BASE_URL=http://localhost:3001/api
# Application configuration
VITE_USE_REAL_API=true
VITE_APP_TITLE=XiaoShiLiu Image-Text Community
```
> 💡 **Configuration Notes**:
> - Backend supports both local storage and third-party image hosting upload strategies
> - Frontend uses Vite environment variables, variable names must start with `VITE_`
> - For detailed configuration instructions, please refer to the [Deployment Guide](DEPLOYMENT_En.md)
### 1. Install Dependencies
```bash
# Using cnpm or npm
cnpm install
# Or using yarn
yarn install
```
### 2. Start Development Server
```bash
# Start development server
npm run dev
# Or using yarn
yarn dev
```
The development server will start at `http://localhost:5173`
### 3. Build Production Version
```bash
# Build production version
npm run build
# Preview production version
npm run preview
```
> ⚠️ **Important Reminder**: The frontend project needs to work with the backend service. For detailed configuration, please refer to the [Deployment Guide](DEPLOYMENT_En.md)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=ZTMYO/XiaoShiLiu&type=Date)](https://www.star-history.com/#ZTMYO/XiaoShiLiu&Date)
---
<div align="center">
Copyright © 2025 - **XiaoShiLiu**\
By ZTMYO\
Made with ❤️ & ⌨️
</div>

View File

@@ -1,274 +0,0 @@
<p align="center">
<img alt="logo" src="../imgs/卜卜.png" width="100" />
</p>
<h1 align="center" style="margin: 20px 30px 0px 30px; font-weight: bold;">XiaoShiLiu</h1>
---
<p align="center">
<b>基於 Express + Vue 前後端分離仿小紅書項目</b>
</p>
<p align="center">
<i>一個高仿小紅書的圖文社群項目,支援圖文發布、社交互動等核心功能,旨在提供從前端到後端的完整實踐範本</i>
<p align="center"><a href="https://www.shiliu.space">演示網站</a> · <a href="https://www.bilibili.com/video/BV1J4agztEBX/?spm_id_from=333.1387.homepage.video_card.click">影片介紹</a>
</p>
<p align="center"><a href="https://github.com/ZTMYO/XiaoShiLiu">簡體中文</a>|<a href="README_En.md">English</a>|<a href="./i18n/README_zh-Hant.md">繁體中文</a>
</p>
<p align="center">
<a href="https://github.com/ZTMYO/XiaoShiLiu/stargazers">
<img src="https://img.shields.io/github/stars/ZTMYO/XiaoShiLiu?style=flat&logo=github&color=brightgreen&label=Stars">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/network/members">
<img src="https://img.shields.io/github/forks/ZTMYO/XiaoShiLiu?style=round-square&color=brightgreen&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiBmaWxsPSJub25lIj4KPHBhdGggZmlsbD0id2hpdGUiIGQ9Ik01IDUuMzcydi44NzhjMCAuNDE0LjMzNi43NS43NS43NWg0LjVhLjc1Ljc1IDAgMCAwIC43NS0uNzV2LS44NzhhMi4yNSAyLjI1IDAgMSAxIDEuNSAwdi44NzhhMi4yNSAyLjI1IDAgMCAxLTIuMjUgMi4yNWgtMS41djIuMTI4YTIuMjUxIDIuMjUxIDAgMSAxLTEuNSAwVjguNWgtMS41QTIuMjUgMi4yNSAwIDAgMSAzLjUgNi4yNXYtLjg3OGEyLjI1IDIuMjUgMCAxIDEgMS41IDBaTTUgMy4yNWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWm02Ljc1Ljc1YS43NS43NSAwIDEgMCAwLTEuNS43NS43NSAwIDAgMCAwIDEuNVptLTMgOC43NWEuNzUuNzUgMCAxIDAtMS41IDAgLjc1Ljc1IDAgMCAwIDEuNSAwWiI+PC9wYXRoPgo8L3N2Zz4=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu">
<img src="https://img.shields.io/badge/XiaoShiLiu-v1.2.0-brightgreen.svg?logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIj4KPHBhdGggZD0iTTAgMCBDNC4yMzMwMTEyMSAyLjgyMjAwNzQ3IDcuMTcxNTk2NjQgNS45NTIyODk5MiA4LjgxMjUgMTAuODc1IEM5LjE4MDc2MjI0IDE2LjQ5MDk5OTE2IDkuMDI4MDYwMDcgMjAuMDUxNjU5ODkgNS44MTI1IDI0Ljg3NSBDMS44ODAxNjE5MSAyOC44NTAzMTQ0NiAtMS4zMzIwOTg0OSAzMC43NTMzMzQzMyAtNyAzMS4xMjUgQy0xMS43MTg5MjIyMyAzMS4wMzg1NzI4NSAtMTUuMjAxOTI2NjkgMjkuODM5MTA3NjUgLTE4LjYzMjgxMjUgMjYuNDQ1MzEyNSBDLTIyLjQ1Nzc0Mjg2IDIyLjA1MjEwNjc3IC0yMy41MDQ5MDc2NCAxOC43NDI5NTY4OSAtMjMuMzk4NDM3NSAxMi45Mjk2ODc1IEMtMjIuOTEyNTgwNTggOC4xOTcwODExNiAtMjAuNjcwMDc0MTQgNS4wOTQ1OTE5MSAtMTcuMTg3NSAyLjA2MjUgQy0xMS43NzQzMTUyMyAtMS44ODQ2MTM5IC02LjE5MjU0NDY4IC0yLjE4NTYwNDAxIDAgMCBaIE0tNy4xODc1IDQuODc1IEMtOC4xNzc1IDUuNTM1IC05LjE2NzUgNi4xOTUgLTEwLjE4NzUgNi44NzUgQy0xMC4xODc1IDcuNTM1IC0xMC4xODc1IDguMTk1IC0xMC4xODc1IDguODc1IEMtMTAuODA2MjUgOS4xNDMxMjUgLTExLjQyNSA5LjQxMTI1IC0xMi4wNjI1IDkuNjg3NSBDLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE0LjQ4NzAyMzMgMTAuODMwNTY4NDggLTE2LjE4NzUgMTMuODc1IEMtMTYuNTc3NjM3MTYgMTUuODY0Njk5NSAtMTYuOTE5NTI2NDkgMTcuODY1MTk4NjkgLTE3LjE4NzUgMTkuODc1IEMtMTYuMTk3NSAyMC4zNyAtMTYuMTk3NSAyMC4zNyAtMTUuMTg3NSAyMC44NzUgQy0xNC40NjU5MDU3NiAyMi41MTg2MzEzNCAtMTMuNzkzOTg1NzkgMjQuMTg1NTAzODYgLTEzLjE4NzUgMjUuODc1IEMtMTIuNTI3NSAyNS44NzUgLTExLjg2NzUgMjUuODc1IC0xMS4xODc1IDI1Ljg3NSBDLTEwLjg1NzUgMjYuODY1IC0xMC41Mjc1IDI3Ljg1NSAtMTAuMTg3NSAyOC44NzUgQy05LjUyNzUgMjcuODg1IC04Ljg2NzUgMjYuODk1IC04LjE4NzUgMjUuODc1IEMtNi44Njc1IDI1Ljg3NSAtNS41NDc1IDI1Ljg3NSAtNC4xODc1IDI1Ljg3NSBDLTMuODU3NSAyNi44NjUgLTMuNTI3NSAyNy44NTUgLTMuMTg3NSAyOC44NzUgQy0zLjE4NzUgMjcuODg1IC0zLjE4NzUgMjYuODk1IC0zLjE4NzUgMjUuODc1IEMtMi4xOTc1IDI1LjU0NSAtMS4yMDc1IDI1LjIxNSAtMC4xODc1IDI0Ljg3NSBDMC40MDMyMDAxNCAyMi45Mjg5NjcyNiAwLjQwMzIwMDE0IDIyLjkyODk2NzI2IDAuODEyNSAyMC44NzUgQzEuNDcyNSAyMC4yMTUgMi4xMzI1IDE5LjU1NSAyLjgxMjUgMTguODc1IEMxLjU3OTU5MDMxIDEzLjExMDE4NTAyIDEuNTc5NTkwMzEgMTMuMTEwMTg1MDIgLTIuMTg3NSA4Ljg3NSBDLTIuODQ3NSA4Ljg3NSAtMy41MDc1IDguODc1IC00LjE4NzUgOC44NzUgQy00LjE4NzUgNy44ODUgLTQuMTg3NSA2Ljg5NSAtNC4xODc1IDUuODc1IEMtNS4xNzc1IDUuNTQ1IC02LjE2NzUgNS4yMTUgLTcuMTg3NSA0Ljg3NSBaIE0tMTguMTg3NSAxOS44NzUgQy0xOC4xODc1IDIyLjg3NSAtMTguMTg3NSAyMi44NzUgLTE4LjE4NzUgMjIuODc1IFogTTIuODEyNSAxOS44NzUgQzMuMTQyNSAyMC44NjUgMy40NzI1IDIxLjg1NSAzLjgxMjUgMjIuODc1IEMzLjgxMjUgMjEuODg1IDMuODEyNSAyMC44OTUgMy44MTI1IDE5Ljg3NSBDMy40ODI1IDE5Ljg3NSAzLjE1MjUgMTkuODc1IDIuODEyNSAxOS44NzUgWiAiIGZpbGw9IiNGQ0ZDRkMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzLjE4NzUsMS4xMjUpIi8+CjxwYXRoIGQ9Ik0wIDAgQzIuMDYyNSAwLjQzNzUgMi4wNjI1IDAuNDM3NSA0IDEgQzQgMS45OSA0IDIuOTggNCA0IEM0Ljk5IDQuMzMgNS45OCA0LjY2IDcgNSBDMy43ODU0ODczMSA2LjYwNzI1NjM1IDAuNTYzODc0NjQgNi4wNTc0ODE4NSAtMyA2IEMtMS4xMjUgMS4xMjUgLTEuMTI1IDEuMTI1IDAgMCBaICIgZmlsbD0iI0U5RTlFOSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTUsMjYpIi8+Cjwvc3ZnPgo=">
</a>
<a href="https://github.com/ZTMYO/XiaoShiLiu/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/ZTMYO/XiaoShiLiu?color=8ebc06">
</a>
</p>
<p align="center">
<img src="https://img.shields.io/static/v1?message=Vue&color=4f4f4f&logo=Vue.js&logoColor=4FC08D&label=">
<img
src="https://img.shields.io/static/v1?&message=JavaScript&color=4f4f4f&logo=JavaScript&logoColor=F7DF1E&label=">
</a>
</p>
> **聲明**
> 本項目基於 [GPLv3 協議](./LICENSE),免費開源,僅供學習交流,禁止轉賣,謹防受騙。如需商用請保留版權信息,確保合法合規使用,運營風險自負,與作者無關。
---
> 📁 **項目結構說明**:本項目包含完整的前後端程式碼,前端位於 `vue3-project/` 目錄,後端位於 `express-project/` 目錄。詳細結構請查看 [項目結構文件](PROJECT_STRUCTURE_zh-Hant.md)。
## 項目展示
### PC端界面
<table>
<tr>
<td><img src="../imgs/1.png" alt="PC端界面1" width="300"/></td>
<td><img src="../imgs/2.png" alt="PC端界面2" width="300"/></td>
<td><img src="../imgs/3.png" alt="PC端界面3" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/4.png" alt="PC端界面4" width="300"/></td>
<td><img src="../imgs/5.png" alt="PC端界面5" width="300"/></td>
<td><img src="../imgs/6.png" alt="PC端界面6" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/7.png" alt="PC端界面7" width="300"/></td>
<td><img src="../imgs/8.png" alt="PC端界面8" width="300"/></td>
<td><img src="../imgs/9.png" alt="PC端界面9" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/10.png" alt="PC端界面10" width="300"/></td>
<td><img src="../imgs/11.png" alt="PC端界面11" width="300"/></td>
<td><img src="../imgs/12.png" alt="PC端界面12" width="300"/></td>
</tr>
<tr>
<td><img src="../imgs/13.png" alt="PC端界面13" width="300"/></td>
<td><img src="../imgs/14.png" alt="PC端界面14" width="300"/></td>
<td><img src="../imgs/15.png" alt="PC端界面15" width="300"/></td>
</tr>
</tr>
<tr>
<td><img src="./doc/imgs/16.png" alt="PC端界面16" width="300"/></td>
<td><img src="./doc/imgs/17.png" alt="PC端界面17" width="300"/></td>
<td><img src="./doc/imgs/18.png" alt="PC端界面18" width="300"/></td>
</tr>
</table>
### 移動端界面
<table>
<tr>
<td><img src="../imgs/m1.png" alt="移動端界面1" width="200"/></td>
<td><img src="../imgs/m2.png" alt="移動端界面2" width="200"/></td>
<td><img src="../imgs/m3.png" alt="移動端界面3" width="200"/></td>
<td><img src="../imgs/m4.png" alt="移動端界面4" width="200"/></td>
</tr>
<tr>
<td><img src="../imgs/m5.png" alt="移動端界面5" width="200"/></td>
<td><img src="../imgs/m6.png" alt="移動端界面6" width="200"/></td>
<td><img src="../imgs/m7.png" alt="移動端界面7" width="200"/></td>
<td><img src="../imgs/m8.png" alt="移動端界面8" width="200"/></td>
</tr>
<tr>
<td><img src="../imgs/m9.png" alt="移動端界面9" width="200"/></td>
<td><img src="../imgs/m10.png" alt="移動端界面10" width="200"/></td>
<td><img src="../imgs/m11.png" alt="移動端界面11" width="200"/></td>
<td><img src="../imgs/m12.png" alt="移動端界面12" width="200"/></td>
</tr>
</table>
## 項目文件
| 文件 | 說明 |
|------|------|
| [部署指南](DEPLOYMENT_zh-Hant.md) | 部署配置和環境搭建說明 |
| [項目結構](PROJECT_STRUCTURE_zh-Hant.md) | 項目目錄結構架構說明 |
| [資料庫設計](DATABASE_DESIGN_zh-Hant.md) | 資料庫表結構設計文件 |
| [API接口文件](API_DOCS_zh-Hant.md) | 後端API接口說明和示例 |
## 項目亮點
- **工程化:** 環境配置、程式碼規範、建構與產物最佳化的完整流程
- **業務能力:** 驗權流程、路由守衛、狀態管理與接口封裝
- **體驗優化:** 骨架屏、延遲載入、預載入、無障礙與響應式適配
- **元件與分層:** 可復用元件拆分、按領域分組與別名引入
- **後台管理:** 基礎CRUD、數據管理與配置面板支援後續擴展權限與統計
- **快速部署:** 基於 Docker 的一鍵部署方案,支援多環境配置與自動化部署
## 技術棧
> 💡點擊可展開查看詳細內容
<details>
<summary><b>前端技術</b></summary>
- **Vue.js 3** - 前端框架Composition API
- **Vue Router 4** - 路由管理
- **Pinia** - 狀態管理
- **Vite** - 建構工具和開發伺服器
- **Axios** - HTTP用戶端
- **VueUse** - Vue組合式工具庫
- **CropperJS** - 圖片裁剪
- **Vue3 Emoji Picker** - 表情選擇器
- **svg-captcha** - 驗證碼產生器
</details>
<details>
<summary><b>後端技術</b></summary>
- **Node.js** - 執行環境
- **Express.js** - Web框架
- **MySQL** - 資料庫
- **JWT** - 身份驗證
- **Multer** - 文件上傳
- **bcrypt** - 密碼加密
- **CORS** - 跨域資源共享
</details>
## 第三方API
- **圖片儲存:** 灌裝的示例圖片來自 [栗次元圖床](https://t.alcy.cc/),提供穩定的圖片儲存服務
- **圖片上傳:** 使用者上傳圖片使用了 [夏柔API](https://api.aa1.cn/doc/xinyew_jdtc.html),確保圖片上傳的穩定性和速度
- **属地查詢:** IP属地查詢服務使用 [保羅API](https://api.pearktrue.cn/dashboard/detail/290)實現精準的IP属地定位功能
## 環境要求
| 元件 | 版本要求 |
|------|----------|
| Node.js | >= 16.0.0 |
| MySQL | >= 5.7 |
| MariaDB | >= 10.3 |
| npm | >= 8.0.0 |
| yarn | >= 1.22.0 |
| 瀏覽器 | 支援ES6+ |
> 提示:上述為傳統本地開發的最低版本要求。若使用 Docker 部署預設鏡像版本如下MySQL 8.0、Node 18-alpine前後端建構/執行、Nginx alpineDocker >= 20、Docker Compose >= 2。詳見[部署指南文件](DEPLOYMENT_zh-Hant.md)。
## 環境配置
項目使用環境變數進行配置管理,前後端分別有獨立的 `.env` 文件:
### 後端配置 (express-project/.env)
```env
# 伺服器配置
PORT=3001
NODE_ENV=development
# 資料庫配置
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=123456
DB_NAME=xiaoshiliu
DB_PORT=3306
# JWT配置
JWT_SECRET=xiaoshiliu_secret_key_2025
JWT_EXPIRES_IN=7d
# 上傳配置
UPLOAD_MAX_SIZE=50mb
# 圖片上傳策略 (local: 本地儲存, imagehost: 第三方圖床)
UPLOAD_STRATEGY=imagehost
# 本地儲存配置
LOCAL_UPLOAD_DIR=uploads
LOCAL_BASE_URL=http://localhost:3001
# 第三方圖床配置
IMAGEHOST_API_URL=https://api.xinyew.cn/api/jdtc
IMAGEHOST_TIMEOUT=60000
```
### 前端配置 (vue3-project/.env)
```env
# API基礎URL配置
VITE_API_BASE_URL=http://localhost:3001/api
# 應用配置
VITE_USE_REAL_API=true
VITE_APP_TITLE=卜卜圖文社區
```
> 💡 **配置說明**
> - 後端支援本地儲存和第三方圖床兩種上傳策略
> - 前端使用 Vite 環境變數,變數名需以 `VITE_` 開頭
> - 詳細配置說明請參考 [部署指南](DEPLOYMENT_zh-Hant.md)
### 1. 安裝依賴
```bash
# 使用 cnpm或npm
cnpm install
# 或使用 yarn
yarn install
```
### 2. 啟動開發伺服器
```bash
# 啟動開發伺服器
npm run dev
# 或使用 yarn
yarn dev
```
開發伺服器將在 `http://localhost:5173` 啟動
### 3. 建構生產版本
```bash
# 建構生產版本
npm run build
# 預覽生產版本
npm run preview
```
> ⚠️ **重要提醒**:前端項目需配合後端服務使用,詳細配置請查看 [部署指南](DEPLOYMENT_zh-Hant.md)
## Star歷史
[![Star History Chart](https://api.star-history.com/svg?repos=ZTMYO/XiaoShiLiu&type=Date)](https://www.star-history.com/#ZTMYO/XiaoShiLiu&Date)
---
<div align="center">
Copyright © 2025 - **XiaoShiLiu**\
By ZTMYO\
Made with ❤️ & ⌨️
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

BIN
doc/imgs/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 595 KiB

View File

@@ -1,95 +0,0 @@
name: xiaoshiliu
services:
mysql:
image: mysql:8.0
container_name: xiaoshiliu-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-123456}
MYSQL_DATABASE: ${DB_NAME:-xiaoshiliu}
MYSQL_USER: ${DB_USER:-xiaoshiliu_user}
MYSQL_PASSWORD: ${DB_PASSWORD:-123456}
TZ: Asia/Shanghai
ports:
- "3307:3306"
volumes:
- /mnt/persist/xsl_mysql:/var/lib/mysql
- /mnt/persist/xiaoshiliu/express-project/scripts/init-database.sql:/docker-entrypoint-initdb.d/init.sql
- /etc/localtime:/etc/localtime:ro
networks:
- xiaoshiliu-network
command:
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
backend:
build: ./express-project
container_name: xiaoshiliu-backend
restart: unless-stopped
environment:
NODE_ENV: production
PORT: 3001
DB_HOST: mysql
DB_USER: ${DB_USER:-xiaoshiliu_user}
DB_PASSWORD: ${DB_PASSWORD:-123456}
DB_NAME: ${DB_NAME:-xiaoshiliu}
DB_PORT: 3306
JWT_SECRET: ${JWT_SECRET:-xiaoshiliu_secret_key_2025}
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
REFRESH_TOKEN_EXPIRES_IN: ${REFRESH_TOKEN_EXPIRES_IN:-30d}
API_BASE_URL: http://localhost:3001
UPLOAD_MAX_SIZE: ${UPLOAD_MAX_SIZE:-300mb}
UPLOAD_STRATEGY: ${UPLOAD_STRATEGY:-localhost}
LOCAL_UPLOAD_DIR: ${LOCAL_UPLOAD_DIR:-uploads}
LOCAL_BASE_URL: ${LOCAL_BASE_URL:-http://localhost:3001}
IMAGEHOST_API_URL: ${IMAGEHOST_API_URL:-https://api.xinyew.cn/api/jdtc}
IMAGEHOST_TIMEOUT: ${IMAGEHOST_TIMEOUT:-60000}
TZ: Asia/Shanghai
ports:
- "3001:3001"
volumes:
- /mnt/file/xiaoshiliu/backend_uploads:/app/uploads
- /etc/localtime:/etc/localtime:ro
networks:
- xiaoshiliu-network
depends_on:
mysql:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/api/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) }).on('error', () => process.exit(1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
frontend:
build: ./vue3-project
container_name: xiaoshiliu-frontend
restart: unless-stopped
environment:
TZ: Asia/Shanghai
VITE_API_BASE_URL: "http://localhost:3001/api"
ports:
- "8080:80"
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- xiaoshiliu-network
depends_on:
backend:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
networks:
xiaoshiliu-network:
driver: bridge

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>卜卜 - 你的校园图文部落</title>
<title>卜卜世界 - 你的图文部落</title>
<!-- 基础favicon -->
<link rel="icon" type="image/x-icon" href="/logo.ico">

View File

@@ -1,7 +1,7 @@
{
"name": "vue3-project",
"version": "1.0.0",
"description": "卜卜校园图文社区Vue3前端项目",
"description": "卜卜世界图文社区Vue3前端项目",
"author": "@ZTMYO",
"private": true,
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "卜卜 - 你的校园图文部落",
"short_name": "卜卜",
"name": "卜卜世界 - 你的图文部落",
"short_name": "卜卜世界",
"icons": [
{
"src": "/android-icon-192x192.png",
@@ -32,5 +32,5 @@
"display": "standalone",
"theme_color": "#ff6b6b",
"background_color": "#ffffff",
"description": "卜卜世界 - 你的校园图文部落"
"description": "卜卜世界 - 你的图文部落"
}

View File

@@ -1209,7 +1209,7 @@ const toggleCollect = async () => {
const handleShare = async () => {
try {
const shareUrl = `${props.item.title}-${props.item.author}| 卜卜 - 你的校园图文部落】${window.location.origin}/post?id=${props.item.id}`
const shareUrl = `${props.item.title}-${props.item.author}| 卜卜世界 - 你的图文部落】${window.location.origin}/post?id=${props.item.id}`
// 检查是否支持现代剪贴板API
if (navigator.clipboard && navigator.clipboard.writeText) {

View File

@@ -122,7 +122,7 @@ const emit = defineEmits(['close'])
const { lock, unlock } = useScrollLock()
// 静态资源URL
const logoUrl = new URL('@/assets/imgs/卜卜.png', import.meta.url).href
const logoUrl = new URL('@/assets/imgs/logo.png', import.meta.url).href
const ztmyoUrl = new URL('@/assets/imgs/ztmyo.png', import.meta.url).href
const liciUrl = new URL('@/assets/imgs/栗次元.ico', import.meta.url).href
const xiaRouUrl = new URL('@/assets/imgs/夏柔.ico', import.meta.url).href

View File

@@ -146,7 +146,7 @@ const themeStore = useThemeStore()
const { confirmState, handleConfirm, handleCancel, confirmLogout } = useConfirm()
const { lock, unlock } = useScrollLock()
const logoUrl = new URL('@/assets/imgs/卜卜.png', import.meta.url).href
const logoUrl = new URL('@/assets/imgs/logo.png', import.meta.url).href
const indicatorPosition = computed(() => {
const index = themeStore.themeOptions.findIndex(option => option.value === themeStore.currentTheme)

View File

@@ -12,7 +12,7 @@ const route = useRoute()
const searchHistoryStore = useSearchHistoryStore()
// 静态资源URL
const logoUrl = new URL('@/assets/imgs/卜卜.png', import.meta.url).href
const logoUrl = new URL('@/assets/imgs/logo.png', import.meta.url).href
const isLargeScreen = ref(window.innerWidth > 695)
const showSidebar = ref(window.innerWidth > 960)

View File

@@ -1,5 +1,5 @@
/**
* 卜卜校园图文社区 - Vite配置文件
* 卜卜世界图文社区 - Vite配置文件
*
* @author ZTMYO
* @github https://github.com/ZTMYO