从零开发校园墙微信小程序(4)——实现内容投稿功能


一、投稿页面设计(信息收集站)

1.1 页面结构分解

<template>
  <nut-form>
    <!-- 图片上传区域 -->
    <nut-form-item label="图片">
      <view class="image-container">
        <!-- 图片预览 -->
        <view v-for="(image, index) in formData.imageList" 
              :key="index"
              @click="previewImage(image)">
          <image :src="image" class="image" />
        </view>
      </view>
      <nut-button @click="chooseImages">选择图片</nut-button>
    </nut-form-item>

    <!-- 文本输入区域 -->
    <nut-form-item>
      <nut-textarea 
        v-model="formData.text" 
        limit-show 
        :max-length="130" />
    </nut-form-item>

    <!-- 提交按钮 -->
    <nut-form-item>
      <nut-button type="primary" @click="uploadWeibo">
        上传
      </nut-button>
    </nut-form-item>
  </nut-form>

  <notify ref="notifyRef" />
</template>

组件选择理由

  • nut-form: 提供表单校验和布局功能
  • nut-textarea: 自带字数统计功能
  • nut-button: 统一按钮交互样式

二、核心功能实现

2.1 图片选择与预览

const chooseImages = async () => {
  const res = await Taro.chooseImage({
    count: 1, // 微信小程序限制最多9张
    sizeType: ["original", "compressed"],
    sourceType: ["album", "camera"]
  });
  formData.value.imageList = res.tempFilePaths;
};

const previewImage = (url) => {
  Taro.previewImage({
    current: url,
    urls: formData.value.imageList
  });
};

注意事项

  1. 微信小程序临时路径有效期仅一次会话
  2. 安卓/iOS系统相机权限处理
  3. 图片压缩策略选择

2.2 投稿表单提交

const uploadWeibo = async () => {
  if (formData.value.text.length < 1) {
    showNotify('warning', '字数太少啦');
    return;
  }

  try {
    const params = {
      text: formData.value.text,
      mode: 0,
      openid: Taro.getStorageSync("loginId"),
      sessionId: Taro.getStorageSync("session_key")
    };

    const res = formData.value.imageList.length > 0 
      ? await uploadWithImage(params)
      : await uploadTextOnly(params);

    handleUploadResult(res);
  } catch (error) {
    showNotify('danger', '投稿失败');
  }
};

三、服务层对接

3.1 投稿API封装

export const contribute = (url, text, mode) => {
  return new Promise((resolve, reject) => {
    if (url) {
      // 带图片投稿
      Taro.uploadFile({
        url: API_ROOT + '/weibo/sendStatus',
        filePath: url,
        name: 'file',
        formData: {
          ...commonParams,
          text, mode
        }
      }).then(resolve).catch(reject);
    } else {
      // 纯文本投稿
      Taro.request({
        url: API_ROOT + '/weibo/sendStatusForText',
        method: 'POST',
        data: {
          ...commonParams,
          text, mode
        }
      }).then(resolve).catch(reject);
    }
  });
};

关键参数说明

参数名来源作用
openid微信登录获取用户唯一标识
sessionId微信登录会话密钥接口鉴权
text用户输入投稿内容
mode业务类型标识区分不同投稿类型

四、用户体验优化

4.1 交互反馈设计

// 显示通知
const showNotify = (type, msg) => {
  notifyRef.value.notify.showMessage(type, msg);
};

// 提交结果处理
const handleUploadResult = (res) => {
  if (res.code >= 200 && res.code <= 400) {
    showNotify('success', res.message);
    setTimeout(() => Taro.navigateBack(), 3000);
  } else {
    showNotify('danger', res.message);
  }
};

4.2 防重复提交

const isSubmitting = ref(false);

const uploadWeibo = async () => {
  if (isSubmitting.value) return;
  
  isSubmitting.value = true;
  try {
    // ...提交逻辑
  } finally {
    isSubmitting.value = false;
  }
};

五、安全与异常处理

5.1 敏感内容过滤

// 在提交前进行校验
const validateContent = (text) => {
  const forbiddenWords = ['暴力', '色情', '政治'];
  return !forbiddenWords.some(word => text.includes(word));
};

5.2 错误类型处理

错误码处理方案
401跳转到登录页面
413提示图片过大
500显示"系统繁忙"提示

六、最佳实践建议

  1. 图片上传优化

    // 压缩图片示例
    const compressImage = async (filePath) => {
      return await Taro.compressImage({
        src: filePath,
        quality: 70
      });
    };
  2. 草稿保存功能

    // 监听输入变化
    watch(() => formData.value, (val) => {
      Taro.setStorageSync('draft', val);
    }, { deep: true });
  3. 加载状态反馈

    <nut-button 
      :loading="isSubmitting"
      :disabled="isSubmitting">
      上传中...
    </nut-button>

下一步计划

  1. 内容展示列表开发
  2. 评论互动功能实现
  3. 消息推送系统集成

"好的投稿功能就像校园公告栏——既要方便发布,又要保证内容质量。在实现基础功能后,持续优化用户体验才是关键!"
最后修改:2025 年 04 月 13 日
如果觉得我的文章对你有用,请随意赞赏