1. 项目背景与核心需求
婚庆行业正经历从传统线下服务向数字化平台的转型浪潮。根据中国婚庆行业协会数据,2023年线上婚庆服务市场规模已达1270亿元,年增长率保持在18%以上。这个背景下,"天长地久婚庆网"的设计需要解决三个核心痛点:
- 信息不对称:新人难以快速获取本地优质婚庆服务商的全景信息
- 服务碎片化:婚纱摄影、婚宴预订、婚庆策划等环节分散在不同平台
- 决策成本高:缺乏直观的案例展示和可信的评价体系
我们采用SpringBoot+Vue的全栈架构,正是基于以下考量:
- 后端需要高并发处理婚礼旺季的流量峰值(SpringBoot的线程池和缓存机制)
- 前端需要丰富的交互效果展示婚礼案例(Vue的组件化开发优势)
- 系统需要快速迭代应对市场变化(前后端分离的敏捷开发模式)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 后端SpringBoot架构
采用分层架构设计:
code复制com.tianchangdijiu
├── config # 安全配置、Swagger配置
├── controller # 暴露RESTful API
├── service # 业务逻辑层
│ ├── impl # 服务实现
├── dao # 数据访问层
├── entity # 数据库实体
├── util # 工具类
└── exception # 全局异常处理
关键配置示例(application.yml):
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/wedding_db?useSSL=false
username: root
password: 加密密码
redis:
host: 127.0.0.1
port: 6379
password: 加密密码
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
2.2 前端Vue架构
使用Vue CLI搭建的项目结构:
code复制src/
├── api/ # 接口请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── CaseGallery.vue # 案例展示组件
│ ├── VendorCard.vue # 商家卡片组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── views/ # 页面组件
│ ├── Home.vue # 首页
│ ├── VendorList.vue # 商家列表
└── App.vue # 根组件
路由配置示例(router/index.js):
javascript复制const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
meta: { title: '天长地久婚庆网' }
},
{
path: '/vendors/:category',
name: 'VendorList',
component: () => import('../views/VendorList.vue'),
props: true
}
]
3. 核心功能实现
3.1 商家入驻系统
采用RBAC权限模型设计:
java复制@Entity
@Table(name = "t_vendor")
public class Vendor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "商家名称不能为空")
private String name;
@ElementCollection
@CollectionTable(name = "t_service_type", joinColumns = @JoinColumn(name = "vendor_id"))
@Column(name = "type")
private Set<String> serviceTypes; // 服务类型:摄影/婚宴/策划等
@OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL)
private List<Case> cases; // 案例展示
}
3.2 智能推荐算法
基于用户行为的协同过滤实现:
java复制public List<Vendor> recommendVendors(Long userId) {
// 1. 获取用户浏览历史
List<BrowseHistory> histories = browseHistoryRepository.findByUserId(userId);
// 2. 提取标签权重
Map<String, Integer> tagWeights = histories.stream()
.flatMap(h -> h.getTags().stream())
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.summingInt(e -> 1)
));
// 3. 计算商家匹配度
return vendorRepository.findAll().stream()
.map(v -> new AbstractMap.SimpleEntry<>(v, calculateScore(v, tagWeights)))
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.limit(10)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
3.3 在线预约系统
使用Quartz实现预约提醒:
java复制@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void sendAppointmentReminders() {
LocalDate tomorrow = LocalDate.now().plusDays(1);
List<Appointment> appointments = appointmentRepository
.findByDateAndStatus(tomorrow, "CONFIRMED");
appointments.forEach(app -> {
String message = String.format(
"尊敬的%s,您明天%s的%s预约即将开始,请准时到场",
app.getCustomerName(),
app.getTime(),
app.getServiceType()
);
smsService.send(app.getPhone(), message);
});
}
4. 系统整合关键点
4.1 跨域解决方案
SpringBoot配置类:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
}
4.2 文件上传处理
前后端协作方案:
vue复制<template>
<input type="file" @change="handleUpload" accept="image/*" multiple>
</template>
<script>
export default {
methods: {
async handleUpload(e) {
const files = e.target.files;
const formData = new FormData();
Array.from(files).forEach(file => {
formData.append('files', file);
});
try {
const res = await this.$http.post('/api/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
this.$emit('upload-success', res.data);
} catch (err) {
console.error('上传失败:', err);
}
}
}
}
</script>
SpringBoot控制器:
java复制@PostMapping("/upload")
public Result upload(@RequestParam("files") MultipartFile[] files) {
List<String> urls = new ArrayList<>();
for (MultipartFile file : files) {
String filename = UUID.randomUUID() + getFileExtension(file.getOriginalFilename());
Path path = Paths.get(uploadDir, filename);
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
urls.add("/uploads/" + filename);
}
return Result.success(urls);
}
5. 推广运营方案
5.1 SEO优化策略
-
关键词布局:
- 首页:婚庆网、婚礼策划、婚纱摄影[城市名]
- 列表页:[服务类型]+[城市名](如"北京婚宴酒店")
- 详情页:商家名称+服务类型+城市名
-
元标签优化(Vue中使用vue-meta):
javascript复制metaInfo() {
return {
title: `${this.vendor.name} - ${this.vendor.serviceType} | 天长地久婚庆网`,
meta: [
{
name: 'description',
content: `${this.vendor.name}提供优质的${this.vendor.serviceType}服务,查看真实案例和用户评价`
},
{ name: 'keywords', content: `${this.vendor.name},${this.vendor.serviceType},${this.vendor.city}婚庆` }
]
}
}
5.2 社交媒体整合
微信小程序对接方案:
java复制@RestController
@RequestMapping("/api/wechat")
public class WechatController {
@GetMapping("/auth")
public Result auth(@RequestParam String code) {
String url = "https://api.weixin.qq.com/sns/jscode2session?" +
"appid=" + appId +
"&secret=" + appSecret +
"&js_code=" + code +
"&grant_type=authorization_code";
WechatAuthResponse response = restTemplate.getForObject(url, WechatAuthResponse.class);
return Result.success(response.getOpenid());
}
}
5.3 数据分析体系
埋点方案设计:
javascript复制// 前端埋点(Vue全局混入)
Vue.mixin({
methods: {
trackEvent(event, data) {
if (process.env.NODE_ENV === 'production') {
axios.post('/api/track', {
event,
data,
path: this.$route.path,
timestamp: Date.now()
});
}
}
}
})
// 使用示例
this.trackEvent('view_vendor_detail', {
vendorId: this.vendor.id
});
SpringBoot埋点数据存储:
java复制@Entity
@Table(name = "t_tracking_event")
public class TrackingEvent {
@Id
private String id;
private String eventType;
private String path;
@Column(columnDefinition = "json")
private String eventData;
@CreationTimestamp
private LocalDateTime createTime;
}
6. 项目部署方案
6.1 后端部署
Dockerfile示例:
dockerfile复制FROM openjdk:11-jdk
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Nginx配置(负载均衡):
nginx复制upstream wedding {
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080 weight=2;
server 192.168.1.103:8080 weight=1;
}
server {
listen 80;
server_name wedding.example.com;
location / {
proxy_pass http://wedding;
proxy_set_header Host $host;
}
}
6.2 前端部署
Vue项目构建优化:
javascript复制// vue.config.js
module.exports = {
chainWebpack: config => {
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
vendor: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: 5,
reuseExistingChunk: true
}
}
})
}
}
CDN加速配置:
html复制<!-- public/index.html -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script>
7. 项目演进路线
7.1 第一阶段:核心功能上线(1-3个月)
- 商家入驻与审核系统
- 基础搜索与筛选功能
- 案例展示与预约系统
7.2 第二阶段:体验优化(4-6个月)
- 智能推荐算法迭代
- VR婚礼场景展示
- 在线合同签署功能
7.3 第三阶段:生态扩展(7-12个月)
- 婚庆供应链整合
- 婚礼金融产品接入
- 行业SaaS工具输出
8. 避坑指南
8.1 图片处理优化
常见问题:婚礼案例图片过大导致加载缓慢
解决方案:
java复制public void compressImage(InputStream input, OutputStream output, float quality) throws IOException {
BufferedImage image = ImageIO.read(input);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = writers.next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality); // 0.7f
try (ImageOutputStream ios = ImageIO.createImageOutputStream(output)) {
writer.setOutput(ios);
writer.write(null, new IIOImage(image, null, null), param);
}
writer.dispose();
}
8.2 高并发场景应对
婚礼旺季流量突增方案:
- 缓存策略:
java复制@Cacheable(value = "vendors", key = "#root.args[0]+'_'+#root.args[1]")
public Page<Vendor> findVendors(String category, int page) {
return vendorRepository.findByCategory(category, PageRequest.of(page, 10));
}
- 限流配置:
java复制@Configuration
public class RateLimitConfig {
@Bean
public FilterRegistrationBean<RateLimitFilter> rateLimitFilter() {
FilterRegistrationBean<RateLimitFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new RateLimitFilter(100, 1)); // 100请求/秒
registration.addUrlPatterns("/api/*");
return registration;
}
}
8.3 移动端适配技巧
Vue响应式布局方案:
css复制/* 案例展示组件 */
.case-gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
@media (max-width: 768px) {
.case-gallery {
grid-template-columns: 1fr;
}
.vendor-card {
flex-direction: column;
}
}
9. 数据安全方案
9.1 敏感信息加密
SpringBoot配置数据库加密:
java复制@Configuration
public class EncryptConfig {
@Bean
public StringEncryptor encryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setPoolSize(4);
encryptor.setPassword(System.getenv("ENCRYPT_PASSWORD"));
encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
return encryptor;
}
}
9.2 防XSS攻击
Vue全局过滤器:
javascript复制// main.js
Vue.filter('escape', function(value) {
const div = document.createElement('div')
div.appendChild(document.createTextNode(value))
return div.innerHTML
})
// 使用方式
<div v-html="comment | escape"></div>
SpringBoot防护配置:
java复制@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'");
}
}
10. 性能监控体系
10.1 SpringBoot监控
Actuator配置:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
tags:
application: wedding-web
10.2 前端性能追踪
使用Lighthouse CI集成:
yaml复制# .github/workflows/lighthouse.yml
name: Lighthouse Audit
on: [push]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run build
- uses: treosh/lighthouse-ci-action@v7
with:
urls: |
http://localhost:5000
http://localhost:5000/vendors
budgetPath: ./lighthouse-budget.json
预算配置文件示例:
json复制{
"performance": {
"first-contentful-paint": ["warn", {"maxNumericValue": 2000}],
"interactive": ["error", {"maxNumericValue": 5000}]
}
}
