JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码小程序+公众号+h5

JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统:数字化革新校园生活服务

在当今高校校园生活中,随着学生消费需求多样化和时间碎片化加剧,校园跑腿和外卖服务需求呈现爆发式增长。传统的校园服务模式无法满足学生群体对即时性、便捷性、个性化服务的迫切需求,而个人跑腿服务又存在信任缺失、效率低下、安全无保障等痛点。JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统应运而生,以其全面的技术架构和创新的服务模式,为校园生活服务带来革命性变革。这套JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统整合了小程序、公众号和H5等多端入口,通过springboot+mybatisplus+mysql构建稳定高效的后台服务,uniapp实现用户端跨平台开发,vue+elementUi打造专业管理后台,彻底解决了校园服务中订单匹配效率低、配送路径不优化、实时追踪不精准、支付结算不安全等行业难题。学生可以通过JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统随时随地发布外卖代买、快递代取、校园跑腿等服务需求,系统智能匹配附近同学或专职骑手,实时追踪服务进度,确保服务过程透明可控。这种JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统真正实现了校园生活服务的数字化转型,构建起连接学生、骑手、商家的完整校园生态体系。

系统架构设计与核心技术优势

本JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统采用前后端分离的现代化架构,后端基于SpringBoot框架提供稳定的RESTful API接口,前端通过uniapp实现一次开发多端部署,管理端使用Vue.js配合ElementUI组件库。这种JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统架构确保了系统的高性能、高可用性和易维护性。

核心架构代码示例:

复制代码
// SpringBoot主启动类配置
@SpringBootApplication
@MapperScan("com.campusrunning.mapper")
@EnableScheduling
@EnableAsync
@EnableCaching
public class CampusRunningApplication {
    public static void main(String[] args) {
        SpringApplication.run(CampusRunningApplication.class, args);
    }
}

// MybatisPlus配置类
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 动态表名插件
        interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor());
        return interceptor;
    }
}

// Redis缓存配置
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        Jackson2JsonRedisSerializer<Object> serializer = 
            new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LazyCollectionDefaultingTyping, 
            ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        
        return template;
    }
    
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10))
            .disableCachingNullValues();
        
        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
    }
}
数据库设计与数据持久层实现

JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统采用MySQL数据库,通过精心设计的表结构确保数据一致性和完整性。核心表包括订单信息表、骑手信息表、商家信息表、用户地址表等。

实体类和Mapper层代码示例:

复制代码
// 校园外卖订单实体类
@Data
@TableName("campus_order")
@ApiModel(value = "CampusOrder对象", description = "校园订单表")
public class CampusOrder {
    @TableId(type = IdType.ASSIGN_ID)
    @ApiModelProperty("订单ID")
    private Long orderId;
    
    @ApiModelProperty("订单编号")
    private String orderNo;
    
    @ApiModelProperty("用户ID")
    private Long userId;
    
    @ApiModelProperty("骑手ID")
    private Long riderId;
    
    @ApiModelProperty("商家ID")
    private Long merchantId;
    
    @ApiModelProperty("订单类型:1-外卖 2-跑腿 3-代取快递")
    private Integer orderType;
    
    @ApiModelProperty("订单状态")
    private Integer orderStatus;
    
    @ApiModelProperty("取货地址")
    private String pickupAddress;
    
    @ApiModelProperty("收货地址")
    private String deliveryAddress;
    
    @ApiModelProperty("订单金额")
    private BigDecimal orderAmount;
    
    @ApiModelProperty("配送费")
    private BigDecimal deliveryFee;
    
    @ApiModelProperty("订单备注")
    private String orderRemark;
    
    @ApiModelProperty("预计送达时间")
    private LocalDateTime estimatedTime;
    
    @ApiModelProperty("实际送达时间")
    private LocalDateTime actualDeliveryTime;
    
    @ApiModelProperty("订单商品信息")
    private String orderItems;
    
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}

// 商家信息实体类
@Data
@TableName("campus_merchant")
@ApiModel(value = "CampusMerchant对象", description = "校园商家表")
public class CampusMerchant {
    @TableId(type = IdType.AUTO)
    @ApiModelProperty("商家ID")
    private Long merchantId;
    
    @ApiModelProperty("商家名称")
    private String merchantName;
    
