【Uni-App+SSM 宠物项目实战】Day13:商家注册

102 阅读10分钟

一、前言

欢迎回到mypet项目实战!🏪 今天我们开启商家端核心功能—— 实现 “商家注册” 模块。平台用户(普通用户)通过提交营业执照、店铺信息等资料,完成商家身份认证后,即可在平台发布宠物用品销售、美容服务等业务,这是连接 “用户需求” 与 “商家服务” 的关键桥梁。

本次实现的核心难点是 “多图上传”(如营业执照 + 店铺门面照),前端通过uni.chooseImage多选图片,循环调用uni.uploadFile上传至后端FileController,后端用 Hutool 工具类校验文件合法性,最终将图片 URL 存入shangjia(商家表)。即使是零基础,也能通过 “分步代码 + 注释解析” 掌握多图上传与商家信息提交的全流程。

📌 学习目标

  1. 掌握 Hutool 的Validator工具类,实现图片格式、文件合法性校验;
  1. 熟练使用uni.chooseImage+uni.uploadFile完成多图选择与循环上传;
  1. 理解 “多图 URL 拼接存储” 逻辑(适配数据库单字段存储多图);
  1. 解决 “上传顺序混乱”“文件大小超限”“商家状态初始化” 等实战问题。

二、前置准备

开始编码前,请确认以下内容已就绪,避免开发受阻:

项目检查内容注意事项
基础依赖1. Day10 登录态正常(需 Token 验证,避免匿名注册);2. Day11 的FileController上传接口可用;3. Hutool 依赖已引入(用于文件校验)若FileController不可用,需先回顾 Day11 代码;Hutool 版本建议与 Day9 一致(4.0.12),避免兼容性问题
数据库表结构shangjia(商家表)需包含以下字段:id(主键)、user_id(关联注册用户 ID)、shangjiamingcheng(商家名称)、zhizhao(营业执照 URL,多图用逗号分隔)、dianpumianmao(店铺门面照 URL,可选)、lianxidianhua(联系电话)、zhuangtai(审核状态:0 - 待审核,1 - 已通过,2 - 已拒绝)、beizhu(备注)若表 / 字段缺失,执行建表 SQL:sqlCREATE TABLE shangjia (id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, shangjiamingcheng VARCHAR(100) NOT NULL, zhizhao VARCHAR(500) NOT NULL, lianxidianhua VARCHAR(20) NOT NULL, zhuangtai TINYINT DEFAULT 0 COMMENT '0-待审核,1-已通过,2-已拒绝');
前端组件1. 已导入 Uni-App 的uni-forms(表单校验)、uni-upload(可选,优化上传体验);2. pages.json配置路由: "pages": [{"path": "pages/shangjia/register","style": {"navigationBarTitleText": "商家注册"}}]若需优化上传 UI,可安装uni-upload组件;路由配置确保页面能正常跳转
文件配置后端config.properties配置多图上传限制:upload.max.size=5242880(单文件最大 5MB)、upload.allow.types=jpg,png,jpeg(允许的图片格式)确保配置文件路径正确,后端能读取到限制参数

三、商家注册流程图

先通过流程图理清 “多图上传→信息填写→提交审核” 的完整逻辑:

flowchart TD 
A[用户进入商家注册页面] --> B[前端加载表单<br>商家名称和电话等输入框] 
B --> C[用户点击上传多图<br> 营业执照加店铺照] 
C --> D[uni.chooseImage多选图片<br>限制最多2张 仅图片格式] 
D --> E[循环调用uni.uploadFile<br>携带Token 调用FileController] 
E --> F{所有图片上传成功} 
F -- 否 --> G[提示部分图片上传失败 请重试] 
F -- 是 --> H[多图URL用逗号拼接<br>如url1 url2] 
H --> I[用户填写其他信息<br>商家名称和联系电话] 
I --> J[点击提交注册<br>前端表单校验] 
J -- 校验失败 --> K[提示商家名称/电话不能为空] 
J -- 校验成功 --> L[携带Token调用/shangjia/register接口<br>传递user_id 多图URL 商家信息] 
L --> M[后端拦截器验证Token<br>解析用户ID 关联商家] 
M -- Token无效 --> N[返回请先登录] 
M -- Token有效 --> O[后端校验 <br>1商家名称非空<br>2营业执照URL非空且格式合法<br>3联系电话格式正确] 
O -- 校验失败 --> P[返回具体错误如营业执照格式无效] 
O -- 校验成功 --> Q[初始化审核状态为0-待审核<br>MP的insert存入shangjia表] 
Q --> R[返回注册提交成功 等待审核] 
R --> S[前端提示成功<br>跳转至商家中心页面]

