uniapp+node.js前后端做帖子模块:发布帖子(社区管理平台的小程序)

@TOC


👍 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!


0前提

温馨提示:我做的思路可能是复杂化了或者说代码写的不规范,如果你觉得可以更加简便的话欢迎分享到评论区或者自己改写一下我的代码,我的后端是写的很简单的没有什么路由分发是直接写的,你可以自由优化 小程序的其他部分你可以看看我往期的文章

1.一些准备

1.1表

帖子表 post

字段名称 类型(长度) 允许空 主键 外键 自增 唯一 说明
id int 帖子id
title varchar(20) 标题
content varchar(20) 内容
images varchar(200) 详情表
classification varchar(20) 帖子分类
likes int 点赞数
comments int 评论数
shares int 分享数
userId int 用户id
communityId int 小区id
creatTime timestamp 创建时间
updateTime timestamp 数据改变时的时间

1.2总体思路

用户可以在首页或者是在帖子详情的页面去点击一个按钮然后跳转到发布帖子的页面,填写完信息之后点击发布,后端接受信息保存到数据库中,点击发布后自动返回上一页,并且如果返回的是首页还需要重新获取一遍帖子列表的数据

2.前端

前端:当进入发帖页时还需要去阻拦一下用户,查看一下用户有没有登陆,如果登录之后才可以进入到这个发帖页(我这里是没有写的是直接默认根据用户登陆了,写的话思路就是查询本地存储是否有token和用户信息)。当进入发帖页之后用户需要去填写这个帖子的标题、内容、上传图片(我这里是没有去限制最多上传多少个图片的),选择帖子的分类(我把帖子的分类写死了的,你们可以写活)填写完这些信息之后点击发布就开始调用发帖的方法了。因为我的这个小程序是平台多个小区,所以就有设置用户在当前哪一个小区发帖,这个帖子就归属到那个小区去。 如果信息没有完整就需要去提示一下用户需要讲信息填写完整 所以总计传入后端的信息有:帖子标题、内容、图片字符串、分类名字、用户id、小区id

xml 复制代码
<template>
  <view>
    <view class="container">
      <view class="input-container">
        <view class="input-item">
          <text class="input-label">帖子标题:</text>
          <input type="text" v-model="post.title" class="input-field" placeholder="请输入帖子标题" />
        </view>
        <view class="input-item">
          <text class="input-label">帖子内容:</text>
          <textarea v-model="post.content" class="input-field" placeholder="请输入帖子内容"></textarea>
        </view>
        <view class="input-item">
          <text class="input-label">选择图片:</text>
          <button @click="chooseImage">上传图片</button>
          <!--          <image v-if="post.image" :src="post.image" class="post-image" mode="aspectFill" /> -->
        </view>
        <view class="image-container">
          <view v-for="(image, index) in images" :key="index" class="image-item">
            <image :src="image" mode="aspectFit" class="image-src"></image>
          </view>
        </view>
        <view class="input-item">
          <text class="input-label">选择分类:</text>
          <picker mode="selector" :range="classification" v-model="selectedCategoryIndex" @change="categoryChange">
            <view class="picker">当前选择:{{ classification[selectedCategoryIndex] }}</view>
          </picker>
        </view>
      </view>
      <view class="button-container">
        <button @click="publishPost">发布帖子</button>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      images: [], // 存储已上传图片的数组
      post: {
        title: '',
        content: '',
        images: '', // 存储已上传图片的数组
        classification: ''
      },
      classification: ['分类1', '分类2', '分类3', '分类4'],
      selectedCategoryIndex: 0
    };
  },
  methods: {
    //选择图片进行上传
    chooseImage() {
      uni.chooseImage({
        count: 1,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          const tempFilePaths = res.tempFilePaths;
          this.images.push(tempFilePaths[0]);
        }
      });
    },
    //选择分类
    categoryChange(e) {
      this.selectedCategoryIndex = e.detail.value;
    },
    //发布帖子
    async publishPost() {
      this.post.classification = this.classification[this.selectedCategoryIndex];
      this.post.images = this.images.join(',');
      console.log(this.post.categorie);
      if (!this.post.title || !this.post.content || !this.post.images || !this.post.classification) {
        uni.showToast({
          title: '请填写完整信息',
          icon: 'none'
        });
        return;
      }
      const res = await this.$myRequest({
        method: 'post',
        url: '/fatie',
        data: {
          title: this.post.title,
          content: this.post.content,
          images: this.post.images,
          classification: this.post.classification,
          userId: this.$store.state.user.id,
          communityId: this.$store.state.communityId
        }
      });
      uni.showToast({
        title: '发布成功',
        icon: 'success'
      });
    }
  }
};
</script>