    @ApiModelProperty("商家类型")
    private String merchantType;
    
    @ApiModelProperty("联系人")
    private String contactPerson;
    
    @ApiModelProperty("联系电话")
    private String contactPhone;
    
    @ApiModelProperty("商家地址")
    private String address;
    
    @ApiModelProperty("营业时间")
    private String businessHours;
    
    @ApiModelProperty("商家评分")
    private BigDecimal rating;
    
    @ApiModelProperty("月销量")
    private Integer monthlySales;
    
    @ApiModelProperty("商家状态")
    private Integer merchantStatus;
    
    @ApiModelProperty("商家介绍")
    private String introduction;
    
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
}

// Mapper接口定义
public interface CampusOrderMapper extends BaseMapper<CampusOrder> {
    
    @Select("SELECT * FROM campus_order WHERE rider_id = #{riderId} AND order_status = #{status}")
    List<CampusOrder> selectByRiderAndStatus(@Param("riderId") Long riderId, 
                                           @Param("status") Integer status);
    
    @Select("<script>" +
            "SELECT * FROM campus_order WHERE 1=1 " +
            "<if test='orderType != null'> AND order_type = #{orderType} </if>" +
            "<if test='orderStatus != null'> AND order_status = #{orderStatus} </if>" +
            "<if test='startTime != null'> AND create_time >= #{startTime} </if>" +
            "<if test='endTime != null'> AND create_time <= #{endTime} </if>" +
            " ORDER BY create_time DESC" +
            "</script>")
    List<CampusOrder> selectOrdersByConditions(@Param("orderType") Integer orderType,
                                             @Param("orderStatus") Integer orderStatus,
                                             @Param("startTime") LocalDateTime startTime,
                                             @Param("endTime") LocalDateTime endTime);
    
    @Update("UPDATE campus_order SET order_status = #{status} WHERE order_id = #{orderId}")
    int updateOrderStatus(@Param("orderId") Long orderId, @Param("status") Integer status);
    
    @Select("SELECT COUNT(*) FROM campus_order WHERE rider_id = #{riderId} " +
            "AND create_time >= #{startTime} AND create_time <= #{endTime}")
    Long countRiderOrders(@Param("riderId") Long riderId,
                         @Param("startTime") LocalDateTime startTime,
                         @Param("endTime") LocalDateTime endTime);
}
业务逻辑层核心实现

JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统的业务逻辑层采用SpringBoot+MyBatisPlus技术栈,通过@Service注解实现业务逻辑,@Transactional确保数据一致性。

业务服务层代码示例:

复制代码
// 校园订单服务接口
public interface CampusOrderService extends IService<CampusOrder> {
    
    OrderCreateResultVO createOrder(OrderCreateDTO createDTO);
    
    boolean acceptOrder(Long orderId, Long riderId);
    
    boolean updateOrderStatus(OrderStatusUpdateDTO updateDTO);
    
    List<RiderVO> findNearbyRiders(LocationDTO locationDTO);
    
    OrderDetailVO getOrderDetail(Long orderId);
    
    boolean cancelOrder(Long orderId, Long userId, String cancelReason);
    
    List<MerchantVO> getNearbyMerchants(CampusQueryDTO queryDTO);
}