四、代码实现

4.1 后端:核心接口开发(2 个关键部分)

4.1.1 1. ShangjiaController:商家注册接口(含多图校验)

路径:src/main/java/com/controller/ShangjiaController.java

核心功能:接收商家信息 + 多图 URL→校验合法性→关联用户 ID→初始化审核状态→存入数据库。

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.lang.Validator;
import com.entity.ShangjiaEntity;
import com.entity.YonghuEntity;
import com.service.ShangjiaService;
import com.service.YonghuService;
import com.utils.R;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@RestController
@RequestMapping("/shangjia")
public class ShangjiaController {
    @Autowired
    private ShangjiaService shangjiaService;
    @Autowired
    private YonghuService yonghuService;
    // JWT密钥(与Day10一致)
    private static final String JWT_SECRET = "mypet-secret-2024";
    // 从配置文件读取允许的图片格式(如jpg,png,jpeg)
    @Value("${upload.allow.types}")
    private String allowImageTypes;
    /**
     * 商家注册接口(需登录,Token验证)
     * @param shangjia 前端传递的商家信息(含多图URL、商家名称等)
     * @param request 用于获取Token,解析用户ID
     */
    @PostMapping("/register")
    public R register(@RequestBody ShangjiaEntity shangjia, HttpServletRequest request) {
        //  从Token解析当前登录用户ID(关联商家与用户,避免越权)
        String token = request.getHeader("token");
        Claims claims = Jwts.parser().setSigningKey(JWT_SECRET).parseClaimsJws(token).getBody();
        Long userId = Long.parseLong(claims.getSubject());
        // 校验用户是否存在(避免无效用户注册)
        YonghuEntity user = yonghuService.getById(userId);
        if (user == null) {
            return R.error("注册用户不存在,请重新登录!");
        }
        //  核心校验:商家基础信息(非空+格式)
        // 校验商家名称(非空+长度限制)
        if (StrUtil.isBlank(shangjia.getShangjiamingcheng()) || shangjia.getShangjiamingcheng().length() > 100) {
            return R.error("商家名称不能为空,且长度不超过100字!");
        }
        // 校验联系电话(手机号格式,用Hutool的Validator)
        if (!Validator.isMobile(shangjia.getLianxidianhua())) {
            return R.error("联系电话格式无效,请输入正确的手机号!");
        }
        //  多图URL校验(营业执照必传,且格式合法)
        String zhizhaoUrls = shangjia.getZhizhao();
        if (StrUtil.isBlank(zhizhaoUrls)) {
            return R.error("营业执照必传,请上传至少1张图片!");
        }
        // 分割多图URL(逗号分隔),校验每张图片格式
        String[] urlArray = zhizhaoUrls.split(",");
        String[] allowTypes = allowImageTypes.split(","); // 从配置读取允许的格式
        for (String url : urlArray) {
            // 提取URL后缀(如"http://xxx/1.jpg" → "jpg")
            String suffix = StrUtil.subAfter(url, ".", true);
            // 校验后缀是否在允许列表中
            if (!Arrays.asList(allowTypes).contains(suffix.toLowerCase())) {
                return R.error("营业执照格式无效,仅支持" + allowImageTypes + "格式!");
            }
        }
        //  初始化商家状态(默认“0-待审核”,避免手动设置)
        shangjia.setUserId(userId); // 关联当前用户ID
        shangjia.setZhuangtai((byte) 0); // 0-待审核
        //  MP的save()方法:存入商家数据到数据库
        boolean registerSuccess = shangjiaService.save(shangjia);
        if (registerSuccess) {
            return R.ok("商家注册提交成功,等待平台审核(1-3个工作日)!");
        } else {
            return R.error("注册提交失败,请重试!");
        }
    }
}

