You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Sails JS实现四步分步注册表单的技术咨询

嘿,我来帮你搞定这个四步注册的事儿!基于你已经有了一次性提交的基础接口,咱们可以从路由拆分、用户状态保持、分步视图渲染这几个核心点入手,下面是具体的实现思路和代码示例:

核心思路

因为是多步表单,关键要解决两个问题:一是每一步提交后能关联到同一个用户条目,二是防止用户跳过步骤直接访问后续页面。这里咱们用Sails自带的Session来存储当前用户ID,既安全又方便。

第一步:初始化用户条目并跳转

这一步负责收集email和password,创建用户基础条目后跳转到第二步。

1. 配置路由(config/routes.js)

先给第一步加两个路由:一个用于展示表单,一个用于处理提交:

// 注册第一步:展示表单
'GET /signup/step1': 'AuthController.showSignupStep1',
// 注册第一步:处理提交
'POST /signup/step1': 'AuthController.processSignupStep1',

2. 控制器逻辑(api/controllers/AuthController.js)

实现两个方法:展示表单和处理提交逻辑,注意要做输入验证和邮箱唯一性检查:

// 展示第一步表单
async showSignupStep1(req, res) {
  // 如果用户已经有session(比如中途返回),可以跳回对应步骤
  if (req.session.userId) {
    const user = await User.findOne({ id: req.session.userId });
    if (!user.zipCode) {
      return res.redirect('/signup/step2');
    }
    return res.redirect('/signup/step3');
  }
  // 渲染第一步视图,传递可能的错误信息
  return res.view('signup/step1', { error: req.flash('error') });
}

// 处理第一步提交
async processSignupStep1(req, res) {
  try {
    // 验证输入格式
    const validatedData = await req.validate({
      email: 'email|required',
      password: 'string|minLength:6|required'
    });

    // 检查邮箱是否已被注册
    const existingUser = await User.findOne({ email: validatedData.email });
    if (existingUser) {
      req.flash('error', '该邮箱已被注册');
      return res.redirect('/signup/step1');
    }

    // 创建用户基础条目,其他字段留空或设默认值
    const newUser = await User.create({
      email: validatedData.email,
      // 用Sails自带的密码加密助手
      password: await sails.helpers.passwords.hashPassword(validatedData.password),
      zipCode: null
    }).fetch();

    // 将用户ID存入Session,用于后续步骤关联
    req.session.userId = newUser.id;

    // 跳转到第二步
    return res.redirect('/signup/step2');
  } catch (err) {
    req.flash('error', err.message);
    return res.redirect('/signup/step1');
  }
}

3. 第一步视图(views/signup/step1.ejs)

简单的表单页面,带上错误提示:

<h2>注册第一步:账号信息</h2>
<form action="/signup/step1" method="POST">
  <!-- 别忘了加CSRF令牌,Sails默认启用 -->
  <input type="hidden" name="_csrf" value="<%= _csrf %>">
  
  <div>
    <label>邮箱:</label>
    <input type="email" name="email" required>
  </div>
  <div>
    <label>密码:</label>
    <input type="password" name="password" minlength="6" required>
  </div>
  <% if (error.length) { %>
    <p style="color:red"><%= error[0] %></p>
  <% } %>
  <button type="submit">进入第二步</button>
</form>
第二步:收集Zip Code并更新用户

这一步负责收集zipCode,更新已创建的用户条目后跳转到第三步。

1. 配置路由(config/routes.js)

同样添加两个路由:

// 注册第二步:展示表单
'GET /signup/step2': 'AuthController.showSignupStep2',
// 注册第二步:处理提交
'POST /signup/step2': 'AuthController.processSignupStep2',

2. 控制器逻辑(api/controllers/AuthController.js)

注意要先检查Session里的用户ID,防止直接访问:

// 展示第二步表单
async showSignupStep2(req, res) {
  // 没有Session则跳回第一步
  if (!req.session.userId) {
    return res.redirect('/signup/step1');
  }
  // 获取当前用户信息,用于回填表单(如果之前提交出错)
  const user = await User.findOne({ id: req.session.userId });
  return res.view('signup/step2', { user, error: req.flash('error') });
}

// 处理第二步提交
async processSignupStep2(req, res) {
  try {
    if (!req.session.userId) {
      return res.redirect('/signup/step1');
    }

    // 验证邮编格式(根据你的需求调整规则)
    const validatedData = await req.validate({
      zipCode: 'string|minLength:5|maxLength:10|required'
    });

    // 更新用户的邮编信息
    await User.updateOne({ id: req.session.userId }).set({ zipCode: validatedData.zipCode });

    // 跳转到第三步
    return res.redirect('/signup/step3');
  } catch (err) {
    req.flash('error', err.message);
    return res.redirect('/signup/step2');
  }
}

3. 第二步视图(views/signup/step2.ejs)

渲染邮编表单,支持回填已输入的内容:

<h2>注册第二步:地址信息</h2>
<form action="/signup/step2" method="POST">
  <input type="hidden" name="_csrf" value="<%= _csrf %>">
  
  <div>
    <label>邮编:</label>
    <input type="text" name="zipCode" value="<%= user.zipCode || '' %>" required>
  </div>
  <% if (error.length) { %>
    <p style="color:red"><%= error[0] %></p>
  <% } %>
  <button type="submit">进入第三步</button>
</form>
第三步:展示相关内容

这一步负责展示注册进度、已填信息汇总,或者后续操作引导。

1. 配置路由(config/routes.js)

添加展示路由:

// 注册第三步:展示内容
'GET /signup/step3': 'AuthController.showSignupStep3',

2. 控制器逻辑(api/controllers/AuthController.js)

同样检查Session,然后获取用户信息传递给视图:

// 展示第三步内容
async showSignupStep3(req, res) {
  if (!req.session.userId) {
    return res.redirect('/signup/step1');
  }

  const user = await User.findOne({ id: req.session.userId });
  // 可以在这里做一些注册完成后的逻辑,比如发送验证邮件
  // await sails.helpers.sendVerificationEmail(user);

  // 渲染第三步视图
  return res.view('signup/step3', { user });
}

3. 第三步视图(views/signup/step3.ejs)

展示注册完成的确认信息:

<h2>注册进度完成!</h2>
<div class="summary">
  <p>你的邮箱:<%= user.email %></p>
  <p>你的邮编:<%= user.zipCode %></p>
</div>
<p>感谢注册,接下来可以:</p>
<ul>
  <li><a href="/login">前往登录</a></li>
  <li><a href="/profile">完善个人资料</a></li>
</ul>
额外注意事项
  • CSRF防护:Sails默认启用CSRF,所以表单里一定要加_csrf隐藏字段,否则提交会失败。
  • Session配置:确保你的Sails项目已经启用Session(默认是开启的,可在config/session.js里调整)。
  • 错误处理:这里用了Sails的flash消息传递错误,比直接把错误挂在URL上更友好。
  • 跳过步骤拦截:每个步骤的控制器都要检查Session里的userId,防止用户直接输入URL跳过步骤。
  • 扩展性:如果后续要加第四步,只需要重复类似的路由、控制器、视图逻辑即可。

内容的提问来源于stack exchange,提问作者qvdp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:46:25