// 校园订单服务实现类
@Service
@Slf4j
public class CampusOrderServiceImpl extends ServiceImpl<CampusOrderMapper, CampusOrder> 
    implements CampusOrderService {
    
    @Autowired
    private CampusRiderMapper campusRiderMapper;
    
    @Autowired
    private CampusMerchantMapper campusMerchantMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private DistanceCalculateService distanceCalculateService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderCreateResultVO createOrder(OrderCreateDTO createDTO) {
        // 验证订单数据
        validateOrderCreateDTO(createDTO);
        
        // 创建订单
        CampusOrder order = new CampusOrder();
        BeanUtils.copyProperties(createDTO, order);
        order.setOrderNo(generateOrderNo());
        order.setOrderStatus(1); // 待接单
        order.setDeliveryFee(calculateDeliveryFee(createDTO));
        
        int result = baseMapper.insert(order);
        if (result > 0) {
            // 推送订单给附近骑手
            pushOrderToNearbyRiders(order);
            
            OrderCreateResultVO resultVO = new OrderCreateResultVO();
            resultVO.setOrderId(order.getOrderId());
            resultVO.setOrderNo(order.getOrderNo());
            resultVO.setEstimatedTime(order.getEstimatedTime());
            resultVO.setDeliveryFee(order.getDeliveryFee());
            resultVO.setOrderAmount(order.getOrderAmount());
            
            log.info("创建校园订单成功,订单ID:{}", order.getOrderId());
            return resultVO;
        }
        
        throw new BusinessException("创建订单失败");
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean acceptOrder(Long orderId, Long riderId) {
        CampusOrder order = baseMapper.selectById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        
        if (!order.getOrderStatus().equals(1)) {
            throw new BusinessException("订单状态不可接单");
        }
        
        // 检查骑手是否在服务范围内
        if (!isRiderInServiceRange(riderId, order.getPickupAddress())) {
            throw new BusinessException("不在服务范围内,无法接单");
        }
        
        // 更新订单状态和骑手信息
        order.setRiderId(riderId);
        order.setOrderStatus(2); // 已接单
        order.setUpdateTime(LocalDateTime.now());
        
        int result = baseMapper.updateById(order);
        if (result > 0) {
            // 更新骑手状态为忙碌
            CampusRider rider = campusRiderMapper.selectById(riderId);
            rider.setWorkStatus(2); // 忙碌
            campusRiderMapper.updateById(rider);
            
            // 发送接单通知
            sendOrderAcceptedNotification(order);
            return true;
        }
        
        return false;
    }
    
    @Override
    public List<RiderVO> findNearbyRiders(LocationDTO locationDTO) {
        // 从Redis获取附近在线的骑手
        String cacheKey = "campus_online_riders:" + locationDTO.getCampusCode();
        List<CampusRider> onlineRiders = (List<CampusRider>) redisTemplate.opsForValue().get(cacheKey);
        
        if (onlineRiders == null) {
            // 从数据库查询在线骑手
            LambdaQueryWrapper<CampusRider> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(CampusRider::getWorkStatus, 1) // 在线
                   .eq(CampusRider::getCampusCode, locationDTO.getCampusCode())
                   .eq(CampusRider::getAuditStatus, 2); // 已审核
            onlineRiders = campusRiderMapper.selectList(wrapper);
            
            // 缓存到Redis,5分钟过期
            redisTemplate.opsForValue().set(cacheKey, onlineRiders, 5, TimeUnit.MINUTES);
        }
        
        // 计算距离并筛选附近的骑手
        return onlineRiders.stream()
                .map(rider -> {
                    RiderVO riderVO = new RiderVO();
                    BeanUtils.copyProperties(rider, riderVO);
                    
                    // 计算距离
                    double distance = distanceCalculateService.calculateDistance(
                        locationDTO.getLatitude(), locationDTO.getLongitude(),
                        rider.getCurrentLat().doubleValue(), rider.getCurrentLng().doubleValue()
                    );
                    riderVO.setDistance(distance);
                    riderVO.setEstimatedTime(calculateEstimatedTime(distance));
                    
                    return riderVO;
                })
                .filter(rider -> rider.getDistance() <= 3.0) // 3公里内的骑手
                .sorted(Comparator.comparingDouble(RiderVO::getDistance))
                .collect(Collectors.toList());
    }
    
    @Override
    public List<MerchantVO> getNearbyMerchants(CampusQueryDTO queryDTO) {
        LambdaQueryWrapper<CampusMerchant> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CampusMerchant::getCampusCode, queryDTO.getCampusCode())
               .eq(CampusMerchant::getMerchantStatus, 1) // 营业中
               .like(StringUtils.isNotBlank(queryDTO.getKeyword()),
                     CampusMerchant::getMerchantName, queryDTO.getKeyword());
        
        if (StringUtils.isNotBlank(queryDTO.getMerchantType())) {
            wrapper.like(CampusMerchant::getMerchantType, queryDTO.getMerchantType());
        }
        
        List<CampusMerchant> merchants = campusMerchantMapper.selectList(wrapper);
        
        return merchants.stream()
                .map(merchant -> {
                    MerchantVO vo = new MerchantVO();
                    BeanUtils.copyProperties(merchant, vo);
                    
                    // 计算距离
                    if (queryDTO.getLatitude() != null && queryDTO.getLongitude() != null) {
                        double distance = distanceCalculateService.calculateDistance(
                            queryDTO.getLatitude(), queryDTO.getLongitude(),
                            merchant.getLatitude().doubleValue(), 
                            merchant.getLongitude().doubleValue()
                        );
                        vo.setDistance(distance);
                    }
                    
                    return vo;
                })
                .sorted(Comparator.comparingDouble(MerchantVO::getDistance))
                .collect(Collectors.toList());
    }
    
    private void validateOrderCreateDTO(OrderCreateDTO createDTO) {
        if (StringUtils.isBlank(createDTO.getPickupAddress())) {
            throw new BusinessException("取货地址不能为空");
        }
        if (StringUtils.isBlank(createDTO.getDeliveryAddress())) {
            throw new BusinessException("收货地址不能为空");
        }
        if (createDTO.getOrderType() == null) {
            throw new BusinessException("订单类型不能为空");
        }
        if (createDTO.getUserId() == null) {
            throw new BusinessException("用户不能为空");
        }
    }
    
    private boolean isRiderInServiceRange(Long riderId, String pickupAddress) {
        // 实现骑手服务范围检查逻辑
        CampusRider rider = campusRiderMapper.selectById(riderId);
        // 这里可以添加更复杂的地理围栏检查
        return rider != null && rider.getWorkStatus().equals(1);
    }
    
    private String generateOrderNo() {
        return "CR" + System.currentTimeMillis() + RandomUtil.randomNumbers(4);
    }
    
    private BigDecimal calculateDeliveryFee(OrderCreateDTO createDTO) {
        // 校园内配送费计算逻辑
        BigDecimal baseFee = new BigDecimal("2.00"); // 校园基础配送费较低
        
        // 根据距离、时间等因素调整费用
        if (isPeakTime()) {
            baseFee = baseFee.add(new BigDecimal("1.00")); // 高峰时段加价
        }
        
        return baseFee;
    }
    
    private boolean isPeakTime() {
        LocalTime now = LocalTime.now();
        return (now.isAfter(LocalTime.of(11, 0)) && now.isBefore(LocalTime.of(13, 0))) ||
               (now.isAfter(LocalTime.of(17, 0)) && now.isBefore(LocalTime.of(19, 0)));
    }
    
    private void pushOrderToNearbyRiders(CampusOrder order) {
        LocationDTO locationDTO = new LocationDTO();
        locationDTO.setLatitude(order.getPickupLat().doubleValue());
        locationDTO.setLongitude(order.getPickupLng().doubleValue());
        locationDTO.setCampusCode(order.getCampusCode());
        
        List<RiderVO> nearbyRiders = findNearbyRiders(locationDTO);
        
        // 推送订单给附近骑手
        nearbyRiders.forEach(rider -> {
            String message = String.format("新订单提醒:%s,配送费:%s元", 
                getOrderTypeText(order.getOrderType()), order.getDeliveryFee());
            pushMessageToRider(rider.getRiderId(), message);
        });
    }
    
    private String getOrderTypeText(Integer orderType) {
        switch (orderType) {
            case 1: return "校园外卖";
            case 2: return "校园跑腿";
            case 3: return "代取快递";
            default: return "其他服务";
        }
    }
    
    private String calculateEstimatedTime(double distance) {
        if (distance < 0.5) {
            return "10分钟内";
        } else if (distance < 1) {
            return "15分钟内";
        } else if (distance < 2) {
            return "20分钟内";
        } else {
            return "30分钟内";
        }
    }
}
控制层和API接口设计