📌 后端关键讲解

  • 多图校验逻辑:将逗号分隔的 URL 拆分为数组,循环校验每张图片的后缀是否在允许列表(如 jpg/png),比单纯校验 “是否包含图片后缀” 更严谨;
  • 状态初始化:默认设置zhuangtai=0(待审核),避免前端篡改状态(如直接设置为 “已通过”);
  • 用户关联:从 Token 解析userId,而非依赖前端传递,确保商家与注册用户一一对应,防止越权注册。

4.1.2 2. Service 层:无需自定义实现(MP 原生方法)

路径(Service):src/main/java/com/service/ShangjiaService.java

路径(ServiceImpl):src/main/java/com/service/impl/ShangjiaServiceImpl.java

Service 接口(继承 MP 的IService,获取原生save()方法):

import com.entity.ShangjiaEntity;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ShangjiaService extends IService<ShangjiaEntity> {
    // 无需添加自定义方法,MP的IService已包含save()(新增)、getById()(单查)等
}

ServiceImpl 实现类(继承 MP 的ServiceImpl,自动实现接口方法):

import com.entity.ShangjiaEntity;
import com.mapper.ShangjiaMapper;
import com.service.ShangjiaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ShangjiaServiceImpl extends ServiceImpl<ShangjiaMapper, ShangjiaEntity> implements ShangjiaService {
    // 无需重写save(),父类已实现(底层调用mapper的insert())
}

4.2 前端:完整表单 + 多图上传 + 校验逻辑

路径:pages/shangjia/register.vue

核心功能:多图选择与上传、表单校验、提交注册、状态提示。

<template>
  <view class="merchant-register-page">
    <!-- 表单容器(uni-forms做校验) -->
    <uni-forms 
      ref="registerForm" 
      :model="form" 
      labelWidth="160rpx" 
      @validate="onValidate"
    >
      <!-- 1. 商家名称 -->
      <uni-forms-item 
        label="商家名称" 
        name="shangjiamingcheng" 
        required
        :rules="[{ required: true, errorMessage: '商家名称不能为空' }, { maxLength: 100, errorMessage: '长度不超过100字' }]"
      >
        <input 
          v-model="form.shangjiamingcheng" 
          placeholder="请输入商家名称(如“宠爱之家宠物用品店”)" 
          class="input"
        />
      </uni-forms-item>
      <!-- 2. 联系电话 -->
      <uni-forms-item 
        label="联系电话" 
        name="lianxidianhua" 
        required
        :rules="[{ required: true, errorMessage: '联系电话不能为空' }, { pattern: /^1[3-9]\d{9}$/, errorMessage: '请输入正确的手机号' }]"
      >
        <input 
          v-model="form.lianxidianhua" 
          type="number" 
          placeholder="请输入用于联系的手机号" 
          class="input"
          maxlength="11"
        />
      </uni-forms-item>
      <!-- 3. 多图上传(营业执照+店铺门面照) -->
      <uni-forms-item 
        label="营业执照上传" 
        required
        :error-message="formErrors.zhizhao"
      >
        <!-- 上传按钮 -->
        <button 
          class="upload-btn" 
          type="default" 
          @click="chooseMultiImages"
        >
          选择图片(最多2张,支持jpg/png)
        </button>
        <!-- 已上传图片预览 -->
        <view class="image-preview-list" v-if="imageUrls.length > 0">
          <view class="image-item" v-for="(url, index) in imageUrls" :key="index">
            <image :src="url" mode="widthFix" class="preview-image"></image>
            <button class="delete-btn" @click="deleteImage(index)">删除</button>
          </view>
        </view>
        <view class="tip-text">提示:需上传清晰的营业执照照片,用于审核</view>
      </uni-forms-item>
      <!-- 4. 提交按钮 -->
      <uni-forms-item class="submit-btn-item">
        <button 
          type="primary" 
          class="submit-btn" 
          @click="submitRegister"
          :disabled="!formValid || isUploading"  <!-- 上传中/表单无效时禁用 -->
        >
          {{ isUploading ? '提交中...' : '提交商家注册' }}
        </button>
      </uni-forms-item>
    </uni-forms>
  </view>
