从零搭建招新小程序:微信云开发 + Dify AI 实战

本文记录了为 AIU(人工智能联盟)协会开发招新报名小程序的完整过程,涵盖技术选型、架构设计、核心功能实现和踩坑经验。

项目背景

每年开学季,学生社团都需要处理大量招新报名工作——收集信息、筛选面试、通知结果。传统做法是纸质表格 +微信群 +Excel 手动管理,效率低且容易出错。

作为某组织技术部部长,我决定用技术解决这个问题:开发一个微信小程序,将整个招新流程线上化。学生在线报名,管理员在线审核,录取结果实时可查,还顺手接入了一个 AI 助手来回答新生关于协会的常见问题。
源码:https://github.com/Linmoqian/AIU_Registration_Mini_Program

技术选型

维度 方案 理由
前端框架 微信小程序原生 无需额外学习成本,性能最优
后端服务 微信云开发 免服务器运维,天然集成微信生态
数据库 云数据库(文档型) 无需建表,灵活应对字段变化
文件存储 云存储 头像图片直传,无需搭建 OSS
AI 能力 Dify 聊天机器人 低代码搭建知识库,SSE 流式响应

这套方案的核心理念是:用最少的运维成本,交付最多的功能。云开发免去了服务器采购、域名备案、SSL 证书等繁琐步骤,让我能把精力集中在业务逻辑上。

架构设计

┌─────────────────────────────────────────────┐
│              微信小程序(前端)                │
│  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────────┐ │
│  │了解协会│  │ 在线  │  │ 录取  │  │ AI 助手  │ │
│  │      │  │ 报名  │  │ 查询  │  │(Dify)   │ │
│  └──────┘  └──────┘  └──────┘  └──────────┘ │
│                  │                           │
│         ┌───────┴───────┐                    │
│         │  管理员后台     │                    │
│         │ (隐藏入口)     │                    │
│         └───────────────┘                    │
└────────────────────┬────────────────────────┘
                     │ 云调用 / HTTP
┌────────────────────┴────────────────────────┐
│            云函数(统一入口)                   │
│  getOpenId · signupSubmit · signupGetStatus  │
│  adminUpsertAdmission · difyChat             │
└──────┬─────────────┬───────────────┬────────┘
       │             │               │
  ┌────▼────┐  ┌─────▼─────┐  ┌─────▼─────┐
  │ 云数据库  │  │  云存储    │  │  Dify API  │
  │ signup   │  │  头像图片  │  │  聊天机器人 │
  │ admissions│  │           │  │           │
  └─────────┘  └───────────┘  └───────────┘

所有云函数走 quickstartFunctions 统一入口,通过 action 字段路由到不同处理逻辑。这样做的好处是只部署一个云函数,减少冷启动开销。

核心功能实现

1. 报名系统:多页表单 + 草稿自动保存

在这里插入图片描述

报名表单字段较多(基本信息、学业信息、志愿选择、个人材料),全部塞在一个页面体验很差。我采用了左右滑动分页的方式:

第1页:姓名、手机、微信、出生日期、性别、政治面貌
第2页:学院、年级、专业班级
第3页:第一志愿、第二志愿、是否服从调剂、个人简介、头像

草稿自动保存是刚需——用户填到一半退出小程序,回来数据不能丢。实现很简单,每次字段变化都写入本地 Storage:

// 表单数据变化时自动保存草稿
onFieldChange(e) {
  const { field, value } = e.detail;
  this.setData({ [`formData.${field}`]: value });
  wx.setStorageSync('signupDraft', this.data.formData);
},

// 页面加载时恢复草稿
onLoad() {
  const draft = wx.getStorageSync('signupDraft');
  if (draft) {
    this.setData({ formData: draft });
  }
}

提交时通过 openid 做 upsert(有则更新,无则新增),防止重复报名:

// 云函数端:基于 openid 的 upsert
const db = cloud.database();
const existing = await db.collection('signup')
  .where({ openid })
  .get();

if (existing.data.length > 0) {
  await db.collection('signup')
    .doc(existing.data[0]._id)
    .update({ data: formData });
} else {
  await db.collection('signup')
    .add({ data: { ...formData, openid } });
}

2. 录取查询:三阶段进度条

录取状态分三个阶段:未报名 → 面试中 → 已录取/已拒绝。前端用进度条直观展示:

┌──────────┐    ┌──────────┐    ┌──────────┐
│  未报名   │───▶│  面试中   │───▶│  已录取   │
│  (灰色)  │    │  (蓝色)   │    │  (绿色)   │
└──────────┘    └──────────┘    └──────────┘
                                    或
                                ┌──────────┐
                                │  已拒绝   │
                                │  (红色)   │
                                └──────────┘

