基于Golang+Vue3快速搭建的博客系统
WANLI 博客系统
项目介绍
基于vue3和gin框架开发的前后端分离个人博客系统,包含md格式的文本编辑展示,点赞评论收藏,新闻热点,匿名聊天室,文章搜索等功能。
项目在线访问:http://bloggo.chat/
访客账号:test 密码:test
也可以使用邮箱自己注册。
GitHub地址:ginblog-wanli
功能展示
B 站视频
图片展示:


技术介绍
开发环境
| 开发工具 | 功能描述 |
|---|---|
| GoLand | 后端开发 |
| Vscode | 前端开发 |
| Apifox | API测试 |
| Ubuntu | 依赖软件运行 |
| xftp、xsheel | Linux 远程工具 |
| 开发环境 | 版本 |
|---|---|
| GoLang | 1.22.3 |
| nodejs | 20.14.0 |
| MySQL | 8.0 |
| Elasticsearch、kibana、ik | 7.12.0 |
| Redis | 7.0.8 |
技术栈
这里只写一些主流的通用技术,详细第三方库:前端参考 package.json 文件,后端参考 go.mod 文件
| 功能描述 | 前端 | 官方地址 |
|---|---|---|
| Vue3框架 | vuejs | https://cn.vuejs.org/ |
| Vue组件 | ant-design-vue | https://next.antdv.com/docs/vue/introduce-cn/ |
| Mark Down | md-editor-v3 | https://imzbf.github.io/md-editor-v3/ |
| 状态管理工具 | pinia | https://pinia.vuejs.org/ |
| 构建工具 | vite | https://cn.vitejs.dev/ |
| 可视化图表库 | echarts | https://echarts.apache.org/zh/index.html |
| 功能描述 | 后端 | 官方地址 |
|---|---|---|
| GO语言 | golang | https://github.com/golang/go |
| WEB框架 | gin | https://gin-gonic.com/zh-cn/docs/ |
| API文档 | swaggo | https://github.com/swaggo |
| ORM 库 | gorm | https://github.com/go-gorm/gorm |
| 日志库 | logrus | https://github.com/sirupsen/logrus |
本地运行
自行安装 Golang、Node、MySQL、Redis 、Elasticsearch 环境
Golang 安装参考官方文档
Node 建议安装使用https://nodejs.org/zh-cn的长期维护版
MySQL、Redis、Elasticsearch 建议使用 Docker 运行
后端项目运行:
# 1、启动MySQL、Redis、Elasticsearch,其中mysql需要新建一个库
# 2、修改项目运行的配置文件 settings.yaml# 3、初始化运行环境
go mod tidy # 下载当前项目所依赖的包
go run main.go -db # mysql建表
go run main.go -es create # elasticsearch建索引# 4、mysql插入菜单表数据
INSERT INTO gvb.menu_models (id, created_at, updated_at, title, path, slogan, abstract, abstract_time, banner_time, sort) VALUES (1, NOW(), NOW(), '首页', '/', '众神眷恋的幻想乡', '天寒地冻路远马亡又何妨', 5, 5, 1);
INSERT INTO gvb.menu_models (id, created_at, updated_at, title, path, slogan, abstract, abstract_time, banner_time, sort) VALUES (2, NOW(), NOW(), '新闻', '/news', '新闻三分钟,知晓天下事', '震惊!男人看了会沉默,女人看了会流泪!不转不是中国人!', 5, 5, 2);
INSERT INTO gvb.menu_models (id, created_at, updated_at, title, path, slogan, abstract, abstract_time, banner_time, sort) VALUES (3, NOW(), NOW(), '文章搜索', '/search', '文章搜索', '文章搜索', 5, 5, 3);
INSERT INTO gvb.menu_models (id, created_at, updated_at, title, path, slogan, abstract, abstract_time, banner_time, sort) VALUES (4, NOW(), NOW(),'聊天室', '/chat_group', '聊天室', '聊天室', 5, 5, 4);# 5、创建第一个用户,后续可在前端创建或注册
go run main.go -u admin # 管理员
go run main.go -u user # 普通用户# 6、启动项目
go run main.go
前端项目运行:
# 下载当前项目所依赖的包
npm insatll
# 启动项目
npm run dev
线上部署(Linux)| 阿里云服务器 | 七牛云存储
本项目线上部署目录结构如下,必需的目录及文件:
gvb└─deploy└─gvb├─elasticsearch│ ├─config│ ├─data│ └─plugins │ └─ik # 使用ik分词器,下载7.12.0版本,然后解压重命名为ik,上传到linux挂载的plugins目录下├─gvb_server # 服务端代码,这个不用容器启动 直接 ./main 启动即可│ ├─docs│ ├─uploads│ ├─main(二进制文件)│ └─settings.yml(配置文件)├─gvb_web│ └─dist├─mysql│ └─data├─nginx│ ├─conf│ ├─html│ └─logs└─redis└─data
安装Docker和docker-compose
只需要提前安装好docker运行环境,可自行上网搜索资料安装
安装地址:[https://developer.aliyun.com/article/708974
依赖软件准备
后端Golang中的settings.yaml文件,请自行修改你的配置内容。
在服务器上使用docker-compose启动所有容器:mysql、redis、elasticsearch、kibana、nginx
docker-compose.yml 和 .env 文件放在部署服务器的 deploy 目录下,cd 到deploy启动docker-compose,以下是各个文件的内容。
1、docker-compose.yml 文件
version: "3"networks:gvb-network:driver: bridgeipam:config:- subnet: ${SUBNET}services:gvb-redis:image: redis:7.0.8-alpinecontainer_name: gvb-redisvolumes:- ${GVB_DATA_DIRECTORY}/redis/data:/dataports:- ${REDIS_PORT}:6379 # 自定义的是暴露出去的端口, Redis 容器内运行固定为 6379command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yesnetworks:gvb-network:ipv4_address: ${REDIS_HOST}gvb-mysql:image: mysql:8.0container_name: gvb-mysqlvolumes:- ${GVB_DATA_DIRECTORY}/mysql/data:/var/lib/mysqlenvironment:- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} # root 账号的密码- MYSQL_DATABASE=${MYSQL_DATABASE} # 初始化的数据库- MYSQL_USER=${MYSQL_USER}- MYSQL_PASSWORD=${MYSQL_PASSWORD}- TZ=Asia/Shanghaicommand: --max_connections=1000--character-set-server=utf8mb4--collation-server=utf8mb4_general_ciports:- ${MYSQL_PORT}:3306 # 自定义的是暴露出去的端口, MySQL 容器内运行固定为 3306networks:gvb-network:ipv4_address: ${MYSQL_HOST}gvb-elasticsearch:image: elasticsearch:7.12.0container_name: gvb-elasticsearchvolumes:- ${GVB_DATA_DIRECTORY}/elasticsearch/data:/usr/share/elasticsearch/data- ${GVB_DATA_DIRECTORY}/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml- ${GVB_DATA_DIRECTORY}/elasticsearch/plugins:/usr/share/elasticsearch/pluginsenvironment:- discovery.type=single-node- ES_JAVA_OPTS=-Xms128m -Xmx256mports:- ${ELASTICSEARCH_PORT01}:9200 # 自定义的是暴露出去的端口, elasticsearch 容器内运行固定为 9200和9300- ${ELASTICSEARCH_PORT02}:9300networks:gvb-network:ipv4_address: ${ELASTICSEARCH_HOST}command:["/bin/sh","-c","chmod -R 777 /usr/share/elasticsearch/data /usr/share/elasticsearch/config /usr/share/elasticsearch/plugins && /usr/local/bin/docker-entrypoint.sh",]gvb-nginx:image: nginx:latestcontainer_name: gvb-nginxvolumes:- ${GVB_DATA_DIRECTORY}/nginx/conf/nginx.conf:/etc/nginx/nginx.conf- ${GVB_DATA_DIRECTORY}/nginx/logs:/var/log/nginx- ${GVB_DATA_DIRECTORY}/gvb_web:/usr/share/nginx/html # 修改路径为 nginx 默认的 web 根目录- ${GVB_DATA_DIRECTORY}/gvb_server:/usr/share/nginx/server # 修改路径为 nginx 默认的服务器目录ports:- ${NGINX_PORT}:80 # 自定义的是暴露出去的端口, nginx 容器内运行固定为 80networks:gvb-network:ipv4_address: ${NGINX_HOST}gvb-kibana:image: kibana:7.12.0container_name: gvb-kibanaenvironment:- ELASTICSEARCH_HOSTS=http://gvb-elasticsearch:9200ports:- ${KIBANA_PORT}:5601networks:gvb-network:ipv4_address: ${KIBANA_HOST}
2、 .env 文件(相关参数自行修改)
# https://docs.docker.com/compose/migrate/
# docker-compose.yml 同目录下的 .env 文件会被加载为其环境变量# COMPOSE_PROJECT_NAME=gin-vue-blog# 数据存储的文件夹位置 (默认在当前路径生成 gvb 文件夹)
GVB_DATA_DIRECTORY=./gvb# Redis
REDIS_PORT=6379
REDIS_PASSWORD=password# Kibana
KIBANA_PORT=5601# MySQL
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=password
MYSQL_DATABASE=gvb_db
MYSQL_USER=gvb
MYSQL_PASSWORD=password# Elasticsearch
ELASTICSEARCH_PORT01=9200
ELASTICSEARCH_PORT02=9300# Nginx
NGINX_PORT=80# Docker Network (一般不需要变, 除非发生冲突)
SUBNET=172.12.0.0/24
REDIS_HOST=172.12.0.2
MYSQL_HOST=172.12.0.3
ELASTICSEARCH_HOST=172.12.0.4
KIBANA_HOST=172.12.0.5
NGINX_HOST=172.12.0.6
后端 settings.yml 配置文件,在目录:gvb\deploy\gvb\gvb_server 下。
mysql:host: 你的服务器地址port: 3306config: charset=utf8mb4&parseTime=True&loc=Localdb: gvb_dbuser: rootpassword: xxxlog_Level: ""
logger:level: infoprefix: '[gvb]'director: logshow-line: truelog-in-console: true
system:host: 0.0.0.0port: 8080env: releasessl-pem: ""ssl-key: ""
site-info:created_at: "2024-07-17"bei_an: 等待中title: 万里的个人博客qq_image: /uploads/file/admin/qq_20240717101939.jpgversion: 1.0.1email: 2597029604@qq.comwechat_image: /uploads/file/admin/wechat_20240717101945.jpgname: WANLIjob: Golang后端开发addr: 北京slogan: 万里slogan_en: WANLIweb: http://bloggo.chat/bilibili_url: https://space.bilibili.com/1829444123?spm_id_from=333.1007.0.0gitee_url: https://gitee.com/xiwanligithub_url: https://github.com/xzhHas/ginblog-wanli
qq:app_id: key: redirect: http://127.0.0.1/login?flag=qq
qiniu:enable: trueaccess_key: secret_key: bucket: gvbdbcdn: http://spaotwd8k.hb-bkt.clouddn.com/zone: z1prefix: gvbsize: 150
email:host: smtp.qq.comport: 465user: xxx@qq.compassword: default-from-email: xxx@qq.comuse_ssl: trueuser_tls: false
jwt:secret: 9Saj0XAf8SdTYHj3lq6EOnyIrSfC5D6Dexpires: 1issuer: xiwanli
upload:size: 150path: uploads/file/
redis:ip: 你的服务器地址port: 6379password: "xxx"pool_size: 100
es:host: http://你的服务器地址port: 9200user: ""password: ""
Elasticsearch 配置文件:elasticsearch.yml,在目录:gvb\deploy\gvb\elasticsearch\config 下。
http.host: 0.0.0.0
nginx配置文件:nginx.conf,在目录:gvb\deploy\gvb\nginx\conf 下。
user root;
worker_processes auto;error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;events {worker_connections 1024;
}http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;tcp_nopush on;client_max_body_size 8M; # 上传文件大小限制keepalive_timeout 65;server {listen 80; # HTTPserver_name bloggo.chat www.bloggo.chat; # 域名# 前端请求处理location / {root /usr/share/nginx/html/dist/;index index.html index.htm;try_files $uri $uri/ /index.html;}# WebSocket 请求处理location /wsUrl/ {rewrite ^/wsUrl/(.*)$ /$1 break; # 长连接时间proxy_pass http://你的服务器地址/api/;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";proxy_redirect off;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Host $server_name;proxy_read_timeout 3600s; # 长连接时间}# API 请求处理location /api/ {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://你的服务器地址/api/;}# 文件上传处理location /uploads/ {alias /usr/share/nginx/server/uploads/;}# Swagger 文档处理location /swagger/ {proxy_pass http://你的服务器地址/swagger/;}}
}
应用程序准备
后端项目打包生成的main文件、docs文件夹、settings.yaml、uploads文件夹复制至部署服务器的 gvb_server 目录下。
# 生成api文档
swag init # 后端go打包(请使用cmd打包,不然打包后的文件还可能是windows的版本)
set GOARCH=amd64
set GOOS=linux
set CGO_ENABLED=0
go build -o main
前端项目打包生成的dist文件夹及其文件复制至部署服务器的 gvb_web 目录下。
# 前端npm打包
npm run build
启动应用
修改好各项配置
# docker compose 启动依赖软件
cd xxxxx/gvb/deploy/
docker compose up -d#启动后端应用
cd xxxxx/gvb/gvb_server/
./main -es create (首先创建es的索引)
./main (启动后端程序)
访问应用
最后
感谢观看。
相关文章:
基于Golang+Vue3快速搭建的博客系统
WANLI 博客系统 项目介绍 基于vue3和gin框架开发的前后端分离个人博客系统,包含md格式的文本编辑展示,点赞评论收藏,新闻热点,匿名聊天室,文章搜索等功能。 项目在线访问:http://bloggo.chat/ 访客账号…...
DVWA中命令执行漏洞细说
在攻击中,命令注入是比较常见的方式,今天我们细说在软件开发中如何避免命令执行漏洞 我们通过DVWA中不同的安全等级来细说命令执行漏洞 1、先调整DVWA的安全等级为Lower,调整等级在DVWA Security页面调整 2、在Command Injection页面输入127.0.0.1&…...
【YOLOv5/v7改进系列】引入中心化特征金字塔的EVC模块
一、导言 现有的特征金字塔方法过于关注层间特征交互而忽视了层内特征的调控。尽管有些方法尝试通过注意力机制或视觉变换器来学习紧凑的层内特征表示,但这些方法往往忽略了对密集预测任务非常重要的被忽视的角落区域。 为了解决这个问题,作者提出了CF…...
【QT】常用控件(概述、QWidget核心属性、按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
一、控件概述 Widget 是 Qt 中的核心概念,英文原义是 “小部件”,此处也把它翻译为 “控件”。控件是构成一个图形化界面的基本要素。 像上述示例中的按钮、列表视图、树形视图、单行输入框、多行输入框、滚动条、下拉框都可以称为 “控件”。 Qt 作为…...
【Python】字母 Rangoli 图案
一、题目 You are given an integer N. Your task is to print an alphabet rangoli of size N. (Rangoli is a form of Indian folk art based on creation of patterns.) Different sizes of alphabet rangoli are shown below: # size 3 ----c---- --c-b-c-- c-b-a-b-c --…...
html+css 实现水波纹按钮
前言:哈喽,大家好,今天给大家分享htmlcss 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 文…...
科技与占星的融合:AI 智能占星师
本文由 ChatMoney团队出品 在科技的前沿领域,诞生了一位独特的存在——AI占星师。它并非传统意义上的占星师,而是融合了先进的人工智能技术与神秘的占星学知识。 这能够凭借其强大的数据分析能力和精准的算法,对星辰的排列和宇宙的能量进行深…...
判断字符串,数组方法
判断字符串方法 在JavaScript中,可以使用typeof操作符来判断一个变量是否为字符串。 function isString(value) {return typeof value string; } 判断数组 在JavaScript中,typeof操作符并不足以准确判断一个变量是否为数组,因为typeof会…...
SpringBoot Vue使用Jwt实现简单的权限管理
为实现Jwt简单的权限管理,我们需要用Jwt工具来生成token,也需要用Jwt来解码token,同时需要添加Jwt拦截器来决定放行还是拦截。下面来实现: 1、gradle引入Jwt、hutool插件 implementation com.auth0:java-jwt:3.10.3implementatio…...
java中的多态
多态基础了解: 面向对象的三大特征:封装,继承,多态。 有了面向对象才有继承和多态,对象代表什么,就封装对应的数据,并提供数据对应的行为,可以把零散的数据和行为进行封装成一个整…...
【数据结构】:用Java实现链表
在 ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为 O(n),效率比较低,因此 ArrayList 不适合做任意位置插入和删除比较多的场景。因此:java 集合中又引入了 LinkedList&…...
前端开发知识(三)-javascript
javascript是一门跨平台、面向对象的脚本语言。 一、引入方式 1.内部脚本:使用<script> ,可以放在任意位置,也可以有多个,一般是放在<body></body>的下方。 2.外部脚本:单独编写.js文件ÿ…...
Windows图形界面(GUI)-MFC-C/C++ - MFC绘图
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 MFC绘图 绘图基础 CPaintDC 实例代码 MFC绘图 绘图基础 设备上下文(Device Context, DC): 设备上下文是一个Windows GDI(图形设备接口)…...
51单片机-第五节-串口通信
1.什么是串口? 串口是通讯接口,实现两个设备的互相通信。 单片机自带UART,其中引脚有TXD发送端,RXD接收端。且电平标准为TTL(5V为1,0V为0)。 2.常见电平标准: (1)TTL电…...
【Linux常用命令】之df命令
Linux常用命令之df命令 文章目录 Linux常用命令之df命令常用命令之df背景介绍 总结 作者简介 听雨:一名在一线从事多年研发的程序员,从事网站后台开发,熟悉java技术栈,对前端技术也有研究,同时也是一名骑行爱好者。 D…...
2024年起重信号司索工(建筑特殊工种)证模拟考试题库及起重信号司索工(建筑特殊工种)理论考试试题
题库来源:安全生产模拟考试一点通公众号小程序 2024年起重信号司索工(建筑特殊工种)证模拟考试题库及起重信号司索工(建筑特殊工种)理论考试试题是由安全生产模拟考试一点通提供,起重信号司索工(建筑特殊工种)证模拟考试题库是根据起重信号司索工(建筑特…...
AWS全服务历史年表:发布日期、GA和服务概述一览 (全)
我一直在尝试从各种角度撰写关于Amazon Web Services(AWS)的信息和魅力。由于我喜欢技术历史,这次我总结了AWS服务发布的历史年表。 虽然AWS官方也通过“Whats New”发布了官方公告,但我一直希望能有一篇文章将公告日期、GA日期&…...
Leetcode 2824. 统计和小于目标的下标对数目
2824. 统计和小于目标的下标对数目 2824. 统计和小于目标的下标对数目 一、题目描述二、我的想法 一、题目描述 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 target ,请你返回满足 0 < i < j < n 且 nums[i] nums[j] < target 的下标对…...
TCP服务器主动断开客户端
自定义消息函数 afx_msg LRESULT CbaseMFCprojectDlg::OnOnsocketbartender(WPARAM wParam, LPARAM lParam) WPARAM wParam:消息来源 res recv(wParam, cs, 65535, 0);获取这个客户端端口socket通道里面的信息长度为65535存放在cs里面 如果获取得到res0即是说明该客户端已经断…...
接口自动化中json.dumps()跟json.loads()区别详解
接口自动化中对于参数处理经常会用到json.dumps()跟json.loads(),下面主要分享一下自己使用总结 1.主要区别 json.dumps() 用于将字典转换为字符串格式 json.loads()用于将字符串转换为字典格式 import jsondict1 {"name":"amy","gender":woma…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...