</template>
<script>
// 导入请求工具和Uni-UI组件
import request from '@/api/request.js';
import uniForms from '@dcloudio/uni-ui/lib/uni-forms/uni-forms';
import uniFormsItem from '@dcloudio/uni-ui/lib/uni-forms-item/uni-forms-item';
export default {
  components: { // 注册组件
    uniForms,
    uniFormsItem
  },
  data() {
    return {
      form: { // 商家注册表单数据
        shangjiamingcheng: '',  // 商家名称
        lianxidianhua: '',      // 联系电话
        zhizhao: ''             // 营业执照多图URL(逗号分隔,提交时赋值)
      },
      imageUrls: [],            // 已上传的图片URL列表(前端预览用)
      formErrors: {},           // 自定义错误提示(如多图上传错误)
      formValid: false,         // 表单整体是否校验通过
      isUploading: false,       // 是否正在上传中(防止重复提交)
      uploadCount: 0            // 已完成上传的图片数量(用于判断是否全部上传成功)
    };
  },
  methods: {
    // 1. 选择多图(最多2张)
    chooseMultiImages() {
      // 限制最多上传2张(营业执照至少1张,可选1-2张)
      const maxCount = 2;
      if (this.imageUrls.length >= maxCount) {
        return uni.showToast({ title: `最多只能上传${maxCount}张图片`, icon: 'none' });
      }
      uni.chooseImage({
        count: maxCount - this.imageUrls.length, // 剩余可选择数量
        sizeType: ['original', 'compressed'],    // 原图/压缩图(压缩图更省流量)
        sourceType: ['album', 'camera'],         //相册 / 相机选图

    success: (chooseRes) => {

    // 开始上传选中的图片(循环上传)

    this.isUploading = true;

    this.uploadCount = 0; // 重置上传计数

    const tempPaths = chooseRes.tempFilePaths; // 选中的临时图片路径

    tempPaths.forEach((tempPath, index) => {

    uni.uploadFile({

    url: '<http://localhost:8080/file/upload>', // 后端 FileController 接口

    filePath: tempPath, // 临时图片路径

    name: 'file', // 与后端 MultipartFile 参数名一致

    header: {

    'token': uni.getStorageSync ('mypet_token'), // 携带 Token 验证登录

    'Content-Type': 'multipart/form-data' // 文件上传必须的 Content-Type

    },

    // 上传进度回调(可选,提升体验)

    progress: (progressRes) => {

    console.log (第${index+1}张图上传进度:${progressRes.progress}%);

    },

    success: (uploadRes) => {

    // 解析上传结果(uploadRes.data 默认是字符串,需转 JSON)

    const uploadData = JSON.parse (uploadRes.data);

    if (uploadData.code === 0) {

    // 上传成功:添加 URL 到预览列表

    this.imageUrls.push (uploadData.file);

    } else {

    // 单张上传失败:提示具体错误

    uni.showToast ({ title: 第${index+1}张图上传失败:${uploadData.msg}, icon: 'none' });

    }

    },

    fail: (uploadErr) => {

    // 网络错误等上传失败

    uni.showToast ({ title: 第${index+1}张图上传失败,请重试, icon: 'none' });

    console.error (' 图片上传失败:', uploadErr);

    },

    complete: () => {

    // 无论成功 / 失败,都计数并判断是否全部上传完成

    this.uploadCount++;

    if (this.uploadCount === tempPaths.length) {

    this.isUploading = false; // 所有图片上传完成,取消上传中状态

    // 提示上传结果

    if (this.imageUrls.length > 0) {

    uni.showToast ({ title: 成功上传${this.imageUrls.length}张图片, icon: 'success' });

    }

    }

    }

    });

    });

    },

    fail: (chooseErr) => {

    // 用户取消选图或选图失败

    console.log (' 选图失败:', chooseErr);

    }

    });

    },

    // 2. 删除已上传的图片

    deleteImage (index) {

    // 从预览列表中删除指定索引的图片

    this.imageUrls.splice (index, 1);

    // 若删除后无图片,清除表单中的 zhizhao 字段

    if (this.imageUrls.length === 0) {

    this.form.zhizhao = '';

    } else {

    // 重新拼接 URL(逗号分隔)

    this.form.zhizhao = this.imageUrls.join (',');

    }

    // 重新触发表单校验

    this.$refs.registerForm.validate ();

    },

    // 3. 表单校验回调(判断整体是否通过)

    onValidate (res) {

    //res:uni-forms 自带校验结果(商家名称、联系电话)

    let zhizhaoValid = true; // 营业执照上传校验结果

    // 校验:至少上传 1 张营业执照图片

    if (this.imageUrls.length === 0) {

    this.formErrors.zhizhao = ' 请至少上传 1 张营业执照图片 ';

    zhizhaoValid = false;

    } else {

    this.formErrors.zhizhao = '';

    // 拼接多图 URL(逗号分隔),赋值给表单字段

    this.form.zhizhao = this.imageUrls.join (',');

    }

    // 表单整体校验通过条件:自带校验通过 + 营业执照校验通过

    this.formValid = res.valid && zhizhaoValid;

    },

    // 4. 提交商家注册

    submitRegister () {

    // 再次手动校验,避免极端情况

    this.$refs.registerForm.validate ();

    if (!this.formValid || this.isUploading) {

    return;

    }

    // 防止重复提交

    this.isUploading = true;

    // 调用后端注册接口

    request.post ('/shangjia/register', this.form, {

    headers: {'token': uni.getStorageSync ('mypet_token') }

    })

    .then (res => {

    if (res.data.code === 0) {

    // 注册成功:提示 + 跳转至商家中心

    uni.showToast ({

    title: res.data.msg,

    icon: 'success',

    duration: 2000,

    success: () => {

    // 跳转后关闭当前页(避免返回重复提交)

    uni.redirectTo ({ url: '/pages/shangjia/center' });

    }

    });

    } else {

    // 注册失败:提示错误信息

    uni.showToast ({ title: res.data.msg, icon: 'none' });

    }

    })

    .catch (err => {

    // 网络错误

    uni.showToast ({ title: ' 网络异常,请稍后再试 ', icon: 'none' });

    console.error (' 商家注册请求失败:', err);

    })

    .finally (() => {

    // 无论成功 / 失败,都取消上传中状态

    this.isUploading = false;

    });

    }

    }

    };