RESTful API设计遵循行业标准,提供统一的响应格式和完整的错误处理机制。

控制器代码示例:

复制代码
// 校园订单控制器
@RestController
@RequestMapping("/api/campus-order")
@Api(tags = "校园订单管理")
@Slf4j
public class CampusOrderController {
    
    @Autowired
    private CampusOrderService campusOrderService;
    
    @PostMapping("/create")
    @ApiOperation("创建校园订单")
    public Result<OrderCreateResultVO> createOrder(@RequestBody @Valid OrderCreateDTO createDTO) {
        try {
            OrderCreateResultVO result = campusOrderService.createOrder(createDTO);
            return Result.success("创建订单成功", result);
        } catch (BusinessException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("创建校园订单失败", e);
            return Result.error("创建订单失败");
        }
    }
    
    @PostMapping("/accept/{orderId}")
    @ApiOperation("接单")
    public Result<String> acceptOrder(@PathVariable Long orderId, @RequestParam Long riderId) {
        try {
            boolean success = campusOrderService.acceptOrder(orderId, riderId);
            return success ? Result.success("接单成功") : Result.error("接单失败");
        } catch (BusinessException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("接单失败", e);
            return Result.error("接单失败");
        }
    }
    
    @GetMapping("/detail/{orderId}")
    @ApiOperation("获取订单详情")
    public Result<OrderDetailVO> getOrderDetail(@PathVariable Long orderId) {
        try {
            OrderDetailVO detail = campusOrderService.getOrderDetail(orderId);
            return Result.success("获取订单详情成功", detail);
        } catch (Exception e) {
            log.error("获取订单详情失败", e);
            return Result.error("获取订单详情失败");
        }
    }
    