3.后端

后端:当接受到前端传来的信息之后到数据库里面去新增这一条帖子信息,这里也是需要验证用户信息的就是验证前端传来的token解析之后是否和传来的用户id是一致的(不过我没加😊,这个验证可以自己搞搞加

xml 复制代码
<template>
  <view>
    <view class="container">
      <view class="input-container">
        <view class="input-item">
          <text class="input-label">帖子标题:</text>
          <input type="text" v-model="post.title" class="input-field" placeholder="请输入帖子标题" />
        </view>
        <view class="input-item">
          <text class="input-label">帖子内容:</text>
          <textarea v-model="post.content" class="input-field" placeholder="请输入帖子内容"></textarea>
        </view>
        <view class="input-item">
          <text class="input-label">选择图片:</text>
          <button @click="chooseImage">上传图片</button>
          <!--          <image v-if="post.image" :src="post.image" class="post-image" mode="aspectFill" /> -->
        </view>
        <view class="image-container">
          <view v-for="(image, index) in images" :key="index" class="image-item">
            <image :src="image" mode="aspectFit" class="image-src"></image>
          </view>
        </view>
        <view class="input-item">
          <text class="input-label">选择分类:</text>
          <picker mode="selector" :range="classification" v-model="selectedCategoryIndex" @change="categoryChange">
            <view class="picker">当前选择:{{ classification[selectedCategoryIndex] }}</view>
          </picker>
        </view>
      </view>
      <view class="button-container">
        <button @click="publishPost">发布帖子</button>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      images: [], // 存储已上传图片的数组
      post: {
        title: '',
        content: '',
        images: '', // 存储已上传图片的数组
        classification: ''
      },
      classification: ['分类1', '分类2', '分类3', '分类4'],
      selectedCategoryIndex: 0
    };
  },
  methods: {
    //选择图片进行上传
    chooseImage() {
      uni.chooseImage({
        count: 1,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera'],
        success: (res) => {
          const tempFilePaths = res.tempFilePaths;
          this.images.push(tempFilePaths[0]);
        }
      });
    },
    //选择分类
    categoryChange(e) {
      this.selectedCategoryIndex = e.detail.value;
    },
    //发布帖子
    async publishPost() {
      this.post.classification = this.classification[this.selectedCategoryIndex];
      this.post.images = this.images.join(',');
      console.log(this.post.categorie);
      if (!this.post.title || !this.post.content || !this.post.images || !this.post.classification) {
        uni.showToast({
          title: '请填写完整信息',
          icon: 'none'
        });
        return;
      }
      const res = await this.$myRequest({
        method: 'post',
        url: '/fatie',
        data: {
          title: this.post.title,
          content: this.post.content,
          images: this.post.images,
          classification: this.post.classification,
          userId: this.$store.state.user.id,
          communityId: this.$store.state.communityId
        }
      });
      uni.showToast({
        title: '发布成功',
        icon: 'success'
      });
    }
  }
};
</script>
相关推荐
程序员码歌1 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
用户21411832636022 小时前
免费玩转 AI 编程!Claude Code Router + Qwen3-Code 实战教程
前端
小小愿望3 小时前
前端无法获取响应头(如 Content-Disposition)的原因与解决方案
前端·后端
小小愿望3 小时前
项目启功需要添加SKIP_PREFLIGHT_CHECK=true该怎么办?
前端
烛阴3 小时前
精简之道:TypeScript 参数属性 (Parameter Properties) 详解
前端·javascript·typescript
海上彼尚4 小时前
使用 npm-run-all2 简化你的 npm 脚本工作流
前端·npm·node.js
开发者小天4 小时前
为什么 /deep/ 现在不推荐使用?
前端·javascript·node.js
如白驹过隙5 小时前
cloudflare缓存配置
前端·缓存
excel5 小时前
JavaScript 异步编程全解析:Promise、Async/Await 与进阶技巧
前端
Jerry说前后端5 小时前
Android 组件封装实践:从解耦到架构演进
android·前端·架构