五、效果验证

按以下步骤验证商家注册与多图上传功能,确保前后端联动正常:

✅ 1. 后端接口测试(Postman)

测试1:多图上传接口(复用Day11的/file/upload

  1. 请求地址http://localhost:8080/file/upload
  2. 请求方式:POST
  3. 请求头token: 有效登录Token
  4. 请求体form-data格式,key=filevalue选择2张jpg/png图片(分2次上传,模拟前端循环)
  5. 成功返回(单张):
    {
      "code": 0,
      "msg": "上传成功",
      "file": "http://localhost:8080/mypet/upload/123.jpg"
    }
    

测试 2:商家注册接口

  1. 请求地址http://localhost:8080/shangjia/register
  1. 请求方式:POST
  1. 请求头:token: 有效登录Token
  1. 请求体(JSON)
{
  "shangjiamingcheng": "宠爱之家宠物用品店",
  "lianxidianhua": "13812345678",
  "zhizhao": "http://localhost:8080/mypet/upload/123.jpg,http://localhost:8080/mypet/upload/456.jpg"
}
  1. 成功返回
{
  "code": 0,
  "msg": "商家注册提交成功,等待平台审核(1-3个工作日)!"
}
  1. 数据库验证:查询shangjia表,新增数据中user_id为 Token 解析的用户 ID,zhizhao字段为逗号分隔的 2 个 URL,zhuangtai=0(待审核)。

✅ 2. 前端功能测试(Uni-App 模拟器 / 真机)

  1. 登录:通过 Day10 登录页登录,确保mypet_token已存储;
  1. 进入注册页面:跳转至pages/shangjia/register.vue,表单初始为空;
  1. 填写基础信息
    • 商家名称:输入 “宠爱之家宠物用品店”;
    • 联系电话:输入 “13812345678”;
  1. 多图上传
    • 点击 “选择图片”→从相册选 2 张图片(营业执照 + 店铺照);
    • 上传完成后,预览区显示 2 张图片,支持点击删除(删除后预览区同步减少);
  1. 提交注册
    • 点击 “提交商家注册”→按钮显示 “提交中...”(防止重复点击);
    • 提交成功后,弹出 “等待审核” 提示→自动跳转至商家中心页面;
  1. 商家中心验证:商家中心显示 “待审核” 状态,与数据库zhuangtai字段同步。

六、常见问题与排查

问题现象可能原因解决方式
1. 多图上传时部分失败1. 单张图片超过后端大小限制;2. 网络波动导致中断;3. Token 过期1. 检查config.properties的upload.max.size,确保图片不超限(如 5MB);2. 前端添加 “重试上传” 按钮,失败后允许重新上传;3. 上传前校验 Token 有效性,过期则提示重新登录
2. 提交时提示 “请至少上传 1 张营业执照”前端imageUrls为空;或form.zhizhao未拼接 URL1. 检查chooseMultiImages是否正确将上传成功的 URL 添加到imageUrls;2. 确认onValidate中this.form.zhizhao = this.imageUrls.join(',')已执行;3. 打印this.imageUrls,确保提交前非空
3. 后端提示 “营业执照格式无效”1. URL 后缀不在允许列表(如.gif);2. 前端拼接 URL 时多逗号 / 空格1. 检查upload.allow.types配置,确保仅允许jpg,png,jpeg;2. 前端拼接 URL 前去除空值(如this.imageUrls.filter(url => url).join(','));3. 打印zhizhaoUrls,确认后缀合法
4. 数据库zhuangtai字段为 null后端未初始化shangjia.setZhuangtai((byte) 0)1. 检查ShangjiaController的注册逻辑,确保状态初始化代码执行;2. 确认shangjia实体类zhuangtai字段类型为Byte(匹配数据库 TINYINT)
5. 前端点击提交无反应1. formValid=false(表单未通过校验);2. isUploading=true(上传中)1. 检查表单错误提示,确保商家名称、电话、图片均已填写 / 上传;2. 等待上传完成(isUploading变为 false)后再提交;3. 打印this.formValid和this.isUploading,定位禁用原因

七、扩展与提升

7.1 功能优化:多图上传进度条与重试机制

当前上传进度仅打印日志,可优化为可视化进度条:

  1. 前端引入uni-progress组件,为每张上传中的图片显示进度;
  1. 上传失败时,在预览图上显示 “重试” 按钮,点击后重新上传该张图片;
  1. 全部上传完成后,提示 “共上传 X 张,成功 X 张,失败 X 张”,清晰展示结果。

7.2 体验优化:图片压缩与格式转换

避免大图片占用过多带宽,前端可在上传前压缩图片:

// 选择图片后压缩(使用uni.getImageInfo+canvas压缩)
uni.getImageInfo({
  src: tempPath,
  success: (imageInfo) => {
    // 压缩逻辑:如宽高超过1000px则等比缩小,质量0.8
    const canvasWidth = imageInfo.width > 1000 ? 1000 : imageInfo.width;
    const canvasHeight = imageInfo.height * (canvasWidth / imageInfo.width);
    // 通过canvas压缩后,再调用uni.uploadFile上传压缩后的临时路径
  }
});

7.3 安全优化:营业执照真实性校验

防止用户上传非营业执照图片,可增加基础校验:

  1. 后端对接第三方 OCR 接口(如阿里云 OCR),提取图片中的 “营业执照编号”“公司名称”;
  1. 校验 OCR 提取的公司名称与商家注册填写的 “商家名称” 是否一致;
  1. 若未提取到营业执照关键信息,返回 “请上传清晰的营业执照图片”,提升审核准确性。

八、课堂互动

🙋‍♂️ 思考题 / 互动:

  1. 若商家需要上传更多类型图片(如店铺环境照、资质证书),如何扩展表单并区分存储(如dianpu_env字段存环境照 URL)?
  1. 前端如何实现 “上传中的图片禁止删除”(避免删除正在上传的文件导致异常)?

💡 互动引导:你的多图上传和商家注册功能跑通了吗?如果遇到 “部分图片上传失败” 或 “审核状态不显示” 的问题,欢迎分享你的uploadRes数据或后端日志,我们一起排查!

九、下节预告

👉 明天 Day14:商家服务列表!我们将学习:

  1. 设计shangjia_service(商家服务表),存储服务名称、价格、描述等;
  1. 实现商家端 “添加服务” 功能(关联商家 ID,仅自己可见);
  1. 前端用uni-list展示服务列表,支持 “编辑 / 删除” 服务;
  1. 后端添加服务状态控制(如 “上架 / 下架”,仅上架服务对用户可见)。

记得提前复习 MP 的 “条件查询”(如按商家 ID 查询服务)用法哦!