    @PostMapping("/cancel/{orderId}")
    @ApiOperation("取消订单")
    public Result<String> cancelOrder(@PathVariable Long orderId, 
                                     @RequestParam Long userId,
                                     @RequestParam String cancelReason) {
        try {
            boolean success = campusOrderService.cancelOrder(orderId, userId, cancelReason);
            return success ? Result.success("取消成功") : Result.error("取消失败");
        } catch (BusinessException e) {
            return Result.error(e.getMessage());
        } catch (Exception e) {
            log.error("取消订单失败", e);
            return Result.error("取消失败");
        }
    }
    
    @GetMapping("/nearby-riders")
    @ApiOperation("查找附近骑手")
    public Result<List<RiderVO>> findNearbyRiders(LocationDTO locationDTO) {
        try {
            List<RiderVO> riders = campusOrderService.findNearbyRiders(locationDTO);
            return Result.success("查找附近骑手成功", riders);
        } catch (Exception e) {
            log.error("查找附近骑手失败", e);
            return Result.error("查找附近骑手失败");
        }
    }
    
    @GetMapping("/nearby-merchants")
    @ApiOperation("查找附近商家")
    public Result<List<MerchantVO>> getNearbyMerchants(CampusQueryDTO queryDTO) {
        try {
            List<MerchantVO> merchants = campusOrderService.getNearbyMerchants(queryDTO);
            return Result.success("查找附近商家成功", merchants);
        } catch (Exception e) {
            log.error("查找附近商家失败", e);
            return Result.error("查找附近商家失败");
        }
    }
    
    @PostMapping("/update-status")
    @ApiOperation("更新订单状态")
    public Result<String> updateOrderStatus(@RequestBody @Valid OrderStatusUpdateDTO updateDTO) {
        try {
            boolean success = campusOrderService.updateOrderStatus(updateDTO);
            return success ? Result.success("更新状态成功") : Result.error("更新状态失败");
        } catch (Exception e) {
            log.error("更新订单状态失败", e);
            return Result.error("更新状态失败");
        }
    }
}

// 统一响应结果封装
@Data
@ApiModel("统一响应结果")
public class Result<T> implements Serializable {
    
    @ApiModelProperty("状态码")
    private Integer code;
    
    @ApiModelProperty("响应消息")
    private String message;
    
    @ApiModelProperty("响应数据")
    private T data;
    
    @ApiModelProperty("时间戳")
    private Long timestamp;
    
    public static <T> Result<T> success(String message, T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMessage(message);
        result.setData(data);
        result.setTimestamp(System.currentTimeMillis());
        return result;
    }
    
    public static <T> Result<T> success(String message) {
        return success(message, null);
    }
    
    public static <T> Result<T> error(String message) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMessage(message);
        result.setTimestamp(System.currentTimeMillis());
        return result;
    }
}
前端uniapp用户端实现

用户端采用uniapp开发,支持编译到小程序、公众号、H5等多个平台,为JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统提供一致的用户体验。

Vue组件代码示例:

复制代码
<template>
  <view class="campus-home-container">
    <!-- 顶部导航 -->
    <view class="header-section">
      <view class="location-info">
        <u-icon name="map" size="36" color="#007aff"></u-icon>
        <text class="campus-name">{{ currentCampus }}</text>
        <u-icon name="arrow-down" size="28" color="#666"></u-icon>
      </view>
      <view class="search-box">
        <u-search
          v-model="searchKeyword"
          placeholder="搜索商家、商品"
          :show-action="false"
          @click="goToSearch"
        ></u-search>
      </view>
    </view>

    <!-- 服务分类 -->
    <view class="service-category-section">
      <view class="category-grid">
        <view 
          v-for="category in serviceCategories" 
          :key="category.id"
          class="category-item"
          @click="handleCategoryClick(category)"
        >
          <image :src="category.icon" class="category-icon"></image>
          <text class="category-name">{{ category.name }}</text>
        </view>
      </view>
    </view>

    <!-- 轮播图 -->
    <view class="banner-section">
      <swiper
        class="banner-swiper"
        indicator-dots
        autoplay
        circular
        interval="3000"
      >
        <swiper-item
          v-for="banner in banners"
          :key="banner.id"
        >
          <image 
            :src="banner.image" 
            class="banner-image"
            mode="aspectFill"
            @click="handleBannerClick(banner)"
          ></image>
        </swiper-item>
      </swiper>
    </view>

    <!-- 附近商家 -->
    <view class="merchants-section">
      <view class="section-header">
        <text class="section-title">附近商家</text>
        <text class="section-more" @click="viewAllMerchants">查看全部</text>
      </view>
      
      <view class="merchant-list">
        <view 
          v-for="merchant in nearbyMerchants" 
          :key="merchant.merchantId"
          class="merchant-card"
          @click="viewMerchantDetail(merchant.merchantId)"
        >
          <image :src="merchant.logo" class="merchant-logo"></image>
          <view class="merchant-info">
            <view class="merchant-header">
              <text class="merchant-name">{{ merchant.merchantName }}</text>
              <view class="merchant-rating">
                <u-rate :value="merchant.rating" size="24" readonly></u-rate>
                <text class="rating-text">{{ merchant.rating }}</text>
              </view>
            </view>
            <view class="merchant-details">
              <text class="merchant-type">{{ merchant.merchantType }}</text>
              <text class="delivery-info">配送约{{ merchant.estimatedTime }} | ¥{{ merchant.deliveryFee }}起送</text>
            </view>
            <view class="merchant-tags">
              <text 
                v-for="tag in merchant.tags" 
                :key="tag"
                class="tag"
              >{{ tag }}</text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 底部导航 -->
    <view class="tabbar">
      <view 
        v-for="tab in tabs" 
        :key="tab.key"
        class="tabbar-item"
        :class="{ active: currentTab === tab.key }"
        @click="switchTab(tab.key)"
      >
        <u-icon :name="tab.icon" :color="currentTab === tab.key ? '#007aff' : '#666'"></u-icon>
        <text class="tabbar-text">{{ tab.text }}</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      currentCampus: '北京大学',
      searchKeyword: '',
      serviceCategories: [
        { id: 1, name: '校园外卖', icon: '/static/icons/takeout.png', type: 'takeout' },
        { id: 2, name: '校园跑腿', icon: '/static/icons/running.png', type: 'running' },
        { id: 3, name: '代取快递', icon: '/static/icons/express.png', type: 'express' },
        { id: 4, name: '帮忙服务', icon: '/static/icons/help.png', type: 'help' },
        { id: 5, name: '零食超市', icon: '/static/icons/snack.png', type: 'snack' },
        { id: 6, name: '水果生鲜', icon: '/static/icons/fruit.png', type: 'fruit' },
        { id: 7, name: '奶茶饮品', icon: '/static/icons/tea.png', type: 'tea' },
        { id: 8, name: '全部服务', icon: '/static/icons/all.png', type: 'all' }
      ],
      banners: [
        { id: 1, image: '/static/banners/1.jpg', link: '/pages/promotion/list' },
        { id: 2, image: '/static/banners/2.jpg', link: '/pages/merchant/list' },
        { id: 3, image: '/static/banners/3.jpg', link: '/pages/activity/detail' }
      ],
      nearbyMerchants: [],
      currentTab: 'home',
      tabs: [
        { key: 'home', text: '首页', icon: 'home' },
        { key: 'order', text: '订单', icon: 'order' },
        { key: 'message', text: '消息', icon: 'chat' },
        { key: 'profile', text: '我的', icon: 'account' }
      ]
    }
  },

  onLoad() {
    this.loadNearbyMerchants()
    this.getCurrentLocation()
  },

  onPullDownRefresh() {
    this.loadNearbyMerchants().finally(() => {
      uni.stopPullDownRefresh()
    })
  },

  methods: {
    async loadNearbyMerchants() {
      try {
        const params = {
          campusCode: this.currentCampus,
          pageNum: 1,
          pageSize: 10
        }

        const res = await this.$http.get('/api/campus-order/nearby-merchants', { params })
        if (res.code === 200) {
          this.nearbyMerchants = res.data
        }
      } catch (error) {
        console.error('加载附近商家失败:', error)
        uni.showToast({
          title: '加载失败',
          icon: 'none'
        })
      }
    },

    handleCategoryClick(category) {
      switch (category.type) {
        case 'takeout':
          uni.navigateTo({
            url: '/pages/merchant/list?type=takeout'
          })
          break
        case 'running':
          uni.navigateTo({
            url: '/pages/running/create'
          })
          break
        case 'express':
          uni.navigateTo({
            url: '/pages/express/create'
          })
          break
        case 'help':
          uni.navigateTo({
            url: '/pages/help/create'
          })
          break
        default:
          uni.navigateTo({
            url: '/pages/merchant/list'
          })
      }
    },

    handleBannerClick(banner) {
      if (banner.link) {
        uni.navigateTo({
          url: banner.link
        })
      }
    },

    goToSearch() {
      uni.navigateTo({
        url: '/pages/search/index'
      })
    },

    viewMerchantDetail(merchantId) {
      uni.navigateTo({
        url: `/pages/merchant/detail?id=${merchantId}`
      })
    },

    viewAllMerchants() {
      uni.navigateTo({
        url: '/pages/merchant/list'
      })
    },

    switchTab(tabKey) {
      this.currentTab = tabKey
      switch (tabKey) {
        case 'order':
          uni.navigateTo({ url: '/pages/order/list' })
          break
        case 'message':
          uni.navigateTo({ url: '/pages/message/list' })
          break
        case 'profile':
          uni.navigateTo({ url: '/pages/profile/index' })
          break
      }
    },

    getCurrentLocation() {
      uni.getLocation({
        type: 'gcj02',
        success: (res) => {
          this.latitude = res.latitude
          this.longitude = res.longitude
        },
        fail: (error) => {
          console.error('获取位置失败:', error)
        }
      })
    }
  }
}
</script>

