去年秋招失败后的那段时间,我每天从学校回出租屋都要绕路经过一家流浪动物救助站。救助站的负责人是个四十多岁的大姐,她给我看了三本厚得像字典的纸质登记册,里面密密麻麻写着编号、转账记录、领养人电话。她说他们最缺的不是爱心,而是工具。后来我的毕业设计选题几乎没有犹豫,就定成了“流浪动物领养助养系统”,技术栈选了SSM加Vue,因为这套组合在毕设圈里成熟、资料多、答辩好讲,而且前后端分离的思路能在论文里写出东西来。
这篇内容我会把从需求分析、数据库设计、后端接口、前端页面到论文写作的完整过程拆开讲,适合准备做类似毕设的同学,也适合想快速了解这套业务和技术栈怎么结合的人。我尽量少说空话,多给能直接落地的表结构、代码思路和踩坑经验。
1. 流浪动物领养助养系统的业务边界与核心功能拆解
1.1 领养和助养,是两个容易被搞混的业务概念
我在确认需求之前先做了一件事,把“领养”和“助养”这两个词给彻底分开。很多同学看到题目里有“领养助养”,就直接把它们当成一个功能做,导致论文里业务概念混乱,数据库设计也容易串字段。
领养是指用户把一只流浪动物接回家,承担它后续的全部抚养责任,这是一个一次性但影响长远的决定。而助养不需要把动物带走,用户可以按月定向资助某一只动物的口粮、疫苗或医疗费用,也属于一种长期承诺,但核心是资金或物资支持。
这两个业务场景在系统里的差异非常明显:领养需要审核,审核通过后动物状态要变成“已被领养”;助养需要生成记录,但动物仍然留在救助站。我在需求分析阶段就把这两条线画成了独立的流程,后来论文里的用例图也以此为骨架,说清楚了整个系统不是简单的“申请—通过”模型,而是两条并行又交汇的业务线。
1.2 角色划分与权限边界
系统我设计了三种角色:游客、注册用户、管理员。游客可以浏览动物列表和公告,但不能提交领养申请,也不能助养;注册用户拥有领养申请、助养记录、收藏动物、修改个人信息的权限;管理员负责动物信息录入、上下架、领养申请审批、助养记录查看、公告发布和数据统计。
权限这块我没单独建五张表的RBAC模型,因为毕设展示阶段没必要过度设计。我在用户表里直接加了一个role字段,0表示管理员,1表示注册用户。后端在每个Controller的方法上面用拦截器判断当前session里的用户角色,管理员接口一律校验role等于0,普通用户接口校验登录状态即可。
这种做法会被指导老师追问,答辩时你得准备好说法。我的回答是:本系统的角色固定且数量少,RBAC模型适合权限维度多、角色动态调整的场景,这里用字段控制更直观,也减少了不必要的外键关联。这个回应目前来看是比较容易过关的。
1.3 功能模块清单:可以直接当需求分析底稿
整理需求时我习惯把所有模块列成一张表,既能防止漏功能,也能直接复制到论文的“功能需求分析”章节。
前台模块:登录注册、动物列表、动物详情、按品种/状态/性别筛选、关键字搜索、领养申请、助养下单、收藏列表、个人中心、公告信息。
后台模块:用户管理、动物信息管理、领养申请审批、助养记录查询、公告管理、数据统计看板。
扩展模块:疫苗提醒、领养回访记录、轮播图管理、留言反馈。
统计看板我强烈建议做,答辩的时候让评委看到图表比看一堆表格有说服力。我使用的是ECharts,展示每月新增领养数、助养金额柱状图、动物种类占比饼图,只需要查两张表做统计,工作量不大,但论文配图效果提升很明显。
2. SSM+Vue这套技术组合的选型理由与配置要点
2.1 为什么后端选SSM而不是Spring Boot
2026年做毕设,很多学校已经允许用Spring Boot了,但我还是选了SSM。原因很简单:SSM的配置过程比Spring Boot多,你能在论文里写的东西就多。Spring Boot很多功能是约定优于配置,一个注解就能跑起来,到论文的“系统实现”章节反而没什么可写的。SSM需要你手写Spring配置文件、SpringMVC配置文件、MyBatis配置文件,每一个配置项背后的原理都能在论文里展开,答辩的时候老师问你“为什么这么配”,你可以讲出一套完整逻辑。
当然这不代表SSM没有缺点。它的麻烦在于jar包版本容易冲突,不同版本的Spring和MyBatis配合经常出问题。我的策略是直接用Maven的dependencyManagement锁定版本,Spring统一用5.2.x,MyBatis用3.5.x,MyBatis-Spring用2.0.x,这套组合我在本地跑通后就不动版本了。
2.2 前端为什么配Vue和Element UI
前端选择Vue 2加Element UI,选Vue 2不是因为Vue 3不好,而是Element UI基于Vue 2最稳定,网上的参考资料也最多。Element UI的表格、表单校验、日期选择器、上传组件都是现成的,对毕设来说比手写一套UI组件节省大量时间。
前端工程化方面我用了vue-cli 4创建项目,配了vue-router和axios。没用vuex,因为系统状态并不多,跨组件共享的数据只有用户登录信息和收藏数,用localStorage加路由传参就够了。vuex在论文里写上“为了减少冗余,未使用vuex,而是通过localStorage维护登录态”,这一句能体现你的思考,而不是照搬教程。
2.3 前后端半分离方案与项目结构
严格意义上的前后端分离是前端部署在Nginx,后端部署在Tomcat,两边通过跨域请求通信。毕设答辩现场容易出现两种尴尬:演示环境的Nginx没配好导致页面白屏,或者跨域拦截直接报错。
我的做法是采用“半分离”方案。开发时前后端完全分离,前端启动在8080端口,后端启动在8081端口,用代理解决跨域。真正打包部署时,把Vue构建生成的dist目录拷贝到SSM项目的webapp目录下,由Tomcat统一托管,前端请求接口时使用相对路径,绕过跨域问题。这种方案既能在论文里写清楚前后端分离架构,又能保证演示时不出幺蛾子。
项目结构大致长这样:
animal-adopt-system/ ├── backend/ # SSM后端工程 │ ├── src/main/java │ │ ├── com.example.controller │ │ ├── com.example.service │ │ ├── com.example.mapper │ │ └── com.example.entity │ ├── src/main/resources │ │ ├── spring-context.xml │ │ ├── spring-mvc.xml │ │ ├── mybatis-config.xml │ │ └── jdbc.properties │ └── src/main/webapp │ ├── static/upload # 图片存储目录 │ └── index.html # Vue打包产物 └── frontend/ # Vue前端工程 ├── src │ ├── api │ ├── router │ ├── views │ └── components └── package.json3. 数据库设计:领养、助养业务落库的第一道坎
3.1 用户表与权限字段设计
用户表取名user,注意别写成sys_user,因为系统里没有复杂的组织架构。字段包含id、username、password、nickname、phone、email、avatar、role、status、create_time。密码存储我用的MD5加密,后来答辩被问到安全问题,我补充了一句“真实项目应使用BCrypt”,这个回答可以主动写进论文的安全设计小节里。
role字段设计成tinyint,0代表管理员,1代表普通用户。status字段0代表正常,1代表禁用。管理员在后台禁用某用户后,该用户登录时接口返回“账号已被禁用”,但已经登录的session不会立即失效,这是一个小缺陷,我在paper里写在后续工作里,没有花精力去实现session踢除。
3.2 动物信息表与状态流转
animal表是整个系统的核心,字段需要覆盖展示和信息管理。表结构我设计如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键 |
| name | varchar | 动物昵称 |
| species | varchar | 种类:猫/狗/其他 |
| breed | varchar | 品种 |
| gender | varchar | 公/母 |
| age | decimal | 年龄,按岁计算 |
| weight | decimal | 体重,公斤 |
| health_status | varchar | 健康状况文字描述 |
| inoculation | varchar | 疫苗情况 |
| sterilization | varchar | 是否绝育 |
| photo | varchar | 图片路径 |
| description | text | 详细描述 |
| status | tinyint | 0待领养/1已领养/2待助养/3已助养/4暂停领养 |
| create_time | datetime | 录入时间 |
| update_time | datetime | 更新时间 |
status字段是整个动物状态流转的关键。设计时需要特别考虑:一只动物被某个用户领养后,它的身份不应该永远被打上“已领养”的标签,因为现实中可能出现退养。我在后台增加了一个“重新上架”按钮,管理员把status从1改回0,动物重新出现在领养列表。这个需求我在需求分析阶段漏掉了,后来是救助站负责人提醒我的,加进去之后论文里的数据流描述也更完整。
检索角度上,列表页需要按species、status、gender做筛选,和一个关键字搜索,我在animal表的species、gender、status三个字段上建了联合索引。数据量不大,不用考虑复杂的索引优化,但论文里提一句索引设计能给数据库设计章节加分。
3.3 领养申请表与审批流程
adopt_apply表记录领养申请,字段包含id、apply_no、user_id、animal_id、applicant_name、applicant_phone、applicant_address、reason、status、create_time、handle_time、handler_remark。
apply_no是申请单号,格式为20260501加四位随机数,方便管理端搜索和线下核对。status字段有四个值:0待审核、1审核通过、2已拒绝、3已撤销。用户可以在个人中心撤销未处理的申请,撤回后status变为3,动物状态不变。
审批流程里有一个关键业务逻辑:同一只动物在同一时刻最多只能有一个“待审核”的申请,否则会出现多个人争一只动物的情况。我实现时控制了这一点,重复申请接口直接返回提示。动物处于“已被领养”状态时,新申请表不允许再插入,前端也会把“申请领养”按钮置灰。
3.4 助养记录表
助养记录表sponsor_record字段包含id、user_id、animal_id、sponsor_type、amount、note、create_time。sponsor_type区分资金和物资,资金类型记录金额,物资类型在note字段里填写物资明细,比如“猫粮10kg、猫砂2袋”。
助养和领养有一个关联点:同一只动物可以被多个用户同时助养,现实中一只救助站的猫可以有多个资助人。所以sponsor_record表不用做唯一性约束,动物表状态为“待领养”的动物也可以展示“已获取助养”的数字。这个逻辑我单独想了一阵,后来参考救助站的实际规则才确认,论文中我用一个ER图局部说明了“动物与助养记录的一对多关系”。
3.5 冗余字段与外键取舍
我在animal表里放了一个sponsor_count字段,用于统计助养次数。这个字段严格来说是冗余的,因为它可以通过count查询得到,但列表页展示时需要频繁统计,每次count会拖慢查询。这个取舍我在论文的数据库设计优化里说明了:以空间换时间,数据量小,冗余字段可控。答辩时老师重点问了这一点,因为方案确实是清晰可解释的。
外键我物理上没有建,只是在逻辑上通过java代码维护关联。理由是毕设系统需要避免删除时触发外键约束的连环问题,同时SSM配合MyBatis管理表关系足够简单。如果你在论文里写“设计了外键”,但数据库里没建,被问到会很难看,所以我直接在论文里写使用了逻辑外键。
4. 后端从Controller到Mapper:业务逻辑如何拆
4.1 统一响应结构:没有它前端会把你骂死
后端接口我统一返回一个Result对象,字段包含code、message、data。code为200表示成功,500表示业务失败,401表示未登录,403表示无权限。前端axios拦截器根据code统一处理提示,不用每个请求单独写判断。
public class Result<T> { private Integer code; private String message; private T data; // 省略构造函数和getter setter }这个结构看起来简单,但很多同学偷懒,有的接口返回Map,有的直接返回字符串,导致前端联调时每个页面都要单独处理异常,非常痛苦。后端接口设计是毕设里性价比最高的一个环节,统一好响应结构,联调时间能少三分之一。
4.2 领养申请的核心逻辑与校验过程
领养申请接口是整个系统最核心的业务操作,我拆成了三层。
Controller层只做参数接收和结果返回,Service层实现业务逻辑,Mapper层做数据库操作。以提交领养申请为例,逻辑如下:
public Result submitAdopt(AdoptApplyVO vo) { // 1. 校验用户是否登录 User user = getCurrentUser(); if (user == null) { return Result.error(401, "请先登录"); } // 2. 校验动物是否存在且状态为待领养 Animal animal = animalMapper.selectById(vo.getAnimalId()); if (animal == null || animal.getStatus() != 0) { return Result.error(500, "该动物当前不可领养"); } // 3. 校验是否已存在待审核申请 int count = adoptApplyMapper.countPendingByAnimalId(vo.getAnimalId()); if (count > 0) { return Result.error(500, "该动物已有一条待审核申请"); } // 4. 生成申请单号并插入数据库 AdoptApply apply = buildApply(vo); adoptApplyMapper.insert(apply); return Result.ok(apply); }这段代码中每一步校验都要能说出理由,答辩时老师最常问的就是“你为什么要先查动物状态”。第3步的防重复申请,我在实现时花了一点时间想SQL怎么写,最后用count加条件完成,逻辑简单可靠。
4.3 图片上传与静态资源映射的坑
动物图片上传我用了Element UI的上传组件,后端接收MultipartFile,把文件保存到本机的webapp/static/upload目录下,文件名用UUID加原始后缀生成,防止重名覆盖。保存成功后返回的路径格式是“/upload/动物名_时间戳.jpg”。
这里有一个特别容易踩的坑:SpringMVC默认不处理静态资源,需要额外配置。我在spring-mvc.xml里加了这样一段:
<mvc:resources mapping="/upload/**" location="/WEB-INF/static/upload/"/>如果图片目录放在webapp/static/upload下,而映射写的是/WEB-INF/static/upload/,路径不一致就会白屏。我最初把图片存在F盘的一个物理目录下,结果前端完全访问不到,后来改成了静态资源映射才正常。建议所有人做毕设时把图片目录固定放在webapp下,不要自定义绝对路径。
4.4 分页与多条件筛选的SQL细节
动物列表的筛选条件有种类、性别、状态、关键字,我用了PageHelper插件做分页,SQL用动态拼接。Mapper里写的SQL如下:
<select id="selectByCondition" resultType="Animal"> select * from animal <where> <if test="species != null and species != ''"> and species = #{species} </if> <if test="gender != null and gender != ''"> and gender = #{gender} </if> <if test="status != null"> and status = #{status} </if> <if test="keyword != null and keyword != ''"> and (name like concat('%', #{keyword}, '%') or description like concat('%', #{keyword}, '%')) </if> </where> order by create_time desc </select>这里要注意MyBatis的if标签里判断字符串不能用“字符串.equals”这种Java代码,而是直接比较。还有like查询中concat函数的使用,MySQL支持,但如果用Oracle数据库会不一样。我这个系统只针对MySQL,所以没有考虑兼容。
4.5 跨域与Session的配合
开发环境前后端分离,跨域是躲不开的问题。我在后端配置了一个CorsFilter过滤器,允许前端开发服务器的域名跨域访问。这里特别提醒:没有配跨域过滤器,前端请求一定报错。而部署阶段前端文件放在了Tomcat里,同源了,跨域配置不影响。
Session跨域的问题要注意。浏览器在8080端口登录后,cookie被写到了8080端口,而请求后端8081端口时不带cookie,导致登录失效。我的解决方案是axios请求加withCredentials: true,后端CorsFilter里也设置allowCredentials为true。这一整套配置不调试一次很难发现,我调这个问题花了两个小时,属于典型的前后端分离开发坑。
5. 前端Vue实战:从登录到领养申请的全流程交互
5.1 路由设计和登录权限拦截
前端页面我规划得比较完整。未登录用户可以访问首页、动物列表、动物详情和公告页面。需要登录的页面包括提交领养申请、提交助养、个人中心和收藏列表。管理员后台单独一组路由,放在/admin路径下。
登录权限用Vue Router的beforeEach守卫控制,核心代码如下:
router.beforeEach((to, from, next) => { const token = localStorage.getItem('token'); if (to.meta.requiresAuth && !token) { next({ path: '/login', query: { redirect: to.fullPath } }); } else { next(); } });localStorage存储的token在论文中可以写为“简易token”,实际上用的是后端sessionId,只是存储到前端变量里。后端所有需要登录的接口都从session里取user信息。这个方案简单,但有一个Bug:用户退登后,别的浏览器用同一个账号登录,旧session还能用。论文的安全设计里我写的是“基于session-cookie机制,未引入分布式会话”,这样把边界情况说清楚了,答辩不会因为这个小问题翻车。
5.2 登录注册页面与表单校验
登录注册页我放在同一个组件里,通过tab切换。注册字段包括用户名、密码、确认密码、手机号、邮箱。手机号的校验是前端正则加后端校验双保险。
前端Element UI的校验规则示例:
rules: { phone: [ { required: true, message: '请输入手机号', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' } ] }后端同样要校验,不能只靠前端。很多毕设系统只做前端校验,后端接口用Postman一测就能绕过,这会让答辩老师觉得系统安全性不足。我在Service里重新校验了一遍手机号和用户名格式,论文里提到“前后端双重校验”是一个加分项。
5.3 动物卡片列表与筛选交互
动物列表页我用的不是el-table,而是卡片布局,每张卡片显示图片、名称、性别、年龄、状态标签和“查看详情”按钮。筛选栏放在页面顶部,包含三个下拉框和一个搜索框,搜索按钮和重置按钮。
卡片布局比表格好看很多,但有一个问题:卡片组件里显示图片需要拼接完整的图片地址。我的后端接口返回的photo字段是“/upload/xxxx.jpg”,这是相对路径。开发环境前端端口和后端端口不同,直接指向前端8080端口找不到图片,所以我在axios实例里配置了baseURL为后端地址,同时把图片地址前缀也拼成后端地址。
这个细节不调试发现不了。建议在开发阶段用一个全局变量存储图片baseUrl,部署阶段再修改为相对路径。我在main.js里定义了一个变量config,所有页面组件从它读取图片前缀,这样后续维护一个地方即可。
5.4 详情页与领养申请弹窗
动物详情页展示了所有信息,还有“申请领养”和“我要助养”两个按钮。点击申请领养会弹出表单,收集领养人姓名、联系电话、联系地址、领养理由。这些字段中联系电话和地址不能自动从user表读取,因为有时用户帮别人提交申请,或者领养人与注册人不是同一人,需要现场输入。
提交成功后跳转到“我的申请”页面,能看到所有申请的审核状态。我加了一个倒计时撤销功能,未审核的申请可以撤销,这个交互在答辩演示时做一次,评委印象比较深。
5.5 管理员后台统计看板
后台首页我放了几张统计卡片和一个柱状图,统计本月待审核领养申请数、本月助养金额、动物总数、待领养动物数。ECharts可以自定义颜色,我配了一个暖色调,整体风格和救助站的年龄特征比较搭配。
管理员的领养审批页面是表达“流程完整性”的关键。每条申请显示申请人信息和动物信息,管理员可以点击“通过”或“拒绝”。通过时需要填写备注,比如“请在一周内来救助站接动物”。这个操作会触发后端事务:更新申请状态、更新动物状态为已领养、向用户发送一条站内信。事务控制我使用了@Transactional注解,因为涉及多张表更新,一旦中途出错,会导致状态不一致。
6. 论文写作:程序之外的另一半工作量
6.1 论文结构模板:照着这个框架写不会乱
毕设论文一般要求一万字以上,我把结构定成了下面这种,适应大多数学校模板:
第一章:绪论。包括选题背景、研究意义、国内外研究现状、研究内容和章节安排。
第二章:需求分析。包括可行性分析、功能需求分析、非功能需求分析。
第三章:系统设计。包括总体架构设计、功能模块设计、数据库概念结构设计和逻辑结构设计。
第四章:系统实现。按模块写:用户模块、动物管理模块、领养申请模块、助养模块,每个模块配页面截图和核心代码说明。
第五章:系统测试。包括测试环境、功能测试用例表、测试结果分析。
第六章:总结与展望。
千万别省略测试章节,很多程序实现了论文最后却没写测试,被导师打回重写。哪怕只是手工点一遍页面,也能整理出二十条用例记录。
6.2 需求分析怎么写才不像抄来的
需求分析最怕写成“系统需要用户登录、需要管理员管理动物信息”这种干巴巴的列举。我的技巧是把业务场景写进去,比如“救助站每天会接到新的流浪动物求助信息,工作人员希望能在系统中快速录入动物基础信息和健康状况,并自动生成待领养列表”。
这种写法把系统功能和真实业务痛点结合,审阅老师一眼能看出你做过调研。国内外研究现状部分不要堆砌网络博客,至少找三篇正规的期刊论文引用,强调近三年国内外在“动物保护信息化”和“领养管理系统”上的探索,有一个真实的引用会大大降低查重风险。
6.3 ER图、用例图、时序图的绘制建议
论文必须有图。我在第三章画了ER图、用例图、系统架构图,第四章画了领养申请时序图。工具我用draw.io这类开源绘图工具完成的,矢量格式清晰度好,而且不用下载安装,浏览器里就能画。
画图的核心原则是图和文字必须对应。有的论文里文字写“领养申请需要填写领养理由”,用例图里却没有“填写领养理由”这一项,答辩时被老师翻到会很尴尬。我每次修改代码加功能,都会同步检查论文中的图是否需要更新。
时序图是最能体现业务理解的,我用它描述了“用户提交领养申请到管理员审核通过”的完整过程。论文里时序图一放,业务逻辑一目了然,答辩讲流程时指着图讲能省一半口水。
6.4 容易被审阅老师挑的毛病
第一个毛病是数据库设计字段说明不全。我最初建表时很多字段只有字段名没有注释,后来统一用COMMENT给每个字段写了备注,同时也在论文的数据库设计小节补充说明。
第二个毛病是界面截图不清晰。很多同学截图时窗口太小,字看不清。我用浏览器开发者工具把页面调到合适的宽度再截图,保持每张截图有明确的重点区域,界面截图统一加红色矩形框标注操作按钮。
第三个毛病是参考文献数量少。现在普遍要求至少15篇以上,我凑了两本中文教材、几篇期刊论文和部分官网文档。格式一定要用学校模板,参考文献的引用格式错误是审阅老师最爱挑的刺。
7. 测试与提交前检查清单:解决完这些再交
7.1 接口和功能测试的执行方式
我没有写自动化测试,用的是接口调试工具加人工测试。后端接口每写完一个模块,先用工具把增删改查全部跑通,确认返回code和data都是预期。然后启动前端,把页面流程过一遍,重点测“提交领养申请”和“管理员审批”这条核心链路。
建议每完成一个模块就做一次测试,不要攒到最后。我朋友在临提交前三天才把所有功能连起来测,一天能找出十几个Bug,改到心态崩溃。我因为边做边测,最后只剩两个小问题。
7.2 最容易在演示现场翻车的三个配置问题
第一,数据库密码和jdbc.properties不一致,演示时连不上数据库,页面直接报500。提交前检查jdbc.properties里的数据库名、用户名、密码是否和本地一致,我因为这个问题翻过一次车,后来把jdbc配置打印到了日志里方便排查。
第二,图片路径不显示。前端访问图片用相对路径时,如果Tomcat的context-path不是根路径,图片全部加载失败。解决办法:ApplicationContext里配置server.servlet.context-path为空字符串,保证URL层级统一。
第三,数据库乱码。MySQL连接串没加characterEncoding=utf8和useSSL=false,插入中文后数据变问号。提交前先把表的默认字符集确认是utf8mb4,连接串统一加上参数。
7.3 演示前必须准备的账号与数据
答辩演示最怕临时注册账号、临时录动物、临时填申请,浪费时间还会紧张。我提前准备了三个账号,分别演示三种角色,并预置了五只动物的数据、两条待审核领养申请、一条助养记录,打开页面就有内容可看。
演示时把“从登录到领养申请再到管理员审批”的完整链路走一遍,最后打开统计看板,让评委看到图表。这条流程我提前练习了至少五遍,每遍控制在八分钟以内。评委多数会问“审批通过后动物状态怎么变化”,这时候直接演示一次,把数据流转过程讲清楚就行。
最后的几句经验
整个项目从12月做到第2年2月,三个月左右。前期花在需求分析上的时间比想象中多,因为救助站的实际业务并不是“简单的领养申请”,里面有很多规则,比如同一只动物不能重复领养、助养和领养可以并存。这些规则是否有价值,关键看系统是不是真的能帮业务方解决痛点。我后来把系统拿给救助站的人看,她们说“这个能省不少事”,比答辩得高分更让我高兴。
如果时间允许,强烈建议你在论文的“展望”部分写一个疫苗提醒功能:系统根据动物的疫苗到期时间,自动给救助站工作人员发送站内提醒。这个功能代码量不大,但能体现出你对业务生命的关怀,也是答辩时能讲出个人思考的亮点。最后提醒一点:Vue项目打包出来的dist文件夹一定要放进Tomcat前先测试一次静态资源路径,别等到了答辩现场才发现所有图片都是裂的。