查询逻辑很简单:根据用户 openid 去 signupadmissions 两个集合联合查询,返回最新状态。
在这里插入图片描述

3. AI 助手:Dify 流式对话

这是整个项目最有意思的部分。通过 Dify 平台搭建了一个协会知识库机器人,新生可以直接问"协会有哪些部门"、"面试流程是什么"之类的问题。

在这里插入图片描述

小程序端通过云函数代理调用 Dify API,实现 SSE 流式响应:

// 云函数端:代理 Dify 聊天请求
const axios = require('axios');

exports.difyChat = async (event) => {
  const { message, conversationId } = event;
  const response = await axios({
    method: 'post',
    url: `${DIFY_API_BASE}/v1/chat-messages`,
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    data: {
      inputs: {},
      query: message,
      response_mode: 'blocking',
      conversation_id: conversationId || undefined,
      user: event.openid,
    },
  });
  return response.data;
};

聊天界面用了 scroll-view 组件实现消息列表自动滚动到底部,支持多轮对话,聊天记录缓存到本地。

4. 管理员后台:隐藏入口设计

管理后台不适合暴露给普通用户,但又需要方便管理员访问。我设计了一个小彩蛋:

// 在 Logo 上监听连续点击
onLogoTap() {
  this.tapCount = (this.tapCount || 0) + 1;
  if (this.tapCount >= 8) {
    this.tapCount = 0;
    wx.navigateTo({ url: '/pages/admin/login' });
  }
  // 3秒内未达到8次则重置
  clearTimeout(this.tapTimer);
  this.tapTimer = setTimeout(() => {
    this.tapCount = 0;
  }, 3000);
}

管理员登录后可以:

  • 查看所有报名学生列表
  • 按部门/状态筛选
  • 按姓名/手机号搜索
  • 查看学生详情(含头像)
  • 执行录取/拒绝操作并指定录取部门

5. HTTP 接口:打通外部系统

除了小程序端,还暴露了 HTTP 接口供协会官网调用:

POST /api/signup          → 网站报名(手机号去重)
GET  /api/status?mobile=  → 查询录取状态
POST /api/admissions      → 录取操作(Token 认证)

这样官网和小程序共享同一套数据,学生通过任一渠道报名都能统一管理。

踩坑记录

云函数冷启动

云函数首次调用有明显的冷启动延迟(1-3秒)。解决方案是在用户进入小程序时预调用一次 getOpenId,把云函数"热"起来,后续操作就不会卡了。

小程序域名白名单

Dify API 域名 api.dify.ai 需要在微信小程序后台的"服务器域名"中添加为合法域名,否则正式版无法请求。开发阶段可以在开发者工具中勾选"不校验合法域名"来绕过。

openid 的安全性

openid 是用户的唯一标识,但不能直接暴露给前端做权限判断。管理员的 openid 列表存储在云函数环境变量中,前端只知道"我是谁",后端才决定"我能做什么"。

项目结构

AIU报名小程序/
├── cloudfunctions/
│   └── quickstartFunctions/     # 统一云函数入口
│       ├── index.js             # 主逻辑(路由到不同 action)
│       └── package.json
├── miniprogram/
│   ├── app.js                   # 全局配置(云环境、Dify Key)
│   ├── app.json                 # 路由、TabBar
│   ├── pages/
│   │   ├── about/               # 了解协会(首页)
│   │   ├── apply/               # 在线报名(多页表单)
│   │   ├── query/               # 录取查询(进度条)
│   │   ├── chat/                # AI 助手(Dify)
│   │   └── admin/               # 管理员后台
│   │       ├── login            # 密码登录
│   │       ├── index            # 学生列表(筛选/搜索)
│   │       └── detail           # 学生详情 + 录取操作
│   └── images/
└── project.config.json

后续规划

  1. 完善管理员界面:增加批量操作、数据导出等功能
  2. 内嵌协会官网:等官网升级 HTTPS 后通过 web-view 组件嵌入
  3. 企业认证上线:目前小程序还在体验版阶段,完成企业认证后才能正式发布

总结

这个项目让我深刻体会到云开发对个人开发者和小团队的效率提升——不用折腾服务器,不用操心部署,写完代码直接上传就能用。Dify 的接入也让协会咨询这个痛点变得简单,不用人工重复回答相同的问题。

如果你也在做类似的社团/组织管理系统,微信云开发 + Dify 的组合值得一试。


本文为项目实战记录,源码仅供 AIU 协会内部使用。如有技术问题欢迎交流。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