<style scoped>
.campus-home-container {
  padding: 30rpx;
  background-color: #f5f5f5;
  min-height: 100vh;
  padding-bottom: 120rpx;
}

.header-section {
  margin-bottom: 30rpx;
}

.location-info {
  display: flex;
  align-items: center;
  margin-bottom: 20rpx;
}

.campus-name {
  font-size: 32rpx;
  font-weight: bold;
  color: #333;
  margin: 0 10rpx;
}

.search-box {
  background: #fff;
  border-radius: 50rpx;
  padding: 0 30rpx;
}

.service-category-section {
  background: #fff;
  border-radius: 20rpx;
  padding: 30rpx;
  margin-bottom: 30rpx;
}

.category-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 30rpx;
}

.category-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.category-icon {
  width: 80rpx;
  height: 80rpx;
  margin-bottom: 15rpx;
}

.category-name {
  font-size: 24rpx;
  color: #333;
}

.banner-section {
  margin-bottom: 30rpx;
}

.banner-swiper {
  height: 300rpx;
  border-radius: 20rpx;
  overflow: hidden;
}

.banner-image {
  width: 100%;
  height: 100%;
}

.merchants-section {
  background: #fff;
  border-radius: 20rpx;
  padding: 30rpx;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30rpx;
}

.section-title {
  font-size: 32rpx;
  font-weight: bold;
  color: #333;
}

.section-more {
  font-size: 26rpx;
  color: #999;
}

.merchant-list {
  display: flex;
  flex-direction: column;
  gap: 30rpx;
}

