尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Uniapp+SpringBoot+Vue全平台博客系统开发实战与避坑指南

Uniapp+SpringBoot+Vue全平台博客系统开发实战与避坑指南 从博客系统这个老话题里做出新意技术选型是最关键的环节。我这次没有走传统单体应用的老路直接选了Uniapp SpringBoot Vue这套组合拳把个人博客从纯PC浏览升级成了覆盖App、小程序、H5和PC管理后台的全平台方案。这篇文章不聊虚的直接把我从数据库建模到三端联调、从打包上架到服务器部署的完整过程拆给你看所有踩过的坑和对应的排查思路都会讲到。如果你正准备做博客类系统或者正在纠结毕业设计/个人项目的技术栈选型这篇文章的内容应该能帮你节省大量的试错时间。我会把每个关键模块的设计原因、参数计算过程和在实际开发中遇到的典型问题全部记录下来尽量保证你照着走能顺利复现少走弯路。1. 整体架构设计与技术选型背后的思考1.1 为什么最终选择这套技术组合先说结论Uniapp解决多端复用SpringBoot解决后端开发效率Vue解决后台管理界面的交互复杂度。这三个框架单独拿出来都不是新东西但组合在一起正好覆盖了个人博客系统的全部使用场景。我之前用纯Vue Node写过一版博客老实说功能都能跑但痛点很致命手机浏览器看文章排版稀烂也没法打包成App推送给朋友用。后来想补一个小程序版本发现代码要全部重写维护成本直接翻倍。正当我犹豫要不要放弃App端时接触到了Uniapp它的核心卖点就是一套代码编译到iOS、Android、H5以及各种小程序平台。这意味着我只需要维护一份移动端代码就能覆盖绝大多数用户访问博客的场景。后端选SpringBoot而不是Node或者Django主要看中三点第一SpringBoot的生态太成熟了做博客系统需要的权限认证、数据库操作、文件上传都有非常稳定的解决方案第二Java的静态类型系统在项目规模变大后优势明显博客系统虽然看起来简单但加上评论、标签、分类、用户体系后涉及的表关系和业务逻辑并不少第三SpringBoot的自动配置极大简化了项目搭建过程一个空的Web项目只需要几行依赖就能跑起来这对追求快速开发的我来说很重要。前端管理后台用Vue的理由就简单多了它的响应式数据绑定和组件化开发方式让我在写文章管理、评论审核这类密集表格交互页面时效率极高加上Element Plus这类组件库已经提供了现成的表格、表单、弹窗组件UI层面的工作量大大减少。1.2 系统的模块划分与核心功能清单在设计阶段我把整个系统按使用角色和终端划分为三个端用户端Uniapp面向普通访客包括文章列表浏览、文章详情阅读、标签分类筛选、评论互动、个人中心、搜索功能等。管理端Vue面向博主本人包括文章发布与编辑支持富文本和Markdown两种格式、文章分类和标签管理、评论审核与删除、站点统计仪表盘、个人资料设置等。服务端SpringBoot为上述两端提供统一RESTful API接口负责数据处理、权限校验、文件存储、日志记录等。数据库层面我设计了6张核心表用户表user、文章表article、分类表category、标签表tag、文章标签关联表article_tag、评论表comment。另外加了两张辅助表系统配置表config用于保存站点标题、公告等全局信息操作日志表log用于记录后台的敏感操作。这个表结构不是拍脑袋定的而是根据博客系统的核心业务流程推导出来的。比如文章和标签的关系一篇文章可能有多个标签一个标签下有多篇文章这就必须用中间表article_tag来维护多对多关系。分类则是典型的一对多所以我直接在article表里冗余了一个category_id字段查询时做一次JOIN就能拿到分类名避免连表太深影响性能。1.3 前后端分离架构下的接口设计约定接口设计方面我统一采用了RESTful风格并且约定了一套固定的返回结构{ code: 200, message: 操作成功, data: {} }code为200表示成功非200为失败message是提示信息data是实际数据。这样设计的好处是前端无论在哪一端Uniapp或Vue都能用同一个拦截器处理错误和加载状态不用针对不同接口做特殊处理。接口路径也做了明确的划分以/api开头表示需要认证的接口以/public开头表示公开接口。比如获取文章列表就是GET /public/article/list发布新文章就是POST /api/article/save。这样的路径规则在后期的权限拦截器里非常好写只需判断路径前缀即可区分是否需要校验Token。分页参数统一使用pageNum页码从1开始和pageSize每页条数返回的数据用PageResult对象包装包括总条数total、总页数pages和当前页数据list三个字段。这样前端无论做下拉加载还是分页组件拿到的数据格式都是固定的。2. SpringBoot后端核心实现与避坑指南2.1 项目初始化的版本选择与配置陷阱创建SpringBoot项目是第一步也是很多新手会卡住的地方。账号本身不是问题问题往往出在版本选择上。如果你直接用Spring Initializr创建项目默认拉取的SpringBoot版本可能是3.x甚至更高而3.x版本要求JDK 17以上并且很多第三方组件比如某些生成验证码的库、老版本的MyBatis Plus还没做好适配运行时会冒出各种奇怪的异常。我这次的推荐组合是SpringBoot 2.7.x JDK 1.8 MyBatis Plus 3.5.x。这套组合非常稳定网上能搜到的资料也多踩坑成本最低。如果你非要用SpringBoot 3.x那请注意JDK必须切到17同时MyBatis Plus需要换用对应的3.5.3以上版本否则启动直接会报ClassNotFound异常。在application.yml配置文件里有一个细节特别容易被忽略就是日期序列化格式。如果你的表里有create_time这样的字段默认情况下返回给前端的格式会是时间戳或者带时区的复杂字符串Uniapp端解析起来很麻烦。建议在配置文件中指定统一的日期格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8同理mybatis-plus的配置也要注意下划线转驼峰的开关否则你的实体类字段和数据库列名无法自动映射mybatis-plus: configuration: map-underscore-to-camel-case: true2.2 文章表设计与MyBatis Plus分页查询实现文章表是博客系统的核心它的字段设计直接影响了查询效率和后续功能的扩展空间。我最终的建表语句大致如下CREATE TABLE article ( id bigint(20) NOT NULL AUTO_INCREMENT, title varchar(200) NOT NULL COMMENT 文章标题, summary varchar(500) DEFAULT NULL COMMENT 文章摘要, content longtext NOT NULL COMMENT 文章正文, cover varchar(500) DEFAULT NULL COMMENT 封面图URL, category_id bigint(20) DEFAULT NULL COMMENT 分类ID, author_id bigint(20) DEFAULT NULL COMMENT 作者ID, status tinyint(4) DEFAULT 1 COMMENT 状态0草稿1发布, is_top tinyint(4) DEFAULT 0 COMMENT 是否置顶, view_count int(11) DEFAULT 0 COMMENT 浏览量, like_count int(11) DEFAULT 0 COMMENT 点赞数, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;正文用longtext而不是text是为了支持较长的图文混排内容。分类ID加索引是因为列表页最常见的查询就是按分类筛选文章。状态加索引是因为前台默认只展示status1的已发布文章。分页查询我利用了MyBatis Plus提供的能力但并没有直接用简单的selectPage因为还需要关联查出分类名称和作者昵称。我的做法是先在Service层把分页条件拼好然后用自定义SQL关联查询public PageResultArticleVO getArticlePage(int pageNum, int pageSize, Long categoryId, String keyword) { PageArticle page new Page(pageNum, pageSize); QueryWrapperArticle wrapper new QueryWrapper(); wrapper.eq(categoryId ! null, a.category_id, categoryId) .like(StringUtils.isNotBlank(keyword), a.title, keyword) .eq(a.status, 1) .orderByDesc(a.is_top) .orderByDesc(a.create_time); PageArticleVO result articleMapper.selectArticlePage(page, wrapper); return new PageResult(result.getTotal(), result.getPages(), result.getRecords()); }这里有个容易踩的坑如果用Wrapper传条件给自定义SQLXML里的${ew.customSqlSegment}才能正确拼接条件。如果你在XML里手写了WHERE 11再拼接参数很容易出现SQL注入风险或者条件丢失我的建议是直接用MyBatis Plus的机制尽量少手写动态SQL。2.3 基于JWT的登录认证与权限控制博客后台肯定不能允许任何人随便发文章所以用户认证是必不可少的一环。我选用了JWTJSON Web Token方案而不是传统的Session方案主要原因是JWT无状态适合前后端分离场景服务端不需要维护会话信息扩容也方便。JWT的核心概念可以这样理解它就是一张带了签名和过期时间的通行证用户登录成功后服务端把用户ID和过期时间加密生成一个字符串返回给前端。前端后续每次请求都在Header里带上这个字符串服务端验证签名合法后就能确定请求者的身份。具体实现上我用的是jjwt这个库生成和解析代码都不复杂// 生成Token String token Jwts.builder() .setSubject(userId.toString()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() 7 * 24 * 3600 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); // 解析Token Claims claims Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody(); Long userId Long.parseLong(claims.getSubject());注意这里的密钥secretKey一定不能硬编码在代码里哪怕是个人博客也要养成好习惯放到配置文件中通过Value注解注入。过期时间我设置成了7天这个时长对个人博客来说比较合适用户不需要频繁登录同时又不至于太长导致安全隐患。权限控制我用的是SpringBoot的拦截器机制。写一个AuthInterceptor在preHandle方法里校验请求路径和Token。如果是/api/开头的路径且未携带有效Token直接返回401错误码如果是公开接口直接放行。通过注册配置指定拦截路径和排除路径代码非常清晰Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns(/api/**) .excludePathPatterns(/public/**); } }3. Vue管理后台与Uniapp移动端的关键实现3.1 Vue后台的搭建、路由设计与富文本编辑器集成Vue管理后台我使用的是Vue 3 Vite Element Plus Pinia这套比较现代的组合。Vite比Webpack最大的优势就是启动速度快改代码热更新几乎无感这对后台开发体验提升非常明显。路由设计上我用了嵌套路由加动态路由的方式。最简单的做法是直接在路由表里配好所有页面组件然后在router.beforeEach里判断登录状态未登录就跳转到/login。如果后续你想再加权限细分可以改成从后端接口获取用户权限码动态过滤路由并添加我这次是直接在静态路由表上做的对个人博客来说够用了。富文本编辑器的选择上我起初直接用Element Plus的输入框结果发现文章排版简直就是灾难。后来换成了wangeditor这是一款国产开源富文本编辑器对Vue3有官方支持集成的代码量很少import WangEditor from wangeditor/editor-for-vue; const editorConfig { placeholder: 请输入内容..., MENU_CONF: { uploadImage: { server: /api/file/upload, fieldName: file, headers: { Authorization: Bearer getToken() } } } };编辑器上传图片的接口通常需要携带Token认证所以在MENU_CONF里配置请求头很重要不然图片传不上去接口会直接报401排查了半天才意识到是这里的问题。在有移动端的情况下我强烈建议你在后台发布文章时同时支持正文的HTML格式存储。因为Uniapp端渲染文章详情时如果内容是纯文本会非常单调如果内容是HTML可以用rich-text组件直接渲染省去自己写解析器的麻烦。3.2 Uniapp跨端开发的环境准备与目录结构规划Uniapp开发前需要先通过HBuilderX创建一个默认模板项目或者在命令行用vue create结合dcloudio/uni-preset-vue模板创建。我用的是HBuilderX对新手最友好因为一键就能运行到微信开发者工具或者浏览器调试效率很高。创建完项目的目录结构大致是这样的├── pages # 页面文件 │ ├── index # 首页文章列表 │ ├── detail # 文章详情 │ ├── category # 分类页 │ ├── search # 搜索页 │ └── mine # 个人中心 ├── static # 静态资源 ├── utils # 工具函数请求封装、格式化等 ├── api # 各模块的接口定义 ├── App.vue # 应用入口文件 ├── main.js # 主入口 ├── manifest.json # 应用配置AppID、权限、SDK配置等 └── pages.json # 页面路由与导航栏配置pages.json相当于小程序里的app.json所有页面的路由都要在这里注册同时可以配置导航栏标题、背景色、tabBar等。一个经常被忽略的配置是globalStyle里的navigationBarTextStyle如果你导航栏背景是深色文字必须配成白色否则会出现黑色文字在黑色背景上完全看不清的情况。manifest.json的作用在Uniapp里极其重要它控制着应用在不同平台的差异化配置。比如你要打包成微信小程序需要在这里配置小程序的AppID要打包成App需要配置App图标、启动图、权限声明等。我在配置iOS打包时就因为没有正确填写Bundle Identifier导致云端打包一直失败后来才发现是manifest里的AppID和证书不匹配。3.3 Uniapp请求封装与文章详情页的渲染与视频播放Uniapp的请求API是uni.request但它不像Axios那样自带拦截器所以需要自己封装一层。我封装了一个request.js统一处理BaseURL、Token注入、响应拦截和错误提示const BASE_URL https://api.example.com; export function request(options) { return new Promise((resolve, reject) { uni.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, Authorization: uni.getStorageSync(token) ? Bearer uni.getStorageSync(token) : }, success: (res) { if (res.data.code 200) { resolve(res.data.data); } else { uni.showToast({ title: res.data.message, icon: none }); reject(res.data); } }, fail: (err) { uni.showToast({ title: 网络异常, icon: none }); reject(err); } }); }); }一个必须提前规划的细节真机调试时localhost和127.0.0.1指向的是手机本身而不是开发电脑所以BaseURL必须换成电脑在局域网内的IP地址。我在联调阶段经常遇到“App里请求失败但浏览器正常”的情况90%都是这个原因。文章详情页是移动端最核心的页面。正文如果是HTML片段可以直接用内置的rich-text组件渲染。但如果正文里包含视频m3u8格式和图片处理起来就要多做一步了。m3u8是流媒体常用的索引文件格式在微信小程序里原生video组件不支持直接播放m3u8需要通过腾讯云视立方插件或者videojs的H5方案来实现。我在做这个项目时考虑到要兼顾H5和小程序没有引入太重的播放器SDK而是做了个折中方案在文章详情页检测到m3u8链接时H5端使用video.js播放小程序端则提示用户跳转到浏览器访问。为了识别文章内容中的视频链接我在后端存储文章时额外维护了一个video_url字段列表接口返回时直接带上前端拿到后统一封装成播放器组件template view v-ifvideoUrl !-- 根据平台条件编译 -- video v-if!isH5 :srcvideoUrl controls/video videojs-video v-else :srcvideoUrl / /view /template这样虽然多写了几行平台判断代码但避免了在小程序端因无法播放m3u8导致整个页面白屏的尴尬局面。3.4 Uniapp的打包发布流程与自定义功能配置Uniapp项目做好后打包发布是绕不开的一步。这里我按目标平台说几个关键注意点。打包成微信小程序在HBuilderX中选择“运行到小程序模拟器-微信开发者工具”前提是先安装微信开发者工具并且开启服务端口。打包上线前需要在小程序后台配置服务器域名必须是HTTPS且已备案的域名否则真机预览时所有请求都会被拦截。我一开始用IP:端口的方式请求后端小程序里直接报“不在以下request合法域名列表中”后来切换成HTTPS域名才解决。打包成App在HBuilderX中点击“发行-原生App-云打包”这里需要配置Android和iOS的证书。Android的证书可以用Android Studio自己生成一个签名文件iOS则需要Apple开发者账号生成描述文件和p12证书。如果你没有Mac电脑iOS的证书生成确实比较麻烦但云打包服务支持在Windows上提交打包请求只是证书部分需要提前准备好。打包成H5在HBuilderX中发行到H5后要特别注意相对路径还是绝对路径的问题。如果你的H5要部署在Nginx的子目录下需要在manifest.json中配置h5.router.base为对应的子目录路径否则刷新页面直接404。关于manifest.json中的权限配置我用到了定位功能在公众号H5中获取用户地理位置需要在App模块配置里勾选Geolocation同时在小程序后台申请对应的接口权限。这里有一步特别容易漏掉在微信公众平台里还需要配置JS接口安全域名否则H5调用定位接口会被微信拦截。4. 三端联调中的典型问题与排查实录4.1 跨域问题引发的“接口老是报错”和解决方案前后端分离架构下跨域问题几乎是逃不掉的。开发环境下我用Vue的代理配置解决Uniapp的H5端也同理Vite的vite.config.js里这样配置server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端代码里的/api/xxx请求会被Vite开发服务器转发到后端浏览器看到的是同源请求不会触发CORS拦截。生产环境下问题就转移到Nginx层了。我的建议是直接在Nginx配置反向代理把/api开头的请求转发到SpringBoot服务同时配置好proxy_set_header传递用户IP等头信息location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }如果你不想配置Nginx也可以在后端加一个CorsFilter允许指定域名跨域但从安全角度我不太推荐直接放开所有来源个人博客可以只允许自己的域名访问。4.2 真机调试连不上后端原来是IP和端口惹的祸这个问题我前面简单提到过这里详细说一下排查思路。真机调试时手机和电脑必须在同一个局域网内然后后端服务的启动地址要监听0.0.0.0不能只监听127.0.0.1。SpringBoot默认是监听所有网卡的这点倒没啥问题。真正的坑在于防火墙。Windows电脑的防火墙默认会拦截外部设备对8080端口的访问导致手机访问不到。我当时排查了半小时一度以为是代码写错了最后发现把防火墙入站规则放行8080端口后问题瞬间消失。另外一个小技巧手机端请求的BaseURL尽量不要写死IP因为家里的路由器和办公室路由器分配给电脑的IP可能不同。我在request.js里做了一个自动获取逻辑开发环境下通过uni.getSystemInfo判断平台H5端直接读当前域名App端则把BaseURL做成可在“个人中心-设置”里手动修改的配置项这样换网络环境时不用重新打包。4.3 文章图片上传后显示不出来数据库存路径还是存URL图片上传是博客系统的刚需。最初我在文章表里存的是相对路径/upload/xxx.jpg结果是后台管理端Vue能正常显示因为后台和图片服务在同一个域名下。但Uniapp端一旦编译成小程序相对路径就完全失效了因为小程序没有域的概念只会把/upload/xxx.jpg当成页面内路径去解析。正确的做法是后端上传接口返回完整的图片URL协议域名相对路径数据库里存的也是完整URL。这样无论哪个端拿到数据后直接赋值给image组件的src属性都能正常显示。具体实现时我封装了一个FileController上传成功后根据配置的file.base-url拼接出完整URL返回String relativePath /upload/ fileName; String fullUrl fileBaseUrl relativePath; return Result.success(fullUrl);这里的fileBaseUrl在开发环境配成http://localhost:8080生产环境配成https://your-domain.com不同环境的切换通过SpringBoot的Profile机制实现省心不少。4.4 Vue打包后布局异常Uniapp小白常犯的样式隔离问题热搜词里有个“vue打包后布局异常”我正好遇到过一回。原因是后台项目里有个组件的样式写在了非scoped的全局样式中开发模式下因为组件渲染顺序的问题正好被覆盖一切正常。打包压缩后CSS文件的合并顺序发生了变化全局样式优先级覆盖了组件局部样式页面布局直接乱掉。排查方法很简单在浏览器开发者工具里查看元素的最终计算样式看是哪条CSS规则覆盖了预期样式然后在代码里显式提高选择器优先级或者补一条!important。但更根本的解决办法是所有组件内样式都加上scoped属性全局公共样式放到单独的common.css里按需引入。Uniapp的样式隔离踩坑更隐蔽Uniapp的样式是全局共享的如果你在页面A的style里定义了一个.title类页面B里也可能受影响。建议所有页面级样式都包裹在页面根节点的自定义class下别用太通用的类名。5. 部署上线与日常运维的实用建议5.1 SpringBoot项目打包与服务器部署的完整过程后端部署我用的是最经典的方案Maven打包成Jar包 Systemd守护进程。打包命令很简单在项目根目录执行mvn clean package -DskipTests然后会在target目录下生成一个blog-server.jar。服务器上我提前装好了JDK8和MySQL8然后把Jar包传到服务器某个目录用Systemd配置成系统服务[Unit] DescriptionBlog Server Afternetwork.target [Service] Typesimple Userroot WorkingDirectory/opt/blog ExecStart/usr/bin/java -Xms512m -Xmx512m -jar /opt/blog/blog-server.jar Restarton-failure [Install] WantedBymulti-user.target-Xms512m -Xmx512m是我根据博客流量配置的堆内存大小个人博客512MB完全够用不用给太多省得内存被占满影响同服务器上的其他服务。数据库的备份我用了crontab定时执行的方案每晚自动导出SQL文件并保留最近7天0 2 * * * mysqldump -uroot -ppassword blog /backup/blog_$(date \%Y\%m\%d).sql find /backup -name blog_*.sql -mtime 7 -delete这套自动化备份流程看起来很简单但真到了数据被误删需要恢复的那天你会感激当时顺手写下的这几行命令。5.2 Vue和Uniapp的构建产物怎么部署到NginxVue管理后台构建后生成的是静态文件部署起来最简单。把dist目录里的内容传到服务器的/usr/share/nginx/html/admin目录然后在Nginx配置里做一个location指向location /admin/ { alias /usr/share/nginx/html/admin/; try_files $uri $uri/ /admin/index.html; }注意try_files那行很关键否则你在管理后台里刷新某个子路由比如/admin/article/edit/1时Nginx会返回404因为服务器上并没有这个物理路径对应的文件。Uniapp打包的H5产物如果也想部署到同一个Nginx下思路一样只不过要注意它打包出来的首页文件通常是index.html并且里面的静态资源路径默认是根路径/static/如果你把它部署到子目录就一定要在打包前改掉manifest.json里的base路径。5.3 H5嵌入微信公众号的定位授权配置备忘热词里提到了“uniapp开发h5嵌入微信公众号中获取定位”这个场景我实际做的时候确实遇到了不少坑。用微信内置浏览器打开H5页面时如果页面需要使用地理位置相关功能统统要依靠微信JS-SDK的授权流程来完成而不是直接在页面里调用浏览器的Geolocation API。整体流程分三步第一步后端通过AppID和AppSecret调用微信接口获取access_token第二步后端拿着access_token和当前页面的URL去生成JS-SDK所需的签名参数第三步前端引入weixin-js-sdk通过wx.config配置签名信息然后在wx.ready回调里调用定位接口。这里有个非常容易踩的雷签名用的URL必须是当前页面完整的URL包括协议、域名、路径和查询参数并且不能做任何encode处理。如果你在使用history路由微信的签名URL会比hash路由更难处理因为URL会随着路由变化而变化每次进入新页面都需要重新算签名。我当时直接把H5定位功能放在了独立的单页里避免这个问题否则每次路由跳转都要重新请求后端获取签名体验会很差。另外记得在微信公众平台的“公众号设置-功能设置-JS接口安全域名”里加上你的H5域名否则wx.config直接失败wx.error里会提示“invalid signature”。6. 个人心得与几个值得留意的细节整个项目从数据库设计到三端上线前后花了两周多的业余时间。回头看这套Uniapp SpringBoot Vue的组合对个人博客来说确实是一个非常有性价比的技术方案。Uniapp让移动端覆盖变成了“写一遍到处编译”SpringBoot让后端开发保持着非常顺畅的节奏Vue则让管理后台的界面做得既能看又能用。有几个细节如果你正在做类似项目可以提前留意一下。一是数据库字段尽量设计得宽裕一点。比如文章摘要字段我一开始只给了200字符结果后来想展示更长的摘要时发现不够用又要改表结构。这种改动虽然不复杂但在生产环境涉及到已有数据的转换还是很麻烦的。二是接口的返回时间格式一定要统一。我在最初几个接口里直接在实体类上用了JsonFormat注解后来才发现有的接口返回的是时间戳有的返回的是格式化后的字符串前端对时间做排序和显示时逻辑非常混乱。后面我统一在配置文件里设置全局格式并且规定所有接口一律返回yyyy-MM-dd HH:mm:ss格式的字符串这个问题才彻底解决。三是如果你也用Uniapp一定要尽早规划条件编译的使用场景。Uniapp支持在代码中通过注释条件编译来区分平台比如#ifdef H5、#ifndef MP-WEIXIN等。我在做分享功能时H5端和小程序端的分享API完全不同如果没有条件编译代码会写得很丑陋。用上条件编译后每个平台只保留自己需要的逻辑可读性大大提升。四是流量统计别忽略了。在文章详情页加入浏览量计数功能时我只在进入页面时调了一次后端接口累加view_count后来发现刷一次就算一次数据太虚。改进方案是通过后端接口判断同一个IP在5分钟内只算一次浏览虽然实现稍微复杂了一点但统计结果可靠很多。这个项目后续如果继续扩展我准备加上文章的全站搜索目前只有标题模糊搜索、文章的定时发布功能以及通过邮件发送评论回复通知。这些都是在不改变现有架构的情况下就能做的增量功能等做完后再找机会把完整的扩展经验整理出来分享给大家。
返回列表