.merchant-card {
  display: flex;
  padding: 20rpx;
  background: #f8f8f8;
  border-radius: 16rpx;
}

.merchant-logo {
  width: 120rpx;
  height: 120rpx;
  border-radius: 12rpx;
  margin-right: 20rpx;
}

.merchant-info {
  flex: 1;
}

.merchant-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 15rpx;
}

.merchant-name {
  font-size: 28rpx;
  font-weight: bold;
  color: #333;
  flex: 1;
}

.merchant-rating {
  display: flex;
  align-items: center;
}

.rating-text {
  font-size: 24rpx;
  color: #ff6b35;
  margin-left: 10rpx;
}

.merchant-details {
  display: flex;
  justify-content: space-between;
  margin-bottom: 15rpx;
}

.merchant-type {
  font-size: 24rpx;
  color: #666;
}

.delivery-info {
  font-size: 22rpx;
  color: #999;
}

.merchant-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10rpx;
}

.tag {
  background: #e6f7ff;
  color: #1890ff;
  padding: 6rpx 12rpx;
  border-radius: 12rpx;
  font-size: 20rpx;
}

.tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: #fff;
  border-top: 1rpx solid #f0f0f0;
  padding: 20rpx 0;
  z-index: 999;
}

.tabbar-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.tabbar-text {
  font-size: 22rpx;
  margin-top: 8rpx;
}
</style>
系统特色与行业价值

JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统通过技术创新和业务整合,为校园生活服务行业提供了全方位的数字化解决方案。这套JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统具备以下核心优势:

技术架构优势:

  • 前后端分离架构,提高开发效率和系统稳定性
  • 多端统一开发,大幅降低维护成本
  • 智能路径规划算法,优化配送效率
  • 实时位置追踪,确保服务过程透明

业务功能优势:

  • 全场景服务覆盖,满足学生多样化需求
  • 智能订单匹配,提高接单效率
  • 校园特色定价,适应学生消费水平
  • 完善评价体系,保障服务质量

性能与安全:

  • Redis缓存优化,提升系统响应速度
  • 数据库读写分离,支持高并发访问
  • 支付安全加密,保障交易安全
  • 校园身份验证,确保用户真实性

JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统以其全面的技术栈和丰富的功能特性,为校园生活服务行业提供了真正意义上的一站式数字化解决方案。从后台的springboot+mybatisplus+mysql稳定架构,到用户端的uniapp跨平台实现,再到管理后台的vue+elementUi优雅界面,每一个技术选型都经过精心考量,确保系统在性能、可维护性和用户体验方面达到最佳平衡。

随着校园生活服务市场规模的不断扩大和数字化程度的持续深化,拥有这样一套完整的JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统将成为校园创业团队和运营商的核心竞争优势。无论是校园创业团队寻求技术支撑,还是现有平台希望优化升级,这套JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码系统都能提供强有力的技术支撑和业务保障,助力创业者在激烈的校园市场竞争中脱颖而出,推动整个校园生活服务行业向数字化、智能化、生态化方向发展。

相关推荐
C嘎嘎嵌入式开发3 小时前
(20)100天python从入门到拿捏《JSON 数据解析》
开发语言·python·json
源码哥_博纳软云3 小时前
JAVA同城预约服务家政服务美容美发洗车保洁搬家维修家装系统源码小程序+公众号+h5
java·开发语言·微信小程序·小程序
红尘客栈23 小时前
Kubernetes 集群调度
java·linux·网络·容器·kubernetes
snow@li3 小时前
d3.js:学习积累
开发语言·前端·javascript
编程岁月3 小时前
java面试-0203-java集合并发修改异常、快速/安全失败原理、解决方法?
java·开发语言·面试
CoderCodingNo4 小时前
【GESP】C++五级考试大纲知识点梳理, (3-4) 链表-双向循环链表
开发语言·c++·链表
whltaoin4 小时前
AI 超级智能体全栈项目阶段五:RAG 四大流程详解、最佳实践与调优(基于 Spring AI 实现)
java·人工智能·spring·rag·springai
junnhwan4 小时前
【苍穹外卖笔记】Day05--Redis入门与店铺营业状态设置
java·数据库·redis·笔记·后端·苍穹外卖
llz_1124 小时前
第五周作业(JavaScript)
开发语言·前端·javascript